'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"; import { Button } from "@/components/ui/button"; import { ExternalLink } from "lucide-react"; import Link from "next/link"; // Import ApexCharts secara dinamis untuk menghindari masalah SSR const Chart = dynamic(() => import('react-apexcharts'), { ssr: false }); interface IPKData { tahun_angkatan: number; rata_rata_ipk: number; } interface IPKChartProps { height?: string; showDetailButton?: boolean; } export default function IPKChart({ height = "h-[300px] sm:h-[350px] md:h-[300px]", showDetailButton = true }: IPKChartProps) { const { theme } = 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: 'straight', 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'], // Warna biru untuk garis 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' } } }); // Perbarui tema saat berubah useEffect(() => { const currentTheme = 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]); useEffect(() => { setMounted(true); }, []); useEffect(() => { const fetchData = async () => { try { setLoading(true); setError(null); const response = await fetch('/api/mahasiswa/ipk'); if (!response.ok) { throw new Error(`Failed to fetch data: ${response.status} ${response.statusText}`); } const result = await response.json(); if (!Array.isArray(result)) { throw new Error('Format data tidak valid diterima dari server'); } setData(result); // Proses data untuk chart const tahunAngkatan = result.map(item => item.tahun_angkatan); const rataRataIPK = result.map(item => item.rata_rata_ipk); setSeries([{ name: 'Rata-rata IPK', data: rataRataIPK }]); setOptions(prev => ({ ...prev, xaxis: { ...prev.xaxis, categories: tahunAngkatan, }, })); } catch (err) { console.error('Error in fetchData:', err); setError(err instanceof Error ? err.message : 'Terjadi kesalahan saat mengambil data'); } finally { setLoading(false); } }; fetchData(); }, []); 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 {showDetailButton && ( )}
); }