import { type FormEvent, useEffect, useMemo, useState } from 'react' import { Link } from 'react-router-dom' import { createEarlyDismissal, fetchEarlyDismissalStudentOptions } from '../../api/session' import { EARLY_DISMISSALS_PATH } from './attendancePaths' type StudentOpt = { id: number firstname: string lastname: string section?: string | null } /** Port of `Views/attendance/early_dismissals_add.php` */ export function EarlyDismissalsAddPage() { const [students, setStudents] = useState([]) const [loading, setLoading] = useState(true) const [error, setError] = useState(null) const [msg, setMsg] = useState(null) const [query, setQuery] = useState('') const [studentId, setStudentId] = useState(null) const [label, setLabel] = useState('') const [date, setDate] = useState(() => new Date().toISOString().slice(0, 10)) const [dismissTime, setDismissTime] = useState('') const [reason, setReason] = useState('') useEffect(() => { let cancelled = false ;(async () => { try { const data = await fetchEarlyDismissalStudentOptions() if (cancelled) return const raw = data.students ?? [] setStudents( raw .map((s) => ({ id: Number(s.id ?? 0), firstname: String(s.firstname ?? ''), lastname: String(s.lastname ?? ''), section: s.class_section_name ?? null, })) .filter((s) => s.id > 0), ) } catch (e) { if (!cancelled) setError(e instanceof Error ? e.message : 'Unable to load students.') } finally { if (!cancelled) setLoading(false) } })() return () => { cancelled = true } }, []) const enriched = useMemo(() => { const norm = (s: string) => s.toLowerCase().trim() return students.map((s) => { const display = `${s.firstname} ${s.lastname}${s.section ? ` — ${s.section}` : ''}` const key = `${norm(s.firstname)} ${norm(s.lastname)} ${norm(s.section ?? '')}` return { ...s, display, key } }) }, [students]) const matches = useMemo(() => { const q = query.toLowerCase().trim() if (!q) return [] return enriched.filter((s) => s.key.includes(q)).slice(0, 20) }, [enriched, query]) async function onSubmit(e: FormEvent) { e.preventDefault() setError(null) setMsg(null) if (!studentId) { setError('Please select a student from the list.') return } try { await createEarlyDismissal({ student_id: studentId, date, dismiss_time: dismissTime, reason: reason || null, }) setMsg('Early dismissal saved.') } catch (err) { setError(err instanceof Error ? err.message : 'Save failed.') } } return (

Add Early Dismissal

Back to List
{error ?
{error}
: null} {msg ?
{msg}
: null}
{ setLabel(ev.target.value) setStudentId(null) setQuery(ev.target.value) }} /> {query.trim() && matches.length > 0 ? (
{matches.map((m) => ( ))}
) : null}
Start typing first or last name, then pick from the list.
setDate(ev.target.value)} />
setDismissTime(ev.target.value)} />