Skip to content

Commit 93c93d7

Browse files
Merge branch 'main' into check-in
2 parents cade327 + 1e15e6f commit 93c93d7

33 files changed

+1177
-313
lines changed

components/Container.tsx

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,10 @@ const api = new ClientAPI("gearboxiscool");
1717
type ContainerProps = {
1818
children: ReactNode;
1919
requireAuthentication: boolean;
20-
hideMenu: boolean;
20+
/**
21+
* Hides the button to open the sidebar.
22+
*/
23+
hideMenu?: boolean;
2124
notForMobile?: boolean | undefined;
2225
};
2326

@@ -134,7 +137,7 @@ export default function Container(props: ContainerProps) {
134137
<div className="drawer-content">
135138
<div className=" sm:w-full h-16 bg-base-200 flex flex-row items-center justify-between sticky top-0 z-10">
136139
<div className="flex flex-row items-center sm:justify-center">
137-
{authenticated && !props.hideMenu ? (
140+
{authenticated && !(props.hideMenu ?? false) ? (
138141
<label htmlFor="menu" className="btn btn-ghost drawer-button">
139142
<BiMenu className="text-3xl" />
140143
</label>

components/Footer.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -56,7 +56,7 @@ export default function Footer() {
5656
></MdAlternateEmail>
5757
Contact
5858
</a>
59-
<a className="link link-hover" href={"https://discord.gg/ha7AnqxFDD"}>
59+
<a className="link link-hover" href="https://discord.gg/ha7AnqxFDD">
6060
<FaBug className="inline mr-1" size={16}></FaBug>
6161
Bug Report/Feature Request
6262
</a>

components/Loading.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ import { BsGearFill } from "react-icons/bs"
22

33

44
export default function Loading(props: {size?: number, className?: string, bg?: string, fill?: string}) {
5-
return <div className={`skeleton w-full h-full flex items-center justify-center ${props.bg} ${props.className}`}>
5+
return <div className={`w-full h-full flex items-center justify-center ${props.bg ?? "skeleton"} ${props.className}`}>
66
<BsGearFill size={props.size ?? 64} className={`${props.fill ?? "text-white"} animate-spin-slow`} />
77
</div>
88
}

components/stats/Picklist.tsx

Lines changed: 30 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,8 @@ function removeTeamFromPicklist(team: CardData, picklists: Picklist[]) {
3939
picklist.update(picklist);
4040
}
4141

42-
function TeamCard(props: { cardData: CardData, draggable: boolean, picklist?: Picklist, rank?: number, lastRank?: number, width?: string, height?: string}) {
42+
function TeamCard(props: { cardData: CardData, draggable: boolean, picklist?: Picklist, rank?: number, lastRank?: number,
43+
width?: string, height?: string}) {
4344
const { number: teamNumber, picklistIndex: picklist } = props.cardData;
4445

4546
const [{ isDragging }, dragRef] = useDrag({
@@ -165,7 +166,14 @@ const api = new ClientAPI("gearboxiscool");
165166

166167
export default function PicklistScreen(props: { teams: number[], reports: Report[], expectedTeamCount: number, picklistId: string }) {
167168
const [picklists, setPicklists] = useState<Picklist[]>([]);
168-
const [loadingPicklists, setLoadingPicklists] = useState(false);
169+
170+
enum LoadState {
171+
NotLoaded,
172+
Loading,
173+
Loaded
174+
}
175+
176+
const [loadingPicklists, setLoadingPicklists] = useState(LoadState.NotLoaded);
169177

170178
const teams = props.teams.map((team) => ({ number: team }));
171179

@@ -197,26 +205,26 @@ export default function PicklistScreen(props: { teams: number[], reports: Report
197205
}
198206

199207
useEffect(() => {
200-
if (picklists.length > 0 || loadingPicklists) return;
208+
if (loadingPicklists !== LoadState.NotLoaded) return;
201209

202-
setLoadingPicklists(true);
210+
setLoadingPicklists(LoadState.Loading);
203211
api.getPicklist(props.picklistId).then((picklistDict) => {
204-
setPicklists(Object.entries(picklistDict.picklists).map((picklist, index) => {
205-
const newPicklist: Picklist = {
206-
index,
207-
name: picklist[0],
208-
teams: picklist[1].map((team: number) => ({ number: team })),
209-
update: updatePicklist
210-
};
211-
212-
for (const team of newPicklist.teams) {
213-
team.picklistIndex = newPicklist.index;
214-
}
215-
216-
return newPicklist;
217-
}));
218-
219-
setLoadingPicklists(false);
212+
setPicklists(Object.entries(picklistDict.picklists).map((picklist, index) => {
213+
const newPicklist: Picklist = {
214+
index,
215+
name: picklist[0],
216+
teams: picklist[1].map((team: number) => ({ number: team })),
217+
update: updatePicklist
218+
};
219+
220+
for (const team of newPicklist.teams) {
221+
team.picklistIndex = newPicklist.index;
222+
}
223+
224+
return newPicklist;
225+
}));
226+
227+
setLoadingPicklists(LoadState.Loaded);
220228
});
221229
});
222230

@@ -239,7 +247,7 @@ export default function PicklistScreen(props: { teams: number[], reports: Report
239247

240248
<div className="w-full h-[30rem] px-4 py-2 flex flex-row space-x-3">
241249
{
242-
loadingPicklists
250+
loadingPicklists === LoadState.Loading
243251
? <div className="w-full h-full flex items-center justify-center">
244252
<div className="loading loading-spinner" />
245253
</div>
@@ -258,7 +266,7 @@ export default function PicklistScreen(props: { teams: number[], reports: Report
258266
}
259267
</div>
260268

261-
{ !loadingPicklists &&
269+
{ loadingPicklists !== LoadState.Loading &&
262270
<button
263271
className="btn btn-circle btn-lg btn-primary absolute right-10 bottom-[21rem] animate-pulse font-bold "
264272
onClick={addPicklist}

components/stats/SmallGraph.tsx

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -111,8 +111,6 @@ export default function SmallGraph(props: { selectedReports: Report[], team: num
111111
return <></>;
112112
}
113113

114-
console.log(datapoints);
115-
116114
return (
117115
<div className="w-full h-2/5 bg-base-300 rounded-lg p-4">
118116
<h1 className="text-2xl font-semibold inline mr-4">Graph</h1>

components/stats/TeamPage.tsx

Lines changed: 39 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import { Competition, Defense, Drivetrain, IntakeTypes, Pitreport, Report, SwerveLevel } from "@/lib/Types";
1+
import { Competition, Defense, Drivetrain, IntakeTypes, Pitreport, Report, SubjectiveReport, SwerveLevel } from "@/lib/Types";
22
import { useEffect, useState } from "react";
33

44
import {
@@ -109,7 +109,9 @@ function TeamCard(props: {
109109
<span className={`${props.rank === 1 && "drop-shadow-glowStrong"}`}>#{props.number}</span>
110110
<div className={`badge badge-${badgeColor} text-2xl p-3`}>{props.rank}{rankSuffix}</div>
111111
</h2>
112-
<p>Avg Points: {avgPoints} ({pointsDiffFromAvgFormatted})</p>
112+
<p>Avg Points: {avgPoints}{" "}
113+
<span className="tooltip" data-tip="Difference from comp-wide average">({pointsDiffFromAvgFormatted})</span>
114+
</p>
113115
<div className="card-actions">
114116
<div className={`badge badge-sm badge-${defenseBadgeColor}`}>
115117
{defense} Defense
@@ -162,66 +164,69 @@ function TeamCard(props: {
162164
);
163165
}
164166

165-
export default function TeamPage(props: { reports: Report[], pitReports: Pitreport[]}) {
167+
export default function TeamPage(props: { reports: Report[], pitReports: Pitreport[], subjectiveReports: SubjectiveReport[] }) {
166168
const reports = props.reports;
167169
const pitReports: { [key: number]: Pitreport } = {};
168-
169-
const [associatingTeams, setAssociatingTeams] = useState(true);
170170
const [teamReports, setTeamReports] = useState<{ [key: number]: Report[] }>(
171171
{}
172172
);
173+
const [teamSubjectiveReports, setTeamSubjectiveReports] = useState<{ [key: number]: SubjectiveReport[] }>({});
173174

174175
const teamNumbers = Object.keys(teamReports);
175176

176-
const [teamRanking, setTeamRanking] = useState<string[]>([]);
177-
178177
const [selectedTeam, setSelectedTeam] = useState<number>();
179178
const selectedReports = teamReports[selectedTeam ? selectedTeam : 0];
180179

181180
const associateTeams = () => {
182-
setAssociatingTeams(true);
183-
181+
const newTeamReports: typeof teamReports = {};
184182
reports.forEach((report) => {
185-
if (!(report.robotNumber in teamReports)) {
186-
teamReports[report.robotNumber] = [report];
183+
if (!(report.robotNumber in newTeamReports)) {
184+
newTeamReports[report.robotNumber] = [report];
187185
} else {
188-
teamReports[report.robotNumber].push(report);
186+
newTeamReports[report.robotNumber].push(report);
189187
}
190188
});
191-
192-
setAssociatingTeams(false);
189+
setTeamReports(newTeamReports);
193190
};
194191

192+
useEffect(() => {
193+
const subjectiveReports: typeof teamSubjectiveReports = {};
194+
props.subjectiveReports.forEach((subjectiveReport) => {
195+
for (const teamNumber of Object.keys(subjectiveReport.robotComments)) {
196+
if (!Object.keys(subjectiveReports).includes(teamNumber)) {
197+
subjectiveReports[Number(teamNumber)] = [subjectiveReport];
198+
} else {
199+
subjectiveReports[Number(teamNumber)].push(subjectiveReport);
200+
}
201+
}
202+
});
203+
setTeamSubjectiveReports(subjectiveReports);
204+
}, [props.subjectiveReports]);
205+
195206
const pointTotals = reports.map((report) => TotalPoints([report]));
196207
const avgPoints = AveragePoints(reports);
197208
const stDev = StandardDeviation(pointTotals);
198209

199-
const rankTeams = () => {
200-
const ranked = Object.keys(teamReports).sort((a, b) => {
201-
const a1 = AveragePoints(teamReports[Number(a)]);
202-
const b1 = AveragePoints(teamReports[Number(b)]);
203-
if (a1 < b1) {
204-
return 1;
205-
} else if (a1 > b1) {
206-
return -1;
207-
}
208-
return 0;
209-
});
210-
setTeamRanking(ranked);
211-
};
212-
213210
useEffect(() => {
214-
if (teamNumbers.length < 1) {
215211
associateTeams();
216-
rankTeams();
217-
}
218-
});
212+
}, [reports]);
219213

220214
// Associate pit reports
221215
props.pitReports.forEach((pitReport) => {
222216
pitReports[pitReport.teamNumber] = pitReport;
223217
});
224218

219+
const teamRanking = Object.keys(teamReports).sort((a, b) => {
220+
const a1 = AveragePoints(teamReports[Number(a)]);
221+
const b1 = AveragePoints(teamReports[Number(b)]);
222+
if (a1 < b1) {
223+
return 1;
224+
} else if (a1 > b1) {
225+
return -1;
226+
}
227+
return 0;
228+
});
229+
225230
return (
226231
<div className="w-full h-min flex flex-row space-x-4">
227232
<div className="w-1/5 h-[50rem] flex flex-col space-y-4 overflow-y-scroll">
@@ -233,9 +238,7 @@ export default function TeamPage(props: { reports: Report[], pitReports: Pitrepo
233238
reports={teamReports[Number(number)]}
234239
pitReport={pitReports[Number(number)]}
235240
rank={index + 1}
236-
onClick={() => {
237-
setSelectedTeam(Number(number));
238-
}}
241+
onClick={() => setSelectedTeam(Number(number))}
239242
compAvgPoints={avgPoints}
240243
compPointsStDev={stDev}
241244
></TeamCard>
@@ -246,6 +249,7 @@ export default function TeamPage(props: { reports: Report[], pitReports: Pitrepo
246249
selectedReports={selectedReports}
247250
selectedTeam={selectedTeam}
248251
pitReport={pitReports[selectedTeam ?? 0]}
252+
subjectiveReports={teamSubjectiveReports[selectedTeam ?? 0]}
249253
></TeamStats>
250254

251255
<div className="w-5/12 h-full flex flex-col space-y-4">

0 commit comments

Comments
 (0)