10 Commits (47dbb96c472f422e9ba86caa48ae4459476ab7d0)

Author SHA1 Message Date
Guillermo Pages 47dbb96c47 feat(admin): implement click-to-edit pattern for club profile fields
continuous-integration/drone/push Build is passing Details
UX Improvements:
- Fields with existing data display as read-only text (not inputs)
- Pencil icon appears on hover (right side of field)
- Click text or icon to convert to editable input
- Auto-blur closes edit mode when field has value
- Prevents accidental edits

Implementation:
- Created reusable EditableField component with pencil icon
- Applied to all optional fields: address (5 fields), contact (3 fields)
- Name and timezone use inline click-to-edit (no separate component)
- Edit state tracked per-field with Set<string>
- Form prefills with existing profile data from API

Visual Design:
- Hover: Border changes to slate-300, background to slate-50
- Pencil icon: slate-400, opacity 0→100 on hover
- Maintains existing validation error styling (red borders)
- Consistent with professional slate theme

User Request: "should not be an input directly (put a pen on the side as well as making the text clickable) and on click convert to input (prevents accidental edits)"
1 month ago
Guillermo Pages a61e64ded0 feat(admin): align UI with Backend Brooke Phase 2 contracts, flip mocks to real endpoints
continuous-integration/drone/push Build is passing Details
Phase 2 Integration Updates:
- Profile UI: Read/write address and contact fields from settings.address/settings.contact JSONB structure
- Court dependencies: Updated modal to show 3 counts (slot_definitions, slot_instances_future, slot_instances_booked)
- Error codes: Fixed duplicate court check to use court_name_duplicate (matches backend)
- Mock flags: Flipped all 9 USE_MOCKS flags to false (courts.ts x7, materialisation.ts x2)

Profile Tab (ClubProfileTab.tsx):
- Read address fields from profile.settings?.address?.line_1 etc.
- Read contact fields from profile.settings?.contact?.phone etc.
- Write to settings structure preserving existing settings
- Added Info icon tooltips: "Stored in settings until native fields ship"
- Removed Integration section (provider/remote_club_id not in API)

Court Dependencies Modal (ClubCourtsTab.tsx):
- Display slot_instances_future count (was upcoming_bookings)
- Display slot_instances_booked count (new field)
- Updated deletion instructions for 3-count structure

Types (courts.ts):
- Created ClubProfileSettings interface for JSONB structure
- Updated ClubProfile to use settings instead of flat fields
- Updated CourtDependencies with court_id + 3 dependency counts
- Updated ClubProfileUpdateRequest to support settings

API Clients:
- courts.ts: Updated mock data to match API contracts (settings structure, 3 counts, court_name_duplicate)
- materialisation.ts: Flipped USE_MOCKS to false for real backend integration

Integration Ready:
- All contract mismatches resolved
- Build succeeds
- Ready for Phase 1 smoke tests against BUILD:290-291

Related: Backend Brooke BUILD:290 (courts CRUD) + BUILD:291 (club profile PATCH)
Contract references: docs/owners/payloads/court-api-contract.md, club-profile-api-contract.md
1 month ago
Guillermo Pages 9a9c3a3b95 feat(admin): add court management UI with Profile/Courts tabs (Phase 2)
continuous-integration/drone/push Build is passing Details
Phase 2 implementation per Chief Cole approval (Chief_Cole-20251107103829)

Club Detail Page Restructure:
- Replaced single-view club detail with tabbed interface
- Three tabs: Profile, Courts, Slot Definitions (links to existing page)
- Tab navigation with active state highlighting
- Breadcrumb navigation maintained

Profile Tab (ClubProfileTab):
- Full club metadata editing form with sections:
  - Basic Information: name (required), timezone (required, IANA dropdown)
  - Location: address line 1/2, city, postal code, country (all optional)
  - Contact: phone, email (validated), website (validated) (all optional)
  - Integration: provider, remote club ID (read-only for Phase 2)
- Client-side validation: required fields, email format, URL format
- Server-side validation: maps backend errors to fields
- Success/error messaging with auto-hide success toast
- Cancel button resets form to original values
- Professional slate theme form styling

Courts Tab (ClubCourtsTab):
- Court list view with empty state
- Add/edit/delete actions per court
- Add Court modal: single field (name), duplicate name validation
- Edit Court modal: pre-populated, same validation
- Delete with cascade blocking:
  - Dependency check before delete (slot definitions, upcoming bookings)
  - Blocking modal shows dependency counts with resolution steps
  - Confirmation modal for clean delete (no dependencies)
- In-memory mock data management (3 courts default)
- Court 1 has mock dependencies (12 slot defs, 45 bookings) for testing

Modal Components:
- CourtFormModal: Add/edit with field-level validation
- DeleteConfirmationModal: Confirm before deletion
- DependenciesBlockingModal: Shows why delete is blocked + resolution steps

All components use professional slate theme
All modals use backdrop blur + center positioning
All forms have loading states + error handling
Build tested and passed (npm run build successful)

Total new lines: ~1400 across 3 components
Ready for mock-driven testing while Backend Brooke builds APIs
1 month ago
Guillermo Pages 251b849500 feat(admin): add materialisation trigger/status UI + court management infrastructure
continuous-integration/drone/push Build is passing Details
Phase 1 continuation + Phase 2 preparation per Chief Cole request (Chief_Cole-20251107102650)

Materialisation UI (Phase 1 continuation):
- Created MaterialisationStatusPanel component with 5 states (never run, success, running, failed, rate limited)
- Polling strategy: 3-second intervals while job running
- Rate-limit countdown timer with live updates
- Idempotency key generation (UUID v4) for manual triggers
- Mock data for development with state cycling
- Integrated into slot definitions page between header and table
- TypeScript types: MaterialisationStatus, MaterialisationTriggerRequest/Response, helpers
- API client with mock implementation (USE_MOCKS flag)
- Professional slate theme consistent with existing UI

Court Management Infrastructure (Phase 2 preparation):
- Created TypeScript types for courts and club profile
- Court types: Court, CourtRequest, CourtDependencies
- Profile types: ClubProfile, ClubProfileUpdateRequest
- Common timezones list (40+ IANA zones)
- Validation helpers (email, URL)
- API client with full CRUD mocks:
  - getClubProfile, updateClubProfile
  - getCourts, createCourt, updateCourt, deleteCourt
  - getCourtDependencies (cascade blocking)
- Mock data: 3 courts, full profile, dependency simulation
- In-memory mock state management

Implementation ready for:
- Next: Club detail tab navigation (Profile/Courts/Slot Definitions)
- Next: Profile tab with edit form
- Next: Courts tab with add/edit/delete modals

Build tested and passed (npm run build successful)
1 month ago
Guillermo Pages 478d43b44a feat(slot-definitions): add create/edit form with validation
continuous-integration/drone/push Build is passing Details
Implement full CRUD form modal for slot definitions with:
- All fields: court, day, time, duration, capacity, date range, description
- Field-level validation with inline error messages
- API contract alignment (HH:MM:SS, 0=Monday format, optional valid_to)
- Overlap detection (409 handling)
- No end date checkbox
- Edit mode support
- Professional slate theme
- Loading states
- Delete functionality integrated

Form validates:
- Required fields
- Duration must be positive
- Capacity must be positive
- End date must be after start date
- Slot cannot extend past midnight
- Backend validation errors shown inline

Fully functional create/edit/delete flow ready for backend integration.
1 month ago
Guillermo Pages a8ad9fed51 feat(slot-definitions): implement Phase 1 slot definition table UI
continuous-integration/drone/push Build is passing Details
Add TypeScript types, API client, and table view for slot definitions.
Uses mock data until backend endpoints are ready.

Components:
- SlotDefinitionsComponent: table with create/edit/delete actions
- TypeScript types matching API contract specs
- API client with CRUD operations (POST/GET/PATCH/DELETE)
- Mock data for local development

Features:
- Professional slate theme throughout
- Empty state with CTA
- Table showing: day, time range, duration, capacity, valid period, description
- Edit/delete action buttons (TODOs for modals)
- Loading and error states with proper UX
- Breadcrumb navigation back to club

Contract alignment:
- Day format: 0=Monday, 6=Sunday
- Time format: HH:MM:SS with display helpers
- Date range: valid_from required, valid_to optional
- RFC-7807 error handling ready

Next: Create/edit form modal with validation
1 month 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
1 month 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
1 month ago
Guillermo Pages 4df827bce6 fix(admin): use useTranslation hook in client components
continuous-integration/drone/push Build is passing Details
Build #6 failed because client components were trying to receive
translations as props from server components, which breaks Next.js
serialization boundaries.

Fix: Use useTranslation() hook directly in client components to access
translations context, matching the pattern used in consumer app.

Changes:
- AdminClubsList: Remove locale/t props, use useTranslation() hook
- AdminClubDetail: Remove locale/t props, use useTranslation() hook
- Simplified page.tsx wrappers to not pass translations

This matches the consumer app pattern and allows proper SSR/client
component boundaries.
1 month ago
Guillermo Pages 9f47dab8d8 refactor(admin): convert to client-side rendering and add missing routes
continuous-integration/drone/push Build is failing Details
Responding to Chief Cole's feedback after validation of BUILD:283:
- Manager portal should match consumer app pattern (client-side fetching)
- Fix 404 errors for /dashboard and /admin/clubs/[id]
- Ensure locale-prefixed routing works smoothly

Changes:
1. Client-side rendering for admin views:
   - Converted /admin/clubs list to use 'use client' pattern
   - Created AdminClubsList.tsx component with useEffect data fetching
   - Removed SSR cookie forwarding (no longer needed for client-side)

2. Added club detail page:
   - Created /admin/clubs/[club_id] route with AdminClubDetail.tsx
   - Client-side fetching with proper loading/error states
   - Support for 401/403/404 error handling with user-friendly messages
   - Breadcrumb navigation back to clubs list

3. Added dashboard route:
   - Created /dashboard that redirects to /admin/clubs
   - Resolves post-login 404 error reported in testing

4. Locale handling:
   - Middleware automatically adds locale prefix to all routes
   - Internal links include locale parameter to avoid extra redirects
   - /dashboard → /en-US/dashboard → /en-US/admin/clubs

Result: Manager portal now follows consumer app patterns with full
client-side data fetching, proper error handling, and complete routing.

Refs: docs/owners/Frontend_Faye-needs-to-read-from-Chief_Cole-20251107073302.md
1 month ago