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