Add a StatusBadge component that renders human-readable labels
(Confirmed, Pending, Waitlisted, etc.) with semantic color classes
for appointment cards in the portal. Replaces raw status strings.
- Added STATUS_LABELS map for human-readable status labels
- Updated STATUS_COLORS to use accessible amber/blue tones
- Exported StatusBadge for testing
- Added unit tests for all 7 badge states plus fallback
- Updated UAT_PLAYBOOK.md §5.12c with status badge test cases
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
QA review pointed out:
- Lint error: 'act' imported but never used in test file
- 6 test failures: date input lacked accessible label
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
- New analytics utility (src/lib/analytics.ts) with ANALYTICS_EVENTS constants
and fireAnalyticsEvent() – thin wrapper over window.dispatchEvent, no-op safe
Built for Plausible/GTM integration later.
- Public booking wizard (Book.tsx): fires step-transition events at each step
(service → time → contact → submit) plus booking_confirmed on the dedicated
confirmation page.
- Portal BookingFlow (Appointments.tsx): fires equivalent events for the
portal booking flow. booking_confirmed fires via useEffect when the inline
success state is shown.
- BookingErrorPage: fires booking_error on mount (no PII in payload).
Events include step name and flow type (public/portal) but contain no PII:
no names, emails, phone numbers, or pet names in any payload.
Co-Authored-By: Paperclip <noreply@paperclip.ing>
Both BookingFlow and RescheduleFlow in Appointments.tsx now fetch
from /api/book/availability when a date is selected, matching the
public booking wizard behavior. Loading and error states shown.
- Removed hardcoded availableTimes arrays from both flows
- Added useEffect that fetches availability on date change
- Shows "Checking availability…" while loading
- Shows error message on fetch failure
- Shows "No available slots" when API returns empty
Added tests for RescheduleFlow dynamic slot fetching covering:
loading, fetched slots, error, empty, API params, and re-fetch on
date change.
Co-Authored-By: Paperclip <noreply@paperclip.ing>
- handlePetSave is now async; calls PATCH before updating local state
- API response used as source of truth for local state update
- Error state shown on API failure; edit form NOT cleared on failure
- Loading/saving indicator in PetForm while API call in flight
Refs: GRO-1470
Co-Authored-By: Paperclip <noreply@paperclip.ing>
This commit ports the GRO-1173 admin UI changes from the app monorepo
into the extracted groombook/web repo, using the correct source paths
(src/ instead of apps/web/src/):
- New BufferRulesSection component (full CRUD UI for /api/buffer-rules)
- Default Buffer (minutes) field added to service create/edit form
- Size Category and Coat Type dropdowns added to PetForm (portal)
- @groombook/types Service interface extended with defaultBufferMinutes
- BufferRulesSection embedded in Settings page
The PetForm already had coatType — this commit adds petSizeCategory
and renders both fields with proper dropdown selectors.
Co-Authored-By: Paperclip <noreply@paperclip.ing>
- Make coatType and petSizeCategory optional on Pet (?:) — they may not be set
- Remove "single" and "short" from COAT_TYPES (not in CoatType union)
- Use { name: "Add" } instead of /add/i to target the + button specifically
- Add optional chaining to puppyCutSpans[0]?.closest() (noUncheckedIndexedAccess)
- Add optional chaining to petsData[0]?.id ?? "" in PetProfiles
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
- Add MedicalAlert, AlertSeverity, CoatType, preferredCuts, medicalAlerts,
temperamentScore, temperamentFlags to @groombook/types Pet interface
- Add aria-label="Add" to the preferred cuts + button
- Fix temperament text expectation from "(/4/5)" to "(4/5)"
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
- Import Pet/MedicalAlert/CoatType/AlertSeverity from @groombook/types (workspace dep)
- Replace getByPlaceholder with getByPlaceholderText in test file
- Add explicit MedicalAlert type to destructured alert param in PetForm
- Add null guards for HTMLElement | undefined in test lines 79/111
- Add htmlFor=coat-type label association for accessible combobox
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
- Copy apps/web/ with all src, components, pages, portal
- Inline packages/types/ as local packages/types module
- Add tsconfig path aliases for @groombook/types
- Port Dockerfile and CI workflow
- Image name: ghcr.io/groombook/web
Co-Authored-By: Paperclip <noreply@paperclip.ing>