From ea495f83823d640e1aab96765595fc37f907c0fa Mon Sep 17 00:00:00 2001 From: root Date: Sun, 26 Apr 2026 14:57:41 -0400 Subject: [PATCH] update exam and attendance --- public/attendnace.png | Bin 0 -> 62263 bytes src/api/session.ts | 45 +- src/pages/AdministratorToolPages.tsx | 1011 ++++++++++++++++++++---- src/pages/teacher/TeacherRestPages.tsx | 37 +- 4 files changed, 912 insertions(+), 181 deletions(-) create mode 100644 public/attendnace.png diff --git a/public/attendnace.png b/public/attendnace.png new file mode 100644 index 0000000000000000000000000000000000000000..5b7e2be3abd3b0b5a14b817ee8ee2e8419907130 GIT binary patch literal 62263 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 AuK)l5 literal 0 HcmV?d00001 diff --git a/src/api/session.ts b/src/api/session.ts index a208538..a278998 100644 --- a/src/api/session.ts +++ b/src/api/session.ts @@ -857,6 +857,33 @@ export async function fetchExamDraftAdminData(): Promise return apiFetch('/api/v1/exams/drafts/admin') } +export async function openProtectedApiFile(path: string): Promise { + const headers = new Headers() + const token = getStoredToken() + if (token) headers.set('Authorization', `Bearer ${token}`) + + const res = await fetch(apiUrl(path), { headers }) + if (!res.ok) { + const body: unknown = await res.json().catch(() => null) + const msg = + typeof body === 'object' && body !== null && 'message' in body + ? String((body as { message?: unknown }).message ?? '') + : '' + throw new Error(msg || `HTTP ${res.status}`) + } + + const blob = await res.blob() + const objectUrl = URL.createObjectURL(blob) + const link = document.createElement('a') + link.href = objectUrl + link.target = '_blank' + link.rel = 'noreferrer' + document.body.appendChild(link) + link.click() + link.remove() + window.setTimeout(() => URL.revokeObjectURL(objectUrl), 60_000) +} + async function fetchMultipartJson(path: string, formData: FormData): Promise { const headers = new Headers({ Accept: 'application/json' }) const token = getStoredToken() @@ -868,10 +895,26 @@ async function fetchMultipartJson(path: string, formData: FormData): Promise< }) const body: unknown = await res.json().catch(() => null) if (!res.ok) { - const msg = + let msg = typeof body === 'object' && body !== null && 'message' in body ? String((body as { message?: unknown }).message ?? '') : '' + + if ( + msg === 'Validation failed.' && + typeof body === 'object' && + body !== null && + 'errors' in body + ) { + const errors = (body as { errors?: Record }).errors + if (errors && typeof errors === 'object') { + const firstField = Object.values(errors)[0] + if (Array.isArray(firstField) && firstField.length > 0) { + msg = String(firstField[0] ?? msg) + } + } + } + throw new Error(msg || `HTTP ${res.status}`) } return body as T diff --git a/src/pages/AdministratorToolPages.tsx b/src/pages/AdministratorToolPages.tsx index 35256f1..9825984 100644 --- a/src/pages/AdministratorToolPages.tsx +++ b/src/pages/AdministratorToolPages.tsx @@ -41,6 +41,7 @@ import { fetchTeacherSubmissions, fetchUsers, notifyTeacherSubmissions, + openProtectedApiFile, removeStudentClass, reviewExamDraft, saveNotificationAlerts, @@ -75,8 +76,6 @@ import type { TeacherSubmissionReportRow, UserListRow, } from '../api/types' -import { apiUrl } from '../lib/apiOrigin' - function AdminParityShell({ title, children, @@ -104,6 +103,19 @@ function formatDateInput(value?: string | null) { return value ? String(value).slice(0, 10) : '' } +function normalizeAttendanceSearch(value: string) { + return value.toLowerCase().replace(/[^a-z0-9]+/g, ' ').trim() +} + +function attendanceSearchMatchesPrefix(query: string, values: string[]) { + if (query === '') return true + return values.some((value) => { + const normalized = normalizeAttendanceSearch(value) + if (normalized.startsWith(query)) return true + return normalized.split(' ').some((part) => part.startsWith(query)) + }) +} + function monthLabel(value: string) { const date = new Date(`${value}T00:00:00`) if (Number.isNaN(date.getTime())) return value @@ -140,6 +152,19 @@ type AttendanceSectionSnapshot = { dates: string[] } +type AttendanceRenderedStudentRow = { + sectionId: string + sectionName: string + student: AttendanceSectionSnapshot['students'][number] +} + +type AttendanceGradeGroup = { + key: string + label: string + order: number + sections: AttendanceSectionSnapshot[] +} + function buildAttendanceSections(data: Awaited>): AttendanceSectionSnapshot[] { const grades = data.grades ?? {} const studentsBySection = data.students_by_section ?? {} @@ -196,6 +221,39 @@ function buildAttendanceSections(data: Awaited() + + function bucketFor(section: AttendanceSectionSnapshot): { key: string; label: string; order: number } { + const name = section.className + if (/\bkg\b/i.test(name)) return { key: 'kg', label: 'KG', order: 0 } + if (/\byouth\b/i.test(name)) return { key: 'youth', label: 'Youth', order: 99 } + if (/\barabic\b/i.test(name)) return { key: 'arabic', label: 'Arabic', order: 100 } + const gradeMatch = /\bgrade\s*(\d+)\b/i.exec(name) + if (gradeMatch) { + const n = Number(gradeMatch[1]) + return { key: `g${n}`, label: `Grade ${n}`, order: n } + } + if (section.classId === 0) return { key: 'kg', label: 'KG', order: 0 } + if (section.classId === 13) return { key: 'youth', label: 'Youth', order: 99 } + return { key: `g${section.classId}`, label: `Grade ${section.classId}`, order: section.classId } + } + + for (const section of sections) { + const bucket = bucketFor(section) + const existing = groups.get(bucket.key) ?? { ...bucket, sections: [] } + existing.sections.push(section) + groups.set(bucket.key, existing) + } + + return Array.from(groups.values()) + .map((group) => ({ + ...group, + sections: group.sections.sort((a, b) => a.className.localeCompare(b.className)), + })) + .sort((a, b) => a.order - b.order || a.label.localeCompare(b.label)) +} + function buildAttendanceAnalysis(sections: AttendanceSectionSnapshot[]) { const overall = { present: 0, late: 0, absent: 0 } const byClass = new Map() @@ -1441,20 +1499,35 @@ export function AdminClassSectionPage() { } export function AdminDailyAttendancePage() { + const [searchParams, setSearchParams] = useSearchParams() + const semesterParam = searchParams.get('semester') ?? '' + const schoolYearParam = searchParams.get('school_year') ?? '' const [data, setData] = useState> | null>(null) const [loading, setLoading] = useState(true) const [error, setError] = useState(null) + const [studentSearch, setStudentSearch] = useState('') + const [tableSearch, setTableSearch] = useState('') + const [activeGradeKey, setActiveGradeKey] = useState('') const [activeSectionId, setActiveSectionId] = useState('') + const [termFilters, setTermFilters] = useState({ + semester: semesterParam, + school_year: schoolYearParam, + }) useEffect(() => { let cancelled = false ;(async () => { setLoading(true) try { - const result = await fetchAdministratorDailyAttendance() + const result = await fetchAdministratorDailyAttendance({ + semester: semesterParam || null, + schoolYear: schoolYearParam || null, + }) if (cancelled) return setData(result) const sections = buildAttendanceSections(result) + const groups = buildAttendanceGradeGroups(sections) + setActiveGradeKey(groups[0]?.key ?? '') setActiveSectionId(sections[0]?.sectionId ?? '') setError(null) } catch (e) { @@ -1466,21 +1539,233 @@ export function AdminDailyAttendancePage() { return () => { cancelled = true } - }, []) + }, [schoolYearParam, semesterParam]) + + useEffect(() => { + setTermFilters({ + semester: semesterParam, + school_year: schoolYearParam, + }) + }, [schoolYearParam, semesterParam]) const sections = useMemo(() => (data ? buildAttendanceSections(data) : []), [data]) - const activeSection = sections.find((row) => row.sectionId === activeSectionId) ?? sections[0] - const visibleDates = activeSection?.dates.slice(-8) ?? [] + const gradeGroups = useMemo(() => buildAttendanceGradeGroups(sections), [sections]) + const normalizedSearch = normalizeAttendanceSearch(studentSearch) + const searchMatches = useMemo(() => { + if (normalizedSearch === '') return [] + return sections.flatMap((section) => + section.students + .filter((student) => { + return attendanceSearchMatchesPrefix(normalizedSearch, [ + student.schoolId, + student.name, + `${student.schoolId} ${student.name}`, + `${student.name} ${student.schoolId}`, + `${student.name} ${section.className}`, + ]) + }) + .map((student) => ({ + section, + student, + })), + ) + }, [normalizedSearch, sections]) + const studentSuggestions = useMemo(() => { + const seen = new Set() + return sections.flatMap((section) => + section.students.flatMap((student) => { + const label = `${student.schoolId} - ${student.name}${section.className ? ` (${section.className})` : ''}` + if (seen.has(label)) return [] + seen.add(label) + return [label] + }), + ) + }, [sections]) + const selectedSearchMatch = searchMatches[0] ?? null + const displayedGrade = gradeGroups.find((group) => group.key === activeGradeKey) ?? gradeGroups[0] + const gradeSections = displayedGrade?.sections ?? [] + const displayedSection = + gradeSections.find((row) => row.sectionId === activeSectionId) ?? + gradeSections[0] ?? + sections.find((row) => row.sectionId === activeSectionId) ?? + sections[0] + const sectionFilter = normalizeAttendanceSearch(tableSearch) + const renderedStudents = useMemo(() => { + if (normalizedSearch !== '') { + const seen = new Set() + return searchMatches.flatMap((match) => { + const key = `${match.section.sectionId}:${match.student.id}` + if (seen.has(key)) return [] + seen.add(key) + return [{ + sectionId: match.section.sectionId, + sectionName: match.section.className, + student: match.student, + }] + }) + } + + if (!displayedSection) return [] + + return displayedSection.students + .filter((student) => { + if (sectionFilter === '') return true + return attendanceSearchMatchesPrefix(sectionFilter, [ + student.schoolId, + student.name, + `${student.schoolId} ${student.name}`, + `${student.name} ${student.schoolId}`, + `${student.name} ${displayedSection.className}`, + ]) + }) + .map((student) => ({ + sectionId: displayedSection.sectionId, + sectionName: displayedSection.className, + student, + })) + }, [displayedSection, normalizedSearch, searchMatches, sectionFilter]) + const visibleDates = useMemo(() => { + if (normalizedSearch !== '') { + const dates = new Set() + for (const match of searchMatches) { + for (const date of match.section.dates) dates.add(date) + } + return Array.from(dates).sort() + } + return displayedSection?.dates ?? [] + }, [displayedSection, normalizedSearch, searchMatches]) + const visibleStudents = useMemo(() => { + return renderedStudents.filter(({ student, sectionName }) => { + if (sectionFilter === '') return true + return attendanceSearchMatchesPrefix(sectionFilter, [ + student.schoolId, + student.name, + `${student.schoolId} ${student.name}`, + `${student.name} ${student.schoolId}`, + `${student.name} ${sectionName}`, + ]) + }) + }, [renderedStudents, sectionFilter]) + + useEffect(() => { + if (!displayedGrade) return + if (!gradeSections.some((section) => section.sectionId === activeSectionId)) { + setActiveSectionId(displayedGrade.sections[0]?.sectionId ?? '') + } + }, [activeSectionId, displayedGrade, gradeSections]) return ( -
- - Attendance Analysis - +
+

Attendance Management

+
+ +
{ + event.preventDefault() + const next = new URLSearchParams() + if (termFilters.school_year.trim() !== '') next.set('school_year', termFilters.school_year.trim()) + if (termFilters.semester.trim() !== '') next.set('semester', termFilters.semester.trim()) + setSearchParams(next) + }} + > +
+ + +
+
+ + +
+
+ + +
+
+ +
+
+
+ Search Student + setStudentSearch(event.target.value)} + /> + +
+ + {studentSuggestions.map((label) => ( + + Searches all grades. + {normalizedSearch !== '' ? ( +
0 ? 'text-success' : 'text-danger'}`}> + {searchMatches.length > 0 + ? `${searchMatches.length} match${searchMatches.length === 1 ? '' : 'es'} found.${selectedSearchMatch ? ` First match: ${selectedSearchMatch.section.className}.` : ''}` + : 'No student matched the current search.'} +
+ ) : null} + {normalizedSearch !== '' && searchMatches.length > 0 ? ( +
+ {searchMatches.slice(0, 12).map((match) => ( + + ))} +
+ ) : null} +
+
+ +
+
+ + Attendance Analysis + +
{error ?
{error}
: null} {loading ? ( @@ -1489,66 +1774,150 @@ export function AdminDailyAttendancePage() {

No attendance sections found.

) : ( <> -
    - {sections.map((section) => ( -
  • +
      + {gradeGroups.map((group) => ( +
    • ))}
    - {activeSection ? ( -
    - - - - - - {visibleDates.map((date) => ( - - ))} - - - - - - - {activeSection.students.map((student) => ( - - - - {visibleDates.map((date) => { - const entry = student.entriesByDate[date] - return ( - - ) - })} - - - +
    + {gradeSections.map((section) => ( + + ))} +
    + + {displayedSection ? ( + <> +
    +

    {normalizedSearch !== '' ? 'Search Results' : displayedSection.className}

    +
    + + + {visibleDates[0] ? formatDate(visibleDates[0]) : '—'} {visibleDates.length > 1 ? `– ${formatDate(visibleDates[visibleDates.length - 1])}` : ''} + + +
    +
    + +
    +
    + Show + + entries +
    +
    + + setTableSearch(event.target.value)} + /> +
    +
    + +
    +
    School IDStudent Name{formatDate(date)}PresentLateAbsent
    {student.schoolId}{student.name} - - {entry?.status ? entry.status : '—'} - - {student.summary.present}{student.summary.late}{student.summary.absent}
    + + + + {normalizedSearch !== '' ? : null} + + {visibleDates.map((date) => ( + + ))} + + + + - ))} - -
    School IDSectionStudent Name{formatDate(date)}PresentLateAbsentT
    -
    + + + {visibleStudents.map(({ sectionId, sectionName, student }) => ( + + {student.schoolId} + {normalizedSearch !== '' ? {sectionName} : null} + {student.name} + {visibleDates.map((date) => { + const entry = student.entriesByDate[date] + const status = entry?.status ?? '' + const badgeClass = + status === 'present' + ? 'success' + : status === 'late' + ? 'warning' + : status === 'absent' + ? 'danger' + : 'secondary' + const shortLabel = + status === 'present' + ? 'P' + : status === 'late' + ? 'L' + : status === 'absent' + ? 'A' + : '—' + return ( + +
    + +
    + {shortLabel} +
    +
    + + ) + })} + {student.summary.present} + {student.summary.late} + {student.summary.absent} + {student.summary.total} + + ))} + {visibleStudents.length === 0 ? ( + + + No students match the current search. + + + ) : null} + + +
+ ) : null} )} @@ -1688,6 +2057,7 @@ export function AdminExamDraftsPage() { const [loading, setLoading] = useState(true) const [error, setError] = useState(null) const [message, setMessage] = useState(null) + const [activeTab, setActiveTab] = useState<'submissions' | 'legacy'>('submissions') const [legacyFile, setLegacyFile] = useState(null) const [legacyForm, setLegacyForm] = useState({ class_section_id: '', @@ -1721,8 +2091,16 @@ export function AdminExamDraftsPage() { async function submitLegacy(event: FormEvent) { event.preventDefault() - if (!legacyFile) return + if (!legacyForm.class_section_id) { + setError('Select a class section before uploading a legacy exam.') + return + } + if (!legacyFile) { + setError('Choose a file to upload.') + return + } try { + setError(null) const result = await uploadLegacyExamDraft({ class_section_id: Number(legacyForm.class_section_id), school_year: legacyForm.school_year, @@ -1754,120 +2132,419 @@ export function AdminExamDraftsPage() { } } - const teacherFileUrl = (name?: string | null) => (name ? apiUrl(`/api/v1/files/exams/teacher/${encodeURIComponent(name)}`) : null) - const finalFileUrl = (name?: string | null) => (name ? apiUrl(`/api/v1/files/exams/final/${encodeURIComponent(name)}`) : null) + const teacherFilePath = (name?: string | null) => (name ? `/api/v1/files/exams/teacher/${encodeURIComponent(name)}` : null) + const finalFilePath = (name?: string | null) => (name ? `/api/v1/files/exams/final/${encodeURIComponent(name)}` : null) + const allowedExtensions = data?.allowed_extensions ?? ['doc', 'docx', 'pdf'] + const maxUploadMb = Math.max(1, Math.round((data?.max_upload_bytes ?? 12 * 1024 * 1024) / 1024 / 1024)) + const classSections = data?.class_sections ?? [] + const drafts = (data?.drafts ?? []).filter((draft) => !Boolean(draft.is_legacy)) + const legacyByClass = data?.legacy_by_class ?? {} + + const draftsByClass = useMemo(() => { + const grouped = new Map() + for (const draft of drafts) { + const sectionId = Number(draft.class_section_id ?? 0) + if (!sectionId) continue + const rows = grouped.get(sectionId) ?? [] + rows.push(draft) + grouped.set(sectionId, rows) + } + for (const rows of grouped.values()) { + rows.sort((a, b) => { + const aTime = String(a.reviewed_at ?? '') + const bTime = String(b.reviewed_at ?? '') + return bTime.localeCompare(aTime) + }) + } + return grouped + }, [drafts]) + + const visibleClasses = useMemo(() => { + const base = classSections + .map((section) => ({ + class_section_id: Number(section.class_section_id ?? 0), + class_section_name: section.class_section_name ?? '', + })) + .filter((section) => section.class_section_id > 0) + + const seen = new Set() + const merged: Array<{ class_section_id: number; class_section_name: string }> = [] + + for (const section of base) { + if (seen.has(section.class_section_id)) continue + seen.add(section.class_section_id) + merged.push(section) + } + + for (const draft of drafts) { + const sectionId = Number(draft.class_section_id ?? 0) + if (!sectionId || seen.has(sectionId)) continue + seen.add(sectionId) + merged.push({ + class_section_id: sectionId, + class_section_name: draft.class_section_name ?? `Class ${sectionId}`, + }) + } + + return merged.sort((a, b) => a.class_section_name.localeCompare(b.class_section_name)) + }, [classSections, drafts]) + + function statusBadgeClass(status?: string | null): string { + switch (String(status ?? '').toLowerCase()) { + case 'submitted': + return 'bg-warning text-dark' + case 'reviewed': + return 'bg-info text-dark' + case 'finalized': + return 'bg-success' + case 'rejected': + return 'bg-danger' + default: + return 'bg-secondary' + } + } return ( {message ?
{message}
: null} {error ?
{error}
: null} -
-
Upload Legacy Exam
-
-
-
- - -
-
- - setLegacyForm((current) => ({ ...current, school_year: event.target.value }))} required /> -
-
- - setLegacyForm((current) => ({ ...current, semester: event.target.value }))} required /> -
-
- - -
-
- - `.${ext}`).join(',')} onChange={(event) => setLegacyFile(event.target.files?.[0] ?? null)} required /> -
-
- -
-
+
+
+

{data?.semester || 'Semester'} {data?.school_year || ''}

+
+
+ Allowed files: {allowedExtensions.join(', ')} + Max size: {maxUploadMb} MB
-
-
Submissions
-
-
- - - - - - - - - - - - - - - {loading ? ( - - ) : (data?.drafts ?? []).length === 0 ? ( - - ) : ( - (data?.drafts ?? []).map((draft) => { - const teacherName = `${draft.teacher_first ?? ''} ${draft.teacher_last ?? ''}`.trim() || 'Admin upload' - const state = reviewState[draft.id] ?? { review_status: draft.status ?? '', admin_comments: draft.admin_comments ?? '', final_file: null } - return ( - - - - - - - - -
TeacherClassTitleTypeVersionStatusFilesReview
Loading drafts…
No exam drafts found.
{teacherName}{draft.class_section_name ?? '—'} -
{draft.draft_title ?? 'Untitled'}
-
{draft.description ?? ''}
-
{draft.exam_type ?? '—'}{draft.version ?? 1}{draft.status ?? '—'} -
- {teacherFileUrl(draft.teacher_file) ? Teacher file : null} - {finalFileUrl(draft.final_pdf_file ?? draft.final_file) ? Final file : null} -
-
-
- -