// ============================================================ // Tribeca Lisboa — FAQ page app (main website, bilingual) // Hero + search + sticky category nav + accordion. Search filters // across questions AND answers; category nav scroll-jumps + spies. // Reuses SiteHeader / RFooter / SiteMenuDrawer. // ============================================================ const { useState: useStateFQ, useRef: useRefFQ, useEffect: useEffectFQ, useMemo: useMemoFQ } = React; function FqSearchIcon() { return ; } function FqCatIcon({ name }) { const p = { fill: 'none', stroke: 'currentColor', strokeWidth: 1.7, strokeLinecap: 'round', strokeLinejoin: 'round' }; switch (name) { case 'star': return ; case 'ticket': return ; case 'grid': return ; case 'pin': return ; case 'access': return ; case 'mail': return ; default: return null; } } // highlight matched query inside text function fqHighlight(text, q) { if (!q) return text; const i = text.toLowerCase().indexOf(q.toLowerCase()); if (i === -1) return text; return [text.slice(0, i), {text.slice(i, i + q.length)}, text.slice(i + q.length)]; } function FqItem({ q, a, open, onToggle, query }) { const wrapRef = useRefFQ(null); const innerRef = useRefFQ(null); useEffectFQ(() => { const wrap = wrapRef.current; if (!wrap) return; if (open) { wrap.style.height = innerRef.current.offsetHeight + 'px'; const t = setTimeout(() => { if (wrap.style.height !== '0px') wrap.style.height = 'auto'; }, 300); return () => clearTimeout(t); } else { wrap.style.height = innerRef.current.offsetHeight + 'px'; void wrap.offsetHeight; wrap.style.height = '0px'; } }, [open]); return (

{fqHighlight(a, query)}

); } function FaqInner() { const lang = useCtx(LangContext); const [menu, setMenu] = useStateFQ(false); const [query, setQuery] = useStateFQ(''); const [openId, setOpenId] = useStateFQ(null); const [active, setActive] = useStateFQ(FAQ[0].id); const q = query.trim().toLowerCase(); // filter categories/items by query (matches question OR answer) const cats = useMemoFQ(() => { if (!q) return FAQ.map((c) => ({ ...c, _items: c.items })); return FAQ.map((c) => { const _items = c.items.filter((it) => `${it.qEn} ${it.qPt} ${it.aEn} ${it.aPt}`.toLowerCase().includes(q)); return { ...c, _items }; }).filter((c) => c._items.length > 0); }, [q]); const totalResults = cats.reduce((n, c) => n + c._items.length, 0); // scroll-spy for active category (only when not searching) useEffectFQ(() => { if (q) return; const onScroll = () => { const mark = (window.innerHeight || 0) * 0.3 + 120; let cur = FAQ[0].id; for (const c of FAQ) { const el = document.getElementById('fq-c-' + c.id); if (el && el.getBoundingClientRect().top <= mark) cur = c.id; } setActive(cur); }; window.addEventListener('scroll', onScroll, { passive: true }); onScroll(); return () => window.removeEventListener('scroll', onScroll); }, [q]); const jumpTo = (id) => { const el = document.getElementById('fq-c-' + id); if (el) { const hdr = (parseInt(getComputedStyle(document.documentElement).getPropertyValue('--hdr-h')) || 82) + 70; window.scrollTo({ top: el.getBoundingClientRect().top + window.scrollY - hdr, behavior: 'smooth' }); } }; const toggle = (id) => setOpenId((cur) => (cur === id ? null : id)); return (
setMenu(true)} />
{tt(lang, 'Help Centre', 'Centro de Ajuda')}

{tt(lang, 'Frequently Asked Questions', 'Perguntas Frequentes')}

{tt(lang, 'Find answers to the most common questions about Tribeca Festival Lisboa.', 'Encontra respostas às perguntas mais comuns sobre o Tribeca Festival Lisboa.')}

setQuery(e.target.value)} placeholder={tt(lang, 'Search questions and answers', 'Procurar perguntas e respostas')} aria-label={tt(lang, 'Search FAQs', 'Procurar nas perguntas frequentes')} /> {query && }
{/* sticky category nav removed per request */}
{q && totalResults === 0 && (
{tt(lang, 'No results', 'Sem resultados')}

{tt(lang, 'Try a different word, or browse the categories.', 'Tenta outra palavra, ou explora as categorias.')}

)} {q && totalResults > 0 && (

{totalResults} {tt(lang, totalResults === 1 ? 'result' : 'results', totalResults === 1 ? 'resultado' : 'resultados')}

)} {cats.map((c) => (

{tt(lang, c.titleEn, c.titlePt)}

{c._items.map((it, i) => { const id = c.id + '-' + i; return toggle(id)} q={tt(lang, it.qEn, it.qPt)} a={tt(lang, it.aEn, it.aPt)} query={query.trim()} />; })}
))}
setMenu(false)} />
); } function Faq() { const [lang] = useLang(); return ( ); } ReactDOM.createRoot(document.getElementById('root')).render();