This commit is contained in:
bipproduction
2025-12-11 17:06:33 +08:00
parent eb5eee6ae9
commit 83f795a726
6 changed files with 156 additions and 204 deletions

View File

@@ -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}`);
});

View File

@@ -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">

View File

@@ -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>

View File

@@ -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">

View File

@@ -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

View 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",
},
});