Bladeren bron

Finished minor bugs and connected with BE

feature/code-cleanup-joca
Djordje Mitrovic 3 jaren geleden
bovenliggende
commit
28b0da1a5f
52 gewijzigde bestanden met toevoegingen van 1512 en 623 verwijderingen
  1. 4
    0
      src/assets/images/svg/arrow-back.svg
  2. 4
    0
      src/assets/images/svg/close-modal.svg
  3. 37
    27
      src/components/Buttons/ArrowButton/ArrowButton.styled.js
  4. 131
    13
      src/components/Cards/CreateOfferCard/CreateOffer.js
  5. 78
    3
      src/components/Cards/CreateOfferCard/CreateOffer.styled.js
  6. 106
    37
      src/components/Cards/CreateOfferCard/FirstPart/FirstPartCreateOffer.js
  7. 11
    8
      src/components/Cards/CreateOfferCard/FirstPart/FirstPartCreateOffer.styled.js
  8. 69
    32
      src/components/Cards/CreateOfferCard/SecondPart/SecondPartCreateOffer.js
  9. 20
    28
      src/components/Cards/CreateOfferCard/SecondPart/SecondPartCreateOffer.styled.js
  10. 41
    0
      src/components/Cards/CreateOfferCard/ThirdPart/ThirdPartCreateOffer.js
  11. 12
    0
      src/components/Cards/CreateOfferCard/ThirdPart/ThirdPartCreateOffer.styled.js
  12. 5
    1
      src/components/Cards/FilterCard/FilterCard.js
  13. 13
    4
      src/components/Cards/FilterCard/FilterDropdown/Checkbox/FilterCheckboxDropdown.js
  14. 9
    1
      src/components/Cards/FilterCard/FilterDropdown/Radio/FilterRadioDropdown.js
  15. 80
    43
      src/components/Cards/ItemDetailsCard/ItemDetailsCard.js
  16. 75
    18
      src/components/Cards/ItemDetailsCard/ItemDetailsCard.styled.js
  17. 1
    0
      src/components/Cards/OfferCard/OfferCard.styled.js
  18. 27
    3
      src/components/Header/Header.js
  19. 6
    5
      src/components/ImagePicker/ImagePicker.styled.js
  20. 3
    3
      src/components/ItemDetails/ItemDetails.js
  21. 0
    1
      src/components/ItemDetails/ItemDetailsHeaderCard/ItemDetailsHeaderCard.js
  22. 23
    19
      src/components/MUI/BackdropComponent.js
  23. 160
    0
      src/components/MUI/NavbarComponent.js
  24. 1
    1
      src/components/Paging/Paging.styled.js
  25. 20
    15
      src/components/Popovers/HeaderPopover/HeaderPopover.js
  26. 63
    54
      src/components/Popovers/HeaderPopover/HeaderPopover.styled.js
  27. 9
    2
      src/components/Popovers/MyPosts/MyPosts.js
  28. 1
    0
      src/components/Popovers/MyProfile/MyProfile.js
  29. 25
    26
      src/components/Popovers/MyProfile/MyProfile.styled.js
  30. 0
    1
      src/components/ProfileCard/ProfileCard.js
  31. 59
    44
      src/components/Scroller/HorizontalScroller.styled.js
  32. 21
    23
      src/components/Select/Option/Option.js
  33. 10
    3
      src/components/StepProgress/StepProgress.styled.js
  34. 52
    11
      src/components/UserReviewsCard/UserReviewsCard.js
  35. 48
    2
      src/components/UserReviewsCard/UserReviewsCard.styled.js
  36. 39
    0
      src/components/UserReviewsCard/UserReviewsSkeleton/UserReviewsSkeleton.js
  37. 57
    0
      src/components/UserReviewsCard/UserReviewsSkeleton/UserReviewsSkeleton.styled.js
  38. 3
    0
      src/constants/stylesConstants.js
  39. 0
    10
      src/hooks/useQueryString.js
  40. 0
    1
      src/hooks/useSorting.js
  41. 24
    3
      src/i18n/resources/rs.js
  42. 7
    4
      src/layouts/ItemDetailsLayout/ItemDetailsLayout.js
  43. 26
    21
      src/layouts/ItemDetailsLayout/ItemDetailsLayout.styled.js
  44. 8
    19
      src/pages/ItemDetailsPage/ItemDetailsPageMUI.js
  45. 1
    13
      src/pages/ProfilePage/ProfilePage.js
  46. 7
    8
      src/pages/RegisterPages/Register/Register.js
  47. 107
    107
      src/request/apiEndpoints.js
  48. 1
    1
      src/request/index.js
  49. 0
    1
      src/request/offersRequest.js
  50. 3
    2
      src/store/middleware/accessTokensMiddleware.js
  51. 2
    3
      src/store/saga/offersSaga.js
  52. 3
    2
      src/themes/primaryTheme/primaryThemeColors.js

+ 4
- 0
src/assets/images/svg/arrow-back.svg Bestand weergeven

@@ -0,0 +1,4 @@
<svg width="24" height="24" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M19 12L5 12" stroke="#1D1D1D" stroke-width="1.6" stroke-linecap="round" stroke-linejoin="round"/>
<path d="M12 19L5 12L12 5" stroke="#1D1D1D" stroke-width="1.6" stroke-linecap="round" stroke-linejoin="round"/>
</svg>

+ 4
- 0
src/assets/images/svg/close-modal.svg Bestand weergeven

@@ -0,0 +1,4 @@
<svg width="24" height="24" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M18 6L6 18" stroke="#1D1D1D" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/>
<path d="M6 6L18 18" stroke="#1D1D1D" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/>
</svg>

+ 37
- 27
src/components/Buttons/ArrowButton/ArrowButton.styled.js Bestand weergeven

@@ -1,41 +1,45 @@
import IconButton from "../../IconButton/IconButton"
import {ReactComponent as DownArrow} from "../../../assets/images/svg/arrow-down.svg"
import IconButton from "../../IconButton/IconButton";
import { ReactComponent as DownArrow } from "../../../assets/images/svg/arrow-down.svg";
import styled from "styled-components";
import selectedTheme from "../../../themes";



export const ArrowIcon = styled(DownArrow)`
${props => props.side === 'left' && `
${(props) =>
props.side === "left" &&
`
transform: rotate(180deg);
`}
width: 18px;
height: 18px;
& path {
${props => props.disabled && `
width: 18px;
height: 18px;
& path {
${(props) =>
props.disabled &&
`
stroke: ${selectedTheme.iconStrokeDisabledColor}
`}
}
`
}
`;
export const ArrowContainer = styled(IconButton)`
border: 1px solid ${selectedTheme.primaryPurple};
border-radius: 100%;
min-width: 40px;
width: 40px;
height: 40px;
display: flex;
box-sizing: border-box;
cursor: pointer;
margin-top: auto;
margin-bottom: auto;
transition: 0.2s all ease;
&:hover {
border: 1px solid ${selectedTheme.primaryPurple};
border-radius: 100%;
min-width: 40px;
width: 40px;
height: 40px;
display: flex;
box-sizing: border-box;
cursor: pointer;
margin-top: auto;
margin-bottom: auto;
transition: 0.2s all ease;
&:hover {
background-color: ${selectedTheme.primaryPurple};
& svg path {
stroke: white;
stroke: white;
}
}
${props => props.disabled && `
}
${(props) =>
props.disabled &&
`
border 1px solid ${selectedTheme.iconStrokeDisabledColor};
&:hover {
background-color: inherit;
@@ -50,4 +54,10 @@ ${props => props.disabled && `
}
`}
`

@media screen and (max-width: 600px) {
min-width: 32px;
width: 32px;
height: 32px;
}
`;

+ 131
- 13
src/components/Cards/CreateOfferCard/CreateOffer.js Bestand weergeven

@@ -24,14 +24,24 @@ import {
RegisterAltText,
RegisterTextContainer,
FieldLabel,
ModalCreateOfferContainer,
ModalBackDrop,
ModalHeader,
BackIcon,
CloseIcon,
} from "./CreateOffer.styled";
import selectedTheme from "../../../themes";
import StepProgress from "../../StepProgress/StepProgress";
import { Label } from "../../CheckBox/Label";
import FirstPartCreateOffer from "./FirstPart/FirstPartCreateOffer";
import SecondPartCreateOffer from "./SecondPart/SecondPartCreateOffer";
import ThirdPartCreateOffer from "./ThirdPart/ThirdPartCreateOffer";
import { addOffer } from "../../../store/actions/offers/offersActions";
import { ReactComponent as ArrowBack } from "../../../assets/images/svg/arrow-back.svg";
import { ReactComponent as CloseButton } from "../../../assets/images/svg/close-modal.svg";
import BackdropComponent from "../../MUI/BackdropComponent";

const CreateOffer = ({ history }) => {
const CreateOffer = ({ history, closeCreateOfferModal }) => {
const dispatch = useDispatch();
const { t } = useTranslation();
const [informations, setInformations] = useState({});
@@ -39,6 +49,8 @@ const CreateOffer = ({ history }) => {
const [currentStep, setCurrentStep] = useState(1);
const handleClickShowPassword = () => setShowPassword(!showPassword);
const handleMouseDownPassword = () => setShowPassword(!showPassword);
const categories = useSelector((state) => state.categories.categories);


// When user refreshes page
// useEffect(() => {
@@ -76,21 +88,127 @@ const CreateOffer = ({ history }) => {
};

const handleNext = (values) => {
setInformations({...values});
setCurrentStep(prevState => prevState+1)
setInformations({ ...informations, ...values });
setCurrentStep((prevState) => prevState + 1);
};

const newImgs =
informations.images &&
informations.images
.filter((img) => img !== undefined)
.map((img) =>
img
.replace("data:image/jpg;base64,", "")
.replace("data:image/jpeg;base64,", "")
.replace("data:image/png;base64,", "")
);

let subcategories = [];
for (const element of categories) {
if (element.name === informations.category) {
subcategories = element.subcategories.map((item) => item.name);
}
}

const offerData = {
name: informations.nameOfProduct,
description: informations.description,
location: {
city: informations.location,
},
condition: informations.condition,
category: {
name: informations.category,
subcategories: subcategories,
},
subcategory: informations.subcategory,
images: newImgs,
};

const submitOffer = (values) => {
dispatch(addOffer(values));
};

const handleSubmitOffer = () => {
submitOffer(offerData);
closeCreateOfferModal(false);
};

const backButtonHandler = () => {
setCurrentStep((prevState) => prevState - 1);
};

const closeModalHandler = () => {
closeCreateOfferModal(false);
};

const goStepBack = (stepNumber) => {
setCurrentStep(stepNumber);
const {
category,
condition,
description,
images,
location,
nameOfProduct,
subcategory,
} = informations;
if (stepNumber === 1) {
setInformations({});
}
if (stepNumber === 2) {
setInformations({
category,
condition,
description,
location,
nameOfProduct,
subcategory,
});
}
};

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

<StepProgress current={currentStep} numberOfSteps={3} />
{currentStep === 1 && <FirstPartCreateOffer handleNext={handleNext}/>}
{currentStep === 2 && <SecondPartCreateOffer handleNext={handleNext} />}
</CreateOfferContainer>
<>
<BackdropComponent
isLoading
handleClose={closeModalHandler}
position="fixed"
/>
<ModalCreateOfferContainer currentStep={currentStep}>
<CreateOfferContainer currentStep={currentStep}>
<ModalHeader>
<BackIcon onClick={backButtonHandler}>
{currentStep !== 1 ? <ArrowBack /> : ""}
</BackIcon>
<CreateOfferTitle component="h1" variant="h5">
{currentStep === 3 ? "Pregled" : "Nova Objava"}
</CreateOfferTitle>
<CloseIcon onClick={closeModalHandler}>
<CloseButton />
</CloseIcon>
</ModalHeader>

<StepProgress
current={currentStep}
numberOfSteps={3}
functions={[() => goStepBack(1), () => goStepBack(2)]}
/>
{currentStep === 1 && (
<FirstPartCreateOffer handleNext={handleNext} />
)}
{currentStep === 2 && (
<SecondPartCreateOffer handleNext={handleNext} />
)}
{currentStep === 3 && (
<ThirdPartCreateOffer
handleSubmitOffer={handleSubmitOffer}
informations={informations}
/>
)}
</CreateOfferContainer>
</ModalCreateOfferContainer>
</>
);
};


+ 78
- 3
src/components/Cards/CreateOfferCard/CreateOffer.styled.js Bestand weergeven

@@ -4,17 +4,87 @@ import selectedTheme from "../../../themes";
import { Label } from "../../CheckBox/Label";
import Select from "../../Select/Select";

export const ModalCreateOfferContainer = styled(Box)`
background-color: #fff;
position: fixed;
overflow-y: auto;
max-height: 90vh;
top: ${(props) =>
props.currentStep === 1 ? "calc(50% - 345px);" : "calc(50% - 350px);"};
left: ${(props) =>
props.currentStep !== 3 ? "calc(50% - 310px);" : "calc(50% - 340px);"};
z-index: 150;
padding: ${(props) => (props.currentStep !== 3 ? "0 120px" : "0 130px")};
&::-webkit-scrollbar {
width: 5px;
}
&::-webkit-scrollbar-track {
background: #ddd;
}
&::-webkit-scrollbar-thumb {
background: #777;
}
scrollbar-width: thin;
scrollbar-color: #ddd;

@media screen and (max-width: 628px) {
height: 740px;
width: 95%;
left: 10px;
padding: 0 30px;
top: 70px;
}
`;

export const ModalHeader = styled(Box)`
display: flex;
justify-content: space-between;
align-items: center;
`;

export const BackIcon = styled(Box)`
cursor: pointer;
position: absolute;
left: 40px;

@media screen and (max-width: 600px) {
left: 20px;

& svg {
width: 20px;
}
}
`;

export const CloseIcon = styled(Box)`
cursor: pointer;
position: absolute;
right: 40px;

@media screen and (max-width: 600px) {
right: 20px;

& svg {
width: 20px;
}
}
`;

export const CreateOfferContainer = styled(Container)`
margin-top: 0px;
display: flex;
width: 380px;
width: ${props => props.currentStep === 3 ? "580px" : "380px"};
flex-direction: column;
align-items: center;

@media screen and (max-width: 600px) {
width: 95%;
}
`;
export const CreateOfferTitle = styled(Typography)`
font-family: "Open Sans";
width: 328px;
height: 33px;
/* width: 328px;
height: 33px; */
text-align: center;
flex: 1;
font-style: normal;
@@ -24,6 +94,11 @@ export const CreateOfferTitle = styled(Typography)`
color: ${selectedTheme.primaryPurple};
margin-top: 36px;
margin-bottom: 40px;

@media screen and (max-width: 600px) {
font-size: 18px;
margin-bottom: 30px;
}
`;
export const CreateOfferDescription = styled(Typography)`
font-family: "Open Sans";

+ 106
- 37
src/components/Cards/CreateOfferCard/FirstPart/FirstPartCreateOffer.js Bestand weergeven

@@ -1,4 +1,4 @@
import React from "react";
import React, { useState } from "react";
import PropTypes from "prop-types";
import { useFormik } from "formik";
import {
@@ -13,8 +13,16 @@ import selectedTheme from "../../../../themes";
import { useTranslation } from "react-i18next";
import Option from "../../../Select/Option/Option";
import { SelectField } from "../CreateOffer.styled";
import { useSelector } from "react-redux";
import useScreenDimensions from "../../../../hooks/useScreenDimensions";

const FirstPartCreateOffer = (props) => {
const [subcat, setSubcat] = useState([{}]);
const locations = useSelector((state) => state.locations.locations);
const categories = useSelector((state) => state.categories.categories);
const dimensions = useScreenDimensions();


const { t } = useTranslation();
const handleSubmit = (values) => {
props.handleNext(values);
@@ -23,23 +31,37 @@ const FirstPartCreateOffer = (props) => {
initialValues: {
nameOfProduct: "",
description: "",
location: "",
category: "",
subcategory: "",
},
validationSchema: Yup.object().shape({
nameOfProduct: Yup.string().required(t("login.nameOfProductRequired")),
description: Yup.string().required(t("login.descriptionRequired")).min(8),
location: Yup.string().oneOf(locations.map((l) => l.city)),
category: Yup.string().oneOf(categories.map((c) => c.name)),
// subcategory: Yup.string().oneOf(
// subcat[0]?.subcategories ? subcat[0].subcategories : []
// ),
}),
onSubmit: handleSubmit,
validateOnBlur: true,
enableReinitialize: true,
});

const handleSubcategories = (category) => {
const filtered = categories.filter((cat) => cat.name === category);
setSubcat(filtered);
};

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

<FieldLabel leftText={"NASLOV"} />
<FieldLabel leftText={t("offer.title")} />
<TitleField
name="nameOfProduct"
placeholder={"Naziv proizvoda..."}
placeholder={t("offer.productName")}
italicPlaceholder
margin="normal"
value={formik.values.nameOfProduct}
@@ -50,44 +72,91 @@ const FirstPartCreateOffer = (props) => {
fullWidth
/>

<FieldLabel leftText={"OPIS PROIZVODA"} />
<DescriptionField
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"}
/>
<FieldLabel leftText={t("offer.productDescription")} />
{dimensions.width > 600 ? (
<DescriptionField
name="description"
placeholder={t("offer.description")}
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"}
/>
) : (
<DescriptionField
name="description"
placeholder={t("offer.description")}
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
/>
)}

<FieldLabel leftText={"LOKACIJA"} />
<SelectField 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>
<FieldLabel leftText={t("offer.location")} />
<SelectField
defaultValue="default"
onChange={(value) => {
formik.setFieldValue("location", value.target.value.city);
}}
>
<Option value="default">{t("offer.choseLocation")}</Option>
{locations.map((loc) => {
return (
<Option key={loc._if} value={loc}>
{loc.city}
</Option>
);
})}
</SelectField>

<FieldLabel leftText={"KATEGORIJA"} />
<SelectField 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>
<FieldLabel leftText={t("offer.category")} />
<SelectField
defaultValue="default"
onChange={(value) => {
formik.setFieldValue("category", value.target.value.name);
}}
>
<Option value="default">{t("offer.choseCategory")}</Option>
{categories.map((cat, i) => {
return (
<Option
key={i}
value={cat}
onClick={() => handleSubcategories(cat.name)}
>
{cat.name}
</Option>
);
})}
</SelectField>

<FieldLabel leftText={"PODKATEGORIJA"} />
<SelectField 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>
<FieldLabel leftText={t("offer.subcategory")} />
<SelectField
defaultValue="default"
onChange={(value) => {
formik.setFieldValue("subcategory", value.target.value.name);
}}
>
<Option value="default">{t("offer.choseSubcategory")}</Option>
{subcat?.length > 0 &&
subcat[0]?.subcategories &&
subcat[0].subcategories.map((sub, i) => {
return (
<Option key={i} value={sub}>
{sub.name}
</Option>
);
})}
</SelectField>

<NextButton
@@ -102,7 +171,7 @@ const FirstPartCreateOffer = (props) => {
// formik.values.password.length === 0
// }
>
NASTAVI
{t("offer.continue")}
</NextButton>
</CreateOfferFormContainer>
);

+ 11
- 8
src/components/Cards/CreateOfferCard/FirstPart/FirstPartCreateOffer.styled.js Bestand weergeven

@@ -36,8 +36,7 @@ export const CreateOfferDescription = styled(Typography)`
`;
export const CreateOfferFormContainer = styled(Box)`
width: 335px;
height: 700px;
padding-top: 20px;
padding: 20px 0 35px 0;
`;
export const FieldLabel = styled(Label)`
position: relative;
@@ -50,13 +49,17 @@ export const FieldLabel = styled(Label)`
cursor: auto;
letter-spacing: 0.2px;
}
`
`;
export const DescriptionField = styled(TextField)`
margin-bottom: 4px;
`
export const TitleField = styled(TextField)`

`
`;
export const TitleField = styled(TextField)``;
export const NextButton = styled(PrimaryButton)`
margin-top: 16px;
`

@media screen and (max-width: 600px) {
width: 332px;
position: absolute;
bottom: 20px;
}
`;

+ 69
- 32
src/components/Cards/CreateOfferCard/SecondPart/SecondPartCreateOffer.js Bestand weergeven

@@ -4,18 +4,25 @@ import {
CreateOfferFormContainer,
FieldLabel,
Scroller,
// ImageListStyled,
SupportedFormats,
InputButtonContainer,
} from "./SecondPartCreateOffer.styled";
import ImagePicker from "../../../ImagePicker/ImagePicker";
// import Select from "../../../Select/Select";
import { useTranslation, Trans } from "react-i18next";
import Option from "../../../Select/Option/Option";
import { SelectAltText, SelectField, SelectText } from "../CreateOffer.styled";
import { NextButton } from "../FirstPart/FirstPartCreateOffer.styled";
import selectedTheme from "../../../../themes";
import { conditionSelectEnum } from "../../../../enums/conditionEnum";
import { useFormik } from "formik";
import * as Yup from "yup";

const SecondPartCreateOffer = () => {
const [images, setImages] = useState([null, null, null]); // 3 images
const numberOfImages = 3;

const SecondPartCreateOffer = (props) => {
const [images, setImages] = useState(
Array.apply(null, Array(numberOfImages)).map(() => {})
); // 3 images
const setImage = (index, image) => {
setImages((prevState) => {
let newState = [...prevState];
@@ -23,9 +30,30 @@ const SecondPartCreateOffer = () => {
return [...newState];
});
};
const { t } = useTranslation();

let imagesEmpty = 0;
images.forEach(item => {
if (item === null || item === undefined) imagesEmpty++;
})

const handleSubmit = (values) => {
props.handleNext(values);
};

const formik = useFormik({
initialValues: {
images: images,
condition: "",
},
validationSchema: Yup.object().shape({}),
onSubmit: handleSubmit,
validateOnBlur: true,
enableReinitialize: true,
});

return (
<CreateOfferFormContainer>
<CreateOfferFormContainer component="form" onSubmit={formik.handleSubmit}>
<Scroller>
{images.map((item, index) => (
<ImagePicker
@@ -33,43 +61,52 @@ const SecondPartCreateOffer = () => {
image={item}
setImage={(image) => setImage(index, image)}
deleteImage={() => setImage(index, null)}
showDeleteIcon
/>
))}
</Scroller>
<FieldLabel leftText="STANJE" />
<SelectField defaultValue={conditionSelectEnum.NEW.value}>
{Object.keys(conditionSelectEnum).map((key) => {
var item = conditionSelectEnum[key];
return (
<Option value={item.value} key={item.value}>
<SelectText>{item.mainText}</SelectText>
<SelectAltText>{item.altText}</SelectAltText>
</Option>
);
})}
</SelectField>
<SupportedFormats>
<Trans i18nKey="offer.supportedImagesFormats" />
</SupportedFormats>
<InputButtonContainer>
<FieldLabel leftText={t("offer.condition")} />
<SelectField
defaultValue="default"
onChange={(value) => {
formik.setFieldValue("condition", value.target.value);
}}
>
<Option value="default">{t("offer.choseCondition")}</Option>
{Object.keys(conditionSelectEnum).map((key) => {
var item = conditionSelectEnum[key];
return (
<Option value={item.mainText} key={item.value}>
<SelectText>{item.mainText}</SelectText>
<SelectAltText>{item.altText}</SelectAltText>
</Option>
);
})}
</SelectField>

<NextButton
type="submit"
variant="contained"
height="48px"
fullWidth
buttoncolor={selectedTheme.primaryPurple}
textcolor="white"
// disabled={
// formik.values.username.length === 0 ||
// formik.values.password.length === 0
// }
>
NASTAVI
</NextButton>
<NextButton
type="submit"
variant="contained"
height="48px"
fullWidth
buttoncolor={selectedTheme.primaryPurple}
textcolor="white"
disabled={imagesEmpty === numberOfImages}
>
{t("offer.continue")}
</NextButton>
</InputButtonContainer>
</CreateOfferFormContainer>
);
};

SecondPartCreateOffer.propTypes = {
children: PropTypes.node,
handleOffer: PropTypes.func,
handleNext: PropTypes.func,
};

export default SecondPartCreateOffer;

+ 20
- 28
src/components/Cards/CreateOfferCard/SecondPart/SecondPartCreateOffer.styled.js Bestand weergeven

@@ -1,29 +1,15 @@
import { Box, ImageList } from "@mui/material";
import { Box, Typography } from "@mui/material";
import styled from "styled-components";
import selectedTheme from "../../../../themes";
import { Label } from "../../../CheckBox/Label";
import HorizontalScroller from "../../../Scroller/HorizontalScroller";
import { ReactComponent as TrashIcon } from "../../../../assets/images/svg/trash.svg";

export const CreateOfferFormContainer = styled(Box)`
width: 350px;
height: 700px;
padding-top: 20px;
margin-top: 20px;
position: relative;
`;

export const ImageCard = styled.img`
width: 216px;
height: 144px;
display: flex;
flex-direction: row;
flex-wrap: nowrap;
`;
export const ImageListStyled = styled(ImageList)`
display: flex;
flex: 1;
overflow: hidden;
cursor: grab;
`;
export const FieldLabel = styled(Label)`
position: relative;
top: 12px;
@@ -36,19 +22,25 @@ export const FieldLabel = styled(Label)`
letter-spacing: 0.2px;
}
`;

export const InputButtonContainer = styled(Box)`
width: 332px;
margin: 25px auto;
display: flex;
flex-direction: column;
justify-content: center;
`;

export const Scroller = styled(HorizontalScroller)`
min-width: 640px;
min-width: 100%;
position: relative;
left: calc(-320px + 50%);
margin-bottom: 36px;
`;
export const Trash = styled(TrashIcon)`
cursor: pointer;
margin: auto;
width: 22px;
height: 22px;
& path {
stroke: white;
}

export const SupportedFormats = styled(Typography)`
font-size: 13px;
width: 100%;
text-align: center;
font-family: "Open Sans";
/* margin-top: 0px; */
`;

+ 41
- 0
src/components/Cards/CreateOfferCard/ThirdPart/ThirdPartCreateOffer.js Bestand weergeven

@@ -0,0 +1,41 @@
import React from "react";
import PropTypes from "prop-types";
import { CreateOfferFormContainer, PreviewCard } from "./ThirdPartCreateOffer.styled";

const ThirdPartCreateOffer = (props) => {
const offer = {
offer: {
category: {
name: props.informations.category,
},
subcategory: props.informations.subcategory,
condition: props.informations.condition,
_created: new Date().toString(),
images: props.informations.images.filter(item => item !== undefined),
name: props.informations.nameOfProduct,
description: props.informations.description
}
}
const handleSubmit = (e) => {
e.preventDefault();
props.handleSubmitOffer();
};

return (
<CreateOfferFormContainer component="form" onSubmit={handleSubmit}>
<PreviewCard
offer={offer}
showBarterButton={false}
showPublishButton
/>
</CreateOfferFormContainer>
);
};

ThirdPartCreateOffer.propTypes = {
children: PropTypes.any,
handleSubmitOffer: PropTypes.func,
informations: PropTypes.object,
};

export default ThirdPartCreateOffer;

+ 12
- 0
src/components/Cards/CreateOfferCard/ThirdPart/ThirdPartCreateOffer.styled.js Bestand weergeven

@@ -0,0 +1,12 @@
import { Box } from "@mui/material";
import styled from "styled-components";
import ItemDetailsCard from "../../ItemDetailsCard/ItemDetailsCard";

export const CreateOfferFormContainer = styled(Box)`
padding-top: 20px;
margin-top: 20px;
width:100%;
`;
export const PreviewCard = styled(ItemDetailsCard)`

`

+ 5
- 1
src/components/Cards/FilterCard/FilterCard.js Bestand weergeven

@@ -110,7 +110,11 @@ const FilterCard = (props) => {
<FilterCheckboxDropdown
searchPlaceholder={t("filters.location.placeholder")}
data={[...filters.locations]}
filters={[...filters.selectedLocations]}
filters={
filters?.selectedLocations?.length > 0
? [...filters.selectedLocations]
: []
}
icon={<Location />}
title={t("filters.location.title")}
setItemsSelected={filters.setSelectedLocations}

+ 13
- 4
src/components/Cards/FilterCard/FilterDropdown/Checkbox/FilterCheckboxDropdown.js Bestand weergeven

@@ -37,12 +37,20 @@ const FilterCheckboxDropdown = (props) => {
}
}, [toSearch]);


useEffect(() => {
if (props.filters?.length > 0) {
setIsOpened(true)
}
}, [props.filters])

const handleChange = (item) => {
console.log(item);
if (props.oneValueAllowed) {
props.setItemsSelected([item]);
} else {
if (props.filters.find(itemInList => itemInList.city.toString() === item.city.toString())) {
props.setItemsSelected([...props.filters.filter((p) => p.city.toString() !== item.city.toString())]);
if (props.filters.find(itemInList => itemInList?.city?.toString() === item?.city?.toString())) {
props.setItemsSelected([...props.filters.filter((p) => p?.city?.toString() !== item?.city?.toString())]);
} else {
props.setItemsSelected([...props.filters, item]);
}
@@ -71,6 +79,7 @@ const FilterCheckboxDropdown = (props) => {
toggleIconClosed={<DropdownDown />}
toggleIconOpened={<DropdownUp />}
fullWidth
open={isOpened}
setIsOpened={setIsOpened}
toggleIconStyles={{
backgroundColor: isOpened
@@ -83,7 +92,7 @@ const FilterCheckboxDropdown = (props) => {
{props.filters.map((item) => (
<SelectedItem key={item.city} onClick={() => handleDelete(item)}>
{
data.find((p) => p.city.toString() === item.city.toString())
data.find((p) => p?.city?.toString() === item?.city?.toString())
?.city
}
<Close style={{ position: "relative", top: "3px" }} />
@@ -124,7 +133,7 @@ const FilterCheckboxDropdown = (props) => {
value={item}
checked={props.filters.find(
(itemInList) =>
itemInList.city.toString() === item.city.toString()
itemInList?.city?.toString() === item?.city?.toString()
) ? true : false}
onChange={() => handleChange(item)}
fullWidth

+ 9
- 1
src/components/Cards/FilterCard/FilterDropdown/Radio/FilterRadioDropdown.js Bestand weergeven

@@ -34,6 +34,14 @@ const FilterRadioDropdown = (props) => {
}
}, [toSearch]);

useEffect(() => {
if (props.selected?._id !== 0 && props.selected !== null && props.selected !== undefined) {
setIsOpened(true);
}
}, [props.selected])

console.log(props.selected)

const handleClear = () => {
setToSearch("");
};
@@ -54,7 +62,7 @@ const FilterRadioDropdown = (props) => {
toggleIconClosed={<DropdownDown />}
toggleIconOpened={<DropdownUp />}
fullWidth
open={props.open}
open={isOpened}
disabled={props.disabled}
setIsOpened={handleOpen}
toggleIconStyles={{

+ 80
- 43
src/components/Cards/ItemDetailsCard/ItemDetailsCard.js Bestand weergeven

@@ -1,4 +1,4 @@
import React, { useEffect } from "react";
import React from "react";
import PropTypes from "prop-types";
import {
CheckButton,
@@ -16,76 +16,99 @@ import {
OfferDetails,
OfferImage,
Scroller,
PublishButtonContainer,
} from "./ItemDetailsCard.styled";
import { NextButton } from "../CreateOfferCard/FirstPart/FirstPartCreateOffer.styled";
import { ReactComponent as Category } from "../../../assets/images/svg/category.svg";
import { ReactComponent as Subcategory } from "../../../assets/images/svg/subcategory.svg";
import { ReactComponent as Quantity } from "../../../assets/images/svg/quantity.svg";
import { ReactComponent as Eye } from "../../../assets/images/svg/eye-striked.svg";
import selectedTheme from "../../../themes";


const ItemDetailsCard = (props) => {
const offer = props.offer;
const dateCreated = new Date(offer?.offer?._created);
const dayCreated = dateCreated.getDate() < 10 ? "0" + dateCreated.getDate() : dateCreated.getDate();
const monthCreated = dateCreated.getMonth() < 10 ? "0" + (dateCreated.getMonth() + 1) : (dateCreated.getMonth() + 1);
const dayCreated =
dateCreated.getDate() < 10
? "0" + dateCreated.getDate()
: dateCreated.getDate();
const monthCreated =
dateCreated.getMonth() < 10
? "0" + (dateCreated.getMonth() + 1)
: dateCreated.getMonth() + 1;
const yearCreated = dateCreated.getFullYear();
console.log(offer);
// console.log(new Date(props.offer.offer._created))

useEffect(() => {
console.log(props.offer);
},[props.offer]);
return (
<ItemDetailsCardContainer sponsored={props.sponsored.toString()} halfwidth={props.halfwidth ? 1 : 0}>
<ItemDetailsCardContainer
sponsored={props.sponsored.toString()}
halfwidth={props.halfwidth ? 1 : 0}
className={props.className}
>
<OfferInfo>
<Info>
<InfoGroup>
<InfoIcon color={selectedTheme.iconStrokeColor} component="span" size="16px">
<InfoIcon
color={selectedTheme.iconStrokeColor}
component="span"
size="16px"
>
<Category width={"14px"} />
</InfoIcon>
<InfoText>{offer?.offer?.category?.name}</InfoText>
<InfoText>{offer?.offer?.category?.name}</InfoText>
</InfoGroup>
<InfoGroup>
<InfoIcon color={selectedTheme.iconStrokeColor} component="span" size="16px">
<InfoIcon
color={selectedTheme.iconStrokeColor}
component="span"
size="16px"
>
<Subcategory width={"14px"} />
</InfoIcon>
<InfoText>{offer?.offer?.subcategory}</InfoText>
</InfoGroup>
<InfoGroup>
<InfoIcon color={selectedTheme.iconStrokeColor} component="span" size="16px">
<Quantity width={"22px"} height={"16px"} />
</InfoIcon>
<InfoText>{offer?.offer?.condition}</InfoText>
<InfoText>{offer?.offer?.subcategory}</InfoText>
</InfoGroup>
<InfoGroup>
<InfoIcon color={"black"} component="span" size="12px" last>
<Eye width={"18px"} height={"20px"} />
<InfoIcon
color={selectedTheme.iconStrokeColor}
component="span"
size="16px"
>
<Quantity width={"22px"} height={"16px"} />
</InfoIcon>
<InfoText>{offer?.offer?.views?.viewers?.length}</InfoText>
<InfoText>{offer?.offer?.condition}</InfoText>
</InfoGroup>
{!props.showPublishButton && (
<InfoGroup views>
<InfoIcon color={"black"} component="span" size="12px" last>
<Eye width={"18px"} height={"20px"} />
</InfoIcon>
<InfoText>{offer?.offer?.views?.viewers?.length}</InfoText>
</InfoGroup>
)}
</Info>
<PostDate>Objavljeno: {dayCreated}.{monthCreated}.{yearCreated}</PostDate>
<PostDate>
{dayCreated}.{monthCreated}.{yearCreated}
</PostDate>
</OfferInfo>
<Details>
<Details hasScrollBar={!props.showPublishButton}>
<OfferTitle>{offer?.offer?.name}</OfferTitle>
<Scroller>
{offer?.offer?.images?.map(item => (
<OfferImage src={item} key={item} />
))}
{offer?.offer?.images?.map((item) => {
return <OfferImage src={item} key={item} />;
})}
</Scroller>
<OfferDetails>
<OfferDescriptionTitle>Opis:</OfferDescriptionTitle>
<OfferDescriptionText>{offer?.offer?.description}</OfferDescriptionText>
<OfferDescriptionText showBarterButton={props.showBarterButton}>
{offer?.offer?.description}
</OfferDescriptionText>
</OfferDetails>
</Details>
{!props.halfwidth ? (
{!props.halfwidth && !props.showPublishButton ? (
<React.Fragment>
<CheckButton
variant={props.sponsored ? "contained" : "outlined"}
buttoncolor={selectedTheme.primaryPurple}
textcolor={props.sponsored ? "white" : selectedTheme.primaryPurple}
style={{fontWeight: "600"}}
style={{ fontWeight: "600" }}
>
Trampi
</CheckButton>
@@ -93,16 +116,24 @@ const ItemDetailsCard = (props) => {
) : (
<></>
)}

{/* {props.image}
{props.title}
{props.description}
{props.category}
{props.author}
{props.location}
{props.quantity}
{props.package}
{props.numberOfViews} */}
{props.showPublishButton && (
<PublishButtonContainer>
<NextButton
type="submit"
variant="contained"
height="48px"
width="350px"
buttoncolor={selectedTheme.primaryPurple}
textcolor="white"
// disabled={
// formik.values.username.length === 0 ||
// formik.values.password.length === 0
// }
>
OBJAVI
</NextButton>
</PublishButtonContainer>
)}
</ItemDetailsCardContainer>
);
};
@@ -113,9 +144,12 @@ ItemDetailsCard.propTypes = {
title: PropTypes.string,
description: PropTypes.string,
category: PropTypes.string,
subcategory: PropTypes.string,
condition: PropTypes.string,
showNumberOfViews: PropTypes.bool,
author: PropTypes.string,
location: PropTypes.string,
image: PropTypes.node,
images: PropTypes.node,
quantity: PropTypes.number,
package: PropTypes.string,
numberOfViews: PropTypes.number,
@@ -134,6 +168,9 @@ ItemDetailsCard.propTypes = {
// city:PropTypes.string
// })
// })
showBarterButton: PropTypes.bool,
showPublishButton: PropTypes.bool,
className: PropTypes.string,
};
ItemDetailsCard.defaultProps = {
halfwidth: false,

+ 75
- 18
src/components/Cards/ItemDetailsCard/ItemDetailsCard.styled.js Bestand weergeven

@@ -21,12 +21,13 @@ export const ItemDetailsCardContainer = styled(Container)`
padding: 18px;
max-width: 2000px;
position: relative;
padding-bottom: 80px;
`;
export const OfferImage = styled.img`
width: 144px;
height: 144px;
border-radius: 4px;
width: 100%;
/* padding-bottom: 70px; */

@media (max-width: 600px) {
padding: 10px;
padding-bottom: 65px;
}
`;
export const OfferInfo = styled(Box)`
display: flex;
@@ -43,17 +44,23 @@ export const InfoGroup = styled(Box)`
flex-direction: row;
align-items: center;
gap: 4px;
@media (max-width: 600px) {
/* flex: 1; */
${(props) => props.last && `flex: none;`}
}
`;
export const PostDate = styled(Typography)`
font-family: "Open Sans";
font-size: 12px;
color: ${selectedTheme.primaryText};
&::before {
content: "Objavljeno: ";
@media (max-width: 600px) {
font-size: 9px;
font-family: "Open Sans";
}
}
@media (max-width: 600px) {
display: none;
position: absolute;
bottom: 23px;
left: 18px;
width: 70px;
}
`;
export const Info = styled(Box)`
@@ -64,6 +71,9 @@ export const Info = styled(Box)`
gap: 0;
justify-content: space-between;
margin-bottom: 15px;
max-width: 92%;
position: relative;
left: 5px;
}
`;
export const InfoIcon = styled(Box)`
@@ -83,9 +93,23 @@ export const OfferTitle = styled(Typography)`
color: ${selectedTheme.primaryPurple};
font-weight: 700;
font-size: 24px;
padding: 0 72px;
@media (max-width: 600px) {
padding: 0 60px;
@media screen and (max-width: 600px) {
padding: 0;
font-size: 18px;
}
`;
export const OfferImage = styled.img`
min-width: 144px;
min-height: 144px;
width: 144px;
height: 144px;
margin-right: 20px;
object-fit: cover;

@media screen and (max-width: 600px) {
min-width: 144px;
margin-right: 13px;
}
`;
export const OfferAuthor = styled(Box)`
@@ -110,7 +134,7 @@ export const OfferDetails = styled(Box)`
flex-direction: column;
flex-wrap: ${(props) => (!props.halfwidth ? "no-wrap" : "wrap")};
justify-content: space-between;
padding: 0 72px;
padding: 0 60px;
@media (max-width: 600px) {
padding: 0;
}
@@ -151,10 +175,18 @@ export const OfferDescriptionText = styled(Box)`
font-size: 16px;
color: ${selectedTheme.primaryDarkText};
line-height: 22px;
max-width: calc(100% - 30px);
max-width: calc(100% - 130px);
padding-bottom: 20px;
@media (max-width: 600px) {
font-size: 14px;
max-width: 100%;
}
/* max-width: calc(100% - 230px); */
max-width: ${(props) => props.showBarterButton && "calc(100% - 230px)"};
/* overflow: hidden; */
/* display: -webkit-box;
-webkit-line-clamp: 5;
-webkit-box-orient: vertical; */
`;
export const OfferDescription = styled(Box)`
flex: 3;
@@ -186,7 +218,7 @@ export const CheckButton = styled(PrimaryButton)`
height: 48px;
position: absolute;
bottom: 9px;
right: 9px;
right: 12px;
&:hover button {
background-color: ${selectedTheme.primaryPurple} !important;
color: white !important;
@@ -199,11 +231,36 @@ export const Details = styled(Box)`
display: flex;
flex-direction: column;
gap: 12px;
${(props) => props.hasScrollBar && `max-height: 400px;`}
overflow-y: auto;
overflow-x: hidden;
::-webkit-scrollbar {
width: 5px;
}
::-webkit-scrollbar-thumb {
background: #c4c4c4;
border-radius: 3px;
}

@media screen and (max-width: 600px) {
margin-top: 15px;
overflow: hidden;
max-height: none;
}
`;
// export const OfferImage = styled.img`
// `
export const Scroller = styled(HorizontalScroller)`
& div {
min-height: 144px;
min-width: 144px;
max-width: 100%;
/* & div {
margin: 0 9px;
}
} */
`;

export const PublishButtonContainer = styled(Box)`
display: flex;
justify-content: center;
margin-bottom: 30px;
`;

+ 1
- 0
src/components/Cards/OfferCard/OfferCard.styled.js Bestand weergeven

@@ -90,6 +90,7 @@ export const OfferTitle = styled(Typography)`
color: ${selectedTheme.primaryPurple};
font-weight: 700;
font-size: 24px;
width: calc(100% - 120px);
cursor: pointer;
@media (max-width: 550px) {
font-size: 18px;

+ 27
- 3
src/components/Header/Header.js Bestand weergeven

@@ -54,12 +54,14 @@ import FilterCard from "../Cards/FilterCard/FilterCard";
import { useQueryString } from "../../hooks/useQueryString";
import { convertQueryStringFrontend } from "../../util/helpers/queryHelpers";
import { fetchMineProfile } from "../../store/actions/profile/profileActions";
import CreateOffer from "../Cards/CreateOfferCard/CreateOffer";

const Header = () => {
const [openDrawer, setOpenDrawer] = useState(false);
const [openFilters, setOpenFilters] = useState(false);
const [showSearchBar, setShowSearchBar] = useState(true);
const [numberOfFilters, setNumberOfFilters] = useState(0);
const [showCreateOfferModal, setShowCreateOfferModal] = useState(false);
const { t } = useTranslation();
const theme = useTheme();
const searchRef = useRef(null);
@@ -111,6 +113,16 @@ const Header = () => {
}
});

const closeCreateOfferModal = () => {
setShowCreateOfferModal(false);
};

if (showCreateOfferModal) {
document.body.style.overflow = "hidden";
} else {
document.body.style.overflow = "auto";
}

const [postsPopoverOpen, setPostsPopoverOpen] = useState(false);
const [postsAnchorEl, setPostsAnchorEl] = useState(null);

@@ -140,6 +152,12 @@ const Header = () => {
setShouldShow(shouldShowHeader);
}, [location.pathname, user, routeMatch]);

useEffect(() => {
setUserPopoverOpen(false);
setMsgPopoverOpen(false);
setPostsPopoverOpen(false);
}, [location.pathname])

const handleToggleDrawer = () => {
setOpenDrawer(!openDrawer);
};
@@ -163,7 +181,9 @@ const Header = () => {
fullWidth
buttoncolor={selectedTheme.primaryYellow}
textcolor="black"
onClick={() => handleToggleDrawer()}
onClick={() => {
handleToggleDrawer();
}}
>
{t("header.addOffer")}
</PrimaryButton>
@@ -247,7 +267,6 @@ const Header = () => {
searchRef.current.removeEventListener("keyup", listener);
};
const handleSearch = (value) => {
console.log(value);
if (value.length === 0) return;
search.searchOffers(value);
};
@@ -270,7 +289,7 @@ const Header = () => {
elevation={0}
position="fixed"
// positionFixed
sx={{ backgroundColor: "white" }}
sx={{ backgroundColor: "white", zIndex: "80" }}
>
<Toolbar>
<ToolsContainer>
@@ -319,6 +338,7 @@ const Header = () => {
onClick={() => {
setUserPopoverOpen(false);
setUserAnchorEl(null);
setShowCreateOfferModal(true);
}}
>
{t("header.addOffer")}
@@ -464,12 +484,16 @@ const Header = () => {
responsiveOpen={openFilters}
closeResponsive={toggleFilters}
/>
{showCreateOfferModal && (
<CreateOffer closeCreateOfferModal={closeCreateOfferModal} />
)}
</HeaderContainer>
);
};

Header.propTypes = {
isGrid: PropTypes.bool,
showModalHandler: PropTypes.func,
};

export default Header;

+ 6
- 5
src/components/ImagePicker/ImagePicker.styled.js Bestand weergeven

@@ -63,8 +63,9 @@ export const AddFile = styled.input`
export const ImageUploaded = styled.img`
width: 144px;
height: 144px;
border-radius: 100px;
object-fit: scale-down;
/* border-radius: 100px; */
/* object-fit: scale-down; */
object-fit: cover;
z-index: 1;
`;
export const ImageOverlay = styled(Box)`
@@ -73,10 +74,10 @@ export const ImageOverlay = styled(Box)`
left: 0;
width: 100%;
height: 100%;
background-color: rgba(0,0,0,0.5);
background-color: rgba(0, 0, 0, 0.5);
z-index: 3;
overflow: hidden;
`
`;
export const Tooltip = styled(Box)`
background-color: rgba(255, 255, 255, 0.5);
width: 100px;
@@ -97,7 +98,7 @@ export const Trash = styled(TrashIcon)`
export const Tools = styled(Box)`
position: absolute;
padding-top: 44px;
padding-left: ${props => props.showDeleteIcon ? "16px" : "45px"};
padding-left: ${(props) => (props.showDeleteIcon ? "16px" : "45px")};
z-index: 4;
flex-direction: row;
display: flex;

+ 3
- 3
src/components/ItemDetails/ItemDetails.js Bestand weergeven

@@ -1,7 +1,7 @@
import React, { useMemo } from 'react';
import Header from "./Header/Header";
import { useSelector } from 'react-redux';
import { ItemDetailsContainer } from './ItemDetails.styled';
import { useSelector } from "react-redux";
import { ItemDetailsContainer } from "./ItemDetails.styled";
import ItemDetailsCard from "../Cards/ItemDetailsCard/ItemDetailsCard";
import ItemDetailsHeaderCard from "./ItemDetailsHeaderCard/ItemDetailsHeaderCard";
import { selectOffer } from '../../store/selectors/offersSelectors';
@@ -29,4 +29,4 @@ const ItemDetails = () => {
)
}

export default ItemDetails;
export default ItemDetails;

+ 0
- 1
src/components/ItemDetails/ItemDetailsHeaderCard/ItemDetailsHeaderCard.js Bestand weergeven

@@ -25,7 +25,6 @@ import { useHistory } from "react-router-dom";

const ItemDetailsHeaderCard = (props) => {
const history = useHistory();
console.log("header offer: ", props.offer);
const offer = props.offer;
if (!props.offer) {
return <div>Loading...</div>;

+ 23
- 19
src/components/MUI/BackdropComponent.js Bestand weergeven

@@ -1,26 +1,30 @@
import React from 'react';
import PropTypes from 'prop-types';
import { Backdrop, CircularProgress } from '@mui/material';
import { alpha } from '@mui/system';
import React from "react";
import PropTypes from "prop-types";
import { Backdrop } from "@mui/material";
// import { alpha } from "@mui/system";

const BackdropComponent = ({ position = 'fixed', isLoading }) => (
<Backdrop
sx={{
// 'fixed' takes whole page, 'absolute' takes whole space of the parent element which needs to have 'relative' position
position,
backgroundColor: ({ palette }) =>
alpha(palette.background.default, palette.action.disabledOpacity),
zIndex: ({ zIndex }) => zIndex.drawer + 1,
}}
open={isLoading}
>
<CircularProgress />
</Backdrop>
const BackdropComponent = ({ position = "fixed", isLoading, handleClose }) => (
<Backdrop
sx={{
// 'fixed' takes whole page, 'absolute' takes whole space of the parent element which needs to have 'relative' position
position,
// zIndex: ({ zIndex }) => zIndex.drawer + 1,
zIndex: 140,
}}
open={isLoading}
onClick={handleClose}
style={{
backgroundColor: "rgba(0,0,0,0.3)",
}}
>
{/* <CircularProgress /> */}
</Backdrop>
);

BackdropComponent.propTypes = {
position: PropTypes.oneOf(['fixed', 'absolute']),
isLoading: PropTypes.bool.isRequired,
position: PropTypes.oneOf(["fixed", "absolute"]),
isLoading: PropTypes.bool.isRequired,
handleClose: PropTypes.func,
};

export default BackdropComponent;

+ 160
- 0
src/components/MUI/NavbarComponent.js Bestand weergeven

@@ -0,0 +1,160 @@
import React, { useState, useMemo, useContext } from "react";
import {
AppBar,
Badge,
Box,
IconButton,
Toolbar,
Typography,
List,
ListItem,
ListItemButton,
ListItemIcon,
ListItemText,
useMediaQuery,
} from "@mui/material";
import { useTheme } from "@mui/system";
import MenuOutlinedIcon from "@mui/icons-material/MenuOutlined";
import ShoppingBasketIcon from "@mui/icons-material/ShoppingBasket";
import Brightness4Icon from "@mui/icons-material/Brightness4";
import Brightness7Icon from "@mui/icons-material/Brightness7";
import MenuList from "./MenuListComponent";
import Drawer from "./DrawerComponent";
import { ColorModeContext } from "../../context/ColorModeContext";

const NavbarComponent = () => {
const [openDrawer, setOpenDrawer] = useState(false);
const theme = useTheme();
const matches = useMediaQuery(theme.breakpoints.down("sm"));
const toggleColorMode = useContext(ColorModeContext);

const handleToggleDrawer = () => {
setOpenDrawer(!openDrawer);
};

const drawerContent = useMemo(
() => (
<List>
<ListItemButton divider onClick={handleToggleDrawer}>
<ListItemIcon>
<ListItemText>Link 1</ListItemText>
</ListItemIcon>
</ListItemButton>
<ListItem divider onClick={handleToggleDrawer}>
<ListItemIcon>
<ListItemText>Link 2</ListItemText>
</ListItemIcon>
</ListItem>
<ListItem divider onClick={handleToggleDrawer}>
<ListItemText>Link 3</ListItemText>
</ListItem>
<ListItem divider>
<IconButton onClick={toggleColorMode}>
<ListItemText>Toggle {theme.palette.mode} mode</ListItemText>
{theme.palette.mode === "dark" ? (
<Brightness7Icon />
) : (
<Brightness4Icon />
)}
</IconButton>
</ListItem>
</List>
),
[handleToggleDrawer]
);

return (
<AppBar
elevation={2}
sx={{ backgroundColor: "background.default", position: "relative" }}
>
<Toolbar>
<Box
component="div"
sx={{
display: "flex",
justifyContent: "space-between",
alignItems: "center",
width: "100%",
}}
>
{matches ? (
<Drawer
open={openDrawer}
toggleOpen={handleToggleDrawer}
content={drawerContent}
/>
) : (
<Box sx={{ display: "flex" }}>
<Typography
variant="h6"
sx={{
marginRight: 3,
cursor: "pointer",
color: "text.primary",
}}
>
Link 1
</Typography>
<Typography
variant="body1"
sx={{
marginRight: 3,
cursor: "pointer",
color: "text.primary",
}}
>
Link 2
</Typography>
<Typography
variant="subtitle1"
sx={{
marginRight: 3,
cursor: "pointer",
color: "text.primary",
}}
>
Link 3
</Typography>
</Box>
)}
<Box>
<MenuList />
</Box>
<Box
sx={{
display: "flex",
justifyContent: "center",
alignItems: "center",
}}
>
{matches ? (
<Box>
<IconButton onClick={handleToggleDrawer}>
<MenuOutlinedIcon />
</IconButton>
</Box>
) : (
<Box>
<IconButton>
<Badge badgeContent={3} color="primary">
<ShoppingBasketIcon color="action" />
</Badge>
</IconButton>
<IconButton sx={{ ml: 1 }} onClick={toggleColorMode}>
{theme.palette.mode === "dark" ? (
<Brightness7Icon />
) : (
<Brightness4Icon />
)}
</IconButton>
</Box>
)}
</Box>
</Box>
</Toolbar>
</AppBar>
);
};

export default NavbarComponent;

+ 1
- 1
src/components/Paging/Paging.styled.js Bestand weergeven

@@ -14,7 +14,7 @@ export const PagingContainer = styled(Box)`
margin-top: 5px;
margin-bottom: 10px;
position: absolute;
bottom: 0;
bottom: 15px;
padding-left: 0;
padding-right: 0;
margin: auto;

+ 20
- 15
src/components/Popovers/HeaderPopover/HeaderPopover.js Bestand weergeven

@@ -19,21 +19,26 @@ const HeaderPopover = (props) => {
<HeaderPopoverContainer>
<PopoverTitle p={2}>{props.title}</PopoverTitle>
<PopoverList>
{props.items?.length > 0 ? props.items.map((item, index) => (
<PopoverListItem key={index}>
<PopoverListItemAvatarContainer>
{props.isProfile ? (
<PopoverListItemProfileAvatar alt={item.alt} src={item.src} />
) : (
<PopoverListItemAvatar alt={item.alt} src={item.src} />
)}
</PopoverListItemAvatarContainer>
<PopoverListItemTextContainer
primary={item.title}
secondary={item.text}
></PopoverListItemTextContainer>
</PopoverListItem>
)) : (
{props.items?.length > 0 ? (
props.items.map((item, index) => (
<PopoverListItem key={index}>
<PopoverListItemAvatarContainer>
{props.isProfile ? (
<PopoverListItemProfileAvatar alt={item.alt} src={item.src} onClick={item?.onClick} />
) : (
<PopoverListItemAvatar alt={item.alt} src={item.src} onClick={item?.onClick} />
)}
</PopoverListItemAvatarContainer>
<PopoverListItemTextContainer
primaryTypographyProps={{
onClick: item.onClick
}}
primary={item.title}
secondary={item.text}
></PopoverListItemTextContainer>
</PopoverListItem>
))
) : (
<PopoverNoItemsText>No items at the moment...</PopoverNoItemsText>
)}
</PopoverList>

+ 63
- 54
src/components/Popovers/HeaderPopover/HeaderPopover.styled.js Bestand weergeven

@@ -1,70 +1,79 @@
import { Avatar, Box, Button, List, ListItem, ListItemAvatar, ListItemText, Typography } from "@mui/material";
import {
Avatar,
Box,
Button,
List,
ListItem,
ListItemAvatar,
ListItemText,
Typography,
} from "@mui/material";
import styled from "styled-components";
import selectedTheme from "../../../themes";
import { ReactComponent as Eye } from "../../../assets/images/svg/eye-striked.svg";
import { ProfileAvatar } from "../MyProfile/MyProfile.styled";


export const HeaderPopoverContainer = styled(Box)`
`
export const HeaderPopoverContainer = styled(Box)``;
export const PopoverTitle = styled(Typography)`
background-color: ${selectedTheme.primaryPurple};
color: white;
width: 100%;
min-width: 270px;
font-family: "Open Sans";
`
background-color: ${selectedTheme.primaryPurple};
color: white;
width: 100%;
min-width: 270px;
font-family: "Open Sans";
`;
export const PopoverList = styled(List)`
width: 100%;
max-width: 360px;
background-color: "white";
`
width: 100%;
max-width: 360px;
background-color: "white";
`;
export const PopoverListItem = styled(ListItem)`
align-items: flex-start;
`
align-items: flex-start;
`;
export const PopoverListItemAvatar = styled(Avatar)`
position: relative;
top: 4px;
`
position: relative;
cursor: pointer;
top: 4px;
`;
export const PopoverListItemProfileAvatar = styled(ProfileAvatar)`
`
export const PopoverListItemAvatarContainer = styled(ListItemAvatar)`
`
cursor: pointer;
`;
export const PopoverListItemAvatarContainer = styled(ListItemAvatar)``;
export const PopoverButton = styled(Button)`
text-decoration: underline;
color: ${selectedTheme.primaryPurple};
font-weight: 500;
text-align: right;
height: 20px;
`
text-decoration: underline;
color: ${selectedTheme.primaryPurple};
font-weight: 500;
text-align: right;
height: 20px;
`;
export const PopoverListItemTextContainer = styled(ListItemText)`
& span {
font-weight: 700;
color: ${selectedTheme.primaryPurple};
}
& p {
font-size: 0.81rem;
& svg {
position: relative;
top: 2px;
}
& span {
font-weight: 700;
color: ${selectedTheme.primaryPurple};
cursor: pointer;
}
& p {
font-size: 0.81rem;
& svg {
position: relative;
top: 2px;
}
`
}
`;
export const EyeIcon = styled(Eye)`
& path {
stroke: ${selectedTheme.primaryYellow};
}
`
& path {
stroke: ${selectedTheme.primaryYellow};
}
`;
export const PopoverButtonsContainer = styled(Box)`
flex-direction: column;
display: flex;
align-items: flex-end;
`
flex-direction: column;
display: flex;
align-items: flex-end;
`;
export const PopoverNoItemsText = styled(Typography)`
text-align: center;
width: 100%;
font-weight: 600;
padding-top: 5px;
font-size: 13px;
font-family: "Open Sans";
`
text-align: center;
width: 100%;
font-weight: 600;
padding-top: 5px;
font-size: 13px;
font-family: "Open Sans";
`;

+ 9
- 2
src/components/Popovers/MyPosts/MyPosts.js Bestand weergeven

@@ -21,17 +21,18 @@ import { useDispatch, useSelector } from "react-redux";
import { selectMineOffers } from "../../../store/selectors/offersSelectors";
import { fetchMineOffers } from "../../../store/actions/offers/offersActions";
import { selectProfileName } from "../../../store/selectors/profileSelectors";
import { useHistory } from "react-router-dom";

export const MyPosts = () => {
const { t } = useTranslation();
const dispatch = useDispatch();
const mineOffers = useSelector(selectMineOffers);
const name = useSelector(selectProfileName);
const history = useHistory();
const [arrayOfMineOffers, setArrayOfMineOffers] = useState([]);
useEffect(() => {
dispatch(fetchMineOffers());
}, []);
console.log("mineOffers: ", mineOffers)
useEffect(() => {
if (mineOffers?.length > 0) {
if (mineOffers.length > 1) {
@@ -40,6 +41,7 @@ export const MyPosts = () => {
alt: "Photo",
src: item.images[0],
title: item.name,
onClick: () => goToOffer(item._id),
text: (
<React.Fragment>
<PostsImgSuit /> {name}
@@ -53,6 +55,7 @@ export const MyPosts = () => {
alt: "Photo",
src: item.images[0],
title: item.name,
onClick: () => goToOffer(item._id),
text: (
<React.Fragment>
<PostsImgSuit /> {name}
@@ -61,10 +64,14 @@ export const MyPosts = () => {
}))
);
} else {
setArrayOfMineOffers([])
setArrayOfMineOffers([]);
}
}
}, [mineOffers]);

const goToOffer = (id) => {
history.push(`/proizvodi/${id}`)
}
return (
<HeaderPopover
title={t("header.myOffers")}

+ 1
- 0
src/components/Popovers/MyProfile/MyProfile.js Bestand weergeven

@@ -31,6 +31,7 @@ export const MyProfile = () => {
alt: "Profile",
src: `${profile.image}`,
title: profile.company.name,
onClick: () => seeMyProfile(),
text: (
<React.Fragment>
<ProfileImgPIB />

+ 25
- 26
src/components/Popovers/MyProfile/MyProfile.styled.js Bestand weergeven

@@ -1,34 +1,33 @@
import { TextField, Avatar } from "@mui/material";
import styled from "styled-components";
import PIB from '@mui/icons-material/AdminPanelSettingsOutlined';
import {ReactComponent as Logout} from "../../../assets/images/svg/log-out.svg";
import PIB from "@mui/icons-material/AdminPanelSettingsOutlined";
import { ReactComponent as Logout } from "../../../assets/images/svg/log-out.svg";

export const ProfileImgPIB = styled(PIB)`
width: 1rem;
height: 1rem;
margin-right: .36rem;
`
width: 1rem;
height: 1rem;
margin-right: 0.36rem;
`;

export const ProfileAvatar = styled(Avatar)`
width: 63px;
height: 63px;
margin-right: 1rem;
`
width: 63px;
height: 63px;
margin-right: 1rem;
`;

export const SearchInput = styled(TextField)`
margin-left: 3.8rem;
background-color: #F4F4F4;
width: 45%;
max-width: 100%;
@media (max-width: 1100px) {
width: 36%;
}
@media (max-width: 900px) {
width: 54%;
}
@media (max-width: 600px) {
width: 36%;
}
`
export const LogoutIcon = styled(Logout)`
`
margin-left: 3.8rem;
background-color: #f4f4f4;
width: 45%;
max-width: 100%;
@media (max-width: 1100px) {
width: 36%;
}
@media (max-width: 900px) {
width: 54%;
}
@media (max-width: 600px) {
width: 36%;
}
`;
export const LogoutIcon = styled(Logout)``;

+ 0
- 1
src/components/ProfileCard/ProfileCard.js Bestand weergeven

@@ -42,7 +42,6 @@ const ProfileCard = (props) => {
100
);
}
console.log(profile);
return (
<>
<ProfileCardContainer>

+ 59
- 44
src/components/Scroller/HorizontalScroller.styled.js Bestand weergeven

@@ -1,39 +1,50 @@
import { Box } from "@mui/material";
import styled from "styled-components";
import {ReactComponent as DownArrow} from "../../assets/images/svg/arrow-down.svg"
import { ReactComponent as DownArrow } from "../../assets/images/svg/arrow-down.svg";
import selectedTheme from "../../themes";
import ScrollContainer from 'react-indiana-drag-scroll'
import ScrollContainer from "react-indiana-drag-scroll";
import { IconButton } from "../Buttons/IconButton/IconButton";


export const HorizontalScrollerContainer = styled(Box)`
display: flex;
flex: 1;
flex-direction: row;
flex-wrap: nowrap;
overflow: hidden;
`
display: flex;
flex: 1;
flex-direction: row;
flex-wrap: nowrap;
overflow: hidden;
padding-right: 5px;

@media screen and (max-width: 600px) {
width: 100%;
}

@media screen and (max-width: 480px) {
width: 340px;
}
`;
export const Arrow = styled(IconButton)`
border: 1px solid ${selectedTheme.primaryPurple};
border-radius: 100%;
min-width: 40px;
width: 40px;
height: 40px;
display: block;
box-sizing: border-box;
cursor: pointer;
padding-left: 8px;
padding-top: 10px;
margin-top: auto;
margin-bottom: auto;
transition: 0.2s all ease;
&:hover {
background-color: ${selectedTheme.primaryPurple};
& svg path {
stroke: white;
}
border: 1px solid ${selectedTheme.primaryPurple};
border-radius: 100%;
min-width: 40px;
width: 40px;
height: 40px;
display: block;
box-sizing: border-box;
cursor: pointer;
padding-left: 8px;
padding-top: 10px;
margin-top: auto;
margin-bottom: auto;
transition: 0.2s all ease;
&:hover {
background-color: ${selectedTheme.primaryPurple};
& svg path {
stroke: white;
}
${props => props.disabled && `
}

${(props) =>
props.disabled &&
`
border 1px solid ${selectedTheme.iconStrokeDisabledColor};
& svg path {
stroke: ${selectedTheme.iconStrokeDisabledColor};
@@ -41,25 +52,29 @@ export const Arrow = styled(IconButton)`
}
`}
`
`;
export const ListContainer = styled(ScrollContainer)`
display: flex;
flex: 1;
flex-direction: row;
flex-wrap: nowrap;
scroll-behavior: smooth;
margin: 0 18px;
user-select: none;
`
display: flex;
flex: 1;
flex-direction: row;
flex-wrap: nowrap;
scroll-behavior: smooth;
margin: 0 18px;
user-select: none;
`;
export const ArrowIcon = styled(DownArrow)`
${props => props.side === 'left' && `
${(props) =>
props.side === "left" &&
`
transform: rotate(180deg);
`}
width: 18px;
height: 18px;
& path {
${props => props.disabled && `
width: 18px;
height: 18px;
& path {
${(props) =>
props.disabled &&
`
stroke: ${selectedTheme.iconStrokeDisabledColor}
`}
}
`
}
`;

+ 21
- 23
src/components/Select/Option/Option.js Bestand weergeven

@@ -1,31 +1,29 @@
import React from 'react'
import PropTypes from 'prop-types'
import { OptionIcon, OptionStyled } from './Option.styled'
import React from "react";
import PropTypes from "prop-types";
import { OptionIcon, OptionStyled } from "./Option.styled";

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

</>)}
{props.children}
<OptionStyled {...props} value={props.value}>
{props.startIcon ? (
<OptionIcon color={props.color}>{props.startIcon}</OptionIcon>
) : (
<></>
)}
{props.children}
</OptionStyled>
)
}
);
};

Option.propTypes = {
children: PropTypes.node,
color: PropTypes.any,
startIcon: PropTypes.any,
value: PropTypes.any,
// selected: PropTypes.bool,
}
children: PropTypes.node,
color: PropTypes.any,
startIcon: PropTypes.any,
value: PropTypes.any,
// selected: PropTypes.bool,
};
Option.defaultProps = {
// selected: true
}
};

export default Option
export default Option;

+ 10
- 3
src/components/StepProgress/StepProgress.styled.js Bestand weergeven

@@ -9,6 +9,10 @@ export const StepProgressContainer = styled(Box)`
position: relative;
left: 2px;
width: 100%;

@media screen and (min-width: 468px) and (max-width: 600px) {
width: 80%;
}
`;

export const StepLine = styled(Box)`
@@ -22,12 +26,15 @@ export const StepLine = styled(Box)`
export const StepBar = styled(Box)`
flex: 0 0 35px;
background-color: ${(props) =>
props.done ? selectedTheme.primaryPurple : selectedTheme.primaryDarkGrayText};
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")};
${(props) =>
props.current || props.done ? selectedTheme.primaryPurple : "white"};
padding-top: 2px;
line-height: 19px;
margin-left: -2px;
@@ -35,7 +42,7 @@ export const StepBar = styled(Box)`
color: #1d1d1d;
z-index: 1;
transition: background-color 1s ease;
${props => props.done && `cursor: pointer;`}
${(props) => props.done && `cursor: pointer;`}
`;
export const Progress = styled(Box)`
height: 9px;

+ 52
- 11
src/components/UserReviewsCard/UserReviewsCard.js Bestand weergeven

@@ -1,6 +1,6 @@
import React from "react";
import React, { useMemo } from "react";
import PropTypes from "prop-types";
import { ReviewList, ReviewsBox, ThumbDown, ThumbUp } from "./UserReviewsCard.styled";
import { NoReviewsAltText, NoReviewsContainer, NoReviewsText, ReviewList, ReviewsBox, ReviewsHeader, ReviewsTitle, ThumbDown, ThumbUp } from "./UserReviewsCard.styled";

import {
Avatar,
@@ -10,20 +10,57 @@ import {
Typography,
Divider,
} from "@mui/material";
import Mockupdata from "./Mockupdata";
// import Mockupdata from "./Mockupdata";
import StarBorderIcon from "@mui/icons-material/StarBorder";
import selectedTheme from "../../themes";
import { useSelector } from "react-redux";
import { selectOffer } from "../../store/selectors/offersSelectors";
import { selectProfile } from "../../store/selectors/profileSelectors";
// import { selectUserId } from "../../store/selectors/loginSelectors";
import { useTranslation } from "react-i18next";
import UserReviewsSkeleton from "./UserReviewsSkeleton/UserReviewsSkeleton";
import useScreenDimensions from "../../hooks/useScreenDimensions";

const UserReviewsCard = (props) => {
var dataMockupdata = JSON.parse(JSON.stringify(Mockupdata));
const {t} = useTranslation();
// const userId = useSelector(selectUserId);
const offer = useSelector(selectOffer);
console.log("user reviews: ", offer);
const dimensions = useScreenDimensions();
const profile = useSelector(selectProfile);
console.log("offer Reviews: ", offer);
console.log("profile reviews: ", profile);
console.log("props.profileReviews: ", props.profileReviews);
// const profileId = useMemo(() => {
// if (props.profileReviews) {
// return profile._id;
// }
// return offer?.offer?.userId;
// }, [props.profileReviews, offer, profile])
// const isMyProfile = useMemo(() => {
// if (userId === profileId) return true;
// return false;
// }, [profileId, userId]);
const lastThreeReviews = useMemo(() => {
if (props.profileReviews) {
return [];
}
return offer?.companyData?.lastThreeReviews;
}, [props.profileReviews, offer, profile])

const NoReviews = () => {
return (
<NoReviewsContainer>
<NoReviewsText>{t("reviews.title")}</NoReviewsText>
<NoReviewsAltText>{t("reviews.altTitle")}</NoReviewsAltText>
<UserReviewsSkeleton numOfElements={dimensions.width < 600 ? 1 : 2} />
</NoReviewsContainer>
)
}

return (
<>
<ReviewsBox>
<Grid
<ReviewsHeader
container
direction="row"
justifyContent="start"
@@ -31,10 +68,10 @@ const UserReviewsCard = (props) => {
sx={{ mb: 1.4 }}
>
<StarBorderIcon color="action" sx={{ mr: 0.9 }} />
<Typography>{props.heading}</Typography>
</Grid>
<ReviewsTitle>Ocene</ReviewsTitle>
</ReviewsHeader>
<ReviewList>
{offer?.companyData?.lastThreeReviews?.map((review) => (
{lastThreeReviews?.length > 0 ? lastThreeReviews?.map((review) => (
<>
<ListItem
alignItems="flex-start"
@@ -81,13 +118,13 @@ const UserReviewsCard = (props) => {
Uspešna trampa: <b>{review.isSuccessfulSwap}</b>
</Typography>
</Grid>
{review.id < dataMockupdata.length - 1 ? (
{review.id < review?.length - 1 ? (
<Divider variant="inset" component="li" sx={{ ml: 0 }} />
) : (
<></>
)}
</>
))}
)) : (<NoReviews></NoReviews>)}
</ReviewList>
</ReviewsBox>
</>
@@ -97,6 +134,10 @@ const UserReviewsCard = (props) => {
UserReviewsCard.propTypes = {
children: PropTypes.node,
heading: PropTypes.string,
profileReviews: PropTypes.bool,
};
UserReviewsCard.defaultProps = {
profileReviews: false,
}

export default UserReviewsCard;

+ 48
- 2
src/components/UserReviewsCard/UserReviewsCard.styled.js Bestand weergeven

@@ -1,12 +1,37 @@
import styled from "styled-components";
import { List, Box } from "@mui/material";
import { List, Box, Typography, Grid } from "@mui/material";
import ThumbUpIcon from "@mui/icons-material/ThumbUp";
import ThumbDownIcon from "@mui/icons-material/ThumbDown";
import selectedTheme from "../../themes";

export const ReviewsBox = styled(Box)`
width: 100%;
height: calc(100% - 90px);
@media (max-width: 1200px) {
padding: 0 50px;
}
@media (max-width: 600px) {
position: relative;
top: -45px;
overflow: hidden;
height: 350px;
max-height: 350px;
padding: 0;
}
`;
export const ReviewsHeader = styled(Grid)`
@media (max-width: 800px) {
display: none;
}
`

export const ReviewsTitle = styled(Typography)`
font-family: "Open Sans";
font-size: 16px;
@media (max-width: 800px) {
display: none;
}
`

export const ReviewList = styled(List)`
background: white;
@@ -14,7 +39,9 @@ export const ReviewList = styled(List)`
border-radius: 4px 0 0 4px;
height: 100%;
width: 100%;
overflow-y: auto;
border: 1px solid ${selectedTheme.borderNormal};

/* overflow-y: auto; */
&::-webkit-scrollbar {
width: 5px;
}
@@ -36,3 +63,22 @@ export const ThumbDown = styled(ThumbDownIcon)`
position: relative;
left: -8px;
`
export const NoReviewsContainer = styled(Box)`
`
export const NoReviewsText = styled(Typography)`
color: ${selectedTheme.primaryPurple};
font-size: 24px;
font-family: "Open Sans";
text-align: center;
font-weight: 700;
width: 100%;
`
export const NoReviewsAltText = styled(Typography)`
font-size: 12px;
color: ${selectedTheme.primaryDarkText};
font-family: "Open Sans";
text-align: center;
width: 100%;
margin-bottom: 36px;
`

+ 39
- 0
src/components/UserReviewsCard/UserReviewsSkeleton/UserReviewsSkeleton.js Bestand weergeven

@@ -0,0 +1,39 @@
import React from 'react'
import PropTypes from 'prop-types'
import { UserReviewsSkeletonCircle, UserReviewsSkeletonContainer, UserReviewsSkeletonItemsContainer, UserReviewsSkeletonLine, UserReviewsSkeletonLineFifth, UserReviewsSkeletonLineForth, UserReviewsSkeletonLineOne, UserReviewsSkeletonLineSecond, UserReviewsSkeletonLineThird, UserReviewsSkeletonSquare } from './UserReviewsSkeleton.styled'

const UserReviewsSkeleton = (props) => {
const array = Array.apply(null, Array(props.numOfElements)).map(() => {})
return (
<UserReviewsSkeletonContainer>
{array.map((item, index) => (
<UserReviewsSkeletonItemsContainer key={index}>
<UserReviewsSkeletonLine>
<UserReviewsSkeletonCircle/>
<UserReviewsSkeletonLineOne />
</UserReviewsSkeletonLine>
<UserReviewsSkeletonLine>
<UserReviewsSkeletonSquare />
<UserReviewsSkeletonLineSecond />
</UserReviewsSkeletonLine>
<UserReviewsSkeletonLine>
<UserReviewsSkeletonLineThird />
</UserReviewsSkeletonLine>
<UserReviewsSkeletonLine>
<UserReviewsSkeletonLineForth />
</UserReviewsSkeletonLine>
<UserReviewsSkeletonLine>
<UserReviewsSkeletonLineFifth />
</UserReviewsSkeletonLine>
</UserReviewsSkeletonItemsContainer>
))}
</UserReviewsSkeletonContainer>
)
}

UserReviewsSkeleton.propTypes = {
children: PropTypes.node,
numOfElements: PropTypes.number,
}

export default UserReviewsSkeleton

+ 57
- 0
src/components/UserReviewsCard/UserReviewsSkeleton/UserReviewsSkeleton.styled.js Bestand weergeven

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

export const UserReviewsSkeletonContainer = styled(Box)`
width: 100%;
`
export const UserReviewsSkeletonItemsContainer = styled(Box)`
width: 100%;
padding: 36px;
`
export const UserReviewsSkeletonLine = styled(Box)`
display: flex;
flex-direction: row;
& * {
background-color: ${selectedTheme.skeletonItemColor};
}
`
export const UserReviewsSkeletonCircle = styled(Box)`
width: 54px;
height: 54px;
border-radius: 100%;
`
export const UserReviewsSkeletonLineOne = styled(Box)`
width: 78px;
height: 18px;
margin-top: 18px;
margin-left: 18px;
`
export const UserReviewsSkeletonLineSecond = styled(Box)`
width: 200px;
height: 14px;
margin-top: 18px;
margin-left: 9px;
margin-bottom: 4px;
flex: 1;
`
export const UserReviewsSkeletonSquare = styled(Box)`
width: 14px;
height: 14px;
margin-top: 18px;
`
export const UserReviewsSkeletonLineThird = styled(Box)`
width: 91px;
height: 14px;
margin-left: 23px;
`
export const UserReviewsSkeletonLineForth = styled(Box)`
width: 154px;
height: 14px;
margin-top: 20px;
margin-bottom: 4px;
`
export const UserReviewsSkeletonLineFifth = styled(Box)`
width: 121px;
height: 14px;
`

+ 3
- 0
src/constants/stylesConstants.js Bestand weergeven

@@ -0,0 +1,3 @@
export const PRIMARY_PURPLE_COLOR = `rgb(90, 57, 131)`;
export const PRIMARY_YELLOW_COLOR = `rgb(247, 178, 38)`;
export const PRIMARY_PURPLE_DISABLED = `rgb(75, 92, 100)`;

+ 0
- 10
src/hooks/useQueryString.js Bestand weergeven

@@ -16,23 +16,17 @@ export const useQueryString = () => {
const [globalQueryString, setGlobalQueryString] = useState("");
const [initial, setInitial] = useState(true);
const [loadedFromURL, setLoadedFromURL] = useState(false);
// const [isFetched, setIsFetched] = useState(false);
const dispatch = useDispatch();
// const sorting = useSorting();

useEffect(() => {
const queryStringLocal = history.location.search.substring(1);
setQueryString(convertQueryStringBackend(queryStringLocal));
setGlobalQueryString(queryStringLocal);
console.log("initial bre")
}, []);

useEffect(() => {
console.log(globalQueryString);
console.log(history.location.search.substring(1))
if (globalQueryString === history.location.search.substring(1))
setLoadedFromURL(true);
// qo.delete("location")
}, [globalQueryString]);

useEffect(() => {
@@ -124,13 +118,9 @@ export const useQueryString = () => {
urlParams.delete(item.key);
}
// }
console.log("item.key: ", item.key);
console.log("item.value: ", item.value);
if (!item.value) return;
urlParams.append(item.key, item.value);
console.log("querytString: ", urlParams.toString())
});
console.log("postavlja se");
setQueryString(urlParams.toString());
return urlParams.toString();
}

+ 0
- 1
src/hooks/useSorting.js Bestand weergeven

@@ -40,7 +40,6 @@ const useSorting = () => {

const setSelectedSortOption = (payload, shouldGoFirstPage = false) => {
dispatch(setFilteredSortOption(payload));
console.log("konzola sort: ", payload)
let _des_date = null;
let _des_popular = null;
if (payload.value === sortOptions.NEW.value) {

+ 24
- 3
src/i18n/resources/rs.js Bestand weergeven

@@ -66,7 +66,7 @@ export default {
forgotPasswordEmail: "Email",
useDifferentEmail: "Iskoristite drugačiju lozinku.",
wrongCredentials: "Pogrešan mail ili lozinka!",
headerTitle: "Ulogujte se"
headerTitle: "Ulogujte se",
},
password: {
weak: "slaba",
@@ -141,8 +141,25 @@ export default {
placeholder: "Pretraži gradove...",
},
},
offer: {
title: "NASLOV",
productName: "Naziv proizvoda...",
productDescription: "OPIS PROIZVODA",
description: "Opis...",
location: "LOKACIJA",
choseLocation: "Izaberi lokaciju",
category: "KATEGORIJA",
choseCategory: "Izaberi kategoriju",
subcategory: "PODKATEGORIJA",
choseSubcategory: "Izaberi podkategoriju",
condition: "STANJE",
choseCondition: "Izaberi Stanje",
supportedImagesFormats:
"Podržani formati fotografija: <strong>.JPG</strong> | <strong>.JPEG</strong> | <strong>.PNG</strong>",
continue: "NASTAVI",
},
apiErrors: {
somethingWentWrong: "Greska sa serverom!"
somethingWentWrong: "Greska sa serverom!",
},
header: {
addOffer: "Dodaj proizvod",
@@ -152,6 +169,10 @@ export default {
myOffers: "Moje objave",
checkEverything: "POGLEDAJ SVE",
myMessages: "Moje poruke",
newOffers: "Najnovije ponude"
newOffers: "Najnovije ponude",
},
reviews: {
title: "Ova kompanija još uvek nema ocenu.",
altTitle: "Budite prvi da je ocenite"
}
};

+ 7
- 4
src/layouts/ItemDetailsLayout/ItemDetailsLayout.js Bestand weergeven

@@ -1,6 +1,10 @@
import React from "react";
import PropTypes from "prop-types";
import { Content, RightCard, ItemDetailsLayoutContainer } from "./ItemDetailsLayout.styled";
import {
Content,
RightCard,
ItemDetailsLayoutContainer,
} from "./ItemDetailsLayout.styled";
import { Grid } from "@mui/material";

const ItemDetailsLayout = (props) => {
@@ -8,13 +12,12 @@ const ItemDetailsLayout = (props) => {
<ItemDetailsLayoutContainer>
{props.children}
<Grid container maxHeight="xl" spacing={2}>
<Content item xs={12} lg={9} xl={9.6} md={8} >
<Content item xs={12} lg={9} xl={9.6} md={12}>
{props.content}
</Content>
<RightCard item xs={0} lg={3} xl={2.4} md={4} >
<RightCard item xs={12} lg={3} xl={2.4} md={12}>
{props.rightCard}
</RightCard>
</Grid>
</ItemDetailsLayoutContainer>
);

+ 26
- 21
src/layouts/ItemDetailsLayout/ItemDetailsLayout.styled.js Bestand weergeven

@@ -2,27 +2,32 @@ import { Container, Grid } from "@mui/material";
import styled from "styled-components";

export const ItemDetailsLayoutContainer = styled(Container)`
padding-left: 60px;
padding-right: 0;
margin: 0;
width: 100%;
max-width: none;
display: flex;
flex: 1;
height: 100%;
@media (max-width: 1024px) {
padding-right: 54px;
}
@media (max-width: 600px) {
padding-left: 18px;
padding-right: 18px;
}
`
padding-left: 60px;
padding-right: 0;
margin: 0;
width: 100%;
max-width: none;
display: flex;
position: relative;
flex: 1;
height: 100%;
@media (max-width: 1024px) {
padding-right: 18px;
}
@media (max-width: 600px) {
padding-left: 18px;
padding-right: 18px;
}
`;

export const RightCard = styled(Grid)`
margin-top: 30px;
border-top-right-radius: 4px;
width: 100%;
`
margin-top: 30px;
border-top-right-radius: 4px;
width: 100%;
/* @media (max-width: 800px) {
position: relative;
bottom: -500px;
} */
`;
export const Content = styled(Grid)`
`
`;

+ 8
- 19
src/pages/ItemDetailsPage/ItemDetailsPageMUI.js Bestand weergeven

@@ -2,20 +2,14 @@ import React, { useEffect } from "react";
import { PropTypes } from "prop-types";
// import Navbar from "../../components/MUI/NavbarComponent";
import { ItemDetailsPageContainer } from "./ItemDetailsPage.styled";
import { useDispatch, useSelector } from "react-redux";
import { useDispatch} from "react-redux";
import ItemDetails from "../../components/ItemDetails/ItemDetails";
import ItemDetailsLayout from "../../layouts/ItemDetailsLayout/ItemDetailsLayout";
import UserReviewsCard from "../../components/UserReviewsCard/UserReviewsCard";
import { fetchOneOffer } from "../../store/actions/offers/offersActions";
import { selectOffer } from "../../store/selectors/offersSelectors";




const ItemDetailsPage = (props) => {

const dispatch = useDispatch();
const offer = useSelector(selectOffer);

const offerId = props.match.params.idProizvod;

@@ -25,19 +19,14 @@ const ItemDetailsPage = (props) => {
}
}, [offerId]);

useEffect(() => {
if (typeof offer !== 'undefined' && typeof offer.userId !== 'undefined' && offer.userId !== '') {
console.log(offer.userId);
}
}, [offer])


return (
<ItemDetailsPageContainer>
{/* <Navbar /> */}
{/* right card mora mi bude Review Card */}
<ItemDetailsLayout content={<ItemDetails />} rightCard={<UserReviewsCard />} />
<ItemDetailsLayout
content={<ItemDetails />}
rightCard={<UserReviewsCard />}
/>

{/* <Box sx={{ mt: 4, mx: 4 }}>
<GridStyled container justifyContent="space-between">
@@ -67,9 +56,9 @@ const ItemDetailsPage = (props) => {
ItemDetailsPage.propTypes = {
match: PropTypes.shape({
params: PropTypes.shape({
idProizvod:PropTypes.string
})
})
idProizvod: PropTypes.string,
}),
}),
};

export default ItemDetailsPage;

+ 1
- 13
src/pages/ProfilePage/ProfilePage.js Bestand weergeven

@@ -10,19 +10,7 @@ import Profile from "../../components/Profile/Profile";
const ProfilePage = () => {
return (
<ProfilePageContainer>
{/* <Navbar /> */}
{/* <ProfilePageWrapper
container
direction="row"
justifyContent="center"
alignItems="start"
sx={{ pt: 3 }}
>
{/* <FilterCard />
<ProfileCard />
<UserReviewsCard heading="Moje ocene" />
</ProfilePageWrapper> */}
<ItemDetailsLayout content={<Profile/>} rightCard={<UserReviewsCard/>} />
<ItemDetailsLayout content={<Profile/>} rightCard={<UserReviewsCard profileReviews/>} />
</ProfilePageContainer>
);
};

+ 7
- 8
src/pages/RegisterPages/Register/Register.js Bestand weergeven

@@ -46,7 +46,7 @@ const Register = () => {
console.log(error);
const { mail, password, PIB, image } = informations;
if (error.type === "mail") {
setInformations({image});
setInformations({ image });
setCurrentStep(1);
setMailError(mail);
if (
@@ -86,20 +86,19 @@ const Register = () => {

const setImage = (image) => {
setImageError(false);
setInformations(prevInfo => ({
setInformations((prevInfo) => ({
...prevInfo,
image
}))
}
image,
}));
};

const goStepBack = (stepNumber) => {
setCurrentStep(stepNumber);
const { mail, password, image } = informations;
if (stepNumber === 1) {
setInformations({image});
setInformations({ image });
}
if (stepNumber === 2) {
setInformations({ mail, password, image });
}
};
@@ -125,7 +124,7 @@ const Register = () => {
/>
</ProgressContainer>

<ProfileImagePicker setImage={setImage} >
<ProfileImagePicker setImage={setImage}>
<ProfilePicture />
</ProfileImagePicker>


+ 107
- 107
src/request/apiEndpoints.js Bestand weergeven

@@ -1,162 +1,162 @@
export default {
accounts: {
get: 'accounts/{accountUid}',
forgotPassword: 'forgot-password',
resetPassword: 'reset-password',
get: "accounts/{accountUid}",
forgotPassword: "forgot-password",
resetPassword: "reset-password",
getCurrentUserPermissions:
'accounts/{currentAccountUid}/users/{currentUserUid}/permissions',
getAddresses: 'accounts/{accountUid}/addresses',
updateAddress: 'account/{accountUid}/addresses/{addressUid}',
deleteAddress: 'accounts/{accountUid}/addresses/{addressUid}',
getUsers: 'accounts/{accountUid}/users',
register: 'users',
updateUser: 'account/{accountUid}/users/{userUid}?actionType={actionType}',
deleteUser: 'accounts/{accountUid}/users/{userUid}',
getSettings: 'accounts/{accountUid}/settings',
getIraSettings: 'accounts/{accountUid}/iraSettings',
getSettingsRegistration: 'application/settings',
agreement: 'accounts/agreement',
"accounts/{currentAccountUid}/users/{currentUserUid}/permissions",
getAddresses: "accounts/{accountUid}/addresses",
updateAddress: "account/{accountUid}/addresses/{addressUid}",
deleteAddress: "accounts/{accountUid}/addresses/{addressUid}",
getUsers: "accounts/{accountUid}/users",
register: "users",
updateUser: "account/{accountUid}/users/{userUid}?actionType={actionType}",
deleteUser: "accounts/{accountUid}/users/{userUid}",
getSettings: "accounts/{accountUid}/settings",
getIraSettings: "accounts/{accountUid}/iraSettings",
getSettingsRegistration: "application/settings",
agreement: "accounts/agreement",
},
authentications: {
getUsernames: 'authenticate/usernames',
login: 'auth/token',
logout: 'auth/logout',
getUserSecurityQuestion: 'users/username/securityquestion',
confirmSecurityQuestion: 'authenticate/confirm',
confirmForgotPassword: 'users/passwords/reset_token',
resetPassword: 'reset-password',
forgotPassword: 'forgot-password',
refreshToken: '/auth/refresh',
generateToken: '/authenticate/generate',
getUsernames: "authenticate/usernames",
login: "auth/token",
logout: "auth/logout",
getUserSecurityQuestion: "users/username/securityquestion",
confirmSecurityQuestion: "authenticate/confirm",
confirmForgotPassword: "users/passwords/reset_token",
resetPassword: "reset-password",
forgotPassword: "forgot-password",
refreshToken: "/auth/refresh",
generateToken: "/authenticate/generate",
authenticate:
'/authenticate?fp={fp}&offer={offer}&landingPageUrl={landingPageUrl}&registrationFlowType={registrationFlowType}',
"/authenticate?fp={fp}&offer={offer}&landingPageUrl={landingPageUrl}&registrationFlowType={registrationFlowType}",
confirmAuthentication:
'/authenticate/confirm?fp={fp}&offer={offer}&landingPageUrl={landingPageUrl}&registrationFlowType={registrationFlowType}',
"/authenticate/confirm?fp={fp}&offer={offer}&landingPageUrl={landingPageUrl}&registrationFlowType={registrationFlowType}",
},
bankAccounts: {
get: 'accounts/{accountUid}/bankaccounts',
get: "accounts/{accountUid}/bankaccounts",
getBankAccount:
'accounts/{accountUid}/bankaccounts/{bankAccountUid}?type={type}',
"accounts/{accountUid}/bankaccounts/{bankAccountUid}?type={type}",
getBankAccountsByType:
'accounts/{accountUid}/bankaccounts?type={type}&active=true',
getBankDetailsByRoutingNumber: 'banks/{routingNumber}',
newAccount: 'accounts/{accountUid}/bankaccounts',
"accounts/{accountUid}/bankaccounts?type={type}&active=true",
getBankDetailsByRoutingNumber: "banks/{routingNumber}",
newAccount: "accounts/{accountUid}/bankaccounts",
deleteAccount:
'accounts/{accountUid}/bankaccounts/{bankAccountUid}?type={type}',
verify: '/accounts/{accountUid}/bankaccountverification/{bankAccountUid}',
postBankAccountRegistration: '/accounts/{applicationUid}/bankaccounts',
getRegistration: 'banks/{applicationUid}/bankaccounts',
"accounts/{accountUid}/bankaccounts/{bankAccountUid}?type={type}",
verify: "/accounts/{accountUid}/bankaccountverification/{bankAccountUid}",
postBankAccountRegistration: "/accounts/{applicationUid}/bankaccounts",
getRegistration: "banks/{applicationUid}/bankaccounts",
},
documents: {
getDocuments: 'accounts/{accountUid}/documents?year={year}',
getDocument: 'accounts/{accountUid}/documents/{documentType}',
getDocuments: "accounts/{accountUid}/documents?year={year}",
getDocument: "accounts/{accountUid}/documents/{documentType}",
},
countries: '/countries',
countries: "/countries",
metalStream: {
getMetalStreamSettings: 'accounts/{accountUid}/metalstream',
getMetalStreamFundings: 'applications/{applicationUid}/metalStreamFunding',
getMetalStreamSettings: "accounts/{accountUid}/metalstream",
getMetalStreamFundings: "applications/{applicationUid}/metalStreamFunding",
},
orders: {
buyForStorage: '/accounts/{accountUid}/orders/buyForStorage',
buyForDelivery: '/accounts/{accountUid}/orders/buyForDelivery',
verifyBuyForDelivery: '/accounts/{accountUid}/orders/buyForDelivery/verify',
sellFromStorage: '/accounts/{accountUid}/orders/sellFromStorage',
fractionalConversion: '/accounts/{accountUid}/orders/fractionalConversion',
buyForStorage: "/accounts/{accountUid}/orders/buyForStorage",
buyForDelivery: "/accounts/{accountUid}/orders/buyForDelivery",
verifyBuyForDelivery: "/accounts/{accountUid}/orders/buyForDelivery/verify",
sellFromStorage: "/accounts/{accountUid}/orders/sellFromStorage",
fractionalConversion: "/accounts/{accountUid}/orders/fractionalConversion",
deliverFromStorageVerify:
'/accounts/{accountUid}/orders/deliverFromStorage/verify',
deliverFromStorage: '/accounts/{accountUid}/orders/deliverFromStorage',
iraCashDistribution: '/accounts/{accountUid}/orders/iraCashDistribution',
iraCashTransfer: '/accounts/{accountUid}/orders/iraCashTransfer',
iraFeeWithdrawal: 'accounts/{accountUid}/orders/iraFeeWithdrawal',
achDeposit: 'accounts/{accountUid}/orders/achDeposit',
wireWithdrawal: '/accounts/{accountUid}/orders/wireWithdrawal',
checkWithdrawal: '/accounts/{accountUid}/orders/checkWithdrawal',
"/accounts/{accountUid}/orders/deliverFromStorage/verify",
deliverFromStorage: "/accounts/{accountUid}/orders/deliverFromStorage",
iraCashDistribution: "/accounts/{accountUid}/orders/iraCashDistribution",
iraCashTransfer: "/accounts/{accountUid}/orders/iraCashTransfer",
iraFeeWithdrawal: "accounts/{accountUid}/orders/iraFeeWithdrawal",
achDeposit: "accounts/{accountUid}/orders/achDeposit",
wireWithdrawal: "/accounts/{accountUid}/orders/wireWithdrawal",
checkWithdrawal: "/accounts/{accountUid}/orders/checkWithdrawal",
},
portfolio: {
getPortfolioValuations: 'accounts/{accountUid}/portfolio/valuations',
getPortfolioMetalPrices: 'marketprices',
getPortfolioValuations: "accounts/{accountUid}/portfolio/valuations",
getPortfolioMetalPrices: "marketprices",
getPortfolioHoldings:
'accounts/{accountUid}/portfolio/products?valuation=true',
getPortfolioProductCodes: '/accounts/{accountUid}/portfolio/productcodes',
getPortfolioBalances: '/accounts/{accountUid}/portfolio/balances',
"accounts/{accountUid}/portfolio/products?valuation=true",
getPortfolioProductCodes: "/accounts/{accountUid}/portfolio/productcodes",
getPortfolioBalances: "/accounts/{accountUid}/portfolio/balances",
getPortfolioProductBySymbol:
'/accounts/{accountUid}/portfolio/products/{symbol}',
getPortfolioTransactions: '/accounts/{accountUid}/transactions',
"/accounts/{accountUid}/portfolio/products/{symbol}",
getPortfolioTransactions: "/accounts/{accountUid}/transactions",
getPortfolioSingleTransaction:
'/accounts/{accountUid}/transactions/{transactionUid}',
getProductPortoflioTransactions: 'accounts/{accountUid}/transactions',
"/accounts/{accountUid}/transactions/{transactionUid}",
getProductPortoflioTransactions: "accounts/{accountUid}/transactions",
getRecentPortfolioTransactions:
'accounts/{accountUid}/transactions?content=Recent',
getFinancialPortfolioTransactions: 'accounts/{accountUid}/transactions',
"accounts/{accountUid}/transactions?content=Recent",
getFinancialPortfolioTransactions: "accounts/{accountUid}/transactions",
getFinancialPortfolioPendingTransactions:
'accounts/{accountUid}/transactions/fundinghistory',
"accounts/{accountUid}/transactions/fundinghistory",
patchFinancialPortfolioPendingTransactions:
'/accounts/{accountUid}/transactions/fundinghistory/{depositKey}',
"/accounts/{accountUid}/transactions/fundinghistory/{depositKey}",
},
products: {
getPrices: '/accounts/{accountUid}/products/prices',
prices: 'accounts/{accountUid}/products/prices?side={side}',
getPrices: "/accounts/{accountUid}/products/prices",
prices: "accounts/{accountUid}/products/prices?side={side}",
tiers:
'/accounts/{accountUid}/products/prices/{symbol}/tiers?side={side}&location={location}',
symbolPrices: '/accounts/{accountUid}/products/{symbol}/prices?side={side}',
getPricesRegistration: 'applications/{applicationUid}/products/prices',
"/accounts/{accountUid}/products/prices/{symbol}/tiers?side={side}&location={location}",
symbolPrices: "/accounts/{accountUid}/products/{symbol}/prices?side={side}",
getPricesRegistration: "applications/{applicationUid}/products/prices",
},
settings: {
get: 'settings',
get: "settings",
},
taxForms: {
getTaxForms: 'settings/taxForms/{applicationType}',
getTaxForms: "settings/taxForms/{applicationType}",
},
users: {
getAccounts: '/users/{userUid}/accounts',
getRegistrationAccounts: '/users/{userUid}/accounts',
updateUser: '/users/{userUid}?updateUserActionType={actionType}',
updateUserPassword: '/users/{userUid}/passwords',
logout: '/auth/logout',
getUsernames: '/users/email',
getAccounts: "/users/{userUid}/accounts",
getRegistrationAccounts: "/users/{userUid}/accounts",
updateUser: "/users/{userUid}?updateUserActionType={actionType}",
updateUserPassword: "/users/{userUid}/passwords",
logout: "/auth/logout",
getUsernames: "/users/email",
createUser:
'/users?fp={fp}&offer={offer}&landingPageUrl={landingPageUrl}&registrationFlowType={registrationFlowType}',
updateUserRegistration: '/users/{userUid}',
invite: '/users/invite',
getProfile: 'users/'
"/users?fp={fp}&offer={offer}&landingPageUrl={landingPageUrl}&registrationFlowType={registrationFlowType}",
updateUserRegistration: "/users/{userUid}",
invite: "/users/invite",
getProfile: "users/",
},
applications: {
application: '/applications/{applicationUid}',
addPerson: '/applications/{applicationUid}/persons',
updatePerson: '/applications/{applicationUid}/persons/{personUid}',
application: "/applications/{applicationUid}",
addPerson: "/applications/{applicationUid}/persons",
updatePerson: "/applications/{applicationUid}/persons/{personUid}",
addPersonWithGiftState:
'/applications/{applicationUid}/UTMA/persons?giftState={giftState}',
"/applications/{applicationUid}/UTMA/persons?giftState={giftState}",
updatePersonWithGiftState:
'/applications/{applicationUid}/UTMA/persons/{personUid}?giftState={giftState}',
"/applications/{applicationUid}/UTMA/persons/{personUid}?giftState={giftState}",
addPersonWithCompanyName:
'/applications/{applicationUid}/IRA/persons?companyName={companyName}',
"/applications/{applicationUid}/IRA/persons?companyName={companyName}",
updatePersonWithCompanyName:
'/applications/{applicationUid}/IRA/persons/{personUid}?companyName={companyName}',
submitLegalEntity: '/applications/{applicationUid}/legalEntities',
"/applications/{applicationUid}/IRA/persons/{personUid}?companyName={companyName}",
submitLegalEntity: "/applications/{applicationUid}/legalEntities",
updateLegalEntity:
'/applications/{applicationUid}/legalEntities/{personUid}',
postNonIraFunding: '/applications/{applicationUid}/funding',
postIraFunding: '/applications/{applicationUid}/iraFunding',
postMSFunding: '/applications/{applicationUid}/metalStreamFunding',
consent: '/applications/{applicationUid}/consents',
"/applications/{applicationUid}/legalEntities/{personUid}",
postNonIraFunding: "/applications/{applicationUid}/funding",
postIraFunding: "/applications/{applicationUid}/iraFunding",
postMSFunding: "/applications/{applicationUid}/metalStreamFunding",
consent: "/applications/{applicationUid}/consents",
updateConsent: `/applications/{applicationUid}/consents/{agreementConsentUid}`,
submitMetalStreamRegistration:
'/applications/{applicationUid}/metalStreamFunding',
"/applications/{applicationUid}/metalStreamFunding",
},
common: {
getCountries: '/countries/',
getTaxForms: '/taxForms/',
getContributionYears: 'contributionYears',
getCountryStates: '/countries/{iso3CountryCode}/states/',
getSecurityQuestions: '/registration/securityQuestions/',
getPortalSecurityQuestions: '/securityQuestions',
getCountries: "/countries/",
getTaxForms: "/taxForms/",
getContributionYears: "contributionYears",
getCountryStates: "/countries/{iso3CountryCode}/states/",
getSecurityQuestions: "/registration/securityQuestions/",
getPortalSecurityQuestions: "/securityQuestions",
},
plaid: {
getToken: '/bankaccounts/createplaidlinktoken',
getToken: "/bankaccounts/createplaidlinktoken",
},
affiliate: {
setCookie: '/affiliate/picture',
setFingerprint: '/affiliate/fingerprint',
setCookie: "/affiliate/picture",
setFingerprint: "/affiliate/fingerprint",
},
offers: {
getOneOffer: 'offers',

+ 1
- 1
src/request/index.js Bestand weergeven

@@ -14,7 +14,7 @@ const request = axios.create({

export const getRequest = (url, params = null, options = null) => {
return request.get(url, { params, ...options });
}
};

export const postRequest = (url, data, params = null, options = null) =>
request.post(url, data, { params, ...options });

+ 0
- 1
src/request/offersRequest.js Bestand weergeven

@@ -6,7 +6,6 @@ export const attemptFetchOffers = (payload) => {
return getRequest(apiEndpoints.offers.getOffers)
}
export const attemptFetchOneOffer = (payload) => {
// console.log(payload);
const url = `${apiEndpoints.offers.getOneOffer}/${payload.payload}/frontend`;
return getRequest(url);
}

+ 3
- 2
src/store/middleware/accessTokensMiddleware.js Bestand weergeven

@@ -32,7 +32,7 @@ export default ({ dispatch }) =>
if (!response.headers?.Authorization) {
response.headers.Authorization = `Bearer ${jwtToken}`;
}
// If refresh token is expired, log out user
if (new Date() > new Date(refreshTokenDecoded?.exp * 1000)) {
dispatch(logoutUser());
@@ -44,9 +44,10 @@ export default ({ dispatch }) =>
token: refresh,
});
const newToken = axiosResponse.data.token;
response.headers.Authorization = `Bearer ${newToken}`
dispatch(refreshUserToken(newToken));
}
return Promise.resolve(response);
}, accessTokensMiddlewareInterceptorName);


+ 2
- 3
src/store/saga/offersSaga.js Bestand weergeven

@@ -88,10 +88,9 @@ function* fetchMoreOffers(payload) {

function* createOffer(payload) {
try {
const data = yield call(attemptAddOffer, payload);
const data = yield call(attemptAddOffer, payload.payload);
console.log(data);
}
catch (e) {
} catch (e) {
console.log(e);
}
}

+ 3
- 2
src/themes/primaryTheme/primaryThemeColors.js Bestand weergeven

@@ -22,5 +22,6 @@ export const primaryThemeColors = {
imagePickerBackground: "#E4E4E4",
iconYellowColor: "#FEB005",
iconMineProfileColor: "#9E9E9E",
iconProfileColor: "#C4C4C4"
}
iconProfileColor: "#C4C4C4",
skeletonItemColor: "#F4F4F4"
}

Laden…
Annuleren
Opslaan