'use client'; import { useEffect, useState } from 'react'; import dynamic from 'next/dynamic'; import { ApexOptions } from 'apexcharts'; import { useTheme } from 'next-themes'; import { Card, CardContent, CardHeader, CardTitle } from "@/components/ui/card"; const Chart = dynamic(() => import('react-apexcharts'), { ssr: false }); interface KategoriIPKPerAngkatanData { kategori_ipk: string; jumlah: number; } interface Props { selectedYear: string; } export default function DistribusiIPKChartPerangkatan({ selectedYear }: Props) { const { theme } = useTheme(); const [data, setData] = useState([]); const [loading, setLoading] = useState(true); const [error, setError] = useState(null); // Label lengkap dengan angka IPK untuk ditampilkan di legend const kategoriLabelsMap: { [key: string]: string } = { 'Sangat Baik': '4.00 - 3.00 Sangat Baik', 'Baik': '2.99 - 2.50 Baik', 'Cukup': '2.49 - 2.00 Cukup', 'Kurang': '< 2.00 Kurang' }; // Urutan kategori untuk sorting const kategoriOrder = ['Sangat Baik', 'Baik', 'Cukup', 'Kurang']; useEffect(() => { const fetchData = async () => { try { setLoading(true); const response = await fetch( `/api/mahasiswa/kategoriipk?tahun_angkatan=${selectedYear}` ); if (!response.ok) { throw new Error('Failed to fetch data'); } const result = await response.json(); // Filter data for selected year and group by kategori_ipk const yearData = result.filter((item: any) => item.tahun_angkatan.toString() === selectedYear ); // Group by kategori_ipk and sum jumlah const groupedData = yearData.reduce((acc: { [key: string]: number }, item: any) => { const kategori = item.kategori_ipk || 'Tidak Diketahui'; acc[kategori] = (acc[kategori] || 0) + item.jumlah; return acc; }, {}); // Convert to array format const chartData = Object.entries(groupedData).map(([kategori_ipk, jumlah]) => ({ kategori_ipk, jumlah: jumlah as number })); // Sort by kategori order const sortedData = chartData.sort((a, b) => { const indexA = kategoriOrder.indexOf(a.kategori_ipk); const indexB = kategoriOrder.indexOf(b.kategori_ipk); return indexA - indexB; }); setData(sortedData); } catch (err) { setError(err instanceof Error ? err.message : 'An error occurred'); } finally { setLoading(false); } }; fetchData(); }, [selectedYear]); // Prepare data for pie chart const series = data.map(item => item.jumlah); const labels = data.map(item => kategoriLabelsMap[item.kategori_ipk] || item.kategori_ipk); const chartOptions: ApexOptions = { chart: { type: 'pie', toolbar: { show: true, }, background: theme === 'dark' ? '#0F172B' : '#fff', }, labels: labels, dataLabels: { enabled: true, formatter: function (val: number) { return `${val.toFixed(0)}%`; }, style: { fontSize: '14px', fontFamily: 'Inter, sans-serif', fontWeight: '500' } }, legend: { position: 'bottom', fontSize: '11px', markers: { size: 8, }, itemMargin: { horizontal: 10, vertical: 5, }, labels: { colors: theme === 'dark' ? '#fff' : '#000' }, formatter: function(seriesName: string) { return seriesName; } }, colors: [ '#008FFB', // Sangat Baik - Blue '#00E396', // Baik - Green '#FEB019', // Cukup - Orange '#EF4444', // Kurang - Red ], tooltip: { theme: theme === 'dark' ? 'dark' : 'light', y: { formatter: function (val: number) { return val + ' mahasiswa'; } } }, plotOptions: { pie: { donut: { size: '0%', }, offsetY: 0, }, }, states: { hover: { filter: { type: 'darken', }, }, }, }; if (loading) { return ( Memuat data distribusi IPK... ); } if (error) { return ( Error: {error} ); } if (data.length === 0) { return ( Distribusi IPK {selectedYear !== 'all' ? ` Angkatan ${selectedYear}` : ''}

Tidak ada data yang tersedia untuk periode ini.

); } return ( Distribusi IPK {selectedYear !== 'all' ? ` Angkatan ${selectedYear}` : ''}
{typeof window !== 'undefined' && ( )}
); }