"use client"; import { useState, useMemo, useCallback } from "react"; import Link from "next/link"; import type { FileRecord } from "@/lib/store"; type SortOrder = "newest" | "oldest" | "name" | "size-desc" | "size-asc"; type TypeFilter = "all" | "backerup" | "config"; function formatBytes(n: number) { if (n < 1024) return `${n} B`; if (n < 1024 * 1024) return `${(n / 1024).toFixed(1)} KB`; return `${(n / 1024 / 1024).toFixed(2)} MB`; } function formatDate(s: string) { return new Date(s).toLocaleDateString("en-US", { month: "short", day: "numeric", year: "numeric", }); } function SearchIcon() { return ( ); } function ArrowIcon() { return ( ); } function XIcon() { return ( ); } function SortIcon() { return ( ); } function TrashIcon() { return ( ); } export default function BrowseClient({ records: allRecords, groups, isAdmin = false, }: { records: FileRecord[]; groups: string[]; isAdmin?: boolean; }) { const [records, setRecords] = useState(allRecords); const [search, setSearch] = useState(""); const [selectedGroup, setSelectedGroup] = useState(null); const [typeFilter, setTypeFilter] = useState("all"); const [sort, setSort] = useState("newest"); const [deleting, setDeleting] = useState(null); const handleDelete = useCallback(async (token: string, name: string, e: React.MouseEvent) => { e.preventDefault(); e.stopPropagation(); if (!confirm(`Delete "${name}"?\n\nThis permanently removes the file and cannot be undone.`)) return; setDeleting(token); try { const res = await fetch(`/api/files/${token}`, { method: "DELETE" }); if (res.ok) { setRecords((prev) => prev.filter((r) => r.token !== token)); } else { const data = await res.json().catch(() => ({})) as { error?: string }; alert(data.error ?? `Delete failed (${res.status})`); } } catch { alert("Network error – could not delete file"); } finally { setDeleting(null); } }, []); const filtered = useMemo(() => { let r = records; if (search.trim()) { const q = search.toLowerCase(); r = r.filter( (rec) => rec.displayName?.toLowerCase().includes(q) || rec.originalName.toLowerCase().includes(q) || rec.description?.toLowerCase().includes(q) || rec.containerName?.toLowerCase().includes(q) || rec.image?.toLowerCase().includes(q) || rec.group?.toLowerCase().includes(q) ); } if (selectedGroup) r = r.filter((rec) => rec.group === selectedGroup); if (typeFilter !== "all") r = r.filter((rec) => rec.type === typeFilter); const sorted = [...r]; switch (sort) { case "newest": sorted.sort((a, b) => new Date(b.uploadedAt).getTime() - new Date(a.uploadedAt).getTime()); break; case "oldest": sorted.sort((a, b) => new Date(a.uploadedAt).getTime() - new Date(b.uploadedAt).getTime()); break; case "name": sorted.sort((a, b) => (a.displayName ?? a.originalName).localeCompare(b.displayName ?? b.originalName) ); break; case "size-desc": sorted.sort((a, b) => b.size - a.size); break; case "size-asc": sorted.sort((a, b) => a.size - b.size); break; } return sorted; }, [records, search, selectedGroup, typeFilter, sort]); const activeFilters = (search.trim() ? 1 : 0) + (selectedGroup ? 1 : 0) + (typeFilter !== "all" ? 1 : 0); function clearAll() { setSearch(""); setSelectedGroup(null); setTypeFilter("all"); setSort("newest"); } return (
{/* ── Search + Sort row ── */}
setSearch(e.target.value)} className="w-full rounded-xl border border-white/8 bg-white/4 pl-10 pr-4 py-2.5 text-sm text-slate-200 placeholder-slate-600 outline-none focus:border-cyan-500/40 focus:bg-white/6 transition-all" /> {search && ( )}
{/* ── Filter pills ── */}
{/* Type pills */} {(["all", "backerup", "config"] as TypeFilter[]).map((t) => ( ))} {groups.length > 0 && ( <>
{groups.map((g) => ( ))} )} {activeFilters > 0 && ( )}
{/* ── Results count ── */}

{filtered.length === records.length ? `${records.length} file${records.length !== 1 ? "s" : ""} shared by the community` : `${filtered.length} of ${records.length} files`}

{/* ── Cards ── */} {filtered.length === 0 ? (
🔍

No results found

Try adjusting your search or clearing some filters.

{activeFilters > 0 && ( )}
) : (
{filtered.map((r) => (
{/* Badges */}
{r.type === "backerup" ? ( .backerup ) : ( .json config )} {r.group && ( {r.group} )}
{/* Title */} {(r.displayName ?? r.containerName) ? (

{r.displayName ?? r.containerName}

) : (

{r.originalName}

)} {/* Image */} {r.image && (

{r.image}

)} {/* Description */} {r.description && (

{r.description}

)}
{/* Arrow */}
{/* Card footer: meta row + admin delete inline */}
{formatBytes(r.size)} · {formatDate(r.uploadedAt)} {r.containerName && r.displayName && ( <> · {r.containerName} )} {isAdmin && ( )}
))}
)}
); }