This commit is contained in:
2026-06-28 18:16:42 -05:00
parent 87624ae484
commit b3eb21e59b

View File

@@ -84,20 +84,38 @@ export default function KoFixtures({ teams, matches }: { teams: Team[]; matches:
}, [koMatches]); }, [koMatches]);
const targetRef = useRef<HTMLDivElement>(null); const targetRef = useRef<HTMLDivElement>(null);
const hasScrolledRef = useRef<string | null>(null);
useEffect(() => { useEffect(() => {
if (mounted && targetRef.current) { if (!mounted || !targetRef.current) return;
targetRef.current.scrollIntoView({ behavior: "smooth", block: "center" }); if (targetMatchId === hasScrolledRef.current) return;
} const el = targetRef.current;
}, [mounted]); const raf = requestAnimationFrame(() => {
const rect = el.getBoundingClientRect();
const absoluteTop = rect.top + window.scrollY;
const offset = 180;
window.scrollTo({ top: Math.max(0, absoluteTop - offset), behavior: "smooth" });
});
hasScrolledRef.current = targetMatchId;
return () => cancelAnimationFrame(raf);
}, [mounted, targetMatchId, koMatches.length]);
const [showScrollTop, setShowScrollTop] = useState(false);
useEffect(() => {
const onScroll = () => setShowScrollTop(window.scrollY > 100);
window.addEventListener("scroll", onScroll, { passive: true });
onScroll();
return () => window.removeEventListener("scroll", onScroll);
}, []);
if (koMatches.length === 0) { if (koMatches.length === 0) {
return <div className="notice">Keine K.o.-Spiele mit bekannten Teams verfügbar.</div>; return <div className="notice">Keine K.o.-Spiele mit bekannten Teams verfügbar.</div>;
} }
return ( return (
<div> <>
{groups.map(([date, groupMatches]) => ( <div>
{groups.map(([date, groupMatches]) => (
<div key={date} style={{ marginBottom: 24 }}> <div key={date} style={{ marginBottom: 24 }}>
<h3 style={{ <h3 style={{
fontFamily: "var(--font-display)", fontSize: 13, fontFamily: "var(--font-display)", fontSize: 13,
@@ -117,14 +135,19 @@ export default function KoFixtures({ teams, matches }: { teams: Team[]; matches:
}; };
const city = STADIUMS[MATCH_STADIUMS[m.matchNumber]]?.city; const city = STADIUMS[MATCH_STADIUMS[m.matchNumber]]?.city;
const isTarget = String(m.id) === String(targetMatchId);
const finished = m.status === "FINISHED";
return ( return (
<div <div
key={m.id} key={m.id}
ref={m.id === targetMatchId ? targetRef : undefined} ref={isTarget ? targetRef : undefined}
style={{ style={{
background: "var(--bg-card)", border: `1px solid ${live ? "var(--turf)" : "var(--line-soft)"}`, background: "var(--bg-card)",
border: `${isTarget ? 2 : 1}px solid ${live ? "var(--turf)" : isTarget ? "var(--turf)" : "var(--line-soft)"}`,
borderRadius: "var(--radius-sm)", padding: "12px 14px", borderRadius: "var(--radius-sm)", padding: "12px 14px",
opacity: finished && !isTarget ? 0.65 : 1,
boxShadow: isTarget ? "0 0 0 1px var(--turf)" : undefined,
}} }}
> >
{/* Kopfzeile */} {/* Kopfzeile */}
@@ -133,7 +156,17 @@ export default function KoFixtures({ teams, matches }: { teams: Team[]; matches:
marginBottom: 8, fontSize: 11, marginBottom: 8, fontSize: 11,
fontFamily: "var(--font-mono)", color: "var(--ink-faint)", fontFamily: "var(--font-mono)", color: "var(--ink-faint)",
}}> }}>
<span> <span style={{ display: "flex", alignItems: "center", gap: 8 }}>
{isTarget && (
<span style={{
background: live ? "var(--turf)" : "var(--turf-deep)",
color: "#fff", fontSize: 9, fontWeight: 700,
padding: "1px 6px", borderRadius: 999,
letterSpacing: "0.04em",
}}>
{live ? "LIVE" : "NÄCHSTES SPIEL"}
</span>
)}
{stageMap[m.stage] ?? m.stage} · Spiel {m.matchNumber || "—"} {stageMap[m.stage] ?? m.stage} · Spiel {m.matchNumber || "—"}
{city ? ` · ${city}` : ""} {city ? ` · ${city}` : ""}
</span> </span>
@@ -200,6 +233,23 @@ export default function KoFixtures({ teams, matches }: { teams: Team[]; matches:
</div> </div>
))} ))}
</div> </div>
{showScrollTop && (
<button
onClick={() => window.scrollTo({ top: 0, behavior: "smooth" })}
style={{
position: "fixed", right: 24, bottom: 24, zIndex: 50,
width: 48, height: 48, borderRadius: "50%",
background: "var(--bg-card)", color: "var(--ink-dim)",
border: "1px solid var(--line)", boxShadow: "0 2px 8px rgba(0,0,0,0.4)",
cursor: "pointer", display: "flex", alignItems: "center", justifyContent: "center",
fontSize: 22, lineHeight: 1,
}}
title="Nach oben scrollen"
>
</button>
)}
</>
); );
} }