"use client"; import { useEffect, useState } from "react"; import { Table, TableBody, TableCell, TableHead, TableHeader, TableRow, } from "@/components/ui/table"; import { Button } from "@/components/ui/button"; import { DownloadIcon, EyeOpenIcon, TrashIcon } from "@radix-ui/react-icons"; import { ChevronLeft, ChevronRight, Loader2 } from "lucide-react"; import { formatDatetime } from "@/utils/formatDatetime"; import { createClient } from "@/utils/supabase/client"; import { toast } from "@/hooks/use-toast"; interface FileTableProps { fetchData: () => Promise; ragData: any[]; } export default function FileTable({ fetchData, ragData }: FileTableProps) { const supabase = createClient(); const [loadingMap, setLoadingMap] = useState>({}); const [currentPage, setCurrentPage] = useState(1); const [sortedData, setSortedData] = useState([]); const itemsPerPage = 10; // Adjust as needed const pagesToShow = 2; // Number of page buttons to display at once useEffect(() => { // Sort data by created_at in descending order (newest first) if (ragData && ragData.length > 0) { const sorted = [...ragData].sort((a, b) => { return ( new Date(b.created_at).getTime() - new Date(a.created_at).getTime() ); }); setSortedData(sorted); } else { setSortedData([]); } }, [ragData]); const downloadAllFiles = async () => { try { const res = await fetch("/api/download-all"); if (!res.ok) { throw new Error("Gagal mengunduh file ZIP"); } const blob = await res.blob(); const url = URL.createObjectURL(blob); const link = document.createElement("a"); link.href = url; link.download = "all-files.zip"; document.body.appendChild(link); link.click(); document.body.removeChild(link); URL.revokeObjectURL(url); } catch (error) { toast({ title: "Gagal", description: "Tidak dapat mengunduh semua file.", variant: "destructive", }); } }; const deleteAllFiles = async () => { const confirmed = window.confirm("Yakin ingin menghapus SEMUA file?"); if (!confirmed) return; try { const fileNames = sortedData.map((item) => item.name); setLoadingMap( fileNames.reduce((acc, name) => ({ ...acc, [name]: true }), {}), ); const { error } = await supabase.storage .from("pnp-bot-storage") .remove(fileNames); if (error) { toast({ title: "Gagal menghapus semua file", description: error.message, variant: "destructive", }); } else { toast({ title: "Semua file berhasil dihapus", description: `${fileNames.length} file telah dihapus.`, }); fetchData(); // refresh data } } catch (err) { console.error("Gagal menghapus semua file:", err); toast({ title: "Terjadi kesalahan", description: "Tidak dapat menghapus semua file.", variant: "destructive", }); } finally { setLoadingMap({}); } }; const deleteItem = async (fileName: string) => { const confirmed = window.confirm( `Yakin ingin menghapus file "${fileName}"?`, ); if (!confirmed) return; try { setLoadingMap((prev) => ({ ...prev, [fileName]: true })); const { error } = await supabase.storage .from("pnp-bot-storage") .remove([fileName]); if (error) { toast({ title: "Gagal menghapus file", description: error.message, variant: "destructive", }); } else { toast({ title: "File berhasil dihapus", description: `File "${fileName}" telah dihapus.`, }); fetchData(); // refresh daftar file } } catch (err) { console.error("Gagal menghapus:", err); toast({ title: "Terjadi kesalahan", description: "Tidak dapat menghapus file.", variant: "destructive", }); } finally { setLoadingMap((prev) => ({ ...prev, [fileName]: false })); } }; // Lihat File (Open in New Tab) const inspectItem = (fileName: string) => { const { data } = supabase.storage .from("pnp-bot-storage") .getPublicUrl(fileName); if (!data?.publicUrl) { toast({ title: "Gagal membuka file", description: `File "${fileName}" tidak memiliki URL publik.`, variant: "destructive", }); return; } window.open(data.publicUrl, "_blank"); }; // Unduh File const downloadItem = async (fileName: string) => { try { // Retrieve the file as a blob using the download method const { data, error } = await supabase.storage .from("pnp-bot-storage") // Use your bucket name .download(fileName); if (error) { toast({ title: "Gagal mengunduh file", description: error.message || "Terjadi kesalahan saat mengunduh.", variant: "destructive", }); return; } // Create a link element to download the file const url = URL.createObjectURL(data); const link = document.createElement("a"); link.href = url; link.download = fileName; // Programmatically trigger the download document.body.appendChild(link); link.click(); document.body.removeChild(link); // Clean up the object URL URL.revokeObjectURL(url); toast({ title: "Unduh berhasil", description: `File "${fileName}" berhasil diunduh.`, duration: 2000, }); } catch (err) { console.error("Gagal mengunduh:", err); toast({ title: "Terjadi kesalahan", description: "Tidak dapat mengunduh file.", variant: "destructive", }); } }; // Calculate pagination const totalPages = Math.ceil(sortedData.length / itemsPerPage); const paginatedData = sortedData.slice( (currentPage - 1) * itemsPerPage, currentPage * itemsPerPage, ); const goToNextPage = () => { if (currentPage < totalPages) { setCurrentPage(currentPage + 1); } }; const goToPrevPage = () => { if (currentPage > 1) { setCurrentPage(currentPage - 1); } }; const goToPage = (page: number) => { setCurrentPage(page); }; // Calculate the range of page numbers to display const startPage = Math.max(1, currentPage - Math.floor(pagesToShow / 2)); const endPage = Math.min(totalPages, startPage + pagesToShow - 1); const pageNumbers = Array.from( { length: endPage - startPage + 1 }, (_, index) => startPage + index, ); return (
# Name Uploaded At File Size
{paginatedData && paginatedData.length > 0 ? ( paginatedData.map((item: any, index: number) => ( {(currentPage - 1) * itemsPerPage + index + 1} {item.name} {formatDatetime(item.created_at)} {item.metadata.size} )) ) : ( No Data Available )}
{/* Pagination Controls */} {sortedData.length > 0 && (
Showing{" "} {(currentPage - 1) * itemsPerPage + 1} {" "} to{" "} {Math.min(currentPage * itemsPerPage, sortedData.length)} {" "} of {sortedData.length} files
{/* Always show first page */} {/* Show "..." if current page is far from start */} {currentPage > 3 && ...} {/* Dynamic page numbers (middle range) */}
{Array.from({ length: Math.min(3, totalPages - 2) }, (_, i) => { let page; if (currentPage <= 2) page = i + 2; // Near start: 2, 3, 4 else if (currentPage >= totalPages - 1) page = totalPages - 2 + i; // Near end else page = currentPage - 1 + i; // Middle range if (page > 1 && page < totalPages) { return ( ); } return null; })}
{/* Show "..." if current page is far from end */} {currentPage < totalPages - 2 && ...} {/* Always show last page (if different from first) */} {totalPages > 1 && ( )}
)}
); }