Admin: Ubah Pie Chart Submenu IKM, Menu PPID

This commit is contained in:
2025-08-13 00:34:44 +08:00
parent a1d55e2b0a
commit a6832cad40

View File

@@ -1,10 +1,20 @@
/* eslint-disable @typescript-eslint/no-explicit-any */
'use client'
import React, { useEffect, useState } from 'react';
import { Box, Center, Flex, Paper, Skeleton, Stack, Text, Title } from '@mantine/core';
'use client';
import colors from '@/con/colors';
import { PieChart, Pie, Cell } from 'recharts';
import { PieChart } from '@mantine/charts'; // ✅ Ganti recharts dengan Mantine
import {
Box,
Center,
Flex,
Paper,
SimpleGrid,
Skeleton,
Stack,
Text,
Title,
} from '@mantine/core';
import { useShallowEffect } from '@mantine/hooks';
import { useState } from 'react';
import { useProxy } from 'valtio/utils';
import indeksKepuasanState from '../../../_state/landing-page/indeks-kepuasan';
@@ -21,13 +31,8 @@ function Page() {
const [donutDataJenisKelamin, setDonutDataJenisKelamin] = useState<ChartDataItem[]>([]);
const [donutDataRating, setDonutDataRating] = useState<ChartDataItem[]>([]);
const [donutDataKelompokUmur, setDonutDataKelompokUmur] = useState<ChartDataItem[]>([]);
const [mounted, setMounted] = useState(false);
useShallowEffect(() => {
setMounted(true);
}, []);
useEffect(() => {
if (data) {
// Hitung total berdasarkan jenis kelamin
const totalLaki = data.filter((item: any) => item.jenisKelamin?.name?.toLowerCase() === 'laki-laki').length;
@@ -43,28 +48,29 @@ function Page() {
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', value: totalLaki, color: colors['blue-button'], label: 'Laki-laki' },
{ name: 'perempuan', value: totalPerempuan, color: '#10A85AFF', label: 'Perempuan' }
{ 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'], label: 'Sangat Baik' },
{ name: 'baik', value: totalBaik, color: '#10A85AFF', label: 'Baik' },
{ name: 'kurang_baik', value: totalKurangBaik, color: '#FFA500', label: 'Kurang Baik' },
{ name: 'sangat_kurang_baik', value: totalSangatKurangBaik, color: '#FF4500', label: 'Sangat Kurang Baik' }
{ name: 'Sangat Baik', value: totalSangatBaik, color: colors['blue-button'] },
{ name: 'Baik', value: totalBaik, color: '#10A85AFF' },
{ name: 'Kurang Baik', value: totalKurangBaik, color: '#FFA500' },
{ name: 'Sangat Kurang Baik', value: totalSangatKurangBaik, color: '#FF4500' },
]);
// Update age group chart data
setDonutDataKelompokUmur([
{ name: 'muda', value: totalMuda, color: colors['blue-button'], label: 'Muda' },
{ name: 'dewasa', value: totalDewasa, color: '#10A85AFF', label: 'Dewasa' },
{ name: 'lansia', value: totalLansia, color: '#FFA500', label: 'Lansia' }
{ name: 'Muda', value: totalMuda, color: colors['blue-button'] },
{ name: 'Dewasa', value: totalDewasa, color: '#10A85AFF' },
{ name: 'Lansia', value: totalLansia, color: '#FFA500' },
]);
}
}, [data])
}, [data]);
if (loading || !data) {
return (
@@ -77,46 +83,43 @@ function Page() {
if (data.length === 0) {
return (
<Stack py={10}>
<Text c='dimmed' ta="center" my="md">Belum ada data untuk ditampilkan</Text>
<Text c="dimmed" ta="center" my="md">
Belum ada data untuk ditampilkan
</Text>
</Stack>
)
);
}
return (
<Stack gap="xs">
<SimpleGrid cols={{ base: 1, md: 3 }}>
{/* Chart Jenis Kelamin */}
<Paper bg={colors['white-1']} p="md" radius="md">
<Stack>
{/* Chart */}
<Box>
<Paper bg={colors['white-1']} p={'md'} style={{ height: '100%' }}>
<Stack>
<Title pb={10} order={4} size="h4">Grafik Berdasarkan Jenis Kelamin Responden</Title>
{mounted && donutDataJenisKelamin.length === 0 ? (
<Text c='dimmed' ta="center" my="md">Belum ada data untuk ditampilkan dalam grafik</Text>
<Title order={4}>Jenis Kelamin</Title>
{donutDataJenisKelamin.every(item => item.value === 0) ? (
<Text c="dimmed" ta="center" my="md">
Belum ada data untuk ditampilkan dalam grafik
</Text>
) : (
<Box>
<Center>
<PieChart width={250} height={350}>
<Pie
<PieChart
withLabels
withTooltip
labelsType="percent"
size={250}
data={donutDataJenisKelamin}
dataKey="value"
nameKey="name"
cx="50%"
cy="50%"
innerRadius={60}
outerRadius={100}
label={({ percent }: { percent: number }) => `${(percent * 100).toFixed(0)}%`}
labelLine={false}
>
{donutDataJenisKelamin.map((entry, index) => (
<Cell key={`cell-${index}`} fill={entry.color} />
))}
</Pie>
</PieChart>
/>
</Center>
<Stack gap="sm" mt="md">
{donutDataJenisKelamin.map((entry) => (
<Flex key={entry.name} gap="md" align="center">
<Box bg={entry.color} w={20} h={20} style={{ flexShrink: 0 }} />
<Text size="sm">{entry.label}: {entry.value || 0}</Text>
<Text size="sm">{entry.name}: {entry.value}</Text>
</Flex>
))}
</Stack>
@@ -124,40 +127,31 @@ function Page() {
)}
</Stack>
</Paper>
</Box>
<Box>
{/* Rating Chart */}
<Paper bg={colors['white-1']} p={'md'} style={{ height: '100%' }}>
{/* Chart Rating */}
<Paper bg={colors['white-1']} p="md" radius="md">
<Stack>
<Title pb={10} order={4}>Grafik Berdasarkan Rating Responden</Title>
{mounted && donutDataRating.length === 0 ? (
<Text c='dimmed' ta="center" my="md">Belum ada data untuk ditampilkan dalam grafik</Text>
<Title order={4}>Pilihan</Title>
{donutDataRating.every(item => item.value === 0) ? (
<Text c="dimmed" ta="center" my="md">
Belum ada data untuk ditampilkan dalam grafik
</Text>
) : (
<Box>
<Center>
<PieChart width={350} height={350}>
<Pie
<PieChart
withLabels
withTooltip
labelsType="percent"
size={250}
data={donutDataRating}
dataKey="value"
nameKey="name"
cx="50%"
cy="50%"
innerRadius={60}
outerRadius={100}
label={({ percent }: { percent: number }) => `${(percent * 100).toFixed(0)}%`}
labelLine={false}
>
{donutDataRating.map((entry, index) => (
<Cell key={`cell-${index}`} fill={entry.color} />
))}
</Pie>
</PieChart>
/>
</Center>
<Stack gap="sm" mt="md">
{donutDataRating.map((entry) => (
<Flex key={entry.name} gap="md" align="center">
<Box bg={entry.color} w={20} h={20} style={{ flexShrink: 0 }} />
<Text size="sm">{entry.label}: {entry.value || 0}</Text>
<Text size="sm">{entry.name}: {entry.value}</Text>
</Flex>
))}
</Stack>
@@ -165,41 +159,31 @@ function Page() {
)}
</Stack>
</Paper>
</Box>
{/* Age Group Chart */}
<Box>
<Paper bg={colors['white-1']} p={'md'} style={{ height: '100%' }}>
{/* Chart Kelompok Umur */}
<Paper bg={colors['white-1']} p="md" radius="md">
<Stack>
<Title pb={10} order={4}>Grafik Berdasarkan Kelompok Umur</Title>
{mounted && donutDataKelompokUmur.length === 0 ? (
<Text c='dimmed' ta="center" my="md">Belum ada data untuk ditampilkan dalam grafik</Text>
<Title order={4}>Umur</Title>
{donutDataKelompokUmur.every(item => item.value === 0) ? (
<Text c="dimmed" ta="center" my="md">
Belum ada data untuk ditampilkan dalam grafik
</Text>
) : (
<Box>
<Center>
<PieChart width={350} height={350}>
<Pie
<PieChart
withLabels
withTooltip
labelsType="percent"
size={250}
data={donutDataKelompokUmur}
dataKey="value"
nameKey="name"
cx="50%"
cy="50%"
innerRadius={60}
outerRadius={100}
label={({ percent }: { percent: number }) => `${(percent * 100).toFixed(0)}%`}
labelLine={false}
>
{donutDataKelompokUmur.map((entry, index) => (
<Cell key={`cell-${index}`} fill={entry.color} />
))}
</Pie>
</PieChart>
/>
</Center>
<Stack gap="sm" mt="md">
{donutDataKelompokUmur.map((entry) => (
<Flex key={entry.name} gap="md" align="center">
<Box bg={entry.color} w={20} h={20} style={{ flexShrink: 0 }} />
<Text size="sm">{entry.label}: {entry.value || 0}</Text>
<Text size="sm">{entry.name}: {entry.value}</Text>
</Flex>
))}
</Stack>
@@ -207,7 +191,7 @@ function Page() {
)}
</Stack>
</Paper>
</Box>
</SimpleGrid>
</Stack>
);
}