fix parent pages and teachers and admin
Web Client CI/CD / Lint (ESLint + TypeScript) (push) Successful in 29s
Web Client CI/CD / Build (tsc + Vite) (push) Successful in 23s
Web Client CI/CD / Deploy to shared hosting (push) Successful in 33s

This commit is contained in:
root
2026-07-09 13:56:26 -04:00
parent 4b78aafa65
commit b895c06dc1
15 changed files with 726 additions and 372 deletions
+68 -11
View File
@@ -222,8 +222,7 @@ export async function fetchReportCardCompleteness(params: {
}
/** Build absolute API URL for iframe / window.open (report PDF HTML). */
export function reportCardStudentUrl(
function reportCardStudentPath(
studentId: number | string,
opts: { school_year: string; semester?: string; download?: boolean; report_date?: string },
): string {
@@ -233,10 +232,10 @@ export function reportCardStudentUrl(
if (opts.download) qs.set('download', '1')
if (opts.report_date) qs.set('report_date', opts.report_date)
qs.set('cb', String(Date.now()))
return apiUrl(`/api/v1/reports/report-cards/students/${encodeURIComponent(String(studentId))}?${qs}`)
return `/api/v1/reports/report-cards/students/${encodeURIComponent(String(studentId))}?${qs}`
}
export function reportCardClassUrl(
function reportCardClassPath(
classSectionId: number | string,
opts: { school_year: string; semester?: string; download?: boolean; report_date?: string },
): string {
@@ -246,7 +245,22 @@ export function reportCardClassUrl(
if (opts.download) qs.set('download', '1')
if (opts.report_date) qs.set('report_date', opts.report_date)
qs.set('cb', String(Date.now()))
return apiUrl(`/api/v1/reports/report-cards/classes/${encodeURIComponent(String(classSectionId))}?${qs}`)
return `/api/v1/reports/report-cards/classes/${encodeURIComponent(String(classSectionId))}?${qs}`
}
/** Build absolute API URL for iframe / window.open (report PDF HTML). */
export function reportCardStudentUrl(
studentId: number | string,
opts: { school_year: string; semester?: string; download?: boolean; report_date?: string },
): string {
return apiUrl(reportCardStudentPath(studentId, opts))
}
export function reportCardClassUrl(
classSectionId: number | string,
opts: { school_year: string; semester?: string; download?: boolean; report_date?: string },
): string {
return apiUrl(reportCardClassPath(classSectionId, opts))
}
/** HTML document for iframe preview (Bearer auth; unlike raw iframe src). */
@@ -288,15 +302,58 @@ export async function fetchReportCardClassHtml(
return res.text()
}
/** Opens PDF download in new tab (authenticated GET). */
export async function openReportCardDownload(url: string): Promise<void> {
async function fetchReportCardPdf(path: string): Promise<Blob> {
const headers = new Headers({ Accept: 'application/pdf,*/*' })
const token = getStoredToken()
if (!token) {
throw new ApiHttpError('Your session has expired. Please sign in again.', 401, null)
}
if (token) headers.set('Authorization', `Bearer ${token}`)
applyStoredSchoolYearHeaders(headers)
const res = await fetch(url, { headers })
if (!res.ok) throw new ApiHttpError(`HTTP ${res.status}`, res.status, null)
const res = await fetch(apiUrl(path), { headers })
if (!res.ok) {
const errBody: unknown = await res.json().catch(() => null)
const msg =
typeof errBody === 'object' && errBody !== null && 'message' in errBody
? String((errBody as { message?: unknown }).message ?? '')
: ''
throw new ApiHttpError(msg || `HTTP ${res.status}`, res.status, errBody)
}
const raw = await res.blob()
const blob = new Blob([await raw.arrayBuffer()], { type: 'application/pdf' })
window.open(URL.createObjectURL(blob), '_blank', 'noopener')
return new Blob([await raw.arrayBuffer()], { type: 'application/pdf' })
}
function openBlob(blob: Blob): void {
const objectUrl = URL.createObjectURL(blob)
window.open(objectUrl, '_blank', 'noopener')
window.setTimeout(() => URL.revokeObjectURL(objectUrl), 60_000)
}
/** Opens PDF download in new tab (authenticated GET). */
export async function openReportCardStudentDownload(
studentId: number | string,
opts: { school_year: string; semester?: string; report_date?: string },
): Promise<void> {
openBlob(
await fetchReportCardPdf(
reportCardStudentPath(studentId, {
...opts,
download: true,
}),
),
)
}
export async function openReportCardClassDownload(
classSectionId: number | string,
opts: { school_year: string; semester?: string; report_date?: string },
): Promise<void> {
openBlob(
await fetchReportCardPdf(
reportCardClassPath(classSectionId, {
...opts,
download: true,
}),
),
)
}