export class FlowFormuleConfigurator extends HTMLElement { constructor() { super(); this.counts = { structure: 0, alimentaire: 0, barnum: 0 }; this.selection = []; this.blocked = false; this.mode = 'free'; } connectedCallback() { try { this.limits = JSON.parse(this.getAttribute('data-limits') || '{}'); this.prices = JSON.parse(this.getAttribute('data-prices') || '{}'); } catch (e) { console.error('Invalid limits/prices JSON', e); return; } this.formuleId = this.getAttribute('data-formule-id'); this.mode = this.getAttribute('data-mode') || 'free'; this.validateBtn = this.querySelector('#btn-validate-pack'); if (this.mode === 'pack') { try { this.selection = JSON.parse(this.getAttribute('data-preselected-ids') || '[]'); } catch (e) { console.error('Invalid preselected-ids JSON', e); } } else { this.querySelectorAll('.product-card').forEach(card => { card.addEventListener('click', (e) => { e.preventDefault(); this.toggleItem(card); }); }); } if (this.validateBtn) { this.validateBtn.addEventListener('click', (e) => { e.preventDefault(); this.validate(); }); } this.checkDuration(); this.updateUI(); } checkDuration() { const datesStr = sessionStorage.getItem('reservation_dates'); if (!datesStr) return; try { const dates = JSON.parse(datesStr); if (!dates.start || !dates.end) return; const start = new Date(dates.start); const end = new Date(dates.end); const diffTime = Math.abs(end - start); const diffDays = Math.ceil(diffTime / (1000 * 60 * 60 * 24)) + 1; let message = null; let block = false; if (diffDays > 5) { message = `Attention : La durée de votre réservation (${diffDays} jours) dépasse la limite autorisée de 5 jours pour cette formule.`; block = true; } else if (diffDays >= 3 && diffDays <= 5) { message = `Information : Pour une durée de ${diffDays} jours, le tarif "5 jours" sera appliqué automatiquement.`; } if (message) { let msgContainer = this.querySelector('.formule-warning'); if (!msgContainer) { msgContainer = document.createElement('div'); this.prepend(msgContainer); } msgContainer.className = `formule-warning p-4 mb-6 rounded-2xl text-sm font-bold text-center border-2 ${block ? 'bg-red-50 border-red-100 text-red-600' : 'bg-blue-50 border-blue-100 text-blue-600'}`; msgContainer.innerHTML = message; } this.blocked = block; this.updateUI(); } catch (e) { console.error(e); } } toggleItem(el) { if (this.blocked || this.mode === 'pack') return; const category = el.getAttribute('data-category'); const id = el.getAttribute('data-id'); const isSelected = el.getAttribute('data-selected') === 'true'; if (isSelected) { this.deselect(el, category, id); } else { if (this.counts[category] < this.limits[category]) { this.select(el, category, id); } else { this.shake(el); } } this.updateUI(); } select(el, category, id) { el.setAttribute('data-selected', 'true'); el.classList.add('ring-4', 'ring-[#f39e36]', 'scale-95'); const indicator = el.querySelector('.selection-indicator'); if (indicator) { indicator.classList.remove('opacity-0', 'group-hover:opacity-100'); indicator.classList.add('opacity-100'); indicator.querySelector('div')?.classList.remove('hidden'); } this.counts[category]++; this.selection.push(id); } deselect(el, category, id) { el.setAttribute('data-selected', 'false'); el.classList.remove('ring-4', 'ring-[#f39e36]', 'scale-95'); const indicator = el.querySelector('.selection-indicator'); if (indicator) { indicator.classList.remove('opacity-100'); indicator.classList.add('opacity-0', 'group-hover:opacity-100'); indicator.querySelector('div')?.classList.add('hidden'); } this.counts[category]--; this.selection = this.selection.filter(item => item !== id); } shake(el) { el.classList.add('animate-pulse'); setTimeout(() => el.classList.remove('animate-pulse'), 500); alert("Limite atteinte pour cette catégorie."); } updateUI() { if (this.mode === 'free') { ['structure', 'alimentaire', 'barnum'].forEach(cat => { const span = this.querySelector(`#count-${cat}`); if (span) span.innerText = this.counts[cat]; }); } const total = this.selection.length; if (this.validateBtn) { if (this.blocked) { this.validateBtn.innerText = 'Durée non autorisée (> 5j)'; this.validateBtn.classList.add('opacity-50', 'pointer-events-none', 'translate-y-4', 'bg-red-600'); this.validateBtn.classList.remove('bg-slate-900', 'hover:bg-[#fc0e50]'); } else { this.validateBtn.innerText = this.mode === 'pack' ? 'Réserver ce pack' : `Valider mon pack (${total})`; this.validateBtn.classList.remove('bg-red-600'); this.validateBtn.classList.add('bg-slate-900', 'hover:bg-[#fc0e50]'); if (total > 0) { this.validateBtn.classList.remove('opacity-50', 'pointer-events-none', 'translate-y-4'); } else { this.validateBtn.classList.add('opacity-50', 'pointer-events-none', 'translate-y-4'); } } } } validate() { if (this.blocked || this.selection.length === 0) return; sessionStorage.setItem('active_formule', this.formuleId); let list = []; try { list = JSON.parse(sessionStorage.getItem('pl_list') || '[]'); } catch(e) {} const newItems = this.selection.filter(id => !list.includes(id)); if (newItems.length > 0) { list = [...list, ...newItems]; sessionStorage.setItem('pl_list', JSON.stringify(list)); } window.dispatchEvent(new CustomEvent('cart:updated')); const cart = document.querySelector('[is="flow-reserve"]'); if (cart) cart.open(); } }