tambahan
This commit is contained in:
@@ -11,7 +11,8 @@ import { cors } from "@elysiajs/cors";
|
||||
import packageJson from "./../package.json";
|
||||
import Configs from "./server/routes/configs_route";
|
||||
import { prisma } from "./server/lib/prisma";
|
||||
import JadwalSholat from "./server/routes/jadwal_sholat";
|
||||
import JadwalShalat from "./server/routes/jadwal_shalat";
|
||||
import { JadwalShalatAdmin } from "./server/routes/jadwal_shalat_admin";
|
||||
const PORT = process.env.PORT || 3000;
|
||||
|
||||
const Docs = new Elysia().use(
|
||||
@@ -71,11 +72,12 @@ const ApiUser = new Elysia({
|
||||
const Api = new Elysia({
|
||||
prefix: "/api",
|
||||
})
|
||||
.use(JadwalShalat)
|
||||
.use(Configs)
|
||||
.use(apiAuth)
|
||||
.use(ApiKeyRoute)
|
||||
.use(ApiUser)
|
||||
.use(JadwalSholat);
|
||||
.use(JadwalShalatAdmin);
|
||||
|
||||
const app = new Elysia()
|
||||
.use(cors())
|
||||
@@ -129,7 +131,7 @@ const app = new Elysia()
|
||||
},
|
||||
},
|
||||
)
|
||||
.get("/*", html)
|
||||
.get("*", html)
|
||||
.listen(PORT, () => {
|
||||
console.log(`Server running at http://localhost:${PORT}`);
|
||||
});
|
||||
|
||||
@@ -1,7 +1,13 @@
|
||||
import clientRoutes from "@/clientRoutes";
|
||||
import { Button, Card, Container, Group, Stack, Title } from "@mantine/core";
|
||||
import { useShallowEffect } from "@mantine/hooks";
|
||||
import { useNavigate } from "react-router-dom";
|
||||
|
||||
export default function Home() {
|
||||
|
||||
useShallowEffect(() => {
|
||||
window.location.reload()
|
||||
},[])
|
||||
return (
|
||||
<Container size={420} py={80}>
|
||||
<Card shadow="sm" padding="xl" radius="md">
|
||||
|
||||
@@ -1,12 +1,13 @@
|
||||
import clientRoutes from "@/clientRoutes";
|
||||
import apiFetch from "@/lib/apiFetch";
|
||||
import {
|
||||
ActionIcon,
|
||||
Button,
|
||||
Card,
|
||||
Container,
|
||||
Flex,
|
||||
Group,
|
||||
Loader,
|
||||
Radio,
|
||||
Stack,
|
||||
Switch,
|
||||
Text,
|
||||
@@ -15,8 +16,10 @@ import {
|
||||
} from "@mantine/core";
|
||||
import { useShallowEffect } from "@mantine/hooks";
|
||||
import { notifications } from "@mantine/notifications";
|
||||
import { IconEye } from "@tabler/icons-react";
|
||||
import type { Configs, User } from "generated/prisma";
|
||||
import { useState } from "react";
|
||||
import { useNavigate } from "react-router";
|
||||
import useSwr from "swr";
|
||||
|
||||
export default function JadwalShalat() {
|
||||
@@ -37,6 +40,7 @@ function ListUser() {
|
||||
apiFetch.api["jadwal-sholat"]["user-list"].get,
|
||||
);
|
||||
const [listUser, setListUser] = useState<User[]>([]);
|
||||
const navigate = useNavigate();
|
||||
useShallowEffect(() => {
|
||||
setListUser(data?.data?.data ?? []);
|
||||
}, [data]);
|
||||
@@ -44,27 +48,38 @@ function ListUser() {
|
||||
if (error) return <Text>{error.message}</Text>;
|
||||
|
||||
return (
|
||||
<Card>
|
||||
<Stack>
|
||||
<Title order={4}>List User</Title>
|
||||
{listUser.map((user) => (
|
||||
<Stack key={user.id}>
|
||||
<Flex>
|
||||
<Text w={200}>{user.name}</Text>
|
||||
<Switch
|
||||
defaultChecked={user.active}
|
||||
onChange={async (e) => {
|
||||
const { data } = await apiFetch.api["jadwal-sholat"][
|
||||
"user-active"
|
||||
].put({ id: user.id, active: e.target.checked });
|
||||
mutate();
|
||||
}}
|
||||
/>
|
||||
</Flex>
|
||||
</Stack>
|
||||
))}
|
||||
</Stack>
|
||||
</Card>
|
||||
<Stack>
|
||||
<Group justify="end">
|
||||
<ActionIcon
|
||||
variant="subtle"
|
||||
color="blue"
|
||||
onClick={() => navigate(clientRoutes["/shalat/shalat"])}
|
||||
>
|
||||
<IconEye />
|
||||
</ActionIcon>
|
||||
</Group>
|
||||
<Card>
|
||||
<Stack>
|
||||
<Title order={4}>List User</Title>
|
||||
{listUser.map((user) => (
|
||||
<Stack key={user.id}>
|
||||
<Flex>
|
||||
<Text w={200}>{user.name}</Text>
|
||||
<Switch
|
||||
defaultChecked={user.active}
|
||||
onChange={async (e) => {
|
||||
const { data } = await apiFetch.api["jadwal-sholat-admin"][
|
||||
"user-active"
|
||||
].put({ id: user.id, active: e.target.checked });
|
||||
mutate();
|
||||
}}
|
||||
/>
|
||||
</Flex>
|
||||
</Stack>
|
||||
))}
|
||||
</Stack>
|
||||
</Card>
|
||||
</Stack>
|
||||
);
|
||||
}
|
||||
|
||||
@@ -110,31 +125,33 @@ function ConfigUpdate() {
|
||||
}, [data]);
|
||||
|
||||
async function handleUpdate() {
|
||||
if (!config?.ikomahKey || !config?.imamKey) return notifications.show({
|
||||
title: "Error",
|
||||
message: "Config updated failed",
|
||||
color: "red",
|
||||
});
|
||||
const { data , status} = await apiFetch.api["jadwal-sholat"]["config"].put({
|
||||
if (!config?.ikomahKey || !config?.imamKey)
|
||||
return notifications.show({
|
||||
title: "Error",
|
||||
message: "Config updated failed",
|
||||
color: "red",
|
||||
});
|
||||
const { data, status } = await apiFetch.api["jadwal-sholat-admin"][
|
||||
"config"
|
||||
].put({
|
||||
id: "1",
|
||||
ikomahKey: config.ikomahKey,
|
||||
imamKey: config.imamKey,
|
||||
});
|
||||
|
||||
if(status === 200 ) {
|
||||
|
||||
if (status === 200) {
|
||||
notifications.show({
|
||||
title: "Success",
|
||||
message: "Config updated successfully",
|
||||
color: "green",
|
||||
});
|
||||
}else{
|
||||
} else {
|
||||
notifications.show({
|
||||
title: "Error",
|
||||
message: "Config updated failed",
|
||||
color: "red",
|
||||
});
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
if (isLoading) return <Loader />;
|
||||
@@ -146,11 +163,19 @@ function ConfigUpdate() {
|
||||
<Title order={4}>Config</Title>
|
||||
<Flex>
|
||||
<Text w={200}>Imam Key</Text>
|
||||
<TextInput defaultValue={config?.imamKey} onChange={(e) => setConfig({ ...config, imamKey: e.target.value })} />
|
||||
<TextInput
|
||||
defaultValue={config?.imamKey}
|
||||
onChange={(e) => setConfig({ ...config, imamKey: e.target.value })}
|
||||
/>
|
||||
</Flex>
|
||||
<Flex>
|
||||
<Text w={200}>Ikomah Key</Text>
|
||||
<TextInput defaultValue={config?.ikomahKey} onChange={(e) => setConfig({ ...config, ikomahKey: e.target.value })} />
|
||||
<TextInput
|
||||
defaultValue={config?.ikomahKey}
|
||||
onChange={(e) =>
|
||||
setConfig({ ...config, ikomahKey: e.target.value })
|
||||
}
|
||||
/>
|
||||
</Flex>
|
||||
<Group justify="end">
|
||||
<Button onClick={handleUpdate}>Update</Button>
|
||||
|
||||
@@ -13,14 +13,13 @@ import {
|
||||
Stack,
|
||||
Text,
|
||||
Title,
|
||||
UnstyledButton
|
||||
UnstyledButton,
|
||||
} from "@mantine/core";
|
||||
import { DatePicker, DatePickerInput } from "@mantine/dates";
|
||||
import { DatePicker } from "@mantine/dates";
|
||||
import dayjs from "dayjs";
|
||||
import "dayjs/locale/id";
|
||||
import duration from "dayjs/plugin/duration";
|
||||
import { useEffect, useMemo, useState } from "react";
|
||||
import { DateScrollPicker } from 'react-date-wheel-picker'
|
||||
|
||||
import {
|
||||
IconCalendar,
|
||||
@@ -39,7 +38,8 @@ import {
|
||||
|
||||
import DateHolidays, { type HolidaysTypes } from "date-holidays";
|
||||
import useSwr from "swr";
|
||||
|
||||
import { useNavigate } from "react-router";
|
||||
import clientRoutes from "@/clientRoutes";
|
||||
dayjs.locale("id");
|
||||
dayjs.extend(duration);
|
||||
|
||||
@@ -62,6 +62,7 @@ export default function AdhanPage() {
|
||||
const [daily, setDaily] = useState<any>(null);
|
||||
const [adhan, setAdhan] = useState<any>(null);
|
||||
const [loading, setLoading] = useState(true);
|
||||
const navigate = useNavigate();
|
||||
|
||||
// tahun & bulan yang dipakai
|
||||
const year = dayjs(date).year();
|
||||
@@ -217,7 +218,12 @@ export default function AdhanPage() {
|
||||
<Stack gap="xl" py="md">
|
||||
<Stack justify="apart" align="center">
|
||||
<Stack justify="center" align="center">
|
||||
<IconCalendar color="cyan" size={"6rem"} stroke={1.3} />
|
||||
<IconCalendar
|
||||
color="cyan"
|
||||
size={"6rem"}
|
||||
stroke={1.3}
|
||||
onClick={() => navigate("/")}
|
||||
/>
|
||||
<Title order={2} fw={700}>
|
||||
Jadwal Sholat & Imam
|
||||
</Title>
|
||||
@@ -245,17 +251,22 @@ export default function AdhanPage() {
|
||||
locale="id"
|
||||
value={date}
|
||||
date={date || undefined}
|
||||
renderDay={(d) => <Text c={ dayjs(d).date() === dayjs(date).date() ? "green" : isHoliday(dayjs(d).format("YYYY-MM-DD")) ? "red" : ""}>{dayjs(d).format("DD")}</Text>}
|
||||
renderDay={(d) => (
|
||||
<Text
|
||||
c={
|
||||
dayjs(d).date() === dayjs(date).date()
|
||||
? "green"
|
||||
: isHoliday(dayjs(d).format("YYYY-MM-DD"))
|
||||
? "red"
|
||||
: ""
|
||||
}
|
||||
>
|
||||
{dayjs(d).format("DD")}
|
||||
</Text>
|
||||
)}
|
||||
defaultDate={date || undefined}
|
||||
onChange={setDate as any}
|
||||
/>
|
||||
{/* <DatePickerInput
|
||||
locale="id"
|
||||
value={date}
|
||||
onChange={setDate as any}
|
||||
placeholder="Pilih tanggal"
|
||||
radius="md"
|
||||
/> */}
|
||||
</Stack>
|
||||
</Card>
|
||||
</SimpleGrid>
|
||||
@@ -531,65 +542,6 @@ function RingkasanBulalan(
|
||||
);
|
||||
})}
|
||||
</SimpleGrid>
|
||||
{/* <Paper radius="sm" >
|
||||
<Table verticalSpacing="sm" >
|
||||
<Table.Thead>
|
||||
<Table.Tr>
|
||||
<Table.Th style={{ width: 120 }}>Tanggal</Table.Th>
|
||||
<Table.Th>Imam</Table.Th>
|
||||
<Table.Th>Ikomah</Table.Th>
|
||||
</Table.Tr>
|
||||
</Table.Thead>
|
||||
<Table.Tbody>
|
||||
{Object.keys(monthly.data.imam).map((d) => {
|
||||
const tglNum = Number(d);
|
||||
const iso = dayjs(
|
||||
`${year}-${String(month).padStart(2, "0")}-${String(tglNum).padStart(2, "0")}`,
|
||||
).format("YYYY-MM-DD");
|
||||
const holiday = isHoliday(iso);
|
||||
const isToday = dayjs(iso).isSame(dayjs(), "day");
|
||||
return (
|
||||
<Table.Tr
|
||||
key={d}
|
||||
c={holiday ? "red.9" : isToday ? "green.9" : ""}
|
||||
>
|
||||
<Table.Td>
|
||||
<Text fw={isToday ? 700 : 500}>
|
||||
{dayjs(iso).format("ddd, DD MMM")}
|
||||
</Text>
|
||||
</Table.Td>
|
||||
<Table.Td>
|
||||
{monthly.data.imam[d] ? (
|
||||
<Badge
|
||||
leftSection={<IconUser size={12} />}
|
||||
variant="light"
|
||||
color="blue"
|
||||
>
|
||||
{monthly.data.imam[d]}
|
||||
</Badge>
|
||||
) : (
|
||||
<Text c="dimmed">-</Text>
|
||||
)}
|
||||
</Table.Td>
|
||||
<Table.Td>
|
||||
{monthly.data.ikomah[d] ? (
|
||||
<Badge
|
||||
leftSection={<IconClock size={12} />}
|
||||
variant="light"
|
||||
color="grape"
|
||||
>
|
||||
{monthly.data.ikomah[d]}
|
||||
</Badge>
|
||||
) : (
|
||||
<Text c="dimmed">-</Text>
|
||||
)}
|
||||
</Table.Td>
|
||||
</Table.Tr>
|
||||
);
|
||||
})}
|
||||
</Table.Tbody>
|
||||
</Table>
|
||||
</Paper> */}
|
||||
</Stack>
|
||||
</Card>
|
||||
);
|
||||
@@ -625,47 +577,6 @@ function FullYearHoliday(year: number, holidays: HolidaysTypes.Holiday[]) {
|
||||
</SimpleGrid>
|
||||
</Stack>
|
||||
)}
|
||||
{/* <Paper radius="lg" >
|
||||
<Table
|
||||
stickyHeader
|
||||
verticalSpacing="md"
|
||||
highlightOnHover
|
||||
w="100%"
|
||||
>
|
||||
<Table.Thead
|
||||
style={{
|
||||
position: "sticky",
|
||||
top: 0,
|
||||
background: "white",
|
||||
zIndex: 2,
|
||||
}}
|
||||
>
|
||||
<Table.Tr>
|
||||
<Table.Th style={{ width: 240 }}>Tanggal</Table.Th>
|
||||
<Table.Th>Nama Libur</Table.Th>
|
||||
</Table.Tr>
|
||||
</Table.Thead>
|
||||
|
||||
<Table.Tbody>
|
||||
{holidays.map((h, idx) => {
|
||||
const tgl = dayjs(h.date).format("dddd, DD MMMM YYYY");
|
||||
return (
|
||||
<Table.Tr key={idx}>
|
||||
<Table.Td>
|
||||
<Group>
|
||||
<IconCalendarStar size={16} />
|
||||
<Text>{tgl}</Text>
|
||||
</Group>
|
||||
</Table.Td>
|
||||
|
||||
<Table.Td style={{ fontWeight: 700 }}>{h.name}</Table.Td>
|
||||
|
||||
</Table.Tr>
|
||||
);
|
||||
})}
|
||||
</Table.Tbody>
|
||||
</Table>
|
||||
</Paper> */}
|
||||
</Stack>
|
||||
</Card>
|
||||
);
|
||||
@@ -708,9 +619,6 @@ function JadwalHariIni(
|
||||
{p.name}
|
||||
</Text>
|
||||
</Group>
|
||||
{/* <Text size="sm" c={p.isPast ? "dimmed" : undefined}>
|
||||
{p.isPast ? "Sudah lewat" : (formatCountdown(p.dt) ?? "-")}
|
||||
</Text> */}
|
||||
</Group>
|
||||
|
||||
<Group justify="apart" align="center">
|
||||
|
||||
@@ -9,6 +9,7 @@ import dayjs from "dayjs";
|
||||
import utc from "dayjs/plugin/utc";
|
||||
import tz from "dayjs/plugin/timezone";
|
||||
import "dayjs/locale/id";
|
||||
import type { User } from "generated/prisma";
|
||||
|
||||
dayjs.extend(utc);
|
||||
dayjs.extend(tz);
|
||||
@@ -29,7 +30,7 @@ function normalize(dateStr: string) {
|
||||
/* ------------------------------------------------------------------
|
||||
MAIN ROUTER
|
||||
------------------------------------------------------------------- */
|
||||
const JadwalSholat = new Elysia({
|
||||
const JadwalShalat = new Elysia({
|
||||
prefix: "/jadwal-sholat",
|
||||
tags: ["jadwal_sholat"],
|
||||
})
|
||||
@@ -137,10 +138,12 @@ const JadwalSholat = new Elysia({
|
||||
},
|
||||
}
|
||||
)
|
||||
.get("/user-list", async () => {
|
||||
const user = await prisma.user.findMany();
|
||||
.get("/user-list", async (ctx) => {
|
||||
const { user }: { user: User } = ctx as any;
|
||||
|
||||
const getUsers = await prisma.user.findMany();
|
||||
return {
|
||||
data: user,
|
||||
data: getUsers,
|
||||
};
|
||||
}, {
|
||||
detail: {
|
||||
@@ -148,32 +151,12 @@ const JadwalSholat = new Elysia({
|
||||
description: "mendapatkan list user",
|
||||
},
|
||||
})
|
||||
.put("/user-active", async ({ body }) => {
|
||||
const { id } = body;
|
||||
const user = await prisma.user.update({
|
||||
where: { id },
|
||||
data: { active: body.active },
|
||||
});
|
||||
return {
|
||||
success: true,
|
||||
data: user,
|
||||
};
|
||||
}, {
|
||||
body: t.Object({
|
||||
id: t.String(),
|
||||
active: t.Boolean(),
|
||||
}),
|
||||
detail: {
|
||||
summary: "Active user",
|
||||
description: "mengaktifkan user",
|
||||
},
|
||||
})
|
||||
.get("/config", async () => {
|
||||
const config = await prisma.configs.findUnique({
|
||||
where: { id: "1" },
|
||||
});
|
||||
console.log(config);
|
||||
|
||||
|
||||
return {
|
||||
data: config,
|
||||
};
|
||||
@@ -182,34 +165,9 @@ const JadwalSholat = new Elysia({
|
||||
summary: "Get config",
|
||||
description: "mendapatkan config",
|
||||
},
|
||||
})
|
||||
.put("/config", async ({ body }) => {
|
||||
const { imamKey, ikomahKey } = body;
|
||||
const config = await prisma.configs.update({
|
||||
where: { id: "1" },
|
||||
data: { imamKey, ikomahKey },
|
||||
});
|
||||
console.log({
|
||||
success: true,
|
||||
config,
|
||||
});
|
||||
return {
|
||||
success: true,
|
||||
data: config,
|
||||
};
|
||||
}, {
|
||||
body: t.Object({
|
||||
id: t.String(),
|
||||
imamKey: t.String(),
|
||||
ikomahKey: t.String(),
|
||||
}),
|
||||
detail: {
|
||||
summary: "Update config",
|
||||
description: "mengupdate config",
|
||||
},
|
||||
});
|
||||
|
||||
export default JadwalSholat;
|
||||
export default JadwalShalat;
|
||||
|
||||
/* ------------------------------------------------------------------
|
||||
FUNCTIONS
|
||||
53
src/server/routes/jadwal_shalat_admin.ts
Normal file
53
src/server/routes/jadwal_shalat_admin.ts
Normal file
@@ -0,0 +1,53 @@
|
||||
import Elysia, { t } from "elysia";
|
||||
import { prisma } from "../lib/prisma";
|
||||
|
||||
export const JadwalShalatAdmin = new Elysia({
|
||||
prefix: "/jadwal-sholat-admin",
|
||||
tags: ["jadwal_sholat_admin"],
|
||||
})
|
||||
.put("/user-active", async ({ body }) => {
|
||||
|
||||
const { id } = body;
|
||||
const user = await prisma.user.update({
|
||||
where: { id },
|
||||
data: { active: body.active },
|
||||
});
|
||||
return {
|
||||
success: true,
|
||||
data: user,
|
||||
};
|
||||
}, {
|
||||
body: t.Object({
|
||||
id: t.String(),
|
||||
active: t.Boolean(),
|
||||
}),
|
||||
detail: {
|
||||
summary: "Active user",
|
||||
description: "mengaktifkan user",
|
||||
},
|
||||
})
|
||||
.put("/config", async ({ body }) => {
|
||||
const { imamKey, ikomahKey } = body;
|
||||
const config = await prisma.configs.update({
|
||||
where: { id: "1" },
|
||||
data: { imamKey, ikomahKey },
|
||||
});
|
||||
console.log({
|
||||
success: true,
|
||||
config,
|
||||
});
|
||||
return {
|
||||
success: true,
|
||||
data: config,
|
||||
};
|
||||
}, {
|
||||
body: t.Object({
|
||||
id: t.String(),
|
||||
imamKey: t.String(),
|
||||
ikomahKey: t.String(),
|
||||
}),
|
||||
detail: {
|
||||
summary: "Update config",
|
||||
description: "mengupdate config",
|
||||
},
|
||||
});
|
||||
Reference in New Issue
Block a user