diff --git a/src/app/(staff)/staff/clients/page.tsx b/src/app/(staff)/staff/clients/page.tsx index 11a214c..d610ec4 100644 --- a/src/app/(staff)/staff/clients/page.tsx +++ b/src/app/(staff)/staff/clients/page.tsx @@ -31,14 +31,29 @@ export default async function StaffClientsPage({ // Scoped via the appointment relation, not "every CustomerProfile row" — // a real business boundary even though this is a single-business v1 app - // (see docs/phase-5-summary.md). `select`-scoped rather than the full - // row + full appointment `include` this used to fetch — the card only - // ever reads status/startAt off each appointment, never the service - // lines/notes/discount that a full include would also pull down for - // every appointment of every client on every page view (see the Phase 7 - // performance pass). + // (see docs/phase-5-summary.md). A registered client with NO appointment + // anywhere yet (freshly added via /staff/clients/add, or self-registered + // but never booked) is also included — otherwise a client staff just + // added would be invisible here until their first booking, which reads + // as "did that even work?". A registered client with appointments only + // at some other business (not reachable in this single-business-per- + // deployment app, but kept as a real predicate rather than an assumption) + // is correctly excluded either way. Guests are never included by this + // second branch — a guest profile is only ever created alongside an + // appointment (see resolveGuestCustomer), so one with zero appointments + // shouldn't exist, but isGuest: false is there as a real guard, not a + // guess. `select`-scoped rather than the full row + full appointment + // `include` this used to fetch — the card only ever reads status/startAt + // off each appointment, never the service lines/notes/discount that a + // full include would also pull down for every appointment of every + // client on every page view (see the Phase 7 performance pass). const customers = await prisma.customerProfile.findMany({ - where: { appointments: { some: { businessId: context.businessId } } }, + where: { + OR: [ + { appointments: { some: { businessId: context.businessId } } }, + { isGuest: false, appointments: { none: {} } }, + ], + }, select: { id: true, firstName: true, @@ -72,7 +87,7 @@ export default async function StaffClientsPage({ const now = new Date(); return ( -
+
) : ( -
+
{sorted.map((customer) => { const completedVisits = customer.appointments.filter( (a) => a.status === "COMPLETED", diff --git a/src/features/staff/components/add-client-form.tsx b/src/features/staff/components/add-client-form.tsx index 28ab352..bdfce2b 100644 --- a/src/features/staff/components/add-client-form.tsx +++ b/src/features/staff/components/add-client-form.tsx @@ -41,8 +41,7 @@ export function AddClientForm() {

{added.name} has been added.

- They can sign in anytime with just their email — no password, no invite email sent. They'll show up - in Clients once they have an appointment. + They can sign in anytime with just their email — no password, no invite email sent.