From 770d0ff79be1d4a585b88d6cad8b1d4406412ad4 Mon Sep 17 00:00:00 2001 From: Soren Zaiser Date: Thu, 28 Mar 2024 20:44:48 -0400 Subject: [PATCH 01/17] Add clock, fix some formatting for pre-event stuff --- .../MultiDisplay/EventRow/index.tsx | 56 +++++++++++++------ .../MultiDisplay/EventRow/styles.module.scss | 11 ++-- src/components/MultiDisplay/index.tsx | 17 +++++- 3 files changed, 59 insertions(+), 25 deletions(-) diff --git a/src/components/MultiDisplay/EventRow/index.tsx b/src/components/MultiDisplay/EventRow/index.tsx index ba4394c..386f124 100644 --- a/src/components/MultiDisplay/EventRow/index.tsx +++ b/src/components/MultiDisplay/EventRow/index.tsx @@ -148,20 +148,42 @@ const EventRow = ({ return `${match.participants.Blue1} ${match.participants.Blue2} ${match.participants.Blue3}`; }; - return ( - <> - {loadingState === 'loading' && ( -
Loading matches...
- )} - {loadingState === 'error' && ( -
Failed to fetch matches
- )} - {loadingState === 'ready' && !qualMatches?.length && ( -
- Waiting for schedule to be posted... -
- )} - {loadingState === 'ready' && qualMatches?.length !== 0 && ( + if (loadingState === 'ready' && (qualMatches?.length ?? 0) < 1) { + return ( + + + {event && event.name && ( + {event.name}
+ )} + Waiting for schedule to be posted... + + + ) + } else if (loadingState === 'loading') { + return ( + + + {event && event.name && ( + {event.name}
+ )} + Loading matches... + + + ) + } else if (loadingState === 'error') { + return ( + + + {event && event.name && ( + {event.name}
+ )} + Failed to fetch matches + + + ) + } else if (loadingState === 'ready' && qualMatches?.length !== 0) { + return ( + <> {/* Sponsor Logo */} @@ -211,9 +233,9 @@ const EventRow = ({ ))} - )} - - ); + + ); + } }; export default EventRow; diff --git a/src/components/MultiDisplay/EventRow/styles.module.scss b/src/components/MultiDisplay/EventRow/styles.module.scss index cef1809..cd44e3b 100644 --- a/src/components/MultiDisplay/EventRow/styles.module.scss +++ b/src/components/MultiDisplay/EventRow/styles.module.scss @@ -3,7 +3,11 @@ $border-color: #fafafa; tr { - color: #fafafa; + color: #fafafa !important; +} + +tbody > tr { + height: 22vh; } hr { @@ -13,11 +17,6 @@ hr { border-width: 3px; } -.infoText { - padding-top: 2em; - text-align: center; -} - .textCenter { text-align: center; } diff --git a/src/components/MultiDisplay/index.tsx b/src/components/MultiDisplay/index.tsx index 6ec1bc4..bf2bd66 100644 --- a/src/components/MultiDisplay/index.tsx +++ b/src/components/MultiDisplay/index.tsx @@ -8,14 +8,27 @@ const MultiQueueing = () => { const events = searchParams.getAll('e'); const season = searchParams.get('s') ?? new Date().getFullYear().toString(); + const calcClock = (): string => { + const now = new Date(); + const str = now.toLocaleString('en-US', { hour: 'numeric', minute: '2-digit', hour12: true }) + return str; + } + const [showLine, setShowLine] = useState<0 | 1>(0); + const [clock, setClock] = useState(calcClock()); useEffect(() => { const interval = setInterval(() => { setShowLine((sl: 0 | 1) => (sl === 0 ? 1 : 0)); }, 5000); - return () => clearInterval(interval); + const clockInterval = setInterval(() => setClock(calcClock()), 60000) + calcClock(); + + return () => { + clearInterval(interval); + clearInterval(clockInterval); + } }, []); return ( @@ -23,7 +36,7 @@ const MultiQueueing = () => { - + From b61e2c8fd05682061e3f22e96eebc999ebb6b115 Mon Sep 17 00:00:00 2001 From: Soren Zaiser Date: Fri, 29 Mar 2024 08:31:23 -0400 Subject: [PATCH 02/17] Gail Updates --- .../MultiDisplay/EventRow/index.tsx | 14 ++++++++----- .../MultiDisplay/EventRow/styles.module.scss | 21 ++++++++++++++++--- src/components/MultiDisplay/index.tsx | 4 ++-- 3 files changed, 29 insertions(+), 10 deletions(-) diff --git a/src/components/MultiDisplay/EventRow/index.tsx b/src/components/MultiDisplay/EventRow/index.tsx index 386f124..a02e818 100644 --- a/src/components/MultiDisplay/EventRow/index.tsx +++ b/src/components/MultiDisplay/EventRow/index.tsx @@ -202,11 +202,13 @@ const EventRow = ({ {nextMatch && ( {nextMatch?.number} - + + + )} @@ -235,6 +237,8 @@ const EventRow = ({ ); + } else { + return null; } }; diff --git a/src/components/MultiDisplay/EventRow/styles.module.scss b/src/components/MultiDisplay/EventRow/styles.module.scss index cd44e3b..e4b516d 100644 --- a/src/components/MultiDisplay/EventRow/styles.module.scss +++ b/src/components/MultiDisplay/EventRow/styles.module.scss @@ -1,5 +1,9 @@ $border-color: #fafafa; +$teamlist-size: 5.5vh; +$matchnumber-size: 18vh; + +$cell-vertical-negative: -3vh; tr { @@ -23,13 +27,22 @@ hr { .matchNumber { text-align: center; - font-size: 10vh; + font-size: $matchnumber-size; font-weight: bold; + position: relative; + top: $cell-vertical-negative; + line-height: 0.8; +} + +.nextMatchScroll { + position: relative; + top: $cell-vertical-negative; } .flexRow { display: flex; flex-direction: row; + font-size: $teamlist-size; } .sponsorLogo { @@ -48,13 +61,15 @@ hr { text-align: center; width: 30vw; font-weight: bold; + border-radius: 1em; + font-size: $teamlist-size; } } .red { - color: red; + background: rgba(255, 0, 0, .5); } .blue { - color: #5454ff; + background: rgba(84, 84, 255, .5); } diff --git a/src/components/MultiDisplay/index.tsx b/src/components/MultiDisplay/index.tsx index bf2bd66..58a38d1 100644 --- a/src/components/MultiDisplay/index.tsx +++ b/src/components/MultiDisplay/index.tsx @@ -37,8 +37,8 @@ const MultiQueueing = () => { - - + + From db7296ad8cafce443079a07b5e2c74bd7121124e Mon Sep 17 00:00:00 2001 From: Soren Zaiser Date: Fri, 29 Mar 2024 09:29:33 -0400 Subject: [PATCH 03/17] Linting, more styling --- .../MultiDisplay/EventRow/index.tsx | 31 +++++++++++++------ .../MultiDisplay/EventRow/styles.module.scss | 7 ----- src/components/MultiDisplay/index.tsx | 14 ++++----- .../MultiDisplay/styles.module.scss | 9 ++++++ 4 files changed, 38 insertions(+), 23 deletions(-) diff --git a/src/components/MultiDisplay/EventRow/index.tsx b/src/components/MultiDisplay/EventRow/index.tsx index a02e818..f88d8d1 100644 --- a/src/components/MultiDisplay/EventRow/index.tsx +++ b/src/components/MultiDisplay/EventRow/index.tsx @@ -132,22 +132,26 @@ const EventRow = ({ } }; + // On event change, check for matches useEffect(() => { if (event) updateMatches(event); }, [event.currentMatchNumber, qualMatches]); const { currentMatch, nextMatch, queueingMatches } = displayMatches; + // Calculate Red alliance string const getRedStr = (match: QualMatch | null): string => { if (!match) return ''; return `${match.participants.Red1} ${match.participants.Red2} ${match.participants.Red3}`; }; + // Calculate Blue alliance string const getBlueStr = (match: QualMatch | null): string => { if (!match) return ''; return `${match.participants.Blue1} ${match.participants.Blue2} ${match.participants.Blue3}`; }; + // Ready w/ no matches if (loadingState === 'ready' && (qualMatches?.length ?? 0) < 1) { return ( @@ -158,8 +162,11 @@ const EventRow = ({ Waiting for schedule to be posted... - ) - } else if (loadingState === 'loading') { + ); + } + + // Loading + if (loadingState === 'loading') { return ( - ) - } else if (loadingState === 'error') { + ); + } + + // Error + if (loadingState === 'error') { return ( + - ) - } else if (loadingState === 'ready' && qualMatches?.length !== 0) { + ); + } + + // Ready and we have matches + if (loadingState === 'ready' && qualMatches?.length !== 0) { return ( <> @@ -237,9 +250,9 @@ const EventRow = ({ ); - } else { - return null; } + + return null; }; export default EventRow; diff --git a/src/components/MultiDisplay/EventRow/styles.module.scss b/src/components/MultiDisplay/EventRow/styles.module.scss index e4b516d..263fee9 100644 --- a/src/components/MultiDisplay/EventRow/styles.module.scss +++ b/src/components/MultiDisplay/EventRow/styles.module.scss @@ -14,13 +14,6 @@ tbody > tr { height: 22vh; } -hr { - margin: 0; - position: absolute; - width: 99%; - border-width: 3px; -} - .textCenter { text-align: center; } diff --git a/src/components/MultiDisplay/index.tsx b/src/components/MultiDisplay/index.tsx index 58a38d1..92a35a4 100644 --- a/src/components/MultiDisplay/index.tsx +++ b/src/components/MultiDisplay/index.tsx @@ -10,9 +10,9 @@ const MultiQueueing = () => { const calcClock = (): string => { const now = new Date(); - const str = now.toLocaleString('en-US', { hour: 'numeric', minute: '2-digit', hour12: true }) + const str = now.toLocaleString('en-US', { hour: 'numeric', minute: '2-digit', hour12: true }); return str; - } + }; const [showLine, setShowLine] = useState<0 | 1>(0); const [clock, setClock] = useState(calcClock()); @@ -22,13 +22,13 @@ const MultiQueueing = () => { setShowLine((sl: 0 | 1) => (sl === 0 ? 1 : 0)); }, 5000); - const clockInterval = setInterval(() => setClock(calcClock()), 60000) + const clockInterval = setInterval(() => setClock(calcClock()), 60000); calcClock(); return () => { clearInterval(interval); clearInterval(clockInterval); - } + }; }, []); return ( @@ -36,10 +36,10 @@ const MultiQueueing = () => {
Field{clock} Current Match Next Match Queueing Matches
{clock}Current MatchNext MatchOn FieldNext Match Queueing Matches
@@ -169,8 +176,11 @@ const EventRow = ({ Loading matches...
@@ -178,10 +188,13 @@ const EventRow = ({ {event.name}
)} Failed to fetch matches -
- + - - + + diff --git a/src/components/MultiDisplay/styles.module.scss b/src/components/MultiDisplay/styles.module.scss index c9bb988..dbaa9f5 100644 --- a/src/components/MultiDisplay/styles.module.scss +++ b/src/components/MultiDisplay/styles.module.scss @@ -8,4 +8,13 @@ $border-color: #222; left: 0; height: 100vh; width: 100vw; + overflow: hidden; +} + +hr { + margin: 0; + position: absolute; + width: 100vw; + border-width: 3px; + border: 3px solid white; } From faafb0596ab39f88bea738a0c663daf52c0f6495 Mon Sep 17 00:00:00 2001 From: Soren Zaiser Date: Fri, 29 Mar 2024 09:32:28 -0400 Subject: [PATCH 04/17] Hot patch --- src/components/MultiDisplay/EventRow/index.tsx | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/src/components/MultiDisplay/EventRow/index.tsx b/src/components/MultiDisplay/EventRow/index.tsx index f88d8d1..48ce6e3 100644 --- a/src/components/MultiDisplay/EventRow/index.tsx +++ b/src/components/MultiDisplay/EventRow/index.tsx @@ -5,6 +5,7 @@ import { ref, onValue, off, + update, } from 'firebase/database'; import { useEffect, useState, useRef } from 'preact/hooks'; import { QualMatch, Event } from '@shared/DbTypes'; @@ -97,11 +98,11 @@ const EventRow = ({ if (matchNumber === null || matchNumber === undefined) { if (dbEventRef.current === undefined) return; // throw new Error('No event ref'); - // update(dbEventRef.current, { - // currentMatchNumber: 1, - // }).catch((e) => { - // console.error(e); - // }); + update(dbEventRef.current, { + currentMatchNumber: 1, + }).catch((err) => { + console.error(err); + }); return; } From 389927d051e609ab8003963e1e220e7ef32aef2c Mon Sep 17 00:00:00 2001 From: Soren Zaiser Date: Fri, 29 Mar 2024 10:44:33 -0400 Subject: [PATCH 05/17] More Styling --- src/components/MultiDisplay/EventRow/styles.module.scss | 9 ++++++++- src/components/MultiDisplay/index.tsx | 8 ++++---- 2 files changed, 12 insertions(+), 5 deletions(-) diff --git a/src/components/MultiDisplay/EventRow/styles.module.scss b/src/components/MultiDisplay/EventRow/styles.module.scss index 263fee9..d5e64e8 100644 --- a/src/components/MultiDisplay/EventRow/styles.module.scss +++ b/src/components/MultiDisplay/EventRow/styles.module.scss @@ -39,8 +39,15 @@ tbody > tr { } .sponsorLogo { - width: 14vw; + display: block; + margin-top: 1vh; + margin-bottom: 1vh; + margin-left: auto; + margin-right: auto; + width: auto; height: auto; + max-width: 15vw; + max-height: 15vh; } .bold { diff --git a/src/components/MultiDisplay/index.tsx b/src/components/MultiDisplay/index.tsx index 92a35a4..ad69874 100644 --- a/src/components/MultiDisplay/index.tsx +++ b/src/components/MultiDisplay/index.tsx @@ -36,10 +36,10 @@ const MultiQueueing = () => {
{clock}{clock} On FieldNext MatchQueueing MatchesNext MatchQueueing Matches
- - - - + + + + From a6a16b6e624bf9776c98f78149665a575cec152f Mon Sep 17 00:00:00 2001 From: Soren Zaiser Date: Fri, 29 Mar 2024 19:48:08 -0400 Subject: [PATCH 06/17] Refactoring --- .../EventRow/AllianceFader/index.tsx | 33 +++++++++++++ .../EventRow/AllianceFader/styles.module.scss | 22 +++++++++ .../MultiDisplay/EventRow/index.tsx | 47 +++++-------------- .../MultiDisplay/EventRow/styles.module.scss | 20 -------- 4 files changed, 66 insertions(+), 56 deletions(-) create mode 100644 src/components/MultiDisplay/EventRow/AllianceFader/index.tsx create mode 100644 src/components/MultiDisplay/EventRow/AllianceFader/styles.module.scss diff --git a/src/components/MultiDisplay/EventRow/AllianceFader/index.tsx b/src/components/MultiDisplay/EventRow/AllianceFader/index.tsx new file mode 100644 index 0000000..a9abf4a --- /dev/null +++ b/src/components/MultiDisplay/EventRow/AllianceFader/index.tsx @@ -0,0 +1,33 @@ +import { h } from 'preact'; +import styles from './styles.module.scss'; + +const AllianceFader = ({ + red, + blue, + showLine, +}: { + red: string; + blue: string; + showLine: 0 | 1; +}) => ( +
+
+ R: {red} +
+
+ B: {blue} +
+
+); + +export default AllianceFader; diff --git a/src/components/MultiDisplay/EventRow/AllianceFader/styles.module.scss b/src/components/MultiDisplay/EventRow/AllianceFader/styles.module.scss new file mode 100644 index 0000000..0b045df --- /dev/null +++ b/src/components/MultiDisplay/EventRow/AllianceFader/styles.module.scss @@ -0,0 +1,22 @@ + +$teamlist-size: 5.5vh; + +.faderBase { + &> div { + position: absolute; + transition: all ease .5s; + text-align: center; + width: 30vw; + font-weight: bold; + border-radius: 1em; + font-size: $teamlist-size; + } +} + +.red { + background: rgba(255, 0, 0, .5); +} + +.blue { + background: rgba(84, 84, 255, .5); +} \ No newline at end of file diff --git a/src/components/MultiDisplay/EventRow/index.tsx b/src/components/MultiDisplay/EventRow/index.tsx index 48ce6e3..de926d6 100644 --- a/src/components/MultiDisplay/EventRow/index.tsx +++ b/src/components/MultiDisplay/EventRow/index.tsx @@ -10,37 +10,15 @@ import { import { useEffect, useState, useRef } from 'preact/hooks'; import { QualMatch, Event } from '@shared/DbTypes'; import styles from './styles.module.scss'; +import AllianceFader from './AllianceFader'; type LoadingState = 'loading' | 'ready' | 'error' | 'noAutomatic'; -const TextFader = ({ - red, - blue, - showLine, -}: { - red: string; - blue: string; - showLine: 0 | 1; -}) => ( -
-
- R: {red} -
-
- B: {blue} -
-
-); +type MatchData = { + currentMatch: QualMatch | null; + nextMatch: QualMatch | null; + queueingMatches: QualMatch[]; +}; const EventRow = ({ token, @@ -64,11 +42,8 @@ const EventRow = ({ const [qualMatches, setQualMatches] = useState([]); // Matches to display - const [displayMatches, setDisplayMatches] = useState<{ - currentMatch: QualMatch | null; - nextMatch: QualMatch | null; - queueingMatches: QualMatch[]; - }>({ currentMatch: null, nextMatch: null, queueingMatches: [] }); + // eslint-disable-next-line max-len + const [displayMatches, setDisplayMatches] = useState({ currentMatch: null, nextMatch: null, queueingMatches: [] }); useEffect(() => { if (!token) return () => { }; @@ -123,7 +98,7 @@ const EventRow = ({ queueingMatches: toFill .map((x) => getMatchByNumber(matchNumber + x)) .filter((x) => x !== null) as QualMatch[], - }; + }; setDisplayMatches(data); setLoadingState('ready'); @@ -217,7 +192,7 @@ const EventRow = ({ {nextMatch?.number} - {x.number} - - tr { .bold { font-weight: bold; } - -.faderBase { - &> div { - position: absolute; - transition: all ease .5s; - text-align: center; - width: 30vw; - font-weight: bold; - border-radius: 1em; - font-size: $teamlist-size; - } -} - -.red { - background: rgba(255, 0, 0, .5); -} - -.blue { - background: rgba(84, 84, 255, .5); -} From 24c6fac4d824c06bdba3b26cc32e9eb9c2fe92f3 Mon Sep 17 00:00:00 2001 From: Soren Zaiser Date: Fri, 29 Mar 2024 19:48:15 -0400 Subject: [PATCH 07/17] Linting --- src/components/MultiDisplay/EventRow/index.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/components/MultiDisplay/EventRow/index.tsx b/src/components/MultiDisplay/EventRow/index.tsx index de926d6..ffff498 100644 --- a/src/components/MultiDisplay/EventRow/index.tsx +++ b/src/components/MultiDisplay/EventRow/index.tsx @@ -98,7 +98,7 @@ const EventRow = ({ queueingMatches: toFill .map((x) => getMatchByNumber(matchNumber + x)) .filter((x) => x !== null) as QualMatch[], - }; + }; setDisplayMatches(data); setLoadingState('ready'); From a1f5545ded14099fa4283a49de959d4bcd0cfa71 Mon Sep 17 00:00:00 2001 From: Soren Zaiser Date: Sat, 30 Mar 2024 09:08:55 -0400 Subject: [PATCH 08/17] Support Breaks --- .../MultiDisplay/EventRow/index.tsx | 143 +++++++++++++----- .../MultiDisplay/EventRow/styles.module.scss | 1 + 2 files changed, 105 insertions(+), 39 deletions(-) diff --git a/src/components/MultiDisplay/EventRow/index.tsx b/src/components/MultiDisplay/EventRow/index.tsx index ffff498..015060c 100644 --- a/src/components/MultiDisplay/EventRow/index.tsx +++ b/src/components/MultiDisplay/EventRow/index.tsx @@ -5,7 +5,7 @@ import { ref, onValue, off, - update, + // update, } from 'firebase/database'; import { useEffect, useState, useRef } from 'preact/hooks'; import { QualMatch, Event } from '@shared/DbTypes'; @@ -14,10 +14,18 @@ import AllianceFader from './AllianceFader'; type LoadingState = 'loading' | 'ready' | 'error' | 'noAutomatic'; +type Break = { + after: number, + level: 'qual', + message: string +}; + +type MatchOrBreak = QualMatch | Break | null; + type MatchData = { - currentMatch: QualMatch | null; - nextMatch: QualMatch | null; - queueingMatches: QualMatch[]; + currentMatch: MatchOrBreak | null; + nextMatch: MatchOrBreak | null; + queueingMatches: MatchOrBreak[]; }; const EventRow = ({ @@ -41,6 +49,9 @@ const EventRow = ({ // This row's matches const [qualMatches, setQualMatches] = useState([]); + // This row's breaks + const [breaks, setBreaks] = useState([]); + // Matches to display // eslint-disable-next-line max-len const [displayMatches, setDisplayMatches] = useState({ currentMatch: null, nextMatch: null, queueingMatches: [] }); @@ -59,6 +70,11 @@ const EventRow = ({ setQualMatches(snap.val() as QualMatch[]); }); + const breaksRef = ref(getDatabase(), `/seasons/${season}/breaks/${token}`); + onValue(breaksRef, (snap) => { + setBreaks(snap.val() as Break[]); + }); + return () => { off(matchesRef); off(eventRef); @@ -73,11 +89,11 @@ const EventRow = ({ if (matchNumber === null || matchNumber === undefined) { if (dbEventRef.current === undefined) return; // throw new Error('No event ref'); - update(dbEventRef.current, { - currentMatchNumber: 1, - }).catch((err) => { - console.error(err); - }); + // update(dbEventRef.current, { + // currentMatchNumber: 1, + // }).catch((err) => { + // console.error(err); + // }); return; } @@ -91,14 +107,37 @@ const EventRow = ({ toFill[i] = i + 2; }); - const data = { - currentMatch: getMatchByNumber(matchNumber), - nextMatch: getMatchByNumber(matchNumber + 1), - // By default, we'll take the three matches after the one on deck - queueingMatches: toFill + // Upcoming matches + const upcoming: MatchOrBreak[] = [ + getMatchByNumber(matchNumber), + getMatchByNumber(matchNumber + 1), + ].concat( // Add Queueing Matches + toFill .map((x) => getMatchByNumber(matchNumber + x)) .filter((x) => x !== null) as QualMatch[], - }; + ); + + // See if there is an upcoming break + breaks.forEach((b: Break) => { + // See if break start is inside what we're showing + if (b.after < (matchNumber + upcoming.length)) { + // Calculate the insert location + const insertAt = b.after - matchNumber; + // Sanity + if (insertAt < 0) return; + // Insert break + upcoming.splice(insertAt, 0, b); + // Remove one from the end + upcoming.pop(); + } + }); + + const data = { + currentMatch: upcoming[0], + nextMatch: upcoming[1], + // By default, we'll take the three matches after the one on deck + queueingMatches: upcoming.slice(2), + } as MatchData; setDisplayMatches(data); setLoadingState('ready'); @@ -111,7 +150,7 @@ const EventRow = ({ // On event change, check for matches useEffect(() => { if (event) updateMatches(event); - }, [event.currentMatchNumber, qualMatches]); + }, [event.currentMatchNumber, qualMatches, breaks]); const { currentMatch, nextMatch, queueingMatches } = displayMatches; @@ -184,44 +223,70 @@ const EventRow = ({ {/* Current Match */} -
+ { currentMatch && (currentMatch as QualMatch)?.number && ( + + )} + + {/* Current Match is Break */} + { currentMatch && (currentMatch as Break)?.message && ( + + )} {/* Next Match */} {/* Queueing Matches */} diff --git a/src/components/MultiDisplay/EventRow/styles.module.scss b/src/components/MultiDisplay/EventRow/styles.module.scss index 1c1e8e5..374ebc1 100644 --- a/src/components/MultiDisplay/EventRow/styles.module.scss +++ b/src/components/MultiDisplay/EventRow/styles.module.scss @@ -36,6 +36,7 @@ tbody > tr { display: flex; flex-direction: row; font-size: $teamlist-size; + margin-bottom: 3px; } .sponsorLogo { From 8e0de18ed8597f60be8be85c6d631f57935483aa Mon Sep 17 00:00:00 2001 From: Soren Zaiser Date: Sat, 30 Mar 2024 09:11:29 -0400 Subject: [PATCH 09/17] Catch if no breaks exist --- src/components/MultiDisplay/EventRow/index.tsx | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/components/MultiDisplay/EventRow/index.tsx b/src/components/MultiDisplay/EventRow/index.tsx index 015060c..d2f24a7 100644 --- a/src/components/MultiDisplay/EventRow/index.tsx +++ b/src/components/MultiDisplay/EventRow/index.tsx @@ -118,7 +118,7 @@ const EventRow = ({ ); // See if there is an upcoming break - breaks.forEach((b: Break) => { + breaks?.forEach((b: Break) => { // See if break start is inside what we're showing if (b.after < (matchNumber + upcoming.length)) { // Calculate the insert location @@ -135,7 +135,6 @@ const EventRow = ({ const data = { currentMatch: upcoming[0], nextMatch: upcoming[1], - // By default, we'll take the three matches after the one on deck queueingMatches: upcoming.slice(2), } as MatchData; From 1dfda90fe4c7a2dd5b95c8a7eaa2a83674ed19c2 Mon Sep 17 00:00:00 2001 From: Soren Zaiser Date: Mon, 1 Apr 2024 23:44:16 -0400 Subject: [PATCH 10/17] Gail's requested changes, messages --- .env.example | 12 +- package-lock.json | 46 +++- package.json | 2 + shared/DbTypes.ts | 68 +++--- .../EventRow/AllianceFader/styles.module.scss | 7 + .../MultiDisplay/EventRow/index.tsx | 210 +++++++++++++----- .../MultiDisplay/EventRow/styles.module.scss | 49 +++- src/components/MultiDisplay/index.tsx | 10 +- 8 files changed, 310 insertions(+), 94 deletions(-) diff --git a/.env.example b/.env.example index 5a3c67a..622da9b 100644 --- a/.env.example +++ b/.env.example @@ -1,8 +1,8 @@ # You can update this to suit your local development environment. Match info should be hosted by a different server # since the dev server isn't keen to do it itself -PREACT_APP_RTDB_URL=https://your-rtdb-instance.firebaseio.com/ -PREACT_APP_FIRE_KEY=your-key -PREACT_APP_FIRE_PROJ=your-project -PREACT_APP_FIRE_APPID=your-app-id -PREACT_APP_FIRE_MEASUREID=your-analytics-id -PREACT_APP_SIGNALR_SERVER=https://fim-admin.evandoes.dev # or remove +APP_RTDB_URL=https://your-rtdb-instance.firebaseio.com/ +APP_FIRE_KEY=your-key +APP_FIRE_PROJ=your-project +APP_FIRE_APPID=your-app-id +APP_FIRE_MEASUREID=your-analytics-id +APP_SIGNALR_SERVER=https://fim-admin.evandoes.dev # or remove diff --git a/package-lock.json b/package-lock.json index e7e3028..619523e 100644 --- a/package-lock.json +++ b/package-lock.json @@ -9,6 +9,7 @@ "version": "0.0.0", "license": "MIT", "dependencies": { + "@gmurph91/react-textfit": "^1.1.4", "@microsoft/signalr": "^7.0.7", "@preact/preset-vite": "^2.5.0", "@react-spring/web": "^9.7.3", @@ -30,6 +31,7 @@ "@types/color": "^3.0.3", "@types/js-cookie": "^3.0.3", "@types/react": "^18.2.14", + "@types/react-textfit": "^1.1.4", "@types/styled-components": "^5.1.26", "babel-plugin-module-resolver": "^5.0.0", "dotenv-webpack": "^7.1.0", @@ -3028,6 +3030,19 @@ "resolved": "https://registry.npmjs.org/@gar/promisify/-/promisify-1.1.3.tgz", "integrity": "sha512-k2Ty1JcVojjJFwrg/ThKi2ujJ7XNLYaFGNB/bWT9wGR+oSMJHMa5w+CUq6p/pVrKeNNgA7pCqEcjSnHVoqJQFw==" }, + "node_modules/@gmurph91/react-textfit": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/@gmurph91/react-textfit/-/react-textfit-1.1.4.tgz", + "integrity": "sha512-s0qQAIcYk8OIxTHwplijjXd1R5aPfF5Glb98Nb5970FzikmazZKmpsinOs8bQoi3CdfKCUpLfZ/sSRxvM/h+rw==", + "dependencies": { + "process": "^0.11.10", + "prop-types": "^15.7.2" + }, + "peerDependencies": { + "react": "^15.0.0 || ^16.0.0 || ^17.0.0 || ^18.0.0", + "react-dom": "^15.0.0 || ^16.0.0 || ^17.0.0 || ^18.0.0" + } + }, "node_modules/@grpc/grpc-js": { "version": "1.7.3", "resolved": "https://registry.npmjs.org/@grpc/grpc-js/-/grpc-js-1.7.3.tgz", @@ -5248,6 +5263,15 @@ "csstype": "^3.0.2" } }, + "node_modules/@types/react-textfit": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/@types/react-textfit/-/react-textfit-1.1.4.tgz", + "integrity": "sha512-tj3aMfbzi12r2yWn4Kzm9IkEHz7uaBU57P19FhzEA+Sr+ex0EuJezAYtBRMW3HjxylJ8PtmwpWgPT/t+j0H6zA==", + "dev": true, + "dependencies": { + "@types/react": "*" + } + }, "node_modules/@types/resolve": { "version": "1.17.1", "resolved": "https://registry.npmjs.org/@types/resolve/-/resolve-1.17.1.tgz", @@ -13936,7 +13960,6 @@ "version": "1.4.0", "resolved": "https://registry.npmjs.org/loose-envify/-/loose-envify-1.4.0.tgz", "integrity": "sha512-lyuxPGr/Wfhrlem2CL/UcnUc1zcqKAImBDzukY7Y5F/yQiNdko6+fRLevlw1HgMySw7f611UIY408EtxRSoK3Q==", - "peer": true, "dependencies": { "js-tokens": "^3.0.0 || ^4.0.0" }, @@ -18323,7 +18346,6 @@ "version": "15.8.1", "resolved": "https://registry.npmjs.org/prop-types/-/prop-types-15.8.1.tgz", "integrity": "sha512-oj87CgZICdulUohogVAR7AjlC0327U4el4L6eAvOqCeudMDVU0NThNaV+b9Df4dXgSP1gXMTnPdhfe/2qDH5cg==", - "peer": true, "dependencies": { "loose-envify": "^1.4.0", "object-assign": "^4.1.1", @@ -25988,6 +26010,15 @@ "resolved": "https://registry.npmjs.org/@gar/promisify/-/promisify-1.1.3.tgz", "integrity": "sha512-k2Ty1JcVojjJFwrg/ThKi2ujJ7XNLYaFGNB/bWT9wGR+oSMJHMa5w+CUq6p/pVrKeNNgA7pCqEcjSnHVoqJQFw==" }, + "@gmurph91/react-textfit": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/@gmurph91/react-textfit/-/react-textfit-1.1.4.tgz", + "integrity": "sha512-s0qQAIcYk8OIxTHwplijjXd1R5aPfF5Glb98Nb5970FzikmazZKmpsinOs8bQoi3CdfKCUpLfZ/sSRxvM/h+rw==", + "requires": { + "process": "^0.11.10", + "prop-types": "^15.7.2" + } + }, "@grpc/grpc-js": { "version": "1.7.3", "resolved": "https://registry.npmjs.org/@grpc/grpc-js/-/grpc-js-1.7.3.tgz", @@ -27789,6 +27820,15 @@ "csstype": "^3.0.2" } }, + "@types/react-textfit": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/@types/react-textfit/-/react-textfit-1.1.4.tgz", + "integrity": "sha512-tj3aMfbzi12r2yWn4Kzm9IkEHz7uaBU57P19FhzEA+Sr+ex0EuJezAYtBRMW3HjxylJ8PtmwpWgPT/t+j0H6zA==", + "dev": true, + "requires": { + "@types/react": "*" + } + }, "@types/resolve": { "version": "1.17.1", "resolved": "https://registry.npmjs.org/@types/resolve/-/resolve-1.17.1.tgz", @@ -34615,7 +34655,6 @@ "version": "1.4.0", "resolved": "https://registry.npmjs.org/loose-envify/-/loose-envify-1.4.0.tgz", "integrity": "sha512-lyuxPGr/Wfhrlem2CL/UcnUc1zcqKAImBDzukY7Y5F/yQiNdko6+fRLevlw1HgMySw7f611UIY408EtxRSoK3Q==", - "peer": true, "requires": { "js-tokens": "^3.0.0 || ^4.0.0" } @@ -37958,7 +37997,6 @@ "version": "15.8.1", "resolved": "https://registry.npmjs.org/prop-types/-/prop-types-15.8.1.tgz", "integrity": "sha512-oj87CgZICdulUohogVAR7AjlC0327U4el4L6eAvOqCeudMDVU0NThNaV+b9Df4dXgSP1gXMTnPdhfe/2qDH5cg==", - "peer": true, "requires": { "loose-envify": "^1.4.0", "object-assign": "^4.1.1", diff --git a/package.json b/package.json index f7d4a3f..38e4779 100644 --- a/package.json +++ b/package.json @@ -10,6 +10,7 @@ "lint": "eslint './src/**/*.{js,jsx,ts,tsx}' './functions/src/**/*.{js,ts}'" }, "dependencies": { + "@gmurph91/react-textfit": "^1.1.4", "@microsoft/signalr": "^7.0.7", "@preact/preset-vite": "^2.5.0", "@react-spring/web": "^9.7.3", @@ -31,6 +32,7 @@ "@types/color": "^3.0.3", "@types/js-cookie": "^3.0.3", "@types/react": "^18.2.14", + "@types/react-textfit": "^1.1.4", "@types/styled-components": "^5.1.26", "babel-plugin-module-resolver": "^5.0.0", "dotenv-webpack": "^7.1.0", diff --git a/shared/DbTypes.ts b/shared/DbTypes.ts index 378a4ff..e333b69 100644 --- a/shared/DbTypes.ts +++ b/shared/DbTypes.ts @@ -1,49 +1,65 @@ import { BracketMatchNumber } from './DoubleEliminationBracketMapping'; -export type EventState = 'Pending' | 'AwaitingQualSchedule' | 'QualsInProgress' -| 'AwaitingAlliances' | 'PlayoffsInProgress' | 'EventOver'; +export type EventState = + | 'Pending' + | 'AwaitingQualSchedule' + | 'QualsInProgress' + | 'AwaitingAlliances' + | 'PlayoffsInProgress' + | 'EventOver'; export type AppMode = 'automatic' | 'assisted'; export type Event = { // TODO: temporary - dataSource?: string, - start: string, - end: string, - name: string, - eventCode: string, - currentMatchNumber: number | null, - playoffMatchNumber: BracketMatchNumber | null + dataSource?: string; + start: string; + end: string; + name: string; + nameShort?: string; + eventCode: string; + currentMatchNumber: number | null; + playoffMatchNumber: BracketMatchNumber | null; streamEmbedLink?: string; - numQualMatches: number | null, - mode: AppMode, - state: EventState, + numQualMatches: number | null; + mode: AppMode; + state: EventState; /** * The timestamp of the most recent data we have from the FRC API, in ms since * the Unix epoch. This number will only ever stay the same or get bigger */ - lastModifiedMs: number | null, + lastModifiedMs: number | null; + message?: string; options: { - showRankings: boolean, - showEventName: boolean, - maxQueueingToShow?: number, - }, - sponsorLogoUrl?: string, + showRankings: boolean; + showEventName: boolean; + maxQueueingToShow?: number; + }; + branding?: { + logo: string; + bgColor: string; + textColor: string; + }; }; -export type DriverStation = 'Red1' | 'Red2' | 'Red3' | 'Blue1' | 'Blue2' -| 'Blue3'; +export type DriverStation = + | 'Red1' + | 'Red2' + | 'Red3' + | 'Blue1' + | 'Blue2' + | 'Blue3'; export type PlayoffMatch = { - winner: 'red' | 'blue' | null, - participants: Record, - redAlliance: number | null, - blueAlliance: number | null + winner: 'red' | 'blue' | null; + participants: Record; + redAlliance: number | null; + blueAlliance: number | null; }; export type QualMatch = { - number: number, - participants: Record, + number: number; + participants: Record; }; export type TeamRanking = { diff --git a/src/components/MultiDisplay/EventRow/AllianceFader/styles.module.scss b/src/components/MultiDisplay/EventRow/AllianceFader/styles.module.scss index 0b045df..8a80b2e 100644 --- a/src/components/MultiDisplay/EventRow/AllianceFader/styles.module.scss +++ b/src/components/MultiDisplay/EventRow/AllianceFader/styles.module.scss @@ -2,6 +2,13 @@ $teamlist-size: 5.5vh; .faderBase { + + display: flex; + flex-direction: column; + // Center items + justify-content: center; + align-items: center; + &> div { position: absolute; transition: all ease .5s; diff --git a/src/components/MultiDisplay/EventRow/index.tsx b/src/components/MultiDisplay/EventRow/index.tsx index d2f24a7..580264d 100644 --- a/src/components/MultiDisplay/EventRow/index.tsx +++ b/src/components/MultiDisplay/EventRow/index.tsx @@ -11,13 +11,15 @@ import { useEffect, useState, useRef } from 'preact/hooks'; import { QualMatch, Event } from '@shared/DbTypes'; import styles from './styles.module.scss'; import AllianceFader from './AllianceFader'; +// @ts-ignore +import { Textfit } from '@gmurph91/react-textfit'; type LoadingState = 'loading' | 'ready' | 'error' | 'noAutomatic'; type Break = { - after: number, - level: 'qual', - message: string + after: number; + level: 'qual'; + message: string; }; type MatchOrBreak = QualMatch | Break | null; @@ -37,6 +39,10 @@ const EventRow = ({ season: string; showLine: 0 | 1; }) => { + // URL parameters + const searchParams = new URLSearchParams(window.location.search); + const useShortName = typeof searchParams.get('useShortName') === 'string'; + // Loading state const [loadingState, setLoadingState] = useState('loading'); @@ -54,10 +60,14 @@ const EventRow = ({ // Matches to display // eslint-disable-next-line max-len - const [displayMatches, setDisplayMatches] = useState({ currentMatch: null, nextMatch: null, queueingMatches: [] }); + const [displayMatches, setDisplayMatches] = useState({ + currentMatch: null, + nextMatch: null, + queueingMatches: [], + }); useEffect(() => { - if (!token) return () => { }; + if (!token) return () => {}; const eventRef = ref(getDatabase(), `/seasons/${season}/events/${token}`); dbEventRef.current = eventRef; @@ -82,7 +92,8 @@ const EventRow = ({ }, [season, token]); // eslint-disable-next-line max-len -- HOW TO MAKE THIS SHORT? - const getMatchByNumber = (matchNumber: number): QualMatch | null => qualMatches?.find((x) => x.number === matchNumber) ?? null; + const getMatchByNumber = (matchNumber: number): QualMatch | null => + qualMatches?.find((x) => x.number === matchNumber) ?? null; const updateMatches = (e: Event): void => { const matchNumber = e.currentMatchNumber; @@ -99,9 +110,10 @@ const EventRow = ({ try { // Make a new array of max queuing matches to display - const maxQ = typeof e.options?.maxQueueingToShow === 'number' - ? e.options?.maxQueueingToShow - : 3; + const maxQ = + typeof e.options?.maxQueueingToShow === 'number' + ? e.options?.maxQueueingToShow + : 3; const toFill = new Array(maxQ).fill(null); toFill.forEach((_, i) => { toFill[i] = i + 2; @@ -111,16 +123,17 @@ const EventRow = ({ const upcoming: MatchOrBreak[] = [ getMatchByNumber(matchNumber), getMatchByNumber(matchNumber + 1), - ].concat( // Add Queueing Matches + ].concat( + // Add Queueing Matches toFill .map((x) => getMatchByNumber(matchNumber + x)) - .filter((x) => x !== null) as QualMatch[], + .filter((x) => x !== null) as QualMatch[] ); // See if there is an upcoming break breaks?.forEach((b: Break) => { // See if break start is inside what we're showing - if (b.after < (matchNumber + upcoming.length)) { + if (b.after < matchNumber + upcoming.length) { // Calculate the insert location const insertAt = b.after - matchNumber; // Sanity @@ -171,7 +184,10 @@ const EventRow = ({ @@ -185,7 +201,10 @@ const EventRow = ({ @@ -199,7 +218,10 @@ const EventRow = ({ @@ -211,25 +233,87 @@ const EventRow = ({ if (loadingState === 'ready' && qualMatches?.length !== 0) { return ( <> + {/* Message */} +
+
+ {/* Logo/Event Name Short Fader */} +
+ {/* Logo */} +
+ {event.name} +
+ {/* Text */} + + + {event.nameShort || event.name} + + +
+ + {/* Message */} + + + {event.message || event.name} + + +
+
+ - {/* Sponsor Logo */} + {/* Field Name / Logo */} {/* Current Match */} - { currentMatch && (currentMatch as QualMatch)?.number && ( + {currentMatch && (currentMatch as QualMatch)?.number && ( )} {/* Current Match is Break */} - { currentMatch && (currentMatch as Break)?.message && ( + {currentMatch && (currentMatch as Break)?.message && ( @@ -240,7 +324,9 @@ const EventRow = ({ {/* Is a Match */} {nextMatch && (nextMatch as QualMatch).number && ( - {(nextMatch as QualMatch)?.number} + + {(nextMatch as QualMatch)?.number} + - {(nextMatch as Break).message} - + {(nextMatch as Break).message} )} {/* Queueing Matches */} - diff --git a/src/components/MultiDisplay/EventRow/styles.module.scss b/src/components/MultiDisplay/EventRow/styles.module.scss index 374ebc1..5cc5cb0 100644 --- a/src/components/MultiDisplay/EventRow/styles.module.scss +++ b/src/components/MultiDisplay/EventRow/styles.module.scss @@ -27,11 +27,6 @@ tbody > tr { line-height: 0.8; } -.nextMatchScroll { - position: relative; - top: $cell-vertical-negative; -} - .flexRow { display: flex; flex-direction: row; @@ -54,3 +49,47 @@ tbody > tr { .bold { font-weight: bold; } + +.w100 { + width: 100%; +} + +.messageContainer { + transition: all ease .5s; + position: relative; + z-index: 3; + height: 0; + width: 0; + left: -101vw; +} + +.messageMover { + width: 100vw; + height: 22vh; + background-color: black; + display: flex; + flex-direction: row; + justify-content: center; + align-items: center; + + &>span { + width: 80%; + } +} + +.faderContainer { + width: 30vw; + height: 22vh; + + &>* { + position: absolute; + transition: all ease .5s; + text-align: center; + width: 30vw; + top: 0; + font-weight: bold; + align-items: center; + justify-content: center; + }; + +} diff --git a/src/components/MultiDisplay/index.tsx b/src/components/MultiDisplay/index.tsx index ad69874..c45b973 100644 --- a/src/components/MultiDisplay/index.tsx +++ b/src/components/MultiDisplay/index.tsx @@ -10,7 +10,11 @@ const MultiQueueing = () => { const calcClock = (): string => { const now = new Date(); - const str = now.toLocaleString('en-US', { hour: 'numeric', minute: '2-digit', hour12: true }); + const str = now.toLocaleString('en-US', { + hour: 'numeric', + minute: '2-digit', + hour12: true, + }); return str; }; @@ -38,8 +42,8 @@ const MultiQueueing = () => { - - + + From 19408ee3c8da43d573a835a3699c180c6bae1be1 Mon Sep 17 00:00:00 2001 From: Soren Zaiser Date: Tue, 2 Apr 2024 00:59:57 -0400 Subject: [PATCH 11/17] Refactor, prepping for playoffs row --- .../EventRow/MessageRow/index.tsx | 57 +++ .../{ => MessageRow}/styles.module.scss | 75 +--- .../MultiDisplay/EventRow/QualRow/index.tsx | 327 +++++++++++++++ .../MultiDisplay/EventRow/index.tsx | 376 +----------------- .../EventRow/sharedStyles.module.scss | 55 +++ src/models/MatchData.ts | 25 ++ 6 files changed, 501 insertions(+), 414 deletions(-) create mode 100644 src/components/MultiDisplay/EventRow/MessageRow/index.tsx rename src/components/MultiDisplay/EventRow/{ => MessageRow}/styles.module.scss (62%) create mode 100644 src/components/MultiDisplay/EventRow/QualRow/index.tsx create mode 100644 src/components/MultiDisplay/EventRow/sharedStyles.module.scss create mode 100644 src/models/MatchData.ts diff --git a/src/components/MultiDisplay/EventRow/MessageRow/index.tsx b/src/components/MultiDisplay/EventRow/MessageRow/index.tsx new file mode 100644 index 0000000..5f331f5 --- /dev/null +++ b/src/components/MultiDisplay/EventRow/MessageRow/index.tsx @@ -0,0 +1,57 @@ +import { h } from 'preact'; +import { Event } from '@shared/DbTypes'; +import styles from './styles.module.scss'; +// @ts-ignore +import { Textfit } from '@gmurph91/react-textfit'; + +const MessageRow = ({ event, showLine }: { event: Event; showLine: 0 | 1 }) => { + return ( +
+
+ {/* Logo/Event Name Short Fader */} +
+ {/* Logo */} +
+ {event.name} +
+ {/* Text */} + + + {event.nameShort || event.name} + + +
+ + {/* Message */} + + + {event.message || event.name} + + +
+
+ ); +}; + +export default MessageRow; diff --git a/src/components/MultiDisplay/EventRow/styles.module.scss b/src/components/MultiDisplay/EventRow/MessageRow/styles.module.scss similarity index 62% rename from src/components/MultiDisplay/EventRow/styles.module.scss rename to src/components/MultiDisplay/EventRow/MessageRow/styles.module.scss index 5cc5cb0..197bd5c 100644 --- a/src/components/MultiDisplay/EventRow/styles.module.scss +++ b/src/components/MultiDisplay/EventRow/MessageRow/styles.module.scss @@ -1,59 +1,3 @@ -$border-color: #fafafa; - -$teamlist-size: 5.5vh; -$matchnumber-size: 18vh; - -$cell-vertical-negative: -3vh; - - -tr { - color: #fafafa !important; -} - -tbody > tr { - height: 22vh; -} - -.textCenter { - text-align: center; -} - -.matchNumber { - text-align: center; - font-size: $matchnumber-size; - font-weight: bold; - position: relative; - top: $cell-vertical-negative; - line-height: 0.8; -} - -.flexRow { - display: flex; - flex-direction: row; - font-size: $teamlist-size; - margin-bottom: 3px; -} - -.sponsorLogo { - display: block; - margin-top: 1vh; - margin-bottom: 1vh; - margin-left: auto; - margin-right: auto; - width: auto; - height: auto; - max-width: 15vw; - max-height: 15vh; -} - -.bold { - font-weight: bold; -} - -.w100 { - width: 100%; -} - .messageContainer { transition: all ease .5s; position: relative; @@ -77,6 +21,10 @@ tbody > tr { } } +.textCenter { + text-align: center; +} + .faderContainer { width: 30vw; height: 22vh; @@ -90,6 +38,19 @@ tbody > tr { font-weight: bold; align-items: center; justify-content: center; - }; + } + ; } + +.sponsorLogo { + display: block; + margin-top: 1vh; + margin-bottom: 1vh; + margin-left: auto; + margin-right: auto; + width: auto; + height: auto; + max-width: 15vw; + max-height: 15vh; +} \ No newline at end of file diff --git a/src/components/MultiDisplay/EventRow/QualRow/index.tsx b/src/components/MultiDisplay/EventRow/QualRow/index.tsx new file mode 100644 index 0000000..3a01449 --- /dev/null +++ b/src/components/MultiDisplay/EventRow/QualRow/index.tsx @@ -0,0 +1,327 @@ +import { h, Fragment } from 'preact'; +import { QualMatch, Event } from '@shared/DbTypes'; +import { + getDatabase, + ref, + onValue, + off, + // update, +} from 'firebase/database'; +import styles from '../sharedStyles.module.scss'; +// @ts-ignore +import { Textfit } from '@gmurph91/react-textfit'; +import { Break, MatchOrBreak, QualMatchData } from '@/models/MatchData'; +import AllianceFader from '../AllianceFader'; +import { useEffect, useState } from 'react'; +import MessageRow from '../MessageRow'; + +type LoadingState = 'loading' | 'ready' | 'error' | 'noAutomatic'; + +const QualRow = ({ + event, + showLine, + season, + token, +}: { + event: Event; + showLine: 0 | 1; + season: string; + token: string; +}) => { + // Loading state + const [loadingState, setLoadingState] = useState('loading'); + + // This row's matches + const [qualMatches, setQualMatches] = useState([]); + + // URL parameters + const searchParams = new URLSearchParams(window.location.search); + const useShortName = typeof searchParams.get('useShortName') === 'string'; + + // This row's breaks + const [breaks, setBreaks] = useState([]); + + // Matches to display + // eslint-disable-next-line max-len + const [displayMatches, setDisplayMatches] = useState({ + currentMatch: null, + nextMatch: null, + queueingMatches: [], + }); + + useEffect(() => { + const matchesRef = ref(getDatabase(), `/seasons/${season}/qual/${token}`); + onValue(matchesRef, (snap) => { + setQualMatches(snap.val() as QualMatch[]); + }); + + const breaksRef = ref(getDatabase(), `/seasons/${season}/breaks/${token}`); + onValue(breaksRef, (snap) => { + setBreaks(snap.val() as Break[]); + }); + + return () => { + off(matchesRef); + off(breaksRef); + }; + }, [season]); + + // eslint-disable-next-line max-len -- HOW TO MAKE THIS SHORT? + const getMatchByNumber = (matchNumber: number): QualMatch | null => + qualMatches?.find((x) => x.number === matchNumber) ?? null; + + const updateMatches = (e: Event): void => { + const matchNumber = e.currentMatchNumber; + + // if (matchNumber === null || matchNumber === undefined) { + // if (dbEventRef.current === undefined) return; // throw new Error('No event ref'); + // // TODO: Why does this always set the match to 1 on page load?? + // // update(dbEventRef.current, { + // // currentMatchNumber: 1, + // // }).catch((err) => { + // // console.error(err); + // // }); + // return; + // } + + // Return if no match number + if (matchNumber === null || matchNumber === undefined) return; + + try { + // Make a new array of max queuing matches to display + const maxQ = + typeof e.options?.maxQueueingToShow === 'number' + ? e.options?.maxQueueingToShow + : 3; + const toFill = new Array(maxQ).fill(null); + toFill.forEach((_, i) => { + toFill[i] = i + 2; + }); + + // Upcoming matches + const upcoming: MatchOrBreak[] = [ + getMatchByNumber(matchNumber), + getMatchByNumber(matchNumber + 1), + ].concat( + // Add Queueing Matches + toFill + .map((x) => getMatchByNumber(matchNumber + x)) + .filter((x) => x !== null) as QualMatch[] + ); + + // See if there is an upcoming break + breaks?.forEach((b: Break) => { + // See if break start is inside what we're showing + if (b.after < matchNumber + upcoming.length) { + // Calculate the insert location + const insertAt = b.after - matchNumber; + // Sanity + if (insertAt < 0) return; + // Insert break + upcoming.splice(insertAt, 0, b); + // Remove one from the end + upcoming.pop(); + } + }); + + const data = { + currentMatch: upcoming[0], + nextMatch: upcoming[1], + queueingMatches: upcoming.slice(2), + } as QualMatchData; + + setDisplayMatches(data); + setLoadingState('ready'); + } catch (err: any) { + setLoadingState('error'); + console.error(err); + } + }; + + // On event change, check for matches + useEffect(() => { + if (event) updateMatches(event); + }, [event.currentMatchNumber, qualMatches, breaks]); + + // Calculate Red alliance string + const getRedStr = (match: QualMatch | null): string => { + if (!match) return ''; + return `${match.participants.Red1} ${match.participants.Red2} ${match.participants.Red3}`; + }; + + // Calculate Blue alliance string + const getBlueStr = (match: QualMatch | null): string => { + if (!match) return ''; + return `${match.participants.Blue1} ${match.participants.Blue2} ${match.participants.Blue3}`; + }; + + // Spread the match data + const { currentMatch, nextMatch, queueingMatches } = displayMatches; + + // Message cases + const case1 = ['loading', 'error'].includes(loadingState); + const case2 = loadingState === 'ready' && (qualMatches?.length ?? 0) < 1; + + // Loading/Error Text + if (case1 || case2) { + return ( + <> + {/* Message */} + + + {/* Loading */} +
+ + + + ); + } + + // Ready and we have matches + if (loadingState === 'ready' && qualMatches?.length !== 0) { + return ( + <> + {/* Message */} + + + {/* Quals */} + + {/* Field Name / Logo */} + + + {/* Current Match */} + {currentMatch && (currentMatch as QualMatch)?.number && ( + + )} + + {/* Current Match is Break */} + {currentMatch && (currentMatch as Break)?.message && ( + + )} + + {/* Next Match */} + + + {/* Queueing Matches */} + + + + ); + } + + return null; +}; + +export default QualRow; diff --git a/src/components/MultiDisplay/EventRow/index.tsx b/src/components/MultiDisplay/EventRow/index.tsx index 580264d..4873a7d 100644 --- a/src/components/MultiDisplay/EventRow/index.tsx +++ b/src/components/MultiDisplay/EventRow/index.tsx @@ -9,26 +9,10 @@ import { } from 'firebase/database'; import { useEffect, useState, useRef } from 'preact/hooks'; import { QualMatch, Event } from '@shared/DbTypes'; -import styles from './styles.module.scss'; -import AllianceFader from './AllianceFader'; -// @ts-ignore -import { Textfit } from '@gmurph91/react-textfit'; - -type LoadingState = 'loading' | 'ready' | 'error' | 'noAutomatic'; - -type Break = { - after: number; - level: 'qual'; - message: string; -}; - -type MatchOrBreak = QualMatch | Break | null; - -type MatchData = { - currentMatch: MatchOrBreak | null; - nextMatch: MatchOrBreak | null; - queueingMatches: MatchOrBreak[]; -}; +import styles from './sharedStyles.module.scss'; +import { Break, MatchOrBreak, QualMatchData } from '@/models/MatchData'; +import QualRow from './QualRow'; +import MessageRow from './MessageRow'; const EventRow = ({ token, @@ -39,28 +23,15 @@ const EventRow = ({ season: string; showLine: 0 | 1; }) => { - // URL parameters - const searchParams = new URLSearchParams(window.location.search); - const useShortName = typeof searchParams.get('useShortName') === 'string'; - - // Loading state - const [loadingState, setLoadingState] = useState('loading'); - // Ref to the event in the database const dbEventRef = useRef(); // This row's events const [event, setEvent] = useState({} as any); - // This row's matches - const [qualMatches, setQualMatches] = useState([]); - - // This row's breaks - const [breaks, setBreaks] = useState([]); - // Matches to display // eslint-disable-next-line max-len - const [displayMatches, setDisplayMatches] = useState({ + const [qualDisplayMatches, setQualDisplayMatches] = useState({ currentMatch: null, nextMatch: null, queueingMatches: [], @@ -75,334 +46,25 @@ const EventRow = ({ setEvent(snap.val() as Event); }); - const matchesRef = ref(getDatabase(), `/seasons/${season}/qual/${token}`); - onValue(matchesRef, (snap) => { - setQualMatches(snap.val() as QualMatch[]); - }); - - const breaksRef = ref(getDatabase(), `/seasons/${season}/breaks/${token}`); - onValue(breaksRef, (snap) => { - setBreaks(snap.val() as Break[]); - }); - return () => { - off(matchesRef); off(eventRef); }; }, [season, token]); - // eslint-disable-next-line max-len -- HOW TO MAKE THIS SHORT? - const getMatchByNumber = (matchNumber: number): QualMatch | null => - qualMatches?.find((x) => x.number === matchNumber) ?? null; - - const updateMatches = (e: Event): void => { - const matchNumber = e.currentMatchNumber; - - if (matchNumber === null || matchNumber === undefined) { - if (dbEventRef.current === undefined) return; // throw new Error('No event ref'); - // update(dbEventRef.current, { - // currentMatchNumber: 1, - // }).catch((err) => { - // console.error(err); - // }); - return; - } - - try { - // Make a new array of max queuing matches to display - const maxQ = - typeof e.options?.maxQueueingToShow === 'number' - ? e.options?.maxQueueingToShow - : 3; - const toFill = new Array(maxQ).fill(null); - toFill.forEach((_, i) => { - toFill[i] = i + 2; - }); - - // Upcoming matches - const upcoming: MatchOrBreak[] = [ - getMatchByNumber(matchNumber), - getMatchByNumber(matchNumber + 1), - ].concat( - // Add Queueing Matches - toFill - .map((x) => getMatchByNumber(matchNumber + x)) - .filter((x) => x !== null) as QualMatch[] - ); - - // See if there is an upcoming break - breaks?.forEach((b: Break) => { - // See if break start is inside what we're showing - if (b.after < matchNumber + upcoming.length) { - // Calculate the insert location - const insertAt = b.after - matchNumber; - // Sanity - if (insertAt < 0) return; - // Insert break - upcoming.splice(insertAt, 0, b); - // Remove one from the end - upcoming.pop(); - } - }); - - const data = { - currentMatch: upcoming[0], - nextMatch: upcoming[1], - queueingMatches: upcoming.slice(2), - } as MatchData; - - setDisplayMatches(data); - setLoadingState('ready'); - } catch (err: any) { - setLoadingState('error'); - console.error(err); - } - }; - - // On event change, check for matches - useEffect(() => { - if (event) updateMatches(event); - }, [event.currentMatchNumber, qualMatches, breaks]); - - const { currentMatch, nextMatch, queueingMatches } = displayMatches; - - // Calculate Red alliance string - const getRedStr = (match: QualMatch | null): string => { - if (!match) return ''; - return `${match.participants.Red1} ${match.participants.Red2} ${match.participants.Red3}`; - }; - - // Calculate Blue alliance string - const getBlueStr = (match: QualMatch | null): string => { - if (!match) return ''; - return `${match.participants.Blue1} ${match.participants.Blue2} ${match.participants.Blue3}`; - }; - - // Ready w/ no matches - if (loadingState === 'ready' && (qualMatches?.length ?? 0) < 1) { - return ( - - - - ); - } - - // Loading - if (loadingState === 'loading') { - return ( - - - - ); - } - - // Error - if (loadingState === 'error') { - return ( - - - - ); - } - - // Ready and we have matches - if (loadingState === 'ready' && qualMatches?.length !== 0) { - return ( - <> - {/* Message */} -
-
- {/* Logo/Event Name Short Fader */} -
- {/* Logo */} -
- {event.name} -
- {/* Text */} - - - {event.nameShort || event.name} - - -
- - {/* Message */} - - - {event.message || event.name} - - -
-
- - - {/* Field Name / Logo */} - - - {/* Current Match */} - {currentMatch && (currentMatch as QualMatch)?.number && ( - - )} - - {/* Current Match is Break */} - {currentMatch && (currentMatch as Break)?.message && ( - - )} - - {/* Next Match */} - - - {/* Queueing Matches */} - - - - ); - } - - return null; + return ( + <> + {['Pending', 'AwaitingQualSchedule', 'QualsInProgress'].includes( + event.state + ) && ( + + )} + + ); }; export default EventRow; diff --git a/src/components/MultiDisplay/EventRow/sharedStyles.module.scss b/src/components/MultiDisplay/EventRow/sharedStyles.module.scss new file mode 100644 index 0000000..c48e0b7 --- /dev/null +++ b/src/components/MultiDisplay/EventRow/sharedStyles.module.scss @@ -0,0 +1,55 @@ +$border-color: #fafafa; + +$teamlist-size: 5.5vh; +$matchnumber-size: 18vh; + +$cell-vertical-negative: -3vh; + + +tr { + color: #fafafa !important; +} + +tbody > tr { + height: 22vh; +} + +.textCenter { + text-align: center; +} + +.matchNumber { + text-align: center; + font-size: $matchnumber-size; + font-weight: bold; + position: relative; + top: $cell-vertical-negative; + line-height: 0.8; +} + +.flexRow { + display: flex; + flex-direction: row; + font-size: $teamlist-size; + margin-bottom: 3px; +} + +.sponsorLogo { + display: block; + margin-top: 1vh; + margin-bottom: 1vh; + margin-left: auto; + margin-right: auto; + width: auto; + height: auto; + max-width: 15vw; + max-height: 15vh; +} + +.bold { + font-weight: bold; +} + +.w100 { + width: 100%; +} diff --git a/src/models/MatchData.ts b/src/models/MatchData.ts new file mode 100644 index 0000000..d36745f --- /dev/null +++ b/src/models/MatchData.ts @@ -0,0 +1,25 @@ +import { PlayoffMatchDisplay } from '@/components/PlayoffQueueing/PlayoffMatchDisplay'; +import { QualMatch } from '@shared/DbTypes'; + +// TODO: this should be moved to DbTypes once the type is available +export type Break = { + after: number; + level: 'qual'; + message: string; +}; + +export type MatchOrBreak = QualMatch | Break | null; + +// Qual Match Data +export type QualMatchData = { + currentMatch: MatchOrBreak | null; + nextMatch: MatchOrBreak | null; + queueingMatches: MatchOrBreak[]; +}; + +// Playoff Match Data +export type PlayoffMatchData = { + currentMatch: PlayoffMatchDisplay | null; + nextMatch: PlayoffMatchDisplay | null; + queueingMatches: PlayoffMatchDisplay[]; +}; From 69a39a17708463cdf3da95f0f28712e500fa95a1 Mon Sep 17 00:00:00 2001 From: Soren Zaiser Date: Tue, 2 Apr 2024 01:01:46 -0400 Subject: [PATCH 12/17] Dead code --- src/components/MultiDisplay/EventRow/index.tsx | 8 -------- 1 file changed, 8 deletions(-) diff --git a/src/components/MultiDisplay/EventRow/index.tsx b/src/components/MultiDisplay/EventRow/index.tsx index 4873a7d..1dea5eb 100644 --- a/src/components/MultiDisplay/EventRow/index.tsx +++ b/src/components/MultiDisplay/EventRow/index.tsx @@ -29,14 +29,6 @@ const EventRow = ({ // This row's events const [event, setEvent] = useState({} as any); - // Matches to display - // eslint-disable-next-line max-len - const [qualDisplayMatches, setQualDisplayMatches] = useState({ - currentMatch: null, - nextMatch: null, - queueingMatches: [], - }); - useEffect(() => { if (!token) return () => {}; From 49a09ffcd95b8bafdf3766f1097c691bfc0626ab Mon Sep 17 00:00:00 2001 From: Soren Zaiser Date: Tue, 2 Apr 2024 01:24:39 -0400 Subject: [PATCH 13/17] =?UTF-8?q?Playofffs,=20but=20make=20it=20=E2=9C=A8u?= =?UTF-8?q?ntested=E2=9C=A8?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../EventRow/PlayoffRow/index.tsx | 306 ++++++++++++++++++ .../MultiDisplay/EventRow/index.tsx | 11 +- 2 files changed, 316 insertions(+), 1 deletion(-) create mode 100644 src/components/MultiDisplay/EventRow/PlayoffRow/index.tsx diff --git a/src/components/MultiDisplay/EventRow/PlayoffRow/index.tsx b/src/components/MultiDisplay/EventRow/PlayoffRow/index.tsx new file mode 100644 index 0000000..eb76163 --- /dev/null +++ b/src/components/MultiDisplay/EventRow/PlayoffRow/index.tsx @@ -0,0 +1,306 @@ +import { h, Fragment } from 'preact'; +import { QualMatch, Event, PlayoffMatch } from '@shared/DbTypes'; +import { + getDatabase, + ref, + onValue, + off, + // update, +} from 'firebase/database'; +import styles from '../sharedStyles.module.scss'; +// @ts-ignore +import { Textfit } from '@gmurph91/react-textfit'; +import { Break, MatchOrBreak, PlayoffMatchData } from '@/models/MatchData'; +import AllianceFader from '../AllianceFader'; +import { useEffect, useState } from 'react'; +import MessageRow from '../MessageRow'; +import DoubleEliminationBracketMapping, { + BracketMatchNumber, +} from '@shared/DoubleEliminationBracketMapping'; +import { PlayoffMatchDisplay } from '@/components/PlayoffQueueing/PlayoffMatchDisplay'; + +type LoadingState = 'loading' | 'ready' | 'error' | 'noAutomatic'; + +const PlayoffRow = ({ + event, + showLine, + season, + token, +}: { + event: Event; + showLine: 0 | 1; + season: string; + token: string; +}) => { + // Loading state + const [loadingState, setLoadingState] = useState('loading'); + + // This row's matches + const [results, setResults] = useState< + Partial> + >({}); + + // URL parameters + const searchParams = new URLSearchParams(window.location.search); + const useShortName = typeof searchParams.get('useShortName') === 'string'; + + // This row's breaks + const [breaks, setBreaks] = useState([]); + + // Matches to display + // eslint-disable-next-line max-len + const [displayMatches, setDisplayMatches] = useState({ + currentMatch: null, + nextMatch: null, + queueingMatches: [], + }); + + useEffect(() => { + const bracketRef = ref( + getDatabase(), + `/seasons/${season}/bracket/${token}` + ); + onValue(bracketRef, (snap) => { + setResults( + snap.val() as Partial> + ); + }); + + return () => { + off(bracketRef); + }; + }, [season]); + + /** + * (Re)populate the match displays with latest data and calculate the current + next matches + */ + const updateMatches = (): void => { + // Get the basic list of matches + const matchDisplays: PlayoffMatchDisplay[] = + DoubleEliminationBracketMapping.matches.map((m) => ({ + result: results ? results[m.number] ?? null : null, + match: m, + num: m?.number, + })); + // TODO: Find a better way to do this? + // TODO: Add multiple entries for finals with break between? + + // Add in the breaks + DoubleEliminationBracketMapping.breakAfter.forEach((b) => { + matchDisplays.splice(matchDisplays.findIndex((m) => m.num === b) + 1, 0, { + result: null, + match: null, + num: null, + customDisplayText: '(Break)', + }); + }); + + matchDisplays.push({ + result: null, + match: null, + num: null, + customDisplayText: '(END)', + }); + + // Get the last match that has a winner + let currentMatchIndex = + matchDisplays.reduce((v, m, i) => (m.result?.winner ? i : v), -1) + 1; + console.log(currentMatchIndex); + + // We have no way of knowing when a break is over, so to reduce confusion never show a break + // as the current match. If we're at the end of the matches we can show that + if ( + matchDisplays[currentMatchIndex].customDisplayText && + matchDisplays.length - 1 > currentMatchIndex + ) { + currentMatchIndex += 1; + } + + try { + setDisplayMatches({ + currentMatch: matchDisplays[currentMatchIndex], + nextMatch: matchDisplays[currentMatchIndex + 1], + // By default, we'll take the three matches after the one on deck + queueingMatches: [2, 3, 4] + .map((x) => matchDisplays[currentMatchIndex + x]) + .filter((x) => x !== undefined) as PlayoffMatchDisplay[], + }); + setLoadingState('ready'); + } catch (e) { + setLoadingState('error'); + console.error(e); + } + }; + + // FIXME (@evanlihou): This effect runs twice on initial load, which causes the "waiting for + // schedule to be posted" message to flash on the screen for one rendering cycle + useEffect(() => { + updateMatches(); + }, [results]); + + // Calculate Red alliance string + const getRedStr = (match: PlayoffMatch | null): string => { + if (!match) return ''; + return `${match.participants.Red1} ${match.participants.Red2} ${match.participants.Red3}`; + }; + + // Calculate Blue alliance string + const getBlueStr = (match: PlayoffMatch | null): string => { + if (!match) return ''; + return `${match.participants.Blue1} ${match.participants.Blue2} ${match.participants.Blue3}`; + }; + + // Spread the match data + const { currentMatch, nextMatch, queueingMatches } = displayMatches; + + // Loading/Error Text + if (['loading', 'error'].includes(loadingState)) { + return ( + <> + {/* Message */} + + + {/* Loading */} + + + + + ); + } + + // Ready and we have matches + if (loadingState === 'ready') { + return ( + <> + {/* Message */} + + + {/* Quals */} + + {/* Field Name / Logo */} + + + {/* Current Match */} + {currentMatch && ( + + )} + + {/* Next Match */} + + + {/* Queueing Matches */} + + + + ); + } + + return null; +}; + +export default PlayoffRow; diff --git a/src/components/MultiDisplay/EventRow/index.tsx b/src/components/MultiDisplay/EventRow/index.tsx index 1dea5eb..a90bc2d 100644 --- a/src/components/MultiDisplay/EventRow/index.tsx +++ b/src/components/MultiDisplay/EventRow/index.tsx @@ -13,6 +13,7 @@ import styles from './sharedStyles.module.scss'; import { Break, MatchOrBreak, QualMatchData } from '@/models/MatchData'; import QualRow from './QualRow'; import MessageRow from './MessageRow'; +import PlayoffRow from './PlayoffRow'; const EventRow = ({ token, @@ -45,15 +46,23 @@ const EventRow = ({ return ( <> + {/* Beginning of Event */} {['Pending', 'AwaitingQualSchedule', 'QualsInProgress'].includes( event.state - ) && ( + ) ? ( + ) : ( + )} ); From 22c730a2dd1879bb98fa5ccfa0b1c4487758a1be Mon Sep 17 00:00:00 2001 From: Soren Zaiser Date: Tue, 2 Apr 2024 13:49:36 -0400 Subject: [PATCH 14/17] Pre-Event Updates --- .../MultiDisplay/EventRow/MessageRow/index.tsx | 2 +- .../EventRow/MessageRow/styles.module.scss | 4 +++- .../MultiDisplay/EventRow/QualRow/index.tsx | 15 +++++++++------ src/components/MultiDisplay/EventRow/index.tsx | 5 +---- .../EventRow/sharedStyles.module.scss | 4 ++++ src/components/MultiDisplay/index.tsx | 4 ++-- 6 files changed, 20 insertions(+), 14 deletions(-) diff --git a/src/components/MultiDisplay/EventRow/MessageRow/index.tsx b/src/components/MultiDisplay/EventRow/MessageRow/index.tsx index 5f331f5..96a3c9b 100644 --- a/src/components/MultiDisplay/EventRow/MessageRow/index.tsx +++ b/src/components/MultiDisplay/EventRow/MessageRow/index.tsx @@ -44,7 +44,7 @@ const MessageRow = ({ event, showLine }: { event: Event; showLine: 0 | 1 }) => { {/* Message */} - + {event.message || event.name} diff --git a/src/components/MultiDisplay/EventRow/MessageRow/styles.module.scss b/src/components/MultiDisplay/EventRow/MessageRow/styles.module.scss index 197bd5c..6650412 100644 --- a/src/components/MultiDisplay/EventRow/MessageRow/styles.module.scss +++ b/src/components/MultiDisplay/EventRow/MessageRow/styles.module.scss @@ -21,8 +21,10 @@ } } -.textCenter { +.messageText { text-align: center; + width: 60vw; + font-weight: bold; } .faderContainer { diff --git a/src/components/MultiDisplay/EventRow/QualRow/index.tsx b/src/components/MultiDisplay/EventRow/QualRow/index.tsx index 3a01449..cead738 100644 --- a/src/components/MultiDisplay/EventRow/QualRow/index.tsx +++ b/src/components/MultiDisplay/EventRow/QualRow/index.tsx @@ -14,6 +14,7 @@ import { Break, MatchOrBreak, QualMatchData } from '@/models/MatchData'; import AllianceFader from '../AllianceFader'; import { useEffect, useState } from 'react'; import MessageRow from '../MessageRow'; +import { reload } from 'firebase/auth'; type LoadingState = 'loading' | 'ready' | 'error' | 'noAutomatic'; @@ -272,12 +273,14 @@ const QualRow = ({ const match = x as QualMatch; return (
- {match.number} - - + {match.number} - +
+ +
); } diff --git a/src/components/MultiDisplay/EventRow/index.tsx b/src/components/MultiDisplay/EventRow/index.tsx index a90bc2d..fff9863 100644 --- a/src/components/MultiDisplay/EventRow/index.tsx +++ b/src/components/MultiDisplay/EventRow/index.tsx @@ -8,11 +8,8 @@ import { // update, } from 'firebase/database'; import { useEffect, useState, useRef } from 'preact/hooks'; -import { QualMatch, Event } from '@shared/DbTypes'; -import styles from './sharedStyles.module.scss'; -import { Break, MatchOrBreak, QualMatchData } from '@/models/MatchData'; +import { Event } from '@shared/DbTypes'; import QualRow from './QualRow'; -import MessageRow from './MessageRow'; import PlayoffRow from './PlayoffRow'; const EventRow = ({ diff --git a/src/components/MultiDisplay/EventRow/sharedStyles.module.scss b/src/components/MultiDisplay/EventRow/sharedStyles.module.scss index c48e0b7..a74f158 100644 --- a/src/components/MultiDisplay/EventRow/sharedStyles.module.scss +++ b/src/components/MultiDisplay/EventRow/sharedStyles.module.scss @@ -50,6 +50,10 @@ tbody > tr { font-weight: bold; } +.queueingMatchNumber { + font-weight: bold; + font-size: 7vh; +} .w100 { width: 100%; } diff --git a/src/components/MultiDisplay/index.tsx b/src/components/MultiDisplay/index.tsx index c45b973..a843c7a 100644 --- a/src/components/MultiDisplay/index.tsx +++ b/src/components/MultiDisplay/index.tsx @@ -39,8 +39,8 @@ const MultiQueueing = () => {
{clock}On FieldNext MatchQueueing Matches{clock}On FieldNext MatchQueueing Matches
{currentMatch?.number} + {(currentMatch as QualMatch)?.number} + + {(currentMatch as Break)?.message} + - {nextMatch && ( + {/* Is a Match */} + {nextMatch && (nextMatch as QualMatch).number && ( - {nextMatch?.number} + {(nextMatch as QualMatch)?.number} )} + + {/* Is a Break */} + {nextMatch && (nextMatch as Break).message && ( + + {(nextMatch as Break).message} + + )} - {queueingMatches.map((x, i) => ( -
- {x.number} - - -
- ))} + {queueingMatches.map((x) => { + // Is a match, not a break + if (x && (x as QualMatch).number) { + const match = x as QualMatch; + return ( +
+ {match.number} - + +
+ ); + } + + // Is a break + return ( +
+ {(x as Break).message} +
+ ); + })}
{event && event.name && ( - {event.name}
+ + {event.name} +
+
)} Waiting for schedule to be posted...
{event && event.name && ( - {event.name}
+ + {event.name} +
+
)} Loading matches...
{event && event.name && ( - {event.name}
+ + {event.name} +
+
)} Failed to fetch matches
- {event.name} + {/* Use event logo */} + {!useShortName && ( + {event.name} + )} + + {/* Use event short name */} + {useShortName && ( +
+ + {event.nameShort || event.name} + +
+ )}
{(currentMatch as QualMatch)?.number} {(currentMatch as Break)?.message} - {queueingMatches.map((x) => { - // Is a match, not a break - if (x && (x as QualMatch).number) { - const match = x as QualMatch; + + {/* Multiple Queueing Matches */} + {queueingMatches.length > 1 && + queueingMatches.map((x) => { + // Is a match, not a break + if (x && (x as QualMatch).number) { + const match = x as QualMatch; + return ( +
+ {match.number} - + +
+ ); + } + + // Is a break return ( -
- {match.number} - - +
+ {(x as Break).message}
); - } - - // Is a break - return ( -
- {(x as Break).message} -
- ); - })} + })} + + {/* Single Queueing Match */} + {queueingMatches.length === 1 && queueingMatches[0] && ( + <> + {queueingMatches[0] && + (queueingMatches[0] as QualMatch).number && ( + + + {(queueingMatches[0] as QualMatch)?.number} + + + + + + )} + + {/* Is a Break */} + {nextMatch && (queueingMatches[0] as Break).message && ( + {(queueingMatches[0] as Break).message} + )} + + )}
{clock} On FieldNext MatchQueueing MatchesUp NextQueueing
+ {event && event.name && ( + + {event.name} +
+
+ )} + + {loadingState === 'error' && case1 + ? 'Failed to fetch matches' + : loadingState === 'loading' + ? 'Loading Matches...' + : 'Waiting for schedule to be posted...'} + +
+ {/* Use event logo */} + {!useShortName && ( + {event.name} + )} + + {/* Use event short name */} + {useShortName && ( +
+ + {event.nameShort || event.name} + +
+ )} +
+ {(currentMatch as QualMatch)?.number} + + {(currentMatch as Break)?.message} + + {/* Is a Match */} + {nextMatch && (nextMatch as QualMatch).number && ( + + + {(nextMatch as QualMatch)?.number} + + + + + + )} + + {/* Is a Break */} + {nextMatch && (nextMatch as Break).message && ( + {(nextMatch as Break).message} + )} + + {/* Multiple Queueing Matches */} + {queueingMatches.length > 1 && + queueingMatches.map((x) => { + // Is a match, not a break + if (x && (x as QualMatch).number) { + const match = x as QualMatch; + return ( +
+ {match.number} - + +
+ ); + } + + // Is a break + return ( +
+ {(x as Break).message} +
+ ); + })} + + {/* Single Queueing Match */} + {queueingMatches.length === 1 && queueingMatches[0] && ( + <> + {queueingMatches[0] && + (queueingMatches[0] as QualMatch).number && ( + + + {(queueingMatches[0] as QualMatch)?.number} + + + + + + )} + + {/* Is a Break */} + {nextMatch && (queueingMatches[0] as Break).message && ( + {(queueingMatches[0] as Break).message} + )} + + )} +
- {event && event.name && ( - - {event.name} -
-
- )} - Waiting for schedule to be posted... -
- {event && event.name && ( - - {event.name} -
-
- )} - Loading matches... -
- {event && event.name && ( - - {event.name} -
-
- )} - Failed to fetch matches -
- {/* Use event logo */} - {!useShortName && ( - {event.name} - )} - - {/* Use event short name */} - {useShortName && ( -
- - {event.nameShort || event.name} - -
- )} -
- {(currentMatch as QualMatch)?.number} - - {(currentMatch as Break)?.message} - - {/* Is a Match */} - {nextMatch && (nextMatch as QualMatch).number && ( - - - {(nextMatch as QualMatch)?.number} - - - - - - )} - - {/* Is a Break */} - {nextMatch && (nextMatch as Break).message && ( - {(nextMatch as Break).message} - )} - - {/* Multiple Queueing Matches */} - {queueingMatches.length > 1 && - queueingMatches.map((x) => { - // Is a match, not a break - if (x && (x as QualMatch).number) { - const match = x as QualMatch; - return ( -
- {match.number} - - -
- ); - } - - // Is a break - return ( -
- {(x as Break).message} -
- ); - })} - - {/* Single Queueing Match */} - {queueingMatches.length === 1 && queueingMatches[0] && ( - <> - {queueingMatches[0] && - (queueingMatches[0] as QualMatch).number && ( - - - {(queueingMatches[0] as QualMatch)?.number} - - - - - - )} - - {/* Is a Break */} - {nextMatch && (queueingMatches[0] as Break).message && ( - {(queueingMatches[0] as Break).message} - )} - - )} -
+ {event && event.name && ( + + {event.name} +
+
+ )} + + {loadingState === 'error' + ? 'Failed to fetch matches' + : 'Loading Matches...'} + +
+ {/* Use event logo */} + {!useShortName && ( + {event.name} + )} + + {/* Use event short name */} + {useShortName && ( +
+ + {event.nameShort || event.name} + +
+ )} +
+ {currentMatch.customDisplayText ?? currentMatch?.num === 'F' + ? 'F' + : `M${currentMatch?.num}`} + + {/* Is a Match */} + {nextMatch && ( + + + {nextMatch.customDisplayText ?? nextMatch?.num === 'F' + ? 'F' + : `M${nextMatch?.num}`} + + {/* TODO: Reenable when sync doesnt suck? + + + + + */} + + )} + + {/* Multiple Queueing Matches */} + {queueingMatches.length > 1 && + queueingMatches.map((x) => { + return ( +
+ + {x.customDisplayText ?? x?.num === 'F' + ? 'F' + : `M${x?.num}`} + + {/* TODO: Reenable when sync doesnt suck? + + */} +
+ ); + })} + + {/* Single Queueing Match */} + {queueingMatches.length === 1 && queueingMatches[0] && ( + <> + {queueingMatches[0] && ( + + + {queueingMatches[0].customDisplayText ?? + queueingMatches[0]?.num === 'F' + ? 'F' + : `M${queueingMatches[0]?.num}`} + + + {/* TODO: Reenable when sync doesnt suck? + + + + */} + + )} + + )} +
- - + + From cd2ac4e3a63ec1c43144e0c3fc35d6f72bc7aca1 Mon Sep 17 00:00:00 2001 From: Soren Zaiser Date: Tue, 2 Apr 2024 14:20:18 -0400 Subject: [PATCH 15/17] More styling --- src/components/MultiDisplay/EventRow/MessageRow/index.tsx | 6 +++--- .../MultiDisplay/EventRow/MessageRow/styles.module.scss | 8 ++++---- src/components/MultiDisplay/EventRow/QualRow/index.tsx | 7 ++++--- src/components/MultiDisplay/index.tsx | 2 +- 4 files changed, 12 insertions(+), 11 deletions(-) diff --git a/src/components/MultiDisplay/EventRow/MessageRow/index.tsx b/src/components/MultiDisplay/EventRow/MessageRow/index.tsx index 96a3c9b..e7969ec 100644 --- a/src/components/MultiDisplay/EventRow/MessageRow/index.tsx +++ b/src/components/MultiDisplay/EventRow/MessageRow/index.tsx @@ -20,7 +20,7 @@ const MessageRow = ({ event, showLine }: { event: Event; showLine: 0 | 1 }) => { {/* Logo/Event Name Short Fader */}
{/* Logo */} -
+
{event.name} { {/* Text */} {event.nameShort || event.name} diff --git a/src/components/MultiDisplay/EventRow/MessageRow/styles.module.scss b/src/components/MultiDisplay/EventRow/MessageRow/styles.module.scss index 6650412..e3e9054 100644 --- a/src/components/MultiDisplay/EventRow/MessageRow/styles.module.scss +++ b/src/components/MultiDisplay/EventRow/MessageRow/styles.module.scss @@ -13,7 +13,7 @@ background-color: black; display: flex; flex-direction: row; - justify-content: center; + justify-content: space-around; align-items: center; &>span { @@ -23,19 +23,19 @@ .messageText { text-align: center; - width: 60vw; + width: 75vw !important; font-weight: bold; } .faderContainer { - width: 30vw; + width: 25vw; height: 22vh; &>* { position: absolute; transition: all ease .5s; text-align: center; - width: 30vw; + width: 25vw; top: 0; font-weight: bold; align-items: center; diff --git a/src/components/MultiDisplay/EventRow/QualRow/index.tsx b/src/components/MultiDisplay/EventRow/QualRow/index.tsx index cead738..9d701a3 100644 --- a/src/components/MultiDisplay/EventRow/QualRow/index.tsx +++ b/src/components/MultiDisplay/EventRow/QualRow/index.tsx @@ -182,9 +182,10 @@ const QualRow = ({ {loadingState === 'error' && case1 ? 'Failed to fetch matches' - : loadingState === 'loading' - ? 'Loading Matches...' - : 'Waiting for schedule to be posted...'} + : loadingState === 'loading' && !qualMatches?.length + ? 'Waiting for schedule to be posted...' + : 'Loading Matches...' + }
diff --git a/src/components/MultiDisplay/index.tsx b/src/components/MultiDisplay/index.tsx index a843c7a..42feb7c 100644 --- a/src/components/MultiDisplay/index.tsx +++ b/src/components/MultiDisplay/index.tsx @@ -26,7 +26,7 @@ const MultiQueueing = () => { setShowLine((sl: 0 | 1) => (sl === 0 ? 1 : 0)); }, 5000); - const clockInterval = setInterval(() => setClock(calcClock()), 60000); + const clockInterval = setInterval(() => setClock(calcClock()), 10000); calcClock(); return () => { From 7bdc3dd91ad64267a1513d16e7411dd778269c99 Mon Sep 17 00:00:00 2001 From: Soren Zaiser Date: Tue, 2 Apr 2024 14:38:23 -0400 Subject: [PATCH 16/17] linttttttttttt --- .eslintrc.js | 17 +--- package.json | 3 +- .../EventRow/MessageRow/index.tsx | 85 +++++++++--------- .../EventRow/PlayoffRow/index.tsx | 89 ++++++++----------- .../MultiDisplay/EventRow/QualRow/index.tsx | 35 ++++---- .../MultiDisplay/EventRow/index.tsx | 20 ++--- src/models/MatchData.ts | 2 +- 7 files changed, 110 insertions(+), 141 deletions(-) diff --git a/.eslintrc.js b/.eslintrc.js index 3492dbc..a0336f8 100644 --- a/.eslintrc.js +++ b/.eslintrc.js @@ -3,25 +3,16 @@ module.exports = { env: { es6: true, }, - extends: [ - 'airbnb', - 'airbnb-typescript', - ], + extends: ['airbnb', 'airbnb-typescript'], parser: '@typescript-eslint/parser', parserOptions: { project: ['tsconfig.eslint.json'], sourceType: 'module', }, - ignorePatterns: [ - '/functions/lib/**/*', - '/build/**/*', - '**/node_modules', - ], - plugins: [ - '@typescript-eslint', - 'import', - ], + ignorePatterns: ['/functions/lib/**/*', '/build/**/*', '**/node_modules'], + plugins: ['@typescript-eslint', 'import'], rules: { + 'linebreak-style': 'off', 'no-console': 'off', 'import/extensions': [ 'error', diff --git a/package.json b/package.json index 38e4779..7f4952b 100644 --- a/package.json +++ b/package.json @@ -7,7 +7,8 @@ "build": "vite build", "serve": "sirv build --port 8080 --cors --single", "dev": "vite", - "lint": "eslint './src/**/*.{js,jsx,ts,tsx}' './functions/src/**/*.{js,ts}'" + "lint": "eslint './src/**/*.{js,jsx,ts,tsx}' './functions/src/**/*.{js,ts}'", + "lint-win": "eslint src/ functions/" }, "dependencies": { "@gmurph91/react-textfit": "^1.1.4", diff --git a/src/components/MultiDisplay/EventRow/MessageRow/index.tsx b/src/components/MultiDisplay/EventRow/MessageRow/index.tsx index e7969ec..929f64b 100644 --- a/src/components/MultiDisplay/EventRow/MessageRow/index.tsx +++ b/src/components/MultiDisplay/EventRow/MessageRow/index.tsx @@ -1,57 +1,56 @@ import { h } from 'preact'; import { Event } from '@shared/DbTypes'; -import styles from './styles.module.scss'; // @ts-ignore import { Textfit } from '@gmurph91/react-textfit'; +import styles from './styles.module.scss'; -const MessageRow = ({ event, showLine }: { event: Event; showLine: 0 | 1 }) => { - return ( +const MessageRow = ({ event, showLine }: { event: Event; showLine: 0 | 1 }) => ( +
-
- {/* Logo/Event Name Short Fader */} -
- {/* Logo */} -
- {event.name} -
- {/* Text */} - - - {event.nameShort || event.name} - - + {/* Logo/Event Name Short Fader */} +
+ {/* Logo */} +
+ {event.name}
- - {/* Message */} - - - {event.message || event.name} + {/* Text */} + + + {event.nameShort || event.name}
+ + {/* Message */} + + + {event.message || event.name} + +
- ); -}; +
+); export default MessageRow; diff --git a/src/components/MultiDisplay/EventRow/PlayoffRow/index.tsx b/src/components/MultiDisplay/EventRow/PlayoffRow/index.tsx index eb76163..efb8281 100644 --- a/src/components/MultiDisplay/EventRow/PlayoffRow/index.tsx +++ b/src/components/MultiDisplay/EventRow/PlayoffRow/index.tsx @@ -1,5 +1,5 @@ import { h, Fragment } from 'preact'; -import { QualMatch, Event, PlayoffMatch } from '@shared/DbTypes'; +import { Event, PlayoffMatch } from '@shared/DbTypes'; import { getDatabase, ref, @@ -7,16 +7,15 @@ import { off, // update, } from 'firebase/database'; -import styles from '../sharedStyles.module.scss'; // @ts-ignore import { Textfit } from '@gmurph91/react-textfit'; -import { Break, MatchOrBreak, PlayoffMatchData } from '@/models/MatchData'; -import AllianceFader from '../AllianceFader'; -import { useEffect, useState } from 'react'; -import MessageRow from '../MessageRow'; +import { useEffect, useState } from 'preact/hooks'; import DoubleEliminationBracketMapping, { BracketMatchNumber, } from '@shared/DoubleEliminationBracketMapping'; +import styles from '../sharedStyles.module.scss'; +import { PlayoffMatchData } from '@/models/MatchData'; +import MessageRow from '../MessageRow'; import { PlayoffMatchDisplay } from '@/components/PlayoffQueueing/PlayoffMatchDisplay'; type LoadingState = 'loading' | 'ready' | 'error' | 'noAutomatic'; @@ -37,16 +36,13 @@ const PlayoffRow = ({ // This row's matches const [results, setResults] = useState< - Partial> + Partial> >({}); // URL parameters const searchParams = new URLSearchParams(window.location.search); const useShortName = typeof searchParams.get('useShortName') === 'string'; - // This row's breaks - const [breaks, setBreaks] = useState([]); - // Matches to display // eslint-disable-next-line max-len const [displayMatches, setDisplayMatches] = useState({ @@ -58,11 +54,11 @@ const PlayoffRow = ({ useEffect(() => { const bracketRef = ref( getDatabase(), - `/seasons/${season}/bracket/${token}` + `/seasons/${season}/bracket/${token}`, ); onValue(bracketRef, (snap) => { setResults( - snap.val() as Partial> + snap.val() as Partial>, ); }); @@ -76,12 +72,12 @@ const PlayoffRow = ({ */ const updateMatches = (): void => { // Get the basic list of matches - const matchDisplays: PlayoffMatchDisplay[] = - DoubleEliminationBracketMapping.matches.map((m) => ({ - result: results ? results[m.number] ?? null : null, - match: m, - num: m?.number, - })); + // eslint-disable-next-line max-len + const matchDisplays: PlayoffMatchDisplay[] = DoubleEliminationBracketMapping.matches.map((m) => ({ + result: results ? results[m.number] ?? null : null, + match: m, + num: m?.number, + })); // TODO: Find a better way to do this? // TODO: Add multiple entries for finals with break between? @@ -103,15 +99,14 @@ const PlayoffRow = ({ }); // Get the last match that has a winner - let currentMatchIndex = - matchDisplays.reduce((v, m, i) => (m.result?.winner ? i : v), -1) + 1; + let currentMatchIndex = matchDisplays.reduce((v, m, i) => (m.result?.winner ? i : v), -1) + 1; console.log(currentMatchIndex); // We have no way of knowing when a break is over, so to reduce confusion never show a break // as the current match. If we're at the end of the matches we can show that if ( - matchDisplays[currentMatchIndex].customDisplayText && - matchDisplays.length - 1 > currentMatchIndex + matchDisplays[currentMatchIndex].customDisplayText + && matchDisplays.length - 1 > currentMatchIndex ) { currentMatchIndex += 1; } @@ -138,18 +133,6 @@ const PlayoffRow = ({ updateMatches(); }, [results]); - // Calculate Red alliance string - const getRedStr = (match: PlayoffMatch | null): string => { - if (!match) return ''; - return `${match.participants.Red1} ${match.participants.Red2} ${match.participants.Red3}`; - }; - - // Calculate Blue alliance string - const getBlueStr = (match: PlayoffMatch | null): string => { - if (!match) return ''; - return `${match.participants.Blue1} ${match.participants.Blue2} ${match.participants.Blue3}`; - }; - // Spread the match data const { currentMatch, nextMatch, queueingMatches } = displayMatches; @@ -203,10 +186,10 @@ const PlayoffRow = ({ {/* Use event short name */} {useShortName && (
- + {event.nameShort || event.name}
@@ -239,8 +222,8 @@ const PlayoffRow = ({ blue={getBlueStr(nextMatch)} showLine={showLine} /> - - + + */} )} @@ -249,25 +232,23 @@ const PlayoffRow = ({ {/* Queueing Matches */}
@@ -216,10 +213,10 @@ const QualRow = ({ {/* Use event short name */} {useShortName && (
- + {event.nameShort || event.name}
@@ -267,8 +264,8 @@ const QualRow = ({ {/* Queueing Matches */}
{clock}
{clock} On Field Up Next Queueing
{/* Multiple Queueing Matches */} - {queueingMatches.length > 1 && - queueingMatches.map((x) => { - return ( -
- - {x.customDisplayText ?? x?.num === 'F' - ? 'F' - : `M${x?.num}`} - - {/* TODO: Reenable when sync doesnt suck? + {queueingMatches.length > 1 + && queueingMatches.map((x) => ( +
+ + {x.customDisplayText ?? x?.num === 'F' + ? 'F' + : `M${x?.num}`} + + {/* TODO: Reenable when sync doesnt suck? */} -
- ); - })} +
+ ))} {/* Single Queueing Match */} {queueingMatches.length === 1 && queueingMatches[0] && ( @@ -275,13 +256,13 @@ const PlayoffRow = ({ {queueingMatches[0] && ( - {queueingMatches[0].customDisplayText ?? - queueingMatches[0]?.num === 'F' + {queueingMatches[0].customDisplayText + ?? queueingMatches[0]?.num === 'F' ? 'F' : `M${queueingMatches[0]?.num}`} - {/* TODO: Reenable when sync doesnt suck? + {/* TODO: Reenable when sync doesnt suck? - qualMatches?.find((x) => x.number === matchNumber) ?? null; + const getMatchByNumber = (matchNumber: number): QualMatch | null => qualMatches?.find((x) => x.number === matchNumber) ?? null; const updateMatches = (e: Event): void => { const matchNumber = e.currentMatchNumber; @@ -90,10 +88,9 @@ const QualRow = ({ try { // Make a new array of max queuing matches to display - const maxQ = - typeof e.options?.maxQueueingToShow === 'number' - ? e.options?.maxQueueingToShow - : 3; + const maxQ = typeof e.options?.maxQueueingToShow === 'number' + ? e.options?.maxQueueingToShow + : 3; const toFill = new Array(maxQ).fill(null); toFill.forEach((_, i) => { toFill[i] = i + 2; @@ -107,7 +104,7 @@ const QualRow = ({ // Add Queueing Matches toFill .map((x) => getMatchByNumber(matchNumber + x)) - .filter((x) => x !== null) as QualMatch[] + .filter((x) => x !== null) as QualMatch[], ); // See if there is an upcoming break @@ -180,12 +177,12 @@ const QualRow = ({ )} + {/* eslint-disable-next-line no-nested-ternary */} {loadingState === 'error' && case1 ? 'Failed to fetch matches' : loadingState === 'loading' && !qualMatches?.length ? 'Waiting for schedule to be posted...' - : 'Loading Matches...' - } + : 'Loading Matches...'}
{/* Multiple Queueing Matches */} - {queueingMatches.length > 1 && - queueingMatches.map((x) => { + {queueingMatches.length > 1 + && queueingMatches.map((x) => { // Is a match, not a break if (x && (x as QualMatch).number) { const match = x as QualMatch; @@ -297,8 +294,8 @@ const QualRow = ({ {/* Single Queueing Match */} {queueingMatches.length === 1 && queueingMatches[0] && ( <> - {queueingMatches[0] && - (queueingMatches[0] as QualMatch).number && ( + {queueingMatches[0] + && (queueingMatches[0] as QualMatch).number && ( {(queueingMatches[0] as QualMatch)?.number} @@ -311,7 +308,7 @@ const QualRow = ({ /> - )} + )} {/* Is a Break */} {nextMatch && (queueingMatches[0] as Break).message && ( diff --git a/src/components/MultiDisplay/EventRow/index.tsx b/src/components/MultiDisplay/EventRow/index.tsx index fff9863..aa6531b 100644 --- a/src/components/MultiDisplay/EventRow/index.tsx +++ b/src/components/MultiDisplay/EventRow/index.tsx @@ -28,7 +28,7 @@ const EventRow = ({ const [event, setEvent] = useState({} as any); useEffect(() => { - if (!token) return () => {}; + if (!token) return () => { }; const eventRef = ref(getDatabase(), `/seasons/${season}/events/${token}`); dbEventRef.current = eventRef; @@ -45,7 +45,7 @@ const EventRow = ({ <> {/* Beginning of Event */} {['Pending', 'AwaitingQualSchedule', 'QualsInProgress'].includes( - event.state + event.state, ) ? ( - ) : ( - - )} + ) : ( + + )} ); }; diff --git a/src/models/MatchData.ts b/src/models/MatchData.ts index d36745f..fd34fb1 100644 --- a/src/models/MatchData.ts +++ b/src/models/MatchData.ts @@ -1,5 +1,5 @@ -import { PlayoffMatchDisplay } from '@/components/PlayoffQueueing/PlayoffMatchDisplay'; import { QualMatch } from '@shared/DbTypes'; +import { PlayoffMatchDisplay } from '@/components/PlayoffQueueing/PlayoffMatchDisplay'; // TODO: this should be moved to DbTypes once the type is available export type Break = { From 22c6bba13c8b2a1a9704bccab61d84ed1352d76c Mon Sep 17 00:00:00 2001 From: Soren Zaiser Date: Tue, 2 Apr 2024 14:42:34 -0400 Subject: [PATCH 17/17] Update styles to not break other things --- .../EventRow/sharedStyles.module.scss | 9 -------- .../MultiDisplay/styles.module.scss | 21 ++++++++++++------- 2 files changed, 14 insertions(+), 16 deletions(-) diff --git a/src/components/MultiDisplay/EventRow/sharedStyles.module.scss b/src/components/MultiDisplay/EventRow/sharedStyles.module.scss index a74f158..ffb9a0a 100644 --- a/src/components/MultiDisplay/EventRow/sharedStyles.module.scss +++ b/src/components/MultiDisplay/EventRow/sharedStyles.module.scss @@ -5,15 +5,6 @@ $matchnumber-size: 18vh; $cell-vertical-negative: -3vh; - -tr { - color: #fafafa !important; -} - -tbody > tr { - height: 22vh; -} - .textCenter { text-align: center; } diff --git a/src/components/MultiDisplay/styles.module.scss b/src/components/MultiDisplay/styles.module.scss index dbaa9f5..26cee8c 100644 --- a/src/components/MultiDisplay/styles.module.scss +++ b/src/components/MultiDisplay/styles.module.scss @@ -9,12 +9,19 @@ $border-color: #222; height: 100vh; width: 100vw; overflow: hidden; -} + tr { + color: #fafafa !important; + } -hr { - margin: 0; - position: absolute; - width: 100vw; - border-width: 3px; - border: 3px solid white; + hr { + margin: 0; + position: absolute; + width: 100vw; + border-width: 3px; + border: 3px solid white; + } + + tbody>tr { + height: 22vh; + } }