diff --git a/assets/css/frontend.css b/assets/css/frontend.css index 99a6b5a..e305d00 100644 --- a/assets/css/frontend.css +++ b/assets/css/frontend.css @@ -34,47 +34,72 @@ 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; } -.us-my-lesson { +#us-booking-app .us-my-lesson { + box-sizing: border-box; + max-width: 100%; border: 1px solid #ddd; border-radius: 4px; padding: 12px 16px; margin-bottom: 8px; display: flex; + flex-wrap: wrap; justify-content: space-between; align-items: center; - gap: 12px; + gap: 8px 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; flex-direction: column; gap: 2px; + flex: 1 1 14em; + min-width: 0; } -.us-my-lesson-title { +#us-booking-app .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; } -.us-my-lesson-duration { +#us-booking-app .us-my-lesson-duration { font-weight: normal; color: #666; } -.us-my-lesson-when { +#us-booking-app .us-my-lesson-when { color: #555; } -.us-my-lesson-actions { +#us-booking-app .us-my-lesson-actions { display: flex; - gap: 12px; + flex-wrap: wrap; + gap: 8px 12px; align-items: center; } -.us-show-all-lessons { +#us-booking-app .us-show-all-lessons { background: transparent; border: 1px solid #ccc; border-radius: 4px; @@ -82,11 +107,11 @@ cursor: pointer; } -.us-show-all-lessons:hover { +#us-booking-app .us-show-all-lessons:hover { border-color: #888; } -.us-cancel-lesson { +#us-booking-app .us-cancel-lesson { background: transparent; border: 1px solid #ccc; border-radius: 4px; @@ -95,24 +120,26 @@ color: #c00; } -.us-cancel-lesson:hover { +#us-booking-app .us-cancel-lesson:hover { border-color: #c00; } -.us-lesson-status { +#us-booking-app .us-lesson-status { + display: inline-block; font-size: 0.85em; font-weight: 600; padding: 2px 10px; border-radius: 10px; background: #eee; + white-space: nowrap; } -.us-lesson-status-confirmed { +#us-booking-app .us-lesson-status-confirmed { background: #e2f5e5; color: #1a7d2e; } -.us-lesson-status-pending { +#us-booking-app .us-lesson-status-pending { background: #fdf3d7; color: #8a6d1a; } @@ -345,6 +372,20 @@ .us-week-day { 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). */ diff --git a/assets/js/booking.js b/assets/js/booking.js index 11261a9..aa51ff7 100644 --- a/assets/js/booking.js +++ b/assets/js/booking.js @@ -582,16 +582,19 @@ function lessonRowHtml(l) { const title = l.offering_title ? escHtml(String(l.offering_title)) : 'Lesson'; const duration = l.duration_minutes ? ` (${escHtml(String(l.duration_minutes))} min)` : ''; + // 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 `
- +
${title}${duration} ${escHtml(dayLabel(dayKey(l.start_dt)))} · ${escHtml(timeOf(l.start_dt))}–${escHtml(timeOf(l.end_dt))} - - +
+
${escHtml(lessonStatusLabel(String(l.status)))} - +
`; } diff --git a/docs/features/lesson-booking.md b/docs/features/lesson-booking.md index d81797b..af19038 100644 --- a/docs/features/lesson-booking.md +++ b/docs/features/lesson-booking.md @@ -154,6 +154,7 @@ 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` - REST endpoint: `Unsupervised\Schedular\Booking\BookingEndpoint` - 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 linked via `payment_id`; the lesson is confirmed when the payment is @@ -161,6 +162,14 @@ instructor may only open their own lessons; the studio **Scheduler** may open an > Unpriced bookings skip the seam entirely and are confirmed at creation. > `GET /policies?scope=booking` returns just the booking-gate policies the form > 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/Unit/Booking/BookingRepositoryTest.php` diff --git a/src/BlockPreview.php b/src/BlockPreview.php index fec2615..a6682ef 100644 --- a/src/BlockPreview.php +++ b/src/BlockPreview.php @@ -86,13 +86,13 @@ class BlockPreview { private static function upcomingLessons(): string { return sprintf( '

%s

' - . '
' + . '
' . '%s (30 min)' - . '%s' - . '' + . '%s
' + . '
' . '%s' . '' - . '
', + . '
', esc_html__( 'Your upcoming lessons', 'unsupervised-schedular' ), esc_html__( 'Piano Lesson', 'unsupervised-schedular' ), esc_html__( 'Monday · 4:00 PM–4:30 PM', 'unsupervised-schedular' ),