| @@ -5,7 +5,6 @@ import { refreshUserToken } from "./store/actions/login/loginActions"; | |||
| import { useLocation } from "react-router-dom"; | |||
| import { | |||
| HOME_PAGE, | |||
| ADS_PAGE, | |||
| AD_DETAILS_PAGE, | |||
| FORGOT_PASSWORD_PAGE, | |||
| @@ -28,14 +27,10 @@ import { | |||
| CREATE_AD_PAGE, | |||
| } from "./constants/pages"; | |||
| // import LoginPage from './pages/LoginPage/LoginPage'; | |||
| import LoginPage from "./pages/LoginPage/LoginPageMUI"; | |||
| // import HomePage from './pages/HomePage/HomePage'; | |||
| import HomePage from "./pages/HomePage/HomePageMUI"; | |||
| import AdsPage from "./pages/AdsPage/AdsPage"; | |||
| import NotFoundPage from "./pages/ErrorPages/NotFoundPage"; | |||
| import ErrorPage from "./pages/ErrorPages/ErrorPage"; | |||
| // import ForgotPasswordPage from './pages/ForgotPasswordPage/ForgotPasswordPage'; | |||
| import ForgotPasswordPage from "./pages/ForgotPasswordPage/ForgotPasswordPageMUI"; | |||
| import PrivateRoute from "./components/Router/PrivateRoute"; | |||
| import ForgotPasswordConfirmationPage from "./pages/ForgotPasswordPage/ForgotPasswordConfirmationPageMUI"; | |||
| @@ -77,7 +72,6 @@ const AppRoutes = () => { | |||
| /> | |||
| <Route exact path={REGISTER_PAGE} component={RegisterPage} /> | |||
| <Route path={RESET_PASSWORD_PAGE} component={ResetPasswordPage} /> | |||
| <PrivateRoute exact path={HOME_PAGE} component={HomePage} /> | |||
| <PrivateRoute exact path={ADS_PAGE} component={AdsPage} /> | |||
| <PrivateRoute exact path={AD_DETAILS_PAGE} component={AdDetailsPage} /> | |||
| <PrivateRoute exact path={USER_DETAILS_PAGE} component={UserDetails} /> | |||
| @@ -0,0 +1,48 @@ | |||
| import * as redux from "react-redux"; | |||
| import store from "../../store"; | |||
| import { Router } from "react-router-dom"; | |||
| import { render } from "@testing-library/react"; | |||
| import history from "../../store/utils/history"; | |||
| import ErrorPage from "../../pages/ErrorPages/ErrorPage"; | |||
| describe("ErrorPage render tests", () => { | |||
| const cont = ( | |||
| <redux.Provider store={store}> | |||
| <Router history={history}> | |||
| <ErrorPage /> | |||
| </Router> | |||
| </redux.Provider> | |||
| ); | |||
| // beforeEach(() => { | |||
| // jest.mock("react-i18next", () => ({ | |||
| // useTranslation: () => ({ | |||
| // t: (key) => key, | |||
| // i18n: { changeLanguage: jest.fn() }, | |||
| // }), | |||
| // })); | |||
| // }); | |||
| afterEach(() => { | |||
| jest.restoreAllMocks(); | |||
| }); | |||
| it("Should render", () => { | |||
| const { container } = render(cont); | |||
| expect(container.getElementsByClassName("c-error-page")[0]).toBeDefined(); | |||
| }); | |||
| it("Should render status code 500", () => { | |||
| const { container } = render(cont); | |||
| expect( | |||
| container.getElementsByClassName("c-error-page__title")[0].textContent | |||
| ).toBe("500"); | |||
| }); | |||
| it("Should render text", () => { | |||
| const { container } = render(cont); | |||
| expect( | |||
| container.getElementsByClassName("c-error-page__text")[0] | |||
| ).toBeDefined(); | |||
| }); | |||
| }); | |||
| @@ -0,0 +1,69 @@ | |||
| import * as redux from "react-redux"; | |||
| import store from "../../store"; | |||
| import { Router } from "react-router-dom"; | |||
| import { render, screen } from "@testing-library/react"; | |||
| import history from "../../store/utils/history"; | |||
| import ForgotPasswordConfirmationPage from "../../pages/ForgotPasswordPage/ForgotPasswordConfirmationPageMUI"; | |||
| describe("ForgotPasswordConfirmationPage render tests", () => { | |||
| const cont = ( | |||
| <redux.Provider store={store}> | |||
| <Router history={history}> | |||
| <ForgotPasswordConfirmationPage /> | |||
| </Router> | |||
| </redux.Provider> | |||
| ); | |||
| afterEach(() => { | |||
| jest.restoreAllMocks(); | |||
| }); | |||
| it("Should render", () => { | |||
| const { container } = render(cont); | |||
| expect( | |||
| container.getElementsByClassName("c-login-container")[0] | |||
| ).toBeDefined(); | |||
| }); | |||
| it("Should render login logo", () => { | |||
| const { container } = render(cont); | |||
| expect(container.getElementsByClassName("login-logo")[0]).toBeDefined(); | |||
| }); | |||
| it("Should render header", () => { | |||
| const { container } = render(cont); | |||
| expect( | |||
| container | |||
| .getElementsByClassName("c-login-container")[0] | |||
| .querySelector("h") | |||
| ).toBeDefined(); | |||
| }); | |||
| it("Should render paragraph", () => { | |||
| const { container } = render(cont); | |||
| expect( | |||
| container | |||
| .getElementsByClassName("c-login-container")[0] | |||
| .querySelector("p") | |||
| ).toBeDefined(); | |||
| }); | |||
| it("Should link for paragraph", () => { | |||
| const { container } = render(cont); | |||
| expect( | |||
| container | |||
| .getElementsByClassName("c-login-container")[0] | |||
| .querySelector("p") | |||
| ).toBeDefined(); | |||
| }); | |||
| it("Should render link for going to login page", () => { | |||
| render(cont); | |||
| expect(screen.getByTestId("back-link")).toBeDefined(); | |||
| }); | |||
| it("Should render dilig logo", () => { | |||
| render(cont); | |||
| expect(screen.getByTestId("dilig-logo")).toBeDefined(); | |||
| }); | |||
| }); | |||
| @@ -0,0 +1,94 @@ | |||
| import * as redux from "react-redux"; | |||
| import store from "../../store"; | |||
| import { Router } from "react-router-dom"; | |||
| import { fireEvent, render, screen, waitFor } from "@testing-library/react"; | |||
| import history from "../../store/utils/history"; | |||
| import ForgotPasswordPage from "../../pages/ForgotPasswordPage/ForgotPasswordPageMUI"; | |||
| describe("ForgotPasswordPage render tests", () => { | |||
| const cont = ( | |||
| <redux.Provider store={store}> | |||
| <Router history={history}> | |||
| <ForgotPasswordPage /> | |||
| </Router> | |||
| </redux.Provider> | |||
| ); | |||
| let spyOnUseDispatch; | |||
| let mockDispatch; | |||
| beforeEach(() => { | |||
| spyOnUseDispatch = jest.spyOn(redux, "useDispatch"); | |||
| mockDispatch = jest.fn(); | |||
| spyOnUseDispatch.mockReturnValue(mockDispatch); | |||
| }); | |||
| afterEach(() => { | |||
| jest.restoreAllMocks(); | |||
| }); | |||
| it("Should render", () => { | |||
| const { container } = render(cont); | |||
| expect( | |||
| container.getElementsByClassName("c-login-container")[0] | |||
| ).toBeDefined(); | |||
| }); | |||
| it("Should render login logo", () => { | |||
| const { container } = render(cont); | |||
| expect(container.getElementsByClassName("login-logo")[0]).toBeDefined(); | |||
| }); | |||
| it("Should render header", () => { | |||
| const { container } = render(cont); | |||
| expect( | |||
| container | |||
| .getElementsByClassName("c-login-container")[0] | |||
| .querySelector("h") | |||
| ).toBeDefined(); | |||
| }); | |||
| it("Should render paragraph", () => { | |||
| const { container } = render(cont); | |||
| expect( | |||
| container | |||
| .getElementsByClassName("c-login-container")[0] | |||
| .querySelector("p") | |||
| ).toBeDefined(); | |||
| }); | |||
| it("Should render email input", () => { | |||
| render(cont); | |||
| expect(screen.getByTestId("email-input")).toBeDefined(); | |||
| }); | |||
| it("Should render submit button", () => { | |||
| const { container } = render(cont); | |||
| expect(container.getElementsByClassName("c-btn")[0]).toBeDefined(); | |||
| }); | |||
| it("Should render link for going to login page", () => { | |||
| render(cont); | |||
| expect(screen.getByTestId("back-link")).toBeDefined(); | |||
| }); | |||
| it("Should render dilig logo", () => { | |||
| render(cont); | |||
| expect(screen.getByTestId("dilig-logo")).toBeDefined(); | |||
| }); | |||
| it("Should not dispatch function because input for email is empty", async () => { | |||
| const { container } = render(cont); | |||
| fireEvent.click(container.getElementsByClassName("c-btn")[0]); | |||
| await waitFor(() => expect(mockDispatch).toBeCalledTimes(0)); | |||
| }); | |||
| it("Should dispatch function becxause input for email is not empty", async () => { | |||
| const { container } = render(cont); | |||
| fireEvent.change(screen.getByTestId("email-input"), { | |||
| target: { value: "dzenis@dilig.net" }, | |||
| }); | |||
| fireEvent.click(container.getElementsByClassName("c-btn")[0]); | |||
| await waitFor(() => expect(mockDispatch).toBeCalledTimes(1)); | |||
| }); | |||
| }); | |||
| @@ -0,0 +1,46 @@ | |||
| import * as redux from "react-redux"; | |||
| import store from "../../store"; | |||
| import { Router } from "react-router-dom"; | |||
| import { render } from "@testing-library/react"; | |||
| import history from "../../store/utils/history"; | |||
| import NotFoundPage from "../../pages/ErrorPages/NotFoundPage"; | |||
| describe("ErrorPage render tests", () => { | |||
| const cont = ( | |||
| <redux.Provider store={store}> | |||
| <Router history={history}> | |||
| <NotFoundPage /> | |||
| </Router> | |||
| </redux.Provider> | |||
| ); | |||
| afterEach(() => { | |||
| jest.restoreAllMocks(); | |||
| }); | |||
| it("Should render", () => { | |||
| const { container } = render(cont); | |||
| expect(container.getElementsByClassName("not-found-page")[0]).toBeDefined(); | |||
| }); | |||
| it("Should render status code 404", () => { | |||
| const { container } = render(cont); | |||
| expect( | |||
| container.getElementsByClassName("c-error-page__title")[0].textContent | |||
| ).toBe("404"); | |||
| }); | |||
| it("Should render text", () => { | |||
| const { container } = render(cont); | |||
| expect( | |||
| container.getElementsByClassName("c-error-page__text")[0] | |||
| ).toBeDefined(); | |||
| }); | |||
| it("Should render button for going back to previous page", () => { | |||
| const { container } = render(cont); | |||
| expect( | |||
| container.getElementsByClassName("c-error-page__button")[0] | |||
| ).toBeDefined(); | |||
| }); | |||
| }); | |||
| @@ -0,0 +1,126 @@ | |||
| import * as redux from "react-redux"; | |||
| import store from "../../store"; | |||
| import { Router } from "react-router-dom"; | |||
| import { fireEvent, render, screen, waitFor } from "@testing-library/react"; | |||
| import history from "../../store/utils/history"; | |||
| import ResetPasswordPage from "../../pages/ForgotPasswordPage/ResetPasswordPageMUI"; | |||
| describe("ResetPassword render tests", () => { | |||
| const cont = ( | |||
| <redux.Provider store={store}> | |||
| <Router history={history}> | |||
| <ResetPasswordPage /> | |||
| </Router> | |||
| </redux.Provider> | |||
| ); | |||
| let spyOnUseDispatch; | |||
| let mockDispatch; | |||
| beforeEach(() => { | |||
| spyOnUseDispatch = jest.spyOn(redux, "useDispatch"); | |||
| mockDispatch = jest.fn(); | |||
| spyOnUseDispatch.mockReturnValue(mockDispatch); | |||
| }); | |||
| afterEach(() => { | |||
| jest.restoreAllMocks(); | |||
| }); | |||
| it("Should render", () => { | |||
| const { container } = render(cont); | |||
| expect( | |||
| container.getElementsByClassName("c-login-container")[0] | |||
| ).toBeDefined(); | |||
| }); | |||
| it("Should render login logo", () => { | |||
| const { container } = render(cont); | |||
| expect(container.getElementsByClassName("login-logo")[0]).toBeDefined(); | |||
| }); | |||
| it("Should render header", () => { | |||
| const { container } = render(cont); | |||
| expect( | |||
| container | |||
| .getElementsByClassName("c-login-container")[0] | |||
| .querySelector("h") | |||
| ).toBeDefined(); | |||
| }); | |||
| it("Should render paragraph", () => { | |||
| const { container } = render(cont); | |||
| expect( | |||
| container | |||
| .getElementsByClassName("c-login-container")[0] | |||
| .querySelector("p") | |||
| ).toBeDefined(); | |||
| }); | |||
| it("Should render password input", () => { | |||
| render(cont); | |||
| expect(screen.getByTestId("password-input")).toBeDefined(); | |||
| }); | |||
| it("Should render confirm password input", () => { | |||
| render(cont); | |||
| expect(screen.getByTestId("confirm-password-input")).toBeDefined(); | |||
| }); | |||
| it("Should render submit button", () => { | |||
| const { container } = render(cont); | |||
| expect(container.getElementsByClassName("c-btn")[0]).toBeDefined(); | |||
| }); | |||
| it("Should render link for going to login page", () => { | |||
| render(cont); | |||
| expect(screen.getByTestId("back-link")).toBeDefined(); | |||
| }); | |||
| it("Should render dilig logo", () => { | |||
| render(cont); | |||
| expect(screen.getByTestId("dilig-logo")).toBeDefined(); | |||
| }); | |||
| it("Should not dispatch function because input for password is empty", async () => { | |||
| const { container } = render(cont); | |||
| fireEvent.change(screen.getByTestId("confirm-password-input"), { | |||
| target: { value: "nekaSifra" }, | |||
| }); | |||
| fireEvent.click(container.getElementsByClassName("c-btn")[0]); | |||
| await waitFor(() => expect(mockDispatch).toBeCalledTimes(0)); | |||
| }); | |||
| it("Should not dispatch function because input for confirm password is empty", async () => { | |||
| const { container } = render(cont); | |||
| fireEvent.change(screen.getByTestId("password-input"), { | |||
| target: { value: "nekaSifra" }, | |||
| }); | |||
| fireEvent.click(container.getElementsByClassName("c-btn")[0]); | |||
| await waitFor(() => expect(mockDispatch).toBeCalledTimes(0)); | |||
| }); | |||
| it("Should not dispatch function because paswwords doesn't match", async () => { | |||
| const { container } = render(cont); | |||
| fireEvent.change(screen.getByTestId("password-input"), { | |||
| target: { value: "nekaSifra" }, | |||
| }); | |||
| fireEvent.change(screen.getByTestId("confirm-password-input"), { | |||
| target: { value: "nekaDrugaSifra" }, | |||
| }); | |||
| fireEvent.click(container.getElementsByClassName("c-btn")[0]); | |||
| await waitFor(() => expect(mockDispatch).toBeCalledTimes(0)); | |||
| }); | |||
| it("Should dispatch function because no input is empty and passwords match", async () => { | |||
| const { container } = render(cont); | |||
| fireEvent.change(screen.getByTestId("password-input"), { | |||
| target: { value: "nekaSifra" }, | |||
| }); | |||
| fireEvent.change(screen.getByTestId("confirm-password-input"), { | |||
| target: { value: "nekaSifra" }, | |||
| }); | |||
| fireEvent.click(container.getElementsByClassName("c-btn")[0]); | |||
| await waitFor(() => expect(mockDispatch).toBeCalledTimes(1)); | |||
| }); | |||
| }); | |||
| @@ -8,7 +8,7 @@ const NotFoundPage = () => { | |||
| return ( | |||
| // <div className="c-error-page"> to be FIXED LATER!!!! | |||
| <div className=""> | |||
| <div className="not-found-page"> | |||
| <Section className="c-error-page__content-container"> | |||
| <div className="c-error-page__content"> | |||
| <h1 className="c-error-page__title">404</h1> | |||
| @@ -1,70 +1,61 @@ | |||
| import React from 'react'; | |||
| import { useTranslation } from 'react-i18next'; | |||
| import React from "react"; | |||
| import { useTranslation } from "react-i18next"; | |||
| import HrLogo from "../../assets/images/hrcenter.png"; | |||
| import DiligLogo from "../../assets/images/logo_horizontal_black.png"; | |||
| import { | |||
| Box, | |||
| Container, | |||
| Typography, | |||
| Link, | |||
| Grid, | |||
| } from '@mui/material'; | |||
| import Backdrop from '../../components/MUI/BackdropComponent'; | |||
| import { BASE_PAGE } from '../../constants/pages'; | |||
| import { NavLink } from 'react-router-dom'; | |||
| import { Box, Container, Typography, Link, Grid } from "@mui/material"; | |||
| import Backdrop from "../../components/MUI/BackdropComponent"; | |||
| import { BASE_PAGE } from "../../constants/pages"; | |||
| import { NavLink } from "react-router-dom"; | |||
| const ForgotPasswordConfirmationPage = () => { | |||
| const { t } = useTranslation(); | |||
| const { t } = useTranslation(); | |||
| return ( | |||
| <Container | |||
| component="main" | |||
| maxWidth="xl" | |||
| className="c-login-container" | |||
| fullwidth="true"> | |||
| <div className="l-t-rectangle"></div> | |||
| <div className="r-b-rectangle"></div> | |||
| <Box | |||
| sx={{ | |||
| marginTop: 2, | |||
| width: 350, | |||
| height: 684, | |||
| display: "flex", | |||
| flexDirection: "column", | |||
| alignItems: "center", | |||
| }} | |||
| > | |||
| <img src={HrLogo} className="login-logo" /> | |||
| <Typography variant="h5" sx={{ m: 2, mt: 3 }}> | |||
| {t("login.forgotYourPassword")} | |||
| </Typography> | |||
| <Typography variant="p"> | |||
| {t("login.forgotYourPasswordConfimation")} | |||
| </Typography> | |||
| <Box | |||
| component="form" | |||
| sx={{ position: 'relative', mt: 1, p: 1 }} | |||
| > | |||
| <Backdrop position="absolute" isLoading={false} /> | |||
| <Grid container justifyContent="center"> | |||
| <Link | |||
| to={BASE_PAGE} | |||
| component={NavLink} | |||
| variant="body2" | |||
| underline="hover" | |||
| > | |||
| {t('login.forgotYourPasswordBackLink')} | |||
| </Link> | |||
| </Grid> | |||
| <div className="flex-center"> | |||
| <img src={DiligLogo} style={{ margin: "70px auto 0px auto" }} /> | |||
| </div> | |||
| </Box> | |||
| </Box> | |||
| </Container> | |||
| ); | |||
| return ( | |||
| <Container | |||
| component="main" | |||
| maxWidth="xl" | |||
| className="c-login-container" | |||
| fullwidth="true" | |||
| > | |||
| <div className="l-t-rectangle"></div> | |||
| <div className="r-b-rectangle"></div> | |||
| <Box | |||
| sx={{ | |||
| marginTop: 2, | |||
| width: 350, | |||
| height: 684, | |||
| display: "flex", | |||
| flexDirection: "column", | |||
| alignItems: "center", | |||
| }} | |||
| > | |||
| <img src={HrLogo} className="login-logo" /> | |||
| <Typography variant="h5" sx={{ m: 2, mt: 3 }}> | |||
| {t("login.forgotYourPassword")} | |||
| </Typography> | |||
| <Typography variant="p"> | |||
| {t("login.forgotYourPasswordConfimation")} | |||
| </Typography> | |||
| <Box component="form" sx={{ position: "relative", mt: 1, p: 1 }}> | |||
| <Backdrop position="absolute" isLoading={false} /> | |||
| <Grid container justifyContent="center"> | |||
| <Link | |||
| to={BASE_PAGE} | |||
| component={NavLink} | |||
| variant="body2" | |||
| underline="hover" | |||
| data-testid="back-link" | |||
| > | |||
| {t("login.forgotYourPasswordBackLink")} | |||
| </Link> | |||
| </Grid> | |||
| <div className="flex-center" data-testid="dilig-logo"> | |||
| <img src={DiligLogo} style={{ margin: "70px auto 0px auto" }} /> | |||
| </div> | |||
| </Box> | |||
| </Box> | |||
| </Container> | |||
| ); | |||
| }; | |||
| export default ForgotPasswordConfirmationPage; | |||
| @@ -1,63 +0,0 @@ | |||
| import React from 'react'; | |||
| import { Formik, Form, Field } from 'formik'; | |||
| import { useTranslation } from 'react-i18next'; | |||
| import * as Yup from 'yup'; | |||
| import i18next from 'i18next'; | |||
| import Auth from '../../components/Auth/Auth'; | |||
| import AuthCard from '../../components/AuthCards/AuthCard'; | |||
| import TextField from '../../components/InputFields/TextField'; | |||
| import Button from '../../components/Button/Button'; | |||
| import Section from '../../components/Section/Section'; | |||
| const forgotPasswordValidationSchema = Yup.object().shape({ | |||
| email: Yup.string().required( | |||
| i18next.t('login.securityQuestion.answerRequired'), | |||
| ), | |||
| }); | |||
| const ForgotPasswordPage = () => { | |||
| const { t } = useTranslation(); | |||
| const handleSubmit = (values) => { | |||
| console.log("Values",values) | |||
| }; | |||
| return ( | |||
| <Auth> | |||
| <AuthCard | |||
| title={t('forgotPassword.title')} | |||
| > | |||
| <Section> | |||
| <div className="c-reset-security"> | |||
| <div className="c-reset-security__form"> | |||
| <Formik | |||
| onSubmit={handleSubmit} | |||
| initialValues={{ email: '' }} | |||
| validationSchema={forgotPasswordValidationSchema} | |||
| > | |||
| <Form> | |||
| <Field | |||
| label={t('login.forgotPasswordEmail')} | |||
| name="email" | |||
| component={TextField} | |||
| /> | |||
| <Button | |||
| className="c-reset-security__button" | |||
| authButton | |||
| variant="primary" | |||
| type="submit" | |||
| > | |||
| {t('forgotPassword.label')} | |||
| </Button> | |||
| </Form> | |||
| </Formik> | |||
| </div> | |||
| </div> | |||
| </Section> | |||
| </AuthCard> | |||
| </Auth> | |||
| ); | |||
| }; | |||
| export default ForgotPasswordPage; | |||
| @@ -102,6 +102,7 @@ const ForgotPasswordPage = ({ history }) => { | |||
| helperText={formik.touched.email && formik.errors.email} | |||
| autoFocus | |||
| fullWidth | |||
| inputProps={{"data-testid": "email-input"}} | |||
| /> | |||
| <Button | |||
| type="submit" | |||
| @@ -118,11 +119,12 @@ const ForgotPasswordPage = ({ history }) => { | |||
| component={NavLink} | |||
| variant="body2" | |||
| underline="hover" | |||
| data-testid="back-link" | |||
| > | |||
| {t('login.forgotYourPasswordBackLink')} | |||
| </Link> | |||
| </Grid> | |||
| <div className="flex-center"> | |||
| <div className="flex-center" data-testid="dilig-logo"> | |||
| <img src={DiligLogo} style={{ margin: "70px auto 0px auto" }} /> | |||
| </div> | |||
| </Box> | |||
| @@ -1,210 +1,224 @@ | |||
| import React, { useState } from 'react'; | |||
| import React, { useState } from "react"; | |||
| import PropTypes from "prop-types"; | |||
| import { useFormik } from 'formik'; | |||
| import { useTranslation } from 'react-i18next'; | |||
| import { useFormik } from "formik"; | |||
| import { useTranslation } from "react-i18next"; | |||
| import { useDispatch } from "react-redux"; | |||
| import DiligLogo from "../../assets/images/logo_horizontal_black.png"; | |||
| import * as Yup from 'yup'; | |||
| import * as Yup from "yup"; | |||
| // import i18next from 'i18next'; | |||
| import HrLogo from "../../assets/images/hrcenter.png"; | |||
| import { | |||
| Box, | |||
| Container, | |||
| Typography, | |||
| Button, | |||
| InputAdornment, | |||
| IconButton, | |||
| TextField, | |||
| Link, | |||
| Grid, | |||
| } from '@mui/material'; | |||
| Box, | |||
| Container, | |||
| Typography, | |||
| Button, | |||
| InputAdornment, | |||
| IconButton, | |||
| TextField, | |||
| Link, | |||
| Grid, | |||
| } from "@mui/material"; | |||
| import { Visibility, VisibilityOff } from "@mui/icons-material"; | |||
| import Backdrop from '../../components/MUI/BackdropComponent'; | |||
| import { BASE_PAGE } from '../../constants/pages'; | |||
| import { NavLink } from 'react-router-dom'; | |||
| import { resetPassword } from '../../store/actions/login/loginActions'; | |||
| import Backdrop from "../../components/MUI/BackdropComponent"; | |||
| import { BASE_PAGE } from "../../constants/pages"; | |||
| import { NavLink } from "react-router-dom"; | |||
| import { resetPassword } from "../../store/actions/login/loginActions"; | |||
| function getQueryVariable(variable) { | |||
| var query = window.location.search.substring(1); | |||
| var vars = query.split("&"); | |||
| for (var i = 0; i < vars.length; i++) { | |||
| var pair = vars[i].split("="); | |||
| if (pair[0] == variable) { return pair[1]; } | |||
| } | |||
| return (false); | |||
| var query = window.location.search.substring(1); | |||
| var vars = query.split("&"); | |||
| for (var i = 0; i < vars.length; i++) { | |||
| var pair = vars[i].split("="); | |||
| if (pair[0] == variable) { | |||
| return pair[1]; | |||
| } | |||
| } | |||
| return false; | |||
| } | |||
| const ResetPasswordPage = ({ history }) => { | |||
| const dispatch = useDispatch(); | |||
| const { t } = useTranslation(); | |||
| const dispatch = useDispatch(); | |||
| const { t } = useTranslation(); | |||
| const [showPassword, setShowPassword] = useState(false); | |||
| const [showConfirmPassword, setShowConfirmPassword] = useState(false); | |||
| const handleClickShowPassword = () => setShowPassword(!showPassword); | |||
| const handleMouseDownPassword = () => setShowPassword(!showPassword); | |||
| const [showPassword, setShowPassword] = useState(false); | |||
| const [showConfirmPassword, setShowConfirmPassword] = useState(false); | |||
| const handleClickShowPassword = () => setShowPassword(!showPassword); | |||
| const handleMouseDownPassword = () => setShowPassword(!showPassword); | |||
| const handleClickShowConfirmPassword = () => setShowConfirmPassword(!showConfirmPassword); | |||
| const handleMouseDownConfirmPassword = () => setShowConfirmPassword(!showConfirmPassword); | |||
| const handleClickShowConfirmPassword = () => | |||
| setShowConfirmPassword(!showConfirmPassword); | |||
| const handleMouseDownConfirmPassword = () => | |||
| setShowConfirmPassword(!showConfirmPassword); | |||
| const resetPasswordValidationSchema = Yup.object().shape({ | |||
| password: Yup.string().required(t("login.passwordRequired")), | |||
| confirmPassword: Yup.string().required(t("login.passwordRequired")) | |||
| .oneOf([Yup.ref('password'), null], t('login.passwordDontMatch')) | |||
| }); | |||
| const resetPasswordValidationSchema = Yup.object().shape({ | |||
| password: Yup.string().required(t("login.passwordRequired")), | |||
| confirmPassword: Yup.string() | |||
| .required(t("login.passwordRequired")) | |||
| .oneOf([Yup.ref("password"), null], t("login.passwordDontMatch")), | |||
| }); | |||
| const handleSubmit = (values) => { | |||
| const password = values.password; | |||
| // const confirmPassword = values.confirmPassword; | |||
| // if (password === confirmPassword) | |||
| { | |||
| const code = getQueryVariable('token'), | |||
| email = getQueryVariable('email'); | |||
| dispatch( | |||
| resetPassword({ | |||
| code, | |||
| email, | |||
| password, | |||
| handleApiResponseSuccess, | |||
| }) | |||
| ); | |||
| } | |||
| }; | |||
| const handleSubmit = (values) => { | |||
| const password = values.password; | |||
| // const confirmPassword = values.confirmPassword; | |||
| // if (password === confirmPassword) | |||
| { | |||
| const code = getQueryVariable("token"), | |||
| email = getQueryVariable("email"); | |||
| dispatch( | |||
| resetPassword({ | |||
| code, | |||
| email, | |||
| password, | |||
| handleApiResponseSuccess, | |||
| }) | |||
| ); | |||
| } | |||
| }; | |||
| const handleApiResponseSuccess = () => { | |||
| history.push({ | |||
| pathname: BASE_PAGE, | |||
| state: { | |||
| from: history.location.pathname, | |||
| }, | |||
| }); | |||
| }; | |||
| const handleApiResponseSuccess = () => { | |||
| history.push({ | |||
| pathname: BASE_PAGE, | |||
| state: { | |||
| from: history.location.pathname, | |||
| }, | |||
| }); | |||
| }; | |||
| const formik = useFormik({ | |||
| initialValues: { | |||
| password: '', | |||
| confirmPassword: '', | |||
| }, | |||
| validationSchema: resetPasswordValidationSchema, | |||
| onSubmit: handleSubmit, | |||
| validateOnBlur: true, | |||
| enableReinitialize: true, | |||
| }); | |||
| const formik = useFormik({ | |||
| initialValues: { | |||
| password: "", | |||
| confirmPassword: "", | |||
| }, | |||
| validationSchema: resetPasswordValidationSchema, | |||
| onSubmit: handleSubmit, | |||
| validateOnBlur: true, | |||
| enableReinitialize: true, | |||
| }); | |||
| return ( | |||
| <Container | |||
| component="main" | |||
| maxWidth="xl" | |||
| className="c-login-container" | |||
| fullwidth="true"> | |||
| <div className="l-t-rectangle"></div> | |||
| <div className="r-b-rectangle"></div> | |||
| <Box | |||
| sx={{ | |||
| marginTop: 2, | |||
| width: 350, | |||
| height: 684, | |||
| display: "flex", | |||
| flexDirection: "column", | |||
| alignItems: "center", | |||
| }} | |||
| > | |||
| <img src={HrLogo} className="login-logo" /> | |||
| <Typography variant="h5" sx={{ m: 2, mt: 3 }}> | |||
| {t("login.resetYourPassword")} | |||
| </Typography> | |||
| <Typography variant="p"> | |||
| {t("login.resetYourPasswordHelpText")} | |||
| </Typography> | |||
| <Box | |||
| component="form" | |||
| onSubmit={formik.handleSubmit} | |||
| sx={{ position: 'relative', mt: 1, p: 1 }} | |||
| > | |||
| <Backdrop position="absolute" isLoading={false} /> | |||
| <TextField | |||
| className="rounded-input" | |||
| name="password" | |||
| label={t("common.labelPassword")} | |||
| margin="normal" | |||
| type={showPassword ? "text" : "password"} | |||
| value={formik.values.password} | |||
| onChange={formik.handleChange} | |||
| error={formik.touched.password && Boolean(formik.errors.password)} | |||
| helperText={formik.touched.password && formik.errors.password} | |||
| fullWidth | |||
| InputProps={{ | |||
| endAdornment: ( | |||
| <InputAdornment position="end"> | |||
| <IconButton | |||
| onClick={handleClickShowPassword} | |||
| onMouseDown={handleMouseDownPassword} | |||
| > | |||
| {showPassword ? <Visibility /> : <VisibilityOff />} | |||
| </IconButton> | |||
| </InputAdornment> | |||
| ), | |||
| }} | |||
| /> | |||
| <TextField | |||
| className="rounded-input" | |||
| name="confirmPassword" | |||
| label={t("common.labelConfirmPassword")} | |||
| margin="normal" | |||
| type={showConfirmPassword ? "text" : "password"} | |||
| value={formik.values.confirmPassword} | |||
| onChange={formik.handleChange} | |||
| error={formik.touched.confirmPassword && Boolean(formik.errors.confirmPassword)} | |||
| helperText={formik.touched.confirmPassword && formik.errors.confirmPassword} | |||
| fullWidth | |||
| InputProps={{ | |||
| endAdornment: ( | |||
| <InputAdornment position="end"> | |||
| <IconButton | |||
| onClick={handleClickShowConfirmPassword} | |||
| onMouseDown={handleMouseDownConfirmPassword} | |||
| > | |||
| {showConfirmPassword ? <Visibility /> : <VisibilityOff />} | |||
| </IconButton> | |||
| </InputAdornment> | |||
| ), | |||
| }} | |||
| /> | |||
| <Button | |||
| type="submit" | |||
| variant="contained" | |||
| sx={{ mt: 3, mb: 2 }} | |||
| fullWidth | |||
| className="c-btn c-btn--primary" | |||
| > | |||
| {t('login.forgotYourPasswordButton')} | |||
| </Button> | |||
| <Grid container justifyContent="center"> | |||
| <Link | |||
| to={BASE_PAGE} | |||
| component={NavLink} | |||
| variant="body2" | |||
| underline="hover" | |||
| > | |||
| {t('login.forgotYourPasswordBackLink')} | |||
| </Link> | |||
| </Grid> | |||
| <div className="flex-center"> | |||
| <img src={DiligLogo} style={{ margin: "70px auto 0px auto" }} /> | |||
| </div> | |||
| </Box> | |||
| </Box> | |||
| </Container> | |||
| ); | |||
| return ( | |||
| <Container | |||
| component="main" | |||
| maxWidth="xl" | |||
| className="c-login-container" | |||
| fullwidth="true" | |||
| > | |||
| <div className="l-t-rectangle"></div> | |||
| <div className="r-b-rectangle"></div> | |||
| <Box | |||
| sx={{ | |||
| marginTop: 2, | |||
| width: 350, | |||
| height: 684, | |||
| display: "flex", | |||
| flexDirection: "column", | |||
| alignItems: "center", | |||
| }} | |||
| > | |||
| <img src={HrLogo} className="login-logo" /> | |||
| <Typography variant="h5" sx={{ m: 2, mt: 3 }}> | |||
| {t("login.resetYourPassword")} | |||
| </Typography> | |||
| <Typography variant="p"> | |||
| {t("login.resetYourPasswordHelpText")} | |||
| </Typography> | |||
| <Box | |||
| component="form" | |||
| onSubmit={formik.handleSubmit} | |||
| sx={{ position: "relative", mt: 1, p: 1 }} | |||
| > | |||
| <Backdrop position="absolute" isLoading={false} /> | |||
| <TextField | |||
| className="rounded-input" | |||
| name="password" | |||
| label={t("common.labelPassword")} | |||
| margin="normal" | |||
| type={showPassword ? "text" : "password"} | |||
| value={formik.values.password} | |||
| onChange={formik.handleChange} | |||
| error={formik.touched.password && Boolean(formik.errors.password)} | |||
| helperText={formik.touched.password && formik.errors.password} | |||
| fullWidth | |||
| inputProps={{ "data-testid": "password-input" }} | |||
| InputProps={{ | |||
| endAdornment: ( | |||
| <InputAdornment position="end"> | |||
| <IconButton | |||
| onClick={handleClickShowPassword} | |||
| onMouseDown={handleMouseDownPassword} | |||
| > | |||
| {showPassword ? <Visibility /> : <VisibilityOff />} | |||
| </IconButton> | |||
| </InputAdornment> | |||
| ), | |||
| }} | |||
| /> | |||
| <TextField | |||
| className="rounded-input" | |||
| name="confirmPassword" | |||
| label={t("common.labelConfirmPassword")} | |||
| margin="normal" | |||
| type={showConfirmPassword ? "text" : "password"} | |||
| value={formik.values.confirmPassword} | |||
| onChange={formik.handleChange} | |||
| error={ | |||
| formik.touched.confirmPassword && | |||
| Boolean(formik.errors.confirmPassword) | |||
| } | |||
| helperText={ | |||
| formik.touched.confirmPassword && formik.errors.confirmPassword | |||
| } | |||
| fullWidth | |||
| inputProps={{ "data-testid": "confirm-password-input" }} | |||
| InputProps={{ | |||
| endAdornment: ( | |||
| <InputAdornment position="end"> | |||
| <IconButton | |||
| onClick={handleClickShowConfirmPassword} | |||
| onMouseDown={handleMouseDownConfirmPassword} | |||
| > | |||
| {showConfirmPassword ? <Visibility /> : <VisibilityOff />} | |||
| </IconButton> | |||
| </InputAdornment> | |||
| ), | |||
| }} | |||
| /> | |||
| <Button | |||
| type="submit" | |||
| variant="contained" | |||
| sx={{ mt: 3, mb: 2 }} | |||
| fullWidth | |||
| className="c-btn c-btn--primary" | |||
| > | |||
| {t("login.forgotYourPasswordButton")} | |||
| </Button> | |||
| <Grid container justifyContent="center"> | |||
| <Link | |||
| to={BASE_PAGE} | |||
| component={NavLink} | |||
| variant="body2" | |||
| underline="hover" | |||
| data-testid="back-link" | |||
| > | |||
| {t("login.forgotYourPasswordBackLink")} | |||
| </Link> | |||
| </Grid> | |||
| <div className="flex-center" data-testid="dilig-logo"> | |||
| <img src={DiligLogo} style={{ margin: "70px auto 0px auto" }} /> | |||
| </div> | |||
| </Box> | |||
| </Box> | |||
| </Container> | |||
| ); | |||
| }; | |||
| ResetPasswordPage.propTypes = { | |||
| history: PropTypes.shape({ | |||
| replace: PropTypes.func, | |||
| push: PropTypes.func, | |||
| location: PropTypes.shape({ | |||
| pathname: PropTypes.string, | |||
| }), | |||
| }), | |||
| } | |||
| history: PropTypes.shape({ | |||
| replace: PropTypes.func, | |||
| push: PropTypes.func, | |||
| location: PropTypes.shape({ | |||
| pathname: PropTypes.string, | |||
| }), | |||
| }), | |||
| }; | |||
| export default ResetPasswordPage; | |||
| @@ -1,15 +0,0 @@ | |||
| import React from 'react'; | |||
| const HomePage = () => { | |||
| return ( | |||
| <div className="c-error-page"> | |||
| <div className="c-error-page__content"> | |||
| <h1 className="c-error-page__title">Home page</h1> | |||
| </div> | |||
| </div> | |||
| ); | |||
| }; | |||
| HomePage.propTypes = {}; | |||
| export default HomePage; | |||
| @@ -1,39 +0,0 @@ | |||
| import React from "react"; | |||
| // import { Box, Grid } from '@mui/material'; | |||
| // import Navbar from "../../components/MUI/NavbarComponent"; | |||
| // import Modals from '../../components/MUI/Examples/ModalsExample'; | |||
| // import DataGrid from '../../components/MUI/Examples/DataGridExample'; | |||
| // import PagingSortingFiltering from '../../components/MUI/Examples/PagingSortingFilteringExample'; | |||
| // import PagingSortingFilteringServerSide from '../../components/MUI/Examples/PagingSortingFilteringExampleServerSide'; | |||
| // import RandomDataProvider from '../../context/RandomDataContext'; | |||
| const HomePage = () => { | |||
| return ( | |||
| <div> | |||
| {/* <Navbar /> */} | |||
| <div className="l-t-rectangle"></div> | |||
| <div className="r-b-rectangle"></div> | |||
| {/* <Box sx={{ mt: 4, mx: 4 }}> | |||
| <Grid container spacing={2} justifyContent="center"> | |||
| <Grid item xs={12} md={3}> | |||
| <Modals /> | |||
| </Grid> | |||
| <Grid item xs={12} md={6}> | |||
| <DataGrid /> | |||
| </Grid> | |||
| <Grid item xs={12} md={9}> | |||
| <PagingSortingFiltering /> | |||
| </Grid> | |||
| <Grid item xs={12} md={9}> */} | |||
| {/* Move to higher components? */} | |||
| {/* <RandomDataProvider> | |||
| <PagingSortingFilteringServerSide /> | |||
| </RandomDataProvider> | |||
| </Grid> | |||
| </Grid> | |||
| </Box> */} | |||
| </div> | |||
| ); | |||
| }; | |||
| export default HomePage; | |||
| @@ -1,146 +0,0 @@ | |||
| import React from 'react'; | |||
| import PropTypes from 'prop-types'; | |||
| import { Field, Form, Formik } from 'formik'; | |||
| import { useDispatch, useSelector } from 'react-redux'; | |||
| import { NavLink } from 'react-router-dom'; | |||
| import * as Yup from 'yup'; | |||
| import { useTranslation } from 'react-i18next'; | |||
| import i18next from 'i18next'; | |||
| import PasswordField from '../../components/InputFields/PasswordField'; | |||
| import Button from '../../components/Button/Button'; | |||
| import TextField from '../../components/InputFields/TextField'; | |||
| import Auth from '../../components/Auth/Auth'; | |||
| import AuthCard from '../../components/AuthCards/AuthCard'; | |||
| import { | |||
| clearLoginErrors, | |||
| fetchUser, | |||
| } from '../../store/actions/login/loginActions'; | |||
| import { | |||
| selectLoginError, | |||
| } from '../../store/selectors/loginSelectors'; | |||
| import { | |||
| FORGOT_PASSWORD_PAGE, HOME_PAGE, | |||
| } from '../../constants/pages'; | |||
| import { selectIsLoadingByActionType } from '../../store/selectors/loadingSelectors'; | |||
| import { LOGIN_USER_LOADING } from '../../store/actions/login/loginActionConstants'; | |||
| const LoginValidationSchema = Yup.object().shape({ | |||
| username: Yup.string().required(i18next.t('login.usernameRequired')), | |||
| password: Yup.string().required(i18next.t('login.passwordRequired')), | |||
| }); | |||
| const LoginPage = ({ history }) => { | |||
| const dispatch = useDispatch(); | |||
| const { t } = useTranslation(); | |||
| const error = useSelector(selectLoginError); | |||
| // When user refreshes page | |||
| // useEffect(() => { | |||
| // function redirectClient() { | |||
| // if (!tokens.RefreshToken && !tokens.JwtToken) { | |||
| // return | |||
| // } | |||
| // } | |||
| // redirectClient(); | |||
| // }, [history, tokens]); | |||
| const isLoading = useSelector( | |||
| selectIsLoadingByActionType(LOGIN_USER_LOADING), | |||
| ); | |||
| const handleApiResponseSuccess =()=>{ | |||
| history.push({ | |||
| pathname: HOME_PAGE, | |||
| state: { | |||
| from: history.location.pathname, | |||
| }, | |||
| }); | |||
| } | |||
| const handleSubmit = (values) => { | |||
| // destructure value as username. | |||
| const { username: Username } = values; | |||
| const { password: Password } = values; | |||
| dispatch(clearLoginErrors()); | |||
| dispatch( | |||
| fetchUser({ | |||
| Username, | |||
| Password, | |||
| handleApiResponseSuccess | |||
| }, | |||
| ), | |||
| ); | |||
| }; | |||
| return ( | |||
| <Auth> | |||
| <AuthCard | |||
| title="Log In" | |||
| isLoading={isLoading} | |||
| > | |||
| <div className="c-login c-login--user"> | |||
| <div className="c-login__form"> | |||
| <Formik | |||
| initialValues={{ | |||
| username: '', | |||
| password: '', | |||
| }} | |||
| onSubmit={handleSubmit} | |||
| validationSchema={LoginValidationSchema} | |||
| validateOnBlur | |||
| enableReinitialize | |||
| > | |||
| {({ values }) => ( | |||
| <Form> | |||
| <Field | |||
| label={t('common.labelUsername')} | |||
| value={values.username.value} | |||
| component={TextField} | |||
| name="username" | |||
| /> | |||
| <Field | |||
| label={ | |||
| <div className="c-login--password__label"> | |||
| {t('common.labelPassword')} | |||
| </div> | |||
| } | |||
| link={ | |||
| <NavLink | |||
| to={FORGOT_PASSWORD_PAGE} | |||
| > | |||
| {t('login.forgotYourPassword')} | |||
| </NavLink> | |||
| } | |||
| name="password" | |||
| component={PasswordField} | |||
| errorMessage={error} | |||
| autoFocus | |||
| /> | |||
| <Button | |||
| className="c-login__button" | |||
| authButton | |||
| variant="primary" | |||
| type="submit" | |||
| > | |||
| {t('common.continue')} | |||
| </Button> | |||
| </Form> | |||
| )} | |||
| </Formik> | |||
| </div> | |||
| </div> | |||
| </AuthCard> | |||
| </Auth> | |||
| ); | |||
| }; | |||
| LoginPage.propTypes = { | |||
| history: PropTypes.shape({ | |||
| replace: PropTypes.func, | |||
| push: PropTypes.func, | |||
| location: PropTypes.shape({ | |||
| pathname: PropTypes.string, | |||
| }), | |||
| }), | |||
| }; | |||
| export default LoginPage; | |||