On the student group classes page, a class the student already has an active enrolment in now shows "You are enrolled in this class." instead of the Enrol button — in both the browse-all catalog and the single-class embed mode ([us_group_classes offering="…"]).
How
loadClasses() in assets/js/group-classes.js fetches offerings?kind=group_class and enrollments in parallel and passes the set of actively-enrolled offering ids into the renderer. Only status === 'active' counts — a cancelled enrolment does not block re-enrolling, matching the server-side duplicate rule (hasActiveEnrollment / 409 already_enrolled), which remains the enforcement layer; this is a UX improvement over the previous flow where the student completed the whole questions/policies form before hitting the 409.
No PHP changes: GET /enrollments already returns the caller's own enrolments with offering_id and status, and the page is login-gated.
Testing
composer test (308 tests), composer lint, composer cs all pass (PHP untouched). JS-only change with no JS harness in the repo — review-verified; worth a click-through with an enrolled student account.
Closes #61
## What
On the student group classes page, a class the student already has an **active** enrolment in now shows "You are enrolled in this class." instead of the Enrol button — in both the browse-all catalog and the single-class embed mode (`[us_group_classes offering="…"]`).
## How
`loadClasses()` in `assets/js/group-classes.js` fetches `offerings?kind=group_class` and `enrollments` in parallel and passes the set of actively-enrolled offering ids into the renderer. Only `status === 'active'` counts — a cancelled enrolment does not block re-enrolling, matching the server-side duplicate rule (`hasActiveEnrollment` / `409 already_enrolled`), which remains the enforcement layer; this is a UX improvement over the previous flow where the student completed the whole questions/policies form before hitting the 409.
No PHP changes: `GET /enrollments` already returns the caller's own enrolments with `offering_id` and `status`, and the page is login-gated.
## Testing
`composer test` (308 tests), `composer lint`, `composer cs` all pass (PHP untouched). JS-only change with no JS harness in the repo — review-verified; worth a click-through with an enrolled student account.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
The class list now loads the student's own enrolments alongside the
catalog; a class they already have an active enrolment in shows "You
are enrolled in this class." instead of the Enrol button, in both the
browse-all catalog and the single-class embed mode. Previously the
button always rendered and a duplicate attempt walked the student
through the whole questions/policies flow before failing with 409
already_enrolled. A cancelled enrolment does not block re-enrolling,
matching the server-side duplicate rule.
Closes#61
Co-Authored-By: Claude Fable 5 <[email protected]>
Blocking a user prevents them from interacting with repositories, such as opening or commenting on pull requests or issues. Learn more about blocking a user.
Closes #61
What
On the student group classes page, a class the student already has an active enrolment in now shows "You are enrolled in this class." instead of the Enrol button — in both the browse-all catalog and the single-class embed mode (
[us_group_classes offering="…"]).How
loadClasses()inassets/js/group-classes.jsfetchesofferings?kind=group_classandenrollmentsin parallel and passes the set of actively-enrolled offering ids into the renderer. Onlystatus === 'active'counts — a cancelled enrolment does not block re-enrolling, matching the server-side duplicate rule (hasActiveEnrollment/409 already_enrolled), which remains the enforcement layer; this is a UX improvement over the previous flow where the student completed the whole questions/policies form before hitting the 409.No PHP changes:
GET /enrollmentsalready returns the caller's own enrolments withoffering_idandstatus, and the page is login-gated.Testing
composer test(308 tests),composer lint,composer csall pass (PHP untouched). JS-only change with no JS harness in the repo — review-verified; worth a click-through with an enrolled student account.🤖 Generated with Claude Code