initial
This commit is contained in:
@@ -0,0 +1,117 @@
|
||||
class RsvReservationSelector extends HTMLElement {
|
||||
static get observedAttributes() {
|
||||
return ['timetable-id', 'name', 'price-per-block'];
|
||||
}
|
||||
|
||||
// ---- Attribute accessors ------------------------------------------------
|
||||
|
||||
get timetableId() { return parseInt(this.getAttribute('timetable-id')); }
|
||||
get inputName() { return this.getAttribute('name') ?? 'reservation'; }
|
||||
get pricePerBlock() { return parseFloat(this.getAttribute('price-per-block')) || 0; }
|
||||
|
||||
// ---- Lifecycle ----------------------------------------------------------
|
||||
|
||||
connectedCallback() {
|
||||
this._slots = [];
|
||||
this.classList.add('rsv-timetable-selector');
|
||||
this._build();
|
||||
}
|
||||
|
||||
attributeChangedCallback(_attr, oldVal, newVal) {
|
||||
if (oldVal === null || oldVal === newVal || !this.isConnected) return;
|
||||
this._build();
|
||||
}
|
||||
|
||||
// ---- Public API ---------------------------------------------------------
|
||||
|
||||
getValue() {
|
||||
return {
|
||||
timetable_id: this.timetableId,
|
||||
timetable_reservations: this._slots.map(s => s.start_utc),
|
||||
};
|
||||
}
|
||||
|
||||
clear() {
|
||||
this.querySelectorAll('.rsv-slots-slot-selected').forEach(s => s.classList.remove('rsv-slots-slot-selected'));
|
||||
this._slots = [];
|
||||
this._commit();
|
||||
}
|
||||
|
||||
// ---- Private ------------------------------------------------------------
|
||||
|
||||
_build() {
|
||||
this._slots = [];
|
||||
this.replaceChildren();
|
||||
|
||||
const tid = document.createElement('input');
|
||||
tid.type = 'hidden';
|
||||
tid.name = `${this.inputName}.timetable_id`;
|
||||
tid.value = this.timetableId;
|
||||
this.appendChild(tid);
|
||||
|
||||
const cal_el = document.createElement('div');
|
||||
cal_el.classList.add('rsv-calendar');
|
||||
|
||||
// Create rsv-timeline with timetable-id set before appending so
|
||||
// connectedCallback sees the correct attribute on first render.
|
||||
const time_el = document.createElement('rsv-timeline');
|
||||
time_el.setAttribute('timetable-id', this.timetableId);
|
||||
|
||||
this.append(cal_el, time_el);
|
||||
|
||||
this._calendar = RsvCalendarPicker.create(cal_el, this.inputName);
|
||||
|
||||
// Date change: clear selection, then push new date to the timeline element.
|
||||
cal_el.addEventListener('change', () => {
|
||||
this.querySelectorAll('.rsv-slots-slot-selected').forEach(s => s.classList.remove('rsv-slots-slot-selected'));
|
||||
this._slots = [];
|
||||
this._commit();
|
||||
time_el.date = this._calendar.date;
|
||||
});
|
||||
|
||||
// Slot toggle: read selected slots from timeline, then commit.
|
||||
time_el.addEventListener('input', e => {
|
||||
e.stopPropagation();
|
||||
this._slots = Array.from(time_el.querySelectorAll('.rsv-slots-slot-selected')).map(s => ({
|
||||
start_utc: s.dataset.start_utc,
|
||||
end_utc: s.dataset.end_utc,
|
||||
}));
|
||||
this._commit();
|
||||
});
|
||||
|
||||
this._commit();
|
||||
}
|
||||
|
||||
_commit() {
|
||||
const name = this.inputName;
|
||||
|
||||
this.querySelectorAll(`input[name="${name}.timetable_reservations[]"]`).forEach(i => i.remove());
|
||||
|
||||
let json = [];
|
||||
this._slots.forEach(slot => {
|
||||
const inp = document.createElement('input');
|
||||
inp.type = 'hidden';
|
||||
inp.name = `${name}.timetable_reservations[]`;
|
||||
inp.value = slot.start_utc;
|
||||
this.appendChild(inp);
|
||||
json.push(slot.start_utc);
|
||||
});
|
||||
|
||||
this.value = JSON.stringify({
|
||||
"timetable_id": this.timetableId,
|
||||
"timetable_reservations": json
|
||||
});
|
||||
|
||||
this.dispatchEvent(new CustomEvent('rsv:slots-changed', {
|
||||
bubbles: true,
|
||||
detail: {
|
||||
name,
|
||||
slots: this._slots,
|
||||
price_per_block: this.pricePerBlock,
|
||||
value: this.getValue(),
|
||||
},
|
||||
}));
|
||||
}
|
||||
}
|
||||
|
||||
customElements.define('rsv-reservation-selector', RsvReservationSelector);
|
||||
Reference in New Issue
Block a user