'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 { Select, SelectContent, SelectItem, SelectTrigger, SelectValue } from "@/components/ui/select"; import { Pagination, PaginationContent, PaginationEllipsis, PaginationItem, PaginationLink, PaginationNext, PaginationPrevious, } from "@/components/ui/pagination"; import { Loader2, AlertTriangle } from "lucide-react"; interface MahasiswaTerancamDO { nim: string; nama: string; tahun_angkatan: number; ipk: number | null; semester: number; sks_total: number | null; alasan_do: string; } interface TabelNamaTerancamDOProps { selectedYear: string; } export default function TabelNamaTerancamDO({ selectedYear }: TabelNamaTerancamDOProps) { const [mahasiswaData, setMahasiswaData] = useState([]); const [loading, setLoading] = useState(true); const [error, setError] = useState(null); // State for pagination const [currentPage, setCurrentPage] = useState(1); const [pageSize, setPageSize] = useState(10); const [paginatedData, setPaginatedData] = useState([]); useEffect(() => { const fetchData = async () => { try { setLoading(true); setError(null); const url = selectedYear === 'all' ? '/api/tabeldetail/terancam-do' : `/api/tabeldetail/terancam-do?tahun_angkatan=${selectedYear}`; const response = await fetch(url, { cache: 'no-store', }); if (!response.ok) { throw new Error('Failed to fetch mahasiswa terancam DO data'); } const data = await response.json(); setMahasiswaData(data); } catch (err) { setError(err instanceof Error ? err.message : 'Terjadi kesalahan'); console.error('Error fetching data:', err); } finally { setLoading(false); } }; fetchData(); }, [selectedYear]); // Update paginated data when data or pagination settings change useEffect(() => { paginateData(); }, [mahasiswaData, currentPage, pageSize]); // Paginate data const paginateData = () => { const startIndex = (currentPage - 1) * pageSize; const endIndex = startIndex + pageSize; setPaginatedData(mahasiswaData.slice(startIndex, endIndex)); }; // Get total number of pages const getTotalPages = () => { return Math.ceil(mahasiswaData.length / pageSize); }; // Handle page change const handlePageChange = (page: number) => { setCurrentPage(page); }; // Handle page size change const handlePageSizeChange = (size: string) => { setPageSize(Number(size)); setCurrentPage(1); // Reset to first page when changing page size }; // Hitung statistik tahun angkatan const tahunAngkatanStats = mahasiswaData.reduce((acc, mahasiswa) => { const tahun = mahasiswa.tahun_angkatan; acc[tahun] = (acc[tahun] || 0) + 1; return acc; }, {} as Record); // Hitung statistik semester const semesterStats = mahasiswaData.reduce((acc, mahasiswa) => { const sem = mahasiswa.semester; acc[sem] = (acc[sem] || 0) + 1; return acc; }, {} as Record); const stats = { total: mahasiswaData.length, total_tahun_angkatan: Object.keys(tahunAngkatanStats).length, total_semester: Object.keys(semesterStats).length }; if (loading) { return (
Loading...
); } if (error) { return ( Error: {error} ); } return ( Tabel Mahasiswa Terancam DO {selectedYear !== 'all' ? `Angkatan ${selectedYear}` : 'Semua Angkatan'} {/* Tampilkan ringkasan statistik */}
Total Mahasiswa Terancam DO
{stats.total}
{/* Tampilkan ringkasan per tahun angkatan */}
{Object.entries(tahunAngkatanStats) .sort(([a], [b]) => Number(a) - Number(b)) // Urutkan berdasarkan tahun angkatan .map(([tahun, count]) => ( Angkatan {tahun}: {count} mahasiswa ))}
{/* Show entries selector */}
Show entries
No NIM Nama Mahasiswa Tahun Angkatan IPK Semester SKS Total Alasan DO {paginatedData.length === 0 ? ( Tidak ada data yang tersedia ) : ( paginatedData.map((mahasiswa, index) => ( {(currentPage - 1) * pageSize + index + 1} {mahasiswa.nim} {mahasiswa.nama} {mahasiswa.tahun_angkatan} {mahasiswa.ipk !== null ? mahasiswa.ipk.toFixed(2) : '-'} {mahasiswa.semester} {mahasiswa.sks_total !== null ? mahasiswa.sks_total : '-'} {mahasiswa.alasan_do || '-'} )) )}
{/* Pagination info and controls */} {!loading && !error && mahasiswaData.length > 0 && (
Showing {getDisplayRange().start} to {getDisplayRange().end} of {mahasiswaData.length} entries
handlePageChange(Math.max(1, currentPage - 1))} className={currentPage === 1 ? "pointer-events-none opacity-50" : "cursor-pointer"} /> {renderPaginationItems()} handlePageChange(Math.min(getTotalPages(), currentPage + 1))} className={currentPage === getTotalPages() ? "pointer-events-none opacity-50" : "cursor-pointer"} />
)}
); // Calculate the range of entries being displayed function getDisplayRange() { if (mahasiswaData.length === 0) return { start: 0, end: 0 }; const start = (currentPage - 1) * pageSize + 1; const end = Math.min(currentPage * pageSize, mahasiswaData.length); return { start, end }; } // Generate pagination items function renderPaginationItems() { const totalPages = getTotalPages(); const items = []; // Always show first page items.push( handlePageChange(1)} className="cursor-pointer" > 1 ); // Show ellipsis if needed if (currentPage > 3) { items.push( ); } // Show pages around current page for (let i = Math.max(2, currentPage - 1); i <= Math.min(totalPages - 1, currentPage + 1); i++) { if (i === 1 || i === totalPages) continue; // Skip first and last pages as they're always shown items.push( handlePageChange(i)} className="cursor-pointer" > {i} ); } // Show ellipsis if needed if (currentPage < totalPages - 2) { items.push( ); } // Always show last page if there's more than one page if (totalPages > 1) { items.push( handlePageChange(totalPages)} className="cursor-pointer" > {totalPages} ); } return items; } }