fixed super admin showing in client list added a reconnect button to google calendar syncying fixed ui issue with whatsapp undo link
This commit is contained in:
21 files changed
+1180
-118
No files matched your search
@@ -9,6 +9,7 @@ import { hasPermission } from "@/lib/auth/permissions";
|
||||
import { prisma } from "@/lib/db/prisma";
|
||||
import { getActingBusinessContext } from "@/lib/business/get-acting-business-context";
|
||||
import { getUnreadNotificationCount } from "@/services/notifications/notification.service";
|
||||
import { clientDirectoryWhere } from "@/services/customer/client-directory";
|
||||
import { matchesCustomerSearch } from "@/services/customer/customer.service";
|
||||
import { getLoyaltySummariesForCustomers } from "@/services/loyalty/loyalty.service";
|
||||
import { InlineNotificationBell } from "@/features/notifications/components/notification-bell";
|
||||
@@ -34,31 +35,14 @@ export default async function StaffClientsPage({
|
||||
hasPermission(context.userId, Permission.MANAGE_BUSINESS_PROFILE),
|
||||
]);
|
||||
|
||||
// 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). 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).
|
||||
// Who counts as a client is defined once, in clientDirectoryWhere (shared with
|
||||
// the detail page so the two can't disagree). `select`-scoped rather than a
|
||||
// full row + appointment `include`: the card only ever reads status/startAt
|
||||
// off each appointment, never the service lines/notes/discount a full
|
||||
// include would 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: {
|
||||
OR: [
|
||||
{ appointments: { some: { businessId: context.businessId } } },
|
||||
{ isGuest: false, appointments: { none: {} } },
|
||||
],
|
||||
},
|
||||
where: clientDirectoryWhere(context.businessId),
|
||||
select: {
|
||||
id: true,
|
||||
firstName: true,
|
||||
|
||||
Reference in new issue
Block a user