Fix New UI Pengaduan
This commit is contained in:
168
Pengaduan-New.md
Normal file
168
Pengaduan-New.md
Normal file
@@ -0,0 +1,168 @@
|
|||||||
|
Create a modern analytics dashboard UI for a village complaint system (Pengaduan Dashboard).
|
||||||
|
|
||||||
|
Tech stack:
|
||||||
|
- React 19 + Vite (Bun runtime)
|
||||||
|
- Mantine UI (core components)
|
||||||
|
- TailwindCSS (layout & spacing only)
|
||||||
|
- Recharts (charts)
|
||||||
|
- TanStack Router
|
||||||
|
- Icons: lucide-react
|
||||||
|
- State: Valtio
|
||||||
|
- Date: dayjs
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 🎨 DESIGN STYLE
|
||||||
|
|
||||||
|
- Clean, minimal, and soft dashboard
|
||||||
|
- Background: light gray (#f3f4f6)
|
||||||
|
- Card: white with subtle shadow
|
||||||
|
- Border radius: 16px–24px (rounded-2xl)
|
||||||
|
- Typography: medium contrast (not too bold)
|
||||||
|
- Primary color: navy blue (#1E3A5F)
|
||||||
|
- Accent: soft blue + neutral gray
|
||||||
|
- Icons inside circular solid background
|
||||||
|
|
||||||
|
Spacing:
|
||||||
|
- Use gap-6 consistently
|
||||||
|
- Internal padding: p-5 or p-6
|
||||||
|
- Layout must feel breathable (no clutter)
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 🧱 LAYOUT STRUCTURE
|
||||||
|
|
||||||
|
### 🔹 TOP SECTION (4 STAT CARDS - GRID)
|
||||||
|
Grid: 4 columns (responsive → 2 / 1)
|
||||||
|
|
||||||
|
Each card contains:
|
||||||
|
- Title (small, muted)
|
||||||
|
- Big number (bold, large)
|
||||||
|
- Subtitle (small gray text)
|
||||||
|
- Right side: circular icon container
|
||||||
|
|
||||||
|
Example:
|
||||||
|
- Total Pengaduan → 42 → "Bulan ini"
|
||||||
|
- Baru → 14 → "Belum diproses"
|
||||||
|
- Diproses → 14 → "Sedang ditangani"
|
||||||
|
- Selesai → 14 → "Terselesaikan"
|
||||||
|
|
||||||
|
Use:
|
||||||
|
- Mantine Card
|
||||||
|
- Group justify="space-between"
|
||||||
|
- Icon inside circle (bg navy, icon white)
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 📈 MAIN CHART (FULL WIDTH)
|
||||||
|
Title: "Tren Pengaduan"
|
||||||
|
|
||||||
|
- Use Recharts LineChart
|
||||||
|
- Smooth line (monotone)
|
||||||
|
- Show dots on each point
|
||||||
|
- Data: Apr → Okt
|
||||||
|
- Value range: 30–60
|
||||||
|
|
||||||
|
Style:
|
||||||
|
- Minimal grid (light dashed)
|
||||||
|
- No heavy colors (use gray/blue line)
|
||||||
|
- Rounded container card
|
||||||
|
- Add small top-right icon (expand)
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 📊 BOTTOM SECTION (3 COLUMN GRID)
|
||||||
|
|
||||||
|
### 🔹 LEFT: "Surat Terbanyak"
|
||||||
|
- Horizontal bar chart (Recharts)
|
||||||
|
- Categories:
|
||||||
|
- KTP
|
||||||
|
- KK
|
||||||
|
- Domisili
|
||||||
|
- Usaha
|
||||||
|
- Lainnya
|
||||||
|
|
||||||
|
Style:
|
||||||
|
- Dark blue bars
|
||||||
|
- Rounded edges
|
||||||
|
- Clean axis
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
### 🔹 CENTER: "Pengajuan Terbaru"
|
||||||
|
List of activity cards:
|
||||||
|
|
||||||
|
Each item:
|
||||||
|
- Name (bold)
|
||||||
|
- Subtitle (jenis surat)
|
||||||
|
- Time (small text)
|
||||||
|
- Status badge (kanan)
|
||||||
|
|
||||||
|
Status:
|
||||||
|
- baru → red
|
||||||
|
- proses → blue
|
||||||
|
- selesai → green
|
||||||
|
|
||||||
|
Style:
|
||||||
|
- Card per item
|
||||||
|
- Soft border
|
||||||
|
- Rounded
|
||||||
|
- Compact spacing
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
### 🔹 RIGHT: "Ajuan Ide Inovatif"
|
||||||
|
List mirip dengan pengajuan terbaru:
|
||||||
|
|
||||||
|
Each item:
|
||||||
|
- Nama
|
||||||
|
- Judul ide
|
||||||
|
- Waktu
|
||||||
|
- Button kecil "Detail"
|
||||||
|
|
||||||
|
Style:
|
||||||
|
- Right-aligned action button
|
||||||
|
- Light border
|
||||||
|
- Clean spacing
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## ⚙️ COMPONENT STRUCTURE
|
||||||
|
|
||||||
|
components/
|
||||||
|
- StatCard.tsx
|
||||||
|
- LineChartCard.tsx
|
||||||
|
- BarChartCard.tsx
|
||||||
|
- ActivityList.tsx
|
||||||
|
- IdeaList.tsx
|
||||||
|
|
||||||
|
routes/
|
||||||
|
- dashboard.tsx
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## ✨ INTERACTIONS (IMPORTANT)
|
||||||
|
|
||||||
|
- Hover card → scale(1.02)
|
||||||
|
- Transition: 150ms ease
|
||||||
|
- Icon circle slightly pop on hover
|
||||||
|
- List item hover → subtle bg change
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 🎯 UX DETAILS
|
||||||
|
|
||||||
|
- Numbers must be visually dominant
|
||||||
|
- Icons must balance layout (not too big)
|
||||||
|
- Avoid heavy borders
|
||||||
|
- Keep everything aligned perfectly
|
||||||
|
- No clutter
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 🚀 OUTPUT
|
||||||
|
|
||||||
|
- Modular React components (NOT one file)
|
||||||
|
- Clean code (production-ready)
|
||||||
|
- Use Mantine properly (no hacky inline styles unless needed)
|
||||||
|
- Use Tailwind only for layout/grid/spacing
|
||||||
@@ -1,32 +1,16 @@
|
|||||||
import {
|
import {
|
||||||
ActionIcon,
|
|
||||||
Badge,
|
Badge,
|
||||||
Box,
|
|
||||||
Button,
|
Button,
|
||||||
Card,
|
Card,
|
||||||
Divider,
|
|
||||||
Grid,
|
Grid,
|
||||||
GridCol,
|
|
||||||
Group,
|
Group,
|
||||||
List,
|
|
||||||
Select,
|
|
||||||
Stack,
|
Stack,
|
||||||
Table,
|
|
||||||
Text,
|
Text,
|
||||||
Textarea,
|
ThemeIcon,
|
||||||
TextInput,
|
|
||||||
Title,
|
Title,
|
||||||
useMantineColorScheme,
|
useMantineColorScheme
|
||||||
} from "@mantine/core";
|
} from "@mantine/core";
|
||||||
import {
|
import { CheckCircle, Clock, FileText, MessageCircle } from "lucide-react";
|
||||||
IconAlertTriangle,
|
|
||||||
IconCheck,
|
|
||||||
IconChevronRight,
|
|
||||||
IconClock,
|
|
||||||
IconMessage,
|
|
||||||
} from "@tabler/icons-react";
|
|
||||||
import type React from "react";
|
|
||||||
import { useState } from "react";
|
|
||||||
import {
|
import {
|
||||||
Bar,
|
Bar,
|
||||||
BarChart,
|
BarChart,
|
||||||
@@ -39,26 +23,47 @@ import {
|
|||||||
YAxis,
|
YAxis,
|
||||||
} from "recharts";
|
} from "recharts";
|
||||||
|
|
||||||
const PengaduanLayananPublik = () => {
|
|
||||||
const { colorScheme } = useMantineColorScheme();
|
|
||||||
const dark = colorScheme === "dark";
|
|
||||||
|
|
||||||
// Summary data
|
// Summary data
|
||||||
const summaryData = {
|
const summaryData = [
|
||||||
total: 42,
|
{
|
||||||
baru: 14,
|
title: "Total Pengaduan",
|
||||||
diproses: 14,
|
value: 42,
|
||||||
selesai: 14,
|
subtitle: "Bulan ini",
|
||||||
};
|
icon: MessageCircle,
|
||||||
|
color: "#1E3A5F",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: "Baru",
|
||||||
|
value: 14,
|
||||||
|
subtitle: "Belum diproses",
|
||||||
|
icon: FileText,
|
||||||
|
color: "#1E3A5F",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: "Diproses",
|
||||||
|
value: 14,
|
||||||
|
subtitle: "Sedang ditangani",
|
||||||
|
icon: Clock,
|
||||||
|
color: "#1E3A5F",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: "Selesai",
|
||||||
|
value: 14,
|
||||||
|
subtitle: "Terselesaikan",
|
||||||
|
icon: CheckCircle,
|
||||||
|
color: "#1E3A5F",
|
||||||
|
},
|
||||||
|
];
|
||||||
|
|
||||||
// Tren pengaduan data
|
// Tren pengaduan data
|
||||||
const trenData = [
|
const trenData = [
|
||||||
{ bulan: "Jan", jumlah: 30 },
|
{ bulan: "Apr", jumlah: 35 },
|
||||||
{ bulan: "Feb", jumlah: 50 },
|
{ bulan: "Mei", jumlah: 48 },
|
||||||
{ bulan: "Mar", jumlah: 42 },
|
|
||||||
{ bulan: "Apr", jumlah: 38 },
|
|
||||||
{ bulan: "Mei", jumlah: 45 },
|
|
||||||
{ bulan: "Jun", jumlah: 42 },
|
{ bulan: "Jun", jumlah: 42 },
|
||||||
|
{ bulan: "Jul", jumlah: 55 },
|
||||||
|
{ bulan: "Agu", jumlah: 50 },
|
||||||
|
{ bulan: "Sep", jumlah: 58 },
|
||||||
|
{ bulan: "Okt", jumlah: 52 },
|
||||||
];
|
];
|
||||||
|
|
||||||
// Surat terbanyak data
|
// Surat terbanyak data
|
||||||
@@ -82,7 +87,7 @@ const PengaduanLayananPublik = () => {
|
|||||||
nama: "Siti Rahayu",
|
nama: "Siti Rahayu",
|
||||||
jenis: "Pelayanan Kesehatan",
|
jenis: "Pelayanan Kesehatan",
|
||||||
waktu: "5 jam yang lalu",
|
waktu: "5 jam yang lalu",
|
||||||
status: "diproses",
|
status: "proses",
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
nama: "Ahmad Fauzi",
|
nama: "Ahmad Fauzi",
|
||||||
@@ -100,7 +105,7 @@ const PengaduanLayananPublik = () => {
|
|||||||
nama: "Joko Widodo",
|
nama: "Joko Widodo",
|
||||||
jenis: "Keamanan",
|
jenis: "Keamanan",
|
||||||
waktu: "2 hari yang lalu",
|
waktu: "2 hari yang lalu",
|
||||||
status: "diproses",
|
status: "proses",
|
||||||
},
|
},
|
||||||
];
|
];
|
||||||
|
|
||||||
@@ -109,187 +114,35 @@ const PengaduanLayananPublik = () => {
|
|||||||
{
|
{
|
||||||
nama: "Andi Prasetyo",
|
nama: "Andi Prasetyo",
|
||||||
judul: "Penerapan Smart Village",
|
judul: "Penerapan Smart Village",
|
||||||
|
waktu: "3 hari yang lalu",
|
||||||
kategori: "Teknologi",
|
kategori: "Teknologi",
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
nama: "Rina Kusuma",
|
nama: "Rina Kusuma",
|
||||||
judul: "Program Ekowisata Desa",
|
judul: "Program Ekowisata Desa",
|
||||||
|
waktu: "5 hari yang lalu",
|
||||||
kategori: "Ekonomi",
|
kategori: "Ekonomi",
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
nama: "Bambang Suryono",
|
nama: "Bambang Suryono",
|
||||||
judul: "Peningkatan Sanitasi",
|
judul: "Peningkatan Sanitasi",
|
||||||
|
waktu: "1 minggu yang lalu",
|
||||||
kategori: "Kesehatan",
|
kategori: "Kesehatan",
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
nama: "Lina Marlina",
|
nama: "Lina Marlina",
|
||||||
judul: "Pusat Kreatif Anak Muda",
|
judul: "Pusat Kreatif Anak Muda",
|
||||||
|
waktu: "2 minggu yang lalu",
|
||||||
kategori: "Pendidikan",
|
kategori: "Pendidikan",
|
||||||
},
|
},
|
||||||
];
|
];
|
||||||
|
|
||||||
const [activeTab, setActiveTab] = useState<"complaints" | "services">(
|
|
||||||
"complaints",
|
|
||||||
);
|
|
||||||
const [newComplaint, setNewComplaint] = useState({
|
|
||||||
title: "",
|
|
||||||
category: "",
|
|
||||||
description: "",
|
|
||||||
});
|
|
||||||
|
|
||||||
// Sample data for complaints
|
|
||||||
const complaints = [
|
|
||||||
{
|
|
||||||
id: 1,
|
|
||||||
title: "Jalan Rusak di Jalan Raya",
|
|
||||||
category: "Infrastruktur",
|
|
||||||
status: "Pending",
|
|
||||||
priority: "High",
|
|
||||||
date: "2024-02-01",
|
|
||||||
reporter: "Bapak Ahmad",
|
|
||||||
},
|
|
||||||
{
|
|
||||||
id: 2,
|
|
||||||
title: "Pemadaman Listrik Berkelanjutan",
|
|
||||||
category: "Utilitas",
|
|
||||||
status: "In Progress",
|
|
||||||
priority: "Medium",
|
|
||||||
date: "2024-02-03",
|
|
||||||
reporter: "Ibu Sari",
|
|
||||||
},
|
|
||||||
{
|
|
||||||
id: 3,
|
|
||||||
title: "Pelayanan Administrasi Lambat",
|
|
||||||
category: "Administrasi",
|
|
||||||
status: "Resolved",
|
|
||||||
priority: "Low",
|
|
||||||
date: "2024-01-28",
|
|
||||||
reporter: "Pak Joko",
|
|
||||||
},
|
|
||||||
{
|
|
||||||
id: 4,
|
|
||||||
title: "Kebersihan Lingkungan",
|
|
||||||
category: "Sanitasi",
|
|
||||||
status: "Pending",
|
|
||||||
priority: "Medium",
|
|
||||||
date: "2024-02-05",
|
|
||||||
reporter: "Bu Dewi",
|
|
||||||
},
|
|
||||||
];
|
|
||||||
|
|
||||||
// Sample data for public services
|
|
||||||
const services = [
|
|
||||||
{
|
|
||||||
id: 1,
|
|
||||||
name: "Pembuatan KTP",
|
|
||||||
description:
|
|
||||||
"Pelayanan pembuatan Kartu Tanda Penduduk baru atau perpanjangan",
|
|
||||||
status: "Available",
|
|
||||||
category: "Administrasi",
|
|
||||||
lastUpdated: "2024-02-01",
|
|
||||||
},
|
|
||||||
{
|
|
||||||
id: 2,
|
|
||||||
name: "Pembuatan Surat Keterangan Usaha",
|
|
||||||
description: "Surat keterangan untuk keperluan usaha atau perizinan",
|
|
||||||
status: "Available",
|
|
||||||
category: "Administrasi",
|
|
||||||
lastUpdated: "2024-02-02",
|
|
||||||
},
|
|
||||||
{
|
|
||||||
id: 3,
|
|
||||||
name: "Pelayanan Kesehatan",
|
|
||||||
description: "Pelayanan kesehatan dasar di puskesmas desa",
|
|
||||||
status: "Available",
|
|
||||||
category: "Kesehatan",
|
|
||||||
lastUpdated: "2024-01-30",
|
|
||||||
},
|
|
||||||
{
|
|
||||||
id: 4,
|
|
||||||
name: "Program Bantuan Sosial",
|
|
||||||
description:
|
|
||||||
"Informasi dan pendaftaran program bantuan sosial dari pemerintah",
|
|
||||||
status: "Limited",
|
|
||||||
category: "Sosial",
|
|
||||||
lastUpdated: "2024-02-04",
|
|
||||||
},
|
|
||||||
];
|
|
||||||
|
|
||||||
const handleInputChange = (
|
|
||||||
e: React.ChangeEvent<HTMLInputElement | HTMLTextAreaElement>,
|
|
||||||
) => {
|
|
||||||
const { name, value } = e.target;
|
|
||||||
setNewComplaint((prev) => ({
|
|
||||||
...prev,
|
|
||||||
[name]: value,
|
|
||||||
}));
|
|
||||||
};
|
|
||||||
|
|
||||||
const handleSelectChange = (value: string | null) => {
|
|
||||||
setNewComplaint((prev) => ({
|
|
||||||
...prev,
|
|
||||||
category: value || "", // Ensure category is always a string
|
|
||||||
}));
|
|
||||||
};
|
|
||||||
|
|
||||||
const handleSubmitComplaint = (e: React.FormEvent) => {
|
|
||||||
e.preventDefault();
|
|
||||||
console.log("Submitting complaint:", newComplaint);
|
|
||||||
// Here you would typically send the complaint to your backend
|
|
||||||
alert("Pengaduan berhasil dikirim!");
|
|
||||||
setNewComplaint({ title: "", category: "", description: "" });
|
|
||||||
};
|
|
||||||
|
|
||||||
// Render complaint table rows
|
|
||||||
const complaintRows = complaints.map((complaint) => (
|
|
||||||
<Table.Tr key={complaint.id}>
|
|
||||||
<Table.Td className="font-medium">
|
|
||||||
<Text c={dark ? "white" : "dark.3"}>{complaint.title}</Text>
|
|
||||||
</Table.Td>
|
|
||||||
<Table.Td>
|
|
||||||
<Text c={dark ? "white" : "dark.3"}>{complaint.category}</Text>
|
|
||||||
</Table.Td>
|
|
||||||
<Table.Td>
|
|
||||||
<Badge
|
|
||||||
variant="filled"
|
|
||||||
color={
|
|
||||||
complaint.status === "Resolved"
|
|
||||||
? "green"
|
|
||||||
: complaint.status === "In Progress"
|
|
||||||
? "yellow"
|
|
||||||
: "red"
|
|
||||||
}
|
|
||||||
>
|
|
||||||
{complaint.status}
|
|
||||||
</Badge>
|
|
||||||
</Table.Td>
|
|
||||||
<Table.Td>
|
|
||||||
<Badge
|
|
||||||
variant="filled"
|
|
||||||
color={
|
|
||||||
complaint.priority === "High"
|
|
||||||
? "red"
|
|
||||||
: complaint.priority === "Medium"
|
|
||||||
? "yellow"
|
|
||||||
: "blue"
|
|
||||||
}
|
|
||||||
>
|
|
||||||
{complaint.priority}
|
|
||||||
</Badge>
|
|
||||||
</Table.Td>
|
|
||||||
<Table.Td>
|
|
||||||
<Text c={dark ? "white" : "dark.3"}>{complaint.date}</Text>
|
|
||||||
</Table.Td>
|
|
||||||
</Table.Tr>
|
|
||||||
));
|
|
||||||
|
|
||||||
// Status badge color mapping
|
|
||||||
const getStatusColor = (status: string) => {
|
const getStatusColor = (status: string) => {
|
||||||
switch (status) {
|
switch (status) {
|
||||||
case "baru":
|
case "baru":
|
||||||
return "red";
|
return "red";
|
||||||
case "diproses":
|
case "proses":
|
||||||
return "yellow";
|
return "blue";
|
||||||
case "selesai":
|
case "selesai":
|
||||||
return "green";
|
return "green";
|
||||||
default:
|
default:
|
||||||
@@ -297,284 +150,202 @@ const PengaduanLayananPublik = () => {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const PengaduanLayananPublik = () => {
|
||||||
|
const { colorScheme } = useMantineColorScheme();
|
||||||
|
const dark = colorScheme === "dark";
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Stack gap="lg">
|
<Stack gap="lg">
|
||||||
{activeTab === "complaints" ? (
|
{/* TOP SECTION - 4 STAT CARDS */}
|
||||||
<>
|
|
||||||
{/* Summary Cards */}
|
|
||||||
<Grid gutter="md">
|
<Grid gutter="md">
|
||||||
<GridCol span={{ base: 12, md: 6, lg: 3 }}>
|
{summaryData.map((item, index) => (
|
||||||
|
<Grid.Col key={index} span={{ base: 12, sm: 6, lg: 3 }}>
|
||||||
<Card
|
<Card
|
||||||
p="md"
|
p="md"
|
||||||
radius="md"
|
radius="xl"
|
||||||
withBorder
|
withBorder
|
||||||
bg={dark ? "#141D34" : "white"}
|
bg={dark ? "#1E293B" : "white"}
|
||||||
style={{ borderColor: dark ? "#141D34" : "white" }}
|
style={{
|
||||||
|
borderColor: dark ? "#334155" : "white",
|
||||||
|
boxShadow: "0 1px 3px 0 rgb(0 0 0 / 0.1)",
|
||||||
|
transition: "transform 0.15s ease, box-shadow 0.15s ease",
|
||||||
|
}}
|
||||||
h="100%"
|
h="100%"
|
||||||
>
|
>
|
||||||
<Group justify="space-between" align="center">
|
<Group justify="space-between" align="center" w="100%">
|
||||||
<Stack gap={0}>
|
<Stack gap={2}>
|
||||||
<Text size="sm" c={dark ? "dark.3" : "dimmed"}>
|
<Text size="sm" c="dimmed">
|
||||||
Total Pengaduan
|
{item.title}
|
||||||
</Text>
|
</Text>
|
||||||
<Text size="xl" fw={700} c={dark ? "dark.0" : "black"}>
|
<Text size="xl" fw={700} c={dark ? "white" : "gray.9"}>
|
||||||
{summaryData.total}
|
{item.value}
|
||||||
|
</Text>
|
||||||
|
<Text size="xs" c="dimmed">
|
||||||
|
{item.subtitle}
|
||||||
</Text>
|
</Text>
|
||||||
</Stack>
|
</Stack>
|
||||||
<Badge
|
<ThemeIcon
|
||||||
variant="light"
|
color={item.color}
|
||||||
color="darmasaba-blue"
|
variant="filled"
|
||||||
p={8}
|
size="lg"
|
||||||
radius="md"
|
radius="xl"
|
||||||
|
style={{
|
||||||
|
transition: "transform 0.15s ease",
|
||||||
|
}}
|
||||||
>
|
>
|
||||||
<IconMessage size={20} />
|
<item.icon style={{ width: "60%", height: "60%" }} />
|
||||||
</Badge>
|
</ThemeIcon>
|
||||||
</Group>
|
</Group>
|
||||||
</Card>
|
</Card>
|
||||||
</GridCol>
|
</Grid.Col>
|
||||||
|
))}
|
||||||
<GridCol span={{ base: 12, md: 6, lg: 3 }}>
|
|
||||||
<Card
|
|
||||||
p="md"
|
|
||||||
radius="md"
|
|
||||||
withBorder
|
|
||||||
bg={dark ? "#141D34" : "white"}
|
|
||||||
style={{ borderColor: dark ? "#141D34" : "white" }}
|
|
||||||
h="100%"
|
|
||||||
>
|
|
||||||
<Group justify="space-between" align="center">
|
|
||||||
<Stack gap={0}>
|
|
||||||
<Text size="sm" c={dark ? "dark.3" : "dimmed"}>
|
|
||||||
Baru
|
|
||||||
</Text>
|
|
||||||
<Text size="xl" fw={700} c={dark ? "dark.0" : "black"}>
|
|
||||||
{summaryData.baru}
|
|
||||||
</Text>
|
|
||||||
</Stack>
|
|
||||||
<Badge variant="light" color="red" p={8} radius="md">
|
|
||||||
<IconAlertTriangle size={20} />
|
|
||||||
</Badge>
|
|
||||||
</Group>
|
|
||||||
</Card>
|
|
||||||
</GridCol>
|
|
||||||
|
|
||||||
<GridCol span={{ base: 12, md: 6, lg: 3 }}>
|
|
||||||
<Card
|
|
||||||
p="md"
|
|
||||||
radius="md"
|
|
||||||
withBorder
|
|
||||||
bg={dark ? "#141D34" : "white"}
|
|
||||||
style={{ borderColor: dark ? "#141D34" : "white" }}
|
|
||||||
h="100%"
|
|
||||||
>
|
|
||||||
<Group justify="space-between" align="center">
|
|
||||||
<Stack gap={0}>
|
|
||||||
<Text size="sm" c={dark ? "dark.3" : "dimmed"}>
|
|
||||||
Diproses
|
|
||||||
</Text>
|
|
||||||
<Text size="xl" fw={700} c={dark ? "dark.0" : "black"}>
|
|
||||||
{summaryData.diproses}
|
|
||||||
</Text>
|
|
||||||
</Stack>
|
|
||||||
<Badge variant="light" color="yellow" p={8} radius="md">
|
|
||||||
<IconClock size={20} />
|
|
||||||
</Badge>
|
|
||||||
</Group>
|
|
||||||
</Card>
|
|
||||||
</GridCol>
|
|
||||||
|
|
||||||
<GridCol span={{ base: 12, md: 6, lg: 3 }}>
|
|
||||||
<Card
|
|
||||||
p="md"
|
|
||||||
radius="md"
|
|
||||||
withBorder
|
|
||||||
bg={dark ? "#141D34" : "white"}
|
|
||||||
style={{ borderColor: dark ? "#141D34" : "white" }}
|
|
||||||
h="100%"
|
|
||||||
>
|
|
||||||
<Group justify="space-between" align="center">
|
|
||||||
<Stack gap={0}>
|
|
||||||
<Text size="sm" c={dark ? "dark.3" : "dimmed"}>
|
|
||||||
Selesai
|
|
||||||
</Text>
|
|
||||||
<Text size="xl" fw={700} c={dark ? "dark.0" : "black"}>
|
|
||||||
{summaryData.selesai}
|
|
||||||
</Text>
|
|
||||||
</Stack>
|
|
||||||
<Badge variant="light" color="green" p={8} radius="md">
|
|
||||||
<IconCheck size={20} />
|
|
||||||
</Badge>
|
|
||||||
</Group>
|
|
||||||
</Card>
|
|
||||||
</GridCol>
|
|
||||||
</Grid>
|
</Grid>
|
||||||
|
|
||||||
{/* Grafik Tren Pengaduan */}
|
{/* MAIN CHART - TREN PENGADUAN */}
|
||||||
<Card
|
<Card
|
||||||
p="md"
|
p="md"
|
||||||
radius="md"
|
radius="xl"
|
||||||
withBorder
|
withBorder
|
||||||
bg={dark ? "#141D34" : "white"}
|
bg={dark ? "#1E293B" : "white"}
|
||||||
style={{ borderColor: dark ? "#141D34" : "white" }}
|
style={{
|
||||||
|
borderColor: dark ? "#334155" : "white",
|
||||||
|
boxShadow: "0 1px 3px 0 rgb(0 0 0 / 0.1)",
|
||||||
|
}}
|
||||||
>
|
>
|
||||||
<Title order={4} mb="md" c={dark ? "dark.0" : "black"}>
|
<Group justify="space-between" mb="md">
|
||||||
Grafik Tren Pengaduan
|
<Title order={4} c={dark ? "white" : "gray.9"}>
|
||||||
|
Tren Pengaduan
|
||||||
</Title>
|
</Title>
|
||||||
|
</Group>
|
||||||
<ResponsiveContainer width="100%" height={300}>
|
<ResponsiveContainer width="100%" height={300}>
|
||||||
<LineChart data={trenData}>
|
<LineChart data={trenData}>
|
||||||
<CartesianGrid
|
<CartesianGrid
|
||||||
strokeDasharray="3 3"
|
strokeDasharray="3 3"
|
||||||
vertical={false}
|
vertical={false}
|
||||||
stroke={
|
stroke={dark ? "#334155" : "#e5e7eb"}
|
||||||
dark
|
|
||||||
? "var(--mantine-color-gray-7)"
|
|
||||||
: "var(--mantine-color-gray-3)"
|
|
||||||
}
|
|
||||||
/>
|
/>
|
||||||
<XAxis
|
<XAxis
|
||||||
dataKey="bulan"
|
dataKey="bulan"
|
||||||
axisLine={false}
|
axisLine={false}
|
||||||
tickLine={false}
|
tickLine={false}
|
||||||
tick={{
|
tick={{ fill: dark ? "#E2E8F0" : "#374151" }}
|
||||||
fill: dark
|
|
||||||
? "var(--mantine-color-text)"
|
|
||||||
: "var(--mantine-color-text)",
|
|
||||||
}}
|
|
||||||
/>
|
/>
|
||||||
<YAxis
|
<YAxis
|
||||||
axisLine={false}
|
axisLine={false}
|
||||||
tickLine={false}
|
tickLine={false}
|
||||||
tick={{
|
tick={{ fill: dark ? "#E2E8F0" : "#374151" }}
|
||||||
fill: dark
|
|
||||||
? "var(--mantine-color-text)"
|
|
||||||
: "var(--mantine-color-text)",
|
|
||||||
}}
|
|
||||||
/>
|
/>
|
||||||
<Tooltip
|
<Tooltip
|
||||||
contentStyle={
|
contentStyle={{
|
||||||
dark
|
backgroundColor: dark ? "#1E293B" : "white",
|
||||||
? {
|
borderColor: dark ? "#334155" : "#e5e7eb",
|
||||||
backgroundColor: "var(--mantine-color-dark-7)",
|
borderRadius: "8px",
|
||||||
borderColor: "var(--mantine-color-dark-6)",
|
}}
|
||||||
}
|
labelStyle={{ color: dark ? "#E2E8F0" : "#374151" }}
|
||||||
: {}
|
|
||||||
}
|
|
||||||
/>
|
/>
|
||||||
<Line
|
<Line
|
||||||
type="monotone"
|
type="monotone"
|
||||||
dataKey="jumlah"
|
dataKey="jumlah"
|
||||||
stroke={
|
stroke="#1E3A5F"
|
||||||
dark
|
|
||||||
? "var(--mantine-color-blue-6)"
|
|
||||||
: "var(--mantine-color-blue-filled)"
|
|
||||||
}
|
|
||||||
strokeWidth={2}
|
strokeWidth={2}
|
||||||
dot={{
|
dot={{
|
||||||
stroke: dark
|
fill: "#1E3A5F",
|
||||||
? "var(--mantine-color-blue-6)"
|
|
||||||
: "var(--mantine-color-blue-filled)",
|
|
||||||
strokeWidth: 2,
|
strokeWidth: 2,
|
||||||
r: 4,
|
r: 4,
|
||||||
}}
|
}}
|
||||||
activeDot={{ r: 6, stroke: "#fff", strokeWidth: 2 }}
|
activeDot={{ r: 6 }}
|
||||||
/>
|
/>
|
||||||
</LineChart>
|
</LineChart>
|
||||||
</ResponsiveContainer>
|
</ResponsiveContainer>
|
||||||
</Card>
|
</Card>
|
||||||
|
|
||||||
{/* Surat Terbanyak & Pengajuan Terbaru & Ide Inovatif */}
|
{/* BOTTOM SECTION - 3 COLUMNS */}
|
||||||
<Grid gutter="md">
|
<Grid gutter="md">
|
||||||
{/* Surat Terbanyak */}
|
{/* LEFT: SURAT TERBANYAK */}
|
||||||
<GridCol span={{ base: 12, lg: 4 }}>
|
<Grid.Col span={{ base: 12, lg: 4 }}>
|
||||||
<Card
|
<Card
|
||||||
p="md"
|
p="md"
|
||||||
radius="md"
|
radius="xl"
|
||||||
withBorder
|
withBorder
|
||||||
bg={dark ? "#141D34" : "white"}
|
bg={dark ? "#1E293B" : "white"}
|
||||||
style={{ borderColor: dark ? "#141D34" : "white" }}
|
style={{
|
||||||
|
borderColor: dark ? "#334155" : "white",
|
||||||
|
boxShadow: "0 1px 3px 0 rgb(0 0 0 / 0.1)",
|
||||||
|
}}
|
||||||
h="100%"
|
h="100%"
|
||||||
>
|
>
|
||||||
<Title order={4} mb="md" c={dark ? "dark.0" : "black"}>
|
<Title order={4} c={dark ? "white" : "gray.9"} mb="md">
|
||||||
Surat Terbanyak
|
Surat Terbanyak
|
||||||
</Title>
|
</Title>
|
||||||
<ResponsiveContainer width="100%" height={250}>
|
<ResponsiveContainer width="100%" height={250}>
|
||||||
<BarChart data={suratData} layout="horizontal">
|
<BarChart data={suratData} layout="vertical">
|
||||||
<CartesianGrid
|
<CartesianGrid
|
||||||
strokeDasharray="3 3"
|
strokeDasharray="3 3"
|
||||||
horizontal={false}
|
horizontal={false}
|
||||||
stroke={
|
stroke={dark ? "#334155" : "#e5e7eb"}
|
||||||
dark
|
|
||||||
? "var(--mantine-color-gray-7)"
|
|
||||||
: "var(--mantine-color-gray-3)"
|
|
||||||
}
|
|
||||||
/>
|
/>
|
||||||
<XAxis
|
<XAxis
|
||||||
dataKey="jumlah"
|
type="number"
|
||||||
axisLine={false}
|
axisLine={false}
|
||||||
tickLine={false}
|
tickLine={false}
|
||||||
tick={{
|
tick={{ fill: dark ? "#E2E8F0" : "#374151" }}
|
||||||
fill: dark
|
|
||||||
? "var(--mantine-color-text)"
|
|
||||||
: "var(--mantine-color-text)",
|
|
||||||
}}
|
|
||||||
/>
|
/>
|
||||||
<YAxis
|
<YAxis
|
||||||
dataKey="jenis"
|
|
||||||
type="category"
|
type="category"
|
||||||
|
dataKey="jenis"
|
||||||
axisLine={false}
|
axisLine={false}
|
||||||
tickLine={false}
|
tickLine={false}
|
||||||
tick={{
|
tick={{ fill: dark ? "#E2E8F0" : "#374151" }}
|
||||||
fill: dark
|
|
||||||
? "var(--mantine-color-text)"
|
|
||||||
: "var(--mantine-color-text)",
|
|
||||||
}}
|
|
||||||
width={80}
|
width={80}
|
||||||
/>
|
/>
|
||||||
<Tooltip
|
<Tooltip
|
||||||
contentStyle={
|
contentStyle={{
|
||||||
dark
|
backgroundColor: dark ? "#1E293B" : "white",
|
||||||
? {
|
borderColor: dark ? "#334155" : "#e5e7eb",
|
||||||
backgroundColor: "var(--mantine-color-dark-7)",
|
borderRadius: "8px",
|
||||||
borderColor: "var(--mantine-color-dark-6)",
|
}}
|
||||||
}
|
|
||||||
: {}
|
|
||||||
}
|
|
||||||
/>
|
|
||||||
<Bar
|
|
||||||
dataKey="jumlah"
|
|
||||||
fill={
|
|
||||||
dark
|
|
||||||
? "var(--mantine-color-blue-6)"
|
|
||||||
: "var(--mantine-color-blue-filled)"
|
|
||||||
}
|
|
||||||
radius={[0, 4, 4, 0]}
|
|
||||||
/>
|
/>
|
||||||
|
<Bar dataKey="jumlah" fill="#1E3A5F" radius={[0, 4, 4, 0]} />
|
||||||
</BarChart>
|
</BarChart>
|
||||||
</ResponsiveContainer>
|
</ResponsiveContainer>
|
||||||
</Card>
|
</Card>
|
||||||
</GridCol>
|
</Grid.Col>
|
||||||
|
|
||||||
{/* Pengajuan Terbaru */}
|
{/* CENTER: PENGAJUAN TERBARU */}
|
||||||
<GridCol span={{ base: 12, lg: 4 }}>
|
<Grid.Col span={{ base: 12, lg: 4 }}>
|
||||||
<Card
|
<Card
|
||||||
p="md"
|
p="md"
|
||||||
radius="md"
|
radius="xl"
|
||||||
withBorder
|
withBorder
|
||||||
bg={dark ? "#141D34" : "white"}
|
bg={dark ? "#1E293B" : "white"}
|
||||||
style={{ borderColor: dark ? "#141D34" : "white" }}
|
style={{
|
||||||
|
borderColor: dark ? "#334155" : "white",
|
||||||
|
boxShadow: "0 1px 3px 0 rgb(0 0 0 / 0.1)",
|
||||||
|
}}
|
||||||
h="100%"
|
h="100%"
|
||||||
>
|
>
|
||||||
<Title order={4} mb="md" c={dark ? "dark.0" : "black"}>
|
<Title order={4} c={dark ? "white" : "gray.9"} mb="md">
|
||||||
Pengajuan Terbaru
|
Pengajuan Terbaru
|
||||||
</Title>
|
</Title>
|
||||||
|
<Stack gap="sm">
|
||||||
{pengajuanTerbaru.map((item, index) => (
|
{pengajuanTerbaru.map((item, index) => (
|
||||||
<Box key={index}>
|
<Card
|
||||||
|
key={index}
|
||||||
|
p="sm"
|
||||||
|
radius="md"
|
||||||
|
withBorder
|
||||||
|
bg={dark ? "#334155" : "#F1F5F9"}
|
||||||
|
style={{
|
||||||
|
borderColor: "transparent",
|
||||||
|
transition: "background-color 0.15s ease",
|
||||||
|
}}
|
||||||
|
>
|
||||||
<Group justify="space-between">
|
<Group justify="space-between">
|
||||||
<Stack gap={0}>
|
<Stack gap={0}>
|
||||||
<Text fw={500} c={dark ? "dark.0" : "black"}>
|
<Text fw={600} c={dark ? "white" : "gray.9"}>
|
||||||
{item.nama}
|
{item.nama}
|
||||||
</Text>
|
</Text>
|
||||||
<Text size="sm" c={dark ? "dark.3" : "dimmed"}>
|
<Text size="sm" c="dimmed">
|
||||||
{item.jenis}
|
{item.jenis}
|
||||||
</Text>
|
</Text>
|
||||||
</Stack>
|
</Stack>
|
||||||
@@ -582,260 +353,77 @@ const PengaduanLayananPublik = () => {
|
|||||||
<Badge
|
<Badge
|
||||||
color={getStatusColor(item.status)}
|
color={getStatusColor(item.status)}
|
||||||
variant="light"
|
variant="light"
|
||||||
|
radius="sm"
|
||||||
>
|
>
|
||||||
{item.status}
|
{item.status}
|
||||||
</Badge>
|
</Badge>
|
||||||
<Text size="xs" c={dark ? "dark.4" : "dimmed"}>
|
<Text size="xs" c="dimmed">
|
||||||
{item.waktu}
|
{item.waktu}
|
||||||
</Text>
|
</Text>
|
||||||
</Stack>
|
</Stack>
|
||||||
</Group>
|
</Group>
|
||||||
<Divider my="sm" />
|
|
||||||
</Box>
|
|
||||||
))}
|
|
||||||
</Card>
|
</Card>
|
||||||
</GridCol>
|
))}
|
||||||
|
</Stack>
|
||||||
|
</Card>
|
||||||
|
</Grid.Col>
|
||||||
|
|
||||||
{/* Ajuan Ide Inovatif */}
|
{/* RIGHT: AJUAN IDE INOVATIF */}
|
||||||
<GridCol span={{ base: 12, lg: 4 }}>
|
<Grid.Col span={{ base: 12, lg: 4 }}>
|
||||||
<Card
|
<Card
|
||||||
p="md"
|
p="md"
|
||||||
radius="md"
|
radius="xl"
|
||||||
withBorder
|
withBorder
|
||||||
bg={dark ? "#141D34" : "white"}
|
bg={dark ? "#1E293B" : "white"}
|
||||||
style={{ borderColor: dark ? "#141D34" : "white" }}
|
style={{
|
||||||
|
borderColor: dark ? "#334155" : "white",
|
||||||
|
boxShadow: "0 1px 3px 0 rgb(0 0 0 / 0.1)",
|
||||||
|
}}
|
||||||
h="100%"
|
h="100%"
|
||||||
>
|
>
|
||||||
<Title order={4} mb="md" c={dark ? "dark.0" : "black"}>
|
<Title order={4} c={dark ? "white" : "gray.9"} mb="md">
|
||||||
Ajuan Ide Inovatif
|
Ajuan Ide Inovatif
|
||||||
</Title>
|
</Title>
|
||||||
|
<Stack gap="sm">
|
||||||
{ideInovatif.map((item, index) => (
|
{ideInovatif.map((item, index) => (
|
||||||
<Box key={index}>
|
<Card
|
||||||
|
key={index}
|
||||||
|
p="sm"
|
||||||
|
radius="md"
|
||||||
|
withBorder
|
||||||
|
bg={dark ? "#334155" : "#F1F5F9"}
|
||||||
|
style={{
|
||||||
|
borderColor: "transparent",
|
||||||
|
transition: "background-color 0.15s ease",
|
||||||
|
}}
|
||||||
|
>
|
||||||
<Group justify="space-between">
|
<Group justify="space-between">
|
||||||
<Stack gap={0}>
|
<Stack gap={0}>
|
||||||
<Text fw={500} c={dark ? "dark.0" : "black"}>
|
<Text fw={600} c={dark ? "white" : "gray.9"}>
|
||||||
{item.judul}
|
{item.judul}
|
||||||
</Text>
|
</Text>
|
||||||
<Text size="sm" c={dark ? "dark.3" : "dimmed"}>
|
<Text size="sm" c="dimmed">
|
||||||
{item.nama}
|
{item.nama}
|
||||||
</Text>
|
</Text>
|
||||||
|
<Text size="xs" c="dimmed">
|
||||||
|
{item.waktu}
|
||||||
|
</Text>
|
||||||
</Stack>
|
</Stack>
|
||||||
<Group>
|
<Button
|
||||||
<Badge color="blue" variant="light">
|
size="xs"
|
||||||
{item.kategori}
|
variant="light"
|
||||||
</Badge>
|
color="darmasaba-blue"
|
||||||
<ActionIcon variant="subtle" color="darmasaba-blue">
|
|
||||||
<IconChevronRight size={16} />
|
|
||||||
</ActionIcon>
|
|
||||||
</Group>
|
|
||||||
</Group>
|
|
||||||
<Divider my="sm" />
|
|
||||||
</Box>
|
|
||||||
))}
|
|
||||||
</Card>
|
|
||||||
</GridCol>
|
|
||||||
</Grid>
|
|
||||||
|
|
||||||
{/* Complaint Submission Form and List */}
|
|
||||||
<Grid gutter="md">
|
|
||||||
{/* Complaint Submission Form */}
|
|
||||||
<GridCol span={{ base: 12, lg: 4 }}>
|
|
||||||
<Card
|
|
||||||
p="md"
|
|
||||||
withBorder
|
|
||||||
radius="md"
|
radius="md"
|
||||||
h="100%"
|
|
||||||
bg={dark ? "#141D34" : "white"}
|
|
||||||
style={{ borderColor: dark ? "#141D34" : "white" }}
|
|
||||||
>
|
>
|
||||||
<Card.Section withBorder inheritPadding py="xs">
|
Detail
|
||||||
<Title order={3} py="xs">
|
|
||||||
Ajukan Pengaduan
|
|
||||||
</Title>
|
|
||||||
</Card.Section>
|
|
||||||
<Card.Section>
|
|
||||||
<form onSubmit={handleSubmitComplaint}>
|
|
||||||
<Stack gap="md" p={"sm"}>
|
|
||||||
<TextInput
|
|
||||||
label="Judul Pengaduan"
|
|
||||||
id="title"
|
|
||||||
name="title"
|
|
||||||
value={newComplaint.title}
|
|
||||||
onChange={handleInputChange}
|
|
||||||
placeholder="Masukkan judul pengaduan"
|
|
||||||
required
|
|
||||||
withAsterisk
|
|
||||||
/>
|
|
||||||
|
|
||||||
<Select
|
|
||||||
label="Kategori"
|
|
||||||
id="category"
|
|
||||||
name="category"
|
|
||||||
value={newComplaint.category}
|
|
||||||
onChange={handleSelectChange}
|
|
||||||
placeholder="Pilih kategori"
|
|
||||||
data={[
|
|
||||||
{ value: "infrastruktur", label: "Infrastruktur" },
|
|
||||||
{ value: "administrasi", label: "Administrasi" },
|
|
||||||
{ value: "utilitas", label: "Utilitas" },
|
|
||||||
{ value: "sanitasi", label: "Sanitasi" },
|
|
||||||
{ value: "kesehatan", label: "Kesehatan" },
|
|
||||||
{ value: "pendidikan", label: "Pendidikan" },
|
|
||||||
]}
|
|
||||||
clearable
|
|
||||||
/>
|
|
||||||
|
|
||||||
<Textarea
|
|
||||||
label="Deskripsi"
|
|
||||||
id="description"
|
|
||||||
name="description"
|
|
||||||
value={newComplaint.description}
|
|
||||||
onChange={handleInputChange}
|
|
||||||
placeholder="Jelaskan pengaduan Anda secara detail..."
|
|
||||||
minRows={4}
|
|
||||||
required
|
|
||||||
withAsterisk
|
|
||||||
/>
|
|
||||||
|
|
||||||
<Button type="submit" mt="md" color="darmasaba-blue">
|
|
||||||
Kirim Pengaduan
|
|
||||||
</Button>
|
</Button>
|
||||||
</Stack>
|
|
||||||
</form>
|
|
||||||
</Card.Section>
|
|
||||||
</Card>
|
|
||||||
</GridCol>
|
|
||||||
|
|
||||||
{/* Complaints List */}
|
|
||||||
<GridCol span={{ base: 12, lg: 8 }}>
|
|
||||||
<Card
|
|
||||||
withBorder
|
|
||||||
radius="md"
|
|
||||||
bg={dark ? "#141D34" : "white"}
|
|
||||||
style={{ borderColor: dark ? "#141D34" : "white" }}
|
|
||||||
>
|
|
||||||
<Card.Section withBorder inheritPadding py="xs">
|
|
||||||
<Title order={3} py="xs">
|
|
||||||
Daftar Pengaduan
|
|
||||||
</Title>
|
|
||||||
</Card.Section>
|
|
||||||
<Card.Section py="md" px="xs">
|
|
||||||
<Table withColumnBorders>
|
|
||||||
<Table.Thead>
|
|
||||||
<Table.Tr>
|
|
||||||
<Table.Th>
|
|
||||||
<Text c={dark ? "white" : "dark.3"}>Judul</Text>
|
|
||||||
</Table.Th>
|
|
||||||
<Table.Th>
|
|
||||||
<Text c={dark ? "white" : "dark.3"}>Kategori</Text>
|
|
||||||
</Table.Th>
|
|
||||||
<Table.Th>
|
|
||||||
<Text c={dark ? "white" : "dark.3"}>Status</Text>
|
|
||||||
</Table.Th>
|
|
||||||
<Table.Th>
|
|
||||||
<Text c={dark ? "white" : "dark.3"}>Prioritas</Text>
|
|
||||||
</Table.Th>
|
|
||||||
<Table.Th>
|
|
||||||
<Text c={dark ? "white" : "dark.3"}>Tanggal</Text>
|
|
||||||
</Table.Th>
|
|
||||||
</Table.Tr>
|
|
||||||
</Table.Thead>
|
|
||||||
<Table.Tbody>{complaintRows}</Table.Tbody>
|
|
||||||
</Table>
|
|
||||||
</Card.Section>
|
|
||||||
</Card>
|
|
||||||
</GridCol>
|
|
||||||
</Grid>
|
|
||||||
</>
|
|
||||||
) : (
|
|
||||||
<Stack gap="lg">
|
|
||||||
<Card withBorder radius="md">
|
|
||||||
<Card.Section withBorder inheritPadding py="xs">
|
|
||||||
<Title order={3} py="xs">
|
|
||||||
Layanan Publik Tersedia
|
|
||||||
</Title>
|
|
||||||
</Card.Section>
|
|
||||||
<Card.Section pt="md">
|
|
||||||
<Grid gutter="md">
|
|
||||||
{services.map((service) => (
|
|
||||||
<GridCol key={service.id} span={{ base: 12, md: 6, lg: 4 }}>
|
|
||||||
<Card withBorder radius="md" h="100%">
|
|
||||||
<Title order={4} mb="sm">
|
|
||||||
{service.name}
|
|
||||||
</Title>
|
|
||||||
<Text size="sm" c={dark ? "white" : "dark.3"} mb="md">
|
|
||||||
{service.description}
|
|
||||||
</Text>
|
|
||||||
<Group justify="space-between">
|
|
||||||
<Badge
|
|
||||||
variant="filled"
|
|
||||||
color={
|
|
||||||
service.status === "Available"
|
|
||||||
? "green"
|
|
||||||
: service.status === "Limited"
|
|
||||||
? "yellow"
|
|
||||||
: "red"
|
|
||||||
}
|
|
||||||
>
|
|
||||||
{service.status}
|
|
||||||
</Badge>
|
|
||||||
<Text size="sm" c={dark ? "white" : "dark.3"}>
|
|
||||||
{service.category}
|
|
||||||
</Text>
|
|
||||||
</Group>
|
</Group>
|
||||||
<Text size="xs" c={dark ? "white" : "dark.3"} mt="sm">
|
|
||||||
Terakhir diperbarui: {service.lastUpdated}
|
|
||||||
</Text>
|
|
||||||
</Card>
|
</Card>
|
||||||
</GridCol>
|
|
||||||
))}
|
))}
|
||||||
</Grid>
|
|
||||||
</Card.Section>
|
|
||||||
</Card>
|
|
||||||
|
|
||||||
<Card withBorder radius="md">
|
|
||||||
<Card.Section withBorder inheritPadding py="xs">
|
|
||||||
<Title order={3} py="xs">
|
|
||||||
Statistik Layanan
|
|
||||||
</Title>
|
|
||||||
</Card.Section>
|
|
||||||
<Card.Section pt="md">
|
|
||||||
<Grid gutter="md">
|
|
||||||
<GridCol span={{ base: 12, md: 4 }}>
|
|
||||||
<Card p="md" bg={dark ? "dark.7" : "gray.0"} radius="md">
|
|
||||||
<Title order={4} mb="xs">
|
|
||||||
Jumlah Layanan Tersedia
|
|
||||||
</Title>
|
|
||||||
<Text size="xl" fw={700} c="darmasaba-blue">
|
|
||||||
12
|
|
||||||
</Text>
|
|
||||||
</Card>
|
|
||||||
</GridCol>
|
|
||||||
<GridCol span={{ base: 12, md: 4 }}>
|
|
||||||
<Card p="md" bg={dark ? "dark.7" : "gray.0"} radius="md">
|
|
||||||
<Title order={4} mb="xs">
|
|
||||||
Layanan Terpopuler
|
|
||||||
</Title>
|
|
||||||
<Text size="xl" fw={700} c="darmasaba-success">
|
|
||||||
4
|
|
||||||
</Text>
|
|
||||||
</Card>
|
|
||||||
</GridCol>
|
|
||||||
<GridCol span={{ base: 12, md: 4 }}>
|
|
||||||
<Card p="md" bg={dark ? "dark.7" : "gray.0"} radius="md">
|
|
||||||
<Title order={4} mb="xs">
|
|
||||||
Permintaan Baru
|
|
||||||
</Title>
|
|
||||||
<Text size="xl" fw={700} c="darmasaba-warning">
|
|
||||||
23
|
|
||||||
</Text>
|
|
||||||
</Card>
|
|
||||||
</GridCol>
|
|
||||||
</Grid>
|
|
||||||
</Card.Section>
|
|
||||||
</Card>
|
|
||||||
</Stack>
|
</Stack>
|
||||||
)}
|
</Card>
|
||||||
|
</Grid.Col>
|
||||||
|
</Grid>
|
||||||
</Stack>
|
</Stack>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|||||||
Reference in New Issue
Block a user