'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, MapPin } from "lucide-react"; interface MahasiswaAsalDaerah { nim: string; nama: string; tahun_angkatan: number; kabupaten: string; } interface TabelAsalDaerahMahasiswaProps { selectedYear: string; } export default function TabelAsalDaerahMahasiswa({ selectedYear }: TabelAsalDaerahMahasiswaProps) { 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/asal-daerah' : `/api/tabeldetail/asal-daerah?tahun_angkatan=${selectedYear}`; const response = await fetch(url, { cache: 'no-store', }); if (!response.ok) { throw new Error('Failed to fetch mahasiswa asal daerah 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 berdasarkan kabupaten const kabupatenStats = mahasiswaData.reduce((acc, mahasiswa) => { const kabupaten = mahasiswa.kabupaten; acc[kabupaten] = (acc[kabupaten] || 0) + 1; return acc; }, {} as Record); // 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); const stats = { total: mahasiswaData.length, total_kabupaten: Object.keys(kabupatenStats).length, total_tahun_angkatan: Object.keys(tahunAngkatanStats).length }; if (loading) { return (
Loading...
); } if (error) { return ( Error: {error} ); } return ( Tabel Asal Daerah Mahasiswa {selectedYear !== 'all' ? `Angkatan ${selectedYear}` : 'Semua Angkatan'} {/* Tampilkan ringkasan statistik */}
Total Mahasiswa
{stats.total}
Total Kabupaten
{stats.total_kabupaten}
Total Tahun Angkatan
{stats.total_tahun_angkatan}
{/* Tampilkan ringkasan kabupaten terbanyak */}
{Object.entries(kabupatenStats) .sort(([,a], [,b]) => b - a) // Urutkan berdasarkan jumlah mahasiswa terbanyak .slice(0, 5) // Ambil 5 kabupaten teratas .map(([kabupaten, count]) => ( {kabupaten}: {count} ))} {Object.keys(kabupatenStats).length > 5 && ( +{Object.keys(kabupatenStats).length - 5} lainnya )}
{/* Show entries selector */}
Show entries
No NIM Nama Mahasiswa Tahun Angkatan Asal Kabupaten {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.kabupaten} )) )}
{/* 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; } }