docs: update all documentation for referral codes, admin schedule page, BookingFlow welcome step, format utilities, and patch_test_duration_hours

- README: add new features (referral codes, admin schedule page, welcome step, format utils, patch_test_duration_hours, created_by_name, admin login redirect), update project structure, update test count to 446/449

- Overview: add referral code support to Auth section, created_by_name to Booking System, admin schedule page to Scheduling and Admin Features, welcome step to Customer Features, update test coverage

- Technical Manual: add format.ts utilities to Shared Utilities, add /admin/schedule route, update handler descriptions (auth, bookings, services), add Referral Code System, Admin Schedule Page, BookingFlow Welcome Step, and patch_test_duration_hours sections, update test coverage

- Admin Manual: add Schedule page to main pages list, add full Schedule (Weekly Calendar View) section, add patch test duration to service creation, update referral history description

- User Manual: add referral code field to registration, add welcome step explanation to Step 1

- Future Work: update header, add #52-58 completed items, update #21 referral system status, add Phase 6 execution order

Ultraworked with [Sisyphus](https://github.com/code-yeongyu/oh-my-openagent)

Co-authored-by: Sisyphus <clio-agent@sisyphuslabs.ai>
This commit is contained in:
2026-05-29 16:21:18 +01:00
co-authored by Sisyphus
parent ec097af0f6
commit 9ba4949d37
6 changed files with 143 additions and 16 deletions
+9 -2
View File
@@ -24,6 +24,13 @@ Nail salon booking platform — Go 1.25 backend + SvelteKit 5 frontend + Docker.
- **Today page enhancements**: interactive daily calendar grid with visual time blockers, today stats summary, responsive layout improvements
- **Auto-select availability**: all booking flows (self-service, admin create, edit request) automatically select the first available date when data loads
- **Shared time slot utilities**: extracted common time slot generation, lunch protection, and formatting logic into a reusable module
- **Shared formatting utilities**: `formatDuration`, `formatDateTime`, `formatDate`, `formatTime`, `calculateAge` in `lib/utils/format.ts`
- **Referral code registration**: new users can enter a 12-character referral code during registration; relationship recorded in `user_referrals` table
- **Admin schedule page**: Google Calendar-style week view at `/admin/schedule` with drag-scroll, booking details modal, and working hours overlays
- **BookingFlow welcome step**: unauthenticated users see a welcome card (Step 0) encouraging login before guest checkout, with clear messaging about lost loyalty/discount benefits
- **Admin login redirect**: admins are redirected to `/today` after login instead of the home page
- **Patch test duration on services**: `patch_test_duration_hours` exposed on Service type; creating a service with duration > 0 auto-creates a patch test record
- **`created_by_name` on bookings**: admin booking details now show who created the booking (admin name)
## Project Structure
@@ -43,7 +50,7 @@ Crussell/
│ ├─ admin/ # BookingCreateModal, RescheduleModal, TimeBlockers, WeeklySchedule, HolidayHours, etc.
│ ├─ today/ # TodayCalendar (interactive grid), CurrentAppointment, PendingApprovals, TodayStats
│ └─ account/ # EditRequestModal, UserBookingModal
├─ frontend/src/lib/utils/ # Shared utilities (timeSlots.ts)
├─ frontend/src/lib/utils/ # Shared utilities (timeSlots.ts, format.ts)
├─ sabredav/ # PHP + Composer for DAV
├─ nginx/ # Nginx reverse-proxy for HTTP & HTTPS
├─ init-scripts/ # PostgreSQL init SQL
@@ -99,7 +106,7 @@ cd backend && go build -o bin/backend ./main.go
# Frontend
cd frontend && npm ci && npm run build
# Tests (444/447 passing, 3 skipped)
# Tests (446/449 passing, 3 skipped)
cd backend && go test -tags "test,dev" ./...
```
+29 -2
View File
@@ -14,6 +14,7 @@ Go to the website and log in with your admin email and password. Once logged in
- **Today** — your daily operations hub. This is where you manage today's appointments, approve new bookings, and handle walk-ins.
- **Admin** — the management dashboard. This is where you set up services, manage customers, adjust schedules, and handle the salon's settings.
- **Schedule** — a weekly calendar view showing all appointments across the week in a Google Calendar-style layout. Access it from the navigation bar.
---
@@ -230,6 +231,7 @@ This is where you manage the list of treatments the salon offers.
- Set the price
- Set how long the service takes (in minutes)
- Set a minimum age requirement (if the service isn't suitable for under-16s, for example)
- Set a **patch test duration** (in hours) — if you enter a value greater than 0, the system automatically creates a patch test record linked to this service. Customers will need to complete this patch test before they can book the service.
**Edit a Service:**
- Click on any service to change its name, description, price, duration, or age requirement
@@ -289,6 +291,31 @@ This is where you set your regular, week-to-week opening hours.
- Toggle any day on or off — for example, if you decide to start opening on Saturdays, just turn Saturday on and set the hours
- Changes take effect immediately — customers will see the updated availability right away
### Schedule (Weekly Calendar View)
The **Schedule** page (`/admin/schedule`) gives you a bird's-eye view of the entire week's appointments in a Google Calendar-style layout.
**What you'll see:**
- A week grid with each day as a column, showing your working hours
- Each appointment shown as a coloured bar spanning its start time to end time
- The customer's name and services inside each bar
- Colour-coded status indicators (pending, confirmed, in progress, completed, cancelled)
- Days when the salon is closed are greyed out
**Navigating the week:**
- Use the **Previous** and **Next** buttons to move between weeks
- Click **Today** to jump back to the current week
- On touch devices, you can **drag** the calendar horizontally to scroll through the day
**Interacting with appointments:**
- **Click any appointment** to open its full details window (BookingModal)
- From the details window, you can edit, reschedule, cancel, or take payment
**Why use this view:**
- See your entire week at a glance instead of just today
- Spot gaps in your schedule where you could fit additional appointments
- Check for busy days that might need extra preparation
### Discount Campaigns
This is where you set up promotional discounts.
@@ -401,8 +428,8 @@ This section shows the customer's patch test history.
### Loyalty and Referrals
- **Loyalty stamps** — their current stamp count
- **Referral code** — their unique code they can share with friends
- **Referral history** — who they've referred and who referred them
- **Referral code** — their unique 12-character code they can share with friends
- **Referral history** — who they've referred (referred users) and who referred them (their referrer). The `user_referrals` table tracks these relationships, created automatically when a new user registers with a valid referral code.
### Privacy and Consent
+20 -3
View File
@@ -1,4 +1,4 @@
**Last Updated:** May 2026 — Admin reschedule modal, time blockers UI, Today calendar with interactive grid, auto-select across all booking flows, shared time slot utilities, GetBookingsByCreatedRange endpoint, 444/447 tests passing (3 skipped)
**Last Updated:** May 2026 — Admin schedule page (weekly calendar view), referral code registration, BookingFlow welcome step for guests, patch_test_duration_hours on services, shared format utilities, created_by_name on bookings, admin login redirect, 446/449 tests passing (3 skipped)
**Status:** Living backlog — add to this as gaps are discovered
---
@@ -15,6 +15,13 @@ No external dependencies. No paid services. No API keys needed.
| 2 | ~~**WalkInCreateModal guest booking errors out**~~ ✅ | S (1-2h) | Frontend | Guest creation now fires at submit time in both walk-in and call-in flows. Phone defaults to +447700900000 if left blank. |
| 3 | ~~**ApprovalModal decline/cancel stub**~~ ✅ | S (2-3h) | Frontend | `handleDecline()` now calls `POST /api/admin/bookings/{id}/cancel`. Backend sets status to `we_cancelled`, acknowledges pending notification, creates cancelled_booking notification. |
| 4 | **CurrentAppointment action stubs** | M (1d) | Frontend | `handleEdit()` ✅ — opens `EditBookingModal` for service management. `handleTakePayment()` ✅ — wired to multi-method PaymentModal. `handleReschedule()` ✅ — opens RescheduleModal with available slot lookup and conflict detection. `handleExtend()`, `handleCancel()` — dead buttons. |
| 52 | ~~**Referral code registration**~~ ✅ | S (2-3h) | Full-stack | **Complete May 2026.** Backend validates 12-char alphanumeric codes during registration, looks up referrer, records in `user_referrals`. Frontend login page has formatted input (xxxx-xxxx-xxxx). Tests: valid + invalid referral code scenarios. |
| 53 | ~~**Admin schedule page**~~ ✅ | M (1-2d) | Frontend | **Complete May 2026.** `/admin/schedule` — Google Calendar-style week view with drag-scroll, booking details modal, working hours overlays, status-coloured bars. Responsive: single-day view on mobile. |
| 54 | ~~**BookingFlow welcome step**~~ ✅ | S (1h) | Frontend | **Complete May 2026.** Unauthenticated users see Step 0 welcome card encouraging login (loyalty stamps, seasonal discounts messaging). "Log In" → `/login`, "Continue as Guest" → Step 1. Step indicator adapts `startAt` based on auth state. |
| 55 | ~~**Shared format utilities**~~ ✅ | S (1h) | Frontend | **Complete May 2026.** `lib/utils/format.ts``formatDuration`, `formatDateTime`, `formatDate`, `formatTime`, `calculateAge`. Used across components for consistent display. |
| 56 | ~~**patch_test_duration_hours on services**~~ ✅ | S (1h) | Full-stack | **Complete May 2026.** Service type includes `patch_test_duration_hours`. Creating service with duration > 0 auto-creates patch test record. All service list endpoints LEFT JOIN patch_tests to populate field. |
| 57 | ~~**created_by_name on bookings**~~ ✅ | XS (15min) | Full-stack | **Complete May 2026.** Booking type includes `created_by_name`. Admin booking handler LEFT JOINs users to resolve creator name. |
| 58 | ~~**Admin login redirect**~~ ✅ | XS (15min) | Frontend | **Complete May 2026.** Admins redirected to `/today` after login instead of home page. Token payload decoded to check role. |
## P1 — High
@@ -42,7 +49,7 @@ No external dependencies. No paid services. No API keys needed.
| 18 | ~~**HSTS header**~~ ✅ | XS (15min) | Backend | Added as a TODO-comment in the security headers middleware. Will be uncommented when HTTPS is enabled in production. |
| 19 | ~~**Referrer-Policy header**~~ ✅ | XS (15min) | Backend | Added as a TODO-comment in the security headers middleware. Will be uncommented when ready for production. |
| 20 | **Business settings management UI** | M (1-2d) | Full-stack | `business_settings` table exists (VAT registration, business name, etc.). No admin page to configure. Changes require direct SQL. |
| 21 | **Referral system UI** | M (1-2d) | Full-stack | `user_referrals` table exists. Users can't see their referral code or track uses. Admin can't manage referral campaigns. |
| 21 | **Referral system UI** | M (1-2d) | Full-stack | `user_referrals` table exists. **Backend complete** — registration accepts and validates referral codes, relationships recorded automatically. Remaining: users can't see their referral code or track uses in their account page. Admin can't manage referral campaigns. |
| 22 | **Analytics endpoints** | M (1-2d) | Backend | `handlers/admin/analytics.go` is 1 line. `get_monthly_business_summary()`, `get_sales_totals()` SQL functions exist. No admin dashboard stats. |
| 23 | ~~**console.log debug statements**~~ ✅ | XS (15min) | Frontend | Removed from BookingFlow.svelte and ImageUpload.svelte. |
| 24 | ~~**Alert-based prototype UX**~~ ✅ | XS (30min) | Frontend | Replaced all `alert()` calls with `toast.success/error/info` from svelte-sonner. |
@@ -212,7 +219,7 @@ Require paid accounts, API approval, or external service credentials. **Do not a
### Phase 5 — Growth + Polish (Week 5+)
31. **#21** Referral system UI (1-2d)
31. **#21** Referral system UI (1-2d)**Backend complete**, remaining: user-facing referral code display, tracking dashboard
32. **#22** Analytics endpoints (1-2d)
33. ~~**#25**~~ ~~Customer relationship view~~ ✅ — implemented
34. **#26** CSV/Excel export (1d)
@@ -231,6 +238,16 @@ Require paid accounts, API approval, or external service credentials. **Do not a
47. **#43** PWA support (3-5d)
48. **Gift card management UI** — Create/redeem gift cards, track balances (E4 backend + admin payment UI complete, management UI pending)
### Phase 6 — Latest (Week 6+)
49. ~~**#52**~~ ~~Referral code registration~~ ✅ — backend + frontend complete
50. ~~**#53**~~ ~~Admin schedule page~~ ✅ — weekly calendar view complete
51. ~~**#54**~~ ~~BookingFlow welcome step~~ ✅ — guest login encouragement complete
52. ~~**#55**~~ ~~Shared format utilities~~ ✅ — format.ts complete
53. ~~**#56**~~ ~~patch_test_duration_hours on services~~ ✅ — auto-creates patch tests
54. ~~**#57**~~ ~~created_by_name on bookings~~ ✅ — admin booking details
55. ~~**#58**~~ ~~Admin login redirect~~ ✅ — redirects to /today
### ⏳ Waiting on External Access
| Item | Blocked On | Unblocks |
+7 -1
View File
@@ -84,11 +84,13 @@ flowchart TD
### Authentication & Identity
- JWT authentication (HS256, 30-day expiry) with auto-refresh
- User registration with input validation (names, UK phone, email, age 16+)
- **Referral code support**: optional 12-character alphanumeric code during registration; validated against `users.referral_code`, relationship recorded in `user_referrals` table
- Password hashing with bcrypt
- Role-based access: `unverified_email`, `verified_email`, `admin`, `guest`, `affiliate`
- Refresh token with role-change detection (forces re-login if role changed)
- Email verification and password reset endpoints (backend ready, frontend not wired)
- Guest/disposable accounts for one-off bookings
- **Admin login redirect**: admins are redirected to `/today` after login instead of the home page
### Booking System
- Three booking flows: self-service (customer), walk-in (admin), call-in (admin)
@@ -100,6 +102,7 @@ flowchart TD
- **Enriched edit requests**: side-by-side original vs proposed snapshots with service details, end-time calculation, and user info
- Admin booking service editing with overlap detection and price/duration overrides
- Idempotency keys for booking deduplication
- **`created_by_name`**: admin booking details include the name of the admin who created the booking
### Scheduling
- Default weekly working hours (Mon-Fri, closed Sat/Sun)
@@ -107,6 +110,7 @@ flowchart TD
- Time blockers (admin-defined unavailable periods, plus slot reservations) — with full UI for creation and management
- Available hours calculation accounting for bookings, blockers, and gaps
- **GetBookingsByCreatedRange**: admin endpoint to query bookings within a created_at date range
- **Admin schedule page** (`/admin/schedule`): Google Calendar-style week view with drag-scroll, booking details modal, working hours overlays, and status-coloured booking bars
### Customer Features
- Profile management with profile picture upload (cropper, separate S3 bucket)
@@ -118,10 +122,12 @@ flowchart TD
- **Saved cards**: manage cards in Account → Cards tab — add/remove cards for faster checkout (soft-deleted on removal, 7-year retention)
- **Tip page**: percentage-based tips (10%, 15%, 20%) or custom amount on completed bookings via `/pay-tip/[id]`
- **Auto-select**: booking flows automatically select the first available date when availability data loads
- **BookingFlow welcome step**: unauthenticated users see a welcome card (Step 0) encouraging login before guest checkout, with messaging about lost loyalty stamps and seasonal discounts
### Admin Features
- Today page (/today): current/next appointment, today's interactive calendar grid, pending approvals, today stats summary
- Admin dashboard (/admin): services CRUD, user management, bookings list, scheduling, time blockers UI
- **Admin schedule page** (`/admin/schedule`): Google Calendar-style week view with drag-scroll, booking details, working hours overlays
- Walk-in booking wizard (3-step) with slot reservation
- Call-in booking wizard (4-step) with slot reservation
- **Reschedule modal**: full reschedule UI on Today page — search available slots, detect conflicts, one-click confirm
@@ -201,7 +207,7 @@ All flows integrate with holiday/exceptional hours and time blockers. All bookin
## Test Coverage
**444/447 tests passing** (3 skipped) across 12+ test packages. Comprehensive coverage of online payments (deposit, full, partial, balance), saved card operations, tip payments, terminal payments, refunds, idempotency, webhook handling, cash/gift card payments, enriched edit request workflows, GetBookingsByCreatedRange endpoint, and scheduling exceptional hours.
**446/449 tests passing** (3 skipped) across 12+ test packages. Comprehensive coverage of online payments (deposit, full, partial, balance), saved card operations, tip payments, terminal payments, refunds, idempotency, webhook handling, cash/gift card payments, enriched edit request workflows, GetBookingsByCreatedRange endpoint, scheduling exceptional hours, and referral code validation.
| Package | Coverage Area |
|---------|--------------|
+73 -8
View File
@@ -47,14 +47,14 @@ Backend (:8080)
| Package | File(s) | Purpose |
|---------|---------|---------|
| `handlers/auth` | local.go, social.go | Registration, login, refresh, email verification |
| `handlers/bookings` | bookings.go, reserve.go, manage.go, admin_reserve.go | Booking CRUD, reservations, admin management, edit requests, discounts, closing hours validation, active booking limits, GetBookingsByCreatedRange |
| `handlers/auth` | local.go, social.go | Registration (with referral code validation), login, refresh, email verification |
| `handlers/bookings` | bookings.go, reserve.go, manage.go, admin_reserve.go | Booking CRUD, reservations, admin management, edit requests, discounts, closing hours validation, active booking limits, GetBookingsByCreatedRange, created_by_name resolution |
| `handlers/payments` | handlers.go, service.go, validators.go | Square payments: terminal, online, refunds, tips, saved cards |
| `handlers/webhooks` | square.go | Square webhook handler for payment status updates |
| `handlers/admin` | users.go, analytics.go, discount_campaigns.go | Admin user management, discount campaigns, analytics (stub) |
| `handlers/today` | today.go | Current/next appointment, today's grid, pending approvals |
| `handlers/user` | profile.go, account.go, guest.go, loyalty.go, customer_relationship.go | User profile, guest creation, loyalty, contact info |
| `handlers/services` | services.go | Service catalog, eligibility filtering |
| `handlers/services` | services.go | Service catalog, eligibility filtering, patch_test_duration_hours auto-creates patch test records |
| `handlers/scheduling` | default-hours.go, exceptional-hours.go, time-blockers.go | Working hours, exceptional groups, time blockers |
| `handlers/portfolio` | images.go | Image upload, listing, tags, filters |
| `handlers/notifications` | notifications.go | Admin notifications (GET, acknowledge) |
@@ -103,6 +103,7 @@ Backend (:8080)
| `/portfolio` | portfolio/+page.svelte | Image gallery with tag/category filtering |
| `/prices` | prices/+page.svelte | Service price list |
| `/schedule` | schedule/+page.svelte | User's upcoming appointments with .ics export, payment buttons |
| `/admin/schedule` | admin/schedule/+page.svelte | Admin weekly calendar view — Google Calendar-style week grid with drag-scroll, booking details modal, working hours overlays |
| `/contact` | contact/+page.svelte | Dynamic contact info from first admin user |
| `/manage` | manage/+page.svelte | Booking management |
| `/demo` | demo/+page.svelte | Demo mode |
@@ -118,14 +119,14 @@ src/lib/components/
├── admin/
│ ├── ApprovalModal.svelte # Booking approval/decline
│ ├── BookingCreateModal.svelte # Admin booking creation (4-step, uses shared timeSlots utils)
│ ├── BookingModal.svelte # View booking details
│ ├── BookingModal.svelte # View booking details (shows created_by_name)
│ ├── BookingsCard.svelte # Bookings list
│ ├── CallInBooking.svelte # Call-in booking flow
│ ├── EditBookingModal.svelte # Edit booking services
│ ├── HolidayHours.svelte # Exceptional schedule management
│ ├── ImageUpload.svelte # Portfolio image upload
│ ├── PatchTestModal.svelte # Record patch test
│ ├── ServicesManagement.svelte # Service CRUD
│ ├── ServicesManagement.svelte # Service CRUD (patch_test_duration_hours)
│ ├── DiscountsManagement.svelte # Discount campaign management
│ ├── UserModal.svelte # User details + relationship data
│ ├── UsersCard.svelte # Users list
@@ -177,6 +178,13 @@ src/lib/components/
- `getDayWithOrdinal()` — formats a CalendarDate with ordinal suffix (e.g., "January 15th")
- Types: `DayHours`, `DayAvailability` — shared type definitions for working/available hours data
- **`lib/utils/format.ts`**: Shared formatting utilities for consistent display across the app
- `formatDuration(minutes)` — converts minutes to human-readable string (e.g., 90 → "1h 30m")
- `formatDateTime(date)` — formats to "Weekday, Month Day at HH:MM AM/PM"
- `formatDate(date)` — formats to "Weekday, Month Day" (no time)
- `formatTime(date)` — formats to "HH:MM AM/PM"
- `calculateAge(dateOfBirth)` — calculates age in years from DOB string
---
## API Reference
@@ -187,7 +195,7 @@ src/lib/components/
|--------|------|------|------------|-------------|
| GET | `/api/services` | Optional | 120/min | List active services (eligibility for authenticated) |
| GET | `/api/services/eligible-for/{user_id}` | Admin | 120/min | Services filtered by user's age/patch test |
| POST | `/api/register` | None | 10/min | Create user account |
| POST | `/api/register` | None | 10/min | Create user account (optional `referralCode` field) |
| POST | `/api/login` | None | 1/5s | Authenticate, receive JWT |
| POST | `/api/verify/generate` | None | — | Generate email verification or password reset code |
| POST | `/api/verify/check` | None | — | Verify code |
@@ -614,6 +622,8 @@ type EnrichedEditRequest struct {
**Patch Test Filtering:** Services linked to `patch_tests` via `service_ids[]`. User must have valid `user_patch_tests` record.
**`patch_test_duration_hours`:** The `Service` and `ServiceResponse` types now include `patch_test_duration_hours`. All service list endpoints (`ServicesHandler`, `ServicesEligibleForUserHandler`, `AllServicesHandler`) `LEFT JOIN patch_tests` to populate this field. When creating a service with `patch_test_duration_hours > 0`, a corresponding `patch_tests` record is auto-created with the service ID in `service_ids`.
**Admin vs. Customer:**
- `/api/services` — returns services with eligibility for authenticated users
- `/api/services/eligible-for/{user_id}` — admin-only, returns services for specific user (used in admin booking flows)
@@ -645,6 +655,61 @@ type EnrichedEditRequest struct {
---
### Referral Code System
**How it works:** During registration, users can optionally provide a 12-character alphanumeric referral code. The backend validates the code format, looks up the referrer by their `referral_code`, and records the relationship in the `user_referrals` table.
**Validation:**
- Code must be exactly 12 alphanumeric characters (`^[a-zA-Z0-9]{12}$`)
- Code is trimmed of whitespace before validation
- If code doesn't match any user's `referral_code`, registration returns 400 "invalid referral code"
- Referral code is optional — registration succeeds without it
**Recording:**
- `INSERT INTO user_referrals (referrer_id, referred_id) VALUES ($1, $2) ON CONFLICT DO NOTHING`
- Wrapped in the same transaction as user creation — atomic with registration
**Frontend:**
- Login/register page has a referral code input field with auto-formatting (xxxx-xxxx-xxxx)
- `handleReferralInput()` strips non-alphanumeric chars, limits to 12, inserts dashes
- On submit, dashes are stripped before sending to the API
**Related:** `generate_referral_code()` SQL function creates 12-char codes with collision detection.
---
### Admin Schedule Page
**How it works:** `/admin/schedule` provides a Google Calendar-style week view for admin users.
**Features:**
- Week navigation (previous/next week buttons) with "Today" reset
- Working hours overlay — days marked as closed are greyed out
- Booking bars positioned by start time and duration, colour-coded by status
- Drag-scroll for horizontal navigation on touch devices
- Click any booking to open `BookingModal` with full details
- Responsive: collapses to single-day view on mobile
**Data loading:**
- Fetches `GET /api/admin/bookings` for the week's date range
- Fetches `GET /api/scheduling/working-hours` for each day
- JSON diff-based refresh — only re-renders when data actually changes
---
### BookingFlow Welcome Step
**How it works:** Unauthenticated users see a "Welcome" step (Step 0) before the service selection step.
**Behaviour:**
- `currentStep` starts at 0 for unauthenticated users, 1 for authenticated users
- Step 0 shows a card explaining benefits of logging in (loyalty stamps, seasonal discounts)
- Two buttons: "Log In" (navigates to `/login`) and "Continue as Guest" (advances to Step 1)
- Step indicator shows `startAt={0}` for guests, `startAt={1}` for logged-in users
- Back button on Step 1 is hidden for authenticated users (they don't have a welcome step to go back to)
---
### Idempotency Keys
**How it works:** `Idempotency-Key` header (optional, 64-char max). If provided, backend checks for existing booking with that key. If found, returns existing booking (200, no duplicate). If not found, creates new booking with key stored.
@@ -738,8 +803,8 @@ go test -tags "test,dev" -v -p 1 -count=2 ./... # Run twice for flaky detection
### Test Coverage
**444/447 tests passing** (3 skipped) across 12+ packages. Comprehensive coverage of online payments (deposit, full, partial, balance), saved card operations, tip payments, terminal payments, refunds, idempotency, webhook handling, and cash/gift card payments, GetBookingsByCreatedRange endpoint, and scheduling exceptional hours validation.
- `handlers/auth` — Authentication
**446/449 tests passing** (3 skipped) across 12+ packages. Comprehensive coverage of online payments (deposit, full, partial, balance), saved card operations, tip payments, terminal payments, refunds, idempotency, webhook handling, and cash/gift card payments, GetBookingsByCreatedRange endpoint, scheduling exceptional hours validation, and referral code registration.
- `handlers/auth` — Authentication (login, register, referral code validation, refresh, verification)
- `handlers/bookings` — User booking flow, guest bookings, reservations, edit requests, discounts, closing hours validation, active booking limits, GetBookingsByCreatedRange
- `handlers/payments` — Square payments (terminal, online, refunds, tips, saved cards)
- `internal/square` — Square client dev mock tests
+5
View File
@@ -15,6 +15,10 @@ When you open the website, you'll see the salon's homepage with:
Tap or click **Book an Appointment** to start.
**If you're not logged in**, you'll see a welcome screen before selecting services. This screen explains the benefits of logging in — specifically that guest bookings don't earn loyalty stamps or qualify for seasonal discounts. You can choose to:
- **Log In** — takes you to the login/register page
- **Continue as Guest** — proceeds to service selection without an account
### Step 2: Choose Your Services
You'll see a list of all available treatments. Each one shows:
@@ -126,6 +130,7 @@ To create a permanent account, go to the **Login** page and choose to register.
- **Email address**: A standard email format
- **Date of birth**: You must be at least 16 years old to create an account
- **Password**: Up to 72 characters
- **Referral code** (optional): If a friend gave you a referral code, enter it here. The code is 12 characters and will be formatted automatically as you type (xxxx-xxxx-xxxx). Using a referral code links your account to the person who referred you.
After registering, your account starts in an "unverified" state. An email verification system exists but isn't fully connected yet — for now, you can still log in and book.