From d6d8fc3b320797004b82ec2fa7db196ebc5878a6 Mon Sep 17 00:00:00 2001 From: Randa Firman Putra Date: Thu, 11 Sep 2025 13:51:01 +0700 Subject: [PATCH] add new feature --- .../datatable/biodata-mahasiswa-dialog.tsx | 411 ++++++++++++++++++ components/datatable/data-table-mahasiswa.tsx | 2 + 2 files changed, 413 insertions(+) create mode 100644 components/datatable/biodata-mahasiswa-dialog.tsx diff --git a/components/datatable/biodata-mahasiswa-dialog.tsx b/components/datatable/biodata-mahasiswa-dialog.tsx new file mode 100644 index 0000000..1f1874c --- /dev/null +++ b/components/datatable/biodata-mahasiswa-dialog.tsx @@ -0,0 +1,411 @@ +"use client"; + +import { useState, useEffect } from "react"; +import { + Dialog, + DialogContent, + DialogHeader, + DialogTitle, + DialogTrigger, +} from "@/components/ui/dialog"; +import { Button } from "@/components/ui/button"; +import { Card, CardContent, CardHeader, CardTitle } from "@/components/ui/card"; +import { + User, + Loader2, + Calendar, + MapPin, + GraduationCap, + Trophy, + DollarSign, + Mail, + Phone, + BookOpen, + Award +} from "lucide-react"; + +// Interface definitions +interface MahasiswaData { + nim: string; + nama: string; + jk: "Pria" | "Wanita"; + agama: string | null; + kabupaten: string | null; + provinsi: string | null; + jenis_pendaftaran: string | null; + tahun_angkatan: string; + ipk: number | null; + id_kelompok_keahlian: number | null; + nama_kelompok_keahlian: string | null; + status_kuliah: "Aktif" | "Cuti" | "Lulus" | "Non-Aktif"; + semester: number; + created_at: string; + updated_at: string; +} + +interface BeasiswaData { + id_beasiswa: number; + nim: string; + nama: string; + nama_beasiswa: string; + sumber_beasiswa: string; + jenis_beasiswa: "Pemerintah" | "Non-Pemerintah"; + created_at: string; +} + +interface PrestasiData { + id_prestasi: number; + nim: string; + nama: string; + jenis_prestasi: "Akademik" | "Non-Akademik"; + nama_prestasi: string; + tingkat_prestasi: "Kabupaten" | "Provinsi" | "Nasional" | "Internasional"; + peringkat: string; + tanggal_prestasi: string; + keterangan: string | null; + created_at: string; +} + +interface BiodataMahasiswaDialogProps { + nim: string; + nama: string; +} + +export default function BiodataMahasiswaDialog({ nim, nama }: BiodataMahasiswaDialogProps) { + const [isOpen, setIsOpen] = useState(false); + const [loading, setLoading] = useState(false); + const [error, setError] = useState(null); + + // Data states + const [mahasiswaData, setMahasiswaData] = useState(null); + const [beasiswaData, setBeasiswaData] = useState([]); + const [prestasiData, setPrestasiData] = useState([]); + + // Fetch all data when dialog opens + const fetchBiodataData = async () => { + try { + setLoading(true); + setError(null); + + // Fetch mahasiswa data + const mahasiswaResponse = await fetch(`/api/keloladata/data-mahasiswa`); + if (!mahasiswaResponse.ok) { + throw new Error("Failed to fetch mahasiswa data"); + } + const mahasiswaResult = await mahasiswaResponse.json(); + + // Find specific student data + const studentData = Array.isArray(mahasiswaResult) + ? mahasiswaResult.find((m: MahasiswaData) => m.nim === nim) + : null; + + setMahasiswaData(studentData); + + // Fetch beasiswa data + try { + const beasiswaResponse = await fetch(`/api/keloladata/data-beasiswa-mahasiswa`); + if (beasiswaResponse.ok) { + const beasiswaResult = await beasiswaResponse.json(); + const filteredBeasiswa = Array.isArray(beasiswaResult) + ? beasiswaResult.filter((b: BeasiswaData) => b.nim === nim) + : []; + setBeasiswaData(filteredBeasiswa); + } else { + setBeasiswaData([]); + } + } catch (err) { + console.warn("Beasiswa data not available:", err); + setBeasiswaData([]); + } + + // Fetch prestasi data + try { + const prestasiResponse = await fetch(`/api/keloladata/data-prestasi-mahasiswa`); + if (prestasiResponse.ok) { + const prestasiResult = await prestasiResponse.json(); + const filteredPrestasi = Array.isArray(prestasiResult) + ? prestasiResult.filter((p: PrestasiData) => p.nim === nim) + : []; + setPrestasiData(filteredPrestasi); + } else { + setPrestasiData([]); + } + } catch (err) { + console.warn("Prestasi data not available:", err); + setPrestasiData([]); + } + + } catch (err) { + console.error("Error fetching biodata:", err); + setError(err instanceof Error ? err.message : "Failed to fetch data"); + } finally { + setLoading(false); + } + }; + + // Handle dialog open + const handleOpenChange = (open: boolean) => { + setIsOpen(open); + if (open) { + fetchBiodataData(); + } else { + // Reset data when closing + setMahasiswaData(null); + setBeasiswaData([]); + setPrestasiData([]); + setError(null); + } + }; + + + // Get status badge color + const getStatusColor = (status: string) => { + switch (status?.toLowerCase()) { + case "aktif": + return "bg-green-100 text-green-800 dark:bg-green-900 dark:text-green-100"; + case "cuti": + return "bg-yellow-100 text-yellow-800 dark:bg-yellow-900 dark:text-yellow-100"; + case "lulus": + return "bg-blue-100 text-blue-800 dark:bg-blue-900 dark:text-blue-100"; + case "non-aktif": + return "bg-red-100 text-red-800 dark:bg-red-900 dark:text-red-100"; + default: + return "bg-gray-100 text-gray-800 dark:bg-gray-900 dark:text-gray-100"; + } + }; + + return ( + + + + + + + + + Profil Mahasiswa - {nama} + + + + {loading ? ( +
+ + Memuat biodata... +
+ ) : error ? ( +
+ Error: {error} +
+ ) : ( +
+ {/* Data Pribadi */} + {mahasiswaData && ( + + + + + Data Pribadi + + + +
+
+ +

{mahasiswaData.nim}

+
+
+ +

{mahasiswaData.nama}

+
+
+ +

{mahasiswaData.jk}

+
+
+ +

{mahasiswaData.agama || "-"}

+
+
+ +

+ {mahasiswaData.kabupaten || "-"} +

+
+
+ +

+ {mahasiswaData.provinsi || "-"} +

+
+
+
+
+ )} + + {/* Data Akademik */} + {mahasiswaData && ( + + + + + Data Akademik + + + +
+
+ +

+ {mahasiswaData.tahun_angkatan} +

+
+
+ +

{mahasiswaData.jenis_pendaftaran || "-"}

+
+
+ +

+ {mahasiswaData.semester} +

+
+
+ +

+ {mahasiswaData.ipk ? Number(mahasiswaData.ipk).toFixed(2) : "-"} +

+
+
+ + + {mahasiswaData.status_kuliah} + +
+
+ +

{mahasiswaData.nama_kelompok_keahlian || "-"}

+
+
+
+
+ )} + +
+ + {/* Data Beasiswa */} + + + + + Riwayat Beasiswa + + + + {beasiswaData.length === 0 ? ( +

+ Tidak ada riwayat beasiswa +

+ ) : ( +
+ {beasiswaData.map((beasiswa) => ( +
+
+
+ +

{beasiswa.nama_beasiswa}

+
+
+ +

{beasiswa.sumber_beasiswa}

+
+
+ + + {beasiswa.jenis_beasiswa} + +
+
+
+ ))} +
+ )} +
+
+ + {/* Data Prestasi */} + + + + + Riwayat Prestasi + + + + {prestasiData.length === 0 ? ( +

+ Tidak ada riwayat prestasi +

+ ) : ( +
+ {prestasiData.map((prestasi) => ( +
+
+
+ +

{prestasi.nama_prestasi}

+
+
+ + + {prestasi.jenis_prestasi} + +
+
+ + + + {prestasi.tingkat_prestasi} + +
+
+ +

+ + {prestasi.peringkat} +

+
+
+ +

+ + {new Date(prestasi.tanggal_prestasi).toLocaleDateString('id-ID', { + day: '2-digit', + month: 'long', + year: 'numeric' + })} +

+
+
+
+ ))} +
+ )} +
+
+
+ )} +
+
+ ); +} diff --git a/components/datatable/data-table-mahasiswa.tsx b/components/datatable/data-table-mahasiswa.tsx index 38a5ca3..753b7e6 100644 --- a/components/datatable/data-table-mahasiswa.tsx +++ b/components/datatable/data-table-mahasiswa.tsx @@ -48,6 +48,7 @@ import { } from "lucide-react"; import EditJenisPendaftaran from "@/components/datatable/edit-jenis-pendaftaran"; import UploadExcelMahasiswa from "@/components/datatable/upload-excel-mahasiswa"; +import BiodataMahasiswaDialog from "@/components/datatable/biodata-mahasiswa-dialog"; import { useToast } from "@/components/ui/toast-provider"; // Define the Mahasiswa type based on API route structure @@ -788,6 +789,7 @@ export default function DataTableMahasiswa() { {mhs.nama_kelompok_keahlian || "-"}
+