From 91213d354f638e9497c61e123834e4ff77574f1a Mon Sep 17 00:00:00 2001 From: MrEgosar Date: Mon, 26 Oct 2026 00:15:37 +0100 Subject: [PATCH] =?UTF-8?q?Stream-=C3=9Cbersicht:=20Matches=20anklickbar,?= =?UTF-8?q?=20Einzelansicht=20pro=20Match?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Karten und Listeneinträge der Stream-Übersicht führen zur Übersicht des jeweiligen Matches (/stream/match/:matchId). Der Zuschauercode bleibt geheim, daher wird nur die Match-ID verlinkt. --- client/src/App.jsx | 1 + client/src/pages/StreamOverviewPage.jsx | 48 +++++++++++++++++++------ client/src/stream-overview.css | 6 ++++ 3 files changed, 44 insertions(+), 11 deletions(-) diff --git a/client/src/App.jsx b/client/src/App.jsx index 7fb403c..0247fea 100644 --- a/client/src/App.jsx +++ b/client/src/App.jsx @@ -14,6 +14,7 @@ export default function App() { {/* Stream-Übersicht ohne Kopfzeile, als Vollbild bzw. OBS-Browserquelle */} } /> + } /> } /> } /> diff --git a/client/src/pages/StreamOverviewPage.jsx b/client/src/pages/StreamOverviewPage.jsx index 3353b79..cc1f6c0 100644 --- a/client/src/pages/StreamOverviewPage.jsx +++ b/client/src/pages/StreamOverviewPage.jsx @@ -1,4 +1,5 @@ import { useEffect, useState } from 'react'; +import { useParams } from 'react-router-dom'; import { api } from '../lib/api.js'; import { FORMAT_LABEL } from '../lib/labels.js'; import { getSocket } from '../lib/useMatch.js'; @@ -14,11 +15,13 @@ const PAGE_SECONDS = 12; /** * Stream-Übersicht aller laufenden Vetos und Matches: /stream * Mit STREAM_KEY: /stream?key=. Optional ?bg=transparent. + * Ein einzelnes Match: /stream/match/, daraus führen die Karten der Übersicht. */ export default function StreamOverviewPage() { const params = new URLSearchParams(window.location.search); const key = params.get('key') ?? ''; const transparent = params.get('bg') === 'transparent'; + const { matchId } = useParams(); const { data, error } = useStreamOverview(key); const now = useClock(); const [page, setPage] = useState(0); @@ -29,8 +32,10 @@ export default function StreamOverviewPage() { return () => document.documentElement.classList.remove('stream-mode', 'stream-transparent'); }, [transparent]); + const activeMatches = (data?.active ?? []).filter((m) => !matchId || m.id === matchId); + // Mehr Matches als auf eine Seite passen: automatisch weiterblättern - const pages = data ? Math.max(1, Math.ceil(data.active.length / PER_PAGE)) : 1; + const pages = Math.max(1, Math.ceil(activeMatches.length / PER_PAGE)); useEffect(() => { if (pages <= 1) { setPage(0); return undefined; } const t = setInterval(() => setPage((p) => (p + 1) % pages), PAGE_SECONDS * 1000); @@ -49,7 +54,7 @@ export default function StreamOverviewPage() { ); } - const active = data?.active ?? []; + const active = activeMatches; const shown = active.slice(page * PER_PAGE, page * PER_PAGE + PER_PAGE); const liveCount = active.filter((m) => m.status === 'live').length; const vetoCount = active.filter((m) => m.status === 'veto').length; @@ -73,11 +78,24 @@ export default function StreamOverviewPage() { {!data &&
Lade Matches …
} {data && shown.length === 0 && (
-

Gerade läuft kein Match

-

{data.upcoming.length ? 'Die nächsten Lobbys stehen unten.' : 'Sobald ein Veto beginnt, erscheint es hier.'}

+ {matchId ? ( + <> +

Dieses Match läuft gerade nicht

+

Es erscheint hier, sobald das Veto oder das Match beginnt.

+ + ) : ( + <> +

Gerade läuft kein Match

+

{data.upcoming.length ? 'Die nächsten Lobbys stehen unten.' : 'Sobald ein Veto beginnt, erscheint es hier.'}

+ + )}
)} - {shown.map((m) => )} + {shown.map((m) => ( + + + + ))}