/* global React */ /* BOHAM Praia — Part A: i18n, shared scroll util, Nav, Hero video */ (function () { const { Button, Tag } = window.BOHAMDesignSystem_8e9a1f; // ---- i18n (shared across all part files) --------------------------------- const LANG_KEY = 'boham-lang'; const SUPPORTED = ['en', 'pt', 'fr']; // Default English. Only a ?lang= in the URL changes the landing language, // so shared links (e.g. ?lang=fr) open in the right language and a plain // boham.com.br always lands in English. let stored = 'en'; try { const urlLang = new URLSearchParams(window.location.search).get('lang'); if (urlLang && SUPPORTED.indexOf(urlLang) !== -1) stored = urlLang; } catch (e) {} window.BohamLangStore = window.BohamLangStore || { current: stored, listeners: new Set() }; window.bohamSetLang = (l) => { const s = window.BohamLangStore; s.current = l; try { localStorage.setItem(LANG_KEY, l); } catch (e) {} try { const u = new URL(window.location.href); u.searchParams.set('lang', l); window.history.replaceState({}, '', u); } catch (e) {} try { document.documentElement.lang = l; } catch (e) {} try { window.bohamApplyMeta(l); } catch (e) {} try { if (typeof window.gtag === 'function') window.gtag('event', 'language_change', { language: l }); } catch (e) {} s.listeners.forEach((fn) => fn(l)); }; try { document.documentElement.lang = window.BohamLangStore.current; } catch (e) {} window.BOHAM_TITLES = { en: 'BOHAM - Kite point and restaurant in Barra Grande, PI', pt: 'BOHAM - Kite point e restaurante em Barra Grande, PI', fr: 'BOHAM - Kite point et restaurant à Barra Grande, PI', }; window.BOHAM_DESCRIPTIONS = { en: 'BOHAM is the kite point and restaurant on the beach of Barra Grande, Piauí (Brazil), a top flat-water kitesurf spot on the Rota das Emoções. Food, caipirinhas, sunset DJ & live music. What to do in Barra Grande: kite, eat, dance.', pt: 'O BOHAM é o kite point e restaurante na praia de Barra Grande, no Piauí (Brasil), um dos melhores pontos de kitesurf da Rota das Emoções. Comida, caipirinhas, DJ ao pôr do sol e música ao vivo. O que fazer em Barra Grande: praticar kitesurf, comer, dançar.', fr: 'BOHAM est le kite point et restaurant situé sur la plage de Barra Grande, dans l’État du Piauí (Brésil), l’un des meilleurs spots de kitesurf de la « Rota das Emoções ». Cuisine, caipirinhas, DJ au coucher du soleil et concerts. Que faire à Barra Grande : pratiquer le kitesurf, manger, danser.', }; // Option B: rewrite title + description + OG/Twitter tags on language change. // (English remains the crawler-indexed default since it's the server-sent HTML.) window.bohamApplyMeta = (l) => { const title = window.BOHAM_TITLES[l] || window.BOHAM_TITLES.en; const desc = window.BOHAM_DESCRIPTIONS[l] || window.BOHAM_DESCRIPTIONS.en; document.title = title; const set = (sel, attr, val) => { const el = document.head.querySelector(sel); if (el) el.setAttribute(attr, val); }; set('meta[name="description"]', 'content', desc); set('meta[property="og:title"]', 'content', title); set('meta[property="og:description"]', 'content', desc); set('meta[property="og:locale"]', 'content', l === 'pt' ? 'pt_BR' : l === 'fr' ? 'fr_FR' : 'en_US'); set('meta[name="twitter:title"]', 'content', title); set('meta[name="twitter:description"]', 'content', desc); document.documentElement.lang = l; }; try { window.bohamApplyMeta(window.BohamLangStore.current); } catch (e) {} window.useBohamLang = () => { const s = window.BohamLangStore; const [lang, set] = React.useState(s.current); React.useEffect(() => { const fn = (l) => set(l); s.listeners.add(fn); return () => s.listeners.delete(fn); }, []); return lang; }; // L(lang, english, portuguese, french) — french falls back to english if omitted window.L = (lang, en, pt, fr) => (lang === 'fr' ? (fr != null ? fr : en) : lang === 'pt' ? pt : en); const L = window.L; // ---- analytics: GA4 event helper + delegated click & scroll tracking ----- window.bohamTrack = window.bohamTrack || function (name, params) { try { if (typeof window.gtag === 'function') window.gtag('event', name, params || {}); } catch (e) {} }; if (!window.__bohamAnalytics) { window.__bohamAnalytics = true; // every link + button click, categorised by destination / label document.addEventListener('click', function (e) { const t = e.target; if (!t || !t.closest) return; const a = t.closest('a[href]'); if (a) { const href = a.getAttribute('href') || ''; let dest = 'link'; if (/wa\.me|whatsapp/i.test(href)) dest = 'whatsapp'; else if (/instagram/i.test(href)) dest = 'instagram'; else if (/tiktok/i.test(href)) dest = 'tiktok'; else if (/tripadvisor/i.test(href)) dest = 'tripadvisor'; else if (/windguru/i.test(href)) dest = 'windguru'; else if (/drive\.google|\/menu/i.test(href)) dest = 'menu'; else if (/share\.google|google\.|maps/i.test(href)) dest = 'google_maps'; window.bohamTrack('outbound_click', { destination: dest, url: href, label: (a.textContent || '').trim().slice(0, 60) }); return; } const btn = t.closest('button'); if (btn) { const label = (btn.textContent || btn.getAttribute('aria-label') || '').trim().slice(0, 60); if (label) window.bohamTrack('cta_click', { label: label }); } }, true); // scroll depth milestones (fire once each) const marks = [25, 50, 75, 100]; const seen = {}; const onScrollDepth = function () { const h = document.documentElement; const max = h.scrollHeight - h.clientHeight; if (max <= 0) return; const pct = Math.round(((h.scrollTop || document.body.scrollTop) / max) * 100); marks.forEach(function (m) { if (pct >= m && !seen[m]) { seen[m] = true; window.bohamTrack('scroll_depth', { percent: m }); } }); }; window.addEventListener('scroll', onScrollDepth, { passive: true }); } // ---- shared smooth-scroll to a section id ("sec-") ------------------- window.bohamScrollTo = (id) => { if (id === 'home') { window.scrollTo({ top: 0, behavior: 'smooth' }); return; } const el = document.getElementById('sec-' + id); if (!el) return; const navH = parseInt(getComputedStyle(document.documentElement).getPropertyValue('--nav-h')) || 84; const y = el.getBoundingClientRect().top + window.scrollY - navH + 1; window.scrollTo({ top: y, behavior: 'smooth' }); }; const WA = 'https://wa.me/5586999857676'; window.BOHAM_WA = WA; const MENU_URL = 'https://drive.google.com/file/d/17MZFCa8g6qj_ptal4HEUmx6xoTE6mw1N/view?usp=drive_link'; // ---- WhatsApp glyph + brand-green button (shared) ------------------------ function WAIcon({ size = 16 }) { return ( ); } function WAButton({ size = 'md', label = 'WhatsApp', style = {} }) { const [hover, setHover] = React.useState(false); const sizes = { sm: { padding: '8px 18px', fontSize: 13, gap: 8, icon: 15 }, md: { padding: '12px 24px', fontSize: 14, gap: 9, icon: 17 } }; const s = sizes[size] || sizes.md; return ( ); } window.BohamWAButton = WAButton; // ---- Menu pill button (orange CTA, opens the menu PDF) ------------------- function MenuButton({ size = 'sm', style = {} }) { const lang = window.useBohamLang(); const [hover, setHover] = React.useState(false); const sizes = { sm: { padding: '8px 16px', fontSize: 13, gap: 8, icon: 15 }, md: { padding: '12px 24px', fontSize: 14, gap: 9, icon: 17 } }; const s = sizes[size] || sizes.sm; return ( ); } window.BohamMenuButton = MenuButton; // ---- language switch ----------------------------------------------------- function LangSwitch({ dark }) { const lang = window.useBohamLang(); const [open, setOpen] = React.useState(false); const langs = [['en', 'EN'], ['pt', 'PT'], ['fr', 'FR']]; const names = { en: 'English', pt: 'Português', fr: 'Français' }; const onCol = dark ? 'var(--boham-espresso)' : 'rgba(251,246,234,0.95)'; const curLabel = (langs.find(([c]) => c === lang) || langs[0])[1]; const ref = React.useRef(null); React.useEffect(() => { const close = (e) => { if (ref.current && !ref.current.contains(e.target)) setOpen(false); }; document.addEventListener('click', close); return () => document.removeEventListener('click', close); }, []); return (
{open && (
{langs.map(([code, label]) => ( ))}
)}
); } // ---- Nav ----------------------------------------------------------------- function Nav() { const lang = window.useBohamLang(); const [scrolled, setScrolled] = React.useState(false); const [open, setOpen] = React.useState(false); React.useEffect(() => { const onScroll = () => setScrolled((window.scrollY || 0) > 40); onScroll(); window.addEventListener('scroll', onScroll, { passive: true }); return () => window.removeEventListener('scroll', onScroll); }, []); const dark = scrolled || open; const links = [ { id: 'about', label: L(lang, 'The place', 'O lugar', 'Le lieu') }, { id: 'eat', label: L(lang, 'Eat & drink', 'Comer & beber', 'Manger & boire') }, { id: 'kite', label: L(lang, 'Kite', 'Kite', 'Kite') }, { id: 'barra', label: 'Barra Grande' }, { id: 'visit', label: L(lang, 'Visit', 'Visite', 'Visiter') }, ]; const go = (id) => { setOpen(false); window.bohamScrollTo(id); }; const handle = (l) => { setOpen(false); if (l.href) { window.open(l.href, '_blank'); } else { window.bohamScrollTo(l.id); } }; return (
{/* mobile panel */}
{links.map((l) => ( ))}
); } // ---- Hero: auto-playing, muted brand video ------------------------------- function Hero() { const lang = window.useBohamLang(); const videoRef = React.useRef(null); React.useEffect(() => { const v = videoRef.current; if (!v) return; v.muted = true; v.volume = 0; v.defaultMuted = true; const START = 4, END = 49; const seekStart = () => { try { v.currentTime = START; } catch (e) {} }; const onMeta = () => { seekStart(); v.play().catch(() => {}); }; const onEnded = () => { seekStart(); v.play().catch(() => {}); }; const onTime = () => { if (v.currentTime >= END) { seekStart(); v.play().catch(() => {}); } }; if (v.readyState >= 1) onMeta(); else v.addEventListener('loadedmetadata', onMeta); v.addEventListener('ended', onEnded); v.addEventListener('timeupdate', onTime); return () => { v.removeEventListener('loadedmetadata', onMeta); v.removeEventListener('ended', onEnded); v.removeEventListener('timeupdate', onTime); }; }, []); return (
{window.BOHAM_NO_VIDEO ? ( BOHAM Praia from above, the beach club at golden hour ) : ( )}
{L(lang, 'Barra Grande · Piauí, Brazil', 'Barra Grande · Piauí, Brasil', 'Barra Grande · Piauí, Brésil')}

{L(lang, 'Where Barra Grande', 'Onde Barra Grande', 'Le rendez-vous')}
{L(lang, 'comes together', 'se encontra', 'de Barra Grande')}

{L(lang, 'Kite point', 'Kite point', 'Kite point')} {L(lang, 'Bar & restaurant', 'Bar & restaurante', 'Bar & restaurant')} {L(lang, 'No dress code', 'No dress code', 'No dress code')}
window.bohamScrollTo('about')} className="boham-scrollcue" style={{ position: 'absolute', bottom: 22, left: '50%', transform: 'translateX(-50%)', cursor: 'pointer', display: 'flex', flexDirection: 'column', alignItems: 'center', gap: 6 }}> {L(lang, 'Scroll', 'Role', 'Scroll')}
); } window.BohamNav = Nav; window.BohamHero = Hero; })();