// screens-library.jsx — library / asset grid + asset detail const { ASSETS: ALL_ASSETS, BINS, COMMENTS, PROJECTS } = window.ZAMPP_DATA; function Library({ navigate, onOpenAsset, project = "Protour 2026" }) { const [bin, setBin] = React.useState("b1"); const [view, setView] = React.useState("grid"); const [filter, setFilter] = React.useState("all"); const [search, setSearch] = React.useState(""); let assets = ALL_ASSETS; if (filter !== "all") assets = assets.filter(a => a.status === filter); if (search) assets = assets.filter(a => a.name.toLowerCase().includes(search.toLowerCase())); return (
{project}
· {assets.length} assets
setSearch(e.target.value)} placeholder="Filter assets…" />
{["all", "ready", "processing", "live", "error"].map(f => ( ))}
{view === "grid" ? (
{assets.map(a => onOpenAsset(a)} />)}
) : (
Name
Duration
Resolution
Codec
Size
Updated
{assets.map(a => (
onOpenAsset(a)}>
{a.name}
{a.status} {a.comments > 0 && · {a.comments} comments}
{a.duration}
{a.res}
{a.codec}
{a.size}
{a.updated}
))}
)}
); } function AssetCard({ asset, onOpen }) { return (
{asset.status === "live" && LIVE} {asset.status === "processing" && Proxy {asset.progress}%} {asset.status === "error" && Error}
{asset.type === "video" &&
{asset.duration}
} {asset.status === "processing" && (
)}
{asset.name}
{asset.res} · {asset.size} {asset.comments > 0 && ( {asset.comments} )}
); } function binIcon(name) { return { grid: "library", live: "record", film: "film", proxy: "proxy", audio: "audio", package: "package" }[name] || "folder"; } window.Library = Library; window.AssetCard = AssetCard;