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:
@@ -131,9 +131,18 @@ export function AppointmentsPage() {
|
|||||||
setError(null);
|
setError(null);
|
||||||
Promise.all([
|
Promise.all([
|
||||||
loadAppointments(),
|
loadAppointments(),
|
||||||
fetch("/api/clients").then((r) => r.json() as Promise<Client[]>).then(setClients),
|
fetch("/api/clients").then((r) => {
|
||||||
fetch("/api/services").then((r) => r.json() as Promise<Service[]>).then(setServices),
|
if (!r.ok) throw new Error(`HTTP ${r.status}`);
|
||||||
fetch("/api/staff").then((r) => r.json() as Promise<Staff[]>).then(setStaff),
|
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"))
|
.catch((e: unknown) => setError(e instanceof Error ? e.message : "Unknown error"))
|
||||||
.finally(() => setLoading(false));
|
.finally(() => setLoading(false));
|
||||||
|
|||||||
@@ -3,6 +3,7 @@ import { useNavigate } from "react-router-dom";
|
|||||||
|
|
||||||
interface StaffUser {
|
interface StaffUser {
|
||||||
id: string;
|
id: string;
|
||||||
|
userId: string | null;
|
||||||
name: string;
|
name: string;
|
||||||
email: string;
|
email: string;
|
||||||
role: string;
|
role: string;
|
||||||
@@ -66,7 +67,7 @@ export function DevLoginSelector() {
|
|||||||
{staff.map((s) => (
|
{staff.map((s) => (
|
||||||
<button
|
<button
|
||||||
key={s.id}
|
key={s.id}
|
||||||
onClick={() => selectUser("staff", s.id, s.name)}
|
onClick={() => selectUser("staff", s.userId ?? s.id, s.name)}
|
||||||
style={userButtonStyle}
|
style={userButtonStyle}
|
||||||
>
|
>
|
||||||
<div style={{ fontWeight: 600, fontSize: 14 }}>{s.name}</div>
|
<div style={{ fontWeight: 600, fontSize: 14 }}>{s.name}</div>
|
||||||
|
|||||||
Reference in New Issue
Block a user