63 lines
1.7 KiB
TypeScript
63 lines
1.7 KiB
TypeScript
import React, { useMemo } from "react";
|
|
import BracketView from "@/features/bracket/components/bracket-view";
|
|
import { groupMatchesIntoBracket } from "@/features/bracket/utils/group";
|
|
import { Match } from "@/features/matches/types";
|
|
import { PicksMap } from "../types";
|
|
import { PickResult, resolvePredictedBracket } from "../utils";
|
|
import { PredictionMatchCard } from "./prediction-match-card";
|
|
|
|
interface PredictionBracketProps {
|
|
matches: Match[];
|
|
picks: PicksMap;
|
|
mode: "edit" | "view";
|
|
perMatch?: Map<number, PickResult>;
|
|
activeLid?: number;
|
|
onActivate?: (lid: number) => void;
|
|
}
|
|
|
|
export const PredictionBracket: React.FC<PredictionBracketProps> = ({
|
|
matches,
|
|
picks,
|
|
mode,
|
|
perMatch,
|
|
activeLid,
|
|
onActivate,
|
|
}) => {
|
|
const bracket = useMemo(() => groupMatchesIntoBracket(matches), [matches]);
|
|
|
|
const resolved = useMemo(
|
|
() => resolvePredictedBracket(matches, picks),
|
|
[matches, picks]
|
|
);
|
|
|
|
const orders = useMemo(() => {
|
|
const map: Record<number, number> = {};
|
|
bracket.winners.flat().forEach((match) => (map[match.lid] = match.order));
|
|
bracket.losers.flat().forEach((match) => (map[match.lid] = match.order));
|
|
return map;
|
|
}, [bracket]);
|
|
|
|
return (
|
|
<BracketView
|
|
bracket={bracket}
|
|
bottomOffset={110}
|
|
renderMatch={(match) => (
|
|
<PredictionMatchCard
|
|
match={match}
|
|
resolved={resolved.get(match.lid)}
|
|
orders={orders}
|
|
mode={mode}
|
|
result={perMatch?.get(match.lid)}
|
|
active={activeLid === match.lid}
|
|
onActivate={
|
|
onActivate &&
|
|
(!match.reset || resolved.get(match.lid)?.resetNecessary)
|
|
? () => onActivate(match.lid)
|
|
: undefined
|
|
}
|
|
/>
|
|
)}
|
|
/>
|
|
);
|
|
};
|