You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

16 KiB

Phase 1: Slot Definition Management - Wireframes & Form States

Owner: Frontend Faye Created: 2025-11-05 Status: Draft for review


Overview

Phase 1 enables venue admins to create, edit, and manage recurring slot templates (slot definitions). These templates are materialized into actual slot instances by Cron Carter's materialisation job.

User Story: As a venue admin, I want to create recurring time slots for my courts so that customers can book them automatically without manual intervention.


Page Structure

Route: /[locale]/admin/clubs/[club_id]/slot-definitions

Navigation from Club Detail:

  • Club detail page → "Manage Schedules" button → Slot Definitions page

Layout:

┌─────────────────────────────────────────────────────────┐
│ [Back to Club] Central Padel Geneva                     │
├─────────────────────────────────────────────────────────┤
│                                                           │
│  Slot Definitions                                         │
│  Recurring time slots for your courts                     │
│                                                           │
│  [+ Create New Definition]                [Filter ▼]     │
│                                                           │
│  ┌─────────────────────────────────────────────────┐    │
│  │ Court 1 - Mondays 18:00-19:00                   │    │
│  │ Capacity: 4 players | Valid from: 2025-11-01   │    │
│  │ Status: ● Active                                │    │
│  │                                    [Edit] [Delete]│    │
│  └─────────────────────────────────────────────────┘    │
│                                                           │
│  ┌─────────────────────────────────────────────────┐    │
│  │ Court 2 - Tuesdays 19:00-20:00                  │    │
│  │ Capacity: 4 players | Valid from: 2025-11-01   │    │
│  │ Status: ● Active                                │    │
│  │                                    [Edit] [Delete]│    │
│  └─────────────────────────────────────────────────┘    │
│                                                           │
└─────────────────────────────────────────────────────────┘

Create/Edit Form Modal

Form Structure

┌────────────────────────────────────────────────────┐
│  Create Slot Definition                      [×]   │
├────────────────────────────────────────────────────┤
│                                                     │
│  Court *                                           │
│  [Select court ▼]                                  │
│                                                     │
│  Day of Week *                                     │
│  [Monday ▼]                                        │
│                                                     │
│  Start Time *                                      │
│  [18] : [00]  (24-hour format)                    │
│                                                     │
│  Duration *                                        │
│  [60] minutes                                      │
│                                                     │
│  Capacity *                                        │
│  [4] players                                       │
│                                                     │
│  Valid From *                                      │
│  [2025-11-15] 📅                                   │
│                                                     │
│  Valid To (optional)                               │
│  [No end date]  📅                                 │
│                                                     │
│  ─────────────────────────────────────────────    │
│                                                     │
│  [Cancel]                    [Create Definition]   │
│                                                     │
└────────────────────────────────────────────────────┘

Form States & Validation

Field Definitions

Court (Required)

  • Type: Dropdown select
  • Options: List of active courts for the club
  • Validation: Must select a court
  • Error: "Please select a court"

Day of Week (Required)

  • Type: Dropdown select
  • Options: Monday (1), Tuesday (2), ..., Sunday (0)
  • Validation: Must select a day
  • Error: "Please select a day of week"

Start Time (Required)

  • Type: Time input (HH:MM)
  • Format: 24-hour
  • Validation:
    • Must be valid time (00:00 - 23:59)
    • Should align with typical business hours warning (e.g., warning if before 06:00 or after 23:00)
  • Error: "Please enter a valid start time"
  • Warning: "⚠️ This time is outside typical business hours (06:00-23:00)"

Duration (Required)

  • Type: Number input
  • Options: Preset buttons: [30 min] [60 min] [90 min] [120 min] or custom
  • Validation:
    • Must be > 0
    • Must be <= 480 minutes (8 hours)
    • Recommended: 30, 60, 90, 120 minutes
  • Error: "Duration must be between 1 and 480 minutes"
  • Warning: "⚠️ Non-standard duration. Most bookings are 60 or 90 minutes."

Capacity (Required)

  • Type: Number input
  • Default: 4 (for padel/tennis doubles)
  • Validation: Must be between 1 and 8
  • Error: "Capacity must be between 1 and 8 players"

Valid From (Required)

  • Type: Date picker
  • Default: Tomorrow's date
  • Validation:
    • Must be today or future date
    • Cannot be before today
  • Error: "Valid from date cannot be in the past"

Valid To (Optional)

  • Type: Date picker or "No end date" checkbox
  • Validation:
    • If set, must be after "Valid From"
    • Warning if > 1 year in future
  • Error: "Valid to must be after valid from date"
  • Warning: "⚠️ Definition valid for more than 1 year. Consider reviewing periodically."

Form Validation States

1. Empty / Initial State

  • All fields empty or default values
  • Submit button disabled
  • No error messages shown

2. Filling Out (In Progress)

  • Fields being completed
  • Real-time validation on blur
  • Submit button disabled until all required fields valid
  • Show field-level errors on blur

3. Valid State

  • All required fields filled and validated
  • No errors shown
  • Submit button enabled and highlighted
  • Preview of materialization impact shown

4. Error State

  • One or more validation errors
  • Error messages shown under relevant fields
  • Submit button disabled
  • Focus on first error field

5. Conflict State (Backend Error)

  • Form submitted but backend returns conflict
  • Error banner: "⚠️ A definition already exists for Court 1 on Mondays at 18:00"
  • Suggestion: "Edit the existing definition or choose a different time"
  • Form fields remain editable

6. Submitting State

  • Submit button shows loading spinner
  • Form fields disabled
  • Cannot close modal
  • Loading text: "Creating definition..."

7. Success State

  • Brief success message: "✓ Slot definition created successfully"
  • Auto-close modal after 1 second
  • Refresh slot definitions list
  • Optional: Show materialisation job status

Materialisation Status Indicator

After creating/editing a definition, show materialisation status:

┌────────────────────────────────────────────────────┐
│  ✓ Definition created successfully                 │
│                                                     │
│  Materialisation Status:                           │
│  ⏳ Slots are being generated... (Job #12345)      │
│                                                     │
│  Expected completion: 2 minutes                    │
│  [View Job Details]                                │
└────────────────────────────────────────────────────┘

States:

  1. Queued: Materialisation job queued (position #3)
  2. Running: Generating slots... (45% complete)
  3. Complete: ✓ 24 new slots created for next 7 days
  4. Error: ⚠️ Materialisation failed (contact support)

Link to Cron Carter: This requires coordination with Cron Carter for job status API.


Delete Confirmation Modal

┌────────────────────────────────────────────────────┐
│  Delete Slot Definition?                     [×]   │
├────────────────────────────────────────────────────┤
│                                                     │
│  Are you sure you want to delete:                  │
│                                                     │
│  📍 Court 1 - Mondays 18:00-19:00                  │
│     Valid from: 2025-11-01                         │
│                                                     │
│  ⚠️ This will not delete existing bookings,       │
│     but future slots will not be generated.        │
│                                                     │
│  [Cancel]                     [Delete Definition]  │
│                                                     │
└────────────────────────────────────────────────────┘

Filter & Sort Options

Filter Dropdown

  • All Courts
  • By Court (Court 1, Court 2, etc.)
  • Active Only
  • Inactive Only
  • By Day of Week

Sort Options

  • Court (A-Z)
  • Day of Week (Mon-Sun)
  • Start Time (Early-Late)
  • Created Date (Newest-Oldest)

Empty States

No Definitions Yet

┌────────────────────────────────────────────────────┐
│                                                     │
│                    📅                               │
│                                                     │
│          No slot definitions yet                   │
│                                                     │
│  Create recurring time slots so customers can      │
│  book your courts automatically.                   │
│                                                     │
│           [+ Create First Definition]              │
│                                                     │
└────────────────────────────────────────────────────┘

No Results (After Filter)

┌────────────────────────────────────────────────────┐
│                                                     │
│                    🔍                               │
│                                                     │
│      No definitions match your filters             │
│                                                     │
│      Try adjusting your filter criteria.           │
│                                                     │
│              [Clear Filters]                       │
│                                                     │
└────────────────────────────────────────────────────┘

Mobile Responsive Considerations

Card Stacking (< 768px)

  • Definition cards stack vertically
  • Edit/Delete buttons move to card footer
  • Form modal takes full screen
  • Time picker uses native mobile inputs

Touch Targets

  • Minimum 44px × 44px for all interactive elements
  • Larger tap areas for primary actions
  • Swipe to delete on mobile (optional)

Accessibility

  • All form fields have proper <label> associations
  • Error messages use aria-describedby
  • Form validation uses aria-invalid
  • Focus management: First field on modal open, first error on validation fail
  • Keyboard navigation: Tab order follows visual order
  • Screen reader announcements for success/error states

API Integration Points

Based on VENUE_ADMIN_DESIGN.md:

GET /admin/clubs/{club_id}/slot-definitions

  • Load existing definitions for display
  • Filter by court_id or active_on date

POST /admin/clubs/{club_id}/slot-definitions

Request Body:

{
  "court_id": 12,
  "dow": 1,
  "starts_at": "18:00:00",
  "duration_minutes": 60,
  "capacity": 4,
  "valid_from": "2025-11-15",
  "valid_to": null
}

PATCH /admin/clubs/{club_id}/slot-definitions/{id}

Request Body: Same as POST (partial updates allowed) Headers: If-Match: "<etag>" for optimistic concurrency

DELETE /admin/clubs/{club_id}/slot-definitions/{id}

Headers: If-Match: "<etag>"


Technical Implementation Notes

Component Structure

/admin/clubs/[club_id]/slot-definitions/
├── page.tsx                    # Main list page
├── components/
│   ├── DefinitionCard.tsx      # Individual definition card
│   ├── DefinitionForm.tsx      # Create/edit modal form
│   ├── DeleteConfirm.tsx       # Delete confirmation modal
│   ├── FilterBar.tsx           # Filter/sort controls
│   └── MaterialisationStatus.tsx  # Job status indicator

State Management

  • Use React useState for form state
  • Consider useReducer for complex form validation
  • Optimistic updates for delete (rollback on error)
  • Polling or WebSocket for materialisation status updates

Form Libraries (Recommendation)

  • React Hook Form: For form state management
  • Zod: For schema validation matching API contracts
  • Or plain React state for simplicity (Phase 1 is small)

Open Questions for Cron Carter

  1. Materialisation Job Status API: What endpoint do we call to check job status?
  2. Real-time Updates: WebSocket, polling, or manual refresh?
  3. Job Failure Handling: What UI should we show if materialisation fails?
  4. Manual Trigger: Should admins be able to manually trigger materialisation?

Next Steps

  1. Review with Chief Cole: Confirm this matches vision
  2. Share with Cron Carter: Align on materialisation status display
  3. Implementation: After Phase 0 integration complete
  4. Design Review: Share with Ops Omar for pilot feedback

Status: Ready for review and implementation planning.