Skip to content

Commit

Permalink
Fixed build issues
Browse files Browse the repository at this point in the history
  • Loading branch information
renatodellosso committed Aug 10, 2024
1 parent f3d0016 commit 7a81314
Show file tree
Hide file tree
Showing 14 changed files with 50 additions and 246 deletions.
2 changes: 0 additions & 2 deletions components/Footer.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -74,8 +74,6 @@ export default function Footer() {
className="link link-hover"
href="https://www.decaturrobotics.org/our-team"
>
<FaList className="inline mr-1" size={16}></FaList>About Us
</a>
<FaList className="inline mr-1" size={16}/>About Us
</Link>
<div>Version {new Date(+process.env.NEXT_PUBLIC_BUILD_TIME).toISOString()}</div>
Expand Down
7 changes: 6 additions & 1 deletion components/PitReport.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -10,10 +10,12 @@ import ImageUpload from "./forms/ImageUpload";
import Card from "./Card";
import { getCompFromLocalStorage, updateCompInLocalStorage } from "@/lib/client/offlineUtils";
import QRCode from "react-qr-code";
import { Analytics } from "@/lib/client/Analytics";

const api = new ClientAPI("gearboxiscool");

export default function PitReportForm(props: { pitReport: Pitreport, layout: FormLayout<PitReportData>, compId?: string }) {
export default function PitReportForm(props: { pitReport: Pitreport, layout: FormLayout<PitReportData>, compId?: string,
usersteamNumber?: number, compName?: string, username?: string }) {
const { session } = useCurrentSession();

const [pitreport, setPitreport] = useState(props.pitReport);
Expand Down Expand Up @@ -60,6 +62,9 @@ export default function PitReportForm(props: { pitReport: Pitreport, layout: For
};
});
})
.then(() => {
Analytics.pitReportSubmitted(pitreport.teamNumber, props.usersteamNumber ?? -1, props.compName ?? "Unknown", props.username ?? "Unknown");
})
.finally(() => {
location.href = location.href.substring(0, location.href.lastIndexOf("/pit"));
});
Expand Down
13 changes: 9 additions & 4 deletions components/StatsPage.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,8 @@ import { useState, useEffect } from "react";
import Container from "@/components/Container";
import PicklistScreen from "./stats/Picklist";
import TeamPage from "./stats/TeamPage";
import PredictionScreen from "./stats/PredictionScreen";
import { games } from "@/lib/games";

const api = new ClientAPI("gearboxiscool");

Expand Down Expand Up @@ -75,6 +77,7 @@ export default function Stats(props: StatsPageProps) {
requireAuthentication={false}
hideMenu={true}
notForMobile={true}
title="Stats"
>
<div className="flex flex-row items-center p-1 pl-2 space-x-2 bg-base-200">
{props.competition?.tbaId !== NotLinkedToTba &&
Expand Down Expand Up @@ -115,7 +118,7 @@ export default function Stats(props: StatsPageProps) {
page === 2 ? "tab-active" : ""
}`}
onClick={() => {
// setPage(2);
setPage(2);
}}
>
Prediction (Coming Soon!)
Expand All @@ -136,10 +139,12 @@ export default function Stats(props: StatsPageProps) {
gameId={props.competition?.gameId ?? defaultGameId} />
)}
{page === 1
? <PicklistScreen
&& <PicklistScreen
teams={Array.from(teams)} reports={reports} expectedTeamCount={props.competition.pitReports.length}
picklist={props.picklists} compId={props.competition._id ?? ""} />
: <></>
picklist={props.picklists} compId={props.competition._id ?? ""} />
}
{
page === 2 && <PredictionScreen reports={reports} teams={Array.from(teams)} game={games[props.competition.gameId]} />
}
</Container>
);
Expand Down
12 changes: 11 additions & 1 deletion components/SubjectiveReportForm.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -9,10 +9,11 @@ import React, { createRef, FormEvent, useState } from "react";
import Loading from "./Loading";
import Card from "./Card";
import QRCode from "react-qr-code";
import { Analytics } from "@/lib/client/Analytics";

const api = new ClientAPI("gearboxiscool");

export default function SubjectiveReportForm(props: { match: Match, compId?: string }) {
export default function SubjectiveReportForm(props: { match: Match, compId?: string, teamNumber?: number, compName?: string }) {
const router = useRouter();
const { teamSlug, seasonSlug, competitonSlug } = router.query;

Expand Down Expand Up @@ -84,6 +85,14 @@ export default function SubjectiveReportForm(props: { match: Match, compId?: str
comp.matches[match._id as string].subjectiveReports.push(subjectiveReport._id!);
});
})
.then(() => {
const teamsWithComments = [...(e.target as any)].map((element: any, index: number) =>
["Whole Match"].concat(match?.blueAlliance.concat(match.redAlliance).map((n) => n.toString()) ?? [])[index]
);

Analytics.subjectiveReportSubmitted(teamsWithComments, props.teamNumber ?? -1, props.compName ?? "Unknown Competition",
session.session.user?.name ?? "Unknown User");
})
.finally(() => {
if (location.href.includes("offline"))
location.href = `/offline/${props.compId}`;
Expand All @@ -94,6 +103,7 @@ export default function SubjectiveReportForm(props: { match: Match, compId?: str

// We have to use router as a dependency because it is only populated after the first render (during hydration)
useInterval(() => api.checkInForSubjectiveReport(match._id as string), 5000, [router]);

return (
<div className="flex flex-col items-center p-12 space-y-6">
{ !match
Expand Down
1 change: 1 addition & 0 deletions components/forms/Form.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ export type FormProps = {
fieldImagePrefix: string;
teamNumber: number;
compName: string;
compId: string;
};

export default function Form(props: FormProps) {
Expand Down
1 change: 1 addition & 0 deletions index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import fs from "fs";
import { App } from "@slack/bolt";
import SlackCommands from "./lib/SlackCommands";
import { IncomingMessage, ServerResponse, request } from "http";
import { startSlackApp } from "./lib/Slack";

console.log("Starting server...");

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -26,92 +26,16 @@ export default function Subjective(props: ResolvedUrlData) {
api.findMatchById(matchId as string).then(setMatch);
}, [match]);

return (
<Container requireAuthentication={true} hideMenu={false}>
{ match
? <SubjectiveReportForm match={match} />
: <div>Loading...</div>
}
</Container>
);

async function submit(e: React.FormEvent<HTMLFormElement>) {
e.preventDefault();

let valid = [...(e.target as any)].filter((element: any) => element.value).length > 0;
if (!valid) {
if (submitButtonRef.current) {
const btn = submitButtonRef.current;

btn.classList.add("btn-error");
btn.innerText = "Please fill out at least one field";
setTimeout(() => {
btn.classList.remove("btn-error");
btn.innerText = "Submit";
}, 1500);
}

return;
}

api.submitSubjectiveReport({
_id: undefined,
match: matchId as string,
matchNumber: match?.number ?? 0,
wholeMatchComment: (e.target as any)[0].value,
robotComments: Object.fromEntries(
[...(e.target as any)].slice(1).map((element: any, index: number) =>
[match?.blueAlliance.concat(match.redAlliance)[index], element.value])
),
submitter: undefined,
submitted: SubjectiveReportSubmissionType.NotSubmitted
}, session.session.user?._id!, teamSlug as string).then((res) => {
window.location.href = `/${teamSlug}/${seasonSlug}/${competitonSlug}`;
});

const teamsWithComments = [...(e.target as any)].map((element: any, index: number) =>
["Whole Match"].concat(match?.blueAlliance.concat(match.redAlliance).map((n) => n.toString()) ?? [])[index]
if (!match)
return (
<Container requireAuthentication={true} hideMenu={false} title="Subjective Scouting">
<div>Loading...</div>
</Container>
);

Analytics.subjectiveReportSubmitted(teamsWithComments, props.team?.number ?? -1, props.competition?.name ?? "Unknown Competition",
session.session.user?.name ?? "Unknown User");
}

// We have to use router as a dependency because it is only populated after the first render (during hydration)
useInterval(() => api.checkInForSubjectiveReport(matchId as string), 5000, [router]);

return (
<Container requireAuthentication={true} hideMenu={false} title={`${match?.number} | Subjective Scouting`}>
<div className="flex flex-col items-center p-12">
{ !match
?
<div className="loading loading-spinner"/>
:
<div className="card w-[80%] bg-base-200">
<div className="card-body">
<div className="card-title">
Match {match.number}
</div>
<form className="flex flex-col" onSubmit={submit}>
{
["Whole Match", ...match.blueAlliance, ...match.redAlliance].map((team, index) => (
<div key={index}>
<div className="label">
<span className={`label-text text-lg ${typeof(team) === "number"
&& (match.blueAlliance.includes(team) ? "text-blue-500" : "text-red-500")}`}>
{team}
</span>
</div>
<textarea className="input input-bordered w-full h-20" placeholder="Enter comments here..."/>
</div>
))
}
<button ref={submitButtonRef} className="btn btn-primary mt-6">Submit</button>
</form>
</div>
</div>
}
</div>
<SubjectiveReportForm match={match} compId={props.competition?._id} teamNumber={props.team?.number} compName={props.competition?.name} />
</Container>
);
}
Original file line number Diff line number Diff line change
Expand Up @@ -9,11 +9,10 @@ import { useCurrentSession } from "@/lib/client/useCurrentSession";
import { games } from "@/lib/games";
import { GameId } from "@/lib/client/GameId";
import { makeObjSerializeable } from "@/lib/client/ClientUtils";
import { FormLayout } from "@/lib/Layout";
import PitReportForm from "@/components/PitReport";
import { makeObjSerializeable } from "@/lib/Utils";
import { BlockElement, FormLayout, FormElement } from "@/lib/Layout";
import { Analytics } from "@/lib/client/Analytics";
import ClientAPI from "@/lib/client/ClientAPI";

const api = new ClientAPI("gearboxiscool");

Expand All @@ -22,148 +21,9 @@ export default function PitreportForm(props: { pitreport: Pitreport, layout: For
const hide = status === "authenticated";

return (
<Container requireAuthentication={false} hideMenu={!hide}>
<PitReportForm pitReport={props.pitreport} layout={props.layout} />
</Container>
);

const [pitreport, setPitreport] = useState(props.pitreport);

const setCallback = useCallback(
(key: any, value: boolean | string | number) => {
setPitreport((old) => {
let copy = structuredClone(old);
//@ts-expect-error
copy.data[key] = value;
return copy;
});
},
[]
);

async function submit() {
// Remove _id from object
const { _id, ...report } = pitreport;

await api.updatePitreport(props.pitreport?._id, {
...report,
submitted: true,
submitter: session.user?._id
});
location.href = location.href.substring(
0,
location.href.lastIndexOf("/pit")
);

Analytics.pitReportSubmitted(
props.pitreport.teamNumber,
props.teamNumber,
props.compName,
session.user?.name ?? "Unknown User"
);
}

function getComponent(element: FormElement<PitReportData>, isLastInHeader: boolean) {
const key = element.key as string;

if (element.type === "image")
return <ImageUpload report={pitreport} callback={setCallback} />

if (element.type === "boolean")
return <Checkbox label={element.label ?? element.key as string} dataKey={key} data={pitreport} callback={setCallback}
divider={!isLastInHeader} />

if (element.type === "number")
return (<>
<h1 className="font-semibold text-lg">{element.label}</h1>
<input
value={pitreport.data?.[key]}
onChange={(e) => setCallback(key, e.target.value)}
type="number"
className="input input-bordered"
placeholder={element.label}
/>
</>);

if (element.type === "string")
return (
<textarea
value={pitreport.data?.comments}
className="textarea textarea-primary w-[90%]"
placeholder="Say Something Important..."
onChange={(e) => {
setCallback("comments", e.target.value);
}}
/>
);

const entries = Object.entries(element.type!).map((entry, index) => {
const color = ["primary", "accent", "secondary"][index % 3];

return (
<>
<span>{entry[0]}</span>
<input
type="radio"
className={`radio radio-${color}`}
onChange={() =>
setCallback(key, entry[1] as boolean | string | number)
}
checked={pitreport.data?.[element.key as string] === entry[1]}
/>
</>
);
});

return (<>
<h1 className="font-semibold text-lg">{element.label}</h1>
<div className="grid grid-cols-2 translate-x-6 space-y-1">{entries}</div>
</>);
}

const components = Object.entries(props.layout).map(([header, elements]) => {
const inputs = elements.map((element, index) => {
if (!Array.isArray(element))
return getComponent(element as FormElement<PitReportData>, index === elements.length - 1);

const block = element as BlockElement<PitReportData>;
return block?.map((row, rowIndex) =>
row.map((element, elementIndex) =>
getComponent(element, elementIndex === row.length - 1)
)
);
});

return (
<div key={header}>
<h1 className="font-semibold text-lg">{header}</h1>
<div className="translate-x-10">
{inputs}
</div>
</div>
);
});

return (
<Container requireAuthentication={false} hideMenu={!hide} title={`${pitreport.teamNumber} | Pit Scouting`}>
<Flex mode="col" className="items-center w-screen h-full space-y-4">
<Card className="w-1/4" coloredTop="bg-accent">
<Flex center={true} mode="col">
<h1 className="text-4xl font-semibold">Pitscouting</h1>
<div className="divider"></div>
<h1 className="font-semibold text-2xl">
<FaRobot className="inline mr-2" size={30}></FaRobot>
Team <span className="text-accent">{pitreport.teamNumber}</span>
</h1>
</Flex>
</Card>
<Card>
{components}
<button className="btn btn-primary " onClick={submit}>
Submit
</button>
</Card>
</Flex>
<Container requireAuthentication={false} hideMenu={!hide} title={`${props.pitreport.teamNumber} | Pit Scouting`}>
<PitReportForm pitReport={props.pitreport} layout={props.layout} usersteamNumber={props.teamNumber}
compName={props.compName} username={session.user?.name} />
</Container>
);
}
Expand Down
Loading

0 comments on commit 7a81314

Please sign in to comment.