// ============================================================
// 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 (
);
}
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 && setQuery('')} aria-label={tt(lang, 'Clear', 'Limpar')}>✕ }
{/* 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( );