diff --git a/.vscode/settings.json b/.vscode/settings.json index 80a7904..c230834 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -28,5 +28,6 @@ "editor.tabSize": 4, "editor.insertSpaces": true, "editor.detectIndentation": false, - "editor.formatOnSave": true + "editor.formatOnSave": true, + "sqltools.formatLanguages": [] } \ No newline at end of file diff --git a/collection/app/(app)/UserSearch.tsx b/collection/app/(app)/UserSearch.tsx index 7ab7a7e..b897670 100644 --- a/collection/app/(app)/UserSearch.tsx +++ b/collection/app/(app)/UserSearch.tsx @@ -29,24 +29,6 @@ export const UserSearch: React.FC = ({ const router = useRouter(); const shortcodeURLParam = useMemo(() => searchParams.get("shortcode") || "", [searchParams]); - const fetchPurchases = useCallback(async (shortcode: string) => { - const res = await fetch(`/api/purchases/${shortcode}`, { - next: { tags: [`purchases:${shortcode}`] }, - }); - if (!res.ok) { - setError("An error occurred"); - return; - } - - const purchases = await res.json(); - if (purchases.status === "error") { - setError(purchases.message); - setPurchases([]); - } else { - setPurchases(purchases.orders); - } - }, []); - // Form // 2 fields: shortcode & academic year purcahses. // Default value of shortcode is from the URL if possible @@ -60,26 +42,67 @@ export const UserSearch: React.FC = ({ }, }, }); + + const fetchPurchases = useCallback( + async (shortcode: string) => { + const res = await fetch( + `/api/purchases/${shortcode}?` + + new URLSearchParams({ + academicYears: form.getValues().academicYears.join(","), + }), + { + next: { tags: [`purchases:${shortcode}`] }, + }, + ); + if (!res.ok) { + setError("An error occurred"); + return; + } + + const purchases = await res.json(); + if (purchases.status === "error") { + setError(purchases.message); + setPurchases([]); + } else { + setPurchases(purchases.orders); + } + }, + [form], + ); + + // This looks a bit weird, but effectively prevent an infinite loop of fetching purchases + const [prevURLParam, setPrevURLParam] = useState(shortcodeURLParam); useEffect(() => { - if (shortcodeURLParam) { - fetchPurchases(shortcodeURLParam); - } else { - setPurchases([]); - form.setFieldValue("shortcode", ""); + if (!shortcodeURLParam) { + // only allow one rerender when the shortcode is clear + // by tracking the previous value + if (prevURLParam) { + setPurchases([]); + form.setFieldValue("shortcode", ""); + setPrevURLParam(""); + } + } + }, [shortcodeURLParam, prevURLParam, form]); + + // Fetch purchases if academic year changes + form.watch("academicYears", (academicYears) => { + if (form.getValues().shortcode) { + startTransition(async () => { + setError(null); + await fetchPurchases(form.getValues().shortcode); + }); } - // can't add form as would cause infinite loop - // eslint-disable-next-line react-hooks/exhaustive-deps - }, [shortcodeURLParam, fetchPurchases]); + }); const submitAction = useCallback( ({ shortcode }: { shortcode: string }) => { - startTransition(() => { + startTransition(async () => { setError(null); - + await fetchPurchases(shortcode); router.push("/?shortcode=" + shortcode); }); }, - [router], + [router, fetchPurchases], ); return ( @@ -96,6 +119,7 @@ export const UserSearch: React.FC = ({ alignItems: "center", }} onSubmit={form.onSubmit(submitAction)} + // eslint-disable-next-line @typescript-eslint/no-empty-function action={() => {}} > @@ -115,6 +139,7 @@ export const UserSearch: React.FC = ({