From 80929e7fed436c6cdad29c392fa33ba8db7bca46 Mon Sep 17 00:00:00 2001 From: Tim Date: Tue, 7 Jul 2026 00:21:34 +0200 Subject: [PATCH] Skore: scrollovatelny zoznam s collapse serii, zrusenie preciarkavania Standings.tsx rozdeleny na fixnu hlavicku, scrollovatelny zoznam kol (overflow-y-auto, na mobile max-h-45vh) a fixne sucty, takze pri viacerych odohratych kolach je vidno cely priebeh. Dokoncena seria (riadok Sigma) je teraz klikatelna a zbaluje/rozbaluje svoje kola. Zaroven zruseny line-through pri neuspesnom tipe v hernom pohlade aj v detaile hry (History.tsx) -- neuspesny tip sa teraz len zobrazuje tlmenou farbou. --- frontend/src/components/Standings.tsx | 147 +++++++++++++++----------- frontend/src/pages/History.tsx | 2 +- 2 files changed, 86 insertions(+), 63 deletions(-) diff --git a/frontend/src/components/Standings.tsx b/frontend/src/components/Standings.tsx index a804ed3..fdf4c07 100644 --- a/frontend/src/components/Standings.tsx +++ b/frontend/src/components/Standings.tsx @@ -14,6 +14,15 @@ interface Props { export default function Standings({ standings, guesses = [], players, myOrder, desktop = false }: Props) { const [open, setOpen] = useState(false); + // Finished series (8/8 rounds) collapsed to just their Σ row; toggled per series. + const [collapsedSeries, setCollapsedSeries] = useState>(new Set()); + const toggleSeries = (si: number) => + setCollapsedSeries((prev) => { + const next = new Set(prev); + if (next.has(si)) next.delete(si); + else next.add(si); + return next; + }); // Player columns in seat order; the local player's column is highlighted. const cols = [...players].sort((a, b) => a.order - b.order); @@ -39,13 +48,11 @@ export default function Standings({ standings, guesses = [], players, myOrder, d total: desktop ? 20 : 18, }; - const table = ( -
- {/* Column headers */} -
+ const gridCols = { gridTemplateColumns: `28px repeat(${cols.length}, 1fr)` }; + + const columnHeader = ( +
+
{cols.map((p) => (
))}
-
+
+
+ ); - {/* Completed rounds, grouped by series with a per-series summary row */} - {standings.flatMap((seriesRounds, si) => { - const priorRounds = seriesRoundOffsets[si]; - const elems = seriesRounds.map((scores, lri) => ( -
+ // Completed rounds, grouped by series with a per-series summary row. Finished + // series can be collapsed to just their Σ row so long games stay scannable. + const rows = standings.flatMap((seriesRounds, si) => { + const priorRounds = seriesRoundOffsets[si]; + const isFinished = seriesRounds.length === ROUNDS_PER_SERIES; + const isCollapsed = isFinished && collapsedSeries.has(si); + const elems = isCollapsed + ? [] + : seriesRounds.map((scores, lri) => ( +
{priorRounds + lri + 1}
{cols.map((p) => { const points = scores[p.order] ?? 0; - // Failed tip (0 points) → show the struck-through tip instead of 0. + // Failed tip → show the tip in the dimmer "0 points" color, no strikethrough. if (points === 0) { return (
{guesses[si]?.[lri]?.[p.order] ?? 0} @@ -100,56 +110,61 @@ export default function Standings({ standings, guesses = [], players, myOrder, d
)); - // After a finished series, sum its points per player. - if (seriesRounds.length === ROUNDS_PER_SERIES) { - elems.push( -
-
- Σ{si + 1} + // After a finished series, sum its points per player. Clicking toggles + // whether that series' individual rounds are shown. + if (isFinished) { + elems.push( +
toggleSeries(si)} + onKeyDown={(e) => (e.key === 'Enter' || e.key === ' ') && toggleSeries(si)} + className="grid items-center py-1 my-0.5 rounded bg-gold/[.07] cursor-pointer select-none" + style={gridCols} + > +
+ {isCollapsed ? '▸' : '▾'} + Σ{si + 1} +
+ {cols.map((p) => { + const sum = seriesRounds.reduce((a, r) => a + (r[p.order] ?? 0), 0); + return ( +
+ {sum}
- {cols.map((p) => { - const sum = seriesRounds.reduce((a, r) => a + (r[p.order] ?? 0), 0); - return ( -
- {sum} -
- ); - })} -
, - ); - } - return elems; - })} + ); + })} +
, + ); + } + return elems; + }); + + const scrollableRounds = ( +
+ {rows} {/* Active round placeholder */} -
+
{completedRounds + 1}
{cols.map((p) => (
·
))}
+
+ ); -
+ const totalsBlock = ( +
- - {/* Totals */} -
+
Σ
@@ -168,13 +183,21 @@ export default function Standings({ standings, guesses = [], players, myOrder, d
); + const content = ( +
+ {columnHeader} + {scrollableRounds} + {totalsBlock} +
+ ); + if (desktop) { return ( ); } @@ -189,7 +212,7 @@ export default function Standings({ standings, guesses = [], players, myOrder, d Skóre {open ? '▲' : '▼'} - {open && table} + {open && content}
); } diff --git a/frontend/src/pages/History.tsx b/frontend/src/pages/History.tsx index f50b561..8c610c5 100644 --- a/frontend/src/pages/History.tsx +++ b/frontend/src/pages/History.tsx @@ -128,7 +128,7 @@ function GameDetailView({ detail, onBack }: { detail: GameDetail; onBack: () => return r.won ? ( {r.points} ) : ( - {r.guess} + {r.guess} ); }; const seriesTotal = (s: number | undefined, seat: number) =>