diff --git a/services/web-ui/public/screens-projects.jsx b/services/web-ui/public/screens-projects.jsx new file mode 100644 index 0000000..4cf4f88 --- /dev/null +++ b/services/web-ui/public/screens-projects.jsx @@ -0,0 +1,98 @@ +// screens-projects.jsx — projects browse + project detail + +const { PROJECTS: ALL_PROJECTS, ASSETS } = window.ZAMPP_DATA; + +function Projects({ onOpenProject, navigate }) { + const [search, setSearch] = React.useState(""); + const [view, setView] = React.useState("grid"); + let projects = ALL_PROJECTS; + if (search) projects = projects.filter(p => p.name.toLowerCase().includes(search.toLowerCase())); + + return ( +
+
+

Projects

+ {projects.length} projects +
+
+ + setSearch(e.target.value)} placeholder="Search projects…" /> +
+
+ + +
+ +
+
+ {view === "grid" ? ( +
+ {projects.map(p => onOpenProject(p)} />)} +
+ ) : ( +
+
+
Project
+
Assets
+
Storage
+
Updated
+
Members
+
+
+ {projects.map(p => ( +
onOpenProject(p)}> +
+
+
{p.name}
+
+
{p.assets}
+
{(p.assets * 1.8).toFixed(1)} GB
+
{p.updated}
+
+ {["KM", "ZG", "JT"].slice(0, 3).map((a, i) => ( +
0 ? -6 : 0, background: avatarColor(a), border: "2px solid var(--bg-1)" }}>{a}
+ ))} +
+ +
+ ))} +
+ )} +
+
+ ); +} + +function ProjectCard({ project, onOpen }) { + const thumbs = ASSETS.slice(0, project.thumbs || 4); + return ( +
+
+ {thumbs.map((a, i) => ( +
+ +
+
+ ))} +
+
+
+ + {project.name} +
+
+ {project.assets} assets + · + updated {project.updated} +
+
+
+
+
+
+
+
+ ); +} + +window.Projects = Projects;