Eloquenza

Preferiti

I corsi che hai salvato per dopo. overbalizing.pro

') ]); document.getElementById('site-header').innerHTML = h; document.getElementById('site-footer').innerHTML = f; initHeader(); initFooter(); } catch(e) {} function initHeader() { const btn = document.querySelector('#btn-mobile'); const menu = document.querySelector('#nav-links'); if (btn && menu) btn.addEventListener('click', () => menu.classList.toggle('hidden')); document.querySelectorAll('[data-open-modal]').forEach(o => o.addEventListener('click', () => document.getElementById(o.dataset.openModal).classList.remove('hidden'))); document.querySelectorAll('[data-close-modal]').forEach(c => c.addEventListener('click', () => c.closest('.modal').classList.add('hidden'))); const ct = document.getElementById('contrastToggle'); document.documentElement.classList.toggle('contrast-125', localStorage.getItem('contrast') === 'high'); if (ct) { ct.checked = localStorage.getItem('contrast') === 'high'; ct.addEventListener('change', () => { document.documentElement.classList.toggle('contrast-125', ct.checked); localStorage.setItem('contrast', ct.checked?'high':'normal'); }); } } function initFooter() { const b = document.getElementById('cookies-banner'); const a = document.getElementById('accept-cookies'); if (b && a) { if (localStorage.getItem('cookieConsent')==='1') b.classList.add('hidden'); else b.classList.remove('hidden'); a.addEventListener('click', ()=>{ localStorage.setItem('cookieConsent','1'); b.classList.add('hidden'); }); } } const listEl = document.getElementById('favList'); const emptyEl = document.getElementById('emptyFav'); const exportBtn = document.getElementById('exportJson'); const clearAll = document.getElementById('clearAll'); const exportModal = document.getElementById('modal-export'); const exportContent = document.getElementById('exportContent'); const exportMeta = document.getElementById('exportMeta'); const copyBtn = document.getElementById('copyJson'); const downloadBtn = document.getElementById('downloadJson'); let favorites = []; try { favorites = JSON.parse(localStorage.getItem('favorites') || '[]').filter((v,i,a)=>a.indexOf(v)===i); } catch(e) { favorites = []; } let notes = {}; try { notes = JSON.parse(localStorage.getItem('favoriteNotes') || '{}') || {}; } catch(e) { notes = {}; } let data = []; const debounce = (fn, t=300) => { let id; return (...a)=>{ clearTimeout(id); id=setTimeout(()=>fn(...a), t);} }; const saveNotes = debounce(() => localStorage.setItem('favoriteNotes', JSON.stringify(notes)), 250); function autoResizeTA(ta) { ta.style.height = 'auto'; ta.style.height = Math.min(ta.scrollHeight, 260) + 'px'; } function formatPrice(n) { try { return new Intl.NumberFormat('it-IT', {style:'currency', currency:'EUR', maximumFractionDigits:0}).format(Number(n||0)); } catch(e){ return '€'+(n||0); } } function render() { listEl.innerHTML = ''; const rows = data.filter(x => favorites.map(Number).includes(Number(x.id))); emptyEl.classList.toggle('hidden', rows.length > 0); rows.forEach(it => { const li = document.createElement('li'); li.className = 'p2aql rounded-lg border border-slate-200 bg-white p-5 flex flex-col'; li.innerHTML = `

${it.title}

${it.city} • ${it.mode} • ${it.duration_hours}h • ${formatPrice(it.price)}

Docente: ${it.teacher}

`; listEl.appendChild(li); }); listEl.querySelectorAll('.btn-remove').forEach(b => b.addEventListener('click', () => { const id = +b.dataset.id; const card = b.closest('li'); if (card) { card.classList.add('p2aql-hide'); setTimeout(() => { favorites = favorites.filter(x => Number(x) !== id); localStorage.setItem('favorites', JSON.stringify(favorites)); render(); }, 160); } else { favorites = favorites.filter(x => Number(x) !== id); localStorage.setItem('favorites', JSON.stringify(favorites)); render(); } })); listEl.querySelectorAll('.note').forEach(ta => { autoResizeTA(ta); ta.addEventListener('input', (e) => { autoResizeTA(ta); const id = +ta.dataset.id; notes[id] = ta.value.slice(0, 600); const counter = ta.parentElement.querySelector('.char'); if (counter) counter.textContent = notes[id].length + '/600'; saveNotes(); }); }); } function openExport() { const rows = data.filter(x => favorites.map(Number).includes(Number(x.id))).map(x => ({ id: x.id, title: x.title, city: x.city, mode: x.mode, duration_hours: x.duration_hours, price: x.price, teacher: x.teacher, note: notes[x.id] || '' })); exportContent.textContent = JSON.stringify(rows, null, 2); const ts = new Date(); exportMeta.textContent = 'Elementi: ' + rows.length + ' • ' + ts.toLocaleString('it-IT'); exportModal.classList.remove('hidden'); } exportBtn.addEventListener('click', (e) => { e.preventDefault(); openExport(); }); clearAll.addEventListener('click', () => { if (!favorites.length) return; if (confirm('Sei sicuro di voler svuotare tutti i preferiti?')) { favorites = []; localStorage.setItem('favorites', JSON.stringify(favorites)); render(); } }); exportModal.querySelectorAll('[data-close-modal]').forEach(c => c.addEventListener('click', () => exportModal.classList.add('hidden'))); exportModal.addEventListener('click', e => { if (e.target.id === 'modal-export') exportModal.classList.add('hidden'); }); document.addEventListener('keydown', e => { if (!exportModal.classList.contains('hidden') && e.key === 'Escape') exportModal.classList.add('hidden'); }); copyBtn.addEventListener('click', async () => { try { await navigator.clipboard.writeText(exportContent.textContent); copyBtn.textContent = 'Copiato'; setTimeout(()=>copyBtn.textContent='Copia',1000); } catch(e) {} }); downloadBtn.addEventListener('click', () => { const blob = new Blob([exportContent.textContent || '[]'], {type:'application/json'}); const url = URL.createObjectURL(blob); const a = document.createElement('a'); const d = new Date(); const name = 'preferiti_' + d.toISOString().slice(0,10) + '.json'; a.href = url; a.download = name; document.body.appendChild(a); a.click(); setTimeout(()=>{ URL.revokeObjectURL(url); a.remove(); }, 0); }); try { const resp = await fetch('catalog.json', {cache:'no-store'}); if (!resp.ok) throw new Error('errore'); data = await resp.json(); } catch(e) { data = []; } render(); });