| ADMIN_HOME_PAGE, | ADMIN_HOME_PAGE, | ||||
| ADMIN_USERS_PAGE, | ADMIN_USERS_PAGE, | ||||
| ADMIN_CATEGORIES_PAGE, | ADMIN_CATEGORIES_PAGE, | ||||
| ADMIN_SUBCATEGORIES_PAGE, | |||||
| // POLICY_PRIVACY_PAGE, | // POLICY_PRIVACY_PAGE, | ||||
| } from "./constants/pages"; | } from "./constants/pages"; | ||||
| import LoginPage from "./pages/LoginPage/LoginPage"; | import LoginPage from "./pages/LoginPage/LoginPage"; | ||||
| import AdminHomePage from "./pages/AdminHomePage/AdminHomePage"; | import AdminHomePage from "./pages/AdminHomePage/AdminHomePage"; | ||||
| import AdminUsersPage from "./pages/AdminUsersPage/AdminUsersPage"; | import AdminUsersPage from "./pages/AdminUsersPage/AdminUsersPage"; | ||||
| import AdminCategoriesPage from "./pages/AdminCategoriesPage/AdminCategoriesPage"; | import AdminCategoriesPage from "./pages/AdminCategoriesPage/AdminCategoriesPage"; | ||||
| import AdminSubcategoriesPage from "./pages/AdminSubcategoriesPage/AdminSubcategoriesPage"; | |||||
| // import PrivacyPolicyPage from "./pages/PrivacyPolicy/PrivacyPolicyPage"; | // import PrivacyPolicyPage from "./pages/PrivacyPolicy/PrivacyPolicyPage"; | ||||
| const AppRoutes = () => { | const AppRoutes = () => { | ||||
| <AuthRoute exact path={ADMIN_LOGIN_PAGE} component={AdminLoginPage} /> | <AuthRoute exact path={ADMIN_LOGIN_PAGE} component={AdminLoginPage} /> | ||||
| <Route path={ADMIN_HOME_PAGE} component={AdminHomePage} /> | <Route path={ADMIN_HOME_PAGE} component={AdminHomePage} /> | ||||
| <Route path={ADMIN_USERS_PAGE} component={AdminUsersPage} /> | <Route path={ADMIN_USERS_PAGE} component={AdminUsersPage} /> | ||||
| <Route path={ADMIN_CATEGORIES_PAGE} component={AdminCategoriesPage} /> | |||||
| <Route | |||||
| path={ADMIN_SUBCATEGORIES_PAGE} | |||||
| component={AdminSubcategoriesPage} | |||||
| /> | |||||
| <Route | |||||
| exact | |||||
| path={ADMIN_CATEGORIES_PAGE} | |||||
| component={AdminCategoriesPage} | |||||
| /> | |||||
| <Route path={NOT_FOUND_PAGE} component={NotFoundPage} /> | <Route path={NOT_FOUND_PAGE} component={NotFoundPage} /> | ||||
| <Route path={ERROR_PAGE} component={ErrorPage} /> | <Route path={ERROR_PAGE} component={ErrorPage} /> | ||||
| <AuthRoute | <AuthRoute |
| import CategoryEditButton from "./CategoryEditButton/CategoryEditButton"; | import CategoryEditButton from "./CategoryEditButton/CategoryEditButton"; | ||||
| import CategoryRemoveButton from "./CategoryRemoveButton/CategoryRemoveButton"; | import CategoryRemoveButton from "./CategoryRemoveButton/CategoryRemoveButton"; | ||||
| import { useTranslation } from "react-i18next"; | import { useTranslation } from "react-i18next"; | ||||
| import { useState } from "react"; | |||||
| import DeleteCategory from "../../Modals/DeleteCategory/DeleteCategory"; | |||||
| const CategoryCard = (props) => { | const CategoryCard = (props) => { | ||||
| const { t } = useTranslation(); | const { t } = useTranslation(); | ||||
| const [openedDeleteModal, setOpenedDeleteModal] = useState(false); | |||||
| return ( | return ( | ||||
| <CategoryCardContainer> | |||||
| <CategoryCardLeftContainer> | |||||
| <CategoryCardName categoryName={props?.category?.name} /> | |||||
| <CategoryCardDetailsContainer> | |||||
| <CategoryDetail | |||||
| label={t("admin.categories.noOfOffers")} | |||||
| value={props?.category?.offerCount} | |||||
| /> | |||||
| {!props.hideSecondLabel && ( | |||||
| <> | |||||
| <CategoryCardContainer className={props.className}> | |||||
| <CategoryCardLeftContainer> | |||||
| <CategoryCardName categoryName={props?.category?.name} /> | |||||
| <CategoryCardDetailsContainer> | |||||
| <CategoryDetail | <CategoryDetail | ||||
| label={props?.secondLabel} | |||||
| value={props?.category?.subcategories?.length} | |||||
| label={t("admin.categories.noOfOffers")} | |||||
| value={props?.category?.offerCount} | |||||
| /> | /> | ||||
| )} | |||||
| </CategoryCardDetailsContainer> | |||||
| </CategoryCardLeftContainer> | |||||
| <CategoryCardRightContainer> | |||||
| <CategoryRemoveButton /> | |||||
| <CategoryEditButton /> | |||||
| {!props.hideCheckButton && <CategoryCheckButton />} | |||||
| </CategoryCardRightContainer> | |||||
| </CategoryCardContainer> | |||||
| {!props.hideSecondLabel && ( | |||||
| <CategoryDetail | |||||
| label={props?.secondLabel} | |||||
| value={props?.category?.subcategories?.length} | |||||
| /> | |||||
| )} | |||||
| </CategoryCardDetailsContainer> | |||||
| </CategoryCardLeftContainer> | |||||
| <CategoryCardRightContainer> | |||||
| <CategoryRemoveButton onClick={() => setOpenedDeleteModal(true)} /> | |||||
| <CategoryEditButton /> | |||||
| {!props.hideCheckButton && <CategoryCheckButton />} | |||||
| </CategoryCardRightContainer> | |||||
| </CategoryCardContainer> | |||||
| {openedDeleteModal && ( | |||||
| <DeleteCategory | |||||
| setOpenedDeleteModal={setOpenedDeleteModal} | |||||
| category={props.category} | |||||
| /> | |||||
| )} | |||||
| </> | |||||
| ); | ); | ||||
| }; | }; | ||||
| hideCheckButton: PropTypes.bool, | hideCheckButton: PropTypes.bool, | ||||
| secondLabel: PropTypes.string, | secondLabel: PropTypes.string, | ||||
| hideSecondLabel: PropTypes.bool, | hideSecondLabel: PropTypes.bool, | ||||
| className: PropTypes.string, | |||||
| }; | }; | ||||
| export default CategoryCard; | export default CategoryCard; |
| RemoveIcon, | RemoveIcon, | ||||
| } from "./CategoryRemoveButton.styled"; | } from "./CategoryRemoveButton.styled"; | ||||
| const CategoryRemoveButton = () => { | |||||
| const CategoryRemoveButton = (props) => { | |||||
| return ( | return ( | ||||
| <CategoryRemoveButtonContainer> | |||||
| <CategoryRemoveButtonContainer onClick={props.onClick}> | |||||
| <RemoveIcon /> | <RemoveIcon /> | ||||
| </CategoryRemoveButtonContainer> | </CategoryRemoveButtonContainer> | ||||
| ); | ); | ||||
| CategoryRemoveButton.propTypes = { | CategoryRemoveButton.propTypes = { | ||||
| category: PropTypes.any, | category: PropTypes.any, | ||||
| onClick: PropTypes.func, | |||||
| }; | }; | ||||
| export default CategoryRemoveButton; | export default CategoryRemoveButton; |
| import React from "react"; | |||||
| import PropTypes from "prop-types"; | |||||
| import { | |||||
| LabeledCardContainer, | |||||
| LabeledCardIconContainer, | |||||
| } from "./LabeledCard.styled"; | |||||
| const LabeledCard = (props) => { | |||||
| return ( | |||||
| <LabeledCardContainer> | |||||
| <LabeledCardIconContainer width={props.width} height={props.height}> | |||||
| {props.icon} | |||||
| </LabeledCardIconContainer> | |||||
| {props.children} | |||||
| </LabeledCardContainer> | |||||
| ); | |||||
| }; | |||||
| LabeledCard.propTypes = { | |||||
| children: PropTypes.node, | |||||
| icon: PropTypes.node, | |||||
| width: PropTypes.string, | |||||
| height: PropTypes.string, | |||||
| }; | |||||
| export default LabeledCard; |
| import { Box, styled } from "@mui/material"; | |||||
| import selectedTheme from "../../../themes"; | |||||
| export const LabeledCardContainer = styled(Box)` | |||||
| background: ${selectedTheme.colors.chatHeaderColor}; | |||||
| border-radius: 2px; | |||||
| border: 1px solid ${selectedTheme.colors.borderNormal}; | |||||
| position: relative; | |||||
| width: ${(props) => props.width || `min-content`}; | |||||
| height: ${(props) => props.height || `57px`}; | |||||
| padding: 18px; | |||||
| `; | |||||
| export const LabeledCardIconContainer = styled(Box)` | |||||
| width: 40px; | |||||
| height: 40px; | |||||
| background: ${selectedTheme.colors.primaryPurple}; | |||||
| position: absolute; | |||||
| top: -20px; | |||||
| right: -20px; | |||||
| border-radius: 100%; | |||||
| `; |
| // Dont show header on auth routes(login, register, etc.) and admin routes | // Dont show header on auth routes(login, register, etc.) and admin routes | ||||
| useEffect(() => { | useEffect(() => { | ||||
| if (isAuthRoute() || (isAdminRoute && !isMobile)) setShouldShow(false); | |||||
| if (isAuthRoute() || (isAdminRoute() && !isMobile)) setShouldShow(false); | |||||
| else setShouldShow(true); | else setShouldShow(true); | ||||
| }, [routeMatch, isMobile]); | }, [routeMatch, isMobile]); | ||||
| IconStyled, | IconStyled, | ||||
| PageTitleContainer, | PageTitleContainer, | ||||
| SelectOption, | SelectOption, | ||||
| SubcategoryIcon, | |||||
| SwapsHeaderIcon, | SwapsHeaderIcon, | ||||
| SwapsIcon, | SwapsIcon, | ||||
| SwapsTitle, | SwapsTitle, | ||||
| <HeaderTitleContainer> | <HeaderTitleContainer> | ||||
| {props.users ? ( | {props.users ? ( | ||||
| <UserIcon /> | <UserIcon /> | ||||
| ) : props.categories ? ( | |||||
| ) : props.categories || props.category ? ( | |||||
| <CategoryIcon /> | <CategoryIcon /> | ||||
| ) : props.subcategories ? ( | |||||
| <SubcategoryIcon /> | |||||
| ) : ( | ) : ( | ||||
| <SwapsHeaderIcon /> | <SwapsHeaderIcon /> | ||||
| )} | )} | ||||
| ? t("admin.users.headerTitle") | ? t("admin.users.headerTitle") | ||||
| : props.categories | : props.categories | ||||
| ? t("admin.categories.headerTitle") | ? t("admin.categories.headerTitle") | ||||
| : props.subcategories | |||||
| ? t("admin.subcategories.subcategoriesHeaderTitle") | |||||
| : props.category | |||||
| ? t("admin.subcategories.headerTitle") | |||||
| : t("header.myOffers")} | : t("header.myOffers")} | ||||
| </HeaderTitleText> | </HeaderTitleText> | ||||
| </HeaderTitleContainer> | </HeaderTitleContainer> | ||||
| )} | )} | ||||
| {/* Select option to choose sorting */} | {/* Select option to choose sorting */} | ||||
| <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(sortEnum).map((property) => { | |||||
| if (sortEnum[property].value === 0) return; | |||||
| return ( | |||||
| <SelectOption | |||||
| value={sortEnum[property]} | |||||
| key={sortEnum[property].value} | |||||
| > | |||||
| {sortEnum[property].mainText} | |||||
| </SelectOption> | |||||
| ); | |||||
| })} | |||||
| </HeaderSelect> | |||||
| {!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(sortEnum).map((property) => { | |||||
| if (sortEnum[property].value === 0) return; | |||||
| return ( | |||||
| <SelectOption | |||||
| value={sortEnum[property]} | |||||
| key={sortEnum[property].value} | |||||
| > | |||||
| {sortEnum[property].mainText} | |||||
| </SelectOption> | |||||
| ); | |||||
| })} | |||||
| </HeaderSelect> | |||||
| )} | |||||
| {/* ^^^^^^ */} | {/* ^^^^^^ */} | ||||
| </HeaderOptions> | </HeaderOptions> | ||||
| </HeaderContainer> | </HeaderContainer> | ||||
| <PageTitleContainer> | <PageTitleContainer> | ||||
| {props.users ? ( | {props.users ? ( | ||||
| <UserIcon /> | <UserIcon /> | ||||
| ) : props.categories ? ( | |||||
| ) : props.categories || props.category ? ( | |||||
| <CategoryIcon /> | <CategoryIcon /> | ||||
| ) : props.subcategories ? ( | |||||
| <SubcategoryIcon /> | |||||
| ) : ( | ) : ( | ||||
| <SwapsIcon /> | <SwapsIcon /> | ||||
| )} | )} | ||||
| ? t("admin.users.headerTitle") | ? t("admin.users.headerTitle") | ||||
| : props.categories | : props.categories | ||||
| ? t("admin.categories.headerTitle") | ? t("admin.categories.headerTitle") | ||||
| : props.subcategories | |||||
| ? t("admin.subcategories.subcategoriesHeaderTitle") | |||||
| : props.category | |||||
| ? t("admin.subcategories.headerTitle") | |||||
| : props?.myOffers | : props?.myOffers | ||||
| ? t("header.myOffers") | ? t("header.myOffers") | ||||
| : t("offer.offers")} | : t("offer.offers")} | ||||
| hideGrid: PropTypes.bool, | hideGrid: PropTypes.bool, | ||||
| className: PropTypes.string, | className: PropTypes.string, | ||||
| hideBackButton: PropTypes.bool, | hideBackButton: PropTypes.bool, | ||||
| category: PropTypes.bool, | |||||
| subcategories: PropTypes.bool, | |||||
| hideSorting: PropTypes.bool, | |||||
| }; | }; | ||||
| Header.defaultProps = { | Header.defaultProps = { | ||||
| isGrid: false, | isGrid: false, |
| import { ReactComponent as CategoryHeader } from "../../../assets/images/svg/category-header.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 User } from "../../../assets/images/svg/user.svg"; | ||||
| import { ReactComponent as Category } from "../../../assets/images/svg/category.svg"; | import { ReactComponent as Category } from "../../../assets/images/svg/category.svg"; | ||||
| import { ReactComponent as Subcategory } from "../../../assets/images/svg/subcategory.svg"; | |||||
| export const HeaderWrapperContainer = styled(Box)` | export const HeaderWrapperContainer = styled(Box)` | ||||
| display: ${(props) => (props.skeleton ? "none" : "block")}; | display: ${(props) => (props.skeleton ? "none" : "block")}; | ||||
| top: 4px; | top: 4px; | ||||
| right: 2px; | right: 2px; | ||||
| `; | `; | ||||
| export const SubcategoryIcon = styled(Subcategory)` | |||||
| position: relative; | |||||
| top: 4px; | |||||
| right: 2px; | |||||
| `; | |||||
| export const PageTitleContainer = styled(Box)` | export const PageTitleContainer = styled(Box)` | ||||
| position: relative; | position: relative; | ||||
| left: 6px; | left: 6px; | ||||
| font-size: 16px; | font-size: 16px; | ||||
| position: relative; | position: relative; | ||||
| bottom: 2px; | bottom: 2px; | ||||
| left: 2px; | |||||
| `; | `; | ||||
| export const UserIcon = styled(User)` | export const UserIcon = styled(User)` | ||||
| position: relative; | position: relative; |
| import React from "react"; | |||||
| import PropTypes from "prop-types"; | |||||
| import BackdropComponent from "../../MUI/BackdropComponent"; | |||||
| import { | |||||
| ButtonsContainer, | |||||
| CategoryName, | |||||
| DeleteCategoryContainer, | |||||
| DeleteIcon, | |||||
| ReassuranceText, | |||||
| } from "./DeleteCategory.styled"; | |||||
| import LabeledCard from "../../Cards/LabeledCard/LabeledCard"; | |||||
| import { useTranslation } from "react-i18next"; | |||||
| import { PrimaryButton } from "../../Buttons/PrimaryButton/PrimaryButton"; | |||||
| const DeleteCategory = (props) => { | |||||
| const { t } = useTranslation(); | |||||
| console.log(props.category); | |||||
| const handleCancel = () => { | |||||
| props.setOpenedDeleteModal(false); | |||||
| }; | |||||
| return ( | |||||
| <> | |||||
| <BackdropComponent | |||||
| isLoading | |||||
| handleClose={() => props.setOpenedDeleteModal(false)} | |||||
| position="fixed" | |||||
| /> | |||||
| <DeleteCategoryContainer> | |||||
| <LabeledCard icon={<DeleteIcon />}> | |||||
| <CategoryName>{props.category.name}</CategoryName> | |||||
| </LabeledCard> | |||||
| <ReassuranceText> | |||||
| {t("admin.categories.reassuranceDelete")} | |||||
| </ReassuranceText> | |||||
| <ButtonsContainer> | |||||
| <PrimaryButton | |||||
| onClick={handleCancel} | |||||
| variant="contained" | |||||
| height="49px" | |||||
| width="180px" | |||||
| > | |||||
| {t("admin.categories.cancel")} | |||||
| </PrimaryButton> | |||||
| <PrimaryButton variant="outlined" height="49px" width="180px"> | |||||
| {t("admin.categories.delete")} | |||||
| </PrimaryButton> | |||||
| </ButtonsContainer> | |||||
| </DeleteCategoryContainer> | |||||
| </> | |||||
| ); | |||||
| }; | |||||
| DeleteCategory.propTypes = { | |||||
| setOpenedDeleteModal: PropTypes.func, | |||||
| category: PropTypes.object, | |||||
| }; | |||||
| export default DeleteCategory; |
| import { Box, Typography } from "@mui/material"; | |||||
| import styled from "styled-components"; | |||||
| import { ReactComponent as Delete } from "../../../assets/images/svg/trash.svg"; | |||||
| import selectedTheme from "../../../themes"; | |||||
| export const DeleteCategoryContainer = styled(Box)` | |||||
| width: 537px; | |||||
| height: 274px; | |||||
| position: fixed; | |||||
| z-index: 150; | |||||
| left: calc(50vw - 268px); | |||||
| top: calc(50vh - 137px); | |||||
| padding-top: 36px; | |||||
| padding-bottom: 18px; | |||||
| background: white; | |||||
| & > * { | |||||
| margin-left: auto; | |||||
| margin-right: auto; | |||||
| } | |||||
| `; | |||||
| export const DeleteIcon = styled(Delete)` | |||||
| z-index: 155; | |||||
| position: relative; | |||||
| top: 10px; | |||||
| left: 11px; | |||||
| & path { | |||||
| stroke: ${selectedTheme.colors.iconYellowColor}; | |||||
| } | |||||
| `; | |||||
| export const CategoryName = styled(Typography)` | |||||
| font-family: ${selectedTheme.fonts.textFont}; | |||||
| font-weight: 700; | |||||
| font-size: 16px; | |||||
| white-space: nowrap; | |||||
| line-height: 21px; | |||||
| color: ${selectedTheme.colors.primaryPurple}; | |||||
| `; | |||||
| export const ReassuranceText = styled(Typography)` | |||||
| font-family: ${selectedTheme.fonts.textFont}; | |||||
| width: 312px; | |||||
| font-weight: 700; | |||||
| text-align: center; | |||||
| display: block; | |||||
| font-size: 16px; | |||||
| line-height: 21px; | |||||
| color: ${selectedTheme.colors.messageText}; | |||||
| margin-top: 36px; | |||||
| `; | |||||
| export const ButtonsContainer = styled(Box)` | |||||
| display: flex; | |||||
| justify-content: center; | |||||
| flex-direction: row; | |||||
| gap: 18px; | |||||
| margin: 36px auto; | |||||
| ` |
| export const ADMIN_HOME_PAGE = "/admin/home"; | export const ADMIN_HOME_PAGE = "/admin/home"; | ||||
| export const ADMIN_USERS_PAGE = "/admin/users"; | export const ADMIN_USERS_PAGE = "/admin/users"; | ||||
| export const ADMIN_CATEGORIES_PAGE = "/admin/categories"; | export const ADMIN_CATEGORIES_PAGE = "/admin/categories"; | ||||
| export const ADMIN_SUBCATEGORIES_PAGE = "/admin/categories/:categoryId"; |
| users: { | users: { | ||||
| headerTitle: "Profili korisnika", | headerTitle: "Profili korisnika", | ||||
| searchPlaceholder: "Pretražite korisnike....", | searchPlaceholder: "Pretražite korisnike....", | ||||
| checkProfile: "Pogledaj profil" | |||||
| checkProfile: "Pogledaj profil", | |||||
| }, | }, | ||||
| categories: { | categories: { | ||||
| checkCategory: "Pogledaj podkategorije", | checkCategory: "Pogledaj podkategorije", | ||||
| noOfOffers: "Broj objava: ", | noOfOffers: "Broj objava: ", | ||||
| noOfSubcategories: "Broj potkategorija: ", | noOfSubcategories: "Broj potkategorija: ", | ||||
| headerTitle: "Kategorije", | headerTitle: "Kategorije", | ||||
| placeholder: "Pretražite kategorije..." | |||||
| } | |||||
| placeholder: "Pretražite kategorije...", | |||||
| reassuranceDelete: | |||||
| "Da li ste sigurni da želite da obrišete odabranu kategoriju?", | |||||
| cancel: "Otkaži", | |||||
| delete: "Obriši", | |||||
| }, | |||||
| subcategories: { | |||||
| noOfOffers: "Broj objava: ", | |||||
| headerTitle: "Kategorija", | |||||
| subcategoriesHeaderTitle: "Podkategorije", | |||||
| placeholder: "Pretražite podkategorije...", | |||||
| }, | |||||
| }, | }, | ||||
| }; | }; |
| import React from "react"; | |||||
| import PropTypes from "prop-types"; | |||||
| import { useDispatch, useSelector } from "react-redux"; | |||||
| import { useEffect } from "react"; | |||||
| import { fetchCategories } from "../../store/actions/categories/categoriesActions"; | |||||
| import { selectCategories } from "../../store/selectors/categoriesSelectors"; | |||||
| import { useTranslation } from "react-i18next"; | |||||
| import { | |||||
| AdminSubcategoriesHeader, | |||||
| AdminSubcategoriesPageContainer, | |||||
| AdminSubcategoriesSearchField, | |||||
| SponsoredCategoryCard, | |||||
| } from "./AdminSubcategoriesPage.styled"; | |||||
| import { selectManualSearchString } from "../../store/selectors/filtersSelectors"; | |||||
| import { useMemo } from "react"; | |||||
| import { setManualSearchString } from "../../store/actions/filters/filtersActions"; | |||||
| import { useRouteMatch } from "react-router-dom"; | |||||
| import CategoryCard from "../../components/Cards/CategoryCard/CategoryCard"; | |||||
| const AdminSubcategoriesPage = () => { | |||||
| const { t } = useTranslation(); | |||||
| const dispatch = useDispatch(); | |||||
| const categories = useSelector(selectCategories); | |||||
| const routeMatch = useRouteMatch(); | |||||
| const manualSearchString = useSelector(selectManualSearchString); | |||||
| useEffect(() => { | |||||
| dispatch(fetchCategories()); | |||||
| }, []); | |||||
| const handleSearch = (value) => { | |||||
| console.log(value); | |||||
| dispatch(setManualSearchString(value)); | |||||
| }; | |||||
| const category = useMemo(() => { | |||||
| if (routeMatch.params?.categoryId) { | |||||
| const categoryId = routeMatch.params.categoryId; | |||||
| return categories.find((item) => item._id === categoryId); | |||||
| } | |||||
| return {}; | |||||
| }, [routeMatch, categories]); | |||||
| const subcategories = useMemo(() => { | |||||
| if (category) { | |||||
| if (manualSearchString) | |||||
| return category.subcategories.filter((subcategory) => | |||||
| subcategory.name | |||||
| .toLowerCase() | |||||
| .includes(manualSearchString.toLowerCase()) | |||||
| ); | |||||
| return category.subcategories; | |||||
| } | |||||
| return []; | |||||
| }, [category, manualSearchString]); | |||||
| return ( | |||||
| <> | |||||
| <AdminSubcategoriesPageContainer> | |||||
| <AdminSubcategoriesSearchField | |||||
| isAdmin | |||||
| handleSearch={handleSearch} | |||||
| placeholder={t("admin.subcategories.placeholder")} | |||||
| /> | |||||
| <AdminSubcategoriesHeader | |||||
| hideSorting | |||||
| myOffers | |||||
| category | |||||
| hideGrid | |||||
| isAdmin | |||||
| hideBackButton | |||||
| /> | |||||
| <SponsoredCategoryCard | |||||
| category={category} | |||||
| hideSecondLabel | |||||
| hideCheckButton | |||||
| /> | |||||
| <AdminSubcategoriesHeader | |||||
| hideSorting | |||||
| myOffers | |||||
| subcategories | |||||
| hideGrid | |||||
| isAdmin | |||||
| hideBackButton | |||||
| /> | |||||
| {subcategories.map((category) => ( | |||||
| <CategoryCard | |||||
| key={category._id} | |||||
| category={category} | |||||
| hideSecondLabel | |||||
| hideCheckButton | |||||
| /> | |||||
| ))} | |||||
| </AdminSubcategoriesPageContainer> | |||||
| </> | |||||
| ); | |||||
| }; | |||||
| AdminSubcategoriesPage.propTypes = { | |||||
| children: PropTypes.node, | |||||
| }; | |||||
| export default AdminSubcategoriesPage; |
| import { Box } from "@mui/material"; | |||||
| import styled from "styled-components"; | |||||
| import CategoryCard from "../../components/Cards/CategoryCard/CategoryCard"; | |||||
| import Header from "../../components/MarketPlace/Header/Header"; | |||||
| import SearchField from "../../components/TextFields/SearchField/SearchField"; | |||||
| import selectedTheme from "../../themes"; | |||||
| export const AdminSubcategoriesPageContainer = styled(Box)` | |||||
| padding: 60px; | |||||
| @media (max-width: 600px) { | |||||
| padding: 18px; | |||||
| position: relative; | |||||
| top: 65px; | |||||
| } | |||||
| `; | |||||
| export const AdminSubcategoriesHeader = styled(Header)` | |||||
| /* top: 40px; */ | |||||
| top: 0; | |||||
| @media (max-width: 600px) { | |||||
| top: -10px; | |||||
| margin-top: 18px; | |||||
| & div { | |||||
| margin-top: 10px; | |||||
| } | |||||
| & div div:nth-child(1) { | |||||
| top: 22px; | |||||
| } | |||||
| } | |||||
| `; | |||||
| export const AdminSubcategoriesSearchField = styled(SearchField)` | |||||
| top: -15px; | |||||
| @media (max-width: 600px) { | |||||
| display: none; | |||||
| } | |||||
| `; | |||||
| export const SponsoredCategoryCard = styled(CategoryCard)` | |||||
| background: ${selectedTheme.colors.backgroundSponsoredColor}; | |||||
| border: 1px solid ${selectedTheme.colors.borderSponsoredColor}; | |||||
| `; |
| ADMIN_CATEGORIES_PAGE, | ADMIN_CATEGORIES_PAGE, | ||||
| ADMIN_HOME_PAGE, | ADMIN_HOME_PAGE, | ||||
| ADMIN_LOGIN_PAGE, | ADMIN_LOGIN_PAGE, | ||||
| ADMIN_SUBCATEGORIES_PAGE, | |||||
| ADMIN_USERS_PAGE, | ADMIN_USERS_PAGE, | ||||
| FORGOT_PASSWORD_MAIL_SENT, | FORGOT_PASSWORD_MAIL_SENT, | ||||
| FORGOT_PASSWORD_PAGE, | FORGOT_PASSWORD_PAGE, | ||||
| routeMatches(ADMIN_LOGIN_PAGE) || | routeMatches(ADMIN_LOGIN_PAGE) || | ||||
| routeMatches(ADMIN_HOME_PAGE) || | routeMatches(ADMIN_HOME_PAGE) || | ||||
| routeMatches(ADMIN_USERS_PAGE) || | routeMatches(ADMIN_USERS_PAGE) || | ||||
| routeMatches(ADMIN_CATEGORIES_PAGE) | |||||
| routeMatches(ADMIN_CATEGORIES_PAGE) || | |||||
| dynamicRouteMatches(ADMIN_SUBCATEGORIES_PAGE) | |||||
| ) | ) | ||||
| return true; | return true; | ||||
| return false; | return false; |