diff --git a/.gitignore b/.gitignore index a6d314b..1f9e232 100644 --- a/.gitignore +++ b/.gitignore @@ -16,12 +16,9 @@ # misc .DS_Store .env.local -.env.development.local -.env.test.local -.env.production.local +.env.* +!.env.template npm-debug.log* yarn-debug.log* yarn-error.log* -.env.production -.env.development diff --git a/src/App.js b/src/App.js index 05f10dd..1946186 100644 --- a/src/App.js +++ b/src/App.js @@ -7,6 +7,7 @@ import Success from './screens/SuccessScreen'; import './App.css'; import Verify from './screens/VerifyScreen'; import Scanner from './screens/ScannerScreen'; +import Lockout from './screens/LockoutScreen'; function App() { return ( @@ -25,6 +26,9 @@ function App() { + + + diff --git a/src/app/store.js b/src/app/store.js index 1457d32..0220126 100644 --- a/src/app/store.js +++ b/src/app/store.js @@ -1,8 +1,10 @@ import { configureStore } from '@reduxjs/toolkit'; import authSlice from '../features/auth/authSlice'; +import covidSlice from '../features/auth/covidSlice'; export const store = configureStore({ reducer: { auth: authSlice, + covid: covidSlice, }, }); diff --git a/src/features/auth/covidSlice.js b/src/features/auth/covidSlice.js new file mode 100644 index 0000000..14691c8 --- /dev/null +++ b/src/features/auth/covidSlice.js @@ -0,0 +1,25 @@ +import { createSlice } from '@reduxjs/toolkit'; +import Cookies from 'js-cookie'; + +const initialState = { + isCovidPositive: Cookies.get('covidPositive') === 'true' ? true : false, +}; + +export const covidSlice = createSlice({ + name: 'covid', + initialState, + reducers: { + setCovidPositive: state => { + state.isCovidPositive = true; + Cookies.set('covidPositive', true); + }, + setCovidNegative: state => { + state.isCovidPositive = false; + Cookies.set('covidPositive', false); + } + }, +}); + +export const { setCovidPositive, setCovidNegative } = covidSlice.actions; + +export default covidSlice.reducer; diff --git a/src/screens/HomeScreen.js b/src/screens/HomeScreen.js index 1d19593..1626813 100644 --- a/src/screens/HomeScreen.js +++ b/src/screens/HomeScreen.js @@ -1,4 +1,10 @@ import { + AlertDialog, + AlertDialogBody, + AlertDialogContent, + AlertDialogFooter, + AlertDialogHeader, + AlertDialogOverlay, Button, Divider, Flex, @@ -6,12 +12,14 @@ import { Link, Spinner, Text, + useToast, } from '@chakra-ui/react'; import axios from 'axios'; -import { Fragment, React, useEffect, useState } from 'react'; +import { Fragment, React, useEffect, useRef, useState } from 'react'; import { useDispatch, useSelector } from 'react-redux'; import { Redirect, useHistory } from 'react-router-dom'; import { authLogout } from '../features/auth/authSlice'; +import { setCovidPositive } from '../features/auth/covidSlice'; function QRCode() { const [url, setURL] = useState(null); @@ -41,6 +49,93 @@ function QRCode() { } } +function ConfirmCOVIDPositiveAlertDialog() { + + const [isOpen, setOpen] = useState(false); + const toast = useToast(); + const history = useHistory(); + const dispatch = useDispatch(); + const onClose = () => { setOpen(false) } + const showErrorToast = (errorMessage = "An error has occured.") => { + toast.closeAll(); + toast({ + title: 'Error!', + description: errorMessage, + status: 'error', + duration: 5000 + }); + } + const onConfirm = () => { + toast({ + title: 'Confirming', + description: 'Hold on while we confirm with our servers.', + status: 'info', + duration: 10000 + }); + axios.post(`${process.env.REACT_APP_API_URL}/covid`,{ + setPositive: true, + },{withCredentials:true}) + .then(res => { + if(res.data.covidPositive){ + dispatch(setCovidPositive()); + toast.closeAll(); + toast({ + title: "Confirmed!", + status: 'info', + duration: 2000, + }); + }else{ + showErrorToast(); + } + }) + .catch(err => { + console.log(err); + try{ + if(err.response.status === 401){ + showErrorToast("You are not logged in!"); + history.push("/login"); + }else{ + showErrorToast(); + } + }catch(e){ + showErrorToast(); + } + }); + setOpen(false); + } + const cancelRef = useRef(); + + return ( + <> + + + + + + Confirm Tested COVID19 Positive + + + Please confirm that you have been tested POSITIVE with + COVID19. Upon confirmation, this app will inform the people + you have come in contact with in the last 7 days. + + + + + + + + + + ); +} + function Home() { const history = useHistory(); const dispatch = useDispatch(); @@ -51,7 +146,18 @@ function Home() { }; const isAuthenticated = useSelector(state => state.auth.isAuthenticated); + const isCovidPositive = useSelector(state => state.covid.isCovidPositive); + useEffect( ()=>{ + axios.post(`${process.env.REACT_APP_API_URL}/covid`,{},{withCredentials:true}) + .then(res=>{ + if(res.data.covidPositive){ + dispatch(setCovidPositive()); + } + }) + .catch(err=>{}); +}, [dispatch]); if (!isAuthenticated) return ; + if (isCovidPositive) return ; return ( )} - diff --git a/src/screens/LockoutScreen.js b/src/screens/LockoutScreen.js new file mode 100644 index 0000000..02ce749 --- /dev/null +++ b/src/screens/LockoutScreen.js @@ -0,0 +1,75 @@ +import { Flex, Heading, Text, useToast } from "@chakra-ui/react"; +import axios from "axios"; +import { useEffect } from "react"; +import { useDispatch, useSelector } from "react-redux"; +import { Redirect, useHistory } from "react-router-dom"; +import { authLogout } from "../features/auth/authSlice"; +import { setCovidNegative, setCovidPositive } from "../features/auth/covidSlice"; + +function Lockout() { + const isAuthenticated = useSelector(state => state.auth.isAuthenticated); + const isCovidPositive = useSelector(state => state.covid.isCovidPositive); + const dispatch = useDispatch(); + const history = useHistory(); + const toast = useToast(); + + useEffect(() => { + toast({ + title: 'Checking your lockout status...', + status: 'info', + duration: 10000, + }); + axios.post(`${process.env.REACT_APP_API_URL}/covid`, {}, { withCredentials: true }) + .then(res => { + toast.closeAll(); + if (res.data.covidPositive) { + dispatch(setCovidPositive()); + } else if (res.data.covidPositive === false) { + dispatch(setCovidNegative()); + } + }) + .catch(err => { + try { + if (err.response.status === 401) { + dispatch(authLogout()); + history.push("/login"); + }else{ + toast.closeAll(); + toast({ + title: 'Server Error Occurred', + status: 'error', + duration: 10000, + }); + } + } + catch (e) { } + }); + + }, [dispatch, history, toast]); + + if (!isAuthenticated) return ; + if (!isCovidPositive) return ; + + return ( + + + Lockout + + You have reported that you have been tested POSITIVE with COVID19. + This lockout is to remind you to quarantine yourself according to local + COVID19 health policies. This lockout will automatically be lifted after + 14 days. +

+ Please avoid contact with other people for the duration of this lockout! +
+
+
+ ); +} + +export default Lockout; \ No newline at end of file diff --git a/src/screens/ScannerScreen.js b/src/screens/ScannerScreen.js index 1fb0a33..c18f16b 100644 --- a/src/screens/ScannerScreen.js +++ b/src/screens/ScannerScreen.js @@ -5,6 +5,7 @@ import QrReader from 'react-qr-reader'; import { useDispatch, useSelector } from 'react-redux'; import { Redirect, useHistory } from 'react-router-dom'; import { authLogout } from '../features/auth/authSlice'; +import { setCovidPositive } from '../features/auth/covidSlice'; function Scanner() { const toast = useToast(); @@ -87,7 +88,18 @@ function Scanner() { }, [scanData, dispatch, history, toast]); const isAuthenticated = useSelector(state => state.auth.isAuthenticated); + const isCovidPositive = useSelector(state => state.covid.isCovidPositive); + useEffect( ()=>{ + axios.post(`${process.env.REACT_APP_API_URL}/covid`,{},{withCredentials:true}) + .then(res=>{ + if(res.data.covidPositive){ + dispatch(setCovidPositive()); + } + }) + .catch(err=>{}); +}, [dispatch]); if (!isAuthenticated) return ; + if (isCovidPositive) return ; return (