You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268
  1. import React, { useState, useEffect, useRef } from "react";
  2. import {
  3. AuthButtonsContainer,
  4. HeaderContainer,
  5. LogoContainer,
  6. MarketplaceLinkRoute,
  7. MarketplaceLinkRouteContainer,
  8. ToolsButtonsContainer,
  9. ToolsContainer,
  10. } from "./Header.styled";
  11. import PropTypes from "prop-types";
  12. import { AppBar, Toolbar, useMediaQuery } from "@mui/material";
  13. import { useTheme } from "@mui/system";
  14. import { ReactComponent as LogoHorizontal } from "../../assets/images/svg/logo-horizontal.svg";
  15. import { useDispatch, useSelector } from "react-redux";
  16. import { selectUserId } from "../../store/selectors/loginSelectors";
  17. import { selectProfileName } from "../../store/selectors/profileSelectors";
  18. import { useHistory, useRouteMatch } from "react-router-dom";
  19. import {
  20. ABOUT_PAGE,
  21. ADMIN_HOME_PAGE,
  22. BASE_PAGE,
  23. HOME_PAGE,
  24. MARKETPLACE_PAGE,
  25. } from "../../constants/pages";
  26. import { fetchMineProfile } from "../../store/actions/profile/profileActions";
  27. import useSearch from "../../hooks/useOffers/useSearch";
  28. import {
  29. isAdminRoute,
  30. isAuthRoute,
  31. routeMatches,
  32. } from "../../util/helpers/routeHelpers";
  33. import AboutHeader from "./AboutHeader/AboutHeader";
  34. import SearchInput from "./SearchInput/SearchInput";
  35. import DrawerContainer from "./DrawerContainer/DrawerContainer";
  36. import OpenDrawerButton from "./OpenDrawerButton/OpenDrawerButton";
  37. import AddOfferButton from "./AddOfferButton/AddOfferButton";
  38. import MySwapsButton from "./MySwapsButton/MySwapsButton";
  39. import MyMessagesButton from "./MyMessagesButton/MyMessagesButton";
  40. import UserButton from "./UserButton/UserButton";
  41. import LoginButton from "./LoginButton/LoginButton";
  42. import RegisterButton from "./RegisterButton/RegisterButton";
  43. import { toggleCreateOfferModal } from "../../store/actions/modal/modalActions";
  44. import { ReactComponent as Marketplace } from "../../assets/images/svg/package.svg";
  45. import { useTranslation } from "react-i18next";
  46. import useIsTablet from "../../hooks/useIsTablet";
  47. import { clearFilters } from "../../store/actions/filters/filtersActions";
  48. import { selectLatestChats } from "../../store/selectors/chatSelectors";
  49. const Header = () => {
  50. const theme = useTheme();
  51. const searchRef = useRef(null);
  52. const matches = useMediaQuery(theme.breakpoints.down("md"));
  53. const user = useSelector(selectUserId);
  54. const search = useSearch(() => {});
  55. const dispatch = useDispatch();
  56. const name = useSelector(selectProfileName);
  57. const history = useHistory();
  58. const drawerRef = useRef(null);
  59. const [shouldShow, setShouldShow] = useState(true);
  60. const routeMatch = useRouteMatch();
  61. const { isTablet } = useIsTablet();
  62. const [logoClicked, setLogoClicked] = useState(false);
  63. const [badge, setBadge] = useState(0);
  64. const { t } = useTranslation();
  65. const allChats = useSelector(selectLatestChats);
  66. const seenLastChat = allChats[0]?.participants?.filter(
  67. (item) => item._id === user
  68. )[0]?.hasSeenLatestMessages;
  69. useEffect(() => {
  70. if (seenLastChat === false) {
  71. setBadge((prevState) => prevState + 1);
  72. }
  73. }, [seenLastChat]);
  74. // Dont show header on auth routes(login, register, etc.) and admin routes
  75. useEffect(() => {
  76. if (isAuthRoute() || (isAdminRoute() && !isTablet)) setShouldShow(false);
  77. else setShouldShow(true);
  78. }, [routeMatch, isTablet]);
  79. // Fetch mine profile on loading home page
  80. useEffect(() => {
  81. if (user && user?.length > 0) {
  82. dispatch(fetchMineProfile());
  83. }
  84. }, []);
  85. useEffect(() => {
  86. if (logoClicked) {
  87. console.log("clicked");
  88. if (isAdminRoute()) {
  89. history.push({
  90. pathname: ADMIN_HOME_PAGE,
  91. state: {
  92. logo: true,
  93. },
  94. });
  95. } else {
  96. if (user) {
  97. history.push({
  98. pathname: HOME_PAGE,
  99. state: {
  100. logo: true,
  101. },
  102. });
  103. } else {
  104. console.log("odje");
  105. history.push({
  106. pathname: MARKETPLACE_PAGE,
  107. state: {
  108. logo: true,
  109. },
  110. });
  111. }
  112. if (searchRef?.current) searchRef.current.value = "";
  113. }
  114. setLogoClicked(false);
  115. }
  116. }, [logoClicked]);
  117. // Sets value into search input based on query string
  118. useEffect(() => {
  119. if (searchRef.current) {
  120. searchRef.current.value = search.searchString ?? "";
  121. }
  122. }, [search.searchString, searchRef.current]);
  123. // Handling search when user is on marketplace and when he is not
  124. const handleSearch = (value) => {
  125. if (isAdminRoute()) {
  126. search.setSearchStringManually(value);
  127. } else {
  128. if (history.location.pathname.includes("/offer")) {
  129. const newQueryString = new URLSearchParams({ search: value });
  130. history.push({
  131. pathname: HOME_PAGE,
  132. search: newQueryString.toString(),
  133. });
  134. }
  135. if (!routeMatches(HOME_PAGE) && !routeMatches(BASE_PAGE)) {
  136. const newQueryString = new URLSearchParams({ search: value });
  137. history.push({
  138. pathname: HOME_PAGE,
  139. search: newQueryString.toString(),
  140. });
  141. } else {
  142. search.searchOffersImmediately(value);
  143. }
  144. }
  145. };
  146. // When user clicks logo, he sends specific state so filters can be removed
  147. const handleLogoClick = () => {
  148. if (
  149. ((routeMatches(HOME_PAGE) || routeMatches(BASE_PAGE)) && user) ||
  150. routeMatches(MARKETPLACE_PAGE)
  151. ) {
  152. dispatch(clearFilters());
  153. }
  154. setLogoClicked(true);
  155. };
  156. const handleAddOfferClick = () => {
  157. dispatch(toggleCreateOfferModal());
  158. };
  159. if (!shouldShow) {
  160. return <></>;
  161. }
  162. return (
  163. <HeaderContainer>
  164. <AppBar
  165. elevation={0}
  166. position="fixed"
  167. sx={{ backgroundColor: "white", zIndex: "80", height: "72px" }}
  168. >
  169. <Toolbar sx={{ p: "15px" }}>
  170. <ToolsContainer>
  171. <LogoContainer onClick={() => handleLogoClick()}>
  172. <LogoHorizontal />
  173. </LogoContainer>
  174. {!history.location.pathname.includes("messages") &&
  175. !history.location.pathname.includes("profiles") ? (
  176. <SearchInput
  177. ref={searchRef}
  178. handleSearch={handleSearch}
  179. user={user}
  180. />
  181. ) : (
  182. <></>
  183. )}
  184. {(routeMatches(ABOUT_PAGE) ||
  185. (!user &&
  186. (routeMatches(HOME_PAGE) || routeMatches(BASE_PAGE)))) && (
  187. <AboutHeader />
  188. )}
  189. {user ? (
  190. <ToolsButtonsContainer
  191. mobile={matches}
  192. shrink={routeMatches(ABOUT_PAGE)}
  193. >
  194. {matches ? (
  195. <OpenDrawerButton
  196. onClick={drawerRef.current?.handleToggleDrawer}
  197. />
  198. ) : (
  199. <React.Fragment>
  200. {!routeMatches(ABOUT_PAGE) && (
  201. <>
  202. <AddOfferButton onClick={handleAddOfferClick} />
  203. <MySwapsButton
  204. handleAddOfferClick={handleAddOfferClick}
  205. />
  206. <MyMessagesButton badge={badge} setBadge={setBadge} />
  207. </>
  208. )}
  209. <UserButton name={name} />
  210. </React.Fragment>
  211. )}
  212. </ToolsButtonsContainer>
  213. ) : (
  214. <AuthButtonsContainer mobile={matches}>
  215. {matches ? (
  216. <OpenDrawerButton
  217. onClick={drawerRef.current?.handleToggleDrawer}
  218. />
  219. ) : (
  220. <React.Fragment>
  221. {routeMatches(ABOUT_PAGE) ||
  222. routeMatches(HOME_PAGE) ||
  223. routeMatches(BASE_PAGE) ? (
  224. <MarketplaceLinkRouteContainer>
  225. <MarketplaceLinkRoute onClick={() => handleLogoClick()}>
  226. {t("admin.navigation.marketplace")}
  227. </MarketplaceLinkRoute>
  228. <Marketplace />
  229. </MarketplaceLinkRouteContainer>
  230. ) : (
  231. <>
  232. <LoginButton />
  233. <RegisterButton />
  234. </>
  235. )}
  236. </React.Fragment>
  237. )}
  238. </AuthButtonsContainer>
  239. )}
  240. </ToolsContainer>
  241. </Toolbar>
  242. </AppBar>
  243. <DrawerContainer ref={drawerRef} />
  244. </HeaderContainer>
  245. );
  246. };
  247. Header.propTypes = {
  248. isGrid: PropTypes.bool,
  249. showModalHandler: PropTypes.func,
  250. manualSearch: PropTypes.func,
  251. };
  252. export default Header;