-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
40 changed files
with
4,777 additions
and
26 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,46 @@ | ||
import { MaterialSymbol } from 'react-material-symbols'; | ||
import LinkButton from '../../components/LinkButton'; | ||
import { useStatusRecieve } from '../../lib/useStatus'; | ||
import { ScouterTable } from './components/ScouterTable'; | ||
import { MatchTable } from './components/MatchTable'; | ||
//import { useFetchJson } from "../../lib/useFetch"; | ||
|
||
function AdminApp() { | ||
const status = useStatusRecieve(); | ||
|
||
// const [schedule] = useFetchJson<MatchSchedule>('/matchSchedule.json'); | ||
|
||
return ( | ||
<main className='flex h-screen w-screen select-none flex-col items-center text-center'> | ||
<h1 className='col-span-4 my-8 text-3xl'>Admin Interface</h1> | ||
|
||
<div className='fixed left-4 top-4 z-20 flex gap-2 rounded-md p-2'> | ||
<LinkButton link='/' className='snap-none'> | ||
<MaterialSymbol | ||
icon='home' | ||
size={60} | ||
fill | ||
grade={200} | ||
color='green' | ||
className='snap-none' | ||
/> | ||
</LinkButton> | ||
</div> | ||
|
||
<div className='grid grid-cols-2 items-center justify-center gap-4'> | ||
<div> | ||
<ScouterTable scouters={status.scouters} /> | ||
<p className='my-6'>Connected Tablets</p> | ||
</div> | ||
<div> | ||
<p>Match Display</p> | ||
<div className='table-container'> | ||
<MatchTable matches={status.matches}></MatchTable> | ||
</div> | ||
</div> | ||
</div> | ||
</main> | ||
); | ||
} | ||
|
||
export default AdminApp; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,27 @@ | ||
import { RobotPosition, SuperPosition } from 'requests'; | ||
import PositionCell from './PositionCell'; | ||
|
||
function MatchRow({ | ||
matchNumber, | ||
scouters, | ||
}: { | ||
matchNumber: string; | ||
scouters: Record<RobotPosition, { schedule: number; real: number[] }> & | ||
Record<SuperPosition, boolean>; | ||
}) { | ||
return ( | ||
<tr> | ||
<th>{matchNumber}</th> | ||
<PositionCell scouter={scouters.red_1} /> | ||
<PositionCell scouter={scouters.red_2} /> | ||
<PositionCell scouter={scouters.red_3} /> | ||
<PositionCell scouter={scouters.red_ss} /> | ||
<PositionCell scouter={scouters.blue_1} /> | ||
<PositionCell scouter={scouters.blue_2} /> | ||
<PositionCell scouter={scouters.blue_3} /> | ||
<PositionCell scouter={scouters.blue_ss} /> | ||
</tr> | ||
); | ||
} | ||
|
||
export default MatchRow; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,29 @@ | ||
import { StatusRecieve } from 'requests'; | ||
import MatchRow from './MatchRow'; | ||
|
||
function MatchTable({ matches }: { matches: StatusRecieve['matches'] }) { | ||
return ( | ||
<table className='match-status h-72 overflow-auto'> | ||
<thead> | ||
<tr> | ||
<th>Match</th> | ||
<th className='status-red col-span-1'>Red 1</th> | ||
<th className='status-red col-span-1'>Red 2</th> | ||
<th className='status-red col-span-1'>Red 3</th> | ||
<th className='status-red col-span-1'>Red SS</th> | ||
<th className='status-blue col-span-1'>Blue 1</th> | ||
<th className='status-blue col-span-1'>Blue 2</th> | ||
<th className='status-blue col-span-1'>Blue 3</th> | ||
<th className='status-blue col-span-1'>Blue SS</th> | ||
</tr> | ||
</thead> | ||
<tbody> | ||
{Object.entries(matches).map(([matchNumber, scouters]) => ( | ||
<MatchRow matchNumber={matchNumber} scouters={scouters} /> | ||
))} | ||
</tbody> | ||
</table> | ||
); | ||
} | ||
|
||
export { MatchTable }; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,24 @@ | ||
import { MaterialSymbol } from 'react-material-symbols'; | ||
|
||
function PositionCell({ | ||
scouter, | ||
}: { | ||
scouter: { schedule: number; real: number[] } | boolean; | ||
}) { | ||
const isBoolean = typeof scouter === 'boolean'; | ||
return ( | ||
<td | ||
className={`w-auto border-2 border-slate-700 text-center ${(isBoolean ? scouter : scouter.real.length > 0) ? 'bg-amber-400' : ''}`}> | ||
{isBoolean ? ( | ||
scouter && <MaterialSymbol icon='check' /> | ||
) : scouter.real.length === 0 ? ( | ||
scouter.schedule | ||
) : scouter.real.length === 1 ? ( | ||
scouter.real[0] | ||
) : ( | ||
<MaterialSymbol icon='warning' /> | ||
)} | ||
</td> | ||
); | ||
} | ||
export default PositionCell; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,60 @@ | ||
import { MaterialSymbol } from 'react-material-symbols'; | ||
import { StatusReport } from 'requests'; | ||
|
||
function BatteryLevelIcon(batteryLevel: number) { | ||
if (batteryLevel > 75) { | ||
return <MaterialSymbol icon='battery_full' className='mb-4 mr-3' />; | ||
} else if (batteryLevel > 50) { | ||
return <MaterialSymbol icon='battery_3_bar' className='mb-4 mr-3' />; | ||
} else if (batteryLevel > 25) { | ||
return <MaterialSymbol icon='battery_1_bar' className='mb-4 mr-3' />; | ||
} else { | ||
return <MaterialSymbol icon='battery_alert' className='mb-4 mr-3' />; | ||
} | ||
} | ||
function ScouterCard({ | ||
scouter, | ||
title, | ||
red = false, | ||
}: { | ||
scouter: StatusReport[]; | ||
title: string; | ||
red?: boolean; | ||
}) { | ||
return ( | ||
<div | ||
className={`${red ? 'border-red-900 bg-red-500' : 'border-blue-900 bg-blue-500'} content-center items-center rounded-md border-2 px-4 text-center text-lg text-white`}> | ||
<div className='mb-2 mt-4 font-semibold'>{title}</div> | ||
{scouter.length === 0 ? ( | ||
<MaterialSymbol icon='wifi_off' size={32} /> | ||
) : scouter.length === 1 ? ( | ||
<> | ||
<div className=''>{scouter[0].matchNumber}</div> | ||
<div>{scouter[0].scouterName}</div> | ||
<div> | ||
{BatteryLevelIcon( | ||
Math.floor((scouter[0].battery ?? 0) * 100) | ||
)} | ||
{Math.floor((scouter[0].battery ?? 0) * 100)}% | ||
</div> | ||
</> | ||
) : ( | ||
<> | ||
<div> | ||
{' '} | ||
<MaterialSymbol | ||
icon='warning' | ||
size={32} | ||
className='text-yellow-300' | ||
/> | ||
</div> | ||
{scouter.map(e => ( | ||
<div>{e.scouterName}</div> | ||
))} | ||
</> | ||
)} | ||
</div> | ||
); | ||
} | ||
|
||
export { ScouterCard }; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,37 @@ | ||
import { RobotPosition, StatusReport, SuperPosition } from 'requests'; | ||
import { ScouterCard } from './ScouterCard'; | ||
|
||
function ScouterTable({ scouters }: { scouters: StatusReport[] }) { | ||
const sortedScouter = Object.fromEntries( | ||
( | ||
[ | ||
'red_1', | ||
'red_2', | ||
'red_3', | ||
'blue_1', | ||
'blue_2', | ||
'blue_3', | ||
'red_ss', | ||
'blue_ss', | ||
] satisfies (RobotPosition | SuperPosition)[] | ||
).map(robotPosition => [ | ||
robotPosition, | ||
scouters.filter(scouter => scouter.robotPosition === robotPosition), | ||
]) | ||
) as Record<RobotPosition | SuperPosition, StatusReport[]>; | ||
|
||
return ( | ||
<div className='grid grid-cols-4 gap-2'> | ||
<ScouterCard scouter={sortedScouter.red_1} title='Red 1' red /> | ||
<ScouterCard scouter={sortedScouter.red_2} title='Red 2' red /> | ||
<ScouterCard scouter={sortedScouter.red_3} title='Red 3' red /> | ||
<ScouterCard scouter={sortedScouter.red_ss} title='Red SS' red /> | ||
<ScouterCard scouter={sortedScouter.blue_1} title='Blue 1' /> | ||
<ScouterCard scouter={sortedScouter.blue_2} title='Blue 2' /> | ||
<ScouterCard scouter={sortedScouter.blue_3} title='Blue 3' /> | ||
<ScouterCard scouter={sortedScouter.blue_ss} title='Blue SS' /> | ||
</div> | ||
); | ||
} | ||
|
||
export { ScouterTable }; |
Oops, something went wrong.