'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'; // Dynamically import ApexCharts to avoid SSR issues const Chart = dynamic(() => import('react-apexcharts'), { ssr: false }); interface IPKLulusTepatData { tahun_angkatan: number; rata_rata_ipk: number; } interface IPKLulusTepatChartProps { selectedYear: string; } export default function IPKLulusTepatChart({ selectedYear }: IPKLulusTepatChartProps) { const { theme, systemTheme } = useTheme(); const [mounted, setMounted] = useState(false); const [loading, setLoading] = useState(true); const [error, setError] = useState(null); const [data, setData] = useState([]); const [series, setSeries] = useState([{ name: 'Rata-rata IPK', data: [] }]); const [options, setOptions] = useState({ chart: { type: 'line', toolbar: { show: true, tools: { download: true, selection: true, zoom: true, zoomin: true, zoomout: true, pan: true, reset: true } }, background: theme === 'dark' ? '#0F172B' : '#fff', zoom: { enabled: true, type: 'x', autoScaleYaxis: true } }, stroke: { curve: 'smooth', width: 3, lineCap: 'round' }, markers: { size: 5, strokeWidth: 2, strokeColors: theme === 'dark' ? ['#fff'] : ['#3B82F6'], colors: ['#3B82F6'], hover: { size: 7 } }, dataLabels: { enabled: true, formatter: function (val: number) { return val.toFixed(2); }, style: { fontSize: '14px', fontWeight: 'bold' }, background: { enabled: false }, offsetY: -10 }, xaxis: { categories: [], title: { text: 'Tahun Angkatan', style: { fontSize: '14px', fontWeight: 'bold', color: theme === 'dark' ? '#fff' : '#000' } }, labels: { style: { fontSize: '12px', colors: theme === 'dark' ? '#fff' : '#000' } }, axisBorder: { show: true, color: theme === 'dark' ? '#374151' : '#E5E7EB' }, axisTicks: { show: true, color: theme === 'dark' ? '#374151' : '#E5E7EB' } }, yaxis: { title: { text: 'Rata-rata IPK', style: { fontSize: '14px', fontWeight: 'bold', color: theme === 'dark' ? '#fff' : '#000' } }, labels: { style: { fontSize: '12px', colors: theme === 'dark' ? '#fff' : '#000' }, formatter: function (val: number) { return val.toFixed(2); } }, min: 0, max: 4, axisBorder: { show: true, color: theme === 'dark' ? '#374151' : '#E5E7EB' } }, grid: { borderColor: theme === 'dark' ? '#374151' : '#E5E7EB', strokeDashArray: 4, padding: { top: 20, right: 0, bottom: 0, left: 0 } }, colors: ['#3B82F6'], // Blue color for line tooltip: { theme: theme === 'dark' ? 'dark' : 'light', y: { formatter: function (val: number) { return val.toFixed(2); } }, marker: { show: true } }, legend: { show: true, position: 'top', horizontalAlign: 'right', labels: { colors: theme === 'dark' ? '#fff' : '#000' } } }); // Update theme when it changes useEffect(() => { const currentTheme = theme === 'system' ? systemTheme : theme; setOptions(prev => ({ ...prev, chart: { ...prev.chart, background: currentTheme === 'dark' ? '#0F172B' : '#fff', }, dataLabels: { ...prev.dataLabels, style: { ...prev.dataLabels?.style, colors: [currentTheme === 'dark' ? '#fff' : '#000'] }, background: { ...prev.dataLabels?.background, foreColor: currentTheme === 'dark' ? '#fff' : '#000', borderColor: currentTheme === 'dark' ? '#374151' : '#3B82F6' } }, xaxis: { ...prev.xaxis, title: { ...prev.xaxis?.title, style: { ...prev.xaxis?.title?.style, color: currentTheme === 'dark' ? '#fff' : '#000' } }, labels: { ...prev.xaxis?.labels, style: { ...prev.xaxis?.labels?.style, colors: currentTheme === 'dark' ? '#fff' : '#000' } }, axisBorder: { ...prev.xaxis?.axisBorder, color: currentTheme === 'dark' ? '#374151' : '#E5E7EB' }, axisTicks: { ...prev.xaxis?.axisTicks, color: currentTheme === 'dark' ? '#374151' : '#E5E7EB' } }, yaxis: { ...prev.yaxis, title: { ...(Array.isArray(prev.yaxis) ? prev.yaxis[0]?.title : prev.yaxis?.title), style: { ...(Array.isArray(prev.yaxis) ? prev.yaxis[0]?.title?.style : prev.yaxis?.title?.style), color: currentTheme === 'dark' ? '#fff' : '#000' } }, labels: { ...(Array.isArray(prev.yaxis) ? prev.yaxis[0]?.labels : prev.yaxis?.labels), style: { ...(Array.isArray(prev.yaxis) ? prev.yaxis[0]?.labels?.style : prev.yaxis?.labels?.style), colors: currentTheme === 'dark' ? '#fff' : '#000' } } }, tooltip: { ...prev.tooltip, theme: currentTheme === 'dark' ? 'dark' : 'light' } })); }, [theme, systemTheme]); useEffect(() => { setMounted(true); }, []); useEffect(() => { const fetchData = async () => { try { setLoading(true); setError(null); const response = await fetch(`/api/mahasiswa/ipk-lulus-tepat?tahunAngkatan=${selectedYear}`); if (!response.ok) { throw new Error('Failed to fetch data'); } const fetchedData: IPKLulusTepatData[] = await response.json(); setData(fetchedData); // Process data for chart const tahunAngkatan = fetchedData.map(item => item.tahun_angkatan); const rataRataIPK = fetchedData.map(item => item.rata_rata_ipk); setSeries([{ name: 'Rata-rata IPK', data: rataRataIPK }]); setOptions(prev => ({ ...prev, xaxis: { ...prev.xaxis, categories: tahunAngkatan, }, })); } catch (error) { setError(error instanceof Error ? error.message : 'An error occurred'); console.error('Error fetching data:', error); } finally { setLoading(false); } }; fetchData(); }, [selectedYear]); if (!mounted) { return null; } if (loading) { return ( Loading... ); } if (error) { return ( Error: {error} ); } if (data.length === 0) { return ( Tidak ada data yang tersedia ); } return ( Rata-rata IPK Mahasiswa Lulus Tepat Waktu
); }