Centralizes auth token management into a reusable apiFetch() helper and getAuthHeaders() utility, eliminating inline Bearer token logic across all frontend files.
Ultraworked with [Sisyphus](https://github.com/code-yeongyu/oh-my-openagent)
Co-authored-by: Sisyphus <clio-agent@sisyphuslabs.ai>
- Release reservation on service change, date change, and step-back navigation
- Add synchronous double-click payment guard (isProcessingPaymentSync)
- Immutable update for confirmedBooking to prevent race-condition overcharge
- Generate fresh idempotency key per submission attempt (was reused across
component lifetime, causing stale-booking illusion on re-submit)
- Release reservation after successful booking submission
- Extract releaseReservation() helper for DRY reservation cleanup
- Race-condition guard in selectTimeWithValidation: pass clicked time
explicitly so stale validation can't clobber a newer selection
Move __bookingFlowCountdownInterval from inline declare global in BookingFlow.svelte to global app.d.ts. Fix authHeaders type from {} to undefined to satisfy TypeScript.
Ultraworked with [Sisyphus](https://github.com/code-yeongyu/oh-my-openagent)
Co-authored-by: Sisyphus <clio-agent@sisyphuslabs.ai>
Send auth token in reserve/availability/working-hours requests so the backend can exclude the user's own reservations. Cancel old reservation via DELETE before reserving a new slot. Track reserved slot time/date for back-navigate detection. Clean up countdown interval via onDestroy and window reference to prevent duplicates.
Ultraworked with [Sisyphus](https://github.com/code-yeongyu/oh-my-openagent)
Co-authored-by: Sisyphus <clio-agent@sisyphuslabs.ai>
- Convert HTML comments in script sections to eslint-disable-next-line
- Fix err->_err references in catch blocks across 8 files
- Fix required→_required and onclose→_onclose prop mismatches
- Revert BookingCreateModal.svelte from no-unused-vars agent damage
- Fix broken regex in account page
- Fix .writable (not in Svelte 5 stable) back to +
- Fix NavBar dynamic href links with proper eslint-disable
Introduce getLondonTodayCalendarDate(), parseWallClockDate(), and formatLocalDateTime() for reliable Europe/London timezone handling. Replace ad-hoc SvelteDate/new Date() usage with these utilities across all components and stores.
Ultraworked with [Sisyphus](https://github.com/code-yeongyu/oh-my-openagent)
Co-authored-by: Sisyphus <clio-agent@sisyphuslabs.ai>
Add print receipt feature to UserBookingModal with full VAT breakdown. Fix VAT rate display (remove double *100). Show VAT breakdown (net + VAT) on booking confirmed page. Add VAT info to EditBookingModal. Show incl. VAT label on BookingFlow total, schedule, and today dashboard. Add VAT note to prices page. Show booking total amount on account page. Improve VAT enable toast in BusinessSettings.
Ultraworked with [Sisyphus](https://github.com/code-yeongyu/oh-my-openagent)
Co-authored-by: Sisyphus <clio-agent@sisyphuslabs.ai>
Load Playfair Display from Google Fonts via preconnect and stylesheet in root layout, then apply to h1 headings on BookingFlow, Account, and Contact pages for a consistent brand typography.
Ultraworked with [Sisyphus](https://github.com/code-yeongyu/oh-my-openagent)
Co-authored-by: Sisyphus <clio-agent@sisyphuslabs.ai>
Update BookingFlow to support custom service selection, add custom_services to booking types, and link CustomServicesManagement into admin pages. Minor updates to schedules, prices, and today routes.
Ultraworked with Sisyphus (https://github.com/code-yeongyu/oh-my-openagent)
Co-authored-by: Sisyphus <clio-agent@sisyphuslabs.ai>
Replace raw <Input type="email"> with <EmailInput> in login (register + login), account (gift card recipient), BookingFlow (guest email), and GiftCardsManagement (admin gift card email).
Removes 30-line validateEmail() function from login page (now handled by EmailInput internally).
Removes validateEmailFormat() from BookingFlow (EmailInput handles format validation; debounced backend email check preserved via onvaluechange/onblur).
Ultraworked with [Sisyphus](https://github.com/code-yeongyu/oh-my-openagent)
Co-authored-by: Sisyphus <clio-agent@sisyphuslabs.ai>
Add proper keys to #each blocks across 15+ components to fix reordering bugs. Replace new Date() with SvelteDate in reactive contexts. Use $derived for computed values (totalPages). Use resolve() from $app/paths for all internal navigation hrefs. Add ARIA labels and keyboard accessibility to NavBar mobile menu. Remove unused handleRetry from UserPaymentModal.
Ultraworked with [Sisyphus](https://github.com/code-yeongyu/oh-my-openagent)
Co-authored-by: Sisyphus <clio-agent@sisyphuslabs.ai>
Backend:
- Add enriched response types (EditSnapshot, EnrichedEditRequest) with original vs proposed snapshots
- Add 4 new GET endpoints for viewing edit requests (user and admin scoped)
- Remove github.com/lib/pq dependency — use native PostgreSQL array scanning
- Clean up edit requests, time blockers, and notifications on booking cancellation
- Validate exceptional closed hours on admin approve (409 Conflict)
- Notification upsert on edit request replace (no duplicate admin notifications)
Frontend:
- New user EditRequestModal with time/services/both modes and lunch protection
- New admin EditRequestModal with side-by-side diff (date/time, services, notes)
- Integrate edit requests into PendingApprovals card and notifications page
- Preload 3 months of availability to prevent calendar snap-back
- Apply lunch protection to isDateUnavailable in BookingFlow and BookingCreateModal
- Fix accessibility: card list items use <button> instead of <div>
Dev & Docs:
- Seed edit requests in local-dev-2.sh
- Update all Obsidian manuals with enriched edit request documentation
- 42 new tests (438/441 passing)
- generateGroupedTimeSlots now accepts lunchProtection map parameter
- Lunch-blocked slots treated as unavailable during grouping, not after
- Consecutive lunch-blocked slots merge into one unavailable button
- Admin BookingCreateModal already had this fix; BookingFlow now matches
- backend/handlers/user/account.go: Wire DELETE /api/user/account to call
anonymize_user() for registered users and delete_guest_user() for guests,
with CardDAV contact cleanup
- backend/handlers/user/profile_test.go: Add TestAccount_DeleteGuest and
enhance TestAccount_Delete to verify anonymization results
- backend/main.go: Add GET /api/health endpoint with DB ping and S3 status
check; add HSTS and Referrer-Policy security headers; replace
http.ListenAndServe with http.Server + graceful SIGTERM/SIGINT shutdown
- frontend/routes/+layout.svelte: Replace alert() with toast notifications
for email verification flow
- frontend/routes/login/+page.svelte: Replace alert() with toast.info for
social login prototype buttons
- frontend/booking/BookingFlow.svelte: Remove 2 console.log debug calls;
add cancellation policy note in Step 3; add timezone policy comment
- frontend/ImageUpload.svelte: Comment out debug console.log
- init-scripts/init-script.sql: Add delete_guest_user() SQL function
- docs: Update README.md and Obsidian notes to reflect completed items
Customer flow: reservation fires on Date/Time → Details transition with
re-validation on time slot tap and on 'Next' click to prevent simultaneous
bookings. 5-step flow: Service → Date/Time → Reserve → Details (countdown)
→ Payment & Review → Confirm. Guest users redirected to home on success.
Admin call-in: reserve slot before final submission (60min TTL).
Admin walk-in: reserve slot on modal open (5min TTL).
Ultraworked with [Sisyphus](https://github.com/code-yeongyu/oh-my-openagent)
Co-authored-by: Sisyphus <clio-agent@sisyphuslabs.ai>
- Add eligibility filtering to /api/services: exclude services below
user's
age, gray out services requiring patch tests that are missing/expired
- Add new endpoint /api/services/eligible-for/{user_id} for admin
booking
flows to check eligibility for a specific user
- Add image metadata stripping: uploads now strip all EXIF/GPS data
via imaging library (security improvement)
- Update ServiceCard frontend: show grayed-out state for ineligible
services with "contact us" link (public) or just warning (admin)
- Add 2 patch test services to seed data: Gel Polish Full Set,
Luxury Gel Manicure (48h each)
- Remove deprecated local-dev.sh script
Backend:
- Enriched GetAllUserBookings response with calculated total_amount,
amount_paid, and duration_minutes.
- Refactored GetBookingHandler to return a flat booking object matching
frontend expectations.
- Added account_role to admin user list response and sorted users by
booking activity.
- Corrected function name oo to AdminCreateBookingForUserHandler.
Frontend:
- Rebuilt BookingCreateModal into a 4-step wizard supporting guest
bookings, service overrides, and real-time availability checks.
- Fixed account dashboard logic to correctly identify upcoming vs past
bookings and sort unpaid items to the top.
- Extracted booking flow into a shared BookingFlow component.
- Redirected admin users from home page to /today.