'use client'; import { useState, useEffect } from 'react'; import { X, Loader2, AlertCircle, ChevronDown, ChevronUp } from 'lucide-react'; import { generateSlotDefinitions, getSlotDefinitionPresets } from '@/src/lib/api/slot-definitions'; import type { Court } from '@/src/types/courts'; import type { SlotDefinitionPreset, GenerateSlotDefinitionsRequest, PatternOverrides, DayOfWeek, PresetInfo, } from '@/src/types/slot-definitions'; import { DAY_NAMES } from '@/src/types/slot-definitions'; interface GenerateSlotDefinitionsModalProps { clubId: number; courts: Court[]; onClose: () => void; onSuccess: () => void; } export default function GenerateSlotDefinitionsModal({ clubId, courts, onClose, onSuccess, }: GenerateSlotDefinitionsModalProps) { // Preset data const [presets, setPresets] = useState([]); const [loadingPresets, setLoadingPresets] = useState(true); // Form state const [preset, setPreset] = useState('workday_standard'); const [selectedCourtIds, setSelectedCourtIds] = useState([]); const [validFrom, setValidFrom] = useState(''); const [validTo, setValidTo] = useState(''); const [showAdvanced, setShowAdvanced] = useState(false); // Pattern overrides const [overrideDays, setOverrideDays] = useState([]); const [overrideStartTime, setOverrideStartTime] = useState(''); const [overrideEndTime, setOverrideEndTime] = useState(''); const [overrideDuration, setOverrideDuration] = useState(''); const [overrideInterval, setOverrideInterval] = useState(''); const [overrideCapacity, setOverrideCapacity] = useState(''); // UI state const [loading, setLoading] = useState(false); const [error, setError] = useState(null); // Fetch presets on mount useEffect(() => { async function loadPresets() { const result = await getSlotDefinitionPresets(); if (result.success) { setPresets(result.data.data.presets); setLoadingPresets(false); } else { setError('Failed to load presets'); setLoadingPresets(false); } } loadPresets(); }, []); function handleSelectAllCourts() { if (selectedCourtIds.length === courts.length) { setSelectedCourtIds([]); } else { setSelectedCourtIds(courts.map(c => c.court_id)); } } function handleCourtToggle(courtId: number) { setSelectedCourtIds(prev => prev.includes(courtId) ? prev.filter(id => id !== courtId) : [...prev, courtId] ); } function handleDayToggle(day: DayOfWeek) { setOverrideDays(prev => prev.includes(day) ? prev.filter(d => d !== day) : [...prev, day] ); } function buildPatternOverrides(): PatternOverrides | undefined { if (!showAdvanced) return undefined; const overrides: PatternOverrides = {}; if (overrideDays.length > 0) overrides.days = overrideDays; if (overrideStartTime) overrides.start_time = `${overrideStartTime}:00`; if (overrideEndTime) overrides.end_time = `${overrideEndTime}:00`; if (overrideDuration) overrides.duration_minutes = parseInt(overrideDuration, 10); if (overrideInterval) overrides.interval_minutes = parseInt(overrideInterval, 10); if (overrideCapacity) overrides.capacity = parseInt(overrideCapacity, 10); return Object.keys(overrides).length > 0 ? overrides : undefined; } async function handleSubmit() { if (selectedCourtIds.length === 0) { setError('Please select at least one court'); return; } setLoading(true); setError(null); const request: GenerateSlotDefinitionsRequest = { preset, court_ids: selectedCourtIds, pattern_overrides: buildPatternOverrides(), }; if (validFrom) request.valid_from = validFrom; if (validTo) request.valid_to = validTo; const result = await generateSlotDefinitions(clubId, request); if (result.success) { onSuccess(); onClose(); } else { setError(result.error.detail); } setLoading(false); } const selectedPreset = presets.find((p) => p.key === preset); return (
{/* Header */}

Generate Slot Definitions

{/* Body */}
{/* Loading State */} {loadingPresets && (
Loading presets...
)} {/* Preset Selection */} {!loadingPresets && presets.length > 0 && (
{selectedPreset && (

{selectedPreset.description}

)}
)} {/* Form Elements */} {!loadingPresets && ( <> {/* Court Selection */}
{courts.map(court => ( ))}

{selectedCourtIds.length} court{selectedCourtIds.length !== 1 ? 's' : ''} selected

{/* Validity Dates */}
setValidFrom(e.target.value)} className="w-full px-4 py-2 border-2 border-slate-200 rounded-lg focus:outline-none focus:border-slate-900" />
setValidTo(e.target.value)} className="w-full px-4 py-2 border-2 border-slate-200 rounded-lg focus:outline-none focus:border-slate-900" />
{/* Advanced Options */}
{showAdvanced && (
{/* Custom Days */}
{[0, 1, 2, 3, 4, 5, 6].map(day => ( ))}
{/* Time Range */}
setOverrideStartTime(e.target.value)} className="w-full px-3 py-2 border-2 border-slate-200 rounded-lg focus:outline-none focus:border-slate-900" />
setOverrideEndTime(e.target.value)} className="w-full px-3 py-2 border-2 border-slate-200 rounded-lg focus:outline-none focus:border-slate-900" />
{/* Duration and Interval */}
setOverrideDuration(e.target.value)} min="1" placeholder="90" className="w-full px-3 py-2 border-2 border-slate-200 rounded-lg focus:outline-none focus:border-slate-900" />
setOverrideInterval(e.target.value)} min="1" placeholder="90" className="w-full px-3 py-2 border-2 border-slate-200 rounded-lg focus:outline-none focus:border-slate-900" />
{/* Capacity */}
setOverrideCapacity(e.target.value)} min="1" placeholder="4" className="w-full px-3 py-2 border-2 border-slate-200 rounded-lg focus:outline-none focus:border-slate-900" />
)}
)} {/* Error Message */} {error && (
{error}
)}
{/* Footer */}
); }