2 Commits
Author SHA1 Message Date
thatguygriff 1975630136 Name the destination page in the continue link
CI / Tests (PHP 8.1) (pull_request) Successful in 49s
CI / Coding Standards (pull_request) Successful in 3m0s
CI / PHPStan (pull_request) Successful in 2m50s
CI / Tests (PHP 8.2) (pull_request) Successful in 47s
CI / No Debug Code (pull_request) Successful in 2s
CI / Tests (PHP 8.3) (pull_request) Successful in 2m43s
CI / Build Plugin Zip (pull_request) Skipped
"Continue to your account" says nothing about where the link goes. Use
the chosen page's own title instead — "Continue to Book a Lesson" — so
the visitor knows before clicking.

An untitled page keeps the generic wording rather than rendering
"Continue to ".
2026-07-28 22:58:24 -03:00
thatguygriff f36c235060 Link a signed-in visitor to the configured continue page
CI / Tests (PHP 8.2) (pull_request) Successful in 47s
CI / Tests (PHP 8.1) (pull_request) Successful in 58s
CI / No Debug Code (pull_request) Successful in 2s
CI / PHPStan (pull_request) Successful in 2m53s
CI / Coding Standards (pull_request) Successful in 2m55s
CI / Tests (PHP 8.3) (pull_request) Successful in 2m37s
CI / Build Plugin Zip (pull_request) Skipped
The registration page's already-logged-in branch returned a bare
sentence with nowhere to go, leaving the visitor to find their own way
to their account. The invited-student branch a few lines above already
built exactly the link that was missing.

Extract that into continueLink() and use it for both logged-in
outcomes. There is deliberately still no wp_login_url() fallback:
sending someone already signed in to the login screen is the same dead
end with extra steps, so with no page configured there is no link.

Both messages now carry the us-register-form wrapper and enqueue the
plugin stylesheet, which the invite branch emitted markup for but never
loaded.

Closes #131
2026-07-28 22:50:10 -03:00
6 changed files with 26 additions and 84 deletions
-5
View File
@@ -11,11 +11,6 @@ When a `v*` tag is pushed, `.gitea/workflows/release.yml` publishes the matching
the plugin to the next patch version and adds a fresh section here for it. Record the plugin to the next patch version and adds a fresh section here for it. Record
each change under the current top section as you work. each change under the current top section as you work.
## [1.2.4]
### Fixed
- The registration page **no longer dead-ends a visitor who is already signed in**. It used to greet them with "You already have an account and are logged in." and nothing else, leaving them to find their own way to the studio. They now get a link onward to the page chosen under the block's **After registration** panel, and the link names it — "Continue to Book a Lesson" rather than the vaguer wording an invited student used to see. With no page chosen, the message appears on its own as before, because sending someone who is already signed in to the sign-in screen helps nobody.
## [1.2.3] ## [1.2.3]
### Changed ### Changed
+16 -57
View File
@@ -34,72 +34,47 @@
margin-top: 8px; margin-top: 8px;
} }
/* .us-my-lessons {
* The upcoming-lessons panel. Every rule here is scoped under #us-booking-app —
* the same id-level specificity .us-slot above uses — because these rows sit in
* whatever layout the theme provides and carry more content than a calendar
* cell. Bare class selectors lost to theme rules on div/span/strong, which
* collapsed the flex layout and piled the details on top of the actions.
*/
#us-booking-app .us-my-lessons {
margin-bottom: 24px; margin-bottom: 24px;
} }
#us-booking-app .us-my-lesson { .us-my-lesson {
box-sizing: border-box;
max-width: 100%;
border: 1px solid #ddd; border: 1px solid #ddd;
border-radius: 4px; border-radius: 4px;
padding: 12px 16px; padding: 12px 16px;
margin-bottom: 8px; margin-bottom: 8px;
display: flex; display: flex;
flex-wrap: wrap;
justify-content: space-between; justify-content: space-between;
align-items: center; align-items: center;
gap: 8px 12px; gap: 12px;
} }
/* .us-my-lesson-info {
* `min-width: 0` lets the title column shrink below its content width — without
* it a long offering title cannot compress and shoves the status pill and
* Cancel button out of the row. The flex-basis keeps the details and the
* actions on one line while there is room, and wraps them once there is not.
*/
#us-booking-app .us-my-lesson-info {
display: flex; display: flex;
flex-direction: column; flex-direction: column;
gap: 2px; gap: 2px;
flex: 1 1 14em;
min-width: 0;
} }
#us-booking-app .us-my-lesson-title, .us-my-lesson-title {
#us-booking-app .us-my-lesson-when {
overflow-wrap: break-word;
word-break: break-word;
}
#us-booking-app .us-my-lesson-title {
font-size: 1.05em; font-size: 1.05em;
} }
#us-booking-app .us-my-lesson-duration { .us-my-lesson-duration {
font-weight: normal; font-weight: normal;
color: #666; color: #666;
} }
#us-booking-app .us-my-lesson-when { .us-my-lesson-when {
color: #555; color: #555;
} }
#us-booking-app .us-my-lesson-actions { .us-my-lesson-actions {
display: flex; display: flex;
flex-wrap: wrap; gap: 12px;
gap: 8px 12px;
align-items: center; align-items: center;
} }
#us-booking-app .us-show-all-lessons { .us-show-all-lessons {
background: transparent; background: transparent;
border: 1px solid #ccc; border: 1px solid #ccc;
border-radius: 4px; border-radius: 4px;
@@ -107,11 +82,11 @@
cursor: pointer; cursor: pointer;
} }
#us-booking-app .us-show-all-lessons:hover { .us-show-all-lessons:hover {
border-color: #888; border-color: #888;
} }
#us-booking-app .us-cancel-lesson { .us-cancel-lesson {
background: transparent; background: transparent;
border: 1px solid #ccc; border: 1px solid #ccc;
border-radius: 4px; border-radius: 4px;
@@ -120,26 +95,24 @@
color: #c00; color: #c00;
} }
#us-booking-app .us-cancel-lesson:hover { .us-cancel-lesson:hover {
border-color: #c00; border-color: #c00;
} }
#us-booking-app .us-lesson-status { .us-lesson-status {
display: inline-block;
font-size: 0.85em; font-size: 0.85em;
font-weight: 600; font-weight: 600;
padding: 2px 10px; padding: 2px 10px;
border-radius: 10px; border-radius: 10px;
background: #eee; background: #eee;
white-space: nowrap;
} }
#us-booking-app .us-lesson-status-confirmed { .us-lesson-status-confirmed {
background: #e2f5e5; background: #e2f5e5;
color: #1a7d2e; color: #1a7d2e;
} }
#us-booking-app .us-lesson-status-pending { .us-lesson-status-pending {
background: #fdf3d7; background: #fdf3d7;
color: #8a6d1a; color: #8a6d1a;
} }
@@ -372,20 +345,6 @@
.us-week-day { .us-week-day {
min-height: 0; min-height: 0;
} }
/*
* A lesson row carries a title, a date/time, a status pill and a button —
* more than fits one narrow line, so stack the details above the actions
* rather than letting them wrap into each other.
*/
#us-booking-app .us-my-lesson {
flex-direction: column;
align-items: stretch;
}
#us-booking-app .us-my-lesson-info {
flex: 0 0 auto;
}
} }
/* Shown only in block-editor previews (see BlockPreview). */ /* Shown only in block-editor previews (see BlockPreview). */
+4 -7
View File
@@ -582,19 +582,16 @@
function lessonRowHtml(l) { function lessonRowHtml(l) {
const title = l.offering_title ? escHtml(String(l.offering_title)) : 'Lesson'; const title = l.offering_title ? escHtml(String(l.offering_title)) : 'Lesson';
const duration = l.duration_minutes ? ` <span class="us-my-lesson-duration">(${escHtml(String(l.duration_minutes))} min)</span>` : ''; const duration = l.duration_minutes ? ` <span class="us-my-lesson-duration">(${escHtml(String(l.duration_minutes))} min)</span>` : '';
// 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 ` return `
<div class="us-my-lesson"> <div class="us-my-lesson">
<div class="us-my-lesson-info"> <span class="us-my-lesson-info">
<strong class="us-my-lesson-title">${title}${duration}</strong> <strong class="us-my-lesson-title">${title}${duration}</strong>
<span class="us-my-lesson-when">${escHtml(dayLabel(dayKey(l.start_dt)))} · ${escHtml(timeOf(l.start_dt))}${escHtml(timeOf(l.end_dt))}</span> <span class="us-my-lesson-when">${escHtml(dayLabel(dayKey(l.start_dt)))} · ${escHtml(timeOf(l.start_dt))}${escHtml(timeOf(l.end_dt))}</span>
</div> </span>
<div class="us-my-lesson-actions"> <span class="us-my-lesson-actions">
<span class="us-lesson-status us-lesson-status-${escHtml(String(l.status))}">${escHtml(lessonStatusLabel(String(l.status)))}</span> <span class="us-lesson-status us-lesson-status-${escHtml(String(l.status))}">${escHtml(lessonStatusLabel(String(l.status)))}</span>
<button type="button" class="us-cancel-lesson" data-lesson-id="${l.id}">Cancel</button> <button type="button" class="us-cancel-lesson" data-lesson-id="${l.id}">Cancel</button>
</div> </span>
</div>`; </div>`;
} }
-9
View File
@@ -154,7 +154,6 @@ instructor may only open their own lessons; the studio **Scheduler** may open an
- Admin lesson detail presenter: `Unsupervised\Schedular\Booking\LessonDetail` (per-lesson intake answers + policy acceptances), template `templates/admin/lesson-detail.php` - Admin lesson detail presenter: `Unsupervised\Schedular\Booking\LessonDetail` (per-lesson intake answers + policy acceptances), template `templates/admin/lesson-detail.php`
- REST endpoint: `Unsupervised\Schedular\Booking\BookingEndpoint` - REST endpoint: `Unsupervised\Schedular\Booking\BookingEndpoint`
- Frontend: `Unsupervised\Schedular\Booking\BookingPage`, `Unsupervised\Schedular\Auth\LoginPage` - Frontend: `Unsupervised\Schedular\Booking\BookingPage`, `Unsupervised\Schedular\Auth\LoginPage`
- Upcoming-lessons panel: rendered client-side into `#us-my-lessons` by `assets/js/booking.js` (`lessonRowHtml`/`renderMyLessons`), mirrored for the editor by `BlockPreview::upcomingLessons()` — keep the two markup shapes in step.
> **Payment seam:** a priced booking is created with `status = pending` and its > **Payment seam:** a priced booking is created with `status = pending` and its
> payment linked via `payment_id`; the lesson is confirmed when the payment is > payment linked via `payment_id`; the lesson is confirmed when the payment is
@@ -162,14 +161,6 @@ instructor may only open their own lessons; the studio **Scheduler** may open an
> Unpriced bookings skip the seam entirely and are confirmed at creation. > Unpriced bookings skip the seam entirely and are confirmed at creation.
> `GET /policies?scope=booking` returns just the booking-gate policies the form > `GET /policies?scope=booking` returns just the booking-gate policies the form
> must collect. > must collect.
>
> **Frontend CSS scoping:** every rule for the booking page's own markup is
> written under `#us-booking-app` (`assets/css/frontend.css`). These panels sit
> inside whatever layout the active theme provides, and bare class selectors lose
> to theme rules on `div`/`span`/`strong` — which flattens the flex layout and
> renders the lesson details on top of the actions. The row's two columns are
> `div`s for the same reason: the layout must not depend on overriding the
> inline default. New booking-page rules should follow both conventions.
## Tests ## Tests
- `tests/Unit/Booking/BookingRepositoryTest.php` - `tests/Unit/Booking/BookingRepositoryTest.php`
+4 -4
View File
@@ -86,13 +86,13 @@ class BlockPreview {
private static function upcomingLessons(): string { private static function upcomingLessons(): string {
return sprintf( return sprintf(
'<div class="us-my-lessons"><h3>%s</h3>' '<div class="us-my-lessons"><h3>%s</h3>'
. '<div class="us-my-lesson"><div class="us-my-lesson-info">' . '<div class="us-my-lesson"><span class="us-my-lesson-info">'
. '<strong class="us-my-lesson-title">%s <span class="us-my-lesson-duration">(30 min)</span></strong>' . '<strong class="us-my-lesson-title">%s <span class="us-my-lesson-duration">(30 min)</span></strong>'
. '<span class="us-my-lesson-when">%s</span></div>' . '<span class="us-my-lesson-when">%s</span></span>'
. '<div class="us-my-lesson-actions">' . '<span class="us-my-lesson-actions">'
. '<span class="us-lesson-status us-lesson-status-confirmed">%s</span>' . '<span class="us-lesson-status us-lesson-status-confirmed">%s</span>'
. '<button type="button" class="us-cancel-lesson" disabled>%s</button>' . '<button type="button" class="us-cancel-lesson" disabled>%s</button>'
. '</div></div></div>', . '</span></div></div>',
esc_html__( 'Your upcoming lessons', 'unsupervised-schedular' ), esc_html__( 'Your upcoming lessons', 'unsupervised-schedular' ),
esc_html__( 'Piano Lesson', 'unsupervised-schedular' ), esc_html__( 'Piano Lesson', 'unsupervised-schedular' ),
esc_html__( 'Monday · 4:00 PM4:30 PM', 'unsupervised-schedular' ), esc_html__( 'Monday · 4:00 PM4:30 PM', 'unsupervised-schedular' ),
+2 -2
View File
@@ -3,7 +3,7 @@
* Plugin Name: Unsupervised Scheduler * Plugin Name: Unsupervised Scheduler
* Plugin URI: https://git.unsupervised.ca/Unsupervised/unsupervised-scheduler * Plugin URI: https://git.unsupervised.ca/Unsupervised/unsupervised-scheduler
* Description: Instructor/student lesson scheduling for WordPress. * Description: Instructor/student lesson scheduling for WordPress.
* Version: 1.2.4 * Version: 1.2.3
* Requires at least: 6.2 * Requires at least: 6.2
* Requires PHP: 8.1 * Requires PHP: 8.1
* Author: Unsupervised * Author: Unsupervised
@@ -21,7 +21,7 @@ if (! defined('ABSPATH')) {
exit; exit;
} }
define('USC_VERSION', '1.2.4'); define('USC_VERSION', '1.2.3');
define('USC_PLUGIN_FILE', __FILE__); define('USC_PLUGIN_FILE', __FILE__);
define('USC_PLUGIN_DIR', plugin_dir_path(__FILE__)); define('USC_PLUGIN_DIR', plugin_dir_path(__FILE__));
define('USC_PLUGIN_URL', plugin_dir_url(__FILE__)); define('USC_PLUGIN_URL', plugin_dir_url(__FILE__));