// app.jsx - product shell for the live preference-card approval surface.
function useViewportIsMobile() {
const [mobile, setMobile] = React.useState(() => window.innerWidth <= 720);
React.useEffect(() => {
const media = window.matchMedia("(max-width: 720px)");
const update = () => setMobile(media.matches);
update();
media.addEventListener?.("change", update);
window.addEventListener("resize", update);
return () => {
media.removeEventListener?.("change", update);
window.removeEventListener("resize", update);
};
}, []);
return mobile;
}
function currentPrefcardView() {
const params = new URLSearchParams(window.location.search);
return params.get("view") === "layout" ? "layout" : "gudid";
}
function setPrefcardViewParam(view) {
const url = new URL(window.location.href);
if (view === "layout") url.searchParams.set("view", "layout");
else url.searchParams.delete("view");
window.history.pushState({ prefcardView: view }, "", url);
}
function PrefcardViewTabs({ activeView, onViewChange, mobile }) {
const tabs = [
{ id: "gudid", label: "GUDID Match Review" },
{ id: "layout", label: "Room Layout" },
];
return (
{tabs.map((tab) => {
const active = activeView === tab.id;
return (
);
})}
);
}
function App() {
const mobile = useViewportIsMobile();
const [activeView, setActiveView] = React.useState(currentPrefcardView);
React.useEffect(() => {
const handlePop = () => setActiveView(currentPrefcardView());
window.addEventListener("popstate", handlePop);
return () => window.removeEventListener("popstate", handlePop);
}, []);
function changeView(view) {
setActiveView(view);
setPrefcardViewParam(view);
}
const viewTabs = (
);
if (activeView === "layout" && window.RoomLayoutView) {
return ;
}
return ;
}
// Defer render until window.PREFCARD is populated from /api/cards.
// Falls back gracefully if window.PREFCARD_READY is absent (synthetic-only mode).
(window.PREFCARD_READY || Promise.resolve()).then(() => {
ReactDOM.createRoot(document.getElementById("root")).render();
});