'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, Users } from "lucide-react"; interface MahasiswaBimbinganDosen { nim: string; nama: string; tahun_angkatan: number; nama_pembimbing_1: string | null; nama_pembimbing_2: string | null; status_bimbingan: string; } interface TabelBimbinganDosenMahasiswaProps { selectedYear: string; selectedDosen: string; } export default function TabelBimbinganDosenMahasiswa({ selectedYear, selectedDosen }: TabelBimbinganDosenMahasiswaProps) { 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); let url = '/api/tabeldetail/bimbingan-dosen?'; const params = new URLSearchParams(); if (selectedYear !== 'all') { params.append('tahun_angkatan', selectedYear); } if (selectedDosen !== 'all') { params.append('nama_dosen', selectedDosen); } url += params.toString(); const response = await fetch(url, { cache: 'no-store', }); if (!response.ok) { throw new Error('Failed to fetch mahasiswa bimbingan dosen 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, selectedDosen]); // 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 }; // Fungsi untuk mendapatkan styling berdasarkan status bimbingan const getStatusBimbinganStyle = (status: string) => { switch (status) { case "Selesai": return "bg-green-100 text-green-800 dark:bg-green-900 dark:text-green-300"; case "Belum Selesai": return "bg-yellow-100 text-yellow-800 dark:bg-yellow-900 dark:text-yellow-300"; default: return "bg-gray-100 text-gray-800 dark:bg-gray-900 dark:text-gray-300"; } }; // Hitung statistik berdasarkan status bimbingan const statusStats = mahasiswaData.reduce((acc, mahasiswa) => { const status = mahasiswa.status_bimbingan; acc[status] = (acc[status] || 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); // Hitung statistik dosen pembimbing const dosenStats = mahasiswaData.reduce((acc, mahasiswa) => { if (mahasiswa.nama_pembimbing_1) { acc[mahasiswa.nama_pembimbing_1] = (acc[mahasiswa.nama_pembimbing_1] || 0) + 1; } if (mahasiswa.nama_pembimbing_2) { acc[mahasiswa.nama_pembimbing_2] = (acc[mahasiswa.nama_pembimbing_2] || 0) + 1; } return acc; }, {} as Record); const stats = { total: mahasiswaData.length, total_status: Object.keys(statusStats).length, total_tahun_angkatan: Object.keys(tahunAngkatanStats).length, total_dosen: Object.keys(dosenStats).length }; if (loading) { return (
Loading...
); } if (error) { return ( Error: {error} ); } return ( Tabel Bimbingan Dosen Mahasiswa {selectedYear !== 'all' ? `Angkatan ${selectedYear}` : 'Semua Angkatan'} {selectedDosen !== 'all' && ` - ${selectedDosen}`} {/* Tampilkan ringkasan statistik */}
Total Mahasiswa
{stats.total}
Total Tahun Angkatan
{stats.total_tahun_angkatan}
{/* Tampilkan ringkasan status bimbingan */}
{Object.entries(statusStats) .sort(([,a], [,b]) => b - a) // Urutkan berdasarkan jumlah mahasiswa terbanyak .map(([status, count]) => ( {status}: {count} ))}
{/* Show entries selector */}
Show entries
No NIM Nama Mahasiswa Tahun Angkatan Pembimbing 1 Pembimbing 2 Status Bimbingan {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.nama_pembimbing_1 || '-'} {mahasiswa.nama_pembimbing_2 || '-'} {mahasiswa.status_bimbingan} )) )}
{/* 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; } }