diff --git a/frontend/src/components/ScheduleBoard.tsx b/frontend/src/components/ScheduleBoard.tsx index e002d56..627a53c 100644 --- a/frontend/src/components/ScheduleBoard.tsx +++ b/frontend/src/components/ScheduleBoard.tsx @@ -99,13 +99,19 @@ export default function ScheduleBoard({ ); }, [matches, isBaseball, lang]); - // 기본 선택: 오늘(없으면 첫 날짜) / A조 / 현재 진행 라운드. + // 기본 선택: 오늘(경기 없으면 다음 경기일, 시즌 종료면 마지막 날짜) / A조 / 현재 진행 라운드. // 단, 직전 세션 선택을 sessionStorage 에 보관 → 상세 진입 후 뒤로가기 시 그대로 복원(오늘로 초기화 X). - const todayKey = useMemo(() => new Date().toISOString().slice(0, 10), []); + // 사이트 전체가 KST 기준이라 "오늘"도 클라이언트 시간대와 무관하게 KST 로 계산. + const todayKey = useMemo( + () => new Date(Date.now() + 9 * 3600_000).toISOString().slice(0, 10), + [], + ); + const defaultDate = (ds: string[], today: string) => + (ds.includes(today) ? today : ds.find((d) => d > today) ?? ds[ds.length - 1]) ?? ""; const [selDate, setSelDate] = useState(() => { const saved = sessionStorage.getItem("tp.sched.date"); if (saved && dates.includes(saved)) return saved; - return (dates.includes(todayKey) ? todayKey : dates[0]) ?? ""; + return defaultDate(dates, todayKey); }); const [selGroup, setSelGroup] = useState(() => { const saved = sessionStorage.getItem("tp.sched.group"); @@ -140,7 +146,11 @@ export default function ScheduleBoard({ useEffect(() => { if (dates.length && !dates.includes(selDate)) { - setSelDate(dates.includes(todayKey) ? todayKey : dates[0]); + // 목록이 비동기 로드될 때도 세션 복원이 동작하게 saved 를 우선 확인 + const saved = sessionStorage.getItem("tp.sched.date"); + setSelDate( + saved && dates.includes(saved) ? saved : defaultDate(dates, todayKey), + ); } }, [dates, selDate, todayKey]); // 리그 전환 시 목록에 없는 팀이면 첫 팀으로 @@ -216,7 +226,18 @@ export default function ScheduleBoard({ {/* 칩: 날짜 / 조 / 라운드 — 단일 줄 가로 스크롤 + 양 끝 화살표(PC에서 마우스로 넘김, 끝 도달 시 숨김) */} {effTab !== "rank" && ( - + {effTab === "date" ? dates.map((d) => ( setSelDate(d)}> @@ -274,9 +295,11 @@ export default function ScheduleBoard({ function ChipScroller({ children, resetKey, + centerKey, }: { children: React.ReactNode; resetKey?: string | number; + centerKey?: string; // 현재 선택값 — 바뀔 때마다 선택 칩을 가운데로 (비동기 로드·칩 클릭 포함) }) { const ref = useRef(null); const [atStart, setAtStart] = useState(true); @@ -290,7 +313,7 @@ function ChipScroller({ setAtEnd(el.scrollLeft >= max - 1); }; - // 탭/목록 변경 시: 선택된 칩을 가운데로 + 재측정 (레이아웃 확정 후) + // 탭/목록/선택 변경 시: 선택된 칩을 가운데로 + 재측정 (레이아웃 확정 후) // 선택 칩이 없으면 맨 앞으로 되감는다. useLayoutEffect(() => { const el = ref.current; @@ -301,7 +324,7 @@ function ChipScroller({ : 0; } measure(); - }, [resetKey]); + }, [resetKey, centerKey]); useEffect(() => { measure();