feat: assessments overview mark as complete

This commit is contained in:
SethBurkart123
2025-06-07 23:49:28 +10:00
parent 841426d7ec
commit ccb4354b26
5 changed files with 669 additions and 285 deletions
+68 -46
View File
@@ -1,5 +1,13 @@
interface Subject { code: string; programme: number; metaclass: number; title: string; }
interface PrefItem { name: string; value: string; }
interface Subject {
code: string;
programme: number;
metaclass: number;
title: string;
}
interface PrefItem {
name: string;
value: string;
}
let cache: { time: number; data: any } | null = null;
const CACHE_MS = 10 * 60 * 1000;
@@ -7,29 +15,31 @@ const student = 69;
async function fetchJSON(url: string, body: any) {
const res = await fetch(`${location.origin}${url}`, {
method: 'POST',
credentials: 'include',
headers: { 'Content-Type': 'application/json; charset=utf-8' },
method: "POST",
credentials: "include",
headers: { "Content-Type": "application/json; charset=utf-8" },
body: JSON.stringify(body),
});
return res.json();
}
async function loadSubjects() {
const res = await fetchJSON('/seqta/student/load/subjects?', {});
return res.payload.filter((s: any) => s.active === 1).flatMap((s: any) => s.subjects);
const res = await fetchJSON("/seqta/student/load/subjects?", {});
return res.payload
.filter((s: any) => s.active === 1)
.flatMap((s: any) => s.subjects);
}
async function loadPrefs(student: number) {
const res = await fetchJSON('/seqta/student/load/prefs?', {
request: 'userPrefs',
const res = await fetchJSON("/seqta/student/load/prefs?", {
request: "userPrefs",
asArray: true,
user: student,
});
const colors: Record<string, string> = {};
res.payload.forEach((p: PrefItem) => {
if (p.name.startsWith('timetable.subject.colour.')) {
const code = p.name.replace('timetable.subject.colour.', '');
if (p.name.startsWith("timetable.subject.colour.")) {
const code = p.name.replace("timetable.subject.colour.", "");
colors[code] = p.value;
}
});
@@ -37,45 +47,57 @@ async function loadPrefs(student: number) {
}
async function loadUpcoming(student: number) {
const res = await fetchJSON('/seqta/student/assessment/list/upcoming?', { student });
const res = await fetchJSON("/seqta/student/assessment/list/upcoming?", {
student,
});
return res.payload;
}
async function loadPast(student: number, subjects: Subject[]) {
const map: Record<number, any> = {};
await Promise.all(subjects.map(async (s) => {
const res = await fetchJSON('/seqta/student/assessment/list/past?', {
programme: s.programme,
metaclass: s.metaclass,
student,
});
if (res.payload.tasks) {
res.payload.tasks.forEach((t: any) => { map[t.id] = t; });
}
}));
await Promise.all(
subjects.map(async (s) => {
const res = await fetchJSON("/seqta/student/assessment/list/past?", {
programme: s.programme,
metaclass: s.metaclass,
student,
});
if (res.payload.tasks) {
res.payload.tasks.forEach((t: any) => {
map[t.id] = t;
});
}
}),
);
return map;
}
async function loadSubmissions(student: number, assessments: any[]) {
const submissionMap: Record<number, boolean> = {};
// Fetch submission status for each assessment
await Promise.all(assessments.map(async (assessment) => {
try {
const res = await fetchJSON('/seqta/student/assessment/submissions/get', {
assessment: assessment.id,
metaclass: assessment.metaclassID,
student,
});
// If there are any submissions, mark as submitted
submissionMap[assessment.id] = res.payload && res.payload.length > 0;
} catch (error) {
console.warn(`Failed to fetch submission for assessment ${assessment.id}:`, error);
submissionMap[assessment.id] = false;
}
}));
await Promise.all(
assessments.map(async (assessment) => {
try {
const res = await fetchJSON(
"/seqta/student/assessment/submissions/get",
{
assessment: assessment.id,
metaclass: assessment.metaclassID,
student,
},
);
submissionMap[assessment.id] = res.payload && res.payload.length > 0;
} catch (error) {
console.warn(
`Failed to fetch submission for assessment ${assessment.id}:`,
error,
);
submissionMap[assessment.id] = false;
}
}),
);
return submissionMap;
}
@@ -88,21 +110,21 @@ export async function getAssessmentsData() {
]);
const pastMap = await loadPast(student, subjects);
const map: Record<number, any> = {};
upcoming.forEach((a: any) => { map[a.id] = { ...a }; });
upcoming.forEach((a: any) => {
map[a.id] = { ...a };
});
Object.values(pastMap).forEach((t: any) => {
if (map[t.id]) Object.assign(map[t.id], t);
else map[t.id] = t;
});
// Load submission data for all assessments
const allAssessments = Object.values(map);
const submissions = await loadSubmissions(student, allAssessments);
// Add submission status to each assessment
allAssessments.forEach((assessment: any) => {
assessment.submitted = submissions[assessment.id] || false;
});
const data = { assessments: allAssessments, subjects, colors };
cache = { time: Date.now(), data };
return data;