aboutsummaryrefslogtreecommitdiff
path: root/react-frontend/src/components
diff options
context:
space:
mode:
authorJulia McCauley <skurvyj@gmail.com>2021-04-16 19:46:45 -0400
committerJulia McCauley <skurvyj@gmail.com>2021-04-16 19:46:45 -0400
commitfa4feff17c9e15b86388fd5ee1ac6771ff4d5148 (patch)
tree72157df02027b860e74097050349d49ebecebc0a /react-frontend/src/components
parenteab479adc987ab20424a542275a697e0c8dbce61 (diff)
parenta7f1433da5ddf11845251a062da96bc42c631f50 (diff)
need to pull new frontend Merge branch 'master' of github.com:cs0320-2021/term-project-cohwille-jmccaul3-mfoiani-rhunt2
Diffstat (limited to 'react-frontend/src/components')
-rw-r--r--react-frontend/src/components/DateSelector.js17
-rw-r--r--react-frontend/src/components/Hub.js24
-rw-r--r--react-frontend/src/components/HubList.js62
-rw-r--r--react-frontend/src/components/InvestorInfo.js66
-rw-r--r--react-frontend/src/components/Loading.js20
-rw-r--r--react-frontend/src/components/TimeSelector.js48
-rw-r--r--react-frontend/src/components/Visualization.js69
7 files changed, 306 insertions, 0 deletions
diff --git a/react-frontend/src/components/DateSelector.js b/react-frontend/src/components/DateSelector.js
new file mode 100644
index 0000000..bf01d44
--- /dev/null
+++ b/react-frontend/src/components/DateSelector.js
@@ -0,0 +1,17 @@
+// CSS import
+import '../css/Route.css';
+import '../css/CoordSelector.css';
+
+/**
+ * The component that selects and displays a coordinate.
+ * @param {Object} props The props for the element.
+ */
+function DateSelector(props) {
+ return (
+ <div className="Flex-coord">
+ <input type="date" value={props.value} onChange={(e) => props.changedFunc(new Date(e.target.value))} onClick={() => props.clickedFunc()}/>
+ </div>
+ );
+}
+
+export default DateSelector; \ No newline at end of file
diff --git a/react-frontend/src/components/Hub.js b/react-frontend/src/components/Hub.js
new file mode 100644
index 0000000..8a3ac1c
--- /dev/null
+++ b/react-frontend/src/components/Hub.js
@@ -0,0 +1,24 @@
+// React import
+import { useState } from "react";
+
+// CSS import
+import '../css/UserCheckin.css';
+
+/**
+ * Componenet for checkins. Has a toggle to show more info.
+ * @param {Object} props The props of the component.
+ * @returns {import('react').HtmlHTMLAttributes} A list element holding a checkin's info.
+ */
+function Hub(props) {
+ // State - toggled
+
+ return (
+ <li className='Checkin'>
+ <div className="Img-flex">
+ <span className="Clickable-name" onClick= {() => console.log(props.id)}>{props.name}</span>
+ <span>{props.value.toFixed(3)}</span>
+ </div>
+ </li>);
+}
+
+export default Hub; \ No newline at end of file
diff --git a/react-frontend/src/components/HubList.js b/react-frontend/src/components/HubList.js
new file mode 100644
index 0000000..f5b1414
--- /dev/null
+++ b/react-frontend/src/components/HubList.js
@@ -0,0 +1,62 @@
+// React and component imports
+import { useEffect, useState } from "react";
+import Hub from "./Hub.js";
+import InvestorInfo from "./InvestorInfo.js";
+
+// CSS import
+import '../css/UserCheckin.css';
+
+/**
+ * Component that build the checkin list and displays checkin info.
+ * @returns {import('react').HtmlHTMLAttributes} A div with the hubs
+ * in a vertical layout.
+ */
+function HubList(props) {
+ const [hubItems, setHubItems] = useState([]);
+ const [isSelected, setIsSelected] = useState(false);
+ const [name, setName] = useState('');
+
+ /**
+ * Loads new the checkins into the current cache/map of hubs.
+ */
+ const updateHubItems = () => {
+ // sort and create the elemnts
+ let hubs = [];
+ const sorted = props.data.sort((a, b) => b.suspicionScore - a.suspicionScore);
+ sorted.forEach(hub => hubs.push(
+ <Hub key={hub.id} id={hub.id} name={hub.name} value={hub.suspicionScore} setSelected={props.setSelected}></Hub>
+ ));
+
+ setHubItems(hubs);
+ }
+
+ const getName = () => {
+ props.data.forEach(hub => {
+ if (hub.id == props.selected) {
+ setName(hub.name);
+ }
+ })
+ setName('');
+ }
+
+ // React hook that updates when the hubs are recalculated
+ useEffect(() => updateHubItems(), [props.data]);
+
+ //React hook to show data for an investor
+ useEffect(() => {
+ setIsSelected(true)
+ getName();
+ }, [props.selected]);
+
+ return (
+ <div className="User-checkin">
+ <div className="Checkins">
+ <h2>Suspicion Ranks</h2>
+ <ul className='Checkin-list'>{hubItems}</ul>
+ </div>
+ <InvestorInfo personId={props.selected} isSelected={isSelected} name={name} dates={props.dates}></InvestorInfo>
+ </div>
+ );
+}
+
+export default HubList; \ No newline at end of file
diff --git a/react-frontend/src/components/InvestorInfo.js b/react-frontend/src/components/InvestorInfo.js
new file mode 100644
index 0000000..d368984
--- /dev/null
+++ b/react-frontend/src/components/InvestorInfo.js
@@ -0,0 +1,66 @@
+// React import
+import { useEffect, useState } from "react";
+
+// CSS import
+import '../css/UserCheckin.css';
+
+/**
+ * Componenet for checkins. Has a toggle to show more info.
+ * @param {Object} props The props of the component.
+ * @returns {import('react').HtmlHTMLAttributes} A list element holding a checkin's info.
+ */
+function InvestorInfo(props) {
+ const [info, setInfo] = useState({});
+
+ const toEpochMilli = date => Date.parse(date);
+ const getInfo = () => {
+ console.log({
+ person: props.name,
+ start: toEpochMilli(props.dates.start),
+ end: toEpochMilli(props.dates.end)
+ });
+
+ if (props.name === "") {
+ return;
+ }
+
+ fetch("http://localhost:4567/profit", {
+ method: "POST",
+ body: JSON.stringify({
+ person: props.name,
+ start: toEpochMilli(props.dates.start),
+ end: toEpochMilli(props.dates.end)
+ }),
+ headers: {
+ "Content-Type": "application/json",
+ },
+ credentials: "same-origin"
+ })
+ .then(res => {
+ console.log(res);
+ res.json();
+ })
+ .then(data => {
+ console.log(data);
+ setInfo(data);
+ })
+ .catch(err => console.log(err));
+ }
+ /*
+
+ const coords = userCoords.map((coord, index) =>
+ <li key={index}>
+ <span>{'('+coord[0].toFixed(6)}, {coord[1].toFixed(6)+')'}</span>
+ </li>
+ );*/
+
+ useEffect(() => getInfo(), [props.name, props.isSelected, props.personId])
+
+ return (
+ <div className="Chosen-user" hidden={props.isSelected}>
+ hi
+ </div>
+ );
+}
+
+export default InvestorInfo; \ No newline at end of file
diff --git a/react-frontend/src/components/Loading.js b/react-frontend/src/components/Loading.js
new file mode 100644
index 0000000..6fdf5ba
--- /dev/null
+++ b/react-frontend/src/components/Loading.js
@@ -0,0 +1,20 @@
+// CSS import
+import '../css/App.css';
+
+/**
+ * Component that shows the program initially loading.
+ * @returns The loading widget - spinning logo :)
+ */
+function Loading() {
+ return (
+ <div className="App Loading">
+ <header className="App-header">
+ <img src={"./logo512.png"} className="App-logo" alt="logo" />
+ <h1 className="App-title">Loading WatchDogs</h1>
+ <p className="App-title">It takes a minute to connect to the servers and database :)</p>
+ </header>
+ </div>
+ );
+}
+
+export default Loading; \ No newline at end of file
diff --git a/react-frontend/src/components/TimeSelector.js b/react-frontend/src/components/TimeSelector.js
new file mode 100644
index 0000000..6960807
--- /dev/null
+++ b/react-frontend/src/components/TimeSelector.js
@@ -0,0 +1,48 @@
+// React/Component imports
+import { useEffect, useState } from "react";
+import DateSelector from './DateSelector.js';
+
+// CSS imports
+import '../css/Route.css';
+
+
+/**
+ * The component that hold the forms for routing.
+ * @param {Object} props
+ */
+function TimeSelector(props) {
+ const [current, setCurrent] = useState("");
+
+ const toValue = date => new Date(date).toISOString().slice(0, 10);
+
+ const [startDate, setStartDate] = useState(props.dates.start);
+ const [endDate, setEndDate] = useState(props.dates.end);
+
+ const changeTimeframe = () => {
+ props.setDates({
+ start: startDate,
+ end: endDate
+ });
+ }
+
+ useEffect(() => setCurrent(""), [startDate, endDate]);
+
+ // The div with the html elements for routing.
+ return (
+ <div className="Route">
+ <div className="Coord-selectors-flex">
+ <DateSelector side={"left"} name={"Start Date"} className="Coord-select-left" clickedFunc={setCurrent}
+ changedFunc={setStartDate} disabled={current==='start' || props.isChanging} value={toValue(startDate)}></DateSelector>
+ <div>
+ <h2>Adjust Timeframe :)</h2>
+ <button className="Btn Route-btn" onClick={() => changeTimeframe()}
+ disabled={current!=="" || props.isChanging}>Change Timeframe</button>
+ </div>
+ <DateSelector side={"right"} name={"End Date"} className="Coord-select-right" clickedFunc={setCurrent}
+ changedFunc={setEndDate} disabled={current==='end' || props.isChanging} value={toValue(endDate)}></DateSelector>
+ </div>
+ </div>
+ );
+}
+
+export default TimeSelector; \ No newline at end of file
diff --git a/react-frontend/src/components/Visualization.js b/react-frontend/src/components/Visualization.js
new file mode 100644
index 0000000..91082e9
--- /dev/null
+++ b/react-frontend/src/components/Visualization.js
@@ -0,0 +1,69 @@
+// JS module imports
+import { useEffect, useRef, useState } from "react";
+import uuid from 'react-uuid';
+import Graph from 'vis-react';
+
+// CSS imports
+import '../css/Canvas.css';
+
+/**
+ * This function renders and mantains thhe canvas.
+ * @param {Object} props The props for the canvas.
+ * @returns {import("react").HtmlHTMLAttributes} The canvas to be retured.
+ */
+function Visualization(props) {
+ const options = {
+ edges: {
+ color: "#ffffff"
+ },
+ autoResize: true
+ };
+ const events = {
+ select: () => event => props.setSelected(event.nodes[0])
+ };
+
+ const [graphState, setGraphState] = useState({
+ nodes: [],
+ edges: []
+ });
+ const getNodes = () => {
+ let nodes = [];
+ props.data.forEach(hub => {
+ nodes.push({
+ id: hub.id,
+ label: hub.name,
+ size: hub.suspicionScore * 10
+ });
+ });
+ return nodes;
+ }
+ const getEdges = () => {
+ let edges = []
+ props.data.forEach(hub => {
+ hub.followers.forEach(follower => {
+ edges.push({
+ from: hub.id,
+ to: follower.id
+ });
+ });
+ });
+ return edges;
+ }
+
+ // Hooks to update graph state
+ useEffect(() => setGraphState({nodes: getNodes(), edges: getEdges()}), [JSON.stringify(props.data)]);
+
+ return (
+ <div className="Map-canvas">
+ <Graph
+ key={uuid()}
+ graph={graphState}
+ options={options}
+ events={events}>
+ </Graph>
+ </div>
+ );
+}
+
+export default Visualization;
+