Drevolia

Catálogo Drevolia

Escolha o seu próximo gesto floral.

Percursos claros para explorar composição, técnica e processo criativo com tempo para praticar.

A carregar cursos.
`; const footerHTML = ``; function initHeaderFooter() { document.querySelector('header').innerHTML = headerHTML; document.querySelector('footer').innerHTML = footerHTML; initGlobalScripts(); } function initGlobalScripts() { document.querySelectorAll('[data-action="toggle-menu"]').forEach(btn => { btn.addEventListener('click', () => { const target = document.getElementById(btn.dataset.target); target.classList.toggle('hidden'); }); }); document.querySelectorAll('[data-action="open-modal"]').forEach(btn => { btn.addEventListener('click', () => { const modal = document.getElementById(btn.dataset.target); modal.classList.remove('hidden'); modal.classList.add('flex'); }); }); document.querySelectorAll('[data-action="close-modal"]').forEach(btn => { btn.addEventListener('click', () => { const modal = btn.closest('[role="dialog"]'); modal.classList.add('hidden'); modal.classList.remove('flex'); }); }); document.querySelectorAll('[data-action="toggle-theme"]').forEach(btn => { btn.addEventListener('click', () => { document.documentElement.classList.toggle('dark'); localStorage.setItem('theme', document.documentElement.classList.contains('dark') ? 'dark' : 'light'); }); }); if (localStorage.getItem('theme') === 'dark') document.documentElement.classList.add('dark'); const cookieBanner = document.getElementById('cookie-catalog'); if (!localStorage.getItem('cookiesAccepted')) cookieBanner.classList.remove('hidden'); document.querySelectorAll('[data-action="accept-cookies"]').forEach(btn => { btn.addEventListener('click', () => { localStorage.setItem('cookiesAccepted', 'true'); cookieBanner.classList.add('hidden'); }); }); } const state = {items: [], page: 1, perPage: 6, search: '', category: 'all', level: 'all'}; const followingKey = 'drevoliaFollowing'; const cartKey = 'drevoliaCart'; function getFollowing() { return JSON.parse(localStorage.getItem(followingKey) || '[]'); } function saveFollowing(arr) { localStorage.setItem(followingKey, JSON.stringify(arr)); } function getCart() { return JSON.parse(localStorage.getItem(cartKey) || '[]'); } function saveCart(arr) { localStorage.setItem(cartKey, JSON.stringify(arr)); } fetch('./catalog.json') .then(r => { if (!r.ok) throw new Error(); return r.json(); }) .then(items => { state.items = items; fillOptions(); render(); }) .catch(() => document.getElementById('catalog-error').classList.remove('hidden')); function fillOptions() { ['category', 'level'].forEach(key => { const el = document.getElementById('catalog-' + key); [...new Set(state.items.map(i => i[key]))].forEach(v => { el.insertAdjacentHTML('beforeend', ``); }); el.addEventListener('change', () => { state[key] = el.value; state.page = 1; render(); }); }); const search = document.getElementById('catalog-search'); search.addEventListener('input', () => { state.search = search.value.toLowerCase(); state.page = 1; render(); }); } function render() { const filtered = state.items.filter(i => { const s = state.search === '' || i.title.toLowerCase().includes(state.search) || i.summary.toLowerCase().includes(state.search); const c = state.category === 'all' || i.category === state.category; const l = state.level === 'all' || i.level === state.level; return s && c && l; }); const status = document.getElementById('catalog-status'); const grid = document.getElementById('catalog-grid'); const pag = document.getElementById('catalog-pagination'); status.textContent = filtered.length + ' cursos encontrados'; grid.innerHTML = ''; pag.innerHTML = ''; const start = (state.page - 1) * state.perPage; const pageItems = filtered.slice(start, start + state.perPage); pageItems.forEach(item => { const isFollowing = getFollowing().includes(item.id); const card = document.createElement('div'); card.className = 'dd23l xk9h7 p2aql rounded-3xl border border-stone-200 bg-white p-8 dark:border-stone-800 dark:bg-stone-900 flex flex-col'; card.innerHTML = `
${item.category} ${item.level}

${item.title}

${item.summary}

${item.price} € · ${item.duration}
`; grid.appendChild(card); }); const totalPages = Math.ceil(filtered.length / state.perPage); for (let p = 1; p <= totalPages; p++) { const b = document.createElement('button'); b.type = 'button'; b.className = `px-5 py-2 text-sm rounded-full border ${p === state.page ? 'bg-stone-900 text-stone-50 dark:bg-stone-800' : 'border-stone-300 dark:border-stone-700'}`; b.textContent = p; b.onclick = () => { state.page = p; render(); }; pag.appendChild(b); } bindCardActions(); } function bindCardActions() { document.querySelectorAll('[data-action="follow"]').forEach(btn => { btn.onclick = () => { const id = parseInt(btn.dataset.id); let f = getFollowing(); if (f.includes(id)) f = f.filter(x => x !== id); else f.push(id); saveFollowing(f); render(); }; }); document.querySelectorAll('[data-action="detail"]').forEach(btn => { btn.onclick = () => { const item = state.items.find(i => i.id === parseInt(btn.dataset.id)); showDetail(item); }; }); document.querySelectorAll('[data-action="add-cart"]').forEach(btn => { btn.onclick = () => { const id = parseInt(btn.dataset.id); let cart = getCart(); const ex = cart.find(x => x.id === id); if (ex) ex.quantity++; else cart.push({id, quantity: 1}); saveCart(cart); btn.textContent = 'Adicionado'; setTimeout(() => { btn.textContent = 'Adicionar'; }, 1200); }; }); } function showDetail(item) { const modal = document.getElementById('product-detail-catalog'); const content = document.getElementById('product-detail-content'); const isFollowing = getFollowing().includes(item.id); content.innerHTML = `
${item.category} ${item.level} · ${item.format}

${item.title}

${item.duration} · ${item.price} €

${item.description}

`; modal.classList.remove('hidden'); modal.classList.add('flex'); content.querySelector('[data-action="close-modal"]').onclick = () => { modal.classList.add('hidden'); modal.classList.remove('flex'); }; content.querySelector('[data-action="follow-detail"]').onclick = () => { let f = getFollowing(); if (f.includes(item.id)) f = f.filter(x => x !== item.id); else f.push(item.id); saveFollowing(f); modal.classList.add('hidden'); modal.classList.remove('flex'); render(); }; content.querySelector('[data-action="add-cart-detail"]').onclick = () => { let cart = getCart(); const ex = cart.find(x => x.id === item.id); if (ex) ex.quantity++; else cart.push({id: item.id, quantity: 1}); saveCart(cart); modal.classList.add('hidden'); modal.classList.remove('flex'); }; } document.addEventListener('DOMContentLoaded', () => { initHeaderFooter(); const savedTheme = localStorage.getItem('theme'); if (savedTheme === 'dark') document.documentElement.classList.add('dark'); });