import { useEffect, useState } from "react"; import type { Staff } from "@groombook/types"; interface StaffForm { name: string; email: string; role: "groomer" | "receptionist" | "manager"; } const EMPTY_FORM: StaffForm = { name: "", email: "", role: "groomer" }; export function StaffPage() { const [staff, setStaff] = useState([]); const [loading, setLoading] = useState(true); const [error, setError] = useState(null); const [editing, setEditing] = useState(null); const [showForm, setShowForm] = useState(false); const [form, setForm] = useState(EMPTY_FORM); const [formError, setFormError] = useState(null); const [saving, setSaving] = useState(false); async function load() { const r = await fetch("/api/staff?includeInactive=true"); if (!r.ok) throw new Error(`HTTP ${r.status}`); setStaff((await r.json()) as Staff[]); } useEffect(() => { load() .catch((e: unknown) => setError(e instanceof Error ? e.message : "Unknown error")) .finally(() => setLoading(false)); }, []); function openNew() { setEditing(null); setForm(EMPTY_FORM); setFormError(null); setShowForm(true); } function openEdit(s: Staff) { setEditing(s); setForm({ name: s.name, email: s.email, role: s.role }); setFormError(null); setShowForm(true); } async function submit(e: React.FormEvent) { e.preventDefault(); setSaving(true); setFormError(null); try { const res = editing ? await fetch(`/api/staff/${editing.id}`, { method: "PATCH", headers: { "Content-Type": "application/json" }, body: JSON.stringify({ name: form.name, role: form.role }) }) : await fetch("/api/staff", { method: "POST", headers: { "Content-Type": "application/json" }, body: JSON.stringify(form) }); if (!res.ok) { const err = (await res.json()) as { error?: string }; throw new Error(err.error ?? `HTTP ${res.status}`); } setShowForm(false); await load(); } catch (e: unknown) { setFormError(e instanceof Error ? e.message : "Failed to save"); } finally { setSaving(false); } } async function toggleActive(s: Staff) { await fetch(`/api/staff/${s.id}`, { method: "PATCH", headers: { "Content-Type": "application/json" }, body: JSON.stringify({ active: !s.active }) }); await load(); } if (loading) return

Loading…

; if (error) return

Error: {error}

; return (

Staff

{staff.length === 0 ? (

No staff members yet.

) : ( {["Name", "Email", "Role", "Status", ""].map((h) => ( ))} {staff.map((s) => ( ))}
{h}
{s.name} {s.email} {s.role} {s.active ? "Active" : "Inactive"}
)} {showForm && (
{ if (e.target === e.currentTarget) setShowForm(false); }} >

{editing ? "Edit Staff" : "New Staff Member"}

setForm((f) => ({ ...f, name: e.target.value }))} required style={inputStyle} />
{!editing && (
setForm((f) => ({ ...f, email: e.target.value }))} required style={inputStyle} />
)}
{formError &&

{formError}

}
)}
); } const btnStyle: React.CSSProperties = { padding: "0.35rem 0.75rem", border: "1px solid #d1d5db", borderRadius: 4, background: "#f9fafb", cursor: "pointer", fontSize: 13 }; const inputStyle: React.CSSProperties = { width: "100%", padding: "0.4rem 0.5rem", border: "1px solid #d1d5db", borderRadius: 4, fontSize: 14, boxSizing: "border-box" }; const labelStyle: React.CSSProperties = { display: "block", fontWeight: 600, marginBottom: "0.25rem", fontSize: 13, color: "#374151" }; const tdStyle: React.CSSProperties = { padding: "0.5rem 0.75rem", borderBottom: "1px solid #e2e8f0" };