Skip to content

Commit 112400c

Browse files
localized match schedule
1 parent 95eef7f commit 112400c

File tree

1 file changed

+82
-66
lines changed

1 file changed

+82
-66
lines changed

client/src/apps/match/MatchApp.tsx

Lines changed: 82 additions & 66 deletions
Original file line numberDiff line numberDiff line change
@@ -22,21 +22,14 @@ import {
2222
} from 'requests';
2323
import LinkButton from '../../components/LinkButton';
2424
import NumberInput from '../../components/NumberInput';
25-
import TeamDropdown from '../../components/TeamDropdown';
2625
import MultiButton from '../../components/MultiButton';
2726
import Checkbox from '../../components/Checkbox';
2827
import TextInput from '../../components/TextInput';
2928
import HoldButton from '../../components/HoldButton';
29+
import SignIn from '../../components/SignIn';
3030
import { useStatus } from '../../lib/useStatus';
3131
import { useQueue } from '../../lib/useQueue';
3232
import { usePreventUnload } from '../../lib/usePreventUnload';
33-
import { useLocalStorage } from '../../lib/useLocalStorage';
34-
import {
35-
getOrCreateTabletId,
36-
TABLET_SLOT_STORAGE_KEY,
37-
formatTabletSlotLabel,
38-
isAssignableRobotPosition,
39-
} from '../../lib/tabletId';
4033
import scheduleFile from '../../assets/matchSchedule.json';
4134
import { formatMatchTime, gameConfig } from '../../lib/gameConfig';
4235

@@ -95,6 +88,16 @@ const matchTimelineSegments: MatchTimelineSegment[] = gameConfig.segments.map(
9588
);
9689

9790
const schedule = scheduleFile as MatchSchedule;
91+
const scheduleMatchNumbers = Object.keys(schedule)
92+
.map(value => Number.parseInt(value, 10))
93+
.filter(Number.isFinite)
94+
.sort((a, b) => a - b);
95+
const firstScheduledMatchNumber = scheduleMatchNumbers[0];
96+
97+
function nextScheduledMatchNumber(matchNumber: number | undefined) {
98+
if (matchNumber == undefined) return firstScheduledMatchNumber;
99+
return scheduleMatchNumbers.find(value => value > matchNumber) ?? matchNumber + 1;
100+
}
98101

99102
const autoStartingOptions: Array<{ label: string; value: AutoStartingPosition | null }> = [
100103
{ label: 'Left', value: 'left' },
@@ -408,15 +411,13 @@ function buildActionTimelineFromTicks(ticks: ActionTick[]): MatchData['actionTim
408411
function MatchApp() {
409412
usePreventUnload();
410413
const [sendQueue, sendAll, queue, sending] = useQueue();
411-
const [tabletId] = useState(getOrCreateTabletId);
412-
const [tabletSlot] = useLocalStorage<RobotPosition | null>(
413-
null,
414-
TABLET_SLOT_STORAGE_KEY
415-
);
416414
const [teamNumber, setTeamNumber] = useState<number>();
417-
const [matchNumber, setMatchNumber] = useState<number>();
415+
const [matchNumber, setMatchNumber] = useState<number | undefined>(
416+
firstScheduledMatchNumber
417+
);
418418
const [scouterName, setScouterName] = useState('');
419419
const [robotPosition, setRobotPosition] = useState<RobotPosition>();
420+
const [signedIn, setSignedIn] = useState(false);
420421
const [showCheck, setShowCheck] = useState(false);
421422

422423
const [robotAbsent, setRobotAbsent] = useState(false);
@@ -546,12 +547,8 @@ function MatchApp() {
546547
[actionTicks]
547548
);
548549

549-
const assignedRobotPosition = isAssignableRobotPosition(tabletSlot)
550-
? tabletSlot
551-
: undefined;
552-
const hasTabletAssignment = assignedRobotPosition != undefined;
553550
const canTrackActions =
554-
hasTabletAssignment && isRunning && !robotAbsent && remainingSec > 0;
551+
isRunning && !robotAbsent && remainingSec > 0;
555552
const sectionClass = 'rounded-2xl border border-white/10 bg-[#1d2433]/95 p-4 shadow-lg shadow-black/25';
556553
const inputClass =
557554
'mt-1 w-full rounded-lg border border-white/15 bg-[#0f1522] px-3 py-2 text-sm text-white outline-none focus:border-[#48c55c]/60 focus:ring-2 focus:ring-[#48c55c]/30';
@@ -567,17 +564,7 @@ function MatchApp() {
567564
);
568565
};
569566

570-
useStatus(tabletId, robotPosition, matchNumber, scouterName);
571-
572-
useEffect(() => {
573-
if (!assignedRobotPosition) {
574-
setRobotPosition(undefined);
575-
setScouterName('');
576-
return;
577-
}
578-
setRobotPosition(assignedRobotPosition);
579-
setScouterName(formatTabletSlotLabel(assignedRobotPosition));
580-
}, [assignedRobotPosition]);
567+
useStatus('', robotPosition, matchNumber, scouterName);
581568

582569
useEffect(() => {
583570
if (!schedule || !robotPosition || matchNumber == undefined) {
@@ -977,11 +964,25 @@ function MatchApp() {
977964
setScrubbingTimeline(false);
978965
};
979966

980-
const handleStartNewMatch = () => {
981-
if (!hasTabletAssignment) {
982-
alert('This tablet is unassigned. Open Admin and set a tablet slot first.');
967+
const handleSignIn = () => {
968+
const trimmedName = scouterName.trim();
969+
if (!trimmedName) {
970+
alert('Enter your name before signing in.');
983971
return;
984972
}
973+
if (!robotPosition) {
974+
alert('Pick your scout position before signing in.');
975+
return;
976+
}
977+
978+
setScouterName(trimmedName);
979+
setSignedIn(true);
980+
if (matchNumber == undefined) {
981+
setMatchNumber(firstScheduledMatchNumber);
982+
}
983+
};
984+
985+
const handleStartNewMatch = () => {
985986
resetScoutingFields();
986987
setIsRunning(true);
987988
};
@@ -992,10 +993,6 @@ function MatchApp() {
992993
};
993994

994995
const handlePauseResume = () => {
995-
if (!hasTabletAssignment) {
996-
alert('This tablet is unassigned. Open Admin and set a tablet slot first.');
997-
return;
998-
}
999996
if (isRunning) {
1000997
endActionHold('shoot');
1001998
endActionHold('pass');
@@ -1006,8 +1003,14 @@ function MatchApp() {
10061003
};
10071004

10081005
const handleSubmit = () => {
1009-
if (robotPosition == undefined || matchNumber == undefined || teamNumber == undefined) {
1010-
alert('Check tablet slot assignment, match number, and team number');
1006+
if (
1007+
!signedIn ||
1008+
!scouterName.trim() ||
1009+
robotPosition == undefined ||
1010+
matchNumber == undefined ||
1011+
teamNumber == undefined
1012+
) {
1013+
alert('Check sign-in, match number, and scheduled team number.');
10111014
return;
10121015
}
10131016
if (activeHoldsRef.current.shoot || activeHoldsRef.current.pass) {
@@ -1048,10 +1051,38 @@ function MatchApp() {
10481051
sendQueue('/data/match', data);
10491052
setShowCheck(true);
10501053
setTimeout(() => setShowCheck(false), 1800);
1051-
setMatchNumber(prev => (prev == undefined ? prev : prev + 1));
1054+
setMatchNumber(prev => nextScheduledMatchNumber(prev));
10521055
handleResetMatch();
10531056
};
10541057

1058+
if (!signedIn) {
1059+
return (
1060+
<div className='min-h-screen bg-gradient-to-b from-[#151a25] via-[#111722] to-[#0b111a] pb-8 text-sm text-white'>
1061+
<main className='mx-auto flex min-h-screen w-full max-w-5xl flex-col items-center justify-center gap-4 px-4 pb-10 pt-5 md:px-6'>
1062+
<section className={`${sectionClass} w-full max-w-2xl text-center`}>
1063+
<h1 className='text-xl font-semibold text-[#48c55c]'>Match Scouting Sign-In</h1>
1064+
<p className='mt-2 text-xs text-gray-300'>
1065+
Choose your scout position once, then this app auto-fills team
1066+
numbers from the hardcoded schedule using match number + position.
1067+
</p>
1068+
</section>
1069+
1070+
<SignIn
1071+
scouterName={scouterName}
1072+
onChangeScouterName={setScouterName}
1073+
robotPosition={robotPosition}
1074+
onChangeRobotPosition={setRobotPosition}
1075+
onSubmit={handleSignIn}
1076+
/>
1077+
1078+
<LinkButton link='/' className='snap-none'>
1079+
<MaterialSymbol icon='home' size={38} fill grade={200} color='green' />
1080+
</LinkButton>
1081+
</main>
1082+
</div>
1083+
);
1084+
}
1085+
10551086
return (
10561087
<div className='min-h-screen bg-gradient-to-b from-[#151a25] via-[#111722] to-[#0b111a] pb-8 text-sm text-white'>
10571088
{showCheck && (
@@ -1070,40 +1101,24 @@ function MatchApp() {
10701101
<div>
10711102
<h1 className='text-xl font-semibold text-[#48c55c]'>Match Scouting</h1>
10721103
<p className='mt-1 text-xs text-gray-400'>
1073-
{scouterName || 'Unassigned Tablet'}{' '}
1104+
{scouterName || 'Scout Not Signed In'}{' '}
10741105
{robotPosition ? `(${robotPosition})` : ''}
10751106
</p>
1076-
<p className='text-[11px] text-gray-500'>
1077-
Tablet ID: {tabletId}
1078-
{hasTabletAssignment ? ' (assigned)' : ' (no assignment)'}
1079-
</p>
10801107
</div>
10811108

10821109
<div className='flex items-center gap-2'>
1110+
<button
1111+
type='button'
1112+
onClick={() => setSignedIn(false)}
1113+
className='rounded-lg bg-[#3a4254] px-3 py-2 text-xs font-semibold text-white'>
1114+
Switch Scout
1115+
</button>
10831116
<LinkButton link='/' className='snap-none'>
10841117
<MaterialSymbol icon='home' size={38} fill grade={200} color='green' />
10851118
</LinkButton>
1086-
<LinkButton link='/admin' className='snap-none'>
1087-
<MaterialSymbol
1088-
icon='admin_panel_settings'
1089-
size={36}
1090-
fill
1091-
grade={200}
1092-
color='orange'
1093-
/>
1094-
</LinkButton>
10951119
</div>
10961120
</header>
10971121

1098-
{!hasTabletAssignment && (
1099-
<section className='rounded-2xl border border-yellow-400/50 bg-yellow-900/30 p-4'>
1100-
<p className='text-sm text-yellow-100'>
1101-
This tablet has no slot assignment. Open Admin on this tablet and set
1102-
`This Tablet Slot` before scouting matches.
1103-
</p>
1104-
</section>
1105-
)}
1106-
11071122
<section className={sectionClass}>
11081123
<h2 className='text-base font-semibold text-[#48c55c]'>Overview</h2>
11091124
<div className='mt-3 grid gap-3 md:grid-cols-2'>
@@ -1120,8 +1135,8 @@ function MatchApp() {
11201135
</div>
11211136
<div>
11221137
<p className='text-xs uppercase tracking-wide text-gray-300'>Team Number</p>
1123-
<div className='mt-1 rounded-lg border border-white/10 bg-[#0f1522] px-2 py-2'>
1124-
<TeamDropdown value={teamNumber} onChange={setTeamNumber} />
1138+
<div className='mt-1 rounded-lg border border-white/10 bg-[#0f1522] px-3 py-2 text-sm font-semibold text-white'>
1139+
{teamNumber ?? 'No scheduled team for selected match/position'}
11251140
</div>
11261141
</div>
11271142
</div>
@@ -1149,7 +1164,8 @@ function MatchApp() {
11491164
<span className='ml-1.5'>Robot Absent</span>
11501165
</Checkbox>
11511166
<p className='text-gray-400'>
1152-
Team auto-fills from schedule using match number + tablet slot.
1167+
Team auto-fills from hardcoded schedule using match number + scout
1168+
position.
11531169
</p>
11541170
</div>
11551171
</section>

0 commit comments

Comments
 (0)