Fix dates not saving on Safari; show grade level under student name
Safari's native <input type="date"> gets reset by React's controlled value, so picked dates never reached state. Make date inputs uncontrolled (defaultValue + onChange) in the profile, academics, and public intake forms. Header now shows grade level instead of a single class. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
@@ -81,7 +81,7 @@ function StudentDetail() {
|
|||||||
<PhotoAvatar studentId={id} photoPath={student?.photo_path as string | null} canEdit={isAdmin} />
|
<PhotoAvatar studentId={id} photoPath={student?.photo_path as string | null} canEdit={isAdmin} />
|
||||||
<div>
|
<div>
|
||||||
<h1 className="text-2xl font-semibold">{student?.first_name} {student?.last_name}</h1>
|
<h1 className="text-2xl font-semibold">{student?.first_name} {student?.last_name}</h1>
|
||||||
<p className="text-muted-foreground text-sm">{(student?.classes as { name: string } | null)?.name ?? "No class"}</p>
|
<p className="text-muted-foreground text-sm">{student?.grade_level ? `Grade ${student.grade_level}` : "No grade level set"}</p>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
@@ -234,7 +234,8 @@ function ProfileTab({ studentId, canEdit, isAdmin }: { studentId: string; canEdi
|
|||||||
|
|
||||||
// ── Edit mode ──
|
// ── Edit mode ──
|
||||||
const T = (k: string, label: string) => <Field label={label}><Input value={val(k)} onChange={(e) => upd(k, e.target.value)} /></Field>;
|
const T = (k: string, label: string) => <Field label={label}><Input value={val(k)} onChange={(e) => upd(k, e.target.value)} /></Field>;
|
||||||
const D = (k: string, label: string) => <Field label={label}><Input type="date" value={val(k)} onChange={(e) => upd(k, e.target.value)} /></Field>;
|
// Uncontrolled (defaultValue) so Safari's native date picker doesn't get reset by React's controlled value.
|
||||||
|
const D = (k: string, label: string) => <Field label={label}><Input type="date" defaultValue={val(k)} onChange={(e) => upd(k, e.target.value)} /></Field>;
|
||||||
const A = (k: string, label: string, rows = 2) => <Field label={label}><Textarea rows={rows} value={val(k)} onChange={(e) => upd(k, e.target.value)} /></Field>;
|
const A = (k: string, label: string, rows = 2) => <Field label={label}><Textarea rows={rows} value={val(k)} onChange={(e) => upd(k, e.target.value)} /></Field>;
|
||||||
return (
|
return (
|
||||||
<div className="bg-card border rounded-lg p-6 space-y-6 mt-4">
|
<div className="bg-card border rounded-lg p-6 space-y-6 mt-4">
|
||||||
@@ -601,7 +602,7 @@ function AcademicsTab({ studentId, canEdit }: { studentId: string; canEdit: bool
|
|||||||
) : (
|
) : (
|
||||||
<>
|
<>
|
||||||
<div className="grid grid-cols-2 gap-3">
|
<div className="grid grid-cols-2 gap-3">
|
||||||
<Field label="Home Ed. Annual Evaluation due to BPS"><Input type="date" value={val("home_ed_eval_due")} onChange={(e) => upd("home_ed_eval_due", e.target.value)} /></Field>
|
<Field label="Home Ed. Annual Evaluation due to BPS"><Input type="date" defaultValue={val("home_ed_eval_due")} onChange={(e) => upd("home_ed_eval_due", e.target.value)} /></Field>
|
||||||
<Field label="Previous school(s)"><Input value={val("previous_schools")} onChange={(e) => upd("previous_schools", e.target.value)} /></Field>
|
<Field label="Previous school(s)"><Input value={val("previous_schools")} onChange={(e) => upd("previous_schools", e.target.value)} /></Field>
|
||||||
</div>
|
</div>
|
||||||
<Field label="Special academic needs / accommodations"><Textarea rows={2} value={val("special_needs")} onChange={(e) => upd("special_needs", e.target.value)} /></Field>
|
<Field label="Special academic needs / accommodations"><Textarea rows={2} value={val("special_needs")} onChange={(e) => upd("special_needs", e.target.value)} /></Field>
|
||||||
|
|||||||
@@ -101,10 +101,10 @@ function IntakePage() {
|
|||||||
<form onSubmit={(e) => { e.preventDefault(); submit.mutate(); }} className="space-y-5">
|
<form onSubmit={(e) => { e.preventDefault(); submit.mutate(); }} className="space-y-5">
|
||||||
<Section title="Student information">
|
<Section title="Student information">
|
||||||
<div className="grid grid-cols-2 md:grid-cols-3 gap-3">
|
<div className="grid grid-cols-2 md:grid-cols-3 gap-3">
|
||||||
<Field label="Date of birth"><Input type="date" value={s.dob} onChange={set("dob")} /></Field>
|
<Field label="Date of birth"><Input type="date" defaultValue={s.dob} onChange={set("dob")} /></Field>
|
||||||
<Field label="Gender"><Select value={s.gender} onValueChange={(v) => setS((f) => ({ ...f, gender: v }))}><SelectTrigger><SelectValue placeholder="Select" /></SelectTrigger><SelectContent><SelectItem value="male">Male</SelectItem><SelectItem value="female">Female</SelectItem><SelectItem value="other">Other</SelectItem></SelectContent></Select></Field>
|
<Field label="Gender"><Select value={s.gender} onValueChange={(v) => setS((f) => ({ ...f, gender: v }))}><SelectTrigger><SelectValue placeholder="Select" /></SelectTrigger><SelectContent><SelectItem value="male">Male</SelectItem><SelectItem value="female">Female</SelectItem><SelectItem value="other">Other</SelectItem></SelectContent></Select></Field>
|
||||||
<Field label="Grade level applying for"><Input value={s.grade_level} onChange={set("grade_level")} /></Field>
|
<Field label="Grade level applying for"><Input value={s.grade_level} onChange={set("grade_level")} /></Field>
|
||||||
<Field label="Preferred start date"><Input type="date" value={s.preferred_start_date} onChange={set("preferred_start_date")} /></Field>
|
<Field label="Preferred start date"><Input type="date" defaultValue={s.preferred_start_date} onChange={set("preferred_start_date")} /></Field>
|
||||||
</div>
|
</div>
|
||||||
</Section>
|
</Section>
|
||||||
<Section title="Primary parent / guardian"><GuardianFields g={primary} setG={setPrimary} /></Section>
|
<Section title="Primary parent / guardian"><GuardianFields g={primary} setG={setPrimary} /></Section>
|
||||||
@@ -149,7 +149,7 @@ function IntakePage() {
|
|||||||
))}
|
))}
|
||||||
<Button type="button" size="sm" variant="outline" onClick={() => setLogins([...logins, { ...emptyLogin }])}><Plus className="h-4 w-4 mr-1" /> Add platform</Button>
|
<Button type="button" size="sm" variant="outline" onClick={() => setLogins([...logins, { ...emptyLogin }])}><Plus className="h-4 w-4 mr-1" /> Add platform</Button>
|
||||||
</div>
|
</div>
|
||||||
<div className="grid grid-cols-2 gap-3"><Field label="Home Ed. Annual Evaluation due to BPS"><Input type="date" value={s.home_ed_eval_due} onChange={set("home_ed_eval_due")} /></Field><Field label="Previous school(s)"><Input value={s.previous_schools} onChange={set("previous_schools")} /></Field></div>
|
<div className="grid grid-cols-2 gap-3"><Field label="Home Ed. Annual Evaluation due to BPS"><Input type="date" defaultValue={s.home_ed_eval_due} onChange={set("home_ed_eval_due")} /></Field><Field label="Previous school(s)"><Input value={s.previous_schools} onChange={set("previous_schools")} /></Field></div>
|
||||||
<Field label="Special academic needs / accommodations"><Textarea rows={2} value={s.special_needs} onChange={set("special_needs")} /></Field>
|
<Field label="Special academic needs / accommodations"><Textarea rows={2} value={s.special_needs} onChange={set("special_needs")} /></Field>
|
||||||
<Field label="Who keeps the portfolio"><Select value={s.portfolio_keeper} onValueChange={(v) => setS((f) => ({ ...f, portfolio_keeper: v }))}><SelectTrigger><SelectValue placeholder="Select" /></SelectTrigger><SelectContent><SelectItem value="parent">Parent/Guardian</SelectItem><SelectItem value="bayside">Bayside Academy</SelectItem></SelectContent></Select></Field>
|
<Field label="Who keeps the portfolio"><Select value={s.portfolio_keeper} onValueChange={(v) => setS((f) => ({ ...f, portfolio_keeper: v }))}><SelectTrigger><SelectValue placeholder="Select" /></SelectTrigger><SelectContent><SelectItem value="parent">Parent/Guardian</SelectItem><SelectItem value="bayside">Bayside Academy</SelectItem></SelectContent></Select></Field>
|
||||||
<Field label="Disciplinary history (blank if none)"><Textarea rows={2} value={s.disciplinary_history} onChange={set("disciplinary_history")} /></Field>
|
<Field label="Disciplinary history (blank if none)"><Textarea rows={2} value={s.disciplinary_history} onChange={set("disciplinary_history")} /></Field>
|
||||||
@@ -166,7 +166,7 @@ function IntakePage() {
|
|||||||
</Section>
|
</Section>
|
||||||
<Section title="Agreement & signature">
|
<Section title="Agreement & signature">
|
||||||
<label className="flex items-start gap-2 text-sm"><Checkbox checked={agree} onCheckedChange={(v) => setAgree(!!v)} className="mt-0.5" /><span>I certify that the information provided is accurate and complete to the best of my knowledge.</span></label>
|
<label className="flex items-start gap-2 text-sm"><Checkbox checked={agree} onCheckedChange={(v) => setAgree(!!v)} className="mt-0.5" /><span>I certify that the information provided is accurate and complete to the best of my knowledge.</span></label>
|
||||||
<div className="grid grid-cols-2 gap-3"><Field label="Signed by (parent/guardian name)"><Input value={s.agreement_signed_by} onChange={set("agreement_signed_by")} /></Field><Field label="Date"><Input type="date" value={s.agreement_signed_date} onChange={set("agreement_signed_date")} /></Field></div>
|
<div className="grid grid-cols-2 gap-3"><Field label="Signed by (parent/guardian name)"><Input value={s.agreement_signed_by} onChange={set("agreement_signed_by")} /></Field><Field label="Date"><Input type="date" defaultValue={s.agreement_signed_date} onChange={set("agreement_signed_date")} /></Field></div>
|
||||||
</Section>
|
</Section>
|
||||||
|
|
||||||
<div className="sticky bottom-0 -mx-6 md:-mx-8 px-6 md:px-8 py-3 bg-background/90 backdrop-blur border-t flex items-center gap-3">
|
<div className="sticky bottom-0 -mx-6 md:-mx-8 px-6 md:px-8 py-3 bg-background/90 backdrop-blur border-t flex items-center gap-3">
|
||||||
|
|||||||
Reference in New Issue
Block a user