浏览代码

Minor changes, started creating createOffer page, started connecting with backend, making some pages responsive

pull/2/head
Djordje Mitrovic 3 年前
父节点
当前提交
af597b3f36
共有 40 个文件被更改,包括 470 次插入173 次删除
  1. 7
    0
      src/assets/images/svg/coffee.svg
  2. 4
    0
      src/assets/images/svg/home.svg
  3. 6
    0
      src/assets/images/svg/truck.svg
  4. 7
    92
      src/components/Cards/CreateOfferCard/CreateOffer.js
  5. 14
    0
      src/components/Cards/CreateOfferCard/CreateOffer.styled.js
  6. 104
    0
      src/components/Cards/CreateOfferCard/FirstPart/FirstPartCreateOffer.js
  7. 50
    0
      src/components/Cards/CreateOfferCard/FirstPart/FirstPartCreateOffer.styled.js
  8. 4
    3
      src/components/Cards/OfferCard/OfferCard.js
  9. 1
    1
      src/components/Cards/OfferCard/OfferCard.styled.js
  10. 11
    2
      src/components/CheckBox/Label.js
  11. 11
    9
      src/components/MarketPlace/Offers/Offers.js
  12. 27
    0
      src/components/Select/Option/Option.js
  13. 13
    0
      src/components/Select/Option/Option.styled.js
  14. 35
    0
      src/components/Select/Select.js
  15. 12
    0
      src/components/Select/Select.styled.js
  16. 1
    0
      src/components/TextFields/TextField/TextField.js
  17. 10
    4
      src/components/TextFields/TextField/TextField.styled.js
  18. 6
    0
      src/pages/ForgotPasswordPage/ForgotPassword.styled.js
  19. 7
    2
      src/pages/ForgotPasswordPage/ForgotPasswordMailSent/MailSent.js
  20. 6
    0
      src/pages/ForgotPasswordPage/ForgotPasswordMailSent/MailSent.styled.js
  21. 3
    5
      src/pages/ForgotPasswordPage/ForgotPasswordPageMUI.js
  22. 0
    1
      src/pages/HomePage/HomePageMUI.js
  23. 6
    0
      src/pages/LoginPage/Login.styled.js
  24. 4
    1
      src/pages/RegisterPages/Register/FirstPart/FirstPartOfRegistration.js
  25. 8
    0
      src/pages/RegisterPages/Register/FirstPart/FirstPartOfRegistration.styled.js
  26. 11
    2
      src/pages/RegisterPages/Register/Register.js
  27. 25
    10
      src/pages/RegisterPages/Register/Register.styled.js
  28. 4
    0
      src/pages/RegisterPages/Register/SecondPart/SecondPartOfRegistration.js
  29. 7
    0
      src/pages/RegisterPages/Register/SecondPart/SecondPartOfRegistration.styled.js
  30. 3
    0
      src/pages/RegisterPages/Register/ThirdPart/ThirdPartOfRegistration.styled.js
  31. 6
    0
      src/pages/ResetPasswordPage/ResetPasswordPage.styled.js
  32. 5
    3
      src/request/forgotPasswordRequest.js
  33. 2
    1
      src/store/actions/offers/offersActionConstants.js
  34. 5
    1
      src/store/actions/offers/offersActions.js
  35. 8
    0
      src/store/reducers/offers/offersReducer.js
  36. 2
    3
      src/store/saga/forgotPasswordSaga.js
  37. 0
    2
      src/store/saga/loginSaga.js
  38. 4
    2
      src/store/saga/offersSaga.js
  39. 30
    29
      src/store/saga/registerSaga.js
  40. 1
    0
      src/themes/primaryTheme/primaryThemeColors.js

+ 7
- 0
src/assets/images/svg/coffee.svg 查看文件

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

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

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

+ 6
- 0
src/assets/images/svg/truck.svg 查看文件

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

+ 7
- 92
src/components/Cards/CreateOfferCard/CreateOffer.js 查看文件

import { NavLink } from "react-router-dom"; import { NavLink } from "react-router-dom";
import * as Yup from "yup"; import * as Yup from "yup";
import { useTranslation } from "react-i18next"; import { useTranslation } from "react-i18next";
import {
fetchUser,
} from "../../../store/actions/login/loginActions";
import { fetchUser } from "../../../store/actions/login/loginActions";
import { FORGOT_PASSWORD_PAGE, HOME_PAGE } from "../../../constants/pages"; import { FORGOT_PASSWORD_PAGE, HOME_PAGE } from "../../../constants/pages";
import { ReactComponent as VisibilityOn } from "../../../assets/images/svg/eye-striked.svg"; import { ReactComponent as VisibilityOn } from "../../../assets/images/svg/eye-striked.svg";
import { ReactComponent as VisibilityOff } from "../../../assets/images/svg/eye.svg"; import { ReactComponent as VisibilityOff } from "../../../assets/images/svg/eye.svg";
CreateOfferFormContainer, CreateOfferFormContainer,
RegisterAltText, RegisterAltText,
RegisterTextContainer, RegisterTextContainer,
FieldLabel,
} from "./CreateOffer.styled"; } from "./CreateOffer.styled";
import selectedTheme from "../../../themes"; import selectedTheme from "../../../themes";
import StepProgress from "../../StepProgress/StepProgress"; import StepProgress from "../../StepProgress/StepProgress";
import { Label } from "../../CheckBox/Label";
import FirstPartCreateOffer from "./FirstPart/FirstPartCreateOffer";


const CreateOffer = ({ history }) => { const CreateOffer = ({ history }) => {
const dispatch = useDispatch(); const dispatch = useDispatch();
); );
}; };


const formik = useFormik({
initialValues: {
nameOfProduct: "",
description: "",
},
validationSchema: Yup.object().shape({
nameOfProduct: Yup.string().required(t("login.nameOfProductRequired")),
description: Yup.string().required(t("login.descriptionRequired")).min(8),
}),
onSubmit: handleSubmit,
validateOnBlur: true,
enableReinitialize: true,
});

return ( return (
<CreateOfferContainer> <CreateOfferContainer>

<CreateOfferTitle component="h1" variant="h5"> <CreateOfferTitle component="h1" variant="h5">
Nova Objava Nova Objava
</CreateOfferTitle> </CreateOfferTitle>


<StepProgress current={1} numberOfSteps={3}/>

<CreateOfferFormContainer component="form" onSubmit={formik.handleSubmit}>
{/* <Backdrop position="absolute" isLoading={isLoading} /> */}

<TextField
name="nameOfProduct"
placeholder={"Naziv proizvoda..."}
italicPlaceholder
margin="normal"
value={formik.values.nameOfProduct}
onChange={formik.handleChange}
error={(formik.touched.nameOfProduct && formik.errors.nameOfProduct)}
helperText={formik.touched.nameOfProduct && formik.errors.nameOfProduct}
autoFocus
fullWidth
/>

<TextField
name="description"
placeholder={"Opis..."}
margin="normal"
italicPlaceholder
value={formik.values.description}
onChange={formik.handleChange}
error={(formik.touched.description && formik.errors.description)}
helperText={formik.touched.description && formik.errors.description}
fullWidth
multiline
minRows={4}
height={"100px"}
/>

<Link
to={FORGOT_PASSWORD_PAGE}
textsize="12px"
component={NavLink}
underline="hover"
align="right"
style={{ marginTop: "18px", marginBottom: "18px" }}
>
{t("login.forgotYourPassword")}
</Link>

<PrimaryButton
type="submit"
variant="contained"
height="48px"
fullWidth={true}
buttoncolor={selectedTheme.primaryPurple}
textcolor="white"
// disabled={
// formik.values.username.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>
</CreateOfferFormContainer>
<StepProgress current={1} numberOfSteps={3} />
<FirstPartCreateOffer />
</CreateOfferContainer> </CreateOfferContainer>
); );
}; };

+ 14
- 0
src/components/Cards/CreateOfferCard/CreateOffer.styled.js 查看文件

import { Box, Container, Typography } from "@mui/material"; import { Box, Container, Typography } from "@mui/material";
import styled from "styled-components"; import styled from "styled-components";
import selectedTheme from "../../../themes"; import selectedTheme from "../../../themes";
import { Label } from "../../CheckBox/Label";


export const CreateOfferContainer = styled(Container)` export const CreateOfferContainer = styled(Container)`
margin-top: 0px; margin-top: 0px;
export const CreateOfferFormContainer = styled(Box)` export const CreateOfferFormContainer = styled(Box)`
width: 335px; width: 335px;
height: 700px; height: 700px;
padding-top: 20px;
`; `;
export const RegisterAltText = styled(Typography)` export const RegisterAltText = styled(Typography)`
font-family: "Poppins"; font-family: "Poppins";
flex-direction: row; flex-direction: row;
margin-top: 36px; margin-top: 36px;
justify-content: center; justify-content: center;
`
export const FieldLabel = styled(Label)`
position: relative;
bottom: -14px;
& label {
font-size: 12px;
font-weight: 600;
line-height: 20px;
color: ${selectedTheme.primaryGrayText};
cursor: auto;
letter-spacing: 0.2px;
}
` `

+ 104
- 0
src/components/Cards/CreateOfferCard/FirstPart/FirstPartCreateOffer.js 查看文件

import React from 'react'
import PropTypes from 'prop-types'
import {useFormik} from "formik";
import { CreateOfferFormContainer, FieldLabel } from './FirstPartCreateOffer.styled'
import { TextField } from '../../../TextFields/TextField/TextField'
import { PrimaryButton } from '../../../Buttons/PrimaryButton/PrimaryButton'
import * as Yup from "yup"
import selectedTheme from '../../../../themes';
import { useTranslation } from 'react-i18next';
import Select from '../../../Select/Select';
import Option from '../../../Select/Option/Option';

const FirstPartCreateOffer = () => {
const {t} = useTranslation();
const handleSubmit = (values) => {
console.log(values)
}
const formik = useFormik({
initialValues: {
nameOfProduct: "",
description: "",
},
validationSchema: Yup.object().shape({
nameOfProduct: Yup.string().required(t("login.nameOfProductRequired")),
description: Yup.string().required(t("login.descriptionRequired")).min(8),
}),
onSubmit: handleSubmit,
validateOnBlur: true,
enableReinitialize: true,
});
return (
<CreateOfferFormContainer component="form" onSubmit={formik.handleSubmit}>
{/* <Backdrop position="absolute" isLoading={isLoading} /> */}

<FieldLabel
leftText={"NASLOV"}
/>
<TextField
name="nameOfProduct"
placeholder={"Naziv proizvoda..."}
italicPlaceholder
margin="normal"
value={formik.values.nameOfProduct}
onChange={formik.handleChange}
error={formik.touched.nameOfProduct && formik.errors.nameOfProduct}
helperText={
formik.touched.nameOfProduct && formik.errors.nameOfProduct
}
autoFocus
fullWidth
/>

<FieldLabel
leftText={"OPIS PROIZVODA"}
/>
<TextField
name="description"
placeholder={"Opis..."}
margin="normal"
italicPlaceholder
value={formik.values.description}
onChange={formik.handleChange}
error={formik.touched.description && formik.errors.description}
helperText={formik.touched.description && formik.errors.description}
fullWidth
multiline
minRows={4}
height={"100px"}
/>

<Select defaultValue={1}>
<Option value={1}>Opcija 1</Option>
<Option value={2}>Opcija 2</Option>
<Option value={3}>Opcija 3</Option>
<Option value={4}>Opcija 4</Option>

</Select>



<PrimaryButton
type="submit"
variant="contained"
height="48px"
fullWidth={true}
buttoncolor={selectedTheme.primaryPurple}
textcolor="white"
// disabled={
// formik.values.username.length === 0 ||
// formik.values.password.length === 0
// }
>
NASTAVI
</PrimaryButton>

</CreateOfferFormContainer>
)
}

FirstPartCreateOffer.propTypes = {
children: PropTypes.any,
}

export default FirstPartCreateOffer

+ 50
- 0
src/components/Cards/CreateOfferCard/FirstPart/FirstPartCreateOffer.styled.js 查看文件

import { Box, Typography } from "@mui/material";
import styled from "styled-components";
import selectedTheme from "../../../../themes";
import { Label } from "../../../CheckBox/Label";

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: 700px;
padding-top: 20px;
`;
export const FieldLabel = styled(Label)`
position: relative;
bottom: -14px;
& label {
font-size: 12px;
font-weight: 600;
line-height: 20px;
color: ${selectedTheme.primaryGrayText};
cursor: auto;
letter-spacing: 0.2px;
}
`

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



const OfferCard = (props) => { const OfferCard = (props) => {
return ( return (
<OfferCardContainer sponsored={props.sponsored.toString()} halfwidth={props.halfwidth ? 1 : 0}>
<OfferImage>{props.image}</OfferImage>
<OfferCardContainer sponsored={props.offer.pinned.toString()} halfwidth={props.halfwidth ? 1 : 0}>
<OfferImage src={props.offer.images[0]}></OfferImage>
<OfferInfo> <OfferInfo>
<OfferTitle>{props.title}</OfferTitle> <OfferTitle>{props.title}</OfferTitle>
<OfferAuthor> <OfferAuthor>
<DetailIcon color="black" component="span" size="16px"> <DetailIcon color="black" component="span" size="16px">
<Eye width={"12px"} height={"11px"} /> <Eye width={"12px"} height={"11px"} />
</DetailIcon> </DetailIcon>
<DetailText>{props.numberOfViews} pregleda</DetailText>
<DetailText>{props.offer.views.viewers.length} pregleda</DetailText>
</OfferViews> </OfferViews>
</OfferDetails> </OfferDetails>
</OfferInfo> </OfferInfo>
numberOfViews: PropTypes.number, numberOfViews: PropTypes.number,
halfwidth: PropTypes.bool, halfwidth: PropTypes.bool,
sponsored: PropTypes.bool, sponsored: PropTypes.bool,
offer: PropTypes.any,
}; };
OfferCard.defaultProps = { OfferCard.defaultProps = {
halfwidth: false, halfwidth: false,

+ 1
- 1
src/components/Cards/OfferCard/OfferCard.styled.js 查看文件

height: 180px; height: 180px;
position: relative; position: relative;
`; `;
export const OfferImage = styled(Box)``;
export const OfferImage = styled.img``;
export const OfferInfo = styled(Box)` export const OfferInfo = styled(Box)`
display: flex; display: flex;
flex: 2; flex: 2;

+ 11
- 2
src/components/CheckBox/Label.js 查看文件



export const Label = (props) => { export const Label = (props) => {
return ( 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>} {props.rightText && <RightLabel>{props.rightText}</RightLabel>}
</LabelContainer> </LabelContainer>
); );
leftText: PropTypes.string, leftText: PropTypes.string,
rightText: PropTypes.oneOfType([PropTypes.number, PropTypes.string]), rightText: PropTypes.oneOfType([PropTypes.number, PropTypes.string]),
maxWidth: PropTypes.string, maxWidth: PropTypes.string,
leftTextStyle: PropTypes.any,
rightTextStyle: PropTypes.any,
containerStyle: PropTypes.any,
className: PropTypes.any,
}; };

+ 11
- 9
src/components/MarketPlace/Offers/Offers.js 查看文件

import React from "react";
import React, { useEffect } from "react";
import PropTypes from "prop-types"; import PropTypes from "prop-types";
import { OffersContainer } from "./Offers.styled"; import { OffersContainer } from "./Offers.styled";
import OfferCard from "../../Cards/OfferCard/OfferCard"; import OfferCard from "../../Cards/OfferCard/OfferCard";
import MockupdataOffers from "../MockupdataOffers";
import { fetchOffers } from "../../../store/actions/offers/offersActions";
import { useDispatch, useSelector } from "react-redux";
import { selectOffers } from "../../../store/selectors/offersSelectors";
// import { fetchOffers } from "../../../store/actions/offers/offersActions"; // import { fetchOffers } from "../../../store/actions/offers/offersActions";
// import { useDispatch, useSelector } from "react-redux"; // import { useDispatch, useSelector } from "react-redux";
// import { selectOffers } from "../../../store/selectors/offersSelectors"; // import { selectOffers } from "../../../store/selectors/offersSelectors";


// Market place nije zavrsen // Market place nije zavrsen
// Koriste se Mockup podaci // Koriste se Mockup podaci
// const dispatch = useDispatch();
// const offers = useSelector(selectOffers);
const dispatch = useDispatch();
const offers = useSelector(selectOffers);


// useEffect(() => {
// dispatch(fetchOffers());
// }, [])
useEffect(() => {
dispatch(fetchOffers());
}, [])


return ( return (
<OffersContainer> <OffersContainer>
{MockupdataOffers.map((item) => {
return <OfferCard {...item} key={item.id} halfwidth={props.isGrid} />;
{offers.map((item) => {
return <OfferCard key={item._id} offer={item} halfwidth={props.isGrid} />;
})} })}
</OffersContainer> </OffersContainer>
); );

+ 27
- 0
src/components/Select/Option/Option.js 查看文件

import React from 'react'
import PropTypes from 'prop-types'
import { OptionIcon, OptionStyled } from './Option.styled'

const Option = props => {
console.log(props)
return (
<OptionStyled {...props}>
{props.startIcon ? (
<OptionIcon color={props.color}>
{props.startIcon}
</OptionIcon>
) :(<>

</>)}
{props.children}
</OptionStyled>
)
}

Option.propTypes = {
children: PropTypes.node,
color: PropTypes.any,
startIcon: PropTypes.any,
}

export default Option

+ 13
- 0
src/components/Select/Option/Option.styled.js 查看文件

import { Box, MenuItem } from "@mui/material";
import styled from "styled-components";
import selectedTheme from "../../../themes";

export const OptionStyled = styled(MenuItem)`
background-color: ${props => props.selected ? selectedTheme.primaryPurple : "white"} !important;
color: ${props => props.selected ? "white" : selectedTheme.selectOptionTextColor};
&:hover {
background-color: ${selectedTheme.primaryPurple} !important;
}
`
export const OptionIcon = styled(Box)`
`

+ 35
- 0
src/components/Select/Select.js 查看文件

import React from "react";
import PropTypes from "prop-types";
import { SelectIcon, SelectStyled } from "./Select.styled";
import { ReactComponent as Down } from "../../assets/images/svg/down-arrow.svg";

// import {Select as SelectMUI} from "@mui/material";

const Select = (props) => {
console.log(props);
return (
<SelectStyled
defaultValue={props.defaultValue}
fullWidth={props.fullwidth}
IconComponent={(iconProps) => (
<SelectIcon {...iconProps}>
<Down />
</SelectIcon>
)}
>
{props.children}
</SelectStyled>
);
};

Select.propTypes = {
children: PropTypes.node,
width: PropTypes.string,
fullwidth: PropTypes.bool,
defaultValue: PropTypes.number,
};
Select.defaultProps = {
fullwidth: true,
};

export default Select;

+ 12
- 0
src/components/Select/Select.styled.js 查看文件

import { Box, Select } from "@mui/material";
import styled from "styled-components";

export const SelectStyled = styled(Select)`
width: ${props => props.width};
height: ${props => props.height};
`
export const SelectIcon = styled(Box)`
position: relative;
top: 0px;
left: -15px;
`

+ 1
- 0
src/components/TextFields/TextField/TextField.js 查看文件

sx={props.style} sx={props.style}
label={props.showAnimation ? props.placeholder : ""} label={props.showAnimation ? props.placeholder : ""}
italicplaceholder={props.italicPlaceholder && isFieldEmpty} italicplaceholder={props.italicPlaceholder && isFieldEmpty}
ref={textInputRef} ref={textInputRef}
focused={props.focused} focused={props.focused}

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

padding: 0; padding: 0;
height: ${(props) => props.height}; height: ${(props) => props.height};
box-sizing: border-box; box-sizing: border-box;
overflow-y: hidden;


& div { & div {
padding-left: 2px; padding-left: 2px;
` `
padding: 10px 16px; padding: 10px 16px;
max-height: ${props.height}; max-height: ${props.height};
overflow-y: auto;
& fieldset {
border: 1px solid rgba(0, 0, 0, 0.23);
border-radius: 4px;
position: relative;
height: 100%;
& textarea {
height: 100% !important;
width: 100% ;
overflow: auto;
font-size: 16px;
} }
`} `}
} }
& div input { & div input {
height: ${(props) => props.height}; height: ${(props) => props.height};
box-sizing: border-box; box-sizing: border-box;

font-size: ${(props) => font-size: ${(props) =>
props.textsize ? props.textsize : "16px"} !important; props.textsize ? props.textsize : "16px"} !important;
font-family: ${(props) => (props.font ? props.font : "")}; font-family: ${(props) => (props.font ? props.font : "")};

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

display: flex; display: flex;
flex-direction: column; flex-direction: column;
align-items: center; align-items: center;
@media (max-height: 900px) {
margin-top: 160px;
}
@media (max-height: 800px) {
margin-top: 120px;
}
`; `;
export const ForgotPasswordTitle = styled(Typography)` export const ForgotPasswordTitle = styled(Typography)`
font-family: "Open Sans"; font-family: "Open Sans";

+ 7
- 2
src/pages/ForgotPasswordPage/ForgotPasswordMailSent/MailSent.js 查看文件

import React from "react";
import React, { useEffect, useState } from "react";
import PropTypes from "prop-types"; import PropTypes from "prop-types";
import { import {
MailSentContainer, MailSentContainer,
import { forgotPassword } from "../../../store/actions/user/userActions"; import { forgotPassword } from "../../../store/actions/user/userActions";


const MailSent = () => { const MailSent = () => {
const [mail, setEmail] = useState("");
const { t } = useTranslation(); const { t } = useTranslation();
const history = useHistory(); const history = useHistory();
const location = useLocation(); const location = useLocation();
const dispatch = useDispatch(); const dispatch = useDispatch();


useEffect(() => {
setEmail(location.state.email);
}, [])

const navigateLogin = () => { const navigateLogin = () => {
history.replace(LOGIN_PAGE); history.replace(LOGIN_PAGE);
}; };


const handleResend = () => { const handleResend = () => {
dispatch(forgotPassword(location.state.email))
dispatch(forgotPassword({email: mail}))
} }


return ( return (

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

display: flex; display: flex;
flex-direction: column; flex-direction: column;
align-items: center; align-items: center;
@media (max-height: 900px) {
margin-top: 200px;
}
@media (max-height: 800px) {
margin-top: 150px;
}
`; `;
export const Title = styled(Typography)` export const Title = styled(Typography)`
font-family: "Open Sans"; font-family: "Open Sans";

+ 3
- 5
src/pages/ForgotPasswordPage/ForgotPasswordPageMUI.js 查看文件

pathname: FORGOT_PASSWORD_MAIL_SENT, pathname: FORGOT_PASSWORD_MAIL_SENT,
state: {email: formik.values.email} state: {email: formik.values.email}
}); });
}
const handleResponseError = () => {
setEmailNotFoundStatus(true); setEmailNotFoundStatus(true);
} }
// const handleResponseError = () => {
// setEmailNotFoundStatus(true);
// console.log("greska!");
// }


const handleSubmit = (values) => { const handleSubmit = (values) => {
// validate email // validate email
dispatch(forgotPassword({email: values.email, handleResponseSuccess, handleResponseError: handleResponseSuccess}));
dispatch(forgotPassword({email: values.email, handleResponseSuccess, handleResponseError}));
}; };


const formik = useFormik({ const formik = useFormik({

+ 0
- 1
src/pages/HomePage/HomePageMUI.js 查看文件

(item) => item.string === queryObject.subcategory.toString() (item) => item.string === queryObject.subcategory.toString()
).id; ).id;
} }
console.log("iz useeffect: ", { category, subcategory, cities });
dispatch(setFilters({ category, subcategory, cities })); dispatch(setFilters({ category, subcategory, cities }));
}, [history.location.search]); }, [history.location.search]);
const handleCl = () => { const handleCl = () => {

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

display: flex; display: flex;
flex-direction: column; flex-direction: column;
align-items: center; align-items: center;
@media (max-height: 900px) {
margin-top: 110px;
}
@media (max-height: 800px) {
margin-top: 70px;
}
`; `;
export const LoginTitle = styled(Typography)` export const LoginTitle = styled(Typography)`
font-family: "Open Sans"; font-family: "Open Sans";

+ 4
- 1
src/pages/RegisterPages/Register/FirstPart/FirstPartOfRegistration.js 查看文件

import React, { useEffect, useState } from "react"; import React, { useEffect, useState } from "react";
import PropTypes from "prop-types"; import PropTypes from "prop-types";
import { import {
ErrorMessage,
FormContainer, FormContainer,
RegisterDescription, RegisterDescription,
} from "./FirstPartOfRegistration.styled"; } from "./FirstPartOfRegistration.styled";
const { t } = useTranslation(); const { t } = useTranslation();


useEffect(() => { useEffect(() => {
console.log(props.error);
if (props.error.length > 0) { if (props.error.length > 0) {
setEmailTakenStatus(true); setEmailTakenStatus(true);
} }
}} }}
/> />


{props.error && (<ErrorMessage>{props.errorMessage}</ErrorMessage>)}

<PrimaryButton <PrimaryButton
type="submit" type="submit"
variant="contained" variant="contained"
children: PropTypes.node, children: PropTypes.node,
handleSubmit: PropTypes.func, handleSubmit: PropTypes.func,
error: PropTypes.string, error: PropTypes.string,
errorMessage: PropTypes.string,
}; };


export default FirstPartOfRegistration; export default FirstPartOfRegistration;

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

margin-top: 31px; margin-top: 31px;
margin-bottom: 2px; margin-bottom: 2px;
letter-spacing: 0.02em; letter-spacing: 0.02em;
`; `;
export const ErrorMessage = styled(Typography)`
color: red;
font-family: "Open Sans";
position: relative;
top: -7px;
font-size: 14px;
`

+ 11
- 2
src/pages/RegisterPages/Register/Register.js 查看文件

const [currentStep, setCurrentStep] = useState(1); const [currentStep, setCurrentStep] = useState(1);
const [informations, setInformations] = useState({}); const [informations, setInformations] = useState({});
const [mailError, setMailError] = useState(""); const [mailError, setMailError] = useState("");
const [mailErrorMessage, setMailErrorMessage] = useState("");
const [PIBErrorMessage, setPIBErrorMessage] = useState("");
const [PIBError, setPIBError] = useState(""); const [PIBError, setPIBError] = useState("");


const handleResponseSuccess = () => { const handleResponseSuccess = () => {
}; };


const handleResponseError = (error) => { const handleResponseError = (error) => {
console.log("handleResponse: ", error);
if (error.type === "mail") { if (error.type === "mail") {
const { mail } = informations; const { mail } = informations;
setInformations({}); setInformations({});
setCurrentStep(1); setCurrentStep(1);
setMailError(mail); setMailError(mail);
if (error.error.response.data.toString() === 'User with email already exists') {
setMailErrorMessage("Vec postoji korisnik sa zadatim mail-om!");
} else {
setMailErrorMessage("Nevalidan format mail-a!")
}
} else { } else {
const { mail, password, PIB } = informations; const { mail, password, PIB } = informations;
setInformations({ mail, password }); setInformations({ mail, password });
setCurrentStep(2); setCurrentStep(2);
setPIBError(PIB.toString()); setPIBError(PIB.toString());
setPIBErrorMessage("PIB broj je zauzet!");
} }
}; };


setInformations({ ...informations, ...values }); setInformations({ ...informations, ...values });
}; };
return ( return (
<RegisterPageContainer>
<RegisterPageContainer currentStep={currentStep}>
<Logo /> <Logo />


<RegisterTitle component="h1" variant="h5"> <RegisterTitle component="h1" variant="h5">
<FirstPartOfRegistration <FirstPartOfRegistration
handleSubmit={handleSubmit} handleSubmit={handleSubmit}
error={mailError} error={mailError}
errorMessage={mailErrorMessage}
/> />
)} )}
{currentStep === 2 && ( {currentStep === 2 && (
<SecondPartOfRegistration <SecondPartOfRegistration
handleSubmit={handleSubmit} handleSubmit={handleSubmit}
error={PIBError} error={PIBError}
errorMessage={PIBErrorMessage}
/> />
)} )}
{currentStep === 3 && ( {currentStep === 3 && (

+ 25
- 10
src/pages/RegisterPages/Register/Register.styled.js 查看文件

align-items: center; align-items: center;
width: 335px; width: 335px;
padding: 0; 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)` export const RegisterTitle = styled(Typography)`
font-family: "Open Sans"; font-family: "Open Sans";
width: 328px; width: 328px;
height: 33px; height: 33px;
text-align: center; text-align: center;
flex: 1;
font-style: normal; font-style: normal;
font-weight: 400; font-weight: 400;
font-size: 24px; font-size: 24px;
line-height: 33px; line-height: 33px;
color: ${selectedTheme.primaryPurple}; color: ${selectedTheme.primaryPurple};
margin-top: 34px; margin-top: 34px;
@media (max-height: 800px) {
margin-top: 26px;
}
`; `;
export const RegisterDescription = styled(Typography)` export const RegisterDescription = styled(Typography)`
font-family: "Open Sans"; font-family: "Open Sans";
text-align: center; text-align: center;
color: ${selectedTheme.primaryGrayText}; color: ${selectedTheme.primaryGrayText};
margin-bottom: 20px; margin-bottom: 20px;
@media (max-height: 800px) {
margin-bottom: 14px;
margin-top: 6px;
}
`; `;
export const FormContainer = styled(Box)` export const FormContainer = styled(Box)`
width: 335px; width: 335px;
flex-direction: row; flex-direction: row;
margin-top: 36px; margin-top: 36px;
justify-content: center; justify-content: center;
@media (max-height: 800px) {
margin-top: 26px;
}
` `
export const ProgressContainer = styled(Container)` export const ProgressContainer = styled(Container)`
width: 100%; width: 100%;
width: 100%; width: 100%;
flex-direction: row; flex-direction: row;
justify-content: center; justify-content: center;
@media (max-height: 800px) {
bottom: 10px;
}
` `
export const FooterText = styled(Typography)` export const FooterText = styled(Typography)`
font-family: "Open Sans"; font-family: "Open Sans";
padding: 0; padding: 0;
font-size: 12px; font-size: 12px;
` `
export const RegisterDescriptionPart = styled(RegisterDescription)`
font-size: 12px;
width: 100%;
text-align: left;
line-height: 16px;
margin-top: 31px;
margin-bottom: 2px;
letter-spacing: 0.02em;
`

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

import React, { useEffect, useState } from "react"; import React, { useEffect, useState } from "react";
import PropTypes from "prop-types"; import PropTypes from "prop-types";
import { import {
ErrorMessage,
FormContainer, FormContainer,
RegisterDescription, RegisterDescription,
} from "./SecondPartOfRegistration.styled"; } from "./SecondPartOfRegistration.styled";
fullWidth={true} fullWidth={true}
/> />


{props.error && (<ErrorMessage>{props.errorMessage}</ErrorMessage>)}

<PrimaryButton <PrimaryButton
type="submit" type="submit"
variant="contained" variant="contained"
children: PropTypes.node, children: PropTypes.node,
handleSubmit: PropTypes.func, handleSubmit: PropTypes.func,
error: PropTypes.string, error: PropTypes.string,
errorMessage: PropTypes.string,
}; };


export default SecondPartOfRegistration; export default SecondPartOfRegistration;

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

margin-bottom: 2px; margin-bottom: 2px;
letter-spacing: 0.02em; letter-spacing: 0.02em;
`; `;
export const ErrorMessage = styled(Typography)`
color: red;
font-family: "Open Sans";
position: relative;
top: -7px;
font-size: 14px;
`

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

margin-top: 31px; margin-top: 31px;
margin-bottom: 2px; margin-bottom: 2px;
letter-spacing: 0.02em; letter-spacing: 0.02em;
@media (max-height: 800px) {
margin-top: 21px;
}
`; `;

+ 6
- 0
src/pages/ResetPasswordPage/ResetPasswordPage.styled.js 查看文件

display: flex; display: flex;
flex-direction: column; flex-direction: column;
align-items: center; align-items: center;
@media (max-height: 900px) {
margin-top: 140px;
}
@media (max-height: 800px) {
margin-top: 70px;
}
`; `;
export const ResetPasswordTitle = styled(Typography)` export const ResetPasswordTitle = styled(Typography)`
font-family: "Open Sans"; font-family: "Open Sans";

+ 5
- 3
src/request/forgotPasswordRequest.js 查看文件

import { postRequest } from ".";
import { postRequest, getRequest } from ".";
import apiEndpoints from "./apiEndpoints"; import apiEndpoints from "./apiEndpoints";


export const forgotPasswordRequest = (payload) =>
postRequest(apiEndpoints.accounts.forgotPassword, payload);
export const forgotPasswordRequest = (payload) => {
const encodedString = encodeURIComponent(payload);
return getRequest(`${apiEndpoints.accounts.forgotPassword}` + '/' + `${encodedString}`);
}


export const resetPasswordRequest = (payload) => export const resetPasswordRequest = (payload) =>
postRequest(apiEndpoints.accounts.resetPassword, payload); postRequest(apiEndpoints.accounts.resetPassword, payload);

+ 2
- 1
src/store/actions/offers/offersActionConstants.js 查看文件

export const OFFERS_ERROR = createErrorType(OFFERS_SCOPE); export const OFFERS_ERROR = createErrorType(OFFERS_SCOPE);
export const OFFERS_CLEAR = createClearType(OFFERS_SCOPE); export const OFFERS_CLEAR = createClearType(OFFERS_SCOPE);


export const OFFERS_SET = "OFFERS_SET";
export const OFFERS_SET = "OFFERS_SET";
export const OFFERS_ADD = "OFFERS_ADD";

+ 5
- 1
src/store/actions/offers/offersActions.js 查看文件

import { OFFERS_CLEAR, OFFERS_ERROR, OFFERS_FETCH, OFFERS_SET, OFFERS_SUCCESS } from "./offersActionConstants";
import { OFFERS_ADD, OFFERS_CLEAR, OFFERS_ERROR, OFFERS_FETCH, OFFERS_SET, OFFERS_SUCCESS } from "./offersActionConstants";


export const fetchOffers = (payload) => ({ export const fetchOffers = (payload) => ({
type: OFFERS_FETCH, type: OFFERS_FETCH,
export const setOffers = (payload) => ({ export const setOffers = (payload) => ({
type: OFFERS_SET, type: OFFERS_SET,
payload, payload,
})
export const addOffers = (payload) => ({
type: OFFERS_ADD,
payload
}) })

+ 8
- 0
src/store/reducers/offers/offersReducer.js 查看文件

import { import {
OFFERS_ADD,
OFFERS_CLEAR, OFFERS_CLEAR,
OFFERS_ERROR, OFFERS_ERROR,
OFFERS_SET, OFFERS_SET,
[OFFERS_ERROR]: fetchOffersError, [OFFERS_ERROR]: fetchOffersError,
[OFFERS_CLEAR]: clearOffers, [OFFERS_CLEAR]: clearOffers,
[OFFERS_SET]: setOffers, [OFFERS_SET]: setOffers,
[OFFERS_ADD]: addOffers,
}, },
initialState initialState
); );
offers: action.payload, offers: action.payload,
}; };
} }
function addOffers(state, action) {
return {
...state,
offers: [...state.offers, ...action.payload]
}
}

+ 2
- 3
src/store/saga/forgotPasswordSaga.js 查看文件



function* forgotPassword({payload}) { function* forgotPassword({payload}) {
try { try {
const data = yield call(forgotPasswordRequest);
console.log(payload)
const data = yield call(forgotPasswordRequest, payload.email);
if (data) { if (data) {
if (payload.handleResponseSuccess) { if (payload.handleResponseSuccess) {
yield call(payload.handleResponseSuccess); yield call(payload.handleResponseSuccess);
} }
} }
catch(e) { catch(e) {
console.log(e);
if (payload.handleResponseError) { if (payload.handleResponseError) {
yield call(payload.handleResponseError); yield call(payload.handleResponseError);
} }
} }
} }
catch(e) { catch(e) {
console.log(e);
if (payload.handleResponseError) { if (payload.handleResponseError) {
yield call(payload.handleResponseError); yield call(payload.handleResponseError);
} }

+ 0
- 2
src/store/saga/loginSaga.js 查看文件

function* fetchUser({ payload }) { function* fetchUser({ payload }) {
try { try {
const { data } = yield call(attemptLogin, payload); const { data } = yield call(attemptLogin, payload);
console.log(data);
if (data.tokens) { if (data.tokens) {
const token = data.tokens[data.tokens.length - 1].token.toString(); const token = data.tokens[data.tokens.length - 1].token.toString();


// cemu sluzi? // cemu sluzi?
const user = jwt.decode(token); const user = jwt.decode(token);
console.log("userJWT: ", user);


yield call(authScopeSetHelper, JWT_TOKEN, token); yield call(authScopeSetHelper, JWT_TOKEN, token);
// yield call(authScopeSetHelper, JWT_REFRESH_TOKEN, data.JwtRefreshToken); // yield call(authScopeSetHelper, JWT_REFRESH_TOKEN, data.JwtRefreshToken);

+ 4
- 2
src/store/saga/offersSaga.js 查看文件

import { all, takeLatest, call } from "@redux-saga/core/effects";
import { all, takeLatest, call, put } from "@redux-saga/core/effects";
import { attemptFetchOffers } from "../../request/offersRequest"; import { attemptFetchOffers } from "../../request/offersRequest";
import { OFFERS_FETCH } from "../actions/offers/offersActionConstants"; import { OFFERS_FETCH } from "../actions/offers/offersActionConstants";
import { setOffers } from "../actions/offers/offersActions";


function* fetchOffers() { function* fetchOffers() {
try { try {
const data = yield call(attemptFetchOffers); const data = yield call(attemptFetchOffers);
console.log(data);
console.log(data.data.items)
yield put(setOffers(data.data.items))
} catch (e) { } catch (e) {
console.log(e); console.log(e);
} }

+ 30
- 29
src/store/saga/registerSaga.js 查看文件

import { attemptRegister } from "../../request/registerRequest"; import { attemptRegister } from "../../request/registerRequest";
import { REGISTER_USER_FETCH } from "../actions/register/registerActionConstants"; import { REGISTER_USER_FETCH } from "../actions/register/registerActionConstants";


function* fetchRegisterUser({payload}) {
function* fetchRegisterUser({ payload }) {
try { try {
console.log("payload: ", payload)


const requestData = { const requestData = {
email: payload.values.mail.toString(),
password: payload.values.password.toString(),
roles: [
{
role: "User"
}
],
company: {
name: payload.values.nameOfFirm.toString(),
PIB: payload.values.PIB.toString(),
contacts: {
telephone: payload.values.phoneNumber.toString(),
location: payload.values.location.toString(),
web: payload.values.website.toString()
}
}
}
console.log(requestData);
const data = yield call(attemptRegister, requestData);
console.log(data);
email: payload.values.mail.toString(),
password: payload.values.password.toString(),
roles: [
{
role: "User",
},
],
company: {
name: payload.values.nameOfFirm.toString(),
PIB: payload.values.PIB.toString(),
contacts: {
telephone: payload.values.phoneNumber.toString(),
location: payload.values.location.toString(),
web: payload.values.website.toString(),
},
},
};
yield call(attemptRegister, requestData);
if (payload.handleResponseSuccess) { if (payload.handleResponseSuccess) {
yield call(payload.handleResponseSuccess); yield call(payload.handleResponseSuccess);
} }
} catch (e) { } catch (e) {
console.log(e.response.data);
let type; let type;
if (e.response?.data?.toString() === 'User with email already exists') {
type = 'mail'
} else if (e.response?.data?.toString() === 'Company with PIB already exists') {
type = "PIB"
if (
e.response?.data?.toString() === "User with email already exists" ||
e.response?.data?.toString() === '"email" must be a valid email'
) {
type = "mail";
} else if (
e.response?.data?.toString() === "Company with PIB already exists"
) {
type = "PIB";
} }
const error = { const error = {
error: e, error: e,
type
}
type,
};
if (payload.handleResponseError) { if (payload.handleResponseError) {
yield call(payload.handleResponseError, error); yield call(payload.handleResponseError, error);
} }

+ 1
- 0
src/themes/primaryTheme/primaryThemeColors.js 查看文件

borderSponsoredColor: "#E5D0FF", borderSponsoredColor: "#E5D0FF",
backgroundSponsoredColor: "#F5EDFF", backgroundSponsoredColor: "#F5EDFF",
offerBackgroundColor: "#F5F5F5", offerBackgroundColor: "#F5F5F5",
selectOptionTextColor: "#1D1D1D",
primaryDarkText: "#505050", primaryDarkText: "#505050",
iconStrokeColor: "#8C8C8C" iconStrokeColor: "#8C8C8C"
} }

正在加载...
取消
保存