// Wander β€” Location permission screen // A dedicated, on-brand gate that explains *why* the tour wants your position, // then asks for it. Because this prototype usually runs far from Singapore, // it gracefully falls back to a simulated walk and says so plainly. function LocationScreen({ onDone, onSkip, brand }) { // status: ask | locating | real | sim | denied | unsupported const [status, setStatus] = React.useState('ask'); const geo = window.WanderGeo; const supported = geo && geo.supported(); // A gentle marina-loop route the sim can stroll while you're on the map. const marinaRoute = React.useMemo(() => { const N = (window.WANDER_DATA && window.WANDER_DATA.NEARBY) || []; return N.filter(p => p.lat != null).map(p => ({ lat: p.lat, lng: p.lng })); }, []); const enable = async () => { if (!geo) { onDone && onDone(); return; } setStatus('locating'); const mode = await geo.start({ route: marinaRoute, loop: true, speed: 16 }); const snap = geo.get(); if (mode === 'real') setStatus('real'); else if (snap.status === 'denied') setStatus('denied'); else if (snap.status === 'unsupported') setStatus('unsupported'); else setStatus('sim'); }; // Once we have a position (real or simulated), give the user a beat to read // the result, then continue into the map. React.useEffect(() => { if (status === 'real' || status === 'sim' || status === 'denied' || status === 'unsupported') { const t = setTimeout(() => onDone && onDone(), 1400); return () => clearTimeout(t); } }, [status]); const result = { real: { icon:'πŸ“', tone:'var(--w-mint)', head:"You're located.", sub:"Live position locked β€” your dot will follow you on the map." }, sim: { icon:'🧭', tone:'var(--w-yellow)', head:'Demo mode β€” simulated walk.', sub:"We can't reach you in Singapore from here, so we'll stroll the route for you." }, denied: { icon:'πŸ›°οΈ', tone:'var(--w-coral)', head:'Location blocked.', sub:"No problem β€” we'll simulate the walk so you can still see it work." }, unsupported: { icon:'🧭', tone:'var(--w-yellow)', head:'No GPS here.', sub:"This browser can't share location, so we'll simulate the walk instead." }, }[status]; return (
{!result ? (

Follow the tour, hands-free.

With your location on, Wander shows your live position, tells you how far each stop is, and starts the story automatically the moment you arrive.

{[ ['πŸ”΅','A live dot that moves as you walk'], ['πŸ“','Real-time distance & walking time to every stop'], ['🎧','Narration that auto-plays when you reach a landmark'], ].map(([e,t]) => (
{e}{t}
))}
We only use location while a tour is open, and never share it. {supported ? '' : 'This browser has no GPS, so a simulated walk is used.'}
) : (

{result.head}

{result.sub}

)}
{!result && ( )} {result && ( )}
); } function LocationRadar({ active, done, icon, brand }) { const accent = brand || '#FFC93C'; return (
{[0,1,2,3].map(i => (
))} {/* sweeping radar line while locating */} {active && (
)}
{icon}
); } function Spinner() { return ; } Object.assign(window, { LocationScreen });