diff --git a/CHANGELOG.md b/CHANGELOG.md index 384d298..9935427 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -13,6 +13,9 @@ each change under the current top section as you work. ## [1.2.2] +### Added +- The **Group Classes** block can now be pinned to a single class, under **Classes shown → Class** in the block sidebar (shortcode: `[us_group_classes offering="…"]`). Pick a class and the block shows only that one, so it can be embedded on a page that describes the class. In this mode the class's own description is left out to avoid repeating the page copy — the card shows the schedule, instructor, price, enrolment deadline and the enrol/withdraw controls. Leaving it on **All classes** keeps the full browsable catalog with descriptions. + ## [1.2.1] ### Fixed diff --git a/assets/js/blocks.js b/assets/js/blocks.js index d7d0f60..96cdd1f 100644 --- a/assets/js/blocks.js +++ b/assets/js/blocks.js @@ -192,7 +192,7 @@ { title: __('Classes shown', 'unsupervised-schedular') }, el(GroupClassSelect, { label: __('Class', 'unsupervised-schedular'), - help: __('Show only one group class, for embedding on a page dedicated to it.', 'unsupervised-schedular'), + help: __('Show only one group class, for embedding on a page dedicated to it. That class’s description is left out — the card shows just the schedule, price and enrolment controls.', 'unsupervised-schedular'), value: attributes.offeringId, onChange: (offeringId) => setAttributes({ offeringId }), }) diff --git a/assets/js/group-classes.js b/assets/js/group-classes.js index 5b9f82d..e770c97 100644 --- a/assets/js/group-classes.js +++ b/assets/js/group-classes.js @@ -12,6 +12,9 @@ // When the shortcode/block pins a single offering, only that class is // shown, so the page can be embedded alongside a full class description. + // The class's own description is then omitted from the card — the page it + // sits on already describes the class — leaving the schedule, price and + // enrolment controls. const singleOfferingId = Number(app.dataset.offering || 0); function apiFetch(path, options = {}) { @@ -148,7 +151,7 @@ ${whenLabel(o) ? `
${escHtml(whenLabel(o))}
` : ''} ${o.instructor_name ? `With ${escHtml(o.instructor_name)}
` : ''} ${o.schedule_note ? `${escHtml(o.schedule_note)}
` : ''} - ${o.description ? `${escHtml(o.description)}
` : ''} + ${!singleOfferingId && o.description ? `${escHtml(o.description)}
` : ''}${escHtml(Number(o.price).toFixed(2))} ${escHtml(o.currency)}
${!enrolledMap.has(Number(o.id)) && isEnrollmentOpen(o) && enrolmentDeadline(o) ? `Enrol by ${escHtml(formatDate(enrolmentDeadline(o)))}
` diff --git a/docs/features/editor-blocks.md b/docs/features/editor-blocks.md index 3d5af19..67e520e 100644 --- a/docs/features/editor-blocks.md +++ b/docs/features/editor-blocks.md @@ -30,7 +30,7 @@ Four blocks have sidebar (inspector) options: | `us-scheduler/student-login` | `bookingPageId` (number) | `0` | Page the "View available lessons" link points to for logged-in visitors, and the post-login redirect target. `0` = the current page. | | `us-scheduler/student-login` | `autoRedirect` (boolean) | `false` | Send logged-in visitors straight to the booking page instead of showing the link. Does nothing until a booking page is chosen. | | `us-scheduler/student-register` | `loginPageId` (number) | `0` | Page the "Sign in to your account" link points to after a student confirms their email. `0` = the WordPress login screen. Shortcode equivalent: `[us_student_register login_page_id="…"]`. | -| `us-scheduler/group-classes` | `offeringId` (number) | `0` | Restrict the page to a single group class, for embedding on a page dedicated to that class. `0` = browse all classes. Shortcode equivalent: `[us_group_classes offering="…"]`. | +| `us-scheduler/group-classes` | `offeringId` (number) | `0` | Restrict the page to a single group class, for embedding on a page dedicated to that class. The class description is then omitted — only the schedule, instructor, price and enrolment controls are shown, so the surrounding page's own copy is not repeated. `0` = browse all classes, descriptions included. Shortcode equivalent: `[us_group_classes offering="…"]`. | The page selects list all published pages; if a chosen page is later deleted, the blocks fall back to their defaults. The group-classes block's class @@ -78,7 +78,9 @@ placeholder content: - **Booking** — `#us-booking-app` with sample `.us-day` / `.us-slot` rows and disabled Book buttons. - **Group classes** — `#us-group-app` with a sample `.us-class` card and a - disabled Enrol button. + disabled Enrol button. When `offeringId` pins a single class the preview + drops the sample description, matching what the live page renders in that + mode. - **Login** — the real `templates/frontend/login-page.php` template (it has no request-state dependencies). - **Registration** — a disabled sample of the `.us-register-form` fields. diff --git a/docs/features/group-classes.md b/docs/features/group-classes.md index fb31d29..8f81309 100644 --- a/docs/features/group-classes.md +++ b/docs/features/group-classes.md @@ -176,7 +176,7 @@ class becomes enrollable for them — they choose whether to enrol. - Model: `Unsupervised\Schedular\GroupClass\Enrollment` - Admin controller: `Unsupervised\Schedular\GroupClass\GroupClassController` — `renderPage` (studio admin per-class summary, `view_all_lessons`) and `renderInstructorPage` (instructor summary + `?class_id` roster detail, `view_own_lessons`) - REST endpoint: `Unsupervised\Schedular\GroupClass\EnrollmentEndpoint` -- Frontend: `Unsupervised\Schedular\GroupClass\GroupClassPage` (`[us_group_classes]` shortcode; `offering="…"` restricts it to a single class for embedding on a dedicated page — the block equivalent is the `offeringId` attribute) +- Frontend: `Unsupervised\Schedular\GroupClass\GroupClassPage` (`[us_group_classes]` shortcode; `offering="…"` restricts it to a single class for embedding on a dedicated page — the block equivalent is the `offeringId` attribute). In single-class mode `assets/js/group-classes.js` leaves the class description out of the card, since the page it is embedded on already describes the class; the schedule, instructor, schedule note, price and enrolment controls are still shown. - Reuses `Registration\RegistrationGate` (intake answers + booking-scoped policy acceptance, type `enrollment`) > **Payment:** a priced enrolment creates a payment via `Payment\PaymentService` diff --git a/src/BlockPreview.php b/src/BlockPreview.php index cc8173a..88b4bd0 100644 --- a/src/BlockPreview.php +++ b/src/BlockPreview.php @@ -58,13 +58,29 @@ class BlockPreview { ); } - public static function groupClasses(): string { + /** + * Sample group-class card. + * + * @param bool $singleClass Whether the block is pinned to one class, in + * which case the live page omits the class + * description and the preview does too. + */ + public static function groupClasses( bool $singleClass = false ): string { + $note = $singleClass + ? __( 'Editor preview — the published page shows the chosen class with its live schedule and enrolment status.', 'unsupervised-schedular' ) + : __( 'Editor preview — students see live group classes on the published page.', 'unsupervised-schedular' ); + + $description = $singleClass + ? '' + : '' . esc_html__( 'A sample class shown so the page can be styled.', 'unsupervised-schedular' ) . '
'; + return sprintf( - '%s
%s
25.00 CAD
%s
%s25.00 CAD
%s