From eb94c7ec34b1777e4297db429d9a521c22dfe7ab Mon Sep 17 00:00:00 2001 From: renee-png Date: Sun, 19 Jul 2026 17:50:53 -0400 Subject: [PATCH] Fix student profile dates not saving Native date pickers blur/refocus the window, which triggered a React Query refetch mid-edit and wiped the in-progress date. Disable refetchOnWindowFocus, and make profile/academics edits work on a snapshot with functional state updates so a background refetch can't clobber input. Co-Authored-By: Claude Opus 4.8 --- src/router.tsx | 9 +++++++- src/routes/_authenticated/students.$id.tsx | 27 +++++++++++++--------- 2 files changed, 24 insertions(+), 12 deletions(-) diff --git a/src/router.tsx b/src/router.tsx index 3423d59..bffbc8c 100644 --- a/src/router.tsx +++ b/src/router.tsx @@ -3,7 +3,14 @@ import { createRouter } from "@tanstack/react-router"; import { routeTree } from "./routeTree.gen"; export const getRouter = () => { - const queryClient = new QueryClient(); + const queryClient = new QueryClient({ + defaultOptions: { + // Don't refetch when the window regains focus — opening a native date + // picker blurs/refocuses the window, which would refetch mid-edit and + // wipe in-progress form input. + queries: { refetchOnWindowFocus: false }, + }, + }); const router = createRouter({ routeTree, diff --git a/src/routes/_authenticated/students.$id.tsx b/src/routes/_authenticated/students.$id.tsx index 346416d..f9c1be6 100644 --- a/src/routes/_authenticated/students.$id.tsx +++ b/src/routes/_authenticated/students.$id.tsx @@ -159,9 +159,13 @@ function ProfileTab({ studentId, canEdit, isAdmin }: { studentId: string; canEdi queryKey: ["classes"], queryFn: async () => (await supabase.from("classes").select("id, name").order("name")).data ?? [], }); - const [form, setForm] = useState | null>(null); - const c = (form ?? s) as Record | null; - const upd = (k: string, v: unknown) => setForm({ ...(c as Record), [k]: v }); + // In edit mode we work on a snapshot (`form`) taken when Edit is pressed, so a + // background refetch can never clobber in-progress input. Functional updates + // avoid stale-closure races. + const [form, setForm] = useState>({}); + const startEdit = () => { setForm({ ...(s as Record) }); setEditing(true); }; + const c = (editing ? form : s) as Record | null; + const upd = (k: string, v: unknown) => setForm((f) => ({ ...f, [k]: v })); const dismissal = (c?.dismissal_methods as string[]) ?? []; const toggleDismissal = (v: string) => upd("dismissal_methods", dismissal.includes(v) ? dismissal.filter((x) => x !== v) : [...dismissal, v]); @@ -180,7 +184,7 @@ function ProfileTab({ studentId, canEdit, isAdmin }: { studentId: string; canEdi const { error } = await supabase.from("students").update(payload as never).eq("id", studentId); if (error) throw error; }, - onSuccess: () => { toast.success("Profile saved"); qc.invalidateQueries({ queryKey: ["student", studentId] }); setForm(null); setEditing(false); }, + onSuccess: () => { toast.success("Profile saved"); qc.invalidateQueries({ queryKey: ["student", studentId] }); setEditing(false); }, onError: (e: Error) => toast.error(e.message), }); @@ -192,7 +196,7 @@ function ProfileTab({ studentId, canEdit, isAdmin }: { studentId: string; canEdi if (!editing) { return (
-
+
{canEdit && }
@@ -281,7 +285,7 @@ function ProfileTab({ studentId, canEdit, isAdmin }: { studentId: string; canEdi
- +
); @@ -513,9 +517,10 @@ function AcademicsTab({ studentId, canEdit }: { studentId: string; canEdit: bool queryKey: ["student", studentId], queryFn: async () => (await supabase.from("students").select("*").eq("id", studentId).single()).data, }); - const [form, setForm] = useState | null>(null); - const c = (form ?? s) as Record | null; - const upd = (k: string, v: unknown) => setForm({ ...(c as Record), [k]: v }); + const [form, setForm] = useState>({}); + const startEdit = () => { setForm({ ...(s as Record) }); setEditing(true); }; + const c = (editing ? form : s) as Record | null; + const upd = (k: string, v: unknown) => setForm((f) => ({ ...f, [k]: v })); const val = (k: string) => (c?.[k] as string) ?? ""; const { data: logins } = useQuery({ queryKey: ["curriculum", studentId], @@ -530,7 +535,7 @@ function AcademicsTab({ studentId, canEdit }: { studentId: string; canEdit: bool }).eq("id", studentId); if (error) throw error; }, - onSuccess: () => { toast.success("Saved"); qc.invalidateQueries({ queryKey: ["student", studentId] }); setForm(null); }, + onSuccess: () => { toast.success("Saved"); qc.invalidateQueries({ queryKey: ["student", studentId] }); }, onError: (e: Error) => toast.error(e.message), }); const addLogin = useMutation({ @@ -543,7 +548,7 @@ function AcademicsTab({ studentId, canEdit }: { studentId: string; canEdit: bool return (
-
+
(v ? startEdit() : setEditing(false))} canEdit={canEdit} />
{!editing ? (