| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470 |
- import React, { useState, useMemo, useEffect, useRef } from "react";
- import {
- AddOfferButton,
- AuthButtonsContainer,
- AuthButtonsDrawerContainer,
- DrawerContainer,
- EndIcon,
- FilterContainer,
- FilterIcon,
- HeaderContainer,
- LoginButton,
- LogoContainer,
- RegisterButton,
- SearchIcon,
- SearchInput,
- SearchInputMobile,
- ToggleDrawerButton,
- ToolsButtonsContainer,
- ToolsContainer,
- UserButton,
- UserName,
- } from "./Header.styled";
- import PropTypes from "prop-types";
- import {
- AppBar,
- Badge,
- Toolbar,
- useMediaQuery,
- Typography,
- } from "@mui/material";
- import { useTheme } from "@mui/system";
- import MenuOutlinedIcon from "@mui/icons-material/MenuOutlined";
- import MailIcon from "@mui/icons-material/EmailOutlined";
- import Autorenew from "@mui/icons-material/Autorenew";
- import AccountCircle from "@mui/icons-material/PersonOutlineOutlined";
- import Drawer from "../MUI/DrawerComponent";
- import { PrimaryButton } from "../Buttons/PrimaryButton/PrimaryButton";
- import PopoverComponent from "../Popovers/PopoverComponent";
- import { MyPosts } from "../Popovers/MyPosts/MyPosts";
- import { MyMessages } from "../Popovers/MyMessages/MyMessages";
- import { MyProfile } from "../Popovers/MyProfile/MyProfile";
- import { ReactComponent as LogoHorizontal } from "../../assets/images/svg/logo-horizontal.svg";
- import selectedTheme from "../../themes";
- import { useTranslation } from "react-i18next";
- import { IconButton } from "../Buttons/IconButton/IconButton";
- import { useDispatch, useSelector } from "react-redux";
- import { selectUserId } from "../../store/selectors/loginSelectors";
- import { useSearch } from "../../hooks/useSearch";
- import { selectProfileName } from "../../store/selectors/profileSelectors";
- import { useHistory, useRouteMatch } from "react-router-dom";
- import { HOME_PAGE, LOGIN_PAGE, REGISTER_PAGE } from "../../constants/pages";
- import useFilters from "../../hooks/useFilters";
- import FilterCard from "../Cards/FilterCard/FilterCard";
- import { useQueryString } from "../../hooks/useQueryString";
- import { convertQueryStringFrontend } from "../../util/helpers/queryHelpers";
- import { fetchMineProfile } from "../../store/actions/profile/profileActions";
-
- const Header = () => {
- const [openDrawer, setOpenDrawer] = useState(false);
- const [openFilters, setOpenFilters] = useState(false);
- const [showSearchBar, setShowSearchBar] = useState(true);
- const [numberOfFilters, setNumberOfFilters] = useState(0);
- const { t } = useTranslation();
- const theme = useTheme();
- const searchRef = useRef(null);
- const matches = useMediaQuery(theme.breakpoints.down("md"));
- const user = useSelector(selectUserId);
- const search = useSearch();
- const dispatch = useDispatch();
- const name = useSelector(selectProfileName);
- const history = useHistory();
- const routeMatch = useRouteMatch();
- const filters = useFilters();
- const searchMobileRef = useRef(null);
- const queryStringHook = useQueryString();
- useEffect(() => {
- dispatch(fetchMineProfile());
- }, []);
- useEffect(() => {
- setUserPopoverOpen(false);
- setUserAnchorEl(null);
- return () => {
- setUserPopoverOpen(false);
- setUserAnchorEl(null);
- };
- }, []);
- useEffect(() => {
- if (history.location.pathname !== "/home") {
- setShowSearchBar(false);
- } else {
- setShowSearchBar(true);
- }
- }, [history.location.pathname])
- useEffect(() => {
- setNumberOfFilters(filters.calculateFiltersChosen());
- }, [
- filters.selectedCategory,
- filters.selectedLocations,
- filters.selectedSubcategory,
- ]);
-
- useEffect(() => {
- if (queryStringHook.loadedFromURL) {
- const queryObject = new URLSearchParams(
- convertQueryStringFrontend(queryStringHook.queryString)
- );
- if (queryObject.has("search")) {
- searchRef.current.value = queryObject.get("search");
- searchMobileRef.current.value = queryObject.get("search");
- }
- }
- });
-
- const [postsPopoverOpen, setPostsPopoverOpen] = useState(false);
- const [postsAnchorEl, setPostsAnchorEl] = useState(null);
-
- const [msgPopoverOpen, setMsgPopoverOpen] = useState(false);
- const [msgAnchorEl, setMsgAnchorEl] = useState(null);
-
- const [userPopoverOpen, setUserPopoverOpen] = useState(false);
- const [userAnchorEl, setUserAnchorEl] = useState(null);
-
- const [shouldShow, setShouldShow] = useState(true);
-
- useEffect(() => {
- let shouldShowHeader = true;
- if (
- location.pathname === "/login" ||
- location.pathname === "/register" ||
- location.pathname === "/register/success" ||
- location.pathname === "/forgot-password" ||
- location.pathname === "/reset-password" ||
- location.pathname === "/"
- ) {
- shouldShowHeader = false;
- }
- if (location.pathname === "/" && user?.length === 0) {
- shouldShowHeader = false;
- }
- setShouldShow(shouldShowHeader);
- }, [location.pathname, user, routeMatch]);
-
- const handleToggleDrawer = () => {
- setOpenDrawer(!openDrawer);
- };
- const handleNavigateLogin = () => {
- setShouldShow(false);
- history.push(LOGIN_PAGE);
- };
- const handleNavigateRegister = () => {
- setShouldShow(false);
- history.push(REGISTER_PAGE);
- };
- const drawerContent = useMemo(
- () => (
- <DrawerContainer>
- {user ? (
- <React.Fragment>
- <PrimaryButton
- type="submit"
- variant="contained"
- height="36px"
- fullWidth
- buttoncolor={selectedTheme.primaryYellow}
- textcolor="black"
- onClick={() => handleToggleDrawer()}
- >
- {t("header.addOffer")}
- </PrimaryButton>
- <ToolsContainer mobile>
- <IconButton
- onClick={(e) => {
- setPostsPopoverOpen(true);
- setPostsAnchorEl(e.currentTarget);
- }}
- sx={{ borderRadius: "4px" }}
- >
- <Autorenew />
- <Typography sx={{ ml: 2 }}>Moje objave</Typography>
- </IconButton>
- <IconButton
- onClick={(e) => {
- setMsgPopoverOpen(true);
- setMsgAnchorEl(e.currentTarget);
- }}
- sx={{ borderRadius: "4px" }}
- >
- <Badge badgeContent={3} color="primary">
- <MailIcon color="action" />
- </Badge>
- <Typography sx={{ ml: 2 }}>Moje poruke</Typography>
- </IconButton>
- <IconButton
- onClick={(e) => {
- setUserPopoverOpen(true);
- setUserAnchorEl(e.currentTarget);
- }}
- sx={{ borderRadius: "4px" }}
- >
- <AccountCircle />
- <Typography sx={{ ml: 2 }}>Moj profil</Typography>
- </IconButton>
- </ToolsContainer>
- </React.Fragment>
- ) : (
- <AuthButtonsDrawerContainer>
- <RegisterButton
- type="submit"
- variant="contained"
- height="36px"
- fullWidth
- buttoncolor={selectedTheme.primaryYellow}
- textcolor={selectedTheme.primaryDarkText}
- onClick={handleNavigateRegister}
- >
- {t("register.headerTitle")}
- </RegisterButton>
- <LoginButton
- type="submit"
- variant="contained"
- height="36px"
- fullWidth
- buttoncolor={selectedTheme.primaryPurple}
- textcolor={selectedTheme.primaryIconBackgroundColor}
- onClick={handleNavigateLogin}
- >
- {t("login.headerTitle")}
- </LoginButton>
- </AuthButtonsDrawerContainer>
- )}
- </DrawerContainer>
- ),
- [handleToggleDrawer]
- );
-
- let listener;
- const handleFocusSearch = () => {
- listener = (event) => {
- if (event.keyCode === 13) {
- event.preventDefault();
- handleSearch(searchRef.current.value);
- }
- };
- searchRef.current.addEventListener("keyup", listener);
- };
- const handleBlurSearch = () => {
- searchRef.current.removeEventListener("keyup", listener);
- };
- const handleSearch = (value) => {
- console.log(value);
- if (value.length === 0) return;
- search.searchOffers(value);
- };
- const toggleFilters = () => {
- setOpenFilters((prevState) => !prevState);
- };
-
- const handleLogoClick = () => {
- history.push(HOME_PAGE);
- }
-
- return (
- <HeaderContainer style={{ display: shouldShow ? "block" : "none" }}>
- <AppBar
- elevation={0}
- position="fixed"
- // positionFixed
- sx={{ backgroundColor: "white" }}
- >
- <Toolbar>
- <ToolsContainer>
- <LogoContainer onClick={() => handleLogoClick()}>
- <LogoHorizontal />
- </LogoContainer>
- {matches && (
- <Drawer
- open={openDrawer}
- toggleOpen={handleToggleDrawer}
- content={drawerContent}
- />
- )}
- <SearchInput
- fullWidth
- InputProps={{
- endAdornment: (
- <EndIcon size="36px">
- <SearchIcon
- onClick={() => handleSearch(searchRef.current.value)}
- />
- </EndIcon>
- ),
- }}
- placeholder={t("header.searchOffers")}
- onFocus={handleFocusSearch}
- onBlur={handleBlurSearch}
- ref={searchRef}
- />
- {user ? (
- <ToolsButtonsContainer mobile={matches}>
- {matches ? (
- <ToggleDrawerButton>
- <IconButton onClick={handleToggleDrawer}>
- <MenuOutlinedIcon />
- </IconButton>
- </ToggleDrawerButton>
- ) : (
- <React.Fragment>
- <AddOfferButton
- type="submit"
- variant="contained"
- fullWidth
- buttoncolor={selectedTheme.primaryYellow}
- textcolor={selectedTheme.primaryDarkText}
- onClick={() => {
- setUserPopoverOpen(false);
- setUserAnchorEl(null);
- }}
- >
- {t("header.addOffer")}
- </AddOfferButton>
- <IconButton
- onClick={(e) => {
- setPostsPopoverOpen(true);
- setPostsAnchorEl(e.currentTarget);
- }}
- style={{
- background: selectedTheme.primaryIconBackgroundColor,
- color: selectedTheme.primaryPurple,
- }}
- >
- <Autorenew />
- </IconButton>
- <IconButton
- onClick={(e) => {
- setMsgPopoverOpen(true);
- setMsgAnchorEl(e.currentTarget);
- }}
- style={{
- background: selectedTheme.primaryIconBackgroundColor,
- color: selectedTheme.primaryPurple,
- }}
- >
- <Badge badgeContent={3} color="primary">
- <MailIcon />
- </Badge>
- </IconButton>
- <UserButton
- onClick={(e) => {
- setUserPopoverOpen(true);
- setUserAnchorEl(e.currentTarget);
- }}
- >
- <UserName>{name}</UserName>
- <IconButton
- style={{
- background: selectedTheme.primaryIconBackgroundColor,
- color: selectedTheme.primaryPurple,
- }}
- >
- <AccountCircle />
- </IconButton>
- </UserButton>
- </React.Fragment>
- )}
- </ToolsButtonsContainer>
- ) : (
- <AuthButtonsContainer mobile={matches}>
- {matches ? (
- <ToggleDrawerButton>
- <IconButton onClick={handleToggleDrawer}>
- <MenuOutlinedIcon />
- </IconButton>
- </ToggleDrawerButton>
- ) : (
- <React.Fragment>
- <LoginButton
- type="submit"
- variant="contained"
- fullWidth
- buttoncolor={selectedTheme.primaryPurple}
- textcolor={selectedTheme.offerBackgroundColor}
- onClick={handleNavigateLogin}
- >
- {t("login.headerTitle")}
- </LoginButton>
- <RegisterButton
- type="submit"
- variant="contained"
- fullWidth
- buttoncolor={selectedTheme.primaryYellow}
- textcolor={selectedTheme.primaryDarkText}
- onClick={handleNavigateRegister}
- >
- {t("register.headerTitle")}
- </RegisterButton>
- </React.Fragment>
- )}
- </AuthButtonsContainer>
- )}
- </ToolsContainer>
- </Toolbar>
- {user && (
- <React.Fragment>
- <PopoverComponent
- anchorEl={postsAnchorEl}
- open={postsPopoverOpen}
- onClose={() => {
- setPostsPopoverOpen(false);
- setPostsAnchorEl(null);
- }}
- content={<MyPosts />}
- />
- <PopoverComponent
- anchorEl={msgAnchorEl}
- open={msgPopoverOpen}
- onClose={() => {
- setMsgPopoverOpen(false);
- setMsgAnchorEl(null);
- }}
- content={<MyMessages />}
- />
- <PopoverComponent
- anchorEl={userAnchorEl}
- open={userPopoverOpen}
- onClose={() => {
- setUserPopoverOpen(false);
- setUserAnchorEl(null);
- }}
- content={<MyProfile />}
- />
- </React.Fragment>
- )}
- </AppBar>
- <SearchInputMobile
- fullWidth
- shouldShow={showSearchBar}
- ref={searchMobileRef}
- InputProps={{
- endAdornment: (
- <React.Fragment>
- <FilterContainer number={numberOfFilters}>
- <FilterIcon onClick={toggleFilters} />
- </FilterContainer>
- <EndIcon size="36px">
- <SearchIcon
- onClick={() => handleSearch(searchMobileRef.current.value)}
- />
- </EndIcon>
- </React.Fragment>
- ),
- }}
- placeholder={t("header.searchOffers")}
- italicPlaceholder
- onFocus={handleFocusSearch}
- onBlur={handleBlurSearch}
- />
- <FilterCard
- responsive={true}
- responsiveOpen={openFilters}
- closeResponsive={toggleFilters}
- />
- </HeaderContainer>
- );
- };
-
- Header.propTypes = {
- isGrid: PropTypes.bool,
- };
-
- export default Header;
|