diff options
Diffstat (limited to 'src/views/Graph.js')
| -rw-r--r-- | src/views/Graph.js | 85 |
1 files changed, 85 insertions, 0 deletions
diff --git a/src/views/Graph.js b/src/views/Graph.js new file mode 100644 index 0000000..eb55ad0 --- /dev/null +++ b/src/views/Graph.js @@ -0,0 +1,85 @@ +/** + * Main interaction logic + */ + +import React, { useState, useEffect, useCallback } from "react"; + +import Detail from "./Detail.js"; +import Legend from "./Legend.js"; +import Quote from "./Quote.js"; +import Credits from "./Credits.js"; +import Title from "./Title.js"; +import buildGraph from "../graph.js"; + +export default function Graph({ db }) { + const [node, setNode] = useState(null); + const [graph, setGraph] = useState(null); + const [selectedCategory, setSelectedCategory] = useState(null); + const [detailVisible, setDetailVisible] = useState(false); + const [creditsVisible, setCreditsVisible] = useState(false); + const [introDone, setIntroDone] = useState(false); + const [introCurtainDone, setIntroCurtainDone] = useState(false); + const [introTextDone, setIntroTextDone] = useState(false); + + /** Build the graph */ + useEffect(() => { + setGraph( + buildGraph({ + db, + handlers: { + click: handleClick, + }, + }) + ); + setTimeout(() => { + setIntroCurtainDone(true); + setTimeout(() => { + setIntroDone(true); + }, 4000); + setTimeout(() => { + setIntroTextDone(true); + }, 8000); + }, 10); + }, []); + + /** 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 ( + <div className={introTextDone ? "" : "intro-text"}> + <Detail node={node} visible={detailVisible} onClose={handleClose} /> + <Legend + visible={introDone && !detailVisible && !creditsVisible} + selected={selectedCategory} + onSelect={handleSelect} + /> + <Quote visible={introDone && !detailVisible && !creditsVisible} /> + <Credits + onToggle={setCreditsVisible} + visible={introDone && !detailVisible} + open={creditsVisible} + /> + <Title visible={introDone && !detailVisible && !creditsVisible} /> + <div className={introCurtainDone ? "curtain done" : "curtain"} /> + </div> + ); +} |
