diff --git a/CHANGELOG.md b/CHANGELOG.md index 5809831..f502657 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -14,7 +14,7 @@ each change under the current top section as you work. ## [1.1.3] ### Added -- Group classes now carry an **enrolment deadline** the instructor sets on the offering. It defaults to the first day of the class, and once it passes students can no longer enrol — the enrolment page shows the class as closed and the API rejects late enrolments. +- Group classes now carry an **enrolment deadline** the instructor sets on the offering. It defaults to the first day of the class, and once it passes students can no longer enrol — the enrolment page shows the class as closed and the API rejects late enrolments. While enrolment is open, each class card shows an "Enrol by" date. - Instructors can add students to any group class by hand from its details page (**Add students directly**), which now appears for public classes too, not just invite-only ones. This bypasses the enrolment deadline and capacity, so a student can be enrolled as a **late enrolment** after the class has closed to self-enrolment. ## [1.1.2] diff --git a/assets/js/group-classes.js b/assets/js/group-classes.js index ed438ca..fb4cee9 100644 --- a/assets/js/group-classes.js +++ b/assets/js/group-classes.js @@ -110,11 +110,16 @@ return `${now.getFullYear()}-${String(now.getMonth() + 1).padStart(2, '0')}-${String(now.getDate()).padStart(2, '0')}`; } - // Enrolment closes at the end of the deadline day — the instructor's set - // deadline, or the first class day by default. Mirrors the server-side + // The effective enrolment deadline: the instructor's set deadline, or the + // first class day by default. Empty when the class has no dates at all. + function enrolmentDeadline(o) { + return o.enrollment_deadline || o.term_start || ''; + } + + // Enrolment closes at the end of the deadline day. Mirrors the server-side // Offering::isEnrollmentOpen() gate. function isEnrollmentOpen(o) { - const deadline = o.enrollment_deadline || o.term_start || ''; + const deadline = enrolmentDeadline(o); return !deadline || todayYmd() <= deadline; } @@ -138,6 +143,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)) && isEnrollmentOpen(o) && enrolmentDeadline(o) + ? `Enrol by ${escHtml(formatDate(enrolmentDeadline(o)))}
` + : ''} ${enrolledOfferingIds.has(Number(o.id)) ? 'You are enrolled in this class.
' : (isEnrollmentOpen(o) diff --git a/docs/features/group-classes.md b/docs/features/group-classes.md index c812399..0c6f267 100644 --- a/docs/features/group-classes.md +++ b/docs/features/group-classes.md @@ -52,7 +52,8 @@ Enrolment also closes after the class's **enrolment deadline** (the instructor's `enrollment_deadline`, defaulting to `term_start` — the first class day; see `offerings.md`). Past the deadline `POST /enrollments` rejects the enrolment with `403 enrollment_closed`, and the class list shows "Enrolment has closed." in place -of the Enrol button. +of the Enrol button. While enrolment is still open the class card shows an +"Enrol by" line with the effective deadline date. The deadline only bounds student **self**-enrolment. An instructor (or studio admin) can still enrol someone by hand from the class **details page** — the **Add students