fix(projects): RenameProjectModal replaces prompt()
This commit is contained in:
parent
6fe5f7d450
commit
004bdd0778
1 changed files with 46 additions and 8 deletions
|
|
@ -48,6 +48,7 @@ function Projects({ onOpenProject, navigate }) {
|
|||
const [view, setView] = React.useState('grid');
|
||||
const [showNew, setShowNew] = React.useState(false);
|
||||
const [menuFor, setMenuFor] = React.useState(null);
|
||||
const [renamingProject, setRenamingProject] = React.useState(null);
|
||||
|
||||
const refresh = React.useCallback(() => {
|
||||
window.ZAMPP_API.fetch('/projects')
|
||||
|
|
@ -68,14 +69,7 @@ function Projects({ onOpenProject, navigate }) {
|
|||
|
||||
const onCreated = (p) => { refresh(); };
|
||||
|
||||
const renameProject = (p) => {
|
||||
setMenuFor(null);
|
||||
const next = prompt('Rename project', p.name);
|
||||
if (!next || !next.trim() || next.trim() === p.name) return;
|
||||
window.ZAMPP_API.fetch('/projects/' + p.id, { method: 'PATCH', body: JSON.stringify({ name: next.trim() }) })
|
||||
.then(refresh)
|
||||
.catch(e => alert('Rename failed: ' + e.message));
|
||||
};
|
||||
const renameProject = (p) => { setMenuFor(null); setRenamingProject(p); };
|
||||
|
||||
const deleteProject = (p) => {
|
||||
setMenuFor(null);
|
||||
|
|
@ -155,6 +149,50 @@ function Projects({ onOpenProject, navigate }) {
|
|||
)}
|
||||
</div>
|
||||
{showNew && <NewProjectModal onClose={() => setShowNew(false)} onCreated={onCreated} />}
|
||||
{renamingProject && (
|
||||
<RenameProjectModal
|
||||
project={renamingProject}
|
||||
onClose={() => setRenamingProject(null)}
|
||||
onSaved={() => { setRenamingProject(null); refresh(); }}
|
||||
/>
|
||||
)}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
function RenameProjectModal({ project, onClose, onSaved }) {
|
||||
const [name, setName] = React.useState(project.name || '');
|
||||
const [saving, setSaving] = React.useState(false);
|
||||
const [err, setErr] = React.useState(null);
|
||||
const submit = () => {
|
||||
const trimmed = name.trim();
|
||||
if (!trimmed || trimmed === project.name) { onClose(); return; }
|
||||
setSaving(true); setErr(null);
|
||||
window.ZAMPP_API.fetch('/projects/' + project.id, { method: 'PATCH', body: JSON.stringify({ name: trimmed }) })
|
||||
.then(onSaved)
|
||||
.catch(e => { setSaving(false); setErr(e.message); });
|
||||
};
|
||||
return (
|
||||
<div className="modal-backdrop" onClick={onClose}>
|
||||
<div className="modal" style={{ width: 420 }} onClick={e => e.stopPropagation()}>
|
||||
<div className="modal-head">
|
||||
<div style={{ fontSize: 15, fontWeight: 600 }}>Rename project</div>
|
||||
<button className="icon-btn" onClick={onClose}><Icon name="x" /></button>
|
||||
</div>
|
||||
<div className="modal-body">
|
||||
<div className="field">
|
||||
<label className="field-label">Project name</label>
|
||||
<input className="field-input" autoFocus value={name}
|
||||
onChange={e => setName(e.target.value)}
|
||||
onKeyDown={e => { if (e.key === 'Enter') submit(); if (e.key === 'Escape') onClose(); }} />
|
||||
</div>
|
||||
{err && <div style={{ fontSize: 12, color: 'var(--danger)', marginTop: 4 }}>{err}</div>}
|
||||
</div>
|
||||
<div className="modal-foot">
|
||||
<button className="btn ghost sm" onClick={onClose}>Cancel</button>
|
||||
<button className="btn primary sm" onClick={submit} disabled={saving || !name.trim()}>{saving ? 'Saving…' : 'Rename'}</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in a new issue