CI / Build Plugin Zip (pull_request) Has been skipped
CI / Tests (PHP 8.2) (pull_request) Successful in 45s
CI / PHPStan (pull_request) Successful in 2m48s
CI / Tests (PHP 8.1) (pull_request) Successful in 41s
CI / No Debug Code (pull_request) Failing after 2s
CI / Coding Standards (pull_request) Successful in 52s
CI / Tests (PHP 8.3) (pull_request) Successful in 2m36s
Availability windows were stored and served as a single bookable row, so a 9:00 AM-4:00 PM window showed to students as one giant slot and booking it consumed the whole day; past and multi-day windows also leaked into the booking page as nonsense entries. - Split windows into consecutive lesson-length slots on save (REST and admin form); each chunk is independently bookable and weekly recurrence creates a series per chunk so "reserve this time weekly" holds the same hour each week - Reject windows spanning multiple days or shorter than the lesson length (400 invalid_window) - Never return slots whose start has passed from GET /availability - Migrate pre-split rows: Plugin::boot re-runs the Installer on version change and AvailabilityRepository::splitOversizedWindows() rewrites unbooked same-day oversized windows in place - Display all times in 12-hour AM/PM form (booking page, wp-admin lists, editor previews) - Add a List | Week view toggle to the student booking page and the instructor availability page, with previous/next-week navigation honouring the site's start_of_week option (new WeekCalendar helper) Co-Authored-By: Claude Fable 5 <[email protected]>
115 lines
4.0 KiB
PHP
115 lines
4.0 KiB
PHP
<?php
|
||
declare(strict_types=1);
|
||
|
||
namespace Unsupervised\Schedular;
|
||
|
||
/**
|
||
* Static, script-free markup for the editor previews of the front-end blocks.
|
||
*
|
||
* The booking and group-class pages are populated by JavaScript on the live
|
||
* site, and the registration page requires a valid invite token — none of
|
||
* which exist inside the block editor. These previews reproduce the same
|
||
* wrapper elements and CSS classes the live pages use, filled with
|
||
* representative placeholder content, so themes can be styled against
|
||
* realistic markup without firing REST calls, redirects, or Stripe.js.
|
||
*/
|
||
class BlockPreview {
|
||
|
||
public static function booking(): string {
|
||
$days = [
|
||
[
|
||
'label' => __( 'Monday', 'unsupervised-schedular' ),
|
||
'slots' => [
|
||
[ '4:00 PM–4:30 PM', 30 ],
|
||
[ '4:30 PM–5:00 PM', 30 ],
|
||
],
|
||
],
|
||
[
|
||
'label' => __( 'Wednesday', 'unsupervised-schedular' ),
|
||
'slots' => [
|
||
[ '5:00 PM–5:45 PM', 45 ],
|
||
],
|
||
],
|
||
];
|
||
|
||
$dayHtml = '';
|
||
foreach ( $days as $day ) {
|
||
$slotHtml = '';
|
||
foreach ( $day['slots'] as $slot ) {
|
||
$slotHtml .= sprintf(
|
||
'<div class="us-slot"><span>%s (%d min)</span><button type="button" class="us-book-btn" disabled>%s</button></div>',
|
||
esc_html( $slot[0] ),
|
||
(int) $slot[1],
|
||
esc_html__( 'Book', 'unsupervised-schedular' )
|
||
);
|
||
}
|
||
|
||
$dayHtml .= sprintf(
|
||
'<div class="us-day"><h3 class="us-day-heading">%s</h3>%s</div>',
|
||
esc_html( $day['label'] ),
|
||
$slotHtml
|
||
);
|
||
}
|
||
|
||
return sprintf(
|
||
'<div id="us-booking-app">%s<div id="us-slot-list">%s</div></div>',
|
||
self::note( __( 'Editor preview — students see live availability on the published page.', 'unsupervised-schedular' ) ),
|
||
$dayHtml
|
||
);
|
||
}
|
||
|
||
public static function groupClasses(): string {
|
||
return sprintf(
|
||
'<div id="us-group-app">%s<div id="us-group-list"><div class="us-class"><h3>%s</h3><p>%s</p><p>%s</p><p>25.00 CAD</p><button type="button" class="us-enrol-btn" disabled>%s</button></div></div></div>',
|
||
self::note( __( 'Editor preview — students see live group classes on the published page.', 'unsupervised-schedular' ) ),
|
||
esc_html__( 'Beginner Group Class', 'unsupervised-schedular' ),
|
||
esc_html__( 'Saturdays 10:00 AM–11:00 AM', 'unsupervised-schedular' ),
|
||
esc_html__( 'A sample class shown so the page can be styled.', 'unsupervised-schedular' ),
|
||
esc_html__( 'Enrol', 'unsupervised-schedular' )
|
||
);
|
||
}
|
||
|
||
/**
|
||
* The live login form renders fine without any request state, so the
|
||
* preview includes the real template (the editing user is logged in, which
|
||
* would otherwise short-circuit to an "already logged in" message).
|
||
*/
|
||
public static function login(): string {
|
||
$error = '';
|
||
|
||
ob_start();
|
||
include USC_PLUGIN_DIR . 'templates/frontend/login-page.php';
|
||
|
||
return self::note( __( 'Editor preview — logged-in visitors are offered a link to the booking page instead.', 'unsupervised-schedular' ) ) . (string) ob_get_clean();
|
||
}
|
||
|
||
public static function registration(): string {
|
||
$fields = sprintf(
|
||
'<p><label for="us-reg-email">%s</label><input type="email" id="us-reg-email" value="[email protected]" readonly></p>',
|
||
esc_html__( 'Email', 'unsupervised-schedular' )
|
||
);
|
||
$fields .= sprintf(
|
||
'<p><label for="us-reg-name">%s</label><input type="text" id="us-reg-name"></p>',
|
||
esc_html__( 'Your name', 'unsupervised-schedular' )
|
||
);
|
||
$fields .= sprintf(
|
||
'<p><label for="us-reg-pass">%s</label><input type="password" id="us-reg-pass"></p>',
|
||
esc_html__( 'Password', 'unsupervised-schedular' )
|
||
);
|
||
$fields .= sprintf(
|
||
'<p><input type="submit" value="%s" disabled></p>',
|
||
esc_attr__( 'Create Account', 'unsupervised-schedular' )
|
||
);
|
||
|
||
return sprintf(
|
||
'<div class="us-register-form">%s<form>%s</form></div>',
|
||
self::note( __( 'Editor preview — the live form requires a valid invite link and lists signup policies.', 'unsupervised-schedular' ) ),
|
||
$fields
|
||
);
|
||
}
|
||
|
||
private static function note( string $text ): string {
|
||
return '<p class="us-editor-note">' . esc_html( $text ) . '</p>';
|
||
}
|
||
}
|