update dashboard admin

Deskripsi:
- list warga
- detail warga

No Issues
This commit is contained in:
2025-11-14 17:19:50 +08:00
parent 6c6ee02cf0
commit 67c066990e
13 changed files with 2014 additions and 1509 deletions

View File

@@ -172,7 +172,7 @@ function ListPelayananSurat({ status }: { status: StatusKey }) {
}
/>
</Group>
{list.length === 0 ? (
{list?.length === 0 ? (
<Flex justify="center" align="center" py={"xl"}>
<Stack gap={4} align="center">
<IconFileSad size={32} color="gray" />
@@ -182,7 +182,7 @@ function ListPelayananSurat({ status }: { status: StatusKey }) {
</Stack>
</Flex>
) : (
list.map((v: any) => (
list?.map((v: any) => (
<Card
key={v.id}
radius="lg"

View File

@@ -67,13 +67,12 @@ function DetailDataPengaduan() {
fileName: "57d5ce89-7d18-4244-9f4c-ca21b70adb7e",
},
});
console.error('client',res)
console.error("client", res);
// const blob = await res.data?.blob();
// setImageSrc(URL.createObjectURL(blob!));
// openModalImage();
}
return (
<>
<Modal

View File

@@ -186,7 +186,7 @@ function ListPengaduan({ status }: { status: StatusKey }) {
</Stack>
</Flex>
) : (
list.map((v: any) => (
list?.map((v: any) => (
<Card
key={v.id}
radius="lg"

View File

@@ -13,14 +13,14 @@ import {
NavLink,
Stack,
Table,
Title
Title,
} from "@mantine/core";
import {
IconBuildingBank,
IconCategory2,
IconMailSpark,
IconUserCog,
IconUsersGroup
IconUsersGroup,
} from "@tabler/icons-react";
import { useLocation } from "react-router-dom";
@@ -104,4 +104,4 @@ export default function DetailSettingPage() {
</Grid>
</Container>
);
}
}

View File

@@ -2,62 +2,66 @@ import apiFetch from "@/lib/apiFetch";
import {
Avatar,
Box,
Button,
Card,
Container,
Divider,
Flex,
Grid,
Group,
LoadingOverlay,
Stack,
Table,
Text,
Title,
} from "@mantine/core";
import { useShallowEffect } from "@mantine/hooks";
import { IconMail, IconMapPin, IconPhone } from "@tabler/icons-react";
import { useState } from "react";
import { useLocation } from "react-router-dom";
import { IconPhone } from "@tabler/icons-react";
import _ from "lodash";
import { useLocation, useNavigate } from "react-router-dom";
import useSwr from "swr";
export default function DetailWargaPage() {
const { search } = useLocation();
const query = new URLSearchParams(search);
const id = query.get("id");
const { data, mutate, isLoading } = useSwr("/", () =>
apiFetch.api.warga.detail.get({
query: {
id: id!,
},
}),
);
useShallowEffect(() => {
mutate();
}, []);
return (
<Container size="xl" py="xl" w={"100%"}>
<Grid>
<Grid.Col span={4}>
<DetailWarga />
</Grid.Col>
<Grid.Col span={8}>
<Stack gap={"xl"}>
<DetailDataHistori />
<DetailDataHistori />
</Stack>
</Grid.Col>
</Grid>
</Container>
<>
<LoadingOverlay visible={isLoading} zIndex={1000} overlayProps={{ radius: "sm", blur: 2 }} />
<Container size="xl" py="xl" w={"100%"}>
<Grid>
<Grid.Col span={4}>
<DetailWarga data={data?.data?.warga} />
</Grid.Col>
<Grid.Col span={8}>
<Stack gap={"xl"}>
<DetailDataHistori data={data?.data?.pengaduan} kategori="pengaduan" />
<DetailDataHistori data={data?.data?.pelayanan} kategori="pelayanan" />
</Stack>
</Grid.Col>
</Grid>
</Container>
</>
);
}
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" },
];
function DetailDataHistori({ data, kategori }: { data: any, kategori: 'pengaduan' | 'pelayanan' }) {
const navigate = useNavigate();
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"
@@ -73,46 +77,59 @@ function DetailDataHistori() {
<Stack gap="md">
<Flex align="center" justify="space-between">
<Title order={4} c="gray.2">
Histori Pengaduan
Histori {_.upperFirst(kategori)}
</Title>
</Flex>
<Divider my={0} />
<Table>
<Table.Thead>
<Table.Tr>
<Table.Th>Tanggal</Table.Th>
<Table.Th>Deskripsi</Table.Th>
<Table.Th>No {_.upperFirst(kategori)}</Table.Th>
<Table.Th>{kategori == "pengaduan" ? "Judul" : "Kategori"}</Table.Th>
<Table.Th>Status</Table.Th>
<Table.Th>User</Table.Th>
<Table.Th></Table.Th>
</Table.Tr>
</Table.Thead>
<Table.Tbody>{rows}</Table.Tbody>
<Table.Tbody>
{
data?.length > 0 ? (
data?.map((item: any, index: number) => (
<Table.Tr key={index}>
<Table.Td>{item.noPengaduan}</Table.Td>
<Table.Td>{kategori == "pengaduan" ? item.title : item.category}</Table.Td>
<Table.Td>{item.status}</Table.Td>
<Table.Td>
<Button
variant="outline"
onClick={() => {
kategori == "pengaduan" ?
navigate(
`/scr/dashboard/pengaduan/detail?id=${item.id}`,
) :
navigate(
`/scr/dashboard/pelayanan-surat/detail-pelayanan?id=${item.id}`,
)
}}
>
Detail
</Button>
</Table.Td>
</Table.Tr>
))
) : (
<Table.Tr>
<Table.Td colSpan={4} align="center">Tidak ada data</Table.Td>
</Table.Tr>
)
}
</Table.Tbody>
</Table>
</Stack>
</Card>
);
}
function DetailWarga() {
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 || [];
function DetailWarga({ data }: { data: any }) {
return (
<Card
radius="md"
@@ -122,38 +139,40 @@ function DetailWarga() {
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)",
boxShadow: "0 0 20px #00ffc814",
}}
>
<Box
style={{
backgroundColor: "#f7d86c",
background:
"linear-gradient(to left top, #23633a, #00685b, #006984, #0065a5, #0059b1, #114ca3, #193f94, #1d3285, #202864, #1d1f45, #171628, #0b0b0b)",
height: 100,
borderRadius: "12px",
position: "relative",
}}
/>
<Group>
{/* Profile image */}
<Avatar
src="https://i.pravatar.cc/150?img=32"
radius={100}
size={90}
style={{
position: "absolute",
top: 80,
left: 30,
border: "4px solid white",
border: "3x solid white",
backgroundColor: "#099268",
}}
/>
>
A
</Avatar>
{/* Main content */}
<Stack ml={115} gap={4}>
<Text fw={700} fz="lg">
Lizbeth Moore
{data?.name}
</Text>
<Text fz="sm" c="dimmed">
Social Media Strategies
Warga Desa
</Text>
</Stack>
</Group>
@@ -161,19 +180,9 @@ function DetailWarga() {
{/* Contact info */}
<Card radius="md" mt="md" p="md" withBorder={false}>
<Stack gap="xs">
<Group gap="xs">
<IconMail size={18} />
<Text size="sm">lizbeth.moore@email.com</Text>
</Group>
<Group gap="xs">
<IconPhone size={18} />
<Text size="sm">+1 555-7788</Text>
</Group>
<Group gap="xs">
<IconMapPin size={18} />
<Text size="sm">Greenway Ave, Los Angeles, CA, USA</Text>
<Text size="sm">{data?.phone}</Text>
</Group>
</Stack>
</Card>

View File

@@ -1,3 +1,4 @@
import apiFetch from "@/lib/apiFetch";
import {
Button,
Card,
@@ -10,41 +11,30 @@ import {
Table,
Title,
} from "@mantine/core";
import { useShallowEffect } from "@mantine/hooks";
import { IconSearch } from "@tabler/icons-react";
import { useState } from "react";
import { useNavigate } from "react-router-dom";
import useSWR from "swr";
export default function ListWargaPage() {
const navigate = useNavigate();
const [value, setValue] = useState("");
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 { data, mutate, isLoading } = useSWR("/", () =>
apiFetch.api.warga.list.get({
query: {
search: value,
},
}),
);
const list = data?.data || [];
const [value, setValue] = useState("");
useShallowEffect(() => {
mutate();
}, [value]);
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.Td>
<Button
variant="outline"
onClick={() => {
navigate(
`/scr/dashboard/warga/detail-warga?id=${element.position}`,
);
}}
>
Detail
</Button>
</Table.Td>
</Table.Tr>
));
return (
<Container size="xl" py="xl" w={"100%"}>
@@ -81,14 +71,39 @@ export default function ListWargaPage() {
<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.Th>Nama</Table.Th>
<Table.Th>No Telepon</Table.Th>
<Table.Th>Aksi</Table.Th>
</Table.Tr>
</Table.Thead>
<Table.Tbody>{rows}</Table.Tbody>
<Table.Tbody>
{
list?.length === 0 ? (
<Table.Tr>
<Table.Td colSpan={3} align="center">Tidak ada data</Table.Td>
</Table.Tr>
) : (
list?.map((item, i) => (
<Table.Tr key={i}>
<Table.Td>{item.name}</Table.Td>
<Table.Td>{item.phone}</Table.Td>
<Table.Td>
<Button
variant="outline"
onClick={() => {
navigate(
`/scr/dashboard/warga/detail-warga?id=${item.id}`,
);
}}
>
Detail
</Button>
</Table.Td>
</Table.Tr>
))
)
}
</Table.Tbody>
</Table>
</Stack>
</Card>