+
);
}
diff --git a/src/app/admin/(dashboard)/landing-page/indeks-kepuasan-masyarakat/_lib/layoutTab.tsx b/src/app/admin/(dashboard)/landing-page/indeks-kepuasan-masyarakat/_lib/layoutTab.tsx
index 3aed1230..ff2dc955 100644
--- a/src/app/admin/(dashboard)/landing-page/indeks-kepuasan-masyarakat/_lib/layoutTab.tsx
+++ b/src/app/admin/(dashboard)/landing-page/indeks-kepuasan-masyarakat/_lib/layoutTab.tsx
@@ -1,63 +1,89 @@
/* eslint-disable react-hooks/exhaustive-deps */
'use client'
-import colors from '@/con/colors';
-import { Stack, Tabs, TabsList, TabsPanel, TabsTab, Title } from '@mantine/core';
+import { Stack, Tabs, TabsList, TabsPanel, TabsTab, Title, Tooltip } from '@mantine/core';
+import { IconChartBar, IconUsers } from '@tabler/icons-react';
import { usePathname, useRouter } from 'next/navigation';
import React, { useEffect, useState } from 'react';
function LayoutTabsKepuasan({ children }: { children: React.ReactNode }) {
- const router = useRouter()
- const pathname = usePathname()
- const tabs = [
- {
- label: "Grafik Kepuasan Masyarakat",
- value: "grafikkepuasannamasyarakat",
- href: "/admin/landing-page/indeks-kepuasan-masyarakat/grafik-kepuasan-masyarakat"
- },
- {
- label: "Responden",
- value: "responden",
- href: "/admin/landing-page/indeks-kepuasan-masyarakat/responden"
- },
-
- ];
- const curentTab = tabs.find(tab => tab.href === pathname)
- const [activeTab, setActiveTab] = useState(curentTab?.value || tabs[0].value);
+ const router = useRouter();
+ const pathname = usePathname();
+ const tabs = [
+ {
+ label: "Grafik Kepuasan",
+ description: "Lihat visualisasi grafik kepuasan masyarakat",
+ value: "grafik",
+ href: "/admin/landing-page/indeks-kepuasan-masyarakat/grafik-kepuasan-masyarakat",
+ icon:
+ },
+ {
+ label: "Responden",
+ description: "Kelola dan tinjau data responden",
+ value: "responden",
+ href: "/admin/landing-page/indeks-kepuasan-masyarakat/responden",
+ icon:
+ },
+ ];
- const handleTabChange = (value: string | null) => {
- const tab = tabs.find(t => t.value === value)
- if (tab) {
- router.push(tab.href)
- }
- setActiveTab(value)
- }
+ const curentTab = tabs.find(tab => tab.href === pathname);
+ const [activeTab, setActiveTab] = useState(curentTab?.value || tabs[0].value);
- useEffect(() => {
- const match = tabs.find(tab => tab.href === pathname)
- if (match) {
- setActiveTab(match.value)
- }
- }, [pathname])
+ const handleTabChange = (value: string | null) => {
+ const tab = tabs.find(t => t.value === value);
+ if (tab) router.push(tab.href);
+ setActiveTab(value);
+ };
- return (
-
- Indeks Kepuasan Masyarakat
-
-
- {tabs.map((e, i) => (
- {e.label}
- ))}
-
- {tabs.map((e, i) => (
-
- {/* Konten dummy, bisa diganti tergantung routing */}
- <>>
-
- ))}
-
- {children}
-
- );
+ useEffect(() => {
+ const match = tabs.find(tab => tab.href === pathname);
+ if (match) setActiveTab(match.value);
+ }, [pathname]);
+
+ return (
+
+
+ Indeks Kepuasan Masyarakat
+
+
+
+ {tabs.map((e, i) => (
+
+
+ {e.label}
+
+
+ ))}
+
+ {tabs.map((e, i) => (
+
+ <>>
+
+ ))}
+
+ {children}
+
+ );
}
-export default LayoutTabsKepuasan;
\ No newline at end of file
+export default LayoutTabsKepuasan;
diff --git a/src/app/admin/(dashboard)/landing-page/indeks-kepuasan-masyarakat/grafik-kepuasan-masyarakat/page.tsx b/src/app/admin/(dashboard)/landing-page/indeks-kepuasan-masyarakat/grafik-kepuasan-masyarakat/page.tsx
index 6bb6d463..1bb400bf 100644
--- a/src/app/admin/(dashboard)/landing-page/indeks-kepuasan-masyarakat/grafik-kepuasan-masyarakat/page.tsx
+++ b/src/app/admin/(dashboard)/landing-page/indeks-kepuasan-masyarakat/grafik-kepuasan-masyarakat/page.tsx
@@ -1,7 +1,7 @@
/* eslint-disable @typescript-eslint/no-explicit-any */
'use client';
import colors from '@/con/colors';
-import { PieChart, BarChart } from '@mantine/charts'; // ✅ Ganti recharts dengan Mantine
+import { PieChart, BarChart } from '@mantine/charts';
import {
Box,
Center,
@@ -22,11 +22,8 @@ interface ChartDataItem {
name: string;
value: number;
color: string;
- label?: string;
}
-
-
function Page() {
const state = useProxy(indeksKepuasanState.responden);
const { data, loading } = state.findMany;
@@ -41,28 +38,23 @@ function Page() {
return;
}
if (data) {
- // Hitung total berdasarkan jenis kelamin
const totalLaki = data.filter((item: any) => item.jenisKelamin?.name?.toLowerCase() === 'laki-laki').length;
const totalPerempuan = data.filter((item: any) => item.jenisKelamin?.name?.toLowerCase() === 'perempuan').length;
- // Hitung total berdasarkan rating
const totalSangatBaik = data.filter((item: any) => item.rating?.name?.toLowerCase() === 'sangat baik').length;
const totalBaik = data.filter((item: any) => item.rating?.name?.toLowerCase() === 'baik').length;
const totalKurangBaik = data.filter((item: any) => item.rating?.name?.toLowerCase() === 'kurang baik').length;
const totalSangatKurangBaik = data.filter((item: any) => item.rating?.name?.toLowerCase() === 'sangat kurang baik').length;
- // Hitung total berdasarkan kelompok umur
const totalMuda = data.filter((item: any) => item.kelompokUmur?.name?.toLowerCase() === 'muda').length;
const totalDewasa = data.filter((item: any) => item.kelompokUmur?.name?.toLowerCase() === 'dewasa').length;
const totalLansia = data.filter((item: any) => item.kelompokUmur?.name?.toLowerCase() === 'lansia').length;
- // Update gender chart data
setDonutDataJenisKelamin([
{ name: 'Laki-laki', value: totalLaki, color: colors['blue-button'] },
{ name: 'Perempuan', value: totalPerempuan, color: '#10A85AFF' },
]);
- // Update rating chart data
setDonutDataRating([
{ name: 'Sangat Baik', value: totalSangatBaik, color: colors['blue-button'] },
{ name: 'Baik', value: totalBaik, color: '#10A85AFF' },
@@ -70,18 +62,15 @@ function Page() {
{ name: 'Sangat Kurang Baik', value: totalSangatKurangBaik, color: '#FF4500' },
]);
- // Update age group chart data
setDonutDataKelompokUmur([
{ name: 'Muda', value: totalMuda, color: colors['blue-button'] },
{ name: 'Dewasa', value: totalDewasa, color: '#10A85AFF' },
{ name: 'Lansia', value: totalLansia, color: '#FFA500' },
]);
- // Process data for bar chart (group by month)
const monthYearMap = new Map();
data.forEach((item: any) => {
- // Try both createdAt and tanggal fields
const dateValue = item.tanggal || item.createdAt;
if (!dateValue) return;
@@ -95,7 +84,6 @@ function Page() {
monthYearMap.set(monthYearKey, (monthYearMap.get(monthYearKey) || 0) + 1);
});
- // Convert map to array and sort by date
const barData = Array.from(monthYearMap.entries())
.map(([key, count]) => {
const [year, month] = key.split('-');
@@ -104,7 +92,7 @@ function Page() {
return {
month: `${monthName} ${year}`,
count,
- sortKey: parseInt(`${year}${String(month).padStart(2, '0')}`, 10)
+ sortKey: parseInt(`${year}${String(month).padStart(2, '0')}`, 10),
};
})
.sort((a, b) => a.sortKey - b.sortKey)
@@ -116,28 +104,27 @@ function Page() {
if (loading || !data) {
return (
-
-
+
+
);
}
if (data.length === 0) {
return (
-
-
- Belum ada data untuk ditampilkan
+
+
+ Belum ada data yang tersedia
);
}
return (
-
- {/* Bar Chart - Data per Tanggal */}
-
- Jumlah Responden per Bulan
-
+
+
+ Tren Jumlah Responden
+
-
- {/* Chart Jenis Kelamin */}
-
+
+
- Jenis Kelamin
+ Distribusi Jenis Kelamin
{donutDataJenisKelamin.every(item => item.value === 0) ? (
- Belum ada data untuk ditampilkan dalam grafik
+ Tidak ada data
) : (
@@ -168,15 +154,15 @@ function Page() {
withLabels
withTooltip
labelsType="percent"
- size={250}
+ size={220}
data={donutDataJenisKelamin}
/>
-
+
{donutDataJenisKelamin.map((entry) => (
-
-
- {entry.name}: {entry.value}
+
+
+ {entry.name}: {entry.value}
))}
@@ -185,13 +171,12 @@ function Page() {
- {/* Chart Rating */}
-
+
- Pilihan
+ Distribusi Penilaian
{donutDataRating.every(item => item.value === 0) ? (
- Belum ada data untuk ditampilkan dalam grafik
+ Tidak ada data
) : (
@@ -200,15 +185,15 @@ function Page() {
withLabels
withTooltip
labelsType="percent"
- size={250}
+ size={220}
data={donutDataRating}
/>
-
+
{donutDataRating.map((entry) => (
-
-
- {entry.name}: {entry.value}
+
+
+ {entry.name}: {entry.value}
))}
@@ -217,13 +202,12 @@ function Page() {
- {/* Chart Kelompok Umur */}
-
+
- Umur
+ Distribusi Kelompok Umur
{donutDataKelompokUmur.every(item => item.value === 0) ? (
- Belum ada data untuk ditampilkan dalam grafik
+ Tidak ada data
) : (
@@ -232,15 +216,15 @@ function Page() {
withLabels
withTooltip
labelsType="percent"
- size={250}
+ size={220}
data={donutDataKelompokUmur}
/>
-
+
{donutDataKelompokUmur.map((entry) => (
-
-
- {entry.name}: {entry.value}
+
+
+ {entry.name}: {entry.value}
))}
@@ -253,4 +237,4 @@ function Page() {
);
}
-export default Page;
\ No newline at end of file
+export default Page;
diff --git a/src/app/admin/(dashboard)/landing-page/indeks-kepuasan-masyarakat/responden/[id]/edit/page.tsx b/src/app/admin/(dashboard)/landing-page/indeks-kepuasan-masyarakat/responden/[id]/edit/page.tsx
index 7d9f6e55..58e82afc 100644
--- a/src/app/admin/(dashboard)/landing-page/indeks-kepuasan-masyarakat/responden/[id]/edit/page.tsx
+++ b/src/app/admin/(dashboard)/landing-page/indeks-kepuasan-masyarakat/responden/[id]/edit/page.tsx
@@ -4,8 +4,8 @@ import React, { useEffect, useState } from 'react';
import { useRouter, useParams } from 'next/navigation';
import { useProxy } from 'valtio/utils';
import colors from '@/con/colors';
-import { Box, Button, Paper, Stack, Title, TextInput, Text, Select } from '@mantine/core';
-import { IconArrowBack } from '@tabler/icons-react';
+import { Box, Button, Group, Paper, Stack, Title, TextInput, Text, Select, Tooltip } from '@mantine/core';
+import { IconArrowBack, IconDeviceFloppy } from '@tabler/icons-react';
import indeksKepuasanState from '@/app/admin/(dashboard)/_state/landing-page/indeks-kepuasan';
import { toast } from 'react-toastify';
@@ -74,23 +74,39 @@ function EditResponden() {
state.update.id = id;
state.update.form = { ...formData }; // <-- sinkronisasi manual
await state.update.submit();
- router.push('/admin/ppid/ikm-desa-darmasaba/responden')
+ router.push('/admin/landing-page/indeks-kepuasan-masyarakat/responden')
}
return (
-
-
- router.back()}>
-
-
-
-
-
- Edit Responden
+
+
+
+ router.back()} p="xs" radius="md">
+
+
+
+
+ Edit Responden
+
+
+
+
+
+ Nama Responden
+
+ }
type='text'
- placeholder="masukkan nama"
+ placeholder="Masukkan nama responden"
value={formData.name}
onChange={(val) => {
setFormData({
@@ -98,9 +114,15 @@ function EditResponden() {
name: val.currentTarget.value
})
}}
+ radius="md"
+ required
/>
+ Tanggal
+
+ }
type="date"
placeholder='Pilih tanggal'
value={formData.tanggal ? new Date(formData.tanggal).toISOString().split('T')[0] : ''}
@@ -111,32 +133,43 @@ function EditResponden() {
tanggal: selectedDate,
});
}}
+ radius="md"
+ required
/>
diff --git a/src/app/admin/(dashboard)/landing-page/indeks-kepuasan-masyarakat/responden/[id]/page.tsx b/src/app/admin/(dashboard)/landing-page/indeks-kepuasan-masyarakat/responden/[id]/page.tsx
index 08849a58..e82733d0 100644
--- a/src/app/admin/(dashboard)/landing-page/indeks-kepuasan-masyarakat/responden/[id]/page.tsx
+++ b/src/app/admin/(dashboard)/landing-page/indeks-kepuasan-masyarakat/responden/[id]/page.tsx
@@ -3,10 +3,10 @@
import { ModalKonfirmasiHapus } from "@/app/admin/(dashboard)/_com/modalKonfirmasiHapus"
import indeksKepuasanState from "@/app/admin/(dashboard)/_state/landing-page/indeks-kepuasan"
import colors from "@/con/colors"
-import { Box, Button, Flex, Paper, Skeleton, Stack, Text } from "@mantine/core"
+import { Box, Button, Group, Paper, Skeleton, Stack, Text, Tooltip } from "@mantine/core"
import { useShallowEffect } from "@mantine/hooks"
-import { IconArrowBack, IconEdit, IconX } from "@tabler/icons-react"
-import { useRouter, useParams } from "next/navigation"
+import { IconArrowBack, IconEdit, IconTrash } from "@tabler/icons-react"
+import { useParams, useRouter } from "next/navigation"
import { useState } from "react"
import { useProxy } from "valtio/utils"
@@ -38,67 +38,89 @@ export default function DetailResponden() {
)
}
return (
-
-
- router.back()}>
-
-
-
-
-
- Detail Responden
+
+ router.back()}
+ leftSection={}
+ mb={15}
+ >
+ Kembali
+
-
-
+
+
+
+ Detail Responden
+
+
+
+
- Nama Responden
- {stateDetail.findUnique.data?.name}
+ Nama Responden
+ {stateDetail.findUnique.data?.name || '-'}
- Tanggal
- {
+ Tanggal
+ {
stateDetail.findUnique.data?.tanggal
? new Date(stateDetail.findUnique.data.tanggal).toLocaleDateString('id-ID')
: '-'
}
- Jenis Kelamin
- {stateDetail.findUnique.data?.jenisKelamin?.name}
+ Jenis Kelamin
+ {stateDetail.findUnique.data?.jenisKelamin?.name || '-'}
- Rating
- {stateDetail.findUnique.data?.rating?.name}
+ Rating
+ {stateDetail.findUnique.data?.rating?.name || '-'}
- Kelompok Umur
- {stateDetail.findUnique.data?.kelompokUmur?.name}
+ Kelompok Umur
+ {stateDetail.findUnique.data?.kelompokUmur?.name || '-'}
-
- {
- if (stateDetail.findUnique.data) {
- setSelectedId(stateDetail.findUnique.data.id);
- setModalHapus(true);
- }
- }}
- disabled={stateDetail.delete.loading || !stateDetail.findUnique.data}
- color={"red"}
- >
-
-
- {
- if (stateDetail.findUnique.data) {
- router.push(`/admin/ppid/ikm-desa-darmasaba/responden/${stateDetail.findUnique.data.id}/edit`);
- }
- }}
- disabled={!stateDetail.findUnique.data}
- color={"green"}
- >
-
-
-
+
+
+
+ {
+ if (stateDetail.findUnique.data) {
+ setSelectedId(stateDetail.findUnique.data.id);
+ setModalHapus(true);
+ }
+ }}
+ disabled={stateDetail.delete.loading || !stateDetail.findUnique.data}
+ leftSection={}
+ >
+ Hapus
+
+
+
+ {
+ if (stateDetail.findUnique.data) {
+ router.push(`/admin/landing-page/indeks-kepuasan-masyarakat/responden/${stateDetail.findUnique.data.id}/edit`);
+ }
+ }}
+ disabled={!stateDetail.findUnique.data}
+ leftSection={}
+ >
+ Edit
+
+
+
diff --git a/src/app/admin/(dashboard)/landing-page/indeks-kepuasan-masyarakat/responden/page.tsx b/src/app/admin/(dashboard)/landing-page/indeks-kepuasan-masyarakat/responden/page.tsx
index 511b05fd..6cfb3f2a 100644
--- a/src/app/admin/(dashboard)/landing-page/indeks-kepuasan-masyarakat/responden/page.tsx
+++ b/src/app/admin/(dashboard)/landing-page/indeks-kepuasan-masyarakat/responden/page.tsx
@@ -1,22 +1,37 @@
'use client';
-import colors from '@/con/colors';
-import { Box, Button, Center, Pagination, Paper, Skeleton, Stack, Table, TableTbody, TableTd, TableTh, TableThead, TableTr, Text, Title } from '@mantine/core';
-import { useShallowEffect } from '@mantine/hooks';
-import { IconDeviceImac, IconSearch } from '@tabler/icons-react';
-import { useRouter } from 'next/navigation';
import { useState } from 'react';
+import { useRouter } from 'next/navigation';
import { useProxy } from 'valtio/utils';
+import { useShallowEffect } from '@mantine/hooks';
+import {
+ Box,
+ Button,
+ Center,
+ Pagination,
+ Paper,
+ Skeleton,
+ Stack,
+ Table,
+ TableTbody,
+ TableTd,
+ TableTh,
+ TableThead,
+ TableTr,
+ Text,
+ Title,
+} from '@mantine/core';
+import { IconDeviceImac, IconSearch } from '@tabler/icons-react';
import HeaderSearch from '../../../_com/header';
import indeksKepuasanState from '../../../_state/landing-page/indeks-kepuasan';
function Responden() {
- const [search, setSearch] = useState("");
+ const [search, setSearch] = useState('');
return (
}
+ title="Data Responden"
+ placeholder="Cari nama responden..."
+ searchIcon={}
value={search}
onChange={(e) => setSearch(e.currentTarget.value)}
/>
@@ -34,84 +49,99 @@ function ListResponden({ search }: ListRespondenProps) {
const router = useRouter();
const { data, page, totalPages, loading, load } = state.findMany;
-
useShallowEffect(() => {
- load(page, 10)
+ load(page, 10);
}, [page]);
-
- const filteredData = (data || []).filter(item => {
+ const filteredData = (data || []).filter((item) => {
const keyword = search.toLowerCase();
- return (
- item.name.toLowerCase().includes(keyword)
- );
+ return item.name.toLowerCase().includes(keyword);
});
if (loading || !data) {
return (
-
-
+
+
);
}
+
if (data.length === 0) {
return (
-
-
-
- Responden
-
-
-
- No
- Nama
- Tanggal
- Jenis Kelamin
- Detail
-
-
-
- Tidak ada data berdasarkan jenis kelamin responden yang tersedia
+
+
+
+ Data Responden
+
+ Belum ada data responden yang tersedia
+
-
+
);
}
return (
-
-
- List Responden
-
+
+
+
+ Daftar Responden
+
+
No
- Nama
+ NamaTanggalJenis Kelamin
- Detail
+ Aksi
{filteredData.length === 0 ? (
-
- Belum ada data responden
+
+
+ Tidak ditemukan data dengan kata kunci pencarian
+
) : (
filteredData.map((item, index) => (
- {index + 1}
- {item.name}
- {item.tanggal
- ? new Date(item.tanggal).toLocaleDateString('id-ID')
- : '-'}
- {item.jenisKelamin.name}
-
- router.push(`/admin/ppid/ikm-desa-darmasaba/responden/${item.id}`)}>
-
+ {index + 1}
+ {item.name}
+
+ {item.tanggal
+ ? new Date(item.tanggal).toLocaleDateString('id-ID', {
+ day: '2-digit',
+ month: 'long',
+ year: 'numeric',
+ })
+ : '-'}
+
+ {item.jenisKelamin.name}
+
+ }
+ onClick={() =>
+ router.push(
+ `/admin/landing-page/indeks-kepuasan-masyarakat/responden/${item.id}`
+ )
+ }
+ >
+ Detail
@@ -123,22 +153,19 @@ function ListResponden({ search }: ListRespondenProps) {