浏览代码

Initial commit

pull/4/head
Djordje Mitrovic 3 年前
父节点
当前提交
ba5e375b09
共有 100 个文件被更改,包括 2488 次插入319 次删除
  1. 1
    0
      package.json
  2. 3
    0
      public/index.html
  3. 20
    15
      src/App.js
  4. 22
    8
      src/AppRoutes.js
  5. 7
    0
      src/assets/images/svg/big-logo-vertical.svg
  6. 4
    0
      src/assets/images/svg/briefcase.svg
  7. 13
    0
      src/assets/images/svg/category-chosen.svg
  8. 6
    0
      src/assets/images/svg/category.svg
  9. 4
    0
      src/assets/images/svg/check-circle.svg
  10. 3
    0
      src/assets/images/svg/checkmark.svg
  11. 4
    0
      src/assets/images/svg/close-black.svg
  12. 4
    0
      src/assets/images/svg/close-white.svg
  13. 7
    0
      src/assets/images/svg/coffee.svg
  14. 3
    0
      src/assets/images/svg/down-arrow.svg
  15. 21
    0
      src/assets/images/svg/dummyImages/offer-1.svg
  16. 21
    0
      src/assets/images/svg/dummyImages/offer-2.svg
  17. 21
    0
      src/assets/images/svg/dummyImages/offer-3.svg
  18. 21
    0
      src/assets/images/svg/dummyImages/offer-4.svg
  19. 4
    0
      src/assets/images/svg/edit.svg
  20. 4
    0
      src/assets/images/svg/eye-striked.svg
  21. 3
    0
      src/assets/images/svg/eye.svg
  22. 5
    0
      src/assets/images/svg/globe.svg
  23. 4
    0
      src/assets/images/svg/home.svg
  24. 11
    0
      src/assets/images/svg/location.svg
  25. 7
    0
      src/assets/images/svg/logo-vertical.svg
  26. 3
    0
      src/assets/images/svg/magnifying-glass.svg
  27. 9
    0
      src/assets/images/svg/mail-sent.svg
  28. 4
    0
      src/assets/images/svg/mail.svg
  29. 4
    0
      src/assets/images/svg/offer-grid-line.svg
  30. 4
    0
      src/assets/images/svg/offer-grid-square.svg
  31. 5
    0
      src/assets/images/svg/quantity.svg
  32. 3
    0
      src/assets/images/svg/radio-checked.svg
  33. 3
    0
      src/assets/images/svg/radio-unchecked.svg
  34. 12
    0
      src/assets/images/svg/refresh.svg
  35. 9
    0
      src/assets/images/svg/register-success.svg
  36. 3
    0
      src/assets/images/svg/star.svg
  37. 3
    0
      src/assets/images/svg/subcategory.svg
  38. 3
    0
      src/assets/images/svg/thumbs-down.svg
  39. 3
    0
      src/assets/images/svg/thumbs-up.svg
  40. 4
    0
      src/assets/images/svg/trash.svg
  41. 6
    0
      src/assets/images/svg/truck.svg
  42. 3
    0
      src/assets/images/svg/up-arrow.svg
  43. 4
    0
      src/assets/images/svg/user.svg
  44. 1
    0
      src/assets/styles/_base.scss
  45. 2
    1
      src/components/Buttons/IconButton/IconButton.js
  46. 8
    0
      src/components/Buttons/IconButton/IconButton.styled.js
  47. 1
    1
      src/components/Buttons/LoginButton/LoginButton.js
  48. 9
    2
      src/components/Buttons/PrimaryButton/PrimaryButton.js
  49. 11
    3
      src/components/Buttons/PrimaryButton/PrimaryButton.styled.js
  50. 6
    4
      src/components/CheckBox/CheckBox.js
  51. 25
    13
      src/components/CheckBox/CheckBox.styled.js
  52. 12
    3
      src/components/CheckBox/Label.js
  53. 6
    0
      src/components/CheckBox/Label.styled.js
  54. 1
    0
      src/components/Dropdown/DropdownItem/DropdownItem.styled.js
  55. 27
    9
      src/components/Dropdown/DropdownList/DropdownList.js
  56. 54
    39
      src/components/Dropdown/DropdownList/DropdownList.styled.js
  57. 4
    3
      src/components/Icon/Icon.js
  58. 4
    0
      src/components/Icon/Icon.styled.js
  59. 19
    0
      src/components/Icon/IconWithNumber/IconWithNumber.js
  60. 19
    0
      src/components/Icon/IconWithNumber/IconWithNumber.styled.js
  61. 28
    0
      src/components/Link/Link.js
  62. 18
    0
      src/components/Link/Link.styled.js
  63. 6
    4
      src/components/Loader/FullPageLoader.js
  64. 10
    0
      src/components/Loader/FullPageLoader.styled.js
  65. 1
    1
      src/components/MUI/DialogComponent.js
  66. 52
    0
      src/components/Radio/Button/RadioButton.js
  67. 40
    0
      src/components/Radio/Button/RadioButton.styled.js
  68. 20
    0
      src/components/Radio/Group/RadioGroup.js
  69. 7
    0
      src/components/Radio/Group/RadioGroup.styled.js
  70. 55
    0
      src/components/StepProgress/StepProgress.js
  71. 45
    0
      src/components/StepProgress/StepProgress.styled.js
  72. 二进制
      src/components/Styles/fonts/Mulish-Regular.ttf
  73. 二进制
      src/components/Styles/fonts/OpenSans-Regular.ttf
  74. 二进制
      src/components/Styles/fonts/Poppins-Regular.ttf
  75. 29
    0
      src/components/Styles/globalStyles.js
  76. 42
    8
      src/components/TextFields/TextField/TextField.js
  77. 36
    4
      src/components/TextFields/TextField/TextField.styled.js
  78. 6
    1
      src/constants/pages.js
  79. 3
    0
      src/constants/sessionStorage.js
  80. 7
    3
      src/i18n/index.js
  81. 135
    0
      src/i18n/resources/rs.js
  82. 26
    0
      src/pages/CreateOffer/CreateOffer.js
  83. 56
    0
      src/pages/CreateOffer/CreateOffer.styled.js
  84. 54
    0
      src/pages/ForgotPasswordPage/ForgotPassword.styled.js
  85. 96
    0
      src/pages/ForgotPasswordPage/ForgotPasswordMailSent/MailSent.js
  86. 77
    0
      src/pages/ForgotPasswordPage/ForgotPasswordMailSent/MailSent.styled.js
  87. 105
    51
      src/pages/ForgotPasswordPage/ForgotPasswordPage.js
  88. 17
    8
      src/pages/HomePage/HomePage.styled.js
  89. 66
    33
      src/pages/HomePage/HomePageMUI.js
  90. 68
    0
      src/pages/LoginPage/Login.styled.js
  91. 183
    105
      src/pages/LoginPage/LoginPage.js
  92. 130
    0
      src/pages/RegisterPages/Register/FirstPart/FirstPartOfRegistration.js
  93. 33
    0
      src/pages/RegisterPages/Register/FirstPart/FirstPartOfRegistration.styled.js
  94. 154
    0
      src/pages/RegisterPages/Register/Register.js
  95. 101
    0
      src/pages/RegisterPages/Register/Register.styled.js
  96. 103
    0
      src/pages/RegisterPages/Register/SecondPart/SecondPartOfRegistration.js
  97. 33
    0
      src/pages/RegisterPages/Register/SecondPart/SecondPartOfRegistration.styled.js
  98. 104
    0
      src/pages/RegisterPages/Register/ThirdPart/ThirdPartOfRegistration.js
  99. 25
    0
      src/pages/RegisterPages/Register/ThirdPart/ThirdPartOfRegistration.styled.js
  100. 0
    0
      src/pages/RegisterPages/RegisterSuccessful.js/RegisterSuccessful.js

+ 1
- 0
package.json 查看文件

@@ -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
- 0
public/index.html 查看文件

@@ -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

+ 20
- 15
src/App.js 查看文件

@@ -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;

+ 22
- 8
src/AppRoutes.js 查看文件

@@ -8,25 +8,39 @@ import {
NOT_FOUND_PAGE,
ERROR_PAGE,
BASE_PAGE,
FORGOT_PASSWORD_MAIL_SENT,
REGISTER_PAGE,
REGISTER_SUCCESSFUL_PAGE,
RESET_PASSWORD_PAGE,
CREATE_OFFER_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';
import CreateOffer from './pages/CreateOffer/CreateOffer';


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}/>
<Route path={CREATE_OFFER_PAGE} component={CreateOffer}/>
<PrivateRoute
exact
path={HOME_PAGE}
@@ -34,7 +48,7 @@ const AppRoutes = () => (
/>
<Redirect from="*" to={NOT_FOUND_PAGE} />
</Switch>
);
)};


export default AppRoutes;

+ 7
- 0
src/assets/images/svg/big-logo-vertical.svg
文件差异内容过多而无法显示
查看文件


+ 4
- 0
src/assets/images/svg/briefcase.svg 查看文件

@@ -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>

+ 13
- 0
src/assets/images/svg/category-chosen.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>

+ 6
- 0
src/assets/images/svg/category.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>

+ 4
- 0
src/assets/images/svg/check-circle.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>

+ 3
- 0
src/assets/images/svg/checkmark.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>

+ 4
- 0
src/assets/images/svg/close-black.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>

+ 4
- 0
src/assets/images/svg/close-white.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>

+ 7
- 0
src/assets/images/svg/coffee.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>

+ 3
- 0
src/assets/images/svg/down-arrow.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>

+ 21
- 0
src/assets/images/svg/dummyImages/offer-1.svg
文件差异内容过多而无法显示
查看文件


+ 21
- 0
src/assets/images/svg/dummyImages/offer-2.svg
文件差异内容过多而无法显示
查看文件


+ 21
- 0
src/assets/images/svg/dummyImages/offer-3.svg
文件差异内容过多而无法显示
查看文件


+ 21
- 0
src/assets/images/svg/dummyImages/offer-4.svg
文件差异内容过多而无法显示
查看文件


+ 4
- 0
src/assets/images/svg/edit.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>

+ 4
- 0
src/assets/images/svg/eye-striked.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>

+ 3
- 0
src/assets/images/svg/eye.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>

+ 5
- 0
src/assets/images/svg/globe.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>

+ 4
- 0
src/assets/images/svg/home.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>

+ 11
- 0
src/assets/images/svg/location.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>

+ 7
- 0
src/assets/images/svg/logo-vertical.svg
文件差异内容过多而无法显示
查看文件


+ 3
- 0
src/assets/images/svg/magnifying-glass.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>

+ 9
- 0
src/assets/images/svg/mail-sent.svg
文件差异内容过多而无法显示
查看文件


+ 4
- 0
src/assets/images/svg/mail.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>

+ 4
- 0
src/assets/images/svg/offer-grid-line.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>

+ 4
- 0
src/assets/images/svg/offer-grid-square.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>

+ 5
- 0
src/assets/images/svg/quantity.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>

+ 3
- 0
src/assets/images/svg/radio-checked.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>

+ 3
- 0
src/assets/images/svg/radio-unchecked.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>

+ 12
- 0
src/assets/images/svg/refresh.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>

+ 9
- 0
src/assets/images/svg/register-success.svg
文件差异内容过多而无法显示
查看文件


+ 3
- 0
src/assets/images/svg/star.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>

+ 3
- 0
src/assets/images/svg/subcategory.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>

+ 3
- 0
src/assets/images/svg/thumbs-down.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>

+ 3
- 0
src/assets/images/svg/thumbs-up.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>

+ 4
- 0
src/assets/images/svg/trash.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>

+ 6
- 0
src/assets/images/svg/truck.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>

+ 3
- 0
src/assets/images/svg/up-arrow.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>

+ 4
- 0
src/assets/images/svg/user.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>

+ 1
- 0
src/assets/styles/_base.scss 查看文件

@@ -3,6 +3,7 @@ body {
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
overflow-anchor: none;
background-color: #F1F1F1;
}

* {

+ 2
- 1
src/components/Buttons/IconButton/IconButton.js 查看文件

@@ -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
}

+ 8
- 0
src/components/Buttons/IconButton/IconButton.styled.js 查看文件

@@ -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};
}
`}
`

+ 1
- 1
src/components/Buttons/LoginButton/LoginButton.js 查看文件

@@ -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
};

+ 9
- 2
src/components/Buttons/PrimaryButton/PrimaryButton.js 查看文件

@@ -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",
};

+ 11
- 3
src/components/Buttons/PrimaryButton/PrimaryButton.styled.js 查看文件

@@ -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 {

+ 6
- 4
src/components/CheckBox/CheckBox.js 查看文件

@@ -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,

+ 25
- 13
src/components/CheckBox/CheckBox.styled.js 查看文件

@@ -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;
}
`;

+ 12
- 3
src/components/CheckBox/Label.js 查看文件

@@ -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,
};

+ 6
- 0
src/components/CheckBox/Label.styled.js 查看文件

@@ -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";

`

+ 1
- 0
src/components/Dropdown/DropdownItem/DropdownItem.styled.js 查看文件

@@ -5,4 +5,5 @@ export const DropdownItemContainer = styled(Box)`
`

export const DropdownItemStyled = styled(Box)`
font-family: "Open Sans";
`

+ 27
- 9
src/components/Dropdown/DropdownList/DropdownList.js 查看文件

@@ -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,
};

+ 54
- 39
src/components/Dropdown/DropdownList/DropdownList.styled.js 查看文件

@@ -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")};
`;

+ 4
- 3
src/components/Icon/Icon.js 查看文件

@@ -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,
}

+ 4
- 0
src/components/Icon/Icon.styled.js 查看文件

@@ -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};
}
`

+ 19
- 0
src/components/Icon/IconWithNumber/IconWithNumber.js 查看文件

@@ -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

+ 19
- 0
src/components/Icon/IconWithNumber/IconWithNumber.styled.js 查看文件

@@ -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";
`

+ 28
- 0
src/components/Link/Link.js 查看文件

@@ -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;

+ 18
- 0
src/components/Link/Link.styled.js 查看文件

@@ -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;"} */
`;

+ 6
- 4
src/components/Loader/FullPageLoader.js 查看文件

@@ -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>
);
};


+ 10
- 0
src/components/Loader/FullPageLoader.styled.js 查看文件

@@ -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;
`

+ 1
- 1
src/components/MUI/DialogComponent.js 查看文件

@@ -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,
};

+ 52
- 0
src/components/Radio/Button/RadioButton.js 查看文件

@@ -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;

+ 40
- 0
src/components/Radio/Button/RadioButton.styled.js 查看文件

@@ -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;
}
`;

+ 20
- 0
src/components/Radio/Group/RadioGroup.js 查看文件

@@ -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

+ 7
- 0
src/components/Radio/Group/RadioGroup.styled.js 查看文件

@@ -0,0 +1,7 @@
import { RadioGroup } from "@mui/material";
import styled from "styled-components";

export const RadioGroupContainer = styled(RadioGroup)`
padding-left: 5px;
width: 100%;
`

+ 55
- 0
src/components/StepProgress/StepProgress.js 查看文件

@@ -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;

+ 45
- 0
src/components/StepProgress/StepProgress.styled.js 查看文件

@@ -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;
`;

二进制
src/components/Styles/fonts/Mulish-Regular.ttf 查看文件


二进制
src/components/Styles/fonts/OpenSans-Regular.ttf 查看文件


二进制
src/components/Styles/fonts/Poppins-Regular.ttf 查看文件


+ 29
- 0
src/components/Styles/globalStyles.js 查看文件

@@ -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;

+ 42
- 8
src/components/TextFields/TextField/TextField.js 查看文件

@@ -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"
};

+ 36
- 4
src/components/TextFields/TextField/TextField.styled.js 查看文件

@@ -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 : "")};
}
`;

+ 6
- 1
src/constants/pages.js 查看文件

@@ -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"

+ 3
- 0
src/constants/sessionStorage.js 查看文件

@@ -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";

+ 7
- 3
src/i18n/index.js 查看文件

@@ -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,
},

+ 135
- 0
src/i18n/resources/rs.js 查看文件

@@ -0,0 +1,135 @@
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!",
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..."
}
}
}

+ 26
- 0
src/pages/CreateOffer/CreateOffer.js 查看文件

@@ -0,0 +1,26 @@
/* eslint-disable */
import React, { useEffect, useState } from "react";
import PropTypes from "prop-types";
import {
CreateOfferContainer,
} from "./CreateOffer.styled";
import CreateOffer from "../../components/Cards/CreateOfferCard/CreateOffer";

const CreateOfferPage = ({ history }) => {
return (
<CreateOfferContainer>
<CreateOffer/>
</CreateOfferContainer>
);
};

CreateOfferPage.propTypes = {
history: PropTypes.shape({
replace: PropTypes.func,
push: PropTypes.func,
location: PropTypes.shape({
pathname: PropTypes.string,
}),
}),
};
export default CreateOfferPage;

+ 56
- 0
src/pages/CreateOffer/CreateOffer.styled.js 查看文件

@@ -0,0 +1,56 @@
import { Box, Container, Typography } from "@mui/material";
import styled from "styled-components";
import selectedTheme from "../../themes";

export const CreateOfferContainer = styled(Container)`
margin-top: 0px;
display: flex;
width: 380px;
flex-direction: column;
align-items: center;
`;
export const CreateOfferTitle = styled(Typography)`
font-family: "Open Sans";
width: 328px;
height: 33px;
text-align: center;
flex: 1;
font-style: normal;
font-weight: 700;
font-size: 24px;
line-height: 33px;
color: ${selectedTheme.primaryPurple};
margin-top: 36px;
margin-bottom: 40px;
`;
export const CreateOfferDescription = 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 CreateOfferFormContainer = 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;
`

+ 54
- 0
src/pages/ForgotPasswordPage/ForgotPassword.styled.js 查看文件

@@ -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;
`

+ 96
- 0
src/pages/ForgotPasswordPage/ForgotPasswordMailSent/MailSent.js 查看文件

@@ -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;

+ 77
- 0
src/pages/ForgotPasswordPage/ForgotPasswordMailSent/MailSent.styled.js 查看文件

@@ -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;
`

+ 105
- 51
src/pages/ForgotPasswordPage/ForgotPasswordPage.js 查看文件

@@ -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>
);
};


+ 17
- 8
src/pages/HomePage/HomePage.styled.js 查看文件

@@ -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)`
`;

+ 66
- 33
src/pages/HomePage/HomePageMUI.js 查看文件

@@ -1,38 +1,71 @@
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, { useEffect } from "react";
import Navbar from "../../components/MUI/NavbarComponent";
// import FilterCard from "../../components/Cards/FilterCard/FilterCard";
import { HomePageContainer } from "./HomePage.styled";
// import MarketPlace from "../../components/MarketPlace/MarketPlace";
// import MainLayout from "../../layouts/MainLayout/MainLayout";
import { useDispatch } from "react-redux";
// import { logoutUser } from "../../store/actions/login/loginActions";
import Mockupdata from "../../components/Cards/FilterCard/Mockupdata";
import qs from "query-string";
import { useHistory } from "react-router-dom";
import { setFilters } from "../../store/actions/filters/filtersActions";
// import ProfileLayout from "../../layouts/ProfileLayout/ProfileLayout";
import FilterCard from "../../components/Cards/FilterCard/FilterCard";
import MainLayout from "../../layouts/MainLayout/MainLayout";
import MarketPlace from "../../components/MarketPlace/MarketPlace";

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>
</>
);
const dispatch = useDispatch();

const history = useHistory();
useEffect(() => {
let category = null, subcategory = null, cities = [], _des_date = false, _des_popular = false, page, size;
const queryString = history.location.search.substring(1);
const queryObject = qs.parse(queryString);

if (queryObject.category) {
category = Mockupdata[1].find(
(item) => item.string === queryObject.category.toString()
).id;
}
if (queryObject.subcategory) {
subcategory = Mockupdata[1].find(
(item) => item.string === queryObject.subcategory.toString()
).id;
}
if (queryObject.city) {
if (Array.isArray(queryObject.city)) {
queryObject.city.forEach((item) => {
cities.push(Mockupdata[0].find((p) => p.string === item).id);
});
} else {
cities.push(
Mockupdata[0].find((p) => p.string === queryObject.city).id
);
}
}
if (queryObject.sortBy) {
if (queryObject.sortBy === "dateAsc") _des_date = false;
if (queryObject.sortBy === "dateDesc") _des_date = true;
if (queryObject.sortBy === "popular") _des_popular = true;
}
if (queryObject.page) {
page = queryObject.page;
}
if (queryObject.size) {
size = queryObject.size;
}

dispatch(setFilters({ category, subcategory, cities, _des_date, _des_popular, page, size }));
}, [history.location.search]);

return (
<HomePageContainer>
<Navbar />
<MainLayout leftCard={<FilterCard />} content={<MarketPlace />} />
</HomePageContainer>
);
};

export default HomePage;

+ 68
- 0
src/pages/LoginPage/Login.styled.js 查看文件

@@ -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;
`;

+ 183
- 105
src/pages/LoginPage/LoginPage.js 查看文件

@@ -1,135 +1,213 @@
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";

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: {
email: "",
password: "",
},
validationSchema: Yup.object().shape({
email: Yup.string().required(t("login.mailRequired")),
password: Yup.string()
.required(t("login.passwordRequired"))
.min(8, t("login.passwordLength")),
}),
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>
);
};


+ 130
- 0
src/pages/RegisterPages/Register/FirstPart/FirstPartOfRegistration.js 查看文件

@@ -0,0 +1,130 @@
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
/>

{formik.errors.mail && formik.touched.mail ? (
<ErrorMessage>{formik.errors.mail}</ErrorMessage>
) : (
<></>
)}

<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.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;

+ 33
- 0
src/pages/RegisterPages/Register/FirstPart/FirstPartOfRegistration.styled.js 查看文件

@@ -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;
`

+ 154
- 0
src/pages/RegisterPages/Register/Register.js 查看文件

@@ -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;

+ 101
- 0
src/pages/RegisterPages/Register/Register.styled.js 查看文件

@@ -0,0 +1,101 @@
import { Box, Container, Typography } from "@mui/material";
import styled from "styled-components";
import selectedTheme from "../../../themes";

export const RegisterPageContainer = styled(Container)`
margin-top: 100px;
display: flex;
flex-direction: column;
align-items: center;
width: 335px;
padding: 0;
flex: 1;
position: relative;
@media (max-height: 900px) {
margin-top: 60px;
}
@media (max-height: 800px) {
margin-top: 30px;
flex: none;
height: 95vh;
${props => props.currentstep === 3 && `height: 105vh`};
${props => props.currentstep === 2 && `height: 100vh`};
}
`;
export const RegisterTitle = styled(Typography)`
font-family: "Open Sans";
width: 328px;
height: 33px;
text-align: center;
font-style: normal;
font-weight: 400;
font-size: 24px;
line-height: 33px;
color: ${selectedTheme.primaryPurple};
margin-top: 34px;
@media (max-height: 800px) {
margin-top: 26px;
}
`;
export const RegisterDescription = 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;
@media (max-height: 800px) {
margin-bottom: 14px;
margin-top: 6px;
}
`;
export const FormContainer = styled(Box)`
width: 335px;
`;
export const LoginAltText = styled(Typography)`
font-family: "Poppins";
color: ${selectedTheme.primaryText};
font-size: 14px;
padding-right: 6px;
line-height: 14px;
`
export const LoginTextContainer = styled(Box)`
display: flex;
flex-direction: row;
margin-top: 36px;
justify-content: center;
@media (max-height: 800px) {
margin-top: 26px;
}
`
export const ProgressContainer = styled(Container)`
width: 100%;
padding: 0;
`
export const Footer = styled(Box)`
position: absolute;
bottom: 36px;
display: flex;
width: 100%;
flex-direction: row;
justify-content: center;
@media (max-height: 800px) {
bottom: 10px;
}
`
export const FooterText = styled(Typography)`
font-family: "Open Sans";
color: #505050;
text-align: center;
width: 330px;
line-height: 16px;
font-weight: 400;
padding: 0;
font-size: 12px;
`

+ 103
- 0
src/pages/RegisterPages/Register/SecondPart/SecondPartOfRegistration.js 查看文件

@@ -0,0 +1,103 @@
import React, { useEffect, useState } from "react";
import PropTypes from "prop-types";
import {
ErrorMessage,
FormContainer,
RegisterDescription,
} from "./SecondPartOfRegistration.styled";
import { useFormik } from "formik";
import * as Yup from "yup";
import { useTranslation } from "react-i18next";
import { TextField } from "../../../../components/TextFields/TextField/TextField";
import { PrimaryButton } from "../../../../components/Buttons/PrimaryButton/PrimaryButton";
import selectedTheme from "../../../../themes";

const SecondPartOfRegistration = (props) => {
const { t } = useTranslation();
const [PIBTakenStatus, setPIBTakenStatus] = useState(false);

useEffect(() => {
if (props.error.length > 0) {
setPIBTakenStatus(true);
}
}, [props.error]);

const formik = useFormik({
initialValues: {
nameOfFirm: "",
PIB: "",
},
validationSchema: Yup.object().shape({
nameOfFirm: Yup.string().required(t("login.usernameRequired")),
PIB: Yup.number()
.required(t("login.passwordRequired"))
.min(100000000, "PIB mora imati 9 karaktera!")
.max(999999999, "PIB mora imati 9 karaktera!"),
}),
onSubmit: props.handleSubmit,
validateOnBlur: true,
enableReinitialize: true,
});
return (
<FormContainer component="form" onSubmit={formik.handleSubmit}>
<RegisterDescription component="p" variant="p">
{t("register.descriptionSecond")}
</RegisterDescription>

<TextField
name="nameOfFirm"
placeholder={t("common.labelFirm")}
margin="normal"
value={formik.values.nameOfFirm}
onChange={formik.handleChange}
error={formik.touched.nameOfFirm && Boolean(formik.errors.nameOfFirm)}
helperText={formik.touched.nameOfFirm && formik.errors.nameOfFirm}
autoFocus
fullWidth
/>

<TextField
name="PIB"
placeholder={t("common.labelPIB")}
margin="normal"
type="number"
value={formik.values.PIB}
onChange={formik.handleChange}
error={
(formik.touched.PIB && Boolean(formik.errors.PIB)) || PIBTakenStatus
}
helperText={formik.touched.PIB && formik.errors.PIB}
fullWidth
/>
{formik.errors.PIB && formik.touched.PIB && (
<ErrorMessage>{formik.errors.PIB}</ErrorMessage>
)}
{props.error && <ErrorMessage>{props.errorMessage}</ErrorMessage>}

<PrimaryButton
type="submit"
variant="contained"
height="48px"
fullWidth
buttoncolor={selectedTheme.primaryPurple}
textcolor="white"
disabled={
formik.values.PIB.length === 0 ||
formik.values.nameOfFirm.length === 0 ||
formik.values.PIB.toString() === props.error
}
>
{t("common.continue")}
</PrimaryButton>
</FormContainer>
);
};

SecondPartOfRegistration.propTypes = {
children: PropTypes.node,
handleSubmit: PropTypes.func,
error: PropTypes.string,
errorMessage: PropTypes.string,
};

export default SecondPartOfRegistration;

+ 33
- 0
src/pages/RegisterPages/Register/SecondPart/SecondPartOfRegistration.styled.js 查看文件

@@ -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.primaryText};
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;
`

+ 104
- 0
src/pages/RegisterPages/Register/ThirdPart/ThirdPartOfRegistration.js 查看文件

@@ -0,0 +1,104 @@
import React from "react";
import PropTypes from "prop-types";
import {
FormContainer,
RegisterDescription,
} from "./ThirdPartOfRegistration.styled";
import { useFormik } from "formik";
import * as Yup from "yup";
import { useTranslation } from "react-i18next";
import { TextField } from "../../../../components/TextFields/TextField/TextField";
import { PrimaryButton } from "../../../../components/Buttons/PrimaryButton/PrimaryButton";
import selectedTheme from "../../../../themes";

const ThirdPartOfRegistration = (props) => {
const { t } = useTranslation();

const formik = useFormik({
initialValues: {
phoneNumber: "",
location: "",
website: "",
},
validationSchema: Yup.object().shape({
phoneNumber: Yup.number().required(t("login.usernameRequired")),
location: Yup.string().required(t("login.passwordRequired")),
website: Yup.string().matches(
/^((ftp|http|https):\/\/)?(www.)?(?!.*(ftp|http|https|www.))[a-zA-Z0-9_-]+(\.[a-zA-Z]+)+((\/)[\w#]+)*(\/\w+\?[a-zA-Z0-9_]+=\w+(&[a-zA-Z0-9_]+=\w+)*)?$/gm
),
}),
onSubmit: props.handleSubmit,
validateOnBlur: true,
enableReinitialize: true,
});

return (
<FormContainer component="form" onSubmit={formik.handleSubmit}>
<RegisterDescription component="p" variant="p">
{t("register.descriptionThird")}
</RegisterDescription>

<TextField
name="phoneNumber"
placeholder={t("common.labelPhone")}
margin="normal"
type="number"
value={formik.values.phoneNumber}
onChange={formik.handleChange}
error={
(formik.touched.phoneNumber && Boolean(formik.errors.phoneNumber))
}
helperText={formik.touched.phoneNumber && formik.errors.phoneNumber}
autoFocus
fullWidth
/>

<TextField
name="location"
placeholder={t("common.labelLocation")}
margin="normal"
type="text"
value={formik.values.location}
onChange={formik.handleChange}
error={formik.touched.location && Boolean(formik.errors.location)}
helperText={formik.touched.location && formik.errors.location}
fullWidth
/>

<TextField
name="website"
placeholder={t("common.labelWebsite")}
margin="normal"
type="text"
value={formik.values.website}
onChange={formik.handleChange}
error={formik.touched.website && Boolean(formik.errors.website)}
helperText={formik.touched.website && formik.errors.website}
fullWidth
/>

<PrimaryButton
type="submit"
variant="contained"
height="48px"
fullWidth
buttoncolor={selectedTheme.primaryPurple}
textcolor="white"
disabled={
formik.values.location.length === 0 &&
formik.values.phoneNumber.length === 0 &&
formik.values.website.length === 0
}
>
{t("common.continue")}
</PrimaryButton>
</FormContainer>
);
};

ThirdPartOfRegistration.propTypes = {
children: PropTypes.node,
handleSubmit: PropTypes.func,
};

export default ThirdPartOfRegistration;

+ 25
- 0
src/pages/RegisterPages/Register/ThirdPart/ThirdPartOfRegistration.styled.js 查看文件

@@ -0,0 +1,25 @@
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.primaryText};
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;
}
`;

+ 0
- 0
src/pages/RegisterPages/RegisterSuccessful.js/RegisterSuccessful.js 查看文件


部分文件因为文件数量过多而无法显示

正在加载...
取消
保存