Nareshkumar Rao
3 years ago
9 changed files with 302 additions and 132 deletions
@ -0,0 +1 @@ |
|||
{} |
@ -1,8 +1,8 @@ |
|||
import { configureStore } from "@reduxjs/toolkit"; |
|||
import authSlice from "../features/auth/authSlice"; |
|||
import { configureStore } from '@reduxjs/toolkit'; |
|||
import authSlice from '../features/auth/authSlice'; |
|||
|
|||
export const store = configureStore({ |
|||
reducer: { |
|||
auth: authSlice, |
|||
}, |
|||
}) |
|||
reducer: { |
|||
auth: authSlice, |
|||
}, |
|||
}); |
|||
|
@ -1,23 +1,23 @@ |
|||
import { createSlice } from '@reduxjs/toolkit' |
|||
import { createSlice } from '@reduxjs/toolkit'; |
|||
import Cookies from 'js-cookie'; |
|||
|
|||
const initialState = { |
|||
isAuthenticated: Cookies.get("authorized"), |
|||
isAuthenticated: Cookies.get('authorized'), |
|||
}; |
|||
|
|||
export const authSlice = createSlice({ |
|||
name: 'auth', |
|||
initialState, |
|||
reducers: { |
|||
authLogin: (state, action) => { |
|||
state.isAuthenticated = true; |
|||
}, |
|||
authLogout: (state) => { |
|||
state.isAuthenticated = false; |
|||
}, |
|||
name: 'auth', |
|||
initialState, |
|||
reducers: { |
|||
authLogin: (state, action) => { |
|||
state.isAuthenticated = true; |
|||
}, |
|||
authLogout: state => { |
|||
state.isAuthenticated = false; |
|||
}, |
|||
}, |
|||
}); |
|||
|
|||
export const {authLogin, authLogout} = authSlice.actions; |
|||
export const { authLogin, authLogout } = authSlice.actions; |
|||
|
|||
export default authSlice.reducer; |
|||
export default authSlice.reducer; |
|||
|
@ -0,0 +1,129 @@ |
|||
import { FormControl, Box, Flex, Image, FormLabel, Input, Select, Heading, Button, useToast } from '@chakra-ui/react'; |
|||
import axios from 'axios'; |
|||
import { useState } from 'react'; |
|||
import { useDispatch } from 'react-redux'; |
|||
import { useHistory } from 'react-router-dom'; |
|||
import { authLogin } from '../features/auth/authSlice'; |
|||
|
|||
function OrgSelect(props) { |
|||
const orgs = ["MISI: Solidariti", "UNDI18"]; |
|||
const orgOptions = orgs.map((name) => { |
|||
return ( |
|||
<option value={name}>{name}</option> |
|||
) |
|||
}); |
|||
|
|||
return ( |
|||
<Select placeholder={props.placeholder} onChange={props.onChange}> |
|||
{orgOptions} |
|||
</Select> |
|||
); |
|||
} |
|||
|
|||
function Create() { |
|||
|
|||
const dispatch = useDispatch(); |
|||
const toast = useToast(); |
|||
const history = useHistory(); |
|||
|
|||
const [name, setName] = useState(null); |
|||
const [email, setEmail] = useState(null); |
|||
const [phoneNumber, setPhoneNumber] = useState(null); |
|||
const [org, setOrg] = useState(null); |
|||
const [password, setPassword] = useState(null); |
|||
|
|||
const handleSubmit = (e) => { |
|||
e.preventDefault(); |
|||
|
|||
if (!name | !email | !phoneNumber | !org | !password) { |
|||
toast({ |
|||
title: 'Problem!', |
|||
description: 'Please fill in all the fields', |
|||
status: 'error', |
|||
duration: 2000, |
|||
isClosable: true, |
|||
}); |
|||
return; |
|||
} |
|||
|
|||
axios |
|||
.post( |
|||
`${process.env.REACT_APP_API_URL}/create`, |
|||
{ |
|||
name: name, |
|||
email: email, |
|||
org: org, |
|||
phoneNumber: org, |
|||
password: password, |
|||
}, |
|||
{ |
|||
withCredentials: true, |
|||
} |
|||
) |
|||
.then(response => { |
|||
if (response.data.success) { |
|||
dispatch(authLogin()); |
|||
history.push('/home'); |
|||
} else { |
|||
toast({ |
|||
title: 'An error occurred', |
|||
description: response.data.message, |
|||
status: 'error', |
|||
duration: 5000, |
|||
isClosable: true, |
|||
}); |
|||
} |
|||
}) |
|||
.catch(e=>{ |
|||
if(e.response.status === 401){ |
|||
toast({ |
|||
title: 'Verification Error', |
|||
description: "You couldn't be verified. Please try scanning the verification QR Code again.", |
|||
status: 'error', |
|||
duration: 9000, |
|||
isClosable: true, |
|||
}); |
|||
} |
|||
}); |
|||
} |
|||
|
|||
return ( |
|||
<Flex |
|||
height="100vh" |
|||
background="teal.100" |
|||
alignItems="center" |
|||
justifyContent="center" |
|||
> |
|||
<Flex direction="column" background="white" p={12} rounded={6}> |
|||
<Heading mb={6}> |
|||
Create Account |
|||
</Heading> |
|||
<form onSubmit={handleSubmit}> |
|||
<FormControl mb={6}> |
|||
<FormLabel>Name:</FormLabel> |
|||
<Input onChange={e => setName(e.target.value)} /> |
|||
</FormControl> |
|||
<FormControl mb={6}> |
|||
<FormLabel >Email:</FormLabel> |
|||
<Input type="email" onChange={e => setEmail(e.target.value)} /> |
|||
</FormControl> |
|||
<FormControl mb={6}> |
|||
<FormLabel>Phone Number:</FormLabel> |
|||
<Input onChange={e => setPhoneNumber(e.target.value)} /> |
|||
</FormControl> |
|||
<FormControl mb={6}> |
|||
<FormLabel>Organization:</FormLabel> |
|||
<OrgSelect placeholder="Select Organization" onChange={e => setOrg(e.target.value)} /> |
|||
</FormControl> |
|||
<FormControl mb={6}> |
|||
<FormLabel>Password:</FormLabel> |
|||
<Input type="password" onChange={e => setPassword(e.target.value)} /> |
|||
</FormControl> |
|||
<Button type="submit">Create!</Button> |
|||
</form> |
|||
</Flex> |
|||
</Flex> |
|||
) |
|||
} |
|||
|
|||
export default Create; |
@ -1,54 +1,52 @@ |
|||
import { |
|||
Box, Flex, Image |
|||
} from '@chakra-ui/react'; |
|||
import { Box, Flex, Image } from '@chakra-ui/react'; |
|||
import axios from 'axios'; |
|||
import { React, useState } from 'react'; |
|||
import { useDispatch, useSelector } from 'react-redux'; |
|||
import { Redirect } from 'react-router-dom'; |
|||
import { authLogout } from '../features/auth/authSlice'; |
|||
|
|||
function QRCode(){ |
|||
function QRCode() { |
|||
const [url, setURL] = useState(null); |
|||
const dispatch = useDispatch(); |
|||
|
|||
const [url, setURL] = useState(null); |
|||
const dispatch = useDispatch(); |
|||
|
|||
if(!url){ |
|||
axios.get(`${process.env.REACT_APP_API_URL}/code`,{withCredentials:true}) |
|||
.then(response =>{ |
|||
if(!response.data.error){ |
|||
if (!url) { |
|||
axios |
|||
.get(`${process.env.REACT_APP_API_URL}/code`, { withCredentials: true }) |
|||
.then(response => { |
|||
if (!response.data.error) { |
|||
setURL(response.data.data); |
|||
} |
|||
}) |
|||
.catch((err)=>{ |
|||
if(err.response.status === 401){ |
|||
.catch(err => { |
|||
if (err.response.status === 401) { |
|||
dispatch(authLogout()); |
|||
} |
|||
}); |
|||
|
|||
} |
|||
|
|||
if(url){ |
|||
return ( |
|||
<Image src={url} /> |
|||
) |
|||
}else{ |
|||
return ( |
|||
<Box /> |
|||
) |
|||
} |
|||
} |
|||
|
|||
function Home() { |
|||
const isAuthenticated = useSelector((state) => state.auth.isAuthenticated); |
|||
if (!isAuthenticated) return <Redirect to="/login" /> |
|||
|
|||
return ( |
|||
<Flex height="100vh" background="teal.100" alignItems="center" justifyContent="center"> |
|||
<Flex direction="column" background="white" p={12} rounded={6}> |
|||
<QRCode/> |
|||
</Flex> |
|||
</Flex> |
|||
); |
|||
|
|||
if (url) { |
|||
return <Image src={url} />; |
|||
} else { |
|||
return <Box />; |
|||
} |
|||
} |
|||
|
|||
function Home() { |
|||
const isAuthenticated = useSelector(state => state.auth.isAuthenticated); |
|||
if (!isAuthenticated) return <Redirect to="/login" />; |
|||
|
|||
return ( |
|||
<Flex |
|||
height="100vh" |
|||
background="teal.100" |
|||
alignItems="center" |
|||
justifyContent="center" |
|||
> |
|||
<Flex direction="column" background="white" p={12} rounded={6}> |
|||
<QRCode /> |
|||
</Flex> |
|||
</Flex> |
|||
); |
|||
} |
|||
|
|||
export default Home; |
|||
export default Home; |
|||
|
@ -1,89 +1,125 @@ |
|||
import { |
|||
Button, Divider, Flex, FormControl, |
|||
FormLabel, Heading, Input, useToast |
|||
Button, |
|||
Divider, |
|||
Flex, |
|||
FormControl, |
|||
FormLabel, |
|||
Heading, |
|||
Input, |
|||
useToast, |
|||
} from '@chakra-ui/react'; |
|||
import axios from 'axios'; |
|||
import { React, useState } from 'react'; |
|||
import { useDispatch } from 'react-redux'; |
|||
import { useHistory } from 'react-router-dom'; |
|||
import { useDispatch, useSelector } from 'react-redux'; |
|||
import { Redirect, useHistory } from 'react-router-dom'; |
|||
import { authLogin } from '../features/auth/authSlice'; |
|||
|
|||
function Login() { |
|||
const [email, setEmail] = useState(null); |
|||
const [password, setPassword] = useState(null); |
|||
const toast = useToast(); |
|||
const history = useHistory(); |
|||
const dispatch = useDispatch(); |
|||
|
|||
const handleSubmit = (e) => { |
|||
|
|||
if(!email | !password){ |
|||
toast({ |
|||
title: "Invalid Login", |
|||
description: "Please fill in email and password", |
|||
status: "error", |
|||
duration: 9000, |
|||
isClosable: true, |
|||
}); |
|||
return; |
|||
} |
|||
|
|||
axios.post(`${process.env.REACT_APP_API_URL}/login`,{ |
|||
email: email, |
|||
password: password, |
|||
}, |
|||
{ |
|||
withCredentials: true, |
|||
}) |
|||
.then(response =>{ |
|||
if(response.data.authorized){ |
|||
const [email, setEmail] = useState(null); |
|||
const [password, setPassword] = useState(null); |
|||
const toast = useToast(); |
|||
const history = useHistory(); |
|||
const dispatch = useDispatch(); |
|||
|
|||
const isAuthenticated = useSelector(state => state.auth.isAuthenticated); |
|||
if (isAuthenticated) return <Redirect to="/home" />; |
|||
|
|||
const handleSubmit = e => { |
|||
if (!email | !password) { |
|||
toast({ |
|||
title: 'Invalid Login', |
|||
description: 'Please fill in email and password', |
|||
status: 'error', |
|||
duration: 9000, |
|||
isClosable: true, |
|||
}); |
|||
return; |
|||
} |
|||
|
|||
axios |
|||
.post( |
|||
`${process.env.REACT_APP_API_URL}/login`, |
|||
{ |
|||
email: email, |
|||
password: password, |
|||
}, |
|||
{ |
|||
withCredentials: true, |
|||
} |
|||
) |
|||
.then(response => { |
|||
if (response.data.authorized) { |
|||
dispatch(authLogin()); |
|||
history.push("/home"); |
|||
|
|||
}else{ |
|||
history.push('/home'); |
|||
} else { |
|||
toast({ |
|||
title: "An error occurred", |
|||
title: 'An error occurred', |
|||
description: response.data.message, |
|||
status: "error", |
|||
status: 'error', |
|||
duration: 9000, |
|||
isClosable: true, |
|||
}); |
|||
} |
|||
}) |
|||
.catch((err)=>{ |
|||
.catch(err => { |
|||
toast({ |
|||
title: "An error occurred", |
|||
description: "Sorry, an error occurred on our side.", |
|||
status: "error", |
|||
title: 'An error occurred', |
|||
description: 'Sorry, an error occurred on our side.', |
|||
status: 'error', |
|||
duration: 9000, |
|||
isClosable: true, |
|||
}); |
|||
}); |
|||
|
|||
e.preventDefault(); |
|||
}; |
|||
|
|||
return ( |
|||
<Flex height="100vh" background="teal.100" alignItems="center" justifyContent="center"> |
|||
<Flex direction="column" background="white" p={12} rounded={6}> |
|||
<Heading size="xl" mb={6}>SSR Covid Tracing</Heading> |
|||
<Heading size="lg" mb={4}>Login</Heading> |
|||
<form onSubmit={handleSubmit}> |
|||
<FormControl mb={6}> |
|||
<FormLabel>Email address</FormLabel> |
|||
<Input type="email" colorScheme="teal" onChange={(event)=>setEmail(event.target.value)}/> |
|||
</FormControl> |
|||
<FormControl mb={6}> |
|||
<FormLabel>Password</FormLabel> |
|||
<Input type="password" colorScheme="teal" onChange={(event)=>setPassword(event.target.value)}/> |
|||
</FormControl> |
|||
<Button mb={6} type="submit">Login!</Button> |
|||
</form> |
|||
<Divider mb={6} /> |
|||
<Button onClick={() => { history.push("/validate") }}>Get Validated!</Button> |
|||
</Flex> |
|||
|
|||
e.preventDefault(); |
|||
}; |
|||
|
|||
return ( |
|||
<Flex |
|||
height="100vh" |
|||
background="teal.100" |
|||
alignItems="center" |
|||
justifyContent="center" |
|||
> |
|||
<Flex direction="column" background="white" p={12} rounded={6}> |
|||
<Heading size="xl" mb={6}> |
|||
SSR Covid Tracing |
|||
</Heading> |
|||
<Heading size="lg" mb={4}> |
|||
Login |
|||
</Heading> |
|||
<form onSubmit={handleSubmit}> |
|||
<FormControl mb={6}> |
|||
<FormLabel>Email address</FormLabel> |
|||
<Input |
|||
type="email" |
|||
colorScheme="teal" |
|||
onChange={event => setEmail(event.target.value)} |
|||
/> |
|||
</FormControl> |
|||
<FormControl mb={6}> |
|||
<FormLabel>Password</FormLabel> |
|||
<Input |
|||
type="password" |
|||
colorScheme="teal" |
|||
onChange={event => setPassword(event.target.value)} |
|||
/> |
|||
</FormControl> |
|||
<Button mb={6} type="submit"> |
|||
Login! |
|||
</Button> |
|||
</form> |
|||
<Divider mb={6} /> |
|||
<Button |
|||
onClick={() => { |
|||
history.push('/validate'); |
|||
}} |
|||
> |
|||
Get Validated! |
|||
</Button> |
|||
</Flex> |
|||
); |
|||
} |
|||
</Flex> |
|||
); |
|||
} |
|||
|
|||
export default Login; |
|||
export default Login; |
|||
|
Loading…
Reference in new issue