"use client"; import { useEffect, useRef, useState } from "react"; import { Panorama } from "./Panorama"; import { api } from "./StartGame"; export function PanoramaPreview({ endpoint, initialId, onClose, }: { endpoint: string; initialId?: string; onClose: () => void; }) { const dialog = useRef(null); const [locations, setLocations] = useState([]), [selected, setSelected] = useState(initialId ?? ""), [urls, setUrls] = useState(null), [ready, setReady] = useState(false), [error, setError] = useState(""); useEffect(() => { dialog.current?.showModal(); let disposed = false; api<{ locations: string[] }>(endpoint) .then((d) => { if (disposed) return; setLocations(d.locations); setSelected((s) => d.locations.includes(s) ? s : (d.locations[0] ?? ""), ); }) .catch((e) => { if (!disposed) setError(e.message); }); return () => { disposed = true; }; }, [endpoint]); useEffect(() => { if (!selected) return; let disposed = false; setUrls(null); setReady(false); setError(""); api<{ faces: string[] }>(`${endpoint}/${selected}`) .then((d) => { if (!disposed) setUrls(d.faces); }) .catch((e) => { if (!disposed) setError(e.message); }); return () => { disposed = true; }; }, [endpoint, selected]); const index = locations.indexOf(selected); return (
{urls && ( setReady(true)} onError={setError} /> )} {error ? (

{error}

) : ( !ready && (

Loading panorama…

) )}

Drag to look around · Scroll to zoom · Check for blocked views and missing terrain.

); }