changes
This commit is contained in:
@@ -1,20 +1,32 @@
|
||||
"use client";
|
||||
|
||||
import { useState, useCallback } from "react";
|
||||
import { GroupTable, Match, Team, ThirdPlaceRow } from "@/lib/types";
|
||||
import { ThirdAssignment, orderedRound } from "@/lib/bracket";
|
||||
import { resolveBracket, ResolvedSide, ResolvedTie } from "@/lib/resolve-bracket";
|
||||
import Flag from "./Flag";
|
||||
|
||||
interface TipState { x: number; y: number; text: string }
|
||||
|
||||
function Side({
|
||||
s, prob, teams,
|
||||
}: { s: ResolvedSide; prob?: number | null; teams: Team[] }) {
|
||||
s, prob, teams, onShowTip, onHideTip,
|
||||
}: {
|
||||
s: ResolvedSide; prob?: number | null; teams: Team[];
|
||||
onShowTip: (text: string, x: number, y: number) => void;
|
||||
onHideTip: () => void;
|
||||
}) {
|
||||
const team = s.teamId ? teams.find((t) => t.id === s.teamId) : undefined;
|
||||
// fix = ein echtes Team steht fest (nicht vorläufig). Eigene Klasse für klares Styling.
|
||||
const fix = s.teamId != null && !s.provisional;
|
||||
const hasTip = !!s.tooltip;
|
||||
|
||||
return (
|
||||
<div
|
||||
className={`side ${s.isWinner ? "win" : ""} ${s.provisional ? "prov" : ""} ${fix ? "fix" : ""}`}
|
||||
title={s.tooltip ?? undefined}
|
||||
{...(hasTip ? {
|
||||
onMouseEnter: (e: React.MouseEvent<HTMLDivElement>) => onShowTip(s.tooltip!, e.clientX, e.clientY),
|
||||
onMouseMove: (e: React.MouseEvent<HTMLDivElement>) => onShowTip(s.tooltip!, e.clientX, e.clientY),
|
||||
onMouseLeave: onHideTip,
|
||||
} : {})}
|
||||
>
|
||||
<span className="nm">
|
||||
{s.teamId ? (
|
||||
@@ -35,12 +47,18 @@ function Side({
|
||||
);
|
||||
}
|
||||
|
||||
function Tie({ tie, teams, isFinal }: { tie: ResolvedTie; teams: Team[]; isFinal?: boolean }) {
|
||||
function Tie({
|
||||
tie, teams, isFinal, onShowTip, onHideTip,
|
||||
}: {
|
||||
tie: ResolvedTie; teams: Team[]; isFinal?: boolean;
|
||||
onShowTip: (text: string, x: number, y: number) => void;
|
||||
onHideTip: () => void;
|
||||
}) {
|
||||
return (
|
||||
<div className={`tie ${isFinal ? "final-tie" : ""}`}>
|
||||
<div className="tie-head">Spiel {tie.matchNumber}</div>
|
||||
<Side s={tie.home} prob={tie.prob?.home} teams={teams} />
|
||||
<Side s={tie.away} prob={tie.prob?.away} teams={teams} />
|
||||
<Side s={tie.home} prob={tie.prob?.home} teams={teams} onShowTip={onShowTip} onHideTip={onHideTip} />
|
||||
<Side s={tie.away} prob={tie.prob?.away} teams={teams} onShowTip={onShowTip} onHideTip={onHideTip} />
|
||||
</div>
|
||||
);
|
||||
}
|
||||
@@ -57,8 +75,6 @@ export default function Bracket({
|
||||
|
||||
const r32ByNum = new Map(r32Array.map((t) => [t.matchNumber, t]));
|
||||
|
||||
// Korrekte Baum-Reihenfolge: von der Wurzel (Finale) rekursiv die Quellen
|
||||
// jeder Runde ermitteln, damit die Spalten vertikal ausgerichtet sind.
|
||||
const sfOrder = orderedRound([104]);
|
||||
const qfOrder = orderedRound(sfOrder);
|
||||
const r16Order = orderedRound(qfOrder);
|
||||
@@ -71,6 +87,10 @@ export default function Bracket({
|
||||
const fin = later[104];
|
||||
const third = later[103];
|
||||
|
||||
const [tip, setTip] = useState<TipState | null>(null);
|
||||
const showTip = useCallback((text: string, x: number, y: number) => setTip({ x, y, text }), []);
|
||||
const hideTip = useCallback(() => setTip(null), []);
|
||||
|
||||
return (
|
||||
<div>
|
||||
<div className="bracket-banner">
|
||||
@@ -87,35 +107,35 @@ export default function Bracket({
|
||||
<div className="round">
|
||||
<div className="round-label">Letzte 32</div>
|
||||
<div className="round-matches">
|
||||
{r32.map((t) => <Tie key={t.matchNumber} tie={t} teams={teams} />)}
|
||||
{r32.map((t) => <Tie key={t.matchNumber} tie={t} teams={teams} onShowTip={showTip} onHideTip={hideTip} />)}
|
||||
</div>
|
||||
</div>
|
||||
<div className="round">
|
||||
<div className="round-label">Achtelfinale</div>
|
||||
<div className="round-matches">
|
||||
{r16.map((t) => <Tie key={t.matchNumber} tie={t} teams={teams} />)}
|
||||
{r16.map((t) => <Tie key={t.matchNumber} tie={t} teams={teams} onShowTip={showTip} onHideTip={hideTip} />)}
|
||||
</div>
|
||||
</div>
|
||||
<div className="round">
|
||||
<div className="round-label">Viertelfinale</div>
|
||||
<div className="round-matches">
|
||||
{qf.map((t) => <Tie key={t.matchNumber} tie={t} teams={teams} />)}
|
||||
{qf.map((t) => <Tie key={t.matchNumber} tie={t} teams={teams} onShowTip={showTip} onHideTip={hideTip} />)}
|
||||
</div>
|
||||
</div>
|
||||
<div className="round">
|
||||
<div className="round-label">Halbfinale</div>
|
||||
<div className="round-matches">
|
||||
{sf.map((t) => <Tie key={t.matchNumber} tie={t} teams={teams} />)}
|
||||
{sf.map((t) => <Tie key={t.matchNumber} tie={t} teams={teams} onShowTip={showTip} onHideTip={hideTip} />)}
|
||||
</div>
|
||||
</div>
|
||||
<div className="round">
|
||||
<div className="round-label">Finale</div>
|
||||
<div className="round-matches">
|
||||
{fin && <Tie tie={fin} teams={teams} isFinal />}
|
||||
{fin && <Tie tie={fin} teams={teams} isFinal onShowTip={showTip} onHideTip={hideTip} />}
|
||||
{third && (
|
||||
<div style={{ marginTop: 20 }}>
|
||||
<div className="round-label" style={{ marginBottom: 8 }}>Spiel um Platz 3</div>
|
||||
<Tie tie={third} teams={teams} />
|
||||
<Tie tie={third} teams={teams} onShowTip={showTip} onHideTip={hideTip} />
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
@@ -131,6 +151,12 @@ export default function Bracket({
|
||||
<span><i style={{ background: "var(--ink-faint)" }} />Platzhalter offen</span>
|
||||
<span>%-Werte: Polymarket-Wahrscheinlichkeit (falls verfügbar)</span>
|
||||
</div>
|
||||
|
||||
{tip && (
|
||||
<div className="kobaum-tip" style={{ left: tip.x + 12, top: tip.y + 12 }}>
|
||||
{tip.text}
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user