Bladeren bron

Code cleanup init

bugfix/520
jovan.cirkovic 3 jaren geleden
bovenliggende
commit
8ce8793926
58 gewijzigde bestanden met toevoegingen van 1345 en 1348 verwijderingen
  1. 0
    20
      src/components/Auth/Auth.js
  2. 0
    24
      src/components/AuthCards/AuthCard.js
  3. 16
    11
      src/components/Buttons/ArrowButton/ArrowButton.js
  4. 0
    93
      src/components/Buttons/Button.js
  5. 25
    15
      src/components/Buttons/IconButton/IconButton.js
  6. 12
    8
      src/components/Buttons/IconButton/IconButton.styled.js
  7. 0
    26
      src/components/Buttons/LoginButton/LoginButton.js
  8. 0
    11
      src/components/Buttons/LoginButton/LoginButton.styled.js
  9. 0
    34
      src/components/Buttons/PrimaryButtonWithIcon/PrimaryButtonWithIcon.js
  10. 0
    28
      src/components/Buttons/PrimaryButtonWithIcon/PrimaryButtonWithIcon.styled.js
  11. 34
    30
      src/components/Cards/ChatCard/ChatCard.js
  12. 5
    193
      src/components/Cards/ChatCard/ChatCard.styled.js
  13. 8
    60
      src/components/Cards/CreateOfferCard/CreateOffer.js
  14. 63
    62
      src/components/Cards/CreateOfferCard/FirstPart/FirstPartCreateOffer.js
  15. 1
    39
      src/components/Cards/CreateOfferCard/SecondPart/SecondPartCreateOffer.js
  16. 7
    10
      src/components/Cards/CreateOfferCard/ThirdPart/ThirdPartCreateOffer.js
  17. 46
    0
      src/components/Cards/FilterCard/Choser/CategoryChoser/CategoryChoser.js
  18. 8
    0
      src/components/Cards/FilterCard/Choser/CategoryChoser/CategoryChoser.styled.js
  19. 30
    0
      src/components/Cards/FilterCard/Choser/LocationChoser/LocationChoser.js
  20. 5
    0
      src/components/Cards/FilterCard/Choser/LocationChoser/LocationChoser.styled.js
  21. 63
    0
      src/components/Cards/FilterCard/Choser/SubcategoryChoser/SubcategoryChoser.js
  22. 4
    0
      src/components/Cards/FilterCard/Choser/SubcategoryChoser/SubcategoryChoser.styled.js
  23. 15
    141
      src/components/Cards/FilterCard/FilterCard.js
  24. 3
    36
      src/components/Cards/FilterCard/FilterCard.styled.js
  25. 7
    4
      src/components/Cards/FilterCard/FilterDropdown/Radio/FilterRadioDropdown.js
  26. 61
    0
      src/components/Cards/FilterCard/FilterFooter/FilterFooter.js
  27. 22
    0
      src/components/Cards/FilterCard/FilterFooter/FilterFooter.styled.js
  28. 28
    0
      src/components/Cards/FilterCard/FilterHeader/FilterHeader.js
  29. 19
    0
      src/components/Cards/FilterCard/FilterHeader/FilterHeader.styled.js
  30. 0
    19
      src/components/Cards/HomeListCard/HomeListCard.js
  31. 29
    0
      src/components/Cards/ItemDetailsCard/Information/Information.js
  32. 20
    0
      src/components/Cards/ItemDetailsCard/Information/Information.styled.js
  33. 109
    135
      src/components/Cards/ItemDetailsCard/ItemDetailsCard.js
  34. 51
    16
      src/components/Cards/ItemDetailsCard/ItemDetailsCard.styled.js
  35. 14
    0
      src/components/Cards/ItemDetailsCard/OfferDetails/OfferDetails.js
  36. 0
    0
      src/components/Cards/ItemDetailsCard/OfferDetails/OfferDetails.styled.js
  37. 2
    4
      src/components/Cards/MiniChatCard/MiniChatCard.js
  38. 5
    5
      src/components/Cards/OfferCard/DeleteOffer/DeleteOffer.js
  39. 5
    5
      src/components/Cards/OfferCard/DeleteOffer/DeleteOffer.styled.js
  40. 11
    7
      src/components/Cards/OfferCard/OfferCard.js
  41. 8
    2
      src/components/ItemDetails/Header/Header.js
  42. 27
    9
      src/components/Profile/ProfileOffers/ProfileOffers.js
  43. 6
    18
      src/components/ProfileCard/EditProfile/EditProfile.js
  44. 3
    3
      src/components/ProfileCard/EditProfile/EditProfile.styled.js
  45. 16
    130
      src/components/ProfileCard/ProfileCard.js
  46. 188
    143
      src/components/ProfileCard/ProfileCard.styled.js
  47. 48
    0
      src/components/ProfileCard/ProfileContact/ProfileContact.js
  48. 72
    0
      src/components/ProfileCard/ProfileContact/ProfileContact.styled.js
  49. 46
    0
      src/components/ProfileCard/ProfileMainInfo/ProfileMainInfo.js
  50. 79
    0
      src/components/ProfileCard/ProfileMainInfo/ProfileMainInfo.styled.js
  51. 44
    0
      src/components/ProfileCard/ProfileStats/ProfileStats.js
  52. 33
    0
      src/components/ProfileCard/ProfileStats/ProfileStats.styled.js
  53. 5
    0
      src/hooks/useFilters.js
  54. 10
    4
      src/i18n/resources/rs.js
  55. 2
    2
      src/request/apiEndpoints.js
  56. 1
    1
      src/request/offersRequest.js
  57. 16
    0
      src/util/helpers/chatHelper.js
  58. 13
    0
      src/util/helpers/dateHelpers.js

+ 0
- 20
src/components/Auth/Auth.js Bestand weergeven

@@ -1,20 +0,0 @@
import React from 'react';
import PropTypes from 'prop-types';
import { useTranslation } from 'react-i18next';

const Auth = ({ children }) => {
const { t } = useTranslation();

return (
<div className="c-auth">
<h1 className="c-auth__title">{t(`login.welcome`)}</h1>
{children}
</div>
);
};

Auth.propTypes = {
children: PropTypes.node,
};

export default Auth;

+ 0
- 24
src/components/AuthCards/AuthCard.js Bestand weergeven

@@ -1,24 +0,0 @@
import React from 'react';
import PropTypes from 'prop-types';
import SectionLoader from '../Loader/SectionLoader';

const AuthCard = ({ children, title, subtitle, isLoading }) => {
return (
<div className="c-auth-card">
<SectionLoader isLoading={isLoading}>
<h1 className="c-auth-card__title">{title}</h1>
<h2 className="c-auth-card__subtitle">{subtitle}</h2>
{children}
</SectionLoader>
</div>
);
};

AuthCard.propTypes = {
children: PropTypes.node,
title: PropTypes.string,
subtitle: PropTypes.string,
isLoading: PropTypes.bool,
};

export default AuthCard;

+ 16
- 11
src/components/Buttons/ArrowButton/ArrowButton.js Bestand weergeven

@@ -1,17 +1,22 @@
import React from 'react'
import { ArrowContainer, ArrowIcon } from "./ArrowButton.styled"
import React from "react";
import { ArrowContainer, ArrowIcon } from "./ArrowButton.styled";
import PropTypes from "prop-types";

export const ArrowButton = (props) => {

return <ArrowContainer onClick={props.onClick} className={props.className} disabled={props.disabled}>
<ArrowIcon side={props.side} disabled={props.disabled}/>
return (
<ArrowContainer
onClick={props.onClick}
className={props.className}
disabled={props.disabled}
>
<ArrowIcon side={props.side} disabled={props.disabled} />
</ArrowContainer>
}
);
};

ArrowButton.propTypes = {
onClick: PropTypes.func,
className: PropTypes.string,
side:PropTypes.string,
disabled:PropTypes.bool,
}
onClick: PropTypes.func,
className: PropTypes.string,
side: PropTypes.string,
disabled: PropTypes.bool,
};

+ 0
- 93
src/components/Buttons/Button.js Bestand weergeven

@@ -1,93 +0,0 @@
import React, { useRef } from 'react';
import PropType from 'prop-types';

const Button = ({
variant,
size,
children,
authButton,
type,
onClick,
textTransform,
className,
disabled,
hidden,
minWidth,
...restProps
}) => {
const buttonRef = useRef(null);

function styles() {
let style = 'c-btn';

if (variant) {
style += ` c-btn--${variant}`;
}

if (size) {
style += ` c-btn--${size}`;
}

if (textTransform) {
style += ` c-btn--${textTransform}`;
}

if (authButton) {
style += ` c-btn--auth`;
}

if (minWidth) {
style += ` c-btn--${minWidth}`;
}

if (hidden) {
style += ` c-btn--hidden`;
}

if (className) {
style += ` ${className}`;
}

return style;
}

function handleClick() {
buttonRef.current.blur();
if (typeof onClick === 'function') {
onClick();
}
}

return (
<button
ref={buttonRef}
className={styles()}
onClick={handleClick}
type={type}
disabled={disabled}
{...restProps}
>
{children}
</button>
);
};

Button.propTypes = {
children: PropType.node,
textTransform: PropType.oneOf(['uppercase', 'capitalize']),
size: PropType.oneOf(['sm', 'md', 'lg', 'xl']),
authButton: PropType.bool,
variant: PropType.string,
type: PropType.oneOf(['button', 'submit', 'reset']),
onClick: PropType.func,
className: PropType.string,
disabled: PropType.bool,
minWidth: PropType.oneOf(['auto']),
hidden: PropType.bool,
};

Button.defaultProps = {
type: 'button',
};

export default Button;

+ 25
- 15
src/components/Buttons/IconButton/IconButton.js Bestand weergeven

@@ -1,21 +1,31 @@
import React from 'react'
import { IconButtonContainer, IconButtonStyled } from "./IconButton.styled"
import React from "react";
import { IconButtonContainer, IconButtonStyled } from "./IconButton.styled";
import PropTypes from "prop-types";

export const IconButton = (props) => {
return <IconButtonContainer style={props.containerStyle} className={props.className}>
<IconButtonStyled disabled={props.disabled} onClick={props.onClick} sx={props.style} iconcolor={props.iconColor}>
{props.children}
</IconButtonStyled>
return (
<IconButtonContainer
style={props.containerStyle}
className={props.className}
>
<IconButtonStyled
disabled={props.disabled}
onClick={props.onClick}
sx={props.style}
iconcolor={props.iconColor}
>
{props.children}
</IconButtonStyled>
</IconButtonContainer>
}
);
};

IconButton.propTypes = {
children: PropTypes.node,
onClick: PropTypes.func,
containerStyle: PropTypes.any,
style: PropTypes.any,
className: PropTypes.string,
iconColor: PropTypes.string,
disabled: PropTypes.bool,
}
children: PropTypes.node,
onClick: PropTypes.func,
containerStyle: PropTypes.any,
style: PropTypes.any,
className: PropTypes.string,
iconColor: PropTypes.string,
disabled: PropTypes.bool,
};

+ 12
- 8
src/components/Buttons/IconButton/IconButton.styled.js Bestand weergeven

@@ -2,17 +2,21 @@ import { Box, IconButton } from "@mui/material";
import styled from "styled-components";
import selectedTheme from "../../../themes";

export const IconButtonContainer = styled(Box)`
`
export const IconButtonContainer = styled(Box)``;

export const IconButtonStyled = styled(IconButton)`
height: ${props => props.height ? props.height : "36px"};
width: ${props => props.width ? props.width : "36px"};
padding: 0;
${props => props.iconcolor && `
height: ${(props) => (props.height ? props.height : "36px")};
width: ${(props) => (props.width ? props.width : "36px")};
padding: 0;
${(props) =>
props.iconcolor &&
`
& svg path {
stroke: ${props.iconcolor};
}
`}
border: ${props => props.border ? "1px solid " + selectedTheme.backgroundSponsoredColor : "none"}
`
border: ${(props) =>
props.border
? "1px solid " + selectedTheme.backgroundSponsoredColor
: "none"}
`;

+ 0
- 26
src/components/Buttons/LoginButton/LoginButton.js Bestand weergeven

@@ -1,26 +0,0 @@
import React from "react";
import { LoginButtonContainer, LoginButtonStyled } from "./LoginButton.styled";
import PropTypes from "prop-types";


//Currently not in use
export const LoginButton = (props) => {
return (
<LoginButtonContainer style={props.containerStyle}>
<LoginButtonStyled {...props} sx={props.style} variant="contained">
Dugme
</LoginButtonStyled>
</LoginButtonContainer>
);
};

LoginButton.propTypes = {
children: PropTypes.node,
type: PropTypes.string,
variant: PropTypes.string,
style: PropTypes.any,
containerStyle: PropTypes.any,
fullWidth: PropTypes.bool,
buttonColor: PropTypes.string,
onClick: PropTypes.func
};

+ 0
- 11
src/components/Buttons/LoginButton/LoginButton.styled.js Bestand weergeven

@@ -1,11 +0,0 @@
import { Box, Button } from "@mui/material";
import styled from "styled-components";


export const LoginButtonContainer = styled(Box)`
`

export const LoginButtonStyled = styled(Button)`
background-color: ${props => props.backgroundColor};
color: ${props => props.textColor}
`

+ 0
- 34
src/components/Buttons/PrimaryButtonWithIcon/PrimaryButtonWithIcon.js Bestand weergeven

@@ -1,34 +0,0 @@
import React from "react";
import PropTypes from "prop-types";
import {
PrimaryButtonWithIconContainer,
IconStyled,
PrimaryButtonWithIconStyled,
} from "./PrimaryButtonWithIcon.styled";

const PrimaryButtonWithIcon = (props) => {
return (
<PrimaryButtonWithIconContainer
style={props.containerStyle}
className={props.className}
>
<PrimaryButtonWithIconStyled sx={props.style} {...props.buttonProps} onClick={props.onClick}>
<IconStyled style={props.iconStyle}>{props.icon}</IconStyled>
{props.children}
</PrimaryButtonWithIconStyled>
</PrimaryButtonWithIconContainer>
);
};

PrimaryButtonWithIcon.propTypes = {
children: PropTypes.node,
icon: PropTypes.node,
className: PropTypes.string,
containerStyle: PropTypes.any,
style: PropTypes.any,
iconStyle: PropTypes.any,
buttonProps: PropTypes.any,
onClick: PropTypes.func,
};

export default PrimaryButtonWithIcon;

+ 0
- 28
src/components/Buttons/PrimaryButtonWithIcon/PrimaryButtonWithIcon.styled.js Bestand weergeven

@@ -1,28 +0,0 @@
import { Box } from "@mui/material";
import styled from "styled-components";
import { Icon } from "../../Icon/Icon";
import { PrimaryButton } from "../PrimaryButton/PrimaryButton";

export const PrimaryButtonWithIconContainer = styled(Box)``;

export const PrimaryButtonWithIconStyled = styled(PrimaryButton)`
position: relative;
`;

export const IconStyled = styled(Icon)`
position: absolute;
padding: 0;
left: 10px;
top: 0;
bottom: 0;
margin-top: auto;
margin-bottom: auto;
line-height: 21px;
& span {
position: absolute;
top: 0;
bottom: 0;
margin-top: auto;
margin-bottom: auto;
}
`;

+ 34
- 30
src/components/Cards/ChatCard/ChatCard.js Bestand weergeven

@@ -1,10 +1,9 @@
import React, { useEffect, useState } from "react";
import React, { useMemo } from "react";
import PropTypes from "prop-types";
import {
CheckButton,
OfferImage,
OfferTitle,
OfferCard,
ChatOffer,
Commands,
ChatInfo,
@@ -26,34 +25,38 @@ import {
OfferTitleMobile,
PhoneIconContainer,
PhoneIcon,
LocationIconContainer,
} from "./ChatCard.styled";
import { ReactComponent as Location } from "../../../assets/images/svg/location.svg";
import selectedTheme from "../../../themes";
import { useHistory } from "react-router-dom";
import useScreenDimensions from "../../../hooks/useScreenDimensions";
//import { useSelector } from "react-redux";
import { useTranslation } from "react-i18next";

const ChatCard = (props) => {
const history = useHistory();
const dimensions = useScreenDimensions();
const [isMobile, setIsMobile] = useState(dimensions.width < 600);
const chat = props.chat;
const { t } = useTranslation();

useEffect(() => {
const resize = (e) => {
if (e.target.outerWidth < 600 && isMobile) setIsMobile(false);
else if (e.target.outerWidth > 600 && !isMobile) setIsMobile(true);
};
window.addEventListener("resize", resize);
const chat = useMemo(() => {
return props.chat;
}, [props.chat]);

return () => window.removeEventListener("resize", resize);
}, []);
const lastMessage = useMemo(() => {
if (chat?.chat?.messages && chat?.chat?.messages?.length > 0) {
return chat.chat.messages[chat.chat.messages.length - 1]?.text;
}
return "";
}, [chat]);

const routeToItem = (userId) => {
history.push(`/messages/${userId}`);
const routeToItem = () => {
history.push(`/messages/${chat?.chat?._id}`);
};
return (
<ChatCardContainer onClick={isMobile ? () => routeToItem(chat?.chat?._id) : () => {}}>
<ChatCardContainer
onClick={
dimensions.width < 600 ? () => routeToItem(chat?.chat?._id) : () => {}
}
>
<Col>
<UserImgWrapper>
<UserImage src={chat?.interlocutorData?.image} />
@@ -61,38 +64,39 @@ const ChatCard = (props) => {

<ChatInfo>
<UserName>{chat?.interlocutorData?.name}</UserName>

{/* Only shows on Mobile */}
<OfferCardContainerMobile>
<OfferTextMobile>Proizvod:</OfferTextMobile>
<OfferTextMobile>{t("messages.cardProduct")}</OfferTextMobile>
<OfferTitleMobile>{chat?.offerData?.name}</OfferTitleMobile>
</OfferCardContainerMobile>
{/* ^^^^^ */}
<LastMessage>
{chat?.chat?.messages
? chat?.chat?.messages[chat?.chat?.messages?.length - 1]?.text
: ""}
</LastMessage>

<LastMessage>{lastMessage}</LastMessage>
<LocationContainer>
<LocationIcon>
<Location height="12px" width="12px" />
</LocationIcon>
<LocationIconContainer>
<LocationIcon />
</LocationIconContainer>
<XSText>{chat?.interlocutorData?.location}</XSText>
</LocationContainer>
</ChatInfo>
</Col>
<Line />

{/* Only shows on Desktop */}
<Col mobileDisappear>
<ChatOffer>
<OfferImgWrapper>
<OfferImage src={chat?.offerData?.firstImage} />
</OfferImgWrapper>
<OfferCardContainer>
<OfferText>Proizvod:</OfferText>
<OfferText>{t("messages.cardProduct")}</OfferText>
<OfferTitle>{chat?.offerData?.name}</OfferTitle>
</OfferCardContainer>
</ChatOffer>
</Col>
{/* ^^^^^^^ */}

<Commands>
<PhoneIconContainer>
<PhoneIcon />
@@ -102,9 +106,9 @@ const ChatCard = (props) => {
textcolor={selectedTheme.primaryPurple}
variant={"outlined"}
style={{ fontWeight: "600" }}
onClick={() => routeToItem(chat?.chat?._id)}
onClick={routeToItem}
>
Pogledaj caskanje
{t("messages.seeChats")}
</CheckButton>
</Commands>
</ChatCardContainer>
@@ -129,7 +133,7 @@ ChatCard.propTypes = {
vertical: PropTypes.bool,
chat: PropTypes.any,
};
OfferCard.defaultProps = {
ChatCard.defaultProps = {
halfwidth: false,
sponsored: false,
};

+ 5
- 193
src/components/Cards/ChatCard/ChatCard.styled.js Bestand weergeven

@@ -3,9 +3,8 @@ import styled from "styled-components";
import selectedTheme from "../../../themes";
import { IconButton } from "../../Buttons/IconButton/IconButton";
import { PrimaryButton } from "../../Buttons/PrimaryButton/PrimaryButton";
import { Icon } from "../../Icon/Icon";
import { ReactComponent as Eye } from "../../../assets/images/svg/eye-striked.svg";
import { ReactComponent as Phone } from "../../../assets/images/svg/phone.svg";
import { ReactComponent as Location } from "../../../assets/images/svg/location.svg";

export const ChatCardContainer = styled(Container)`
display: flex;
@@ -68,20 +67,9 @@ export const OfferImgWrapper = styled(Box)`
min-width: 72px;
max-width: 72px;
`;

export const OfferFlexContainer = styled(Container)`
display: flex;
flex-direction: row;
margin: 0;
padding: 0;
max-height: 184px;
@media (max-width: 600px) {
${(props) =>
props.vertical &&
`
flex-direction: column;
`}
}
export const LocationIcon = styled(Location)`
height: 12px;
width: 12px;
`;

export const OfferCardContainer = styled(Container)`
@@ -106,19 +94,6 @@ export const OfferCardContainerMobile = styled(Box)`
}
`;

export const OfferInfo = styled(Box)`
display: flex;
flex: 2;
flex-direction: column;
justify-content: space-between;
margin-left: 18px;
${(props) =>
props.vertical &&
`
margin-left: 0;
margin-top: 5px;
`}
`;
export const OfferTitle = styled(Typography)`
font-family: "Open Sans";
flex: 1;
@@ -166,129 +141,6 @@ export const OfferTitleMobile = styled(Typography)`
}
`;

export const OfferAuthor = styled(Box)`
display: flex;
flex: 1;
flex-direction: column;
`;
export const OfferAuthorName = styled(Typography)`
font-family: "Open Sans";
line-height: 22px;
font-size: 16px;
color: ${selectedTheme.primaryText};
@media (max-width: 600px) {
font-size: 14px;
${(props) =>
props.vertical &&
`
line-height: 19px;
font-size: 14px;
position: absolute;
bottom: 80px;
`}
}
`;
export const OfferLocation = styled(Typography)`
font-family: "Open Sans";
color: ${selectedTheme.primaryDarkText};
line-height: 16px;
font-size: 12px;
${(props) =>
props.vertical &&
`
font-size: 12px;
margin-top: 5px;
position: absolute;
bottom: 61px;
`}
`;
export const OfferDetails = styled(Box)`
display: flex;
flex-direction: row;
flex-wrap: ${(props) => (!props.halfwidth ? "no-wrap" : "wrap")};
justify-content: start;
gap: 1rem;
@media (max-width: 650px) {
flex-direction: column;
justify-content: center;
gap: 0;
}
`;
export const OfferCategory = styled(Box)`
font-family: "Open Sans";
color: ${selectedTheme.primaryText};
line-height: 16px;
font-size: 12px;
${(props) =>
props.vertical &&
`
position: absolute;
bottom: 15px;
`}
`;
export const OfferPackage = styled(Box)`
font-family: "Open Sans";
color: ${selectedTheme.primaryText};
line-height: 16px;
font-size: 12px;
`;
export const OfferViews = styled(Box)`
font-family: "Open Sans";
color: ${selectedTheme.primaryText};
line-height: 16px;
font-size: 12px;
${(props) =>
props.vertical &&
`
display: none;
`}
`;
export const OfferDescriptionTitle = styled(Box)`
font-family: "Open Sans";
font-size: 12px;
color: ${selectedTheme.primaryDarkText};
line-height: 16px;
`;
export const OfferDescriptionText = styled(Box)`
font-family: "Open Sans";
font-size: 16px;
color: ${selectedTheme.primaryDarkText};
line-height: 22px;
max-width: calc(100% - 230px);
max-height: 120px;
overflow: hidden;
display: -webkit-box;
-webkit-line-clamp: 5;
-webkit-box-orient: vertical;
@media (max-width: 1500px) {
display: none;
}
`;
export const OfferDescription = styled(Box)`
flex: 3;
margin: auto 0;
padding-left: 35px;
@media (max-width: 1500px) {
display: none;
}
`;

export const DetailIcon = styled(Icon)`
& svg {
width: 14px;
position: relative;
top: -1px;
}
`;
export const DetailText = styled(Typography)`
font-family: "Open Sans";
color: ${selectedTheme.primaryText};
line-height: 16px;
font-size: 12px;
position: relative;
top: -2px;
left: 3px;
`;
export const CheckButton = styled(PrimaryButton)`
width: 180px;
height: 48px;
@@ -338,44 +190,6 @@ export const PhoneIconContainer = styled(IconButton)`
}
}
`;
export const OfferImageContainer = styled(Box)`
min-width: 144px;
min-height: 144px;
width: 144px;
height: 144px;
@media (max-width: 600px) {
${(props) =>
!props.vertical
? `
min-width: 108px;
min-height: 108px;
width: 108px;
height: 108px;
`
: `margin-top: 4px;`}
border-radius: 4px;
overflow: hidden;
box-shadow: 4px 4px 9px rgba(0, 0, 0, 0.12);
}
`;
export const OfferTitleAboveImage = styled(OfferTitle)`
padding-bottom: 12px;
padding-top: 5px;
padding-left: 1px;
display: block;
${(props) => props.vertical && `display: none;`}
@media (min-width: 551px) {
display: none;
}
`;
export const EyeIcon = styled(Eye)`
width: 12px;
height: 11px;
@media (max-width: 600px) {
position: relative;
top: 1px !important;
}
`;

export const ChatOffer = styled(Box)`
display: flex;
@@ -409,8 +223,6 @@ export const Commands = styled(Box)`
}
`;

export const OfferCard = styled(Box)``;

export const ChatInfo = styled(Box)`
height: 100%;
display: flex;
@@ -471,7 +283,7 @@ export const LocationContainer = styled(Box)`
}
`;

export const LocationIcon = styled(Box)`
export const LocationIconContainer = styled(Box)`
height: 12px;
width: auto;
position: relative;

+ 8
- 60
src/components/Cards/CreateOfferCard/CreateOffer.js Bestand weergeven

@@ -1,38 +1,17 @@
/* eslint-disable */
import React, { useEffect, useState } from "react";
import React, { useState } from "react";
import PropTypes from "prop-types";
import { useFormik } from "formik";
import { useDispatch, useSelector } from "react-redux";
import { NavLink, useHistory } from "react-router-dom";
import * as Yup from "yup";
import { useTranslation } from "react-i18next";
import { fetchLogin } from "../../../store/actions/login/loginActions";
import { FORGOT_PASSWORD_PAGE, HOME_PAGE } from "../../../constants/pages";
import { ReactComponent as VisibilityOn } from "../../../assets/images/svg/eye-striked.svg";
import { ReactComponent as VisibilityOff } from "../../../assets/images/svg/eye.svg";
import Backdrop from "../../MUI/BackdropComponent";
import { selectIsLoadingByActionType } from "../../../store/selectors/loadingSelectors";
import { LOGIN_USER_LOADING } from "../../../store/actions/login/loginActionConstants";
import { TextField } from "../../TextFields/TextField/TextField";
import { PrimaryButton } from "../../Buttons/PrimaryButton/PrimaryButton";
import { IconButton } from "../../Buttons/IconButton/IconButton";
import Link from "../../Link/Link";
import { useHistory } from "react-router-dom";
import { HOME_PAGE } from "../../../constants/pages";
import {
CreateOfferContainer,
CreateOfferTitle,
CreateOfferFormContainer,
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";
@@ -47,31 +26,12 @@ import BackdropComponent from "../../MUI/BackdropComponent";

const CreateOffer = ({ history, closeCreateOfferModal, editOffer, offer }) => {
const dispatch = useDispatch();
const { t } = useTranslation();
const [informations, setInformations] = useState({});
const [showPassword, setShowPassword] = useState(false);
const [currentStep, setCurrentStep] = useState(1);
const handleClickShowPassword = () => setShowPassword(!showPassword);
const handleMouseDownPassword = () => setShowPassword(!showPassword);
const categories = useSelector((state) => state.categories.categories);
const historyRouter = useHistory();

// When user refreshes page
// useEffect(() => {
// function redirectClient() {
// if (!tokens.RefreshToken && !tokens.JwtToken) {
// return;
// }
// }

// redirectClient();
// }, [history, tokens]);

const isLoading = useSelector(
selectIsLoadingByActionType(LOGIN_USER_LOADING)
);

const handleApiResponseSuccess = (status) => {
const handleApiResponseSuccess = () => {
if (editOffer === undefined) {
const userId = historyRouter.location.pathname.slice(
9,
@@ -90,24 +50,11 @@ const CreateOffer = ({ history, closeCreateOfferModal, editOffer, offer }) => {
}
};

const handleSubmit = (values) => {
const { username: email, password: password } = values;
dispatch(
fetchLogin({
email,
password,
handleApiResponseSuccess,
})
);
};

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

console.log(informations);

const newImgs =
informations.images &&
informations.images
@@ -126,8 +73,6 @@ const CreateOffer = ({ history, closeCreateOfferModal, editOffer, offer }) => {
}
}

console.log(informations);

const offerData = {
name: informations.nameOfProduct,
description: informations.description,
@@ -175,7 +120,7 @@ const CreateOffer = ({ history, closeCreateOfferModal, editOffer, offer }) => {
category,
condition,
description,
images,
// images,
location,
nameOfProduct,
subcategory,
@@ -251,5 +196,8 @@ CreateOffer.propTypes = {
pathname: PropTypes.string,
}),
}),
closeCreateOfferModal: PropTypes.func,
editOffer: PropTypes.bool,
offer: PropTypes.object,
};
export default CreateOffer;

+ 63
- 62
src/components/Cards/CreateOfferCard/FirstPart/FirstPartCreateOffer.js Bestand weergeven

@@ -29,8 +29,6 @@ const FirstPartCreateOffer = (props) => {
let scat = categories.filter(
(cat) => cat.name === props.offer.category.name
);

console.log(categories);
console.log(scat[0].subcategories.map((x) => x.name));
setSubcat(scat[0].subcategories.map((x) => x.name));
}
@@ -67,15 +65,12 @@ const FirstPartCreateOffer = (props) => {

const handleSubcategories = (category) => {
const filtered = categories.filter((cat) => cat.name === category);
console.log(filtered[0].subcategories.map((c) => c.name));
setSubcat(filtered[0].subcategories.map((c) => c.name));
};

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

<FieldLabel leftText={t("offer.title")} />
<TitleField
name="nameOfProduct"
@@ -122,68 +117,74 @@ const FirstPartCreateOffer = (props) => {
/>
)}

<FieldLabel leftText={t("offer.location")} />
<SelectField
defaultValue={
props.offer === undefined ? "default" : props.offer.location.city
}
onChange={(value) => {
formik.setFieldValue("location", value.target.value);
}}
>
<SelectOption value="default">{t("offer.choseLocation")}</SelectOption>
{locations.map((loc) => {
return (
<SelectOption key={loc._if} value={loc.city}>
{loc.city}
</SelectOption>
);
})}
</SelectField>

<FieldLabel leftText={t("offer.category")} />
<SelectField
defaultValue={
props.offer === undefined ? "default" : props.offer.category.name
}
onChange={(value) => {
formik.setFieldValue("category", value.target.value);
}}
>
<SelectOption value="default">{t("offer.choseCategory")}</SelectOption>
{categories.map((cat, i) => {
return (
<SelectOption
key={i}
value={cat.name}
onClick={() => handleSubcategories(cat.name)}
>
{cat.name}
</SelectOption>
);
})}
</SelectField>
<FieldLabel leftText={t("offer.location")} />
<SelectField
defaultValue={
props.offer === undefined ? "default" : props.offer.location.city
}
onChange={(value) => {
formik.setFieldValue("location", value.target.value);
}}
>
<SelectOption value="default">
{t("offer.choseLocation")}
</SelectOption>
{locations.map((loc) => {
return (
<SelectOption key={loc._if} value={loc.city}>
{loc.city}
</SelectOption>
);
})}
</SelectField>

<FieldLabel leftText={t("offer.subcategory")} />
<SelectField
defaultValue={
props.offer === undefined ? "default" : props.offer.subcategory
}
// defaultValue="default"
onChange={(value) => {
formik.setFieldValue("subcategory", value.target.value);
}}
>
<SelectOption value="default">{t("offer.choseSubcategory")}</SelectOption>
{subcat &&
subcat.map((sub, i) => {
<FieldLabel leftText={t("offer.category")} />
<SelectField
defaultValue={
props.offer === undefined ? "default" : props.offer.category.name
}
onChange={(value) => {
formik.setFieldValue("category", value.target.value);
}}
>
<SelectOption value="default">
{t("offer.choseCategory")}
</SelectOption>
{categories.map((cat, i) => {
return (
<SelectOption key={i} value={sub}>
{sub}
<SelectOption
key={i}
value={cat.name}
onClick={() => handleSubcategories(cat.name)}
>
{cat.name}
</SelectOption>
);
})}
</SelectField>
</SelectField>

<FieldLabel leftText={t("offer.subcategory")} />
<SelectField
defaultValue={
props.offer === undefined ? "default" : props.offer.subcategory
}
// defaultValue="default"
onChange={(value) => {
formik.setFieldValue("subcategory", value.target.value);
}}
>
<SelectOption value="default">
{t("offer.choseSubcategory")}
</SelectOption>
{subcat &&
subcat.map((sub, i) => {
return (
<SelectOption key={i} value={sub}>
{sub}
</SelectOption>
);
})}
</SelectField>
</CreateOfferFormContainer>

<NextButton

+ 1
- 39
src/components/Cards/CreateOfferCard/SecondPart/SecondPartCreateOffer.js Bestand weergeven

@@ -25,19 +25,9 @@ const SecondPartCreateOffer = (props) => {
const [images, setImages] = useState(
Array.apply(null, Array(numberOfImages)).map(() => {})
); // 3 images
const { t } = useTranslation();

useEffect(() => {
// let editedImages = [];

// if (props.offer !== undefined && props.offer.images.length === 1) {
// editedImages.push(props.offer.images[0]);
// editedImages.push("");
// editedImages.push("");
// } else if (props.offer !== undefined && props.offer.images.length === 2) {
// editedImages.push(props.offer.images[0]);
// editedImages.push(props.offer.images[1]);
// editedImages.push("");
// }
setImages((prevState) => {
let editedImages = [...prevState];
if (props.offer !== undefined && props.offer.images.length === 1) {
@@ -46,7 +36,6 @@ const SecondPartCreateOffer = (props) => {

if (props.offer !== undefined && props.offer.images.length === 2) {
editedImages[0] = props.offer.images[0];

editedImages[1] = props.offer.images[1];
}

@@ -61,7 +50,6 @@ const SecondPartCreateOffer = (props) => {
return [...newState];
});
};
const { t } = useTranslation();

const imagesEmpty = useMemo(() => {
let numOfImagesEmpty = 0;
@@ -70,10 +58,6 @@ const SecondPartCreateOffer = (props) => {
});
return numOfImagesEmpty;
}, [images]);
// for (let i = 0; i < numberOfImages; i++) {
// let item = images[i];
// if (item === null || item === undefined) imagesEmpty++;
// }

const handleSubmit = (values) => {
props.handleNext(values);
@@ -90,8 +74,6 @@ const SecondPartCreateOffer = (props) => {
enableReinitialize: true,
});

console.log("slike", images);

return (
<>
<CreateOfferFormContainer component="form" onSubmit={formik.handleSubmit}>
@@ -107,25 +89,6 @@ const SecondPartCreateOffer = (props) => {
/>
);
})}
{/* {props.offer === undefined
? images.map((item, index) => (
<ImagePicker
key={index}
image={item}
setImage={(image) => setImage(index, image)}
deleteImage={() => setImage(index, null)}
showDeleteIcon
/>
))
: editedImages.map((item, index) => (
<ImagePicker
key={index}
image={item}
setImage={(image) => setImage(index, image)}
deleteImage={() => setImage(index, null)}
showDeleteIcon
/>
))} */}
</Scroller>
<SupportedFormats>
<Trans i18nKey="offer.supportedImagesFormats" />
@@ -163,7 +126,6 @@ const SecondPartCreateOffer = (props) => {
buttoncolor={selectedTheme.primaryPurple}
textcolor="white"
onClick={formik.handleSubmit}
// disabled={imagesEmpty === numberOfImages}
disabled={
props.offer === undefined ? imagesEmpty === numberOfImages : false
}

+ 7
- 10
src/components/Cards/CreateOfferCard/ThirdPart/ThirdPartCreateOffer.js Bestand weergeven

@@ -1,16 +1,13 @@
import React from "react";
import PropTypes from "prop-types";
import {
// CreateOfferFormContainer,
PreviewCard,
} from "./ThirdPartCreateOffer.styled";
import { PreviewCard } from "./ThirdPartCreateOffer.styled";
import { NextButton } from "../FirstPart/FirstPartCreateOffer.styled";
import selectedTheme from "../../../../themes";
import { CreateOfferFormContainer } from "../CreateOffer.styled";
import { useTranslation } from "react-i18next";

const ThirdPartCreateOffer = (props) => {
const {t} = useTranslation();
const { t } = useTranslation();
const offer = {
offer: {
category: {
@@ -31,7 +28,11 @@ const ThirdPartCreateOffer = (props) => {

return (
<>
<CreateOfferFormContainer currentStep={3} component="form" onSubmit={handleSubmit}>
<CreateOfferFormContainer
currentStep={3}
component="form"
onSubmit={handleSubmit}
>
<PreviewCard
offer={offer}
showBarterButton={false}
@@ -48,10 +49,6 @@ const ThirdPartCreateOffer = (props) => {
textcolor="white"
fullWidth
onClick={handleSubmit}
// disabled={
// formik.values.username.length === 0 ||
// formik.values.password.length === 0
// }
>
{t("offer.publish")}
</NextButton>

+ 46
- 0
src/components/Cards/FilterCard/Choser/CategoryChoser/CategoryChoser.js Bestand weergeven

@@ -0,0 +1,46 @@
import React from "react";
import PropTypes from "prop-types";
import FilterRadioDropdown from "../../FilterDropdown/Radio/FilterRadioDropdown";
import { CategoryChosenIcon, CategoryIcon } from "./CategoryChoser.styled";
import { useTranslation } from "react-i18next";

const firstCategoryOption = {
label: "SVE KATEGORIJE",
value: { _id: 0 },
};

const CategoryChoser = (props) => {
const filters = props.filters;
const { t } = useTranslation();
const handleSelectCategory = (category) => {
filters.setSelectedCategory(category);
filters.clearSelectedSubcategory();
};
return (
<FilterRadioDropdown
data={[...filters?.categories]}
icon={
filters.selectedCategory?.name ? (
<CategoryChosenIcon />
) : (
<CategoryIcon />
)
}
title={
filters.selectedCategory?.name
? filters.selectedCategory?.name
: t("filters.categories.title")
}
searchPlaceholder={t("filters.categories.placeholder")}
setSelected={handleSelectCategory}
selected={filters.selectedCategory}
firstOption={firstCategoryOption}
/>
);
};

CategoryChoser.propTypes = {
filters: PropTypes.any,
};

export default CategoryChoser;

+ 8
- 0
src/components/Cards/FilterCard/Choser/CategoryChoser/CategoryChoser.styled.js Bestand weergeven

@@ -0,0 +1,8 @@
import { ReactComponent as Category } from "../../../../../assets/images/svg/category.svg";
import { ReactComponent as CategoryChosen } from "../../../../../assets/images/svg/category-chosen.svg";
import styled from "styled-components"

export const CategoryChosenIcon = styled(CategoryChosen)`
`
export const CategoryIcon = styled(Category)`
`

+ 30
- 0
src/components/Cards/FilterCard/Choser/LocationChoser/LocationChoser.js Bestand weergeven

@@ -0,0 +1,30 @@
import React from "react";
import PropTypes from "prop-types";
import FilterCheckboxDropdown from "../../FilterDropdown/Checkbox/FilterCheckboxDropdown";
import { LocationIcon } from "./LocationChoser.styled";
import { useTranslation } from "react-i18next";

const LocationChoser = (props) => {
const { t } = useTranslation();
const filters = props.filters;
return (
<FilterCheckboxDropdown
searchPlaceholder={t("filters.location.placeholder")}
data={[...filters.locations]}
filters={
filters?.selectedLocations?.length > 0
? [...filters.selectedLocations]
: []
}
icon={<LocationIcon />}
title={t("filters.location.title")}
setItemsSelected={filters.setSelectedLocations}
/>
);
};

LocationChoser.propTypes = {
filters: PropTypes.any,
};

export default LocationChoser;

+ 5
- 0
src/components/Cards/FilterCard/Choser/LocationChoser/LocationChoser.styled.js Bestand weergeven

@@ -0,0 +1,5 @@
import styled from "styled-components";
import { ReactComponent as Location } from "../../../../../assets/images/svg/location.svg";

export const LocationIcon = styled(Location)`
`

+ 63
- 0
src/components/Cards/FilterCard/Choser/SubcategoryChoser/SubcategoryChoser.js Bestand weergeven

@@ -0,0 +1,63 @@
import React, { useEffect, useMemo, useState } from "react";
import PropTypes from "prop-types";
import { SubcategoryIcon } from "./SubcategoryChoser.styled";
import FilterRadioDropdown from "../../FilterDropdown/Radio/FilterRadioDropdown";
import _ from "lodash";
import { useTranslation } from "react-i18next";

const firstSubcategoryOption = {
label: "SVE PODKATEGORIJE",
value: { _id: 0 },
};

const SubcategoryChoser = (props) => {
const filters = props.filters;
const { t } = useTranslation();
const [isOpened, setIsOpened] = useState(false);
const [isDisabled, setIsDisabled] = useState(true);

const setInitialOpen = useMemo(() => {
return _.once(() => {
setIsOpened(true);
});
}, []);

useEffect(() => {
if (!filters.selectedCategory || filters.selectedCategory?._id === 0) {
setIsOpened(false);
setIsDisabled(true);
} else {
setIsDisabled(false);
setInitialOpen();
}
}, [filters.selectedCategory]);

const handleOpen = () => {
setIsOpened((prevState) => !prevState);
};
return (
<FilterRadioDropdown
data={filters.subcategories ? [...filters.subcategories] : []}
icon={<SubcategoryIcon />}
title={
filters.selectedSubcategory?.name
? filters.selectedSubcategory?.name
: t("filters.subcategories.title")
}
searchPlaceholder={t("filters.subcategories.placeholder")}
setSelected={filters.setSelectedSubcategory}
selected={filters.selectedSubcategory}
open={isOpened}
disabled={isDisabled}
handleOpen={handleOpen}
firstOption={firstSubcategoryOption}
/>
);
};

SubcategoryChoser.propTypes = {
filters: PropTypes.any,
};

export default SubcategoryChoser;

+ 4
- 0
src/components/Cards/FilterCard/Choser/SubcategoryChoser/SubcategoryChoser.styled.js Bestand weergeven

@@ -0,0 +1,4 @@
import styled from "styled-components";
import { ReactComponent as Subcategory } from "../../../../../assets/images/svg/subcategory.svg";

export const SubcategoryIcon = styled(Subcategory)``;

+ 15
- 141
src/components/Cards/FilterCard/FilterCard.js Bestand weergeven

@@ -1,165 +1,39 @@
import React, { useEffect, useState } from "react";
import React from "react";
import PropTypes from "prop-types";
import {
ContentContainer,
FilterCardContainer,
Footer,
Header,
Title,
} from "./FilterCard.styled";
import { ReactComponent as Subcategory } from "../../../assets/images/svg/subcategory.svg";
import { ReactComponent as Category } from "../../../assets/images/svg/category.svg";
import { ReactComponent as CategoryChosen } from "../../../assets/images/svg/category-chosen.svg";
import { ReactComponent as Location } from "../../../assets/images/svg/location.svg";
import Link from "../../Link/Link";
import { PrimaryButton } from "../../Buttons/PrimaryButton/PrimaryButton";
import FilterCheckboxDropdown from "./FilterDropdown/Checkbox/FilterCheckboxDropdown";
import FilterRadioDropdown from "./FilterDropdown/Radio/FilterRadioDropdown";
import { useTranslation } from "react-i18next";
import selectedTheme from "../../../themes";
import { ContentContainer, FilterCardContainer } from "./FilterCard.styled";
import useFilters from "../../../hooks/useFilters";
import HeaderBack from "../../ItemDetails/Header/Header";
import FilterHeader from "./FilterHeader/FilterHeader";
import FilterFooter from "./FilterFooter/FilterFooter";
import CategoryChoser from "./Choser/CategoryChoser/CategoryChoser";
import SubcategoryChoser from "./Choser/SubcategoryChoser/SubcategoryChoser";
import LocationChoser from "./Choser/LocationChoser/LocationChoser";

const FilterCard = (props) => {
const { t } = useTranslation();
const [isOpened, setIsOpened] = useState(false);
const [isDisabled, setIsDisabled] = useState(true);
const filters = useFilters(props.myOffers);

useEffect(() => {
if (!filters.selectedCategory || filters.selectedCategory?._id === 0) {
setIsOpened(false);
setIsDisabled(true);
} else {
setIsDisabled(false);
}
}, [filters.selectedCategory]);

const handleSelectCategory = (category) => {
filters.setSelectedCategory(category);
filters.setSelectedSubcategory();
};

const handleOpen = () => {
setIsOpened((prevState) => !prevState);
};

const handleFilters = () => {
filters.applyFilters();
if (props.closeResponsive) props.closeResponsive();
};
const clearFilters = () => {
filters.clearFilters();
};

return (
<FilterCardContainer
responsiveOpen={props.responsiveOpen}
responsive={props.responsive}
myOffers={props.myOffers}
>
{/* Header title for my offers */}
{props.myOffers && <HeaderBack />}
<Header>
<Title>{t("filters.title")}</Title>
<Link
to="#"
textsize={"12px"}
font={"Open Sans"}
onClick={clearFilters}
>
{t("filters.cancel")}
</Link>
</Header>

<FilterHeader />

<ContentContainer>
{/* Categories */}
<FilterRadioDropdown
data={[...filters?.categories]}
icon={
filters.selectedCategory?.name ? <CategoryChosen /> : <Category />
}
title={
filters.selectedCategory?.name
? filters.selectedCategory?.name
: t("filters.categories.title")
}
searchPlaceholder={t("filters.categories.placeholder")}
setSelected={handleSelectCategory}
selected={filters.selectedCategory}
firstOption={{
label: "SVE KATEGORIJE",
value: { _id: 0 },
}}
/>
<CategoryChoser filters={filters} />

{/* Subcategories */}
<FilterRadioDropdown
data={filters.subcategories ? [...filters.subcategories] : []}
icon={<Subcategory />}
title={
filters.selectedSubcategory?.name
? filters.selectedSubcategory?.name
: t("filters.subcategories.title")
}
searchPlaceholder={t("filters.subcategories.placeholder")}
setSelected={filters.setSelectedSubcategory}
selected={filters.selectedSubcategory}
open={isOpened}
disabled={isDisabled}
handleOpen={handleOpen}
firstOption={{
label: "SVE PODKATEGORIJE",
value: { _id: 0 },
}}
/>
<SubcategoryChoser filters={filters} />

{/* Locations */}
<FilterCheckboxDropdown
searchPlaceholder={t("filters.location.placeholder")}
data={[...filters.locations]}
filters={
filters?.selectedLocations?.length > 0
? [...filters.selectedLocations]
: []
}
icon={<Location />}
title={t("filters.location.title")}
setItemsSelected={filters.setSelectedLocations}
/>
<LocationChoser filters={filters} />
</ContentContainer>

<Footer responsiveOpen={props.responsiveOpen}>
{props.responsiveOpen && (
<PrimaryButton
variant="outlined"
fullWidth
onClick={props.closeResponsive}
textcolor={selectedTheme.primaryPurple}
font="Open Sans"
style={{
fontWeight: "600",
fontSize: "12px",
border: "0",
textAlign: "center",
}}
>
ZATVORI
</PrimaryButton>
)}
<PrimaryButton
variant="outlined"
fullWidth
onClick={handleFilters}
textcolor={selectedTheme.primaryPurple}
font="Open Sans"
style={{
fontWeight: "600",
fontSize: "12px",
borderColor: selectedTheme.primaryPurple,
}}
>
{t("filters.usefilters")}
</PrimaryButton>
</Footer>
<FilterFooter />
</FilterCardContainer>
);
};

+ 3
- 36
src/components/Cards/FilterCard/FilterCard.styled.js Bestand weergeven

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

export const FilterCardContainer = styled(Box)`
position: fixed;
@@ -50,40 +49,6 @@ export const FilterCardContainer = styled(Box)`
margin-top: -14px;
}
`;
export const Title = styled(Typography)`
font-size: 24px;
line-height: 33px;
font-weight: 700;
font-family: "Open Sans";
color: ${selectedTheme.primaryText};
position: relative;
`;
export const Header = styled(Box)`
display: flex;
flex-direction: row;
justify-content: space-between;
align-items: center;
margin-bottom: 1rem;
`;

export const Footer = styled(Box)`
position: "sticky";
${(props) =>
props.responsiveOpen &&
`
flex-direction: row;
display: flex;
justify-content: space-around;`}
bottom: 0;
& div button {
height: 48px;
padding-top: 7px;
}
& div button:hover {
background-color: ${selectedTheme.primaryPurple} !important;
color: ${selectedTheme.primaryBackgroundColor} !important;
}
`;
export const ContentContainer = styled(Box)`
overflow-y: auto;
height: 100%;
@@ -101,3 +66,5 @@ export const ContentContainer = styled(Box)`
scrollbar-color: #ddd;
${() => window.scrollbars.visible && `padding-right: 15px`};
`;



+ 7
- 4
src/components/Cards/FilterCard/FilterDropdown/Radio/FilterRadioDropdown.js Bestand weergeven

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

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

}, [props.selected]);

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

+ 61
- 0
src/components/Cards/FilterCard/FilterFooter/FilterFooter.js Bestand weergeven

@@ -0,0 +1,61 @@
import React from "react";
import PropTypes from "prop-types";
import { FilterFooterContainer } from "./FilterFooter.styled";
import selectedTheme from "../../../../themes";
import { PrimaryButton } from "../../../Buttons/PrimaryButton/PrimaryButton";
import { useTranslation } from "react-i18next";
import useFilters from "../../../../hooks/useFilters";

const FilterFooter = (props) => {
const { t } = useTranslation();
const filters = useFilters();
const handleFilters = () => {
filters.applyFilters();
if (props.closeResponsive) props.closeResponsive();
};
return (
<FilterFooterContainer>
{props.responsiveOpen && (
<PrimaryButton
variant="outlined"
fullWidth
onClick={props.closeResponsive}
textcolor={selectedTheme.primaryPurple}
font="Open Sans"
style={{
fontWeight: "600",
fontSize: "12px",
border: "0",
textAlign: "center",
}}
>
{t("common.close")}
</PrimaryButton>
)}
<PrimaryButton
variant="outlined"
fullWidth
onClick={handleFilters}
textcolor={selectedTheme.primaryPurple}
font="Open Sans"
style={{
fontWeight: "600",
fontSize: "12px",
borderColor: selectedTheme.primaryPurple,
}}
>
{t("filters.usefilters")}
</PrimaryButton>
</FilterFooterContainer>
);
};

(FilterFooter.propTypes = {
responsiveOpen: PropTypes.bool,
closeResponsive: PropTypes.func,
}),
(FilterFooter.defaultProps = {
responsiveOpen: false,
});

export default FilterFooter;

+ 22
- 0
src/components/Cards/FilterCard/FilterFooter/FilterFooter.styled.js Bestand weergeven

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

export const FilterFooterContainer = styled(Box)`
position: "sticky";
${(props) =>
props.responsiveOpen &&
`
flex-direction: row;
display: flex;
justify-content: space-around;`}
bottom: 0;
& div button {
height: 48px;
padding-top: 7px;
}
& div button:hover {
background-color: ${selectedTheme.primaryPurple} !important;
color: ${selectedTheme.primaryBackgroundColor} !important;
}
`;

+ 28
- 0
src/components/Cards/FilterCard/FilterHeader/FilterHeader.js Bestand weergeven

@@ -0,0 +1,28 @@
import React from "react";
import PropTypes from "prop-types";
import { FilterHeaderContainer, Title } from "./FilterHeader.styled";
import { useTranslation } from "react-i18next";
import useFilters from "../../../../hooks/useFilters";
import Link from "../../../Link/Link";

const FilterHeader = () => {
const filters = useFilters();
const { t } = useTranslation();
const clearFilters = () => {
filters.clearFilters();
};
return (
<FilterHeaderContainer>
<Title>{t("filters.title")}</Title>
<Link to="#" textsize={"12px"} font={"Open Sans"} onClick={clearFilters}>
{t("filters.cancel")}
</Link>
</FilterHeaderContainer>
);
};

FilterHeader.propTypes = {
children: PropTypes.node,
};

export default FilterHeader;

+ 19
- 0
src/components/Cards/FilterCard/FilterHeader/FilterHeader.styled.js Bestand weergeven

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

export const FilterHeaderContainer = styled(Box)`
display: flex;
flex-direction: row;
justify-content: space-between;
align-items: center;
margin-bottom: 1rem;
`;
export const Title = styled(Typography)`
font-size: 24px;
line-height: 33px;
font-weight: 700;
font-family: "Open Sans";
color: ${selectedTheme.primaryText};
position: relative;
`;

+ 0
- 19
src/components/Cards/HomeListCard/HomeListCard.js Bestand weergeven

@@ -1,19 +0,0 @@
import React from 'react';
//import PropTypes from 'prop-types';
//import SectionLoader from '../Loader/SectionLoader';
import { Box } from '@mui/system';

const HomeListCard = () => {
return (
<Box> Title </Box>
);
};

// AuthCard.propTypes = {
// children: PropTypes.node,
// title: PropTypes.string,
// subtitle: PropTypes.string,
// isLoading: PropTypes.bool,
// };

export default HomeListCard;

+ 29
- 0
src/components/Cards/ItemDetailsCard/Information/Information.js Bestand weergeven

@@ -0,0 +1,29 @@
import React from "react";
import PropTypes from "prop-types";
import selectedTheme from "../../../../themes";
import { InfoGroup, InfoIcon, InfoText } from "./Information.styled";

const Information = (props) => {
return (
<InfoGroup hide={props.hide}>
<InfoIcon
color={selectedTheme.iconStrokeColor}
component="span"
size="16px"
>
{/* <CategoryIcon width={"14px"} /> */}
{props.icon}
</InfoIcon>
{/* <InfoText>{offer?.offer?.category?.name}</InfoText> */}
<InfoText>{props.value}</InfoText>
</InfoGroup>
);
};

Information.propTypes = {
icon: PropTypes.node,
value: PropTypes.string,
hide: PropTypes.bool,
};

export default Information;

+ 20
- 0
src/components/Cards/ItemDetailsCard/Information/Information.styled.js Bestand weergeven

@@ -0,0 +1,20 @@
import { Box, Typography } from "@mui/material";
import styled from "styled-components";

export const InfoGroup = styled(Box)`
display: ${props => props.hide ? 'none' : 'flex'};
flex-direction: row;
align-items: center;
gap: 4px;
`;
export const InfoIcon = styled(Box)`
display: flex;
align-items: center;
`;
export const InfoText = styled(Typography)`
font-family: "Open Sans";
text-transform: capitalize;
@media (max-width: 600px) {
font-size: 12px;
}
`;

+ 109
- 135
src/components/Cards/ItemDetailsCard/ItemDetailsCard.js Bestand weergeven

@@ -1,14 +1,12 @@
import React, { useEffect } from "react";
import React, { useEffect, useMemo, useState } from "react";
import PropTypes from "prop-types";
import {
CheckButton,
ItemDetailsCardContainer,
OfferInfo,
Info,
DateEditDeleteContainer,
PostDate,
InfoIcon,
InfoText,
InfoGroup,
OfferTitle,
OfferDescriptionText,
OfferDescriptionTitle,
@@ -16,177 +14,153 @@ import {
OfferDetails,
OfferImage,
Scroller,
CategoryIcon,
SubcategoryIcon,
QuantityIcon,
EyeIcon,
EditIconContainer,
EditIcon,
RemoveIconContainer,
RemoveIcon,
} from "./ItemDetailsCard.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";
import { useDispatch, useSelector } from "react-redux";
import { selectLatestChats } from "../../../store/selectors/chatSelectors";
import { useHistory } from "react-router-dom";
import { increaseCounter } from "../../../store/actions/counter/counterActions";
import _ from "lodash";
import { selectUserId } from "../../../store/selectors/loginSelectors";
import { formatDateLocale } from "../../../util/helpers/dateHelpers";
import { startChat } from "../../../util/helpers/chatHelper";
import Information from "./Information/Information";
import { useTranslation } from "react-i18next";
import DeleteOffer from "../OfferCard/DeleteOffer/DeleteOffer";
import CreateOffer from "../CreateOfferCard/CreateOffer";

const ItemDetailsCard = (props) => {
const [showModalRemove, setShowModalRemove] = useState(false);
const [showModalEdit, setShowModalEdit] = useState(false);
const offer = props.offer;
const history = useHistory();
const chats = useSelector(selectLatestChats);
const userId = useSelector(selectUserId);
const { t } = useTranslation();
const dispatch = useDispatch();
const dateCreated = new Date(offer?.offer?._created);

const increaseOfferCounter = useMemo(() => {
return _.once(function (id) {
dispatch(increaseCounter(id));
});
}, []);

useEffect(() => {
if (offer?.offer?._id) {
_.once(function () {
dispatch(increaseCounter(offer?.offer?._id));
})();
increaseOfferCounter(offer?.offer?._id);
}
}, [offer]);

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();
const date = formatDateLocale(new Date(offer?.offer?._created));

const startExchange = () => {
const chatItem = chats.find(
(item) => item.chat.offerId === offer?.offer?._id
);
if (chatItem !== undefined) {
history.push(`/messages/${chatItem.chat._id}`);
} else {
if (offer?.offer?.userId !== userId) {
history.push(`/messages/newMessage`, {
offerId: offer?.offer?._id,
});
}
}
startChat(chats, offer, userId);
};

const closeEditModalHandler = () => {
setShowModalEdit(false);
};

const closeRemoveModalHandler = () => {
setShowModalRemove(false);
};

console.log(offer);
return (
<ItemDetailsCardContainer
sponsored={props.sponsored.toString()}
halfwidth={props.halfwidth ? 1 : 0}
className={props.className}
>
<OfferInfo>
<Info>
<InfoGroup>
<InfoIcon
color={selectedTheme.iconStrokeColor}
component="span"
size="16px"
>
<Category width={"14px"} />
</InfoIcon>
<InfoText>{offer?.offer?.category?.name}</InfoText>
</InfoGroup>
<InfoGroup>
<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>
</InfoGroup>
{!props.hideViews && (
<InfoGroup views>
<InfoIcon color={"black"} component="span" size="12px" last>
<Eye width={"18px"} height={"20px"} />
</InfoIcon>
<InfoText>{offer?.offer?.views?.count}</InfoText>
</InfoGroup>
)}
</Info>
<PostDate>
{dayCreated}.{monthCreated}.{yearCreated}
</PostDate>
</OfferInfo>
<Details
hasScrollBar={!props.showPublishButton}
exchange={props.showExchangeButton}
<>
<ItemDetailsCardContainer
sponsored={props.sponsored.toString()}
halfwidth={props.halfwidth ? 1 : 0}
className={props.className}
>
<OfferTitle>{offer?.offer?.name}</OfferTitle>
<Scroller>
{offer?.offer?.images?.map((item) => {
return <OfferImage src={item} key={item} />;
})}
</Scroller>
<OfferDetails>
<OfferDescriptionTitle>Opis:</OfferDescriptionTitle>
<OfferDescriptionText showBarterButton={props.showExchangeButton}>
{offer?.offer?.description}
</OfferDescriptionText>
</OfferDetails>
</Details>
{!props.halfwidth && props.showExchangeButton ? (
<React.Fragment>
<OfferInfo>
<Info>
<Information
icon={<CategoryIcon />}
value={offer?.offer?.category?.name}
/>
<Information
icon={<SubcategoryIcon />}
value={offer?.offer?.subcategory}
/>
<Information
icon={<QuantityIcon />}
value={offer?.offer?.condition}
/>
<Information
icon={<EyeIcon />}
value={offer?.offer?.views?.count}
/>
</Info>
<DateEditDeleteContainer>
<PostDate>{date}</PostDate>
<EditIconContainer onClick={() => setShowModalEdit(true)}>
<EditIcon />
</EditIconContainer>
<RemoveIconContainer onClick={() => setShowModalRemove(true)}>
<RemoveIcon />
</RemoveIconContainer>
</DateEditDeleteContainer>
</OfferInfo>
<Details
hasScrollBar={!props.showPublishButton}
exchange={props.showExchangeButton}
>
<OfferTitle>{offer?.offer?.name}</OfferTitle>
<Scroller>
{offer?.offer?.images?.map((item) => {
return <OfferImage src={item} key={item} />;
})}
</Scroller>
<OfferDetails>
<OfferDescriptionTitle>
{t("itemDetailsCard.description")}
</OfferDescriptionTitle>
<OfferDescriptionText showBarterButton={props.showExchangeButton}>
{offer?.offer?.description}
</OfferDescriptionText>
</OfferDetails>
</Details>
{!props.halfwidth && props.showExchangeButton && (
<CheckButton
variant={props.sponsored ? "contained" : "outlined"}
buttoncolor={selectedTheme.primaryPurple}
textcolor={props.sponsored ? "white" : selectedTheme.primaryPurple}
style={{ fontWeight: "600" }}
onClick={startExchange}
>
Trampi
{t("itemDetailsCard.startExchangeButton")}
</CheckButton>
</React.Fragment>
) : (
<></>
)}
</ItemDetailsCardContainer>
{showModalRemove && (
<DeleteOffer
offer={offer.offer}
closeModalHandler={closeRemoveModalHandler}
/>
)}
{showModalEdit && (
<CreateOffer
editOffer
offer={offer.offer}
closeCreateOfferModal={closeEditModalHandler}
/>
)}
</ItemDetailsCardContainer>
</>
);
};

ItemDetailsCard.propTypes = {
children: PropTypes.node,
id: PropTypes.number,
title: PropTypes.string,
description: PropTypes.string,
category: PropTypes.string,
subcategory: PropTypes.string,
condition: PropTypes.string,
showNumberOfViews: PropTypes.bool,
author: PropTypes.string,
location: PropTypes.string,
images: PropTypes.node,
quantity: PropTypes.number,
package: PropTypes.string,
numberOfViews: PropTypes.number,
halfwidth: PropTypes.bool,
sponsored: PropTypes.bool,
offer: PropTypes.any,
hideViews: PropTypes.bool,
showExchangeButton: PropTypes.bool,
// offer: PropTypes.shape({
// images: PropTypes.any,
// name:PropTypes.string,
// description:PropTypes.string,
// condition:PropTypes.string,
// category:PropTypes.shape({
// name:PropTypes.string
// }),
// location:PropTypes.shape({
// city:PropTypes.string
// })
// })
showBarterButton: PropTypes.bool,
showPublishButton: PropTypes.bool,
className: PropTypes.string,

+ 51
- 16
src/components/Cards/ItemDetailsCard/ItemDetailsCard.styled.js Bestand weergeven

@@ -5,6 +5,13 @@ import selectedTheme from "../../../themes";
import { PrimaryButton } from "../../Buttons/PrimaryButton/PrimaryButton";
import { Icon } from "../../Icon/Icon";
import HorizontalScroller from "../../Scroller/HorizontalScroller";
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 { IconButton } from "../../Buttons/IconButton/IconButton";
import { ReactComponent as Edit } from "../../../assets/images/svg/edit.svg";
import { ReactComponent as Remove } from "../../../assets/images/svg/trash.svg";

export const ItemDetailsCardContainer = styled(Container)`
display: flex;
@@ -39,12 +46,33 @@ export const OfferInfo = styled(Box)`
margin: 0;
}
`;
export const InfoGroup = styled(Box)`
export const DateEditDeleteContainer = styled(Box)`
display: flex;
flex-direction: row;
align-items: center;
gap: 4px;
`;
export const EditIconContainer = styled(IconButton)`
width: 40px;
height: 40px;
background-color: ${selectedTheme.primaryIconBackgroundColor};
border-radius: 100%;
padding-top: 2px;
text-align: center;
margin-left: 18px;
`;
export const EditIcon = styled(Edit)``;

export const RemoveIconContainer = styled(IconButton)`
width: 40px;
height: 40px;
background-color: ${selectedTheme.primaryIconBackgroundColor};
border-radius: 100%;
padding-top: 2px;
text-align: center;
margin-left: 18px;
`;

export const RemoveIcon = styled(Remove)``;

export const PostDate = styled(Typography)`
font-family: "Open Sans";
font-size: 12px;
@@ -76,17 +104,6 @@ export const Info = styled(Box)`
left: 5px;
}
`;
export const InfoIcon = styled(Box)`
display: flex;
align-items: center;
`;
export const InfoText = styled(Typography)`
font-family: "Open Sans";
text-transform: capitalize;
@media (max-width: 600px) {
font-size: 12px;
}
`;
export const OfferTitle = styled(Typography)`
font-family: "Open Sans";
flex: 1;
@@ -176,7 +193,8 @@ export const OfferDescriptionText = styled(Box)`
color: ${selectedTheme.primaryDarkText};
line-height: 22px;
padding-bottom: 20px;
max-width: ${(props) => props.showBarterButton ? "calc(100% - 230px)" : "100%"};
max-width: ${(props) =>
props.showBarterButton ? "calc(100% - 230px)" : "100%"};
@media (max-width: 600px) {
font-size: 14px;
max-width: 100%;
@@ -219,6 +237,7 @@ export const CheckButton = styled(PrimaryButton)`
position: absolute;
bottom: 9px;
right: 12px;
font-weight: 600;
&:hover button {
background-color: ${selectedTheme.primaryPurple} !important;
color: white !important;
@@ -245,7 +264,8 @@ export const Details = styled(Box)`
@media screen and (max-width: 600px) {
margin-top: 15px;
${(props) =>
!props.hasScrollBar && props.exchange &&
!props.hasScrollBar &&
props.exchange &&
`
overflow: hidden;
max-height: none;`}
@@ -267,3 +287,18 @@ export const PublishButtonContainer = styled(Box)`
justify-content: center;
margin-bottom: 30px;
`;
export const CategoryIcon = styled(Category)`
width: 14px;
`;
export const SubcategoryIcon = styled(Subcategory)`
width: 14px;
`;
export const QuantityIcon = styled(Quantity)`
width: 22px;
height: 16px;
`;

export const EyeIcon = styled(Eye)`
width: 18px;
height: 20px;
`;

+ 14
- 0
src/components/Cards/ItemDetailsCard/OfferDetails/OfferDetails.js Bestand weergeven

@@ -0,0 +1,14 @@
import React from 'react'
import PropTypes from 'prop-types'

const OfferDetails = () => {
return (
<div>OfferDetails</div>
)
}

OfferDetails.propTypes = {
offer: PropTypes.any,
}

export default OfferDetails

+ 0
- 0
src/components/Cards/ItemDetailsCard/OfferDetails/OfferDetails.styled.js Bestand weergeven


+ 2
- 4
src/components/Cards/MiniChatCard/MiniChatCard.js Bestand weergeven

@@ -15,10 +15,8 @@ const MiniChatCard = (props) => {
const { t } = useTranslation();
const history = useHistory();
const changeChat = () => {
// if (!props.selected) {
history.push(`/messages/${props?.chat?.chat?._id}`)
// }
}
history.push(`/messages/${props?.chat?.chat?._id}`);
};
return (
<MiniChatCardContainer selected={props.selected} onClick={changeChat}>
<ProfileImage src={props?.chat?.interlocutorData?.image} />

src/components/Cards/OfferCard/DeleteOffer.js → src/components/Cards/OfferCard/DeleteOffer/DeleteOffer.js Bestand weergeven

@@ -15,15 +15,15 @@ import {
RemoveIcon,
SaveButton,
CategoryIcon,
} from "./DeleteOffer.styles";
import selectedTheme from "../../../themes";
import { ReactComponent as Category } from "../../../assets/images/svg/category.svg";
import BackdropComponent from "../../MUI/BackdropComponent";
} from "./DeleteOffer.styled";
import selectedTheme from "../../../../themes";
import { ReactComponent as Category } from "../../../../assets/images/svg/category.svg";
import BackdropComponent from "../../../MUI/BackdropComponent";
import { useDispatch } from "react-redux";
import {
fetchProfileOffers,
removeOffer,
} from "../../../store/actions/offers/offersActions";
} from "../../../../store/actions/offers/offersActions";
import { useTranslation, Trans } from "react-i18next";

const DeleteOffer = (props) => {

src/components/Cards/OfferCard/DeleteOffer.styles.js → src/components/Cards/OfferCard/DeleteOffer/DeleteOffer.styled.js Bestand weergeven

@@ -1,11 +1,11 @@
import { Typography } from "@mui/material";
import { Box } from "@mui/system";
import styled from "styled-components";
import { PrimaryButton } from "../../Buttons/PrimaryButton/PrimaryButton";
import { Icon } from "../../Icon/Icon";
import { ReactComponent as Remove } from "../../../assets/images/svg/trash-gold.svg";
import selectedTheme from "../../../themes";
import { IconButton } from "../../Buttons/IconButton/IconButton";
import { PrimaryButton } from "../../../Buttons/PrimaryButton/PrimaryButton";
import { Icon } from "../../../Icon/Icon";
import { ReactComponent as Remove } from "../../../../assets/images/svg/trash-gold.svg";
import selectedTheme from "../../../../themes";
import { IconButton } from "../../../Buttons/IconButton/IconButton";

export const DeleteOfferContainer = styled(Box)`
width: 537px;

+ 11
- 7
src/components/Cards/OfferCard/OfferCard.js Bestand weergeven

@@ -30,7 +30,7 @@ import {
StarIcon,
StarIconContainer,
} from "./OfferCard.styled";
import DeleteOffer from "./DeleteOffer";
import DeleteOffer from "./DeleteOffer/DeleteOffer";
import { ReactComponent as Category } from "../../../assets/images/svg/category.svg";
import { ReactComponent as Message } from "../../../assets/images/svg/mail.svg";
import selectedTheme from "../../../themes";
@@ -114,12 +114,16 @@ const OfferCard = (props) => {
</DetailIcon>
<DetailText>{props?.offer?.category?.name}</DetailText>
</OfferCategory>
{props.dontShowViews ? (<></>) : (<OfferViews vertical={props.vertical}>
<DetailIcon color="black" component="span" size="16px">
<EyeIcon />
</DetailIcon>
<DetailText>{props?.offer?.views?.count}</DetailText>
</OfferViews>)}
{props.dontShowViews ? (
<></>
) : (
<OfferViews vertical={props.vertical}>
<DetailIcon color="black" component="span" size="16px">
<EyeIcon />
</DetailIcon>
<DetailText>{props?.offer?.views?.count}</DetailText>
</OfferViews>
)}
</OfferDetails>
</OfferInfo>
{!props.halfwidth ? (

+ 8
- 2
src/components/ItemDetails/Header/Header.js Bestand weergeven

@@ -4,6 +4,7 @@ import { useHistory } from "react-router-dom";
//import { IconButton } from "../../Buttons/IconButton/IconButton";
import { HeaderContainer, HeaderText, ButtonContainer } from "./Header.styled";
import { ArrowButton } from "../../Buttons/ArrowButton/ArrowButton";
import { useTranslation } from "react-i18next";

// const DownArrow = (props) => (
// <IconStyled {...props}>
@@ -13,16 +14,21 @@ import { ArrowButton } from "../../Buttons/ArrowButton/ArrowButton";

const Header = (props) => {
const history = useHistory();
const { t } = useTranslation();

const handleBackButton = () => {
history.goBack();
};

return (
<HeaderContainer onClick={handleBackButton} component="header" className={props.className}>
<HeaderContainer
onClick={handleBackButton}
component="header"
className={props.className}
>
<ButtonContainer>
<ArrowButton side={"left"}></ArrowButton>
<HeaderText>Nazad na objave</HeaderText>
<HeaderText>{t("profile.back")}</HeaderText>
</ButtonContainer>
</HeaderContainer>
);

+ 27
- 9
src/components/Profile/ProfileOffers/ProfileOffers.js Bestand weergeven

@@ -39,18 +39,20 @@ const ProfileOffers = (props) => {
const userId = useSelector(selectUserId);

const messageUser = (offer) => {
const chatItem = chats.find(item => item.chat.offerId === offer?.offer?._id);
const chatItem = chats.find(
(item) => item.chat.offerId === offer?.offer?._id
);
if (chatItem !== undefined) {
history.push(`/messages/${chatItem.chat._id}`)
history.push(`/messages/${chatItem.chat._id}`);
} else {
if (offer?.offer?.userId !== userId) {
history.push(`/messages/newMessage`, {
offerId: offer?.offer?._id
})
offerId: offer?.offer?._id,
});
}
}
}
};
useEffect(() => {
let newOffersToShow = [...offersToShow];
if (sortOption.value === sortEnum.OLD.value) {
@@ -134,7 +136,9 @@ const ProfileOffers = (props) => {
sx={{ mb: 1.4 }}
>
<OffersIcon />
<HeaderTitle>{props.isMyProfile ? "Moje objave" : "Objave kompanije"}</HeaderTitle>
<HeaderTitle>
{props.isMyProfile ? "Moje objave" : "Objave kompanije"}
</HeaderTitle>
</Grid>
<SearchInput
fullWidth
@@ -155,12 +159,26 @@ const ProfileOffers = (props) => {
<OffersContainer>
{dimensions.width > 600 ? (
offersToShow.map((item) => (
<OfferCard isMyOffer={props.isMyProfile} offer={item} key={JSON.stringify(item)} pinned messageUser={messageUser} />
<OfferCard
isMyOffer={props.isMyProfile}
offer={item}
key={JSON.stringify(item)}
pinned
messageUser={messageUser}
/>
))
) : (
<OffersScroller hideArrows>
{offersToShow.map((item) => (
<OfferCard vertical isMyOffer={props.isMyProfile} offer={item} key={JSON.stringify(item)} pinned messageUser={messageUser} />))}
<OfferCard
vertical
isMyOffer={props.isMyProfile}
offer={item}
key={JSON.stringify(item)}
pinned
messageUser={messageUser}
/>
))}
</OffersScroller>
)}
</OffersContainer>

src/components/ProfileCard/EditProfile.js → src/components/ProfileCard/EditProfile/EditProfile.js Bestand weergeven

@@ -1,6 +1,6 @@
import React, { useState, useEffect } from "react";
import PropTypes from "prop-types";
import BackdropComponent from "../MUI/BackdropComponent";
import BackdropComponent from "../../MUI/BackdropComponent";
import {
EditProfileContainer,
ProfileImageContainer,
@@ -16,18 +16,18 @@ import {
ErrorMessage,
ProfileImagePicker,
} from "./EditProfile.styled";
import selectedTheme from "../../themes";
import selectedTheme from "../../../themes";
import { useFormik } from "formik";
import * as Yup from "yup";
import { ReactComponent as ArrowBack } from "../../assets/images/svg/arrow-back.svg";
import { ReactComponent as CloseIcon } from "../../assets/images/svg/close-modal.svg";
import { ReactComponent as ArrowBack } from "../../../assets/images/svg/arrow-back.svg";
import { ReactComponent as CloseIcon } from "../../../assets/images/svg/close-modal.svg";
import { useTranslation } from "react-i18next";
import {
editMineProfile,
fetchMineProfile,
} from "../../store/actions/profile/profileActions";
} from "../../../store/actions/profile/profileActions";
import { useDispatch } from "react-redux";
import useScreenDimensions from "../../hooks/useScreenDimensions";
import useScreenDimensions from "../../../hooks/useScreenDimensions";
import { useRouteMatch } from "react-router-dom";

const EditProfile = (props) => {
@@ -129,7 +129,6 @@ const EditProfile = (props) => {
value={formik.values.firmName}
onChange={formik.handleChange}
error={formik.touched.firmName && formik.errors.firmName}
// helperText={formik.touched.firmName && formik.errors.firmName}
margin="normal"
fullWidth
/>
@@ -139,7 +138,6 @@ const EditProfile = (props) => {
value={formik.values.firmPIB}
onChange={formik.handleChange}
error={formik.touched.firmPIB && formik.errors.firmPIB}
// helperText={formik.touched.firmPIB && formik.errors.firmPIB}
margin="normal"
fullWidth
/>
@@ -151,9 +149,6 @@ const EditProfile = (props) => {
value={formik.values.firmLocation}
onChange={formik.handleChange}
error={formik.touched.firmLocation && formik.errors.firmLocation}
// helperText={
// formik.touched.firmLocation && formik.errors.firmLocation
// }
margin="normal"
fullWidth
/>
@@ -188,9 +183,6 @@ const EditProfile = (props) => {
value={formik.values.firmPhone}
onChange={formik.handleChange}
error={formik.touched.firmPhone && formik.errors.firmPhone}
// helperText={
// formik.touched.firmPhone && formik.errors.firmPhone
// }
margin="normal"
fullWidth
/>
@@ -225,8 +217,6 @@ const EditProfile = (props) => {
) : (
<ButtonsContainer>
<SaveButton
// type="submit"
// variant="outlined"
height="44px"
width="155px"
buttoncolor={selectedTheme.primaryPurple}
@@ -260,8 +250,6 @@ EditProfile.propTypes = {
closeModalHandler: PropTypes.func,
setImage: PropTypes.func,
reFetchProfile: PropTypes.func,
// error: PropTypes.string,
// errorMessage: PropTypes.string,
};

export default EditProfile;

src/components/ProfileCard/EditProfile.styled.js → src/components/ProfileCard/EditProfile/EditProfile.styled.js Bestand weergeven

@@ -1,8 +1,8 @@
import styled from "styled-components";
import { Box, TextField, Typography } from "@mui/material";
import ImagePicker from "../ImagePicker/ImagePicker";
import { PrimaryButton } from "../Buttons/PrimaryButton/PrimaryButton";
import { Label } from "../CheckBox/Label";
import ImagePicker from "../../ImagePicker/ImagePicker";
import { PrimaryButton } from "../../Buttons/PrimaryButton/PrimaryButton";
import { Label } from "../../CheckBox/Label";

export const EditProfileContainer = styled(Box)`
background-color: #fff;

+ 16
- 130
src/components/ProfileCard/ProfileCard.js Bestand weergeven

@@ -3,26 +3,14 @@ import PropTypes from "prop-types";
import {
EditButton,
ProfileCardWrapper,
ProfileName,
ProfilePIB,
ProfileMainInfo,
ProfileContact,
ContactItem,
ProfileStats,
StatsItem,
ProfileCardContainer,
AvatarImage,
ProfileCardHeader,
HeaderTitle,
PocketIcon,
LocationIcon,
MailIcon,
GlobeIcon,
ProfilePIBContainer,
EditIcon,
MessageIcon,
MessageButton,
ProfileInfoContainer,
} from "./ProfileCard.styled";
import { Grid, Stack } from "@mui/material";
import PersonOutlineIcon from "@mui/icons-material/PersonOutline";
import { useRouteMatch } from "react-router-dom";
import { fetchProfile } from "../../store/actions/profile/profileActions";
@@ -32,7 +20,10 @@ import { selectProfile } from "../../store/selectors/profileSelectors";
import { selectUserId } from "../../store/selectors/loginSelectors";
import { useState } from "react";
import { fetchProfileOffers } from "../../store/actions/offers/offersActions";
import EditProfile from "./EditProfile";
import EditProfile from "./EditProfile/EditProfile";
import ProfileMainInfo from "./ProfileMainInfo/ProfileMainInfo";
import ProfileContact from "./ProfileContact/ProfileContact";
import ProfileStats from "./ProfileStats/ProfileStats";
import { useTranslation } from "react-i18next";

const ProfileCard = () => {
@@ -81,16 +72,10 @@ const ProfileCard = () => {
return (
<>
<ProfileCardContainer>
<Grid
container
direction="row"
justifyContent="start"
alignItems="center"
sx={{ mb: 1.4 }}
>
<ProfileCardHeader>
<PersonOutlineIcon color="action" sx={{ mr: 0.9 }} />
<HeaderTitle>{t("profile.myProfile")}</HeaderTitle>
</Grid>
</ProfileCardHeader>
<ProfileCardWrapper variant="outlined" isMyProfile={isMyProfile}>
{isMyProfile ? (
<EditButton onClick={() => setEditProfileModal(true)}>
@@ -101,116 +86,17 @@ const ProfileCard = () => {
<MessageIcon />
</MessageButton>
)}
<Grid
container
direction="column"
justifyContent="center"
alignItems="start"
>
{/* Profile Main Info */}
<ProfileMainInfo
container
direction="row"
justifyContent="start"
alignItems="start"
>
<Grid
direction="column"
justifyContent="start"
alignItems="center"
>
<AvatarImage alt="Player.rs" src={profile?.image} />
</Grid>
<Grid
direction="column"
justifyContent="center"
alignItems="start"
sx={{ ml: 2 }}
>
<ProfileName isMyProfile={isMyProfile} variant="h5">
{profile?.company?.name}
</ProfileName>
<ProfilePIBContainer
container
direction="row"
justifyContent="center"
alignItems="center"
>
<PocketIcon />
<ProfilePIB isMyProfile={isMyProfile} variant="subtitle2">
{t("profile.PIB")} {profile?.company?.PIB}
</ProfilePIB>
</ProfilePIBContainer>
</Grid>
</ProfileMainInfo>
<ProfileInfoContainer>
{/* Profile Main Info */}
<ProfileMainInfo profile={profile} isMyProfile={isMyProfile} />
{/* Profile Contact */}
<ProfileContact
container
direction={{ xs: "column", sm: "row" }}
justifyContent={{ xs: "center", sm: "start" }}
alignItems={{ xs: "start", sm: "center" }}
>
<Stack direction="row">
<LocationIcon isMyProfile={isMyProfile} />
<ContactItem isMyProfile={isMyProfile} variant="subtitle2">
{profile?.company?.contacts?.location}
</ContactItem>
</Stack>
<Stack direction="row">
<MailIcon isMyProfile={isMyProfile} />
<ContactItem isMyProfile={isMyProfile} variant="subtitle2">
{profile?.email}
</ContactItem>
</Stack>
<Stack direction="row">
<GlobeIcon isMyProfile={isMyProfile} />
<ContactItem isMyProfile={isMyProfile} variant="subtitle2">
{profile?.company?.contacts?.web}
</ContactItem>
</Stack>
</ProfileContact>
<ProfileContact profile={profile} isMyProfile={isMyProfile} />
{/* Profile Stats */}
<ProfileStats
container
direction="row"
justifyContent="start"
alignItems="center"
>
<Grid
container
direction="column"
justifyContent="center"
alignItems="start"
sx={{ width: "fit-content" }}
>
<StatsItem variant="subtitle2">
<b>{profile?.statistics?.publishes?.count}</b>
{t("profile.publishes")}
</StatsItem>

<StatsItem variant="subtitle2">
<b>{percentOfSucceededExchanges}%</b>
{t("profile.successComunication")}
</StatsItem>
</Grid>
<Grid
container
direction="column"
justifyContent="center"
alignItems="start"
sx={{ width: "fit-content" }}
>
<StatsItem variant="subtitle2">
<b>{profile?.statistics?.views?.count}</b>
{t("profile.numberOfViews")}
</StatsItem>
<StatsItem variant="subtitle2">
<b>{percentOfSucceededExchanges}%</b>
{t("profile.successCooperation")}
</StatsItem>
</Grid>
</ProfileStats>
</Grid>
profile={profile}
percentOfSucceededExchanges={percentOfSucceededExchanges}
/>
</ProfileInfoContainer>
</ProfileCardWrapper>
</ProfileCardContainer>
{editProfileModal && (

+ 188
- 143
src/components/ProfileCard/ProfileCard.styled.js Bestand weergeven

@@ -2,10 +2,10 @@ import styled from "styled-components";
import { Card, Typography, Grid, Box } from "@mui/material";
import selectedTheme from "../../themes";
import { ReactComponent as Edit } from "../../assets/images/svg/edit.svg";
import { ReactComponent as Pocket } from "../../assets/images/svg/pocket.svg";
import { ReactComponent as Globe } from "../../assets/images/svg/globe.svg";
// import { ReactComponent as Pocket } from "../../assets/images/svg/pocket.svg";
// import { ReactComponent as Globe } from "../../assets/images/svg/globe.svg";
import { ReactComponent as Mail } from "../../assets/images/svg/mail.svg";
import { ReactComponent as Location } from "../../assets/images/svg/location.svg";
// import { ReactComponent as Location } from "../../assets/images/svg/location.svg";
// import { PRIMARY_PURPLE_COLOR, PRIMARY_YELLOW_COLOR } from '../../constants/stylesConstants';

export const ProfileCardContainer = styled(Box)`
@@ -52,97 +52,128 @@ export const ProfileCardWrapper = styled(Card)`
position: relative;
`;

export const ProfileName = styled(Typography)`
color: ${(props) =>
props.isMyProfile
? selectedTheme.primaryYellow
: selectedTheme.primaryPurple};
font-weight: 700;
font-size: 24px;
font-family: "Open Sans";
margin-bottom: 5px;
@media (max-width: 600px) {
font-size: 18px;
}
`;
// export const ProfileName = styled(Typography)`
// color: ${(props) =>
// props.isMyProfile
// ? selectedTheme.primaryYellow
// : selectedTheme.primaryPurple};
// font-weight: 700;
// font-size: 24px;
// font-family: "Open Sans";
// margin-bottom: 5px;
// @media (max-width: 600px) {
// font-size: 18px;
// }
// `;

export const ProfilePIB = styled(Typography)`
color: ${(props) =>
props.isMyProfile ? "white" : selectedTheme.primaryDarkText};
margin-top: 0.18rem;
font-family: "Open Sans";
font-size: 16px;
padding-top: 1px;
@media (max-width: 600px) {
font-size: 14px;
}
`;
export const ProfilePIBContainer = styled(Grid)`
position: relative;
left: 5px;
`;
// export const ProfilePIB = styled(Typography)`
// color: ${(props) =>
// props.isMyProfile ? "white" : selectedTheme.primaryDarkText};
// margin-top: 0.18rem;
// font-family: "Open Sans";
// font-size: 16px;
// padding-top: 1px;
// @media (max-width: 600px) {
// font-size: 14px;
// }
// `;
// export const ProfilePIBContainer = styled(Grid)`
// display: flex;
// justify-content: center;
// align-items: center;
// position: relative;
// left: 5px;
// `;

export const ProfileMainInfo = styled(Grid)``;
// export const ProfileMainInfo = styled(Grid)`
// display: flex;
// justify-content: start;
// align-items: start;
// `;

export const ProfileContact = styled(Grid)`
padding-top: 2rem;
padding-bottom: 2rem;
@media (max-width: 600px) {
padding-bottom: 1rem;
}
`;
// export const AvatarImageContainer = styled(Grid)`
// display: flex;
// justify-content: start;
// align-items: center;
// `;

export const ContactItem = styled(Typography)`
margin-right: 2rem;
margin-left: 0.4rem;
color: ${(props) =>
props.isMyProfile ? "white" : selectedTheme.primaryDarkText};
display: unset;
font-family: "Open Sans";
letter-spacing: 0.02em;
font-size: 16px;
position: relative;
bottom: 1px;
@media (max-width: 600px) {
font-size: 14px;
bottom: 4px;
}
`;
// export const ProfileMainInfoGrid = styled(Grid)`
// display: flex;
// flex-direction: column;
// align-items: start;
// margin-left: 16px;
// `;

export const StatsItem = styled(Typography)`
margin-right: 2rem;
display: unset;
margin-left: 1rem;
font-family: "Open Sans";
font-size: 16px;
margin-bottom: 2px;
@media (max-width: 600px) {
font-size: 12px;
}
`;
// export const ProfileContact = styled(Grid)`
// padding-top: 2rem;
// padding-bottom: 2rem;
// @media (max-width: 600px) {
// padding-bottom: 1rem;
// }
// `;

export const ProfileStats = styled(Grid)`
background: ${selectedTheme.primaryDarkTextSecond};
width: calc(100% + 2rem);
padding-top: 1.3rem;
padding-bottom: 1.3rem;
margin-bottom: -1rem;
margin-left: -1rem;
border-radius: 0 0 4px 4px;
`;
export const AvatarImage = styled.img`
min-height: 144px;
min-width: 144px;
width: 144px;
height: 144px;
border-radius: 100%;
@media (max-width: 600px) {
min-height: 90px;
min-width: 90px;
width: 90px;
height: 90px;
}
// export const ContactItem = styled(Typography)`
// margin-right: 2rem;
// margin-left: 0.4rem;
// color: ${(props) =>
// props.isMyProfile ? "white" : selectedTheme.primaryDarkText};
// display: unset;
// font-family: "Open Sans";
// letter-spacing: 0.02em;
// font-size: 16px;
// position: relative;
// bottom: 1px;
// @media (max-width: 600px) {
// font-size: 14px;
// bottom: 4px;
// }
// `;

// export const StatsItem = styled(Typography)`
// margin-right: 2rem;
// display: unset;
// margin-left: 1rem;
// font-family: "Open Sans";
// font-size: 16px;
// margin-bottom: 2px;
// @media (max-width: 600px) {
// font-size: 12px;
// }
// `;

// export const ProfileStats = styled(Grid)`
// display: flex;
// justify-content: start;
// align-items: center;
// background: ${selectedTheme.primaryDarkTextSecond};
// width: calc(100% + 2rem);
// padding-top: 1.3rem;
// padding-bottom: 1.3rem;
// margin-bottom: -1rem;
// margin-left: -1rem;
// border-radius: 0 0 4px 4px;
// `;
// export const AvatarImage = styled.img`
// min-height: 144px;
// min-width: 144px;
// width: 144px;
// height: 144px;
// border-radius: 100%;
// @media (max-width: 600px) {
// min-height: 90px;
// min-width: 90px;
// width: 90px;
// height: 90px;
// }
// `;

export const ProfileCardHeader = styled(Grid)`
display: flex;
justify-content: start;
align-items: center;
margin-bottom: 11px;
`;

export const HeaderTitle = styled(Typography)`
font-size: 16px;
font-family: "Open Sans";
@@ -152,62 +183,62 @@ export const HeaderTitle = styled(Typography)`
font-size: 12px;
}
`;
export const PocketIcon = styled(Pocket)`
width: 22px;
height: 22px;
position: relative;
left: -5px;
top: 2px;
& path {
stroke: #b4b4b4;
}
@media (max-width: 600px) {
width: 14px;
height: 14px;
}
`;
export const MailIcon = styled(Mail)`
height: 24px;
width: 24px;
& path {
stroke: ${(props) =>
props.isMyProfile
? selectedTheme.iconMineProfileColor
: selectedTheme.iconProfileColor};
}
@media (max-width: 600px) {
width: 14px;
height: 14px;
}
`;
export const GlobeIcon = styled(Globe)`
height: 22px;
width: 22px;
& path {
stroke: ${(props) =>
props.isMyProfile
? selectedTheme.iconMineProfileColor
: selectedTheme.iconProfileColor};
}
@media (max-width: 600px) {
width: 14px;
height: 14px;
}
`;
export const LocationIcon = styled(Location)`
height: 22px;
width: 22px;
& path {
stroke: ${(props) =>
props.isMyProfile
? selectedTheme.iconMineProfileColor
: selectedTheme.iconProfileColor};
}
@media (max-width: 600px) {
width: 14px;
height: 14px;
}
`;
// export const PocketIcon = styled(Pocket)`
// width: 22px;
// height: 22px;
// position: relative;
// left: -5px;
// top: 2px;
// & path {
// stroke: #b4b4b4;
// }
// @media (max-width: 600px) {
// width: 14px;
// height: 14px;
// }
// `;
// export const MailIcon = styled(Mail)`
// height: 24px;
// width: 24px;
// & path {
// stroke: ${(props) =>
// props.isMyProfile
// ? selectedTheme.iconMineProfileColor
// : selectedTheme.iconProfileColor};
// }
// @media (max-width: 600px) {
// width: 14px;
// height: 14px;
// }
// `;
// export const GlobeIcon = styled(Globe)`
// height: 22px;
// width: 22px;
// & path {
// stroke: ${(props) =>
// props.isMyProfile
// ? selectedTheme.iconMineProfileColor
// : selectedTheme.iconProfileColor};
// }
// @media (max-width: 600px) {
// width: 14px;
// height: 14px;
// }
// `;
// export const LocationIcon = styled(Location)`
// height: 22px;
// width: 22px;
// & path {
// stroke: ${(props) =>
// props.isMyProfile
// ? selectedTheme.iconMineProfileColor
// : selectedTheme.iconProfileColor};
// }
// @media (max-width: 600px) {
// width: 14px;
// height: 14px;
// }
// `;
export const MessageIcon = styled(Mail)`
width: 19.5px;
height: 19.5px;
@@ -223,3 +254,17 @@ export const MessageIcon = styled(Mail)`
right: 0.5px;
}
`;

export const ProfileInfoContainer = styled(Grid)`
display: flex;
flex-direction: column;
justify-content: center;
align-items: start;
`;

// export const ProfileStatsGrid = styled(Grid)`
// display: flex;
// flex-direction: column;
// justify-content: center;
// align-items: start;
// `;

+ 48
- 0
src/components/ProfileCard/ProfileContact/ProfileContact.js Bestand weergeven

@@ -0,0 +1,48 @@
import React from "react";
import PropTypes from "prop-types";
import {
ProfileContactContainer,
LocationIcon,
ContactItem,
MailIcon,
GlobeIcon,
} from "./ProfileContact.styled";
import { Stack } from "@mui/material";

const ProfileContact = (props) => {
return (
<ProfileContactContainer
container
direction={{ xs: "column", sm: "row" }}
justifyContent={{ xs: "center", sm: "start" }}
alignItems={{ xs: "start", sm: "center" }}
>
<Stack direction="row">
<LocationIcon isMyProfile={props.isMyProfile} />
<ContactItem isMyProfile={props.isMyProfile} variant="subtitle2">
{props.profile?.company?.contacts?.location}
</ContactItem>
</Stack>
<Stack direction="row">
<MailIcon isMyProfile={props.isMyProfile} />
<ContactItem isMyProfile={props.isMyProfile} variant="subtitle2">
{props.profile?.email}
</ContactItem>
</Stack>
<Stack direction="row">
<GlobeIcon isMyProfile={props.isMyProfile} />
<ContactItem isMyProfile={props.isMyProfile} variant="subtitle2">
{props.profile?.company?.contacts?.web}
</ContactItem>
</Stack>
</ProfileContactContainer>
);
};

ProfileContact.propTypes = {
profile: PropTypes.object,
isMyProfile: PropTypes.bool,
children: PropTypes.node,
};

export default ProfileContact;

+ 72
- 0
src/components/ProfileCard/ProfileContact/ProfileContact.styled.js Bestand weergeven

@@ -0,0 +1,72 @@
import styled from "styled-components";
import { Grid, Typography } from "@mui/material";
import { ReactComponent as Location } from "../../../assets/images/svg/location.svg";
import { ReactComponent as Mail } from "../../../assets/images/svg/mail.svg";
import { ReactComponent as Globe } from "../../../assets/images/svg/globe.svg";
import selectedTheme from "../../../themes";

export const ProfileContactContainer = styled(Grid)`
padding-top: 2rem;
padding-bottom: 2rem;
@media (max-width: 600px) {
padding-bottom: 1rem;
}
`;
export const LocationIcon = styled(Location)`
height: 22px;
width: 22px;
& path {
stroke: ${(props) =>
props.isMyProfile
? selectedTheme.iconMineProfileColor
: selectedTheme.iconProfileColor};
}
@media (max-width: 600px) {
width: 14px;
height: 14px;
}
`;
export const ContactItem = styled(Typography)`
margin-right: 2rem;
margin-left: 0.4rem;
color: ${(props) =>
props.isMyProfile ? "white" : selectedTheme.primaryDarkText};
display: unset;
font-family: "Open Sans";
letter-spacing: 0.02em;
font-size: 16px;
position: relative;
bottom: 1px;
@media (max-width: 600px) {
font-size: 14px;
bottom: 4px;
}
`;
export const MailIcon = styled(Mail)`
height: 24px;
width: 24px;
& path {
stroke: ${(props) =>
props.isMyProfile
? selectedTheme.iconMineProfileColor
: selectedTheme.iconProfileColor};
}
@media (max-width: 600px) {
width: 14px;
height: 14px;
}
`;
export const GlobeIcon = styled(Globe)`
height: 22px;
width: 22px;
& path {
stroke: ${(props) =>
props.isMyProfile
? selectedTheme.iconMineProfileColor
: selectedTheme.iconProfileColor};
}
@media (max-width: 600px) {
width: 14px;
height: 14px;
}
`;

+ 46
- 0
src/components/ProfileCard/ProfileMainInfo/ProfileMainInfo.js Bestand weergeven

@@ -0,0 +1,46 @@
import React from "react";
import PropTypes from "prop-types";
import {
ProfileMainInfoContainer,
AvatarImageContainer,
AvatarImage,
ProfileMainInfoGrid,
ProfileName,
ProfilePIBContainer,
PocketIcon,
ProfilePIB,
} from "./ProfileMainInfo.styled";
import { useTranslation } from "react-i18next";

const ProfileMainInfo = (props) => {
const { t } = useTranslation();
return (
<ProfileMainInfoContainer>
<AvatarImageContainer>
<AvatarImage
alt={props.profile?.company?.name}
src={props.profile?.image}
/>
</AvatarImageContainer>
<ProfileMainInfoGrid>
<ProfileName isMyProfile={props.isMyProfile} variant="h5">
{props.profile?.company?.name}
</ProfileName>
<ProfilePIBContainer>
<PocketIcon />
<ProfilePIB isMyProfile={props.isMyProfile} variant="subtitle2">
{t("profile.PIB")} {props.profile?.company?.PIB}
</ProfilePIB>
</ProfilePIBContainer>
</ProfileMainInfoGrid>
</ProfileMainInfoContainer>
);
};

ProfileMainInfo.propTypes = {
profile: PropTypes.object,
isMyProfile: PropTypes.bool,
children: PropTypes.node,
};

export default ProfileMainInfo;

+ 79
- 0
src/components/ProfileCard/ProfileMainInfo/ProfileMainInfo.styled.js Bestand weergeven

@@ -0,0 +1,79 @@
import styled from "styled-components";
import { Grid, Typography } from "@mui/material";
import selectedTheme from "../../../themes";
import { ReactComponent as Pocket } from "../../../assets/images/svg/pocket.svg";

export const ProfileMainInfoContainer = styled(Grid)`
display: flex;
justify-content: start;
align-items: start;
`;
export const AvatarImageContainer = styled(Grid)`
display: flex;
justify-content: start;
align-items: center;
`;
export const AvatarImage = styled.img`
min-height: 144px;
min-width: 144px;
width: 144px;
height: 144px;
border-radius: 100%;
@media (max-width: 600px) {
min-height: 90px;
min-width: 90px;
width: 90px;
height: 90px;
}
`;
export const ProfileMainInfoGrid = styled(Grid)`
display: flex;
flex-direction: column;
align-items: start;
margin-left: 16px;
`;
export const ProfileName = styled(Typography)`
color: ${(props) =>
props.isMyProfile
? selectedTheme.primaryYellow
: selectedTheme.primaryPurple};
font-weight: 700;
font-size: 24px;
font-family: "Open Sans";
margin-bottom: 5px;
@media (max-width: 600px) {
font-size: 18px;
}
`;
export const ProfilePIBContainer = styled(Grid)`
display: flex;
justify-content: center;
align-items: center;
position: relative;
left: 5px;
`;
export const PocketIcon = styled(Pocket)`
width: 22px;
height: 22px;
position: relative;
left: -5px;
top: 2px;
& path {
stroke: #b4b4b4;
}
@media (max-width: 600px) {
width: 14px;
height: 14px;
}
`;
export const ProfilePIB = styled(Typography)`
color: ${(props) =>
props.isMyProfile ? "white" : selectedTheme.primaryDarkText};
margin-top: 0.18rem;
font-family: "Open Sans";
font-size: 16px;
padding-top: 1px;
@media (max-width: 600px) {
font-size: 14px;
}
`;

+ 44
- 0
src/components/ProfileCard/ProfileStats/ProfileStats.js Bestand weergeven

@@ -0,0 +1,44 @@
import React from "react";
import PropTypes from "prop-types";
import {
ProfileStatsContainer,
ProfileStatsGrid,
StatsItem,
} from "./ProfileStats.styled";
import { useTranslation } from "react-i18next";

const ProfileStats = (props) => {
const { t } = useTranslation();
return (
<ProfileStatsContainer>
<ProfileStatsGrid>
<StatsItem variant="subtitle2">
<b>{props.profile?.statistics?.publishes?.count}</b>
{t("profile.publishes")}
</StatsItem>

<StatsItem variant="subtitle2">
<b>{props.percentOfSucceededExchanges}%</b>
{t("profile.successExchange")}
</StatsItem>
</ProfileStatsGrid>
<ProfileStatsGrid>
<StatsItem variant="subtitle2">
<b>{props.profile?.statistics?.views?.count}</b>
{t("profile.numberOfViews")}
</StatsItem>
<StatsItem variant="subtitle2">
<b>{props.percentOfSucceededExchanges}%</b>
{t("profile.successComunication")}
</StatsItem>
</ProfileStatsGrid>
</ProfileStatsContainer>
);
};

ProfileStats.propTypes = {
profile: PropTypes.object,
percentOfSucceededExchanges: PropTypes.number,
};

export default ProfileStats;

+ 33
- 0
src/components/ProfileCard/ProfileStats/ProfileStats.styled.js Bestand weergeven

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

export const ProfileStatsContainer = styled(Grid)`
display: flex;
justify-content: start;
align-items: center;
background: ${selectedTheme.primaryDarkTextSecond};
width: calc(100% + 2rem);
padding-top: 1.3rem;
padding-bottom: 1.3rem;
margin-bottom: -1rem;
margin-left: -1rem;
border-radius: 0 0 4px 4px;
`;
export const ProfileStatsGrid = styled(Grid)`
display: flex;
flex-direction: column;
justify-content: center;
align-items: start;
`;
export const StatsItem = styled(Typography)`
margin-right: 2rem;
display: unset;
margin-left: 1rem;
font-family: "Open Sans";
font-size: 16px;
margin-bottom: 2px;
@media (max-width: 600px) {
font-size: 12px;
}
`;

+ 5
- 0
src/hooks/useFilters.js Bestand weergeven

@@ -207,6 +207,7 @@ const useFilters = (myOffers) => {

// Setters
const setSelectedCategory = (payload) => {
console.log('payl: ', payload);
if (isApplied !== false) {
dispatch(setIsAppliedStatus(false));
}
@@ -222,6 +223,9 @@ const useFilters = (myOffers) => {
dispatch(setFilteredSubcategory(payload));
}
};
const clearSelectedSubcategory = () => {
setSelectedSubcategory();
}
const setSelectedLocations = (payload) => {
if (isApplied !== false) {
dispatch(setIsAppliedStatus(false));
@@ -235,6 +239,7 @@ const useFilters = (myOffers) => {
setSelectedCategory,
selectedSubcategory,
setSelectedSubcategory,
clearSelectedSubcategory,
selectedLocations,
setSelectedLocations,
categories,

+ 10
- 4
src/i18n/resources/rs.js Bestand weergeven

@@ -192,6 +192,7 @@ export default {
miniChatHeaderTitle: "Moje Poruke",
send: "Pošalji",
sendPlaceholder: "Poruka...",
seeChats: "Pogledaj ćaskanje",
},
editProfile: {
website: "Web Sajt*",
@@ -225,9 +226,14 @@ export default {
profile: {
myProfile: "Moj profil",
PIB: "PIB:",
publishes: "objava",
successComunication: "uspešna komunikacija",
numberOfViews: "ukupnih pregleda",
successCooperation: "korektna saradnja",
publishes: " objava",
successExchange: " uspešna trampa",
numberOfViews: " ukupnih pregleda",
successComunication: " korektna komunikacija",
back: "Nazad na objave",
},
itemDetailsCard: {
description: "Opis: ",
startExchangeButton: "Trampi",
},
};

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

@@ -24,8 +24,8 @@ export default {
getUserSecurityQuestion: "users/username/securityquestion",
confirmSecurityQuestion: "authenticate/confirm",
confirmForgotPassword: "users/passwords/reset_token",
resetPassword: "reset-password",
forgotPassword: "forgot-password",
resetPassword: "auth/reset-password",
forgotPassword: "auth/forgot-password",
refreshToken: "/auth/refresh",
generateToken: "/authenticate/generate",
authenticate:

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

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

+ 16
- 0
src/util/helpers/chatHelper.js Bestand weergeven

@@ -0,0 +1,16 @@
import history from "../../store/utils/history";

export const startChat = (chats, offer, userId) => {
const chatItem = chats.find(
(item) => item.chat.offerId === offer?.offer?._id
);
if (chatItem !== undefined) {
history.push(`/messages/${chatItem.chat._id}`);
} else {
if (offer?.offer?.userId !== userId) {
history.push(`/messages/newMessage`, {
offerId: offer?.offer?._id,
});
}
}
}

+ 13
- 0
src/util/helpers/dateHelpers.js Bestand weergeven

@@ -38,3 +38,16 @@ export function formatDateRange(dates) {
const end = formatDate(dates.end);
return i18next.t('common.date.range', { start, end });
}

export function formatDateLocale(date) {
const dayCreated =
date.getDate() < 10
? "0" + date.getDate()
: date.getDate();
const monthCreated =
date.getMonth() < 10
? "0" + (date.getMonth() + 1)
: date.getMonth() + 1;
const yearCreated = date.getFullYear();
return `${dayCreated}.${monthCreated}.${yearCreated}`;
}

Laden…
Annuleren
Opslaan