| @@ -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; | |||
| @@ -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; | |||
| @@ -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, | |||
| }; | |||
| @@ -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; | |||
| @@ -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, | |||
| }; | |||
| @@ -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"} | |||
| `; | |||
| @@ -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 | |||
| }; | |||
| @@ -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} | |||
| ` | |||
| @@ -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; | |||
| @@ -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; | |||
| } | |||
| `; | |||
| @@ -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, | |||
| }; | |||
| @@ -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; | |||
| @@ -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; | |||
| @@ -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 | |||
| @@ -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 | |||
| } | |||
| @@ -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> | |||
| @@ -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; | |||
| @@ -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)` | |||
| ` | |||
| @@ -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; | |||
| @@ -0,0 +1,5 @@ | |||
| import styled from "styled-components"; | |||
| import { ReactComponent as Location } from "../../../../../assets/images/svg/location.svg"; | |||
| export const LocationIcon = styled(Location)` | |||
| ` | |||
| @@ -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; | |||
| @@ -0,0 +1,4 @@ | |||
| import styled from "styled-components"; | |||
| import { ReactComponent as Subcategory } from "../../../../../assets/images/svg/subcategory.svg"; | |||
| export const SubcategoryIcon = styled(Subcategory)``; | |||
| @@ -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> | |||
| ); | |||
| }; | |||
| @@ -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`}; | |||
| `; | |||
| @@ -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={{ | |||
| @@ -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; | |||
| @@ -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; | |||
| } | |||
| `; | |||
| @@ -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; | |||
| @@ -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; | |||
| `; | |||
| @@ -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; | |||
| @@ -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; | |||
| @@ -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; | |||
| } | |||
| `; | |||
| @@ -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, | |||
| @@ -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; | |||
| `; | |||
| @@ -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 | |||
| @@ -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} /> | |||
| @@ -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) => { | |||
| @@ -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; | |||
| @@ -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 ? ( | |||
| @@ -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> | |||
| ); | |||
| @@ -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> | |||
| @@ -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; | |||
| @@ -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; | |||
| @@ -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 && ( | |||
| @@ -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; | |||
| // `; | |||
| @@ -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; | |||
| @@ -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; | |||
| } | |||
| `; | |||
| @@ -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; | |||
| @@ -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; | |||
| } | |||
| `; | |||
| @@ -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; | |||
| @@ -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; | |||
| } | |||
| `; | |||
| @@ -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, | |||
| @@ -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", | |||
| }, | |||
| }; | |||
| @@ -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: | |||
| @@ -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) => { | |||
| @@ -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, | |||
| }); | |||
| } | |||
| } | |||
| } | |||
| @@ -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}`; | |||
| } | |||