'use client'; import { useEffect, useMemo, 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'; const Chart = dynamic(() => import('react-apexcharts'), { ssr: false }); interface TerancamDOResponse { tahun_angkatan: number; jumlah_mahasiswa_do: number; } interface TerancamDOChartProps { selectedYear?: string; height?: string; showDetailButton?: boolean; } export default function TerancamDOChart({ selectedYear = 'all', height = 'h-[300px] sm:h-[320px]', showDetailButton = true, }: TerancamDOChartProps) { const { theme } = useTheme(); const [data, setData] = useState([]); const [loading, setLoading] = useState(true); const [error, setError] = useState(null); useEffect(() => { const fetchData = async () => { try { setLoading(true); setError(null); const url = selectedYear === 'all' ? '/api/mahasiswa/terancamdo' : `/api/mahasiswa/terancamdo?tahun_angkatan=${selectedYear}`; const response = await fetch(url); if (!response.ok) { const errorText = await response.text(); throw new Error( `Failed to fetch data: ${response.status} ${response.statusText} - ${errorText}`, ); } const result = await response.json(); if (!Array.isArray(result)) { throw new Error('Invalid data format received from server'); } const sorted = [...result].sort( (a, b) => a.tahun_angkatan - b.tahun_angkatan, ); setData(sorted); } catch (err) { console.error('Error fetching terancam DO data:', err); setError( err instanceof Error ? err.message : 'Terjadi kesalahan saat memuat data', ); } finally { setLoading(false); } }; fetchData(); }, [selectedYear]); const categories = useMemo( () => data.map((item) => item.tahun_angkatan), [data], ); const series = useMemo( () => [ { name: 'Mahasiswa Terancam DO', data: data.map((item) => item.jumlah_mahasiswa_do), }, ], [data], ); const chartOptions: ApexOptions = { chart: { type: 'bar', toolbar: { show: true, }, background: 'transparent', }, plotOptions: { bar: { horizontal: false, columnWidth: '55%', borderRadius: 2, }, }, dataLabels: { enabled: true, formatter: (val: number) => val.toString(), style: { colors: [theme === 'dark' ? '#f9fafb' : '#1f2937'], }, }, stroke: { show: true, width: 2, colors: ['transparent'], }, xaxis: { categories, title: { text: 'Tahun Angkatan', style: { fontSize: '14px', fontWeight: 'bold', color: theme === 'dark' ? '#f9fafb' : '#1f2937', }, }, labels: { style: { colors: theme === 'dark' ? '#e5e7eb' : '#4b5563', }, }, }, yaxis: { title: { text: 'Jumlah Mahasiswa', style: { fontSize: '14px', fontWeight: 'bold', color: theme === 'dark' ? '#f9fafb' : '#1f2937', }, }, labels: { style: { colors: theme === 'dark' ? '#e5e7eb' : '#4b5563', }, }, min: 0, forceNiceScale: true, }, legend: { show: false, }, grid: { borderColor: theme === 'dark' ? '#374151' : '#e5e7eb', strokeDashArray: 4, padding: { top: 20, right: 20, left: 10, }, }, colors: ['#ef4444'], tooltip: { theme: theme === 'dark' ? 'dark' : 'light', y: { formatter: (val: number) => `${val} mahasiswa`, }, }, }; if (loading) { return ( Memuat data terancam DO... ); } if (error) { return ( Gagal memuat data

{error}

); } if (!data.length) { return ( Mahasiswa Terancam DO

Tidak ada mahasiswa yang teridentifikasi terancam DO pada periode ini.

); } return (
Mahasiswa Terancam Drop Out {selectedYear !== 'all' ? ` Angkatan ${selectedYear}` : ''} {showDetailButton && ( )}
{typeof window !== 'undefined' && ( )}
); }