選択できるのは25トピックまでです。 トピックは、先頭が英数字で、英数字とダッシュ('-')を使用した35文字以内のものにしてください。

Header.js 5.9KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177
  1. import React, { useState, useEffect, useRef } from "react";
  2. import {
  3. AuthButtonsContainer,
  4. HeaderContainer,
  5. LogoContainer,
  6. ToolsButtonsContainer,
  7. ToolsContainer,
  8. } from "./Header.styled";
  9. import PropTypes from "prop-types";
  10. import { AppBar, Toolbar, useMediaQuery } from "@mui/material";
  11. import { useTheme } from "@mui/system";
  12. import { ReactComponent as LogoHorizontal } from "../../assets/images/svg/logo-horizontal.svg";
  13. import { useDispatch, useSelector } from "react-redux";
  14. import { selectUserId } from "../../store/selectors/loginSelectors";
  15. import { selectProfileName } from "../../store/selectors/profileSelectors";
  16. import { useHistory, useRouteMatch } from "react-router-dom";
  17. import { ABOUT_PAGE, BASE_PAGE, HOME_PAGE } from "../../constants/pages";
  18. import { fetchMineProfile } from "../../store/actions/profile/profileActions";
  19. import CreateOffer from "../Cards/CreateOfferCard/CreateOffer";
  20. import useSearch from "../../hooks/useOffers/useSearch";
  21. import { isAuthRoute, routeMatches } from "../../util/helpers/routeHelpers";
  22. import AboutHeader from "./AboutHeader/AboutHeader";
  23. import SearchInput from "./SearchInput/SearchInput";
  24. import DrawerContainer from "./DrawerContainer/DrawerContainer";
  25. import OpenDrawerButton from "./OpenDrawerButton/OpenDrawerButton";
  26. import AddOfferButton from "./AddOfferButton/AddOfferButton";
  27. import MySwapsButton from "./MySwapsButton/MySwapsButton";
  28. import MyMessagesButton from "./MyMessagesButton/MyMessagesButton";
  29. import UserButton from "./UserButton/UserButton";
  30. import LoginButton from "./LoginButton/LoginButton";
  31. import RegisterButton from "./RegisterButton/RegisterButton";
  32. const Header = () => {
  33. const [showCreateOfferModal, setShowCreateOfferModal] = useState(false);
  34. const theme = useTheme();
  35. const searchRef = useRef(null);
  36. const matches = useMediaQuery(theme.breakpoints.down("md"));
  37. const user = useSelector(selectUserId);
  38. const search = useSearch(() => {});
  39. const dispatch = useDispatch();
  40. const name = useSelector(selectProfileName);
  41. const history = useHistory();
  42. const drawerRef = useRef(null);
  43. const [shouldShow, setShouldShow] = useState(true);
  44. const routeMatch = useRouteMatch();
  45. // Dont show header on auth routes(login, register, etc.)
  46. useEffect(() => {
  47. if (isAuthRoute()) setShouldShow(false);
  48. else setShouldShow(true);
  49. }, [routeMatch]);
  50. // Fetch mine profile on loading home page
  51. useEffect(() => {
  52. if (user && user?.length > 0) {
  53. dispatch(fetchMineProfile());
  54. }
  55. }, []);
  56. // Sets value into search input based on query string
  57. useEffect(() => {
  58. if (searchRef.current) {
  59. searchRef.current.value = search.searchString ?? "";
  60. }
  61. }, [search.searchString, searchRef.current]);
  62. // Removes scroll when modal is open
  63. if (showCreateOfferModal) {
  64. document.body.style.overflow = "hidden";
  65. } else {
  66. document.body.style.overflow = "auto";
  67. }
  68. // Handling search when user is on marketplace and when he is not
  69. const handleSearch = (value) => {
  70. if (!routeMatches(HOME_PAGE) && !routeMatches(BASE_PAGE)) {
  71. const newQueryString = new URLSearchParams({ search: value });
  72. history.push({
  73. pathname: HOME_PAGE,
  74. search: newQueryString.toString(),
  75. });
  76. } else {
  77. search.searchOffers(value);
  78. }
  79. };
  80. // When user clicks logo, he sends specific state so filters can be removed
  81. const handleLogoClick = () => {
  82. history.push({
  83. pathname: HOME_PAGE,
  84. state: {
  85. logo: true,
  86. },
  87. });
  88. };
  89. const handleAddOfferClick = () => {
  90. setShowCreateOfferModal(true);
  91. };
  92. const closeCreateOfferModal = () => {
  93. setShowCreateOfferModal(false);
  94. };
  95. return (
  96. <HeaderContainer style={{ display: shouldShow ? "block" : "none" }}>
  97. <AppBar
  98. elevation={0}
  99. position="fixed"
  100. sx={{ backgroundColor: "white", zIndex: "80", height: "72px" }}
  101. >
  102. <Toolbar sx={{ p: "15px" }}>
  103. <ToolsContainer>
  104. <LogoContainer onClick={() => handleLogoClick()}>
  105. <LogoHorizontal />
  106. </LogoContainer>
  107. <SearchInput ref={searchRef} handleSearch={handleSearch} />
  108. {routeMatches(ABOUT_PAGE) && <AboutHeader />}
  109. {user ? (
  110. <ToolsButtonsContainer
  111. mobile={matches}
  112. shrink={routeMatches(ABOUT_PAGE)}
  113. >
  114. {matches ? (
  115. <OpenDrawerButton
  116. onClick={drawerRef.current.handleToggleDrawer}
  117. />
  118. ) : (
  119. <React.Fragment>
  120. {!routeMatches(ABOUT_PAGE) && (
  121. <>
  122. <AddOfferButton onClick={handleAddOfferClick} />
  123. <MySwapsButton
  124. handleAddOfferClick={handleAddOfferClick}
  125. />
  126. <MyMessagesButton />
  127. </>
  128. )}
  129. <UserButton name={name} />
  130. </React.Fragment>
  131. )}
  132. </ToolsButtonsContainer>
  133. ) : (
  134. <AuthButtonsContainer mobile={matches}>
  135. {matches ? (
  136. <OpenDrawerButton
  137. onClick={drawerRef.current.handleToggleDrawer}
  138. />
  139. ) : (
  140. <React.Fragment>
  141. <LoginButton />
  142. <RegisterButton />
  143. </React.Fragment>
  144. )}
  145. </AuthButtonsContainer>
  146. )}
  147. </ToolsContainer>
  148. </Toolbar>
  149. </AppBar>
  150. <DrawerContainer
  151. ref={drawerRef}
  152. showCreateOfferModal={setShowCreateOfferModal}
  153. />
  154. {showCreateOfferModal && (
  155. <CreateOffer closeCreateOfferModal={closeCreateOfferModal} />
  156. )}
  157. </HeaderContainer>
  158. );
  159. };
  160. Header.propTypes = {
  161. isGrid: PropTypes.bool,
  162. showModalHandler: PropTypes.func,
  163. };
  164. export default Header;