diff --git a/CHANGELOG.md b/CHANGELOG.md index cfa0cbf..6a90a08 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -13,6 +13,19 @@ each change under the current top section as you work. ## [1.4.1] +### Added +- **Group classes now appear in "Your upcoming lessons".** A class is stored as a term rather than as bookable slots, so nothing that listed lessons could ever show one — a student whose whole term was a group class saw an empty schedule, and an instructor teaching one saw nothing on their My Lessons page. Each remaining session of a class you are enrolled in now sorts in among your lessons by date, labelled **group class**; instructors see every session of the classes they teach, one row per session however many students are in it. A session has no Cancel button, because there is no such thing as cancelling one date of a term — withdrawing from the class is still done from the class page. A class whose date, time or length has not been filled in yields no sessions and is left out rather than shown at a time nobody chose. +- The same group-class sessions now appear in **Upcoming lessons** on a student's admin detail page, so one table answers "what are they booked into next week?". Only upcoming ones — the **Group-class enrolments** table below already holds the history. +- **A policy can be renamed.** The title was fixed at creation, so a typo or a change of wording meant creating a second policy and re-collecting everyone's acceptance. Renaming changes only what students read above the policy text: the slug stays put, so every version already accepted stays attached. + +### Fixed +- **Deleting a student now gives back what they had booked.** WordPress deletes a user without knowing anything about lessons, so their bookings were left behind: the times stayed marked as booked and nobody else could take them, the lessons stayed on the instructor's schedule under a name that no longer resolved, and a group class kept a seat filled by nobody. Deleting an account now cancels each of its upcoming lessons, frees the time for rebooking, cancels its active class enrolments, and voids any payment still pending on them. Past lessons are left exactly as they are — they happened, and the payment report has to keep adding up. A paid lesson is not credited back: a credit could only be spent on the account being deleted, so a refund owed to someone who has left stays the studio's decision to make. +- **A weak password is now caught before the form is submitted, not after.** The strength meter scores the password as you type, but zxcvbn's dictionary arrives a moment after the page loads — so a password typed straight away was never scored at all, and the first you heard of it was the server rejecting the whole form. The password is now re-scored on submit, so the verdict is always the one your password actually earns. + +### Changed +- **Signup is one page again.** The studio's registration questions used to be a second step behind a **Next** button; they are now asked on the main form, in an **About you** panel above the students you are adding. What the studio needs to know about you is part of registering, not a sequel to it — and there is now one submit rather than three. +- **Signup asks an adult student for their birth year**, the same four-digit year already asked of every student being registered on someone else's behalf. It is asked only when you are a student yourself — choosing **on behalf of one or more students** leaves the whole **About you** panel out, since those questions describe a student and in that case you are not one. + ## [1.4.0] ### Added diff --git a/assets/css/frontend.css b/assets/css/frontend.css index 59e2960..6f10988 100644 --- a/assets/css/frontend.css +++ b/assets/css/frontend.css @@ -438,15 +438,40 @@ opacity: 0.75; } -/* Parent/guardian signup: the child blocks revealed by the checkbox. */ -.us-guardian { +/* + * Marks a row in the upcoming panel as a group-class session. The list mixes + * one-to-one lessons and classes, and only the class rows have no Cancel button + * — without a label that reads as a missing button rather than a different kind + * of thing. + */ +#us-booking-app .us-my-lesson-kind { + display: inline-block; + margin-left: 6px; + padding: 1px 6px; + border-radius: 10px; + background: #eef1f5; + color: #3c434a; + font-size: 0.75em; + font-weight: 600; + text-transform: uppercase; + letter-spacing: 0.03em; + vertical-align: middle; +} + +/* + * The signup form's grouped sections: who you are registering, your own + * details, and the students you are adding. One box style for all three so the + * form reads as a short list of decisions rather than an undifferentiated + * column of fields. + */ +.us-reg-group { margin: 16px 0; padding: 12px 14px; border: 1px solid #ddd; border-radius: 4px; } -.us-guardian legend { +.us-reg-group legend { padding: 0 6px; font-weight: 600; } diff --git a/assets/js/booking.js b/assets/js/booking.js index 6e1147a..299fa45 100644 --- a/assets/js/booking.js +++ b/assets/js/booking.js @@ -588,6 +588,9 @@ function lessonStatusLabel(status) { if (status === 'pending') return 'Pending payment'; if (status === 'confirmed') return 'Confirmed'; + // A group-class session carries its enrolment's status, and "active" + // reads as jargon next to "Confirmed". + if (status === 'active') return 'Enrolled'; return status.charAt(0).toUpperCase() + status.slice(1); } @@ -603,21 +606,31 @@ return ` — ${escHtml(String(l.student_name))}`; } + // A group-class session is a date in a term, not a booked slot: there is no + // lesson to cancel and no time to release, so it carries no Cancel button. + // Withdrawing from the class is a separate decision, made on the class page. + function isGroupSession(l) { + return l.kind === 'group_class'; + } + function lessonRowHtml(l) { - const title = l.offering_title ? escHtml(String(l.offering_title)) : 'Lesson'; + const group = isGroupSession(l); + const title = l.offering_title ? escHtml(String(l.offering_title)) : (group ? 'Group class' : 'Lesson'); const duration = l.duration_minutes ? ` (${escHtml(String(l.duration_minutes))} min)` : ''; + const badge = group ? ' Group class' : ''; + const action = group ? '' : ``; // The two columns are divs, not spans: as spans the layout only held up // while the stylesheet's display:flex won, and a theme rule on span // collapsed the row onto itself. return `
+ slug)); + ?> +
+ +