Files
portaldata/components/chartstable/tabeljumlahmahasiswa.tsx
Randa Firman Putra db3db43434 revisi nih boz
2025-10-29 11:53:03 +07:00

156 lines
5.4 KiB
TypeScript

'use client';
import { useEffect, useState } from 'react';
import {
Table,
TableBody,
TableCell,
TableHead,
TableHeader,
TableRow
} from "@/components/ui/table";
import { Card, CardContent, CardHeader, CardTitle } from "@/components/ui/card";
import { Loader2 } from "lucide-react";
interface MahasiswaStatistik {
tahun_angkatan: number;
total_mahasiswa: number;
pria: number;
wanita: number;
}
export default function TabelJumlahMahasiswa() {
const [statistikData, setStatistikData] = useState<MahasiswaStatistik[]>([]);
const [loading, setLoading] = useState(true);
const [error, setError] = useState<string | null>(null);
useEffect(() => {
const fetchData = async () => {
try {
const statistikResponse = await fetch('/api/mahasiswa/statistik', {
cache: 'no-store',
});
if (!statistikResponse.ok) {
throw new Error('Failed to fetch statistik data');
}
const statistikData = await statistikResponse.json();
setStatistikData(statistikData);
} catch (err) {
setError(err instanceof Error ? err.message : 'Terjadi kesalahan');
console.error('Error fetching data:', err);
} finally {
setLoading(false);
}
};
fetchData();
}, []);
// Hitung total keseluruhan
const grandTotal = {
total_mahasiswa: statistikData.reduce((sum, item) => sum + item.total_mahasiswa, 0),
pria: statistikData.reduce((sum, item) => sum + item.pria, 0),
wanita: statistikData.reduce((sum, item) => sum + item.wanita, 0),
};
if (loading) {
return (
<Card className="bg-white dark:bg-slate-900 shadow-lg">
<CardHeader>
<CardTitle className="text-xl font-bold dark:text-white">
<div className="flex items-center gap-2">
<Loader2 className="h-5 w-5 animate-spin" />
Loading...
</div>
</CardTitle>
</CardHeader>
</Card>
);
}
if (error) {
return (
<Card className="bg-white dark:bg-slate-900 shadow-lg">
<CardHeader>
<CardTitle className="text-xl font-bold text-red-500 dark:text-red-400">
Error: {error}
</CardTitle>
</CardHeader>
</Card>
);
}
return (
<Card className="bg-white dark:bg-slate-900 shadow-lg">
<CardContent>
<div className="border rounded-md overflow-hidden">
<Table>
<TableHeader>
<TableRow className="bg-gray-50 dark:bg-slate-800">
<TableHead className="font-semibold text-center">Tahun Angkatan</TableHead>
<TableHead className="font-semibold text-center">Laki-laki</TableHead>
<TableHead className="font-semibold text-center">Perempuan</TableHead>
<TableHead className="font-semibold text-center">Total</TableHead>
</TableRow>
</TableHeader>
<TableBody>
{statistikData.length === 0 ? (
<TableRow>
<TableCell colSpan={4} className="text-center py-8 text-muted-foreground">
Tidak ada data yang tersedia
</TableCell>
</TableRow>
) : (
<>
{statistikData.map((item, index) => (
<TableRow
key={item.tahun_angkatan}
className={index % 2 === 0 ? "bg-white dark:bg-slate-900" : "bg-gray-50/50 dark:bg-slate-800/50"}
>
<TableCell className="text-center font-medium dark:text-white">
{item.tahun_angkatan}
</TableCell>
<TableCell className="text-center">
<div className="font-medium dark:text-white">{item.pria}</div>
</TableCell>
<TableCell className="text-center">
<div className="font-medium dark:text-white">{item.wanita}</div>
</TableCell>
<TableCell className="text-center">
<div className="font-semibold dark:text-white">
{item.total_mahasiswa}
</div>
</TableCell>
</TableRow>
))}
{/* Total Row */}
<TableRow className="bg-blue-50 dark:bg-blue-900/20 border-t-2 border-blue-200 dark:border-blue-700 dark:text-white">
<TableCell className="text-center font-bold">
TOTAL
</TableCell>
<TableCell className="text-center">
<div className="font-bold dark:text-white">{grandTotal.pria}</div>
</TableCell>
<TableCell className="text-center">
<div className="font-bold dark:text-white">{grandTotal.wanita}</div>
</TableCell>
<TableCell className="text-center">
<div className="font-bold text-lg">
{grandTotal.total_mahasiswa}
</div>
</TableCell>
</TableRow>
</>
)}
</TableBody>
</Table>
</div>
</CardContent>
</Card>
);
}