From 7a5c98927d13f7d0c51024db2696bd67621b3a43 Mon Sep 17 00:00:00 2001 From: renatodellosso Date: Mon, 30 Dec 2024 12:38:48 -0500 Subject: [PATCH 1/5] Fix constant report updates and match links not working --- components/competition/MatchScheduleCard.tsx | 4 ++-- components/forms/Form.tsx | 22 +++++++++++++++----- 2 files changed, 19 insertions(+), 7 deletions(-) diff --git a/components/competition/MatchScheduleCard.tsx b/components/competition/MatchScheduleCard.tsx index a3e8f0cc..2d72c4cf 100644 --- a/components/competition/MatchScheduleCard.tsx +++ b/components/competition/MatchScheduleCard.tsx @@ -198,7 +198,7 @@ export default function MatchScheduleCard(props: { 1000; return ( -

{report.robotNumber}

- + ); })} diff --git a/components/forms/Form.tsx b/components/forms/Form.tsx index 5ea60da8..95d1fa05 100644 --- a/components/forms/Form.tsx +++ b/components/forms/Form.tsx @@ -1,5 +1,5 @@ import { AllianceColor, Report, QuantData, FieldPos } from "@/lib/Types"; -import { useCallback, useState } from "react"; +import { useCallback, useEffect, useState } from "react"; import FormPage from "./FormPages"; import { useCurrentSession } from "@/lib/client/useCurrentSession"; import { FaArrowLeft, FaArrowRight } from "react-icons/fa"; @@ -14,6 +14,7 @@ import Slider from "./Sliders"; import { BlockElement, FormLayout, FormElement } from "@/lib/Layout"; import Loading from "../Loading"; import { Analytics } from "@/lib/client/Analytics"; +import useDynamicState from "@/lib/client/useDynamicState"; const api = new ClientApi(); @@ -32,6 +33,7 @@ export default function Form(props: FormProps) { const [page, setPage] = useState(0); const [formData, setFormData] = useState(props.report?.data); const [syncing, setSyncing] = useState(false); + const [changeNumber, setChangeNumber, getChangeNumber] = useDynamicState(0); const [submitting, setSubmitting] = useState(false); const alliance = props.report?.color; @@ -64,10 +66,20 @@ export default function Form(props: FormProps) { ); } + // Don't sync more than once every 500ms const sync = useCallback(async () => { - setSyncing(true); - await api.updateReport({ data: formData }, props.report?._id!); - setSyncing(false); + const newChangeNumber = changeNumber! + 1; + setChangeNumber(newChangeNumber); + + setTimeout(async () => { + getChangeNumber(async (currentNumber) => { + if (currentNumber !== newChangeNumber) return; + + setSyncing(true); + await api.updateReport({ data: formData }, props.report?._id!); + setSyncing(false); + }); + }, 500); }, [formData, props.report?._id]); const setCallback = useCallback( @@ -82,7 +94,7 @@ export default function Form(props: FormProps) { [sync], ); - useCallback(() => { + useEffect(() => { // Set all Nan values to 0 for (const key in formData) { if (typeof formData[key] === "number" && isNaN(formData[key])) { From 771fd76ba55928a1ff0818073c4c3a8c9dd0d181 Mon Sep 17 00:00:00 2001 From: renatodellosso Date: Mon, 30 Dec 2024 12:48:43 -0500 Subject: [PATCH 2/5] Better error logging for form submit failures --- components/forms/Form.tsx | 27 ++++++++++++++++++--------- 1 file changed, 18 insertions(+), 9 deletions(-) diff --git a/components/forms/Form.tsx b/components/forms/Form.tsx index 95d1fa05..3c55eeaf 100644 --- a/components/forms/Form.tsx +++ b/components/forms/Form.tsx @@ -15,6 +15,7 @@ import { BlockElement, FormLayout, FormElement } from "@/lib/Layout"; import Loading from "../Loading"; import { Analytics } from "@/lib/client/Analytics"; import useDynamicState from "@/lib/client/useDynamicState"; +import toast from "react-hot-toast"; const api = new ClientApi(); @@ -47,15 +48,17 @@ export default function Form(props: FormProps) { .submitForm(props.report?._id!, formData) .then(() => { console.log("Submitted form successfully!"); + + location.href = location.href.substring( + 0, + location.href.lastIndexOf("/"), + ); }) - .finally(() => { - if (location.href.includes("offline")) - location.href = `/offline/${props.compId}`; - else - location.href = location.href.substring( - 0, - location.href.lastIndexOf("/"), - ); + .catch((err) => { + console.error("Failed to submit form. Error:", err); + toast.error("Failed to submit form. Please try again. Error:", err); + + setSubmitting(false); }); Analytics.quantReportSubmitted( @@ -80,7 +83,13 @@ export default function Form(props: FormProps) { setSyncing(false); }); }, 500); - }, [formData, props.report?._id]); + }, [ + formData, + props.report?._id, + changeNumber, + getChangeNumber, + setChangeNumber, + ]); const setCallback = useCallback( (key: any, value: boolean | string | number | object) => { From 4e0def33a8eb35b886e8ca644d382dea8535a7be Mon Sep 17 00:00:00 2001 From: renatodellosso Date: Mon, 30 Dec 2024 12:55:32 -0500 Subject: [PATCH 3/5] Add error message display to form submit --- components/forms/Form.tsx | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/components/forms/Form.tsx b/components/forms/Form.tsx index 3c55eeaf..e6724d79 100644 --- a/components/forms/Form.tsx +++ b/components/forms/Form.tsx @@ -36,6 +36,7 @@ export default function Form(props: FormProps) { const [syncing, setSyncing] = useState(false); const [changeNumber, setChangeNumber, getChangeNumber] = useDynamicState(0); const [submitting, setSubmitting] = useState(false); + const [submitErrorMsg, setSubmitErrorMsg] = useState(); const alliance = props.report?.color; @@ -57,6 +58,7 @@ export default function Form(props: FormProps) { .catch((err) => { console.error("Failed to submit form. Error:", err); toast.error("Failed to submit form. Please try again. Error:", err); + setSubmitErrorMsg(err.toString()); setSubmitting(false); }); @@ -287,6 +289,11 @@ export default function Form(props: FormProps) { "Submit" )} + {submitErrorMsg ? ( +

{submitErrorMsg}

+ ) : ( + <> + )} , ); From 9cb766b397339a1929250bc066bb827f303e3ebc Mon Sep 17 00:00:00 2001 From: renatodellosso Date: Mon, 30 Dec 2024 15:21:48 -0500 Subject: [PATCH 4/5] XP meter in profile --- components/XpProgressBar.tsx | 19 +++++++++++++++++++ components/competition/MatchScheduleCard.tsx | 4 ++-- pages/profile.tsx | 2 ++ 3 files changed, 23 insertions(+), 2 deletions(-) create mode 100644 components/XpProgressBar.tsx diff --git a/components/XpProgressBar.tsx b/components/XpProgressBar.tsx new file mode 100644 index 00000000..adb5f15d --- /dev/null +++ b/components/XpProgressBar.tsx @@ -0,0 +1,19 @@ +import { User } from "@/lib/Types"; +import { xpRequiredForNextLevel } from "@/lib/Xp"; +import { useState } from "react"; + +export default function XpProgressBar({ user, size }: { user: User, size: string }) { + const [hovered, setHovered] = useState(false); + + return ( +
setHovered(true)} + onMouseLeave={() => setHovered(false)} + > + {hovered ? `${user.xp}/${xpRequiredForNextLevel(user.level)}` : `Lvl ${user.level}`} +
+ ); +} diff --git a/components/competition/MatchScheduleCard.tsx b/components/competition/MatchScheduleCard.tsx index 2d72c4cf..6b0241e8 100644 --- a/components/competition/MatchScheduleCard.tsx +++ b/components/competition/MatchScheduleCard.tsx @@ -287,7 +287,7 @@ export default function MatchScheduleCard(props: {
No subjective scouter assigned
)} - @@ -301,7 +301,7 @@ export default function MatchScheduleCard(props: { : 0 } in progress`} ) - + ))} diff --git a/pages/profile.tsx b/pages/profile.tsx index e973e1b0..f1d2074e 100644 --- a/pages/profile.tsx +++ b/pages/profile.tsx @@ -19,6 +19,7 @@ import TeamCard from "@/components/TeamCard"; import { UpdateModal } from "@/components/UpdateModal"; import { Analytics } from "@/lib/client/Analytics"; import { signOut } from "next-auth/react"; +import XpProgressBar from "@/components/XpProgressBar"; const api = new ClientApi(); @@ -120,6 +121,7 @@ export default function Profile(props: { teamList: Team[] }) { <> )} + { user != null && } From 5cfa086b1d31e91c2970cdeb3f054bba5516fea6 Mon Sep 17 00:00:00 2001 From: renatodellosso Date: Tue, 31 Dec 2024 09:23:09 -0500 Subject: [PATCH 5/5] Fix formatting issues --- components/XpProgressBar.tsx | 25 +++++++++++++++++++------ pages/profile.tsx | 7 ++++++- 2 files changed, 25 insertions(+), 7 deletions(-) diff --git a/components/XpProgressBar.tsx b/components/XpProgressBar.tsx index adb5f15d..b07dda3a 100644 --- a/components/XpProgressBar.tsx +++ b/components/XpProgressBar.tsx @@ -2,18 +2,31 @@ import { User } from "@/lib/Types"; import { xpRequiredForNextLevel } from "@/lib/Xp"; import { useState } from "react"; -export default function XpProgressBar({ user, size }: { user: User, size: string }) { - const [hovered, setHovered] = useState(false); +export default function XpProgressBar({ + user, + size, +}: { + user: User; + size: string; +}) { + const [hovered, setHovered] = useState(false); return (
setHovered(true)} - onMouseLeave={() => setHovered(false)} + onMouseEnter={() => setHovered(true)} + onMouseLeave={() => setHovered(false)} > - {hovered ? `${user.xp}/${xpRequiredForNextLevel(user.level)}` : `Lvl ${user.level}`} + {hovered + ? `${user.xp}/${xpRequiredForNextLevel(user.level)}` + : `Lvl ${user.level}`}
); } diff --git a/pages/profile.tsx b/pages/profile.tsx index f1d2074e..9cae10d8 100644 --- a/pages/profile.tsx +++ b/pages/profile.tsx @@ -121,7 +121,12 @@ export default function Profile(props: { teamList: Team[] }) { <> )} - { user != null && } + {user != null && ( + + )}