Merge pull request 'Show booked lesson info on upcoming lists and add admin booking detail' (#104) from feature/lesson-booking-detail into main
CI / Tests (PHP 8.2) (push) Successful in 39s
CI / Coding Standards (push) Successful in 2m52s
CI / PHPStan (push) Successful in 2m55s
CI / Tests (PHP 8.3) (push) Successful in 2m36s
CI / Tests (PHP 8.1) (push) Successful in 55s
CI / No Debug Code (push) Successful in 2s
CI / Build Plugin Zip (push) Successful in 2m46s

Reviewed-on: #104
This commit was merged in pull request #104.
This commit is contained in:
2026-07-24 14:12:33 +00:00
12 changed files with 569 additions and 21 deletions
+32
View File
@@ -46,6 +46,26 @@
display: flex;
justify-content: space-between;
align-items: center;
gap: 12px;
}
.us-my-lesson-info {
display: flex;
flex-direction: column;
gap: 2px;
}
.us-my-lesson-title {
font-size: 1.05em;
}
.us-my-lesson-duration {
font-weight: normal;
color: #666;
}
.us-my-lesson-when {
color: #555;
}
.us-my-lesson-actions {
@@ -54,6 +74,18 @@
align-items: center;
}
.us-show-all-lessons {
background: transparent;
border: 1px solid #ccc;
border-radius: 4px;
padding: 6px 14px;
cursor: pointer;
}
.us-show-all-lessons:hover {
border-color: #888;
}
.us-cancel-lesson {
background: transparent;
border: 1px solid #ccc;
+38 -9
View File
@@ -388,6 +388,25 @@
return status.charAt(0).toUpperCase() + status.slice(1);
}
// How many upcoming lessons to show before the "Show all" reveal.
const INITIAL_LESSON_COUNT = 5;
function lessonRowHtml(l) {
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>` : '';
return `
<div class="us-my-lesson">
<span class="us-my-lesson-info">
<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>
<span class="us-my-lesson-actions">
<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>
</span>
</div>`;
}
function renderMyLessons(lessons) {
const upcoming = lessons.filter((l) => l.start_dt);
if (!upcoming.length) {
@@ -395,20 +414,30 @@
return;
}
// Show only the soonest few by default; the rest sit hidden behind a
// reveal so a busy student's list stays short.
const visible = upcoming.slice(0, INITIAL_LESSON_COUNT);
const hidden = upcoming.slice(INITIAL_LESSON_COUNT);
myLessons.innerHTML = `
<div class="us-my-lessons">
<h3>Your upcoming lessons</h3>
${upcoming.map((l) => `
<div class="us-my-lesson">
<span>${escHtml(dayLabel(dayKey(l.start_dt)))} · ${escHtml(timeOf(l.start_dt))}${escHtml(timeOf(l.end_dt))}</span>
<span class="us-my-lesson-actions">
<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>
</span>
</div>
`).join('')}
${visible.map(lessonRowHtml).join('')}
${hidden.length ? `
<div class="us-my-lessons-more" hidden>${hidden.map(lessonRowHtml).join('')}</div>
<button type="button" class="us-show-all-lessons">Show all ${upcoming.length} lessons</button>
` : ''}
</div>`;
const moreBox = myLessons.querySelector('.us-my-lessons-more');
const showAll = myLessons.querySelector('.us-show-all-lessons');
if (showAll && moreBox) {
showAll.addEventListener('click', () => {
moreBox.hidden = false;
showAll.remove();
});
}
myLessons.querySelectorAll('.us-cancel-lesson').forEach((btn) => {
btn.addEventListener('click', () => cancelLesson(Number(btn.dataset.lessonId)));
});