6 Commits (6ebc57dd36d25020cee4edec73b69f1ad07cce71)

Author SHA1 Message Date
Guillermo Pages 6ebc57dd36 feat: migrate to API v2.0 with facility-based routing (Build 358+)
continuous-integration/drone/push Build is passing Details
Complete migration to match backend breaking changes from Build 355+ and Build 358+:

**Terminology Migration (Build 355+):**
- Rename club → facility (club_id → facility_id, club_name → facility_name)
- Rename remote → origin/provider (remote_server_id → origin_id, remote_type → provider)
- Update all field references: remote_name → origin_name, remote_logo_url → origin_logo_url

**Facility-Based Routing (Build 358+):**
- Change routing from provider-based to facility-based
- Update URL parameters: remote_slug → facility_slug in all booking/slot endpoints
- Update discovery endpoint: /remotes → /facilities
- Update slot responses: remote object → facility object with new field structure
- Update user settings: default_remote_sport.origin_slug → facility_slug

**Files Updated:**
- 32 files modified (TypeScript types, API clients, hooks, components)
- 150+ field name changes across the codebase
- All response interfaces updated to match new API contract

**Verification:**
- TypeScript compilation: ✓ No errors
- ESLint: ✓ No migration-related issues

BREAKING CHANGES: Requires backend Build 358+ for facility-based routing
3 months ago
Guillermo Pages 6a80607430 feat(bookings): add dry_run slot picker with live validation
continuous-integration/drone/push Build is passing Details
Implemented complete slot picker flow with real-time validation:

**Components Created:**

1. **SlotPickerTile** (src/components/bookings/SlotPickerTile.tsx)
   - Individual slot tile with dry_run validation
   - 4 validation states: idle, validating, valid, invalid
   - Real-time API calls to validateMoveBooking() on selection
   - Visual feedback: checkmark (✓) for valid, X for invalid, spinner during validation
   - Displays validation errors inline with bullet points
   - Shows success message "✓ Valid - ready to confirm"
   - Integrates CapacityDisplay component
   - Color-coded borders (green=valid, red=invalid, gray=idle)
   - Disabled state for full/cancelled slots
   - onValidationResult callback for parent coordination

2. **SlotPickerModal** (src/components/bookings/SlotPickerModal.tsx)
   - Full-screen modal for slot selection
   - Groups slots by date (weekday, month, day, year)
   - Sorts dates chronologically
   - Filters out current slot
   - 2-column grid layout for slots
   - Info banner with policy hints (14-day window, product-type, club match)
   - Confirm button disabled until valid slot selected
   - Loading states with spinner
   - Empty state with helpful message
   - Tracks validation state from child tiles

3. **CancelBookingModal** (src/components/bookings/CancelBookingModal.tsx)
   - Confirmation modal for booking cancellation
   - Optional reason textarea (500 char limit)
   - Displays grace period policy (reads from booking.policies or defaults to 15 min)
   - Shows booking details (court, time, attendees count)
   - Warning banner: "This action cannot be undone"
   - Policy info banner with grace period details
   - Two-button layout: "Keep Booking" / "Yes, Cancel Booking"
   - Loading state with spinner

**Features:**
- Live dry_run validation on slot selection (no manual trigger needed)
- Real-time feedback with checkmarks/errors
- Graceful error handling (network failures, validation errors)
- Parameterized error messages from getBookingErrorMessage()
- SSR-safe with proper disabled states
- Professional slate theme matching existing UI
- Responsive grid layouts

**Integration:**
- SlotPickerTile calls validateMoveBooking() API automatically
- SlotPickerModal coordinates validation state
- CancelBookingModal reads policy fields from BookingDetail
- All components ready for integration into BookingDrawer

Related: Phase 3, Booking Admin API v1.1, BUILD #23
3 months ago
Guillermo Pages 13097541f1 feat(bookings): add provider-aware UI components for booking management
continuous-integration/drone/push Build is passing Details
Implemented complete UI foundation for booking drawer with provider gating:

**Components Created:**

1. **ProviderBanner** (src/components/bookings/ProviderBanner.tsx)
   - Displays informational banner for FairPlay clubs
   - "This club is managed by {provider}" messaging
   - Only shows for non-local providers
   - Blue theme with Info icon

2. **CapacityDisplay** (src/components/bookings/CapacityDisplay.tsx)
   - Shows "X / Y booked · Z remaining" format
   - Three variants: default, compact, inline
   - Color-coded availability (red=full, orange=low, gray=available)
   - Responsive text sizing

3. **NotifyPlayersToggle** (src/components/bookings/NotifyPlayersToggle.tsx)
   - Toggle for controlling player notifications
   - Defaults to ON (true)
   - Persists preference to localStorage (key: booking_admin_notify_players)
   - SSR-safe with hydration protection
   - Bell/BellOff icon feedback
   - Exports getStoredNotifyPreference() helper

4. **BookingDrawer** (src/components/bookings/BookingDrawer.tsx)
   - Main booking management UI (360+ lines)
   - Provider-aware: disables actions for FairPlay clubs
   - Displays: time, location, capacity, attendees, booked_by
   - Status badges (confirmed/cancelled/no_show)
   - Attendee type badges (app_user/guest/remote_member)
   - Action buttons: Move, Edit Attendees, Cancel (hidden for FairPlay)
   - ETag support for optimistic concurrency
   - Loading and error states
   - Integrates all sub-components

**Features:**
- Read-only mode for FairPlay bookings (provider.manages_slot_storage === false)
- Capacity display with color-coded availability
- Notification toggle with localStorage persistence
- Professional slate theme matching existing UI
- Fully typed with BookingDetail interface
- Error handling with user-friendly messages

**TODO Placeholders:**
- Move booking flow (button wired, implementation pending)
- Edit attendees flow (button wired, implementation pending)
- Cancel booking flow (button wired, implementation pending)

Related: Phase 3, Booking Admin API v1.1, BUILD #22
3 months ago
Guillermo Pages b3778b22af feat(design): extend professional slate theme throughout manager portal
continuous-integration/drone/push Build is passing Details
Extended the professional slate gray color scheme from the landing page
to all admin components and navigation. Replaced all purple/pink/indigo
gradients with clean slate-900/600/200 colors for a timeless,
enterprise-focused aesthetic.

Changes:
- Updated AdminClubsList.tsx with slate theme
- Updated AdminClubDetail.tsx with slate theme
- Updated AdminAuthGuard.tsx loading states with slate colors
- Updated Navigation.tsx header, menu items, and footer with slate theme
- Updated layout.tsx body and footer with slate colors
- Added ~30 new translation keys to dictionaries/en.json

Design system:
- Primary: slate-900 (almost black)
- Text: slate-900 (headings), slate-600 (body), slate-500 (muted)
- Borders: slate-200 (2px), slate-300 on hover
- Backgrounds: white, slate-50, slate-100
- Professional rounded corners: rounded-2xl, rounded-xl, rounded-lg
- Clean typography: tracking-tight, font-bold/medium/light
3 months ago
Guillermo Pages 8e0bbd58d9 feat(landing+auth): add marketing landing page and admin auth guards
continuous-integration/drone/push Build is passing Details
Per Chief Cole's guidance (Chief_Cole-20251107080515), enhanced manager
portal with showcase landing and auth protection.

Changes:
1. Marketing Landing Page:
   - Hero section with gradient backgrounds and value props
   - Feature tiles showcasing club management, scheduling, booking insights
   - CTA buttons linking to login
   - Marketing copy focused on venue admin benefits
   - Responsive design matching consumer app style

2. Auth Guards for /admin Routes:
   - Created AdminAuthGuard component using useSwissOIDAuth hook
   - Redirects unauthenticated users to login immediately
   - Shows loading state during auth check
   - Preserves locale in redirect flow
   - Wrapped all /admin/clubs pages with guard

3. Protected Routes:
   - /admin/clubs - guarded
   - /admin/clubs/[club_id] - guarded
   - / - public landing (no guard needed)

Result: Unauthenticated users see marketing showcase at root, and are
redirected to login if they try to access /admin routes directly.

Refs: docs/owners/Frontend_Faye-needs-to-read-from-Chief_Cole-20251107080515.md
3 months ago
Guillermo Pages c275bf1dcc feat(phase-0): integrate admin clubs API with staging backend
Phase 0 venue admin integration complete:
- Implemented GET /admin/clubs API integration
- Three-state response handling: 401 (auth), empty (no access), success (club list)
- RFC-7807 error handling with proper error display
- Club cards with navigation to detail pages
- Staging environment configuration (.env.staging)
- TypeScript interfaces aligned with VENUE_ADMIN_DESIGN.md

Integration points:
- API base URL: https://staging.api.playchoo.com
- Endpoints: /admin/clubs, /admin/clubs/{club_id}
- Auth: Cookie-based SwissOID (handled by API)
- Stub mode: Clubs 3 (Central Padel) and 7 (Riverside Tennis)

Files changed:
- src/app/[locale]/admin/clubs/page.tsx: API integration
- src/lib/api/admin-clubs.ts: API client with mock data
- src/types/admin-api.ts: TypeScript interfaces
- .env.staging: Staging configuration

Ready for:
- Live testing against staging stubs
- E2E tests with admin accounts (pending Access Avery seeding)

Refs: VENUE_ADMIN_DESIGN.md, VENUE_ADMIN_EXECUTION_PLAN.md
3 months ago