| @@ -130,7 +130,9 @@ const Header = () => { | |||
| {!routeMatches(ABOUT_PAGE) && ( | |||
| <> | |||
| <AddOfferButton onClick={handleAddOfferClick} /> | |||
| <MySwapsButton /> | |||
| <MySwapsButton | |||
| handleAddOfferClick={handleAddOfferClick} | |||
| /> | |||
| <MyMessagesButton /> | |||
| </> | |||
| )} | |||
| @@ -9,7 +9,7 @@ import { useState } from "react"; | |||
| import { useEffect } from "react"; | |||
| import { useLocation } from "react-router-dom"; | |||
| const MySwapsButton = () => { | |||
| const MySwapsButton = (props) => { | |||
| const location = useLocation(); | |||
| const [postsPopoverOpen, setPostsPopoverOpen] = useState(false); | |||
| const [postsAnchorEl, setPostsAnchorEl] = useState(null); | |||
| @@ -26,6 +26,10 @@ const MySwapsButton = () => { | |||
| setPostsPopoverOpen(false); | |||
| setPostsAnchorEl(null); | |||
| }; | |||
| const closePopover = () => { | |||
| setPostsPopoverOpen(false); | |||
| props.handleAddOfferClick(); | |||
| }; | |||
| return ( | |||
| <> | |||
| <IconButton | |||
| @@ -44,7 +48,9 @@ const MySwapsButton = () => { | |||
| setPostsPopoverOpen(false); | |||
| setPostsAnchorEl(null); | |||
| }} | |||
| content={<MyPosts closePopover={closePostsPopover} />} | |||
| content={ | |||
| <MyPosts addOffer={closePopover} closePopover={closePostsPopover} /> | |||
| } | |||
| /> | |||
| </> | |||
| ); | |||
| @@ -52,6 +58,7 @@ const MySwapsButton = () => { | |||
| MySwapsButton.propTypes = { | |||
| onClick: PropTypes.func, | |||
| handleAddOfferClick: PropTypes.func, | |||
| }; | |||
| export default MySwapsButton; | |||
| @@ -11,18 +11,17 @@ import { | |||
| PopoverListItemAvatarContainer, | |||
| PopoverListItemProfileAvatar, | |||
| PopoverListItemTextContainer, | |||
| PopoverNoItemsText, | |||
| PopoverTitle, | |||
| SecondaryText, | |||
| SecondaryTextContainer, | |||
| } from "./HeaderPopover.styled"; | |||
| import { useTranslation } from "react-i18next"; | |||
| import useIsMobile from "../../../hooks/useIsMobile"; | |||
| import { getImageUrl, variants } from "../../../util/helpers/imageUrlGetter"; | |||
| import { useMemo } from "react"; | |||
| import MyMessagesNotFound from "../MyMessages/MyMessagesNotFound/MyMessagesNotFound"; | |||
| import MyPostsNotFound from "../MyPosts/MyPostsNotFound/MyPostsNotFound"; | |||
| const HeaderPopover = (props) => { | |||
| const { t } = useTranslation(); | |||
| const { isMobile } = useIsMobile(); | |||
| const items = useMemo(() => props.items, [props.items]); | |||
| return ( | |||
| @@ -72,7 +71,13 @@ const HeaderPopover = (props) => { | |||
| ); | |||
| }) | |||
| ) : ( | |||
| <PopoverNoItemsText>{t("header.noItems")}</PopoverNoItemsText> | |||
| <> | |||
| {props.noMessages ? ( | |||
| <MyMessagesNotFound /> | |||
| ) : ( | |||
| <MyPostsNotFound addOffer={props.addOffer} /> | |||
| )} | |||
| </> | |||
| )} | |||
| </PopoverList> | |||
| <PopoverButtonsContainer hideButtons={props.hideButtons}> | |||
| @@ -84,6 +89,7 @@ const HeaderPopover = (props) => { | |||
| variant="text" | |||
| endIcon={props.buttonIcon} | |||
| onClick={props.buttonOnClick} | |||
| disabled={props.noMessages || props.noPosts} | |||
| > | |||
| {props.buttonText} | |||
| </PopoverButton> | |||
| @@ -119,6 +125,9 @@ HeaderPopover.propTypes = { | |||
| secondButtonOnClick: PropTypes.func, | |||
| hideButtons: PropTypes.bool, | |||
| bigText: PropTypes.string, | |||
| noMessages: PropTypes.bool, | |||
| noPosts: PropTypes.bool, | |||
| addOffer: PropTypes.func, | |||
| }; | |||
| export default HeaderPopover; | |||
| @@ -23,7 +23,7 @@ export const PopoverTitle = styled(Typography)` | |||
| `; | |||
| export const PopoverList = styled(List)` | |||
| width: 100%; | |||
| max-width: 360px; | |||
| max-width: 270px; | |||
| background-color: "white"; | |||
| `; | |||
| export const PopoverListItem = styled(ListItem)` | |||
| @@ -78,12 +78,27 @@ export const PopoverButtonsContainer = styled(Box)` | |||
| align-items: flex-end; | |||
| `; | |||
| export const PopoverNoItemsText = styled(Typography)` | |||
| text-align: center; | |||
| /* text-align: center; */ | |||
| width: 100%; | |||
| font-weight: 600; | |||
| font-weight: 700; | |||
| padding-top: 5px; | |||
| font-size: 13px; | |||
| padding-left: 18px; | |||
| font-size: 16px; | |||
| font-family: ${selectedTheme.fonts.textFont}; | |||
| color: ${selectedTheme.colors.primaryPurple}; | |||
| `; | |||
| export const PopoverAddItemText = styled(Typography)` | |||
| font-family: ${selectedTheme.fonts.textFont}; | |||
| font-size: 12px; | |||
| padding-left: 18px; | |||
| padding-bottom: 91px; | |||
| `; | |||
| export const PopoverAddItemButton = styled(Typography)` | |||
| font-family: ${selectedTheme.fonts.textFont}; | |||
| font-size: 12px; | |||
| color: ${selectedTheme.colors.primaryPurple}; | |||
| text-decoration: underline; | |||
| cursor: pointer; | |||
| `; | |||
| export const NameOfProduct = styled(Typography)` | |||
| font-size: 12px; | |||
| @@ -8,6 +8,7 @@ import { selectUserId } from "../../../store/selectors/loginSelectors"; | |||
| import HeaderPopover from "../HeaderPopover/HeaderPopover"; | |||
| import PropTypes from "prop-types"; | |||
| import { makeErrorToastMessage } from "../../../store/utils/makeToastMessage"; | |||
| import { EyeIcon } from "./MyMessages.styled"; | |||
| export const MyMessages = (props) => { | |||
| const { t } = useTranslation(); | |||
| @@ -58,6 +59,8 @@ export const MyMessages = (props) => { | |||
| items={lastChats} | |||
| buttonOnClick={goToMessages} | |||
| buttonText={t("header.checkEverything")} | |||
| buttonIcon={<EyeIcon color={chats?.length === 0} />} | |||
| noMessages={chats?.length === 0} | |||
| /> | |||
| ); | |||
| }; | |||
| @@ -1,18 +1,29 @@ | |||
| import { TextField } from "@mui/material"; | |||
| import styled from "styled-components"; | |||
| import { ReactComponent as Eye } from "../../../assets/images/svg/eye-striked.svg"; | |||
| import selectedTheme from "../../../themes"; | |||
| export const SearchInput = styled(TextField)` | |||
| margin-left: 3.8rem; | |||
| background-color: #F4F4F4; | |||
| width: 45%; | |||
| max-width: 100%; | |||
| @media (max-width: 1100px) { | |||
| width: 36%; | |||
| } | |||
| @media (max-width: 900px) { | |||
| width: 54%; | |||
| } | |||
| @media (max-width: 600px) { | |||
| width: 36%; | |||
| } | |||
| ` | |||
| margin-left: 3.8rem; | |||
| background-color: #f4f4f4; | |||
| width: 45%; | |||
| max-width: 100%; | |||
| @media (max-width: 1100px) { | |||
| width: 36%; | |||
| } | |||
| @media (max-width: 900px) { | |||
| width: 54%; | |||
| } | |||
| @media (max-width: 600px) { | |||
| width: 36%; | |||
| } | |||
| `; | |||
| export const EyeIcon = styled(Eye)` | |||
| & path { | |||
| stroke: ${(props) => | |||
| props.color | |||
| ? selectedTheme.colors.iconStrokeDisabledColor | |||
| : selectedTheme.colors.iconYellowColor}; | |||
| } | |||
| `; | |||
| @@ -0,0 +1,33 @@ | |||
| import React from "react"; | |||
| import { | |||
| MessagesNotFoundContainer, | |||
| MessagesNotFoundText, | |||
| MessagesNotFoundTextSecond, | |||
| MessagesNotFoundSkeleton, | |||
| SkeletonImage, | |||
| SkeletonLinesContainer, | |||
| SkeletonFirstLine, | |||
| SkeletonSecondLine, | |||
| } from "./MyMessagesNotFound.styled"; | |||
| import { useTranslation } from "react-i18next"; | |||
| const MyMessagesNotFound = () => { | |||
| const { t } = useTranslation(); | |||
| return ( | |||
| <MessagesNotFoundContainer> | |||
| <MessagesNotFoundText> {t("messages.noMessages")}</MessagesNotFoundText> | |||
| <MessagesNotFoundTextSecond> | |||
| {t("messages.noMessagesSecond")} | |||
| </MessagesNotFoundTextSecond> | |||
| <MessagesNotFoundSkeleton> | |||
| <SkeletonImage /> | |||
| <SkeletonLinesContainer> | |||
| <SkeletonFirstLine /> | |||
| <SkeletonSecondLine /> | |||
| </SkeletonLinesContainer> | |||
| </MessagesNotFoundSkeleton> | |||
| </MessagesNotFoundContainer> | |||
| ); | |||
| }; | |||
| export default MyMessagesNotFound; | |||
| @@ -0,0 +1,53 @@ | |||
| import styled from "styled-components"; | |||
| import { Box, Typography } from "@mui/material"; | |||
| import selectedTheme from "../../../../themes"; | |||
| export const MessagesNotFoundContainer = styled(Box)``; | |||
| export const MessagesNotFoundText = styled(Typography)` | |||
| width: 100%; | |||
| font-weight: 700; | |||
| padding-top: 5px; | |||
| padding-left: 18px; | |||
| font-size: 16px; | |||
| font-family: ${selectedTheme.fonts.textFont}; | |||
| color: ${selectedTheme.colors.primaryPurple}; | |||
| `; | |||
| export const MessagesNotFoundTextSecond = styled(Typography)` | |||
| font-family: ${selectedTheme.fonts.textFont}; | |||
| font-size: 12px; | |||
| padding-left: 18px; | |||
| `; | |||
| export const MessagesNotFoundSkeleton = styled(Box)` | |||
| margin: 18px 0 0 18px; | |||
| display: flex; | |||
| `; | |||
| export const SkeletonImage = styled(Box)` | |||
| width: 54px; | |||
| height: 54px; | |||
| border-radius: 100%; | |||
| background-color: ${selectedTheme.colors.skeletonItemColor}; | |||
| `; | |||
| export const SkeletonLinesContainer = styled(Box)` | |||
| display: flex; | |||
| flex-direction: column; | |||
| margin-left: 9px; | |||
| `; | |||
| export const SkeletonFirstLine = styled(Box)` | |||
| width: 109px; | |||
| height: 18px; | |||
| border-radius: 2px; | |||
| margin-bottom: 6px; | |||
| background-color: ${selectedTheme.colors.skeletonItemColor}; | |||
| `; | |||
| export const SkeletonSecondLine = styled(Box)` | |||
| width: 62px; | |||
| height: 14px; | |||
| border-radius: 2px; | |||
| background-color: ${selectedTheme.colors.skeletonItemColor}; | |||
| `; | |||
| @@ -1,5 +1,5 @@ | |||
| import React, { useEffect, useState } from "react"; | |||
| import { PostsImgSuit } from "./MyPosts.styled"; | |||
| import { EyeIcon, PostsImgSuit } from "./MyPosts.styled"; | |||
| import PropTypes from "prop-types"; | |||
| // const dummyData2 = [ | |||
| @@ -87,10 +87,14 @@ export const MyPosts = (props) => { | |||
| items={mineOffersToRender} | |||
| buttonText={t("header.checkEverything")} | |||
| buttonOnClick={goToMySwaps} | |||
| buttonIcon={<EyeIcon color={mineOffers.length === 0} />} | |||
| noPosts={mineOffers.length === 0} | |||
| addOffer={props.addOffer} | |||
| /> | |||
| ); | |||
| }; | |||
| MyPosts.propTypes = { | |||
| closePopover: PropTypes.func, | |||
| addOffer: PropTypes.func, | |||
| }; | |||
| @@ -1,29 +1,40 @@ | |||
| import { TextField, Avatar } from "@mui/material"; | |||
| import Suit from '@mui/icons-material/WorkOutline'; | |||
| import Suit from "@mui/icons-material/WorkOutline"; | |||
| import styled from "styled-components"; | |||
| import { ReactComponent as Eye } from "../../../assets/images/svg/eye-striked.svg"; | |||
| import selectedTheme from "../../../themes"; | |||
| export const PostsImgSuit = styled(Suit)` | |||
| width: 1rem; | |||
| height: 1rem; | |||
| margin-right: .36rem; | |||
| ` | |||
| width: 1rem; | |||
| height: 1rem; | |||
| margin-right: 0.36rem; | |||
| `; | |||
| export const PostsAvatar = styled(Avatar)` | |||
| border-radius: 4px; | |||
| ` | |||
| border-radius: 4px; | |||
| `; | |||
| export const SearchInput = styled(TextField)` | |||
| margin-left: 3.8rem; | |||
| background-color: #F4F4F4; | |||
| width: 45%; | |||
| max-width: 100%; | |||
| @media (max-width: 1100px) { | |||
| width: 36%; | |||
| } | |||
| @media (max-width: 900px) { | |||
| width: 54%; | |||
| } | |||
| @media (max-width: 600px) { | |||
| width: 36%; | |||
| } | |||
| ` | |||
| margin-left: 3.8rem; | |||
| background-color: #f4f4f4; | |||
| width: 45%; | |||
| max-width: 100%; | |||
| @media (max-width: 1100px) { | |||
| width: 36%; | |||
| } | |||
| @media (max-width: 900px) { | |||
| width: 54%; | |||
| } | |||
| @media (max-width: 600px) { | |||
| width: 36%; | |||
| } | |||
| `; | |||
| export const EyeIcon = styled(Eye)` | |||
| & path { | |||
| stroke: ${(props) => | |||
| props.color | |||
| ? selectedTheme.colors.iconStrokeDisabledColor | |||
| : selectedTheme.colors.iconYellowColor}; | |||
| } | |||
| `; | |||
| @@ -0,0 +1,44 @@ | |||
| import React from "react"; | |||
| import PropTypes from "prop-types"; | |||
| import { | |||
| PostsNotFoundButton, | |||
| PostsNotFoundContainer, | |||
| PostsNotFoundText, | |||
| PostsNotFoundTextSecond, | |||
| PostsNotFoundSkeleton, | |||
| PostsNotFoundSkeletonImage, | |||
| } from "./MyPostsNotFound.styled"; | |||
| import { useTranslation } from "react-i18next"; | |||
| import { | |||
| SkeletonFirstLine, | |||
| SkeletonLinesContainer, | |||
| SkeletonSecondLine, | |||
| } from "../../MyMessages/MyMessagesNotFound/MyMessagesNotFound.styled"; | |||
| const MyPostsNotFound = (props) => { | |||
| const { t } = useTranslation(); | |||
| return ( | |||
| <PostsNotFoundContainer> | |||
| <PostsNotFoundText>{t("header.noItems")}</PostsNotFoundText> | |||
| <PostsNotFoundTextSecond> | |||
| <PostsNotFoundButton onClick={props.addOffer}> | |||
| {t("header.addItem")} | |||
| </PostsNotFoundButton> | |||
| {t("header.yourFirstOffer")} | |||
| </PostsNotFoundTextSecond> | |||
| <PostsNotFoundSkeleton> | |||
| <PostsNotFoundSkeletonImage /> | |||
| <SkeletonLinesContainer> | |||
| <SkeletonFirstLine /> | |||
| <SkeletonSecondLine /> | |||
| </SkeletonLinesContainer> | |||
| </PostsNotFoundSkeleton> | |||
| </PostsNotFoundContainer> | |||
| ); | |||
| }; | |||
| MyPostsNotFound.propTypes = { | |||
| addOffer: PropTypes.func, | |||
| }; | |||
| export default MyPostsNotFound; | |||
| @@ -0,0 +1,41 @@ | |||
| import styled from "styled-components"; | |||
| import { Box, Typography } from "@mui/material"; | |||
| import selectedTheme from "../../../../themes"; | |||
| export const PostsNotFoundContainer = styled(Box)``; | |||
| export const PostsNotFoundText = styled(Typography)` | |||
| width: 100%; | |||
| font-weight: 700; | |||
| padding-top: 5px; | |||
| padding-left: 18px; | |||
| font-size: 16px; | |||
| font-family: ${selectedTheme.fonts.textFont}; | |||
| color: ${selectedTheme.colors.primaryPurple}; | |||
| `; | |||
| export const PostsNotFoundTextSecond = styled(Typography)` | |||
| font-family: ${selectedTheme.fonts.textFont}; | |||
| font-size: 12px; | |||
| padding-left: 18px; | |||
| `; | |||
| export const PostsNotFoundButton = styled(Typography)` | |||
| font-family: ${selectedTheme.fonts.textFont}; | |||
| font-size: 12px; | |||
| color: ${selectedTheme.colors.primaryPurple}; | |||
| text-decoration: underline; | |||
| cursor: pointer; | |||
| `; | |||
| export const PostsNotFoundSkeleton = styled(Box)` | |||
| margin: 18px 0 0 18px; | |||
| display: flex; | |||
| `; | |||
| export const PostsNotFoundSkeletonImage = styled(Box)` | |||
| width: 54px; | |||
| height: 54px; | |||
| border-radius: 2px; | |||
| background-color: ${selectedTheme.colors.skeletonItemColor}; | |||
| `; | |||
| @@ -2,7 +2,6 @@ import { Box } from "@mui/material"; | |||
| import styled from "styled-components"; | |||
| import { ReactComponent as Logout } from "../../../../assets/images/svg/log-out.svg"; | |||
| export const MiddleButton = styled(Box)` | |||
| margin: 0 16px; | |||
| padding-top: 14px; | |||
| @@ -58,13 +58,12 @@ export const MyProfile = (props) => { | |||
| pathname: ABOUT_PAGE, | |||
| state: { | |||
| clicked: true, | |||
| navigation: scrollConstants.about.pricesPage | |||
| } | |||
| navigation: scrollConstants.about.pricesPage, | |||
| }, | |||
| }); | |||
| props.closePopover(); | |||
| }; | |||
| return ( | |||
| <HeaderPopover | |||
| title={t("header.myProfile")} | |||
| @@ -77,11 +76,11 @@ export const MyProfile = (props) => { | |||
| secondButtonText={t("header.prices")} | |||
| secondButtonOnClick={seePrices} | |||
| > | |||
| <LogoutButton /> | |||
| <GrayButtonsContainer> | |||
| <AboutButton closePopover={props.closePopover}/> | |||
| <AboutButton closePopover={props.closePopover} /> | |||
| <PrivacyPolicyButton closePopover={props.closePopover} /> | |||
| </GrayButtonsContainer> | |||
| <LogoutButton /> | |||
| </HeaderPopover> | |||
| ); | |||
| }; | |||
| @@ -10,7 +10,6 @@ export const ProfileImgPIB = styled(PIB)` | |||
| margin-right: 0.36rem; | |||
| `; | |||
| export const ProfileAvatar = styled(Avatar)` | |||
| width: 63px; | |||
| height: 63px; | |||
| @@ -37,14 +36,19 @@ export const GrayButton = styled(Box)` | |||
| & button { | |||
| margin-bottom: 5.5px; | |||
| margin-top: 5.5px; | |||
| color: ${selectedTheme.colors.primaryGrayText}; | |||
| margin-right: 0; | |||
| color: ${selectedTheme.colors.primaryPurple}; | |||
| } | |||
| `; | |||
| export const GrayButtonsContainer = styled(Box)` | |||
| margin: 16px 0; | |||
| margin-bottom: 16px; | |||
| margin-left: 16px; | |||
| margin-right: 16px; | |||
| padding-top: 16px; | |||
| border-top: 1px solid rgba(77, 77, 77, 0.12); | |||
| `; | |||
| export const DollarIcon = styled(Dollar)` | |||
| position: relative; | |||
| left: -4px; | |||
| margin-left: 10px; | |||
| ` | |||
| `; | |||
| @@ -198,11 +198,13 @@ export default { | |||
| oldOffers: "Najstarije ponude", | |||
| popularOffers: "Najpopularnije ponude", | |||
| navMenu: "Navigacioni Meni", | |||
| noItems: "Trenutno nema ni jedne stavke...", | |||
| noItems: "Objave nisu pronađene.", | |||
| logout: "Odjavite se", | |||
| about: "O trampi", | |||
| prices: "Cenovnik", | |||
| privacy: "Politika privatnosti", | |||
| addItem: "Dodajte", | |||
| yourFirstOffer: " svoju prvu objavu.", | |||
| }, | |||
| reviews: { | |||
| title: "Ova kompanija još uvek nema ocenu.", | |||
| @@ -229,6 +231,8 @@ export default { | |||
| noMessagesToast: "Nemate ni jednu poruku!", | |||
| notAllowedChat: "Trampa za ovaj proizvod je završena.", | |||
| goBack: "Nazad na sve poruke", | |||
| noMessages: "Poruke nisu pronađene.", | |||
| noMessagesSecond: "Nažalost, nemate ni jednu poruku.", | |||
| }, | |||
| editProfile: { | |||
| website: "Web Sajt*", | |||
| @@ -242,7 +246,6 @@ export default { | |||
| labelLocationRequired: "Lokacija je obavezna!", | |||
| labelPhoneValid: "Unesite validan broj telefona", | |||
| labelPhoneRequired: "Broj telefona je obavezan!", | |||
| labelLocationValid: "Unesite validnu lokaciju!", | |||
| }, | |||
| deleteOffer: { | |||
| areYouSure: "Da li ste sigurni da želite da <br /> obrišete proizvod?", | |||
| @@ -399,8 +402,4 @@ export default { | |||
| description: "Opis", | |||
| email: "Mejl kompanije", | |||
| }, | |||
| carousel: { | |||
| imagesReview: "Pregled fotografija", | |||
| offer: "Proizvod:", | |||
| }, | |||
| }; | |||