Make remaining date inputs Safari-safe (uncontrolled)

Attendance filter, gradebook assignment date, and tuition entry date now use
defaultValue (with a remount key where the field resets after submit).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
2026-07-19 19:46:33 -04:00
co-authored by Claude Opus 4.8
parent d3c9c71564
commit e95171a0d4
3 changed files with 5 additions and 4 deletions
+3 -2
View File
@@ -221,6 +221,7 @@ export function GradebookGrid({ classId, canEdit }: { classId: string; canEdit:
}); });
const [na, setNa] = useState({ name: "", category_id: "", max_points: "100", date: "" }); const [na, setNa] = useState({ name: "", category_id: "", max_points: "100", date: "" });
const [dateKey, setDateKey] = useState(0); // bump to remount the uncontrolled date input after adding
const addAssignment = useMutation({ const addAssignment = useMutation({
mutationFn: async () => { mutationFn: async () => {
if (!na.name.trim()) throw new Error("Assignment name required"); if (!na.name.trim()) throw new Error("Assignment name required");
@@ -231,7 +232,7 @@ export function GradebookGrid({ classId, canEdit }: { classId: string; canEdit:
}); });
if (error) throw error; if (error) throw error;
}, },
onSuccess: () => { setNa({ name: "", category_id: "", max_points: "100", date: "" }); qc.invalidateQueries({ queryKey: ["assignments", classId] }); toast.success("Assignment added"); }, onSuccess: () => { setNa({ name: "", category_id: "", max_points: "100", date: "" }); setDateKey((k) => k + 1); qc.invalidateQueries({ queryKey: ["assignments", classId] }); toast.success("Assignment added"); },
onError: (e: Error) => toast.error(e.message), onError: (e: Error) => toast.error(e.message),
}); });
const delAssignment = useMutation({ const delAssignment = useMutation({
@@ -253,7 +254,7 @@ export function GradebookGrid({ classId, canEdit }: { classId: string; canEdit:
<SelectContent>{cfg.categories.map((c) => <SelectItem key={c.id} value={c.id}>{c.name}</SelectItem>)}</SelectContent> <SelectContent>{cfg.categories.map((c) => <SelectItem key={c.id} value={c.id}>{c.name}</SelectItem>)}</SelectContent>
</Select> </Select>
<Input type="number" placeholder="Max pts" value={na.max_points} onChange={(e) => setNa({ ...na, max_points: e.target.value })} /> <Input type="number" placeholder="Max pts" value={na.max_points} onChange={(e) => setNa({ ...na, max_points: e.target.value })} />
<Input type="date" value={na.date} onChange={(e) => setNa({ ...na, date: e.target.value })} /> <Input key={dateKey} type="date" defaultValue={na.date} onChange={(e) => setNa({ ...na, date: e.target.value })} />
<Button onClick={() => addAssignment.mutate()} disabled={addAssignment.isPending}><Plus className="h-4 w-4 mr-1" /> Add</Button> <Button onClick={() => addAssignment.mutate()} disabled={addAssignment.isPending}><Plus className="h-4 w-4 mr-1" /> Add</Button>
</div> </div>
</div> </div>
+1 -1
View File
@@ -69,7 +69,7 @@ function AttendancePage() {
<SelectContent>{(classes ?? []).map((c) => <SelectItem key={c.id} value={c.id}>{c.name}</SelectItem>)}</SelectContent> <SelectContent>{(classes ?? []).map((c) => <SelectItem key={c.id} value={c.id}>{c.name}</SelectItem>)}</SelectContent>
</Select> </Select>
</div> </div>
<Input type="date" className="w-44" value={date} onChange={(e) => setDate(e.target.value)} /> <Input type="date" className="w-44" defaultValue={date} onChange={(e) => setDate(e.target.value)} />
</div> </div>
{classId && ( {classId && (
+1 -1
View File
@@ -734,7 +734,7 @@ function LedgerTab({ studentId, canEdit }: { studentId: string; canEdit: boolean
<div className="grid grid-cols-5 gap-2"> <div className="grid grid-cols-5 gap-2">
<select className="border rounded-md px-2 text-sm" value={form.kind} onChange={(e) => setForm({ ...form, kind: e.target.value })}><option value="charge">Charge</option><option value="payment">Payment</option></select> <select className="border rounded-md px-2 text-sm" value={form.kind} onChange={(e) => setForm({ ...form, kind: e.target.value })}><option value="charge">Charge</option><option value="payment">Payment</option></select>
<select className="border rounded-md px-2 text-sm" value={form.category} onChange={(e) => setForm({ ...form, category: e.target.value })}><option value="tuition">Tuition</option><option value="late_pickup">Late pickup</option><option value="activity">Activity</option><option value="other">Other</option></select> <select className="border rounded-md px-2 text-sm" value={form.category} onChange={(e) => setForm({ ...form, category: e.target.value })}><option value="tuition">Tuition</option><option value="late_pickup">Late pickup</option><option value="activity">Activity</option><option value="other">Other</option></select>
<Input type="date" value={form.date} onChange={(e) => setForm({ ...form, date: e.target.value })} /> <Input type="date" defaultValue={form.date} onChange={(e) => setForm({ ...form, date: e.target.value })} />
<Input placeholder="Amount ($)" value={form.amount} onChange={(e) => setForm({ ...form, amount: e.target.value })} /> <Input placeholder="Amount ($)" value={form.amount} onChange={(e) => setForm({ ...form, amount: e.target.value })} />
<Input placeholder="Note" value={form.note} onChange={(e) => setForm({ ...form, note: e.target.value })} /> <Input placeholder="Note" value={form.note} onChange={(e) => setForm({ ...form, note: e.target.value })} />
</div> </div>