GRO-218: Customer portal now fetches real data via impersonation session.
Backend (portal.ts):
- Add GET /portal/me, /portal/services, /portal/appointments, /portal/pets, /portal/invoices
- Add getClientIdFromSession() helper for DRY auth validation
- Add imports: lte, clients, pets, services, staff, invoices, invoiceLineItems, groomingVisitLogs
Frontend (portal sections):
- Dashboard: fetches appointments, pets, invoices, branding from API
- Appointments: fetches from /portal/appointments; booking submits to /portal/waitlist
- PetProfiles: fetches pets and appointments from API; no vaccinations tab (no DB table)
- BillingPayments: fetches invoices from /portal/invoices; uses totalCents not amount
- Communication: local-only messages/notifications; fetches branding from /api/branding
- AccountSettings: fetches personal info from /portal/me and pets from /portal/pets
- ReportCards: fetches appointments with reportCardId; empty state when none
Stubbed features (no DB tables): loyalty points, messages, signed agreements, vaccinations.
Co-Authored-By: Paperclip <noreply@paperclip.ing>
Replace all hardcoded brand color hex values with CSS custom properties
so BrandingContext drives both the customer portal and staff site.
- index.css: add derived accent/primary vars using color-mix()
(--color-accent-hover, --color-accent-dark, --color-accent-light,
--color-accent-lighter, --color-primary-dark); fix focus ring styles
to use var(--color-primary) instead of hardcoded hex
- BrandingContext.tsx: also update <meta name="theme-color"> in sync
with primaryColor so PWA theme-color tracks branding at runtime
- portal/sections: replace bg-[#8b7355], text-[#6b5a42], bg-[#f0ebe4],
bg-[#faf5ef], hover:bg-[#7a6549] etc. with Tailwind v4 CSS var
utilities (bg-(--color-accent), text-(--color-accent-dark), etc.)
- pages: replace inline style "#4f8a6f"/"#3d7a5f" with
var(--color-primary) / var(--color-primary-dark) across Appointments,
Book, Clients, GroupBooking, Invoices, Reports, Services, Staff, and
DevSessionIndicator
Closes#91
Co-Authored-By: Paperclip <noreply@paperclip.ing>