- {filtered.length === allRecords.length
- ? `${allRecords.length} file${allRecords.length !== 1 ? "s" : ""} shared by the community`
- : `${filtered.length} of ${allRecords.length} files`}
+ {filtered.length === records.length
+ ? `${records.length} file${records.length !== 1 ? "s" : ""} shared by the community`
+ : `${filtered.length} of ${records.length} files`}
{/* ── Cards ── */}
@@ -241,11 +273,11 @@ export default function BrowseClient({
) : (
{filtered.map((r) => (
-
+
+
{/* Badges */}
@@ -295,20 +327,34 @@ export default function BrowseClient({
-
- {/* Meta row */}
-
- {formatBytes(r.size)}
- ·
- {formatDate(r.uploadedAt)}
- {r.containerName && r.displayName && (
- <>
- ·
- {r.containerName}
- >
- )}
-
+
+ {/* Card footer: meta row + admin delete inline */}
+
+ {formatBytes(r.size)}
+ ·
+ {formatDate(r.uploadedAt)}
+ {r.containerName && r.displayName && (
+ <>
+ ·
+ {r.containerName}
+ >
+ )}
+ {isAdmin && (
+
+ )}
+
+
))}
)}
diff --git a/frontend/app/browse/page.tsx b/frontend/app/browse/page.tsx
index 4d374b6..eabeee0 100644
--- a/frontend/app/browse/page.tsx
+++ b/frontend/app/browse/page.tsx
@@ -1,9 +1,14 @@
import Link from "next/link";
import { readMeta, listGroups } from "@/lib/store";
+import { getSession } from "@/lib/session";
import BrowseClient from "./BrowseClient";
export default async function BrowsePage() {
- const [allRecords, groups] = await Promise.all([readMeta(), listGroups()]);
+ const [allRecords, groups, session] = await Promise.all([
+ readMeta(),
+ listGroups(),
+ getSession(),
+ ]);
return (
@@ -31,7 +36,7 @@ export default async function BrowsePage() {
{/* Client section: search + filter + cards */}
-
+
);
}
diff --git a/frontend/app/files/[token]/DeleteFileButton.tsx b/frontend/app/files/[token]/DeleteFileButton.tsx
new file mode 100644
index 0000000..6d89bf0
--- /dev/null
+++ b/frontend/app/files/[token]/DeleteFileButton.tsx
@@ -0,0 +1,55 @@
+"use client";
+
+import { useState } from "react";
+import { useRouter } from "next/navigation";
+
+export default function DeleteFileButton({ token, name }: { token: string; name: string }) {
+ const router = useRouter();
+ const [loading, setLoading] = useState(false);
+
+ async function handleDelete() {
+ if (!confirm(`Delete "${name}"?\n\nThis permanently removes the file and cannot be undone.`)) return;
+ setLoading(true);
+ try {
+ const res = await fetch(`/api/files/${token}`, { method: "DELETE" });
+ if (res.ok) {
+ router.push("/browse");
+ router.refresh();
+ } 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 {
+ setLoading(false);
+ }
+ }
+
+ return (
+