| @@ -24,6 +24,7 @@ | |||
| "lodash": "^4.17.21", | |||
| "lodash.isempty": "^4.4.0", | |||
| "owasp-password-strength-test": "^1.3.0", | |||
| "query-string": "^7.1.1", | |||
| "react": "^17.0.2", | |||
| "react-dom": "^17.0.2", | |||
| "react-helmet-async": "^1.0.9", | |||
| @@ -3,6 +3,9 @@ | |||
| <head> | |||
| <meta charset="utf-8" /> | |||
| <link rel="icon" href="%PUBLIC_URL%/favicon.ico" /> | |||
| <link rel="stylesheet" type="text/css" href="https://fonts.googleapis.com/css?family=Open+Sans"> | |||
| <link rel="stylesheet" type="text/css" href="https://fonts.googleapis.com/css?family=Poppins"> | |||
| <link rel="stylesheet" type="text/css" href="https://fonts.googleapis.com/css?family=Mulish"> | |||
| <meta name="viewport" content="width=device-width, initial-scale=1" /> | |||
| <meta name="theme-color" content="#000000" /> | |||
| <meta | |||
| @@ -1,24 +1,29 @@ | |||
| import React from 'react'; | |||
| import { Router } from 'react-router-dom'; | |||
| import { Helmet } from 'react-helmet-async'; | |||
| import i18next from 'i18next'; | |||
| import history from './store/utils/history'; | |||
| import AppRoutes from './AppRoutes'; | |||
| import React from "react"; | |||
| import { Router } from "react-router-dom"; | |||
| import { Helmet } from "react-helmet-async"; | |||
| import i18next from "i18next"; | |||
| import history from "./store/utils/history"; | |||
| import AppRoutes from "./AppRoutes"; | |||
| import GlobalStyle from "./components/Styles/globalStyles"; | |||
| import { StyledEngineProvider } from "@mui/material"; | |||
| const App = () => ( | |||
| const App = () => { | |||
| return ( | |||
| <> | |||
| <Router history={history}> | |||
| <Helmet> | |||
| <title> | |||
| {i18next.t('app.title')} | |||
| </title> | |||
| <title>{i18next.t("app.title")}</title> | |||
| </Helmet> | |||
| <main className="l-page"> | |||
| <AppRoutes /> | |||
| </main> | |||
| </Router> | |||
| {/* <main className="l-page"> */} | |||
| <StyledEngineProvider injectFirst> | |||
| <GlobalStyle /> | |||
| <AppRoutes /> | |||
| </StyledEngineProvider> | |||
| {/* </main> */} | |||
| </Router> | |||
| </> | |||
| ); | |||
| }; | |||
| export default App; | |||
| export default App; | |||
| @@ -8,25 +8,36 @@ import { | |||
| NOT_FOUND_PAGE, | |||
| ERROR_PAGE, | |||
| BASE_PAGE, | |||
| FORGOT_PASSWORD_MAIL_SENT, | |||
| REGISTER_PAGE, | |||
| REGISTER_SUCCESSFUL_PAGE, | |||
| RESET_PASSWORD_PAGE, | |||
| } from './constants/pages'; | |||
| // import LoginPage from './pages/LoginPage/LoginPage'; | |||
| import LoginPage from './pages/LoginPage/LoginPageMUI'; | |||
| // import HomePage from './pages/HomePage/HomePage'; | |||
| import LoginPage from './pages/LoginPage/LoginPage'; | |||
| import HomePage from './pages/HomePage/HomePageMUI'; | |||
| 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 ForgotPasswordPage from './pages/ForgotPasswordPage/ForgotPasswordPage'; | |||
| import PrivateRoute from './components/Router/PrivateRoute'; | |||
| import MailSent from './pages/ForgotPasswordPage/ForgotPasswordMailSent/MailSent'; | |||
| import Register from './pages/RegisterPages/Register/Register'; | |||
| import RegisterSuccessful from './pages/RegisterPages/RegisterSuccessful.js/RegisterSuccessful'; | |||
| import ResetPasswordPage from './pages/ResetPasswordPage/ResetPasswordPage'; | |||
| const AppRoutes = () => ( | |||
| const AppRoutes = () => { | |||
| return ( | |||
| <Switch> | |||
| <Route exact path={BASE_PAGE} component={LoginPage} /> | |||
| <Route exact path={LOGIN_PAGE} component={LoginPage} /> | |||
| <Route path={NOT_FOUND_PAGE} component={NotFoundPage} /> | |||
| <Route path={REGISTER_SUCCESSFUL_PAGE} component={RegisterSuccessful} /> | |||
| <Route path={REGISTER_PAGE} component={Register} /> | |||
| <Route path={ERROR_PAGE} component={ErrorPage} /> | |||
| <Route path={FORGOT_PASSWORD_MAIL_SENT} component={MailSent} /> | |||
| <Route path={FORGOT_PASSWORD_PAGE} component={ForgotPasswordPage} /> | |||
| <Route path={RESET_PASSWORD_PAGE} component={ResetPasswordPage}/> | |||
| <PrivateRoute | |||
| exact | |||
| path={HOME_PAGE} | |||
| @@ -34,7 +45,7 @@ const AppRoutes = () => ( | |||
| /> | |||
| <Redirect from="*" to={NOT_FOUND_PAGE} /> | |||
| </Switch> | |||
| ); | |||
| )}; | |||
| export default AppRoutes; | |||
| @@ -0,0 +1,4 @@ | |||
| <svg width="22" height="22" viewBox="0 0 22 22" fill="none" xmlns="http://www.w3.org/2000/svg"> | |||
| <path d="M18.3334 6.41663H3.66671C2.65419 6.41663 1.83337 7.23744 1.83337 8.24996V17.4166C1.83337 18.4291 2.65419 19.25 3.66671 19.25H18.3334C19.3459 19.25 20.1667 18.4291 20.1667 17.4166V8.24996C20.1667 7.23744 19.3459 6.41663 18.3334 6.41663Z" stroke="#C4C4C4" stroke-width="1.6" stroke-linecap="round" stroke-linejoin="round"/> | |||
| <path d="M14.6667 19.25V4.58333C14.6667 4.0971 14.4736 3.63079 14.1297 3.28697C13.7859 2.94315 13.3196 2.75 12.8334 2.75H9.16671C8.68048 2.75 8.21416 2.94315 7.87035 3.28697C7.52653 3.63079 7.33337 4.0971 7.33337 4.58333V19.25" stroke="#C4C4C4" stroke-width="1.6" stroke-linecap="round" stroke-linejoin="round"/> | |||
| </svg> | |||
| @@ -0,0 +1,13 @@ | |||
| <svg width="25" height="28" viewBox="0 0 25 28" fill="none" xmlns="http://www.w3.org/2000/svg"> | |||
| <g clip-path="url(#clip0_86_8377)"> | |||
| <path d="M7.49117 6.3122L1.21472 7.6463L2.54882 13.9227L8.82527 12.5886L7.49117 6.3122Z" stroke="#9677BE" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/> | |||
| <path d="M17.3542 4.21577L11.0778 5.54987L12.4119 11.8263L18.6883 10.4922L17.3542 4.21577Z" stroke="#9677BE" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/> | |||
| <path d="M19.4506 14.0787L13.1742 15.4128L14.5083 21.6893L20.7847 20.3552L19.4506 14.0787Z" stroke="#9677BE" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/> | |||
| <path d="M9.5876 16.1752L3.31116 17.5093L4.64526 23.7857L10.9217 22.4516L9.5876 16.1752Z" stroke="#9677BE" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/> | |||
| </g> | |||
| <defs> | |||
| <clipPath id="clip0_86_8377"> | |||
| <rect width="22" height="22" fill="white" transform="translate(-2.04688 5.52814) rotate(-12)"/> | |||
| </clipPath> | |||
| </defs> | |||
| </svg> | |||
| @@ -0,0 +1,6 @@ | |||
| <svg width="22" height="22" viewBox="0 0 22 22" fill="none" xmlns="http://www.w3.org/2000/svg"> | |||
| <path d="M9.16667 2.75H2.75V9.16667H9.16667V2.75Z" stroke="#4D4D4D" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/> | |||
| <path d="M19.2499 2.75H12.8333V9.16667H19.2499V2.75Z" stroke="#4D4D4D" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/> | |||
| <path d="M19.2499 12.8333H12.8333V19.25H19.2499V12.8333Z" stroke="#4D4D4D" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/> | |||
| <path d="M9.16667 12.8333H2.75V19.25H9.16667V12.8333Z" stroke="#4D4D4D" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/> | |||
| </svg> | |||
| @@ -0,0 +1,4 @@ | |||
| <svg width="18" height="18" viewBox="0 0 18 18" fill="none" xmlns="http://www.w3.org/2000/svg"> | |||
| <path d="M16.5 8.31002V9.00002C16.4991 10.6173 15.9754 12.191 15.007 13.4864C14.0386 14.7818 12.6775 15.7294 11.1265 16.1879C9.57557 16.6465 7.91794 16.5914 6.40085 16.031C4.88376 15.4705 3.58849 14.4346 2.70822 13.0778C1.82795 11.721 1.40984 10.1161 1.51626 8.50226C1.62267 6.88844 2.24791 5.35227 3.29871 4.12283C4.34951 2.89338 5.76959 2.03656 7.34714 1.68013C8.92469 1.3237 10.5752 1.48677 12.0525 2.14502" stroke="#C4C4C4" stroke-width="1.6" stroke-linecap="round" stroke-linejoin="round"/> | |||
| <path d="M16.5 3L9 10.5075L6.75 8.2575" stroke="#C4C4C4" stroke-width="1.6" stroke-linecap="round" stroke-linejoin="round"/> | |||
| </svg> | |||
| @@ -0,0 +1,3 @@ | |||
| <svg width="12" height="9" viewBox="0 0 12 9" fill="none" xmlns="http://www.w3.org/2000/svg"> | |||
| <path d="M1 5.2L3.85714 8L11 1" stroke="#FEB005" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/> | |||
| </svg> | |||
| @@ -0,0 +1,4 @@ | |||
| <svg width="16" height="16" viewBox="0 0 10 11" fill="none" xmlns="http://www.w3.org/2000/svg"> | |||
| <path d="M7.50024 3.4978L2.50006 8.49799" stroke="black" stroke-linecap="round"/> | |||
| <path d="M2.50024 3.4978L7.50043 8.49799" stroke="black" stroke-linecap="round"/> | |||
| </svg> | |||
| @@ -0,0 +1,4 @@ | |||
| <svg width="16" height="16" viewBox="0 0 10 11" fill="none" xmlns="http://www.w3.org/2000/svg"> | |||
| <path d="M7.50024 3.4978L2.50006 8.49799" stroke="white" stroke-linecap="round"/> | |||
| <path d="M2.50024 3.4978L7.50043 8.49799" stroke="white" stroke-linecap="round"/> | |||
| </svg> | |||
| @@ -0,0 +1,7 @@ | |||
| <svg width="12" height="12" viewBox="0 0 12 12" fill="none" xmlns="http://www.w3.org/2000/svg"> | |||
| <path d="M9 4H9.5C10.0304 4 10.5391 4.21071 10.9142 4.58579C11.2893 4.96086 11.5 5.46957 11.5 6C11.5 6.53043 11.2893 7.03914 10.9142 7.41421C10.5391 7.78929 10.0304 8 9.5 8H9" stroke="#FEB005" stroke-linecap="round" stroke-linejoin="round"/> | |||
| <path d="M1 4H9V8.5C9 9.03043 8.78929 9.53914 8.41421 9.91421C8.03914 10.2893 7.53043 10.5 7 10.5H3C2.46957 10.5 1.96086 10.2893 1.58579 9.91421C1.21071 9.53914 1 9.03043 1 8.5V4Z" stroke="#FEB005" stroke-linecap="round" stroke-linejoin="round"/> | |||
| <path d="M3 0.5V2" stroke="#FEB005" stroke-linecap="round" stroke-linejoin="round"/> | |||
| <path d="M5 0.5V2" stroke="#FEB005" stroke-linecap="round" stroke-linejoin="round"/> | |||
| <path d="M7 0.5V2" stroke="#FEB005" stroke-linecap="round" stroke-linejoin="round"/> | |||
| </svg> | |||
| @@ -0,0 +1,3 @@ | |||
| <svg width="14" height="8" viewBox="0 0 14 8" fill="none" xmlns="http://www.w3.org/2000/svg"> | |||
| <path d="M1.5 1.25L7 6.75L12.5 1.25" stroke="#5A3984" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/> | |||
| </svg> | |||
| @@ -0,0 +1,4 @@ | |||
| <svg width="18" height="18" viewBox="0 0 18 18" fill="none" xmlns="http://www.w3.org/2000/svg"> | |||
| <path d="M8.25 3H3C2.60218 3 2.22064 3.15804 1.93934 3.43934C1.65804 3.72064 1.5 4.10218 1.5 4.5V15C1.5 15.3978 1.65804 15.7794 1.93934 16.0607C2.22064 16.342 2.60218 16.5 3 16.5H13.5C13.8978 16.5 14.2794 16.342 14.5607 16.0607C14.842 15.7794 15 15.3978 15 15V9.75" stroke="#5A3984" stroke-width="1.6" stroke-linecap="round" stroke-linejoin="round"/> | |||
| <path d="M13.875 1.87505C14.1734 1.57668 14.578 1.40906 15 1.40906C15.422 1.40906 15.8266 1.57668 16.125 1.87505C16.4234 2.17342 16.591 2.57809 16.591 3.00005C16.591 3.422 16.4234 3.82668 16.125 4.12505L9 11.25L6 12L6.75 9.00005L13.875 1.87505Z" stroke="#5A3984" stroke-width="1.6" stroke-linecap="round" stroke-linejoin="round"/> | |||
| </svg> | |||
| @@ -0,0 +1,4 @@ | |||
| <svg width="22" height="16" viewBox="0 0 22 16" fill="none" xmlns="http://www.w3.org/2000/svg"> | |||
| <path d="M13.9999 7.99994C13.9999 8.79557 13.6838 9.55862 13.1212 10.1212C12.5586 10.6838 11.7956 10.9999 10.9999 10.9999C10.2043 10.9999 9.44126 10.6838 8.87866 10.1212C8.31606 9.55862 8 8.79557 8 7.99994C8 7.20431 8.31606 6.44126 8.87866 5.87866C9.44126 5.31606 10.2043 5 10.9999 5C11.7956 5 12.5586 5.31606 13.1212 5.87866C13.6838 6.44126 13.9999 7.20431 13.9999 7.99994V7.99994Z" stroke="#5A3984" stroke-linecap="round" stroke-linejoin="round"/> | |||
| <path d="M1.45898 7.99986C2.73296 3.94294 6.52388 1 11.0008 1C15.4787 1 19.2686 3.94294 20.5426 7.99986C19.2686 12.0568 15.4787 14.9997 11.0008 14.9997C6.52388 14.9997 2.73296 12.0568 1.45898 7.99986Z" stroke="#5A3984" stroke-linecap="round" stroke-linejoin="round"/> | |||
| </svg> | |||
| @@ -0,0 +1,3 @@ | |||
| <svg width="23" height="18" viewBox="0 0 17 16" fill="none" xmlns="http://www.w3.org/2000/svg"> | |||
| <path d="M4.24741 12.2086L1.42675 15M7.02641 13.3083C7.51222 13.3992 8.00558 13.4448 8.5 13.4444C12.0193 13.4444 14.998 11.1554 16 8C15.7302 7.15074 15.3147 6.3538 14.7716 5.64411L7.02641 13.3083ZM10.1677 6.35033C9.72551 5.91271 9.12576 5.66686 8.50039 5.66686C7.87502 5.66686 7.27527 5.91271 6.83307 6.35033C6.39087 6.78796 6.14244 7.3815 6.14244 8.00039C6.14244 8.61928 6.39087 9.21282 6.83307 9.65044L10.1677 6.35033ZM10.1677 6.34956L6.83386 9.64889L10.1677 6.34956ZM10.1661 6.35111L12.7518 3.79222L10.1661 6.35111ZM6.83228 9.65044L4.24662 12.2093L6.83228 9.65044ZM15.5732 1L12.7518 3.79222L15.5732 1ZM12.7518 3.79222C11.4846 2.983 10.0081 2.55354 8.5 2.55556C4.98067 2.55556 2.00204 4.84456 1 8C1.55325 9.7348 2.702 11.2236 4.24741 12.2086L12.7518 3.79222Z" stroke="#5A3984" stroke-linecap="round" stroke-linejoin="round"/> | |||
| </svg> | |||
| @@ -0,0 +1,5 @@ | |||
| <svg width="24" height="24" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg"> | |||
| <path d="M12 22C17.5228 22 22 17.5228 22 12C22 6.47715 17.5228 2 12 2C6.47715 2 2 6.47715 2 12C2 17.5228 6.47715 22 12 22Z" stroke="#C4C4C4" stroke-width="1.6" stroke-linecap="round" stroke-linejoin="round"/> | |||
| <path d="M2 12H22" stroke="#C4C4C4" stroke-width="1.6" stroke-linecap="round" stroke-linejoin="round"/> | |||
| <path d="M12 2C14.5013 4.73835 15.9228 8.29203 16 12C15.9228 15.708 14.5013 19.2616 12 22C9.49872 19.2616 8.07725 15.708 8 12C8.07725 8.29203 9.49872 4.73835 12 2V2Z" stroke="#C4C4C4" stroke-width="1.6" stroke-linecap="round" stroke-linejoin="round"/> | |||
| </svg> | |||
| @@ -0,0 +1,4 @@ | |||
| <svg width="12" height="12" viewBox="0 0 12 12" fill="none" xmlns="http://www.w3.org/2000/svg"> | |||
| <path d="M1.5 4.5L6 1L10.5 4.5V10C10.5 10.2652 10.3946 10.5196 10.2071 10.7071C10.0196 10.8946 9.76522 11 9.5 11H2.5C2.23478 11 1.98043 10.8946 1.79289 10.7071C1.60536 10.5196 1.5 10.2652 1.5 10V4.5Z" stroke="#5A3984" stroke-linecap="round" stroke-linejoin="round"/> | |||
| <path d="M4.5 11V6H7.5V11" stroke="#5A3984" stroke-linecap="round" stroke-linejoin="round"/> | |||
| </svg> | |||
| @@ -0,0 +1,11 @@ | |||
| <svg width="22" height="22" viewBox="0 0 22 22" fill="none" xmlns="http://www.w3.org/2000/svg"> | |||
| <g clip-path="url(#clip0_2_29355)"> | |||
| <path d="M19.25 9.16663C19.25 15.5833 11 21.0833 11 21.0833C11 21.0833 2.75 15.5833 2.75 9.16663C2.75 6.97859 3.61919 4.88017 5.16637 3.333C6.71354 1.78582 8.81196 0.916626 11 0.916626C13.188 0.916626 15.2865 1.78582 16.8336 3.333C18.3808 4.88017 19.25 6.97859 19.25 9.16663Z" stroke="#4D4D4D" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/> | |||
| <path d="M11 11.9166C12.5188 11.9166 13.75 10.6854 13.75 9.16663C13.75 7.64784 12.5188 6.41663 11 6.41663C9.48122 6.41663 8.25 7.64784 8.25 9.16663C8.25 10.6854 9.48122 11.9166 11 11.9166Z" stroke="#4D4D4D" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/> | |||
| </g> | |||
| <defs> | |||
| <clipPath id="clip0_2_29355"> | |||
| <rect width="22" height="22" fill="white"/> | |||
| </clipPath> | |||
| </defs> | |||
| </svg> | |||
| @@ -0,0 +1,3 @@ | |||
| <svg width="18" height="18" viewBox="0 0 18 18" fill="none" xmlns="http://www.w3.org/2000/svg"> | |||
| <path d="M12.5 11H11.71L11.43 10.73C12.41 9.59 13 8.11 13 6.5C13 2.91 10.09 0 6.5 0C2.91 0 0 2.91 0 6.5C0 10.09 2.91 13 6.5 13C8.11 13 9.59 12.41 10.73 11.43L11 11.71V12.5L16 17.49L17.49 16L12.5 11ZM6.5 11C4.01 11 2 8.99 2 6.5C2 4.01 4.01 2 6.5 2C8.99 2 11 4.01 11 6.5C11 8.99 8.99 11 6.5 11Z" fill="#5A3984"/> | |||
| </svg> | |||
| @@ -0,0 +1,4 @@ | |||
| <svg width="20" height="20" viewBox="0 0 20 20" fill="none" xmlns="http://www.w3.org/2000/svg"> | |||
| <path d="M3.33341 3.33337H16.6667C17.5834 3.33337 18.3334 4.08337 18.3334 5.00004V15C18.3334 15.9167 17.5834 16.6667 16.6667 16.6667H3.33341C2.41675 16.6667 1.66675 15.9167 1.66675 15V5.00004C1.66675 4.08337 2.41675 3.33337 3.33341 3.33337Z" stroke="#5A3984" stroke-width="1.6" stroke-linecap="round" stroke-linejoin="round"/> | |||
| <path d="M18.3334 5L10.0001 10.8333L1.66675 5" stroke="#5A3984" stroke-width="1.6" stroke-linecap="round" stroke-linejoin="round"/> | |||
| </svg> | |||
| @@ -0,0 +1,4 @@ | |||
| <svg width="40" height="40" viewBox="0 0 40 40" fill="none" xmlns="http://www.w3.org/2000/svg"> | |||
| <circle cx="20" cy="20" r="20" fill="#E4E4E4"/> | |||
| <path fill-rule="evenodd" clip-rule="evenodd" d="M13 14C13 13.7348 13.1054 13.4804 13.2929 13.2929C13.4804 13.1054 13.7348 13 14 13H26C26.2652 13 26.5196 13.1054 26.7071 13.2929C26.8946 13.4804 27 13.7348 27 14C27 14.2652 26.8946 14.5196 26.7071 14.7071C26.5196 14.8946 26.2652 15 26 15H14C13.7348 15 13.4804 14.8946 13.2929 14.7071C13.1054 14.5196 13 14.2652 13 14ZM13 18C13 17.7348 13.1054 17.4804 13.2929 17.2929C13.4804 17.1054 13.7348 17 14 17H26C26.2652 17 26.5196 17.1054 26.7071 17.2929C26.8946 17.4804 27 17.7348 27 18C27 18.2652 26.8946 18.5196 26.7071 18.7071C26.5196 18.8946 26.2652 19 26 19H14C13.7348 19 13.4804 18.8946 13.2929 18.7071C13.1054 18.5196 13 18.2652 13 18ZM13 22C13 21.7348 13.1054 21.4804 13.2929 21.2929C13.4804 21.1054 13.7348 21 14 21H26C26.2652 21 26.5196 21.1054 26.7071 21.2929C26.8946 21.4804 27 21.7348 27 22C27 22.2652 26.8946 22.5196 26.7071 22.7071C26.5196 22.8946 26.2652 23 26 23H14C13.7348 23 13.4804 22.8946 13.2929 22.7071C13.1054 22.5196 13 22.2652 13 22ZM13 26C13 25.7348 13.1054 25.4804 13.2929 25.2929C13.4804 25.1054 13.7348 25 14 25H26C26.2652 25 26.5196 25.1054 26.7071 25.2929C26.8946 25.4804 27 25.7348 27 26C27 26.2652 26.8946 26.5196 26.7071 26.7071C26.5196 26.8946 26.2652 27 26 27H14C13.7348 27 13.4804 26.8946 13.2929 26.7071C13.1054 26.5196 13 26.2652 13 26Z" fill="#5A3984"/> | |||
| </svg> | |||
| @@ -0,0 +1,4 @@ | |||
| <svg width="40" height="40" viewBox="0 0 40 40" fill="none" xmlns="http://www.w3.org/2000/svg"> | |||
| <circle cx="20" cy="20" r="20" fill="#E4E4E4"/> | |||
| <path d="M12 14C12 13.4696 12.2107 12.9609 12.5858 12.5858C12.9609 12.2107 13.4696 12 14 12H16C16.5304 12 17.0391 12.2107 17.4142 12.5858C17.7893 12.9609 18 13.4696 18 14V16C18 16.5304 17.7893 17.0391 17.4142 17.4142C17.0391 17.7893 16.5304 18 16 18H14C13.4696 18 12.9609 17.7893 12.5858 17.4142C12.2107 17.0391 12 16.5304 12 16V14ZM22 14C22 13.4696 22.2107 12.9609 22.5858 12.5858C22.9609 12.2107 23.4696 12 24 12H26C26.5304 12 27.0391 12.2107 27.4142 12.5858C27.7893 12.9609 28 13.4696 28 14V16C28 16.5304 27.7893 17.0391 27.4142 17.4142C27.0391 17.7893 26.5304 18 26 18H24C23.4696 18 22.9609 17.7893 22.5858 17.4142C22.2107 17.0391 22 16.5304 22 16V14ZM12 24C12 23.4696 12.2107 22.9609 12.5858 22.5858C12.9609 22.2107 13.4696 22 14 22H16C16.5304 22 17.0391 22.2107 17.4142 22.5858C17.7893 22.9609 18 23.4696 18 24V26C18 26.5304 17.7893 27.0391 17.4142 27.4142C17.0391 27.7893 16.5304 28 16 28H14C13.4696 28 12.9609 27.7893 12.5858 27.4142C12.2107 27.0391 12 26.5304 12 26V24ZM22 24C22 23.4696 22.2107 22.9609 22.5858 22.5858C22.9609 22.2107 23.4696 22 24 22H26C26.5304 22 27.0391 22.2107 27.4142 22.5858C27.7893 22.9609 28 23.4696 28 24V26C28 26.5304 27.7893 27.0391 27.4142 27.4142C27.0391 27.7893 26.5304 28 26 28H24C23.4696 28 22.9609 27.7893 22.5858 27.4142C22.2107 27.0391 22 26.5304 22 26V24Z" stroke="#8C8C8C" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/> | |||
| </svg> | |||
| @@ -0,0 +1,5 @@ | |||
| <svg width="12" height="12" viewBox="0 0 12 12" fill="none" xmlns="http://www.w3.org/2000/svg"> | |||
| <path d="M6 1L1 3.5L6 6L11 3.5L6 1Z" stroke="#4D4D4D" stroke-linecap="round" stroke-linejoin="round"/> | |||
| <path d="M1 8.5L6 11L11 8.5" stroke="#4D4D4D" stroke-linecap="round" stroke-linejoin="round"/> | |||
| <path d="M1 6L6 8.5L11 6" stroke="#4D4D4D" stroke-linecap="round" stroke-linejoin="round"/> | |||
| </svg> | |||
| @@ -0,0 +1,3 @@ | |||
| <svg width="14" height="14" viewBox="0 0 14 14" fill="none" xmlns="http://www.w3.org/2000/svg"> | |||
| <rect x="0.5" y="0.5" width="13" height="13" rx="6.5" fill="#64468B" stroke="#5A3984"/> | |||
| </svg> | |||
| @@ -0,0 +1,3 @@ | |||
| <svg width="14" height="14" viewBox="0 0 14 14" fill="none" xmlns="http://www.w3.org/2000/svg"> | |||
| <rect x="0.5" y="0.5" width="13" height="13" rx="6.5" stroke="#5A3984"/> | |||
| </svg> | |||
| @@ -0,0 +1,12 @@ | |||
| <svg width="18" height="18" viewBox="0 0 18 18" fill="none" xmlns="http://www.w3.org/2000/svg"> | |||
| <g clip-path="url(#clip0_86_8725)"> | |||
| <path d="M0.75 3V7.5H5.25" stroke="#FEB005" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/> | |||
| <path d="M17.25 15V10.5H12.75" stroke="#FEB005" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/> | |||
| <path d="M15.3675 6.75006C14.9871 5.67515 14.3407 4.71411 13.4884 3.95662C12.6361 3.19913 11.6059 2.66988 10.4938 2.41825C9.38167 2.16662 8.22393 2.20081 7.12861 2.51764C6.03328 2.83446 5.03606 3.42359 4.23 4.23006L0.75 7.50006M17.25 10.5001L13.77 13.7701C12.9639 14.5765 11.9667 15.1657 10.8714 15.4825C9.77607 15.7993 8.61833 15.8335 7.50621 15.5819C6.3941 15.3302 5.36385 14.801 4.5116 14.0435C3.65935 13.286 3.01288 12.325 2.6325 11.2501" stroke="#FEB005" stroke-width="1.6" stroke-linecap="round" stroke-linejoin="round"/> | |||
| </g> | |||
| <defs> | |||
| <clipPath id="clip0_86_8725"> | |||
| <rect width="18" height="18" fill="white"/> | |||
| </clipPath> | |||
| </defs> | |||
| </svg> | |||
| @@ -0,0 +1,3 @@ | |||
| <svg width="18" height="17" viewBox="0 0 18 17" fill="none" xmlns="http://www.w3.org/2000/svg"> | |||
| <path d="M9 1.5L11.3175 6.195L16.5 6.9525L12.75 10.605L13.635 15.765L9 13.3275L4.365 15.765L5.25 10.605L1.5 6.9525L6.6825 6.195L9 1.5Z" stroke="#4D4D4D" stroke-width="1.6" stroke-linecap="round" stroke-linejoin="round"/> | |||
| </svg> | |||
| @@ -0,0 +1,3 @@ | |||
| <svg width="20" height="20" viewBox="0 0 20 20" fill="none" xmlns="http://www.w3.org/2000/svg"> | |||
| <path d="M10 1.75V18.25M10 1.75H16.4167C16.9029 1.75 17.3692 1.94315 17.713 2.28697C18.0568 2.63079 18.25 3.0971 18.25 3.58333V16.4167C18.25 16.9029 18.0568 17.3692 17.713 17.713C17.3692 18.0568 16.9029 18.25 16.4167 18.25H10V1.75ZM10 1.75H3.58333C3.0971 1.75 2.63079 1.94315 2.28697 2.28697C1.94315 2.63079 1.75 3.0971 1.75 3.58333V16.4167C1.75 16.9029 1.94315 17.3692 2.28697 17.713C2.63079 18.0568 3.0971 18.25 3.58333 18.25H10V1.75Z" stroke="#4D4D4D" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/> | |||
| </svg> | |||
| @@ -0,0 +1,3 @@ | |||
| <svg width="18" height="18" viewBox="0 0 18 18" fill="none" xmlns="http://www.w3.org/2000/svg"> | |||
| <path d="M7.49999 11.25V14.25C7.49999 14.8468 7.73704 15.4191 8.159 15.841C8.58096 16.263 9.15326 16.5 9.74999 16.5L12.75 9.75003V1.50003H4.28999C3.92825 1.49594 3.57721 1.62272 3.30156 1.85702C3.02592 2.09132 2.84423 2.41735 2.78999 2.77503L1.75499 9.52503C1.72236 9.74001 1.73686 9.95952 1.79749 10.1683C1.85811 10.3772 1.96342 10.5703 2.1061 10.7344C2.24878 10.8985 2.42543 11.0296 2.62381 11.1186C2.82219 11.2076 3.03756 11.2525 3.25499 11.25H7.49999ZM12.75 1.50003H14.7525C15.177 1.49252 15.5894 1.64113 15.9116 1.91764C16.2337 2.19415 16.4431 2.57932 16.5 3.00003V8.25003C16.4431 8.67073 16.2337 9.0559 15.9116 9.33241C15.5894 9.60892 15.177 9.75753 14.7525 9.75003H12.75" fill="#FF3A3A"/> | |||
| </svg> | |||
| @@ -0,0 +1,3 @@ | |||
| <svg width="18" height="18" viewBox="0 0 18 18" fill="none" xmlns="http://www.w3.org/2000/svg"> | |||
| <path d="M10.5 6.75V3.75C10.5 3.15326 10.2629 2.58097 9.84099 2.15901C9.41903 1.73705 8.84674 1.5 8.25 1.5L5.25 8.25V16.5H13.71C14.0717 16.5041 14.4228 16.3773 14.6984 16.143C14.9741 15.9087 15.1558 15.5827 15.21 15.225L16.245 8.475C16.2776 8.26002 16.2631 8.04051 16.2025 7.83169C16.1419 7.62287 16.0366 7.42972 15.8939 7.26564C15.7512 7.10155 15.5746 6.97045 15.3762 6.88141C15.1778 6.79238 14.9624 6.74754 14.745 6.75H10.5ZM5.25 16.5H3C2.60218 16.5 2.22064 16.342 1.93934 16.0607C1.65804 15.7794 1.5 15.3978 1.5 15V9.75C1.5 9.35218 1.65804 8.97064 1.93934 8.68934C2.22064 8.40804 2.60218 8.25 3 8.25H5.25" fill="#0FB834"/> | |||
| </svg> | |||
| @@ -0,0 +1,4 @@ | |||
| <svg width="18" height="18" viewBox="0 0 18 18" fill="none" xmlns="http://www.w3.org/2000/svg"> | |||
| <path d="M2.25 4.5H3.75H15.75" stroke="#5A3984" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/> | |||
| <path d="M6 4.5V3C6 2.60218 6.15804 2.22064 6.43934 1.93934C6.72064 1.65804 7.10218 1.5 7.5 1.5H10.5C10.8978 1.5 11.2794 1.65804 11.5607 1.93934C11.842 2.22064 12 2.60218 12 3V4.5M14.25 4.5V15C14.25 15.3978 14.092 15.7794 13.8107 16.0607C13.5294 16.342 13.1478 16.5 12.75 16.5H5.25C4.85218 16.5 4.47064 16.342 4.18934 16.0607C3.90804 15.7794 3.75 15.3978 3.75 15V4.5H14.25Z" stroke="#5A3984" stroke-width="1.6" stroke-linecap="round" stroke-linejoin="round"/> | |||
| </svg> | |||
| @@ -0,0 +1,6 @@ | |||
| <svg width="12" height="12" viewBox="0 0 12 12" fill="none" xmlns="http://www.w3.org/2000/svg"> | |||
| <path d="M8 1.5H0.5V8H8V1.5Z" stroke="#5A3984" stroke-linecap="round" stroke-linejoin="round"/> | |||
| <path d="M8 4H10L11.5 5.5V8H8V4Z" stroke="#5A3984" stroke-linecap="round" stroke-linejoin="round"/> | |||
| <path d="M2.75 10.5C3.44036 10.5 4 9.94036 4 9.25C4 8.55964 3.44036 8 2.75 8C2.05964 8 1.5 8.55964 1.5 9.25C1.5 9.94036 2.05964 10.5 2.75 10.5Z" stroke="#5A3984" stroke-linecap="round" stroke-linejoin="round"/> | |||
| <path d="M9.25 10.5C9.94036 10.5 10.5 9.94036 10.5 9.25C10.5 8.55964 9.94036 8 9.25 8C8.55964 8 8 8.55964 8 9.25C8 9.94036 8.55964 10.5 9.25 10.5Z" stroke="#5A3984" stroke-linecap="round" stroke-linejoin="round"/> | |||
| </svg> | |||
| @@ -0,0 +1,3 @@ | |||
| <svg width="14" height="8" viewBox="0 0 14 8" fill="none" xmlns="http://www.w3.org/2000/svg"> | |||
| <path d="M12.5 6.75L7 1.25L1.5 6.75" stroke="#5A3984" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/> | |||
| </svg> | |||
| @@ -0,0 +1,4 @@ | |||
| <svg width="20" height="20" viewBox="0 0 20 20" fill="none" xmlns="http://www.w3.org/2000/svg"> | |||
| <path d="M16.6666 17.5V15.8333C16.6666 14.9493 16.3154 14.1014 15.6903 13.4763C15.0652 12.8512 14.2173 12.5 13.3333 12.5H6.66659C5.78253 12.5 4.93468 12.8512 4.30956 13.4763C3.68444 14.1014 3.33325 14.9493 3.33325 15.8333V17.5" stroke="#5A3984" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round"/> | |||
| <path d="M10.0001 9.16667C11.841 9.16667 13.3334 7.67428 13.3334 5.83333C13.3334 3.99238 11.841 2.5 10.0001 2.5C8.15913 2.5 6.66675 3.99238 6.66675 5.83333C6.66675 7.67428 8.15913 9.16667 10.0001 9.16667Z" stroke="#5A3984" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round"/> | |||
| </svg> | |||
| @@ -3,6 +3,7 @@ body { | |||
| -webkit-font-smoothing: antialiased; | |||
| -moz-osx-font-smoothing: grayscale; | |||
| overflow-anchor: none; | |||
| background-color: #F1F1F1; | |||
| } | |||
| * { | |||
| @@ -4,7 +4,7 @@ import PropTypes from "prop-types"; | |||
| export const IconButton = (props) => { | |||
| return <IconButtonContainer style={props.containerStyle} className={props.className}> | |||
| <IconButtonStyled onClick={props.onClick} sx={props.style}> | |||
| <IconButtonStyled onClick={props.onClick} sx={props.style} iconcolor={props.iconColor}> | |||
| {props.children} | |||
| </IconButtonStyled> | |||
| </IconButtonContainer> | |||
| @@ -16,4 +16,5 @@ IconButton.propTypes = { | |||
| containerStyle: PropTypes.any, | |||
| style: PropTypes.any, | |||
| className: PropTypes.string, | |||
| iconColor: PropTypes.string | |||
| } | |||
| @@ -5,4 +5,12 @@ export const IconButtonContainer = styled(Box)` | |||
| ` | |||
| export const IconButtonStyled = styled(IconButton)` | |||
| height: ${props => props.height ? props.height : "36px"}; | |||
| width: ${props => props.width ? props.width : "36px"}; | |||
| padding: 0; | |||
| ${props => props.iconcolor && ` | |||
| & svg path { | |||
| stroke: ${props.iconcolor}; | |||
| } | |||
| `} | |||
| ` | |||
| @@ -20,7 +20,7 @@ LoginButton.propTypes = { | |||
| variant: PropTypes.string, | |||
| style: PropTypes.any, | |||
| containerStyle: PropTypes.any, | |||
| fullWidth: PropTypes.string, | |||
| fullWidth: PropTypes.bool, | |||
| buttonColor: PropTypes.string, | |||
| onClick: PropTypes.func | |||
| }; | |||
| @@ -7,9 +7,11 @@ import { | |||
| export const PrimaryButton = (props) => { | |||
| return ( | |||
| <PrimaryButtonContainer style={props.containerStyle} className={props.className}> | |||
| <PrimaryButtonContainer | |||
| style={props.containerStyle} | |||
| className={props.className} | |||
| > | |||
| <PrimaryButtonStyled {...props} sx={props.style}> | |||
| {props.children} | |||
| </PrimaryButtonStyled> | |||
| </PrimaryButtonContainer> | |||
| @@ -27,4 +29,9 @@ PrimaryButton.propTypes = { | |||
| textcolor: PropTypes.string, | |||
| className: PropTypes.string, | |||
| onClick: PropTypes.func, | |||
| font: PropTypes.string, | |||
| }; | |||
| PrimaryButton.defaultProps = { | |||
| font: "Open Sans", | |||
| }; | |||
| @@ -6,15 +6,23 @@ export const PrimaryButtonContainer = styled(Box)``; | |||
| export const PrimaryButtonStyled = styled(Button)` | |||
| background-color: ${(props) => | |||
| props.variant === "contained" ? props.buttoncolor : "transparent"}; | |||
| props.disabled | |||
| ? selectedTheme.primaryPurpleDisabled | |||
| : props.variant === "contained" | |||
| ? props.buttoncolor | |||
| : "transparent"} !important; | |||
| border-color: ${(props) => | |||
| props.variant === "outlined" ? props.buttoncolor : "transparent"}; | |||
| color: ${(props) => props.textcolor}; | |||
| color: ${(props) => | |||
| props.disabled | |||
| ? selectedTheme.primaryTextDisabled | |||
| : props.textcolor} !important; | |||
| box-shadow: 0 0 0 0; | |||
| font-size: 10px; | |||
| font-size: 12px; | |||
| letter-spacing: 1px; | |||
| font-weight: 100; | |||
| width: ${(props) => props.width}; | |||
| font-family: ${(props) => props.font}; | |||
| height: ${(props) => props.height}; | |||
| &:hover { | |||
| @@ -23,13 +23,14 @@ export const CheckBox = (props) => { | |||
| className={props.className} | |||
| > | |||
| <FormControlLabelStyled | |||
| fullWidth={props.fullWidth} | |||
| fullwidth={props.fullWidth ? 1 : 0} | |||
| control={ | |||
| <CheckBoxStyled | |||
| sx={props.checkBoxStyle} | |||
| boxcolor={props.color} | |||
| checked={props.value ? props.value : checked} | |||
| checked={props.checked} | |||
| onClick={handleClick} | |||
| value={props.value} | |||
| /> | |||
| } | |||
| label={ | |||
| @@ -51,9 +52,10 @@ CheckBox.propTypes = { | |||
| color: PropTypes.string, | |||
| name: PropTypes.string, | |||
| leftText: PropTypes.string, | |||
| rightText: PropTypes.string, | |||
| rightText: PropTypes.oneOfType([PropTypes.string, PropTypes.number]), | |||
| maxWidth: PropTypes.string, | |||
| value: PropTypes.bool, | |||
| checked: PropTypes.bool, | |||
| value: PropTypes.number, | |||
| onChange: PropTypes.func, | |||
| containerStyle: PropTypes.any, | |||
| checkBoxStyle: PropTypes.any, | |||
| @@ -2,25 +2,37 @@ import { Box, Checkbox, FormControlLabel } from "@mui/material"; | |||
| import styled from "styled-components"; | |||
| export const CheckBoxContainer = styled(Box)` | |||
| ${props => props.fullWidth && (` | |||
| ${(props) => | |||
| props.fullWidth && | |||
| ` | |||
| width: 100%; | |||
| display: flex; | |||
| flex: 1; | |||
| `)} | |||
| ` | |||
| `} | |||
| `; | |||
| export const CheckBoxStyled = styled(Checkbox)` | |||
| color: ${props => props.boxcolor} !important; | |||
| padding: 6px; | |||
| ` | |||
| color: ${(props) => props.boxcolor} !important; | |||
| padding: 6px; | |||
| `; | |||
| export const FormControlLabelStyled = styled(FormControlLabel)` | |||
| ${props => props.fullWidth && (` | |||
| ${(props) => | |||
| props.fullwidth && | |||
| ` | |||
| width: 100%; | |||
| display: flex; | |||
| flex: 1; | |||
| `)} | |||
| margin-right: 0; | |||
| & span:nth-child(2) { | |||
| flex: 1; | |||
| } | |||
| ` | |||
| `} | |||
| margin-right: 0; | |||
| & label { | |||
| font-family: "Open Sans"; | |||
| font-size: 12px; | |||
| } | |||
| & span:nth-child(1) svg { | |||
| width: 18px; | |||
| height: 18px; | |||
| } | |||
| & span:nth-child(2) { | |||
| flex: 1; | |||
| } | |||
| `; | |||
| @@ -4,8 +4,13 @@ import PropTypes from "prop-types"; | |||
| export const Label = (props) => { | |||
| return ( | |||
| <LabelContainer onClick={props.onClick} maxWidth={props.maxWidth}> | |||
| <LeftLabel>{props.leftText}</LeftLabel> | |||
| <LabelContainer | |||
| onClick={props.onClick} | |||
| maxWidth={props.maxWidth} | |||
| style={props.containerStyle} | |||
| className={props.className} | |||
| > | |||
| <LeftLabel style={props.leftTextStyle}>{props.leftText}</LeftLabel> | |||
| {props.rightText && <RightLabel>{props.rightText}</RightLabel>} | |||
| </LabelContainer> | |||
| ); | |||
| @@ -14,6 +19,10 @@ export const Label = (props) => { | |||
| Label.propTypes = { | |||
| onClick: PropTypes.func, | |||
| leftText: PropTypes.string, | |||
| rightText: PropTypes.string, | |||
| rightText: PropTypes.oneOfType([PropTypes.number, PropTypes.string]), | |||
| maxWidth: PropTypes.string, | |||
| leftTextStyle: PropTypes.any, | |||
| rightTextStyle: PropTypes.any, | |||
| containerStyle: PropTypes.any, | |||
| className: PropTypes.any, | |||
| }; | |||
| @@ -1,5 +1,6 @@ | |||
| import { Box, FormLabel } from "@mui/material"; | |||
| import styled from "styled-components"; | |||
| import selectedTheme from "../../themes"; | |||
| export const LabelContainer = styled(Box)` | |||
| display: flex; | |||
| @@ -9,12 +10,14 @@ export const LabelContainer = styled(Box)` | |||
| ` | |||
| export const LeftLabel = styled(FormLabel)` | |||
| font-family: "Open Sans"; | |||
| overflow: hidden; | |||
| text-overflow: ellipsis; | |||
| white-space: nowrap; | |||
| max-width: 200px; | |||
| flex: 1; | |||
| cursor: pointer; | |||
| color: ${selectedTheme.primaryText}; | |||
| ` | |||
| export const RightLabel = styled(FormLabel)` | |||
| margin-left: 10px; | |||
| @@ -23,4 +26,7 @@ export const RightLabel = styled(FormLabel)` | |||
| white-space: nowrap; | |||
| max-width: 100px; | |||
| cursor: pointer; | |||
| color: ${selectedTheme.primaryText}; | |||
| font-family: "Open Sans"; | |||
| ` | |||
| @@ -5,4 +5,5 @@ export const DropdownItemContainer = styled(Box)` | |||
| ` | |||
| export const DropdownItemStyled = styled(Box)` | |||
| font-family: "Open Sans"; | |||
| ` | |||
| @@ -7,36 +7,50 @@ import { | |||
| ListContainer, | |||
| ToggleIconClosed, | |||
| ToggleIconOpened, | |||
| DropdownOptions, | |||
| ToggleContainer, | |||
| } from "./DropdownList.styled"; | |||
| import PropTypes from "prop-types"; | |||
| const DropdownList = (props) => { | |||
| const [listShown, setListShown] = useState(props.defaultOpen); | |||
| const handleShow = () => { | |||
| if (props.setIsOpened) { | |||
| props.setIsOpened(!listShown); | |||
| } | |||
| setListShown((prevState) => !prevState); | |||
| }; | |||
| return ( | |||
| <DropdownListContainer fullWidth={props.fullWidth}> | |||
| <DropdownListContainer fullwidth={props.fullWidth ? 1 : 0}> | |||
| <DropdownHeader> | |||
| {props.dropdownIcon && ( | |||
| <DropdownIcon>{props.dropdownIcon}</DropdownIcon> | |||
| <DropdownIcon onClick={() => handleShow()}> | |||
| {props.dropdownIcon} | |||
| </DropdownIcon> | |||
| )} | |||
| <DropdownTitle onClick={() => setListShown((prevState) => !prevState)}> | |||
| <DropdownTitle onClick={() => handleShow()} textcolor={props.textcolor}> | |||
| {props.title} | |||
| </DropdownTitle> | |||
| {listShown ? ( | |||
| <ToggleIconOpened | |||
| onClick={() => setListShown((prevState) => !prevState)} | |||
| style={props.toggleIconStyles} | |||
| onClick={() => handleShow()} | |||
| > | |||
| {props.toggleIconOpened} | |||
| </ToggleIconOpened> | |||
| ) : ( | |||
| <ToggleIconClosed | |||
| onClick={() => setListShown((prevState) => !prevState)} | |||
| style={props.toggleIconStyles} | |||
| onClick={() => handleShow()} | |||
| > | |||
| {props.toggleIconClosed} | |||
| </ToggleIconClosed> | |||
| )} | |||
| </DropdownHeader> | |||
| <ListContainer shouldShow={listShown}>{props.children}</ListContainer> | |||
| <ToggleContainer shouldShow={listShown}> | |||
| <DropdownOptions>{props.headerOptions}</DropdownOptions> | |||
| <ListContainer>{props.children}</ListContainer> | |||
| </ToggleContainer> | |||
| </DropdownListContainer> | |||
| ); | |||
| }; | |||
| @@ -50,10 +64,14 @@ DropdownList.propTypes = { | |||
| toggleIconClosed: PropTypes.node, | |||
| children: PropTypes.node, | |||
| fullWidth: PropTypes.bool, | |||
| defaultOpen: PropTypes.bool | |||
| defaultOpen: PropTypes.bool, | |||
| toggleIconStyles: PropTypes.any, | |||
| headerOptions: PropTypes.node, | |||
| textcolor: PropTypes.string, | |||
| setIsOpened: PropTypes.func, | |||
| }; | |||
| DropdownList.defaultProps = { | |||
| fullWidth: false, | |||
| defaultOpen: true | |||
| defaultOpen: false, | |||
| }; | |||
| @@ -1,51 +1,66 @@ | |||
| import { Box, Typography } from "@mui/material"; | |||
| import styled from "styled-components"; | |||
| import selectedTheme from "../../../themes"; | |||
| import { Icon } from "../../Icon/Icon"; | |||
| import { IconButton } from "../../Buttons/IconButton/IconButton"; | |||
| export const DropdownListContainer = styled(Box)` | |||
| width: ${props => props.fullWidth ? '100%' : (props.width ? props.width : '250px')}; | |||
| padding: 8px; | |||
| ` | |||
| width: ${(props) => | |||
| props.fullwidth ? "100%" : props.width ? props.width : "250px"}; | |||
| padding: 8px 0; | |||
| `; | |||
| export const DropdownTitle = styled(Typography)` | |||
| display: flex; | |||
| flex: 1; | |||
| cursor: pointer; | |||
| padding-left: 9px; | |||
| font-size: 18px; | |||
| font-weight: 100; | |||
| padding-bottom: 10px; | |||
| ` | |||
| export const ToggleIconOpened = styled(Icon)` | |||
| cursor: pointer; | |||
| color: ${selectedTheme.primaryPurple}; | |||
| ` | |||
| export const ToggleIconClosed = styled(Icon)` | |||
| cursor: pointer; | |||
| color: ${selectedTheme.primaryPurple}; | |||
| ` | |||
| export const DropdownIcon = styled(Icon)` | |||
| font-size: 24px !important; | |||
| & span { | |||
| font-size: 24px; | |||
| & svg { | |||
| font-size: 24px; | |||
| } | |||
| display: flex; | |||
| flex: 1; | |||
| cursor: pointer; | |||
| padding-left: 9px; | |||
| font-size: 16px; | |||
| font-weight: 400; | |||
| padding-bottom: 10px; | |||
| padding-top: 5px; | |||
| padding-right: 0.9rem; | |||
| font-family: "Open Sans"; | |||
| color: ${props => props.textcolor ? props.textcolor : selectedTheme.primaryText}; | |||
| `; | |||
| export const ToggleIconOpened = styled(IconButton)` | |||
| cursor: pointer; | |||
| color: ${selectedTheme.primaryPurple}; | |||
| & span { | |||
| ${props => props.backgroundColor ? `background-color: ${props.backgroundColor}` : ``} | |||
| } | |||
| `; | |||
| export const ToggleIconClosed = styled(IconButton)` | |||
| cursor: pointer; | |||
| color: ${selectedTheme.primaryPurple}; | |||
| & span { | |||
| ${props => props.backgroundColor ? `background-color: ${props.backgroundColor}` : ``} | |||
| } | |||
| `; | |||
| export const DropdownIcon = styled(IconButton)` | |||
| font-size: 22px !important; | |||
| & span { | |||
| font-size: 22px; | |||
| & svg { | |||
| font-size: 22px; | |||
| } | |||
| ` | |||
| } | |||
| `; | |||
| export const ListContainer = styled(Box)` | |||
| padding-left: 15px; | |||
| display: ${props => props.shouldShow ? "block" : "none"}; | |||
| ` | |||
| padding-left: 15px; | |||
| margin-left: 15px; | |||
| `; | |||
| export const DropdownHeader = styled(Box)` | |||
| display: flex; | |||
| flex-direction: row; | |||
| ` | |||
| display: flex; | |||
| flex-direction: row; | |||
| `; | |||
| export const DropdownOptions = styled(Box)` | |||
| `; | |||
| export const ToggleContainer = styled(Box)` | |||
| display: ${(props) => (props.shouldShow ? "block" : "none")}; | |||
| `; | |||
| @@ -5,8 +5,8 @@ import PropTypes from "prop-types"; | |||
| export const Icon = (props) => { | |||
| return ( | |||
| <IconContainer style={props.containerStyle} className={props.className} onClick={props.onClick}> | |||
| <IconStyled sx={props.style} color={props.color} size={props.size} fontSize={props.fontSize}> | |||
| <IconContainer style={props.containerStyle} className={props.className} onClick={props.onClick} component={props.component}> | |||
| <IconStyled sx={props.style} color={props.color} size={props.size} fontSize={props.iconsize}> | |||
| {props.children} | |||
| </IconStyled> | |||
| </IconContainer> | |||
| @@ -19,7 +19,8 @@ Icon.propTypes = { | |||
| style: PropTypes.any, | |||
| color: PropTypes.string, | |||
| size: PropTypes.string, | |||
| fontSize: PropTypes.string, | |||
| iconsize: PropTypes.string, | |||
| className: PropTypes.any, | |||
| onClick: PropTypes.func, | |||
| component: PropTypes.any, | |||
| } | |||
| @@ -2,10 +2,14 @@ import { Box, Icon } from "@mui/material"; | |||
| import styled from "styled-components"; | |||
| export const IconContainer = styled(Box)` | |||
| ` | |||
| export const IconStyled = styled(Icon)` | |||
| color: ${props => props.color}; | |||
| width: ${props => props.size}; | |||
| height: ${props => props.size}; | |||
| & svg path { | |||
| stroke: ${props => props.color}; | |||
| } | |||
| ` | |||
| @@ -0,0 +1,19 @@ | |||
| import React from 'react' | |||
| import PropTypes from 'prop-types' | |||
| import { IconWithNumberContainer, Number } from './IconWithNumber.styled' | |||
| const IconWithNumber = (props) => { | |||
| return ( | |||
| <IconWithNumberContainer> | |||
| {props.children} | |||
| {props.number > 0 && <Number>{props.number}</Number>} | |||
| </IconWithNumberContainer> | |||
| ) | |||
| } | |||
| IconWithNumber.propTypes = { | |||
| children: PropTypes.node, | |||
| number: PropTypes.number, | |||
| } | |||
| export default IconWithNumber | |||
| @@ -0,0 +1,19 @@ | |||
| import { Box } from "@mui/material"; | |||
| import styled from "styled-components"; | |||
| import selectedTheme from "../../../themes"; | |||
| export const IconWithNumberContainer = styled(Box)` | |||
| position: relative; | |||
| ` | |||
| export const Number = styled(Box)` | |||
| background-color: ${selectedTheme.primaryPurple}; | |||
| border-radius: 100%; | |||
| color: white; | |||
| position: absolute; | |||
| width: 16px; | |||
| height: 16px; | |||
| font-size: 10px; | |||
| bottom: 0; | |||
| right: -5px; | |||
| font-family: "Open Sans"; | |||
| ` | |||
| @@ -0,0 +1,28 @@ | |||
| import React from "react"; | |||
| import PropTypes from "prop-types"; | |||
| import { LinkStyled } from "./Link.styled"; | |||
| const Link = (props) => { | |||
| return ( | |||
| <LinkStyled {...props} href={props.href} onClick={props.onClick}> | |||
| {props.children} | |||
| </LinkStyled> | |||
| ); | |||
| }; | |||
| Link.propTypes = { | |||
| href: PropTypes.string, | |||
| children: PropTypes.node, | |||
| font: PropTypes.string, | |||
| align: PropTypes.oneOf(["left", "right", "center"]), | |||
| textsize: PropTypes.string, | |||
| lineheight: PropTypes.string, | |||
| onClick: PropTypes.func, | |||
| }; | |||
| Link.defaultProps = { | |||
| font: "Poppins", | |||
| align: "left", | |||
| textsize: "14px", | |||
| }; | |||
| export default Link; | |||
| @@ -0,0 +1,18 @@ | |||
| import { Link } from "@mui/material"; | |||
| import styled from "styled-components"; | |||
| import selectedTheme from "../../themes"; | |||
| export const LinkStyled = styled(Link)` | |||
| cursor: pointer; | |||
| color: ${selectedTheme.primaryPurple}; | |||
| font-family: ${(props) => props.font}; | |||
| font-style: normal; | |||
| font-weight: 400; | |||
| font-size: ${props => props.textsize ? props.textsize : "14px"}; | |||
| line-height: ${props => props.lineheight ? props.lineheight : "14px"}; | |||
| text-decoration-line: underline; | |||
| display: block; | |||
| text-align: ${props => props.align === "right" ? "right" : (props.align === "center" ? "center" : "left")}; | |||
| /* ${props => props.align === "right" && "display: block; text-align: right;"} | |||
| ${props => props.align === "center" && "display: block; text-align: center;"} */ | |||
| `; | |||
| @@ -1,10 +1,12 @@ | |||
| import React from 'react'; | |||
| import React from "react"; | |||
| import { ReactComponent as Logo } from "../../assets/images/svg/big-logo-vertical.svg"; | |||
| import { FullPageLoaderContainer } from "./FullPageLoader.styled"; | |||
| const FullPageLoader = () => { | |||
| return ( | |||
| <div className="c-loader c-loader--page"> | |||
| <div className="c-loader__icon" /> | |||
| </div> | |||
| <FullPageLoaderContainer> | |||
| <Logo /> | |||
| </FullPageLoaderContainer> | |||
| ); | |||
| }; | |||
| @@ -0,0 +1,10 @@ | |||
| import { Container } from "@mui/material"; | |||
| import styled from "styled-components"; | |||
| export const FullPageLoaderContainer = styled(Container)` | |||
| height: 100%; | |||
| width: 100vw; | |||
| padding-top: 250px; | |||
| text-align: center; | |||
| ` | |||
| @@ -49,7 +49,7 @@ DialogComponent.propTypes = { | |||
| open: PropTypes.bool.isRequired, | |||
| content: PropTypes.any, | |||
| onClose: PropTypes.func.isRequired, | |||
| maxWidth: PropTypes.oneOf(['xs', 'sm', 'md', 'lg', 'xl']), | |||
| maxWidth: PropTypes.any, | |||
| fullWidth: PropTypes.bool, | |||
| responsive: PropTypes.bool, | |||
| }; | |||
| @@ -0,0 +1,52 @@ | |||
| import React from "react"; | |||
| import PropTypes from "prop-types"; | |||
| import { | |||
| FormControlLabelStyled, | |||
| RadioButtonContainer, | |||
| RadioButtonStyled, | |||
| } from "./RadioButton.styled"; | |||
| import { ReactComponent as RadioChecked } from "../../../assets/images/svg/radio-checked.svg"; | |||
| import { ReactComponent as RadioUnchecked } from "../../../assets/images/svg/radio-unchecked.svg"; | |||
| import { Label } from "../../CheckBox/Label"; | |||
| const RadioButton = (props) => { | |||
| return ( | |||
| <RadioButtonContainer fullwidth={props.fullWidth ? 1 : 0}> | |||
| <FormControlLabelStyled | |||
| value={props.value} | |||
| fullwidth={props.fullWidth ? 1 : 0} | |||
| control={ | |||
| <RadioButtonStyled | |||
| icon={<RadioUnchecked />} | |||
| onChange={() => props.onChange(props.value)} | |||
| checkedIcon={<RadioChecked />} | |||
| checked={props.checked} | |||
| /> | |||
| } | |||
| label={ | |||
| <Label | |||
| leftText={props.label} | |||
| rightText={props.number} | |||
| onClick={() => props.onChange(props.value)} | |||
| /> | |||
| } | |||
| /> | |||
| </RadioButtonContainer> | |||
| ); | |||
| }; | |||
| RadioButton.propTypes = { | |||
| children: PropTypes.node, | |||
| value: PropTypes.number, | |||
| label: PropTypes.string, | |||
| number: PropTypes.number, | |||
| fullWidth: PropTypes.bool, | |||
| checked: PropTypes.bool, | |||
| onChange: PropTypes.func, | |||
| }; | |||
| RadioButton.defaultProps = { | |||
| fullWidth: false, | |||
| }; | |||
| export default RadioButton; | |||
| @@ -0,0 +1,40 @@ | |||
| import { Box, FormControlLabel, Radio } from "@mui/material"; | |||
| import styled from "styled-components"; | |||
| export const RadioButtonContainer = styled(Box)` | |||
| ${(props) => | |||
| props.fullwidth && | |||
| ` | |||
| width: 100%; | |||
| display: flex; | |||
| flex: 1; | |||
| `} | |||
| `; | |||
| export const RadioButtonStyled = styled(Radio)` | |||
| margin-top: 5px; | |||
| margin-bottom: 5px; | |||
| margin-right: 9px; | |||
| width: 14px; | |||
| height: 14px; | |||
| `; | |||
| export const FormControlLabelStyled = styled(FormControlLabel)` | |||
| ${(props) => | |||
| props.fullwidth && | |||
| ` | |||
| width: 100%; | |||
| display: flex; | |||
| flex: 1; | |||
| `} | |||
| margin-right: 0; | |||
| & label { | |||
| font-family: "Open Sans"; | |||
| font-size: 12px; | |||
| } | |||
| & span:nth-child(1) svg { | |||
| width: 16px; | |||
| height: 16px; | |||
| } | |||
| & span:nth-child(2) { | |||
| flex: 1; | |||
| } | |||
| `; | |||
| @@ -0,0 +1,20 @@ | |||
| import React from 'react' | |||
| import PropTypes from 'prop-types' | |||
| import { RadioGroupContainer } from './RadioGroup.styled' | |||
| const RadioGroup = (props) => { | |||
| return ( | |||
| <RadioGroupContainer onChange={props.onChange} value={props.value}> | |||
| {props.children} | |||
| </RadioGroupContainer> | |||
| ) | |||
| } | |||
| RadioGroup.propTypes = { | |||
| children: PropTypes.node, | |||
| onChange: PropTypes.func, | |||
| value: PropTypes.any, | |||
| defaultValue: PropTypes.any, | |||
| } | |||
| export default RadioGroup | |||
| @@ -0,0 +1,7 @@ | |||
| import { RadioGroup } from "@mui/material"; | |||
| import styled from "styled-components"; | |||
| export const RadioGroupContainer = styled(RadioGroup)` | |||
| padding-left: 5px; | |||
| width: 100%; | |||
| ` | |||
| @@ -0,0 +1,55 @@ | |||
| import React from "react"; | |||
| import PropTypes from "prop-types"; | |||
| import { StepProgressContainer, Progress, StepBar, StepLine } from "./StepProgress.styled"; | |||
| import { ReactComponent as Checkmark } from "../../assets/images/svg/checkmark.svg"; | |||
| const StepProgress = (props) => { | |||
| const steps = []; | |||
| for (let i = 1; i <= props.numberOfSteps; i++) { | |||
| steps.push({ | |||
| done: i < props.current, | |||
| current: i === props.current, | |||
| }); | |||
| } | |||
| const functions = []; | |||
| steps.forEach((item,index) => { | |||
| if (props.functions[index]) { | |||
| functions.push(props.functions[index]) | |||
| } else { | |||
| functions.push(() => {}) | |||
| } | |||
| }) | |||
| return ( | |||
| <StepProgressContainer done> | |||
| {steps.map((item, index) => | |||
| index === 0 ? ( | |||
| <StepBar current={item.current} done={item.done} key={index} onClick={item.done ? props.functions[index] : () => {console.log("neuspeh")}}> | |||
| {item.done ? <Checkmark /> : index+1} | |||
| </StepBar> | |||
| ) : ( | |||
| <React.Fragment key={index}> | |||
| <StepLine done={item.done || item.current} > | |||
| <Progress done={item.done || item.current} /> | |||
| </StepLine> | |||
| <StepBar current={item.current} done={item.done} onClick={item.done ? props.functions[index] : () => {}} > | |||
| {item.done ? <Checkmark /> : index+1} | |||
| </StepBar> | |||
| </React.Fragment> | |||
| ) | |||
| )} | |||
| </StepProgressContainer> | |||
| ); | |||
| }; | |||
| StepProgress.propTypes = { | |||
| children: PropTypes.node, | |||
| handleNext: PropTypes.node, | |||
| current: PropTypes.number, | |||
| numberOfSteps: PropTypes.number, | |||
| functions: PropTypes.array | |||
| }; | |||
| StepProgress.defaultProps = { | |||
| functions: [] | |||
| } | |||
| export default StepProgress; | |||
| @@ -0,0 +1,45 @@ | |||
| import { Box } from "@mui/material"; | |||
| import styled from "styled-components"; | |||
| import selectedTheme from "../../themes"; | |||
| export const StepProgressContainer = styled(Box)` | |||
| display: flex; | |||
| height: 35px; | |||
| flex-direction: row; | |||
| position: relative; | |||
| left: 2px; | |||
| width: 100%; | |||
| `; | |||
| export const StepLine = styled(Box)` | |||
| margin-top: 13px; | |||
| background-color: white; | |||
| width: 100%; | |||
| margin-left: -1px; | |||
| height: 9px; | |||
| `; | |||
| export const StepBar = styled(Box)` | |||
| flex: 0 0 35px; | |||
| background-color: ${(props) => | |||
| props.done ? selectedTheme.primaryPurple : selectedTheme.primaryDarkGrayText}; | |||
| border-radius: 100%; | |||
| font-family: "Open Sans"; | |||
| text-align: center; | |||
| border: 5px solid | |||
| ${(props) => (props.current || props.done ? selectedTheme.primaryPurple : "white")}; | |||
| padding-top: 2px; | |||
| line-height: 19px; | |||
| margin-left: -2px; | |||
| font-size: 14px; | |||
| color: #1d1d1d; | |||
| z-index: 1; | |||
| transition: background-color 1s ease; | |||
| ${props => props.done && `cursor: pointer;`} | |||
| `; | |||
| export const Progress = styled(Box)` | |||
| height: 9px; | |||
| width: ${(props) => (props.done ? "100%" : "0")}; | |||
| background-color: ${selectedTheme.primaryPurple}; | |||
| transition: width 1s; | |||
| `; | |||
| @@ -0,0 +1,29 @@ | |||
| import { createGlobalStyle } from 'styled-components'; | |||
| // import OpenSans from "./fonts/OpenSans-Regular.ttf" | |||
| // import Poppins from "./fonts/Poppins-Regular.ttf" | |||
| // import Mulish from "./fonts/Mulish-Regular.ttf" | |||
| const GlobalStyle = createGlobalStyle` | |||
| ${'' /* @font-face { | |||
| font-family: 'Open Sans'; | |||
| src: url(${OpenSans}) format('truetype'); | |||
| font-weight: 400; | |||
| font-style: normal; | |||
| font-display: auto; | |||
| } | |||
| @font-face { | |||
| font-family: 'Poppins'; | |||
| src: url(${Poppins}) format('truetype'); | |||
| font-weight: 400; | |||
| font-style: normal; | |||
| font-display: auto; | |||
| } | |||
| @font-face { | |||
| font-family: "Mulish"; | |||
| src: url(${Mulish}) format('truetype'); | |||
| font-weight: 400; | |||
| font-style: normal; | |||
| font-display: auto; | |||
| } */} | |||
| `; | |||
| export default GlobalStyle; | |||
| @@ -1,11 +1,11 @@ | |||
| import React, { useEffect, useState } from "react"; | |||
| import React, { useEffect, useRef, useState } from "react"; | |||
| import { TextFieldContainer, TextFieldStyled } from "./TextField.styled"; | |||
| import PropTypes from "prop-types"; | |||
| export const TextField = (props) => { | |||
| const [isFieldEmpty, setIsFieldEmpty] = useState(true); | |||
| //for italicPlaceholder | |||
| // for italicPlaceholder | |||
| useEffect(() => { | |||
| if (props.value.length === 0) { | |||
| setIsFieldEmpty(true); | |||
| @@ -13,15 +13,39 @@ export const TextField = (props) => { | |||
| setIsFieldEmpty(false); | |||
| } | |||
| }, [props.value]); | |||
| const textInputRef = useRef(); | |||
| return ( | |||
| <TextFieldContainer style={props.containerStyle} className={props.className}> | |||
| <TextFieldContainer | |||
| style={props.containerStyle} | |||
| className={props.className} | |||
| height={props.height} | |||
| > | |||
| <TextFieldStyled | |||
| {...props} | |||
| placeholder={props.placeholder} | |||
| width={props.width} | |||
| height={props.height} | |||
| id={props.id} | |||
| name={props.name} | |||
| value={props.value} | |||
| onChange={props.onChange} | |||
| error={props.error} | |||
| multiline={props.multiline} | |||
| minRows={props.minRows} | |||
| // helperText={props.helperText} | |||
| autoFocus={props.autoFocus} | |||
| fullWidth={props.fullWidth} | |||
| type={props.type} | |||
| textsize={props.textsize} | |||
| font={props.font} | |||
| InputProps={props.InputProps} | |||
| sx={props.style} | |||
| label={props.showAnimation ? props.placeholder : ""} | |||
| italic={props.italicPlaceholder && isFieldEmpty} | |||
| italicplaceholder={(props.italicPlaceholder && isFieldEmpty) ? "true" : "false"} | |||
| ref={textInputRef} | |||
| focused={props.focused} | |||
| > | |||
| {props.children} | |||
| </TextFieldStyled> | |||
| @@ -48,20 +72,30 @@ TextField.propTypes = { | |||
| height: PropTypes.string, | |||
| name: PropTypes.string, | |||
| label: PropTypes.string, | |||
| value: PropTypes.string, | |||
| value: PropTypes.oneOfType([PropTypes.string, PropTypes.number]), | |||
| onChange: PropTypes.func, | |||
| error: PropTypes.string, | |||
| id: PropTypes.number, | |||
| error: PropTypes.bool, | |||
| helperText: PropTypes.string, | |||
| autoFocus: PropTypes.bool, | |||
| fullWidth: PropTypes.bool, | |||
| type: PropTypes.string, | |||
| textsize: PropTypes.string, | |||
| font: PropTypes.string, | |||
| ref: PropTypes.any, | |||
| minRows: PropTypes.number, | |||
| multiline: PropTypes.bool, | |||
| focused: PropTypes.bool, | |||
| InputProps: PropTypes.shape({ | |||
| startAdornment: PropTypes.node, | |||
| endAdornment: PropTypes.node, | |||
| style: PropTypes.any, | |||
| }), | |||
| }; | |||
| TextField.defaultProps = { | |||
| italicPlaceholder: false, | |||
| showAnimation: false, | |||
| height: "48px", | |||
| // font: "Open Sans" | |||
| }; | |||
| @@ -1,19 +1,51 @@ | |||
| import { Box, TextField } from "@mui/material"; | |||
| import styled from "styled-components"; | |||
| const backgroundColor = `rgb(241, 241, 241)`; | |||
| import selectedTheme from "../../../themes"; | |||
| export const TextFieldContainer = styled(Box)` | |||
| width: 100%; | |||
| height: ${(props) => props.height}; | |||
| box-sizing: border-box; | |||
| margin: 16px 0; | |||
| padding-left: 0; | |||
| `; | |||
| export const TextFieldStyled = styled(TextField)` | |||
| background-color: ${backgroundColor}; | |||
| background-color: ${selectedTheme.primaryBackgroundColor}; | |||
| width: ${(props) => props.width}; | |||
| font-style: ${(props) => (props.italic === true ? "italic" : "normal")}; | |||
| font-style: ${(props) => | |||
| props.italicplaceholder === "true" ? "italic" : "normal"}; | |||
| padding-left: 0; | |||
| margin: 0; | |||
| padding: 0; | |||
| height: ${(props) => props.height}; | |||
| box-sizing: border-box; | |||
| overflow-y: hidden; | |||
| & div { | |||
| padding-left: 2px; | |||
| ${(props) => | |||
| props.multiline && | |||
| ` | |||
| padding: 10px 16px; | |||
| max-height: ${props.height}; | |||
| position: relative; | |||
| height: 100%; | |||
| & textarea { | |||
| height: 100% !important; | |||
| width: 100% ; | |||
| overflow: auto; | |||
| font-size: 16px; | |||
| } | |||
| `} | |||
| } | |||
| & div input { | |||
| height: ${(props) => props.height}; | |||
| box-sizing: border-box; | |||
| font-size: ${(props) => | |||
| props.textsize ? props.textsize : "16px"} !important; | |||
| font-family: ${(props) => (props.font ? props.font : "")}; | |||
| } | |||
| `; | |||
| @@ -3,4 +3,9 @@ export const LOGIN_PAGE = '/login'; | |||
| export const FORGOT_PASSWORD_PAGE = '/forgot-password'; | |||
| export const HOME_PAGE = '/home'; | |||
| export const ERROR_PAGE = '/error-page'; | |||
| export const NOT_FOUND_PAGE = '/not-found'; | |||
| export const NOT_FOUND_PAGE = '/not-found'; | |||
| export const FORGOT_PASSWORD_MAIL_SENT = '/forgot-password/mail-sent' | |||
| export const REGISTER_PAGE = "/register" | |||
| export const REGISTER_SUCCESSFUL_PAGE = "/register/success"; | |||
| export const RESET_PASSWORD_PAGE = "/reset-password/:token" | |||
| export const CREATE_OFFER_PAGE = "/create-offer" | |||
| @@ -0,0 +1,3 @@ | |||
| export const SESSION_STORAGE_SCOPE = "AUTH"; | |||
| export const IMPERSONATE_USER_UID = "IMPERSONATE_USER_UID"; | |||
| export const REGISTRATION_USER_UID = "REGISTRATION_USER_UID"; | |||
| @@ -3,13 +3,17 @@ import i18n from 'i18next'; | |||
| import { initReactI18next } from 'react-i18next'; | |||
| import enTranslations from './resources/en'; | |||
| import rsTranslations from './resources/rs' | |||
| i18n.use(initReactI18next).init({ | |||
| lng: 'en', | |||
| fallbackLng: 'en', | |||
| lng: 'rs', | |||
| fallbackLng: 'rs', | |||
| debug: false, | |||
| supportedLngs: ['en'], | |||
| supportedLngs: ['rs', 'en'], | |||
| resources: { | |||
| rs: { | |||
| translation: rsTranslations, | |||
| }, | |||
| en: { | |||
| translation: enTranslations, | |||
| }, | |||
| @@ -0,0 +1,136 @@ | |||
| export default { | |||
| app: { | |||
| title: 'Trampa' | |||
| }, | |||
| refresh: { | |||
| title: 'Jel si aktivan?', | |||
| cta: | |||
| "You were registered as not active, please confirm that you are active in the next minute, if you don't you will be logged out.", | |||
| }, | |||
| common: { | |||
| close: 'Zatvori', | |||
| send: "Pošalji", | |||
| sendAgain: "Pošalji ponovo.", | |||
| trademark: 'TM', | |||
| search: 'Pretraga', | |||
| error: 'Greška', | |||
| continue: 'Nastavi', | |||
| labelUsername: 'Username', | |||
| labelEmail: 'Email', | |||
| labelPassword: 'Lozinka', | |||
| labelFirm: "Ime Firme", | |||
| labelPIB: "PIB", | |||
| labelPhone: "Telefon", | |||
| labelLocation: "Lokacija", | |||
| labelWebsite: "Adresa Websajta", | |||
| next: 'Sledeće', | |||
| nextPage: 'Sledeća strana', | |||
| previousPage: 'Prethodna strana', | |||
| back: 'Nazad', | |||
| goBack: 'Idi nazad', | |||
| ok: 'Ok', | |||
| done: 'Gotovo', | |||
| confirm: 'Potvrdi', | |||
| printDownload: 'Print/Download', | |||
| cancel: 'Obustavi', | |||
| remove: 'Izbriši', | |||
| invite: 'Pozovi', | |||
| save: 'Sačuvaj', | |||
| complete: 'Završi', | |||
| download: 'Download', | |||
| yes: 'Da', | |||
| no: 'Ne', | |||
| to: 'do', | |||
| select: 'Izaberi...', | |||
| none: 'Ni jedan', | |||
| date: { | |||
| range: '{{start}} do {{end}}', | |||
| }, | |||
| }, | |||
| login: { | |||
| welcome: 'React template', | |||
| welcomeText: 'Trampa sa kolegama na dohvat ruke', | |||
| dontHaveAccount: "Nemate nalog? ", | |||
| emailFormat: 'Nevalidan format email adrese!', | |||
| emailRequired: 'Email adresa je obavezna!', | |||
| noUsers: 'Ne postoji korisnik sa zadatom email adresom.', | |||
| passwordStrength: 'Your password is {{strength}}.', | |||
| passwordLength: 'Lozinka mora imati najmanje 8 karaktera!', | |||
| signUpRecommendation: 'Registrujte se.', | |||
| email: 'Unesite email adresu kako biste se prijavili', | |||
| logInTitle: 'Uloguj se', | |||
| logIn: 'Uloguj se', | |||
| signUp: 'Registrujte se.', | |||
| usernameRequired: 'Username je obavezan!', | |||
| passwordRequired: 'Lozinka je obavezna!', | |||
| forgotYourPassword: 'Zaboravili ste lozinku?', | |||
| forgotPasswordEmail:'Email', | |||
| useDifferentEmail: 'Iskoristite drugačiju lozinku.', | |||
| wrongCredentials: 'Pogrešan mail ili lozinka!' | |||
| }, | |||
| password: { | |||
| weak: 'slaba', | |||
| average: 'srednja', | |||
| good: 'dobra', | |||
| strong: 'jaka', | |||
| }, | |||
| register: { | |||
| title: "Registruj se", | |||
| descriptionMain: "Trampa sa kolegama na dohvat ruke", | |||
| descriptionFirst: "Email i Lozinka biće Vam primarni način da se ulogujete u aplikaciju", | |||
| descriptionSecond: 'Ovaj korak nije obavezan za razgledanje artikla ali za proces trampe je obavezan. Uvek možete popuniti ova polja u podešavanjima naloga kasnije', | |||
| descriptionThird: 'Ovaj korak nije obavezan za razgledanje artikla ali za proces trampe je obavezan. Uvek možete popuniti ova polja u podešavanjima naloga kasnije', | |||
| loginText: "Već posedujete nalog?", | |||
| emailFormat: 'Nevalidan format email adrese!', | |||
| emailTaken: "E-mail je zauzet!", | |||
| login: "Ulogujte se.", | |||
| acceptTerms: `Pri klikom na dugme "Registruj se", prihvatate naše`, | |||
| terms: "Uslove Korišćenja", | |||
| success: 'Registracija Uspešna', | |||
| PIBTaken: "PIB je zauzet!", | |||
| PIBnoOfCharacters: "PIB mora imati 9 karaktera!", | |||
| welcome: 'Dobro došli na trampu, želimo vam uspešno trampovanje!', | |||
| }, | |||
| forgotPassword: { | |||
| title: 'Povrati lozinku', | |||
| description: 'Molimo vas unesite email sa koji cemo vam poslati link za povratak lozinke', | |||
| label: 'Pošalji email', | |||
| emailRequired: 'Email je obavezan!', | |||
| emailFormat: 'Nevalidan format email adrese!', | |||
| mailSent: "E-Mail poslat!", | |||
| mailSentDescription: "Poslat vam je email sa instrukcijama kako da resetujete lozinku", | |||
| mailNotFound: "Mejl nije povezan ni sa jednim nalogom!", | |||
| notRecievedMail: "Niste dobili email?", | |||
| checkSpam: "U slučaju da Vam ne stigne email, pogledajte <strong>Spam</strong> folder email provajdera", | |||
| forgotPassword: { | |||
| title: 'Zaboravili ste lozinku', | |||
| subtitle: | |||
| 'Odgovorite na tajno pitanje kako biste povratili svoj nalog: ', | |||
| label: 'Obnovite lozinku', | |||
| }, | |||
| }, | |||
| resetPassword: { | |||
| title: "Unesite novu lozinku", | |||
| description: "Poslali ste zahtev za promenu lozinke, molimo Vas da unesete novu željenu lozinku", | |||
| passwordLabel: "Nova Lozinka", | |||
| passwordConfirmLabel: "Potvrdite Lozinku", | |||
| buttonText: "Postavi lozinku" | |||
| }, | |||
| filters: { | |||
| title: "Filteri", | |||
| cancel: "Poništi filtere", | |||
| usefilters: 'Primeni filtere', | |||
| categories: { | |||
| title: "Kategorija", | |||
| placeholder: 'Pretraži kategorije...' | |||
| }, | |||
| subcategories: { | |||
| title: "Podkategorija", | |||
| placeholder: "Pretraži podkategorije..." | |||
| }, | |||
| location: { | |||
| title: "Lokacija", | |||
| placeholder: "Pretraži gradove..." | |||
| } | |||
| } | |||
| } | |||
| @@ -0,0 +1,3 @@ | |||
| export default { | |||
| email: "", | |||
| }; | |||
| @@ -0,0 +1,4 @@ | |||
| export default { | |||
| email: "", | |||
| password: "", | |||
| }; | |||
| @@ -0,0 +1,4 @@ | |||
| export default { | |||
| mail: "", | |||
| password: "", | |||
| }; | |||
| @@ -0,0 +1,4 @@ | |||
| export default { | |||
| nameOfFirm: "", | |||
| PIB: "", | |||
| }; | |||
| @@ -0,0 +1,5 @@ | |||
| export default { | |||
| phoneNumber: "", | |||
| location: "", | |||
| website: "", | |||
| }; | |||
| @@ -0,0 +1,4 @@ | |||
| export default { | |||
| password: "", | |||
| passwordConfirm: "", | |||
| }; | |||
| @@ -0,0 +1,54 @@ | |||
| import { Box, Container, Typography } from "@mui/material"; | |||
| import styled from "styled-components"; | |||
| import selectedTheme from "../../themes"; | |||
| export const ForgotPasswordPageContainer = styled(Container)` | |||
| margin-top: 200px; | |||
| display: flex; | |||
| flex-direction: column; | |||
| align-items: center; | |||
| @media (max-height: 900px) { | |||
| margin-top: 160px; | |||
| } | |||
| @media (max-height: 800px) { | |||
| margin-top: 120px; | |||
| } | |||
| `; | |||
| export const ForgotPasswordTitle = styled(Typography)` | |||
| font-family: "Open Sans"; | |||
| width: 328px; | |||
| height: 33px; | |||
| text-align: center; | |||
| flex: 1; | |||
| font-style: normal; | |||
| font-weight: 400; | |||
| font-size: 24px; | |||
| line-height: 33px; | |||
| color: ${selectedTheme.primaryPurple}; | |||
| margin-top: 36px; | |||
| `; | |||
| export const ForgotPasswordDescription = styled(Typography)` | |||
| font-family: "Open Sans"; | |||
| margin-top: 9px; | |||
| width: 221px; | |||
| font-style: normal; | |||
| font-weight: 400; | |||
| font-size: 16px; | |||
| line-height: 22px; | |||
| display: flex; | |||
| align-items: center; | |||
| text-align: center; | |||
| color: ${selectedTheme.primaryGrayText}; | |||
| margin-bottom: 20px; | |||
| `; | |||
| export const FormContainer = styled(Box)` | |||
| width: 335px; | |||
| height: 216px; | |||
| `; | |||
| export const ErrorMessage = styled(Typography)` | |||
| color: red; | |||
| font-family: "Open Sans"; | |||
| position: relative; | |||
| top: -7px; | |||
| font-size: 14px; | |||
| ` | |||
| @@ -0,0 +1,96 @@ | |||
| import React, { useEffect, useState } from "react"; | |||
| import PropTypes from "prop-types"; | |||
| import { | |||
| MailSentContainer, | |||
| Description, | |||
| Footer, | |||
| FooterText, | |||
| FormContainer, | |||
| SendAgainTextContainer, | |||
| StandardText, | |||
| Title, | |||
| } from "./MailSent.styled"; | |||
| import { ReactComponent as MailSentImage } from "../../../assets/images/svg/mail-sent.svg"; | |||
| import { PrimaryButton } from "../../../components/Buttons/PrimaryButton/PrimaryButton"; | |||
| import { NavLink, useHistory, useLocation } from "react-router-dom"; | |||
| import Link from "../../../components/Link/Link"; | |||
| import { Trans, useTranslation } from "react-i18next"; | |||
| import { LOGIN_PAGE } from "../../../constants/pages"; | |||
| import selectedTheme from "../../../themes"; | |||
| import { useDispatch } from "react-redux"; | |||
| import { forgotPassword } from "../../../store/actions/user/userActions"; | |||
| const MailSent = () => { | |||
| const [mail, setEmail] = useState(""); | |||
| const { t } = useTranslation(); | |||
| const history = useHistory(); | |||
| const location = useLocation(); | |||
| const dispatch = useDispatch(); | |||
| useEffect(() => { | |||
| setEmail(location.state.email); | |||
| }, []); | |||
| const navigateLogin = () => { | |||
| history.replace(LOGIN_PAGE); | |||
| }; | |||
| const handleResend = () => { | |||
| dispatch(forgotPassword({ email: mail })); | |||
| }; | |||
| return ( | |||
| <MailSentContainer> | |||
| <MailSentImage /> | |||
| <Title component="h1" variant="h5"> | |||
| {t("forgotPassword.mailSent")} | |||
| </Title> | |||
| <Description component="h1" variant="h6"> | |||
| {t("forgotPassword.mailSentDescription")} | |||
| </Description> | |||
| <FormContainer> | |||
| <PrimaryButton | |||
| type="submit" | |||
| variant="contained" | |||
| height="48px" | |||
| fullWidth | |||
| buttoncolor={selectedTheme.primaryPurple} | |||
| textcolor="white" | |||
| onClick={navigateLogin} | |||
| > | |||
| {t("login.logIn")} | |||
| </PrimaryButton> | |||
| <SendAgainTextContainer> | |||
| <StandardText>{t("forgotPassword.notRecievedMail")}</StandardText> | |||
| <Link | |||
| to="#" | |||
| component={NavLink} | |||
| underline="hover" | |||
| align="center" | |||
| textsize="16px" | |||
| onClick={handleResend} | |||
| > | |||
| {t("common.sendAgain")} | |||
| </Link> | |||
| </SendAgainTextContainer> | |||
| </FormContainer> | |||
| <Footer> | |||
| <FooterText> | |||
| <Trans i18nKey="forgotPassword.checkSpam" /> | |||
| </FooterText> | |||
| </Footer> | |||
| </MailSentContainer> | |||
| ); | |||
| }; | |||
| MailSent.propTypes = { | |||
| children: PropTypes.node, | |||
| }; | |||
| export default MailSent; | |||
| @@ -0,0 +1,77 @@ | |||
| import { Box, Container, Typography } from "@mui/material"; | |||
| import styled from "styled-components"; | |||
| import selectedTheme from "../../../themes"; | |||
| export const MailSentContainer = styled(Container)` | |||
| margin-top: 300px; | |||
| display: flex; | |||
| flex-direction: column; | |||
| align-items: center; | |||
| @media (max-height: 900px) { | |||
| margin-top: 200px; | |||
| } | |||
| @media (max-height: 800px) { | |||
| margin-top: 150px; | |||
| } | |||
| `; | |||
| export const Title = styled(Typography)` | |||
| font-family: "Open Sans"; | |||
| color: ${selectedTheme.primaryText}; | |||
| width: 328px; | |||
| height: 33px; | |||
| text-align: center; | |||
| flex: 1; | |||
| font-style: normal; | |||
| font-weight: 400; | |||
| font-size: 24px; | |||
| line-height: 33px; | |||
| color: ${selectedTheme.primaryPurple}; | |||
| margin-top: 6px; | |||
| `; | |||
| export const Description = styled(Typography)` | |||
| font-family: "Open Sans"; | |||
| margin-top: 9px; | |||
| width: 279px; | |||
| font-style: normal; | |||
| font-weight: 400; | |||
| font-size: 16px; | |||
| line-height: 22px; | |||
| display: flex; | |||
| align-items: center; | |||
| text-align: center; | |||
| color: ${selectedTheme.primaryGrayText}; | |||
| margin-bottom: 36px; | |||
| `; | |||
| export const FormContainer = styled(Box)` | |||
| width: 335px; | |||
| height: 216px; | |||
| `; | |||
| export const StandardText = styled(Typography)` | |||
| font-family: "Open Sans"; | |||
| color: ${selectedTheme.primaryText}; | |||
| font-size: 16px; | |||
| padding-right: 6px; | |||
| line-height: 14px; | |||
| text-align: center; | |||
| ` | |||
| export const SendAgainTextContainer = styled(Box)` | |||
| display: flex; | |||
| flex-direction: row; | |||
| margin-top: 36px; | |||
| justify-content: center; | |||
| ` | |||
| export const Footer = styled(Box)` | |||
| position: absolute; | |||
| bottom: 36px; | |||
| display: flex; | |||
| width: 100%; | |||
| flex-direction: row; | |||
| justify-content: center; | |||
| ` | |||
| export const FooterText = styled(StandardText)` | |||
| width: 340px; | |||
| line-height: 22px; | |||
| font-weight: 400; | |||
| padding: 0; | |||
| font-size: 16px; | |||
| ` | |||
| @@ -1,62 +1,116 @@ | |||
| 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/Buttons/Button'; | |||
| import Section from '../../components/Section/Section'; | |||
| const forgotPasswordValidationSchema = Yup.object().shape({ | |||
| email: Yup.string().required( | |||
| i18next.t('login.securityQuestion.answerRequired'), | |||
| ), | |||
| }); | |||
| import React, { useState } from "react"; | |||
| import { useFormik } from "formik"; | |||
| import { useTranslation } from "react-i18next"; | |||
| import * as Yup from "yup"; | |||
| // import i18next from "i18next"; | |||
| import { ReactComponent as Logo } from "../../assets/images/svg/logo-vertical.svg"; | |||
| import { | |||
| ForgotPasswordPageContainer, | |||
| ForgotPasswordDescription, | |||
| ForgotPasswordTitle, | |||
| FormContainer, | |||
| ErrorMessage, | |||
| } from "./ForgotPassword.styled"; | |||
| import { TextField } from "../../components/TextFields/TextField/TextField"; | |||
| import { PrimaryButton } from "../../components/Buttons/PrimaryButton/PrimaryButton"; | |||
| import { useHistory } from "react-router-dom"; | |||
| import { FORGOT_PASSWORD_MAIL_SENT } from "../../constants/pages"; | |||
| import selectedTheme from "../../themes"; | |||
| import { useDispatch } from "react-redux"; | |||
| import { forgotPassword } from "../../store/actions/user/userActions"; | |||
| const ForgotPasswordPage = () => { | |||
| const history = useHistory(); | |||
| const { t } = useTranslation(); | |||
| const dispatch = useDispatch(); | |||
| const [emailNotFoundStatus, setEmailNotFoundStatus] = useState(false); | |||
| const forgotPasswordValidationSchema = Yup.object().shape({ | |||
| email: Yup.string() | |||
| .required(t("forgotPassword.emailRequired")) | |||
| .email(t("forgotPassword.emailFormat")), | |||
| }); | |||
| const handleResponseSuccess = () => { | |||
| history.push({ | |||
| pathname: FORGOT_PASSWORD_MAIL_SENT, | |||
| state: { email: formik.values.email }, | |||
| }); | |||
| }; | |||
| const handleResponseError = () => { | |||
| setEmailNotFoundStatus(true); | |||
| }; | |||
| const handleSubmit = (values) => { | |||
| console.log("Values",values) | |||
| dispatch( | |||
| forgotPassword({ | |||
| email: values.email, | |||
| handleResponseSuccess, | |||
| handleResponseError, | |||
| }) | |||
| ); | |||
| }; | |||
| const formik = useFormik({ | |||
| initialValues: { | |||
| email: "", | |||
| }, | |||
| validationSchema: forgotPasswordValidationSchema, | |||
| onSubmit: handleSubmit, | |||
| validateOnBlur: true, | |||
| enableReinitialize: true, | |||
| }); | |||
| 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> | |||
| <ForgotPasswordPageContainer> | |||
| <Logo /> | |||
| <ForgotPasswordTitle component="h1" variant="h5"> | |||
| {t("forgotPassword.title")} | |||
| </ForgotPasswordTitle> | |||
| <ForgotPasswordDescription component="h1" variant="h6"> | |||
| {t("forgotPassword.description")} | |||
| </ForgotPasswordDescription> | |||
| <FormContainer component="form" onSubmit={formik.handleSubmit}> | |||
| {/* <Backdrop position="absolute" isLoading={isLoading} /> */} | |||
| <TextField | |||
| name="email" | |||
| placeholder={t("common.labelEmail")} | |||
| margin="normal" | |||
| value={formik.values.email} | |||
| error={ | |||
| (formik.touched.email && Boolean(formik.errors.email)) || | |||
| emailNotFoundStatus | |||
| } | |||
| helperText={formik.touched.email && formik.errors.email} | |||
| onChange={formik.handleChange} | |||
| autoFocus | |||
| fullWidth | |||
| /> | |||
| {formik.errors.email && formik.touched.email && ( | |||
| <ErrorMessage>{formik.errors.email}</ErrorMessage> | |||
| )} | |||
| {emailNotFoundStatus && ( | |||
| <ErrorMessage>{t("forgotPassword.mailNotFound")}</ErrorMessage> | |||
| )} | |||
| <PrimaryButton | |||
| type="submit" | |||
| variant="contained" | |||
| height="48px" | |||
| fullWidth | |||
| buttoncolor={selectedTheme.primaryPurple} | |||
| textcolor="white" | |||
| disabled={formik.values.email?.length === 0} | |||
| > | |||
| {t("common.send")} | |||
| </PrimaryButton> | |||
| </FormContainer> | |||
| </ForgotPasswordPageContainer> | |||
| ); | |||
| }; | |||
| @@ -1,8 +1,17 @@ | |||
| import styledComponents from 'styled-components'; | |||
| import { Box, Grid } from '@mui/material'; | |||
| export const BoxStyled = styledComponents(Box)` | |||
| ` | |||
| export const GridStyled = styledComponents(Grid)` | |||
| ` | |||
| import styled from "styled-components"; | |||
| import { Container, Grid } from "@mui/material"; | |||
| import selectedTheme from "../../themes"; | |||
| export const HomePageContainer = styled(Container)` | |||
| padding: 0; | |||
| margin: 0; | |||
| height: 100%; | |||
| width: 100%; | |||
| max-width: none; | |||
| flex: 1; | |||
| display: flex; | |||
| flex-direction: column; | |||
| background-color: ${selectedTheme.offerBackgroundColor}; | |||
| `; | |||
| export const GridStyled = styled(Grid)` | |||
| `; | |||
| @@ -1,38 +1,12 @@ | |||
| import React from 'react'; | |||
| import { Box } 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'; | |||
| import { GridStyled } from './HomePage.styled'; | |||
| import React from "react"; | |||
| const HomePage = () => { | |||
| return ( | |||
| <> | |||
| <Navbar /> | |||
| <Box sx={{ mt: 4, mx: 4 }}> | |||
| <GridStyled container spacing={2} justifyContent="center"> | |||
| <GridStyled item xs={12} md={3}> | |||
| <Modals /> | |||
| </GridStyled> | |||
| <GridStyled item xs={12} md={6}> | |||
| <DataGrid /> | |||
| </GridStyled> | |||
| <GridStyled item xs={12} md={9}> | |||
| <PagingSortingFiltering /> | |||
| </GridStyled> | |||
| <GridStyled item xs={12} md={9}> | |||
| {/* Move to higher components? */} | |||
| <RandomDataProvider> | |||
| <PagingSortingFilteringServerSide /> | |||
| </RandomDataProvider> | |||
| </GridStyled> | |||
| </GridStyled> | |||
| </Box> | |||
| </> | |||
| ); | |||
| return ( | |||
| <div> | |||
| Home page | |||
| </div> | |||
| ); | |||
| }; | |||
| export default HomePage; | |||
| @@ -0,0 +1,68 @@ | |||
| import { Box, Container, Typography } from "@mui/material"; | |||
| import styled from "styled-components"; | |||
| import selectedTheme from "../../themes"; | |||
| export const LoginPageContainer = styled(Container)` | |||
| margin-top: 150px; | |||
| display: flex; | |||
| flex-direction: column; | |||
| align-items: center; | |||
| @media (max-height: 900px) { | |||
| margin-top: 110px; | |||
| } | |||
| @media (max-height: 800px) { | |||
| margin-top: 70px; | |||
| } | |||
| `; | |||
| export const LoginTitle = styled(Typography)` | |||
| font-family: "Open Sans"; | |||
| width: 328px; | |||
| height: 33px; | |||
| text-align: center; | |||
| flex: 1; | |||
| font-style: normal; | |||
| font-weight: 400; | |||
| font-size: 24px; | |||
| line-height: 33px; | |||
| color: ${selectedTheme.primaryPurple}; | |||
| margin-top: 36px; | |||
| `; | |||
| export const LoginDescription = styled(Typography)` | |||
| font-family: "Open Sans"; | |||
| margin-top: 9px; | |||
| width: 221px; | |||
| font-style: normal; | |||
| font-weight: 400; | |||
| font-size: 16px; | |||
| line-height: 22px; | |||
| display: flex; | |||
| align-items: center; | |||
| text-align: center; | |||
| color: ${selectedTheme.primaryGrayText}; | |||
| margin-bottom: 20px; | |||
| `; | |||
| export const LoginFormContainer = styled(Box)` | |||
| width: 335px; | |||
| height: 216px; | |||
| `; | |||
| export const RegisterAltText = styled(Typography)` | |||
| font-family: "Poppins"; | |||
| color: ${selectedTheme.primaryText}; | |||
| font-size: 14px; | |||
| padding-right: 6px; | |||
| line-height: 14px; | |||
| `; | |||
| export const RegisterTextContainer = styled(Box)` | |||
| display: flex; | |||
| flex-direction: row; | |||
| margin-top: 36px; | |||
| justify-content: center; | |||
| `; | |||
| export const ErrorMessage = styled(Typography)` | |||
| color: red; | |||
| font-family: "Open Sans"; | |||
| position: relative; | |||
| top: -12px; | |||
| height: 20px; | |||
| font-size: 14px; | |||
| `; | |||
| @@ -1,135 +1,207 @@ | |||
| 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/Buttons/Button'; | |||
| import TextField from '../../components/InputFields/TextField'; | |||
| import Auth from '../../components/Auth/Auth'; | |||
| import AuthCard from '../../components/AuthCards/AuthCard'; | |||
| /* eslint-disable */ | |||
| import React, { useEffect, useState } from "react"; | |||
| import PropTypes from "prop-types"; | |||
| import { useFormik } 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 { | |||
| clearLoginErrors, | |||
| fetchUser, | |||
| } from '../../store/actions/login/loginActions'; | |||
| } from "../../store/actions/login/loginActions"; | |||
| import { selectLoginError } from "../../store/selectors/loginSelectors"; | |||
| import { FORGOT_PASSWORD_PAGE, HOME_PAGE } from "../../constants/pages"; | |||
| import { ReactComponent as VisibilityOn } from "../../assets/images/svg/eye-striked.svg"; | |||
| import { ReactComponent as VisibilityOff } from "../../assets/images/svg/eye.svg"; | |||
| import Backdrop from "../../components/MUI/BackdropComponent"; | |||
| import { selectIsLoadingByActionType } from "../../store/selectors/loadingSelectors"; | |||
| import { LOGIN_USER_LOADING } from "../../store/actions/login/loginActionConstants"; | |||
| import { TextField } from "../../components/TextFields/TextField/TextField"; | |||
| import { PrimaryButton } from "../../components/Buttons/PrimaryButton/PrimaryButton"; | |||
| import { IconButton } from "../../components/Buttons/IconButton/IconButton"; | |||
| import Link from "../../components/Link/Link"; | |||
| import { ReactComponent as Logo } from "../../assets/images/svg/logo-vertical.svg"; | |||
| 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')), | |||
| }); | |||
| LoginPageContainer, | |||
| LoginTitle, | |||
| LoginDescription, | |||
| LoginFormContainer, | |||
| RegisterAltText, | |||
| RegisterTextContainer, | |||
| ErrorMessage, | |||
| } from "./Login.styled"; | |||
| import selectedTheme from "../../themes"; | |||
| import loginValidation from "../../validations/loginValidation"; | |||
| import loginInitialValues from "../../initialValues/loginInitialValues"; | |||
| const LoginPage = ({ history }) => { | |||
| const dispatch = useDispatch(); | |||
| const { t } = useTranslation(); | |||
| const error = useSelector(selectLoginError); | |||
| const [showPassword, setShowPassword] = useState(false); | |||
| const handleClickShowPassword = () => setShowPassword(!showPassword); | |||
| const handleMouseDownPassword = () => setShowPassword(!showPassword); | |||
| // When user refreshes page | |||
| // useEffect(() => { | |||
| // function redirectClient() { | |||
| // if (!tokens.RefreshToken && !tokens.JwtToken) { | |||
| // return | |||
| // } | |||
| // } | |||
| // function redirectClient() { | |||
| // if (!tokens.RefreshToken && !tokens.JwtToken) { | |||
| // return; | |||
| // } | |||
| // } | |||
| // redirectClient(); | |||
| // redirectClient(); | |||
| // }, [history, tokens]); | |||
| const isLoading = useSelector( | |||
| selectIsLoadingByActionType(LOGIN_USER_LOADING), | |||
| selectIsLoadingByActionType(LOGIN_USER_LOADING) | |||
| ); | |||
| const handleApiResponseSuccess =()=>{ | |||
| useEffect(() => { | |||
| dispatch(clearLoginErrors()); | |||
| }, []); | |||
| 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 | |||
| }, | |||
| ), | |||
| ); | |||
| const { email, password: password } = values; | |||
| dispatch(clearLoginErrors()); | |||
| dispatch( | |||
| fetchUser({ | |||
| email, | |||
| password, | |||
| handleApiResponseSuccess, | |||
| }) | |||
| ); | |||
| }; | |||
| const formik = useFormik({ | |||
| initialValues: loginInitialValues, | |||
| validationSchema: loginValidation, | |||
| onSubmit: handleSubmit, | |||
| validateOnBlur: true, | |||
| enableReinitialize: true, | |||
| }); | |||
| useEffect(() => { | |||
| if (error) { | |||
| if (formik.errors.email || formik.errors.password) { | |||
| dispatch(clearLoginErrors()); | |||
| } | |||
| } | |||
| }, [formik.errors.email, formik.errors.password]) | |||
| 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> | |||
| <LoginPageContainer> | |||
| <Logo /> | |||
| <LoginTitle component="h1" variant="h5"> | |||
| {t("login.logInTitle")} | |||
| </LoginTitle> | |||
| <LoginDescription component="h1" variant="h6"> | |||
| {t("login.welcomeText")} | |||
| </LoginDescription> | |||
| <LoginFormContainer component="form" onSubmit={formik.handleSubmit}> | |||
| <Backdrop position="absolute" isLoading={isLoading} /> | |||
| <TextField | |||
| name="email" | |||
| placeholder={t("common.labelEmail")} | |||
| margin="normal" | |||
| value={formik.values.email} | |||
| onChange={formik.handleChange} | |||
| error={ | |||
| (formik.touched.email && formik.errors.email) || error.length > 0 | |||
| } | |||
| helperText={formik.touched.email && formik.errors.email} | |||
| autoFocus | |||
| fullWidth | |||
| /> | |||
| <TextField | |||
| name="password" | |||
| placeholder={t("common.labelPassword")} | |||
| margin="normal" | |||
| type={showPassword ? "text" : "password"} | |||
| value={formik.values.password} | |||
| onChange={formik.handleChange} | |||
| error={ | |||
| (formik.touched.password && formik.errors.password) || | |||
| error.length > 0 | |||
| } | |||
| helperText={formik.touched.password && formik.errors.password} | |||
| fullWidth | |||
| InputProps={{ | |||
| endAdornment: ( | |||
| <IconButton | |||
| onClick={handleClickShowPassword} | |||
| onMouseDown={handleMouseDownPassword} | |||
| > | |||
| {showPassword ? <VisibilityOn /> : <VisibilityOff />} | |||
| </IconButton> | |||
| ), | |||
| }} | |||
| /> | |||
| {formik.errors.password && formik.touched.password && ( | |||
| <ErrorMessage>{formik.errors.password}</ErrorMessage> | |||
| )} | |||
| {error.length > 0 && !formik.errors.password && <ErrorMessage>{error}</ErrorMessage>} | |||
| <Link | |||
| to={FORGOT_PASSWORD_PAGE} | |||
| textsize="12px" | |||
| component={NavLink} | |||
| underline="hover" | |||
| align="right" | |||
| style={{ | |||
| marginTop: error.length > 0 ? "0" : "18px", | |||
| marginBottom: "18px", | |||
| }} | |||
| > | |||
| {t("login.forgotYourPassword")} | |||
| </Link> | |||
| <PrimaryButton | |||
| type="submit" | |||
| variant="contained" | |||
| height="48px" | |||
| fullWidth | |||
| buttoncolor={selectedTheme.primaryPurple} | |||
| textcolor="white" | |||
| disabled={ | |||
| formik.values.email.length === 0 || | |||
| formik.values.password.length === 0 | |||
| } | |||
| > | |||
| {t("login.logIn")} | |||
| </PrimaryButton> | |||
| <RegisterTextContainer> | |||
| <RegisterAltText> | |||
| {t("login.dontHaveAccount").padEnd(2, " ")} | |||
| </RegisterAltText> | |||
| <Link | |||
| to="/register" | |||
| component={NavLink} | |||
| underline="hover" | |||
| align="center" | |||
| > | |||
| {t("login.signUp")} | |||
| </Link> | |||
| </RegisterTextContainer> | |||
| </LoginFormContainer> | |||
| </LoginPageContainer> | |||
| ); | |||
| }; | |||
| @@ -1,250 +0,0 @@ | |||
| /* eslint-disable */ | |||
| import React, { useEffect, useState } from "react"; | |||
| import PropTypes from "prop-types"; | |||
| import { useFormik } 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 { | |||
| clearLoginErrors, | |||
| fetchUser, | |||
| } from "../../store/actions/login/loginActions"; | |||
| import { selectLoginError } from "../../store/selectors/loginSelectors"; | |||
| import { FORGOT_PASSWORD_PAGE, HOME_PAGE } from "../../constants/pages"; | |||
| import { | |||
| Box, | |||
| Button, | |||
| Container, | |||
| Grid, | |||
| InputAdornment, | |||
| Link, | |||
| Typography, | |||
| } from "@mui/material"; | |||
| import { | |||
| LocationOn, | |||
| LocationOnOutlined, | |||
| Visibility, | |||
| VisibilityOff, | |||
| } from "@mui/icons-material"; | |||
| import Backdrop from "../../components/MUI/BackdropComponent"; | |||
| import ErrorMessage from "../../components/MUI/ErrorMessageComponent"; | |||
| import { selectIsLoadingByActionType } from "../../store/selectors/loadingSelectors"; | |||
| import { LOGIN_USER_LOADING } from "../../store/actions/login/loginActionConstants"; | |||
| import { TextField } from "../../components/TextFields/TextField/TextField"; | |||
| import { PrimaryButton } from "../../components/Buttons/PrimaryButton/PrimaryButton"; | |||
| import { IconButton } from "../../components/Buttons/IconButton/IconButton"; | |||
| import { Icon } from "../../components/Icon/Icon"; | |||
| import PrimaryButtonWithIcon from "../../components/Buttons/PrimaryButtonWithIcon/PrimaryButtonWithIcon"; | |||
| import TextFieldWithIcon from "../../components/TextFields/TextFieldWithIcon/TextFieldWithIcon"; | |||
| import DropdownList from "../../components/Dropdown/DropdownList/DropdownList"; | |||
| import DropdownItem from "../../components/Dropdown/DropdownItem/DropdownItem"; | |||
| import { CheckBox } from "../../components/CheckBox/CheckBox"; | |||
| import selectedTheme from "../../themes"; | |||
| const LoginPage = ({ history }) => { | |||
| const dispatch = useDispatch(); | |||
| const { t } = useTranslation(); | |||
| const error = useSelector(selectLoginError); | |||
| const [showPassword, setShowPassword] = useState(false); | |||
| const handleClickShowPassword = () => setShowPassword(!showPassword); | |||
| const handleMouseDownPassword = () => setShowPassword(!showPassword); | |||
| // 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) => { | |||
| const { username: Username, password: Password } = values; | |||
| dispatch(clearLoginErrors()); | |||
| dispatch( | |||
| fetchUser({ | |||
| Username, | |||
| Password, | |||
| handleApiResponseSuccess, | |||
| }) | |||
| ); | |||
| }; | |||
| const formik = useFormik({ | |||
| initialValues: { | |||
| username: "", | |||
| password: "", | |||
| }, | |||
| validationSchema: Yup.object().shape({ | |||
| username: Yup.string().required(t("login.usernameRequired")), | |||
| password: Yup.string().required(t("login.passwordRequired")), | |||
| }), | |||
| onSubmit: handleSubmit, | |||
| validateOnBlur: true, | |||
| enableReinitialize: true, | |||
| }); | |||
| return ( | |||
| <Container component="main" maxWidth="md"> | |||
| <Box | |||
| sx={{ | |||
| marginTop: 32, | |||
| display: "flex", | |||
| flexDirection: "column", | |||
| alignItems: "center", | |||
| }} | |||
| > | |||
| <Typography component="h1" variant="h5"> | |||
| {t("login.logInTitle")} | |||
| </Typography> | |||
| {error && <ErrorMessage error={error} />} | |||
| <Box | |||
| component="form" | |||
| onSubmit={formik.handleSubmit} | |||
| sx={{ position: "relative", mt: 1, p: 1 }} | |||
| > | |||
| <Backdrop position="absolute" isLoading={isLoading} /> | |||
| <TextField | |||
| name="username" | |||
| placeholder={t("common.labelUsername")} | |||
| margin="normal" | |||
| value={formik.values.username} | |||
| onChange={formik.handleChange} | |||
| error={formik.touched.username && Boolean(formik.errors.username)} | |||
| helperText={formik.touched.username && formik.errors.username} | |||
| autoFocus | |||
| fullWidth | |||
| /> | |||
| <TextField | |||
| name="password" | |||
| placeholder={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: ( | |||
| <IconButton | |||
| onClick={handleClickShowPassword} | |||
| onMouseDown={handleMouseDownPassword} | |||
| > | |||
| {showPassword ? <Visibility /> : <VisibilityOff />} | |||
| </IconButton> | |||
| ), | |||
| }} | |||
| /> | |||
| <DropdownList | |||
| title="Naslov" | |||
| toggleIconOpened={<Visibility />} | |||
| toggleIconClosed={<VisibilityOff />} | |||
| dropdownIcon={<LocationOnOutlined />} | |||
| fullWidth | |||
| defaultOpen={false} | |||
| > | |||
| <DropdownItem> | |||
| <CheckBox fullWidth leftText="Kategorija" rightText="124" /> | |||
| </DropdownItem> | |||
| <DropdownItem> | |||
| <CheckBox fullWidth leftText="Kategorija" rightText="124" /> | |||
| </DropdownItem> | |||
| <DropdownItem> | |||
| <CheckBox fullWidth leftText="Kategorija" rightText="124" /> | |||
| </DropdownItem> | |||
| <DropdownItem> | |||
| <CheckBox fullWidth leftText="Kategorija" rightText="124" /> | |||
| </DropdownItem> | |||
| <DropdownItem> | |||
| <CheckBox fullWidth leftText="Kategorija" rightText="124" /> | |||
| </DropdownItem> | |||
| <DropdownItem> | |||
| <CheckBox fullWidth leftText="Kategorija" rightText="124" /> | |||
| </DropdownItem> | |||
| <DropdownItem> | |||
| <CheckBox fullWidth leftText="Kategorija" rightText="124" /> | |||
| </DropdownItem> | |||
| </DropdownList> | |||
| <PrimaryButtonWithIcon | |||
| icon={<Visibility />} | |||
| sx={{ mt: 3, mb: 2 }} | |||
| buttonProps={{ | |||
| type: "submit", | |||
| variant: "contained", | |||
| height: "40px", | |||
| fullWidth: true, | |||
| buttoncolor: selectedTheme.primaryPurple, | |||
| textcolor: "white", | |||
| }} | |||
| > | |||
| {t("login.logIn")} | |||
| </PrimaryButtonWithIcon> | |||
| <Grid container> | |||
| <Grid | |||
| item | |||
| xs={12} | |||
| md={6} | |||
| sx={{ textAlign: { xs: "center", md: "left" } }} | |||
| > | |||
| <Link | |||
| to={FORGOT_PASSWORD_PAGE} | |||
| component={NavLink} | |||
| variant="body2" | |||
| underline="hover" | |||
| > | |||
| {t("login.forgotYourPassword")} | |||
| </Link> | |||
| </Grid> | |||
| <Grid | |||
| item | |||
| xs={12} | |||
| md={6} | |||
| sx={{ textAlign: { xs: "center", md: "right" } }} | |||
| > | |||
| <Link | |||
| to="#" | |||
| component={NavLink} | |||
| variant="body2" | |||
| underline="hover" | |||
| > | |||
| {t("login.dontHaveAccount")} | |||
| </Link> | |||
| </Grid> | |||
| </Grid> | |||
| </Box> | |||
| </Box> | |||
| </Container> | |||
| ); | |||
| }; | |||
| LoginPage.propTypes = { | |||
| history: PropTypes.shape({ | |||
| replace: PropTypes.func, | |||
| push: PropTypes.func, | |||
| location: PropTypes.shape({ | |||
| pathname: PropTypes.string, | |||
| }), | |||
| }), | |||
| }; | |||
| export default LoginPage; | |||
| @@ -0,0 +1,128 @@ | |||
| import React, { useEffect, useState } from "react"; | |||
| import PropTypes from "prop-types"; | |||
| import { | |||
| ErrorMessage, | |||
| FormContainer, | |||
| RegisterDescription, | |||
| } from "./FirstPartOfRegistration.styled"; | |||
| import { useFormik } from "formik"; | |||
| import * as Yup from "yup"; | |||
| import { useTranslation } from "react-i18next"; | |||
| import { TextField } from "../../../../components/TextFields/TextField/TextField"; | |||
| import { IconButton } from "../../../../components/Buttons/IconButton/IconButton"; | |||
| import { ReactComponent as VisibilityOn } from "../../../../assets/images/svg/eye.svg"; | |||
| import { ReactComponent as VisibilityOff } from "../../../../assets/images/svg/eye-striked.svg"; | |||
| import { PrimaryButton } from "../../../../components/Buttons/PrimaryButton/PrimaryButton"; | |||
| import selectedTheme from "../../../../themes"; | |||
| const FirstPartOfRegistration = (props) => { | |||
| const [showPassword, setShowPassword] = useState(false); | |||
| const [emailTakenStatus, setEmailTakenStatus] = useState(false); | |||
| const { t } = useTranslation(); | |||
| useEffect(() => { | |||
| if (props.error.length > 0) { | |||
| setEmailTakenStatus(true); | |||
| } | |||
| }, [props.error]); | |||
| const formik = useFormik({ | |||
| initialValues: { | |||
| mail: "", | |||
| password: "", | |||
| }, | |||
| validationSchema: Yup.object().shape({ | |||
| mail: Yup.string() | |||
| .email(t("forgotPassword.emailFormat")) | |||
| .required(t("login.usernameRequired")), | |||
| password: Yup.string() | |||
| .required(t("login.passwordRequired")) | |||
| .min(8, t("login.passwordLength")), | |||
| }), | |||
| onSubmit: props.handleSubmit, | |||
| validateOnBlur: true, | |||
| enableReinitialize: true, | |||
| }); | |||
| const handleClickShowPassword = () => { | |||
| setShowPassword((prevState) => !prevState); | |||
| }; | |||
| return ( | |||
| <FormContainer component="form" onSubmit={formik.handleSubmit}> | |||
| <RegisterDescription component="p" variant="p"> | |||
| {t("register.descriptionFirst")} | |||
| </RegisterDescription> | |||
| <TextField | |||
| name="mail" | |||
| placeholder={t("common.labelEmail")} | |||
| margin="normal" | |||
| value={formik.values.mail} | |||
| onChange={(value) => formik.setFieldValue("mail", value.target.value)} | |||
| error={ | |||
| (formik.touched.mail && Boolean(formik.errors.mail)) || | |||
| emailTakenStatus | |||
| } | |||
| helperText={formik.touched.mail && formik.errors.mail} | |||
| autoFocus | |||
| fullWidth | |||
| /> | |||
| <TextField | |||
| name="password" | |||
| placeholder={t("common.labelPassword")} | |||
| margin="normal" | |||
| type={showPassword ? "text" : "password"} | |||
| value={formik.values.password} | |||
| onChange={(value) => | |||
| formik.setFieldValue("password", value.target.value) | |||
| } | |||
| error={formik.touched.password && Boolean(formik.errors.password)} | |||
| helperText={formik.touched.password && formik.errors.password} | |||
| fullWidth | |||
| InputProps={{ | |||
| endAdornment: ( | |||
| <IconButton onClick={handleClickShowPassword}> | |||
| {showPassword ? <VisibilityOn /> : <VisibilityOff />} | |||
| </IconButton> | |||
| ), | |||
| }} | |||
| /> | |||
| {formik.errors.mail && formik.touched.mail ? ( | |||
| <ErrorMessage>{formik.errors.mail}</ErrorMessage> | |||
| ) : formik.errors.password && formik.touched.password ? ( | |||
| <ErrorMessage>{formik.errors.password}</ErrorMessage> | |||
| ) : ( | |||
| <></> | |||
| )} | |||
| {props.error && <ErrorMessage>{props.errorMessage}</ErrorMessage>} | |||
| <PrimaryButton | |||
| type="submit" | |||
| variant="contained" | |||
| height="48px" | |||
| fullWidth | |||
| buttoncolor={selectedTheme.primaryPurple} | |||
| textcolor="white" | |||
| disabled={ | |||
| formik.values.mail.length === 0 || | |||
| formik.values.password.length === 0 || | |||
| formik.values.mail === props.error | |||
| } | |||
| > | |||
| {t("common.continue")} | |||
| </PrimaryButton> | |||
| </FormContainer> | |||
| ); | |||
| }; | |||
| FirstPartOfRegistration.propTypes = { | |||
| children: PropTypes.node, | |||
| handleSubmit: PropTypes.func, | |||
| error: PropTypes.string, | |||
| errorMessage: PropTypes.string, | |||
| }; | |||
| export default FirstPartOfRegistration; | |||
| @@ -0,0 +1,33 @@ | |||
| import { Typography } from "@mui/material"; | |||
| import styled from "styled-components"; | |||
| import selectedTheme from "../../../../themes"; | |||
| export const FormContainer = styled.form` | |||
| width: 335px; | |||
| `; | |||
| export const RegisterDescription = styled(Typography)` | |||
| font-family: "Open Sans"; | |||
| font-style: normal; | |||
| font-weight: 400; | |||
| display: flex; | |||
| align-items: center; | |||
| color: ${selectedTheme.primaryGrayText}; | |||
| font-size: 12px; | |||
| width: 100%; | |||
| text-align: left; | |||
| line-height: 16px; | |||
| margin-top: 31px; | |||
| margin-bottom: 2px; | |||
| letter-spacing: 0.02em; | |||
| @media (max-height: 800px) { | |||
| margin-top: 14px; | |||
| } | |||
| `; | |||
| export const ErrorMessage = styled(Typography)` | |||
| color: red; | |||
| font-family: "Open Sans"; | |||
| position: relative; | |||
| top: -7px; | |||
| font-size: 14px; | |||
| ` | |||
| @@ -0,0 +1,154 @@ | |||
| import React, { useState } from "react"; | |||
| import PropTypes from "prop-types"; | |||
| import { | |||
| RegisterPageContainer, | |||
| Footer, | |||
| FooterText, | |||
| LoginAltText, | |||
| LoginTextContainer, | |||
| ProgressContainer, | |||
| RegisterDescription, | |||
| RegisterTitle, | |||
| } from "./Register.styled"; | |||
| import { ReactComponent as Logo } from "../../../assets/images/svg/logo-vertical.svg"; | |||
| import { NavLink, useHistory } from "react-router-dom"; | |||
| import { Trans, useTranslation } from "react-i18next"; | |||
| import Link from "../../../components/Link/Link"; | |||
| import StepProgress from "../../../components/StepProgress/StepProgress"; | |||
| import { REGISTER_SUCCESSFUL_PAGE } from "../../../constants/pages"; | |||
| import FirstPartOfRegistration from "./FirstPart/FirstPartOfRegistration"; | |||
| import SecondPartOfRegistration from "./SecondPart/SecondPartOfRegistration"; | |||
| import ThirdPartOfRegistration from "./ThirdPart/ThirdPartOfRegistration"; | |||
| import { useDispatch } from "react-redux"; | |||
| import { fetchRegisterUser } from "../../../store/actions/register/registerActions"; | |||
| const Register = () => { | |||
| const { t } = useTranslation(); | |||
| const history = useHistory(); | |||
| const dispatch = useDispatch(); | |||
| const [currentStep, setCurrentStep] = useState(1); | |||
| const [informations, setInformations] = useState({}); // Values of fields typed in all steps | |||
| const [mailError, setMailError] = useState(""); // Wrong mail typed | |||
| const [mailErrorMessage, setMailErrorMessage] = useState(""); // Error message caused by typing wrong mail | |||
| const [PIBError, setPIBError] = useState(""); // Wrong PIB typed | |||
| const [PIBErrorMessage, setPIBErrorMessage] = useState(""); // Error message caused by typing wrong PIB | |||
| const handleResponseSuccess = () => { | |||
| history.push(REGISTER_SUCCESSFUL_PAGE); | |||
| }; | |||
| const handleResponseError = (error) => { | |||
| if (error.type === "mail") { | |||
| const { mail } = informations; | |||
| setInformations({}); | |||
| setCurrentStep(1); | |||
| setMailError(mail); | |||
| if ( | |||
| error.error.response.data.toString() === | |||
| "User with email already exists" | |||
| ) { | |||
| setMailErrorMessage(t("register.emailTaken")); | |||
| } else { | |||
| setMailErrorMessage(t("register.emailFormat")); | |||
| } | |||
| } else { | |||
| const { mail, password, PIB } = informations; | |||
| setInformations({ mail, password }); | |||
| setCurrentStep(2); | |||
| setPIBError(PIB.toString()); | |||
| setPIBErrorMessage(t("register.PIBTaken")); | |||
| } | |||
| }; | |||
| const registerUser = (values) => { | |||
| dispatch( | |||
| fetchRegisterUser({ values, handleResponseSuccess, handleResponseError }) | |||
| ); | |||
| }; | |||
| const handleSubmit = (values) => { | |||
| if (currentStep !== 3) { | |||
| setCurrentStep((prevState) => prevState + 1); | |||
| } else { | |||
| registerUser({ ...informations, ...values }); | |||
| } | |||
| setInformations({ ...informations, ...values }); | |||
| }; | |||
| const goStepBack = (stepNumber) => { | |||
| setCurrentStep(stepNumber); | |||
| if (stepNumber === 1) { | |||
| setInformations({}); | |||
| } | |||
| if (stepNumber === 2) { | |||
| const { mail, password } = informations; | |||
| setInformations({ mail, password }); | |||
| } | |||
| }; | |||
| return ( | |||
| <RegisterPageContainer currentstep={currentStep}> | |||
| <Logo /> | |||
| <RegisterTitle component="h1" variant="h5"> | |||
| {t("register.title")} | |||
| </RegisterTitle> | |||
| <RegisterDescription component="h1" variant="h6"> | |||
| {t("register.descriptionMain")} | |||
| </RegisterDescription> | |||
| <ProgressContainer> | |||
| <StepProgress | |||
| functions={[() => goStepBack(1), () => goStepBack(2)]} | |||
| current={currentStep} | |||
| numberOfSteps={3} | |||
| /> | |||
| </ProgressContainer> | |||
| {currentStep === 1 && ( | |||
| <FirstPartOfRegistration | |||
| handleSubmit={handleSubmit} | |||
| error={mailError} | |||
| errorMessage={mailErrorMessage} | |||
| /> | |||
| )} | |||
| {currentStep === 2 && ( | |||
| <SecondPartOfRegistration | |||
| handleSubmit={handleSubmit} | |||
| error={PIBError} | |||
| errorMessage={PIBErrorMessage} | |||
| /> | |||
| )} | |||
| {currentStep === 3 && ( | |||
| <ThirdPartOfRegistration handleSubmit={handleSubmit} /> | |||
| )} | |||
| <LoginTextContainer> | |||
| <LoginAltText>{t("register.loginText")}</LoginAltText> | |||
| <Link to="/login" component={NavLink} underline="hover" align="center"> | |||
| {t("register.login")} | |||
| </Link> | |||
| </LoginTextContainer> | |||
| <Footer> | |||
| <FooterText> | |||
| <Trans i18nKey="register.acceptTerms" />{" "} | |||
| <NavLink | |||
| to="#" | |||
| style={{ color: "black", fontWeight: "500", cursor: "pointer" }} | |||
| > | |||
| <Trans i18nKey="register.terms" /> | |||
| </NavLink> | |||
| </FooterText> | |||
| </Footer> | |||
| </RegisterPageContainer> | |||
| ); | |||
| }; | |||
| Register.propTypes = { | |||
| children: PropTypes.node, | |||
| }; | |||
| export default Register; | |||