Quellcode durchsuchen

Partly finished

feature/498
djordjemitrovic00 vor 3 Jahren
Ursprung
Commit
5f8e78e7a9
51 geänderte Dateien mit 25953 neuen und 705 gelöschten Zeilen
  1. 24700
    41
      package-lock.json
  2. 36
    0
      src/components/Cards/OfferCard/CheckButton/CheckButton.js
  3. 18
    0
      src/components/Cards/OfferCard/CheckButton/CheckButton.styled.js
  4. 10
    23
      src/components/Cards/OfferCard/OfferCard.js
  5. 1
    44
      src/components/Cards/OfferCard/OfferCard.styled.js
  6. 26
    0
      src/components/Cards/OfferCard/OfferDescription/OfferDescription.js
  7. 33
    0
      src/components/Cards/OfferCard/OfferDescription/OfferDescription.styled.js
  8. 35
    0
      src/components/Cards/UserReviewsCard/ReviewDetails/ReviewDetails.js
  9. 17
    0
      src/components/Cards/UserReviewsCard/ReviewDetails/ReviewDetails.styled.js
  10. 42
    0
      src/components/Cards/UserReviewsCard/ReviewQuote/ReviewQuote.js
  11. 31
    0
      src/components/Cards/UserReviewsCard/ReviewQuote/ReviewQuote.styled.js
  12. 31
    0
      src/components/Cards/UserReviewsCard/ReviewerProfile/ReviewerProfile.js
  13. 25
    0
      src/components/Cards/UserReviewsCard/ReviewerProfile/ReviewerProfile.styled.js
  14. 21
    76
      src/components/Cards/UserReviewsCard/UserReviewsCard.js
  15. 41
    96
      src/components/Cards/UserReviewsCard/UserReviewsCard.styled.js
  16. 31
    0
      src/components/CreateReview/FirstStep/CommentField/CommentField.js
  17. 31
    0
      src/components/CreateReview/FirstStep/CommentField/CommentField.styled.js
  18. 41
    0
      src/components/CreateReview/FirstStep/CorrectCommunicationField/CorrectCommunicationField.js
  19. 23
    93
      src/components/CreateReview/FirstStep/FirstStepCreateReview.js
  20. 1
    28
      src/components/CreateReview/FirstStep/FirstStepCreateReview.styled.js
  21. 27
    0
      src/components/CreateReview/FirstStep/NextButton/NextButton.js
  22. 0
    0
      src/components/CreateReview/FirstStep/NextButton/NextButton.styled.js
  23. 43
    0
      src/components/CreateReview/FirstStep/SuccessfulSwapField/SuccessfulSwapField.js
  24. 26
    0
      src/components/CreateReview/SecondStep/NextButton/NextButton.js
  25. 0
    0
      src/components/CreateReview/SecondStep/NextButton/NextButton.styled.js
  26. 3
    13
      src/components/CreateReview/SecondStep/SecondStepCreateReview.js
  27. 18
    11
      src/components/CreateReview/ThirdStep/ThirdStepCreateReview.js
  28. 3
    0
      src/components/DirectChat/DirectChat.js
  29. 0
    1
      src/components/DirectChat/DirectChatNewMessage/DirectChatNewMessage.js
  30. 3
    1
      src/components/Header/AboutHeader/AboutHeader.js
  31. 27
    0
      src/components/Header/AddOfferButton/AddOfferButton.js
  32. 8
    0
      src/components/Header/AddOfferButton/AddOfferButton.styled.js
  33. 42
    0
      src/components/Header/DrawerContainer/DrawerContainer.js
  34. 0
    0
      src/components/Header/DrawerContainer/DrawerContainer.styled.js
  35. 52
    155
      src/components/Header/Header.js
  36. 2
    98
      src/components/Header/Header.styled.js
  37. 28
    0
      src/components/Header/MyMessagesButton/MyMessagesButton.js
  38. 0
    0
      src/components/Header/MyMessagesButton/MyMessagesButton.styled.js
  39. 25
    0
      src/components/Header/MySwapsButton/MySwapsButton.js
  40. 3
    0
      src/components/Header/MySwapsButton/MySwapsButton.styled.js
  41. 21
    0
      src/components/Header/OpenDrawerButton/OpenDrawerButton.js
  42. 6
    0
      src/components/Header/OpenDrawerButton/OpenDrawerButton.styled.js
  43. 58
    0
      src/components/Header/SearchInput/SearchInput.js
  44. 73
    0
      src/components/Header/SearchInput/SearchInput.styled.js
  45. 29
    0
      src/components/Header/UserButton/UserButton.js
  46. 17
    0
      src/components/Header/UserButton/UserButton.styled.js
  47. 8
    2
      src/enums/reviewEnum.js
  48. 4
    0
      src/i18n/resources/rs.js
  49. 8
    0
      src/initialValues/createReviewInitialValues/firstPartCreateReviewInitialValues.js
  50. 6
    0
      src/validations/createReviewValidations/firstPartCreateReviewValidation.js
  51. 219
    23
      yarn.lock

+ 24700
- 41
package-lock.json
Datei-Diff unterdrückt, da er zu groß ist
Datei anzeigen


+ 36
- 0
src/components/Cards/OfferCard/CheckButton/CheckButton.js Datei anzeigen

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

+ 18
- 0
src/components/Cards/OfferCard/CheckButton/CheckButton.styled.js Datei anzeigen

@@ -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;
}
`;

+ 10
- 23
src/components/Cards/OfferCard/OfferCard.js Datei anzeigen

@@ -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>
) : (
<></>

+ 1
- 44
src/components/Cards/OfferCard/OfferCard.styled.js Datei anzeigen

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

+ 26
- 0
src/components/Cards/OfferCard/OfferDescription/OfferDescription.js Datei anzeigen

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

+ 33
- 0
src/components/Cards/OfferCard/OfferDescription/OfferDescription.styled.js Datei anzeigen

@@ -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;
`;

+ 35
- 0
src/components/Cards/UserReviewsCard/ReviewDetails/ReviewDetails.js Datei anzeigen

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

+ 17
- 0
src/components/Cards/UserReviewsCard/ReviewDetails/ReviewDetails.styled.js Datei anzeigen

@@ -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;
`;

+ 42
- 0
src/components/Cards/UserReviewsCard/ReviewQuote/ReviewQuote.js Datei anzeigen

@@ -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>&quot;{props.quote}&quot;</ReviewQuoteText>
</ReviewQuoteTextContainer>
</ReviewQuoteContainer>
);
};

ReviewQuote.propTypes = {
quote: PropTypes.string,
isSuccessfulSwap: PropTypes.string,
};

export default ReviewQuote;

+ 31
- 0
src/components/Cards/UserReviewsCard/ReviewQuote/ReviewQuote.styled.js Datei anzeigen

@@ -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;
`;

+ 31
- 0
src/components/Cards/UserReviewsCard/ReviewerProfile/ReviewerProfile.js Datei anzeigen

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

+ 25
- 0
src/components/Cards/UserReviewsCard/ReviewerProfile/ReviewerProfile.styled.js Datei anzeigen

@@ -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;
`

+ 21
- 76
src/components/Cards/UserReviewsCard/UserReviewsCard.js Datei anzeigen

@@ -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>&quot;{review?.quote}&quot;</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>
);
};

+ 41
- 96
src/components/Cards/UserReviewsCard/UserReviewsCard.styled.js Datei anzeigen

@@ -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;
`
`;

+ 31
- 0
src/components/CreateReview/FirstStep/CommentField/CommentField.js Datei anzeigen

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

+ 31
- 0
src/components/CreateReview/FirstStep/CommentField/CommentField.styled.js Datei anzeigen

@@ -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;
}
}
}
`;

+ 41
- 0
src/components/CreateReview/FirstStep/CorrectCommunicationField/CorrectCommunicationField.js Datei anzeigen

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

+ 23
- 93
src/components/CreateReview/FirstStep/FirstStepCreateReview.js Datei anzeigen

@@ -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>
);
};

+ 1
- 28
src/components/CreateReview/FirstStep/FirstStepCreateReview.styled.js Datei anzeigen

@@ -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;
}
}
}
`;


+ 27
- 0
src/components/CreateReview/FirstStep/NextButton/NextButton.js Datei anzeigen

@@ -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
src/components/CreateReview/FirstStep/NextButton/NextButton.styled.js Datei anzeigen


+ 43
- 0
src/components/CreateReview/FirstStep/SuccessfulSwapField/SuccessfulSwapField.js Datei anzeigen

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

+ 26
- 0
src/components/CreateReview/SecondStep/NextButton/NextButton.js Datei anzeigen

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

+ 0
- 0
src/components/CreateReview/SecondStep/NextButton/NextButton.styled.js Datei anzeigen


+ 3
- 13
src/components/CreateReview/SecondStep/SecondStepCreateReview.js Datei anzeigen

@@ -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>
);
};

+ 18
- 11
src/components/CreateReview/ThirdStep/ThirdStepCreateReview.js Datei anzeigen

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

+ 3
- 0
src/components/DirectChat/DirectChat.js Datei anzeigen

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

+ 0
- 1
src/components/DirectChat/DirectChatNewMessage/DirectChatNewMessage.js Datei anzeigen

@@ -74,7 +74,6 @@ const DirectChatNewMessage = (props) => {

const initiateNewChat = (typedValue) => {
const offerId = location.state.offerId;
console.log("here");
dispatch(
startNewChat({
offerId,

+ 3
- 1
src/components/Header/AboutHeader/AboutHeader.js Datei anzeigen

@@ -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")}

+ 27
- 0
src/components/Header/AddOfferButton/AddOfferButton.js Datei anzeigen

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

+ 8
- 0
src/components/Header/AddOfferButton/AddOfferButton.styled.js Datei anzeigen

@@ -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;
`;

+ 42
- 0
src/components/Header/DrawerContainer/DrawerContainer.js Datei anzeigen

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

+ 0
- 0
src/components/Header/DrawerContainer/DrawerContainer.styled.js Datei anzeigen


+ 52
- 155
src/components/Header/Header.js Datei anzeigen

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

+ 2
- 98
src/components/Header/Header.styled.js Datei anzeigen

@@ -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)``;

+ 28
- 0
src/components/Header/MyMessagesButton/MyMessagesButton.js Datei anzeigen

@@ -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
src/components/Header/MyMessagesButton/MyMessagesButton.styled.js Datei anzeigen


+ 25
- 0
src/components/Header/MySwapsButton/MySwapsButton.js Datei anzeigen

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

+ 3
- 0
src/components/Header/MySwapsButton/MySwapsButton.styled.js Datei anzeigen

@@ -0,0 +1,3 @@
import styled from "styled-components";
import { ReactComponent as Swaps } from "../../../assets/images/svg/swaps.svg";
export const SwapsIcon = styled(Swaps)``;

+ 21
- 0
src/components/Header/OpenDrawerButton/OpenDrawerButton.js Datei anzeigen

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

+ 6
- 0
src/components/Header/OpenDrawerButton/OpenDrawerButton.styled.js Datei anzeigen

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

export const ToggleDrawerButton = styled(Box)`
max-width: 40px;
`;

+ 58
- 0
src/components/Header/SearchInput/SearchInput.js Datei anzeigen

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

+ 73
- 0
src/components/Header/SearchInput/SearchInput.styled.js Datei anzeigen

@@ -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;
}
`;

+ 29
- 0
src/components/Header/UserButton/UserButton.js Datei anzeigen

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

+ 17
- 0
src/components/Header/UserButton/UserButton.styled.js Datei anzeigen

@@ -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;
`;

+ 8
- 2
src/enums/reviewEnum.js Datei anzeigen

@@ -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"
}
}

+ 4
- 0
src/i18n/resources/rs.js Datei anzeigen

@@ -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",

+ 8
- 0
src/initialValues/createReviewInitialValues/firstPartCreateReviewInitialValues.js Datei anzeigen

@@ -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 || "",
});

+ 6
- 0
src/validations/createReviewValidations/firstPartCreateReviewValidation.js Datei anzeigen

@@ -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")),
});

+ 219
- 23
yarn.lock Datei anzeigen

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

Laden…
Abbrechen
Speichern