"use client"; import { useParams, useRouter } from "next/navigation"; import { useCallback, useEffect, useRef, useState } from "react"; import { api } from "@/lib/api/client"; import type { components } from "@/lib/api/schema"; import { Button } from "@/components/ui/button"; import { Card, CardContent } from "@/components/ui/card"; type Media = components["schemas"]["MediaRead"]; function humanSize(bytes: number) { if (bytes < 1024) return `${bytes} B`; if (bytes < 1024 * 1024) return `${(bytes / 1024).toFixed(0)} KB`; return `${(bytes / 1024 / 1024).toFixed(1)} MB`; } export default function MediaPage() { const router = useRouter(); const params = useParams<{ id: string }>(); const treeId = params.id; const [items, setItems] = useState([]); const [ready, setReady] = useState(false); const [uploading, setUploading] = useState(false); const fileRef = useRef(null); const load = useCallback(async () => { const { data, response } = await api.GET("/api/v1/trees/{tree_id}/media", { params: { path: { tree_id: treeId } }, }); if (response.status === 401) { router.push("/login"); return; } setItems(data ?? []); setReady(true); }, [router, treeId]); useEffect(() => { load(); }, [load]); async function onFile(e: React.ChangeEvent) { const file = e.target.files?.[0]; if (!file) return; setUploading(true); const fd = new FormData(); fd.append("file", file); // Plain fetch for multipart (same origin → cookie auth via Caddy). await fetch(`/api/v1/trees/${treeId}/media`, { method: "POST", body: fd, credentials: "include", }); setUploading(false); if (fileRef.current) fileRef.current.value = ""; load(); } async function remove(id: string) { await api.DELETE("/api/v1/trees/{tree_id}/media/{media_id}", { params: { path: { tree_id: treeId, media_id: id } }, }); load(); } if (!ready) return

Loading…

; return (

Media

{items.length === 0 ? (

No media yet — upload scans, photos, or documents and attach them to facts.

) : (
{items.map((m) => ( {m.content_type.startsWith("image/") ? ( // eslint-disable-next-line @next/next/no-img-element {m.title ) : (
{(m.original_filename.split(".").pop() ?? "file").toUpperCase()}
)}
{m.title ?? m.original_filename}
{humanSize(m.byte_size)}
))}
)}
); }