Ver código fonte

Merge branch 'feature/1608' of https://git.dilig.net/selenaaasi/trampa-frontend

feature/1726
djordjemitrovic00 3 anos atrás
pai
commit
0b8ca2c2b5
56 arquivos alterados com 1006 adições e 766 exclusões
  1. 17
    12
      public/index.html
  2. 9
    8
      src/App.js
  3. 13
    33
      src/AppRoutes.js
  4. 1
    0
      src/components/Buttons/IconButton/IconButton.js
  5. 1
    1
      src/components/Cards/FilterCard/FilterCard.js
  6. 13
    12
      src/components/Cards/FilterCard/FilterDropdown/Checkbox/FilterCheckboxDropdown.js
  7. 25
    21
      src/components/Cards/FilterCard/FilterDropdown/Checkbox/FilterSubDropdown/FilterSubDropdown.js
  8. 32
    29
      src/components/Cards/FilterCard/FilterDropdown/Radio/FilterRadioDropdown.js
  9. 0
    1
      src/components/Cards/ItemDetailsCard/ItemDetailsCard.js
  10. 1
    0
      src/components/Cards/ItemDetailsCard/OfferDetails/OfferDetails.js
  11. 2
    2
      src/components/Cards/MiniChatCard/MiniChatCard.js
  12. 2
    3
      src/components/Cards/OfferCard/OfferCard.js
  13. 7
    5
      src/components/Cards/OfferCard/SkeletonOfferCard/SkeletonOfferCard.js
  14. 1
    1
      src/components/Cards/OfferCard/SkeletonOfferCard/SkeletonOfferCard.styled.js
  15. 0
    3
      src/components/Cards/RequestExchangeCard/RequestExchangeCard.js
  16. 9
    4
      src/components/Dropdown/DropdownList/DropdownList.js
  17. 2
    2
      src/components/Header/Drawer/Buttons/MyMessagesButton/MyMessagesButton.js
  18. 3
    0
      src/components/Header/MyMessagesButton/MyMessagesButton.js
  19. 3
    0
      src/components/Header/MySwapsButton/MySwapsButton.js
  20. 0
    2
      src/components/Header/SearchInput/SearchInput.js
  21. 3
    0
      src/components/Header/UserButton/UserButton.js
  22. 54
    0
      src/components/MarketPlace/Header/GridButtons/GridButtons.js
  23. 20
    0
      src/components/MarketPlace/Header/GridButtons/GridButtons.styled.js
  24. 24
    160
      src/components/MarketPlace/Header/Header.js
  25. 3
    193
      src/components/MarketPlace/Header/Header.styled.js
  26. 51
    0
      src/components/MarketPlace/Header/HeaderSelect/HeaderSelect.js
  27. 38
    0
      src/components/MarketPlace/Header/HeaderSelect/HeaderSelect.styled.js
  28. 113
    0
      src/components/MarketPlace/Header/TooltipHeader/TooltipHeader.js
  29. 153
    0
      src/components/MarketPlace/Header/TooltipHeader/TooltipHeader.styled.js
  30. 43
    92
      src/components/MarketPlace/Offers/Offers.js
  31. 0
    39
      src/components/MarketPlace/Offers/Offers.styled.js
  32. 43
    0
      src/components/MarketPlace/Offers/OffersFilterButton/OffersFilterButton.js
  33. 28
    0
      src/components/MarketPlace/Offers/OffersFilterButton/OffersFilterButton.styled.js
  34. 73
    0
      src/components/MarketPlace/Offers/OffersList/OffersList.js
  35. 12
    0
      src/components/MarketPlace/Offers/OffersList/OffersList.styled.js
  36. 0
    55
      src/components/MarketPlace/Offers/OffersNotFound.js
  37. 67
    0
      src/components/MarketPlace/Offers/OffersNotFound/OffersNotFound.js
  38. 3
    3
      src/components/MarketPlace/Offers/OffersNotFound/OffersNotFound.styled.js
  39. 50
    0
      src/components/MarketPlace/Offers/OffersSearchField/OffersSearchField.js
  40. 0
    0
      src/components/MarketPlace/Offers/OffersSearchField/OffersSearchField.styled.js
  41. 0
    1
      src/components/Modals/Modal.js
  42. 5
    0
      src/components/Paging/Paging.js
  43. 6
    6
      src/constants/pages.js
  44. 12
    2
      src/i18n/resources/rs.js
  45. 3
    0
      src/index.css
  46. 1
    1
      src/index.js
  47. 10
    8
      src/pages/DirectChatPage/DirectChatPage.js
  48. 1
    1
      src/pages/DirectChatPage/DirectChatPage.styled.js
  49. 37
    9
      src/pages/HomePage/HomePage.js
  50. 0
    43
      src/pages/HomePage/HomePageMUI.js
  51. 8
    8
      src/pages/MessagesListPage/MessagesListPage.js
  52. 1
    1
      src/pages/MessagesListPage/MessagesListPage.styled.js
  53. 0
    1
      src/store/saga/categoriesSaga.js
  54. BIN
      src/themes/primaryTheme/fonts/OpenSans-Regular.ttf
  55. 3
    3
      src/util/helpers/messageHelper.js
  56. 0
    1
      src/util/helpers/reviewsHelper.js

+ 17
- 12
public/index.html Ver arquivo

@@ -3,25 +3,30 @@
<head>
<meta charset="utf-8" />
<link rel="icon" href="%PUBLIC_URL%/favicon.png" />
<link
<!-- <link
rel="stylesheet"
type="text/css"
href="https://fonts.googleapis.com/css?family=Open+Sans:wght@700;600;500;400;300"
/>
href="https://fonts.googleapis.com/css?family=Open+Sans:wght@700;600;500;400;300&display=swap"
/> -->
<link
rel="stylesheet"
type="text/css"
href="https://fonts.googleapis.com/css?family=Poppins"
rel="preload"
as="style"
href="https://fonts.googleapis.com/css?family=Poppins&display=swap"
onload="this.onload=null;this.rel='stylesheet';this.type='text/css'"
/>
<link
rel="stylesheet"
type="text/css"
href="https://fonts.googleapis.com/css?family=Mulish"
style
rel="preload"
as="style"
href="https://fonts.googleapis.com/css?family=Mulish&display=swap"
onload="this.onload=null;this.rel='stylesheet';this.type='text/css'"
/>
<link
rel="stylesheet"
type="text/css"
href="https://fonts.googleapis.com/css?family=DM+Sans:300,400,500,600,700,800"
style
rel="preload"
as="style"
href="https://fonts.googleapis.com/css?family=DM+Sans:300,400,500,600,700,800&display=swap"
onload="this.onload=null;this.rel='stylesheet';this.type='text/css'"
/>
<meta name="viewport" content="width=device-width, initial-scale=1" />
<meta name="theme-color" content="#000000" />

+ 9
- 8
src/App.js Ver arquivo

@@ -1,19 +1,20 @@
/*eslint-disable*/
import React, { useState, useEffect } from "react";
import React, { useEffect } from "react";
import { Router } from "react-router-dom";
import { Helmet } from "react-helmet-async";
import { ToastContainer } from "react-toastify";
import { StyledEngineProvider } from "@mui/material";
import { useSelector } from "react-redux";
import i18next from "i18next";

import { selectUserId } from "./store/selectors/loginSelectors";
import history from "./store/utils/history";
import AppRoutes from "./AppRoutes";
import { socketInit } from "./socket/socket";

import Header from "./components/Header/Header";
import { StyledEngineProvider } from "@mui/material";
import GlobalStyle from "./components/Styles/globalStyles";
import { ToastContainer } from "react-toastify";
import "react-toastify/dist/ReactToastify.css";
import { socketInit } from "./socket/socket";
import { useSelector } from "react-redux";
import { selectUserId } from "./store/selectors/loginSelectors";
import Modal from "./components/Modals/Modal";
import "react-toastify/dist/ReactToastify.css";

const App = () => {
const userId = useSelector(selectUserId);

+ 13
- 33
src/AppRoutes.js Ver arquivo

@@ -1,7 +1,5 @@
/* eslint-disable */
import React from "react";
import { Redirect, Route, Switch, useLocation } from "react-router-dom";

import { Redirect, Route, Switch } from "react-router-dom";
import {
LOGIN_PAGE,
ADMIN_LOGIN_PAGE,
@@ -17,21 +15,15 @@ import {
ITEM_DETAILS_PAGE,
FORGOT_PASSWORD_PAGE,
PROFILE_PAGE,
CHAT_MESSAGE_PAGE,
CHAT_PAGE,
MY_OFFERS_PAGE,
// PRICES_PAGE,
ABOUT_PAGE,
ADMIN_HOME_PAGE,
ADMIN_USERS_PAGE,
ADMIN_CATEGORIES_PAGE,
ADMIN_SUBCATEGORIES_PAGE,
// POLICY_PRIVACY_PAGE,
MESSAGES_LIST_PAGE,
DIRECT_CHAT_PAGE,
} from "./constants/pages";
// import SlideRoutes from "react-slide-routes";
import LoginPage from "./pages/LoginPage/LoginPage";
import AdminLoginPage from "./pages/AdminLoginPage/AdminLoginPage";
import HomePage from "./pages/HomePage/HomePageMUI";
import HomePage from "./pages/HomePage/HomePage";
import NotFoundPage from "./pages/ErrorPages/NotFoundPage";
import ErrorPage from "./pages/ErrorPages/ErrorPage";
import ForgotPasswordPage from "./pages/ForgotPasswordPage/ForgotPasswordPage";
@@ -43,48 +35,36 @@ import ResetPasswordPage from "./pages/ResetPasswordPage/ResetPasswordPage";
import CreateOffer from "./pages/CreateOffer/CreateOffer";
import ItemDetailsPage from "./pages/ItemDetailsPage/ItemDetailsPageMUI";
import ProfilePage from "./pages/ProfilePage/ProfilePage";
import ChatMessagesPage from "./pages/ChatMessages/ChatMessages";
import ChatPage from "./pages/Chat/Chat";
import DirectChatPage from "./pages/DirectChatPage/DirectChatPage";
import MessagesListPage from "./pages/MessagesListPage/MessagesListPage";
import MyOffers from "./pages/MyOffers/MyOffers";
// import PricesPage from "./pages/Prices/PricesPage";
import AboutPage from "./pages/About/AboutPage";
import AuthRoute from "./components/Router/AuthRoute";
import AdminRoute from "./components/Router/AdminRoute";
import AdminHomePage from "./pages/AdminHomePage/AdminHomePage";
// import PrivacyPolicyPage from "./pages/PrivacyPolicy/PrivacyPolicyPage";

const AppRoutes = () => {
// const location = useLocation();
return (
<Switch>
<Route exact path={BASE_PAGE} component={HomePage} />
<AuthRoute exact path={LOGIN_PAGE} component={LoginPage} />
<AuthRoute exact path={ADMIN_LOGIN_PAGE} component={AdminLoginPage} />
<AdminRoute path={ADMIN_HOME_PAGE} component={AdminHomePage} />
<Route path={NOT_FOUND_PAGE} component={NotFoundPage} />
<Route path={ERROR_PAGE} component={ErrorPage} />
<Route path={REGISTER_SUCCESSFUL_PAGE} component={RegisterSuccessful} />
<AuthRoute path={REGISTER_PAGE} component={Register} />
<AuthRoute path={FORGOT_PASSWORD_MAIL_SENT} component={MailSent} />
<AuthRoute path={FORGOT_PASSWORD_PAGE} component={ForgotPasswordPage} />
<AuthRoute path={RESET_PASSWORD_PAGE} component={ResetPasswordPage} />
<Route path={REGISTER_SUCCESSFUL_PAGE} component={RegisterSuccessful} />
<Route path={CREATE_OFFER_PAGE} component={CreateOffer} />
<Route path={ITEM_DETAILS_PAGE} component={ItemDetailsPage} />
<Route path={PROFILE_PAGE} component={ProfilePage} />
{/* <Route path={PRICES_PAGE} component={PricesPage} /> */}
<Route path={ABOUT_PAGE} component={AboutPage} />
{/* <Route path={POLICY_PRIVACY_PAGE} component={PrivacyPolicyPage} /> */}
<Route
path={HOME_PAGE}
component={(props) => {
return <HomePage key={props.match.params.id} />;
}}
/>
{/* <SlideRoutes location={location}> */}
<PrivateRoute exact path={CHAT_PAGE} component={ChatPage} />
<PrivateRoute path={CHAT_MESSAGE_PAGE} component={ChatMessagesPage} />
{/* </SlideRoutes> */}
<Route path={HOME_PAGE} component={HomePage} />
<PrivateRoute exact path={MESSAGES_LIST_PAGE} component={MessagesListPage} />
<PrivateRoute path={DIRECT_CHAT_PAGE} component={DirectChatPage} />
<PrivateRoute path={MY_OFFERS_PAGE} component={MyOffers} />
<AdminRoute path={ADMIN_HOME_PAGE} component={AdminHomePage} />
<Route path={ERROR_PAGE} component={ErrorPage} />
<Route path={NOT_FOUND_PAGE} component={NotFoundPage} />
<Redirect from="*" to={NOT_FOUND_PAGE} />
</Switch>
);

+ 1
- 0
src/components/Buttons/IconButton/IconButton.js Ver arquivo

@@ -18,6 +18,7 @@ export const IconButton = (props) => {
onClick={props.onClick}
sx={props.style}
iconcolor={props.iconColor}
{...props}
>
{props.children}
</IconButtonStyled>

+ 1
- 1
src/components/Cards/FilterCard/FilterCard.js Ver arquivo

@@ -29,7 +29,7 @@ const FilterCard = (props) => {
myOffers={props.myOffers}
skeleton={props.skeleton}
>
<SkeletonFilterCard skeleton={props.skeleton} />
{props?.skeleton && <SkeletonFilterCard skeleton={props.skeleton} />}
{/* Header title for my offers */}
{props.myOffers && <HeaderBack />}


+ 13
- 12
src/components/Cards/FilterCard/FilterDropdown/Checkbox/FilterCheckboxDropdown.js Ver arquivo

@@ -73,18 +73,19 @@ const FilterCheckboxDropdown = (props) => {
setItemsSelected={props.setItemsSelected}
companies={props.companies}
>
{dataToShow.map((item) => {
return (
<DropdownItem key={item.city}>
<Checkbox
item={item}
filters={props.filters}
onChange={() => handleChange(item)}
companies={props.companies}
/>
</DropdownItem>
);
})}
{(isOpened || props?.open) &&
dataToShow.map((item) => {
return (
<DropdownItem key={item.city}>
<Checkbox
item={item}
filters={props.filters}
onChange={() => handleChange(item)}
companies={props.companies}
/>
</DropdownItem>
);
})}
</CheckboxDropdownList>
);
};

+ 25
- 21
src/components/Cards/FilterCard/FilterDropdown/Checkbox/FilterSubDropdown/FilterSubDropdown.js Ver arquivo

@@ -54,27 +54,31 @@ const FilterSubDropdown = (props) => {
setItemsSelected={props.setItemsSelected}
companies={props.companies}
>
<FilterSmallDropdown
letters={t("filters.company.firstSort")}
dataToShow={dataToShow}
filters={props.filters}
setItemsSelected={props.setItemsSelected}
companies={props.companies}
/>
<FilterSmallDropdown
letters={t("filters.company.secondSort")}
dataToShow={dataToShow}
filters={props.filters}
setItemsSelected={props.setItemsSelected}
companies={props.companies}
/>
<FilterSmallDropdown
letters={t("filters.company.thirdSort")}
dataToShow={dataToShow}
filters={props.filters}
setItemsSelected={props.setItemsSelected}
companies={props.companies}
/>
{(isOpened || props?.open) && (
<>
<FilterSmallDropdown
letters={t("filters.company.firstSort")}
dataToShow={dataToShow}
filters={props.filters}
setItemsSelected={props.setItemsSelected}
companies={props.companies}
/>
<FilterSmallDropdown
letters={t("filters.company.secondSort")}
dataToShow={dataToShow}
filters={props.filters}
setItemsSelected={props.setItemsSelected}
companies={props.companies}
/>
<FilterSmallDropdown
letters={t("filters.company.thirdSort")}
dataToShow={dataToShow}
filters={props.filters}
setItemsSelected={props.setItemsSelected}
companies={props.companies}
/>
</>
)}
</CheckboxDropdownList>
);
};

+ 32
- 29
src/components/Cards/FilterCard/FilterDropdown/Radio/FilterRadioDropdown.js Ver arquivo

@@ -37,7 +37,8 @@ const FilterRadioDropdown = (props) => {
if (
props.selected?._id !== 0 &&
props.selected !== null &&
props.selected !== undefined
props.selected !== undefined &&
Object.keys(props.selected).length !== 0
) {
setIsOpened(true);
}
@@ -101,39 +102,41 @@ const FilterRadioDropdown = (props) => {
</React.Fragment>
}
>
<RadioGroup>
{props.firstOption && (
<DropdownItem>
<RadioButton
value={props.firstOption.value}
label={props.firstOption.label}
// number={item.numberOfProducts}
fullWidth
checked={!props.selected || props.selected._id === 0}
onChange={props.setSelected}
/>
</DropdownItem>
)}
{dataToShow.map((item) => {
return (
<DropdownItem
key={item.name}
onClick={() => props.setSelected(item)}
>
{(isOpened || props?.open) && (
<RadioGroup>
{props.firstOption && (
<DropdownItem>
<RadioButton
value={item}
label={item?.name ? item?.name : item?.length > 0 ? item : ""}
number={item.offerCount}
value={props.firstOption.value}
label={props.firstOption.label}
// number={item.numberOfProducts}
fullWidth
checked={
JSON.stringify(props.selected) === JSON.stringify(item)
}
checked={!props.selected || props.selected._id === 0}
onChange={props.setSelected}
/>
</DropdownItem>
);
})}
</RadioGroup>
)}
{dataToShow.map((item) => {
return (
<DropdownItem
key={item.name}
onClick={() => props.setSelected(item)}
>
<RadioButton
value={item}
label={item?.name ? item?.name : item?.length > 0 ? item : ""}
number={item.offerCount}
fullWidth
checked={
JSON.stringify(props.selected) === JSON.stringify(item)
}
onChange={props.setSelected}
/>
</DropdownItem>
);
})}
</RadioGroup>
)}
</DropdownList>
);
};

+ 0
- 1
src/components/Cards/ItemDetailsCard/ItemDetailsCard.js Ver arquivo

@@ -97,7 +97,6 @@ const ItemDetailsCard = (props) => {
);
};
const showPinOfferModalHandler = () => {
console.log(offer);
dispatch(
toggleDeleteOfferModal({
offer: offer?.offer,

+ 1
- 0
src/components/Cards/ItemDetailsCard/OfferDetails/OfferDetails.js Ver arquivo

@@ -71,6 +71,7 @@ const OfferDetails = (props) => {
? images[index]
: getImageUrl(item, variants.offerCard, isMobile)
}
alt={t("offer.imageAlt")}
key={item}
previewCard={props.previewCard}
onClick={() =>

+ 2
- 2
src/components/Cards/MiniChatCard/MiniChatCard.js Ver arquivo

@@ -14,7 +14,7 @@ import useIsMobile from "../../../hooks/useIsMobile";
import { getImageUrl, variants } from "../../../util/helpers/imageUrlGetter";
import history from "../../../store/utils/history";
import { replaceInRoute } from "../../../util/helpers/routeHelpers";
import { CHAT_MESSAGE_PAGE } from "../../../constants/pages";
import { DIRECT_CHAT_PAGE } from "../../../constants/pages";
import BlockedProfile from "../ProfileCard/BlockedProfile/BlockedProfile";

const MiniChatCard = (props) => {
@@ -22,7 +22,7 @@ const MiniChatCard = (props) => {
const { isMobile } = useIsMobile();
const changeChat = () => {
history.push(
replaceInRoute(CHAT_MESSAGE_PAGE, {
replaceInRoute(DIRECT_CHAT_PAGE, {
idChat: props?.chat?.chat?._id,
})
);

+ 2
- 3
src/components/Cards/OfferCard/OfferCard.js Ver arquivo

@@ -128,7 +128,6 @@ const OfferCard = (props) => {

const acceptExchange = (event) => {
event.stopPropagation();
console.log("props exchange");
props.acceptExchange();
};

@@ -139,8 +138,6 @@ const OfferCard = (props) => {
return true;
}, [userId, props.offer]);

console.log("props", props);

return (
<React.Fragment>
<OfferCardContainer
@@ -185,6 +182,7 @@ const OfferCard = (props) => {
)
: ""
}
alt={t("offer.imageAlt")}
vertical={props.vertical}
></OfferImage>
</OfferImageContainer>
@@ -303,6 +301,7 @@ const OfferCard = (props) => {
<Tooltip title={t("messages.tooltip")}>
<TooltipInnerContainer>
<MessageIcon
aria-label={t("labels.messageUser")}
showMessageIcon={showMessageIcon}
vertical={props.vertical}
onClick={messageUser}

+ 7
- 5
src/components/Cards/OfferCard/SkeletonOfferCard/SkeletonOfferCard.js Ver arquivo

@@ -27,11 +27,8 @@ import useIsMobile from "../../../../hooks/useIsMobile";
const SkeletonOfferCard = (props) => {
const { isMobile } = useIsMobile();
return (
<SkeletonOfferCardsContainer>
<SkeletonOfferCardContainer
vertical={props.vertical}
skeleton={props.skeleton}
>
<SkeletonOfferCardsContainer skeleton={props.skeleton}>
<SkeletonOfferCardContainer vertical={props.vertical}>
<SkeletonTitleAboveImage vertical={props.vertical} />
<LeftPart vertical={props.vertical}>
<SkeletonImage vertical={props.vertical} />
@@ -73,5 +70,10 @@ SkeletonOfferCard.propTypes = {
vertical: PropTypes.bool,
aboveChat: PropTypes.bool,
};
SkeletonOfferCard.defaultProps = {
skeleton: false,
vertical: false,
aboveChat: false,
};

export default SkeletonOfferCard;

+ 1
- 1
src/components/Cards/OfferCard/SkeletonOfferCard/SkeletonOfferCard.styled.js Ver arquivo

@@ -7,7 +7,7 @@ import {
} from "../../../Styles/globalStyleComponents";

export const SkeletonOfferCardsContainer = styled(Box)`
display: flex;
display: ${props => props.skeleton ? "flex" : "none"};
`;

export const SkeletonOfferCardContainer = styled(BackgroundTransition)`

+ 0
- 3
src/components/Cards/RequestExchangeCard/RequestExchangeCard.js Ver arquivo

@@ -29,13 +29,10 @@ const RequestExchangeCard = (props) => {
() => exchange?.buyer?.userId === userId,
[exchange, userId]
);
console.log("requester", requester);
console.log("exchange: ", exchange);
const haveIAccepted = useMemo(
() => (amIBuyer ? exchange?.buyer?.accepted : exchange?.seller?.accepted),
[amIBuyer, exchange]
);
console.log(haveIAccepted)
const interlucatorUserId = useMemo(
() => (amIBuyer ? exchange?.seller?.userId : exchange?.buyer?.userId),
[exchange, amIBuyer]

+ 9
- 4
src/components/Dropdown/DropdownList/DropdownList.js Ver arquivo

@@ -11,26 +11,29 @@ import {
ToggleContainer,
} from "./DropdownList.styled";
import PropTypes from "prop-types";
import { useTranslation } from "react-i18next";

const DropdownList = (props) => {
const [listShown, setListShown] = useState(props.defaultOpen);
const { t } = useTranslation();
useEffect(() => {
if (props.open !== null || props.open !== undefined)
setListShown(props.open);
}, [props.open]);

const handleShow = () => {
if (props.setIsOpened)
props.setIsOpened(!listShown);
if (!props.disabled)
setListShown((prevState) => !prevState);
if (props.setIsOpened) props.setIsOpened(!listShown);
if (!props.disabled) setListShown((prevState) => !prevState);
if (!(props.open !== null || props.open !== undefined))
setListShown((prevState) => !prevState);
};

return (
<DropdownListContainer fullwidth={props.fullWidth ? 1 : 0}>
<DropdownHeader>
{props.dropdownIcon && (
<DropdownIcon
aria-label={t("labels.dropdownIcon")}
onClick={!props.disabled ? () => handleShow() : () => {}}
disabled={props.disabled}
>
@@ -50,6 +53,7 @@ const DropdownList = (props) => {
: listShown
) ? (
<ToggleIconOpened
aria-label={t("labels.dropdownClose")}
style={props.toggleIconStyles}
onClick={!props.disabled ? () => handleShow() : () => {}}
>
@@ -57,6 +61,7 @@ const DropdownList = (props) => {
</ToggleIconOpened>
) : (
<ToggleIconClosed
aria-label={t("labels.dropdownOpen")}
style={props.toggleIconStyles}
onClick={!props.disabled ? () => handleShow() : () => {}}
disabled={props.disabled}

+ 2
- 2
src/components/Header/Drawer/Buttons/MyMessagesButton/MyMessagesButton.js Ver arquivo

@@ -5,13 +5,13 @@ import { IconButton } from "../../../../Buttons/IconButton/IconButton";
import { useTranslation } from "react-i18next";
import { MailIcon } from "./MyMessagesButton.styled";
import history from "../../../../../store/utils/history";
import { CHAT_PAGE } from "../../../../../constants/pages";
import { MESSAGES_LIST_PAGE } from "../../../../../constants/pages";

const MyMessagesButton = (props) => {
const { t } = useTranslation();
const handleClick = () => {
props.toggleDrawer();
history.push(CHAT_PAGE);
history.push(MESSAGES_LIST_PAGE);
};
return (
<DrawerButton onClick={handleClick}>

+ 3
- 0
src/components/Header/MyMessagesButton/MyMessagesButton.js Ver arquivo

@@ -9,9 +9,11 @@ import PopoverComponent from "../../Popovers/PopoverComponent";
import { MyMessages } from "../../Popovers/MyMessages/MyMessages";
import { useLocation } from "react-router-dom";
import { useEffect } from "react";
import { useTranslation } from "react-i18next";

const MyMessagesButton = () => {
const location = useLocation();
const { t } = useTranslation();
const [msgPopoverOpen, setMsgPopoverOpen] = useState(false);
const [msgAnchorEl, setMsgAnchorEl] = useState(null);
useEffect(() => {
@@ -29,6 +31,7 @@ const MyMessagesButton = () => {
return (
<>
<IconButton
aria-label={t("header.myMessages")}
onClick={openMsgPopover}
style={{
background: selectedTheme.colors.primaryIconBackgroundColor,

+ 3
- 0
src/components/Header/MySwapsButton/MySwapsButton.js Ver arquivo

@@ -8,8 +8,10 @@ import { MyPosts } from "../../Popovers/MyPosts/MyPosts";
import { useState } from "react";
import { useEffect } from "react";
import { useLocation } from "react-router-dom";
import { useTranslation } from "react-i18next";

const MySwapsButton = (props) => {
const {t} = useTranslation();
const location = useLocation();
const [postsPopoverOpen, setPostsPopoverOpen] = useState(false);
const [postsAnchorEl, setPostsAnchorEl] = useState(null);
@@ -33,6 +35,7 @@ const MySwapsButton = (props) => {
return (
<>
<IconButton
aria-label={t("header.myOffers")}
onClick={openPostsPopover}
style={{
background: selectedTheme.colors.primaryIconBackgroundColor,

+ 0
- 2
src/components/Header/SearchInput/SearchInput.js Ver arquivo

@@ -25,8 +25,6 @@ const SearchInput = forwardRef((props, ref) => {
};
const listener = useCallback(
(event) => {
console.log(event);
console.log(ref);
if (event.keyCode === 13) {
event.preventDefault();
handleManualSearch();

+ 3
- 0
src/components/Header/UserButton/UserButton.js Ver arquivo

@@ -9,9 +9,11 @@ import { MyProfile } from "../../Popovers/MyProfile/MyProfile";
import { useState } from "react";
import { useEffect } from "react";
import { useLocation } from "react-router-dom";
import { useTranslation } from "react-i18next";

const UserButton = (props) => {
const location = useLocation();
const {t} = useTranslation();
const [userPopoverOpen, setUserPopoverOpen] = useState(false);
const [userAnchorEl, setUserAnchorEl] = useState(null);

@@ -32,6 +34,7 @@ const UserButton = (props) => {
<UserButtonContainer onClick={openUserPopover}>
<UserName>{props.name}</UserName>
<IconButton
aria-label={t("header.myProfile")}
style={{
background: selectedTheme.colors.primaryIconBackgroundColor,
color: selectedTheme.colors.primaryPurple,

+ 54
- 0
src/components/MarketPlace/Header/GridButtons/GridButtons.js Ver arquivo

@@ -0,0 +1,54 @@
import React from "react";
import PropTypes from "prop-types";
import {
GridButton,
GridButtonsContainer,
GridLineIcon,
GridSquareIcon,
} from "./GridButtons.styled";
import selectedTheme from "../../../../themes";

const GridButtons = (props) => {
return (
<GridButtonsContainer hideGrid={props?.hideGrid}>
{/* Setting display of offer cards to full width */}
<GridButton
iconColor={
props?.isGrid
? selectedTheme.colors.iconStrokeColor
: selectedTheme.colors.primaryPurple
}
onClick={() => props?.setIsGrid(false)}
>
<GridLineIcon />
</GridButton>
{/* ^^^^^^ */}

{/* Setting display of offer cards to half width (Grid) */}
<GridButton
iconColor={
props?.isGrid
? selectedTheme.colors.primaryPurple
: selectedTheme.colors.iconStrokeColor
}
onClick={() => props?.setIsGrid(true)}
>
<GridSquareIcon />
</GridButton>
{/* ^^^^^^ */}
</GridButtonsContainer>
);
};

GridButtons.propTypes = {
isGrid: PropTypes.bool,
setIsGrid: PropTypes.func,
hideGrid: PropTypes.bool,
};
GridButtons.defaultProps = {
isGrid: false,
setIsGrid: () => {},
hideGrid: false,
};

export default GridButtons;

+ 20
- 0
src/components/MarketPlace/Header/GridButtons/GridButtons.styled.js Ver arquivo

@@ -0,0 +1,20 @@
import { Box } from "@mui/material";
import styled from "styled-components";
import { IconButton } from "../../../Buttons/IconButton/IconButton";
import { ReactComponent as GridSquare } from "../../../../assets/images/svg/offer-grid-square.svg";
import { ReactComponent as GridLine } from "../../../../assets/images/svg/offer-grid-line.svg";

export const GridButton = styled(IconButton)`
padding: 2px 10px;
@media (max-width: 1500px) {
display: none;
}
`;
export const GridButtonsContainer = styled(Box)`
flex-direction: row;
display: ${(props) => (props.hideGrid ? "none" : "flex")};
justify-content: space-between;
margin-right: 40px;
`;
export const GridSquareIcon = styled(GridSquare)``;
export const GridLineIcon = styled(GridLine)``;

+ 24
- 160
src/components/MarketPlace/Header/Header.js Ver arquivo

@@ -1,61 +1,31 @@
import React, { useMemo } from "react";
import PropTypes from "prop-types";
import {
ButtonContainer,
CategoryHeaderIcon,
CategoryIcon,
HeaderAltLocation,
HeaderButton,
HeaderButtons,
HeaderCategoryString,
HeaderCompanyString,
HeaderContainer,
HeaderLocation,
HeaderLocationsMainString,
HeaderLocationsString,
HeaderOptions,
HeaderSelect,
HeaderSubcategoryString,
HeaderText,
HeaderTitleContainer,
HeaderTitleText,
HeaderWrapperContainer,
IconStyled,
LocationIcon,
PageTitleContainer,
SelectOption,
SubcategoryIcon,
SwapsHeaderIcon,
SwapsIcon,
SwapsTitle,
TooltipInnerContainer,
UserIcon,
} from "./Header.styled";
import { ReactComponent as GridSquare } from "../../../assets/images/svg/offer-grid-square.svg";
import { ReactComponent as GridLine } from "../../../assets/images/svg/offer-grid-line.svg";
import { ReactComponent as Down } from "../../../assets/images/svg/down-arrow.svg";
import selectedTheme from "../../../themes";
import { sortEnum } from "../../../enums/sortEnum";
import { useTranslation } from "react-i18next";
import { Tooltip } from "@mui/material";
import SkeletonHeader from "./SkeletonHeader/SkeletonHeader";
import { useSelector } from "react-redux";
import { selectHeaderString } from "../../../store/selectors/filtersSelectors";
import useIsMobile from "../../../hooks/useIsMobile";
import { ArrowButton } from "../../Buttons/ArrowButton/ArrowButton";
// import { ArrowButton } from "../../Buttons/ArrowButton/ArrowButton";
import history from "../../../store/utils/history";

const DownArrow = (props) => (
<IconStyled {...props}>
<Down />
</IconStyled>
);
// import { ArrowButton } from "../../Buttons/ArrowButton/ArrowButton";
import TooltipHeader from "./TooltipHeader/TooltipHeader";
import GridButtons from "./GridButtons/GridButtons";
import HeaderSelect from "./HeaderSelect/HeaderSelect";

const Header = (props) => {
const { t } = useTranslation();
const sorting = props?.sorting;
const headerString = useSelector(selectHeaderString);
const { isMobile } = useIsMobile();

// Changing header string on refresh or on load
@@ -104,25 +74,11 @@ const Header = (props) => {
);
});

const handleChangeSelect = (event) => {
sorting?.changeSorting(event.target.value);
};
const handleClickCategory = () => {
props?.offers?.filters?.locations.clear();
props?.offers?.filters?.subcategory.clear();
props?.offers?.applyFilters();
};
const handleClickSubcategory = () => {
props?.offers?.filters?.locations.clear();
props?.offers?.applyFilters();
};
const goBack = () => {
history.goBack();
};

return (
<>
<SkeletonHeader skeleton={props?.skeleton} myOffers={props?.myOffers} />
{props?.skeleton && (
<SkeletonHeader skeleton={props?.skeleton} myOffers={props?.myOffers} />
)}
<HeaderWrapperContainer
className={props.className}
skeleton={props?.skeleton}
@@ -130,120 +86,28 @@ const Header = (props) => {
>
<HeaderContainer>
{/* Setting appropriate header title if page is market place or my offers */}
<Tooltip title={headerString.text}>
<TooltipInnerContainer>
{!props?.myOffers ? (
<>
<CategoryHeaderIcon />
<HeaderLocation>
{/* {headerString} */}
<HeaderCategoryString
component="span"
onClick={handleClickCategory}
>
{headerString.categoryString}
{/* {headerString.subcategoryString && <>&nbsp;</>} */}
</HeaderCategoryString>
<HeaderSubcategoryString
component="span"
onClick={handleClickSubcategory}
>
{headerString.subcategoryString}
{/* {headerString.locationsString && <>&nbsp;</>} */}
</HeaderSubcategoryString>
<HeaderLocationsString component="span">
<HeaderLocationsMainString component="span">
{headerString.locationsString}
</HeaderLocationsMainString>
<HeaderCompanyString>
{headerString.companiesString}
</HeaderCompanyString>
<HeaderAltLocation component="span">
{altString}
</HeaderAltLocation>
</HeaderLocationsString>
</HeaderLocation>
</>
) : (
<>
{!isMobile ? (
<HeaderTitleContainer>
{headerIcon}
<HeaderTitleText>{headerTitle}</HeaderTitleText>
</HeaderTitleContainer>
) : (
!props.hideBackButton && (
<ButtonContainer onClick={goBack}>
<ArrowButton side={"left"}></ArrowButton>
<HeaderText>{t("messages.goBack")}</HeaderText>
</ButtonContainer>
)
)}
</>
)}
</TooltipInnerContainer>
</Tooltip>
<TooltipHeader
altText={altString}
headerTitle={headerTitle}
headerIcon={headerIcon}
offers={props?.offers}
hideBackButton={props?.hideBackButton}
/>
{/* ^^^^^^ */}

<HeaderOptions>
{!props.hideGrid && (
<HeaderButtons>
{/* Setting display of offer cards to full width */}
<HeaderButton
iconColor={
props?.isGrid
? selectedTheme.colors.iconStrokeColor
: selectedTheme.colors.primaryPurple
}
onClick={() => props?.setIsGrid(false)}
>
<GridLine />
</HeaderButton>
{/* ^^^^^^ */}

{/* Setting display of offer cards to half width (Grid) */}
<HeaderButton
iconColor={
props?.isGrid
? selectedTheme.colors.primaryPurple
: selectedTheme.colors.iconStrokeColor
}
onClick={() => props?.setIsGrid(true)}
>
<GridSquare />
</HeaderButton>
{/* ^^^^^^ */}
</HeaderButtons>
)}
<GridButtons
hideGrid={props?.hideGrid}
isGrid={props?.isGrid}
setIsGrid={props?.setIsGrid}
/>

{/* Select option to choose sorting */}
{!props.hideSorting && (
<HeaderSelect
value={
sorting?.selectedSortOption?.value
? sorting?.selectedSortOption
: "default"
}
IconComponent={DownArrow}
onChange={handleChangeSelect}
myOffers={props?.myOffers}
>
<SelectOption style={{ display: "none" }} value="default">
{t("reviews.sortBy")}
</SelectOption>
{Object.keys(sorting?.sortOptions).map((property) => {
if (sorting?.sortOptions[property].value === 0) return;
return (
<SelectOption
value={sorting?.sortOptions[property]}
key={sorting?.sortOptions[property].value}
>
{sorting?.sortOptions[property].mainText}
</SelectOption>
);
})}
</HeaderSelect>
)}
<HeaderSelect
myOffers={props?.myOffers}
sorting={sorting}
hideSorting={props?.hideSorting}
/>
{/* ^^^^^^ */}
</HeaderOptions>
</HeaderContainer>

+ 3
- 193
src/components/MarketPlace/Header/Header.styled.js Ver arquivo

@@ -1,11 +1,7 @@
import { Box, Link, MenuItem, Typography } from "@mui/material";
import { Box, Typography } from "@mui/material";
import styled from "styled-components";
import selectedTheme from "../../../themes";
import { IconButton } from "../../Buttons/IconButton/IconButton";
import Option from "../../Select/Option/Option";
import Select from "../../Select/Select";
import { ReactComponent as Swaps } from "../../../assets/images/svg/swaps.svg";
import { ReactComponent as CategoryHeader } from "../../../assets/images/svg/category-header.svg";
import { ReactComponent as User } from "../../../assets/images/svg/user.svg";
import { ReactComponent as Category } from "../../../assets/images/svg/category.svg";
import { ReactComponent as Subcategory } from "../../../assets/images/svg/subcategory.svg";
@@ -23,166 +19,20 @@ export const HeaderContainer = styled(Box)`
justify-content: space-between;
align-items: center;
`;
export const TooltipInnerContainer = styled(Box)`
width: 100%;
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
& * {
display: inline;
}
`;
export const HeaderLocation = styled(Typography)`
font-family: ${selectedTheme.fonts.textFont};
color: ${selectedTheme.colors.primaryPurple};
font-weight: 700;
line-height: 22px;
font-size: 16px;
flex: 2;
margin-left: 9px;
max-width: 50%;
position: relative;
top: -2px;

&:after {
content: ${(props) => (props.initial ? `":"` : `""`)};
@media (max-width: 600px) {
content: "";
}
}
@media (max-width: 600px) {
font-size: 12px;
padding-top: 3px;
}
`;
export const HeaderCategoryString = styled(Typography)`
font-family: ${selectedTheme.fonts.textFont};
color: ${selectedTheme.colors.primaryPurple};
font-weight: 700;
line-height: 22px;
font-size: 16px;
/* position: relative;
bottom: 2px; */
cursor: pointer;
@media (max-width: 600px) {
font-size: 12px;
padding-top: 3px;
}
`;
export const HeaderSubcategoryString = styled(Typography)`
font-family: ${selectedTheme.fonts.textFont};
color: ${selectedTheme.colors.primaryPurple};
font-weight: 700;
line-height: 22px;
font-size: 16px;
/* position: relative;
bottom: 2px; */
cursor: pointer;
@media (max-width: 600px) {
font-size: 12px;
padding-top: 3px;
}
`;
export const HeaderLocationsString = styled(Typography)`
/* position: relative;
bottom: 2px; */
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
@media (max-width: 600px) {
font-size: 12px;
padding-top: 3px;
}
max-width: 100%;
`;
export const HeaderLocationsMainString = styled(Typography)`
font-family: ${selectedTheme.fonts.textFont};
max-width: 200px;
color: ${selectedTheme.colors.primaryPurple};
font-weight: 700;
line-height: 22px;
font-size: 16px;
@media (max-width: 600px) {
font-size: 12px;
padding-top: 3px;
}
`;
export const HeaderCompanyString = styled(Typography)`
font-family: ${selectedTheme.fonts.textFont};
max-width: 200px;
color: ${selectedTheme.colors.primaryPurple};
font-weight: 700;
line-height: 22px;
font-size: 16px;
@media (max-width: 600px) {
font-size: 12px;
padding-top: 3px;
}
`;
export const HeaderButton = styled(IconButton)`
padding: 2px 10px;
@media (max-width: 1500px) {
display: none;
}
`;
export const HeaderOptions = styled(Box)`
display: flex;
flex-direction: row;
flex: 1;
justify-content: end;
`;
export const HeaderSelect = styled(Select)`
width: 210px;
height: 35px;
font-family: ${selectedTheme.fonts.textFont};
margin-top: 3px;
font-weight: 400;
position: relative;
left: -5px;
background-color: white;
& div:first-child {
padding-left: 8px;
}

@media (max-width: 650px) {
width: 144px;
height: 30px;
font-size: 14px;
top: 60px;
left: ${(props) => (props.myOffers ? "-7px" : "0")};
}
`;
export const SelectItem = styled(MenuItem)`
font-family: ${selectedTheme.fonts.textFont};
`;
export const SelectOption = styled(Option)`
@media (max-width: 600px) {
height: 20px !important;
min-height: 35px;
margin: 2px;
}
`;
export const IconStyled = styled(Box)`
position: relative;
top: 0;
right: 10px;
`;
export const HeaderButtons = styled(Box)`
flex-direction: row;
display: flex;
justify-content: space-between;
margin-right: 40px;
`;
export const HeaderAltLocation = styled(Typography)`
font-family: ${selectedTheme.fonts.textFont};
font-size: 16px;
color: ${selectedTheme.colors.primaryText};
position: relative;
top: 0.5px;
@media (max-width: 600px) {
display: none;
}
`;

export const RefreshIcon = styled(Swaps)`
width: 18px;
height: 18px;
@@ -200,15 +50,6 @@ export const MySwapsTitle = styled(Typography)`
position: relative;
left: 9px;
`;
export const CategoryHeaderIcon = styled(CategoryHeader)`
position: relative;
top: 4px;
@media (max-width: 600px) {
width: 12px;
height: 12px;
top: 1px;
}
`;
export const CategoryIcon = styled(Category)`
position: relative;
top: 4px;
@@ -243,42 +84,11 @@ export const SwapsTitle = styled(Typography)`
line-height: 16px;
color: ${selectedTheme.colors.primaryText};
`;
export const ButtonContainer = styled(Link)`
width: fit-content;
cursor: pointer;
display: flex;
justify-content: start;
align-items: center;
gap: 12px;
text-decoration: none;
min-width: 200px;
`;
export const HeaderText = styled(Typography)`
font-family: ${selectedTheme.fonts.textFont};
line-height: 22px;
font-size: 16px;
color: ${selectedTheme.colors.primaryPurple};
border-bottom: 1px dotted ${selectedTheme.colors.primaryPurple};
@media (max-width: 600px) {
font-size: 14px;
}
`;

export const SwapsHeaderIcon = styled(SwapsIcon)`
width: 18px;
height: 18px;
`;
export const HeaderTitleContainer = styled(Box)`
position: relative;
left: 5px;
`;
export const HeaderTitleText = styled(Typography)`
font-family: ${selectedTheme.fonts.textFont};
color: ${selectedTheme.colors.primaryText};
font-size: 16px;
position: relative;
bottom: 2px;
left: 2px;
`;
export const UserIcon = styled(User)`
position: relative;
top: 3px;

+ 51
- 0
src/components/MarketPlace/Header/HeaderSelect/HeaderSelect.js Ver arquivo

@@ -0,0 +1,51 @@
import React from "react";
import PropTypes from "prop-types";
import { useTranslation } from "react-i18next";
import { HeaderSelectContainer, SelectOption } from "./HeaderSelect.styled";

const HeaderSelect = (props) => {
const sorting = props?.sorting;
const { t } = useTranslation();
const handleChangeSelect = (event) => {
sorting?.changeSorting(event.target.value);
};
return (
<HeaderSelectContainer
hideSorting={props?.hideSorting}
value={
sorting?.selectedSortOption?.value
? sorting?.selectedSortOption
: "default"
}
onChange={handleChangeSelect}
myOffers={props?.myOffers}
>
<SelectOption style={{ display: "none" }} value="default">
{t("reviews.sortBy")}
</SelectOption>
{Object.keys(sorting?.sortOptions).map((property) => {
if (sorting?.sortOptions[property].value === 0) return;
return (
<SelectOption
value={sorting?.sortOptions[property]}
key={sorting?.sortOptions[property].value}
>
{sorting?.sortOptions[property].mainText}
</SelectOption>
);
})}
</HeaderSelectContainer>
);
};

HeaderSelect.propTypes = {
sorting: PropTypes.any,
myOffers: PropTypes.bool,
hideSorting: PropTypes.bool,
};
HeaderSelect.defaultProps = {
myOffers: false,
hideSorting: false,
};

export default HeaderSelect;

+ 38
- 0
src/components/MarketPlace/Header/HeaderSelect/HeaderSelect.styled.js Ver arquivo

@@ -0,0 +1,38 @@
import { MenuItem } from "@mui/material";
import styled from "styled-components";
import selectedTheme from "../../../../themes";
import Option from "../../../Select/Option/Option";
import Select from "../../../Select/Select";

export const HeaderSelectContainer = styled(Select)`
width: 210px;
height: 35px;
font-family: ${selectedTheme.fonts.textFont};
margin-top: 3px;
font-weight: 400;
position: relative;
left: -5px;
background-color: white;
display: ${(props) => props.hideSorting && "none"};
& div:first-child {
padding-left: 8px;
}

@media (max-width: 650px) {
width: 144px;
height: 30px;
font-size: 14px;
top: 60px;
left: ${(props) => (props.myOffers ? "-7px" : "0")};
}
`;
export const SelectItem = styled(MenuItem)`
font-family: ${selectedTheme.fonts.textFont};
`;
export const SelectOption = styled(Option)`
@media (max-width: 600px) {
height: 20px !important;
min-height: 35px;
margin: 2px;
}
`;

+ 113
- 0
src/components/MarketPlace/Header/TooltipHeader/TooltipHeader.js Ver arquivo

@@ -0,0 +1,113 @@
import React from "react";
import PropTypes from "prop-types";
import { Tooltip } from "@mui/material";
import {
ButtonContainer,
CategoryHeaderIcon,
HeaderAltLocation,
HeaderCategoryString,
HeaderCompanyString,
HeaderLocation,
HeaderLocationsMainString,
HeaderLocationsString,
HeaderSubcategoryString,
HeaderText,
HeaderTitleContainer,
HeaderTitleText,
TooltipInnerContainer,
} from "./TooltipHeader.styled";
import { useSelector } from "react-redux";
import { selectHeaderString } from "../../../../store/selectors/filtersSelectors";
import useIsMobile from "../../../../hooks/useIsMobile";
import { ArrowButton } from "../../../Buttons/ArrowButton/ArrowButton";
import { useTranslation } from "react-i18next";
import history from "../../../../store/utils/history";

const TooltipHeader = (props) => {
const headerString = useSelector(selectHeaderString);
const { isMobile } = useIsMobile();
const { t } = useTranslation();

const handleClickCategory = () => {
props?.offers?.filters?.locations.clear();
props?.offers?.filters?.subcategory.clear();
props?.offers?.applyFilters();
};
const handleClickSubcategory = () => {
props?.offers?.filters?.locations.clear();
props?.offers?.applyFilters();
};
const goBack = () => {
history.goBack();
};
return (
<Tooltip title={headerString.text}>
<TooltipInnerContainer>
{!props?.myOffers ? (
<>
<CategoryHeaderIcon />
<HeaderLocation>
<HeaderCategoryString
component="span"
onClick={handleClickCategory}
>
{headerString.categoryString}
</HeaderCategoryString>
<HeaderSubcategoryString
component="span"
onClick={handleClickSubcategory}
>
{headerString.subcategoryString}
</HeaderSubcategoryString>
<HeaderLocationsString component="span">
<HeaderLocationsMainString component="span">
{headerString.locationsString}
</HeaderLocationsMainString>
<HeaderCompanyString>
{headerString.companiesString}
</HeaderCompanyString>
<HeaderAltLocation component="span">
{props?.altText}
</HeaderAltLocation>
</HeaderLocationsString>
</HeaderLocation>
</>
) : (
<>
{!isMobile ? (
<HeaderTitleContainer>
{props?.headerIcon}
<HeaderTitleText>{props?.headerTitle}</HeaderTitleText>
</HeaderTitleContainer>
) : (
!props.hideBackButton && (
<ButtonContainer onClick={goBack}>
<ArrowButton side={"left"}></ArrowButton>
<HeaderText>{t("messages.goBack")}</HeaderText>
</ButtonContainer>
)
)}
</>
)}
</TooltipInnerContainer>
</Tooltip>
);
};

TooltipHeader.propTypes = {
myOffers: PropTypes.bool,
altText: PropTypes.string,
headerIcon: PropTypes.node,
headerTitle: PropTypes.string,
hideBackButton: PropTypes.bool,
offers: PropTypes.any,
};
TooltipHeader.defaultProps = {
myOffers: false,
altText: "",
headerIcon: <></>,
headerString: "",
hideBackButton: false,
};

export default TooltipHeader;

+ 153
- 0
src/components/MarketPlace/Header/TooltipHeader/TooltipHeader.styled.js Ver arquivo

@@ -0,0 +1,153 @@
import { Box, Link, Typography } from "@mui/material";
import styled from "styled-components";
import { ReactComponent as CategoryHeader } from "../../../../assets/images/svg/category-header.svg";
import selectedTheme from "../../../../themes";

export const TooltipInnerContainer = styled(Box)`
width: 100%;
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
& * {
display: inline;
}
`;
export const CategoryHeaderIcon = styled(CategoryHeader)`
position: relative;
top: 4px;
@media (max-width: 600px) {
width: 12px;
height: 12px;
top: 1px;
}
`;
export const HeaderLocation = styled(Typography)`
font-family: ${selectedTheme.fonts.textFont};
color: ${selectedTheme.colors.primaryPurple};
font-weight: 700;
line-height: 22px;
font-size: 16px;
flex: 2;
margin-left: 9px;
max-width: 50%;
position: relative;
top: -2px;

&:after {
content: ${(props) => (props.initial ? `":"` : `""`)};
@media (max-width: 600px) {
content: "";
}
}
@media (max-width: 600px) {
font-size: 12px;
padding-top: 3px;
}
`;

export const HeaderCategoryString = styled(Typography)`
font-family: ${selectedTheme.fonts.textFont};
color: ${selectedTheme.colors.primaryPurple};
font-weight: 700;
line-height: 22px;
font-size: 16px;
/* position: relative;
bottom: 2px; */
cursor: pointer;
@media (max-width: 600px) {
font-size: 12px;
padding-top: 3px;
}
`;
export const HeaderSubcategoryString = styled(Typography)`
font-family: ${selectedTheme.fonts.textFont};
color: ${selectedTheme.colors.primaryPurple};
font-weight: 700;
line-height: 22px;
font-size: 16px;
/* position: relative;
bottom: 2px; */
cursor: pointer;
@media (max-width: 600px) {
font-size: 12px;
padding-top: 3px;
}
`;
export const HeaderLocationsString = styled(Typography)`
/* position: relative;
bottom: 2px; */
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
@media (max-width: 600px) {
font-size: 12px;
padding-top: 3px;
}
max-width: 100%;
`;
export const HeaderLocationsMainString = styled(Typography)`
font-family: ${selectedTheme.fonts.textFont};
max-width: 200px;
color: ${selectedTheme.colors.primaryPurple};
font-weight: 700;
line-height: 22px;
font-size: 16px;
@media (max-width: 600px) {
font-size: 12px;
padding-top: 3px;
}
`;
export const HeaderCompanyString = styled(Typography)`
font-family: ${selectedTheme.fonts.textFont};
max-width: 200px;
color: ${selectedTheme.colors.primaryPurple};
font-weight: 700;
line-height: 22px;
font-size: 16px;
@media (max-width: 600px) {
font-size: 12px;
padding-top: 3px;
}
`;
export const HeaderAltLocation = styled(Typography)`
font-family: ${selectedTheme.fonts.textFont};
font-size: 16px;
color: ${selectedTheme.colors.primaryText};
position: relative;
top: 0.5px;
@media (max-width: 600px) {
display: none;
}
`;
export const HeaderTitleContainer = styled(Box)`
position: relative;
left: 5px;
`;
export const HeaderTitleText = styled(Typography)`
font-family: ${selectedTheme.fonts.textFont};
color: ${selectedTheme.colors.primaryText};
font-size: 16px;
position: relative;
bottom: 2px;
left: 2px;
`;
export const ButtonContainer = styled(Link)`
width: fit-content;
cursor: pointer;
display: flex;
justify-content: start;
align-items: center;
gap: 12px;
text-decoration: none;
min-width: 200px;
`;
export const HeaderText = styled(Typography)`
font-family: ${selectedTheme.fonts.textFont};
line-height: 22px;
font-size: 16px;
color: ${selectedTheme.colors.primaryPurple};
border-bottom: 1px dotted ${selectedTheme.colors.primaryPurple};
@media (max-width: 600px) {
font-size: 14px;
}
`;

+ 43
- 92
src/components/MarketPlace/Offers/Offers.js Ver arquivo

@@ -1,102 +1,31 @@
import React, { useRef } from "react";
import React from "react";
import PropTypes from "prop-types";
import { FilterContainer, FilterIcon, OffersContainer } from "./Offers.styled";
import OfferCard from "../../Cards/OfferCard/OfferCard";
import { useSelector } from "react-redux";
import Paging from "../../Paging/Paging";
import { selectLatestChats } from "../../../store/selectors/chatSelectors";
import { selectUserId } from "../../../store/selectors/loginSelectors";
import { startChat } from "../../../util/helpers/chatHelper";
import OffersNotFound from "./OffersNotFound";
// import HeadersMyOffers from "./SearchBar/SearchBar";
import SkeletonOfferCard from "../../Cards/OfferCard/SkeletonOfferCard/SkeletonOfferCard";
import BigProfileCard from "../../Cards/ProfileCard/BigProfileCard/BigProfileCard";
import SearchField from "../../TextFields/SearchField/SearchField";
import { useTranslation } from "react-i18next";
import OffersList from "./OffersList/OffersList";
import OffersFilterButton from "./OffersFilterButton/OffersFilterButton";
import OffersSearchField from "./OffersSearchField/OffersSearchField";
import OffersNotFound from "./OffersNotFound/OffersNotFound";

const Offers = (props) => {
const chats = useSelector(selectLatestChats);
const offersRef = useRef(null);
const userId = useSelector(selectUserId);
const { t } = useTranslation();
const offers = props?.offers;
// For skeleton screen
const arrayForMapping = Array.apply(null, Array(4)).map(() => {});

const messageOneUser = (offer) => {
startChat(chats, offer, userId);
};
const toggleFilters = () => {
props?.toggleFilters();
};

return (
<>
{!props?.skeleton ? (
<>
<FilterContainer
isAdmin={props?.isAdmin}
onClick={toggleFilters}
number={offers?.filters?.numOfFiltersChosen}
myOffers={props?.myOffers}
>
<FilterIcon />
</FilterContainer>
{(props?.myOffers || props?.isAdmin) && (
// <HeadersMyOffers
<SearchField
searchMyOffers={offers?.search?.searchOffers}
handleSearch={offers?.apply}
isAdmin={props?.isAdmin}
offers={offers}
isUsers={props.isUsers}
placeholder={
props.isUsers
? t("admin.users.searchPlaceholder")
: t("header.searchOffers")
}
/>
)}
{offers?.allOffersToShow?.length === 0 ? (
<OffersNotFound />
) : (
<OffersContainer ref={offersRef}>
{props.isUsers
? props.users?.map((item) => (
<BigProfileCard
key={item._id}
profile={item}
halfwidth={props?.isGrid}
/>
))
: offers?.allOffersToShow?.map((item) => {
return (
<OfferCard
key={item._id}
offer={item}
halfwidth={props?.isGrid}
messageUser={messageOneUser}
isMyOffer={item?.userId === userId || props?.isAdmin}
isAdmin={props?.isAdmin}
/>
);
})}
<Paging
totalElements={offers?.totalOffers}
elementsPerPage={10}
current={parseInt(offers?.paging?.currentPage)}
changePage={offers?.paging?.changePage}
/>
</OffersContainer>
)}
</>
) : (
<>
{arrayForMapping.map((item, index) => (
<SkeletonOfferCard key={index} skeleton />
))}
</>
)}
<OffersFilterButton />
<OffersSearchField />
<OffersNotFound />
<OffersList
loading={props?.skeleton}
offers={offers}
isAdmin={props.isAdmin}
isGrid={props?.isGrid}
isUsers={props?.isUsers}
users={props?.users}
/>
{props?.skeleton &&
arrayForMapping.map((item, index) => (
<SkeletonOfferCard key={index} skeleton={props?.skeleton} />
))}
</>
);
};
@@ -106,7 +35,15 @@ Offers.propTypes = {
isGrid: PropTypes.bool,
myOffers: PropTypes.bool,
skeleton: PropTypes.bool,
offers: PropTypes.any,
offers: PropTypes.shape({
apply: PropTypes.func,
search: PropTypes.shape({
searchOffers: PropTypes.func,
}),
filters: PropTypes.shape({
numOfFiltersChosen: PropTypes.number,
}),
}),
toggleFilters: PropTypes.func,
isAdmin: PropTypes.bool,
isUsers: PropTypes.bool,
@@ -116,6 +53,20 @@ Offers.propTypes = {
Offers.defaultProps = {
myOffers: false,
users: [],
isAdmin: false,
isUsers: false,
isGrid: false,
skeleton: false,
toggleFilters: () => {},
offers: {
apply: () => {},
search: {
searchOffers: () => {},
},
filters: {
numOfFiltersChosen: 0,
},
},
};

export default Offers;

+ 0
- 39
src/components/MarketPlace/Offers/Offers.styled.js Ver arquivo

@@ -1,39 +0,0 @@
import { Box } from "@mui/material";
import styled from "styled-components";
import selectedTheme from "../../../themes";
import IconWithNumber from "../../Icon/IconWithNumber/IconWithNumber";
import { ReactComponent as Filter } from "../../../assets/images/svg/filter.svg";


export const OffersContainer = styled(Box)`
display: flex;
flex-direction: row;
flex-wrap: wrap;
justify-content: space-between;
margin-top: 5px;
position: relative;
padding-bottom: 60px;
`;
export const FilterContainer = styled(IconWithNumber)`
position: absolute;
top: 93px;
right: 24px;
cursor: pointer;
background-color: ${selectedTheme.colors.primaryBackgroundColor} !important;
& div {
width: 16px;
height: 16px;
background-color: ${selectedTheme.colors.primaryPurple};
position: absolute;
top: -5px;
right: -5px;
line-height: 15px;
text-align: center;
}
@media (min-width: 600px) {
display: none;
}
`;
export const FilterIcon = styled(Filter)`
background-color: ${selectedTheme.colors.primaryBackgroundColor};
`;

+ 43
- 0
src/components/MarketPlace/Offers/OffersFilterButton/OffersFilterButton.js Ver arquivo

@@ -0,0 +1,43 @@
import React from "react";
import PropTypes from "prop-types";
import { FilterContainer, FilterIcon } from "./OffersFilterButton.styled";

const OffersFilterButton = (props) => {
const toggleFilters = () => {
props?.toggleFilters();
};
return (
<FilterContainer
isAdmin={props?.isAdmin}
onClick={toggleFilters}
number={props?.offers?.filters?.numOfFiltersChosen}
myOffers={props?.myOffers}
>
<FilterIcon />
</FilterContainer>
);
};

OffersFilterButton.propTypes = {
isAdmin: PropTypes.bool,
offers: PropTypes.shape({
filters: PropTypes.shape({
numOfFiltersChosen: PropTypes.number,
}),
}),
myOffers: PropTypes.bool,
toggleFilters: PropTypes.func,
};

OffersFilterButton.defaultProps = {
isAdmin: false,
offers: {
filters: {
numOfFiltersChosen: 0,
},
},
myOffers: false,
toggleFilters: () => {},
};

export default OffersFilterButton;

+ 28
- 0
src/components/MarketPlace/Offers/OffersFilterButton/OffersFilterButton.styled.js Ver arquivo

@@ -0,0 +1,28 @@
import styled from "styled-components";
import selectedTheme from "../../../../themes";
import IconWithNumber from "../../../Icon/IconWithNumber/IconWithNumber";
import { ReactComponent as Filter } from "../../../../assets/images/svg/filter.svg";

export const FilterContainer = styled(IconWithNumber)`
position: absolute;
top: 93px;
right: 24px;
cursor: pointer;
background-color: ${selectedTheme.colors.primaryBackgroundColor} !important;
& div {
width: 16px;
height: 16px;
background-color: ${selectedTheme.colors.primaryPurple};
position: absolute;
top: -5px;
right: -5px;
line-height: 15px;
text-align: center;
}
@media (min-width: 600px) {
display: none;
}
`;
export const FilterIcon = styled(Filter)`
background-color: ${selectedTheme.colors.primaryBackgroundColor};
`;

+ 73
- 0
src/components/MarketPlace/Offers/OffersList/OffersList.js Ver arquivo

@@ -0,0 +1,73 @@
import React from "react";
import PropTypes from "prop-types";
import { useSelector } from "react-redux";
import { selectTotalOffers } from "../../../../store/selectors/offersSelectors";
import { OffersContainer } from "./OffersList.styled";
import BigProfileCard from "../../../Cards/ProfileCard/BigProfileCard/BigProfileCard";
import OfferCard from "../../../Cards/OfferCard/OfferCard";
import Paging from "../../../Paging/Paging";
import { startChat } from "../../../../util/helpers/chatHelper";
import { selectLatestChats } from "../../../../store/selectors/chatSelectors";
import { selectUserId } from "../../../../store/selectors/loginSelectors";

const OffersList = (props) => {
const totalOffers = useSelector(selectTotalOffers);
const chats = useSelector(selectLatestChats);
const userId = useSelector(selectUserId);
const offers = props?.offers;
const messageOneUser = (offer) => {
startChat(chats, offer, userId);
};
return (
<OffersContainer show={!props?.loading && totalOffers !== 0}>
{props.isUsers
? props.users?.map((item) => (
<BigProfileCard
key={item._id}
profile={item}
halfwidth={props?.isGrid}
/>
))
: offers?.allOffersToShow?.map((item) => {
return (
<OfferCard
key={item._id}
offer={item}
halfwidth={props?.isGrid}
messageUser={messageOneUser}
isMyOffer={item?.userId === userId || props?.isAdmin}
isAdmin={props?.isAdmin}
/>
);
})}
<Paging
totalElements={offers?.totalOffers}
elementsPerPage={10}
current={parseInt(offers?.paging?.currentPage)}
changePage={offers?.paging?.changePage}
/>
</OffersContainer>
);
};

OffersList.propTypes = {
offers: PropTypes.any,
isGrid: PropTypes.bool,
isUsers: PropTypes.bool,
users: PropTypes.array,
isAdmin: PropTypes.bool,
loading: PropTypes.bool,
};

OffersList.defaultProps = {
isGrid: false,
isUsers: false,
users: [],
isAdmin: false,
offers: {
allOffersToShow: [],
},
loading: false,
};

export default OffersList;

+ 12
- 0
src/components/MarketPlace/Offers/OffersList/OffersList.styled.js Ver arquivo

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

export const OffersContainer = styled(Box)`
display: ${props => props.show ? "flex" : "none"};
flex-direction: row;
flex-wrap: wrap;
justify-content: space-between;
margin-top: 5px;
position: relative;
padding-bottom: 60px;
`;

+ 0
- 55
src/components/MarketPlace/Offers/OffersNotFound.js Ver arquivo

@@ -1,55 +0,0 @@
import React from "react";
import { ReactComponent as LogoBroken } from "../../../assets/images/svg/logo-broken.svg";
import {
Button,
OffersNotFoundContainer,
OffersNotFoundLogo,
OffersNotFoundDescription,
OffersNotFoundHeading,
} from "./OffersNotFound.styled";
import selectedTheme from "../../../themes";
import { Trans, useTranslation } from "react-i18next";
import { useHistory } from "react-router-dom";
import { HOME_PAGE } from "../../../constants/pages";
import { useDispatch } from "react-redux";
import { fetchOffers } from "../../../store/actions/offers/offersActions";

const OffersNotFound = () => {
const dispatch = useDispatch();
const history = useHistory();
const { t } = useTranslation();

const showAllOffersHandler = () => {
dispatch(fetchOffers({ queryString: "" }));
history.replace({
pathname: HOME_PAGE,
state: {
from: history.location.pathname,
},
});
};

return (
<OffersNotFoundContainer>
<OffersNotFoundLogo>
<LogoBroken />
</OffersNotFoundLogo>
<OffersNotFoundHeading>
{t("offersNotFound.notFound")}
</OffersNotFoundHeading>
<OffersNotFoundDescription>
<Trans i18nKey="offersNotFound.errorMessage" />
</OffersNotFoundDescription>
<Button
variant="contained"
buttoncolor={selectedTheme.colors.primaryYellow}
textcolor="black"
onClick={showAllOffersHandler}
>
{t("offersNotFound.showAllOffers")}
</Button>
</OffersNotFoundContainer>
);
};

export default OffersNotFound;

+ 67
- 0
src/components/MarketPlace/Offers/OffersNotFound/OffersNotFound.js Ver arquivo

@@ -0,0 +1,67 @@
import React from "react";
import PropTypes from "prop-types";
import { ReactComponent as LogoBroken } from "../../../../assets/images/svg/logo-broken.svg";
import {
Button,
OffersNotFoundContainer,
OffersNotFoundLogo,
OffersNotFoundDescription,
OffersNotFoundHeading,
} from "./OffersNotFound.styled";
import selectedTheme from "../../../../themes";
import { Trans, useTranslation } from "react-i18next";
import { useHistory } from "react-router-dom";
import { HOME_PAGE } from "../../../../constants/pages";
import { useDispatch, useSelector } from "react-redux";
import { fetchOffers } from "../../../../store/actions/offers/offersActions";
import { selectTotalOffers } from "../../../../store/selectors/offersSelectors";

const OffersNotFound = () => {
const dispatch = useDispatch();
const history = useHistory();
const totalOffers = useSelector(selectTotalOffers);
const { t } = useTranslation();

const showAllOffersHandler = () => {
dispatch(fetchOffers({ queryString: "" }));
history.replace({
pathname: HOME_PAGE,
state: {
from: history.location.pathname,
},
});
};

return (
<>
<OffersNotFoundContainer show={totalOffers === 0}>
<OffersNotFoundLogo>
<LogoBroken />
</OffersNotFoundLogo>
<OffersNotFoundHeading>
{t("offersNotFound.notFound")}
</OffersNotFoundHeading>
<OffersNotFoundDescription>
<Trans i18nKey="offersNotFound.errorMessage" />
</OffersNotFoundDescription>
<Button
variant="contained"
buttoncolor={selectedTheme.colors.primaryYellow}
textcolor="black"
onClick={showAllOffersHandler}
>
{t("offersNotFound.showAllOffers")}
</Button>
</OffersNotFoundContainer>
</>
);
};

OffersNotFound.propTypes = {
skeleton: PropTypes.bool,
};
OffersNotFound.defaultProps = {
skeleton: false,
};

export default OffersNotFound;

src/components/MarketPlace/Offers/OffersNotFound.styled.js → src/components/MarketPlace/Offers/OffersNotFound/OffersNotFound.styled.js Ver arquivo

@@ -1,11 +1,11 @@
import styled from "styled-components";
import { Typography } from "@mui/material";
import { Box } from "@mui/system";
import selectedTheme from "../../../themes";
import { PrimaryButton } from "../../Buttons/PrimaryButton/PrimaryButton";
import selectedTheme from "../../../../themes";
import { PrimaryButton } from "../../../Buttons/PrimaryButton/PrimaryButton";

export const OffersNotFoundContainer = styled(Box)`
display: flex;
display: ${props => props.show ? "flex" : "none"};
flex-direction: column;
align-items: center;
justify-content: center;

+ 50
- 0
src/components/MarketPlace/Offers/OffersSearchField/OffersSearchField.js Ver arquivo

@@ -0,0 +1,50 @@
import React from "react";
import PropTypes from "prop-types";
import SearchField from "../../../TextFields/SearchField/SearchField";
import { useTranslation } from "react-i18next";

const OffersSearchField = (props) => {
const offers = props?.offers;
const { t } = useTranslation();
if (props?.myOffers || props?.isAdmin)
return (
<SearchField
searchMyOffers={offers?.search?.searchOffers}
handleSearch={offers?.apply}
isAdmin={props?.isAdmin}
offers={offers}
isUsers={props.isUsers}
placeholder={
props.isUsers
? t("admin.users.searchPlaceholder")
: t("header.searchOffers")
}
/>
);
return <></>;
};

OffersSearchField.propTypes = {
offers: PropTypes.shape({
apply: PropTypes.func,
search: PropTypes.shape({
searchOffers: PropTypes.func,
}),
}),
isUsers: PropTypes.bool,
isAdmin: PropTypes.bool,
myOffers: PropTypes.bool,
};
OffersSearchField.defaultProps = {
offers: {
apply: () => {},
search: {
searchOffers: () => {},
},
},
isUsers: false,
isAdmin: false,
myOffers: false,
};

export default OffersSearchField;

+ 0
- 0
src/components/MarketPlace/Offers/OffersSearchField/OffersSearchField.styled.js Ver arquivo


+ 0
- 1
src/components/Modals/Modal.js Ver arquivo

@@ -25,7 +25,6 @@ const Modal = () => {
} else {
document.body.style.overflow = "auto";
}
console.log("MODALS: ", modals);
return (
<>
{modals?.createOfferModal && <CreateOffer {...modals?.props} />}

+ 5
- 0
src/components/Paging/Paging.js Ver arquivo

@@ -7,8 +7,11 @@ import {
PagingContainer,
ThreeDots,
} from "./Paging.styled";
import { useTranslation } from "react-i18next";

const Paging = (props) => {
const {t} = useTranslation();

// Determining total pages
const pages = props.pages
? props.pages
@@ -27,6 +30,7 @@ const Paging = (props) => {
<PagingContainer className={props.className}>
{/* Left arrow */}
<Arrow
aria-label={t("labels.prevPage")}
onClick={() => props.changePage(props.current - 1)}
disabled={props.current - 1 < 1}
>
@@ -71,6 +75,7 @@ const Paging = (props) => {

{/* Right arrow */}
<Arrow
aria-label={t("labels.nextPage")}
onClick={() => props.changePage(props.current + 1)}
disabled={props.current + 1 > pages}
>

+ 6
- 6
src/constants/pages.js Ver arquivo

@@ -10,18 +10,18 @@ export const REGISTER_PAGE = "/register";
export const REGISTER_SUCCESSFUL_PAGE = "/register/success";
export const RESET_PASSWORD_PAGE = "/reset-password/:token";
export const CREATE_OFFER_PAGE = "/create-offer";
export const ITEM_DETAILS_PAGE = "/proizvodi/:idProizvod";
export const PROFILE_PAGE = "/profile/:idProfile";
export const CHAT_PAGE = "/messages";
export const CHAT_MESSAGE_PAGE = "/messages/:idChat";
export const ITEM_DETAILS_PAGE = "/offers/:offerId";
export const PROFILE_PAGE = "/profiles/:profileId";
export const MESSAGES_LIST_PAGE = "/messages";
export const DIRECT_CHAT_PAGE = "/messages/:chatId";
export const MY_OFFERS_PAGE = "/myoffers";
export const ABOUT_PAGE = "/about";
export const PRICES_PAGE = "/prices";
export const POLICY_PRIVACY_PAGE = "/policy";
export const ADMIN_HOME_PAGE = "/admin";
export const ADMIN_USERS_PAGE = "/admin/users";
export const ADMIN_SINGLE_USER_PAGE = "/admin/users/:idProfile";
export const ADMIN_ITEM_DETAILS_PAGE = "/admin/proizvodi/:idProizvod";
export const ADMIN_SINGLE_USER_PAGE = "/admin/profiles/:profileId";
export const ADMIN_ITEM_DETAILS_PAGE = "/admin/offers/:offerId";
export const ADMIN_CATEGORIES_PAGE = "/admin/categories";
export const ADMIN_LOCATIONS_PAGE = "/admin/locations";
export const ADMIN_PAYMENT_PAGE = "/admin/payment";

+ 12
- 2
src/i18n/resources/rs.js Ver arquivo

@@ -195,6 +195,7 @@ export default {
checkButtonLabel: "Pogledaj proizvod",
offers: "Objave",
tooltip: "Izmeni objavu",
imageAlt: "Offer image",
},
apiErrors: {
somethingWentWrong: "Greška sa serverom!",
@@ -256,12 +257,13 @@ export default {
tooltip: "Pošalji poruku",
requestSent: "Uspešno ste ponudili trampu kompaniji.",
requestAccepted: "Kompanija je prihvatila trampu sa Vama.",
requestReceived: "Da li želite da prihvatite trampu sa nama za gorenavedeni proizvod?",
requestReceived:
"Da li želite da prihvatite trampu sa nama za gorenavedeni proizvod?",
acceptRequest: "Prihvati",
acceptedRequest: "Prihvaćeno",
declineRequest: "Odbij",
requestSuccessfulLong: "Uspešno ste ostvarili trampu sa ovom kompanijom.",
requestSentLong: "Ponudili ste trampu kompaniji. Čeka se odgovor..."
requestSentLong: "Ponudili ste trampu kompaniji. Čeka se odgovor...",
},
editProfile: {
website: "Web Sajt",
@@ -590,4 +592,12 @@ export default {
confirm: "Obriši komentar",
},
},
labels: {
dropdownIcon: "Dropdown icon",
dropdownOpen: "Open dropdown",
dropdownClose: "Close dropdown",
messageUser: "Message user",
prevPage: "Previous page",
nextPage: "Next page",
},
};

+ 3
- 0
src/index.css Ver arquivo

@@ -1,3 +1,6 @@
.ToastBody * {
font-family: "DM Sans";
}
* {
font-display: swap;
}

+ 1
- 1
src/index.js Ver arquivo

@@ -18,7 +18,7 @@ ReactDOM.render(
<Provider store={store}>
<ColorModeProvider>
<PersistGate loading={null} persistor={persistor}>
<GlobalStyle/>
<GlobalStyle />
<App />
</PersistGate>
</ColorModeProvider>

src/pages/ChatMessages/ChatMessages.js → src/pages/DirectChatPage/DirectChatPage.js Ver arquivo

@@ -4,32 +4,34 @@ import MiniChatColumn from "../../components/DirectChat/MiniChatColumn/MiniChatC
import ChatGridLayout from "../../layouts/ChatGridLayout/ChatGridLayout";
import { useSwipeable } from "react-swipeable";
import {
ChatMessagesPageContainer,
DirectChatPageContainer,
SwiperContainer,
} from "./ChatMessages.styled";
} from "./DirectChatPage.styled";
import { useHistory } from "react-router-dom";
export const ChatMessagesPage = () => {
export const DirectChatPage = () => {
const history = useHistory();

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

const handlersBox = useSwipeable({
onSwipedRight: () => setTimeout(goBack, 0),
trackMouse: false,
// preventDefaultTouchmoveEvent: true
});
return (
<SwiperContainer {...handlersBox}>
<ChatMessagesPageContainer>
<DirectChatPageContainer>
<ChatGridLayout
content={<DirectChat />}
leftCard={<MiniChatColumn />}
/>
</ChatMessagesPageContainer>
</DirectChatPageContainer>
</SwiperContainer>
);
};

ChatMessagesPage.propTypes = {};
DirectChatPage.propTypes = {};

export default ChatMessagesPage;
export default DirectChatPage;

src/pages/ChatMessages/ChatMessages.styled.js → src/pages/DirectChatPage/DirectChatPage.styled.js Ver arquivo

@@ -2,7 +2,7 @@ import { Container } from "@mui/system";
import styled from "styled-components";
import { transitionOnLoadFromRight } from "../../components/Styles/globalStyleComponents";

export const ChatMessagesPageContainer = styled(Container)`
export const DirectChatPageContainer = styled(Container)`
max-width: none;
@media (max-width: 600px) {
animation: 0.2s ease 0s 1 ${transitionOnLoadFromRight};

+ 37
- 9
src/pages/HomePage/HomePage.js Ver arquivo

@@ -1,15 +1,43 @@
import React from 'react';
import React, { useState } from "react";
import { HomePageContainer } from "./HomePage.styled";
import FilterCard from "../../components/Cards/FilterCard/FilterCard";
import MainLayout from "../../layouts/MainLayout/MainLayout";
import MarketPlace from "../../components/MarketPlace/MarketPlace";
import { selectIsLoadingByActionType } from "../../store/selectors/loadingSelectors";
import { useSelector } from "react-redux";
import { OFFERS_SCOPE } from "../../store/actions/offers/offersActionConstants";
import useOffers from "../../hooks/useOffers/useOffers";

const HomePage = () => {
const isLoadingOffers = useSelector(
selectIsLoadingByActionType(OFFERS_SCOPE)
);
const [filtersOpened, setFiltersOpened] = useState(false);
const offers = useOffers();
const toggleFilters = () => {
setFiltersOpened((prevFiltersOpened) => !prevFiltersOpened);
};

return (
<div className="c-error-page">
<div className="c-error-page__content">
<h1 className="c-error-page__title">Home page</h1>
</div>
</div>
<HomePageContainer>
<MainLayout
leftCard={
<FilterCard
offers={offers}
filtersOpened={filtersOpened}
skeleton={isLoadingOffers}
toggleFilters={toggleFilters}
/>
}
content={
<MarketPlace
offers={offers}
skeleton={isLoadingOffers}
toggleFilters={toggleFilters}
/>
}
/>
</HomePageContainer>
);
};

HomePage.propTypes = {};

export default HomePage;

+ 0
- 43
src/pages/HomePage/HomePageMUI.js Ver arquivo

@@ -1,43 +0,0 @@
import React, { useState } from "react";
import { HomePageContainer } from "./HomePage.styled";
import FilterCard from "../../components/Cards/FilterCard/FilterCard";
import MainLayout from "../../layouts/MainLayout/MainLayout";
import MarketPlace from "../../components/MarketPlace/MarketPlace";
import { selectIsLoadingByActionType } from "../../store/selectors/loadingSelectors";
import { useSelector } from "react-redux";
import { OFFERS_SCOPE } from "../../store/actions/offers/offersActionConstants";
import useOffers from "../../hooks/useOffers/useOffers";

const HomePage = () => {
const isLoadingOffers = useSelector(
selectIsLoadingByActionType(OFFERS_SCOPE)
);
const [filtersOpened, setFiltersOpened] = useState(false);
const offers = useOffers();
const toggleFilters = () => {
setFiltersOpened((prevFiltersOpened) => !prevFiltersOpened);
};

return (
<HomePageContainer>
<MainLayout
leftCard={
<FilterCard
offers={offers}
filtersOpened={filtersOpened}
skeleton={isLoadingOffers}
toggleFilters={toggleFilters}
/>
}
content={
<MarketPlace
offers={offers}
skeleton={isLoadingOffers}
toggleFilters={toggleFilters}
/>
}
/>
</HomePageContainer>
);
};
export default HomePage;

src/pages/Chat/Chat.js → src/pages/MessagesListPage/MessagesListPage.js Ver arquivo

@@ -1,29 +1,29 @@
import React from "react";
import { useHistory } from "react-router-dom";
import { ChatColumn } from "../../components/ChatColumn/ChatColumn";
import { CHAT_MESSAGE_PAGE } from "../../constants/pages";
import { DIRECT_CHAT_PAGE } from "../../constants/pages";
import ChatLayout from "../../layouts/ChatLayout/ChatLayout";
import { replaceInRoute } from "../../util/helpers/routeHelpers";
import { ChatPageContainer } from "./Chat.styled";
import { MessagesListPageContainer } from "./MessagesListPage.styled";

export const ChatPage = () => {
export const MessagesListPage = () => {
const history = useHistory();
const navigateToChat = (chatId) => {
setTimeout(() => {
history.push(
replaceInRoute(CHAT_MESSAGE_PAGE, {
replaceInRoute(DIRECT_CHAT_PAGE, {
idChat: chatId,
})
);
}, 120);
};
return (
<ChatPageContainer>
<MessagesListPageContainer>
<ChatLayout content={<ChatColumn navigateToChat={navigateToChat} />} />
</ChatPageContainer>
</MessagesListPageContainer>
);
};

ChatPage.propTypes = {};
MessagesListPage.propTypes = {};

export default ChatPage;
export default MessagesListPage;

src/pages/Chat/Chat.styled.js → src/pages/MessagesListPage/MessagesListPage.styled.js Ver arquivo

@@ -2,7 +2,7 @@ import { Container } from "@mui/system";
import styled from "styled-components";
import { transitionOnLoadFromLeft } from "../../components/Styles/globalStyleComponents";

export const ChatPageContainer = styled(Container)`
export const MessagesListPageContainer = styled(Container)`
padding: 0;
margin: 0;
animation: 0.2s ease 0s 1 ${transitionOnLoadFromLeft};

+ 0
- 1
src/store/saga/categoriesSaga.js Ver arquivo

@@ -10,7 +10,6 @@ import {
function* fetchCategories() {
try {
const data = yield call(attemptFetchCategories);
console.log("ASDFASDF", data);
if (!data?.data) throw new Error();
yield put(setCategories(data.data));
yield put(fetchCategoriesSuccess());

BIN
src/themes/primaryTheme/fonts/OpenSans-Regular.ttf Ver arquivo


+ 3
- 3
src/util/helpers/messageHelper.js Ver arquivo

@@ -1,4 +1,4 @@
import { CHAT_MESSAGE_PAGE } from "../../constants/pages";
import { DIRECT_CHAT_PAGE } from "../../constants/pages";
import history from "../../store/utils/history";
import { replaceInRoute } from "./routeHelpers";

@@ -8,12 +8,12 @@ export const messageUserHelper = (chats, userId, offer) => {
);
if (chatItem !== undefined) {
history.push(
replaceInRoute(CHAT_MESSAGE_PAGE, { idChat: chatItem.chat._id })
replaceInRoute(DIRECT_CHAT_PAGE, { idChat: chatItem.chat._id })
);
} else {
if (offer?.offer?.userId !== userId) {
history.push(
replaceInRoute(CHAT_MESSAGE_PAGE, { idChat: "newMessage" }),
replaceInRoute(DIRECT_CHAT_PAGE, { idChat: "newMessage" }),
{
offerId: offer?.offer?._id,
}

+ 0
- 1
src/util/helpers/reviewsHelper.js Ver arquivo

@@ -2,7 +2,6 @@ import { reviewEnum } from "../../enums/reviewEnum";

export const sortReviews = (reviews = [], positive = false) => {
let newReviews;
console.log(reviews);
if (!Array.isArray(reviews)) return [];
if (positive) {
newReviews = [

Carregando…
Cancelar
Salvar