diff --git a/services/web-ui/public/screens-projects.jsx b/services/web-ui/public/screens-projects.jsx index e0bdab3..02c4ef2 100644 --- a/services/web-ui/public/screens-projects.jsx +++ b/services/web-ui/public/screens-projects.jsx @@ -1,17 +1,67 @@ // screens-projects.jsx +function NewProjectModal({ onClose, onCreated }) { + const [name, setName] = React.useState(''); + const [saving, setSaving] = React.useState(false); + const [err, setErr] = React.useState(null); + + const create = () => { + if (!name.trim()) { setErr('Name is required'); return; } + setSaving(true); setErr(null); + window.ZAMPP_API.fetch('/projects', { method: 'POST', body: JSON.stringify({ name: name.trim() }) }) + .then(p => { onCreated(p); onClose(); }) + .catch(e => { setSaving(false); setErr(e.message || 'Failed to create project'); }); + }; + + return ( +
+
e.stopPropagation()}> +
+
New project
+ +
+
+
+ + setName(e.target.value)} + placeholder="e.g. Sunday Night Game" autoFocus + onKeyDown={e => e.key === 'Enter' && !saving && create()} /> +
+ {err &&
{err}
} +
+
+ + + +
+
+
+ ); +} + function Projects({ onOpenProject, navigate }) { - const { PROJECTS: ALL_PROJECTS, ASSETS } = window.ZAMPP_DATA; + const [projects, setProjects] = React.useState(window.ZAMPP_DATA.PROJECTS); + const { ASSETS } = window.ZAMPP_DATA; 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())); + const [showNew, setShowNew] = React.useState(false); + + const onCreated = (p) => { + const updated = [p, ...window.ZAMPP_DATA.PROJECTS]; + window.ZAMPP_DATA.PROJECTS = updated; + setProjects(updated); + }; + + let filtered = projects; + if (search) filtered = filtered.filter(p => p.name.toLowerCase().includes(search.toLowerCase())); return (

Projects

- {projects.length} projects + {filtered.length} projects
@@ -21,35 +71,43 @@ function Projects({ onOpenProject, navigate }) {
- +
- {projects.length === 0 ? ( -
No projects yet. Create one to get started.
+ {filtered.length === 0 ? ( +
+ {search ? 'No matching projects.' : 'No projects yet.'} + {!search && ( +
+ +
+ )} +
) : view === 'grid' ? (
- {projects.map(p => onOpenProject(p)} />)} + {filtered.map(p => onOpenProject(p)} />)}
) : (
Project
Assets
Storage
Updated
- {projects.map(p => ( + {filtered.map(p => (
onOpenProject(p)}>
-
+
{p.name}
-
{p.assets}
+
{p.assets || 0}
-
{p.updated}
+
{p.updated || '—'}
))}
)}
+ {showNew && setShowNew(false)} onCreated={onCreated} />}
); } @@ -69,16 +127,16 @@ function ProjectCard({ project, assets, onOpen }) {
- + {project.name}
- {project.assets} assets + {project.assets || 0} assets · - updated {project.updated} + updated {project.updated || '—'}
-
+