Group class offerings now carry real dates: the add/edit form takes a start date plus a sessions control (one-off, or weekly for N sessions; the end date is computed as start + (N-1) weeks via Offering::weeklyTermEnd). Dates are validated strictly (Y-m-d) and shown in the offerings list and on the student-facing class card, including the weekly session count. [us_group_classes offering="<id>"] (block attribute offeringId, chosen from a dropdown of active classes fetched from the public offerings endpoint) restricts the page to a single class so the enrolment flow can be embedded on a page dedicated to that class; a pinned class that is no longer offered reports itself closed instead of falling back to the catalog. Offerings are now editable from the admin screen: an Edit button prefills the shared add/edit form and saving posts usc_action=update. Updates always preserve the original owner and currency, and non-admin instructors can only load and update their own offerings. The form also gains the previously missing description field and an Active toggle (the admin-UI counterpart of the REST is_active flag) so an edit cannot wipe data the form never collected. Closes #59 Co-Authored-By: Claude Fable 5 <[email protected]>
5.4 KiB
Editor Blocks
Gutenberg dynamic-block wrappers for the plugin's four front-end shortcodes, so the pages can be previewed and styled inside the block editor instead of appearing as grey shortcode text.
Blocks
| Block | Wraps shortcode | Front-end renderer |
|---|---|---|
us-scheduler/booking |
[us_booking] |
Booking\BookingPage::render() |
us-scheduler/student-login |
[us_student_login] |
Auth\LoginPage::render() |
us-scheduler/student-register |
[us_student_register] |
Auth\RegistrationPage::render() |
us-scheduler/group-classes |
[us_group_classes] |
GroupClass\GroupClassPage::render() |
The shortcodes remain registered for back-compat; blocks and shortcodes share
the same page objects (constructed once in Plugin::boot()), so front-end
output is identical either way. Pasting a shortcode into the block editor
auto-converts it to the matching block via a transforms.from shortcode
transform.
Block options
Three blocks have sidebar (inspector) options:
| Block | Attribute | Default | Effect |
|---|---|---|---|
us-scheduler/booking |
loginPageId (number) |
0 |
Page the "log in to book a lesson" link points to for logged-out visitors. 0 = the WordPress login screen (with a redirect back to the current page). |
us-scheduler/booking |
autoRedirect (boolean) |
false |
Send logged-out visitors straight to the login page instead of showing the link. |
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/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="…"]. |
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
select is a dropdown of active group classes fetched from
GET /us-scheduler/v1/offerings?kind=group_class; a stored class that is no
longer offered shows as "Unavailable class #N" rather than silently falling
back to all classes. The link targets are also available
to the shortcodes as [us_booking login_page_id="…"] and
[us_student_login booking_page_id="…"]; auto-redirect is block-only.
Auto-redirect cannot happen during block rendering (output has already
started, so a Location header cannot be sent). Instead
BlockRegistrar::maybeAutoRedirect() runs on template_redirect, parses the
queried singular post's content for the block (including inside nested
blocks), and redirects when the block opts in. A block whose target is its
own page is ignored to avoid a redirect loop.
How it works
BlockRegistrar(src/BlockRegistrar.php) hooksinitand registers each block withregister_block_type(): arender_callbackper block, the shared editor script (assets/js/blocks.js, handleus-scheduler-blocks), and the front-end stylesheet (assets/css/frontend.css, handleus-scheduler) as the blockstyleso it also loads inside the editor and previews pick up theme styling.assets/js/blocks.js(vanilla JS, no build step) registers the client side of each block — title, icon, keywords, shortcode transform — and renders the editor preview withwp.serverSideRender, which fetches the server-rendered markup via the/wp/v2/block-rendererREST route.BlockPreview(src/BlockPreview.php) supplies static, script-free markup for editor previews.BlockRegistrar::isEditorPreview()detects the block-renderer context via theREST_REQUESTconstant (front-end template rendering never happens inside a REST request) and renders the preview instead of the live page.
Editor preview behaviour
Live pages cannot run in the editor: booking and group classes are populated by JavaScript making authenticated REST calls (and may load Stripe.js), registration requires a valid invite token, and login short-circuits for logged-in users (the editing admin always is). Each preview therefore reproduces the live wrapper elements and CSS classes with representative placeholder content:
- Booking —
#us-booking-appwith sample.us-day/.us-slotrows and disabled Book buttons. - Group classes —
#us-group-appwith a sample.us-classcard and a disabled Enrol button. - Login — the real
templates/frontend/login-page.phptemplate (it has no request-state dependencies). - Registration — a disabled sample of the
.us-register-formfields.
Each preview starts with a .us-editor-note paragraph explaining what the
published page shows instead. The note class only appears in editor previews.
Tests
tests/Unit/BlockRegistrarTest.php— hook registration, block/asset registration, attribute schemas, front-end delegation to the page objects, preview-mode routing, auto-redirect behaviour.tests/Unit/Booking/BookingPageTest.php— logged-out login-link targets and fallbacks.tests/Unit/Auth/LoginPageTest.php— logged-in booking-link targets and fallbacks.tests/Unit/BlockPreviewTest.php— preview markup mirrors the live CSS classes/ids and includes the editor note.