Files
Reservair/assets/js/elements/RsvReservationSummary.js
Martin Slachta 0d829845c4 initial
2026-06-11 19:03:29 +02:00

101 lines
3.4 KiB
JavaScript
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
class RsvReservationSummary extends HTMLElement {
// ---- Lifecycle ----------------------------------------------------------
connectedCallback() {
this._all_slots = new Map(); // name → { slots, price_per_block }
this._form = this.closest('form');
this._build();
if (this._form) {
this._handler = e => {
this._all_slots.set(e.detail.name, {
slots: e.detail.slots,
price_per_block: e.detail.price_per_block,
});
this._render();
};
this._form.addEventListener('rsv:slots-changed', this._handler);
}
}
disconnectedCallback() {
if (this._form && this._handler) {
this._form.removeEventListener('rsv:slots-changed', this._handler);
}
}
// ---- Private ------------------------------------------------------------
_build() {
const s = ReservairStrings.summary;
this.innerHTML = `
<div class="rsv-summary-header">
<span class="rsv-summary-title">${s.title}</span>
<button type="button" class="rsv-summary-clear">${s.clear_all}</button>
</div>
<ul class="rsv-summary-list"></ul>
<div class="rsv-summary-footer">
<span class="rsv-summary-count"></span>
<div class="rsv-summary-price"></div>
</div>
`;
this.hidden = true;
this.querySelector('.rsv-summary-clear').addEventListener('click', () => {
this._form?.querySelectorAll('rsv-reservation-selector').forEach(sel => sel.clear());
});
}
_render() {
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');
const count_el = this.querySelector('.rsv-summary-count');
const price_el = this.querySelector('.rsv-summary-price');
const s = ReservairStrings.summary;
const locale = navigator.language;
this.hidden = n === 0;
if (n === 0) {
list.replaceChildren();
count_el.textContent = '';
price_el.textContent = '';
return;
}
const time_opts = { hour: '2-digit', minute: '2-digit' };
list.replaceChildren(...all_slots.map(slot => {
const start = new Date(slot.start_utc);
const end = new Date(slot.end_utc);
const li = document.createElement('li');
li.className = 'rsv-summary-item';
li.innerHTML = `
<div class="rsv-summary-item-info">
<span class="rsv-summary-item-date">${start.toLocaleDateString(locale, { weekday: 'long', day: 'numeric', month: 'long' })}</span>
<span class="rsv-summary-item-time">${start.toLocaleTimeString(locale, time_opts)} ${end.toLocaleTimeString(locale, time_opts)}</span>
</div>
${slot.price_per_block > 0 ? `<span class="rsv-summary-item-price">${slot.price_per_block} ${s.currency}</span>` : ''}
`;
return li;
}));
const total = all_slots.reduce((sum, slot) => sum + slot.price_per_block, 0);
count_el.textContent = this._fmt_count(n);
price_el.textContent = total > 0 ? `${total} ${s.currency}` : '';
}
_fmt_count(n) {
const s = ReservairStrings.summary;
if (n === 1) return s.count_one;
if (n < 5) return s.count_few.replace('%d', n);
return s.count_many.replace('%d', n);
}
}
customElements.define('rsv-reservation-summary', RsvReservationSummary);