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
master
Guillermo Pages 1 month ago
parent b7c02c9418
commit 1b7497b6d2

@ -240,7 +240,7 @@ export default function SlotDefinitionForm({
value={durationMinutes}
onChange={(e) => setDurationMinutes(parseInt(e.target.value) || 0)}
min="1"
step="15"
step="1"
className={`w-full px-4 py-3 border-2 rounded-lg font-medium transition-colors ${
errors.duration_minutes
? 'border-red-300 focus:border-red-500'

@ -164,10 +164,17 @@ export default function ClubCourtsTab({ clubId }: ClubCourtsTabProps) {
<h3 className="text-xl font-bold text-slate-900 mb-2">
{court.name}
</h3>
<div className="space-y-1">
{court.sport_variation && (
<p className="text-sm font-medium text-slate-700">
{court.sport_variation.sport.name} - {court.sport_variation.name}
</p>
)}
<p className="text-sm text-slate-600">
ID: {court.court_id} · Created {formatTimestamp(court.created_at)}
</p>
</div>
</div>
<div className="flex items-center space-x-2">
<button
@ -245,7 +252,10 @@ interface CourtFormModalProps {
function CourtFormModal({ clubId, court, onClose, onSuccess }: CourtFormModalProps) {
const isEditing = !!court;
const [name, setName] = useState(court?.name || '');
const [sportVariationId, setSportVariationId] = useState<number>(court?.sport_variation_id || 0);
// Get sport_variation_id from nested structure or fall back to deprecated flat field
const [sportVariationId, setSportVariationId] = useState<number>(
court?.sport_variation?.sport_variation_id || court?.sport_variation_id || 0
);
const [sports, setSports] = useState<Sport[]>([]);
const [loadingSports, setLoadingSports] = useState(true);
const [saving, setSaving] = useState(false);

@ -7,7 +7,17 @@
export interface Court {
court_id: number;
name: string;
sport_variation_id?: number; // For backward compatibility (deprecated)
sport_variation?: {
sport_variation_id: number;
name: string;
slug: string;
sport: {
sport_id: number;
name: string;
slug: string;
};
};
created_at: string; // ISO 8601 timestamp
updated_at: string; // ISO 8601 timestamp
}

Loading…
Cancel
Save