fix(courts): use club detail courts data instead of separate fetch
continuous-integration/drone/push Build is passing Details

Root cause: GET /admin/clubs/{id}/courts endpoint doesn't include
sport_variation nested structure, but GET /admin/clubs/{id} does.

Changes:
- Updated AdminClubDetail.courts to use Court[] type (includes sport_variation)
- ClubDetailTabs now passes courts + onUpdate callback to ClubCourtsTab
- ClubCourtsTab accepts courts as props instead of fetching separately
- Removed redundant getCourts() API call
- Removed debug logging

This fixes the court edit dropdown issue where sport variation wasn't
displaying because the data wasn't available from the courts endpoint.
master
Guillermo Pages 1 month ago
parent e21581dcd0
commit 86fa2a92e6

@ -205,7 +205,11 @@ export default function ClubDetailTabs({ clubId }: ClubDetailTabsProps) {
)}
{activeTab === 'courts' && (
<ClubCourtsTab clubId={clubId} />
<ClubCourtsTab
clubId={clubId}
courts={clubDetail.courts}
onUpdate={loadClubDetail}
/>
)}
</div>
);

@ -1,9 +1,8 @@
'use client';
import { useState, useEffect } from 'react';
import { useState } from 'react';
import { Loader2, AlertCircle, Plus, Edit, Trash2, AlertTriangle, X } from 'lucide-react';
import {
getCourts,
createCourt,
updateCourt,
deleteCourt,
@ -15,11 +14,11 @@ import { formatTimestamp } from '@/src/types/courts';
interface ClubCourtsTabProps {
clubId: number;
courts: Court[];
onUpdate: () => void;
}
export default function ClubCourtsTab({ clubId }: ClubCourtsTabProps) {
const [courts, setCourts] = useState<Court[]>([]);
const [loading, setLoading] = useState(true);
export default function ClubCourtsTab({ clubId, courts, onUpdate }: ClubCourtsTabProps) {
const [error, setError] = useState<string | null>(null);
// Modal state
@ -31,24 +30,6 @@ export default function ClubCourtsTab({ clubId }: ClubCourtsTabProps) {
const [selectedCourt, setSelectedCourt] = useState<Court | null>(null);
const [dependencies, setDependencies] = useState<CourtDependencies | null>(null);
useEffect(() => {
loadCourts();
}, [clubId]);
async function loadCourts() {
setLoading(true);
const result = await getCourts(clubId);
if (result.success) {
setCourts(result.data);
setError(null);
} else {
setError(result.error.detail);
}
setLoading(false);
}
function handleAdd() {
setShowAddModal(true);
}
@ -88,20 +69,11 @@ export default function ClubCourtsTab({ clubId }: ClubCourtsTabProps) {
setDependencies(null);
}
async function handleSuccess() {
await loadCourts();
function handleSuccess() {
onUpdate(); // Trigger parent to refresh club detail (which includes courts)
closeModals();
}
// Loading state
if (loading) {
return (
<div className="flex items-center justify-center py-20">
<Loader2 className="w-8 h-8 text-slate-600 animate-spin" />
</div>
);
}
// Error state
if (error && courts.length === 0) {
return (
@ -262,12 +234,6 @@ function CourtFormModal({ clubId, court, onClose, onSuccess }: CourtFormModalPro
const [fieldError, setFieldError] = useState('');
const [sportVariationError, setSportVariationError] = useState('');
// Debug: log the court data and extracted sport variation ID
useEffect(() => {
console.log('Court data:', court);
console.log('Extracted sport_variation_id:', initialSportVariationId);
}, [court]);
useEffect(() => {
async function loadSports() {
setLoadingSports(true);

@ -34,7 +34,7 @@ export interface AdminClubDetail {
name: string;
timezone: string;
};
courts: AdminCourt[];
courts: import('./courts').Court[];
slot_definitions: AdminSlotDefinition[];
upcoming_slots: AdminSlot[];
provider: AdminProviderInfo;
@ -43,6 +43,7 @@ export interface AdminClubDetail {
export interface AdminCourt {
court_id: number;
name: string;
// Deprecated: use Court type from courts.ts which includes sport_variation
}
export interface AdminSlotDefinition {

Loading…
Cancel
Save