diff options
Diffstat (limited to 'client/src/pages/Update')
-rw-r--r-- | client/src/pages/Update/Address/Address.jsx | 186 | ||||
-rw-r--r-- | client/src/pages/Update/Address/Address.module.css | 19 | ||||
-rw-r--r-- | client/src/pages/Update/Agreement/Agreement.jsx | 122 | ||||
-rw-r--r-- | client/src/pages/Update/Agreement/Agreement.module.css | 13 | ||||
-rw-r--r-- | client/src/pages/Update/Biometric/Biometric.jsx | 18 | ||||
-rw-r--r-- | client/src/pages/Update/Demographic/Demographic.jsx | 24 | ||||
-rw-r--r-- | client/src/pages/Update/DocumentScanner/DocumentScanner.jsx | 240 | ||||
-rw-r--r-- | client/src/pages/Update/DocumentScanner/DocumentScanner.module.css | 53 | ||||
-rw-r--r-- | client/src/pages/Update/DocumentScanner/styles.js | 7 | ||||
-rw-r--r-- | client/src/pages/Update/FormOne/FormOne.module.css | 4 | ||||
-rw-r--r-- | client/src/pages/Update/Otp/Otp.jsx | 106 | ||||
-rw-r--r-- | client/src/pages/Update/Otp/Otp.module.css | 5 | ||||
-rw-r--r-- | client/src/pages/Update/Update.jsx | 19 | ||||
-rw-r--r-- | client/src/pages/Update/UpdateSelect/UpdateSelect.jsx | 8 |
14 files changed, 506 insertions, 318 deletions
diff --git a/client/src/pages/Update/Address/Address.jsx b/client/src/pages/Update/Address/Address.jsx index 9159508..20a97f7 100644 --- a/client/src/pages/Update/Address/Address.jsx +++ b/client/src/pages/Update/Address/Address.jsx @@ -27,7 +27,7 @@ const Address = () => { })) const customStyles = { - control: (base, state) => ({ + control: (base) => ({ ...base, width: '330px', height: '60px', @@ -35,7 +35,7 @@ const Address = () => { border: '3px solid', borderRadius: '10px !important' }), - input: (base, state) => ({ + input: (base) => ({ ...base, display: 'flex', justifyContent: 'center', @@ -55,89 +55,11 @@ const Address = () => { setEditable2(!editable2) } - console.log(userData.address.village) - return ( <> - <Header subheading={t('ENROLLMENT')} /> + <Header subheading={t('UPDATE')} /> <div className={styles.address}> <div className={styles.address__container}> - <div className={styles.input}> - <div className={styles.input__container}> - <label htmlFor="state">{t('STATE')}</label> - <div className={styles.input__edit}> - <Select - id="state" - name="state" - options={updatedStates('IN')} - defaultValue={userData.address.state} - isDisabled={editable1} - isSearchable={!editable1} - onChange={(e) => { - setUserData({ - ...userData, - address: { - ...userData.address, - state: e - } - }) - }} - styles={customStyles} - /> - <EditButton - onClick={handleEdit1} - enabled={!editable1 ? '1' : '0'} - /> - </div> - </div> - </div> - <div className={styles.input}> - <div className={styles.input__container}> - <label htmlFor="city">{t('DISTRICT')}</label> - <div className={styles.input__edit}> - <Select - id="city" - name="city" - options={updatedCities('IN', userData.address.state.isoCode)} - defaultValue={userData.address.district} - isDisabled={editable2} - isSearchable={!editable2} - onChange={(e) => { - setUserData({ - ...userData, - address: { - ...userData.address, - district: e - } - }) - }} - styles={customStyles} - /> - <EditButton - onClick={handleEdit2} - enabled={!editable2 ? '1' : '0'} - /> - </div> - </div> - </div> - <UpdateInput - id="town" - label={t('VILLAGE_TOWN')} - defaultValue={userData.address.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}> <UpdateInput id="houseNo" label={t('HOUSE_NUMBER_APARTMENT')} @@ -155,36 +77,65 @@ const Address = () => { placeholder={t('ENTER_YOUR_HOUSE_NUMBER_APARTMENT')} /> <UpdateInput - id="street" - label={t('STREET_ROAD')} - defaultValue={userData.address.street} + id="town" + label={t('VILLAGE_TOWN')} + defaultValue={userData.address.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> + <div className={styles.input__edit}> + <Select + id="state" + name="state" + options={updatedStates('IN')} + defaultValue={userData.address.state} + isDisabled={editable1} + isSearchable={!editable1} + onChange={(e) => { + setUserData({ + ...userData, + address: { + ...userData.address, + state: e + } + }) + }} + styles={customStyles} + /> + <EditButton + onClick={handleEdit1} + enabled={!editable1 ? '1' : '0'} + /> + </div> + </div> + </div> + <div className={styles.address__container}> <UpdateInput - id="locality" - label={t('AREA_LOCALITY')} - defaultValue={userData.address.locality} + id="street" + label={t('STREET_ROAD')} + defaultValue={userData.address.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')} /> <UpdateInput id="postOffice" @@ -202,23 +153,50 @@ const Address = () => { }} placeholder={t('ENTER_YOUR_AREA_POST_OFFICE')} /> + <div className={styles.input__container}> + <label htmlFor="city">{t('DISTRICT')}</label> + <div className={styles.input__edit}> + <Select + id="city" + name="city" + options={updatedCities('IN', userData.address.state.isoCode)} + defaultValue={userData.address.district} + isDisabled={editable2} + isSearchable={!editable2} + onChange={(e) => { + setUserData({ + ...userData, + address: { + ...userData.address, + district: e + } + }) + }} + styles={customStyles} + /> + <EditButton + onClick={handleEdit2} + enabled={!editable2 ? '1' : '0'} + /> + </div> + </div> </div> <div className={styles.address__container}> <UpdateInput - id="landmark" - label={t('LANDMARK')} - defaultValue={userData.address.landmark} + id="locality" + label={t('AREA_LOCALITY')} + defaultValue={userData.address.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')} /> <UpdateInput id="pincode" @@ -236,6 +214,22 @@ const Address = () => { }} placeholder={t('ENTER_YOUR_AREA_PINCODE')} /> + <UpdateInput + id="landmark" + label={t('LANDMARK')} + defaultValue={userData.address.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/Update/Address/Address.module.css b/client/src/pages/Update/Address/Address.module.css index 41cbf17..ccaca08 100644 --- a/client/src/pages/Update/Address/Address.module.css +++ b/client/src/pages/Update/Address/Address.module.css @@ -1,33 +1,22 @@ .address { display: flex; justify-content: center; + margin: 40px 0px 0px; } .address__container { margin: 0px 20px; } -.input { +.input__container { display: flex; + flex-direction: column; justify-content: center; font-family: 'Barlow'; font-size: var(--font-medium-s); } -.input__container { - display: flex; - flex-direction: column; -} - -.input__edit{ +.input__edit { display: flex; flex-direction: row; } - -.input__field { - width: 300px; - margin: 10px 0px; - padding: 20px 10px; - border: 3px solid; - border-radius: 10px; -} diff --git a/client/src/pages/Update/Agreement/Agreement.jsx b/client/src/pages/Update/Agreement/Agreement.jsx index 804561b..2d1361d 100644 --- a/client/src/pages/Update/Agreement/Agreement.jsx +++ b/client/src/pages/Update/Agreement/Agreement.jsx @@ -1,57 +1,111 @@ -import React from 'react' +import React, { useState } from 'react' import Header from '../../../components/Header/Header' import CardAgreement from '../../../components/Card/CardAgreement' import styles from './Agreement.module.css' import Input from '../../../components/Input/Input' -import { Grid, Button } from '@mui/material' import { Link } from 'react-router-dom' import SubmitButton from '../../../components/SubmitButton/SubmitButton' +import { Button, Typography } from '@mui/material' import { useTranslation } from 'react-i18next' +import { sendOTP, updateUser } from '../../../services/apiservice' import { userContext } from '../../../context/User' import { useMutation } from 'react-query' -import { updateUser } from '../../../services/apiservice' +import { ToastContainer, toast } from 'react-toastify' +import 'react-toastify/dist/ReactToastify.css' -const Agreement = () => { +const Agreement = ({ unverified, setUnverified }) => { + const { t } = useTranslation() + const [otp, setOtp] = useState() + const [disabled, setDisabled] = useState(false) + const [finalDisable, setFinalDisable] = useState(false) + const [show, setShow] = useState(false) const { userData } = userContext() + const updateUse = useMutation(() => updateUser(userData._id, { ...userData })) - const { t } = useTranslation() + const { data, mutate } = useMutation(() => + sendOTP({ mobile: `+91${userData?.mobile}` }) + ) + + console.log('Disabled: ', disabled, 'Final Disable: ', finalDisable) + + const verifyOTP = () => { + if (data?.data?.otpCode === Number(otp)) { + console.log('Disabled: ', disabled, 'Final Disable: ', finalDisable) + setFinalDisable(true) + setDisabled(true) + setShow(false) + setUnverified(false) + toast.success(t('OTP_VERIFIED!')) + } else { + toast.error(t('INCORRECT_OTP!')) + } + } + + const sendResendOTP = () => { + setTimeout(() => { + if (finalDisable === false) { + console.log('Disabled: ', disabled, 'Final Disable: ', finalDisable) + setDisabled(false) + } + }, 30000) + } + return ( <> - <Header subheading={t('UPDATE')} /> + <ToastContainer + autoClose={1000} + hideProgressBar={true} + theme={'colored'} + /> + <Header subheading={t('ENROLLMENT')} /> <div className={styles.card__container}> <CardAgreement image={`${process.env.PUBLIC_URL}/assets/images/agreement.svg`} /> </div> - <Input - type="text" - id="otp" - label={t('PLEASE_VERIFY_YOUR_IDENTITY')} - placeholder="XXXX" - /> - <Grid container columnSpacing={10} justifyContent="center"> - <Grid item> - <Button - color="primary" - size="large" - type="submit" - variant="contained" - > - {t('SEND_OTP')} - </Button> - </Grid> - <Grid item> - <Button - color="primary" - size="large" - type="submit" - variant="contained" - > - {t('RESEND')} - </Button> - </Grid> - </Grid> + <div className={styles.card__elements}> + <Typography>{t('PLEASE_VERIFY_YOUR_IDENTITY')}</Typography> + <Button + color="primary" + size="large" + type="submit" + variant="contained" + disabled={disabled} + sx={{ marginTop: '1rem' }} + onClick={() => { + mutate() + setDisabled(true) + setShow(true) + sendResendOTP() + }} + > + {show ? t('RESEND') : t('SEND_OTP')} + </Button> + {show && ( + <> + <Input + type="text" + id="otp" + value={otp} + onChange={(e) => setOtp(e.target.value)} + maxLength="6" + placeholder="XXXXXX" + /> + <Button + color="primary" + size="large" + type="submit" + variant="contained" + onClick={() => { + verifyOTP() + }} + > + {t('VERIFY_OTP')} + </Button> + </> + )} + </div> <Link to="/update/final-slip"> <SubmitButton onClick={() => updateUse.mutate()} /> </Link> diff --git a/client/src/pages/Update/Agreement/Agreement.module.css b/client/src/pages/Update/Agreement/Agreement.module.css index c618a4d..2580d47 100644 --- a/client/src/pages/Update/Agreement/Agreement.module.css +++ b/client/src/pages/Update/Agreement/Agreement.module.css @@ -1,4 +1,11 @@ .card__container { - display: flex; - justify-content: center; - }
\ No newline at end of file + display: flex; + justify-content: center; +} + +.card__elements { + display: flex; + justify-content: center; + align-items: center; + flex-direction: column; +} diff --git a/client/src/pages/Update/Biometric/Biometric.jsx b/client/src/pages/Update/Biometric/Biometric.jsx index 72aa1b7..6737ed9 100644 --- a/client/src/pages/Update/Biometric/Biometric.jsx +++ b/client/src/pages/Update/Biometric/Biometric.jsx @@ -11,20 +11,14 @@ const Biometric = () => { const [page, setPage] = useState(4) const { userData, oriUserData, setUserData } = userContext() - const [formData, setFormData] = useState({ - photo: '', - irisScan: '', - fingerPrint: '' - }) - const conditionalComponent = () => { switch (page) { case 0: - return <PhotoCapture formData={formData} setFormData={setFormData} /> + return <PhotoCapture /> case 1: - return <Fingerprint formData={formData} setFormData={setFormData} /> + return <Fingerprint /> case 2: - return <IrisScan formData={formData} setFormData={setFormData} /> + return <IrisScan /> default: return <BiometricSelect page={page} setPage={setPage} /> } @@ -49,21 +43,21 @@ const Biometric = () => { case 0: return ( <> - <SubmitButton onClick={() => handleSubmit()}> Next</SubmitButton> + <SubmitButton onClick={() => handleSubmit()} /> <BackButton onClick={() => handleBack()} /> </> ) case 1: return ( <> - <SubmitButton onClick={() => setPage(4)}> Next</SubmitButton> + <SubmitButton onClick={() => setPage(4)} /> <BackButton onClick={() => setPage(page - 1)} /> </> ) case 2: return ( <> - <SubmitButton onClick={() => setPage(4)}> Next</SubmitButton> + <SubmitButton onClick={() => setPage(4)} /> <BackButton onClick={() => setPage(page - 1)} /> </> ) diff --git a/client/src/pages/Update/Demographic/Demographic.jsx b/client/src/pages/Update/Demographic/Demographic.jsx index 61fe972..0f89fe2 100644 --- a/client/src/pages/Update/Demographic/Demographic.jsx +++ b/client/src/pages/Update/Demographic/Demographic.jsx @@ -13,6 +13,7 @@ import UpdateSelect from '../UpdateSelect/UpdateSelect' import { useTranslation } from 'react-i18next' import { userContext } from '../../../context/User' import { ToastContainer, toast } from 'react-toastify' +import BackButton from '../../../components/BackButton/BackButton' import 'react-toastify/dist/ReactToastify.css' const Demographic = () => { @@ -87,13 +88,26 @@ const Demographic = () => { const conditionalButton = () => { switch (page) { case 0: - return <SubmitButton onClick={handleSubmit}>Next</SubmitButton> + return ( + <> + <SubmitButton onClick={handleSubmit} /> + <BackButton onClick={() => setPage(page - 1)} /> + </> + ) case 1: - return <SubmitButton onClick={handleSubmit}>Next</SubmitButton> + return ( + <> + <SubmitButton onClick={handleSubmit} /> + <BackButton onClick={() => setPage(page - 1)} /> + </> + ) case 2: - return <SubmitButton onClick={handleSubmit}>Next</SubmitButton> - default: - return <SubmitButton onClick={handleSubmit}>Next</SubmitButton> + return ( + <> + <SubmitButton onClick={handleSubmit} /> + <BackButton onClick={() => setPage(page - 1)} /> + </> + ) } } return ( diff --git a/client/src/pages/Update/DocumentScanner/DocumentScanner.jsx b/client/src/pages/Update/DocumentScanner/DocumentScanner.jsx index f6fe0b5..0fe8d42 100644 --- a/client/src/pages/Update/DocumentScanner/DocumentScanner.jsx +++ b/client/src/pages/Update/DocumentScanner/DocumentScanner.jsx @@ -3,34 +3,18 @@ import React, { useState } from 'react' import Webcam from 'react-webcam' import Header from '../../../components/Header/Header' import styles from './DocumentScanner.module.css' -import { - Button, - Grid, - Typography, - StepLabel, - Step, - Stepper, - Box -} from '@mui/material' +import { Button, Typography, StepLabel, Step, Stepper } from '@mui/material' import SubmitButton from '../../../components/SubmitButton/SubmitButton' import { useTranslation } from 'react-i18next' import { userContext } from '../../../context/User' +import { toast } from 'react-toastify' +import { useStyles } from './styles' const DocumentScanner = () => { const { userData, oriUserData, setUserData } = userContext() const { t } = useTranslation() - - // JSON.stringify(oriUserData?.address) === let steps - // use conditional statements to compare userData and oriUserData to determine the steps - // 1st case: if only address is changed, then step=['POA'] - // 2nd case: if only either name or gender is changed, then step=['POI'] - // 3rd case: if only dob is changed, then step=['DOB'] - // 4th case: If only address and name or gender is changed, then step=['POA', 'POI'] - // 5th case: If only address and dob is changed, then step=['POA', 'DOB'] - // 6th case: If only name or gender and dob is changed, then step=['POI', 'DOB'] - // 7th case: If everything is changed, then step=['POA', 'POI', 'DOB'] if ( (userData.address !== oriUserData.address && userData.dob !== oriUserData.dob && @@ -71,7 +55,7 @@ const DocumentScanner = () => { const [doccu] = useState({ POI: '', POA: '', DOB: '' }) - console.log(documents) + const classes = useStyles() const webcamRef = React.useRef(null) @@ -90,7 +74,15 @@ const DocumentScanner = () => { if (activeStep === steps.length - 1) { setUserData({ ...userData, documents: documents }) } - setActiveStep((prevActiveStep) => prevActiveStep + 1) + if ( + (!documents.POI && activeStep === 0) || + (!documents.POA && activeStep === 1) || + (!documents.DOB && activeStep === 2) + ) { + toast.error(t('SCAN_YOUR_DOCUMENT')) + } else { + setActiveStep((prevActiveStep) => prevActiveStep + 1) + } } const handleBack = () => { @@ -100,67 +92,85 @@ const DocumentScanner = () => { const WebcamComponent = ({ doc }) => { return ( <> - <div className={styles.card__container}> - {documents[doc] === '' ? ( - <Webcam - audio={false} - height={400} - ref={webcamRef} - screenshotFormat="image/jpeg" - width={600} - videoConstraints={{ - height: 400, - width: 600, - facingMode: 'user' - }} + <div className={styles.container}> + <button + className={styles.button} + disabled={activeStep === 0} + onClick={handleBack} + > + <img + src={`${process.env.PUBLIC_URL}/assets/images/back_inverse.svg`} + alt="" + className={styles.image} /> - ) : ( - <img src={documents[doc]} /> - )} + </button> + <div className={styles.card__container}> + {documents[doc] === '' ? ( + <Webcam + audio={false} + height={400} + ref={webcamRef} + screenshotFormat="image/jpeg" + width={600} + videoConstraints={{ + height: 400, + width: 600, + facingMode: 'user' + }} + /> + ) : ( + <img src={documents[doc]} /> + )} + </div> + <button onClick={handleNext} className={styles.button}> + <img + src={`${process.env.PUBLIC_URL}/assets/images/next_inverse.svg`} + alt="" + className={styles.image} + /> + </button> + </div> + <div className={styles.button__container}> + <Button + color="primary" + size="large" + type="submit" + variant="contained" + sx={{ margin: '0px 20px' }} + onClick={(e) => { + e.preventDefault() + capture(doc) + }} + > + {t('SCAN')} + </Button> + <Button + color="primary" + size="large" + type="submit" + variant="contained" + sx={{ margin: '0px 20px' }} + onClick={(e) => { + e.preventDefault() + doccu[doc] = '' + setDocuments({ + ...documents, + POI: doccu.POI, + POA: doccu.POA, + DOB: doccu.DOB + }) + }} + > + {t('RESET')} + </Button> </div> - <Grid container columnSpacing={10} justifyContent="center"> - <Grid item> - <Button - color="primary" - size="large" - type="submit" - variant="contained" - onClick={(e) => { - e.preventDefault() - capture(doc) - }} - > - {t('SCAN')} - </Button> - </Grid> - <Grid item> - <Button - color="primary" - size="large" - type="submit" - variant="contained" - onClick={(e) => { - e.preventDefault() - doccu[doc] = '' - setDocuments({ - ...documents, - POI: doccu.POI, - POA: doccu.POA, - DOB: doccu.DOB - }) - }} - > - {t('RESET')} - </Button> - </Grid> - </Grid> <br></br> <div> - <Grid container justifyContent="center"> + <div> <Typography align="center"> {t('KINDLY_CLICK_THE_PICTURE_OF_YOUR_DOCUMENTS')} </Typography> - </Grid> + </div> </div> </> ) @@ -168,55 +178,43 @@ const DocumentScanner = () => { return ( <> - <Header subheading={t('ENROLLMENT')} /> + <Header subheading={t('UPDATE')} /> <SubmitButton /> - <Box sx={{ width: '100%' }}> - <Stepper activeStep={activeStep}> - {steps.map((label, index) => { - const stepProps = {} - const labelProps = {} - return ( - <Step key={label} {...stepProps}> - <StepLabel {...labelProps}>{label}</StepLabel> - </Step> - ) - })} - </Stepper> - {activeStep === steps.length ? ( - <React.Fragment> - <Typography sx={{ mt: 2, mb: 1 }}> + <div className={styles.stepper__container}> + <div className={styles.box}> + <Stepper activeStep={activeStep} sx={{ width: '60%' }}> + {steps.map((label, index) => { + const stepProps = {} + const labelProps = {} + return ( + <Step key={label} {...stepProps}> + <StepLabel + {...labelProps} + classes={{ label: classes.stepLabel }} + > + {label} + </StepLabel> + </Step> + ) + })} + </Stepper> + {activeStep === steps.length ? ( + <Typography variant="h3" sx={{ mt: 8, mb: 1 }}> {t('ALL_STEPS_COMPLETED')} </Typography> - <Box sx={{ display: 'flex', flexDirection: 'row', pt: 2 }}> - <Box sx={{ flex: '1 1 auto' }} /> - </Box> - </React.Fragment> - ) : ( - <React.Fragment> - {activeStep === 0 ? ( - <WebcamComponent doc="POI" /> - ) : activeStep === 1 ? ( - <WebcamComponent doc="POA" /> - ) : ( - activeStep === 2 && <WebcamComponent doc="DOB" /> - )} - <Box sx={{ display: 'flex', flexDirection: 'row', pt: 2 }}> - <Button - color="inherit" - disabled={activeStep === 0} - onClick={handleBack} - sx={{ mr: 1 }} - > - {t('BACK')} - </Button> - <Box sx={{ flex: '1 1 auto' }} /> - <Button onClick={handleNext}> - {activeStep === steps.length - 1 ? t('FINISH') : t('NEXT')} - </Button> - </Box> - </React.Fragment> - )} - </Box> + ) : ( + <React.Fragment> + {activeStep === 0 ? ( + <WebcamComponent doc="POI" /> + ) : activeStep === 1 ? ( + <WebcamComponent doc="POA" /> + ) : ( + activeStep === 2 && <WebcamComponent doc="DOB" /> + )} + </React.Fragment> + )} + </div> + </div> </> ) } diff --git a/client/src/pages/Update/DocumentScanner/DocumentScanner.module.css b/client/src/pages/Update/DocumentScanner/DocumentScanner.module.css index ec59f61..f73d192 100644 --- a/client/src/pages/Update/DocumentScanner/DocumentScanner.module.css +++ b/client/src/pages/Update/DocumentScanner/DocumentScanner.module.css @@ -1,5 +1,50 @@ .card__container { - display: flex; - justify-content: center; - } -
\ No newline at end of file + display: flex; + justify-content: center; + align-items: center; + margin: 20px; +} + +.stepper__container { + display: flex; + justify-content: center; +} + +.button__container { + display: flex; + justify-content: space-evenly; + align-items: center; +} + +.button { + background: transparent; + border: none; +} + +.image { + height: 50px; + width: 50px; +} + +.image:hover { + cursor: pointer; + transform: scale(1.1); +} + +.image:active { + transform: scale(0.98); +} + +.box { + display: flex; + justify-content: center; + align-items: center; + flex-direction: column; + width: 100%; + height: 100%; +} + +.container { + display: flex; + align-items: center; +} diff --git a/client/src/pages/Update/DocumentScanner/styles.js b/client/src/pages/Update/DocumentScanner/styles.js new file mode 100644 index 0000000..0b7e915 --- /dev/null +++ b/client/src/pages/Update/DocumentScanner/styles.js @@ -0,0 +1,7 @@ +import { makeStyles } from '@mui/styles' + +export const useStyles = makeStyles({ + stepLabel: { + fontSize: '20px' + } +}) diff --git a/client/src/pages/Update/FormOne/FormOne.module.css b/client/src/pages/Update/FormOne/FormOne.module.css index abde7ef..e0cff0e 100644 --- a/client/src/pages/Update/FormOne/FormOne.module.css +++ b/client/src/pages/Update/FormOne/FormOne.module.css @@ -34,14 +34,14 @@ } .formone__dob_input { - width: 300px; + width: 330px; margin: 10px 0px; padding: 11px 10px; border: 3px solid; border-radius: 10px; } -.input__edit{ +.input__edit { display: flex; flex-direction: row; } diff --git a/client/src/pages/Update/Otp/Otp.jsx b/client/src/pages/Update/Otp/Otp.jsx index 31d8096..bce6ef7 100644 --- a/client/src/pages/Update/Otp/Otp.jsx +++ b/client/src/pages/Update/Otp/Otp.jsx @@ -1,19 +1,26 @@ -import React, { useEffect } from 'react' +import React, { useState, useEffect } from 'react' import Header from '../../../components/Header/Header' import Input from '../../../components/Input/Input' -import { Button, Grid } from '@mui/material' +import { Button } from '@mui/material' import { useNavigate } from 'react-router-dom' import { useTranslation } from 'react-i18next' import { userContext } from '../../../context/User' -import { useQuery } from 'react-query' -import { getUserByAadhaar } from '../../../services/apiservice' -import styles from './Otp.module.css' +import { useQuery, useMutation } from 'react-query' +import { getUserByAadhaar, sendOTP } from '../../../services/apiservice' import SubmitButton from '../../../components/SubmitButton/SubmitButton' +import { toast, ToastContainer } from 'react-toastify' + +import styles from './Otp.module.css' const Otp = () => { const navigate = useNavigate() const { t } = useTranslation() - const { aadhaarNumber, setUserData, oriUserData, setOriUserData } = + const [otp, setOtp] = useState() + const [disabled, setDisabled] = useState(false) + const [finalDisable, setFinalDisable] = useState(false) + const [unverified, setUnverified] = useState(true) + const [show, setShow] = useState(false) + const { aadhaarNumber, userData, setUserData, oriUserData, setOriUserData } = userContext() useEffect(() => { @@ -22,7 +29,6 @@ const Otp = () => { const isLongEnough = aadhaarNumber?.toString().length > 11 - // Make api call using the provided aadhaar number and set the user data in the context if the api call is successful. Set form data to the user data if the api call is successful and prevent too many re-renders. const { isLoading, isError, data } = useQuery('user', async () => { if (isLongEnough) { const response = await getUserByAadhaar(aadhaarNumber) @@ -30,6 +36,31 @@ const Otp = () => { } }) + const mutateOTP = useMutation(() => + sendOTP({ mobile: `+91${userData?.mobile}` }) + ) + + const verifyOTP = () => { + if (mutateOTP?.data?.data?.otpCode === Number(otp)) { + setFinalDisable(true) + setDisabled(true) + setShow(false) + setUnverified(false) + toast.success(t('OTP_VERIFIED!')) + } else { + toast.error(t('INCORRECT_OTP')) + } + } + + const sendResendOTP = () => { + setTimeout(() => { + if (finalDisable === false) { + console.log('Disabled: ', disabled, 'Final Disable: ', finalDisable) + setDisabled(false) + } + }, 30000) + } + if (isLoading) { return <div>{t('loading')}</div> } @@ -43,29 +74,66 @@ const Otp = () => { } return ( <> + <ToastContainer + autoClose={1000} + hideProgressBar={true} + theme={'colored'} + /> <Header subheading={`${t('UPDATE')}`} /> <div className={styles.subheading__container}> - <h3 className={styles.subheading}> {t('ENTER_OTP')} </h3> - <Input - type="text" - id="aadhaarNumber" - placeholder={`${t('ENTER_OTP')}`} - /> - <Grid container columnSpacing={10} justifyContent="center"> - <Grid item> + <h3 className={styles.subheading}>{t('ENTER_OTP')}</h3> + <p className={styles.subsubheading}> + {t('SENT_TO_YOUR_REGISTERED_MOBILE_NUMBER')} + </p> + <Button + color="primary" + size="large" + type="submit" + variant="contained" + disabled={disabled} + sx={{ marginTop: '1rem' }} + onClick={() => { + mutateOTP.mutate() + setDisabled(true) + setShow(true) + sendResendOTP() + }} + > + {show ? t('RESEND') : t('SEND_OTP')} + </Button> + {show && ( + <> + <Input + type="text" + id="otp" + value={otp} + onChange={(e) => setOtp(e.target.value)} + maxLength="6" + placeholder={t('ENTER_OTP')} + /> <Button color="primary" size="large" type="submit" variant="contained" - onClick={() => {}} + onClick={() => { + verifyOTP() + }} > {t('VERIFY_OTP')} </Button> - </Grid> - </Grid> + </> + )} </div> - <SubmitButton onClick={() => navigate('/update/select-update')} /> + <SubmitButton + onClick={() => { + if (unverified) { + toast.error(t('PLEASE_VERIFY_OTP')) + } else { + navigate('/update/select-update') + } + }} + /> </> ) } diff --git a/client/src/pages/Update/Otp/Otp.module.css b/client/src/pages/Update/Otp/Otp.module.css index 261d7aa..b88d5d4 100644 --- a/client/src/pages/Update/Otp/Otp.module.css +++ b/client/src/pages/Update/Otp/Otp.module.css @@ -12,3 +12,8 @@ font-size: var(--font-medium); font-weight: 400; } + +.subsubheading { + font-size: var(--font-medium-s); + margin: 10px 0px; +} diff --git a/client/src/pages/Update/Update.jsx b/client/src/pages/Update/Update.jsx index 2ef98ec..ecf1677 100644 --- a/client/src/pages/Update/Update.jsx +++ b/client/src/pages/Update/Update.jsx @@ -6,6 +6,8 @@ import { Grid, Button } from '@mui/material' import { userContext } from '../../context/User' import { useNavigate } from 'react-router-dom' import { useTranslation } from 'react-i18next' +import { ToastContainer, toast } from 'react-toastify' +import { validAadhaar } from '../../constants/RegEx' const Update = () => { const { aadhaarNumber, setAadhaarNumber } = userContext() @@ -15,11 +17,18 @@ const Update = () => { return ( <> + <ToastContainer + autoClose={1000} + hideProgressBar={true} + theme={'colored'} + /> <Header subheading={`${t('UPDATE')}`} /> <div className={styles.subheading__container}> - <h3 className={styles.subheading}> {t('PROVIDE_AADHAAR_NUMBER')} </h3> + <h3 className={styles.subheading}> + {t('PROVIDE_YOUR_AADHAAR_NUMBER')} + </h3> <Input - type="text" + type="number" id="aadhaarNumber" value={aadhaarNumber} onChange={(e) => setAadhaarNumber(e.target.value)} @@ -34,7 +43,11 @@ const Update = () => { type="submit" variant="contained" onClick={() => { - navigate('/update/otp') + if (!validAadhaar.test(aadhaarNumber)) { + toast.error(t('Please enter a valid aadhaar number')) + } else { + navigate('/update/otp') + } }} > {t('SUBMIT')} diff --git a/client/src/pages/Update/UpdateSelect/UpdateSelect.jsx b/client/src/pages/Update/UpdateSelect/UpdateSelect.jsx index e57587a..3c2edb3 100644 --- a/client/src/pages/Update/UpdateSelect/UpdateSelect.jsx +++ b/client/src/pages/Update/UpdateSelect/UpdateSelect.jsx @@ -1,27 +1,27 @@ import { t } from 'i18next' import React from 'react' import { Link } from 'react-router-dom' - import Card from '../../../components/Card/Card' import Header from '../../../components/Header/Header' import SubmitButton from '../../../components/SubmitButton/SubmitButton' + import styles from './UpdateSelect.module.css' const UpdateSelect = () => { return ( <> - <Header subheading={t('MERA_AADHAAR_MERI_PEHCHAN')} /> + <Header subheading={t('UPDATE')} /> <div className={styles.card__container}> <Link to="/update/demographic"> <Card title={t('DEMOGRAPHIC')} - image={`${process.env.PUBLIC_URL}/assets/images/enrollment.svg`} + image={`${process.env.PUBLIC_URL}/assets/images/demographic.svg`} /> </Link> <Link to="/update/biometric"> <Card title={t('BIOMETRIC')} - image={`${process.env.PUBLIC_URL}/assets/images/update.svg`} + image={`${process.env.PUBLIC_URL}/assets/images/biometrics.svg`} /> </Link> <Link to="/update/agreement"> |