upd: dashboard admin

Deskripsi:
- pagination list pengaduan

No Issues
This commit is contained in:
2025-12-02 11:22:05 +08:00
parent 4996da4189
commit cc7c8eb704
2 changed files with 60 additions and 36 deletions

View File

@@ -6,8 +6,10 @@ import {
Container, Container,
Divider, Divider,
Flex, Flex,
Grid,
Group, Group,
Input, Input,
Pagination,
Stack, Stack,
Tabs, Tabs,
Text, Text,
@@ -124,22 +126,25 @@ function ListPengaduan({ status }: { status: StatusKey }) {
const navigate = useNavigate(); const navigate = useNavigate();
const [page, setPage] = useState(1); const [page, setPage] = useState(1);
const [value, setValue] = useState(""); const [value, setValue] = useState("");
const { data, mutate, isLoading } = useSwr("/", async () => { const { data, mutate, isLoading } = useSwr("/", async () =>
const res = await apiFetch.api.pengaduan.list.get({ apiFetch.api.pengaduan.list.get({
query: { query: {
status, status,
search: value, search: value,
take: "", take: "",
page: "", page: page.toString(),
}, },
}); })
);
return Array.isArray(res?.data) ? res.data : []; // ⬅ paksa return array useShallowEffect(() => {
}); setPage(1);
mutate();
}, [status, value]);
useShallowEffect(() => { useShallowEffect(() => {
mutate(); mutate();
}, [status, value]); }, [page]);
useShallowEffect(() => { useShallowEffect(() => {
const unsubscribe = subscribe(state, () => mutate()); const unsubscribe = subscribe(state, () => mutate());
@@ -163,30 +168,39 @@ function ListPengaduan({ status }: { status: StatusKey }) {
</Card> </Card>
); );
const list = data || []; const list = data?.data?.data || [];
const total = data?.data?.total || 0;
const totalPage = data?.data?.totalPages || 1;
const pageSize = data?.data?.pageSize || 10;
const pageNow = data?.data?.page || 1;
return ( return (
<Stack gap="xl"> <Stack gap="xl">
<Group grow> <Grid>
<Input <Grid.Col span={10}>
value={value} <Input
placeholder="Cari pengaduan..." value={value}
onChange={(event) => setValue(event.currentTarget.value)} placeholder="Cari pengaduan..."
leftSection={<IconSearch size={16} />} onChange={(event) => setValue(event.currentTarget.value)}
rightSectionPointerEvents="all" leftSection={<IconSearch size={16} />}
rightSection={ rightSectionPointerEvents="all"
<CloseButton rightSection={
aria-label="Clear input" <CloseButton
onClick={() => setValue("")} aria-label="Clear input"
style={{ display: value ? undefined : "none" }} onClick={() => setValue("")}
/> style={{ display: value ? undefined : "none" }}
} />
/> }
{/* <Group justify="flex-end"> />
<Text size="sm">Menampilkan {Number(data?.data?.length) * (page - 1) + 1} {Math.min(10, Number(data?.data?.length) * page)} dari {Number(data?.data?.length)}</Text> </Grid.Col>
<Pagination total={Number(data?.data?.length)} value={page} onChange={setPage} withPages={false} /> <Grid.Col span={2}>
</Group> */} <Group justify="space-between" grow>
</Group> <Text size="sm">{`${pageSize * (page - 1) + 1} ${Math.min(total, pageSize * page)} of ${total}`}</Text>
<Pagination total={totalPage} value={page} onChange={setPage} withPages={false} />
</Group>
</Grid.Col>
</Grid>
{list.length === 0 ? ( {list.length === 0 ? (
<Flex justify="center" align="center" py={"xl"}> <Flex justify="center" align="center" py={"xl"}>
<Stack gap={4} align="center"> <Stack gap={4} align="center">
@@ -217,14 +231,14 @@ function ListPengaduan({ status }: { status: StatusKey }) {
<Flex align="center" justify="space-between"> <Flex align="center" justify="space-between">
<Flex direction={"column"}> <Flex direction={"column"}>
<Title order={3} c="gray.2"> <Title order={3} c="gray.2">
{v.title} {v.title.toString()}
</Title> </Title>
<Group> <Group>
<Title order={6} c="gray.5"> <Title order={6} c="gray.5">
#{v.noPengaduan} #{v.noPengaduan.toString()}
</Title> </Title>
<Text size="sm" c="dimmed"> <Text size="sm" c="dimmed">
{v.updatedAt} {v.updatedAt.toString()}
</Text> </Text>
</Group> </Group>
</Flex> </Flex>
@@ -257,7 +271,7 @@ function ListPengaduan({ status }: { status: StatusKey }) {
Tanggal Aduan Tanggal Aduan
</Text> </Text>
</Group> </Group>
<Text size="md">{v.createdAt}</Text> <Text size="md">{v.createdAt.toLocaleDateString("id-ID", { day: "numeric", month: "long", year: "numeric" })}</Text>
</Flex> </Flex>
<Flex direction={"column"} justify="flex-start"> <Flex direction={"column"} justify="flex-start">
<Group gap="xs"> <Group gap="xs">

View File

@@ -646,6 +646,10 @@ const PengaduanRoute = new Elysia({
} }
} }
const totalData = await prisma.pengaduan.count({
where
});
const data = await prisma.pengaduan.findMany({ const data = await prisma.pengaduan.findMany({
skip, skip,
take: !take ? 10 : Number(take), take: !take ? 10 : Number(take),
@@ -683,12 +687,20 @@ const PengaduanRoute = new Elysia({
detail: item.detail, detail: item.detail,
status: item.status, status: item.status,
location: item.location, location: item.location,
createdAt: item.createdAt.toLocaleDateString("id-ID", { day: "numeric", month: "long", year: "numeric" }), createdAt: item.createdAt,
updatedAt: 'terakhir diperbarui ' + getLastUpdated(item.updatedAt), updatedAt: 'terakhir diperbarui ' + getLastUpdated(item.updatedAt),
} }
}) })
return dataFix const dataReturn = {
data: dataFix,
total: totalData,
page: Number(page) || 1,
pageSize: !take ? 10 : Number(take),
totalPages: Math.ceil(totalData / (!take ? 10 : Number(take)))
}
return dataReturn
}, { }, {
query: t.Object({ query: t.Object({
take: t.String({ optional: true }), take: t.String({ optional: true }),
@@ -790,8 +802,6 @@ const PengaduanRoute = new Elysia({
description: "Tool untuk delete file Seafile", description: "Tool untuk delete file Seafile",
}, },
}) })
; ;
export default PengaduanRoute export default PengaduanRoute