/** * Main React app logic */ import React, { useState, useEffect, useCallback } from "react"; import * as THREE from "three"; import { MTLLoader, OBJLoader } from "@hbis/three-obj-mtl-loader"; import Detail from "./Detail.js"; import Legend from "./Legend.js"; import buildGraph from "../graph.js"; export default function App() { const [db, setDb] = useState(null); const [node, setNode] = useState(null); const [graph, setGraph] = useState(null); const [selectedCategory, setSelectedCategory] = useState(null); const [detailVisible, setDetailVisible] = useState(null); /** Load the database */ useEffect(async () => { const newDb = await loadDB(); await loadObjects(newDb); setDb(newDb); setGraph( buildGraph({ db: newDb, handlers: { click: handleClick, }, }) ); }, []); /** Click to open a node */ const handleClick = useCallback((node) => { setNode(node); setDetailVisible(true); }); /** Click to close the media modal */ const handleClose = useCallback((node) => { setDetailVisible(false); }); /** Select or clear the category */ const handleSelect = useCallback((category) => { if (category === selectedCategory) { setSelectedCategory(null); graph.onSelect(null); } else { setSelectedCategory(category); graph.onSelect(category); } }); return (