Your Fallows

Tip: Add more from the catalog.

synterixa.top

Favorites JSON

Tip: Press Ctrl/Cmd + E to open this modal anytime.

Copied to clipboard
') ]); document.querySelector('header').innerHTML = h; document.querySelector('footer').innerHTML = f; document.body.addEventListener('click', (e) => { const t = e.target; if (t.matches('[data-open]')) { e.preventDefault(); const el = document.querySelector(t.getAttribute('data-open')); if (el?.showModal) el.showModal(); } if (t.matches('[data-close]')) { e.preventDefault(); const el = document.querySelector(t.getAttribute('data-close')); if (el?.close) el.close(); } }); const btn = document.querySelector('#acceptCookies'); if (btn) btn.addEventListener('click', () => { localStorage.setItem('cookieConsent','true'); const m=document.querySelector('#cookieModal'); if(m?.close) m.close(); }); if (localStorage.getItem('cookieConsent') !== 'true') { const d = document.querySelector('#cookieModal'); if (d?.showModal) setTimeout(()=>d.showModal(),600); } } function formatCurrency(n) { return new Intl.NumberFormat('en-CA',{style:'currency',currency:'CAD'}).format(n); } function updateCount() { const el = document.getElementById('favCount'); const count = state.favorites.size; el.textContent = count ? `• ${count} item${count!==1?'s':''}` : '• 0 items'; } function render() { const list = document.getElementById('favList'); list.innerHTML = ''; const items = state.items; updateCount(); if (!items.length) { list.innerHTML = '
  • No favorites yet. Browse the catalog and tap the heart icon to save courses.
  • '; return; } for (const item of items) { const li = document.createElement('li'); li.className = 'xk9h7 p-4 flex flex-col sm:flex-row sm:items-center gap-3 hover:bg-gray-50 dark:hover:bg-white/5 transition-colors'; const tags = [ item.category, item.level, item.format, (item.durationHours || 0)+'h' ].filter(Boolean).join(' • '); li.innerHTML = `
    ${item.title}
    ${tags} • ${formatCurrency(item.priceCAD || 0)}
    `; list.appendChild(li); } } document.getElementById('favList').addEventListener('click', (e) => { if (e.target.classList.contains('btn-remove')) { const id = Number(e.target.getAttribute('data-id')); state.favorites.delete(id); localStorage.setItem('favorites', JSON.stringify(Array.from(state.favorites))); render(); } }); document.getElementById('clearAll').addEventListener('click', () => { if (!state.favorites.size) return; if (confirm('Remove all favorites?')) { state.favorites.clear(); localStorage.setItem('favorites', '[]'); render(); } }); function openExportModal() { const items = state.items; const json = JSON.stringify(items, null, 2); const extra = { domain: 'synterixa.top', exportedAt: new Date().toISOString(), count: items.length }; const composed = json + '\n\n' + JSON.stringify(extra, null, 2); const ta = document.getElementById('exportText'); ta.value = composed; if (ta.setSelectionRange) { ta.focus(); ta.setSelectionRange(0, ta.value.length); } const dlg = document.getElementById('exportModal'); if (dlg?.showModal) dlg.showModal(); } document.getElementById('exportBtn').addEventListener('click', openExportModal); async function copyText(text) { try { await navigator.clipboard.writeText(text); showToast('Copied to clipboard'); } catch { const ta = document.createElement('textarea'); ta.value = text; ta.setAttribute('readonly',''); ta.style.position = 'absolute'; ta.style.left = '-9999px'; document.body.appendChild(ta); ta.select(); try { document.execCommand('copy'); showToast('Copied to clipboard'); } catch {} document.body.removeChild(ta); } } document.getElementById('copyJSON').addEventListener('click', async () => { await copyText(document.getElementById('exportText').value); }); document.getElementById('copyMin').addEventListener('click', async () => { const ids = Array.from(state.favorites.values()); const payload = JSON.stringify({ ids, domain:'synterixa.top', exportedAt:new Date().toISOString() }, null, 2); await copyText(payload); }); document.getElementById('downloadJSON').addEventListener('click', () => { const blob = new Blob([document.getElementById('exportText').value], {type:'application/json'}); const url = URL.createObjectURL(blob); const a = document.createElement('a'); a.href = url; a.download = 'synterixa-favorites.json'; a.click(); URL.revokeObjectURL(url); }); document.getElementById('exportText').addEventListener('focus', (e) => { const v = e.target.value; e.target.setSelectionRange(0, v.length); }); function showToast(msg) { const t = document.getElementById('toast'); t.querySelector('div').textContent = msg; t.classList.add('active'); clearTimeout(showToast._to); showToast._to = setTimeout(()=>t.classList.remove('active'), 1400); } window.addEventListener('keydown', (e) => { const isMac = navigator.platform.toUpperCase().includes('MAC'); if ((isMac ? e.metaKey : e.ctrlKey) && e.key.toLowerCase() === 'e') { e.preventDefault(); openExportModal(); } if (e.key === 'Escape') { const dlg = document.getElementById('exportModal'); if (dlg?.open) dlg.close(); } }); window.addEventListener('storage', (e) => { if (e.key === 'favorites') { state.favorites = safeParseFavorites(); render(); } }); function applyFromURL() { const url = new URL(location.href); const f = url.searchParams.get('f'); if (!f) return; const ids = f.split(',').map(v => Number(v.trim())).filter(Number.isFinite); if (ids.length) { state.favorites = new Set(ids); localStorage.setItem('favorites', JSON.stringify(ids)); render(); } } async function init() { await injectPartials(); try { state.data = await fetch('./catalog.json').then(r => { if (!r.ok) throw new Error('Failed to load catalog'); return r.json(); }); } catch (err) { state.data = []; const list = document.getElementById('favList'); list.innerHTML = '
  • Error loading catalog. Please try again later.
  • '; } applyFromURL(); render(); } init();