diff --git a/backend/app/routes/courts.py b/backend/app/routes/courts.py index 8b76e51..b491759 100644 --- a/backend/app/routes/courts.py +++ b/backend/app/routes/courts.py @@ -59,22 +59,24 @@ def get_court_schedule(court_id: int, db: Session = Depends(get_db)): .all() ) - schedule = [] - for m in matches: - schedule.append( + return { + "court": court.name, + "matches": [ { "id": m.id, - "tournament_id": m.tournament_id, + "tournament_id": m.tournament.id, "tournament_name": m.tournament.name, - "time": m.start_time.strftime("%H:%M") if m.start_time else "TBD", - "status": m.status, + "duration": m.tournament.duration, + "time": m.start_time.strftime("%H:%M") if m.start_time else None, + "status": m.status.value, "match_number": m.match_number, "p1": m.p1_team.name if m.p1_team else "TBD", "p2": m.p2_team.name if m.p2_team else "TBD", - "p1_sets": sum(1 for s in m.sets if s["p1"] > s["p2"]) if m.sets else 0, - "p2_sets": sum(1 for s in m.sets if s["p2"] > s["p1"]) if m.sets else 0, + "p1_sets": len([s for s in m.sets if s.get("p1", 0) > s.get("p2", 0)]), + "p2_sets": len([s for s in m.sets if s.get("p2", 0) > s.get("p1", 0)]), "ref_name": m.ref_team.name if m.ref_team else m.ref_label, } - ) - - return {"court": court.name, "matches": schedule} + for m in matches + if m.start_time + ], + } diff --git a/frontend/src/pages/Courts.tsx b/frontend/src/pages/Courts.tsx index 250da39..1aa939f 100644 --- a/frontend/src/pages/Courts.tsx +++ b/frontend/src/pages/Courts.tsx @@ -14,6 +14,7 @@ interface CourtMatch { tournament_id: string; tournament_name: string; time: string; + duration: number; status: string; match_number: number; p1: string; @@ -72,32 +73,65 @@ const CourtColumn = ({ courtId, onDelete, role }: { courtId: number, onDelete: ( void fetchSchedule(); }, [courtId]); + let isDayFinished = false; + let activeIndex = -1; + + if (data && data.matches.length > 0 && currentTime) { + const [currH, currM] = currentTime.split(':').map(Number); + const currTotalMins = currH * 60 + currM; + + for (let i = 0; i < data.matches.length; i++) { + const m = data.matches[i]; + if (!m.time) continue; + + const [mH, mM] = m.time.split(':').map(Number); + const mStartTotalMins = mH * 60 + mM; + const duration = m.duration || 30; + const mEndTotalMins = mStartTotalMins + duration; + + if (currTotalMins >= mStartTotalMins && currTotalMins < mEndTotalMins) { + activeIndex = i; + } + } + const lastMatch = data.matches[data.matches.length - 1]; + if (lastMatch.time) { + const [lastH, lastM] = lastMatch.time.split(':').map(Number); + const lastStartTotal = lastH * 60 + lastM; + const lastDuration = lastMatch.duration || 30; + const lastEndTotal = lastStartTotal + lastDuration; + + if (currTotalMins >= lastEndTotal) { + isDayFinished = true; + activeIndex = -1; + } + } + } + // AUTO-SCROLL LOGIC useEffect(() => { if (data && currentTime && !hasScrolled && scrollContainerRef.current) { setTimeout(() => { - const line = scrollContainerRef.current?.querySelector('.now-line'); - if (line) { - line.scrollIntoView({ behavior: 'smooth', block: 'start' }); - setHasScrolled(true); + const container = scrollContainerRef.current; + if (!container) return; + + if (isDayFinished) { + container.scrollTo({ top: container.scrollHeight, behavior: 'smooth' }); + } else { + const line = container.querySelector('.now-line') as HTMLElement; + if (line) { + container.scrollTo({ + top: line.offsetTop - 20, + behavior: 'smooth' + }); + } } + setHasScrolled(true); }, 500); } - }, [data, currentTime, hasScrolled]); + }, [data, currentTime, hasScrolled, isDayFinished]); if (!data) return