fix calendar page
Web Client CI/CD / Lint (ESLint + TypeScript) (push) Successful in 32s
Web Client CI/CD / Build (tsc + Vite) (push) Successful in 23s
Web Client CI/CD / Deploy to shared hosting (push) Successful in 47s

This commit is contained in:
root
2026-07-05 14:18:49 -04:00
parent 405dc3e379
commit 8cacd0874f
+39 -17
View File
@@ -980,17 +980,17 @@ export function AdminCalendarAddEventPage() {
}, []) }, [])
if (loading && !options) { if (loading && !options) {
return <AdminParityShell title="Add Event"><p className="text-muted">Loading</p></AdminParityShell> return <AdminParityShell title="Add School Calendar Entry"><p className="text-muted">Loading</p></AdminParityShell>
} }
return ( return (
<CalendarEventForm <CalendarEventForm
title="Add Event" title="Add School Calendar Entry"
initial={{ initial={{
event_types: options?.event_types ?? [], event_types: options?.event_types ?? [],
defaults: options?.defaults, defaults: options?.defaults,
}} }}
submitLabel="Add Event" submitLabel="Add School Calendar Entry"
submitting={false} submitting={false}
onSubmit={async (payload) => { onSubmit={async (payload) => {
await createAdministratorCalendarEvent(payload as never) await createAdministratorCalendarEvent(payload as never)
@@ -1029,18 +1029,18 @@ export function AdminCalendarEditPage() {
}, [eventId]) }, [eventId])
if (loading || !event) { if (loading || !event) {
return <AdminParityShell title="Edit Event"><p className="text-muted">Loading</p></AdminParityShell> return <AdminParityShell title="Edit School Calendar Entry"><p className="text-muted">Loading</p></AdminParityShell>
} }
return ( return (
<CalendarEventForm <CalendarEventForm
title="Edit Event" title="Edit School Calendar Entry"
initial={{ initial={{
...event, ...event,
event_types: options?.event_types ?? [], event_types: options?.event_types ?? [],
defaults: options?.defaults, defaults: options?.defaults,
}} }}
submitLabel="Update Event" submitLabel="Update School Calendar Entry"
submitting={false} submitting={false}
onSubmit={async (payload) => { onSubmit={async (payload) => {
await updateAdministratorCalendarEvent(Number(eventId), payload) await updateAdministratorCalendarEvent(Number(eventId), payload)
@@ -1059,6 +1059,7 @@ export function AdminCalendarViewPage() {
const [loading, setLoading] = useState(true) const [loading, setLoading] = useState(true)
const [error, setError] = useState<string | null>(null) const [error, setError] = useState<string | null>(null)
const schoolYear = searchParams.get('school_year') ?? '' const schoolYear = searchParams.get('school_year') ?? ''
const semester = searchParams.get('semester') ?? ''
const { options, currentYear } = useSchoolYearOptions({ const { options, currentYear } = useSchoolYearOptions({
preferredYear: schoolYear, preferredYear: schoolYear,
}) })
@@ -1074,12 +1075,12 @@ export function AdminCalendarViewPage() {
try { try {
const data = await fetchAdministratorCalendarEvents({ const data = await fetchAdministratorCalendarEvents({
schoolYear: schoolYear || null, schoolYear: schoolYear || null,
semester: null, semester: semester || null,
}) })
setEvents(data.data?.events ?? []) setEvents(data.data?.events ?? [])
setError(null) setError(null)
} catch (e) { } catch (e) {
setError(e instanceof Error ? e.message : 'Unable to load calendar events.') setError(e instanceof Error ? e.message : 'Unable to load school calendar entries.')
} finally { } finally {
setLoading(false) setLoading(false)
} }
@@ -1087,16 +1088,16 @@ export function AdminCalendarViewPage() {
useEffect(() => { useEffect(() => {
void load() void load()
}, [schoolYear]) }, [schoolYear, semester])
async function onDelete(eventId: number) { async function onDelete(eventId: number) {
if (!window.confirm('Delete this event?')) return if (!window.confirm('Delete this school calendar entry?')) return
await deleteAdministratorCalendarEvent(eventId) await deleteAdministratorCalendarEvent(eventId)
await load() await load()
} }
return ( return (
<AdminParityShell title="Event list"> <AdminParityShell title="School Calendar">
{error ? <div className="alert alert-danger">{error}</div> : null} {error ? <div className="alert alert-danger">{error}</div> : null}
<div className="d-flex gap-2 mb-3 flex-wrap justify-content-between align-items-center"> <div className="d-flex gap-2 mb-3 flex-wrap justify-content-between align-items-center">
@@ -1107,7 +1108,7 @@ export function AdminCalendarViewPage() {
to={`/app/administrator/calendar_add_event${schoolYear ? `?school_year=${encodeURIComponent(schoolYear)}` : ''}`} to={`/app/administrator/calendar_add_event${schoolYear ? `?school_year=${encodeURIComponent(schoolYear)}` : ''}`}
className="btn btn-success" className="btn btn-success"
> >
Add New Event Add School Calendar Entry
</Link> </Link>
</div> </div>
@@ -1116,8 +1117,10 @@ export function AdminCalendarViewPage() {
onSubmit={(event) => { onSubmit={(event) => {
event.preventDefault() event.preventDefault()
const year = String(new FormData(event.currentTarget).get('school_year') ?? '').trim() const year = String(new FormData(event.currentTarget).get('school_year') ?? '').trim()
const semester = String(new FormData(event.currentTarget).get('semester') ?? '').trim()
const next = new URLSearchParams() const next = new URLSearchParams()
if (year) next.set('school_year', year) if (year) next.set('school_year', year)
if (semester) next.set('semester', semester)
setSearchParams(next) setSearchParams(next)
}} }}
> >
@@ -1136,6 +1139,19 @@ export function AdminCalendarViewPage() {
))} ))}
</select> </select>
</div> </div>
<div>
<label htmlFor="cal-semester" className="form-label">Semester</label>
<select
id="cal-semester"
name="semester"
className="form-select"
defaultValue={semester}
>
<option value="">-</option>
<option value="Fall">Fall</option>
<option value="Spring">Spring</option>
</select>
</div>
<div className="d-flex gap-2 align-self-end"> <div className="d-flex gap-2 align-self-end">
<button className="btn btn-secondary" type="submit">Apply</button> <button className="btn btn-secondary" type="submit">Apply</button>
<button <button
@@ -1159,15 +1175,18 @@ export function AdminCalendarViewPage() {
<th>Type</th> <th>Type</th>
<th>Description</th> <th>Description</th>
<th>Date</th> <th>Date</th>
<th>Audience</th> <th>Notify Parent</th>
<th>Notify Teacher</th>
<th>Notify Admin</th>
<th>No School</th>
<th>Actions</th> <th>Actions</th>
</tr> </tr>
</thead> </thead>
<tbody> <tbody>
{loading ? ( {loading ? (
<tr><td colSpan={7} className="text-muted">Loading events</td></tr> <tr><td colSpan={10} className="text-muted">Loading school calendar entries</td></tr>
) : events.length === 0 ? ( ) : events.length === 0 ? (
<tr><td colSpan={7} className="text-muted">No events found.</td></tr> <tr><td colSpan={10} className="text-muted">No school calendar entries found.</td></tr>
) : ( ) : (
events.map((row) => ( events.map((row) => (
<tr key={row.id ?? row.title + row.start}> <tr key={row.id ?? row.title + row.start}>
@@ -1176,7 +1195,10 @@ export function AdminCalendarViewPage() {
<td>{String(row.extendedProps?.event_type ?? '—')}</td> <td>{String(row.extendedProps?.event_type ?? '—')}</td>
<td>{row.description || '—'}</td> <td>{row.description || '—'}</td>
<td>{formatDate(row.start)}</td> <td>{formatDate(row.start)}</td>
<td>{eventAudienceBadges(row).join(', ') || '—'}</td> <td className="text-center"><input type="checkbox" disabled checked={Boolean(row.extendedProps?.notify_parent)} readOnly /></td>
<td className="text-center"><input type="checkbox" disabled checked={Boolean(row.extendedProps?.notify_teacher)} readOnly /></td>
<td className="text-center"><input type="checkbox" disabled checked={Boolean(row.extendedProps?.notify_admin)} readOnly /></td>
<td className="text-center"><input type="checkbox" disabled checked={Boolean(row.extendedProps?.no_school)} readOnly /></td>
<td className="d-flex gap-2 flex-wrap"> <td className="d-flex gap-2 flex-wrap">
{row.id ? ( {row.id ? (
<> <>
@@ -1188,7 +1210,7 @@ export function AdminCalendarViewPage() {
</button> </button>
</> </>
) : ( ) : (
<span className="text-muted small">Meeting event</span> <span className="text-muted small">Meeting entry</span>
)} )}
</td> </td>
</tr> </tr>