"use client"; import { useState, useEffect } from "react"; import { Table, TableBody, TableCell, TableHead, TableHeader, TableRow } from "@/components/ui/table"; import { Button } from "@/components/ui/button"; import { Input } from "@/components/ui/input"; import { Dialog, DialogContent, DialogHeader, DialogTitle, DialogFooter, DialogClose } from "@/components/ui/dialog"; import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue } from "@/components/ui/select"; import { Pagination, PaginationContent, PaginationEllipsis, PaginationItem, PaginationLink, PaginationNext, PaginationPrevious, } from "@/components/ui/pagination"; import { PlusCircle, Pencil, Trash2, Search, X, Loader2, Filter } from "lucide-react"; import UploadExcelBeasiswaMahasiswa from "@/components/datatable/upload-file-beasiswa-mahasiswa"; import { useToast } from "@/components/ui/toast-provider"; // Define the BeasiswaMahasiswa type interface BeasiswaMahasiswa { id_beasiswa: number; nim: string; nama: string; nama_beasiswa: string; sumber_beasiswa: string; jenis_beasiswa: "Pemerintah" | "Non-Pemerintah"; created_at: string; } export default function DataTableBeasiswaMahasiswa() { const { showSuccess, showError } = useToast(); // State for data const [beasiswaMahasiswa, setBeasiswaMahasiswa] = useState([]); const [filteredData, setFilteredData] = useState([]); const [loading, setLoading] = useState(true); const [error, setError] = useState(null); // State for filtering const [searchTerm, setSearchTerm] = useState(""); const [filterJenisBeasiswa, setFilterJenisBeasiswa] = useState(""); // State for pagination const [currentPage, setCurrentPage] = useState(1); const [pageSize, setPageSize] = useState(10); const [paginatedData, setPaginatedData] = useState([]); // State for form const [formMode, setFormMode] = useState<"add" | "edit">("add"); const [formData, setFormData] = useState>({ jenis_beasiswa: "Pemerintah" }); const [isSubmitting, setIsSubmitting] = useState(false); const [isDialogOpen, setIsDialogOpen] = useState(false); // State for delete confirmation const [deleteId, setDeleteId] = useState(null); const [isDeleting, setIsDeleting] = useState(false); const [isDeleteDialogOpen, setIsDeleteDialogOpen] = useState(false); // Fetch data on component mount useEffect(() => { fetchBeasiswaMahasiswa(); }, []); // Filter data when search term or filter changes useEffect(() => { filterData(); }, [searchTerm, filterJenisBeasiswa, beasiswaMahasiswa]); // Update paginated data when filtered data or pagination settings change useEffect(() => { paginateData(); }, [filteredData, currentPage, pageSize]); // Fetch beasiswa mahasiswa data from API const fetchBeasiswaMahasiswa = async () => { try { setLoading(true); let url = "/api/keloladata/data-beasiswa-mahasiswa"; // Add filters to URL if they exist const params = new URLSearchParams(); if (searchTerm) { params.append("search", searchTerm); } if (filterJenisBeasiswa && filterJenisBeasiswa !== "all") { params.append("jenis_beasiswa", filterJenisBeasiswa); } if (params.toString()) { url += `?${params.toString()}`; } const response = await fetch(url); if (!response.ok) { throw new Error("Failed to fetch data"); } const data = await response.json(); setBeasiswaMahasiswa(data); setFilteredData(data); setError(null); } catch (err) { setError("Error fetching data. Please try again later."); console.error("Error fetching data:", err); } finally { setLoading(false); } }; // Filter data based on search term and filters const filterData = () => { let filtered = [...beasiswaMahasiswa]; // Filter by search term if (searchTerm) { filtered = filtered.filter( (item) => (item.nim?.toLowerCase() || "").includes(searchTerm.toLowerCase()) || (item.nama?.toLowerCase() || "").includes(searchTerm.toLowerCase()) || (item.nama_beasiswa?.toLowerCase() || "").includes(searchTerm.toLowerCase()) || (item.sumber_beasiswa?.toLowerCase() || "").includes(searchTerm.toLowerCase()) ); } // Filter by jenis beasiswa if (filterJenisBeasiswa && filterJenisBeasiswa !== "all") { filtered = filtered.filter((item) => item.jenis_beasiswa === filterJenisBeasiswa); } setFilteredData(filtered); // Reset to first page when filters change setCurrentPage(1); }; // Paginate data const paginateData = () => { const startIndex = (currentPage - 1) * pageSize; const endIndex = startIndex + pageSize; setPaginatedData(filteredData.slice(startIndex, endIndex)); }; // Get total number of pages const getTotalPages = () => { return Math.ceil(filteredData.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 }; // Reset form data const resetForm = () => { setFormData({ jenis_beasiswa: "Pemerintah" }); }; // Handle form input changes const handleInputChange = (e: React.ChangeEvent) => { const { name, value } = e.target; setFormData((prev) => ({ ...prev, [name]: value })); }; // Handle select input changes const handleSelectChange = (name: string, value: string) => { setFormData((prev) => ({ ...prev, [name]: value })); }; // Open form dialog for adding new beasiswa const handleAdd = () => { setFormMode("add"); resetForm(); setIsDialogOpen(true); }; // Open form dialog for editing beasiswa const handleEdit = (data: BeasiswaMahasiswa) => { setFormMode("edit"); setFormData(data); setIsDialogOpen(true); }; // Open delete confirmation dialog const handleDeleteConfirm = (id: number) => { setDeleteId(id); setIsDeleteDialogOpen(true); }; // Submit form for add/edit const handleSubmit = async (e: React.FormEvent) => { e.preventDefault(); try { setIsSubmitting(true); if (formMode === "add") { // Add new beasiswa const response = await fetch("/api/keloladata/data-beasiswa-mahasiswa", { method: "POST", headers: { "Content-Type": "application/json", }, body: JSON.stringify(formData), }); const responseData = await response.json(); if (!response.ok) { // Handle specific NIM not found error if (response.status === 404 && responseData.message.includes("tidak terdaftar")) { showError("Gagal!", `NIM ${formData.nim} tidak terdaftar dalam database. Silakan cek kembali NIM yang dimasukkan.`); throw new Error(`NIM ${formData.nim} tidak terdaftar. Silakan cek kembali NIM yang dimasukkan.`); } showError("Gagal!", "Gagal menambahkan beasiswa"); throw new Error(responseData.message || "Failed to add beasiswa"); } // Show success message with student info showSuccess("Berhasil!", "Beasiswa mahasiswa berhasil ditambahkan"); } else { // Edit existing beasiswa const response = await fetch(`/api/keloladata/data-beasiswa-mahasiswa?id=${formData.id_beasiswa}`, { method: "PUT", headers: { "Content-Type": "application/json", }, body: JSON.stringify(formData), }); const responseData = await response.json(); if (!response.ok) { // Handle specific NIM not found error if (response.status === 404 && responseData.message.includes("tidak terdaftar")) { throw new Error(`NIM ${formData.nim} tidak terdaftar. Silakan cek kembali NIM yang dimasukkan.`); } showError("Gagal!", responseData.message || "Failed to update beasiswa"); throw new Error(responseData.message || "Failed to update beasiswa"); } showSuccess("Berhasil!", "Beasiswa mahasiswa berhasil diperbarui"); } // Refresh data after successful operation await fetchBeasiswaMahasiswa(); setIsDialogOpen(false); resetForm(); } catch (err) { console.error("Error submitting form:", err); } finally { setIsSubmitting(false); } }; // Delete beasiswa const handleDelete = async () => { if (!deleteId) return; try { setIsDeleting(true); const response = await fetch(`/api/keloladata/data-beasiswa-mahasiswa?id=${deleteId}`, { method: "DELETE", }); if (!response.ok) { const errorData = await response.json(); throw new Error(errorData.message || "Failed to delete beasiswa"); } // Refresh data after successful deletion await fetchBeasiswaMahasiswa(); setIsDeleteDialogOpen(false); setDeleteId(null); showSuccess("Berhasil!", "Beasiswa mahasiswa berhasil dihapus"); } catch (err) { console.error("Error deleting beasiswa:", err); } finally { setIsDeleting(false); } }; // Generate pagination items const renderPaginationItems = () => { const totalPages = getTotalPages(); const items = []; // Always show first page items.push( handlePageChange(1)} > 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)} > {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)} > {totalPages} ); } return items; }; // Calculate the range of entries being displayed const getDisplayRange = () => { if (filteredData.length === 0) return { start: 0, end: 0 }; const start = (currentPage - 1) * pageSize + 1; const end = Math.min(currentPage * pageSize, filteredData.length); return { start, end }; }; return (

Data Beasiswa Mahasiswa

{/* Filters */}
setSearchTerm(e.target.value)} /> {searchTerm && ( setSearchTerm("")} /> )}
{/* Show entries selector */}
Show entries
{/* Table */} {loading ? (
) : error ? (
{error}
) : (
{/* ID */} NIM Nama Nama Beasiswa Sumber Beasiswa Jenis Beasiswa {/* Tanggal */} Aksi {paginatedData.length === 0 ? ( Tidak ada data yang sesuai dengan filter ) : ( paginatedData.map((beasiswa) => ( {/* {beasiswa.id_beasiswa} */} {beasiswa.nim} {beasiswa.nama} {beasiswa.nama_beasiswa} {beasiswa.sumber_beasiswa} {beasiswa.jenis_beasiswa}
)) )}
)} {/* Pagination info and controls */} {!loading && !error && filteredData.length > 0 && (
Showing {getDisplayRange().start} to {getDisplayRange().end} of {filteredData.length} entries
handlePageChange(Math.max(1, currentPage - 1))} className={currentPage === 1 ? "pointer-events-none opacity-50" : ""} /> {renderPaginationItems()} handlePageChange(Math.min(getTotalPages(), currentPage + 1))} className={currentPage === getTotalPages() ? "pointer-events-none opacity-50" : ""} />
)} {/* Add/Edit Dialog */} {formMode === "add" ? "Tambah Beasiswa" : "Edit Beasiswa"}
{/* Delete Confirmation Dialog */} Konfirmasi Hapus

Apakah Anda yakin ingin menghapus data beasiswa ini?

Tindakan ini tidak dapat dibatalkan.

); }