update exam and attendance

This commit is contained in:
root
2026-04-26 14:57:41 -04:00
parent 0687d4677f
commit ea495f8382
4 changed files with 912 additions and 181 deletions
+44 -1
View File
@@ -857,6 +857,33 @@ export async function fetchExamDraftAdminData(): Promise<ExamDraftAdminResponse>
return apiFetch<ExamDraftAdminResponse>('/api/v1/exams/drafts/admin')
}
export async function openProtectedApiFile(path: string): Promise<void> {
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<T>(path: string, formData: FormData): Promise<T> {
const headers = new Headers({ Accept: 'application/json' })
const token = getStoredToken()
@@ -868,10 +895,26 @@ async function fetchMultipartJson<T>(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<string, unknown> }).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