diff options
Diffstat (limited to 'client/src')
18 files changed, 287 insertions, 190 deletions
diff --git a/client/src/App.js b/client/src/App.js index c39f14e..0d6d904 100644 --- a/client/src/App.js +++ b/client/src/App.js @@ -1,9 +1,11 @@ import React from 'react' +import LanguageSelect from './components/LanguageSelect/LanguageSelect' import Index from './routes' const App = () => { return ( <> + <LanguageSelect /> <Index /> </> ) diff --git a/client/src/components/Input/Input.module.css b/client/src/components/Input/Input.module.css index b02591c..59867e9 100644 --- a/client/src/components/Input/Input.module.css +++ b/client/src/components/Input/Input.module.css @@ -2,6 +2,7 @@ display: flex; justify-content: center; font-family: 'Barlow'; + margin: 15px 0px; font-size: var(--font-medium-s); } @@ -11,7 +12,7 @@ } .input__field { - width: 300px; + width: 330px; margin: 10px 0px; padding: 18px 10px; border: 3px solid; diff --git a/client/src/components/LanguageSelect/LanguageSelect.js b/client/src/components/LanguageSelect/LanguageSelect.jsx index ac455b8..dd2997f 100644 --- a/client/src/components/LanguageSelect/LanguageSelect.js +++ b/client/src/components/LanguageSelect/LanguageSelect.jsx @@ -1,13 +1,9 @@ -import React from 'react' +import React, { useState, useEffect } from 'react' import { useTranslation } from 'react-i18next' import i18next from 'i18next' +import { Button, Popover, List, ListItem, ListSubheader } from '@mui/material' -import ArrowDropDown from '@mui/icons-material/ArrowDropDown' -import Button from '@mui/material/Button' -import Popover from '@mui/material/Popover' -import List from '@mui/material/List' -import ListItem from '@mui/material/ListItem' -import ListSubheader from '@mui/material/ListSubheader' +import styles from './LanguageSelect.module.css' const languageMap = { en: { label: 'English', dir: 'ltr', active: true }, @@ -18,16 +14,22 @@ const LanguageSelect = () => { const selected = localStorage.getItem('i18nextLng') || 'en' const { t } = useTranslation() - const [menuAnchor, setMenuAnchor] = React.useState(null) - React.useEffect(() => { + const [menuAnchor, setMenuAnchor] = useState(null) + useEffect(() => { document.body.dir = languageMap[selected]?.dir }, [menuAnchor, selected]) return ( - <div className="d-flex justify-content-end align-items-center language-select-root"> - <Button onClick={({ currentTarget }) => setMenuAnchor(currentTarget)}> - {languageMap[selected]?.label} - <ArrowDropDown fontSize="small" /> + <div className={styles.language}> + <Button + onClick={({ currentTarget }) => setMenuAnchor(currentTarget)} + sx={{ margin: '0px 15px', padding: '0px' }} + > + <img + src={`${process.env.PUBLIC_URL}/assets/images/language.svg`} + height="80px" + width="80px" + /> </Button> <Popover open={!!menuAnchor} @@ -44,7 +46,7 @@ const LanguageSelect = () => { > <div> <List> - <ListSubheader>{t('select_language')}</ListSubheader> + <ListSubheader>{t('SELECT_LANGUAGE')}</ListSubheader> {Object.keys(languageMap)?.map((item) => ( <ListItem button diff --git a/client/src/components/LanguageSelect/LanguageSelect.module.css b/client/src/components/LanguageSelect/LanguageSelect.module.css new file mode 100644 index 0000000..9a4029c --- /dev/null +++ b/client/src/components/LanguageSelect/LanguageSelect.module.css @@ -0,0 +1,5 @@ +.language { + position: absolute; + top: 100px; + right: 150px; +} diff --git a/client/src/components/Modal/Modal.jsx b/client/src/components/Modal/Modal.jsx index 312d01e..57cb9bb 100644 --- a/client/src/components/Modal/Modal.jsx +++ b/client/src/components/Modal/Modal.jsx @@ -1,7 +1,9 @@ import React from 'react' -import { Modal, Typography, Box, Button } from '@mui/material' +import { Modal, Box, Button } from '@mui/material' +import styles from './Modal.module.css' +import { Container } from '@mui/system' -const PopUpModal = () => { +const PopUpModal = ({ title, description, image }) => { const style = { position: 'absolute', top: '50%', @@ -18,8 +20,14 @@ const PopUpModal = () => { const handleClose = () => setOpen(false) return ( - <> - <Button onClick={handleOpen}>Open modal</Button> + <div className={styles.modal}> + <Button onClick={handleOpen} sx={{ borderRadius: '50%' }}> + <img + src={`${process.env.PUBLIC_URL}/assets/images/help.svg`} + height="65px" + width="65px" + /> + </Button> <Modal open={open} onClose={handleClose} @@ -27,15 +35,21 @@ const PopUpModal = () => { aria-describedby="modal-modal-description" > <Box sx={style}> - <Typography id="modal-modal-title" variant="h6" component="h2"> - Text in a modal - </Typography> - <Typography id="modal-modal-description" sx={{ mt: 2 }}> - Duis mollis, est non commodo luctus, nisi erat porttitor ligula. - </Typography> + <h1 id="modal-modal-title" className={styles.modal__title}> + {title} + </h1> + <Container sx={{ display: 'flex' }}> + <img + src={image} + height="200px" + width="200px" + className={styles.modal__image} + /> + <p className={styles.modal__content}>{description}</p> + </Container> </Box> </Modal> - </> + </div> ) } diff --git a/client/src/components/Modal/Modal.module.css b/client/src/components/Modal/Modal.module.css new file mode 100644 index 0000000..547445b --- /dev/null +++ b/client/src/components/Modal/Modal.module.css @@ -0,0 +1,16 @@ +.modal { + margin: 0px 15px; +} + +.modal__title { + text-align: center; + margin: 20px 0px 40px; +} + +.modal__image { + width: 40%; +} + +.modal__content { + width: 60%; +} diff --git a/client/src/pages/Enrollment/Address/Address.jsx b/client/src/pages/Enrollment/Address/Address.jsx index 9ae1857..3d1c520 100644 --- a/client/src/pages/Enrollment/Address/Address.jsx +++ b/client/src/pages/Enrollment/Address/Address.jsx @@ -4,9 +4,9 @@ import Input from '../../../components/Input/Input' import { State, City } from 'country-state-city' import Select from 'react-select' import { userContext } from '../../../context/User' +import { useTranslation } from 'react-i18next' import styles from './Address.module.css' -import { useTranslation } from 'react-i18next' const Address = () => { const { t } = useTranslation() @@ -26,7 +26,7 @@ const Address = () => { })) const customStyles = { - control: (base, state) => ({ + control: (base) => ({ ...base, width: '330px', height: '60px', @@ -34,7 +34,7 @@ const Address = () => { border: '3px solid', borderRadius: '10px !important' }), - input: (base, state) => ({ + input: (base) => ({ ...base, display: 'flex', justifyContent: 'center', @@ -49,66 +49,6 @@ const Address = () => { <Header subheading={t('ENROLLMENT')} /> <div className={styles.address}> <div className={styles.address__container}> - <div className={styles.input}> - <div className={styles.input__container}> - <label htmlFor="state">{t('STATE')}</label> - <Select - id="state" - name="state" - options={updatedStates('IN')} - value={userData.address?.state} - onChange={(e) => { - setUserData({ - ...userData, - address: { - ...userData.address, - state: e - } - }) - }} - styles={customStyles} - /> - </div> - </div> - <div className={styles.input}> - <div className={styles.input__container}> - <label htmlFor="city">{t('DISTRICT')}</label> - <Select - id="city" - name="city" - options={updatedCities('IN', userData.address?.state?.isoCode)} - value={userData.address?.district} - onChange={(e) => { - setUserData({ - ...userData, - address: { - ...userData.address, - district: e - } - }) - }} - styles={customStyles} - /> - </div> - </div> - <Input - id="town" - label={t('VILLAGE_TOWN')} - value={userData.village} - type="text" - onChange={(e) => { - setUserData({ - ...userData, - address: { - ...userData.address, - village: e.target.value - } - }) - }} - placeholder={t('ENTER_YOUR_VILLAGE_TOWN')} - /> - </div> - <div className={styles.address__container}> <Input id="houseNo" label={t('HOUSE_NUMBER_APARTMENT')} @@ -126,36 +66,57 @@ const Address = () => { placeholder={t('ENTER_YOUR_HOUSE_NUMBER_APARTMENT')} /> <Input - id="street" - label={t('STREET_ROAD')} - value={userData.street} + id="town" + label={t('VILLAGE_TOWN')} + value={userData.village} type="text" onChange={(e) => { setUserData({ ...userData, address: { ...userData.address, - street: e.target.value + village: e.target.value } }) }} - placeholder={t('ENTER_YOUR_STREET_ROAD')} + placeholder={t('ENTER_YOUR_VILLAGE_TOWN')} /> + <div className={styles.input__container}> + <label htmlFor="state">{t('STATE')}</label> + <Select + id="state" + name="state" + options={updatedStates('IN')} + value={userData.address?.state} + onChange={(e) => { + setUserData({ + ...userData, + address: { + ...userData.address, + state: e + } + }) + }} + styles={customStyles} + /> + </div> + </div> + <div className={styles.address__container}> <Input - id="locality" - label={t('AREA_LOCALITY')} - value={userData.locality} + id="street" + label={t('STREET_ROAD')} + value={userData.street} type="text" onChange={(e) => { setUserData({ ...userData, address: { ...userData.address, - locality: e.target.value + street: e.target.value } }) }} - placeholder={t('ENTER_YOUR_AREA_LOCALITY')} + placeholder={t('ENTER_YOUR_STREET_ROAD')} /> <Input id="postOffice" @@ -173,23 +134,42 @@ const Address = () => { }} placeholder={t('ENTER_YOUR_AREA_POST_OFFICE')} /> + <div className={styles.input__container}> + <label htmlFor="city">{t('DISTRICT')}</label> + <Select + id="city" + name="city" + options={updatedCities('IN', userData.address?.state?.isoCode)} + value={userData.address?.district} + onChange={(e) => { + setUserData({ + ...userData, + address: { + ...userData.address, + district: e + } + }) + }} + styles={customStyles} + /> + </div> </div> <div className={styles.address__container}> <Input - id="landmark" - label={t('LANDMARK')} - value={userData.landmark} + id="locality" + label={t('AREA_LOCALITY')} + value={userData.locality} type="text" onChange={(e) => { setUserData({ ...userData, address: { ...userData.address, - landmark: e.target.value + locality: e.target.value } }) }} - placeholder={t('ENTER_ANY_NEAREST_LANDMARK')} + placeholder={t('ENTER_YOUR_AREA_LOCALITY')} /> <Input id="pincode" @@ -207,6 +187,22 @@ const Address = () => { }} placeholder={t('ENTER_YOUR_AREA_PINCODE')} /> + <Input + id="landmark" + label={t('LANDMARK')} + value={userData.landmark} + type="text" + onChange={(e) => { + setUserData({ + ...userData, + address: { + ...userData.address, + landmark: e.target.value + } + }) + }} + placeholder={t('ENTER_ANY_NEAREST_LANDMARK')} + /> </div> </div> </> diff --git a/client/src/pages/Enrollment/Address/Address.module.css b/client/src/pages/Enrollment/Address/Address.module.css index 26ca909..eafa781 100644 --- a/client/src/pages/Enrollment/Address/Address.module.css +++ b/client/src/pages/Enrollment/Address/Address.module.css @@ -1,28 +1,17 @@ .address { display: flex; justify-content: center; + margin: 40px 0px 0px; } .address__container { margin: 0px 20px; } -.input { +.input__container { display: flex; justify-content: center; + flex-direction: column; font-family: 'Barlow'; font-size: var(--font-medium-s); } - -.input__container { - display: flex; - flex-direction: column; -} - -.input__field { - width: 300px; - margin: 10px 0px; - padding: 20px 10px; - border: 3px solid; - border-radius: 10px; -} diff --git a/client/src/pages/Enrollment/Agreement/Agreement.jsx b/client/src/pages/Enrollment/Agreement/Agreement.jsx index d3a5b90..7b1b9c6 100644 --- a/client/src/pages/Enrollment/Agreement/Agreement.jsx +++ b/client/src/pages/Enrollment/Agreement/Agreement.jsx @@ -81,10 +81,11 @@ const Agreement = ({ unverified, setUnverified }) => { {show && ( <> <Input - type="number" + type="text" id="otp" value={otp} onChange={(e) => setOtp(e.target.value)} + maxLength="6" placeholder="XXXXXX" /> <Button diff --git a/client/src/pages/Enrollment/Enrollment.jsx b/client/src/pages/Enrollment/Enrollment.jsx index 8b62b3c..88bdf47 100644 --- a/client/src/pages/Enrollment/Enrollment.jsx +++ b/client/src/pages/Enrollment/Enrollment.jsx @@ -33,19 +33,28 @@ const Enrollment = () => { const navigate = useNavigate() const [unverified, setUnverified] = useState(true) - const pushUser = useMutation((payload) => createUser(payload), { - onSuccess: () => { - console.log('Before mutate') + const { mutate } = useMutation((payload) => createUser(payload), { + onSuccess: (data) => { setConfirm.mutate({ mobile: `+91${userData.mobile}`, - id: pushUser.data._id + id: data?.data?.result?._id }) - console.log('After mutate') setPage(page + 1) + }, + onError: (error) => { + console.log(error) + if (error?.response?.data?.message === 'User already exists.') { + setUserData(initialUserData) + navigate('/error') + } else { + toast.error(t('SOMETHING_WENT_WRONG')) + } } }) - const setConfirm = useMutation((payload) => sendMessage(payload)) + const setConfirm = useMutation((payload) => { + sendMessage(payload) + }) const handleSubmit = () => { if (page === 0) { @@ -75,26 +84,26 @@ const Enrollment = () => { setPage(page + 1) } } else if (page === 2) { - if (!userData.address.state.name) { - toast.error(t('PLEASE_SELECT_YOUR_STATE')) - } else if (!userData.address.district.name) { - toast.error(t('PLEASE_SELECT_YOUR_DISTRICT')) - } else if (userData.address.village === '') { - toast.error(t('PLEASE_ENTER_YOUR_VILLAGE')) - } else if (userData.address.houseNo === '') { + if (userData.address.houseNo === '') { toast.error(t('PLEASE_ENTER_YOUR_HOUSE_NUMBER')) } else if (userData.address.street === '') { toast.error(t('PLEASE_ENTER_YOUR_STREET')) } else if (userData.address.locality === '') { toast.error(t('PLEASE_ENTER_YOUR_LOCALITY')) + } else if (userData.address.village === '') { + toast.error(t('PLEASE_ENTER_YOUR_VILLAGE')) } else if (userData.address.postOffice === '') { toast.error(t('PLEASE_ENTER_YOUR_AREA_POST_OFFICE')) - } else if (userData.address.landmark === '') { - toast.error(t('PLEASE_ENTER_NEAREST_LANDMARK')) } else if (userData.address.pincode === '') { toast.error(t('PLEASE_ENTER_YOUR_AREA_PINCODE')) } else if (!validPincode.test(userData.address.pincode)) { toast.error(t('PLEASE_ENTER_VALID_PINCODE')) + } else if (!userData.address.state.name) { + toast.error(t('PLEASE_SELECT_YOUR_STATE')) + } else if (!userData.address.district.name) { + toast.error(t('PLEASE_SELECT_YOUR_DISTRICT')) + } else if (userData.address.landmark === '') { + toast.error(t('PLEASE_ENTER_NEAREST_LANDMARK')) } else { setPage(page + 1) } @@ -106,11 +115,7 @@ const Enrollment = () => { } } else if (page === 4) { if (!userData.documents.POI) { - toast.error(t('PLEASE_TAKE_THE_PICTURE_OF_THE_PROOF_OF_IDENTITY')) - } else if (!userData.documents.POA) { - toast.error(t('PLEASE_TAKE_THE_PICTURE_OF_THE_PROOF_OF_ADDRESS')) - } else if (!userData.documents.DOB) { - toast.error(t('PLEASE_TAKE_THE_PICTURE_OF_THE_PROOF_OF_DATE_OF_BIRTH')) + toast.error(t('SCAN_YOUR_DOCUMENT')) } else { setPage(page + 1) } @@ -119,21 +124,25 @@ const Enrollment = () => { } else if (page === 6) { setPage(page + 1) } else if (page === 7) { - pushUser.mutate({ - indianResident: userData.indianResident, - name: userData.name, - gender: userData.gender, - dob: userData.dob, - mobile: userData.mobile, - email: userData.email, - address: userData.address, - photo: userData.photo, - documents: { - POI: userData.documents.POI, - POA: userData.documents.POA, - DOB: userData.documents.DOB - } - }) + if (unverified) { + toast.error(t('PLEASE_VERIFY_OTP')) + } else { + mutate({ + indianResident: userData.indianResident, + name: userData.name, + gender: userData.gender, + dob: userData.dob, + mobile: userData.mobile, + email: userData.email, + address: userData.address, + photo: userData.photo, + documents: { + POI: userData.documents.POI, + POA: userData.documents.POA, + DOB: userData.documents.DOB + } + }) + } } else if (page === 8) { setUserData(initialUserData) navigate('/') @@ -198,7 +207,7 @@ const Enrollment = () => { case 7: return ( <> - <SubmitButton onClick={handleSubmit} disabled={unverified} /> + <SubmitButton onClick={handleSubmit} /> <BackButton onClick={() => setPage(page - 1)} /> </> ) diff --git a/client/src/pages/Enrollment/Enrollment.module.css b/client/src/pages/Enrollment/Enrollment.module.css deleted file mode 100644 index e69de29..0000000 --- a/client/src/pages/Enrollment/Enrollment.module.css +++ /dev/null diff --git a/client/src/pages/Enrollment/FormOne/FormOne.module.css b/client/src/pages/Enrollment/FormOne/FormOne.module.css index 35d1e49..fae8e9f 100644 --- a/client/src/pages/Enrollment/FormOne/FormOne.module.css +++ b/client/src/pages/Enrollment/FormOne/FormOne.module.css @@ -15,15 +15,22 @@ display: flex; align-items: center; margin: 15px; + cursor: pointer; } .formone__resident input[type='radio'] { width: 1.5rem; height: 1.5rem; + cursor: pointer; +} + +.formone__resident label { + margin-left: 10px; } .formone__gender { display: flex; + margin-bottom: 10px; } .formone__dob { diff --git a/client/src/pages/Enrollment/FormTwo/FormTwo.jsx b/client/src/pages/Enrollment/FormTwo/FormTwo.jsx index 05ad075..0bce4bc 100644 --- a/client/src/pages/Enrollment/FormTwo/FormTwo.jsx +++ b/client/src/pages/Enrollment/FormTwo/FormTwo.jsx @@ -1,44 +1,46 @@ import React from 'react' +import { useTranslation } from 'react-i18next' import Input from '../../../components/Input/Input' import Header from '../../../components/Header/Header' -import SubmitButton from '../../../components/SubmitButton/SubmitButton' -import { useTranslation } from 'react-i18next' import { userContext } from '../../../context/User' +import styles from './FormTwo.module.css' + const FormTwo = () => { const { t } = useTranslation() const { userData, setUserData } = userContext() return ( - <div className="formtwo"> + <> <Header subheading={t('ENROLLMENT')} /> - <Input - id="mobile" - value={userData.mobile} - label={t('MOBILE')} - type="text" - onChange={(e) => { - setUserData({ - ...userData, - mobile: e.target.value - }) - }} - placeholder={t('ENTER_YOUR_MOBILE_NUMBER')} - /> - <Input - id="email" - value={userData.email} - label={t('EMAIL')} - type="email" - onChange={(e) => { - setUserData({ - ...userData, - email: e.target.value - }) - }} - placeholder={t('ENTER_YOUR_EMAIL_ID')} - /> - <SubmitButton /> - </div> + <div className={styles.formtwo__input}> + <Input + id="mobile" + value={userData.mobile} + label={t('MOBILE')} + type="text" + onChange={(e) => { + setUserData({ + ...userData, + mobile: e.target.value + }) + }} + placeholder={t('ENTER_YOUR_MOBILE_NUMBER')} + /> + <Input + id="email" + value={userData.email} + label={t('EMAIL')} + type="email" + onChange={(e) => { + setUserData({ + ...userData, + email: e.target.value + }) + }} + placeholder={t('ENTER_YOUR_EMAIL_ID')} + /> + </div> + </> ) } diff --git a/client/src/pages/Enrollment/FormTwo/FormTwo.module.css b/client/src/pages/Enrollment/FormTwo/FormTwo.module.css index 8b13789..d135f8f 100644 --- a/client/src/pages/Enrollment/FormTwo/FormTwo.module.css +++ b/client/src/pages/Enrollment/FormTwo/FormTwo.module.css @@ -1 +1,3 @@ - +.formtwo__input { + margin: 60px; +} diff --git a/client/src/pages/Error/Error.jsx b/client/src/pages/Error/Error.jsx new file mode 100644 index 0000000..5d06226 --- /dev/null +++ b/client/src/pages/Error/Error.jsx @@ -0,0 +1,28 @@ +import React, { useEffect } from 'react' +import { useNavigate } from 'react-router-dom' + +import styles from './Error.module.css' + +const Error = ({ message }) => { + const navigate = useNavigate() + + useEffect(() => { + setTimeout(() => { + navigate('/') + }, 3000) + }, []) + + return ( + <> + <div className={styles.error}> + <img + src={`${process.env.PUBLIC_URL}/assets/images/error.svg`} + className={styles.error__image} + /> + <h1 className={styles.error__title}>{message}</h1> + </div> + </> + ) +} + +export default Error diff --git a/client/src/pages/Error/Error.module.css b/client/src/pages/Error/Error.module.css new file mode 100644 index 0000000..d66c6b7 --- /dev/null +++ b/client/src/pages/Error/Error.module.css @@ -0,0 +1,18 @@ +.error { + display: flex; + height: 100vh; + width: 100vw; + flex-direction: column; + justify-content: center; + align-items: center; +} + +.error__title { + font-family: 'Barlow', sans-serif; + font-weight: 400; + font-size: var(--font-large); +} + +.error__image { + margin-left: 40px; +} diff --git a/client/src/pages/Home/Home.jsx b/client/src/pages/Home/Home.jsx index 4539120..7f1fe04 100644 --- a/client/src/pages/Home/Home.jsx +++ b/client/src/pages/Home/Home.jsx @@ -3,7 +3,6 @@ import { useTranslation } from 'react-i18next' import { Link } from 'react-router-dom' import Card from '../../components/Card/Card' import Header from '../../components/Header/Header' -import LanguageSelect from '../../components/LanguageSelect/LanguageSelect' import PopUpModal from '../../components/Modal/Modal' import styles from './Home.module.css' @@ -12,8 +11,7 @@ const Home = ({ page, setPage }) => { return ( <> <Header subheading={t('MERA_AADHAAR_MERI_PEHCHAN')} /> - <PopUpModal /> - <LanguageSelect /> + <PopUpModal title={t('FORM_ONE')} /> <div className={styles.card__container}> <Link to="/enrollment"> <Card diff --git a/client/src/routes/index.js b/client/src/routes/index.js index 6bc2342..ad8b500 100644 --- a/client/src/routes/index.js +++ b/client/src/routes/index.js @@ -9,15 +9,22 @@ import UpdateSelect from '../pages/Update/UpdateSelect/UpdateSelect' import Biometric from '../pages/Update/Biometric/Biometric' import Agreement from '../pages/Update/Agreement/Agreement' import FinalSlip from '../pages/Update/FinalSlip/FinalSlip' +import Error from '../pages/Error/Error' import Otp from '../pages/Update/Otp/Otp' +import { useTranslation } from 'react-i18next' const Index = () => { + const { t } = useTranslation() return ( <Routes> <Route exact path="/" element={<Home />} /> <Route path="enrollment"> <Route index element={<Enrollment />} /> </Route> + <Route + path="error" + element={<Error message={t('USER_ALREADY_EXISTS')} />} + /> <Route path="update"> <Route index element={<Update />} /> <Route path="otp" element={<Otp />} /> |