diff --git a/assets/js/group-classes.js b/assets/js/group-classes.js index b28661d..7e5de90 100644 --- a/assets/js/group-classes.js +++ b/assets/js/group-classes.js @@ -89,7 +89,7 @@ return `${formatDate(o.term_start)} – ${formatDate(o.term_end)} (${sessions} weekly sessions)`; } - function renderClasses(offerings) { + function renderClasses(offerings, enrolledOfferingIds) { let groups = offerings.filter((o) => o.kind === 'group_class'); if (singleOfferingId) { groups = groups.filter((o) => Number(o.id) === singleOfferingId); @@ -108,7 +108,9 @@ ${o.schedule_note ? `
${escHtml(o.schedule_note)}
` : ''} ${o.description ? `${escHtml(o.description)}
` : ''}${escHtml(Number(o.price).toFixed(2))} ${escHtml(o.currency)}
- + ${enrolledOfferingIds.has(Number(o.id)) + ? 'You are enrolled in this class.
' + : ``} `).join(''); @@ -188,8 +190,20 @@ clearError(); list.style.display = 'block'; confirm.style.display = 'none'; - apiFetch('offerings?kind=group_class') - .then(renderClasses) + // The student's own enrolments are fetched alongside the catalog so a + // class they already have an active enrolment in shows its status + // instead of offering to enrol them again (the API would reject the + // duplicate anyway). A cancelled enrolment does not block re-enrolling. + Promise.all([ + apiFetch('offerings?kind=group_class'), + apiFetch('enrollments'), + ]) + .then(([offerings, enrollments]) => renderClasses( + offerings, + new Set(enrollments + .filter((e) => e.status === 'active') + .map((e) => Number(e.offering_id))) + )) .catch((err) => showError(err.message)); } diff --git a/docs/features/group-classes.md b/docs/features/group-classes.md index def60c4..5665396 100644 --- a/docs/features/group-classes.md +++ b/docs/features/group-classes.md @@ -22,6 +22,12 @@ sessions. The class card on the enrolment page shows the date or date range with the session count. ## Enrolment Flow +The class list is loaded together with the student's own enrolments +(`GET /enrollments`); a class the student already has an `active` enrolment in +shows "You are enrolled in this class." instead of the Enrol button (the +server would reject the duplicate with `409 already_enrolled` regardless — a +cancelled enrolment does not block re-enrolling). + 1. Student opens a group class from the offering catalog. 2. Student answers the offering's questions (`GET /offerings/{id}/questions`). 3. Student accepts the current published policy versions (`GET /policies`) — required to continue.