// ============================================================ // Sabor Flow Da Nang — main.js // Update SCHEDULE array monthly when the weekly program changes. // ============================================================ const SCHEDULE = [ { day: 'Monday', when: '8:30 pm', venue: 'Webe Coffee', social: 'BOM', music: '8 Bachata · 1 Salsa · 1 Kizomba', city: 'Da Nang', organizer: 'Luu Phuong & Shai', mapUrl: 'https://maps.app.goo.gl/sznmGXHmiiaWf1ke6' }, { day: 'Tuesday', when: '9 pm', venue: 'La Riva', social: 'Latino Dancing', music: '2 Salsa · 2 Bachata · 2 Kizomba', city: 'Hoi An', organizer: 'David Tavares', mapUrl: 'https://maps.app.goo.gl/3ZyB8icd8oswRghE7' }, { day: 'Tuesday', when: '9 pm', venue: 'Caliz Bar', social: 'Sensual Night', music: '3 Bachata · 2 Salsa · 2 Kizomba', city: 'Da Nang', organizer: 'Daisy Nguyen', mapUrl: 'https://maps.app.goo.gl/YagFKw2gcTJp9PJc7' }, { day: 'Wednesday', when: '7:30 pm', venue: 'Ket Fai Bar', social: 'Bachata Kiz Night', music: 'Kizomba 7:30 · Bachata 9 pm', city: 'Da Nang', organizer: 'Sean Kim', mapUrl: 'https://maps.app.goo.gl/XYxY4UCnnJjCAomK6' }, { day: 'Thursday', when: '9 pm', venue: 'Malibu', social: 'Salsa Nights', music: '2 Salsa · 2 Bachata', city: 'Da Nang', organizer: 'Lucho Giraldes', mapUrl: 'https://maps.app.goo.gl/hZttmc9UcymnKfWP8' }, { day: 'Friday', when: '9 pm', venue: 'An Thuong By Night', social: 'Dance Unity Party', music: '2 Salsa · 2 Bachata · 2 Kizomba', city: 'Da Nang', organizer: 'Nadiya Yagfarova', mapUrl: 'https://maps.app.goo.gl/9cHcJcDgan9ntowt9' }, { day: 'Saturday', when: '9 pm', venue: 'La Riva', social: 'Latino Dancing', music: '2 Salsa · 2 Bachata · 2 Kizomba', city: 'Hoi An', organizer: 'David Tavares', mapUrl: 'https://maps.app.goo.gl/3ZyB8icd8oswRghE7' }, { day: 'Saturday', when: '9 pm', venue: 'An Thuong By Night', social: 'Bachata Party', music: 'Only Bachata', city: 'Da Nang', organizer: 'Vaclav & Kseniya', mapUrl: 'https://maps.app.goo.gl/9cHcJcDgan9ntowt9' }, { day: 'Sunday', when: '9 pm', venue: 'Last Call', social: 'Latin Dance Social', music: '3 Bachata · 2 Salsa', city: 'Da Nang', organizer: 'Vaclav & Kseniya', mapUrl: 'https://maps.app.goo.gl/1tEE4itDEeErhEmG6' }, { day: 'Sunday', when: '9 pm', venue: 'Corner Bar', social: 'Sunday Latin', music: '3 Bachata · 2 Salsa · 3 Kizomba', city: 'Da Nang', organizer: 'Daisy Nguyen', mapUrl: 'https://maps.app.goo.gl/QyuWvCg2DZoFiRyd6' }, ]; const DAYS_ORDER = ['Sunday', 'Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday', 'Saturday']; function getTodayName() { return DAYS_ORDER[new Date().getDay()]; } // Parse "2 Salsa · 3 Bachata · 1 Kizomba" into sfB-chip spans function musicToChips(music) { const styleMap = { salsa: 'salsa', bachata: 'bachata', kizomba: 'kizomba', zouk: 'zouk' }; return music.split('·').map(s => s.trim()).filter(Boolean).map(segment => { let cls = ''; for (const [key, val] of Object.entries(styleMap)) { if (segment.toLowerCase().includes(key)) { cls = val; break; } } return `${segment}`; }).join(''); } // ---- Nav (mobile) ---- function initNav() { const hamburger = document.getElementById('sfB-hamburger'); const mobileNav = document.getElementById('sfB-mobile-nav'); const closeBtn = document.getElementById('sfB-mobile-nav-close'); if (!hamburger || !mobileNav) return; hamburger.addEventListener('click', () => mobileNav.classList.add('open')); if (closeBtn) closeBtn.addEventListener('click', () => mobileNav.classList.remove('open')); mobileNav.querySelectorAll('a').forEach(link => { link.addEventListener('click', () => mobileNav.classList.remove('open')); }); // close on backdrop click mobileNav.addEventListener('click', e => { if (e.target === mobileNav) mobileNav.classList.remove('open'); }); } // ---- Schedule: full list (schedule.html) ---- function renderScheduleList() { const list = document.getElementById('sfB-schedule-list'); if (!list) return; const now = new Date(); const todayName = DAYS_ORDER[now.getDay()]; const startIdx = DAYS_ORDER.indexOf(todayName); // Map each day name to how many days from today it is (0–6) const dayOffset = {}; DAYS_ORDER.forEach(name => { dayOffset[name] = (DAYS_ORDER.indexOf(name) - startIdx + 7) % 7; }); const sorted = [...SCHEDULE].sort((a, b) => dayOffset[a.day] - dayOffset[b.day]); list.innerHTML = sorted.map(row => { const isToday = row.day === todayName; const offset = dayOffset[row.day]; const date = new Date(now); date.setDate(now.getDate() + offset); const dayNum = `${date.getDate()}/${date.getMonth() + 1}`; const cityClass = row.city === 'Hoi An' ? 'hoian' : 'danang'; const venueEl = row.mapUrl ? `${row.venue}` : row.venue; return `
${dayNum} ${row.day}
${isToday ? '▶ Tonight' : ''}
${row.when || ''}
${row.social} ${row.organizer}
${musicToChips(row.music)}
📍 ${venueEl}
${row.city}
`; }).join(''); } // ---- Home: "Coming up" teaser (4 cards starting from today) ---- function renderScheduleTeaser() { const container = document.getElementById('sfB-coming-row'); if (!container) return; const today = getTodayName(); const startIdx = DAYS_ORDER.indexOf(today); const order = [...DAYS_ORDER.slice(startIdx), ...DAYS_ORDER.slice(0, startIdx)]; const sorted = [...SCHEDULE].sort( (a, b) => order.indexOf(a.day) - order.indexOf(b.day) ); container.innerHTML = sorted.slice(0, 4).map(row => `
${row.day}
${row.when || ''}

${row.social}

@ ${row.venue} · ${row.city}
${musicToChips(row.music)}
`).join(''); } // ---- Filter pills (studios.html / classes.html) ---- function initFilters() { const pills = document.querySelectorAll('.filter-pill'); if (!pills.length) return; pills.forEach(pill => { pill.addEventListener('click', () => { pills.forEach(p => p.classList.remove('active')); pill.classList.add('active'); const filter = pill.dataset.filter; document.querySelectorAll('.filterable-card').forEach(card => { if (filter === 'all') { card.classList.remove('hidden'); } else { const styles = (card.dataset.styles || '') .split(',') .map(s => s.trim().toLowerCase()); card.classList.toggle('hidden', !styles.includes(filter)); } }); }); }); } // ---- Init ---- document.addEventListener('DOMContentLoaded', () => { initNav(); renderScheduleList(); renderScheduleTeaser(); initFilters(); const yearEl = document.getElementById('footer-year'); if (yearEl) yearEl.textContent = new Date().getFullYear(); });