fix(gro-158): add r.ok checks before .json() in AppointmentsPage and fix DevLoginSelector userId fallback

Two fixes for the admin page blank / TypeError: b.filter issue:

1. Appointments.tsx: Add r.ok status checks before calling r.json() on
   /api/clients, /api/services, and /api/staff. Previously, 403/404 error
   responses would have their JSON bodies (e.g. {error:"Forbidden"}) passed
   to state setters, causing Array.prototype.filter to fail on non-array
   objects. Now errors are thrown and caught by the existing .catch() handler,
   setting the error state instead.

2. DevLoginSelector.tsx: Add userId field to StaffUser and use
   s.userId ?? s.id when calling selectUser. If the API returns a non-null
   userId (post-migration), that is used as the dev login identifier;
   otherwise falls back to staff.id (pre-migration records where userId
   is null).

Co-Authored-By: Paperclip <noreply@paperclip.ing>
This commit is contained in:
Barkley Trimsworth
2026-03-28 02:20:35 +00:00
parent 0c760caddb
commit 2232d9d1f5
2 changed files with 14 additions and 4 deletions
+12 -3
View File
@@ -131,9 +131,18 @@ export function AppointmentsPage() {
setError(null);
Promise.all([
loadAppointments(),
fetch("/api/clients").then((r) => r.json() as Promise<Client[]>).then(setClients),
fetch("/api/services").then((r) => r.json() as Promise<Service[]>).then(setServices),
fetch("/api/staff").then((r) => r.json() as Promise<Staff[]>).then(setStaff),
fetch("/api/clients").then((r) => {
if (!r.ok) throw new Error(`HTTP ${r.status}`);
return r.json() as Promise<Client[]>;
}).then(setClients),
fetch("/api/services").then((r) => {
if (!r.ok) throw new Error(`HTTP ${r.status}`);
return r.json() as Promise<Service[]>;
}).then(setServices),
fetch("/api/staff").then((r) => {
if (!r.ok) throw new Error(`HTTP ${r.status}`);
return r.json() as Promise<Staff[]>;
}).then(setStaff),
])
.catch((e: unknown) => setError(e instanceof Error ? e.message : "Unknown error"))
.finally(() => setLoading(false));
+2 -1
View File
@@ -3,6 +3,7 @@ import { useNavigate } from "react-router-dom";
interface StaffUser {
id: string;
userId: string | null;
name: string;
email: string;
role: string;
@@ -66,7 +67,7 @@ export function DevLoginSelector() {
{staff.map((s) => (
<button
key={s.id}
onClick={() => selectUser("staff", s.id, s.name)}
onClick={() => selectUser("staff", s.userId ?? s.id, s.name)}
style={userButtonStyle}
>
<div style={{ fontWeight: 600, fontSize: 14 }}>{s.name}</div>