import { useEffect, useState } from "react"; import { api, type DocumentCategory, type Entity, type PortalDocument, type User, } from "../api"; import { categoryLabel, formatBytes, formatDate } from "../format"; const CATEGORIES: DocumentCategory[] = ["statement", "k1", "capital_account", "tax", "other"]; export default function FundAdminHome() { const [entities, setEntities] = useState([]); const [error, setError] = useState(""); const [loading, setLoading] = useState(true); useEffect(() => { api .listEntities() .then(setEntities) .catch((e) => setError(e.message)) .finally(() => setLoading(false)); }, []); if (loading) return

Loading…

; if (error) return

{error}

; if (entities.length === 0) return

You don't have access to any entities yet.

; return (
{entities.map((e) => ( ))}
); } function EntityDocs({ entity }: { entity: Entity }) { const [docs, setDocs] = useState([]); const [investors, setInvestors] = useState([]); const [error, setError] = useState(""); const load = () => { api.listDocuments({ entity_id: entity.id }).then(setDocs).catch((e) => setError(e.message)); }; useEffect(() => { load(); api.investorsForEntity(entity.id).then(setInvestors).catch(() => {}); }, [entity.id]); const investorName = (id: number | null) => id == null ? "Shared (all investors)" : investors.find((i) => i.id === id)?.name ?? `Investor ${id}`; return (

{entity.name}

{entity.type}
{error &&

{error}

}

Documents

{docs.length === 0 ? (

No documents yet.

) : (
    {docs.map((d) => (
  • {d.title} {categoryLabel(d.category)} · {investorName(d.investor_user_id)} {formatDate(d.created_at)} Download
  • ))}
)}
); } function UploadForm({ entity, investors, onUploaded, setError, }: { entity: Entity; investors: User[]; onUploaded: () => void; setError: (s: string) => void; }) { const [category, setCategory] = useState("statement"); const [investorId, setInvestorId] = useState(""); const [title, setTitle] = useState(""); const [file, setFile] = useState(null); const [busy, setBusy] = useState(false); const submit = async () => { if (!file) return; setError(""); setBusy(true); try { const form = new FormData(); form.set("entity_id", String(entity.id)); form.set("category", category); if (title) form.set("title", title); if (investorId !== "") form.set("investor_user_id", String(investorId)); form.set("file", file); await api.uploadDocument(form); setTitle(""); setFile(null); setInvestorId(""); onUploaded(); } catch (e: any) { setError(e.message || "Upload failed"); } finally { setBusy(false); } }; return (
setTitle(e.target.value)} />
setFile(e.target.files?.[0] ?? null)} className="text-sm" /> {file && {formatBytes(file.size)}}
); } const inputCls = "w-full px-3 py-2 border border-gray-300 rounded text-sm focus:outline-none focus:ring-2 focus:ring-orange-500 focus:border-transparent";