From dfa1316135161402a55d14cc905904272a6015d1 Mon Sep 17 00:00:00 2001 From: Xiaohan Liu Date: Sun, 9 Apr 2023 15:02:15 -0500 Subject: [PATCH 01/16] all tasks displayed by flexible children --- src/components/AllTasksSection/index.js | 49 +++++++++++++------ .../AllTasksSection/index.module.css | 22 ++++++--- src/components/OnYourRadar/index.js | 0 src/components/OnYourRadar/index.module.css | 0 src/components/TaskListItem/index.module.css | 5 +- src/components/UpcomingComponent/index.js | 4 +- src/lib/constants.js | 2 + src/pages/Roadmap/index.js | 4 +- 8 files changed, 59 insertions(+), 27 deletions(-) create mode 100644 src/components/OnYourRadar/index.js create mode 100644 src/components/OnYourRadar/index.module.css diff --git a/src/components/AllTasksSection/index.js b/src/components/AllTasksSection/index.js index 664a9c1..1777eb6 100644 --- a/src/components/AllTasksSection/index.js +++ b/src/components/AllTasksSection/index.js @@ -2,27 +2,48 @@ import styles from "./index.module.css"; import classNames from "classnames/bind"; import React from "react"; import { TaskListItem } from "../../components/TaskListItem"; +import { useState, useEffect } from "react"; +import { COLORS_ARR } from "../../lib/constants"; const cx = classNames.bind(styles); export const AllTasksSection = React.forwardRef((props, ref) => { const { taskList } = props; + const [isExpanded, setIsExpanded] = useState(false); + const [color, setColor] = useState("#0198BA26"); + + const toggleExpansion = () => { + setIsExpanded(!isExpanded); + }; + + useEffect(() => { + // randomize color for the display block + setColor(COLORS_ARR[Math.floor(Math.random() * COLORS_ARR.length)]); + }, []); return ( -
-

{taskList[0]?.childName}

-
- {taskList.map((item, index) => ( - - ))} +
+

+ {taskList[0]?.childName} +

+
+ {isExpanded && + taskList.map((item, index) => ( + + ))}
); diff --git a/src/components/AllTasksSection/index.module.css b/src/components/AllTasksSection/index.module.css index e8e3ad7..1c58e6a 100644 --- a/src/components/AllTasksSection/index.module.css +++ b/src/components/AllTasksSection/index.module.css @@ -1,17 +1,23 @@ @import url("https://fonts.googleapis.com/css?family=Poppins"); -.tasksSection { - border-bottom: 3px solid black; - margin-left: 3vw; - margin-right: 3vw; - padding: 4vw; +.entireSection { + border-radius: 50px; + margin-top: 3vw; + margin-bottom: 3vw; + padding-top: 3vw; + padding-bottom: 3vw; } .childName { font-family: "Poppins"; font-weight:400; - font-size: 3vw; - color: #8B5674; + font-size: 5vw; margin: 0; - margin-right: auto; + margin-left: 1vh; +} + +.tasksSection { + margin-top: 3vw; + margin-bottom: 3vw; + background-color: rgba(255, 255, 255, 0.5); } \ No newline at end of file diff --git a/src/components/OnYourRadar/index.js b/src/components/OnYourRadar/index.js new file mode 100644 index 0000000..e69de29 diff --git a/src/components/OnYourRadar/index.module.css b/src/components/OnYourRadar/index.module.css new file mode 100644 index 0000000..e69de29 diff --git a/src/components/TaskListItem/index.module.css b/src/components/TaskListItem/index.module.css index 833737e..7d6b8d9 100644 --- a/src/components/TaskListItem/index.module.css +++ b/src/components/TaskListItem/index.module.css @@ -2,8 +2,8 @@ .tasks_div { border-bottom: 3px solid black; - margin-left: 3vw; - margin-right: 3vw; + /* margin-left: 2vw; + margin-right: 2vw; */ padding: 4vw; display: flex; justify-content: flex-end; @@ -32,4 +32,5 @@ color: #8B5674; margin: 0; margin-right: auto; + float: right; } \ No newline at end of file diff --git a/src/components/UpcomingComponent/index.js b/src/components/UpcomingComponent/index.js index 0280ae2..128bcf6 100644 --- a/src/components/UpcomingComponent/index.js +++ b/src/components/UpcomingComponent/index.js @@ -5,6 +5,7 @@ import { useNavigate } from "react-router-dom"; import { ROUTES } from "../../lib/constants"; import { CheckBox } from "../CheckBox"; import { checkEvent, uncheckEvent } from "../../lib/services"; +import { COLORS_ARR } from "../../lib/constants"; import React from "react"; const cx = classNames.bind(styles); @@ -25,8 +26,7 @@ export const UpcomingComponent = (props) => { useEffect(() => { // randomize color for the display block - const colors = ["#0198BA26", "#E3D15033", "#8B567478"]; - setColor(colors[Math.floor(Math.random() * colors.length)]); + setColor(COLORS_ARR[Math.floor(Math.random() * COLORS_ARR.length)]); }, []); const handleChecked = () => { diff --git a/src/lib/constants.js b/src/lib/constants.js index 00a9960..a061372 100644 --- a/src/lib/constants.js +++ b/src/lib/constants.js @@ -3,6 +3,8 @@ export const PRIORITY_LEVEL = { PRIORITY_LEVEL: 2, }; +export const COLORS_ARR = ["#0198BA26", "#E3D15033", "#8B567478"]; + export const WINDOW_TYPE = { WEB: "WEB", MOBILE: "MOBILE", diff --git a/src/pages/Roadmap/index.js b/src/pages/Roadmap/index.js index 52918fa..97f04d4 100644 --- a/src/pages/Roadmap/index.js +++ b/src/pages/Roadmap/index.js @@ -14,6 +14,7 @@ import { getAgeGivenBirthday, } from "../../lib/utils"; import { AuthButton } from "../../components/AuthButton"; +import { toast } from "react-toastify"; const cx = classNames.bind(styles); @@ -82,7 +83,8 @@ export const Roadmap = ({ toast }) => { headers: { "Content-Type": "application/json" }, body: JSON.stringify(inputObj), }) - .then((response) => console.log(response.json())) + .then((response) => response.json()) + .then((data) => toast("Successfully uploaded the csv!")) .catch((error) => { console.error(error); }); From 7b85043139023a7ab651910f61137c0fb2d06b87 Mon Sep 17 00:00:00 2001 From: Gabriel Dong Date: Sun, 9 Apr 2023 15:13:09 -0500 Subject: [PATCH 02/16] jwt completed --- package-lock.json | 115 +++++++++++++++++++++++++++++++++ package.json | 1 + src/lib/constants.js | 2 + src/lib/services.js | 8 +++ src/pages/AllTasks/index.js | 27 ++++++-- src/pages/Community/index.js | 21 ++++++ src/pages/Home/index.js | 37 +++++++++-- src/pages/Login/index.js | 42 +++++++++--- src/pages/Roadmap/index.js | 19 +++++- src/pages/TaskDetails/index.js | 23 ++++++- src/pages/Upcoming/index.js | 23 ++++++- 11 files changed, 294 insertions(+), 24 deletions(-) diff --git a/package-lock.json b/package-lock.json index d91426e..21c026c 100644 --- a/package-lock.json +++ b/package-lock.json @@ -10,6 +10,7 @@ "dependencies": { "classnames": "^2.3.2", "firebase": "^8.10.1", + "jsonwebtoken": "^9.0.0", "papaparse": "^5.4.1", "react": "^17.0.2", "react-circular-progressbar": "^2.1.0", @@ -5737,6 +5738,11 @@ "isarray": "^1.0.0" } }, + "node_modules/buffer-equal-constant-time": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/buffer-equal-constant-time/-/buffer-equal-constant-time-1.0.1.tgz", + "integrity": "sha512-zRpUiDwd/xk6ADqPMATG8vc9VPrkck7T07OIx0gnjmJAnHnTVXNQG3vfvWNuiZIkwu9KrKdA1iJKfsfTVxE6NA==" + }, "node_modules/buffer-from": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.2.tgz", @@ -7554,6 +7560,14 @@ "stream-shift": "^1.0.0" } }, + "node_modules/ecdsa-sig-formatter": { + "version": "1.0.11", + "resolved": "https://registry.npmjs.org/ecdsa-sig-formatter/-/ecdsa-sig-formatter-1.0.11.tgz", + "integrity": "sha512-nagl3RYrbNv6kQkeJIpt6NJZy8twLB/2vtz6yN9Z4vRKHN4/QZJIEbqohALSgwKdnksuY3k5Addp5lg8sVoVcQ==", + "dependencies": { + "safe-buffer": "^5.0.1" + } + }, "node_modules/ee-first": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/ee-first/-/ee-first-1.1.1.tgz", @@ -12791,6 +12805,35 @@ "graceful-fs": "^4.1.6" } }, + "node_modules/jsonwebtoken": { + "version": "9.0.0", + "resolved": "https://registry.npmjs.org/jsonwebtoken/-/jsonwebtoken-9.0.0.tgz", + "integrity": "sha512-tuGfYXxkQGDPnLJ7SibiQgVgeDgfbPq2k2ICcbgqW8WxWLBAxKQM/ZCu/IT8SOSwmaYl4dpTFCW5xZv7YbbWUw==", + "dependencies": { + "jws": "^3.2.2", + "lodash": "^4.17.21", + "ms": "^2.1.1", + "semver": "^7.3.8" + }, + "engines": { + "node": ">=12", + "npm": ">=6" + } + }, + "node_modules/jsonwebtoken/node_modules/semver": { + "version": "7.3.8", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.8.tgz", + "integrity": "sha512-NB1ctGL5rlHrPJtFDVIVzTyQylMLu9N9VICA6HSFJo8MCGVTMW6gfpicwKmmK/dAjTOrqu5l63JJOpDSrAis3A==", + "dependencies": { + "lru-cache": "^6.0.0" + }, + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" + } + }, "node_modules/jsx-ast-utils": { "version": "3.2.1", "resolved": "https://registry.npmjs.org/jsx-ast-utils/-/jsx-ast-utils-3.2.1.tgz", @@ -12803,6 +12846,25 @@ "node": ">=4.0" } }, + "node_modules/jwa": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/jwa/-/jwa-1.4.1.tgz", + "integrity": "sha512-qiLX/xhEEFKUAJ6FiBMbes3w9ATzyk5W7Hvzpa/SLYdxNtng+gcurvrI7TbACjIXlsJyr05/S1oUhZrc63evQA==", + "dependencies": { + "buffer-equal-constant-time": "1.0.1", + "ecdsa-sig-formatter": "1.0.11", + "safe-buffer": "^5.0.1" + } + }, + "node_modules/jws": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/jws/-/jws-3.2.2.tgz", + "integrity": "sha512-YHlZCB6lMTllWDtSPHz/ZXTsi8S00usEV6v1tjq8tOUZzw7DpSDWVXjXDre6ed1w/pd495ODpHZYSdkRTsa0HA==", + "dependencies": { + "jwa": "^1.4.1", + "safe-buffer": "^5.0.1" + } + }, "node_modules/killable": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/killable/-/killable-1.0.1.tgz", @@ -25677,6 +25739,11 @@ } } }, + "buffer-equal-constant-time": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/buffer-equal-constant-time/-/buffer-equal-constant-time-1.0.1.tgz", + "integrity": "sha512-zRpUiDwd/xk6ADqPMATG8vc9VPrkck7T07OIx0gnjmJAnHnTVXNQG3vfvWNuiZIkwu9KrKdA1iJKfsfTVxE6NA==" + }, "buffer-from": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.2.tgz", @@ -27131,6 +27198,14 @@ "stream-shift": "^1.0.0" } }, + "ecdsa-sig-formatter": { + "version": "1.0.11", + "resolved": "https://registry.npmjs.org/ecdsa-sig-formatter/-/ecdsa-sig-formatter-1.0.11.tgz", + "integrity": "sha512-nagl3RYrbNv6kQkeJIpt6NJZy8twLB/2vtz6yN9Z4vRKHN4/QZJIEbqohALSgwKdnksuY3k5Addp5lg8sVoVcQ==", + "requires": { + "safe-buffer": "^5.0.1" + } + }, "ee-first": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/ee-first/-/ee-first-1.1.1.tgz", @@ -31068,6 +31143,27 @@ "universalify": "^2.0.0" } }, + "jsonwebtoken": { + "version": "9.0.0", + "resolved": "https://registry.npmjs.org/jsonwebtoken/-/jsonwebtoken-9.0.0.tgz", + "integrity": "sha512-tuGfYXxkQGDPnLJ7SibiQgVgeDgfbPq2k2ICcbgqW8WxWLBAxKQM/ZCu/IT8SOSwmaYl4dpTFCW5xZv7YbbWUw==", + "requires": { + "jws": "^3.2.2", + "lodash": "^4.17.21", + "ms": "^2.1.1", + "semver": "^7.3.8" + }, + "dependencies": { + "semver": { + "version": "7.3.8", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.8.tgz", + "integrity": "sha512-NB1ctGL5rlHrPJtFDVIVzTyQylMLu9N9VICA6HSFJo8MCGVTMW6gfpicwKmmK/dAjTOrqu5l63JJOpDSrAis3A==", + "requires": { + "lru-cache": "^6.0.0" + } + } + } + }, "jsx-ast-utils": { "version": "3.2.1", "resolved": "https://registry.npmjs.org/jsx-ast-utils/-/jsx-ast-utils-3.2.1.tgz", @@ -31077,6 +31173,25 @@ "object.assign": "^4.1.2" } }, + "jwa": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/jwa/-/jwa-1.4.1.tgz", + "integrity": "sha512-qiLX/xhEEFKUAJ6FiBMbes3w9ATzyk5W7Hvzpa/SLYdxNtng+gcurvrI7TbACjIXlsJyr05/S1oUhZrc63evQA==", + "requires": { + "buffer-equal-constant-time": "1.0.1", + "ecdsa-sig-formatter": "1.0.11", + "safe-buffer": "^5.0.1" + } + }, + "jws": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/jws/-/jws-3.2.2.tgz", + "integrity": "sha512-YHlZCB6lMTllWDtSPHz/ZXTsi8S00usEV6v1tjq8tOUZzw7DpSDWVXjXDre6ed1w/pd495ODpHZYSdkRTsa0HA==", + "requires": { + "jwa": "^1.4.1", + "safe-buffer": "^5.0.1" + } + }, "killable": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/killable/-/killable-1.0.1.tgz", diff --git a/package.json b/package.json index a6f4ed8..b691d6a 100644 --- a/package.json +++ b/package.json @@ -5,6 +5,7 @@ "dependencies": { "classnames": "^2.3.2", "firebase": "^8.10.1", + "jsonwebtoken": "^9.0.0", "papaparse": "^5.4.1", "react": "^17.0.2", "react-circular-progressbar": "^2.1.0", diff --git a/src/lib/constants.js b/src/lib/constants.js index 00a9960..6b98222 100644 --- a/src/lib/constants.js +++ b/src/lib/constants.js @@ -140,3 +140,5 @@ export const SCHOOL_DISTRICT = [ { label: "Tomball" }, { label: "Waller" }, ]; + +export const TIMEOUT = 7200000; diff --git a/src/lib/services.js b/src/lib/services.js index 0cdb698..7760a88 100644 --- a/src/lib/services.js +++ b/src/lib/services.js @@ -210,3 +210,11 @@ export const getChildrenTasksArray = ( }); }); }; + +export const logoutTimer = () => { + setTimeout(() => { + localStorage.removeItem("jwtToken"); + localStorage.removeItem("userID"); + return; + }, 15000); +}; diff --git a/src/pages/AllTasks/index.js b/src/pages/AllTasks/index.js index 0689b8f..1ad2b3d 100644 --- a/src/pages/AllTasks/index.js +++ b/src/pages/AllTasks/index.js @@ -4,6 +4,8 @@ import styles from "./index.module.css"; import { AllTasksSection } from "../../components/AllTasksSection"; import ReactSearchBox from "react-search-box"; import { getChildrenTasksArray } from "../../lib/services"; +import { useNavigate } from "react-router-dom"; +import { TIMEOUT } from "../../lib/constants"; const cx = classNames.bind(styles); @@ -12,6 +14,9 @@ export const AllTasks = () => { const [searchQuery, setSearchQuery] = useState(""); //TODO: get information using cache const childrenId = ["63e5c4936d51fdbbbedb5503"]; + const [timer, setTimer] = useState(); + + const navigate = useNavigate(); useEffect(() => { getChildrenTasksArray(childrenId, false, allTaskArray, setAllTaskArray); @@ -27,6 +32,22 @@ export const AllTasks = () => { return task.title.toLowerCase().includes(searchQuery.toLowerCase()); }) ); + useEffect(() => { + console.log(localStorage); + setTimer( + setTimeout(() => { + localStorage.removeItem("jwtToken"); + localStorage.removeItem("userID"); + navigate("/login"); + }, TIMEOUT) + ); + }, []); + + useEffect(() => { + return () => { + clearTimeout(timer); + }; + }, [timer]); return (
{ overflow: "scroll", overscrollBehavior: "none", height: "92vh", - }} - > + }}> { overflow: "scroll", overscrollBehavior: "none", height: "66vh", - }} - > + }}> {filteredSections.map((childTasks, childTasksIndex) => ( ))} diff --git a/src/pages/Community/index.js b/src/pages/Community/index.js index d18834f..4374df4 100644 --- a/src/pages/Community/index.js +++ b/src/pages/Community/index.js @@ -4,6 +4,8 @@ import styles from "./index.module.css"; import { BackArrow } from "../../components/BackArrow"; import { NavBar } from "../NavBar"; import { CreatePost } from "../../components/CreatePost"; +import { useNavigate } from "react-router-dom"; +import { TIMEOUT } from "../../lib/constants"; // component imports import Dropdown from "../../components/CommunityHeader"; @@ -101,6 +103,9 @@ export const Community = () => { "Autism", ]); const [showCreatePost, setShowCreatePost] = useState(false); + const [timer, setTimer] = useState(); + + const navigate = useNavigate(); useEffect(() => { fetch("/community") @@ -114,6 +119,22 @@ export const Community = () => { }); }, []); + useEffect(() => { + setTimer( + setTimeout(() => { + localStorage.removeItem("jwtToken"); + localStorage.removeItem("userID"); + navigate("/login"); + }, TIMEOUT) + ); + }, []); + + useEffect(() => { + return () => { + clearTimeout(timer); + }; + }, [timer]); + const createPost = () => { setShowCreatePost(!showCreatePost); }; diff --git a/src/pages/Home/index.js b/src/pages/Home/index.js index 62254a0..a50c3b4 100644 --- a/src/pages/Home/index.js +++ b/src/pages/Home/index.js @@ -4,7 +4,8 @@ import styles from "./index.module.css"; import { NavBar } from "../NavBar"; import { ROUTES } from "../../lib/constants"; import { useWindowSize } from "../../lib/hooks"; -import { WINDOW_TYPE } from "../../lib/constants"; +import { WINDOW_TYPE, TIMEOUT } from "../../lib/constants"; +import { useNavigate } from "react-router-dom"; import { CircularProgressbarWithChildren, @@ -27,6 +28,8 @@ export const Home = () => { "Register for Autism Symposium", "Intensive IEP support & training", ]); + const [timer, setTimer] = useState(); + const navigate = useNavigate(); useEffect(() => { fetch("/userData") @@ -41,6 +44,23 @@ export const Home = () => { .catch((error) => console.log(error)); }, []); + useEffect(() => { + console.log(localStorage); + setTimer( + setTimeout(() => { + localStorage.removeItem("jwtToken"); + localStorage.removeItem("userID"); + navigate("/login"); + }, TIMEOUT) + ); + }, []); + + useEffect(() => { + return () => { + clearTimeout(timer); + }; + }, [timer]); + const hpElements = hpList.map((thing, index) => (

{index + 1 + ". " + thing} @@ -53,12 +73,16 @@ export const Home = () => { )); return ( -

+
+ })}>

Welcome 

{lastName} Family!

@@ -80,8 +104,7 @@ export const Home = () => { styles={buildStyles({ pathColor: "#E3D150", trailColor: "#F9F6DC", - })} - > + })}>
{points}
Points
@@ -100,7 +123,7 @@ export const Home = () => {
-
+
); }; diff --git a/src/pages/Login/index.js b/src/pages/Login/index.js index cf347e6..eb6f2b8 100644 --- a/src/pages/Login/index.js +++ b/src/pages/Login/index.js @@ -4,6 +4,7 @@ import classNames from "classnames/bind"; import { ReactComponent as ReactLogo } from "../../svg/F2F-logo.svg"; import styles from "./index.module.css"; import { ROUTES } from "../../lib/constants"; +import { STATUS_CODE } from "../../lib/constants"; const cx = classNames.bind(styles); @@ -14,21 +15,21 @@ export const Login = () => { const [error, setError] = useState(""); const [isLoggedIn, setIsLoggedIn] = useState(false); const [rememberMe, setRememberMe] = useState(false); - const [userID, setUserID] = useState(-1); const navigate = useNavigate(); useEffect(() => { if (isLoggedIn) { - navigate("/home", { - state: { - email: email, - userID: userID, - }, - }); + navigate("/home"); } }, [isLoggedIn, navigate]); useEffect(() => { + const userID = checkIfLoggedIn(); + console.log(userID); + if (userID) { + navigate("/home"); + } + // Check if there is a rememberMeToken in the localStorage const rememberMeToken = JSON.parse(localStorage.getItem("rememberMeToken")); if (rememberMeToken) { @@ -42,7 +43,7 @@ export const Login = () => { setIsLoading(true); setError(""); - fetch("http://localhost:3001/users/login", { + fetch(process.env.REACT_APP_HOST_URL + "/users/login", { method: "POST", headers: { "Content-Type": "application/json" }, body: JSON.stringify({ email: email, password: password }), @@ -52,9 +53,17 @@ export const Login = () => { }) .then((res) => { console.log(res); - if (res.message === "SUCCESS") { + if (res.message === STATUS_CODE.SUCESS) { + localStorage.setItem("userID", res.id); + localStorage.setItem("jwtToken", res.token); + fetch(process.env.REACT_APP_HOST_URL + "/users/getChildren") + .then((response) => { + response.json(); + }) + .then((data) => { + localStorage.setItem("children", data); + }); setIsLoggedIn(true); - setUserID(res.userID); } else { setError(res.message); } @@ -73,6 +82,19 @@ export const Login = () => { setIsLoading(false); }; + const checkIfLoggedIn = () => { + // console.log(localStorage.getItem("jwtToken")); + const rememberMeToken = localStorage.getItem("jwtToken"); + console.log(rememberMeToken); + if (rememberMeToken) { + // User is logged in + return rememberMeToken; + } else { + // User is not logged in + return null; + } + }; + return (
diff --git a/src/pages/Roadmap/index.js b/src/pages/Roadmap/index.js index 52918fa..db09b26 100644 --- a/src/pages/Roadmap/index.js +++ b/src/pages/Roadmap/index.js @@ -3,7 +3,7 @@ import classNames from "classnames/bind"; import Papa from "papaparse"; import { useAuth } from "../../lib/AuthContext"; import styles from "./index.module.css"; -import { ROUTES, PRIORITY_LEVEL } from "../../lib/constants"; +import { ROUTES, PRIORITY_LEVEL, TIMEOUT } from "../../lib/constants"; import { getChildrenTasksArray } from "../../lib/services"; import { ReactComponent as Calender } from "../../svg/roadmapCalender.svg"; import { ReactComponent as Box } from "../../svg/roadmapBox.svg"; @@ -27,6 +27,7 @@ export const Roadmap = ({ toast }) => { const [elseList, setElseList] = useState([]); //TODO: get the information from cache const childrenId = ["63e5c4936d51fdbbbedb5503"]; + const [timer, setTimer] = useState(); const getStats = (childrenId) => { childrenId.forEach((childId) => { @@ -125,6 +126,22 @@ export const Roadmap = ({ toast }) => {

)); + useEffect(() => { + setTimer( + setTimeout(() => { + localStorage.removeItem("jwtToken"); + localStorage.removeItem("userID"); + navigate("/login"); + }, TIMEOUT) + ); + }, []); + + useEffect(() => { + return () => { + clearTimeout(timer); + }; + }, [timer]); + return (
{ const [resources, setResources] = useState([]); const [checked, setChecked] = useState(completed); + const [timer, setTimer] = useState(); + + const navigate = useNavigate(); + + useEffect(() => { + console.log(localStorage); + setTimer( + setTimeout(() => { + localStorage.removeItem("jwtToken"); + localStorage.removeItem("userID"); + navigate("/login"); + }, TIMEOUT) + ); + }, []); + + useEffect(() => { + return () => { + clearTimeout(timer); + }; + }, [timer]); useEffect(() => { const url = "/tasks/" + taskId; diff --git a/src/pages/Upcoming/index.js b/src/pages/Upcoming/index.js index 80af95a..d34562c 100644 --- a/src/pages/Upcoming/index.js +++ b/src/pages/Upcoming/index.js @@ -3,8 +3,9 @@ import classNames from "classnames/bind"; import { UpcomingComponent } from "../../components/UpcomingComponent"; import { useWindowSize } from "../../lib/hooks"; import { useState, useEffect } from "react"; -import { WINDOW_TYPE } from "../../lib/constants"; +import { WINDOW_TYPE, TIMEOUT } from "../../lib/constants"; import { getChildrenTasksArray } from "../../lib/services"; +import { useNavigate } from "react-router-dom"; const cx = classNames.bind(styles); @@ -14,6 +15,9 @@ export const Upcoming = ({ toast }) => { const [taskArray, setTaskArray] = useState([]); //TODO: get information using cache const childrenId = ["63e5c4936d51fdbbbedb5503"]; + const [timer, setTimer] = useState(); + + const navigate = useNavigate(); useEffect(() => { getChildrenTasksArray(childrenId, true, taskArray, setTaskArray); @@ -23,6 +27,23 @@ export const Upcoming = ({ toast }) => { return index === self.findIndex((o) => o._id === obj._id); }); + useEffect(() => { + console.log(localStorage); + setTimer( + setTimeout(() => { + localStorage.removeItem("jwtToken"); + localStorage.removeItem("userID"); + navigate("/login"); + }, TIMEOUT) + ); + }, []); + + useEffect(() => { + return () => { + clearTimeout(timer); + }; + }, [timer]); + return ( <>
From db4035384b513fea24425124d3cbe70b837757df Mon Sep 17 00:00:00 2001 From: Xiaohan Liu Date: Sun, 9 Apr 2023 15:49:06 -0500 Subject: [PATCH 03/16] moved radar to home page --- src/components/OnYourRadar/index.js | 39 ++++++++++++++ src/components/OnYourRadar/index.module.css | 37 ++++++++++++++ src/pages/Home/index.js | 56 ++++----------------- src/pages/Home/index.module.css | 36 ------------- src/pages/Roadmap/index.js | 48 ++++-------------- src/pages/Roadmap/index.module.css | 39 -------------- 6 files changed, 96 insertions(+), 159 deletions(-) diff --git a/src/components/OnYourRadar/index.js b/src/components/OnYourRadar/index.js index e69de29..33d8073 100644 --- a/src/components/OnYourRadar/index.js +++ b/src/components/OnYourRadar/index.js @@ -0,0 +1,39 @@ +import styles from "./index.module.css"; +import classNames from "classnames/bind"; +import React from "react"; +import { useState, useEffect } from "react"; +import { getChildrenTasksArray } from "../../lib/services"; + +const cx = classNames.bind(styles); + +export const OnYourRadar = React.forwardRef((props, ref) => { + const { childrenId } = props; + const [hpList, sethpList] = useState([]); + const [elseList, setElseList] = useState([]); + + useEffect(() => { + getChildrenTasksArray(childrenId, true, hpList, sethpList); + getChildrenTasksArray(childrenId, false, elseList, setElseList); + }, []); + + const hpElements = hpList.flat().map((thing, index) => ( +

+ {index + 1 + ". " + thing.title} +

+ )); + const elseElements = elseList.flat().map((thing, index) => ( +

+ {index + 1 + ". " + thing.title} +

+ )); + + return ( +
+

On Your Radar

+

High Priority

+

{hpElements}

+

All Tasks

+

{elseElements}

+
+ ); +}); diff --git a/src/components/OnYourRadar/index.module.css b/src/components/OnYourRadar/index.module.css index e69de29..7cc44d9 100644 --- a/src/components/OnYourRadar/index.module.css +++ b/src/components/OnYourRadar/index.module.css @@ -0,0 +1,37 @@ +.todo_div { + border: 6px #0198ba; + border-style: solid; + border-radius: 50px; + margin-top: 10vw; + margin-left: 2vw; + margin-right: 2vw; + padding-left: 3vw; + padding-bottom: 10vw; + } + + .radar { + font-family: "Poppins"; + font-weight: 900; + color: black; + font-size: 7vw; + margin-top: 3vw; + } + + .priority { + font-family: "Poppins"; + font-weight: bolder; + color: #8b5674; + font-size: 5vw; + margin-top: 6vw; + } + + .priority.else { + color: #e3d150; + } + + .list { + font-family: 'Poppins'; + color: black; + font-weight: 600; + font-size: 3vw; +} \ No newline at end of file diff --git a/src/pages/Home/index.js b/src/pages/Home/index.js index 62254a0..3918017 100644 --- a/src/pages/Home/index.js +++ b/src/pages/Home/index.js @@ -1,11 +1,10 @@ -import React, { useState, useEffect, createContext } from "react"; +import React, { useState, useEffect } from "react"; import classNames from "classnames/bind"; import styles from "./index.module.css"; import { NavBar } from "../NavBar"; -import { ROUTES } from "../../lib/constants"; import { useWindowSize } from "../../lib/hooks"; import { WINDOW_TYPE } from "../../lib/constants"; - +import { OnYourRadar } from "../../components/OnYourRadar"; import { CircularProgressbarWithChildren, buildStyles, @@ -18,42 +17,18 @@ export const Home = () => { const { width, type } = useWindowSize(); const isMobile = type === WINDOW_TYPE.MOBILE; - + // use Cache to store the user const [lastName, setLastName] = useState("Adam's"); const [goal, setGoal] = useState(100); const [points, setPoints] = useState(71); - const [hpList, sethpList] = useState(["Medicaid Waitlist"]); - const [elseList, setElseList] = useState([ - "Register for Autism Symposium", - "Intensive IEP support & training", - ]); - - useEffect(() => { - fetch("/userData") - .then((response) => response.json()) - .then((data) => { - setLastName(data.lastName); - setGoal(data.goal); - setPoints(data.points); - sethpList(data.hpList); - setElseList(data.elseList); - }) - .catch((error) => console.log(error)); - }, []); - const hpElements = hpList.map((thing, index) => ( -

- {index + 1 + ". " + thing} -

- )); - const elseElements = elseList.map((thing, index) => ( -

- {index + 1 + ". " + thing} -

- )); + // TODO: cache + const childrenId = ["63e5c4936d51fdbbbedb5503"]; return ( -
+
{
Points
-
-

On Your Radar

-

High Priority

- {hpElements} -

Everything Else

- {elseElements} - -
+
-
+
); }; diff --git a/src/pages/Home/index.module.css b/src/pages/Home/index.module.css index 1dd2946..116887f 100644 --- a/src/pages/Home/index.module.css +++ b/src/pages/Home/index.module.css @@ -79,42 +79,6 @@ font-size: 6vw; } -.todo_div { - border: 6px #0198BA; - border-style: solid; - border-radius: 50px; - margin: 2vw; - margin-bottom: 4vw; - padding: 3vw; -} - -.radar { - font-family: 'Poppins'; - font-weight: 900; - color: black; - font-size: 7vw; - margin-top: 3vw; -} - -.priority { - font-family: 'Poppins'; - font-weight: bolder; - color: #8B5674; - font-size: 5vw; - margin-top: 6vw; -} - -.priority.else { - color: #E3D150; -} - -.list { - font-family: 'Poppins'; - color: black; - font-weight: 600; - font-size: 3vw; -} - .link_div { text-align: center; margin-top: 8vw; diff --git a/src/pages/Roadmap/index.js b/src/pages/Roadmap/index.js index 97f04d4..f7d7ccd 100644 --- a/src/pages/Roadmap/index.js +++ b/src/pages/Roadmap/index.js @@ -24,8 +24,6 @@ export const Roadmap = ({ toast }) => { const [numAllTasks, setNumAllTasks] = useState(0); const uploadRef = useRef(); const [importFile, setImportFile] = useState(null); - const [hpList, sethpList] = useState([]); - const [elseList, setElseList] = useState([]); //TODO: get the information from cache const childrenId = ["63e5c4936d51fdbbbedb5503"]; @@ -36,9 +34,7 @@ export const Roadmap = ({ toast }) => { fetch(process.env.REACT_APP_HOST_URL + childUrl) .then((response) => response.json()) .then((childrenData) => { - const childName = childrenData.firstName; const age = getAgeGivenBirthday(childrenData.birthDate); - const completedTasks = childrenData.completedTasks; const params = { disabilities: JSON.stringify(childrenData.disabilities), age: JSON.stringify(age), @@ -61,8 +57,6 @@ export const Roadmap = ({ toast }) => { useEffect(() => { getStats(childrenId); - getChildrenTasksArray(childrenId, true, hpList, sethpList); - getChildrenTasksArray(childrenId, false, elseList, setElseList); }, []); // set the import csv file @@ -116,31 +110,14 @@ export const Roadmap = ({ toast }) => { .catch((error) => console.error(error)); }; - const hpElements = hpList.flat().map((thing, index) => ( -

- {index + 1 + ". " + thing.title} -

- )); - const elseElements = elseList.flat().map((thing, index) => ( -

- {index + 1 + ". " + thing.title} -

- )); - return (
- {/*
-

Road Map

-

- Below are all the tasks needed to be completed -

-
*/} - + }} + >
{
navigate(ROUTES.UPCOMING_TASKS)} - className={cx(styles.tasks_div)}> + className={cx(styles.tasks_div)} + >
@@ -177,7 +155,8 @@ export const Roadmap = ({ toast }) => { position: "relative", display: "flex", margin: "10px", - }}> + }} + >

Upcoming

@@ -191,7 +170,8 @@ export const Roadmap = ({ toast }) => {
navigate(ROUTES.ALL_TASKS)} - className={cx(styles.tasks_div, "all")}> + className={cx(styles.tasks_div, "all")} + >
@@ -201,7 +181,8 @@ export const Roadmap = ({ toast }) => { position: "relative", display: "flex", margin: "10px", - }}> + }} + >

All Tasks

@@ -210,15 +191,6 @@ export const Roadmap = ({ toast }) => {

{numAllTasks}

- - {/* just for mvp */} -
-

On Your Radar

-

High Priority

- {hpElements} -

All Tasks

- {elseElements} -
); }; diff --git a/src/pages/Roadmap/index.module.css b/src/pages/Roadmap/index.module.css index 7773310..867dedf 100644 --- a/src/pages/Roadmap/index.module.css +++ b/src/pages/Roadmap/index.module.css @@ -58,45 +58,6 @@ margin-left: auto; } -/* just for mvp */ -.todo_div { - border: 6px #0198ba; - border-style: solid; - border-radius: 50px; - margin-top: 10vw; - margin-left: 2vw; - margin-right: 2vw; - padding-left: 3vw; - padding-bottom: 10vw; -} - -.radar { - font-family: "Poppins"; - font-weight: 900; - color: black; - font-size: 7vw; - margin-top: 3vw; -} - -.priority { - font-family: "Poppins"; - font-weight: bolder; - color: #8b5674; - font-size: 5vw; - margin-top: 6vw; -} - -.priority.else { - color: #e3d150; -} - -.list { - font-family: "Poppins"; - color: black; - font-weight: 600; - font-size: 3vw; -} - .csvButton { margin-bottom: 2vh; } From a7603e974f72028f2c2e2d32aa699eec7710c8c3 Mon Sep 17 00:00:00 2001 From: Xiaohan Liu Date: Sun, 9 Apr 2023 15:59:26 -0500 Subject: [PATCH 04/16] factored out PointsDisplay --- src/components/PointsDisplay/index.js | 41 +++++++++++++++++++ src/components/PointsDisplay/index.module.css | 36 ++++++++++++++++ src/pages/Home/index.js | 29 ++----------- src/pages/Home/index.module.css | 30 -------------- 4 files changed, 80 insertions(+), 56 deletions(-) create mode 100644 src/components/PointsDisplay/index.js create mode 100644 src/components/PointsDisplay/index.module.css diff --git a/src/components/PointsDisplay/index.js b/src/components/PointsDisplay/index.js new file mode 100644 index 0000000..3341139 --- /dev/null +++ b/src/components/PointsDisplay/index.js @@ -0,0 +1,41 @@ +import styles from "./index.module.css"; +import classNames from "classnames/bind"; +import React from "react"; +import { useState, useEffect } from "react"; +import { getChildrenTasksArray } from "../../lib/services"; +import { + CircularProgressbarWithChildren, + buildStyles, +} from "react-circular-progressbar"; + +const cx = classNames.bind(styles); + +export const PointsDisplay = React.forwardRef((props, ref) => { + const { childrenId } = props; + const [goal, setGoal] = useState(100); + const [points, setPoints] = useState(71); + + return ( +
+
+

{goal - points}

+

+  points away from your weekly goal +

+
+
+ +
{points}
+
Points
+
+
+
+ ); +}); diff --git a/src/components/PointsDisplay/index.module.css b/src/components/PointsDisplay/index.module.css new file mode 100644 index 0000000..e4eeac3 --- /dev/null +++ b/src/components/PointsDisplay/index.module.css @@ -0,0 +1,36 @@ +.text_div { + margin-left: auto; + margin-right: auto; + text-align: center; + position: relative; +} + +.points { + font-family: 'Poppins'; + font-weight: 800; + font-size: 4.2vw; + margin: auto; + display: inline-block; + color: #000000; +} + +.points.text { + font-weight: 600; + color: #818181; +} + +.progress_circle { + width: 40vw; + height: 40vw; + margin-top: 5vw; + margin-bottom: 5vw; + margin-left: auto; + margin-right: auto; +} + +.progress_circle_text { + font-family: 'Poppins'; + font-weight: 900; + color: black; + font-size: 6vw; +} \ No newline at end of file diff --git a/src/pages/Home/index.js b/src/pages/Home/index.js index 3918017..b0fdd0e 100644 --- a/src/pages/Home/index.js +++ b/src/pages/Home/index.js @@ -5,10 +5,7 @@ import { NavBar } from "../NavBar"; import { useWindowSize } from "../../lib/hooks"; import { WINDOW_TYPE } from "../../lib/constants"; import { OnYourRadar } from "../../components/OnYourRadar"; -import { - CircularProgressbarWithChildren, - buildStyles, -} from "react-circular-progressbar"; +import { PointsDisplay } from "../../components/PointsDisplay"; import "react-circular-progressbar/dist/styles.css"; const cx = classNames.bind(styles); @@ -17,10 +14,8 @@ export const Home = () => { const { width, type } = useWindowSize(); const isMobile = type === WINDOW_TYPE.MOBILE; - // use Cache to store the user + // TODO: use Cache to store the user const [lastName, setLastName] = useState("Adam's"); - const [goal, setGoal] = useState(100); - const [points, setPoints] = useState(71); // TODO: cache const childrenId = ["63e5c4936d51fdbbbedb5503"]; @@ -42,25 +37,7 @@ export const Home = () => {

You're 

Cruising it!

-
-

{goal - points}

-

-  points away from your weekly goal -

-
-
- -
{points}
-
Points
-
-
+
diff --git a/src/pages/Home/index.module.css b/src/pages/Home/index.module.css index 116887f..3a86360 100644 --- a/src/pages/Home/index.module.css +++ b/src/pages/Home/index.module.css @@ -49,36 +49,6 @@ font-weight: 900; } -.points { - font-family: 'Poppins'; - font-weight: 800; - font-size: 4.2vw; - margin: auto; - display: inline-block; - color: #000000; -} - -.points.text { - font-weight: 600; - color: #818181; -} - -.progress_circle { - width: 40vw; - height: 40vw; - margin-top: 5vw; - margin-bottom: 5vw; - margin-left: auto; - margin-right: auto; -} - -.progress_circle_text { - font-family: 'Poppins'; - font-weight: 900; - color: black; - font-size: 6vw; -} - .link_div { text-align: center; margin-top: 8vw; From 47ec3f1b3ab3887d0f72a5988ba3be465fd88b53 Mon Sep 17 00:00:00 2001 From: Gabriel Dong Date: Wed, 12 Apr 2023 17:11:54 -0500 Subject: [PATCH 05/16] merge conflict --- package-lock.json | 129 +++++++++++++++++++++++-- package.json | 3 +- src/App.js | 2 - src/components/AuthInputBlock/index.js | 1 + src/lib/constants.js | 5 +- src/lib/services.js | 85 +--------------- src/pages/Community/index.js | 6 +- src/pages/Community/index.module.css | 15 +-- src/pages/Roadmap/index.module.css | 4 - src/pages/SignUp/index.js | 78 +++------------ 10 files changed, 158 insertions(+), 170 deletions(-) diff --git a/package-lock.json b/package-lock.json index 21c026c..a24de85 100644 --- a/package-lock.json +++ b/package-lock.json @@ -9,6 +9,7 @@ "version": "0.1.0", "dependencies": { "classnames": "^2.3.2", + "env-cmd": "^10.1.0", "firebase": "^8.10.1", "jsonwebtoken": "^9.0.0", "papaparse": "^5.4.1", @@ -7690,6 +7691,75 @@ "url": "https://github.com/fb55/entities?sponsor=1" } }, + "node_modules/env-cmd": { + "version": "10.1.0", + "resolved": "https://registry.npmjs.org/env-cmd/-/env-cmd-10.1.0.tgz", + "integrity": "sha512-mMdWTT9XKN7yNth/6N6g2GuKuJTsKMDHlQFUDacb/heQRRWOTIZ42t1rMHnQu4jYxU1ajdTeJM+9eEETlqToMA==", + "dependencies": { + "commander": "^4.0.0", + "cross-spawn": "^7.0.0" + }, + "bin": { + "env-cmd": "bin/env-cmd.js" + }, + "engines": { + "node": ">=8.0.0" + } + }, + "node_modules/env-cmd/node_modules/cross-spawn": { + "version": "7.0.3", + "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.3.tgz", + "integrity": "sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==", + "dependencies": { + "path-key": "^3.1.0", + "shebang-command": "^2.0.0", + "which": "^2.0.1" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/env-cmd/node_modules/path-key": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz", + "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==", + "engines": { + "node": ">=8" + } + }, + "node_modules/env-cmd/node_modules/shebang-command": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz", + "integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==", + "dependencies": { + "shebang-regex": "^3.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/env-cmd/node_modules/shebang-regex": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz", + "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==", + "engines": { + "node": ">=8" + } + }, + "node_modules/env-cmd/node_modules/which": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", + "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==", + "dependencies": { + "isexe": "^2.0.0" + }, + "bin": { + "node-which": "bin/node-which" + }, + "engines": { + "node": ">= 8" + } + }, "node_modules/errno": { "version": "0.1.8", "resolved": "https://registry.npmjs.org/errno/-/errno-0.1.8.tgz", @@ -14183,9 +14253,9 @@ "integrity": "sha512-4hLB8Py4zZce5s4yd9XzopqwVv/yGNhV1Bl8NTmCq1763HeK2+EwVTv+leGeL13Dnh2wfbqowVPXCIO0z4taYw==" }, "node_modules/papaparse": { - "version": "5.4.1", - "resolved": "https://registry.npmjs.org/papaparse/-/papaparse-5.4.1.tgz", - "integrity": "sha512-HipMsgJkZu8br23pW15uvo6sib6wne/4woLZPlFf3rpDyMe9ywEXUsuD7+6K9PRkJlVT51j/sCOYDKGGS3ZJrw==" + "version": "5.3.2", + "resolved": "https://registry.npmjs.org/papaparse/-/papaparse-5.3.2.tgz", + "integrity": "sha512-6dNZu0Ki+gyV0eBsFKJhYr+MdQYAzFUGlBMNj3GNrmHxmz1lfRa24CjFObPXtjcetlOv5Ad299MhIK0znp3afw==" }, "node_modules/parallel-transform": { "version": "1.2.0", @@ -27304,6 +27374,53 @@ "resolved": "https://registry.npmjs.org/entities/-/entities-2.2.0.tgz", "integrity": "sha512-p92if5Nz619I0w+akJrLZH0MX0Pb5DX39XOwQTtXSdQQOaYH03S1uIQp4mhOZtAXrxq4ViO67YTiLBo2638o9A==" }, + "env-cmd": { + "version": "10.1.0", + "resolved": "https://registry.npmjs.org/env-cmd/-/env-cmd-10.1.0.tgz", + "integrity": "sha512-mMdWTT9XKN7yNth/6N6g2GuKuJTsKMDHlQFUDacb/heQRRWOTIZ42t1rMHnQu4jYxU1ajdTeJM+9eEETlqToMA==", + "requires": { + "commander": "^4.0.0", + "cross-spawn": "^7.0.0" + }, + "dependencies": { + "cross-spawn": { + "version": "7.0.3", + "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.3.tgz", + "integrity": "sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==", + "requires": { + "path-key": "^3.1.0", + "shebang-command": "^2.0.0", + "which": "^2.0.1" + } + }, + "path-key": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz", + "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==" + }, + "shebang-command": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz", + "integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==", + "requires": { + "shebang-regex": "^3.0.0" + } + }, + "shebang-regex": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz", + "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==" + }, + "which": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", + "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==", + "requires": { + "isexe": "^2.0.0" + } + } + } + }, "errno": { "version": "0.1.8", "resolved": "https://registry.npmjs.org/errno/-/errno-0.1.8.tgz", @@ -32231,9 +32348,9 @@ "integrity": "sha512-4hLB8Py4zZce5s4yd9XzopqwVv/yGNhV1Bl8NTmCq1763HeK2+EwVTv+leGeL13Dnh2wfbqowVPXCIO0z4taYw==" }, "papaparse": { - "version": "5.4.1", - "resolved": "https://registry.npmjs.org/papaparse/-/papaparse-5.4.1.tgz", - "integrity": "sha512-HipMsgJkZu8br23pW15uvo6sib6wne/4woLZPlFf3rpDyMe9ywEXUsuD7+6K9PRkJlVT51j/sCOYDKGGS3ZJrw==" + "version": "5.3.2", + "resolved": "https://registry.npmjs.org/papaparse/-/papaparse-5.3.2.tgz", + "integrity": "sha512-6dNZu0Ki+gyV0eBsFKJhYr+MdQYAzFUGlBMNj3GNrmHxmz1lfRa24CjFObPXtjcetlOv5Ad299MhIK0znp3afw==" }, "parallel-transform": { "version": "1.2.0", diff --git a/package.json b/package.json index b691d6a..04e98de 100644 --- a/package.json +++ b/package.json @@ -4,6 +4,7 @@ "private": true, "dependencies": { "classnames": "^2.3.2", + "env-cmd": "^10.1.0", "firebase": "^8.10.1", "jsonwebtoken": "^9.0.0", "papaparse": "^5.4.1", @@ -19,7 +20,7 @@ "scripts": { "start": "react-scripts start", "build": "react-scripts build", - "test": "react-scripts", + "test": "react-scripts test", "eject": "react-scripts eject" }, "eslintConfig": { diff --git a/src/App.js b/src/App.js index dbc70aa..c9e971b 100644 --- a/src/App.js +++ b/src/App.js @@ -15,7 +15,6 @@ import { Roadmap } from "./pages/Roadmap"; import { Community } from "./pages/Community"; import { TaskDetails } from "./pages/TaskDetails"; import { AllTasks } from "./pages/AllTasks"; -import { EmailVerification } from "./pages/Verification"; const App = () => { return ( @@ -39,7 +38,6 @@ const App = () => { } /> } /> } /> - } /> diff --git a/src/components/AuthInputBlock/index.js b/src/components/AuthInputBlock/index.js index bd22279..47e1806 100644 --- a/src/components/AuthInputBlock/index.js +++ b/src/components/AuthInputBlock/index.js @@ -15,6 +15,7 @@ export const AuthInputBlock = (props) => { isMobile } = props; + console.log(isMobile) return
{ - console.log("email " + email); - return new Promise((resolve, reject) => { - //make localhost call a constant - fetch(`http://localhost:3001/verification/checkMongo/?email=${email}`, { - method: "GET", - headers: { "Content-Type": "application/json" }, - }) - .then((response) => response.json()) - .then((response) => { - resolve(response); - }) - .catch((err) => reject(err)); - }); -}; - -export const salesForceCheck = (email) => { - return new Promise((resolve, reject) => { - //make localhost call a constant - fetch(`http://localhost:3001/verification/checkSF/?email=${email}`, { - method: "GET", - headers: { "Content-Type": "application/json" }, - }) - .then((response) => response.json()) - .then((response) => resolve(response)) - .catch((err) => reject(err)); - }); -}; - -export const sendVerificationEmail = (email) => { +export const signUp = (inputs) => { return new Promise((resolve, reject) => { - fetch(`http://localhost:3001/verification/sendEmail/?email=${email}`, { - method: "GET", + fetch(process.env.REACT_APP_HOST_URL + "/users", { + method: "POST", headers: { "Content-Type": "application/json" }, + body: JSON.stringify(inputs), }) .then((response) => response.json()) .then((response) => resolve(response)) @@ -48,55 +20,6 @@ export const sendVerificationEmail = (email) => { }); }; -export const signUp = (inputs) => { - // need to fix process.env later - // fetch(process.env.HOST_URL + '/users', { - // return mongoCheck(inputs.email).then((res) => { - // console.log(res); - // if (res.status === "Found") { - // console.log("here"); - // return { message: "toLogin" }; - // } else { - // return salesForceCheck(inputs.email).then((res) => { - // console.log(res) - // if (res === STATUS_CODE.SUCESS) { - // return { message: "sendVerification" }; - // } else { - // return { message: "sendSFForm" }; - // } - // }); - // } - // }); - - inputs.schoolDistrict = inputs.schoolDistrict.label; - return fetch("http://localhost:3001" + "/users", { - method: "POST", - headers: { "Content-Type": "application/json" }, - body: JSON.stringify(inputs), - }) - .then((res) => { - console.log(res); - console.log(JSON.stringify(inputs)); - }) - .catch((err) => { - console.log(err); - }); -}; - -// export const checkEvent = (inputs) => { -// return new Promise((resolve, reject) => { -// // need to fix process.env later -// fetch("http://localhost:3001/tasks/checkEvent", { -// method: "POST", -// headers: { "Content-Type": "application/json" }, -// body: JSON.stringify(inputs), -// }) -// .then((response) => response.json()) -// .then((response) => resolve(response)) -// .catch((err) => reject(err)); -// }); -// }; - export const getChildrenByIdBatch = (childrenId) => { const url = formGetRequest("/children/getChildrenByIdBatch/", { id: JSON.stringify(childrenId), diff --git a/src/pages/Community/index.js b/src/pages/Community/index.js index 4374df4..4060db8 100644 --- a/src/pages/Community/index.js +++ b/src/pages/Community/index.js @@ -3,7 +3,6 @@ import classNames from "classnames"; import styles from "./index.module.css"; import { BackArrow } from "../../components/BackArrow"; import { NavBar } from "../NavBar"; -import { CreatePost } from "../../components/CreatePost"; import { useNavigate } from "react-router-dom"; import { TIMEOUT } from "../../lib/constants"; @@ -99,8 +98,8 @@ export const Community = () => { ]); const [options, setOptions] = useState([ "All Disabilities", - "ADHD", "Autism", + "Cant be ", ]); const [showCreatePost, setShowCreatePost] = useState(false); const [timer, setTimer] = useState(); @@ -136,7 +135,7 @@ export const Community = () => { }, [timer]); const createPost = () => { - setShowCreatePost(!showCreatePost); + console.log("called"); }; return ( @@ -167,7 +166,6 @@ export const Community = () => {
- {showCreatePost && }
); diff --git a/src/pages/Community/index.module.css b/src/pages/Community/index.module.css index 3fa814c..1d5cecd 100644 --- a/src/pages/Community/index.module.css +++ b/src/pages/Community/index.module.css @@ -36,13 +36,6 @@ body { z-index: 2; } -.create_post:hover { - cursor: pointer; - transform: scale(1.01); - transition: 0.2s; - box-shadow: 0 6px 4px darkgray; -} - .posts { margin-top: 10vh; } @@ -50,3 +43,11 @@ body { .create_post img { width: 70%; } + +.create_post:hover { + cursor: pointer; +} + +.create_post { + cursor: pointer; +} diff --git a/src/pages/Roadmap/index.module.css b/src/pages/Roadmap/index.module.css index 7773310..64b19f2 100644 --- a/src/pages/Roadmap/index.module.css +++ b/src/pages/Roadmap/index.module.css @@ -96,7 +96,3 @@ font-weight: 600; font-size: 3vw; } - -.csvButton { - margin-bottom: 2vh; -} diff --git a/src/pages/SignUp/index.js b/src/pages/SignUp/index.js index a163e75..4ff3cd9 100644 --- a/src/pages/SignUp/index.js +++ b/src/pages/SignUp/index.js @@ -6,17 +6,14 @@ import { DISABILITY, WINDOW_TYPE, STATUS_CODE, - ROUTES, } from "../../lib/constants"; import { AuthInputBlock } from "../../components/AuthInputBlock"; import { AuthSelectBlock } from "../../components/AuthSelectBlock"; import { AuthButton } from "../../components/AuthButton"; -import { useEffect, useState } from "react"; -import { signUp, sendVerificationEmail } from "../../lib/services"; +import { useState } from "react"; +import { signUp } from "../../lib/services"; import { useNavigate } from "react-router-dom"; import { useWindowSize } from "../../lib/hooks"; -import { mongoCheck } from "../../lib/services"; - const cx = classNames.bind(styles); // Register page for authentication @@ -32,13 +29,6 @@ export const SignUp = ({ toast }) => { const [disability, setDisability] = useState([]); const [zipCode, setZipCode] = useState(""); const [phoneNumber, setPhoneNumber] = useState(""); - const [verifCode, setVerifCode] = useState(-1); - const [error, setError] = useState(""); - - useEffect(() => { - console.log(verifCode); - //navigate or make visibl - }, [verifCode]); const onRegister = () => { if (!email) toast("Please provide your email"); @@ -53,56 +43,21 @@ export const SignUp = ({ toast }) => { else if (!zipCode) toast("Please provide your zip code"); else if (!phoneNumber) toast("Please provide your phone number"); else { - mongoCheck(email).then((res) => { - console.log(res); - if (res.status === "Found") { - setError("Email already exists"); - } else { - navigate(ROUTES.VERIFICATION, { - state: { - email: email, - password: password, - firstName: firstName, - lastName: lastName, - schoolDistrict: schoolDistrict, - zipCode: zipCode, - phoneNumber: phoneNumber, - }, - }); - } - }); // send response to backend and create a record - // signUp({ - // email, - // password, - // firstName, - // lastName, - // schoolDistrict, - // zipCode, - // phoneNumber, - // }) - // .then((res) => { - // // console.log(res); - // // navigate("/login") - // // let message = res.message; - // // //make constants later - // // console.log(message); - // // if (message === "toLogin") { - // // console.log("1"); - // // navigate("/login"); - // // } - // // if (message === "sendVerification") { - // // sendVerificationEmail(email).then((code) => { - // // setVerifCode(code); - // // }); - // // //if input code === code , we continue - // // } - // // if (message === "sendSFForm") { - // // console.log("3"); - // // // navigate("/createUser") - // // } - // }) - // .catch((err) => toast("Internal error")); + signUp({ + email, + password, + firstName, + lastName, + schoolDistrict, + zipCode, + phoneNumber, + }) + .then((res) => { + const { status } = res; + if (status === STATUS_CODE.SUCESS) navigate("/login"); + }) + .catch((err) => toast("Internal error")); } }; @@ -177,7 +132,6 @@ export const SignUp = ({ toast }) => { onChange={setPhoneNumber} isMobile={isMobile} /> - {error &&
{error}
} Date: Wed, 12 Apr 2023 18:24:35 -0500 Subject: [PATCH 06/16] finished point display for a single child --- src/components/PointsDisplay/index.js | 35 +++++++++++++++++-- src/components/PointsDisplay/index.module.css | 8 +++++ src/pages/Home/index.js | 2 +- src/pages/Roadmap/index.js | 30 ---------------- 4 files changed, 41 insertions(+), 34 deletions(-) diff --git a/src/components/PointsDisplay/index.js b/src/components/PointsDisplay/index.js index 3341139..16a2cc8 100644 --- a/src/components/PointsDisplay/index.js +++ b/src/components/PointsDisplay/index.js @@ -2,7 +2,7 @@ import styles from "./index.module.css"; import classNames from "classnames/bind"; import React from "react"; import { useState, useEffect } from "react"; -import { getChildrenTasksArray } from "../../lib/services"; +import { getAgeGivenBirthday, formGetRequest } from "../../lib/utils"; import { CircularProgressbarWithChildren, buildStyles, @@ -11,13 +11,42 @@ import { const cx = classNames.bind(styles); export const PointsDisplay = React.forwardRef((props, ref) => { - const { childrenId } = props; + const { childId } = props; const [goal, setGoal] = useState(100); - const [points, setPoints] = useState(71); + const [points, setPoints] = useState(0); + const [childName, setChildName] = useState(""); + + useEffect(() => { + // get child's name and disabilities + const childUrl = "/children/" + childId; + fetch(process.env.REACT_APP_HOST_URL + childUrl) + .then((response) => response.json()) + .then((childrenData) => { + const childName = childrenData.firstName; + setChildName(childName); + const age = getAgeGivenBirthday(childrenData.birthDate); + const completedTasks = childrenData.completedTasks; + setPoints(completedTasks.length); + const params = { + disabilities: JSON.stringify(childrenData.disabilities), + age: JSON.stringify(age), + }; + + // get tasks based on children's attributes + const url = formGetRequest("/tasks/byAttributes/", params); + fetch(process.env.REACT_APP_HOST_URL + url) + .then((response) => response.json()) + .then((taskData) => { + setGoal(taskData.length); + }) + .catch((error) => console.log(error)); + }); + }, []); return (
+

{childName}

{goal - points}

 points away from your weekly goal diff --git a/src/components/PointsDisplay/index.module.css b/src/components/PointsDisplay/index.module.css index e4eeac3..f916330 100644 --- a/src/components/PointsDisplay/index.module.css +++ b/src/components/PointsDisplay/index.module.css @@ -5,6 +5,14 @@ position: relative; } +.name { + font-family: 'Poppins'; + font-weight: 800; + font-size: 3vw; + margin: auto; + color: #000000; +} + .points { font-family: 'Poppins'; font-weight: 800; diff --git a/src/pages/Home/index.js b/src/pages/Home/index.js index 1f1c6ce..ccb898e 100644 --- a/src/pages/Home/index.js +++ b/src/pages/Home/index.js @@ -35,7 +35,7 @@ export const Home = () => {

You're 

Cruising it!

- +
diff --git a/src/pages/Roadmap/index.js b/src/pages/Roadmap/index.js index 5e2cd15..e06075a 100644 --- a/src/pages/Roadmap/index.js +++ b/src/pages/Roadmap/index.js @@ -111,36 +111,6 @@ export const Roadmap = ({ toast }) => { .catch((error) => console.error(error)); }; -<<<<<<< HEAD -======= - const hpElements = hpList.flat().map((thing, index) => ( -

- {index + 1 + ". " + thing.title} -

- )); - const elseElements = elseList.flat().map((thing, index) => ( -

- {index + 1 + ". " + thing.title} -

- )); - - useEffect(() => { - setTimer( - setTimeout(() => { - localStorage.removeItem("jwtToken"); - localStorage.removeItem("userID"); - navigate("/login"); - }, TIMEOUT) - ); - }, []); - - useEffect(() => { - return () => { - clearTimeout(timer); - }; - }, [timer]); - ->>>>>>> 47ec3f1b3ab3887d0f72a5988ba3be465fd88b53 return (
Date: Fri, 14 Apr 2023 20:06:20 -0500 Subject: [PATCH 07/16] finished page slider --- package-lock.json | 44 ++++++++++++++++++++++---- package.json | 1 + src/components/PointsDisplay/index.js | 44 +++++++++++++++----------- src/components/Slider/index.js | 21 ++++++++++++ src/components/Slider/index.module.css | 0 src/pages/Home/index.js | 14 +++----- src/pages/Roadmap/index.js | 1 - testRequests.rest | 2 +- 8 files changed, 90 insertions(+), 37 deletions(-) create mode 100644 src/components/Slider/index.js create mode 100644 src/components/Slider/index.module.css diff --git a/package-lock.json b/package-lock.json index a24de85..cbcd9e4 100644 --- a/package-lock.json +++ b/package-lock.json @@ -20,6 +20,7 @@ "react-scripts": "4.0.3", "react-search-box": "^2.3.0", "react-select": "^5.7.0", + "react-slidy": "^4.3.3", "react-toastify": "^8.1.0" }, "devDependencies": { @@ -10664,6 +10665,11 @@ "node": ">= 0.4" } }, + "node_modules/intersection-observer": { + "version": "0.10.0", + "resolved": "https://registry.npmjs.org/intersection-observer/-/intersection-observer-0.10.0.tgz", + "integrity": "sha512-fn4bQ0Xq8FTej09YC/jqKZwtijpvARlRp6wxL5WTA6yPe2YWSJ5RJh7Nm79rK2qB0wr6iDQzH60XGq5V/7u8YQ==" + }, "node_modules/ip": { "version": "1.1.5", "resolved": "https://registry.npmjs.org/ip/-/ip-1.1.5.tgz", @@ -14253,9 +14259,9 @@ "integrity": "sha512-4hLB8Py4zZce5s4yd9XzopqwVv/yGNhV1Bl8NTmCq1763HeK2+EwVTv+leGeL13Dnh2wfbqowVPXCIO0z4taYw==" }, "node_modules/papaparse": { - "version": "5.3.2", - "resolved": "https://registry.npmjs.org/papaparse/-/papaparse-5.3.2.tgz", - "integrity": "sha512-6dNZu0Ki+gyV0eBsFKJhYr+MdQYAzFUGlBMNj3GNrmHxmz1lfRa24CjFObPXtjcetlOv5Ad299MhIK0znp3afw==" + "version": "5.4.1", + "resolved": "https://registry.npmjs.org/papaparse/-/papaparse-5.4.1.tgz", + "integrity": "sha512-HipMsgJkZu8br23pW15uvo6sib6wne/4woLZPlFf3rpDyMe9ywEXUsuD7+6K9PRkJlVT51j/sCOYDKGGS3ZJrw==" }, "node_modules/parallel-transform": { "version": "1.2.0", @@ -16581,6 +16587,19 @@ "react-dom": "^16.8.0 || ^17.0.0 || ^18.0.0" } }, + "node_modules/react-slidy": { + "version": "4.3.3", + "resolved": "https://registry.npmjs.org/react-slidy/-/react-slidy-4.3.3.tgz", + "integrity": "sha512-SWdHk+x5epue3Kg5YdpO0kPhjh+K4PbOSKvRNbt++KEhG87NbvY6kLmuGQ0CmhzoW26vVMMkT4Conjj0ylW8Tg==", + "dependencies": { + "intersection-observer": "0.10.0" + }, + "peerDependencies": { + "prop-types": "15", + "react": ">= 16.8.0", + "react-dom": ">= 16.8.0" + } + }, "node_modules/react-toastify": { "version": "8.2.0", "resolved": "https://registry.npmjs.org/react-toastify/-/react-toastify-8.2.0.tgz", @@ -29629,6 +29648,11 @@ "side-channel": "^1.0.4" } }, + "intersection-observer": { + "version": "0.10.0", + "resolved": "https://registry.npmjs.org/intersection-observer/-/intersection-observer-0.10.0.tgz", + "integrity": "sha512-fn4bQ0Xq8FTej09YC/jqKZwtijpvARlRp6wxL5WTA6yPe2YWSJ5RJh7Nm79rK2qB0wr6iDQzH60XGq5V/7u8YQ==" + }, "ip": { "version": "1.1.5", "resolved": "https://registry.npmjs.org/ip/-/ip-1.1.5.tgz", @@ -32348,9 +32372,9 @@ "integrity": "sha512-4hLB8Py4zZce5s4yd9XzopqwVv/yGNhV1Bl8NTmCq1763HeK2+EwVTv+leGeL13Dnh2wfbqowVPXCIO0z4taYw==" }, "papaparse": { - "version": "5.3.2", - "resolved": "https://registry.npmjs.org/papaparse/-/papaparse-5.3.2.tgz", - "integrity": "sha512-6dNZu0Ki+gyV0eBsFKJhYr+MdQYAzFUGlBMNj3GNrmHxmz1lfRa24CjFObPXtjcetlOv5Ad299MhIK0znp3afw==" + "version": "5.4.1", + "resolved": "https://registry.npmjs.org/papaparse/-/papaparse-5.4.1.tgz", + "integrity": "sha512-HipMsgJkZu8br23pW15uvo6sib6wne/4woLZPlFf3rpDyMe9ywEXUsuD7+6K9PRkJlVT51j/sCOYDKGGS3ZJrw==" }, "parallel-transform": { "version": "1.2.0", @@ -34225,6 +34249,14 @@ "use-isomorphic-layout-effect": "^1.1.2" } }, + "react-slidy": { + "version": "4.3.3", + "resolved": "https://registry.npmjs.org/react-slidy/-/react-slidy-4.3.3.tgz", + "integrity": "sha512-SWdHk+x5epue3Kg5YdpO0kPhjh+K4PbOSKvRNbt++KEhG87NbvY6kLmuGQ0CmhzoW26vVMMkT4Conjj0ylW8Tg==", + "requires": { + "intersection-observer": "0.10.0" + } + }, "react-toastify": { "version": "8.2.0", "resolved": "https://registry.npmjs.org/react-toastify/-/react-toastify-8.2.0.tgz", diff --git a/package.json b/package.json index 04e98de..8e42708 100644 --- a/package.json +++ b/package.json @@ -15,6 +15,7 @@ "react-scripts": "4.0.3", "react-search-box": "^2.3.0", "react-select": "^5.7.0", + "react-slidy": "^4.3.3", "react-toastify": "^8.1.0" }, "scripts": { diff --git a/src/components/PointsDisplay/index.js b/src/components/PointsDisplay/index.js index 16a2cc8..5e06cdb 100644 --- a/src/components/PointsDisplay/index.js +++ b/src/components/PointsDisplay/index.js @@ -11,35 +11,41 @@ import { const cx = classNames.bind(styles); export const PointsDisplay = React.forwardRef((props, ref) => { + // const { childName, points, goal } = props; const { childId } = props; - const [goal, setGoal] = useState(100); - const [points, setPoints] = useState(0); const [childName, setChildName] = useState(""); + const [points, setPoints] = useState(0); + const [goal, setGoal] = useState(0); useEffect(() => { // get child's name and disabilities const childUrl = "/children/" + childId; + console.log(childId); fetch(process.env.REACT_APP_HOST_URL + childUrl) .then((response) => response.json()) .then((childrenData) => { - const childName = childrenData.firstName; - setChildName(childName); - const age = getAgeGivenBirthday(childrenData.birthDate); - const completedTasks = childrenData.completedTasks; - setPoints(completedTasks.length); - const params = { - disabilities: JSON.stringify(childrenData.disabilities), - age: JSON.stringify(age), - }; + if (childrenData === undefined) { + console.log("No child data"); + } else { + const childName = childrenData.firstName; + setChildName(childName); + const age = getAgeGivenBirthday(childrenData.birthDate); + const completedTasks = childrenData.completedTasks; + setPoints(completedTasks.length); + const params = { + disabilities: JSON.stringify(childrenData.disabilities), + age: JSON.stringify(age), + }; - // get tasks based on children's attributes - const url = formGetRequest("/tasks/byAttributes/", params); - fetch(process.env.REACT_APP_HOST_URL + url) - .then((response) => response.json()) - .then((taskData) => { - setGoal(taskData.length); - }) - .catch((error) => console.log(error)); + // get tasks based on children's attributes + const url = formGetRequest("/tasks/byAttributes/", params); + fetch(process.env.REACT_APP_HOST_URL + url) + .then((response) => response.json()) + .then((taskData) => { + setGoal(taskData.length); + }) + .catch((error) => console.log(error)); + } }); }, []); diff --git a/src/components/Slider/index.js b/src/components/Slider/index.js new file mode 100644 index 0000000..5da4733 --- /dev/null +++ b/src/components/Slider/index.js @@ -0,0 +1,21 @@ +import React from "react"; +import styles from "./index.module.css"; +import classNames from "classnames/bind"; +import { PointsDisplay } from "../PointsDisplay"; +import ReactSlidy from "react-slidy"; +import "react-slidy/lib/styles.css"; + +const cx = classNames.bind(styles); + +// build a page slider component +export const Slider = (props) => { + const { childrenId } = props; + + return ( + + {childrenId.map((childId) => ( + + ))} + + ); +}; diff --git a/src/components/Slider/index.module.css b/src/components/Slider/index.module.css new file mode 100644 index 0000000..e69de29 diff --git a/src/pages/Home/index.js b/src/pages/Home/index.js index ccb898e..9f27a50 100644 --- a/src/pages/Home/index.js +++ b/src/pages/Home/index.js @@ -1,11 +1,11 @@ -import React, { useState, useEffect } from "react"; +import React, { useEffect, useState } from "react"; import classNames from "classnames/bind"; import styles from "./index.module.css"; import { NavBar } from "../NavBar"; import { useWindowSize } from "../../lib/hooks"; import { WINDOW_TYPE } from "../../lib/constants"; import { OnYourRadar } from "../../components/OnYourRadar"; -import { PointsDisplay } from "../../components/PointsDisplay"; +import { Slider } from "../../components/Slider"; import "react-circular-progressbar/dist/styles.css"; const cx = classNames.bind(styles); @@ -16,7 +16,7 @@ export const Home = () => { // TODO: use Cache to store the user const [lastName, setLastName] = useState("Adam's"); // TODO: cache - const childrenId = ["63e5c4936d51fdbbbedb5503"]; + const childrenId = ["63e5c4936d51fdbbbedb5503", "63e5c4296d51fdbbbedb5500"]; return (
{

You're 

Cruising it!

- +
); }; - -//issues: -//what happens when todo list becomes larger than the screen -//or family last name is too long -//fix navbar for computer screen (looks bad on screen anyways) -//spacing can be tweaked diff --git a/src/pages/Roadmap/index.js b/src/pages/Roadmap/index.js index e06075a..42448b0 100644 --- a/src/pages/Roadmap/index.js +++ b/src/pages/Roadmap/index.js @@ -4,7 +4,6 @@ import Papa from "papaparse"; import { useAuth } from "../../lib/AuthContext"; import styles from "./index.module.css"; import { ROUTES, PRIORITY_LEVEL, TIMEOUT } from "../../lib/constants"; -import { getChildrenTasksArray } from "../../lib/services"; import { ReactComponent as Calender } from "../../svg/roadmapCalender.svg"; import { ReactComponent as Box } from "../../svg/roadmapBox.svg"; import { useNavigate } from "react-router-dom"; diff --git a/testRequests.rest b/testRequests.rest index a17c335..d040340 100644 --- a/testRequests.rest +++ b/testRequests.rest @@ -23,7 +23,7 @@ Content-Type: application/json ### -GET http://localhost:3001/children/63e5c4936d51fdbbbedb5503 +GET http://localhost:3001/children/ Content-Type: application/json ### From 79a36bf55c0e36f1211cd12d67c5c6ede4fa1288 Mon Sep 17 00:00:00 2001 From: Xiaohan Liu Date: Sat, 15 Apr 2023 12:27:20 -0500 Subject: [PATCH 08/16] finished progress bar, refactored slider --- package-lock.json | 132 ++++++------------ package.json | 1 + src/components/PointsDisplay/index.js | 42 +----- src/components/PointsDisplay/index.module.css | 2 +- src/components/Slider/index.js | 13 +- src/lib/utils.js | 9 ++ src/pages/Home/index.js | 65 ++++++++- src/pages/Home/index.module.css | 5 +- src/pages/Roadmap/index.js | 3 +- testRequests.rest | 2 +- 10 files changed, 134 insertions(+), 140 deletions(-) diff --git a/package-lock.json b/package-lock.json index cbcd9e4..4573ade 100644 --- a/package-lock.json +++ b/package-lock.json @@ -8,6 +8,7 @@ "name": "react-auth-template", "version": "0.1.0", "dependencies": { + "@ramonak/react-progress-bar": "^5.0.3", "classnames": "^2.3.2", "env-cmd": "^10.1.0", "firebase": "^8.10.1", @@ -1752,11 +1753,11 @@ } }, "node_modules/@babel/runtime": { - "version": "7.16.0", - "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.16.0.tgz", - "integrity": "sha512-Nht8L0O8YCktmsDV6FqFue7vQLRx3Hb0B37lS5y0jDRqRxlBG4wIJHnf9/bgSE2UyipKFA01YtS+npRdTWBUyw==", + "version": "7.21.0", + "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.21.0.tgz", + "integrity": "sha512-xwII0//EObnq89Ji5AKYQaRYiW/nZ3llSv29d49IuxPhKbtJoLP+9QUUZ4nVragQVtaVGeZrpB+ZtG/Pdy/POw==", "dependencies": { - "regenerator-runtime": "^0.13.4" + "regenerator-runtime": "^0.13.11" }, "engines": { "node": ">=6.9.0" @@ -1889,17 +1890,6 @@ "@babel/core": "^7.0.0-0" } }, - "node_modules/@emotion/babel-plugin/node_modules/@babel/runtime": { - "version": "7.20.7", - "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.20.7.tgz", - "integrity": "sha512-UF0tvkUtxwAgZ5W/KrkHf0Rn0fdnLDU9ScxBrEVNUprE/MzirjK4MJUX1/BVDv00Sv8cljtukVK1aky++X1SjQ==", - "dependencies": { - "regenerator-runtime": "^0.13.11" - }, - "engines": { - "node": ">=6.9.0" - } - }, "node_modules/@emotion/babel-plugin/node_modules/babel-plugin-macros": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/babel-plugin-macros/-/babel-plugin-macros-3.1.0.tgz", @@ -1936,11 +1926,6 @@ "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/@emotion/babel-plugin/node_modules/regenerator-runtime": { - "version": "0.13.11", - "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.13.11.tgz", - "integrity": "sha512-kY1AZVr2Ra+t+piVaJ4gxaFaReZVH40AKNo7UCX6W+dEwBo/2oZJzqfuN1qLq1oL45o56cPaTXELwrTh8Fpggg==" - }, "node_modules/@emotion/babel-plugin/node_modules/resolve": { "version": "1.22.1", "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.1.tgz", @@ -2014,22 +1999,6 @@ } } }, - "node_modules/@emotion/react/node_modules/@babel/runtime": { - "version": "7.20.7", - "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.20.7.tgz", - "integrity": "sha512-UF0tvkUtxwAgZ5W/KrkHf0Rn0fdnLDU9ScxBrEVNUprE/MzirjK4MJUX1/BVDv00Sv8cljtukVK1aky++X1SjQ==", - "dependencies": { - "regenerator-runtime": "^0.13.11" - }, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@emotion/react/node_modules/regenerator-runtime": { - "version": "0.13.11", - "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.13.11.tgz", - "integrity": "sha512-kY1AZVr2Ra+t+piVaJ4gxaFaReZVH40AKNo7UCX6W+dEwBo/2oZJzqfuN1qLq1oL45o56cPaTXELwrTh8Fpggg==" - }, "node_modules/@emotion/serialize": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/@emotion/serialize/-/serialize-1.1.1.tgz", @@ -3339,6 +3308,15 @@ "resolved": "https://registry.npmjs.org/@protobufjs/utf8/-/utf8-1.1.0.tgz", "integrity": "sha512-Vvn3zZrhQZkkBE8LSuW3em98c0FwgO4nxzv6OdSxPKJIEKY2bGbHn+mhGIPerzI4twdxaP8/0+06HBpwf345Lw==" }, + "node_modules/@ramonak/react-progress-bar": { + "version": "5.0.3", + "resolved": "https://registry.npmjs.org/@ramonak/react-progress-bar/-/react-progress-bar-5.0.3.tgz", + "integrity": "sha512-VxXGKN74q94jYoeYuFNJm3xvWhVz9dy+alFZ8S4ZmTTr/05CCq9PjwthT8JB27UdAvn8pHvKBmemV8JU2cZi6A==", + "peerDependencies": { + "react": "^16.0.0 || ^17 || ^18", + "react-dom": "^16.0.0 || ^17 || ^18" + } + }, "node_modules/@remix-run/router": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/@remix-run/router/-/router-1.0.3.tgz", @@ -15922,13 +15900,13 @@ } }, "node_modules/prop-types": { - "version": "15.7.2", - "resolved": "https://registry.npmjs.org/prop-types/-/prop-types-15.7.2.tgz", - "integrity": "sha512-8QQikdH7//R2vurIJSutZ1smHYTcLpRWEOlHnzcWHmBYrOGUysKwSsrC89BCiFj3CbrfJ/nXFdJepOVrY1GCHQ==", + "version": "15.8.1", + "resolved": "https://registry.npmjs.org/prop-types/-/prop-types-15.8.1.tgz", + "integrity": "sha512-oj87CgZICdulUohogVAR7AjlC0327U4el4L6eAvOqCeudMDVU0NThNaV+b9Df4dXgSP1gXMTnPdhfe/2qDH5cg==", "dependencies": { "loose-envify": "^1.4.0", "object-assign": "^4.1.1", - "react-is": "^16.8.1" + "react-is": "^16.13.1" } }, "node_modules/protobufjs": { @@ -16737,9 +16715,9 @@ } }, "node_modules/regenerator-runtime": { - "version": "0.13.9", - "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.13.9.tgz", - "integrity": "sha512-p3VT+cOEgxFsRRA9X4lkI1E+k2/CtnKtU4gcxyaCUreilL/vqI6CdZ3wxVUx3UOUg+gnUOQQcRI7BmSI656MYA==" + "version": "0.13.11", + "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.13.11.tgz", + "integrity": "sha512-kY1AZVr2Ra+t+piVaJ4gxaFaReZVH40AKNo7UCX6W+dEwBo/2oZJzqfuN1qLq1oL45o56cPaTXELwrTh8Fpggg==" }, "node_modules/regenerator-transform": { "version": "0.14.5", @@ -19197,9 +19175,9 @@ } }, "node_modules/tslib": { - "version": "2.3.1", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.3.1.tgz", - "integrity": "sha512-77EbyPPpMz+FRFRuAFlWMtmgUWGe9UOG2Z25NqCwiIjRhOf5iKGuzSe5P2w1laq+FkRy4p+PCuVkJSGkzTEKVw==" + "version": "2.5.0", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.5.0.tgz", + "integrity": "sha512-336iVw3rtn2BUK7ORdIAHTyxHGRIHVReokCR3XjbckJMK7ms8FysBfhLR8IXnAgy7T0PTPNBWKiH514FOW/WSg==" }, "node_modules/tsutils": { "version": "3.21.0", @@ -22677,11 +22655,11 @@ } }, "@babel/runtime": { - "version": "7.16.0", - "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.16.0.tgz", - "integrity": "sha512-Nht8L0O8YCktmsDV6FqFue7vQLRx3Hb0B37lS5y0jDRqRxlBG4wIJHnf9/bgSE2UyipKFA01YtS+npRdTWBUyw==", + "version": "7.21.0", + "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.21.0.tgz", + "integrity": "sha512-xwII0//EObnq89Ji5AKYQaRYiW/nZ3llSv29d49IuxPhKbtJoLP+9QUUZ4nVragQVtaVGeZrpB+ZtG/Pdy/POw==", "requires": { - "regenerator-runtime": "^0.13.4" + "regenerator-runtime": "^0.13.11" } }, "@babel/runtime-corejs3": { @@ -22781,14 +22759,6 @@ "@babel/helper-plugin-utils": "^7.18.6" } }, - "@babel/runtime": { - "version": "7.20.7", - "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.20.7.tgz", - "integrity": "sha512-UF0tvkUtxwAgZ5W/KrkHf0Rn0fdnLDU9ScxBrEVNUprE/MzirjK4MJUX1/BVDv00Sv8cljtukVK1aky++X1SjQ==", - "requires": { - "regenerator-runtime": "^0.13.11" - } - }, "babel-plugin-macros": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/babel-plugin-macros/-/babel-plugin-macros-3.1.0.tgz", @@ -22812,11 +22782,6 @@ "has": "^1.0.3" } }, - "regenerator-runtime": { - "version": "0.13.11", - "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.13.11.tgz", - "integrity": "sha512-kY1AZVr2Ra+t+piVaJ4gxaFaReZVH40AKNo7UCX6W+dEwBo/2oZJzqfuN1qLq1oL45o56cPaTXELwrTh8Fpggg==" - }, "resolve": { "version": "1.22.1", "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.1.tgz", @@ -22872,21 +22837,6 @@ "@emotion/utils": "^1.2.0", "@emotion/weak-memoize": "^0.3.0", "hoist-non-react-statics": "^3.3.1" - }, - "dependencies": { - "@babel/runtime": { - "version": "7.20.7", - "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.20.7.tgz", - "integrity": "sha512-UF0tvkUtxwAgZ5W/KrkHf0Rn0fdnLDU9ScxBrEVNUprE/MzirjK4MJUX1/BVDv00Sv8cljtukVK1aky++X1SjQ==", - "requires": { - "regenerator-runtime": "^0.13.11" - } - }, - "regenerator-runtime": { - "version": "0.13.11", - "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.13.11.tgz", - "integrity": "sha512-kY1AZVr2Ra+t+piVaJ4gxaFaReZVH40AKNo7UCX6W+dEwBo/2oZJzqfuN1qLq1oL45o56cPaTXELwrTh8Fpggg==" - } } }, "@emotion/serialize": { @@ -23920,6 +23870,12 @@ "resolved": "https://registry.npmjs.org/@protobufjs/utf8/-/utf8-1.1.0.tgz", "integrity": "sha512-Vvn3zZrhQZkkBE8LSuW3em98c0FwgO4nxzv6OdSxPKJIEKY2bGbHn+mhGIPerzI4twdxaP8/0+06HBpwf345Lw==" }, + "@ramonak/react-progress-bar": { + "version": "5.0.3", + "resolved": "https://registry.npmjs.org/@ramonak/react-progress-bar/-/react-progress-bar-5.0.3.tgz", + "integrity": "sha512-VxXGKN74q94jYoeYuFNJm3xvWhVz9dy+alFZ8S4ZmTTr/05CCq9PjwthT8JB27UdAvn8pHvKBmemV8JU2cZi6A==", + "requires": {} + }, "@remix-run/router": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/@remix-run/router/-/router-1.0.3.tgz", @@ -33722,13 +33678,13 @@ } }, "prop-types": { - "version": "15.7.2", - "resolved": "https://registry.npmjs.org/prop-types/-/prop-types-15.7.2.tgz", - "integrity": "sha512-8QQikdH7//R2vurIJSutZ1smHYTcLpRWEOlHnzcWHmBYrOGUysKwSsrC89BCiFj3CbrfJ/nXFdJepOVrY1GCHQ==", + "version": "15.8.1", + "resolved": "https://registry.npmjs.org/prop-types/-/prop-types-15.8.1.tgz", + "integrity": "sha512-oj87CgZICdulUohogVAR7AjlC0327U4el4L6eAvOqCeudMDVU0NThNaV+b9Df4dXgSP1gXMTnPdhfe/2qDH5cg==", "requires": { "loose-envify": "^1.4.0", "object-assign": "^4.1.1", - "react-is": "^16.8.1" + "react-is": "^16.13.1" } }, "protobufjs": { @@ -34368,9 +34324,9 @@ } }, "regenerator-runtime": { - "version": "0.13.9", - "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.13.9.tgz", - "integrity": "sha512-p3VT+cOEgxFsRRA9X4lkI1E+k2/CtnKtU4gcxyaCUreilL/vqI6CdZ3wxVUx3UOUg+gnUOQQcRI7BmSI656MYA==" + "version": "0.13.11", + "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.13.11.tgz", + "integrity": "sha512-kY1AZVr2Ra+t+piVaJ4gxaFaReZVH40AKNo7UCX6W+dEwBo/2oZJzqfuN1qLq1oL45o56cPaTXELwrTh8Fpggg==" }, "regenerator-transform": { "version": "0.14.5", @@ -36297,9 +36253,9 @@ } }, "tslib": { - "version": "2.3.1", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.3.1.tgz", - "integrity": "sha512-77EbyPPpMz+FRFRuAFlWMtmgUWGe9UOG2Z25NqCwiIjRhOf5iKGuzSe5P2w1laq+FkRy4p+PCuVkJSGkzTEKVw==" + "version": "2.5.0", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.5.0.tgz", + "integrity": "sha512-336iVw3rtn2BUK7ORdIAHTyxHGRIHVReokCR3XjbckJMK7ms8FysBfhLR8IXnAgy7T0PTPNBWKiH514FOW/WSg==" }, "tsutils": { "version": "3.21.0", diff --git a/package.json b/package.json index 8e42708..7732700 100644 --- a/package.json +++ b/package.json @@ -3,6 +3,7 @@ "version": "0.1.0", "private": true, "dependencies": { + "@ramonak/react-progress-bar": "^5.0.3", "classnames": "^2.3.2", "env-cmd": "^10.1.0", "firebase": "^8.10.1", diff --git a/src/components/PointsDisplay/index.js b/src/components/PointsDisplay/index.js index 5e06cdb..968bcbe 100644 --- a/src/components/PointsDisplay/index.js +++ b/src/components/PointsDisplay/index.js @@ -1,8 +1,6 @@ import styles from "./index.module.css"; import classNames from "classnames/bind"; import React from "react"; -import { useState, useEffect } from "react"; -import { getAgeGivenBirthday, formGetRequest } from "../../lib/utils"; import { CircularProgressbarWithChildren, buildStyles, @@ -11,43 +9,7 @@ import { const cx = classNames.bind(styles); export const PointsDisplay = React.forwardRef((props, ref) => { - // const { childName, points, goal } = props; - const { childId } = props; - const [childName, setChildName] = useState(""); - const [points, setPoints] = useState(0); - const [goal, setGoal] = useState(0); - - useEffect(() => { - // get child's name and disabilities - const childUrl = "/children/" + childId; - console.log(childId); - fetch(process.env.REACT_APP_HOST_URL + childUrl) - .then((response) => response.json()) - .then((childrenData) => { - if (childrenData === undefined) { - console.log("No child data"); - } else { - const childName = childrenData.firstName; - setChildName(childName); - const age = getAgeGivenBirthday(childrenData.birthDate); - const completedTasks = childrenData.completedTasks; - setPoints(completedTasks.length); - const params = { - disabilities: JSON.stringify(childrenData.disabilities), - age: JSON.stringify(age), - }; - - // get tasks based on children's attributes - const url = formGetRequest("/tasks/byAttributes/", params); - fetch(process.env.REACT_APP_HOST_URL + url) - .then((response) => response.json()) - .then((taskData) => { - setGoal(taskData.length); - }) - .catch((error) => console.log(error)); - } - }); - }, []); + const { childName, points, goal } = props; return (
@@ -55,7 +17,7 @@ export const PointsDisplay = React.forwardRef((props, ref) => {

{childName}

{goal - points}

-  points away from your weekly goal +  points away from weekly goal

diff --git a/src/components/PointsDisplay/index.module.css b/src/components/PointsDisplay/index.module.css index f916330..796f508 100644 --- a/src/components/PointsDisplay/index.module.css +++ b/src/components/PointsDisplay/index.module.css @@ -8,7 +8,7 @@ .name { font-family: 'Poppins'; font-weight: 800; - font-size: 3vw; + font-size: 4.5vw; margin: auto; color: #000000; } diff --git a/src/components/Slider/index.js b/src/components/Slider/index.js index 5da4733..d231a18 100644 --- a/src/components/Slider/index.js +++ b/src/components/Slider/index.js @@ -4,17 +4,24 @@ import classNames from "classnames/bind"; import { PointsDisplay } from "../PointsDisplay"; import ReactSlidy from "react-slidy"; import "react-slidy/lib/styles.css"; +import { getRandomColor } from "../../lib/utils"; const cx = classNames.bind(styles); // build a page slider component export const Slider = (props) => { - const { childrenId } = props; + const { childrenStats } = props; return ( - {childrenId.map((childId) => ( - + {childrenStats.map((childStats) => ( + ))} ); diff --git a/src/lib/utils.js b/src/lib/utils.js index 850c36a..36793dd 100644 --- a/src/lib/utils.js +++ b/src/lib/utils.js @@ -1,3 +1,12 @@ +import { COLORS_ARR } from "./constants"; + +/** + * @return a random color from the array + */ +export const getRandomColor = () => { + return COLORS_ARR[Math.floor(Math.random() * COLORS_ARR.length)]; +}; + /** * @param {String} string the string to be assessed * @return {Object} a json object containing the website links and text descriptions diff --git a/src/pages/Home/index.js b/src/pages/Home/index.js index 9f27a50..a3db878 100644 --- a/src/pages/Home/index.js +++ b/src/pages/Home/index.js @@ -6,7 +6,8 @@ import { useWindowSize } from "../../lib/hooks"; import { WINDOW_TYPE } from "../../lib/constants"; import { OnYourRadar } from "../../components/OnYourRadar"; import { Slider } from "../../components/Slider"; -import "react-circular-progressbar/dist/styles.css"; +import ProgressBar from "@ramonak/react-progress-bar"; +import { formGetRequest, getAgeGivenBirthday } from "../../lib/utils"; const cx = classNames.bind(styles); @@ -15,9 +16,60 @@ export const Home = () => { const isMobile = type === WINDOW_TYPE.MOBILE; // TODO: use Cache to store the user const [lastName, setLastName] = useState("Adam's"); + const [totalPoints, setTotalPoints] = useState(0); + const [totalGoal, setTotalGoal] = useState(0); + const [childrenStats, setChildrenStats] = useState([]); // TODO: cache const childrenId = ["63e5c4936d51fdbbbedb5503", "63e5c4296d51fdbbbedb5500"]; + const getChildrenPointsStats = async () => { + let totalPoints = 0; + let totalGoal = 0; + let childrenStats = []; + const childPromises = childrenId.map(async (childId) => { + // get child's name and disabilities + const childUrl = "/children/" + childId; + const response = await fetch(process.env.REACT_APP_HOST_URL + childUrl); + const childData = await response.json(); + const childName = childData.firstName; + const age = getAgeGivenBirthday(childData.birthDate); + totalPoints += childData.completedTasks.length; + const params = { + disabilities: JSON.stringify(childData.disabilities), + age: JSON.stringify(age), + }; + + // get tasks based on children's attributes + const url = formGetRequest("/tasks/byAttributes/", params); + const taskResponse = await fetch(process.env.REACT_APP_HOST_URL + url); + const taskData = await taskResponse.json(); + totalGoal += taskData.length; + const childStats = { + childId, + childName, + points: childData.completedTasks.length, + goal: taskData.length, + }; + childrenStats.push(childStats); + }); + + await Promise.all(childPromises); // wait for all child promises to complete + + return { totalPoints, totalGoal, childrenStats }; + }; + + useEffect(async () => { + const { totalPoints, totalGoal, childrenStats } = + await getChildrenPointsStats(); + setTotalPoints(totalPoints); + setTotalGoal(totalGoal); + setChildrenStats(childrenStats); + }, []); + + if (childrenStats.length !== childrenId.length) { + return
Loading...
; + } + return (
{

You're 

Cruising it!

- + +
diff --git a/src/pages/Home/index.module.css b/src/pages/Home/index.module.css index 3a86360..bb496cc 100644 --- a/src/pages/Home/index.module.css +++ b/src/pages/Home/index.module.css @@ -61,7 +61,4 @@ color: #0198BA; font-size: 3vw; font-weight: 400; -} - -/* need to fix font later */ -/*Not set to percentage*/ \ No newline at end of file +} \ No newline at end of file diff --git a/src/pages/Roadmap/index.js b/src/pages/Roadmap/index.js index 42448b0..e53bae8 100644 --- a/src/pages/Roadmap/index.js +++ b/src/pages/Roadmap/index.js @@ -96,7 +96,8 @@ export const Roadmap = ({ toast }) => { }; const onExport = async () => { - fetch("http://localhost:3001/users/exportCSV") + const exportUrl = "/users/exportCSV"; + fetch(process.env.REACT_APP_HOST_URL + exportUrl) .then((response) => response.arrayBuffer()) .then((arrayBuffer) => { const blob = new Blob([arrayBuffer], { type: "text/csv" }); diff --git a/testRequests.rest b/testRequests.rest index d040340..5dabcb4 100644 --- a/testRequests.rest +++ b/testRequests.rest @@ -23,7 +23,7 @@ Content-Type: application/json ### -GET http://localhost:3001/children/ +GET http://localhost:3001/children/63e5c4296d51fdbbbedb5500 Content-Type: application/json ### From ebac2f9ab763f1972f11d8d88a2f300480117d2a Mon Sep 17 00:00:00 2001 From: Xiaohan Liu Date: Sat, 15 Apr 2023 12:29:42 -0500 Subject: [PATCH 09/16] added loading to on your radar --- src/components/OnYourRadar/index.js | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/components/OnYourRadar/index.js b/src/components/OnYourRadar/index.js index 33d8073..e54c9b7 100644 --- a/src/components/OnYourRadar/index.js +++ b/src/components/OnYourRadar/index.js @@ -27,6 +27,10 @@ export const OnYourRadar = React.forwardRef((props, ref) => {

)); + if (hpElements.length === 0 || elseElements.length === 0) { + return
Loading...
; + } + return (

On Your Radar

From 34de672a72b6639943e2465d3efa95768a818380 Mon Sep 17 00:00:00 2001 From: Xiaohan Liu Date: Sat, 15 Apr 2023 15:00:03 -0500 Subject: [PATCH 10/16] added web version home page --- src/components/OnYourRadar/index.js | 66 ++++++++-- src/components/OnYourRadar/index.module.css | 117 +++++++++++++----- src/components/PointsDisplay/index.js | 46 +++++-- src/components/PointsDisplay/index.module.css | 44 ++++++- src/components/Slider/index.js | 3 +- src/pages/Home/index.js | 49 ++++++-- src/pages/Home/index.module.css | 20 ++- 7 files changed, 284 insertions(+), 61 deletions(-) diff --git a/src/components/OnYourRadar/index.js b/src/components/OnYourRadar/index.js index e54c9b7..e18b609 100644 --- a/src/components/OnYourRadar/index.js +++ b/src/components/OnYourRadar/index.js @@ -7,7 +7,7 @@ import { getChildrenTasksArray } from "../../lib/services"; const cx = classNames.bind(styles); export const OnYourRadar = React.forwardRef((props, ref) => { - const { childrenId } = props; + const { childrenId, isMobile } = props; const [hpList, sethpList] = useState([]); const [elseList, setElseList] = useState([]); @@ -32,12 +32,64 @@ export const OnYourRadar = React.forwardRef((props, ref) => { } return ( -
-

On Your Radar

-

High Priority

-

{hpElements}

-

All Tasks

-

{elseElements}

+
+

+ On Your Radar +

+
+
+

+ High Priority +

+

+ {hpElements} +

+
+
+

+ All Tasks +

+

+ {elseElements} +

+
+
); }); diff --git a/src/components/OnYourRadar/index.module.css b/src/components/OnYourRadar/index.module.css index 7cc44d9..1d7af08 100644 --- a/src/components/OnYourRadar/index.module.css +++ b/src/components/OnYourRadar/index.module.css @@ -1,37 +1,86 @@ +.todo_div.mobile { + border: 6px #0198ba; + border-style: solid; + border-radius: 50px; + margin-top: 10vw; + margin-left: 2vw; + margin-right: 2vw; + padding-left: 3vw; + padding-bottom: 10vw; +} + .todo_div { - border: 6px #0198ba; - border-style: solid; - border-radius: 50px; - margin-top: 10vw; - margin-left: 2vw; - margin-right: 2vw; - padding-left: 3vw; - padding-bottom: 10vw; - } - - .radar { - font-family: "Poppins"; - font-weight: 900; - color: black; - font-size: 7vw; - margin-top: 3vw; - } - - .priority { - font-family: "Poppins"; - font-weight: bolder; - color: #8b5674; - font-size: 5vw; - margin-top: 6vw; - } + border: 6px #0198ba; + border-style: solid; + border-radius: 50px; + margin-top: 5vw; + margin-left: 2vw; + margin-right: 2vw; + padding-left: 3vw; + padding-bottom: 10vw; +} + +.priorityParent{ + display: flex; + justify-content: space-between; +} + +.priorityParent.mobile{ + display: block; +} + +.priorityBlock{ + flex: 1; + display: inline-block; +} + +.priorityBlock.mobile{ + display: block; +} + +.radar.mobile { + font-family: "Poppins"; + font-weight: 900; + color: black; + font-size: 3vw; + margin-top: 3vw; +} - .priority.else { - color: #e3d150; - } - - .list { - font-family: 'Poppins'; - color: black; - font-weight: 600; - font-size: 3vw; +.radar { + font-family: "Poppins"; + font-weight: 900; + color: black; + font-size: 3vw; +} + +.priority.mobile { + font-family: "Poppins"; + font-weight: bolder; + color: #8b5674; + font-size: 3vw; +} + +.priority { + font-family: "Poppins"; + font-weight: bolder; + color: #8b5674; + font-size: 3vw; +} + +.priority.else { + color: #e3d150; +} + +.list { + font-family: 'Poppins'; + color: black; + font-weight: 600; + font-size: 3vw; +} + +.list.mobile { + font-family: 'Poppins'; + color: black; + font-weight: 600; + font-size: 6vw; } \ No newline at end of file diff --git a/src/components/PointsDisplay/index.js b/src/components/PointsDisplay/index.js index 968bcbe..3fdd6c3 100644 --- a/src/components/PointsDisplay/index.js +++ b/src/components/PointsDisplay/index.js @@ -9,18 +9,38 @@ import { const cx = classNames.bind(styles); export const PointsDisplay = React.forwardRef((props, ref) => { - const { childName, points, goal } = props; + const { childName, points, goal, isMobile } = props; return (
-

{childName}

-

{goal - points}

-

+

+ {childName} +

+

+ {goal - points} +

+

 points away from weekly goal

-
+
{ trailColor: "#F9F6DC", })} > -
{points}
-
Points
+
+ {points} +
+
+ Points +
diff --git a/src/components/PointsDisplay/index.module.css b/src/components/PointsDisplay/index.module.css index 796f508..677a468 100644 --- a/src/components/PointsDisplay/index.module.css +++ b/src/components/PointsDisplay/index.module.css @@ -1,3 +1,7 @@ +.pointsBlock { + margin-top: 4vw +} + .text_div { margin-left: auto; margin-right: auto; @@ -5,15 +9,24 @@ position: relative; } +.name.mobile { + font-family: 'Poppins'; + font-weight: 800; + font-size: 5vw; + margin: 1vh; + color: #000000; +} + .name { font-family: 'Poppins'; font-weight: 800; - font-size: 4.5vw; + font-size: 3vw; margin: auto; color: #000000; } -.points { + +.points.mobile { font-family: 'Poppins'; font-weight: 800; font-size: 4.2vw; @@ -22,12 +35,30 @@ color: #000000; } +.points { + font-family: 'Poppins'; + font-weight: 800; + font-size: 2.7vw; + margin: auto; + display: inline-block; + color: #000000; +} + .points.text { font-weight: 600; color: #818181; } .progress_circle { + width: 30vw; + height: 30vw; + margin-top: 4vw; + margin-bottom: 2vw; + margin-left: auto; + margin-right: auto; +} + +.progress_circle.mobile { width: 40vw; height: 40vw; margin-top: 5vw; @@ -36,9 +67,16 @@ margin-right: auto; } -.progress_circle_text { +.progress_circle_text.mobile { font-family: 'Poppins'; font-weight: 900; color: black; font-size: 6vw; +} + +.progress_circle_text { + font-family: 'Poppins'; + font-weight: 900; + color: black; + font-size: 3vw; } \ No newline at end of file diff --git a/src/components/Slider/index.js b/src/components/Slider/index.js index d231a18..48bf209 100644 --- a/src/components/Slider/index.js +++ b/src/components/Slider/index.js @@ -10,7 +10,7 @@ const cx = classNames.bind(styles); // build a page slider component export const Slider = (props) => { - const { childrenStats } = props; + const { childrenStats, isMobile } = props; return ( @@ -21,6 +21,7 @@ export const Slider = (props) => { childName={childStats.childName} points={childStats.points} goal={childStats.goal} + isMobile={isMobile} /> ))} diff --git a/src/pages/Home/index.js b/src/pages/Home/index.js index a3db878..e6661d7 100644 --- a/src/pages/Home/index.js +++ b/src/pages/Home/index.js @@ -20,7 +20,12 @@ export const Home = () => { const [totalGoal, setTotalGoal] = useState(0); const [childrenStats, setChildrenStats] = useState([]); // TODO: cache - const childrenId = ["63e5c4936d51fdbbbedb5503", "63e5c4296d51fdbbbedb5500"]; + const childrenId = [ + "63e5c4936d51fdbbbedb5503", + "63e5c4296d51fdbbbedb5500", + "63e5c4176d51fdbbbedb54fd", + "63e5c40a6d51fdbbbedb54fa", + ]; const getChildrenPointsStats = async () => { let totalPoints = 0; @@ -79,13 +84,41 @@ export const Home = () => { [styles.mobile]: isMobile, })} > -
-

Welcome 

-

{lastName} Family!

+
+

+ Welcome  +

+

+ {lastName} Family! +

-

You're 

-

Cruising it!

+

+ You're  +

+

+ Cruising it! +

{ isLabelVisible={false} animateOnRender={true} /> - - + +
diff --git a/src/pages/Home/index.module.css b/src/pages/Home/index.module.css index bb496cc..cd5e536 100644 --- a/src/pages/Home/index.module.css +++ b/src/pages/Home/index.module.css @@ -22,6 +22,15 @@ margin-top: 3vw; } .welcome { + font-family: 'Poppins'; + font-style: normal; + font-size: 4vw; + margin: auto; + display: inline-block; + color: #A8A8A8; +} + +.welcome.mobile { font-family: 'Poppins'; font-style: normal; font-size: 7vw; @@ -38,7 +47,16 @@ .cruising { font-family: 'Poppins'; font-style: normal; - font-size: 5vw; + font-size: 3vw; + margin: auto; + display: inline-block; + color: #A8A8A8; +} + +.cruising.mobile { + font-family: 'Poppins'; + font-style: normal; + font-size: 6vw; margin: auto; display: inline-block; color: #A8A8A8; From 0efcce50353c3262cf099f82623a9403bd5ba87d Mon Sep 17 00:00:00 2001 From: Xiaohan Liu Date: Sat, 15 Apr 2023 18:40:12 -0500 Subject: [PATCH 11/16] added web version to home and roadmap --- src/components/AllTasksSection/index.js | 11 ++- .../AllTasksSection/index.module.css | 11 ++- src/components/AuthButton/index.module.css | 14 ++-- src/components/BackArrow/index.js | 2 +- src/components/BackArrow/index.module.css | 2 +- src/components/CheckBox/index.js | 9 +-- src/components/CheckBox/index.module.css | 13 +++- src/components/TaskListItem/index.js | 21 ++++-- src/components/TaskListItem/index.module.css | 25 +++++-- src/components/UpcomingComponent/index.js | 2 + .../UpcomingComponent/index.module.css | 15 +--- src/lib/hooks.js | 5 ++ src/lib/icons.js | 40 +++++----- src/pages/AllTasks/index.js | 26 ++++--- src/pages/Home/index.module.css | 7 +- src/pages/HomeLayout/index.js | 2 +- src/pages/HomeLayout/index.module.css | 48 ++++++------ src/pages/NavBar/index.js | 50 ++++++++++--- src/pages/NavBar/index.module.css | 31 ++++++-- src/pages/Roadmap/index.js | 74 ++++++++++++++++--- src/pages/Roadmap/index.module.css | 25 +++++-- testRequests.rest | 2 +- 22 files changed, 293 insertions(+), 142 deletions(-) diff --git a/src/components/AllTasksSection/index.js b/src/components/AllTasksSection/index.js index 1777eb6..759cbcd 100644 --- a/src/components/AllTasksSection/index.js +++ b/src/components/AllTasksSection/index.js @@ -8,7 +8,7 @@ import { COLORS_ARR } from "../../lib/constants"; const cx = classNames.bind(styles); export const AllTasksSection = React.forwardRef((props, ref) => { - const { taskList } = props; + const { taskList, isMobile } = props; const [isExpanded, setIsExpanded] = useState(false); const [color, setColor] = useState("#0198BA26"); @@ -28,7 +28,12 @@ export const AllTasksSection = React.forwardRef((props, ref) => { backgroundColor: color, }} > -

+

{taskList[0]?.childName}

@@ -38,10 +43,10 @@ export const AllTasksSection = React.forwardRef((props, ref) => { taskName={item.title} dueAt={item.timePeriod} taskId={item._id} - childName={item.childName} childId={item.childId} completed={item.completed} key={index} + isMobile={isMobile} /> ))}
diff --git a/src/components/AllTasksSection/index.module.css b/src/components/AllTasksSection/index.module.css index 1c58e6a..859cf69 100644 --- a/src/components/AllTasksSection/index.module.css +++ b/src/components/AllTasksSection/index.module.css @@ -9,13 +9,22 @@ } .childName { + font-family: "Poppins"; + font-weight:400; + font-size: 2vw; + margin: 0; + margin-left: 6vh; +} + +.childName.mobile { font-family: "Poppins"; font-weight:400; font-size: 5vw; margin: 0; - margin-left: 1vh; + margin-left: 6vh; } + .tasksSection { margin-top: 3vw; margin-bottom: 3vw; diff --git a/src/components/AuthButton/index.module.css b/src/components/AuthButton/index.module.css index 93030ab..58aaa5b 100644 --- a/src/components/AuthButton/index.module.css +++ b/src/components/AuthButton/index.module.css @@ -2,22 +2,23 @@ @value font from "../../index.module.css"; .button { - width: 100%; - height: 55px; + width: 50%; + height: 5vh; background-color: #0198BA; color: white; font-family: "Poppins"; - font-size: 20px; + font-size: 2vw; display: flex; justify-content: center; align-items: center; border-radius: 5px; cursor: pointer; + margin: auto; } .button.mobile { - width: 100%; - min-height: 7vh; + width: 80%; + min-height: 5vh; background-color: #0198BA; color: white; font-family: "Poppins"; @@ -25,6 +26,7 @@ display: flex; justify-content: center; align-items: center; - border-radius: 20px; + border-radius: 2vh; cursor: pointer; + margin: 4vh; } \ No newline at end of file diff --git a/src/components/BackArrow/index.js b/src/components/BackArrow/index.js index b1c9920..fb5f270 100644 --- a/src/components/BackArrow/index.js +++ b/src/components/BackArrow/index.js @@ -6,7 +6,7 @@ import backArrow from "../../images/Vector.png"; const cx = classNames.bind(styles); -export const BackArrow = ({ showBackArrow = true }) => { +export const BackArrow = ({ showBackArrow = true, isMobile }) => { const navigate = useNavigate(); const goBack = () => { navigate(-1); diff --git a/src/components/BackArrow/index.module.css b/src/components/BackArrow/index.module.css index b9bc152..443e57e 100644 --- a/src/components/BackArrow/index.module.css +++ b/src/components/BackArrow/index.module.css @@ -1,7 +1,7 @@ .backArrow { display: flex; justify-content: center; - width: 5%; + width: 2%; height: auto; margin-top: 4vh; margin-left: 5%; diff --git a/src/components/CheckBox/index.js b/src/components/CheckBox/index.js index 7351eaa..dd81649 100644 --- a/src/components/CheckBox/index.js +++ b/src/components/CheckBox/index.js @@ -7,14 +7,13 @@ const cx = classNames.bind(styles); // The caption of each home page export const CheckBox = (props) => { - const { value, onChange } = props; - - const { type } = useWindowSize(); - const isMobile = type === WINDOW_TYPE.MOBILE; + const { value, onChange, isMobile } = props; return ( { - const { taskName, dueAt, taskId, childName, childId, completed } = props; + const { taskName, dueAt, taskId, childId, completed, isMobile } = props; const navigate = useNavigate(); const [checked, setChecked] = useState(completed); @@ -29,11 +29,22 @@ export const TaskListItem = React.forwardRef((props, ref) => { }) } > -

{taskName}

-

{dueAt}

-

{childName}

+

+ {taskName} +

+

+ {dueAt} +

- +
); }); diff --git a/src/components/TaskListItem/index.module.css b/src/components/TaskListItem/index.module.css index 7d6b8d9..384bc15 100644 --- a/src/components/TaskListItem/index.module.css +++ b/src/components/TaskListItem/index.module.css @@ -1,15 +1,28 @@ @import url("https://fonts.googleapis.com/css?family=Poppins"); .tasks_div { + border-bottom: 1px solid black; + padding: 2vw; + display: flex; + justify-content: flex-end; + } + +.tasks_div.mobile { border-bottom: 3px solid black; - /* margin-left: 2vw; - margin-right: 2vw; */ padding: 4vw; display: flex; justify-content: flex-end; } .taskName { + font-family: "Poppins"; + font-style: normal; + font-size: 2vw; + font-weight: 500; + margin: 0; +} + +.taskName.mobile { font-family: "Poppins"; font-style: normal; font-size: 5vw; @@ -17,7 +30,7 @@ margin: 0; } -.taskDate { +.taskDate.mobile { font-family: "Poppins"; font-weight:400; font-size: 4vw; @@ -25,12 +38,10 @@ margin: 0; } -.childName { +.taskDate { font-family: "Poppins"; font-weight:400; - font-size: 3vw; + font-size: 1.5vw; color: #8B5674; margin: 0; - margin-right: auto; - float: right; } \ No newline at end of file diff --git a/src/components/UpcomingComponent/index.js b/src/components/UpcomingComponent/index.js index 128bcf6..244bfc9 100644 --- a/src/components/UpcomingComponent/index.js +++ b/src/components/UpcomingComponent/index.js @@ -41,6 +41,8 @@ export const UpcomingComponent = (props) => { className={cx(styles.upcomingWrapper)} style={{ backgroundColor: color, + padding: "4vh", + margin: "4vh", }} >
{ */ export const useBackArrow = () => { const { pathname } = useLocation(); + const { width, type } = useWindowSize(); + const isMobile = type === WINDOW_TYPE.MOBILE; + if (!isMobile) { + return { showBackArrow: false }; + } switch (pathname) { case ROUTES.LOGIN: return { showBackArrow: false }; diff --git a/src/lib/icons.js b/src/lib/icons.js index 48d7f57..f25054b 100644 --- a/src/lib/icons.js +++ b/src/lib/icons.js @@ -1,17 +1,13 @@ -import { useWindowSize } from "./hooks"; - export const HomeIcon = (props) => { - const color = props.filled ? "#0198BA" : "#CCCCCC"; - const textColor = props.filled ? "black" : "#CCCCCC"; - const { height } = useWindowSize(); + const { isMobile, filled } = props; + const color = filled ? "#0198BA" : "#CCCCCC"; + const textColor = filled ? "black" : "#CCCCCC"; return ( { }; export const RoadmapIcon = (props) => { - const color = props.filled ? "#0198BA" : "#CCCCCC"; - const textColor = props.filled ? "black" : "#CCCCCC"; - const { height } = useWindowSize(); + const { isMobile, filled } = props; + const color = filled ? "#0198BA" : "#CCCCCC"; + const textColor = filled ? "black" : "#CCCCCC"; return ( { }; export const CommunityIcon = (props) => { - const color = props.filled ? "#0198BA" : "#CCCCCC"; - const textColor = props.filled ? "black" : "#CCCCCC"; - const { height } = useWindowSize(); + const { isMobile, filled } = props; + const color = filled ? "#0198BA" : "#CCCCCC"; + const textColor = filled ? "black" : "#CCCCCC"; return ( { + const { width, type } = useWindowSize(); + const isMobile = type === WINDOW_TYPE.MOBILE; + const [allTaskArray, setAllTaskArray] = useState([]); const [searchQuery, setSearchQuery] = useState(""); //TODO: get information using cache @@ -55,27 +59,29 @@ export const AllTasks = () => { overflow: "scroll", overscrollBehavior: "none", height: "92vh", - }}> + }} + >
+ }} + > {filteredSections.map((childTasks, childTasksIndex) => ( - + ))}
); }; - -//first two headers may go on separate lines -//check this for other code -//add search bar implementation** diff --git a/src/pages/Home/index.module.css b/src/pages/Home/index.module.css index cd5e536..4b58113 100644 --- a/src/pages/Home/index.module.css +++ b/src/pages/Home/index.module.css @@ -3,12 +3,9 @@ .container { width: 100%; box-sizing: border-box; - padding: 70px 40px 80px 40px; -} -.container.mobile { - width: 100%; padding: 2vw 2vw 2vw 2vw; } + .text_div { margin-left: auto; margin-right: auto; @@ -16,7 +13,7 @@ position: relative; } .text_div.first { - margin-top: 10vw; + margin-top: 5vw; } .text_div.second { margin-top: 3vw; diff --git a/src/pages/HomeLayout/index.js b/src/pages/HomeLayout/index.js index 891f48e..0908ed4 100644 --- a/src/pages/HomeLayout/index.js +++ b/src/pages/HomeLayout/index.js @@ -37,7 +37,7 @@ export const HomeLayout = () => { {" "}
)} - + { const isMobile = type === WINDOW_TYPE.MOBILE; const navigate = useNavigate(); const { pathname } = useLocation(); - const isSmall = width < 600 || isMobile; const goTo = (route) => { navigate(route); @@ -26,21 +25,41 @@ export const NavBar = ({ showNavBar = true }) => { [styles.mobile]: isMobile, })} > -
+
goTo(ROUTES.HOME)} - className={cx(styles.navItem)} + className={cx(styles.navItem, { + [styles.mobile]: isMobile, + })} > -
- +
+
goTo(ROUTES.ROADMAP)} - className={cx(styles.navItem)} + className={cx(styles.navItem, { + [styles.mobile]: isMobile, + })} > -
+
{
goTo(ROUTES.COMMUNITY)} - className={cx(styles.navItem)} + className={cx(styles.navItem, { + [styles.mobile]: isMobile, + })} > -
- +
+
diff --git a/src/pages/NavBar/index.module.css b/src/pages/NavBar/index.module.css index 42b5f10..318fc3f 100644 --- a/src/pages/NavBar/index.module.css +++ b/src/pages/NavBar/index.module.css @@ -1,31 +1,46 @@ .page { + margin: 0; width: 100%; display: flex; } -.page.module { +.page.mobile { margin: 0; width: 100%; - display: flex; } .navBar { box-shadow: 1px -5px 10px #D9D9D9; + margin: auto; width: 100%; - height: 8vh; + height: 15vh; left: 0; - bottom: 0; - position: absolute; + position: fixed; display: flex; z-index: 100; + bottom: 0; } @media screen and (min-width: 1000px) { .navBar { top: 0; + height: 15vh; } } +.navItem.mobile { + box-sizing: border-box; + width: 33.333%; + height: 100%; + background-color: #ffffff; + padding: 5px 10px; + align-items: center; + display: flex; + justify-content: center; + margin-bottom: 20px; + cursor: pointer; +} + .navItem { box-sizing: border-box; width: 33.333%; @@ -39,6 +54,12 @@ cursor: pointer; } +.icon_div.mobile { + text-align: center; + display: flex; + justify-content: center; +} + .icon_div { text-align: center; display: flex; diff --git a/src/pages/Roadmap/index.js b/src/pages/Roadmap/index.js index e53bae8..0e2365b 100644 --- a/src/pages/Roadmap/index.js +++ b/src/pages/Roadmap/index.js @@ -14,10 +14,14 @@ import { } from "../../lib/utils"; import { AuthButton } from "../../components/AuthButton"; import { toast } from "react-toastify"; +import { useWindowSize } from "../../lib/hooks"; +import { WINDOW_TYPE } from "../../lib/constants"; const cx = classNames.bind(styles); export const Roadmap = ({ toast }) => { + const { width, type } = useWindowSize(); + const isMobile = type === WINDOW_TYPE.MOBILE; const navigate = useNavigate(); const [numTasks, setNumTasks] = useState(0); const [numAllTasks, setNumAllTasks] = useState(0); @@ -124,7 +128,7 @@ export const Roadmap = ({ toast }) => { className={cx(styles.csvButton)} label="Import Task CSV" onClick={onImport} - isMobile={true} + isMobile={isMobile} /> { className={cx(styles.csvButton)} label="Export Task CSV" onClick={onExport} - isMobile={true} + isMobile={isMobile} />
navigate(ROUTES.UPCOMING_TASKS)} - className={cx(styles.tasks_div)} + className={cx(styles.tasks_div, { + [styles.mobile]: isMobile, + })} >
- +
{ margin: "10px", }} > -

Upcoming

+

+ Upcoming +

-

+

All tasks with priority level 2

-

{numTasks}

+

+ {numTasks} +

navigate(ROUTES.ALL_TASKS)} - className={cx(styles.tasks_div, "all")} + className={cx(styles.tasks_div, "all", { + [styles.mobile]: isMobile, + })} >
- +
{ margin: "10px", }} > -

All Tasks

+

+ All Tasks +

-

Everything on the list

+

+ Everything on the list +

-

{numAllTasks}

+

+ {numAllTasks} +

diff --git a/src/pages/Roadmap/index.module.css b/src/pages/Roadmap/index.module.css index 867dedf..6ba9980 100644 --- a/src/pages/Roadmap/index.module.css +++ b/src/pages/Roadmap/index.module.css @@ -3,15 +3,15 @@ .header { font-family: "Poppins"; font-style: normal; - font-size: 8vw; + font-size: 2vw; font-weight: 900; display: inline-block; color: black; margin-bottom: 0; } -.header.small { - font-size: 3vw; +.header.mobile { + font-size: 4vw; font-weight: normal; margin-top: 0; } @@ -31,10 +31,18 @@ background-color: #f9f6dc; } -.icon { +.icon.mobile { height: 12vw; width: 12vw; } +.icon { + height: 6vw; + width: 6vw; +} + +.taskDesc.mobile { + font-size: 7vw; +} .taskDesc { margin: 0; @@ -45,19 +53,24 @@ display: inline-block; font-family: "Poppins"; font-style: normal; - font-size: 7vw; + font-size: 3vw; font-weight: 900; } + .taskNum { display: inline-block; font-family: "Poppins"; font-style: normal; - font-size: 6vw; + font-size: 3vw; font-weight: bolder; margin-left: auto; } +.taskNum.mobile { + font-size: 6vw; +} + .csvButton { margin-bottom: 2vh; } diff --git a/testRequests.rest b/testRequests.rest index 5dabcb4..ff06cdb 100644 --- a/testRequests.rest +++ b/testRequests.rest @@ -28,7 +28,7 @@ Content-Type: application/json ### -GET http://localhost:3001/children/63d58b72c2e0063e64001a1e +GET http://localhost:3001/children/ Content-Type: application/json From 8dbffc991676f79b654cc6a058607113c93706df Mon Sep 17 00:00:00 2001 From: Xiaohan Liu Date: Mon, 17 Apr 2023 11:28:18 -0500 Subject: [PATCH 12/16] refactored task API, fine-tuned web version --- src/components/BackArrow/index.js | 7 +- src/components/BackArrow/index.module.css | 9 +++ src/components/OnYourRadar/index.js | 11 ++- src/components/OnYourRadar/index.module.css | 2 +- src/components/UpcomingComponent/index.js | 25 ++----- .../UpcomingComponent/index.module.css | 7 +- src/lib/services.js | 75 +++++++++---------- src/pages/AllTasks/index.js | 14 ++-- src/pages/Home/index.js | 5 +- src/pages/Home/index.module.css | 7 ++ src/pages/HomeLayout/index.module.css | 30 ++------ src/pages/NavBar/index.module.css | 8 +- src/pages/Roadmap/index.js | 62 ++++++++------- src/pages/Upcoming/index.js | 16 ++-- testRequests.rest | 5 +- 15 files changed, 143 insertions(+), 140 deletions(-) diff --git a/src/components/BackArrow/index.js b/src/components/BackArrow/index.js index fb5f270..7a68ef3 100644 --- a/src/components/BackArrow/index.js +++ b/src/components/BackArrow/index.js @@ -16,14 +16,13 @@ export const BackArrow = ({ showBackArrow = true, isMobile }) => { <> {showBackArrow && ( - //
- - //
)} ); diff --git a/src/components/BackArrow/index.module.css b/src/components/BackArrow/index.module.css index 443e57e..216eec4 100644 --- a/src/components/BackArrow/index.module.css +++ b/src/components/BackArrow/index.module.css @@ -5,4 +5,13 @@ height: auto; margin-top: 4vh; margin-left: 5%; + } + + .backArrow.mobile { + display: flex; + justify-content: center; + width: 4%; + height: auto; + margin-top: 4vh; + margin-left: 5%; } \ No newline at end of file diff --git a/src/components/OnYourRadar/index.js b/src/components/OnYourRadar/index.js index e18b609..fb8b05f 100644 --- a/src/components/OnYourRadar/index.js +++ b/src/components/OnYourRadar/index.js @@ -11,9 +11,14 @@ export const OnYourRadar = React.forwardRef((props, ref) => { const [hpList, sethpList] = useState([]); const [elseList, setElseList] = useState([]); - useEffect(() => { - getChildrenTasksArray(childrenId, true, hpList, sethpList); - getChildrenTasksArray(childrenId, false, elseList, setElseList); + useEffect(async () => { + const { taskArray } = await getChildrenTasksArray(childrenId, true); + sethpList(taskArray); + }, []); + + useEffect(async () => { + const { taskArray } = await getChildrenTasksArray(childrenId, false); + setElseList(taskArray); }, []); const hpElements = hpList.flat().map((thing, index) => ( diff --git a/src/components/OnYourRadar/index.module.css b/src/components/OnYourRadar/index.module.css index 1d7af08..75f9a85 100644 --- a/src/components/OnYourRadar/index.module.css +++ b/src/components/OnYourRadar/index.module.css @@ -75,7 +75,7 @@ font-family: 'Poppins'; color: black; font-weight: 600; - font-size: 3vw; + font-size: 2vw; } .list.mobile { diff --git a/src/components/UpcomingComponent/index.js b/src/components/UpcomingComponent/index.js index 244bfc9..497f30c 100644 --- a/src/components/UpcomingComponent/index.js +++ b/src/components/UpcomingComponent/index.js @@ -19,6 +19,7 @@ export const UpcomingComponent = (props) => { completed, priority, childId, + childName, isMobile, } = props; const [checked, setChecked] = useState(completed); @@ -54,16 +55,16 @@ export const UpcomingComponent = (props) => { className={cx(styles.title, { [styles.mobile]: isMobile, })} + onClick={() => + navigate(ROUTES.TASK_DETAILS, { + state: { taskId, completed, childId }, + }) + } > - {title} + {title + " - " + childName}

- {/* */}

{ }) } > - {time} + {time + ", priority level: " + priority}

{ > {content}

-

- navigate(ROUTES.TASK_DETAILS, { state: { taskId, completed } }) - } - > - {priority} -

); diff --git a/src/components/UpcomingComponent/index.module.css b/src/components/UpcomingComponent/index.module.css index a6e49f0..f9ccbb1 100644 --- a/src/components/UpcomingComponent/index.module.css +++ b/src/components/UpcomingComponent/index.module.css @@ -16,6 +16,7 @@ font-weight: 500; margin: 0; color: #000000; + width: 90%; } .title.mobile { @@ -59,10 +60,4 @@ margin: 2; color: #818181; -} - -.upcomingIcon { - width: 20px; - height: 20px; - cursor: pointer; } \ No newline at end of file diff --git a/src/lib/services.js b/src/lib/services.js index 0201cca..49860c2 100644 --- a/src/lib/services.js +++ b/src/lib/services.js @@ -86,52 +86,45 @@ export const uncheckEvent = (childId, taskId) => { /** * @param {Array} childrenId an array of children Id's * @param {boolean} priority the priority level queried for Upcoming tasks - * @param {Array} taskArray the task array to be set: a 2D array where each child possesses their respective - * tasks based on age and disabilities - * @param {Function} setTaskArray the function to set task array + * @return {Array} taskArray the nested 2D array of tasks belonging to each child */ -export const getChildrenTasksArray = ( - childrenId, - priority, - taskArray, - setTaskArray -) => { - childrenId.forEach((childId) => { + +export const getChildrenTasksArray = async (childrenId, priority) => { + let taskArray = []; + const childPromises = childrenId.map(async (childId) => { // get child's name and disabilities const childUrl = "/children/" + childId; - fetch(process.env.REACT_APP_HOST_URL + childUrl) - .then((response) => response.json()) - .then((childrenData) => { - const childName = childrenData.firstName; - const age = getAgeGivenBirthday(childrenData.birthDate); - const completedTasks = childrenData.completedTasks; - const params = { - disabilities: JSON.stringify(childrenData.disabilities), - age: JSON.stringify(age), - }; - if (priority) { - params.priority = JSON.stringify(2); - } + const response = await fetch(process.env.REACT_APP_HOST_URL + childUrl); + const childData = await response.json(); + const childName = childData.firstName; + const completedTasks = childData.completedTasks; + const age = getAgeGivenBirthday(childData.birthDate); + const params = { + disabilities: JSON.stringify(childData.disabilities), + age: JSON.stringify(age), + }; + if (priority) { + params.priority = JSON.stringify(2); + } - // get tasks based on children's attributes - const url = formGetRequest("/tasks/byAttributes/", params); - fetch(process.env.REACT_APP_HOST_URL + url) - .then((response) => response.json()) - .then((taskData) => { - const namedTasks = taskData.map((item) => { - return { - ...item, - childName: childName, - childId: childId, - completed: completedTasks.includes(item._id), - }; - }); - const newTaskArray = [...taskArray, namedTasks]; - setTaskArray(newTaskArray); - }) - .catch((error) => console.log(error)); - }); + // get tasks based on children's attributes + const url = formGetRequest("/tasks/byAttributes/", params); + const taskResponse = await fetch(process.env.REACT_APP_HOST_URL + url); + const taskData = await taskResponse.json(); + const namedTasks = taskData.map((item) => { + return { + ...item, + childName: childName, + childId: childId, + completed: completedTasks.includes(item._id), + }; + }); + taskArray.push(namedTasks); }); + + await Promise.all(childPromises); // wait for all child promises to complete + + return { taskArray }; }; export const logoutTimer = () => { diff --git a/src/pages/AllTasks/index.js b/src/pages/AllTasks/index.js index 9910c9d..ee08834 100644 --- a/src/pages/AllTasks/index.js +++ b/src/pages/AllTasks/index.js @@ -17,13 +17,18 @@ export const AllTasks = () => { const [allTaskArray, setAllTaskArray] = useState([]); const [searchQuery, setSearchQuery] = useState(""); //TODO: get information using cache - const childrenId = ["63e5c4936d51fdbbbedb5503"]; + const childrenId = [ + "63e5c4936d51fdbbbedb5503", + "643b22b6ee8225a6684ac159", + "643b22b6ee8225a6684ac15b", + ]; const [timer, setTimer] = useState(); const navigate = useNavigate(); - useEffect(() => { - getChildrenTasksArray(childrenId, false, allTaskArray, setAllTaskArray); + useEffect(async () => { + const { taskArray } = await getChildrenTasksArray(childrenId, false); + setAllTaskArray(taskArray); }, []); // handler for search box @@ -36,8 +41,8 @@ export const AllTasks = () => { return task.title.toLowerCase().includes(searchQuery.toLowerCase()); }) ); + useEffect(() => { - console.log(localStorage); setTimer( setTimeout(() => { localStorage.removeItem("jwtToken"); @@ -71,7 +76,6 @@ export const AllTasks = () => { style={{ overflow: "scroll", overscrollBehavior: "none", - height: "66vh", }} > {filteredSections.map((childTasks, childTasksIndex) => ( diff --git a/src/pages/Home/index.js b/src/pages/Home/index.js index e6661d7..205440e 100644 --- a/src/pages/Home/index.js +++ b/src/pages/Home/index.js @@ -22,9 +22,8 @@ export const Home = () => { // TODO: cache const childrenId = [ "63e5c4936d51fdbbbedb5503", - "63e5c4296d51fdbbbedb5500", - "63e5c4176d51fdbbbedb54fd", - "63e5c40a6d51fdbbbedb54fa", + "643b22b6ee8225a6684ac159", + "643b22b6ee8225a6684ac15b", ]; const getChildrenPointsStats = async () => { diff --git a/src/pages/Home/index.module.css b/src/pages/Home/index.module.css index 4b58113..6281742 100644 --- a/src/pages/Home/index.module.css +++ b/src/pages/Home/index.module.css @@ -1,6 +1,13 @@ @import url('https://fonts.googleapis.com/css?family=Poppins'); .container { + width: 70%; + margin: auto; + box-sizing: border-box; + padding: 2vw 2vw 2vw 2vw; +} + +.container.mobile { width: 100%; box-sizing: border-box; padding: 2vw 2vw 2vw 2vw; diff --git a/src/pages/HomeLayout/index.module.css b/src/pages/HomeLayout/index.module.css index 1e49a22..ed02bb9 100644 --- a/src/pages/HomeLayout/index.module.css +++ b/src/pages/HomeLayout/index.module.css @@ -1,23 +1,12 @@ @import url('https://fonts.googleapis.com/css?family=Poppins'); -.page { - width: 100%; - display: flex; -} - -.page.mobile { - margin: 0; - padding: 0; - width: 100%; - display: flex; -} - .container { box-sizing: border-box; margin: auto; - padding-bottom: auto; + padding: auto; + width: 70%; height: 100vh; - overflow: auto; + overflow: auto; } .container.mobile { @@ -38,14 +27,6 @@ text-align: center; } -.header.mobile { - display: flex; - justify-content: center; - width: 45px; - height: 45px; - margin-left: 5%; -} - .header { display: flex; justify-content: center; @@ -54,6 +35,10 @@ margin-left: 5%; } +.header.mobile { + padding-top: 4vh; +} + .block { box-sizing: border-box; display: flex; @@ -73,4 +58,5 @@ overscroll-behavior: none; max-width: 100%; height: 75vh; + padding: 2vh 2vh 2vh 2vh; } \ No newline at end of file diff --git a/src/pages/NavBar/index.module.css b/src/pages/NavBar/index.module.css index 318fc3f..c14b786 100644 --- a/src/pages/NavBar/index.module.css +++ b/src/pages/NavBar/index.module.css @@ -21,12 +21,16 @@ bottom: 0; } -@media screen and (min-width: 1000px) { +.navBar.mobile { + height: 10vh; +} + +/* @media screen and (min-width: 1000px) { .navBar { top: 0; height: 15vh; } - } + } */ .navItem.mobile { box-sizing: border-box; diff --git a/src/pages/Roadmap/index.js b/src/pages/Roadmap/index.js index 0e2365b..e41531e 100644 --- a/src/pages/Roadmap/index.js +++ b/src/pages/Roadmap/index.js @@ -28,39 +28,45 @@ export const Roadmap = ({ toast }) => { const uploadRef = useRef(); const [importFile, setImportFile] = useState(null); //TODO: get the information from cache - const childrenId = ["63e5c4936d51fdbbbedb5503"]; + const childrenId = [ + "63e5c4936d51fdbbbedb5503", + "643b22b6ee8225a6684ac159", + "643b22b6ee8225a6684ac15b", + ]; const [timer, setTimer] = useState(); - const getStats = (childrenId) => { - childrenId.forEach((childId) => { + const getStats = async (childrenId) => { + let childrenStatsData = { numUpcoming: 0, numAll: 0 }; + const childPromises = childrenId.map(async (childId) => { // get child's name and disabilities const childUrl = "/children/" + childId; - fetch(process.env.REACT_APP_HOST_URL + childUrl) - .then((response) => response.json()) - .then((childrenData) => { - const age = getAgeGivenBirthday(childrenData.birthDate); - const params = { - disabilities: JSON.stringify(childrenData.disabilities), - age: JSON.stringify(age), - //TODO: fix the data for upcoming vs priority - priority: JSON.stringify(2), - }; + const response = await fetch(process.env.REACT_APP_HOST_URL + childUrl); + const childData = await response.json(); + const age = getAgeGivenBirthday(childData.birthDate); + const params = { + disabilities: JSON.stringify(childData.disabilities), + age: JSON.stringify(age), + //TODO: fix the data for upcoming vs priority + priority: JSON.stringify(2), + }; - // get tasks based on children's attributes - const url = formGetRequest("/tasks/getStats/", params); - fetch(process.env.REACT_APP_HOST_URL + url) - .then((response) => response.json()) - .then((data) => { - setNumTasks(data.numUpcoming); - setNumAllTasks(data.numAll); - }) - .catch((error) => console.log(error)); - }); + // get tasks based on children's attributes + const url = formGetRequest("/tasks/getStats/", params); + const statsResponse = await fetch(process.env.REACT_APP_HOST_URL + url); + const statsData = await statsResponse.json(); + console.log(statsData); + childrenStatsData.numUpcoming += statsData.numUpcoming; + childrenStatsData.numAll += statsData.numAll; }); + + await Promise.all(childPromises); // wait for all child promises to complete + return childrenStatsData; }; - useEffect(() => { - getStats(childrenId); + useEffect(async () => { + const { numUpcoming, numAll } = await getStats(childrenId); + setNumAllTasks(numAll); + setNumTasks(numUpcoming); }, []); // set the import csv file @@ -173,7 +179,7 @@ export const Roadmap = ({ toast }) => { [styles.mobile]: isMobile, })} > - Upcoming + High Priority

@@ -182,7 +188,7 @@ export const Roadmap = ({ toast }) => { [styles.mobile]: isMobile, })} > - All tasks with priority level 2 + All tasks with priority level higher than 2

{

); }; - -//Make each box into a compenent (lot of redundant code)** (move to components folder) diff --git a/src/pages/Upcoming/index.js b/src/pages/Upcoming/index.js index d34562c..7f8b90f 100644 --- a/src/pages/Upcoming/index.js +++ b/src/pages/Upcoming/index.js @@ -5,6 +5,7 @@ import { useWindowSize } from "../../lib/hooks"; import { useState, useEffect } from "react"; import { WINDOW_TYPE, TIMEOUT } from "../../lib/constants"; import { getChildrenTasksArray } from "../../lib/services"; +import { separateWebsiteLink } from "../../lib/utils"; import { useNavigate } from "react-router-dom"; const cx = classNames.bind(styles); @@ -14,13 +15,18 @@ export const Upcoming = ({ toast }) => { const isMobile = useWindowSize().type === WINDOW_TYPE.MOBILE; const [taskArray, setTaskArray] = useState([]); //TODO: get information using cache - const childrenId = ["63e5c4936d51fdbbbedb5503"]; + const childrenId = [ + "63e5c4936d51fdbbbedb5503", + "643b22b6ee8225a6684ac159", + "643b22b6ee8225a6684ac15b", + ]; const [timer, setTimer] = useState(); const navigate = useNavigate(); - useEffect(() => { - getChildrenTasksArray(childrenId, true, taskArray, setTaskArray); + useEffect(async () => { + const { taskArray } = await getChildrenTasksArray(childrenId, true); + setTaskArray(taskArray); }, []); const deduplicatedList = taskArray.flat().filter((obj, index, self) => { @@ -28,7 +34,6 @@ export const Upcoming = ({ toast }) => { }); useEffect(() => { - console.log(localStorage); setTimer( setTimeout(() => { localStorage.removeItem("jwtToken"); @@ -53,10 +58,11 @@ export const Upcoming = ({ toast }) => { taskId={task._id} title={task.title} time={task.timePeriod} - content={task.details} + content={separateWebsiteLink(task.details).otherStrings} completed={task.completed} priority={task.priority} childId={task.childId} + childName={task.childName} isMobile={isMobile} /> ))} diff --git a/testRequests.rest b/testRequests.rest index ff06cdb..c3522b9 100644 --- a/testRequests.rest +++ b/testRequests.rest @@ -54,11 +54,12 @@ POST http://localhost:3001/tasks Content-Type: application/json { - "title": "Task 3", + "title": "Task 5", "details": "Call LIDDA based on county|https://resources.hhs.texas.gov/pages/find-services|https://resources.hhs.texas.gov/pages", "disabilities": ["ADHD", "disability1", "disability2"], "timePeriod": "monthly", - "age": "Adult" + "age": "Adult", + "priority": 1 } ### From d38ac5323f15f58ef42c1fe233d6450c50bfb413 Mon Sep 17 00:00:00 2001 From: Xiaohan Liu Date: Mon, 17 Apr 2023 15:00:03 -0500 Subject: [PATCH 13/16] fine-tuned styling --- src/App.js | 9 ++++++--- src/components/CheckBox/index.module.css | 4 ++-- src/pages/Home/index.module.css | 4 ++-- src/pages/Roadmap/index.js | 2 -- 4 files changed, 10 insertions(+), 9 deletions(-) diff --git a/src/App.js b/src/App.js index c9e971b..8d4e8fd 100644 --- a/src/App.js +++ b/src/App.js @@ -30,9 +30,12 @@ const App = () => { }> } /> } /> - } /> - } /> - } /> + } /> + } + /> + } /> } /> } /> diff --git a/src/components/CheckBox/index.module.css b/src/components/CheckBox/index.module.css index 5c56025..af1d3f9 100644 --- a/src/components/CheckBox/index.module.css +++ b/src/components/CheckBox/index.module.css @@ -1,7 +1,7 @@ .checkBox{ display: inline-block; - width: 6vh; - height: 6vh; + width: 5vh; + height: 5vh; background: #E0E0E0; margin-left: auto; margin-right: 0; diff --git a/src/pages/Home/index.module.css b/src/pages/Home/index.module.css index 6281742..8883140 100644 --- a/src/pages/Home/index.module.css +++ b/src/pages/Home/index.module.css @@ -4,13 +4,13 @@ width: 70%; margin: auto; box-sizing: border-box; - padding: 2vw 2vw 2vw 2vw; + padding: 2vw 2vw 10vw 2vw; } .container.mobile { width: 100%; box-sizing: border-box; - padding: 2vw 2vw 2vw 2vw; + padding: 2vw 2vw 10vw 2vw; } .text_div { diff --git a/src/pages/Roadmap/index.js b/src/pages/Roadmap/index.js index e41531e..8802dbd 100644 --- a/src/pages/Roadmap/index.js +++ b/src/pages/Roadmap/index.js @@ -13,7 +13,6 @@ import { getAgeGivenBirthday, } from "../../lib/utils"; import { AuthButton } from "../../components/AuthButton"; -import { toast } from "react-toastify"; import { useWindowSize } from "../../lib/hooks"; import { WINDOW_TYPE } from "../../lib/constants"; @@ -54,7 +53,6 @@ export const Roadmap = ({ toast }) => { const url = formGetRequest("/tasks/getStats/", params); const statsResponse = await fetch(process.env.REACT_APP_HOST_URL + url); const statsData = await statsResponse.json(); - console.log(statsData); childrenStatsData.numUpcoming += statsData.numUpcoming; childrenStatsData.numAll += statsData.numAll; }); From 75f330a45b85d7e04d74f315978dd3c40ca7ffe0 Mon Sep 17 00:00:00 2001 From: Xiaohan Liu Date: Mon, 17 Apr 2023 15:33:24 -0500 Subject: [PATCH 14/16] added spinner and fine-tuned styles --- package-lock.json | 16 +++++ package.json | 1 + src/components/AllTasksSection/index.js | 4 +- .../AllTasksSection/index.module.css | 10 ++- src/components/Caption/index.js | 71 ++++++++++--------- src/components/Caption/index.module.css | 16 ++--- src/components/OnYourRadar/index.js | 3 +- src/components/OnYourRadar/index.module.css | 25 ++++--- src/components/PointsDisplay/index.module.css | 26 +++---- src/components/TaskListItem/index.module.css | 4 +- src/components/UpcomingComponent/index.js | 1 - .../UpcomingComponent/index.module.css | 20 +----- src/pages/AllTasks/index.js | 10 ++- src/pages/Home/index.js | 3 +- src/pages/Home/index.module.css | 6 +- src/pages/HomeLayout/index.module.css | 13 ++-- src/pages/LoadScreen/index.js | 9 +-- src/pages/Roadmap/index.js | 5 ++ src/pages/Roadmap/index.module.css | 33 ++++++--- src/pages/Upcoming/index.js | 5 ++ 20 files changed, 158 insertions(+), 123 deletions(-) diff --git a/package-lock.json b/package-lock.json index 4573ade..702b407 100644 --- a/package-lock.json +++ b/package-lock.json @@ -22,6 +22,7 @@ "react-search-box": "^2.3.0", "react-select": "^5.7.0", "react-slidy": "^4.3.3", + "react-spinners": "^0.13.8", "react-toastify": "^8.1.0" }, "devDependencies": { @@ -16578,6 +16579,15 @@ "react-dom": ">= 16.8.0" } }, + "node_modules/react-spinners": { + "version": "0.13.8", + "resolved": "https://registry.npmjs.org/react-spinners/-/react-spinners-0.13.8.tgz", + "integrity": "sha512-3e+k56lUkPj0vb5NDXPVFAOkPC//XyhKPJjvcGjyMNPWsBKpplfeyialP74G7H7+It7KzhtET+MvGqbKgAqpZA==", + "peerDependencies": { + "react": "^16.0.0 || ^17.0.0 || ^18.0.0", + "react-dom": "^16.0.0 || ^17.0.0 || ^18.0.0" + } + }, "node_modules/react-toastify": { "version": "8.2.0", "resolved": "https://registry.npmjs.org/react-toastify/-/react-toastify-8.2.0.tgz", @@ -34213,6 +34223,12 @@ "intersection-observer": "0.10.0" } }, + "react-spinners": { + "version": "0.13.8", + "resolved": "https://registry.npmjs.org/react-spinners/-/react-spinners-0.13.8.tgz", + "integrity": "sha512-3e+k56lUkPj0vb5NDXPVFAOkPC//XyhKPJjvcGjyMNPWsBKpplfeyialP74G7H7+It7KzhtET+MvGqbKgAqpZA==", + "requires": {} + }, "react-toastify": { "version": "8.2.0", "resolved": "https://registry.npmjs.org/react-toastify/-/react-toastify-8.2.0.tgz", diff --git a/package.json b/package.json index 7732700..3c21a4b 100644 --- a/package.json +++ b/package.json @@ -17,6 +17,7 @@ "react-search-box": "^2.3.0", "react-select": "^5.7.0", "react-slidy": "^4.3.3", + "react-spinners": "^0.13.8", "react-toastify": "^8.1.0" }, "scripts": { diff --git a/src/components/AllTasksSection/index.js b/src/components/AllTasksSection/index.js index 759cbcd..6cacc09 100644 --- a/src/components/AllTasksSection/index.js +++ b/src/components/AllTasksSection/index.js @@ -23,7 +23,9 @@ export const AllTasksSection = React.forwardRef((props, ref) => { return (
{ - const { - mainTitle, - subTitle, - className, - style, - } = props; + const { mainTitle, subTitle, className, style } = props; - const { type } = useWindowSize(); - const isMobile = type === WINDOW_TYPE.MOBILE; - - return
-
- {mainTitle} -
-
- {subTitle} -
+
+ {mainTitle} +
+
+ {subTitle} +
+ ); }; Caption.propTypes = { - mainTitle: PropTypes.string.isRequired, - subTitle: PropTypes.string.isRequired, - className: PropTypes.string, - style: PropTypes.objectOf(PropTypes.string), -} \ No newline at end of file + mainTitle: PropTypes.string.isRequired, + subTitle: PropTypes.string.isRequired, + className: PropTypes.string, + style: PropTypes.objectOf(PropTypes.string), +}; diff --git a/src/components/Caption/index.module.css b/src/components/Caption/index.module.css index 75dfc26..403d0c2 100644 --- a/src/components/Caption/index.module.css +++ b/src/components/Caption/index.module.css @@ -9,36 +9,36 @@ border: 0; } -.mainTitle.mobile { +.mainTitle { height: fit-content; font-family: "Poppins"; font-style: normal; - font-size: 8vw; + font-size: 3vw; font-weight: 900; } -.mainTitle { +.mainTitle.mobile { height: fit-content; font-family: "Poppins"; font-style: normal; - font-size: 4vw; + font-size: 8vw; font-weight: 900; } -.subTitle.mobile { +.subTitle { height: fit-content; font-family: "Poppins"; font-style: normal; - font-size: 4vw; + font-size: 1vw; font-weight: 500; color: #818181; } -.subTitle { +.subTitle.mobile { height: fit-content; font-family: "Poppins"; font-style: normal; - font-size: 2vw; + font-size: 4vw; font-weight: 500; color: #818181; } \ No newline at end of file diff --git a/src/components/OnYourRadar/index.js b/src/components/OnYourRadar/index.js index fb8b05f..650cec0 100644 --- a/src/components/OnYourRadar/index.js +++ b/src/components/OnYourRadar/index.js @@ -3,6 +3,7 @@ import classNames from "classnames/bind"; import React from "react"; import { useState, useEffect } from "react"; import { getChildrenTasksArray } from "../../lib/services"; +import { Loader } from "../../pages/LoadScreen"; const cx = classNames.bind(styles); @@ -33,7 +34,7 @@ export const OnYourRadar = React.forwardRef((props, ref) => { )); if (hpElements.length === 0 || elseElements.length === 0) { - return
Loading...
; + return ; } return ( diff --git a/src/components/OnYourRadar/index.module.css b/src/components/OnYourRadar/index.module.css index 75f9a85..98cf67b 100644 --- a/src/components/OnYourRadar/index.module.css +++ b/src/components/OnYourRadar/index.module.css @@ -1,19 +1,19 @@ -.todo_div.mobile { - border: 6px #0198ba; +.todo_div { + border: 3px #0198ba; border-style: solid; border-radius: 50px; - margin-top: 10vw; + margin-top: 5vw; margin-left: 2vw; margin-right: 2vw; padding-left: 3vw; padding-bottom: 10vw; } -.todo_div { +.todo_div.mobile { border: 6px #0198ba; border-style: solid; border-radius: 50px; - margin-top: 5vw; + margin-top: 10vw; margin-left: 2vw; margin-right: 2vw; padding-left: 3vw; @@ -24,16 +24,15 @@ display: flex; justify-content: space-between; } - -.priorityParent.mobile{ - display: block; -} - .priorityBlock{ flex: 1; display: inline-block; } +.priorityParent.mobile{ + display: block; +} + .priorityBlock.mobile{ display: block; } @@ -50,7 +49,7 @@ font-family: "Poppins"; font-weight: 900; color: black; - font-size: 3vw; + font-size: 2vw; } .priority.mobile { @@ -64,7 +63,7 @@ font-family: "Poppins"; font-weight: bolder; color: #8b5674; - font-size: 3vw; + font-size: 2vw; } .priority.else { @@ -75,7 +74,7 @@ font-family: 'Poppins'; color: black; font-weight: 600; - font-size: 2vw; + font-size: 1.7vw; } .list.mobile { diff --git a/src/components/PointsDisplay/index.module.css b/src/components/PointsDisplay/index.module.css index 677a468..ae6dfd2 100644 --- a/src/components/PointsDisplay/index.module.css +++ b/src/components/PointsDisplay/index.module.css @@ -9,19 +9,19 @@ position: relative; } -.name.mobile { +.name { font-family: 'Poppins'; font-weight: 800; - font-size: 5vw; - margin: 1vh; + font-size: 2vw; + margin: auto; color: #000000; } -.name { +.name.mobile { font-family: 'Poppins'; font-weight: 800; - font-size: 3vw; - margin: auto; + font-size: 5vw; + margin: 1vh; color: #000000; } @@ -38,7 +38,7 @@ .points { font-family: 'Poppins'; font-weight: 800; - font-size: 2.7vw; + font-size: 1.8vw; margin: auto; display: inline-block; color: #000000; @@ -50,8 +50,8 @@ } .progress_circle { - width: 30vw; - height: 30vw; + width: 20vw; + height: 20vw; margin-top: 4vw; margin-bottom: 2vw; margin-left: auto; @@ -67,16 +67,16 @@ margin-right: auto; } -.progress_circle_text.mobile { +.progress_circle_text { font-family: 'Poppins'; font-weight: 900; color: black; - font-size: 6vw; + font-size: 2vw; } -.progress_circle_text { +.progress_circle_text.mobile { font-family: 'Poppins'; font-weight: 900; color: black; - font-size: 3vw; + font-size: 6vw; } \ No newline at end of file diff --git a/src/components/TaskListItem/index.module.css b/src/components/TaskListItem/index.module.css index 384bc15..2e672f8 100644 --- a/src/components/TaskListItem/index.module.css +++ b/src/components/TaskListItem/index.module.css @@ -17,7 +17,7 @@ .taskName { font-family: "Poppins"; font-style: normal; - font-size: 2vw; + font-size: 1.4vw; font-weight: 500; margin: 0; } @@ -41,7 +41,7 @@ .taskDate { font-family: "Poppins"; font-weight:400; - font-size: 1.5vw; + font-size: 1.2vw; color: #8B5674; margin: 0; } \ No newline at end of file diff --git a/src/components/UpcomingComponent/index.js b/src/components/UpcomingComponent/index.js index 497f30c..6f8dc08 100644 --- a/src/components/UpcomingComponent/index.js +++ b/src/components/UpcomingComponent/index.js @@ -43,7 +43,6 @@ export const UpcomingComponent = (props) => { style={{ backgroundColor: color, padding: "4vh", - margin: "4vh", }} >
{ const { width, type } = useWindowSize(); const isMobile = type === WINDOW_TYPE.MOBILE; - + const [loaded, setLoaded] = useState(false); const [allTaskArray, setAllTaskArray] = useState([]); const [searchQuery, setSearchQuery] = useState(""); //TODO: get information using cache @@ -29,6 +30,7 @@ export const AllTasks = () => { useEffect(async () => { const { taskArray } = await getChildrenTasksArray(childrenId, false); setAllTaskArray(taskArray); + setLoaded(true); }, []); // handler for search box @@ -58,6 +60,8 @@ export const AllTasks = () => { }; }, [timer]); + if (!loaded) return ; + return (
{
{ }, []); if (childrenStats.length !== childrenId.length) { - return
Loading...
; + return ; } return ( diff --git a/src/pages/Home/index.module.css b/src/pages/Home/index.module.css index 8883140..941b2ee 100644 --- a/src/pages/Home/index.module.css +++ b/src/pages/Home/index.module.css @@ -19,16 +19,18 @@ text-align: center; position: relative; } + .text_div.first { margin-top: 5vw; } + .text_div.second { margin-top: 3vw; } .welcome { font-family: 'Poppins'; font-style: normal; - font-size: 4vw; + font-size: 3vw; margin: auto; display: inline-block; color: #A8A8A8; @@ -51,7 +53,7 @@ .cruising { font-family: 'Poppins'; font-style: normal; - font-size: 3vw; + font-size: 2vw; margin: auto; display: inline-block; color: #A8A8A8; diff --git a/src/pages/HomeLayout/index.module.css b/src/pages/HomeLayout/index.module.css index ed02bb9..0fd9150 100644 --- a/src/pages/HomeLayout/index.module.css +++ b/src/pages/HomeLayout/index.module.css @@ -12,7 +12,13 @@ .container.mobile { height: 100%; width: 100%; - padding: 2vw; + padding: 0vw; +} + +.caption { + margin-top: 1vh; + margin-bottom: 1vh; + text-align: center; } .caption.mobile { @@ -21,11 +27,6 @@ text-align: center; } -.caption { - margin-top: 1vh; - margin-bottom: 1vh; - text-align: center; -} .header { display: flex; diff --git a/src/pages/LoadScreen/index.js b/src/pages/LoadScreen/index.js index f85f1fa..ef4311a 100644 --- a/src/pages/LoadScreen/index.js +++ b/src/pages/LoadScreen/index.js @@ -5,20 +5,13 @@ import logo from "../../images/F2F-logo.png"; import "./index.css"; export const Loader = () => { - const navigate = useNavigate(); - return (
- +
); diff --git a/src/pages/Roadmap/index.js b/src/pages/Roadmap/index.js index 8802dbd..952ad05 100644 --- a/src/pages/Roadmap/index.js +++ b/src/pages/Roadmap/index.js @@ -15,6 +15,7 @@ import { import { AuthButton } from "../../components/AuthButton"; import { useWindowSize } from "../../lib/hooks"; import { WINDOW_TYPE } from "../../lib/constants"; +import Loader from "../LoadScreen"; const cx = classNames.bind(styles); @@ -22,6 +23,7 @@ export const Roadmap = ({ toast }) => { const { width, type } = useWindowSize(); const isMobile = type === WINDOW_TYPE.MOBILE; const navigate = useNavigate(); + const [loaded, setLoaded] = useState(false); const [numTasks, setNumTasks] = useState(0); const [numAllTasks, setNumAllTasks] = useState(0); const uploadRef = useRef(); @@ -65,6 +67,7 @@ export const Roadmap = ({ toast }) => { const { numUpcoming, numAll } = await getStats(childrenId); setNumAllTasks(numAll); setNumTasks(numUpcoming); + setLoaded(true); }, []); // set the import csv file @@ -119,6 +122,8 @@ export const Roadmap = ({ toast }) => { .catch((error) => console.error(error)); }; + if (!loaded) return ; + return (
{ const isMobile = useWindowSize().type === WINDOW_TYPE.MOBILE; const [taskArray, setTaskArray] = useState([]); + const [loaded, setLoaded] = useState(false); //TODO: get information using cache const childrenId = [ "63e5c4936d51fdbbbedb5503", @@ -27,6 +29,7 @@ export const Upcoming = ({ toast }) => { useEffect(async () => { const { taskArray } = await getChildrenTasksArray(childrenId, true); setTaskArray(taskArray); + setLoaded(true); }, []); const deduplicatedList = taskArray.flat().filter((obj, index, self) => { @@ -49,6 +52,8 @@ export const Upcoming = ({ toast }) => { }; }, [timer]); + if (!loaded) return ; + return ( <>
From 9b1a9edba87e314d8ae4a54f515a47e31836173d Mon Sep 17 00:00:00 2001 From: Xiaohan Liu Date: Sat, 22 Apr 2023 18:39:15 -0500 Subject: [PATCH 15/16] integrated authentication --- src/App.js | 2 + src/components/AddChild/index.js | 146 +++++++++++++ src/components/AddChild/index.module.css | 85 ++++++++ src/components/CommunityPost/index.js | 24 +-- src/components/CommunityPost/index.module.css | 2 +- src/components/CreatePost/index.js | 24 ++- src/components/CreatePost/index.module.css | 7 +- src/components/OnYourRadar/index.js | 4 - src/components/ProfilePicture/index.js | 5 +- src/lib/constants.js | 5 +- src/lib/services.js | 44 ++++ src/lib/utils.js | 6 +- src/pages/AllTasks/index.js | 16 +- src/pages/Community/index.js | 151 +++---------- src/pages/Community/index.module.css | 27 ++- src/pages/Home/index.js | 45 +++- src/pages/Login/index.js | 17 +- src/pages/NavBar/index.module.css | 97 +++++---- src/pages/Roadmap/index.js | 25 ++- src/pages/SignUp/index.js | 199 ++++++++++++++---- src/pages/SignUp/index.module.css | 28 ++- src/pages/TaskDetails/index.js | 6 +- src/pages/Upcoming/index.js | 9 +- testRequests.rest | 10 +- 24 files changed, 700 insertions(+), 284 deletions(-) create mode 100644 src/components/AddChild/index.js create mode 100644 src/components/AddChild/index.module.css diff --git a/src/App.js b/src/App.js index 8d4e8fd..929b4b8 100644 --- a/src/App.js +++ b/src/App.js @@ -15,6 +15,7 @@ import { Roadmap } from "./pages/Roadmap"; import { Community } from "./pages/Community"; import { TaskDetails } from "./pages/TaskDetails"; import { AllTasks } from "./pages/AllTasks"; +import { EmailVerification } from "./pages/Verification"; const App = () => { return ( @@ -41,6 +42,7 @@ const App = () => { } /> } /> } /> + } /> diff --git a/src/components/AddChild/index.js b/src/components/AddChild/index.js new file mode 100644 index 0000000..031c506 --- /dev/null +++ b/src/components/AddChild/index.js @@ -0,0 +1,146 @@ +import React, { useState, useEffect } from "react"; +import classNames from "classnames/bind"; +import styles from "./index.module.css"; +import { useWindowSize } from "../../lib/hooks"; +import { + AUTH_INPUT_LABELS, + SCHOOL_DISTRICT, + DISABILITY, + WINDOW_TYPE, + STATUS_CODE, +} from "../../lib/constants"; +import { AuthInputBlock } from "../../components/AuthInputBlock"; +import { AuthSelectBlock } from "../../components/AuthSelectBlock"; +import { AuthButton } from "../AuthButton"; + +const cx = classNames.bind(styles); + +export function AddChild(props) { + const isMobile = useWindowSize().type === WINDOW_TYPE.MOBILE; + + const [child, setChild] = useState({}); + const [isLoading, setIsLoading] = useState(false); + const [error, setError] = useState(""); + const [submitted, setSubmitted] = useState(false); + const [leavePage, setLeavePage] = useState(false); + + useEffect(() => { + if (leavePage) { + if (submitted) { + props.setChildren([...props.currChildren, child]); + } + props.setAddChild(false); + } + }, [leavePage]); + + const checkValidBirthday = () => { + const birthday = child.birthDate; + + // Regular expression for MM-DD-YYYY format + const regex = /^\d{2}-\d{2}-\d{4}$/; + + // Check if the input matches the regular expression + if (!regex.test(birthday)) { + return false; + } + + // Check if the date is valid + const parts = birthday.split("-"); + const month = parseInt(parts[0], 10); + const day = parseInt(parts[1], 10); + const year = parseInt(parts[2], 10); + + // JavaScript Date object will automatically handle leap year + const date = new Date(year, month - 1, day); + const isValid = + date.getFullYear() === year && + date.getMonth() === month - 1 && + date.getDate() === day; + + return isValid; + }; + + const onSubmit = async () => { + if (!child.firstName) props.toast("Please provide your child's name"); + else if (!child.birthDate) + props.toast("Please provide your child's birthdate"); + else if (!checkValidBirthday(child.birthDate)) + props.toast("Please enter the birthday in the correct format"); + else if (!child.schoolDistrict) + props.toast("Please provide your child's school district"); + else if (!child.disabilities) + props.toast("Please provide your child's disability"); + else { + setSubmitted(true); + setLeavePage(true); + } + }; + + return ( +
+
+
+
+ setLeavePage(true)} + style={{ + borderRadius: "30%", + height: "auto", + width: "30px", + display: "flex", + alignItems: "center", + justifyContent: "center", + }} + /> +
{" "} +
+

Add a Child

+ setChild({ ...child, firstName: value })} + /> + setChild({ ...child, birthDate: value })} + /> + + setChild({ ...child, schoolDistrict: value.label }) + } + /> + setChild({ ...child, disabilities: value })} + /> + +
+
+ ); +} diff --git a/src/components/AddChild/index.module.css b/src/components/AddChild/index.module.css new file mode 100644 index 0000000..f9175f3 --- /dev/null +++ b/src/components/AddChild/index.module.css @@ -0,0 +1,85 @@ +.content { + position: fixed; + top: 0; + left: 0; + width: 100%; + height: 100vh; + background-color: rgba(0, 0, 0, 0.2); + + display: flex; + justify-content: center; + align-items: center; +} + +.popup { + display: block; + background-color: white; + width: 80%; + height: auto; + + font-family: "Poppins"; + padding: 30px; + border-radius: 30px; +} + +.title { + margin: 0; + font-size: 7vw; +} + +.desc { + font-size: 4vw; + width: 100%; +} + +.input { + width: 95%; + font-family: "Poppins"; + font-size: 3vw; + height: 30vh; + padding: 10px; + margin: 15px 0; + border-radius: 20px; +} + +.submit { + /* background-color: rgb(2, 152, 186); + border-radius: 20px; + font-size: 5vw; + padding: 10px; + width: 50%; + color: white; */ + width: 99%; + height: 6vh; + font-size: 2vh; + font-family: "Poppins"; + font-weight: bold; + color: white; + border-width: 0; + border-radius: 20px; + background-color: rgb(2, 152, 186); + padding: 0; +} +.submit:hover { + cursor: pointer; + transform: scale(1.01); + transition: 0.2s; + box-shadow: 0 6px 4px darkgray; +} + +.submit_wrapper { + display: flex; + align-items: center; + justify-content: center; + border-width: 0; +} + +.close_wrapper { + display: flex; + border-radius: 50%; +} + +.close { + margin-left: auto; + width: 5vw; +} diff --git a/src/components/CommunityPost/index.js b/src/components/CommunityPost/index.js index d3b3f8d..ebf10ed 100644 --- a/src/components/CommunityPost/index.js +++ b/src/components/CommunityPost/index.js @@ -10,40 +10,34 @@ const Post = (props) => {
- +

- {props.user} + {props.name}

-

{props.location}

+ {props.heading}
-

{props.content}

+

{props.body}

-
+ {/*
- {props.user}  + {props.name}  - {props.caption} -
-
-

- View all {props.comments.length} comments -

- {props.comments[0].user}  + {props.comments}  - {props.comments[0].comment} + {props.comments}

-
+
*/}
); }; diff --git a/src/components/CommunityPost/index.module.css b/src/components/CommunityPost/index.module.css index 4e18e82..b265e64 100644 --- a/src/components/CommunityPost/index.module.css +++ b/src/components/CommunityPost/index.module.css @@ -39,7 +39,7 @@ } .post_info { - font-size: 1.5vw; + font-size: 3.5vw; } .post_caption { diff --git a/src/components/CreatePost/index.js b/src/components/CreatePost/index.js index f48d999..f49848b 100644 --- a/src/components/CreatePost/index.js +++ b/src/components/CreatePost/index.js @@ -1,12 +1,14 @@ import React, { useState } from "react"; import classNames from "classnames/bind"; import styles from "./index.module.css"; +import { AuthInputBlock } from "../AuthInputBlock"; const cx = classNames.bind(styles); -export function CreatePost() { +export function CreatePost(props) { const [postContent, setPostContent] = useState(""); const [isLoading, setIsLoading] = useState(false); + const [postTitle, setPostTitle] = useState(""); const [error, setError] = useState(""); const handleSubmit = (e) => { @@ -14,12 +16,16 @@ export function CreatePost() { setIsLoading(true); setError(""); - fetch("/createPost", { + fetch(process.env.REACT_APP_HOST_URL + "/posts", { method: "POST", headers: { "Content-Type": "application/json", }, - body: JSON.stringify({ postContent }), + body: JSON.stringify({ + name: localStorage.getItem("firstName"), + title: postTitle, + body: postContent, + }), }) .then((res) => { if (!res.ok) { @@ -35,6 +41,8 @@ export function CreatePost() { setIsLoading(false); setError(err.message); }); + props.setCreatePost(false); + props.rotate(false); }; return ( @@ -42,6 +50,14 @@ export function CreatePost() {

Create a Post

+
+ setPostTitle(value)} + /> +
+
); -} +} \ No newline at end of file diff --git a/src/components/CreatePost/index.module.css b/src/components/CreatePost/index.module.css index b66a01c..f0d6f48 100644 --- a/src/components/CreatePost/index.module.css +++ b/src/components/CreatePost/index.module.css @@ -5,7 +5,6 @@ width: 100%; height: 100vh; background-color: rgba(0, 0, 0, 0.2); - display: flex; justify-content: center; align-items: center; @@ -15,7 +14,7 @@ display: block; background-color: white; width: 80%; - height: 50%; + height: auto; font-family: "Poppins"; padding: 30px; @@ -73,3 +72,7 @@ justify-content: center; border-width: 0; } + +.content_container { + font-size: 10vw; +} \ No newline at end of file diff --git a/src/components/OnYourRadar/index.js b/src/components/OnYourRadar/index.js index 650cec0..90adad5 100644 --- a/src/components/OnYourRadar/index.js +++ b/src/components/OnYourRadar/index.js @@ -33,10 +33,6 @@ export const OnYourRadar = React.forwardRef((props, ref) => {

)); - if (hpElements.length === 0 || elseElements.length === 0) { - return ; - } - return (
- +
); } diff --git a/src/lib/constants.js b/src/lib/constants.js index caf3dbb..e9ce7b4 100644 --- a/src/lib/constants.js +++ b/src/lib/constants.js @@ -11,7 +11,7 @@ export const WINDOW_TYPE = { }; export const STATUS_CODE = { - SUCESS: "SUCESS", + SUCESS: "SUCCESS", ERROR: "ERROR", }; @@ -27,6 +27,7 @@ export const ROUTES = { UPCOMING_TASKS: "/upcoming", ALL_TASKS: "/tasks", TASK_DETAILS: "/task-details", + VERIFICATION: "/verification", }; export const HOME_NAV_LABELS = { @@ -48,6 +49,8 @@ export const AUTH_INPUT_LABELS = { ZIP_CODE: "Zip Code", PHONE_NUMBER: "Phone Number", SIGN_UP: "Sign Up!", + ADD_CHILD: "Add Child", + BIRTH_DATE: "Birth Date (MM-DD-YYYY)", }; // page titles diff --git a/src/lib/services.js b/src/lib/services.js index 49860c2..c156923 100644 --- a/src/lib/services.js +++ b/src/lib/services.js @@ -7,8 +7,52 @@ import { PRIORITY_LEVEL, STATUS_CODE } from "./constants"; import { formGetRequest, getAgeGivenBirthday } from "./utils"; import { toast } from "react-toastify"; +export const mongoCheck = (email) => { + console.log("email " + email); + return new Promise((resolve, reject) => { + //make localhost call a constant + fetch(`http://localhost:3001/verification/checkMongo/?email=${email}`, { + method: "GET", + headers: { "Content-Type": "application/json" }, + }) + .then((response) => response.json()) + .then((response) => { + resolve(response); + }) + .catch((err) => reject(err)); + }); +}; +export const sendVerificationEmail = (email) => { + return new Promise((resolve, reject) => { + fetch(`http://localhost:3001/verification/sendEmail/?email=${email}`, { + method: "GET", + headers: { "Content-Type": "application/json" }, + }) + .then((response) => response.json()) + .then((response) => resolve(response)) + .catch((err) => reject(err)); + }); +}; + +export const signUpChildren = (inputs) => { + return new Promise((resolve, reject) => { + fetch(process.env.REACT_APP_HOST_URL + "/children", { + method: "POST", + headers: { "Content-Type": "application/json" }, + body: JSON.stringify(inputs), + }) + .then((response) => response.json()) + .then((response) => resolve(response)) + .catch((err) => reject(err)); + }); +}; + export const signUp = (inputs) => { + console.log("user call to backend"); + console.log(inputs); return new Promise((resolve, reject) => { + console.log(JSON.stringify(inputs)); + console.log(inputs); fetch(process.env.REACT_APP_HOST_URL + "/users", { method: "POST", headers: { "Content-Type": "application/json" }, diff --git a/src/lib/utils.js b/src/lib/utils.js index 36793dd..bd380da 100644 --- a/src/lib/utils.js +++ b/src/lib/utils.js @@ -62,9 +62,9 @@ export const importCSVToJSON = (data) => { let obj = {}; for (let c = 0; c < data[r].length; ++c) { var content = data[r][c]; - // convert the string to array with spliterator "/" - if (content.includes("/")) { - content = content.split("/"); + // convert the string to array with spliterator "|" + if (content.includes("|")) { + content = content.split("|"); } obj[keys[c.toString()]] = content; } diff --git a/src/pages/AllTasks/index.js b/src/pages/AllTasks/index.js index a22e696..335819c 100644 --- a/src/pages/AllTasks/index.js +++ b/src/pages/AllTasks/index.js @@ -17,12 +17,7 @@ export const AllTasks = () => { const [loaded, setLoaded] = useState(false); const [allTaskArray, setAllTaskArray] = useState([]); const [searchQuery, setSearchQuery] = useState(""); - //TODO: get information using cache - const childrenId = [ - "63e5c4936d51fdbbbedb5503", - "643b22b6ee8225a6684ac159", - "643b22b6ee8225a6684ac15b", - ]; + const childrenId = JSON.parse(localStorage.getItem("children")); const [timer, setTimer] = useState(); const navigate = useNavigate(); @@ -33,6 +28,12 @@ export const AllTasks = () => { setLoaded(true); }, []); + useEffect(() => { + return () => { + clearTimeout(timer); + }; + }, [timer]); + // handler for search box const handleSearch = (text) => { setSearchQuery(text); @@ -47,8 +48,7 @@ export const AllTasks = () => { useEffect(() => { setTimer( setTimeout(() => { - localStorage.removeItem("jwtToken"); - localStorage.removeItem("userID"); + localStorage.clear(); navigate("/login"); }, TIMEOUT) ); diff --git a/src/pages/Community/index.js b/src/pages/Community/index.js index 4060db8..a854d12 100644 --- a/src/pages/Community/index.js +++ b/src/pages/Community/index.js @@ -5,139 +5,51 @@ import { BackArrow } from "../../components/BackArrow"; import { NavBar } from "../NavBar"; import { useNavigate } from "react-router-dom"; import { TIMEOUT } from "../../lib/constants"; - // component imports import Dropdown from "../../components/CommunityHeader"; import Post from "../../components/CommunityPost"; - //image imports import PFP from "../../images/PFP.png"; import PlusSign from "../../images/PlusSign.png"; - +import { CreatePost } from "../../components/CreatePost"; const cx = classNames.bind(styles); - export const Community = () => { - const [posts, setPosts] = useState([ - { - user: "blah", - location: "nash", - img: PFP, - content: "lorem", - caption: "lorem", - comments: [ - { user: "user1", comment: "good comment" }, - { user: "user2", comment: "okay comment" }, - ], - }, - { - user: "blah2", - location: "nash", - img: PFP, - content: "lorem", - caption: "lorem", - comments: [ - { user: "user1", comment: "good comment" }, - { user: "user2", comment: "okay comment" }, - ], - }, - { - user: "blah2", - location: "nash", - img: PFP, - content: "lorem", - caption: "lorem", - comments: [ - { user: "user1", comment: "good comment" }, - { user: "user2", comment: "okay comment" }, - ], - }, - { - user: "blah2", - location: "nash", - img: PFP, - content: "lorem", - caption: "lorem", - comments: [ - { user: "user1", comment: "good comment" }, - { user: "user2", comment: "okay comment" }, - ], - }, - { - user: "blah2", - location: "nash", - img: PFP, - content: "lorem", - caption: "lorem", - comments: [ - { user: "user1", comment: "good comment" }, - { user: "user2", comment: "okay comment" }, - ], - }, - { - user: "blah2", - location: "nash", - img: PFP, - content: "lorem", - caption: "lorem", - comments: [ - { user: "user1", comment: "good comment" }, - { user: "user2", comment: "okay comment" }, - ], - }, - { - user: "blah2", - location: "nash", - img: PFP, - content: "lorem", - caption: "lorem", - comments: [ - { user: "user1", comment: "good comment" }, - { user: "user2", comment: "okay comment" }, - ], - }, - ]); - const [options, setOptions] = useState([ - "All Disabilities", - "Autism", - "Cant be ", - ]); - const [showCreatePost, setShowCreatePost] = useState(false); - const [timer, setTimer] = useState(); - - const navigate = useNavigate(); - useEffect(() => { - fetch("/community") - .then((response) => response.json()) - .then((data) => { - setOptions(data.options); - setPosts(data.posts); + getPosts(); + }, []); + const getPosts = () => { + fetch(process.env.REACT_APP_HOST_URL + "/posts") + .then((response) => { + return response.json(); }) - .catch((error) => { - console.log(error.message); + .then((data) => { + console.log(data); + setPosts(data); }); - }, []); - + }; + const [posts, setPosts] = useState([]); + const [options, setOptions] = useState(["All Disabilities"]); + const [showCreatePost, setShowCreatePost] = useState(false); + const [rotate, setRotate] = useState(false); + const [timer, setTimer] = useState(); + const navigate = useNavigate(); useEffect(() => { setTimer( setTimeout(() => { - localStorage.removeItem("jwtToken"); - localStorage.removeItem("userID"); + localStorage.clear(); navigate("/login"); }, TIMEOUT) ); }, []); - useEffect(() => { return () => { clearTimeout(timer); }; }, [timer]); - const createPost = () => { - console.log("called"); + setShowCreatePost(!showCreatePost); + setRotate(!rotate); }; - return (
{
+ {showCreatePost && ( + + )}
- {posts.map((post) => { + {posts.reverse().map((post) => { return ( ); })}
-
+
{ + createPost(); + }}>
); -}; +}; \ No newline at end of file diff --git a/src/pages/Community/index.module.css b/src/pages/Community/index.module.css index 1d5cecd..1cec5cd 100644 --- a/src/pages/Community/index.module.css +++ b/src/pages/Community/index.module.css @@ -31,6 +31,7 @@ body { align-items: center; overflow: hidden; position: absolute; + cursor: pointer; right: 4vw; bottom: 10vh; z-index: 2; @@ -48,6 +49,30 @@ body { cursor: pointer; } -.create_post { + +.create_post_rotate { + width: 160px; + height: 160px; + background-color: #0298ba; + box-shadow: 0 2px 16px 0 gray; + border-radius: 50%; + display: flex; + justify-content: center; + align-items: center; + overflow: hidden; + position: absolute; cursor: pointer; + right: 4vw; + bottom: 10vh; + z-index: 2; + transform: rotate(45deg); + transition: transform 0.1s ease-in-out; } + +.create_post_rotate img { + width: 70%; +} + +.create_post_rotate:hover { + cursor: pointer; +} \ No newline at end of file diff --git a/src/pages/Home/index.js b/src/pages/Home/index.js index b1cd728..d0f2d40 100644 --- a/src/pages/Home/index.js +++ b/src/pages/Home/index.js @@ -8,6 +8,9 @@ import { OnYourRadar } from "../../components/OnYourRadar"; import { Slider } from "../../components/Slider"; import ProgressBar from "@ramonak/react-progress-bar"; import { formGetRequest, getAgeGivenBirthday } from "../../lib/utils"; +import { AuthButton } from "../../components/AuthButton"; +import { useNavigate } from "react-router-dom"; +import { TIMEOUT } from "../../lib/constants"; import { Loader } from "../LoadScreen"; const cx = classNames.bind(styles); @@ -15,17 +18,19 @@ const cx = classNames.bind(styles); export const Home = () => { const { width, type } = useWindowSize(); const isMobile = type === WINDOW_TYPE.MOBILE; - // TODO: use Cache to store the user - const [lastName, setLastName] = useState("Adam's"); + const [lastName, setLastName] = useState(localStorage.getItem("lastName")); const [totalPoints, setTotalPoints] = useState(0); const [totalGoal, setTotalGoal] = useState(0); const [childrenStats, setChildrenStats] = useState([]); - // TODO: cache - const childrenId = [ - "63e5c4936d51fdbbbedb5503", - "643b22b6ee8225a6684ac159", - "643b22b6ee8225a6684ac15b", - ]; + const childrenId = JSON.parse(localStorage.getItem("children")); + const [timer, setTimer] = useState(); + + const navigate = useNavigate(); + + const logout = () => { + localStorage.clear(); + navigate("/login"); + }; const getChildrenPointsStats = async () => { let totalPoints = 0; @@ -63,12 +68,25 @@ export const Home = () => { return { totalPoints, totalGoal, childrenStats }; }; + useEffect(() => { + return () => { + clearTimeout(timer); + }; + }, [timer]); + useEffect(async () => { const { totalPoints, totalGoal, childrenStats } = await getChildrenPointsStats(); setTotalPoints(totalPoints); setTotalGoal(totalGoal); setChildrenStats(childrenStats); + console.log(localStorage); + setTimer( + setTimeout(() => { + localStorage.clear(); + navigate("/login"); + }, TIMEOUT) + ); }, []); if (childrenStats.length !== childrenId.length) { @@ -77,7 +95,11 @@ export const Home = () => { return (
{ /> + logout()} + isMobile={isMobile} + />
diff --git a/src/pages/Login/index.js b/src/pages/Login/index.js index eb6f2b8..eb8afbd 100644 --- a/src/pages/Login/index.js +++ b/src/pages/Login/index.js @@ -52,17 +52,12 @@ export const Login = () => { return response.json(); }) .then((res) => { - console.log(res); if (res.message === STATUS_CODE.SUCESS) { localStorage.setItem("userID", res.id); localStorage.setItem("jwtToken", res.token); - fetch(process.env.REACT_APP_HOST_URL + "/users/getChildren") - .then((response) => { - response.json(); - }) - .then((data) => { - localStorage.setItem("children", data); - }); + localStorage.setItem("firstName", res.firstName); + localStorage.setItem("lastName", res.lastName); + localStorage.setItem("children", JSON.stringify(res.children)); setIsLoggedIn(true); } else { setError(res.message); @@ -138,7 +133,8 @@ export const Login = () => { + style={{ textDecoration: "none", color: "rgb(2, 152, 186)" }} + > Forgot Password @@ -156,7 +152,8 @@ export const Login = () => { Don't have an account?  + style={{ textDecoration: "none", color: "rgb(2, 152, 186)" }} + > Sign up diff --git a/src/pages/NavBar/index.module.css b/src/pages/NavBar/index.module.css index c14b786..37a5cf0 100644 --- a/src/pages/NavBar/index.module.css +++ b/src/pages/NavBar/index.module.css @@ -1,25 +1,24 @@ .page { - margin: 0; - width: 100%; - display: flex; + margin: 0; + width: 100%; + display: flex; } - .page.mobile { - margin: 0; - width: 100%; + margin: 0; + width: 100%; } - .navBar { - box-shadow: 1px -5px 10px #D9D9D9; - margin: auto; - width: 100%; - height: 15vh; - left: 0; - position: fixed; - display: flex; - z-index: 100; - bottom: 0; + box-shadow: 1px -5px 10px #D9D9D9; + margin: auto; + width: 100%; + height: 7.5vh; + left: 0; + position: fixed; + display: flex; + z-index: 100; + bottom: 0; } +<<<<<<< HEAD .navBar.mobile { height: 10vh; @@ -32,40 +31,48 @@ } } */ +======= +.navBar.mobile { + height: 10vh; +} +/* @media screen and (min-width: 1000px) { + .navBar { + top: 0; + height: 15vh; + } +} */ +>>>>>>> 3654b8cf76b0bf140e1717ec3f84cfce70c80d45 .navItem.mobile { - box-sizing: border-box; - width: 33.333%; - height: 100%; - background-color: #ffffff; - padding: 5px 10px; - align-items: center; - display: flex; - justify-content: center; - margin-bottom: 20px; - cursor: pointer; + box-sizing: border-box; + width: 33.333%; + height: 100%; + background-color: #FFFFFF; + padding: 5px 10px; + align-items: center; + display: flex; + justify-content: center; + margin-bottom: 20px; + cursor: pointer; } - .navItem { - box-sizing: border-box; - width: 33.333%; - height: 100%; - background-color: #ffffff; - padding: 5px 10px; - align-items: center; - display: flex; - justify-content: center; - margin-bottom: 20px; - cursor: pointer; + box-sizing: border-box; + width: 33.333%; + height: 100%; + background-color: #FFFFFF; + padding: 5px 10px; + align-items: center; + display: flex; + justify-content: center; + margin-bottom: 20px; + cursor: pointer; } - .icon_div.mobile { - text-align: center; - display: flex; - justify-content: center; + text-align: center; + display: flex; + justify-content: center; } - .icon_div { - text-align: center; - display: flex; - justify-content: center; + text-align: center; + display: flex; + justify-content: center; } \ No newline at end of file diff --git a/src/pages/Roadmap/index.js b/src/pages/Roadmap/index.js index 952ad05..3135b9b 100644 --- a/src/pages/Roadmap/index.js +++ b/src/pages/Roadmap/index.js @@ -28,12 +28,7 @@ export const Roadmap = ({ toast }) => { const [numAllTasks, setNumAllTasks] = useState(0); const uploadRef = useRef(); const [importFile, setImportFile] = useState(null); - //TODO: get the information from cache - const childrenId = [ - "63e5c4936d51fdbbbedb5503", - "643b22b6ee8225a6684ac159", - "643b22b6ee8225a6684ac15b", - ]; + const childrenId = JSON.parse(localStorage.getItem("children")); const [timer, setTimer] = useState(); const getStats = async (childrenId) => { @@ -48,11 +43,12 @@ export const Roadmap = ({ toast }) => { disabilities: JSON.stringify(childData.disabilities), age: JSON.stringify(age), //TODO: fix the data for upcoming vs priority - priority: JSON.stringify(2), + priority: JSON.stringify(PRIORITY_LEVEL.PRIORITY_LEVEL), }; // get tasks based on children's attributes const url = formGetRequest("/tasks/getStats/", params); + console.log(url); const statsResponse = await fetch(process.env.REACT_APP_HOST_URL + url); const statsData = await statsResponse.json(); childrenStatsData.numUpcoming += statsData.numUpcoming; @@ -70,6 +66,21 @@ export const Roadmap = ({ toast }) => { setLoaded(true); }, []); + useEffect(() => { + return () => { + clearTimeout(timer); + }; + }, [timer]); + + useEffect(() => { + setTimer( + setTimeout(() => { + localStorage.clear(); + navigate("/login"); + }, TIMEOUT) + ); + }, []); + // set the import csv file useEffect(() => { if (importFile) { diff --git a/src/pages/SignUp/index.js b/src/pages/SignUp/index.js index 4ff3cd9..6e97b4c 100644 --- a/src/pages/SignUp/index.js +++ b/src/pages/SignUp/index.js @@ -4,18 +4,25 @@ import { AUTH_INPUT_LABELS, SCHOOL_DISTRICT, DISABILITY, + ROUTES, WINDOW_TYPE, STATUS_CODE, } from "../../lib/constants"; import { AuthInputBlock } from "../../components/AuthInputBlock"; import { AuthSelectBlock } from "../../components/AuthSelectBlock"; import { AuthButton } from "../../components/AuthButton"; -import { useState } from "react"; -import { signUp } from "../../lib/services"; +import { useState, useEffect } from "react"; +import { signUp, signUpChildren, mongoCheck } from "../../lib/services"; import { useNavigate } from "react-router-dom"; import { useWindowSize } from "../../lib/hooks"; +import { AddChild } from "../../components/AddChild"; const cx = classNames.bind(styles); +//CHANGE THE BOXES FOR EMPTY CHILD +// WHERE IS OUR VERIFICATION +// ADD CHECKS FOR CHILD INFORMATION/HAS ALL CHILD INFORMATION +// DELETE CHILD/EDIT CHILD/VIEW CHILD + // Register page for authentication export const SignUp = ({ toast }) => { const navigate = useNavigate(); @@ -29,38 +36,155 @@ export const SignUp = ({ toast }) => { const [disability, setDisability] = useState([]); const [zipCode, setZipCode] = useState(""); const [phoneNumber, setPhoneNumber] = useState(""); + const [children, setChildren] = useState([]); + + const [addChildPopUp, setAddChildPopUp] = useState(false); + const [childIDArray, setChildIDArray] = useState([]); + const [registered, setRegistered] = useState(false); + const [error, setError] = useState(""); + const [renderedChildren, setRenderedChildren] = useState(); - const onRegister = () => { + async function addChildren() { + try { + const promises = children.map(async (child) => { + let disArray = []; + for (let i = 0; i < child.disabilities.length; i++) { + disArray.push(child.disabilities[i].label); + } + let fn = child.firstName; + let bd = child.birthDate; + let sd = child.schoolDistrict; + const result = await signUpChildren({ + firstName: fn, + birthDate: bd, + disabilities: disArray, + schoolDistrict: sd, + }); + return result; + }); + const results = await Promise.all(promises); + console.log("returned child ids:", results); + setChildIDArray(results); + } catch (error) { + console.log(error); + } + } + + useEffect(() => { + if (childIDArray.length === children.length && registered) { + mongoCheck(email).then((res) => { + if (res.status === "Found") { + setError("Email already exists"); + toast(error); + } else { + navigate(ROUTES.VERIFICATION, { + state: { + email: email, + password: password, + firstName: firstName, + lastName: lastName, + schoolDistrict: schoolDistrict, + zipCode: zipCode, + phoneNumber: phoneNumber, + children: childIDArray, + }, + }); + } + }); + } + }, [childIDArray]); + + const onRegister = async () => { if (!email) toast("Please provide your email"); else if (!password) toast("Please provide your password"); else if (password.length < 8) toast("Password length must be at least 8"); else if (password !== repeatPassword) toast("Passwords mismatch"); else if (!firstName) toast("Please provide your first name"); else if (!lastName) toast("Please provide your last name"); - else if (!schoolDistrict) - toast("Please provide your children's school district"); - else if (!disability) toast("Please provide your children's disabilities"); else if (!zipCode) toast("Please provide your zip code"); else if (!phoneNumber) toast("Please provide your phone number"); + else if (children.length === 0 || children === []) + toast("Please add at least one child"); else { // send response to backend and create a record - signUp({ - email, - password, - firstName, - lastName, - schoolDistrict, - zipCode, - phoneNumber, - }) - .then((res) => { - const { status } = res; - if (status === STATUS_CODE.SUCESS) navigate("/login"); - }) - .catch((err) => toast("Internal error")); + addChildren(); + setRegistered(true); } }; + function handleClick(i) { + children.splice(i, 1); + renderChildrenFunc(); + } + + useEffect(() => { + renderChildrenFunc(); + }, [children]); + + function renderChildrenFunc() { + const inputs = []; + if (children.length >= 1) { + for (let j = 0; j < children.length / 3; j++) { + const array = []; + for (let i = j * 3; i < children.length && i < j * 3 + 3; i++) { + const child = children[i]; + array.push( +
+
+

+ {child.firstName} +

+ +
+
+ ); + } + inputs.push( +
+ {array[0]} + {array.length >= 1 && array[1]} + {array.length >= 2 && array[2]} +
+ ); + } + } + setRenderedChildren(inputs); + } + return ( <> { onChange={setLastName} isMobile={isMobile} /> - - { onChange={setPhoneNumber} isMobile={isMobile} /> + {renderedChildren} + setAddChildPopUp(true)} + isMobile={isMobile} + /> + {addChildPopUp && ( + + )} { console.log(localStorage); setTimer( setTimeout(() => { - localStorage.removeItem("jwtToken"); - localStorage.removeItem("userID"); + localStorage.clear(); navigate("/login"); }, TIMEOUT) ); @@ -90,6 +89,3 @@ export const TaskDetails = () => {
); }; - -// need to import image/svg from backend -// for page and each resource card diff --git a/src/pages/Upcoming/index.js b/src/pages/Upcoming/index.js index d05d9cc..9af9632 100644 --- a/src/pages/Upcoming/index.js +++ b/src/pages/Upcoming/index.js @@ -17,11 +17,7 @@ export const Upcoming = ({ toast }) => { const [taskArray, setTaskArray] = useState([]); const [loaded, setLoaded] = useState(false); //TODO: get information using cache - const childrenId = [ - "63e5c4936d51fdbbbedb5503", - "643b22b6ee8225a6684ac159", - "643b22b6ee8225a6684ac15b", - ]; + const childrenId = JSON.parse(localStorage.getItem("children")); const [timer, setTimer] = useState(); const navigate = useNavigate(); @@ -39,8 +35,7 @@ export const Upcoming = ({ toast }) => { useEffect(() => { setTimer( setTimeout(() => { - localStorage.removeItem("jwtToken"); - localStorage.removeItem("userID"); + localStorage.clear(); navigate("/login"); }, TIMEOUT) ); diff --git a/testRequests.rest b/testRequests.rest index c3522b9..c92bcc4 100644 --- a/testRequests.rest +++ b/testRequests.rest @@ -28,7 +28,7 @@ Content-Type: application/json ### -GET http://localhost:3001/children/ +GET http://localhost:3001/children/643b22b6ee8225a6684ac15b Content-Type: application/json @@ -46,7 +46,7 @@ Content-Type: application/json ### -GET http://localhost:3001/tasks/byAttributes/?disabilities=["ADHD","disability2"]&age=30 +GET http://localhost:3001/tasks/byAttributes/?disabilities=["ADHD","disability2"] Content-Type: application/json ### @@ -63,5 +63,9 @@ Content-Type: application/json } ### -GET http://localhost:3001/tasks +GET http://localhost:3001/tasks/byAttributes/?disabilities=["ADHD/ADD"]&age="Adult" +Content-Type: application/json + +### +GET http://localhost:3001/tasks/getStats/?disabilities=["ADHD/ADD"]&age="Adult"&priority=2 Content-Type: application/json \ No newline at end of file From b287a9cc497764fc4afceba1b2c0790b11465a5d Mon Sep 17 00:00:00 2001 From: Xiaohan Liu Date: Sat, 22 Apr 2023 19:08:34 -0500 Subject: [PATCH 16/16] added visibility only to admin --- src/pages/Roadmap/index.js | 56 ++++++++++++++++++++------------------ 1 file changed, 29 insertions(+), 27 deletions(-) diff --git a/src/pages/Roadmap/index.js b/src/pages/Roadmap/index.js index 3135b9b..f54ade7 100644 --- a/src/pages/Roadmap/index.js +++ b/src/pages/Roadmap/index.js @@ -1,7 +1,6 @@ -import React, { useState, useEffect, useRef, createContext } from "react"; +import React, { useState, useEffect, useRef } from "react"; import classNames from "classnames/bind"; import Papa from "papaparse"; -import { useAuth } from "../../lib/AuthContext"; import styles from "./index.module.css"; import { ROUTES, PRIORITY_LEVEL, TIMEOUT } from "../../lib/constants"; import { ReactComponent as Calender } from "../../svg/roadmapCalender.svg"; @@ -30,6 +29,7 @@ export const Roadmap = ({ toast }) => { const [importFile, setImportFile] = useState(null); const childrenId = JSON.parse(localStorage.getItem("children")); const [timer, setTimer] = useState(); + const userId = localStorage.getItem("userID"); const getStats = async (childrenId) => { let childrenStatsData = { numUpcoming: 0, numAll: 0 }; @@ -42,13 +42,11 @@ export const Roadmap = ({ toast }) => { const params = { disabilities: JSON.stringify(childData.disabilities), age: JSON.stringify(age), - //TODO: fix the data for upcoming vs priority priority: JSON.stringify(PRIORITY_LEVEL.PRIORITY_LEVEL), }; // get tasks based on children's attributes const url = formGetRequest("/tasks/getStats/", params); - console.log(url); const statsResponse = await fetch(process.env.REACT_APP_HOST_URL + url); const statsData = await statsResponse.json(); childrenStatsData.numUpcoming += statsData.numUpcoming; @@ -143,29 +141,33 @@ export const Roadmap = ({ toast }) => { height: "80vh", }} > -
- - setImportFile(e.target.files[0])} - /> -
-
- -
+ {userId === process.env.REACT_APP_ADMIN_ID && ( +
+
+ + setImportFile(e.target.files[0])} + /> +
+
+ +
+
+ )}
navigate(ROUTES.UPCOMING_TASKS)}