Entrar / Registrarse

Demo local — no se envían datos.

Catálogo

Resultados: 0
'; document.getElementById('theme-fallback')?.addEventListener('click', toggleTheme); }); fetch('./footer.html').then(r=>r.text()).then(f=>{ document.querySelector('footer').innerHTML = f; bindFooter(); }).catch(()=>{ document.querySelector('footer').innerHTML = ''; }); } function toggleTheme(){ document.documentElement.classList.toggle('dark'); localStorage.setItem('theme', document.documentElement.classList.contains('dark')?'dark':'light'); } function bindHeader(){ document.querySelectorAll('[data-modal-target]').forEach(b=> b.onclick = ()=> document.getElementById(b.dataset.modalTarget).showModal()); document.getElementById('theme-toggle')?.addEventListener('click', toggleTheme); } function bindFooter(){ document.getElementById('cookies-accept')?.addEventListener('click', ()=> { localStorage.setItem('cookiesAccepted','1'); document.getElementById('cookies-banner')?.classList.add('hidden'); }); } (function initTheme(){ if(localStorage.getItem('theme')==='dark') document.documentElement.classList.add('dark'); })(); injectHF(); function getFallows(){ return JSON.parse(localStorage.getItem('fallows')||'[]'); } function setFallows(v){ localStorage.setItem('fallows', JSON.stringify(v)); } function getCart(){ return JSON.parse(localStorage.getItem('cart')||'[]'); } function setCart(v){ localStorage.setItem('cart', JSON.stringify(v)); } function renderSkeleton(n=8){ const g = el('grid'); g.innerHTML=''; for(let i=0;i
`; g.appendChild(s); } const p = el('pagination'); p.innerHTML=''; } function syncURL(){ const params = new URLSearchParams(); const qv = el('q').value.trim(); if(qv) params.set('q', qv); const cv = el('category').value; if(cv) params.set('category', cv); const lv = el('location').value; if(lv) params.set('location', lv); const pv = el('priceMax').value; if(pv) params.set('priceMax', pv); const dv = el('durationMin').value; if(dv) params.set('durationMin', dv); if(state.page>1) params.set('page', String(state.page)); const qs = params.toString(); history.replaceState(null, '', qs ? ('?'+qs) : location.pathname + location.hash); } function restoreFiltersFromURL(){ const p = new URLSearchParams(location.search); if(p.has('q')) el('q').value = p.get('q') || ''; if(p.has('category')) el('category').value = p.get('category') || ''; if(p.has('location')) el('location').value = p.get('location') || ''; if(p.has('priceMax')) el('priceMax').value = p.get('priceMax') || ''; if(p.has('durationMin')) el('durationMin').value = p.get('durationMin') || ''; if(p.has('page')) { const pg = parseInt(p.get('page')||'1',10); if(!isNaN(pg)&&pg>0) state.page=pg; } } async function loadCatalog(){ try{ state.loading = true; renderSkeleton(state.perPage); const res = await fetch('./catalog.json', {cache:'no-store'}); if(!res.ok) throw new Error('Network'); const data = await res.json(); state.data = Array.isArray(data)?data:[]; // categories state.categories.clear(); state.data.forEach(p=> state.categories.add(p.category)); const catSel = el('category'); const currentCat = catSel.value; catSel.innerHTML = ''; [...state.categories].sort().forEach(c=>{ const o = document.createElement('option'); o.value=c; o.textContent=c; catSel.appendChild(o); }); if(currentCat) catSel.value = currentCat; restoreFiltersFromURL(); applyFilters(false); renderLdItemList(); // open from hash if(location.hash && location.hash.length>1){ const slug = location.hash.slice(1); const item = state.data.find(p=> p.slug === slug); if(item) openDetails(item.id); } }catch(e){ const g = el('grid'); g.innerHTML = '
No se pudo cargar el catálogo. Intenta nuevamente.
'; }finally{ state.loading = false; } } function applyFilters(updateUrl = true){ const q = el('q').value.trim().toLowerCase(); const cat = el('category').value; const loc = el('location').value; const pmax = parseInt(el('priceMax').value || '0', 10); const dmin = parseInt(el('durationMin').value || '0', 10); state.filtered = state.data.filter(p=>{ if(cat && p.category !== cat) return false; if(loc && p.location !== loc) return false; if(pmax && p.price > pmax) return false; if(dmin && p.durationMinutes < dmin) return false; if(q){ const blob = (p.title + ' ' + p.category + ' ' + p.tags.join(' ') + ' ' + p.description).toLowerCase(); if(!blob.includes(q)) return false; } return true; }); if(state.page > Math.ceil(state.filtered.length/state.perPage)) state.page = 1; el('results-count').textContent = state.filtered.length; el('page-indicator').textContent = state.page; renderGrid(); renderPagination(); if(updateUrl) syncURL(); } function renderGrid(){ const start = (state.page-1)*state.perPage; const visible = state.filtered.slice(start, start+state.perPage); const favs = new Set(getFallows()); const g = el('grid'); g.innerHTML=''; if(visible.length === 0){ g.innerHTML = '
No hay resultados para los filtros aplicados.
'; return; } visible.forEach(p=>{ const card = document.createElement('article'); card.id = p.slug || p.id; const disable = !p.availability; const availability = p.availability ? 'Disponible' : 'Agotado'; card.className = 'overflow-hidden rounded-2xl border border-slate-200 dark:border-slate-800 c-raise bg-white dark:bg-slate-900'; card.innerHTML = `
Imagen generada del paquete ${p.title}

${p.title}

${availability}

${p.category} • ${p.location} • ${p.durationMinutes} min

${p.price.toLocaleString('es-CL')} CLP

${'★★★★★'.slice(0, Math.round(p.rating||5))}
`; g.appendChild(card); }); g.querySelectorAll('.fav-btn').forEach(b=> b.addEventListener('click', (ev)=>{ ev.stopPropagation(); const id = b.dataset.id; const arr = getFallows(); const i = arr.indexOf(id); if(i>-1){ arr.splice(i,1); } else { arr.push(id); } setFallows(arr); applyFilters(); })); g.querySelectorAll('.details-btn').forEach(b=> b.addEventListener('click', ()=> openDetails(b.dataset.id))); g.querySelectorAll('.add-cart-btn').forEach(b=> b.addEventListener('click', ()=>{ if(b.disabled) return; const cart = getCart(); const id = b.dataset.id; const found = cart.find(i=>i.id===id); if(found){ found.quantity += 1; } else { cart.push({id, quantity:1}); } setCart(cart); toast('Añadido al carrito'); })); } function renderPagination(){ const total = Math.ceil(state.filtered.length / state.perPage) || 1; const p = el('pagination'); p.innerHTML=''; const mkBtn = (label, page, disabled=false, isCurrent=false)=>{ const btn = document.createElement('button'); btn.textContent = label; btn.className = 'p2aql rounded-full border px-3 py-1 text-sm ' + (isCurrent?'bg-slate-900 text-white border-slate-900 dark:bg-slate-100 dark:text-slate-900 dark:border-slate-100':'border-slate-300 hover:bg-slate-50 dark:border-slate-700 dark:hover:bg-slate-800'); btn.disabled = disabled || isCurrent; btn.addEventListener('click', ()=>{ state.page = page; el('page-indicator').textContent = state.page; renderGrid(); renderPagination(); window.scrollTo({top:0, behavior:'smooth'}); syncURL(); }); return btn; }; p.appendChild(mkBtn('«', 1, state.page===1)); p.appendChild(mkBtn('‹', Math.max(1, state.page-1), state.page===1)); for(let i=1;i<=total;i++){ if(i===1 || i===total || Math.abs(i-state.page)<=1){ p.appendChild(mkBtn(String(i), i, false, i===state.page)); }else if(Math.abs(i-state.page)===2){ const dot = document.createElement('span'); dot.textContent='…'; dot.className='px-1 text-slate-400'; p.appendChild(dot); } } p.appendChild(mkBtn('›', Math.min(total, state.page+1), state.page===total)); p.appendChild(mkBtn('»', total, state.page===total)); } function openDetails(id){ const p = state.data.find(x=>x.id===id); const c = document.getElementById('details-content'); if(!p) return; c.innerHTML = `
Vista generada del paquete ${p.title}

${p.title}

${p.description}

    ${Array.isArray(p.features)?p.features.map(f=>`
  • • ${f}
  • `).join(''):''}

${p.price.toLocaleString('es-CL')} CLP

${p.availability?'Disponible':'Agotado'}
${p.category} • ${p.location} • ${p.durationMinutes} min

chiladros.pro

`; const dlg = document.getElementById('details-modal'); dlg.showModal(); c.querySelector('.close-modal').onclick = ()=> dlg.close(); c.querySelector('.add-cart-modal')?.addEventListener('click', (e)=> { const cart = getCart(); const id = e.target.dataset.id; const found = cart.find(i=>i.id===id); if(found){ found.quantity += 1; } else { cart.push({id, quantity:1}); } setCart(cart); toast('Añadido al carrito'); dlg.close(); }); c.querySelector('.add-fav-modal').onclick = (e)=> { const arr = getFallows(); const id = e.target.dataset.id; if(!arr.includes(id)) arr.push(id); setFallows(arr); toast('Guardado en favoritos'); applyFilters(); }; dlg.addEventListener('click', (e)=>{ const rect = c.getBoundingClientRect(); const inDialog = e.clientX >= rect.left && e.clientX <= rect.right && e.clientY >= rect.top && e.clientY <= rect.bottom; if(!inDialog) dlg.close(); }, {once:true}); } function toast(msg){ let t = document.querySelector('#toast-x3l9p'); if(!t){ t = document.createElement('div'); t.id='toast-x3l9p'; t.className='fixed bottom-4 left-1/2 -translate-x-1/2 z-50'; document.body.appendChild(t); } const note = document.createElement('div'); note.className='mb-2 rounded-full bg-slate-900 px-4 py-2 text-white shadow dark:bg-slate-100 dark:text-slate-900'; note.textContent = msg; t.appendChild(note); setTimeout(()=>{ note.style.transition='opacity .3s ease, transform .3s ease'; note.style.opacity='0'; note.style.transform='translateY(6px)'; }, 1400); setTimeout(()=> note.remove(), 1800); } ['q','category','location','priceMax','durationMin'].forEach(id=> document.getElementById(id).addEventListener('input', ()=> applyFilters())); document.getElementById('resetFilters').addEventListener('click', ()=>{ ['q','category','location','priceMax','durationMin'].forEach(id=> document.getElementById(id).value=''); state.page = 1; applyFilters(); }); window.addEventListener('keydown', (e)=> { if(e.key==='Escape'){ document.getElementById('details-modal')?.close(); } if((e.ctrlKey || e.metaKey) && e.key.toLowerCase()==='k'){ e.preventDefault(); el('q').focus(); } }); window.addEventListener('hashchange', ()=>{ if(location.hash && location.hash.length>1){ const slug = location.hash.slice(1); const item = state.data.find(p=> p.slug === slug); if(item) openDetails(item.id); } }); loadCatalog(); function renderLdItemList(){ const itemList = { "@context":"https://schema.org", "@type":"ItemList", "itemListElement": state.data.slice(0,10).map((p,i)=> ({ "@type":"ListItem", "position": i+1, "url": "https://chiladros.pro/catalog.html#"+p.slug, "name": p.title })) }; const s = document.createElement('script'); s.type='application/ld+json'; s.textContent = JSON.stringify(itemList); document.head.appendChild(s); }