update: dashboard admin

Deskripsi:
- list pelayanan surat
- detail pelayanan surat

No Issues
This commit is contained in:
2025-11-11 11:11:21 +08:00
parent ddefbbbbff
commit 663e36bc4b
6 changed files with 724 additions and 320 deletions

View File

@@ -18,6 +18,7 @@ import Home from "./pages/Home";
import CredentialPage from "./pages/scr/dashboard/credential/credential_page"; import CredentialPage from "./pages/scr/dashboard/credential/credential_page";
import DashboardHome from "./pages/scr/dashboard/dashboard_home"; import DashboardHome from "./pages/scr/dashboard/dashboard_home";
import ListPelayananPage from "./pages/scr/dashboard/pelayanan-surat/list_pelayanan_page"; import ListPelayananPage from "./pages/scr/dashboard/pelayanan-surat/list_pelayanan_page";
import DetailPelayananPage from "./pages/scr/dashboard/pelayanan-surat/detail_pelayanan_page";
import ListPage from "./pages/scr/dashboard/pengaduan/list_page"; import ListPage from "./pages/scr/dashboard/pengaduan/list_page";
import DetailPage from "./pages/scr/dashboard/pengaduan/detail_page"; import DetailPage from "./pages/scr/dashboard/pengaduan/detail_page";
import ApikeyPage from "./pages/scr/dashboard/apikey/apikey_page"; import ApikeyPage from "./pages/scr/dashboard/apikey/apikey_page";
@@ -99,6 +100,10 @@ export default function AppRoutes() {
path="/scr/dashboard/pelayanan-surat/list-pelayanan" path="/scr/dashboard/pelayanan-surat/list-pelayanan"
element={<ListPelayananPage />} element={<ListPelayananPage />}
/> />
<Route
path="/scr/dashboard/pelayanan-surat/detail-pelayanan"
element={<DetailPelayananPage />}
/>
<Route <Route
path="/scr/dashboard/pengaduan/list" path="/scr/dashboard/pengaduan/list"
element={<ListPage />} element={<ListPage />}

View File

@@ -20,6 +20,7 @@ const clientRoutes = {
"/scr/dashboard/credential/credential": "/scr/dashboard/credential/credential", "/scr/dashboard/credential/credential": "/scr/dashboard/credential/credential",
"/scr/dashboard/dashboard-home": "/scr/dashboard/dashboard-home", "/scr/dashboard/dashboard-home": "/scr/dashboard/dashboard-home",
"/scr/dashboard/pelayanan-surat/list-pelayanan": "/scr/dashboard/pelayanan-surat/list-pelayanan", "/scr/dashboard/pelayanan-surat/list-pelayanan": "/scr/dashboard/pelayanan-surat/list-pelayanan",
"/scr/dashboard/pelayanan-surat/detail-pelayanan": "/scr/dashboard/pelayanan-surat/detail-pelayanan",
"/scr/dashboard/pengaduan/list": "/scr/dashboard/pengaduan/list", "/scr/dashboard/pengaduan/list": "/scr/dashboard/pengaduan/list",
"/scr/dashboard/pengaduan/detail": "/scr/dashboard/pengaduan/detail", "/scr/dashboard/pengaduan/detail": "/scr/dashboard/pengaduan/detail",
"/scr/dashboard/apikey/apikey": "/scr/dashboard/apikey/apikey", "/scr/dashboard/apikey/apikey": "/scr/dashboard/apikey/apikey",

View File

@@ -0,0 +1,370 @@
import apiFetch from "@/lib/apiFetch";
import {
Anchor,
Badge,
Button,
Card,
Container,
Divider,
Flex,
Grid,
Group,
Modal,
Stack,
Table,
Text,
Textarea,
Title,
} from "@mantine/core";
import { useDisclosure, useShallowEffect } from "@mantine/hooks";
import {
IconAlignJustified,
IconCategory,
IconFileCertificate,
IconInfoTriangle,
IconMapPin,
IconMessageReport,
IconPhotoScan,
IconUser,
} from "@tabler/icons-react";
import { useState } from "react";
import { useLocation } from "react-router-dom";
import useSwr from "swr";
export default function DetailPelayananPage() {
const { search } = useLocation();
const query = new URLSearchParams(search);
const id = query.get("id");
return (
<Container size="xl" py="xl" w={"100%"}>
<Grid>
<Grid.Col span={8}>
<Stack gap={"xl"}>
<DetailDataPelayanan />
<DetailDataHistori />
</Stack>
</Grid.Col>
<Grid.Col span={4}>
<DetailUserPelayanan />
</Grid.Col>
</Grid>
</Container>
);
}
function DetailDataPelayanan() {
const [opened, { open, close }] = useDisclosure(false);
const [catModal, setCatModal] = useState<"tolak" | "terima">("tolak");
return (
<>
<Modal
opened={opened}
onClose={close}
title={"Konfirmasi"}
centered
overlayProps={{ backgroundOpacity: 0.55, blur: 3 }}
>
<Stack gap="sm">
{catModal === "tolak" ? (
<>
<Text>
Anda yakin ingin menolak pengaduan ini? Berikan alasan penolakan
</Text>
<Textarea size="md" minRows={5} />
<Group justify="center" grow>
<Button variant="light" onClick={close}>
Batal
</Button>
<Button variant="filled" color="red" onClick={close}>
Tolak
</Button>
</Group>
</>
) : (
<>
<Text>Anda yakin ingin menerima pengaduan ini?</Text>
<Group justify="center" grow>
<Button variant="light" onClick={close}>
Batal
</Button>
<Button variant="filled" color="green" onClick={close}>
Terima
</Button>
</Group>
</>
)}
</Stack>
</Modal>
<Card
radius="md"
p="lg"
withBorder
style={{
background:
"linear-gradient(145deg, rgba(25,25,25,0.95), rgba(45,45,45,0.85))",
borderColor: "rgba(100,100,100,0.2)",
boxShadow: "0 0 20px rgba(0,255,200,0.08)",
}}
>
<Stack gap={"md"}>
<Flex align="center" justify="space-between">
<Group gap="xs">
<Title order={4} c="gray.2">
Pelayanan Surat
</Title>
<Title order={4} c="dimmed">
#PGf-2345-33
</Title>
</Group>
<Badge
size="xl"
variant="light"
radius="sm"
color={"yellow"}
style={{ textTransform: "none" }}
>
antrian
</Badge>
</Flex>
<Divider my={0} />
<Grid>
<Grid.Col span={6}>
<Stack gap="md">
<Flex direction={"column"} justify="flex-start">
<Group gap="xs">
<IconAlignJustified size={20} />
<Text size="md">Judul</Text>
</Group>
<Text size="md" c={"white"}>
Judul Pelayanan Surat
</Text>
</Flex>
<Flex direction={"column"} justify="flex-start">
<Group gap="xs">
<IconMapPin size={20} />
<Text size="md">Lokasi</Text>
</Group>
<Text size="md" c="white">
fwef
</Text>
</Flex>
</Stack>
</Grid.Col>
<Grid.Col span={6}>
<Stack gap="md">
<Flex direction={"column"} justify="flex-start">
<Group gap="xs">
<IconCategory size={20} />
<Text size="md">Kategori</Text>
</Group>
<Text size="md" c="white">
fwef
</Text>
</Flex>
<Flex direction={"column"} justify="flex-start">
<Group gap="xs">
<IconPhotoScan size={20} />
<Text size="md">Gambar</Text>
</Group>
<Anchor href="https://mantine.dev/" target="_blank">
Lihat Gambar
</Anchor>
</Flex>
</Stack>
</Grid.Col>
<Grid.Col span={12}>
<Stack gap="md">
<Flex direction={"column"} justify="flex-start">
<Group gap="xs">
<IconAlignJustified size={20} />
<Text size="md">Detail</Text>
</Group>
<Text size="md" c="white">
Lorem ipsum dolor sit, amet consectetur adipisicing elit.
Illum, corporis iusto. Suscipit veritatis quas, non nobis
fuga, laudantium accusantium tempora sint aliquid architecto
totam esse eum excepturi nostrum fugiat ut.
</Text>
</Flex>
<Flex direction={"column"} justify="flex-start">
<Group gap="xs">
<IconInfoTriangle size={20} />
<Text size="md">Keterangan</Text>
</Group>
<Text size="md" c={"white"}>
Lorem ipsum dolor, sit amet consectetur adipisicing elit. At
fugiat eligendi nesciunt dolore? Maiores a cumque vitae
suscipit incidunt quos beatae modi, vel, id ullam quae
voluptas, deserunt quas placeat.
</Text>
</Flex>
</Stack>
</Grid.Col>
<Grid.Col span={12}>
<Group justify="center" grow>
<Button
variant="light"
onClick={() => {
setCatModal("tolak");
open();
}}
>
Tolak
</Button>
<Button
variant="filled"
onClick={() => {
setCatModal("terima");
open();
}}
>
Terima
</Button>
</Group>
</Grid.Col>
</Grid>
</Stack>
</Card>
</>
);
}
function DetailDataHistori() {
const elements = [
{ position: 6, mass: 12.011, symbol: "C", name: "Carbon" },
{ position: 7, mass: 14.007, symbol: "N", name: "Nitrogen" },
{ position: 39, mass: 88.906, symbol: "Y", name: "Yttrium" },
{ position: 56, mass: 137.33, symbol: "Ba", name: "Barium" },
{ position: 58, mass: 140.12, symbol: "Ce", name: "Cerium" },
];
const rows = elements.map((element) => (
<Table.Tr key={element.name}>
<Table.Td>{element.position}</Table.Td>
<Table.Td>{element.name}</Table.Td>
<Table.Td>{element.symbol}</Table.Td>
<Table.Td>{element.mass}</Table.Td>
</Table.Tr>
));
return (
<Card
radius="md"
p="lg"
withBorder
style={{
background:
"linear-gradient(145deg, rgba(25,25,25,0.95), rgba(45,45,45,0.85))",
borderColor: "rgba(100,100,100,0.2)",
boxShadow: "0 0 20px rgba(0,255,200,0.08)",
}}
>
<Stack gap="md">
<Flex align="center" justify="space-between">
<Title order={4} c="gray.2">
Histori Pengaduan
</Title>
</Flex>
<Divider my={0} />
<Table>
<Table.Thead>
<Table.Tr>
<Table.Th>Tanggal</Table.Th>
<Table.Th>Deskripsi</Table.Th>
<Table.Th>Status</Table.Th>
<Table.Th>User</Table.Th>
</Table.Tr>
</Table.Thead>
<Table.Tbody>{rows}</Table.Tbody>
</Table>
</Stack>
</Card>
);
}
function DetailUserPelayanan() {
const [page, setPage] = useState(1);
const [value, setValue] = useState("");
const { data, mutate, isLoading } = useSwr("/", () =>
apiFetch.api.pengaduan.list.get({
query: {
status,
search: value,
take: "",
page: "",
},
}),
);
useShallowEffect(() => {
mutate();
}, [status, value]);
const list = data?.data || [];
return (
<Card
radius="md"
p="lg"
withBorder
style={{
background:
"linear-gradient(145deg, rgba(25,25,25,0.95), rgba(45,45,45,0.85))",
borderColor: "rgba(100,100,100,0.2)",
boxShadow: "0 0 20px rgba(0,255,200,0.08)",
}}
>
<Stack gap="md">
<Flex align="center" justify="space-between">
<Flex direction={"column"}>
<Title order={4} c="gray.2">
Warga
</Title>
</Flex>
</Flex>
<Divider my={0} />
<Stack gap="md">
<Group justify="space-between">
<Group gap="xs">
<IconUser size={20} />
<Text size="md">Nama</Text>
</Group>
<Text size="md" c={"white"}>
Amalia Dwi Yustiani
</Text>
</Group>
<Group justify="space-between">
<Group gap="xs">
<IconMapPin size={20} />
<Text size="md">Telepon</Text>
</Group>
<Text size="md" c="white">
08123456789
</Text>
</Group>
<Group justify="space-between">
<Group gap="xs">
<IconMessageReport size={20} />
<Text size="md">Jumlah Pengaduan</Text>
</Group>
<Text size="md" c="white">
10
</Text>
</Group>
<Group justify="space-between">
<Group gap="xs">
<IconFileCertificate size={20} />
<Text size="md">Jumlah Pelayanan Surat</Text>
</Group>
<Text size="md" c="white">
10
</Text>
</Group>
</Stack>
</Stack>
</Card>
);
}

View File

@@ -133,6 +133,8 @@ function ListPelayananSurat({ status }: { status: StatusKey }) {
mutate(); mutate();
}, [status, value]); }, [status, value]);
const navigate = useNavigate();
if (isLoading) if (isLoading)
return ( return (
<Card <Card
@@ -169,17 +171,13 @@ function ListPelayananSurat({ status }: { status: StatusKey }) {
/> />
} }
/> />
{/* <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>
<Pagination total={Number(data?.data?.length)} value={page} onChange={setPage} withPages={false} />
</Group> */}
</Group> </Group>
{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">
<IconFileSad size={32} color="gray" /> <IconFileSad size={32} color="gray" />
<Text c="dimmed" size="sm"> <Text c="dimmed" size="sm">
No pengaduan have been added yet. No pelayanan surat have been added yet.
</Text> </Text>
</Stack> </Stack>
</Flex> </Flex>
@@ -196,6 +194,9 @@ function ListPelayananSurat({ status }: { status: StatusKey }) {
borderColor: "rgba(100,100,100,0.2)", borderColor: "rgba(100,100,100,0.2)",
boxShadow: "0 0 20px rgba(0,255,200,0.08)", boxShadow: "0 0 20px rgba(0,255,200,0.08)",
}} }}
onClick={() => {
navigate(`/scr/dashboard/pelayanan-surat/detail-pelayanan?id=${v.id}`);
}}
> >
<Stack gap="md"> <Stack gap="md">
<Flex align="center" justify="space-between"> <Flex align="center" justify="space-between">

View File

@@ -1,345 +1,370 @@
import apiFetch from "@/lib/apiFetch"; import apiFetch from "@/lib/apiFetch";
import { import {
Anchor, Anchor,
Badge, Badge,
Button, Button,
Card, Card,
Container, Container,
Divider, Divider,
Flex, Flex,
Grid, Grid,
Group, Group,
Modal, Modal,
Stack, Stack,
Table, Table,
Text, Text,
Textarea, Textarea,
Title Title,
} from "@mantine/core"; } from "@mantine/core";
import { useDisclosure, useShallowEffect } from "@mantine/hooks"; import { useDisclosure, useShallowEffect } from "@mantine/hooks";
import { import {
IconAlignJustified, IconAlignJustified,
IconCategory, IconCategory,
IconFileCertificate, IconFileCertificate,
IconInfoTriangle, IconInfoTriangle,
IconMapPin, IconMapPin,
IconMessageReport, IconMessageReport,
IconPhotoScan, IconPhotoScan,
IconUser IconUser,
} from "@tabler/icons-react"; } from "@tabler/icons-react";
import { useState } from "react"; import { useState } from "react";
import { useLocation } from "react-router-dom"; import { useLocation } from "react-router-dom";
import useSwr from "swr"; import useSwr from "swr";
export default function DetailPengaduanPage() { export default function DetailPengaduanPage() {
const { search } = useLocation(); const { search } = useLocation();
const query = new URLSearchParams(search); const query = new URLSearchParams(search);
const id = query.get("id"); const id = query.get("id");
return ( return (
<Container size="xl" py="xl" w={"100%"}> <Container size="xl" py="xl" w={"100%"}>
<Grid> <Grid>
<Grid.Col span={8}> <Grid.Col span={8}>
<Stack gap={"xl"}> <Stack gap={"xl"}>
<DetailDataPengaduan /> <DetailDataPengaduan />
<DetailDataHistori /> <DetailDataHistori />
</Stack> </Stack>
</Grid.Col> </Grid.Col>
<Grid.Col span={4}> <Grid.Col span={4}>
<DetailUserPengaduan /> <DetailUserPengaduan />
</Grid.Col> </Grid.Col>
</Grid> </Grid>
</Container> </Container>
); );
} }
function DetailDataPengaduan() { function DetailDataPengaduan() {
const [opened, { open, close }] = useDisclosure(false); const [opened, { open, close }] = useDisclosure(false);
const [catModal, setCatModal] = useState<'tolak' | 'terima'>('tolak'); const [catModal, setCatModal] = useState<"tolak" | "terima">("tolak");
return ( return (
<> <>
<Modal opened={opened} onClose={close} title={"Konfirmasi"} centered overlayProps={{ backgroundOpacity: 0.55, blur: 3 }}> <Modal
<Stack gap="sm"> opened={opened}
{ onClose={close}
catModal === 'tolak' title={"Konfirmasi"}
? ( centered
<> overlayProps={{ backgroundOpacity: 0.55, blur: 3 }}
<Text>Anda yakin ingin menolak pengaduan ini? Berikan alasan penolakan</Text> >
<Stack gap="sm">
{catModal === "tolak" ? (
<>
<Text>
Anda yakin ingin menolak pengaduan ini? Berikan alasan penolakan
</Text>
<Textarea size="md" minRows={5} /> <Textarea size="md" minRows={5} />
<Group justify="center" grow> <Group justify="center" grow>
<Button variant="light" onClick={close}>Batal</Button> <Button variant="light" onClick={close}>
<Button variant="filled" color="red" onClick={close}>Tolak</Button> Batal
</Group> </Button>
</> <Button variant="filled" color="red" onClick={close}>
) Tolak
: </Button>
( </Group>
<> </>
<Text>Anda yakin ingin menerima pengaduan ini?</Text> ) : (
<Group justify="center" grow> <>
<Button variant="light" onClick={close}>Batal</Button> <Text>Anda yakin ingin menerima pengaduan ini?</Text>
<Button variant="filled" color="green" onClick={close}>Terima</Button> <Group justify="center" grow>
</Group> <Button variant="light" onClick={close}>
</> Batal
) </Button>
} <Button variant="filled" color="green" onClick={close}>
Terima
</Button>
</Group>
</>
)}
</Stack>
</Modal>
</Stack> <Card
</Modal> radius="md"
p="lg"
<Card withBorder
radius="md" style={{
p="lg" background:
withBorder "linear-gradient(145deg, rgba(25,25,25,0.95), rgba(45,45,45,0.85))",
style={{ borderColor: "rgba(100,100,100,0.2)",
background: boxShadow: "0 0 20px rgba(0,255,200,0.08)",
"linear-gradient(145deg, rgba(25,25,25,0.95), rgba(45,45,45,0.85))", }}
borderColor: "rgba(100,100,100,0.2)", >
boxShadow: "0 0 20px rgba(0,255,200,0.08)", <Stack gap={"md"}>
}} <Flex align="center" justify="space-between">
> <Group gap="xs">
<Stack gap={"md"}> <Title order={4} c="gray.2">
<Flex align="center" justify="space-between"> Pengaduan
</Title>
<Title order={4} c="dimmed">
#PGf-2345-33
</Title>
</Group>
<Badge
size="xl"
variant="light"
radius="sm"
color={"yellow"}
style={{ textTransform: "none" }}
>
antrian
</Badge>
</Flex>
<Divider my={0} />
<Grid>
<Grid.Col span={6}>
<Stack gap="md">
<Flex direction={"column"} justify="flex-start">
<Group gap="xs"> <Group gap="xs">
<Title order={4} c="gray.2"> <IconAlignJustified size={20} />
Pengaduan <Text size="md">Judul</Text>
</Title>
<Title order={4} c="dimmed">
#PGf-2345-33
</Title>
</Group> </Group>
<Badge <Text size="md" c={"white"}>
size="xl" Judul Pengaduan
variant="light" </Text>
radius="sm" </Flex>
color={"yellow"} <Flex direction={"column"} justify="flex-start">
style={{ textTransform: "none" }} <Group gap="xs">
> <IconMapPin size={20} />
antrian <Text size="md">Lokasi</Text>
</Badge> </Group>
</Flex> <Text size="md" c="white">
<Divider my={0} /> fwef
<Grid> </Text>
<Grid.Col span={6}> </Flex>
<Stack gap="md"> </Stack>
<Flex direction={"column"} justify="flex-start"> </Grid.Col>
<Group gap="xs"> <Grid.Col span={6}>
<IconAlignJustified size={20} /> <Stack gap="md">
<Text size="md"> <Flex direction={"column"} justify="flex-start">
Judul <Group gap="xs">
</Text> <IconCategory size={20} />
</Group> <Text size="md">Kategori</Text>
<Text size="md" c={"white"}>Judul Pengaduan</Text> </Group>
</Flex> <Text size="md" c="white">
<Flex direction={"column"} justify="flex-start"> fwef
<Group gap="xs"> </Text>
<IconMapPin size={20} /> </Flex>
<Text size="md"> <Flex direction={"column"} justify="flex-start">
Lokasi <Group gap="xs">
</Text> <IconPhotoScan size={20} />
</Group> <Text size="md">Gambar</Text>
<Text size="md" c="white">fwef</Text> </Group>
</Flex> <Anchor href="https://mantine.dev/" target="_blank">
</Stack> Lihat Gambar
</Grid.Col> </Anchor>
<Grid.Col span={6}> </Flex>
<Stack gap="md"> </Stack>
<Flex direction={"column"} justify="flex-start"> </Grid.Col>
<Group gap="xs"> <Grid.Col span={12}>
<IconCategory size={20} /> <Stack gap="md">
<Text size="md"> <Flex direction={"column"} justify="flex-start">
Kategori <Group gap="xs">
</Text> <IconAlignJustified size={20} />
</Group> <Text size="md">Detail</Text>
<Text size="md" c="white">fwef</Text> </Group>
</Flex> <Text size="md" c="white">
<Flex direction={"column"} justify="flex-start"> Lorem ipsum dolor sit, amet consectetur adipisicing elit.
<Group gap="xs"> Illum, corporis iusto. Suscipit veritatis quas, non nobis
<IconPhotoScan size={20} /> fuga, laudantium accusantium tempora sint aliquid architecto
<Text size="md"> totam esse eum excepturi nostrum fugiat ut.
Gambar </Text>
</Text> </Flex>
</Group> <Flex direction={"column"} justify="flex-start">
<Anchor href="https://mantine.dev/" target="_blank"> <Group gap="xs">
Lihat Gambar <IconInfoTriangle size={20} />
</Anchor> <Text size="md">Keterangan</Text>
</Flex> </Group>
</Stack> <Text size="md" c={"white"}>
</Grid.Col> Lorem ipsum dolor, sit amet consectetur adipisicing elit. At
<Grid.Col span={12}> fugiat eligendi nesciunt dolore? Maiores a cumque vitae
<Stack gap="md"> suscipit incidunt quos beatae modi, vel, id ullam quae
<Flex direction={"column"} justify="flex-start"> voluptas, deserunt quas placeat.
<Group gap="xs"> </Text>
<IconAlignJustified size={20} /> </Flex>
<Text size="md"> </Stack>
Detail </Grid.Col>
</Text> <Grid.Col span={12}>
</Group> <Group justify="center" grow>
<Text size="md" c="white"> <Button
Lorem ipsum dolor sit, amet consectetur adipisicing elit. Illum, corporis iusto. Suscipit veritatis quas, non nobis fuga, laudantium accusantium tempora sint aliquid architecto totam esse eum excepturi nostrum fugiat ut. variant="light"
</Text> onClick={() => {
</Flex> setCatModal("tolak");
<Flex direction={"column"} justify="flex-start"> open();
<Group gap="xs"> }}
<IconInfoTriangle size={20} /> >
<Text size="md"> Tolak
Keterangan </Button>
</Text> <Button
</Group> variant="filled"
<Text size="md" c={"white"}> onClick={() => {
Lorem ipsum dolor, sit amet consectetur adipisicing elit. At fugiat eligendi nesciunt dolore? Maiores a cumque vitae suscipit incidunt quos beatae modi, vel, id ullam quae voluptas, deserunt quas placeat. setCatModal("terima");
</Text> open();
</Flex> }}
</Stack> >
</Grid.Col> Terima
<Grid.Col span={12}> </Button>
<Group justify="center" grow> </Group>
<Button variant="light" onClick={() => { setCatModal('tolak'); open() }}>Tolak</Button> </Grid.Col>
<Button variant="filled" onClick={() => { setCatModal('terima'); open() }}>Terima</Button> </Grid>
</Group> </Stack>
</Grid.Col> </Card>
</Grid> </>
</Stack> );
</Card>
</>
);
} }
function DetailDataHistori() { function DetailDataHistori() {
const elements = [ const elements = [
{ position: 6, mass: 12.011, symbol: 'C', name: 'Carbon' }, { position: 6, mass: 12.011, symbol: "C", name: "Carbon" },
{ position: 7, mass: 14.007, symbol: 'N', name: 'Nitrogen' }, { position: 7, mass: 14.007, symbol: "N", name: "Nitrogen" },
{ position: 39, mass: 88.906, symbol: 'Y', name: 'Yttrium' }, { position: 39, mass: 88.906, symbol: "Y", name: "Yttrium" },
{ position: 56, mass: 137.33, symbol: 'Ba', name: 'Barium' }, { position: 56, mass: 137.33, symbol: "Ba", name: "Barium" },
{ position: 58, mass: 140.12, symbol: 'Ce', name: 'Cerium' }, { position: 58, mass: 140.12, symbol: "Ce", name: "Cerium" },
]; ];
const rows = elements.map((element) => ( const rows = elements.map((element) => (
<Table.Tr key={element.name}> <Table.Tr key={element.name}>
<Table.Td>{element.position}</Table.Td> <Table.Td>{element.position}</Table.Td>
<Table.Td>{element.name}</Table.Td> <Table.Td>{element.name}</Table.Td>
<Table.Td>{element.symbol}</Table.Td> <Table.Td>{element.symbol}</Table.Td>
<Table.Td>{element.mass}</Table.Td> <Table.Td>{element.mass}</Table.Td>
</Table.Tr> </Table.Tr>
)); ));
return ( return (
<Card <Card
radius="md" radius="md"
p="lg" p="lg"
withBorder withBorder
style={{ style={{
background: background:
"linear-gradient(145deg, rgba(25,25,25,0.95), rgba(45,45,45,0.85))", "linear-gradient(145deg, rgba(25,25,25,0.95), rgba(45,45,45,0.85))",
borderColor: "rgba(100,100,100,0.2)", borderColor: "rgba(100,100,100,0.2)",
boxShadow: "0 0 20px rgba(0,255,200,0.08)", boxShadow: "0 0 20px rgba(0,255,200,0.08)",
}} }}
> >
<Stack gap="md"> <Stack gap="md">
<Flex align="center" justify="space-between"> <Flex align="center" justify="space-between">
<Title order={4} c="gray.2"> <Title order={4} c="gray.2">
Histori Pengaduan Histori Pengaduan
</Title> </Title>
</Flex> </Flex>
<Divider my={0} /> <Divider my={0} />
<Table> <Table>
<Table.Thead> <Table.Thead>
<Table.Tr> <Table.Tr>
<Table.Th>Tanggal</Table.Th> <Table.Th>Tanggal</Table.Th>
<Table.Th>Deskripsi</Table.Th> <Table.Th>Deskripsi</Table.Th>
<Table.Th>Status</Table.Th> <Table.Th>Status</Table.Th>
<Table.Th>User</Table.Th> <Table.Th>User</Table.Th>
</Table.Tr> </Table.Tr>
</Table.Thead> </Table.Thead>
<Table.Tbody>{rows}</Table.Tbody> <Table.Tbody>{rows}</Table.Tbody>
</Table> </Table>
</Stack> </Stack>
</Card> </Card>
);
)
} }
function DetailUserPengaduan() { function DetailUserPengaduan() {
const [page, setPage] = useState(1); const [page, setPage] = useState(1);
const [value, setValue] = useState(""); const [value, setValue] = useState("");
const { data, mutate, isLoading } = useSwr("/", () => const { data, mutate, isLoading } = useSwr("/", () =>
apiFetch.api.pengaduan.list.get({ apiFetch.api.pengaduan.list.get({
query: { query: {
status, status,
search: value, search: value,
take: "", take: "",
page: "", page: "",
}, },
}), }),
); );
useShallowEffect(() => { useShallowEffect(() => {
mutate(); mutate();
}, [status, value]); }, [status, value]);
const list = data?.data || []; const list = data?.data || [];
return ( return (
<Card <Card
radius="md" radius="md"
p="lg" p="lg"
withBorder withBorder
style={{ style={{
background: background:
"linear-gradient(145deg, rgba(25,25,25,0.95), rgba(45,45,45,0.85))", "linear-gradient(145deg, rgba(25,25,25,0.95), rgba(45,45,45,0.85))",
borderColor: "rgba(100,100,100,0.2)", borderColor: "rgba(100,100,100,0.2)",
boxShadow: "0 0 20px rgba(0,255,200,0.08)", boxShadow: "0 0 20px rgba(0,255,200,0.08)",
}} }}
> >
<Stack gap="md"> <Stack gap="md">
<Flex align="center" justify="space-between"> <Flex align="center" justify="space-between">
<Flex direction={"column"}> <Flex direction={"column"}>
<Title order={4} c="gray.2"> <Title order={4} c="gray.2">
Warga Warga
</Title> </Title>
</Flex> </Flex>
</Flex> </Flex>
<Divider my={0} /> <Divider my={0} />
<Stack gap="md"> <Stack gap="md">
<Group justify="space-between" > <Group justify="space-between">
<Group gap="xs"> <Group gap="xs">
<IconUser size={20} /> <IconUser size={20} />
<Text size="md"> <Text size="md">Nama</Text>
Nama </Group>
</Text> <Text size="md" c={"white"}>
</Group> Amalia Dwi Yustiani
<Text size="md" c={"white"}>Amalia Dwi Yustiani</Text> </Text>
</Group> </Group>
<Group justify="space-between" > <Group justify="space-between">
<Group gap="xs"> <Group gap="xs">
<IconMapPin size={20} /> <IconMapPin size={20} />
<Text size="md"> <Text size="md">Telepon</Text>
Telepon </Group>
</Text> <Text size="md" c="white">
</Group> 08123456789
<Text size="md" c="white">08123456789</Text> </Text>
</Group> </Group>
<Group justify="space-between" > <Group justify="space-between">
<Group gap="xs"> <Group gap="xs">
<IconMessageReport size={20} /> <IconMessageReport size={20} />
<Text size="md"> <Text size="md">Jumlah Pengaduan</Text>
Jumlah Pengaduan </Group>
</Text> <Text size="md" c="white">
</Group> 10
<Text size="md" c="white">10</Text> </Text>
</Group> </Group>
<Group justify="space-between" > <Group justify="space-between">
<Group gap="xs"> <Group gap="xs">
<IconFileCertificate size={20} /> <IconFileCertificate size={20} />
<Text size="md"> <Text size="md">Jumlah Pelayanan Surat</Text>
Jumlah Pelayanan Surat </Group>
</Text> <Text size="md" c="white">
</Group> 10
<Text size="md" c="white">10</Text> </Text>
</Group> </Group>
</Stack> </Stack>
</Stack> </Stack>
</Card> </Card>
); );
} }

View File

@@ -198,7 +198,9 @@ function ListPengaduan({ status }: { status: StatusKey }) {
borderColor: "rgba(100,100,100,0.2)", borderColor: "rgba(100,100,100,0.2)",
boxShadow: "0 0 20px rgba(0,255,200,0.08)", boxShadow: "0 0 20px rgba(0,255,200,0.08)",
}} }}
onClick={() => navigate(`/scr/dashboard/pengaduan/detail?id=${v.id}`)} onClick={() =>
navigate(`/scr/dashboard/pengaduan/detail?id=${v.id}`)
}
> >
<Stack gap="md"> <Stack gap="md">
<Flex align="center" justify="space-between"> <Flex align="center" justify="space-between">