| @@ -0,0 +1,36 @@ | |||
| import React from "react"; | |||
| import PropTypes from "prop-types"; | |||
| import selectedTheme from "../../../../themes"; | |||
| import { replaceInRoute } from "../../../../util/helpers/routeHelpers"; | |||
| import { ITEM_DETAILS_PAGE } from "../../../../constants/pages"; | |||
| import { useTranslation } from "react-i18next"; | |||
| import { CheckButtonContainer } from "./CheckButton.styled"; | |||
| const CheckButton = (props) => { | |||
| const { t } = useTranslation(); | |||
| const routeToItem = (itemId) => { | |||
| history.push( | |||
| replaceInRoute(ITEM_DETAILS_PAGE, { | |||
| idProizvod: itemId, | |||
| }) | |||
| ); | |||
| }; | |||
| return ( | |||
| <CheckButtonContainer | |||
| variant={props.sponsored ? "contained" : "outlined"} | |||
| buttoncolor={selectedTheme.colors.primaryPurple} | |||
| textcolor={props.sponsored ? "white" : selectedTheme.colors.primaryPurple} | |||
| style={{ fontWeight: "600" }} | |||
| onClick={() => routeToItem(props.offerId)} | |||
| > | |||
| {t("offer.checkButtonLabel")} | |||
| </CheckButtonContainer> | |||
| ); | |||
| }; | |||
| CheckButton.propTypes = { | |||
| sponsored: PropTypes.bool, | |||
| offerId: PropTypes.string, | |||
| }; | |||
| export default CheckButton; | |||
| @@ -0,0 +1,18 @@ | |||
| import styled from "styled-components"; | |||
| import selectedTheme from "../../../../themes"; | |||
| import { PrimaryButton } from "../../../Buttons/PrimaryButton/PrimaryButton"; | |||
| export const CheckButtonContainer = styled(PrimaryButton)` | |||
| width: 180px; | |||
| height: 48px; | |||
| position: absolute; | |||
| bottom: 9px; | |||
| right: 9px; | |||
| &:hover button { | |||
| background-color: ${selectedTheme.colors.primaryPurple} !important; | |||
| color: white !important; | |||
| } | |||
| @media (max-width: 650px) { | |||
| display: none; | |||
| } | |||
| `; | |||
| @@ -1,7 +1,6 @@ | |||
| import React, { useMemo, useState } from "react"; | |||
| import PropTypes from "prop-types"; | |||
| import { | |||
| CheckButton, | |||
| DetailIcon, | |||
| DetailText, | |||
| EditIcon, | |||
| @@ -13,9 +12,6 @@ import { | |||
| OfferAuthorName, | |||
| OfferCardContainer, | |||
| OfferCategory, | |||
| OfferDescription, | |||
| OfferDescriptionText, | |||
| OfferDescriptionTitle, | |||
| OfferDetails, | |||
| OfferFlexContainer, | |||
| OfferImage, | |||
| @@ -34,13 +30,14 @@ import { | |||
| } from "./OfferCard.styled"; | |||
| import DeleteOffer from "./DeleteOffer/DeleteOffer"; | |||
| import { ReactComponent as Message } from "../../../assets/images/svg/mail.svg"; | |||
| import selectedTheme from "../../../themes"; | |||
| import { useHistory } from "react-router-dom"; | |||
| import CreateOffer from "../CreateOfferCard/CreateOffer"; | |||
| import { useSelector } from "react-redux"; | |||
| import { selectUserId } from "../../../store/selectors/loginSelectors"; | |||
| import useIsMobile from "../../../hooks/useIsMobile"; | |||
| import { getImageUrl, variants } from "../../../util/helpers/imageUrlGetter"; | |||
| import OfferDescription from "./OfferDescription/OfferDescription"; | |||
| import CheckButton from "./CheckButton/CheckButton"; | |||
| const OfferCard = (props) => { | |||
| const [deleteOfferModal, setDeleteOfferModal] = useState(false); | |||
| @@ -93,17 +90,20 @@ const OfferCard = (props) => { | |||
| } | |||
| halfwidth={props.halfwidth ? 1 : 0} | |||
| > | |||
| {/* This only shows on vertical offer card */} | |||
| <OfferTitleAboveImage | |||
| vertical={props.vertical} | |||
| onClick={() => routeToItem(props?.offer?._id)} | |||
| > | |||
| {props?.offer?.name} | |||
| </OfferTitleAboveImage> | |||
| {/* ^^^^^^^ */} | |||
| <OfferFlexContainer vertical={props.vertical}> | |||
| <OfferImageContainer vertical={props.vertical}> | |||
| <OfferImage | |||
| src={ | |||
| props?.offer?.images | |||
| props?.offer?.images | |||
| ? getImageUrl( | |||
| props?.offer?.images[0], | |||
| variants.offerCard, | |||
| @@ -151,24 +151,11 @@ const OfferCard = (props) => { | |||
| {!props.halfwidth ? ( | |||
| <React.Fragment> | |||
| <Line /> | |||
| <OfferDescription> | |||
| <OfferDescriptionTitle>Opis:</OfferDescriptionTitle> | |||
| <OfferDescriptionText> | |||
| {props?.offer?.description} | |||
| </OfferDescriptionText> | |||
| </OfferDescription> | |||
| <OfferDescription description={props?.offer?.description} /> | |||
| <CheckButton | |||
| variant={props.sponsored ? "contained" : "outlined"} | |||
| buttoncolor={selectedTheme.colors.primaryPurple} | |||
| textcolor={ | |||
| props.sponsored ? "white" : selectedTheme.colors.primaryPurple | |||
| } | |||
| style={{ fontWeight: "600" }} | |||
| onClick={() => routeToItem(props?.offer?._id)} | |||
| > | |||
| Pogledaj proizvod | |||
| </CheckButton> | |||
| offerId={props?.offer?._id} | |||
| sponsored={props.sponsored} | |||
| /> | |||
| </React.Fragment> | |||
| ) : ( | |||
| <></> | |||
| @@ -2,7 +2,6 @@ import { Box, Container, Typography } from "@mui/material"; | |||
| 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 Remove } from "../../../assets/images/svg/trash.svg"; | |||
| @@ -195,35 +194,7 @@ export const OfferViews = styled(Box)` | |||
| display: none; | |||
| `} | |||
| `; | |||
| export const OfferDescriptionTitle = styled(Box)` | |||
| font-family: ${selectedTheme.fonts.textFont}; | |||
| font-size: 12px; | |||
| color: ${selectedTheme.colors.primaryDarkText}; | |||
| line-height: 16px; | |||
| `; | |||
| export const OfferDescriptionText = styled(Box)` | |||
| font-family: ${selectedTheme.fonts.textFont}; | |||
| font-size: 16px; | |||
| color: ${selectedTheme.colors.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 Line = styled(Box)` | |||
| border-left: 1px solid rgba(0, 0, 0, 0.15); | |||
| height: 100px; | |||
| @@ -249,20 +220,6 @@ export const DetailText = styled(Typography)` | |||
| top: -2px; | |||
| left: 3px; | |||
| `; | |||
| export const CheckButton = styled(PrimaryButton)` | |||
| width: 180px; | |||
| height: 48px; | |||
| position: absolute; | |||
| bottom: 9px; | |||
| right: 9px; | |||
| &:hover button { | |||
| background-color: ${selectedTheme.colors.primaryPurple} !important; | |||
| color: white !important; | |||
| } | |||
| @media (max-width: 650px) { | |||
| display: none; | |||
| } | |||
| `; | |||
| export const MessageIcon = styled(IconButton)` | |||
| ${(props) => !props.showMessageIcon && "display: none;"} | |||
| width: 40px; | |||
| @@ -0,0 +1,26 @@ | |||
| import React from "react"; | |||
| import PropTypes from "prop-types"; | |||
| import { | |||
| OfferDescriptionContainer, | |||
| OfferDescriptionText, | |||
| OfferDescriptionTitle, | |||
| } from "./OfferDescription.styled"; | |||
| import { useTranslation } from "react-i18next"; | |||
| const OfferDescription = (props) => { | |||
| const { t } = useTranslation(); | |||
| return ( | |||
| <OfferDescriptionContainer> | |||
| <OfferDescriptionTitle> | |||
| {t("offer.descriptionLabel")} | |||
| </OfferDescriptionTitle> | |||
| <OfferDescriptionText>{props.description}</OfferDescriptionText> | |||
| </OfferDescriptionContainer> | |||
| ); | |||
| }; | |||
| OfferDescription.propTypes = { | |||
| description: PropTypes.string, | |||
| }; | |||
| export default OfferDescription; | |||
| @@ -0,0 +1,33 @@ | |||
| import { Box } from "@mui/material"; | |||
| import styled from "styled-components"; | |||
| import selectedTheme from "../../../../themes"; | |||
| export const OfferDescriptionText = styled(Box)` | |||
| font-family: ${selectedTheme.fonts.textFont}; | |||
| font-size: 16px; | |||
| color: ${selectedTheme.colors.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 OfferDescriptionContainer = styled(Box)` | |||
| flex: 3; | |||
| margin: auto 0; | |||
| padding-left: 35px; | |||
| @media (max-width: 1500px) { | |||
| display: none; | |||
| } | |||
| `; | |||
| export const OfferDescriptionTitle = styled(Box)` | |||
| font-family: ${selectedTheme.fonts.textFont}; | |||
| font-size: 12px; | |||
| color: ${selectedTheme.colors.primaryDarkText}; | |||
| line-height: 16px; | |||
| `; | |||
| @@ -0,0 +1,35 @@ | |||
| import React from "react"; | |||
| import PropTypes from "prop-types"; | |||
| import { | |||
| ReviewDetailsContainer, | |||
| ReviewDetailsText, | |||
| ReviewDetailsValue, | |||
| } from "./ReviewDetails.styled"; | |||
| import { useTranslation } from "react-i18next"; | |||
| const ReviewDetails = (props) => { | |||
| const { t } = useTranslation(); | |||
| return ( | |||
| <ReviewDetailsContainer sx={{ pl: 2, pb: 2 }}> | |||
| <ReviewDetailsText variant="body2" sx={{ display: "block" }}> | |||
| {t("reviews.isCorrectCommunication") + ": "} | |||
| <ReviewDetailsValue> | |||
| {props?.isGoodCommunication?.toUpperCase()} | |||
| </ReviewDetailsValue> | |||
| </ReviewDetailsText> | |||
| <ReviewDetailsText variant="body2" sx={{ display: "block" }}> | |||
| {t("reviews.hasExchangeSucceed") + ": "} | |||
| <ReviewDetailsValue> | |||
| {props?.isSuccessfulSwap?.toUpperCase()} | |||
| </ReviewDetailsValue> | |||
| </ReviewDetailsText> | |||
| </ReviewDetailsContainer> | |||
| ); | |||
| }; | |||
| ReviewDetails.propTypes = { | |||
| isGoodCommunication: PropTypes.string, | |||
| isSuccessfulSwap: PropTypes.string, | |||
| }; | |||
| export default ReviewDetails; | |||
| @@ -0,0 +1,17 @@ | |||
| import { Grid, Typography } from "@mui/material"; | |||
| import styled from "styled-components"; | |||
| import selectedTheme from "../../../../themes"; | |||
| export const ReviewDetailsContainer = styled(Grid)``; | |||
| export const ReviewDetailsText = styled(Typography)` | |||
| font-family: ${selectedTheme.fonts.textFont}; | |||
| font-size: 12px; | |||
| color: ${selectedTheme.colors.primaryDarkText}; | |||
| font-style: italic; | |||
| letter-spacing: 0.02em; | |||
| `; | |||
| export const ReviewDetailsValue = styled(Typography)` | |||
| color: ${selectedTheme.colors.primaryPurple}; | |||
| font-style: normal; | |||
| font-weight: 600; | |||
| `; | |||
| @@ -0,0 +1,42 @@ | |||
| import React from "react"; | |||
| import PropTypes from "prop-types"; | |||
| import { | |||
| ReviewQuoteContainer, | |||
| ReviewQuoteTextContainer, | |||
| ReviewQuoteText, | |||
| ThumbContainer, | |||
| ThumbDown, | |||
| ThumbUp, | |||
| } from "./ReviewQuote.styled"; | |||
| import { reviewEnum } from "../../../../enums/reviewEnum"; | |||
| const ReviewQuote = (props) => { | |||
| return ( | |||
| <ReviewQuoteContainer | |||
| container | |||
| direction="row" | |||
| justifyContent="start" | |||
| alignItems="center" | |||
| spacing={2} | |||
| > | |||
| <ThumbContainer item> | |||
| {props.isSuccessfulSwap.toLowerCase() === | |||
| reviewEnum.YES.mainText.toLowerCase() ? ( | |||
| <ThumbUp color="success" /> | |||
| ) : ( | |||
| <ThumbDown color="error" /> | |||
| )} | |||
| </ThumbContainer> | |||
| <ReviewQuoteTextContainer item> | |||
| <ReviewQuoteText>"{props.quote}"</ReviewQuoteText> | |||
| </ReviewQuoteTextContainer> | |||
| </ReviewQuoteContainer> | |||
| ); | |||
| }; | |||
| ReviewQuote.propTypes = { | |||
| quote: PropTypes.string, | |||
| isSuccessfulSwap: PropTypes.string, | |||
| }; | |||
| export default ReviewQuote; | |||
| @@ -0,0 +1,31 @@ | |||
| import { Grid, Typography } from "@mui/material"; | |||
| import styled from "styled-components"; | |||
| import selectedTheme from "../../../../themes"; | |||
| import ThumbUpIcon from "@mui/icons-material/ThumbUp"; | |||
| import ThumbDownIcon from "@mui/icons-material/ThumbDown"; | |||
| export const ReviewQuoteContainer = styled(Grid)` | |||
| position: relative; | |||
| left: 8px; | |||
| padding-left: 2px; | |||
| padding-top: 2px; | |||
| padding-bottom: 2px; | |||
| `; | |||
| export const ThumbContainer = styled(Grid)` | |||
| max-width: 20px; | |||
| `; | |||
| export const ReviewQuoteTextContainer = styled(Grid)``; | |||
| export const ReviewQuoteText = styled(Typography)` | |||
| font-family: ${selectedTheme.fonts.textFont}; | |||
| font-size: 12px; | |||
| color: ${selectedTheme.colors.primaryDarkText}; | |||
| `; | |||
| export const ThumbUp = styled(ThumbUpIcon)` | |||
| position: relative; | |||
| left: -8px; | |||
| `; | |||
| export const ThumbDown = styled(ThumbDownIcon)` | |||
| position: relative; | |||
| left: -8px; | |||
| top: 3px; | |||
| `; | |||
| @@ -0,0 +1,31 @@ | |||
| import React from "react"; | |||
| import PropTypes from "prop-types"; | |||
| import useIsMobile from "../../../../hooks/useIsMobile"; | |||
| import { getImageUrl, variants } from "../../../../util/helpers/imageUrlGetter"; | |||
| import { | |||
| ProfileContainer, | |||
| ProfileImage, | |||
| ProfileImageContainer, | |||
| ProfileName, | |||
| } from "./ReviewerProfile.styled"; | |||
| const ReviewerProfile = (props) => { | |||
| const { isMobile } = useIsMobile(); | |||
| return ( | |||
| <ProfileContainer> | |||
| <ProfileImageContainer> | |||
| <ProfileImage | |||
| src={getImageUrl(props.profileImage, variants.reviewCard, isMobile)} | |||
| /> | |||
| </ProfileImageContainer> | |||
| <ProfileName>{props.profileName}</ProfileName> | |||
| </ProfileContainer> | |||
| ); | |||
| }; | |||
| ReviewerProfile.propTypes = { | |||
| profileName: PropTypes.string, | |||
| profileImage: PropTypes.string, | |||
| }; | |||
| export default ReviewerProfile; | |||
| @@ -0,0 +1,25 @@ | |||
| import { Box, ListItem, Typography } from "@mui/material" | |||
| import styled from "styled-components" | |||
| import selectedTheme from "../../../../themes" | |||
| export const ProfileImage = styled.img` | |||
| width: 54px; | |||
| height: 54px; | |||
| border-radius: 100%; | |||
| ` | |||
| export const ProfileImageContainer = styled(Box)` | |||
| width: 54px; | |||
| height: 54px; | |||
| border-radius: 100%; | |||
| margin-right: 14px; | |||
| ` | |||
| export const ProfileName = styled(Typography)` | |||
| font-weight: 600; | |||
| font-size: 16px; | |||
| font-family: ${selectedTheme.fonts.textFont}; | |||
| color: ${selectedTheme.colors.primaryPurple}; | |||
| ` | |||
| export const ProfileContainer = styled(ListItem)` | |||
| align-items: flex-start; | |||
| margin-top: 2px; | |||
| ` | |||
| @@ -1,31 +1,13 @@ | |||
| import React, { useMemo } from "react"; | |||
| import PropTypes from "prop-types"; | |||
| import { | |||
| ProfileImage, | |||
| ProfileImageContainer, | |||
| ProfileName, | |||
| ReviewContainer, | |||
| ReviewDetails, | |||
| ReviewDetailsText, | |||
| ReviewDetailsValue, | |||
| ReviewQuote, | |||
| ReviewQuoteBox, | |||
| ReviewQuoteText, | |||
| ThumbBox, | |||
| ThumbDown, | |||
| ThumbUp, | |||
| } from "./UserReviewsCard.styled"; | |||
| import { ListItem } from "@mui/material"; | |||
| import selectedTheme from "../../../themes"; | |||
| import { useTranslation } from "react-i18next"; | |||
| import useIsMobile from "../../../hooks/useIsMobile"; | |||
| import { getImageUrl, variants } from "../../../util/helpers/imageUrlGetter"; | |||
| import { ReviewContainer } from "./UserReviewsCard.styled"; | |||
| import ReviewOffer from "./ReviewOffer/ReviewOffer"; | |||
| import { reviewEnum } from "../../../enums/reviewEnum"; | |||
| import ReviewerProfile from "./ReviewerProfile/ReviewerProfile"; | |||
| import ReviewQuote from "./ReviewQuote/ReviewQuote"; | |||
| import ReviewDetails from "./ReviewDetails/ReviewDetails"; | |||
| const UserReviewsCard = (props) => { | |||
| const { t } = useTranslation(); | |||
| const { isMobile } = useIsMobile(); | |||
| const review = useMemo(() => { | |||
| if (props.givingReview) { | |||
| @@ -33,23 +15,23 @@ const UserReviewsCard = (props) => { | |||
| ...props.review, | |||
| }; | |||
| } | |||
| let isSuccessfulSwap = "DA"; | |||
| let isSuccessfulSwap = reviewEnum.YES.mainText.toUpperCase(); | |||
| if ( | |||
| props.review.succeeded === "failed" || | |||
| props.review.succeeded === reviewEnum.NO.backendText || | |||
| props.review.isSuccessfulSwap === reviewEnum.NO.mainText | |||
| ) | |||
| isSuccessfulSwap = "NE"; | |||
| let isGoodCommunication = "DA"; | |||
| isSuccessfulSwap = reviewEnum.NO.mainText.toUpperCase(); | |||
| let isGoodCommunication = reviewEnum.YES.mainText.toUpperCase(); | |||
| if ( | |||
| props.review.communication === "could be better" || | |||
| props.review.communication === reviewEnum.NOT_BAD.backendText || | |||
| props.review.isCorrectCommunication === reviewEnum.NOT_BAD.mainText | |||
| ) | |||
| isGoodCommunication = "MOŽE BOLJE"; | |||
| isGoodCommunication = reviewEnum.NOT_BAD.mainText.toUpperCase(); | |||
| if ( | |||
| props.review.communication === "no" || | |||
| props.review.communication === reviewEnum.NO.backendTextSecond || | |||
| props.review.isCorrectCommunication === reviewEnum.NO.mainText | |||
| ) | |||
| isGoodCommunication = "NE"; | |||
| isGoodCommunication = reviewEnum.NO.mainText.toUpperCase(); | |||
| return { | |||
| name: props.review.userWhoGaveReview.name, | |||
| image: props.review.userWhoGaveReview.image, | |||
| @@ -60,56 +42,19 @@ const UserReviewsCard = (props) => { | |||
| offerImage: props.review.offer.image, | |||
| }; | |||
| }, [props.review]); | |||
| console.log(props); | |||
| return ( | |||
| <ReviewContainer key={review?.image}> | |||
| <ListItem alignItems="flex-start" sx={{ alignItems: "center", mt: 2 }}> | |||
| <ProfileImageContainer> | |||
| {/* <ProfileImage alt={review?.name} src={review?.image} /> */} | |||
| <ProfileImage | |||
| src={getImageUrl(review?.image, variants.reviewCard, isMobile)} | |||
| /> | |||
| </ProfileImageContainer> | |||
| <ProfileName sx={{ color: selectedTheme.colors.primaryPurple }}> | |||
| <b>{review?.name}</b> | |||
| </ProfileName> | |||
| </ListItem> | |||
| <ReviewerProfile profileName={review.name} profileImage={review.image} /> | |||
| <ReviewQuote | |||
| container | |||
| direction="row" | |||
| justifyContent="start" | |||
| alignItems="center" | |||
| spacing={2} | |||
| sx={{ pl: 2, py: 2 }} | |||
| > | |||
| <ThumbBox item> | |||
| {review.isSuccessfulSwap.toLowerCase() === | |||
| reviewEnum.YES.mainText.toLowerCase() ? ( | |||
| <ThumbUp color="success" /> | |||
| ) : ( | |||
| <ThumbDown color="error" /> | |||
| )} | |||
| </ThumbBox> | |||
| <ReviewQuoteBox item> | |||
| <ReviewQuoteText>"{review?.quote}"</ReviewQuoteText> | |||
| </ReviewQuoteBox> | |||
| </ReviewQuote> | |||
| <ReviewDetails sx={{ pl: 2, pb: 2 }}> | |||
| <ReviewDetailsText variant="body2" sx={{ display: "block" }}> | |||
| {t("reviews.isCorrectCommunication") + ": "} | |||
| <ReviewDetailsValue> | |||
| {review?.isGoodCommunication?.toUpperCase()} | |||
| </ReviewDetailsValue> | |||
| </ReviewDetailsText> | |||
| <ReviewDetailsText variant="body2" sx={{ display: "block" }}> | |||
| {t("reviews.hasExchangeSucceed") + ": "} | |||
| <ReviewDetailsValue> | |||
| {review?.isSuccessfulSwap?.toUpperCase()} | |||
| </ReviewDetailsValue> | |||
| </ReviewDetailsText> | |||
| </ReviewDetails> | |||
| <ReviewOffer name={review.offerName} image={review.offerImage}/> | |||
| isSuccessfulSwap={review?.isSuccessfulSwap} | |||
| quote={review?.quote} | |||
| /> | |||
| <ReviewDetails | |||
| isSuccessfulSwap={review?.isSuccessfulSwap} | |||
| isGoodCommunication={review?.isGoodCommunication} | |||
| /> | |||
| <ReviewOffer name={review.offerName} image={review.offerImage} /> | |||
| </ReviewContainer> | |||
| ); | |||
| }; | |||
| @@ -1,31 +1,30 @@ | |||
| import styled from "styled-components"; | |||
| import { List, Box, Typography, Grid } from "@mui/material"; | |||
| import ThumbUpIcon from "@mui/icons-material/ThumbUp"; | |||
| import ThumbDownIcon from "@mui/icons-material/ThumbDown"; | |||
| import selectedTheme from "../../../themes"; | |||
| export const ReviewsBox = styled(Box)` | |||
| width: 100%; | |||
| height: calc(100% - 90px); | |||
| max-height: 100vh; | |||
| padding-bottom: 20px; | |||
| @media (max-width: 1200px) { | |||
| padding: 0; | |||
| } | |||
| @media (max-width: 600px) { | |||
| position: relative; | |||
| top: -45px; | |||
| overflow: hidden; | |||
| height: 350px; | |||
| max-height: 350px; | |||
| padding: 0; | |||
| } | |||
| width: 100%; | |||
| height: calc(100% - 90px); | |||
| max-height: 100vh; | |||
| padding-bottom: 20px; | |||
| @media (max-width: 1200px) { | |||
| padding: 0; | |||
| } | |||
| @media (max-width: 600px) { | |||
| position: relative; | |||
| top: -45px; | |||
| overflow: hidden; | |||
| height: 350px; | |||
| max-height: 350px; | |||
| padding: 0; | |||
| } | |||
| `; | |||
| export const ReviewsHeader = styled(Grid)` | |||
| @media (max-width: 800px) { | |||
| display: none; | |||
| } | |||
| ` | |||
| `; | |||
| export const ReviewsTitle = styled(Typography)` | |||
| font-family: ${selectedTheme.fonts.textFont}; | |||
| @@ -33,41 +32,31 @@ export const ReviewsTitle = styled(Typography)` | |||
| @media (max-width: 800px) { | |||
| display: none; | |||
| } | |||
| ` | |||
| `; | |||
| export const ReviewList = styled(List)` | |||
| background: white; | |||
| padding: 2rem; | |||
| border-radius: 4px 0 0 4px; | |||
| height: 100%; | |||
| width: 100%; | |||
| border: 1px solid ${selectedTheme.colors.borderNormal}; | |||
| background: white; | |||
| padding: 2rem; | |||
| border-radius: 4px 0 0 4px; | |||
| height: 100%; | |||
| width: 100%; | |||
| border: 1px solid ${selectedTheme.colors.borderNormal}; | |||
| /* overflow-y: auto; */ | |||
| &::-webkit-scrollbar { | |||
| width: 5px; | |||
| } | |||
| &::-webkit-scrollbar-track { | |||
| background: #ddd; | |||
| } | |||
| &::-webkit-scrollbar-thumb { | |||
| background: #777; | |||
| } | |||
| scrollbar-width: thin; | |||
| scrollbar-color: #ddd; | |||
| /* overflow-y: auto; */ | |||
| &::-webkit-scrollbar { | |||
| width: 5px; | |||
| } | |||
| &::-webkit-scrollbar-track { | |||
| background: #ddd; | |||
| } | |||
| &::-webkit-scrollbar-thumb { | |||
| background: #777; | |||
| } | |||
| scrollbar-width: thin; | |||
| scrollbar-color: #ddd; | |||
| `; | |||
| export const ThumbUp = styled(ThumbUpIcon)` | |||
| position: relative; | |||
| left: -8px; | |||
| ` | |||
| export const ThumbDown = styled(ThumbDownIcon)` | |||
| position: relative; | |||
| left: -8px; | |||
| top: 3px; | |||
| ` | |||
| export const NoReviewsContainer = styled(Box)` | |||
| ` | |||
| export const NoReviewsContainer = styled(Box)``; | |||
| export const NoReviewsText = styled(Typography)` | |||
| color: ${selectedTheme.colors.primaryPurple}; | |||
| font-size: 24px; | |||
| @@ -75,8 +64,7 @@ export const NoReviewsText = styled(Typography)` | |||
| text-align: center; | |||
| font-weight: 700; | |||
| width: 100%; | |||
| ` | |||
| `; | |||
| export const NoReviewsAltText = styled(Typography)` | |||
| font-size: 12px; | |||
| color: ${selectedTheme.colors.primaryDarkText}; | |||
| @@ -84,51 +72,8 @@ export const NoReviewsAltText = styled(Typography)` | |||
| text-align: center; | |||
| width: 100%; | |||
| margin-bottom: 36px; | |||
| ` | |||
| export const ProfileImage = styled.img` | |||
| width: 54px; | |||
| height: 54px; | |||
| border-radius: 100%; | |||
| ` | |||
| export const ProfileImageContainer = styled(Box)` | |||
| width: 54px; | |||
| height: 54px; | |||
| border-radius: 100%; | |||
| margin-right: 14px; | |||
| ` | |||
| export const ReviewQuote = styled(Grid)` | |||
| position: relative; | |||
| left: 8px; | |||
| ` | |||
| export const ThumbBox = styled(Grid)` | |||
| max-width: 20px; | |||
| ` | |||
| export const ReviewQuoteBox = styled(Grid)` | |||
| ` | |||
| export const ReviewQuoteText = styled(Typography)` | |||
| font-family: ${selectedTheme.fonts.textFont}; | |||
| font-size: 12px; | |||
| color: ${selectedTheme.colors.primaryDarkText}; | |||
| ` | |||
| export const ReviewDetails = styled(Grid)` | |||
| ` | |||
| export const ReviewDetailsText = styled(Typography)` | |||
| font-family: ${selectedTheme.fonts.textFont}; | |||
| font-size: 12px; | |||
| color: ${selectedTheme.colors.primaryDarkText}; | |||
| font-style: italic; | |||
| letter-spacing: 0.02em; | |||
| ` | |||
| export const ReviewDetailsValue = styled(Typography)` | |||
| color: ${selectedTheme.colors.primaryPurple}; | |||
| font-style: normal; | |||
| font-weight: 600; | |||
| ` | |||
| export const ProfileName = styled(Typography)` | |||
| font-weight: 600; | |||
| font-size: 16px; | |||
| font-family: ${selectedTheme.fonts.textFont}; | |||
| ` | |||
| `; | |||
| export const ReviewContainer = styled(Box)` | |||
| padding-bottom: 20px; | |||
| ` | |||
| `; | |||
| @@ -0,0 +1,31 @@ | |||
| import React from "react"; | |||
| import PropTypes from "prop-types"; | |||
| import { FieldLabel } from "../FirstStepCreateReview.styled"; | |||
| import { CommentFieldContainer } from "./CommentField.styled"; | |||
| import { useTranslation } from "react-i18next"; | |||
| import useIsMobile from "../../../../hooks/useIsMobile"; | |||
| const CommentField = (props) => { | |||
| const { t } = useTranslation(); | |||
| const { isMobile } = useIsMobile(); | |||
| return ( | |||
| <> | |||
| <FieldLabel leftText={t("reviews.comment")} /> | |||
| <CommentFieldContainer | |||
| fullWidth | |||
| multiline | |||
| minRows={4} | |||
| value={props.formik.values.comment} | |||
| name="comment" | |||
| onChange={props.formik.handleChange} | |||
| height={isMobile ? "64px" : "100px"} | |||
| /> | |||
| </> | |||
| ); | |||
| }; | |||
| CommentField.propTypes = { | |||
| formik: PropTypes.any, | |||
| }; | |||
| export default CommentField; | |||
| @@ -0,0 +1,31 @@ | |||
| import styled from "styled-components"; | |||
| import selectedTheme from "../../../../themes"; | |||
| import { TextField } from "../../../TextFields/TextField/TextField"; | |||
| export const CommentFieldContainer = styled(TextField)` | |||
| & * { | |||
| font-family: ${selectedTheme.fonts.textFont}; | |||
| font-size: 16px; | |||
| &::-webkit-scrollbar { | |||
| width: 5px; | |||
| } | |||
| &::-webkit-scrollbar-track { | |||
| background: #ddd; | |||
| } | |||
| &::-webkit-scrollbar-thumb { | |||
| background: #777; | |||
| } | |||
| scrollbar-width: thin; | |||
| scrollbar-color: #ddd; | |||
| @media (max-width: 600px) { | |||
| & * { | |||
| font-size: 12px !important; | |||
| /* line-height: 16px; */ | |||
| } | |||
| & div { | |||
| padding: 4px !important; | |||
| padding-left: 8px !important; | |||
| } | |||
| } | |||
| } | |||
| `; | |||
| @@ -0,0 +1,41 @@ | |||
| import React from "react"; | |||
| import PropTypes from "prop-types"; | |||
| import { useTranslation } from "react-i18next"; | |||
| import { | |||
| FieldLabel, | |||
| SelectField, | |||
| SelectOption, | |||
| } from "../FirstStepCreateReview.styled"; | |||
| import { reviewEnum } from "../../../../enums/reviewEnum"; | |||
| const CorrectCommunicationField = (props) => { | |||
| const { t } = useTranslation(); | |||
| return ( | |||
| <> | |||
| <FieldLabel | |||
| leftText={t("reviews.isCorrectCommunication").toUpperCase()} | |||
| /> | |||
| <SelectField | |||
| defaultValue={props.formik.values.correctCommunication} | |||
| onChange={(event) => | |||
| props.formik.setFieldValue("correctCommunication", event.target.value) | |||
| } | |||
| > | |||
| {Object.keys(reviewEnum).map((property) => ( | |||
| <SelectOption | |||
| key={reviewEnum[property].value} | |||
| value={reviewEnum[property].mainText} | |||
| > | |||
| {reviewEnum[property].mainText} | |||
| </SelectOption> | |||
| ))} | |||
| </SelectField> | |||
| </> | |||
| ); | |||
| }; | |||
| CorrectCommunicationField.propTypes = { | |||
| formik: PropTypes.any, | |||
| }; | |||
| export default CorrectCommunicationField; | |||
| @@ -1,4 +1,4 @@ | |||
| import React, { useEffect } from "react"; | |||
| import React from "react"; | |||
| import PropTypes from "prop-types"; | |||
| import { | |||
| FirstStepCreateReviewContainer, | |||
| @@ -6,53 +6,34 @@ import { | |||
| ProfileImage, | |||
| ProfileImageContainer, | |||
| ProfileName, | |||
| FieldLabel, | |||
| SelectField, | |||
| SelectOption, | |||
| CommentField, | |||
| } from "./FirstStepCreateReview.styled"; | |||
| import { useTranslation } from "react-i18next"; | |||
| import LittleOfferCard from "../../Cards/LittleOfferCard/LittleOfferCard"; | |||
| import { reviewEnum } from "../../../enums/reviewEnum"; | |||
| import { NextButton } from "../CreateReview.styled"; | |||
| import selectedTheme from "../../../themes"; | |||
| import { useFormik } from "formik"; | |||
| import * as Yup from "yup"; | |||
| import useIsMobile from "../../../hooks/useIsMobile"; | |||
| import { getImageUrl, variants } from "../../../util/helpers/imageUrlGetter"; | |||
| import { useMemo } from "react"; | |||
| import firstPartCreateReviewInitialValues from "../../../initialValues/createReviewInitialValues/firstPartCreateReviewInitialValues"; | |||
| import firstPartCreateReviewValidation from "../../../validations/createReviewValidations/firstPartCreateReviewValidation"; | |||
| import CorrectCommunicationField from "./CorrectCommunicationField/CorrectCommunicationField"; | |||
| import SuccessfulSwapField from "./SuccessfulSwapField/SuccessfulSwapField"; | |||
| import CommentField from "./CommentField/CommentField"; | |||
| import NextButton from "./NextButton/NextButton"; | |||
| const FirstStepCreateReview = (props) => { | |||
| const offer = props.offer; | |||
| const interlocutor = props.interlocutor; | |||
| const { isMobile } = useIsMobile(); | |||
| const { t } = useTranslation(); | |||
| const handleSubmit = (values) => { | |||
| props.goToNextStep(values); | |||
| }; | |||
| useEffect(() => { | |||
| if (props.informations?.exchangeSucceed) { | |||
| formik.setFieldValue( | |||
| "exchangeSucceed", | |||
| props.informations?.exchangeSucceed | |||
| ); | |||
| formik.setFieldValue( | |||
| "correctCommunication", | |||
| props.informations?.correctCommunication | |||
| ); | |||
| formik.setFieldValue("comment", props.informations?.comment); | |||
| } | |||
| const initialValues = useMemo(() => { | |||
| return firstPartCreateReviewInitialValues(props.informations); | |||
| }, [props.informations]); | |||
| const formik = useFormik({ | |||
| initialValues: { | |||
| exchangeSucceed: reviewEnum.YES.mainText, | |||
| correctCommunication: reviewEnum.YES.mainText, | |||
| comment: "", | |||
| }, | |||
| validationSchema: Yup.object().shape({ | |||
| comment: Yup.string().min(5, t("reviews.commentError")), | |||
| }), | |||
| initialValues, | |||
| validationSchema: firstPartCreateReviewValidation, | |||
| onSubmit: handleSubmit, | |||
| validateOnBlur: true, | |||
| enableReinitialize: true, | |||
| @@ -65,8 +46,13 @@ const FirstStepCreateReview = (props) => { | |||
| > | |||
| <CreateReviewTitle>{t("reviews.modalTitle")}</CreateReviewTitle> | |||
| <ProfileImageContainer> | |||
| {/* <ProfileImage src={interlocutor.image} /> */} | |||
| <ProfileImage src={getImageUrl(interlocutor.image, variants.createReviewCard, false)} /> | |||
| <ProfileImage | |||
| src={getImageUrl( | |||
| interlocutor.image, | |||
| variants.createReviewCard, | |||
| false | |||
| )} | |||
| /> | |||
| </ProfileImageContainer> | |||
| <ProfileName>{interlocutor.name}</ProfileName> | |||
| <LittleOfferCard | |||
| @@ -74,67 +60,11 @@ const FirstStepCreateReview = (props) => { | |||
| name={offer?.name} | |||
| categoryName={offer?.category?.name} | |||
| /> | |||
| <FieldLabel | |||
| leftText={t("reviews.isCorrectCommunication").toUpperCase()} | |||
| /> | |||
| <SelectField | |||
| defaultValue={formik.values.correctCommunication} | |||
| onChange={(event) => | |||
| formik.setFieldValue("correctCommunication", event.target.value) | |||
| } | |||
| > | |||
| {Object.keys(reviewEnum).map((property) => ( | |||
| <SelectOption | |||
| key={reviewEnum[property].value} | |||
| value={reviewEnum[property].mainText} | |||
| > | |||
| {reviewEnum[property].mainText} | |||
| </SelectOption> | |||
| ))} | |||
| </SelectField> | |||
| <FieldLabel leftText={t("reviews.hasExchangeSucceed").toUpperCase()} /> | |||
| <SelectField | |||
| defaultValue={formik.values.exchangeSucceed} | |||
| exchange | |||
| onChange={(event) => | |||
| formik.setFieldValue("exchangeSucceed", event.target.value) | |||
| } | |||
| > | |||
| {Object.keys(reviewEnum).map((property) => { | |||
| if (property === "NOT_BAD") return; | |||
| return ( | |||
| <SelectOption | |||
| key={reviewEnum[property].value} | |||
| value={reviewEnum[property].mainText} | |||
| > | |||
| {reviewEnum[property].mainText} | |||
| </SelectOption> | |||
| ); | |||
| })} | |||
| </SelectField> | |||
| <FieldLabel leftText={t("reviews.comment")} /> | |||
| <CommentField | |||
| fullWidth | |||
| multiline | |||
| minRows={4} | |||
| value={formik.values.comment} | |||
| name="comment" | |||
| onChange={formik.handleChange} | |||
| height={isMobile ? "64px" : "100px"} | |||
| /> | |||
| <NextButton | |||
| variant="contained" | |||
| buttoncolor={selectedTheme.colors.primaryPurple} | |||
| fullWidth | |||
| height="48px" | |||
| type="submit" | |||
| disabled={formik.values.comment?.length < 5} | |||
| > | |||
| {t("common.continue")} | |||
| </NextButton> | |||
| <CorrectCommunicationField formik={formik} /> | |||
| <SuccessfulSwapField formik={formik} /> | |||
| <CommentField formik={formik} /> | |||
| <NextButton formik={formik} /> | |||
| </FirstStepCreateReviewContainer> | |||
| ); | |||
| }; | |||
| @@ -4,7 +4,6 @@ import selectedTheme from "../../../themes"; | |||
| import { Label } from "../../CheckBox/Label"; | |||
| import Option from "../../Select/Option/Option"; | |||
| import Select from "../../Select/Select"; | |||
| import { TextField } from "../../TextFields/TextField/TextField"; | |||
| export const FirstStepCreateReviewContainer = styled(Box)` | |||
| text-align: center; | |||
| @@ -87,30 +86,4 @@ export const SelectOption = styled(Option)` | |||
| min-height: 35px; | |||
| } | |||
| `; | |||
| export const CommentField = styled(TextField)` | |||
| & * { | |||
| font-family: ${selectedTheme.fonts.textFont}; | |||
| font-size: 16px; | |||
| &::-webkit-scrollbar { | |||
| width: 5px; | |||
| } | |||
| &::-webkit-scrollbar-track { | |||
| background: #ddd; | |||
| } | |||
| &::-webkit-scrollbar-thumb { | |||
| background: #777; | |||
| } | |||
| scrollbar-width: thin; | |||
| scrollbar-color: #ddd; | |||
| @media (max-width: 600px) { | |||
| & * { | |||
| font-size: 12px !important; | |||
| /* line-height: 16px; */ | |||
| } | |||
| & div { | |||
| padding: 4px !important; | |||
| padding-left: 8px !important; | |||
| } | |||
| } | |||
| } | |||
| `; | |||
| @@ -0,0 +1,27 @@ | |||
| import React from "react"; | |||
| import PropTypes from "prop-types"; | |||
| import selectedTheme from "../../../../themes"; | |||
| import { NextButton as NextButtonContainer } from "../../CreateReview.styled"; | |||
| import { useTranslation } from "react-i18next"; | |||
| const NextButton = (props) => { | |||
| const { t } = useTranslation(); | |||
| return ( | |||
| <NextButtonContainer | |||
| variant="contained" | |||
| buttoncolor={selectedTheme.colors.primaryPurple} | |||
| fullWidth | |||
| height="48px" | |||
| type="submit" | |||
| disabled={props.formik.values.comment?.length < 5} | |||
| > | |||
| {t("common.continue")} | |||
| </NextButtonContainer> | |||
| ); | |||
| }; | |||
| NextButton.propTypes = { | |||
| formik: PropTypes.any, | |||
| }; | |||
| export default NextButton; | |||
| @@ -0,0 +1,43 @@ | |||
| import React from "react"; | |||
| import PropTypes from "prop-types"; | |||
| import { | |||
| FieldLabel, | |||
| SelectField, | |||
| SelectOption, | |||
| } from "../FirstStepCreateReview.styled"; | |||
| import { reviewEnum } from "../../../../enums/reviewEnum"; | |||
| import { useTranslation } from "react-i18next"; | |||
| const SuccessfulSwapField = (props) => { | |||
| const { t } = useTranslation(); | |||
| return ( | |||
| <> | |||
| <FieldLabel leftText={t("reviews.hasExchangeSucceed").toUpperCase()} /> | |||
| <SelectField | |||
| defaultValue={props.formik.values.exchangeSucceed} | |||
| exchange | |||
| onChange={(event) => | |||
| props.formik.setFieldValue("exchangeSucceed", event.target.value) | |||
| } | |||
| > | |||
| {Object.keys(reviewEnum).map((property) => { | |||
| if (property === "NOT_BAD") return; | |||
| return ( | |||
| <SelectOption | |||
| key={reviewEnum[property].value} | |||
| value={reviewEnum[property].mainText} | |||
| > | |||
| {reviewEnum[property].mainText} | |||
| </SelectOption> | |||
| ); | |||
| })} | |||
| </SelectField> | |||
| </> | |||
| ); | |||
| }; | |||
| SuccessfulSwapField.propTypes = { | |||
| formik: PropTypes.any, | |||
| }; | |||
| export default SuccessfulSwapField; | |||
| @@ -0,0 +1,26 @@ | |||
| import React from "react"; | |||
| import PropTypes from "prop-types"; | |||
| import { NextButton as NextButtonContainer } from "../../CreateReview.styled"; | |||
| import selectedTheme from "../../../../themes"; | |||
| import { useTranslation } from "react-i18next"; | |||
| const NextButton = (props) => { | |||
| const { t } = useTranslation(); | |||
| return ( | |||
| <NextButtonContainer | |||
| variant="contained" | |||
| buttoncolor={selectedTheme.colors.primaryPurple} | |||
| fullWidth | |||
| height="48px" | |||
| onClick={props.onClick} | |||
| > | |||
| {t("reviews.leaveComment")} | |||
| </NextButtonContainer> | |||
| ); | |||
| }; | |||
| NextButton.propTypes = { | |||
| onClick: PropTypes.func, | |||
| }; | |||
| export default NextButton; | |||
| @@ -4,21 +4,19 @@ import { | |||
| ReviewCard, | |||
| SecondStepCreateReviewContainer, | |||
| } from "./SecondStepCreateReview.styled"; | |||
| import { CreateReviewTitle, NextButton } from "../CreateReview.styled"; | |||
| import { CreateReviewTitle } from "../CreateReview.styled"; | |||
| import { useTranslation } from "react-i18next"; | |||
| import selectedTheme from "../../../themes"; | |||
| import { useSelector } from "react-redux"; | |||
| import { selectMineProfile } from "../../../store/selectors/profileSelectors"; | |||
| import NextButton from "./NextButton/NextButton"; | |||
| const SecondStepCreateReview = (props) => { | |||
| const { t } = useTranslation(); | |||
| const mineProfile = useSelector(selectMineProfile); | |||
| console.log(mineProfile); | |||
| const goToNextStep = () => { | |||
| props.goToNextStep(); | |||
| }; | |||
| console.log(props); | |||
| return ( | |||
| <SecondStepCreateReviewContainer> | |||
| @@ -37,15 +35,7 @@ const SecondStepCreateReview = (props) => { | |||
| }, | |||
| ]} | |||
| /> | |||
| <NextButton | |||
| variant="contained" | |||
| buttoncolor={selectedTheme.colors.primaryPurple} | |||
| fullWidth | |||
| height="48px" | |||
| onClick={goToNextStep} | |||
| > | |||
| {t("reviews.leaveComment")} | |||
| </NextButton> | |||
| <NextButton onClick={goToNextStep} /> | |||
| </SecondStepCreateReviewContainer> | |||
| ); | |||
| }; | |||
| @@ -1,19 +1,26 @@ | |||
| import React from 'react' | |||
| import PropTypes from 'prop-types' | |||
| import { AltTitle, LogoImage, MainTitle, ThirdStepCreateReviewContainer } from './ThirdStepCreateReview.styled' | |||
| import React from "react"; | |||
| import PropTypes from "prop-types"; | |||
| import { | |||
| AltTitle, | |||
| LogoImage, | |||
| MainTitle, | |||
| ThirdStepCreateReviewContainer, | |||
| } from "./ThirdStepCreateReview.styled"; | |||
| import { useTranslation } from "react-i18next"; | |||
| const ThirdStepCreateReview = () => { | |||
| const { t } = useTranslation(); | |||
| return ( | |||
| <ThirdStepCreateReviewContainer> | |||
| <LogoImage /> | |||
| <MainTitle>Hvala Vam </MainTitle> | |||
| <AltTitle >na izdvojenom vremenu i datoj oceni!</AltTitle> | |||
| <LogoImage /> | |||
| <MainTitle>{t("reviews.finishedReviewTitle")}</MainTitle> | |||
| <AltTitle>{t("reviews.finishedReviewAltTitle")}</AltTitle> | |||
| </ThirdStepCreateReviewContainer> | |||
| ) | |||
| } | |||
| ); | |||
| }; | |||
| ThirdStepCreateReview.propTypes = { | |||
| children: PropTypes.node, | |||
| } | |||
| children: PropTypes.node, | |||
| }; | |||
| export default ThirdStepCreateReview | |||
| export default ThirdStepCreateReview; | |||
| @@ -69,12 +69,15 @@ const DirectChat = () => { | |||
| }; | |||
| }, [chat, location.state, offer]); | |||
| // Fetch chat after it is created | |||
| // (renders after state of location changes) | |||
| useEffect(() => { | |||
| if (routeMatch.params.idChat) { | |||
| refreshChat(); | |||
| } | |||
| }, [routeMatch.params.idChat, location.state?.offerId]); | |||
| // Listener to socket.IO chat | |||
| useEffect(() => { | |||
| addMesageListener((data) => { | |||
| if ( | |||
| @@ -74,7 +74,6 @@ const DirectChatNewMessage = (props) => { | |||
| const initiateNewChat = (typedValue) => { | |||
| const offerId = location.state.offerId; | |||
| console.log("here"); | |||
| dispatch( | |||
| startNewChat({ | |||
| offerId, | |||
| @@ -50,7 +50,9 @@ const AboutHeader = () => { | |||
| {t("prices.header.navigation")} | |||
| </LinkRoute> | |||
| <LinkRoute | |||
| selected={aboutRouteSelected === scrollConstants.about.privacyPolicyPage} | |||
| selected={ | |||
| aboutRouteSelected === scrollConstants.about.privacyPolicyPage | |||
| } | |||
| onClick={navigatePrivacyPolicy} | |||
| > | |||
| {t("privacyPolicy.header.navigation")} | |||
| @@ -0,0 +1,27 @@ | |||
| import React from "react"; | |||
| import PropTypes from "prop-types"; | |||
| import { useTranslation } from "react-i18next"; | |||
| import selectedTheme from "../../../themes"; | |||
| import { AddOfferButtonContainer } from "./AddOfferButton.styled"; | |||
| const AddOfferButton = (props) => { | |||
| const { t } = useTranslation(); | |||
| return ( | |||
| <AddOfferButtonContainer | |||
| type="submit" | |||
| variant="contained" | |||
| fullWidth | |||
| buttoncolor={selectedTheme.colors.primaryYellow} | |||
| textcolor={selectedTheme.colors.yellowButtonTextColor} | |||
| onClick={props.onClick} | |||
| > | |||
| {t("header.addOffer")} | |||
| </AddOfferButtonContainer> | |||
| ); | |||
| }; | |||
| AddOfferButton.propTypes = { | |||
| onClick: PropTypes.func, | |||
| }; | |||
| export default AddOfferButton; | |||
| @@ -0,0 +1,8 @@ | |||
| import styled from "styled-components"; | |||
| import { PrimaryButton } from "../../Buttons/PrimaryButton/PrimaryButton"; | |||
| export const AddOfferButtonContainer = styled(PrimaryButton)` | |||
| height: 49px; | |||
| width: 180px; | |||
| font-weight: 600; | |||
| `; | |||
| @@ -0,0 +1,42 @@ | |||
| import React from "react"; | |||
| import PropTypes from "prop-types"; | |||
| import useIsMobile from "../../../hooks/useIsMobile"; | |||
| import { Drawer as HeaderDrawer } from "../Drawer/Drawer"; | |||
| import Drawer from "../../MUI/DrawerComponent"; | |||
| import { useState } from "react"; | |||
| import { forwardRef } from "react"; | |||
| import { useImperativeHandle } from "react"; | |||
| const DrawerContainer = forwardRef((props, ref) => { | |||
| const [openDrawer, setOpenDrawer] = useState(false); | |||
| const { isMobile } = useIsMobile(); | |||
| useImperativeHandle(ref, () => ({ | |||
| handleToggleDrawer | |||
| })) | |||
| const handleToggleDrawer = () => { | |||
| setOpenDrawer((prevOpenDrawer) => !prevOpenDrawer); | |||
| }; | |||
| if (!isMobile) return <></>; | |||
| return ( | |||
| <Drawer | |||
| open={openDrawer} | |||
| toggleOpen={handleToggleDrawer} | |||
| content={ | |||
| <HeaderDrawer | |||
| toggleDrawer={handleToggleDrawer} | |||
| addOffer={() => props.showCreateOfferModal(true)} | |||
| /> | |||
| } | |||
| /> | |||
| ); | |||
| }); | |||
| DrawerContainer.displayName = "DrawerContainer"; | |||
| DrawerContainer.propTypes = { | |||
| showCreateOfferModal: PropTypes.func, | |||
| }; | |||
| export default DrawerContainer; | |||
| @@ -1,31 +1,22 @@ | |||
| import React, { useState, useEffect, useRef } from "react"; | |||
| import { | |||
| AddOfferButton, | |||
| AuthButtonsContainer, | |||
| EndIcon, | |||
| // EndIcon, | |||
| // FilterContainer, | |||
| // FilterIcon, | |||
| HeaderContainer, | |||
| LoginButton, | |||
| LogoContainer, | |||
| RegisterButton, | |||
| SearchIcon, | |||
| SearchInput, | |||
| SearchInputMobile, | |||
| SwapsIcon, | |||
| ToggleDrawerButton, | |||
| // SearchIcon, | |||
| // SearchInput, | |||
| // SearchInputMobile, | |||
| ToolsButtonsContainer, | |||
| ToolsContainer, | |||
| UserButton, | |||
| UserName, | |||
| } from "./Header.styled"; | |||
| import PropTypes from "prop-types"; | |||
| import { AppBar, Badge, Toolbar, useMediaQuery } from "@mui/material"; | |||
| import { AppBar, Toolbar, useMediaQuery } from "@mui/material"; | |||
| import { useTheme } from "@mui/system"; | |||
| import MenuOutlinedIcon from "@mui/icons-material/MenuOutlined"; | |||
| import MailIcon from "@mui/icons-material/EmailOutlined"; | |||
| import AccountCircle from "@mui/icons-material/PersonOutlineOutlined"; | |||
| import Drawer from "../MUI/DrawerComponent"; | |||
| import PopoverComponent from "../Popovers/PopoverComponent"; | |||
| import { MyPosts } from "../Popovers/MyPosts/MyPosts"; | |||
| import { MyMessages } from "../Popovers/MyMessages/MyMessages"; | |||
| @@ -33,7 +24,6 @@ import { MyProfile } from "../Popovers/MyProfile/MyProfile"; | |||
| import { ReactComponent as LogoHorizontal } from "../../assets/images/svg/logo-horizontal.svg"; | |||
| import selectedTheme from "../../themes"; | |||
| import { useTranslation } from "react-i18next"; | |||
| import { IconButton } from "../Buttons/IconButton/IconButton"; | |||
| import { useDispatch, useSelector } from "react-redux"; | |||
| import { selectUserId } from "../../store/selectors/loginSelectors"; | |||
| import { selectProfileName } from "../../store/selectors/profileSelectors"; | |||
| @@ -49,19 +39,22 @@ import { | |||
| REGISTER_SUCCESSFUL_PAGE, | |||
| RESET_PASSWORD_PAGE, | |||
| } from "../../constants/pages"; | |||
| // import { convertQueryStringForFrontend } from "../../util/helpers/queryHelpers"; | |||
| import { fetchMineProfile } from "../../store/actions/profile/profileActions"; | |||
| import CreateOffer from "../Cards/CreateOfferCard/CreateOffer"; | |||
| import { Drawer as HeaderDrawer } from "./Drawer/Drawer"; | |||
| import useSearch from "../../hooks/useOffers/useSearch"; | |||
| import { routeMatches } from "../../util/helpers/routeHelpers"; | |||
| import AboutHeader from "./AboutHeader/AboutHeader"; | |||
| import { useCallback } from "react"; | |||
| // import useQueryString from "../../hooks/useOffers/useQueryString"; | |||
| // import { useCallback } from "react"; | |||
| import SearchInput from "./SearchInput/SearchInput"; | |||
| import DrawerContainer from "./DrawerContainer/DrawerContainer"; | |||
| import OpenDrawerButton from "./OpenDrawerButton/OpenDrawerButton"; | |||
| import AddOfferButton from "./AddOfferButton/AddOfferButton"; | |||
| import MySwapsButton from "./MySwapsButton/MySwapsButton"; | |||
| import MyMessagesButton from "./MyMessagesButton/MyMessagesButton"; | |||
| import UserButton from "./UserButton/UserButton"; | |||
| const Header = () => { | |||
| // const setOpenFilters = useState(false)[1]; | |||
| const [showSearchBar, setShowSearchBar] = useState(true); | |||
| const setShowSearchBar = useState(true)[1]; | |||
| const [showCreateOfferModal, setShowCreateOfferModal] = useState(false); | |||
| const { t } = useTranslation(); | |||
| const theme = useTheme(); | |||
| @@ -73,8 +66,7 @@ const Header = () => { | |||
| const name = useSelector(selectProfileName); | |||
| const history = useHistory(); | |||
| const routeMatch = useRouteMatch(); | |||
| const searchMobileRef = useRef(null); | |||
| const [openDrawer, setOpenDrawer] = useState(false); | |||
| const drawerRef = useRef(null); | |||
| useEffect(() => { | |||
| if (user && user?.length > 0) { | |||
| @@ -102,18 +94,6 @@ const Header = () => { | |||
| } | |||
| }, [history.location.pathname]); | |||
| // useEffect(() => { | |||
| // if (queryStringHook.loadedFromURL) { | |||
| // const queryObject = new URLSearchParams( | |||
| // convertQueryStringForFrontend(queryStringHook.queryString) | |||
| // ); | |||
| // if (queryObject.has("search")) { | |||
| // searchRef.current.value = queryObject.get("search"); | |||
| // searchMobileRef.current.value = queryObject.get("search"); | |||
| // } | |||
| // } | |||
| // }); | |||
| const closeCreateOfferModal = () => { | |||
| setShowCreateOfferModal(false); | |||
| }; | |||
| @@ -164,21 +144,6 @@ const Header = () => { | |||
| history.push(REGISTER_PAGE); | |||
| }; | |||
| let listener = useCallback( | |||
| (event) => { | |||
| if (event.keyCode === 13) { | |||
| event.preventDefault(); | |||
| handleSearch(searchRef.current.value); | |||
| } | |||
| }, | |||
| [searchRef.current] | |||
| ); | |||
| const handleFocusSearch = () => { | |||
| searchRef.current.addEventListener("keyup", listener); | |||
| }; | |||
| const handleBlurSearch = () => { | |||
| searchRef.current.removeEventListener("keyup", listener); | |||
| }; | |||
| const handleSearch = (value) => { | |||
| if (!routeMatches(HOME_PAGE) && !routeMatches(BASE_PAGE)) { | |||
| const newQueryString = new URLSearchParams({ search: value }); | |||
| @@ -194,10 +159,6 @@ const Header = () => { | |||
| // setOpenFilters((prevState) => !prevState); | |||
| // }; | |||
| const handleToggleDrawer = () => { | |||
| setOpenDrawer(!openDrawer); | |||
| }; | |||
| const handleLogoClick = () => { | |||
| history.push({ | |||
| pathname: HOME_PAGE, | |||
| @@ -206,6 +167,23 @@ const Header = () => { | |||
| }, | |||
| }); | |||
| }; | |||
| const handleAddOfferClick = () => { | |||
| setUserPopoverOpen(false); | |||
| setUserAnchorEl(null); | |||
| setShowCreateOfferModal(true); | |||
| }; | |||
| const openPostsPopover = (event) => { | |||
| setPostsPopoverOpen(true); | |||
| setPostsAnchorEl(event.currentTarget); | |||
| }; | |||
| const openMesgPopover = (event) => { | |||
| setMsgPopoverOpen(true); | |||
| setMsgAnchorEl(event.currentTarget); | |||
| }; | |||
| const openUserPopover = (event) => { | |||
| setUserPopoverOpen(true); | |||
| setUserAnchorEl(event.currentTarget); | |||
| }; | |||
| const closePostsPopover = () => { | |||
| setPostsPopoverOpen(false); | |||
| setPostsAnchorEl(null); | |||
| @@ -226,41 +204,18 @@ const Header = () => { | |||
| position="fixed" | |||
| sx={{ backgroundColor: "white", zIndex: "80", height: "72px" }} | |||
| > | |||
| <Toolbar sx={{p: "15px"}}> | |||
| <Toolbar sx={{ p: "15px" }}> | |||
| <ToolsContainer> | |||
| <LogoContainer onClick={() => handleLogoClick()}> | |||
| <LogoHorizontal /> | |||
| </LogoContainer> | |||
| {matches && ( | |||
| <Drawer | |||
| open={openDrawer} | |||
| toggleOpen={handleToggleDrawer} | |||
| content={ | |||
| <HeaderDrawer | |||
| toggleDrawer={handleToggleDrawer} | |||
| addOffer={() => setShowCreateOfferModal(true)} | |||
| /> | |||
| } | |||
| /> | |||
| )} | |||
| {!routeMatches(ABOUT_PAGE) && ( | |||
| <SearchInput | |||
| fullWidth | |||
| InputProps={{ | |||
| endAdornment: ( | |||
| <EndIcon size="36px"> | |||
| <SearchIcon | |||
| onClick={() => handleSearch(searchRef.current.value)} | |||
| /> | |||
| </EndIcon> | |||
| ), | |||
| }} | |||
| placeholder={t("header.searchOffers")} | |||
| onFocus={handleFocusSearch} | |||
| onBlur={handleBlurSearch} | |||
| ref={searchRef} | |||
| /> | |||
| )} | |||
| <DrawerContainer | |||
| ref={drawerRef} | |||
| showCreateOfferModal={setShowCreateOfferModal} | |||
| /> | |||
| <SearchInput ref={searchRef} handleSearch={handleSearch} /> | |||
| {routeMatches(ABOUT_PAGE) && <AboutHeader />} | |||
| {user ? ( | |||
| @@ -269,86 +224,28 @@ const Header = () => { | |||
| shrink={routeMatches(ABOUT_PAGE)} | |||
| > | |||
| {matches ? ( | |||
| <ToggleDrawerButton> | |||
| <IconButton onClick={handleToggleDrawer}> | |||
| <MenuOutlinedIcon /> | |||
| </IconButton> | |||
| </ToggleDrawerButton> | |||
| <OpenDrawerButton | |||
| onClick={drawerRef.current.handleToggleDrawer} | |||
| /> | |||
| ) : ( | |||
| <React.Fragment> | |||
| {!routeMatches(ABOUT_PAGE) && ( | |||
| <> | |||
| <AddOfferButton | |||
| type="submit" | |||
| variant="contained" | |||
| fullWidth | |||
| buttoncolor={selectedTheme.colors.primaryYellow} | |||
| textcolor={selectedTheme.colors.yellowButtonTextColor} | |||
| onClick={() => { | |||
| setUserPopoverOpen(false); | |||
| setUserAnchorEl(null); | |||
| setShowCreateOfferModal(true); | |||
| }} | |||
| > | |||
| {t("header.addOffer")} | |||
| </AddOfferButton> | |||
| <IconButton | |||
| onClick={(e) => { | |||
| setPostsPopoverOpen(true); | |||
| setPostsAnchorEl(e.currentTarget); | |||
| }} | |||
| style={{ | |||
| background: | |||
| selectedTheme.colors.primaryIconBackgroundColor, | |||
| color: selectedTheme.colors.primaryPurple, | |||
| }} | |||
| > | |||
| <SwapsIcon /> | |||
| </IconButton> | |||
| <IconButton | |||
| onClick={(e) => { | |||
| setMsgPopoverOpen(true); | |||
| setMsgAnchorEl(e.currentTarget); | |||
| }} | |||
| style={{ | |||
| background: | |||
| selectedTheme.colors.primaryIconBackgroundColor, | |||
| color: selectedTheme.colors.primaryPurple, | |||
| }} | |||
| > | |||
| <Badge color="primary"> | |||
| <MailIcon /> | |||
| </Badge> | |||
| </IconButton> | |||
| <AddOfferButton onClick={handleAddOfferClick} /> | |||
| <MySwapsButton onClick={openPostsPopover} /> | |||
| <MyMessagesButton onClick={openMesgPopover} /> | |||
| </> | |||
| )} | |||
| <UserButton | |||
| onClick={(e) => { | |||
| setUserPopoverOpen(true); | |||
| setUserAnchorEl(e.currentTarget); | |||
| }} | |||
| > | |||
| <UserName>{name}</UserName> | |||
| <IconButton | |||
| style={{ | |||
| background: selectedTheme.colors.primaryIconBackgroundColor, | |||
| color: selectedTheme.colors.primaryPurple, | |||
| }} | |||
| > | |||
| <AccountCircle /> | |||
| </IconButton> | |||
| </UserButton> | |||
| <UserButton onClick={openUserPopover} name={name}/> | |||
| </React.Fragment> | |||
| )} | |||
| </ToolsButtonsContainer> | |||
| ) : ( | |||
| <AuthButtonsContainer mobile={matches}> | |||
| {matches ? ( | |||
| <ToggleDrawerButton> | |||
| <IconButton onClick={handleToggleDrawer}> | |||
| <MenuOutlinedIcon /> | |||
| </IconButton> | |||
| </ToggleDrawerButton> | |||
| <OpenDrawerButton | |||
| onClick={drawerRef.current.handleToggleDrawer} | |||
| /> | |||
| ) : ( | |||
| <React.Fragment> | |||
| <LoginButton | |||
| @@ -409,7 +306,7 @@ const Header = () => { | |||
| </React.Fragment> | |||
| )} | |||
| </AppBar> | |||
| <SearchInputMobile | |||
| {/* <SearchInputMobile | |||
| fullWidth | |||
| shouldShow={showSearchBar} | |||
| ref={searchMobileRef} | |||
| @@ -426,7 +323,7 @@ const Header = () => { | |||
| italicPlaceholder | |||
| onFocus={handleFocusSearch} | |||
| onBlur={handleBlurSearch} | |||
| /> | |||
| /> */} | |||
| {/* <FilterCard | |||
| responsive={true} | |||
| responsiveOpen={openFilters} | |||
| @@ -1,41 +1,8 @@ | |||
| import { Box, Typography } from "@mui/material"; | |||
| import { Box } from "@mui/material"; | |||
| import styled from "styled-components"; | |||
| import { PrimaryButton } from "../Buttons/PrimaryButton/PrimaryButton"; | |||
| import { TextField } from "../TextFields/TextField/TextField"; | |||
| import { ReactComponent as Search } from "../../assets/images/svg/magnifying-glass.svg"; | |||
| import { ReactComponent as Swaps } from "../../assets/images/svg/swaps.svg"; | |||
| import selectedTheme from "../../themes"; | |||
| import { Icon } from "../Icon/Icon"; | |||
| export const SearchInput = styled(TextField)` | |||
| background-color: ${selectedTheme.colors.primaryBackgroundColor}; | |||
| width: 45%; | |||
| flex: 3; | |||
| max-width: 520px; | |||
| margin-right: 30px; | |||
| font-family: ${selectedTheme.fonts.textFont}; | |||
| @media (max-width: 1700px) { | |||
| margin-left: 15%; | |||
| } | |||
| @media (max-width: 1550px) { | |||
| margin-left: 15%; | |||
| } | |||
| @media (max-width: 1320px) { | |||
| margin-left: 7%; | |||
| } | |||
| @media (max-width: 1100px) { | |||
| width: 36%; | |||
| } | |||
| @media (max-width: 1000px) { | |||
| width: 36%; | |||
| margin-left: 5%; | |||
| margin-right: 10px; | |||
| } | |||
| @media (max-width: 550px) { | |||
| display: none; | |||
| width: 0; | |||
| } | |||
| `; | |||
| export const DrawerContainer = styled(Box)` | |||
| display: flex; | |||
| flex-direction: column; | |||
| @@ -80,44 +47,6 @@ export const ToolsButtonsContainer = styled(Box)` | |||
| justify-content: right; | |||
| } | |||
| `; | |||
| export const ToggleDrawerButton = styled(Box)` | |||
| max-width: 40px; | |||
| `; | |||
| export const AddOfferButton = styled(PrimaryButton)` | |||
| height: 49px; | |||
| width: 180px; | |||
| font-weight: 600; | |||
| `; | |||
| export const EndIcon = styled(Icon)``; | |||
| export const SearchIcon = styled(Search)` | |||
| position: relative; | |||
| top: 11px; | |||
| left: 4px; | |||
| cursor: pointer; | |||
| color: ${selectedTheme.colors.primaryPurple}; | |||
| & path { | |||
| width: 18px; | |||
| height: 18px; | |||
| } | |||
| @media (max-width: 600px) { | |||
| height: 14px; | |||
| width: 14px; | |||
| left: 11px; | |||
| } | |||
| `; | |||
| export const UserButton = styled(Box)` | |||
| display: flex; | |||
| flex-direction: row; | |||
| cursor: pointer; | |||
| `; | |||
| export const UserName = styled(Typography)` | |||
| color: ${selectedTheme.colors.primaryPurple}; | |||
| padding-top: 5px; | |||
| padding-right: 10px; | |||
| font-family: ${selectedTheme.fonts.textFont}; | |||
| font-weight: 600; | |||
| white-space: nowrap; | |||
| `; | |||
| export const ToolsContainer = styled(Box)` | |||
| display: flex; | |||
| flex-direction: row; | |||
| @@ -176,29 +105,4 @@ export const AuthButtonsDrawerContainer = styled(Box)` | |||
| flex: 1; | |||
| justify-content: space-around; | |||
| `; | |||
| export const SearchInputMobile = styled(SearchInput)` | |||
| @media (max-width: 550px) { | |||
| display: block; | |||
| position: relative; | |||
| width: 80%; | |||
| top: 70px; | |||
| height: 46px; | |||
| left: -5px; | |||
| font-family: ${selectedTheme.fonts.textFont}; | |||
| ${(props) => !props.shouldShow && `display: none;`} | |||
| & div { | |||
| background-color: white; | |||
| height: 40px; | |||
| overflow: visible; | |||
| & input { | |||
| font-size: 14px !important; | |||
| } | |||
| } | |||
| } | |||
| @media (min-width: 551px) { | |||
| display: none; | |||
| width: 0; | |||
| } | |||
| `; | |||
| export const HeaderContainer = styled(Box)``; | |||
| export const SwapsIcon = styled(Swaps)``; | |||
| @@ -0,0 +1,28 @@ | |||
| import React from "react"; | |||
| import PropTypes from "prop-types"; | |||
| import selectedTheme from "../../../themes"; | |||
| import { IconButton } from "../../Buttons/IconButton/IconButton"; | |||
| import MailIcon from "@mui/icons-material/EmailOutlined"; | |||
| import { Badge } from "@mui/material"; | |||
| const MyMessagesButton = (props) => { | |||
| return ( | |||
| <IconButton | |||
| onClick={props.onClick} | |||
| style={{ | |||
| background: selectedTheme.colors.primaryIconBackgroundColor, | |||
| color: selectedTheme.colors.primaryPurple, | |||
| }} | |||
| > | |||
| <Badge color="primary"> | |||
| <MailIcon /> | |||
| </Badge> | |||
| </IconButton> | |||
| ); | |||
| }; | |||
| MyMessagesButton.propTypes = { | |||
| onClick: PropTypes.func, | |||
| }; | |||
| export default MyMessagesButton; | |||
| @@ -0,0 +1,25 @@ | |||
| import React from "react"; | |||
| import PropTypes from "prop-types"; | |||
| import selectedTheme from "../../../themes"; | |||
| import { IconButton } from "../../Buttons/IconButton/IconButton"; | |||
| import { SwapsIcon } from "./MySwapsButton.styled"; | |||
| const MySwapsButton = (props) => { | |||
| return ( | |||
| <IconButton | |||
| onClick={props.onClick} | |||
| style={{ | |||
| background: selectedTheme.colors.primaryIconBackgroundColor, | |||
| color: selectedTheme.colors.primaryPurple, | |||
| }} | |||
| > | |||
| <SwapsIcon /> | |||
| </IconButton> | |||
| ); | |||
| }; | |||
| MySwapsButton.propTypes = { | |||
| onClick: PropTypes.func, | |||
| }; | |||
| export default MySwapsButton; | |||
| @@ -0,0 +1,3 @@ | |||
| import styled from "styled-components"; | |||
| import { ReactComponent as Swaps } from "../../../assets/images/svg/swaps.svg"; | |||
| export const SwapsIcon = styled(Swaps)``; | |||
| @@ -0,0 +1,21 @@ | |||
| import React from "react"; | |||
| import PropTypes from "prop-types"; | |||
| import MenuOutlinedIcon from "@mui/icons-material/MenuOutlined"; | |||
| import { IconButton } from "../../Buttons/IconButton/IconButton"; | |||
| import { ToggleDrawerButton } from "./OpenDrawerButton.styled"; | |||
| const OpenDrawerButton = (props) => { | |||
| return ( | |||
| <ToggleDrawerButton> | |||
| <IconButton onClick={props.onClick}> | |||
| <MenuOutlinedIcon /> | |||
| </IconButton> | |||
| </ToggleDrawerButton> | |||
| ); | |||
| }; | |||
| OpenDrawerButton.propTypes = { | |||
| onClick: PropTypes.func, | |||
| }; | |||
| export default OpenDrawerButton; | |||
| @@ -0,0 +1,6 @@ | |||
| import { Box } from "@mui/material"; | |||
| import styled from "styled-components"; | |||
| export const ToggleDrawerButton = styled(Box)` | |||
| max-width: 40px; | |||
| `; | |||
| @@ -0,0 +1,58 @@ | |||
| import React from "react"; | |||
| import PropTypes from "prop-types"; | |||
| import { | |||
| EndIcon, | |||
| SearchIcon, | |||
| SearchInputContainer, | |||
| } from "./SearchInput.styled"; | |||
| import { forwardRef } from "react"; | |||
| import { useCallback } from "react"; | |||
| import { useTranslation } from "react-i18next"; | |||
| import { routeMatches } from "../../../util/helpers/routeHelpers"; | |||
| import { ABOUT_PAGE } from "../../../constants/pages"; | |||
| const SearchInput = forwardRef((props, ref) => { | |||
| const { t } = useTranslation(); | |||
| const listener = useCallback( | |||
| (event) => { | |||
| if (event.keyCode === 13) { | |||
| event.preventDefault(); | |||
| props.handleSearch(ref.current.value); | |||
| } | |||
| }, | |||
| [ref.current] | |||
| ); | |||
| const handleFocusSearch = () => { | |||
| ref.current.addEventListener("keyup", listener); | |||
| }; | |||
| const handleBlurSearch = () => { | |||
| ref.current.removeEventListener("keyup", listener); | |||
| }; | |||
| if (routeMatches(ABOUT_PAGE)) { | |||
| return <></>; | |||
| } | |||
| return ( | |||
| <SearchInputContainer | |||
| fullWidth | |||
| InputProps={{ | |||
| endAdornment: ( | |||
| <EndIcon size="36px"> | |||
| <SearchIcon onClick={() => props.handleSearch(ref.current.value)} /> | |||
| </EndIcon> | |||
| ), | |||
| }} | |||
| placeholder={t("header.searchOffers")} | |||
| onFocus={handleFocusSearch} | |||
| onBlur={handleBlurSearch} | |||
| ref={ref} | |||
| /> | |||
| ); | |||
| }); | |||
| SearchInput.displayName = "SearchInput"; | |||
| SearchInput.propTypes = { | |||
| handleSearch: PropTypes.func, | |||
| }; | |||
| export default SearchInput; | |||
| @@ -0,0 +1,73 @@ | |||
| import styled from "styled-components"; | |||
| import selectedTheme from "../../../themes"; | |||
| import { TextField } from "../../TextFields/TextField/TextField"; | |||
| import { ReactComponent as Search } from "../../../assets/images/svg/magnifying-glass.svg"; | |||
| import { Icon } from "../../Icon/Icon"; | |||
| export const SearchInputContainer = styled(TextField)` | |||
| background-color: ${selectedTheme.colors.primaryBackgroundColor}; | |||
| width: 45%; | |||
| flex: 3; | |||
| max-width: 520px; | |||
| margin-right: 30px; | |||
| font-family: ${selectedTheme.fonts.textFont}; | |||
| @media (max-width: 1700px) { | |||
| margin-left: 15%; | |||
| } | |||
| @media (max-width: 1550px) { | |||
| margin-left: 15%; | |||
| } | |||
| @media (max-width: 1320px) { | |||
| margin-left: 7%; | |||
| } | |||
| @media (max-width: 1100px) { | |||
| width: 36%; | |||
| } | |||
| @media (max-width: 1000px) { | |||
| width: 36%; | |||
| margin-left: 5%; | |||
| margin-right: 10px; | |||
| } | |||
| @media (max-width: 550px) { | |||
| /* display: none; */ | |||
| /* width: 0; */ | |||
| display: block; | |||
| /* position: relative; */ | |||
| width: 80%; | |||
| /* top: 70px; */ | |||
| height: 46px; | |||
| margin-right: 27px; | |||
| /* left: -5px; */ | |||
| font-family: ${selectedTheme.fonts.textFont}; | |||
| /* ${(props) => !props.shouldShow && `display: none;`} */ | |||
| & div { | |||
| /* background-color: white; */ | |||
| height: 46px; | |||
| overflow: visible; | |||
| & input { | |||
| font-size: 14px !important; | |||
| } | |||
| } | |||
| } | |||
| `; | |||
| export const EndIcon = styled(Icon)` | |||
| @media (max-width: 600px) { | |||
| display: none; | |||
| } | |||
| `; | |||
| export const SearchIcon = styled(Search)` | |||
| position: relative; | |||
| top: 11px; | |||
| left: 4px; | |||
| cursor: pointer; | |||
| color: ${selectedTheme.colors.primaryPurple}; | |||
| & path { | |||
| width: 18px; | |||
| height: 18px; | |||
| } | |||
| @media (max-width: 600px) { | |||
| height: 14px; | |||
| width: 14px; | |||
| left: 11px; | |||
| } | |||
| `; | |||
| @@ -0,0 +1,29 @@ | |||
| import React from "react"; | |||
| import PropTypes from "prop-types"; | |||
| import selectedTheme from "../../../themes"; | |||
| import { AccountCircle } from "@mui/icons-material"; | |||
| import { IconButton } from "../../Buttons/IconButton/IconButton"; | |||
| import { UserButtonContainer, UserName } from "./UserButton.styled"; | |||
| const UserButton = (props) => { | |||
| return ( | |||
| <UserButtonContainer onClick={props.onClick}> | |||
| <UserName>{props.name}</UserName> | |||
| <IconButton | |||
| style={{ | |||
| background: selectedTheme.colors.primaryIconBackgroundColor, | |||
| color: selectedTheme.colors.primaryPurple, | |||
| }} | |||
| > | |||
| <AccountCircle /> | |||
| </IconButton> | |||
| </UserButtonContainer> | |||
| ); | |||
| }; | |||
| UserButton.propTypes = { | |||
| onClick: PropTypes.func, | |||
| name: PropTypes.string, | |||
| }; | |||
| export default UserButton; | |||
| @@ -0,0 +1,17 @@ | |||
| import { Box, Typography } from "@mui/material"; | |||
| import styled from "styled-components"; | |||
| import selectedTheme from "../../../themes"; | |||
| export const UserButtonContainer = styled(Box)` | |||
| display: flex; | |||
| flex-direction: row; | |||
| cursor: pointer; | |||
| `; | |||
| export const UserName = styled(Typography)` | |||
| color: ${selectedTheme.colors.primaryPurple}; | |||
| padding-top: 5px; | |||
| padding-right: 10px; | |||
| font-family: ${selectedTheme.fonts.textFont}; | |||
| font-weight: 600; | |||
| white-space: nowrap; | |||
| `; | |||
| @@ -2,13 +2,19 @@ export const reviewEnum = { | |||
| YES: { | |||
| value: 1, | |||
| mainText: "Da", | |||
| backendText: "succeeded" | |||
| }, | |||
| NO: { | |||
| value: 2, | |||
| mainText: "Ne" | |||
| mainText: "Ne", | |||
| // Unsuccessful swap | |||
| backendText: "failed", | |||
| // Not good communication | |||
| backendTextSecond: "no" | |||
| }, | |||
| NOT_BAD: { | |||
| value: 3, | |||
| mainText: "Može bolje" | |||
| mainText: "Može bolje", | |||
| backendText: "could be better" | |||
| } | |||
| } | |||
| @@ -170,6 +170,8 @@ export default { | |||
| changeOffer: "Izmena Objave", | |||
| newOffer: "Nova Objava", | |||
| product: "Proizvod", | |||
| descriptionLabel: "Opis:", | |||
| checkButtonLabel: "Pogledaj proizvod" | |||
| }, | |||
| apiErrors: { | |||
| somethingWentWrong: "Greška sa serverom!", | |||
| @@ -202,6 +204,8 @@ export default { | |||
| selectFieldError: "Odaberite jedno polje!", | |||
| leaveComment: "Ostavi komentar", | |||
| rates: "Ocene kompanije", | |||
| finishedReviewTitle: "Hvala vam", | |||
| finishedReviewAltTitle: "na izdvojenom vremenu i datoj oceni!" | |||
| }, | |||
| messages: { | |||
| headerTitle: "Moje Ćaskanje", | |||
| @@ -0,0 +1,8 @@ | |||
| import { reviewEnum } from "../../enums/reviewEnum"; | |||
| export default (informations) => ({ | |||
| exchangeSucceed: informations?.exchangeSucceed || reviewEnum.YES.mainText, | |||
| correctCommunication: | |||
| informations?.correctCommunication || reviewEnum.YES.mainText, | |||
| comment: informations?.comment || "", | |||
| }); | |||
| @@ -0,0 +1,6 @@ | |||
| import i18next from "i18next"; | |||
| import * as Yup from "yup"; | |||
| export default Yup.object().shape({ | |||
| comment: Yup.string().min(5, i18next.t("reviews.commentError")), | |||
| }); | |||
| @@ -88,11 +88,11 @@ | |||
| "@babel/types" "^7.12.13" | |||
| "@babel/helper-annotate-as-pure@^7.16.0": | |||
| "integrity" "sha512-s6t2w/IPQVTAET1HitoowRGXooX8mCgtuP5195wD/QJPV6wYjpujCGF7JuMODVX2ZAJOf1GT6DT9MHEZvLOFSw==" | |||
| "resolved" "https://registry.npmjs.org/@babel/helper-annotate-as-pure/-/helper-annotate-as-pure-7.16.7.tgz" | |||
| "version" "7.16.7" | |||
| "integrity" "sha512-duORpUiYrEpzKIop6iNbjnwKLAKnJ47csTyRACyEmWj0QdUrm5aqNJGHSSEQSUAvNW0ojX0dOmK9dZduvkfeXA==" | |||
| "resolved" "https://registry.npmjs.org/@babel/helper-annotate-as-pure/-/helper-annotate-as-pure-7.18.6.tgz" | |||
| "version" "7.18.6" | |||
| dependencies: | |||
| "@babel/types" "^7.16.7" | |||
| "@babel/types" "^7.18.6" | |||
| "@babel/helper-builder-binary-assignment-operator-visitor@^7.12.13": | |||
| "integrity" "sha512-CZOv9tGphhDRlVjVkAgm8Nhklm9RzSmWpX2my+t7Ua/KT616pEzXsQCjinzvkRvHWJ9itO4f296efroX23XCMA==" | |||
| @@ -192,11 +192,11 @@ | |||
| "@babel/types" "^7.13.12" | |||
| "@babel/helper-module-imports@^7.16.0": | |||
| "integrity" "sha512-LVtS6TqjJHFc+nYeITRo6VLXve70xmq7wPhWTqDJusJEgGmkAACWwMiTNrvfoQo6hEhFwAIixNkvB0jPXDL8Wg==" | |||
| "resolved" "https://registry.npmjs.org/@babel/helper-module-imports/-/helper-module-imports-7.16.7.tgz" | |||
| "version" "7.16.7" | |||
| "integrity" "sha512-0NFvs3VkuSYbFi1x2Vd6tKrywq+z/cLeYC/RJNFrIX/30Bf5aiGYbtvGXolEktzJH8o5E5KJ3tT+nkxuuZFVlA==" | |||
| "resolved" "https://registry.npmjs.org/@babel/helper-module-imports/-/helper-module-imports-7.18.6.tgz" | |||
| "version" "7.18.6" | |||
| dependencies: | |||
| "@babel/types" "^7.16.7" | |||
| "@babel/types" "^7.18.6" | |||
| "@babel/helper-module-transforms@^7.12.1", "@babel/helper-module-transforms@^7.13.0", "@babel/helper-module-transforms@^7.14.0", "@babel/helper-module-transforms@^7.14.2": | |||
| "integrity" "sha512-OznJUda/soKXv0XhpvzGWDnml4Qnwp16GN+D/kZIdLsWoHj05kyu8Rm5kXmMef+rVJZ0+4pSGLkeixdqNUATDA==" | |||
| @@ -269,10 +269,10 @@ | |||
| "resolved" "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.14.0.tgz" | |||
| "version" "7.14.0" | |||
| "@babel/helper-validator-identifier@^7.16.7": | |||
| "integrity" "sha512-hsEnFemeiW4D08A5gUAZxLBTXpZ39P+a+DGDsHw1yxqyQ/jzFEnxf5uTEGp+3bzAbNOxU1paTgYS4ECU/IgfDw==" | |||
| "resolved" "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.16.7.tgz" | |||
| "version" "7.16.7" | |||
| "@babel/helper-validator-identifier@^7.18.6": | |||
| "integrity" "sha512-MmetCkz9ej86nJQV+sFCxoGGrUbU3q02kgLciwkrt9QqEB7cP39oKEY0PakknEO0Gu20SskMRi+AYZ3b1TpN9g==" | |||
| "resolved" "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.18.6.tgz" | |||
| "version" "7.18.6" | |||
| "@babel/helper-validator-option@^7.12.1", "@babel/helper-validator-option@^7.12.17": | |||
| "integrity" "sha512-TopkMDmLzq8ngChwRlyjR6raKD6gMSae4JdYDB8bByKreQgG0RBTuKe9LRxW3wFtUnjxOPRKBDwEH6Mg5KeDfw==" | |||
| @@ -1250,12 +1250,12 @@ | |||
| "@babel/helper-validator-identifier" "^7.14.0" | |||
| "to-fast-properties" "^2.0.0" | |||
| "@babel/types@^7.16.7": | |||
| "integrity" "sha512-ThN1mBcMq5pG/Vm2IcBmPPfyPXbd8S02rS+OBIDENdufvqC7Z/jHPCv9IcP01277aKtDI8g/2XysBN4hA8niiw==" | |||
| "resolved" "https://registry.npmjs.org/@babel/types/-/types-7.18.4.tgz" | |||
| "version" "7.18.4" | |||
| "@babel/types@^7.18.6": | |||
| "integrity" "sha512-WwMLAg2MvJmt/rKEVQBBhIVffMmnilX4oe0sRe7iPOHIGsqpruFHHdrfj4O1CMMtgMtCU4oPafZjDPCRgO57Wg==" | |||
| "resolved" "https://registry.npmjs.org/@babel/types/-/types-7.18.9.tgz" | |||
| "version" "7.18.9" | |||
| dependencies: | |||
| "@babel/helper-validator-identifier" "^7.16.7" | |||
| "@babel/helper-validator-identifier" "^7.18.6" | |||
| "to-fast-properties" "^2.0.0" | |||
| "@bcoe/v8-coverage@^0.2.3": | |||
| @@ -1833,6 +1833,16 @@ | |||
| "redux-thunk" "^2.4.1" | |||
| "reselect" "^4.1.5" | |||
| "@rive-app/canvas@1.0.83": | |||
| "integrity" "sha512-IARYWsnh1NPWY2wTYZ15TBg8Bbe9LEPGSHHd8TivmCfagK61WtAPiPjApGUN3Fbk0MUWjmbNwtv9aK3x7QRkog==" | |||
| "resolved" "https://registry.npmjs.org/@rive-app/canvas/-/canvas-1.0.83.tgz" | |||
| "version" "1.0.83" | |||
| "@rive-app/webgl@1.0.79": | |||
| "integrity" "sha512-zP8q0D1EOvS0bllhRy3iWwwLxsZ6y7Q01HdZNWo4tNui6EDRC7DRNr40mLSMDKqgF79eZo9vf3lkk8/Wai0fsA==" | |||
| "resolved" "https://registry.npmjs.org/@rive-app/webgl/-/webgl-1.0.79.tgz" | |||
| "version" "1.0.79" | |||
| "@rollup/plugin-node-resolve@^7.1.1": | |||
| "integrity" "sha512-RxtSL3XmdTAE2byxekYLnx+98kEUOrPHF/KRVjLH+DEIHy6kjIw7YINQzn+NXiH/NTrQLAwYs0GWB+csWygA9Q==" | |||
| "resolved" "https://registry.npmjs.org/@rollup/plugin-node-resolve/-/plugin-node-resolve-7.1.3.tgz" | |||
| @@ -1880,6 +1890,11 @@ | |||
| dependencies: | |||
| "@sinonjs/commons" "^1.7.0" | |||
| "@socket.io/component-emitter@~3.1.0": | |||
| "integrity" "sha512-+9jVqKhRSpsc591z5vX+X5Yyw+he/HCB4iQ/RYxw35CEPaY1gnsNE43nf9n9AaYjAQrTiI/mOwKUKdUs9vf7Xg==" | |||
| "resolved" "https://registry.npmjs.org/@socket.io/component-emitter/-/component-emitter-3.1.0.tgz" | |||
| "version" "3.1.0" | |||
| "@surma/rollup-plugin-off-main-thread@^1.1.1": | |||
| "integrity" "sha512-yBMPqmd1yEJo/280PAMkychuaALyQ9Lkb5q1ck3mjJrFuEobIfhnQ4J3mbvBoISmR3SWMWV+cGB/I0lCQee79A==" | |||
| "resolved" "https://registry.npmjs.org/@surma/rollup-plugin-off-main-thread/-/rollup-plugin-off-main-thread-1.4.2.tgz" | |||
| @@ -2084,6 +2099,21 @@ | |||
| dependencies: | |||
| "@babel/types" "^7.3.0" | |||
| "@types/component-emitter@^1.2.10": | |||
| "integrity" "sha512-SRXjM+tfsSlA9VuG8hGO2nft2p8zjXCK1VcC6N4NXbBbYbSia9kzCChYQajIjzIqOOOuh5Ock6MmV2oux4jDZQ==" | |||
| "resolved" "https://registry.npmjs.org/@types/component-emitter/-/component-emitter-1.2.11.tgz" | |||
| "version" "1.2.11" | |||
| "@types/cookie@^0.4.1": | |||
| "integrity" "sha512-XW/Aa8APYr6jSVVA1y/DEIZX0/GMKLEVekNG727R8cs56ahETkRAy/3DR7+fJyh7oUgGwNQaRfXCun0+KbWY7Q==" | |||
| "resolved" "https://registry.npmjs.org/@types/cookie/-/cookie-0.4.1.tgz" | |||
| "version" "0.4.1" | |||
| "@types/cors@^2.8.12": | |||
| "integrity" "sha512-vt+kDhq/M2ayberEtJcIN/hxXy1Pk+59g2FV/ZQceeaTyCtCucjL2Q7FXlFjtWn4n15KCr1NE2lNNFhp0lEThw==" | |||
| "resolved" "https://registry.npmjs.org/@types/cors/-/cors-2.8.12.tgz" | |||
| "version" "2.8.12" | |||
| "@types/eslint@^7.2.6": | |||
| "integrity" "sha512-LKmQCWAlnVHvvXq4oasNUMTJJb2GwSyTY8+1C7OH5ILR8mPLaljv1jxL1bXW3xB3jFbQxTKxJAvI8PyjB09aBg==" | |||
| "resolved" "https://registry.npmjs.org/@types/eslint/-/eslint-7.2.13.tgz" | |||
| @@ -2177,7 +2207,7 @@ | |||
| "resolved" "https://registry.npmjs.org/@types/minimatch/-/minimatch-3.0.4.tgz" | |||
| "version" "3.0.4" | |||
| "@types/node@*": | |||
| "@types/node@*", "@types/node@>=10.0.0": | |||
| "integrity" "sha512-+aHJvoCsVhO2ZCuT4o5JtcPrCPyDE3+1nvbDprYes+pPkEsbjH7AGUCNtjMOXS0fqH14t+B7yLzaqSz92FPWyw==" | |||
| "resolved" "https://registry.npmjs.org/@types/node/-/node-15.12.0.tgz" | |||
| "version" "15.12.0" | |||
| @@ -3198,6 +3228,11 @@ | |||
| "resolved" "https://registry.npmjs.org/base64-js/-/base64-js-1.5.1.tgz" | |||
| "version" "1.5.1" | |||
| "base64id@~2.0.0", "base64id@2.0.0": | |||
| "integrity" "sha512-lGe34o6EHj9y3Kts9R4ZYs/Gr+6N7MCaMlIFA3F1R2O5/m7K06AxfSeO5530PEERE6/WyEg3lsuyw4GHlPZHog==" | |||
| "resolved" "https://registry.npmjs.org/base64id/-/base64id-2.0.0.tgz" | |||
| "version" "2.0.0" | |||
| "basic-auth@~2.0.1": | |||
| "integrity" "sha512-NF+epuEdnUYVlGuhaxbbq+dvJttwLnGY+YixlXlME5KpQ5W3CnXA5cVTneY3SPbPDRkcjMbifrwmFYcClgOZeg==" | |||
| "resolved" "https://registry.npmjs.org/basic-auth/-/basic-auth-2.0.1.tgz" | |||
| @@ -3938,7 +3973,7 @@ | |||
| "resolved" "https://registry.npmjs.org/commondir/-/commondir-1.0.1.tgz" | |||
| "version" "1.0.1" | |||
| "component-emitter@^1.2.1": | |||
| "component-emitter@^1.2.1", "component-emitter@~1.3.0": | |||
| "integrity" "sha512-Rd3se6QB+sO1TwqZjscQrurpEPIfO0/yYnSin6Q/rD3mOutHvUrCAhJub3r90uNb+SESBuE0QYoB90YdfatsRg==" | |||
| "resolved" "https://registry.npmjs.org/component-emitter/-/component-emitter-1.3.0.tgz" | |||
| "version" "1.3.0" | |||
| @@ -4051,6 +4086,11 @@ | |||
| "resolved" "https://registry.npmjs.org/cookie-signature/-/cookie-signature-1.0.6.tgz" | |||
| "version" "1.0.6" | |||
| "cookie@~0.4.1": | |||
| "integrity" "sha512-aSWTXFzaKWkvHO1Ny/s+ePFpvKsPnjc551iI41v3ny/ow6tBG5Vd+FuqGNhh1LxOmVzOlGUriIlOaokOvhaStA==" | |||
| "resolved" "https://registry.npmjs.org/cookie/-/cookie-0.4.2.tgz" | |||
| "version" "0.4.2" | |||
| "cookie@0.4.0": | |||
| "integrity" "sha512-+Hp8fLp57wnUSt0tY0tHEXh4voZRDnoIrZPqlo3DPiI4y9lwg/jqx+1Om94/W6ZaPDOUbnjOt/99w66zk+l1Xg==" | |||
| "resolved" "https://registry.npmjs.org/cookie/-/cookie-0.4.0.tgz" | |||
| @@ -4101,7 +4141,7 @@ | |||
| "resolved" "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz" | |||
| "version" "1.0.2" | |||
| "cors@^2.8.5": | |||
| "cors@^2.8.5", "cors@~2.8.5": | |||
| "integrity" "sha512-KIHbLJqu73RGr/hnbrO9uBeixNGuvSQjul/jdFvS/KFSIH1hWVd1ng7zOHx+YrEfInLG7q4n6GHQ9cDtxv/P6g==" | |||
| "resolved" "https://registry.npmjs.org/cors/-/cors-2.8.5.tgz" | |||
| "version" "2.8.5" | |||
| @@ -4495,7 +4535,7 @@ | |||
| "resolved" "https://registry.npmjs.org/debounce/-/debounce-1.2.1.tgz" | |||
| "version" "1.2.1" | |||
| "debug@*", "debug@^4.0.1", "debug@^4.1.0", "debug@^4.1.1", "debug@^4.3.1", "debug@4": | |||
| "debug@*", "debug@^4.0.1", "debug@^4.1.0", "debug@^4.1.1", "debug@^4.3.1", "debug@~4.3.1", "debug@4": | |||
| "integrity" "sha512-doEwdvm4PCeK4K3RQN2ZC2BYUBaxwLARCqZmMjtF8a51J2Rb0xpVloFRnCODwqjpwnAoao4pelN8l3RJdv3gRQ==" | |||
| "resolved" "https://registry.npmjs.org/debug/-/debug-4.3.1.tgz" | |||
| "version" "4.3.1" | |||
| @@ -4551,6 +4591,13 @@ | |||
| dependencies: | |||
| "ms" "^2.1.1" | |||
| "debug@~4.3.2": | |||
| "integrity" "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==" | |||
| "resolved" "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz" | |||
| "version" "4.3.4" | |||
| dependencies: | |||
| "ms" "2.1.2" | |||
| "debug@2.6.9": | |||
| "integrity" "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==" | |||
| "resolved" "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz" | |||
| @@ -4972,6 +5019,38 @@ | |||
| dependencies: | |||
| "once" "^1.4.0" | |||
| "engine.io-client@~6.2.1": | |||
| "integrity" "sha512-8ZQmx0LQGRTYkHuogVZuGSpDqYZtCM/nv8zQ68VZ+JkOpazJ7ICdsSpaO6iXwvaU30oFg5QJOJWj8zWqhbKjkQ==" | |||
| "resolved" "https://registry.npmjs.org/engine.io-client/-/engine.io-client-6.2.2.tgz" | |||
| "version" "6.2.2" | |||
| dependencies: | |||
| "@socket.io/component-emitter" "~3.1.0" | |||
| "debug" "~4.3.1" | |||
| "engine.io-parser" "~5.0.3" | |||
| "ws" "~8.2.3" | |||
| "xmlhttprequest-ssl" "~2.0.0" | |||
| "engine.io-parser@~5.0.3": | |||
| "integrity" "sha512-+nVFp+5z1E3HcToEnO7ZIj3g+3k9389DvWtvJZz0T6/eOCPIyyxehFcedoYrZQrp0LgQbD9pPXhpMBKMd5QURg==" | |||
| "resolved" "https://registry.npmjs.org/engine.io-parser/-/engine.io-parser-5.0.4.tgz" | |||
| "version" "5.0.4" | |||
| "engine.io@~6.2.0": | |||
| "integrity" "sha512-4KzwW3F3bk+KlzSOY57fj/Jx6LyRQ1nbcyIadehl+AnXjKT7gDO0ORdRi/84ixvMKTym6ZKuxvbzN62HDDU1Lg==" | |||
| "resolved" "https://registry.npmjs.org/engine.io/-/engine.io-6.2.0.tgz" | |||
| "version" "6.2.0" | |||
| dependencies: | |||
| "@types/cookie" "^0.4.1" | |||
| "@types/cors" "^2.8.12" | |||
| "@types/node" ">=10.0.0" | |||
| "accepts" "~1.3.4" | |||
| "base64id" "2.0.0" | |||
| "cookie" "~0.4.1" | |||
| "cors" "~2.8.5" | |||
| "debug" "~4.3.1" | |||
| "engine.io-parser" "~5.0.3" | |||
| "ws" "~8.2.3" | |||
| "enhanced-resolve@^4.3.0": | |||
| "integrity" "sha512-Nv9m36S/vxpsI+Hc4/ZGRs0n9mXqSWGGq49zxb/cJfPAQMbUtttJAlNPS4AQzaBdw/pKskw5bMbekT/Y7W/Wlg==" | |||
| "resolved" "https://registry.npmjs.org/enhanced-resolve/-/enhanced-resolve-4.5.0.tgz" | |||
| @@ -5076,6 +5155,11 @@ | |||
| "es5-ext" "^0.10.35" | |||
| "es6-symbol" "^3.1.1" | |||
| "es6-promise@^4.2.8": | |||
| "integrity" "sha512-HJDGx5daxeIvxdBxvG2cb9g4tEvwIk3i8+nhX0yGrYmZUzbkdg8QbDevheDB8gd0//uPj4c1EQua8Q+MViT0/w==" | |||
| "resolved" "https://registry.npmjs.org/es6-promise/-/es6-promise-4.2.8.tgz" | |||
| "version" "4.2.8" | |||
| "es6-symbol@^3.1.1", "es6-symbol@~3.1.3": | |||
| "integrity" "sha512-NJ6Yn3FuDinBaBRWl/q5X/s4koRHBrgKAu+yGI6JCBeiu3qrcbJhwT2GeR/EXVfylRk8dpQVJoLEFhK+Mu31NA==" | |||
| "resolved" "https://registry.npmjs.org/es6-symbol/-/es6-symbol-3.1.3.tgz" | |||
| @@ -8679,6 +8763,11 @@ | |||
| "resolved" "https://registry.npmjs.org/nwsapi/-/nwsapi-2.2.0.tgz" | |||
| "version" "2.2.0" | |||
| "object-assign@^3.0.0": | |||
| "integrity" "sha512-jHP15vXVGeVh1HuaA2wY6lxk+whK/x4KBG88VXeRma7CCun7iGD5qPc4eYykQ9sdQvg8jkwFKsSxHln2ybW3xQ==" | |||
| "resolved" "https://registry.npmjs.org/object-assign/-/object-assign-3.0.0.tgz" | |||
| "version" "3.0.0" | |||
| "object-assign@^4", "object-assign@^4.0.1", "object-assign@^4.1.0", "object-assign@^4.1.1": | |||
| "integrity" "sha1-IQmtx5ZYh8/AXLvUQsrIv7s2CGM=" | |||
| "resolved" "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz" | |||
| @@ -10228,6 +10317,17 @@ | |||
| "regenerator-runtime" "^0.13.7" | |||
| "whatwg-fetch" "^3.4.1" | |||
| "react-autosuggest@^10.1.0": | |||
| "integrity" "sha512-/azBHmc6z/31s/lBf6irxPf/7eejQdR0IqnZUzjdSibtlS8+Rw/R79pgDAo6Ft5QqCUTyEQ+f0FhL+1olDQ8OA==" | |||
| "resolved" "https://registry.npmjs.org/react-autosuggest/-/react-autosuggest-10.1.0.tgz" | |||
| "version" "10.1.0" | |||
| dependencies: | |||
| "es6-promise" "^4.2.8" | |||
| "prop-types" "^15.7.2" | |||
| "react-themeable" "^1.1.0" | |||
| "section-iterator" "^2.0.0" | |||
| "shallow-equal" "^1.2.1" | |||
| "react-dev-utils@^11.0.3": | |||
| "integrity" "sha512-dx0LvIGHcOPtKbeiSUM4jqpBl3TcY7CDjZdfOIcKeznE7BWr9dg0iPG90G5yfVQ+p/rGNMXdbfStvzQZEVEi4A==" | |||
| "resolved" "https://registry.npmjs.org/react-dev-utils/-/react-dev-utils-11.0.4.tgz" | |||
| @@ -10258,7 +10358,7 @@ | |||
| "strip-ansi" "6.0.0" | |||
| "text-table" "0.2.0" | |||
| "react-dom@*", "react-dom@^15.0.0 || ^16.0.0 || ^17.0.0 || ^18.0.0", "react-dom@^16.6.0 || ^17.0.0 || ^18.0.0", "react-dom@^16.8.0 || ^17.0.0", "react-dom@^17.0.0 || ^18.0.0", "react-dom@^17.0.2", "react-dom@>= 16.8.0", "react-dom@>=16.6.0": | |||
| "react-dom@*", "react-dom@^15.0.0 || ^16.0.0 || ^17.0.0 || ^18.0.0", "react-dom@^16.6.0 || ^17.0.0 || ^18.0.0", "react-dom@^16.8.0 || ^17.0.0", "react-dom@^17.0.0 || ^18.0.0", "react-dom@^17.0.2", "react-dom@>= 16.8.0", "react-dom@>=16", "react-dom@>=16.6.0": | |||
| "integrity" "sha512-s4h96KtLDUQlsENhMn1ar8t2bEa+q/YAtj8pPPdIjPDGBDIVNsrD9aXNWqspUe6AzKCIG0C1HZZLqLV7qpOBGA==" | |||
| "resolved" "https://registry.npmjs.org/react-dom/-/react-dom-17.0.2.tgz" | |||
| "version" "17.0.2" | |||
| @@ -10468,6 +10568,25 @@ | |||
| "react-input-autosize" "^3.0.0" | |||
| "react-transition-group" "^4.3.0" | |||
| "react-singleton-hook@^3.4.0": | |||
| "integrity" "sha512-eQEpyacGAaRejmWUizUdNNQFn5AO0iaKRSl1jxgC0FQadVY/I1WFuPrYiutglPzO9s8yEbIh95UXVJQel4d7HQ==" | |||
| "resolved" "https://registry.npmjs.org/react-singleton-hook/-/react-singleton-hook-3.4.0.tgz" | |||
| "version" "3.4.0" | |||
| "react-themeable@^1.1.0": | |||
| "integrity" "sha512-kl5tQ8K+r9IdQXZd8WLa+xxYN04lLnJXRVhHfdgwsUJr/SlKJxIejoc9z9obEkx1mdqbTw1ry43fxEUwyD9u7w==" | |||
| "resolved" "https://registry.npmjs.org/react-themeable/-/react-themeable-1.1.0.tgz" | |||
| "version" "1.1.0" | |||
| dependencies: | |||
| "object-assign" "^3.0.0" | |||
| "react-toastify@^9.0.3": | |||
| "integrity" "sha512-0QZJk0SqYBxouRBGCFU3ymvjlwimRRhVH7SzqGRiVrQ001KSoUNbGKx9Yq42aoPv18n45yJzEFG82zqv3HnASg==" | |||
| "resolved" "https://registry.npmjs.org/react-toastify/-/react-toastify-9.0.3.tgz" | |||
| "version" "9.0.3" | |||
| dependencies: | |||
| "clsx" "^1.1.1" | |||
| "react-transition-group@^4.3.0", "react-transition-group@^4.4.2": | |||
| "integrity" "sha512-/RNYfRAMlZwDSr6z4zNKV6xu53/e2BuaBbGhbyYIXTrmgu/bGHzmqOs7mJSJBHy9Ud+ApHx3QjrkKSp1pxvlFg==" | |||
| "resolved" "https://registry.npmjs.org/react-transition-group/-/react-transition-group-4.4.2.tgz" | |||
| @@ -10478,7 +10597,7 @@ | |||
| "loose-envify" "^1.4.0" | |||
| "prop-types" "^15.6.2" | |||
| "react@*", "react@^0.14.0 || ^15.0.0 || ^16.0.0 || ^17.0.0", "react@^15.0.0 || ^16.0.0 || ^17.0.0 || ^18.0.0", "react@^16.3.0 || ^17.0.0", "react@^16.6.0 || ^17.0.0 || ^18.0.0", "react@^16.8.0 || ^17.0.0", "react@^16.8.3 || ^17 || ^18", "react@^16.9.0 || ^17.0.0 || ^18", "react@^17.0.0 || ^18.0.0", "react@^17.0.2", "react@^17.0.2 || ^18.0.0", "react@>= 16", "react@>= 16.8.0", "react@>=15", "react@>=16.6.0", "react@>=16.8.0", "react@17.0.2": | |||
| "react@*", "react@^0.14.0 || ^15.0.0 || ^16.0.0 || ^17.0.0", "react@^15.0.0 || ^16.0.0 || ^17.0.0 || ^18.0.0", "react@^16.3.0 || ^17.0.0", "react@^16.6.0 || ^17.0.0 || ^18.0.0", "react@^16.8.0 || ^17.0.0", "react@^16.8.0 || ^17.0.0 || ^18.0.0", "react@^16.8.3 || ^17 || ^18", "react@^16.9.0 || ^17.0.0 || ^18", "react@^17.0.0 || ^18.0.0", "react@^17.0.2", "react@^17.0.2 || ^18.0.0", "react@>= 16", "react@>= 16.8.0", "react@>=15", "react@>=16", "react@>=16.3.0", "react@>=16.6.0", "react@>=16.8.0", "react@15 - 18", "react@17.0.2": | |||
| "integrity" "sha512-gnhPt75i/dq/z3/6q/0asP78D0u592D5L1pd7M8P+dck6Fu/jJeL6iVVK23fptSUZj8Vjf++7wXA8UNclGQcbA==" | |||
| "resolved" "https://registry.npmjs.org/react/-/react-17.0.2.tgz" | |||
| "version" "17.0.2" | |||
| @@ -11018,6 +11137,14 @@ | |||
| "hash-base" "^3.0.0" | |||
| "inherits" "^2.0.1" | |||
| "rive-react@^3.0.23": | |||
| "integrity" "sha512-CMJaWgnVEZKLAsu5p1bBkBniCbaTLI+kqBh++y3XdK2aG4MCfYgxYr90rHstn/z4VW8/NP/i/l1NRYxrzgSgsw==" | |||
| "resolved" "https://registry.npmjs.org/rive-react/-/rive-react-3.0.23.tgz" | |||
| "version" "3.0.23" | |||
| dependencies: | |||
| "@rive-app/canvas" "1.0.83" | |||
| "@rive-app/webgl" "1.0.79" | |||
| "rollup-plugin-babel@^4.3.3": | |||
| "integrity" "sha512-Lek/TYp1+7g7I+uMfJnnSJ7YWoD58ajo6Oarhlex7lvUce+RCKRuGRSgztDO3/MF/PuGKmUL5iTHKf208UNszw==" | |||
| "resolved" "https://registry.npmjs.org/rollup-plugin-babel/-/rollup-plugin-babel-4.4.0.tgz" | |||
| @@ -11186,6 +11313,11 @@ | |||
| "ajv" "^6.12.5" | |||
| "ajv-keywords" "^3.5.2" | |||
| "section-iterator@^2.0.0": | |||
| "integrity" "sha512-xvTNwcbeDayXotnV32zLb3duQsP+4XosHpb/F+tu6VzEZFmIjzPdNk6/O+QOOx5XTh08KL2ufdXeCO33p380pQ==" | |||
| "resolved" "https://registry.npmjs.org/section-iterator/-/section-iterator-2.0.0.tgz" | |||
| "version" "2.0.0" | |||
| "select-hose@^2.0.0": | |||
| "integrity" "sha1-Yl2GWPhlr0Psliv8N2o3NZpJlMo=" | |||
| "resolved" "https://registry.npmjs.org/select-hose/-/select-hose-2.0.0.tgz" | |||
| @@ -11378,6 +11510,11 @@ | |||
| "inherits" "^2.0.1" | |||
| "safe-buffer" "^5.0.1" | |||
| "shallow-equal@^1.2.1": | |||
| "integrity" "sha512-S4vJDjHHMBaiZuT9NPb616CSmLf618jawtv3sufLl6ivK8WocjAo58cXwbRV1cgqxH0Qbv+iUt6m05eqEa2IRA==" | |||
| "resolved" "https://registry.npmjs.org/shallow-equal/-/shallow-equal-1.2.1.tgz" | |||
| "version" "1.2.1" | |||
| "shallowequal@^1.1.0": | |||
| "integrity" "sha512-y0m1JoUZSlPAjXVtPPW70aZWfIL/dSP7AFkRnniLCrK/8MDKog3TySTBmckD+RObVxH0v4Tox67+F14PdED2oQ==" | |||
| "resolved" "https://registry.npmjs.org/shallowequal/-/shallowequal-1.1.0.tgz" | |||
| @@ -11487,6 +11624,50 @@ | |||
| "source-map-resolve" "^0.5.0" | |||
| "use" "^3.1.0" | |||
| "socket.io-adapter@~2.4.0": | |||
| "integrity" "sha512-W4N+o69rkMEGVuk2D/cvca3uYsvGlMwsySWV447y99gUPghxq42BxqLNMndb+a1mm/5/7NeXVQS7RLa2XyXvYg==" | |||
| "resolved" "https://registry.npmjs.org/socket.io-adapter/-/socket.io-adapter-2.4.0.tgz" | |||
| "version" "2.4.0" | |||
| "socket.io-client@^4.5.1": | |||
| "integrity" "sha512-e6nLVgiRYatS+AHXnOnGi4ocOpubvOUCGhyWw8v+/FxW8saHkinG6Dfhi9TU0Kt/8mwJIAASxvw6eujQmjdZVA==" | |||
| "resolved" "https://registry.npmjs.org/socket.io-client/-/socket.io-client-4.5.1.tgz" | |||
| "version" "4.5.1" | |||
| dependencies: | |||
| "@socket.io/component-emitter" "~3.1.0" | |||
| "debug" "~4.3.2" | |||
| "engine.io-client" "~6.2.1" | |||
| "socket.io-parser" "~4.2.0" | |||
| "socket.io-parser@~4.0.4": | |||
| "integrity" "sha512-sNjbT9dX63nqUFIOv95tTVm6elyIU4RvB1m8dOeZt+IgWwcWklFDOdmGcfo3zSiRsnR/3pJkjY5lfoGqEe4Eig==" | |||
| "resolved" "https://registry.npmjs.org/socket.io-parser/-/socket.io-parser-4.0.5.tgz" | |||
| "version" "4.0.5" | |||
| dependencies: | |||
| "@types/component-emitter" "^1.2.10" | |||
| "component-emitter" "~1.3.0" | |||
| "debug" "~4.3.1" | |||
| "socket.io-parser@~4.2.0": | |||
| "integrity" "sha512-V4GrkLy+HeF1F/en3SpUaM+7XxYXpuMUWLGde1kSSh5nQMN4hLrbPIkD+otwh6q9R6NOQBN4AMaOZ2zVjui82g==" | |||
| "resolved" "https://registry.npmjs.org/socket.io-parser/-/socket.io-parser-4.2.1.tgz" | |||
| "version" "4.2.1" | |||
| dependencies: | |||
| "@socket.io/component-emitter" "~3.1.0" | |||
| "debug" "~4.3.1" | |||
| "socket.io@^4.5.1": | |||
| "integrity" "sha512-0y9pnIso5a9i+lJmsCdtmTTgJFFSvNQKDnPQRz28mGNnxbmqYg2QPtJTLFxhymFZhAIn50eHAKzJeiNaKr+yUQ==" | |||
| "resolved" "https://registry.npmjs.org/socket.io/-/socket.io-4.5.1.tgz" | |||
| "version" "4.5.1" | |||
| dependencies: | |||
| "accepts" "~1.3.4" | |||
| "base64id" "~2.0.0" | |||
| "debug" "~4.3.2" | |||
| "engine.io" "~6.2.0" | |||
| "socket.io-adapter" "~2.4.0" | |||
| "socket.io-parser" "~4.0.4" | |||
| "sockjs-client@^1.4.0", "sockjs-client@^1.5.0": | |||
| "integrity" "sha512-VnVAb663fosipI/m6pqRXakEOw7nvd7TUgdr3PlR/8V2I95QIdwT8L4nMxhyU8SmDBHYXU1TOElaKOmKLfYzeQ==" | |||
| "resolved" "https://registry.npmjs.org/sockjs-client/-/sockjs-client-1.5.1.tgz" | |||
| @@ -13179,6 +13360,11 @@ | |||
| "resolved" "https://registry.npmjs.org/ws/-/ws-7.4.6.tgz" | |||
| "version" "7.4.6" | |||
| "ws@~8.2.3": | |||
| "integrity" "sha512-wBuoj1BDpC6ZQ1B7DWQBYVLphPWkm8i9Y0/3YdHjHKHiohOJ1ws+3OccDWtH+PoC9DZD5WOTrJvNbWvjS6JWaA==" | |||
| "resolved" "https://registry.npmjs.org/ws/-/ws-8.2.3.tgz" | |||
| "version" "8.2.3" | |||
| "xdg-basedir@^4.0.0": | |||
| "integrity" "sha512-PSNhEJDejZYV7h50BohL09Er9VaIefr2LMAf3OEmpCkjOi34eYyQYAXUTjEQtZJTKcF0E2UKTh+osDLsgNim9Q==" | |||
| "resolved" "https://registry.npmjs.org/xdg-basedir/-/xdg-basedir-4.0.0.tgz" | |||
| @@ -13194,6 +13380,11 @@ | |||
| "resolved" "https://registry.npmjs.org/xmlchars/-/xmlchars-2.2.0.tgz" | |||
| "version" "2.2.0" | |||
| "xmlhttprequest-ssl@~2.0.0": | |||
| "integrity" "sha512-QKxVRxiRACQcVuQEYFsI1hhkrMlrXHPegbbd1yn9UHOmRxY+si12nQYzri3vbzt8VdTTRviqcKxcyllFas5z2A==" | |||
| "resolved" "https://registry.npmjs.org/xmlhttprequest-ssl/-/xmlhttprequest-ssl-2.0.0.tgz" | |||
| "version" "2.0.0" | |||
| "xtend@^4.0.0", "xtend@~4.0.1": | |||
| "integrity" "sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ==" | |||
| "resolved" "https://registry.npmjs.org/xtend/-/xtend-4.0.2.tgz" | |||
| @@ -13296,6 +13487,11 @@ | |||
| "resolved" "https://registry.npmjs.org/yocto-queue/-/yocto-queue-0.1.0.tgz" | |||
| "version" "0.1.0" | |||
| "yup-password@^0.2.2": | |||
| "integrity" "sha512-2PHfqGWtbXg4OfDV7VKFIb3hyEaYgTYpEORnFqgGAYqzENWmGzWMoeGvJg2Ohmq6maTRxhJzLZpNTITrqlZTrA==" | |||
| "resolved" "https://registry.npmjs.org/yup-password/-/yup-password-0.2.2.tgz" | |||
| "version" "0.2.2" | |||
| "yup@^0.32.9": | |||
| "integrity" "sha512-Z2Fe1bn+eLstG8DRR6FTavGD+MeAwyfmouhHsIUgaADz8jvFKbO/fXc2trJKZg+5EBjh4gGm3iU/t3onKlXHIg==" | |||
| "resolved" "https://registry.npmjs.org/yup/-/yup-0.32.11.tgz" | |||