"use client"; import { useState } from "react"; import { ColumnDef, flexRender, getCoreRowModel, getPaginationRowModel, getSortedRowModel, useReactTable, SortingState, RowSelectionState, } from "@tanstack/react-table"; import { useQuery } from "@tanstack/react-query"; interface FileData { id: string; filename: string; mimetype: string; size: number; createdAt: string; updatedAt: string; } const columns: ColumnDef[] = [ { id: "select", header: ({ table }) => (
table.toggleAllPageRowsSelected(!!e.target.checked)} className="w-4 h-4 text-blue-600 bg-gray-100 border-gray-300 rounded focus:ring-blue-500" />
), cell: ({ row }) => (
row.toggleSelected(!!e.target.checked)} className="w-4 h-4 text-blue-600 bg-gray-100 border-gray-300 rounded focus:ring-blue-500" />
), enableSorting: false, enableHiding: false, }, { accessorKey: "filename", header: "File Name", cell: ({ row }) => (
{row.getValue("filename")}
), }, { accessorKey: "mimetype", header: "Type", cell: ({ row }) => (
{row.getValue("mimetype")}
), }, { accessorKey: "size", header: "Size", cell: ({ row }) => { const bytes = row.getValue("size") as number; if (bytes === 0) return "0 Bytes"; const k = 1024; const sizes = ["Bytes", "KB", "MB", "GB"]; const i = Math.floor(Math.log(bytes) / Math.log(k)); return parseFloat((bytes / Math.pow(k, i)).toFixed(2)) + " " + sizes[i]; }, }, { accessorKey: "createdAt", header: "Created", cell: ({ row }) => { const date = new Date(row.getValue("createdAt")); return date.toLocaleDateString("en-US", { year: "numeric", month: "short", day: "numeric", hour: "2-digit", minute: "2-digit", }); }, }, { accessorKey: "updatedAt", header: "Updated", cell: ({ row }) => { const date = new Date(row.getValue("updatedAt")); return date.toLocaleDateString("en-US", { year: "numeric", month: "short", day: "numeric", hour: "2-digit", minute: "2-digit", }); }, }, ]; export function FilesTable() { const [sorting, setSorting] = useState([]); const [rowSelection, setRowSelection] = useState({}); const { data, isLoading, isError, error, refetch } = useQuery({ queryKey: ["files"], queryFn: async () => { const response = await fetch("/api/files"); if (!response.ok) { throw new Error("Failed to fetch files"); } const data = await response.json(); return data.files as FileData[]; }, }); const table = useReactTable({ data: data || [], columns, state: { sorting, rowSelection, }, onSortingChange: setSorting, onRowSelectionChange: setRowSelection, getCoreRowModel: getCoreRowModel(), getPaginationRowModel: getPaginationRowModel(), getSortedRowModel: getSortedRowModel(), enableRowSelection: true, }); const handleRefresh = () => { refetch(); }; const handleDownload = (fileId: string, filename: string) => { const downloadUrl = `/api/files/${fileId}`; const link = document.createElement('a'); link.href = downloadUrl; link.download = filename; document.body.appendChild(link); link.click(); document.body.removeChild(link); }; const handleDownloadSelected = () => { const selectedRows = table.getSelectedRowModel().rows; if (selectedRows.length === 0) return; if (selectedRows.length === 1) { // Single file download const selected = selectedRows[0]; handleDownload(selected.original.id, selected.original.filename); } else { // Multiple files - download each one selectedRows.forEach((row, index) => { setTimeout(() => { handleDownload(row.original.id, row.original.filename); }, index * 500); // Stagger downloads by 500ms to avoid browser blocking }); } }; if (isLoading) { return (

Files in Database

{[...Array(5)].map((_, i) => (
))}
); } if (isError) { return (
Error: {error?.message || "Failed to load files"}
); } if (!data || data.length === 0) { return (

No files found

Upload some files to get started.

); } return (

Files in Database

{table.getHeaderGroups().map((headerGroup) => ( {headerGroup.headers.map((header) => ( ))} ))} {table.getRowModel().rows.map((row) => ( {row.getVisibleCells().map((cell) => ( ))} ))}
{flexRender(header.column.columnDef.header, header.getContext())} {header.column.getIsSorted() && ( {header.column.getIsSorted() === "asc" ? "↑" : "↓"} )}
{flexRender(cell.column.columnDef.cell, cell.getContext())}
{/* Pagination */}
Showing {table.getRowModel().rows.length} of {data.length} results
); }