(#3) - templating

This commit is contained in:
Martin Slachta
2026-06-14 07:16:13 +02:00
parent f4d3972d07
commit 8e264b8892
32 changed files with 870 additions and 126 deletions
+8
View File
@@ -179,6 +179,14 @@ export const RsvCalendarPicker = (() => {
new InputEvent('change', { bubbles: true, cancelable: true, composed: true })
);
},
// Re-check the radio for the current date. The date lives in JS state, so
// this restores the visual selection after a native form.reset() clears it.
reselect() {
if (this.date === null) return;
const radio = this.body.querySelector(`input[id="${this.date.toISOString()}"]`);
if (radio) radio.checked = true;
},
};
container.classList.add('rsv-calendar');
@@ -37,6 +37,16 @@ class RsvReservationSelector extends HTMLElement {
this.querySelectorAll('.rsv-slots-slot-selected').forEach(s => s.classList.remove('rsv-slots-slot-selected'));
this._slots = [];
this._commit();
// _commit clears only the slots; keep the picked date selected, re-asserting
// it in case a surrounding form.reset() just unchecked the calendar radio.
this._calendar?.reselect();
}
// Reset for a new reservation: drop the local selection (keeping the date) and
// reload availability so slots booked by the previous submission show as full.
reset() {
this.clear();
this.querySelector('rsv-timeline')?.refresh();
}
// ---- Private ------------------------------------------------------------
+25 -1
View File
@@ -25,6 +25,31 @@ class RsvReservationSummary extends HTMLElement {
}
}
// ---- Public API ---------------------------------------------------------
// Detached, static copy of the current selection for the success message.
// Mirrors the live layout minus the interactive "clear all" control.
snapshot() {
const s = ReservairStrings.summary;
const list = this.querySelector('.rsv-summary-list');
const count = this.querySelector('.rsv-summary-count');
const price = this.querySelector('.rsv-summary-price');
const node = document.createElement('div');
node.className = 'rsv-summary rsv-summary-snapshot';
node.innerHTML = `
<div class="rsv-summary-header">
<span class="rsv-summary-title">${s.title}</span>
</div>
<ul class="rsv-summary-list">${list ? list.innerHTML : ''}</ul>
<div class="rsv-summary-footer">
<span class="rsv-summary-count">${count ? count.textContent : ''}</span>
<div class="rsv-summary-price">${price ? price.textContent : ''}</div>
</div>
`;
return node;
}
// ---- Private ------------------------------------------------------------
_build() {
@@ -51,7 +76,6 @@ class RsvReservationSummary extends HTMLElement {
const all_slots = [...this._all_slots.values()].flatMap(({ slots, price_per_block }) =>
slots.map(s => ({ ...s, price_per_block }))
);
console.log(all_slots);
const n = all_slots.length;
const list = this.querySelector('.rsv-summary-list');
+14 -5
View File
@@ -35,6 +35,14 @@ class RsvTimeline extends HTMLElement {
this._render();
}
// ---- Public API ---------------------------------------------------------
// Re-fetch availability for the current date, e.g. after a booking occupied
// some slots. The date is unchanged, so attributeChangedCallback won't fire.
refresh() {
this._render();
}
// ---- Private ------------------------------------------------------------
_on_click(event) {
@@ -59,10 +67,6 @@ class RsvTimeline extends HTMLElement {
const occupancy = await RsvTimetableService.get_availability_for_date(this.timetableId, this.date);
if (v !== this._version) return;
if(occupancy.length === 0) {
this.replaceChildren(this._notice(s.no_blocks));
return;
}
const header = document.createElement('div');
header.classList.add('rsv-slots-label');
@@ -70,6 +74,11 @@ class RsvTimeline extends HTMLElement {
weekday: 'long', day: 'numeric', month: 'long',
}).replace(',', '');
if(occupancy.length === 0) {
this.replaceChildren(header, this._notice(s.no_blocks));
return;
}
const blocks = [];
for (const { from_minutes, to_minutes, block_size_in_minutes, occupancy: block_occ } of occupancy) {
@@ -107,7 +116,7 @@ class RsvTimeline extends HTMLElement {
cell.classList.add('rsv-slots-slot', 'rsv-slots-slot-available');
cell.dataset.start_utc = from.toISOString();
cell.dataset.end_utc = to.toISOString();
if (left === 0) cell.classList.add('rsv-slots-slot-full');
if (left <= 0) cell.classList.add('rsv-slots-slot-full');
const time_el = document.createElement('span');
time_el.classList.add('rsv-slots-slot-time');