5 Commits (e21581dcd0da1821505efa2bdc1125b0b3c0b369)

Author SHA1 Message Date
Guillermo Pages e21581dcd0 debug: add console logging for court sport variation initialization
continuous-integration/drone/push Build is passing Details
Added debug logging to investigate sport variation dropdown issue:
- Log court data object on mount
- Log extracted sport_variation_id value
- Added visual disabled state (gray background) for locked dropdown
- Extracted initialSportVariationId to const for better debugging

This will help identify if:
1. Court data has sport_variation nested structure
2. sport_variation_id is being extracted correctly
3. Dropdown value is being set properly

Related: BUILD #21 sport variation display issue
1 month ago
Guillermo Pages 1b7497b6d2 fix(admin): duration validation + sport variation display
continuous-integration/drone/push Build is passing Details
Fixed two issues reported by user:

1. Slot definition duration validation error:
   - Changed step from "15" to "1" on duration input
   - HTML5 validation was failing because with min="1" and step="15",
     valid values were 1, 16, 31, 46, 61, 76, 91... (not 90!)
   - Now accepts any integer duration >= 1 minute
   - Error "nearest 76 or 91" resolved

2. Sport variation not showing in court edit form:
   - Updated Court type to include nested sport_variation structure
   - Backend now returns full sport_variation object with sport details
   - Updated CourtFormModal to extract sport_variation_id from nested
     structure: court.sport_variation.sport_variation_id
   - Added sport variation display in court list (e.g., "Padel - Indoor")
   - Maintains backward compatibility with deprecated flat field

Changes:
- SlotDefinitionForm: step="1" instead of step="15"
- Court interface: added optional sport_variation nested object
- ClubCourtsTab: reads sport_variation_id from nested structure
- ClubCourtsTab: displays "Sport - Variation" in court list

Related: Backend Brooke nested sport_variation response structure
1 month ago
Guillermo Pages 36c5fe2183 feat(admin): add sport variation selection to court creation + fix profile trim crash
continuous-integration/drone/push Build is passing Details
Court Sport Variation (BUILD:296-297 requirement):
- Added Sport and SportVariation types to courts.ts
- Created getSports() API client for GET /admin/sports
- Updated Court and CourtRequest types with sport_variation_id field
- Added sport variation dropdown to court creation modal
- Auto-selects first variation for new courts
- Sport type locked after creation (disabled in edit mode)
- Mock data updated with sport_variation_id values

Profile Bug Fix:
- Fixed click-to-edit crash when field values are empty/undefined
- Added null checks before calling .trim() in hasFieldValue() and EditableField
- Error: "Cannot read properties of undefined (reading 'trim')"
- Now safely handles empty string values

UI Details:
- Sport dropdown shows "Padel - Indoor", "Padel - Outdoor", etc.
- Loading spinner while fetching sports
- Validation error if no sport variation selected
- Form includes both name and sport_variation_id in POST request

Backend Brooke message: Court creation now requires sport_variation_id parameter
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