update exam and attendance
This commit is contained in:
File diff suppressed because it is too large
Load Diff
@@ -1,8 +1,7 @@
|
||||
import { useEffect, useMemo, useState, type FormEvent } from 'react'
|
||||
import { Link, useParams, useSearchParams } from 'react-router-dom'
|
||||
import { fetchAdministratorCalendarEvents } from '../../api/session'
|
||||
import { fetchAdministratorCalendarEvents, openProtectedApiFile } from '../../api/session'
|
||||
import type { ExamDraftRow, SchoolCalendarEventRow } from '../../api/types'
|
||||
import { apiUrl } from '../../lib/apiOrigin'
|
||||
import { TeacherShell } from './TeacherShell'
|
||||
import { useTeacherResource } from './useTeacherResource'
|
||||
import { postTeacherMultipart } from '../../api/teacherSession'
|
||||
@@ -114,8 +113,8 @@ type FrontendMeResponse = {
|
||||
const EXAM_DRAFT_MAX_BYTES = 12 * 1024 * 1024
|
||||
const EXAM_DRAFT_ALLOWED_EXTENSIONS = ['doc', 'docx']
|
||||
|
||||
function teacherExamFileUrl(kind: 'teacher' | 'final', filename?: string | null) {
|
||||
return filename ? apiUrl(`/api/v1/files/exams/${kind}/${encodeURIComponent(filename)}`) : null
|
||||
function teacherExamFilePath(kind: 'teacher' | 'final', filename?: string | null) {
|
||||
return filename ? `/api/v1/files/exams/${kind}/${encodeURIComponent(filename)}` : null
|
||||
}
|
||||
|
||||
/** `teacher/competition_scores/index.php` */
|
||||
@@ -883,8 +882,8 @@ export function TeacherExamDraftsPage() {
|
||||
</tr>
|
||||
) : (
|
||||
(payload?.drafts ?? []).map((draft) => {
|
||||
const teacherFile = teacherExamFileUrl('teacher', draft.teacher_file)
|
||||
const finalFile = teacherExamFileUrl('final', draft.final_pdf_file ?? draft.final_file)
|
||||
const teacherFile = teacherExamFilePath('teacher', draft.teacher_file)
|
||||
const finalFile = teacherExamFilePath('final', draft.final_pdf_file ?? draft.final_file)
|
||||
return (
|
||||
<tr key={draft.id}>
|
||||
<td>
|
||||
@@ -900,16 +899,24 @@ export function TeacherExamDraftsPage() {
|
||||
<td>
|
||||
<div className="d-flex flex-column gap-1 small">
|
||||
{teacherFile ? (
|
||||
<a href={teacherFile} target="_blank" rel="noreferrer">
|
||||
<button
|
||||
type="button"
|
||||
className="btn btn-link p-0 text-start"
|
||||
onClick={() => void openProtectedApiFile(teacherFile)}
|
||||
>
|
||||
{draft.teacher_filename ?? 'Teacher file'}
|
||||
</a>
|
||||
</button>
|
||||
) : (
|
||||
<span className="text-muted">No uploaded draft</span>
|
||||
)}
|
||||
{finalFile ? (
|
||||
<a href={finalFile} target="_blank" rel="noreferrer">
|
||||
<button
|
||||
type="button"
|
||||
className="btn btn-link p-0 text-start"
|
||||
onClick={() => void openProtectedApiFile(finalFile)}
|
||||
>
|
||||
{draft.final_filename ?? 'Reviewed final'}
|
||||
</a>
|
||||
</button>
|
||||
) : null}
|
||||
</div>
|
||||
</td>
|
||||
@@ -937,7 +944,7 @@ export function TeacherExamDraftsPage() {
|
||||
) : (
|
||||
<div className="row g-3">
|
||||
{(payload?.legacy_exams ?? []).map((draft) => {
|
||||
const finalFile = teacherExamFileUrl('final', draft.final_pdf_file ?? draft.final_file)
|
||||
const finalFile = teacherExamFilePath('final', draft.final_pdf_file ?? draft.final_file)
|
||||
return (
|
||||
<div key={draft.id} className="col-12 col-xl-6">
|
||||
<article className="teacher-calendar-agenda-item h-100">
|
||||
@@ -951,9 +958,13 @@ export function TeacherExamDraftsPage() {
|
||||
</p>
|
||||
<p className="small text-muted mb-2">{draft.description ?? 'No description provided.'}</p>
|
||||
{finalFile ? (
|
||||
<a className="btn btn-sm btn-outline-primary" href={finalFile} target="_blank" rel="noreferrer">
|
||||
<button
|
||||
type="button"
|
||||
className="btn btn-sm btn-outline-primary"
|
||||
onClick={() => void openProtectedApiFile(finalFile)}
|
||||
>
|
||||
Download exam
|
||||
</a>
|
||||
</button>
|
||||
) : (
|
||||
<span className="text-muted small">No file available.</span>
|
||||
)}
|
||||
|
||||
Reference in New Issue
Block a user