COACHING PROGRAMS

Choose a practice that fits your season.

Thoughtfully designed programs blending kettlebell mastery, chlorophyll-rich recovery, and mindful movement.

DISCOVER YOUR PATH
All Programs
`; function initHeaderFooter() { document.querySelector('header').innerHTML = headerHTML; document.querySelector('footer').innerHTML = footerHTML; // Mobile menu const mobileBtn = document.querySelector('[data-mobile-toggle]'); const mobileMenu = document.querySelector('[data-mobile-menu]'); if (mobileBtn && mobileMenu) { mobileBtn.addEventListener('click', () => { mobileMenu.classList.toggle('hidden'); }); } // Theme toggle const themeBtn = document.querySelector('[data-theme-toggle]'); if (themeBtn) { themeBtn.addEventListener('click', () => { document.body.classList.toggle('bg-[#F7F3E8]'); document.body.classList.toggle('bg-[#20352A]'); document.body.classList.toggle('text-[#20352A]'); document.body.classList.toggle('text-[#F7F3E8]'); }); } // Login/Register modals const loginModal = document.createElement('div'); loginModal.className = 'hidden fixed inset-0 z-50 flex items-center justify-center bg-black/40'; loginModal.innerHTML = `
Welcome back
`; document.body.appendChild(loginModal); document.querySelectorAll('[data-open-login]').forEach(btn => btn.addEventListener('click', () => loginModal.classList.remove('hidden'))); loginModal.addEventListener('click', e => { if (e.target === loginModal || e.target.hasAttribute('data-close-login')) loginModal.classList.add('hidden'); }); // Cookie banner const cookieBanner = document.querySelector('[data-cookie-banner]'); if (cookieBanner && !localStorage.getItem('enduviaCookieAccepted')) { cookieBanner.classList.remove('hidden'); cookieBanner.classList.add('flex'); cookieBanner.querySelector('[data-cookie-accept]').addEventListener('click', () => { localStorage.setItem('enduviaCookieAccepted', 'true'); cookieBanner.classList.add('hidden'); }); cookieBanner.querySelector('[data-cookie-decline]').addEventListener('click', () => cookieBanner.classList.add('hidden')); } } let allPrograms = []; let currentPage = 1; const perPage = 6; let currentFilters = { search: '', category: '', level: '', sort: 'price-low' }; async function loadCatalog() { try { const res = await fetch('./catalog.json'); allPrograms = await res.json(); if (!Array.isArray(allPrograms)) allPrograms = []; } catch (e) { allPrograms = []; } setupFilters(); renderCatalog(); } function setupFilters() { const search = document.getElementById('search-input'); const category = document.getElementById('category-filter'); const level = document.getElementById('level-filter'); const sort = document.getElementById('sort-select'); search.addEventListener('input', () => { currentFilters.search = search.value.toLowerCase(); currentPage = 1; renderCatalog(); }); category.addEventListener('change', () => { currentFilters.category = category.value; currentPage = 1; renderCatalog(); }); level.addEventListener('change', () => { currentFilters.level = level.value; currentPage = 1; renderCatalog(); }); sort.addEventListener('change', () => { currentFilters.sort = sort.value; currentPage = 1; renderCatalog(); }); } function filterAndSortPrograms() { let filtered = allPrograms.filter(p => { const matchesSearch = !currentFilters.search || p.title.toLowerCase().includes(currentFilters.search) || p.summary.toLowerCase().includes(currentFilters.search) || p.description.toLowerCase().includes(currentFilters.search); const matchesCategory = !currentFilters.category || p.category === currentFilters.category; const matchesLevel = !currentFilters.level || p.level === currentFilters.level; return matchesSearch && matchesCategory && matchesLevel; }); if (currentFilters.sort === 'price-low') filtered.sort((a, b) => a.price - b.price); if (currentFilters.sort === 'price-high') filtered.sort((a, b) => b.price - a.price); if (currentFilters.sort === 'duration') filtered.sort((a, b) => parseInt(a.duration) - parseInt(b.duration)); return filtered; } function renderCatalog() { const grid = document.getElementById('catalog-grid'); const countEl = document.getElementById('result-count'); grid.innerHTML = ''; const filtered = filterAndSortPrograms(); const start = (currentPage - 1) * perPage; const pageItems = filtered.slice(start, start + perPage); countEl.textContent = `${filtered.length} programs found`; if (pageItems.length === 0) { grid.innerHTML = `
No programs match your filters.
`; } pageItems.forEach(program => { const isFav = (JSON.parse(localStorage.getItem('enduviaFavorites') || '[]')).includes(program.id); const card = document.createElement('div'); card.className = `forest-card bg-white border border-[#C9D6C4] rounded-3xl p-7 flex flex-col`; card.innerHTML = `
${program.category}
${program.title}
$${program.price}
${program.currency}
${program.summary}
${program.level}
${program.duration}
Save to Fallows Add to cart
`; grid.appendChild(card); card.querySelector('[data-detail]').addEventListener('click', () => openDetailModal(program)); }); renderPagination(filtered.length); } function renderPagination(total) { const container = document.getElementById('pagination'); container.innerHTML = ''; const pages = Math.ceil(total / perPage); if (pages <= 1) return; for (let i = 1; i <= pages; i++) { const btn = document.createElement('button'); btn.className = `page-btn w-9 h-9 text-sm rounded-2xl border border-[#C9D6C4] ${i === currentPage ? 'active' : ''}`; btn.textContent = i; btn.addEventListener('click', () => { currentPage = i; renderCatalog(); }); container.appendChild(btn); } } function openDetailModal(program) { const modal = document.getElementById('detail-modal'); document.getElementById('modal-title').textContent = program.title; document.getElementById('modal-description').textContent = program.description; document.getElementById('modal-duration').textContent = program.duration; document.getElementById('modal-sessions').textContent = program.sessions; document.getElementById('modal-level').textContent = program.level; document.getElementById('modal-price').textContent = `$${program.price} ${program.currency}`; const equipContainer = document.getElementById('modal-equipment'); equipContainer.innerHTML = program.equipment.map(item => `
${item}
` ).join(''); const favBtn = document.getElementById('modal-favorite'); const cartBtn = document.getElementById('modal-add-cart'); favBtn.onclick = () => { let favs = JSON.parse(localStorage.getItem('enduviaFavorites') || '[]'); if (!favs.includes(program.id)) { favs.push(program.id); localStorage.setItem('enduviaFavorites', JSON.stringify(favs)); } window.location.href = './fallows.html'; }; cartBtn.onclick = () => { let cart = JSON.parse(localStorage.getItem('enduviaCart') || '{}'); cart[program.id] = (cart[program.id] || 0) + 1; localStorage.setItem('enduviaCart', JSON.stringify(cart)); window.location.href = './cart.html'; }; modal.classList.remove('hidden'); document.getElementById('close-modal').onclick = () => modal.classList.add('hidden'); modal.onclick = (e) => { if (e.target === modal) modal.classList.add('hidden'); }; } function init() { initHeaderFooter(); loadCatalog(); } window.onload = init;