upd: list pengaduan dashboard
This commit is contained in:
@@ -12,11 +12,10 @@ import {
|
||||
Title
|
||||
} from "@mantine/core";
|
||||
import { useShallowEffect } from "@mantine/hooks";
|
||||
import { showNotification } from "@mantine/notifications";
|
||||
import { IconAlignJustified, IconClockHour3, IconMapPin } from "@tabler/icons-react";
|
||||
import { IconAlignJustified, IconClockHour3, IconFileSad, IconMapPin } from "@tabler/icons-react";
|
||||
import { useLocation, useNavigate } from "react-router-dom";
|
||||
import useSwr from "swr";
|
||||
import { proxy, subscribe } from "valtio";
|
||||
import { proxy } from "valtio";
|
||||
|
||||
const state = proxy({ reload: "" });
|
||||
function reloadState() {
|
||||
@@ -26,9 +25,7 @@ function reloadState() {
|
||||
export default function PengaduanListPage() {
|
||||
const { search } = useLocation();
|
||||
const query = new URLSearchParams(search);
|
||||
|
||||
const status = query.get("status");
|
||||
console.log(status, "status");
|
||||
|
||||
return (
|
||||
<Container
|
||||
@@ -38,7 +35,7 @@ export default function PengaduanListPage() {
|
||||
>
|
||||
<Stack gap="xl">
|
||||
<TabListPengaduan status={status || "all"} />
|
||||
<ListPengaduan />
|
||||
<ListPengaduan status={status || "all"} />
|
||||
</Stack>
|
||||
</Container>
|
||||
);
|
||||
@@ -46,47 +43,40 @@ export default function PengaduanListPage() {
|
||||
|
||||
function TabListPengaduan({ status }: { status: string }) {
|
||||
const navigate = useNavigate();
|
||||
const dataCount = useSwr("/pengaduan/count", () =>
|
||||
apiFetch.api.pengaduan.count.get().then((res) => res.data)
|
||||
);
|
||||
|
||||
return (
|
||||
<Tabs defaultValue={status || "all"} color="teal">
|
||||
<Tabs.List grow>
|
||||
<Tabs.Tab value="all" onClick={() => { navigate("?status=all") }}>Semua</Tabs.Tab>
|
||||
<Tabs.Tab value="antrian" onClick={() => { navigate("?status=antrian") }}>Antrian</Tabs.Tab>
|
||||
<Tabs.Tab value="diterima" onClick={() => { navigate("?status=diterima") }}>Diterima</Tabs.Tab>
|
||||
<Tabs.Tab value="dikerjakan" onClick={() => { navigate("?status=dikerjakan") }}>Dikerjakan</Tabs.Tab>
|
||||
<Tabs.Tab value="ditolak" onClick={() => { navigate("?status=ditolak") }}>Ditolak</Tabs.Tab>
|
||||
<Tabs.Tab value="selesai" onClick={() => { navigate("?status=selesai") }}>Selesai</Tabs.Tab>
|
||||
<Tabs.Tab value="all" onClick={() => { navigate("?status=all") }}>Semua ({dataCount?.data?.semua || 0})</Tabs.Tab>
|
||||
<Tabs.Tab value="antrian" onClick={() => { navigate("?status=antrian") }}>Antrian ({dataCount?.data?.antrian || 0})</Tabs.Tab>
|
||||
<Tabs.Tab value="diterima" onClick={() => { navigate("?status=diterima") }}>Diterima ({dataCount?.data?.diterima || 0})</Tabs.Tab>
|
||||
<Tabs.Tab value="dikerjakan" onClick={() => { navigate("?status=dikerjakan") }}>Dikerjakan ({dataCount?.data?.dikerjakan || 0})</Tabs.Tab>
|
||||
<Tabs.Tab value="selesai" onClick={() => { navigate("?status=selesai") }}>Selesai ({dataCount?.data?.selesai || 0})</Tabs.Tab>
|
||||
<Tabs.Tab value="ditolak" onClick={() => { navigate("?status=ditolak") }}>Ditolak ({dataCount?.data?.ditolak || 0})</Tabs.Tab>
|
||||
</Tabs.List>
|
||||
</Tabs>
|
||||
);
|
||||
}
|
||||
|
||||
function ListPengaduan() {
|
||||
function ListPengaduan({ status }: { status: string }) {
|
||||
const { data, mutate, isLoading } = useSwr("/", () =>
|
||||
apiFetch.api.credential.list.get(),
|
||||
apiFetch.api.pengaduan.list.get({
|
||||
query: {
|
||||
status,
|
||||
search: "",
|
||||
take: "",
|
||||
page: ""
|
||||
},
|
||||
}),
|
||||
);
|
||||
|
||||
useShallowEffect(() => {
|
||||
const unsubscribe = subscribe(state, () => mutate());
|
||||
return () => unsubscribe();
|
||||
}, []);
|
||||
mutate();
|
||||
}, [status]);
|
||||
|
||||
async function handleRemove(id: string) {
|
||||
try {
|
||||
await apiFetch.api.credential.rm.delete({ id });
|
||||
showNotification({
|
||||
color: "teal",
|
||||
title: "Credential Deleted",
|
||||
message: "The credential was successfully removed.",
|
||||
});
|
||||
reloadState();
|
||||
} catch {
|
||||
showNotification({
|
||||
color: "red",
|
||||
title: "Error",
|
||||
message: "Failed to delete credential. Please try again.",
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
if (isLoading)
|
||||
return (
|
||||
@@ -100,87 +90,103 @@ function ListPengaduan() {
|
||||
}}
|
||||
>
|
||||
<Text size="sm" c="dimmed">
|
||||
Loading credentials...
|
||||
Loading pengaduan...
|
||||
</Text>
|
||||
</Card>
|
||||
);
|
||||
|
||||
const list = data?.data?.list || [];
|
||||
const list = data?.data || [];
|
||||
|
||||
return (
|
||||
<Card
|
||||
radius="lg"
|
||||
p="xl"
|
||||
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={3} c="gray.2">
|
||||
Dompet Hilang
|
||||
</Title>
|
||||
<Group>
|
||||
<Title order={6} c="gray.5">
|
||||
#PGD-061125-001
|
||||
</Title>
|
||||
<Text size="sm" c="dimmed">
|
||||
updated 2 minutes ago
|
||||
<Stack gap="xl">
|
||||
{
|
||||
list.length === 0 ? (
|
||||
<Flex justify="center" align="center" py={"xl"}>
|
||||
<Stack gap={4} align="center">
|
||||
<IconFileSad size={32} color="gray" />
|
||||
<Text c="dimmed" size="sm">
|
||||
No pengaduan have been added yet.
|
||||
</Text>
|
||||
</Group>
|
||||
</Stack>
|
||||
</Flex>
|
||||
<Badge
|
||||
size="xl"
|
||||
variant="light"
|
||||
radius="sm"
|
||||
color="gray"
|
||||
style={{ textTransform: "none" }}
|
||||
>
|
||||
Antrian
|
||||
</Badge>
|
||||
</Flex>
|
||||
<Divider my={0} />
|
||||
<Stack gap="sm">
|
||||
<Flex direction={"column"} justify="flex-start">
|
||||
<Group gap="xs">
|
||||
<IconClockHour3 size={20} color="white" />
|
||||
<Text size="md" c="white">
|
||||
Tanggal Aduan
|
||||
</Text>
|
||||
</Group>
|
||||
<Text size="md">
|
||||
05 November 2025
|
||||
</Text>
|
||||
</Flex>
|
||||
<Flex direction={"column"} justify="flex-start">
|
||||
<Group gap="xs">
|
||||
<IconMapPin size={20} color="white" />
|
||||
<Text size="md" c="white">
|
||||
Lokasi
|
||||
</Text>
|
||||
</Group>
|
||||
<Text size="md">
|
||||
Jalan Darmasaba Raya no 77
|
||||
</Text>
|
||||
</Flex>
|
||||
<Flex direction={"column"} justify="flex-start">
|
||||
<Group gap="xs">
|
||||
<IconAlignJustified size={20} color="white" />
|
||||
<Text size="md" c="white">
|
||||
Detail
|
||||
</Text>
|
||||
</Group>
|
||||
<Text size="md">
|
||||
Lorem, ipsum dolor sit amet consectetur adipisicing elit. Quis, obcaecati. Sint natus culpa temporibus neque quasi expedita ratione, facere optio incidunt quibusdam suscipit nam nemo delectus beatae similique velit obcaecati?
|
||||
</Text>
|
||||
</Flex>
|
||||
</Stack>
|
||||
</Stack>
|
||||
</Card>
|
||||
) :
|
||||
list.map((v: any) => (
|
||||
<Card
|
||||
key={v.id}
|
||||
radius="lg"
|
||||
p="xl"
|
||||
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={3} c="gray.2">
|
||||
{v.title}
|
||||
</Title>
|
||||
<Group>
|
||||
<Title order={6} c="gray.5">
|
||||
#{v.noPengaduan}
|
||||
</Title>
|
||||
<Text size="sm" c="dimmed">
|
||||
{v.updatedAt}
|
||||
</Text>
|
||||
</Group>
|
||||
</Flex>
|
||||
<Badge
|
||||
size="xl"
|
||||
variant="light"
|
||||
radius="sm"
|
||||
color={v.status === "diterima" ? "green" : v.status === "ditolak" ? "red" : v.status === "selesai" ? "blue" : v.status === "dikerjakan" ? "purple" : "yellow"}
|
||||
style={{ textTransform: "none" }}
|
||||
>
|
||||
{v.status}
|
||||
</Badge>
|
||||
</Flex>
|
||||
<Divider my={0} />
|
||||
<Stack gap="sm">
|
||||
<Flex direction={"column"} justify="flex-start">
|
||||
<Group gap="xs">
|
||||
<IconClockHour3 size={20} color="white" />
|
||||
<Text size="md" c="white">
|
||||
Tanggal Aduan
|
||||
</Text>
|
||||
</Group>
|
||||
<Text size="md">
|
||||
{v.createdAt}
|
||||
</Text>
|
||||
</Flex>
|
||||
<Flex direction={"column"} justify="flex-start">
|
||||
<Group gap="xs">
|
||||
<IconMapPin size={20} color="white" />
|
||||
<Text size="md" c="white">
|
||||
Lokasi
|
||||
</Text>
|
||||
</Group>
|
||||
<Text size="md">
|
||||
{v.location}
|
||||
</Text>
|
||||
</Flex>
|
||||
<Flex direction={"column"} justify="flex-start">
|
||||
<Group gap="xs">
|
||||
<IconAlignJustified size={20} color="white" />
|
||||
<Text size="md" c="white">
|
||||
Detail
|
||||
</Text>
|
||||
</Group>
|
||||
<Text size="md">
|
||||
{v.detail}
|
||||
</Text>
|
||||
</Flex>
|
||||
</Stack>
|
||||
</Stack>
|
||||
</Card>
|
||||
))}
|
||||
</Stack>
|
||||
);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user