summaryrefslogtreecommitdiff
path: root/src/views/Graph.js
diff options
context:
space:
mode:
authorJules Laplace <julescarbon@gmail.com>2021-09-27 15:38:49 +0200
committerJules Laplace <julescarbon@gmail.com>2021-09-27 15:38:49 +0200
commit8c14599404e3905ebfedb148f9d23d09f26331e3 (patch)
tree1952dd070e4d74445838c1d864d824c9e083a46c /src/views/Graph.js
parent64408333a8b5378564911766f6e40add0862e28f (diff)
graph, intro
Diffstat (limited to 'src/views/Graph.js')
-rw-r--r--src/views/Graph.js85
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>
+ );
+}