| ABOUT_PAGE, | ABOUT_PAGE, | ||||
| ADMIN_HOME_PAGE, | ADMIN_HOME_PAGE, | ||||
| ADMIN_USERS_PAGE, | ADMIN_USERS_PAGE, | ||||
| ADMIN_CATEGORIES_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 AuthRoute from "./components/Router/AuthRoute"; | import AuthRoute from "./components/Router/AuthRoute"; | ||||
| 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 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={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 React from "react"; | |||||
| import PropTypes from "prop-types"; | |||||
| import { | |||||
| CategoryCardContainer, | |||||
| CategoryCardLeftContainer, | |||||
| CategoryCardRightContainer, | |||||
| } from "./CategoryCard.styled"; | |||||
| import CategoryCardName from "./CategoryCardName/CategoryCardName"; | |||||
| import CategoryDetail from "./CategoryDetail/CategoryDetail"; | |||||
| import CategoryCheckButton from "./CategoryCheckButton/CategoryCheckButton"; | |||||
| import CategoryEditButton from "./CategoryEditButton/CategoryEditButton"; | |||||
| import CategoryRemoveButton from "./CategoryRemoveButton/CategoryRemoveButton"; | |||||
| import { useTranslation } from "react-i18next"; | |||||
| const CategoryCard = (props) => { | |||||
| const { t } = useTranslation(); | |||||
| return ( | |||||
| <CategoryCardContainer> | |||||
| <CategoryCardLeftContainer> | |||||
| <CategoryCardName categoryName={props?.category?.name} /> | |||||
| <CategoryDetail | |||||
| label={t("admin.categories.noOfOffers")} | |||||
| value={props?.category?.offerCount} | |||||
| /> | |||||
| {!props.hideSecondLabel && ( | |||||
| <CategoryDetail | |||||
| label={props?.secondLabel} | |||||
| value={props?.category?.subcategories?.length} | |||||
| /> | |||||
| )} | |||||
| </CategoryCardLeftContainer> | |||||
| <CategoryCardRightContainer> | |||||
| <CategoryRemoveButton /> | |||||
| <CategoryEditButton /> | |||||
| {!props.hideCheckButton && <CategoryCheckButton />} | |||||
| </CategoryCardRightContainer> | |||||
| </CategoryCardContainer> | |||||
| ); | |||||
| }; | |||||
| CategoryCard.propTypes = { | |||||
| children: PropTypes.node, | |||||
| category: PropTypes.object, | |||||
| hideCheckButton: PropTypes.bool, | |||||
| secondLabel: PropTypes.string, | |||||
| hideSecondLabel: PropTypes.bool, | |||||
| }; | |||||
| export default CategoryCard; |
| import { Box } from "@mui/material"; | |||||
| import styled from "styled-components"; | |||||
| export const CategoryCardContainer = styled(Box)` | |||||
| background: white; | |||||
| height: 84px; | |||||
| width: calc(100% - 10px); | |||||
| margin: 5px; | |||||
| margin-top: 13px; | |||||
| margin-bottom: 13px; | |||||
| display: flex; | |||||
| flex-direction: row; | |||||
| justify-content: space-between; | |||||
| `; | |||||
| export const CategoryCardLeftContainer = styled(Box)` | |||||
| display: flex; | |||||
| flex-direction: row; | |||||
| `; | |||||
| export const CategoryCardRightContainer = styled(Box)` | |||||
| display: flex; | |||||
| flex-direction: row; | |||||
| `; |
| import React from "react"; | |||||
| import PropTypes from "prop-types"; | |||||
| import { | |||||
| CategoryCardNameContainer, | |||||
| CategoryCardNameText, | |||||
| } from "./CategoryCardName.styled"; | |||||
| const CategoryCardName = (props) => { | |||||
| return ( | |||||
| <CategoryCardNameContainer> | |||||
| <CategoryCardNameText>{props.categoryName}</CategoryCardNameText> | |||||
| </CategoryCardNameContainer> | |||||
| ); | |||||
| }; | |||||
| CategoryCardName.propTypes = { | |||||
| children: PropTypes.node, | |||||
| categoryName: PropTypes.string, | |||||
| }; | |||||
| export default CategoryCardName; |
| import { Box, Typography } from "@mui/material"; | |||||
| import styled from "styled-components"; | |||||
| import selectedTheme from "../../../../themes"; | |||||
| export const CategoryCardNameContainer = styled(Box)` | |||||
| padding: 18px; | |||||
| min-width: 234px; | |||||
| `; | |||||
| export const CategoryCardNameText = styled(Typography)` | |||||
| font-family: ${selectedTheme.fonts.textFont}; | |||||
| font-weight: 700; | |||||
| font-size: 16px; | |||||
| line-height: 21px; | |||||
| padding-top: 12px; | |||||
| color: ${selectedTheme.colors.primaryPurple}; | |||||
| cursor: pointer; | |||||
| `; |
| import React from "react"; | |||||
| import PropTypes from "prop-types"; | |||||
| import selectedTheme from "../../../../themes"; | |||||
| import { CheckButton } from "./CategoryCheckButton.styled"; | |||||
| import { useTranslation } from "react-i18next"; | |||||
| const CategoryCheckButton = () => { | |||||
| const { t } = useTranslation(); | |||||
| return ( | |||||
| <CheckButton | |||||
| variant={"outlined"} | |||||
| buttoncolor={selectedTheme.colors.primaryPurple} | |||||
| textcolor={selectedTheme.colors.primaryPurple} | |||||
| style={{ fontWeight: "600" }} | |||||
| > | |||||
| {t("admin.categories.checkCategory")} | |||||
| </CheckButton> | |||||
| ); | |||||
| }; | |||||
| CategoryCheckButton.propTypes = { | |||||
| category: PropTypes.any, | |||||
| }; | |||||
| export default CategoryCheckButton; |
| import styled from "styled-components"; | |||||
| import selectedTheme from "../../../../themes"; | |||||
| import { PrimaryButton } from "../../../Buttons/PrimaryButton/PrimaryButton"; | |||||
| export const CheckButton = styled(PrimaryButton)` | |||||
| width: 224px; | |||||
| height: 48px; | |||||
| margin-top: 9px; | |||||
| margin-right: 9px; | |||||
| & button:hover { | |||||
| background-color: ${selectedTheme.colors.primaryPurple} !important; | |||||
| color: white !important; | |||||
| } | |||||
| @media (max-width: 850px) { | |||||
| display: none; | |||||
| } | |||||
| `; |
| import React from "react"; | |||||
| import PropTypes from "prop-types"; | |||||
| import { | |||||
| CategoryDetailContainer, | |||||
| CategoryDetailLabel, | |||||
| CategoryDetailValue, | |||||
| } from "./CategoryDetail.styled"; | |||||
| const CategoryDetail = (props) => { | |||||
| return ( | |||||
| <CategoryDetailContainer> | |||||
| <CategoryDetailLabel>{props.label}</CategoryDetailLabel> | |||||
| <CategoryDetailValue>{props.value}</CategoryDetailValue> | |||||
| </CategoryDetailContainer> | |||||
| ); | |||||
| }; | |||||
| CategoryDetail.propTypes = { | |||||
| label: PropTypes.string, | |||||
| value: PropTypes.string, | |||||
| }; | |||||
| export default CategoryDetail; |
| import { Box, Typography } from "@mui/material"; | |||||
| import styled from "styled-components"; | |||||
| import selectedTheme from "../../../../themes"; | |||||
| import { hexToRGB } from "../../../../util/helpers/colorHelper"; | |||||
| export const CategoryDetailContainer = styled(Box)` | |||||
| /* display: flex; | |||||
| flex-direction: row; */ | |||||
| margin-top: 20px; | |||||
| margin-bottom: 20px; | |||||
| min-width: 150px; | |||||
| text-align: center; | |||||
| border-left: 1px solid ${hexToRGB(selectedTheme.colors.primaryText, 0.13)}; | |||||
| `; | |||||
| export const CategoryDetailLabel = styled(Typography)` | |||||
| font-family: ${selectedTheme.fonts.textFont}; | |||||
| color: ${selectedTheme.colors.primaryText}; | |||||
| font-size: 12px; | |||||
| letter-spacing: 0.01rem; | |||||
| padding-top: 14px; | |||||
| padding-right: 3px; | |||||
| `; | |||||
| export const CategoryDetailValue = styled(Typography)` | |||||
| font-family: ${selectedTheme.fonts.textFont}; | |||||
| font-weight: 700; | |||||
| font-size: 16px; | |||||
| line-height: 21px; | |||||
| padding-top: 11px; | |||||
| color: ${selectedTheme.colors.primaryPurple}; | |||||
| `; |
| import React from "react"; | |||||
| import PropTypes from "prop-types"; | |||||
| import { | |||||
| CategoryEditButtonContainer, | |||||
| EditIcon, | |||||
| } from "./CategoryEditButton.styled"; | |||||
| const CategoryEditButton = () => { | |||||
| return ( | |||||
| <CategoryEditButtonContainer> | |||||
| <EditIcon /> | |||||
| </CategoryEditButtonContainer> | |||||
| ); | |||||
| }; | |||||
| CategoryEditButton.propTypes = { | |||||
| category: PropTypes.any, | |||||
| }; | |||||
| export default CategoryEditButton; |
| import styled from "styled-components"; | |||||
| import selectedTheme from "../../../../themes"; | |||||
| import { IconButton } from "../../../Buttons/IconButton/IconButton"; | |||||
| import { ReactComponent as Edit } from "../../../../assets/images/svg/edit.svg"; | |||||
| export const CategoryEditButtonContainer = styled(IconButton)` | |||||
| width: 40px; | |||||
| height: 40px; | |||||
| background-color: ${selectedTheme.colors.primaryIconBackgroundColor}; | |||||
| border-radius: 100%; | |||||
| position: relative; | |||||
| top: 22px; | |||||
| margin-right: 18px; | |||||
| padding-top: 2px; | |||||
| text-align: center; | |||||
| @media (max-width: 600px) { | |||||
| width: 30px; | |||||
| height: 30px; | |||||
| top: 16px; | |||||
| right: 16px; | |||||
| padding: 0; | |||||
| ${(props) => | |||||
| props.vertical && | |||||
| ` | |||||
| display: none; | |||||
| `} | |||||
| & button svg { | |||||
| width: 16px; | |||||
| height: 16px; | |||||
| position: relative; | |||||
| top: -3px; | |||||
| left: -3.5px; | |||||
| } | |||||
| } | |||||
| `; | |||||
| export const EditIcon = styled(Edit)` | |||||
| ` |
| import React from "react"; | |||||
| import PropTypes from "prop-types"; | |||||
| import { | |||||
| CategoryRemoveButtonContainer, | |||||
| RemoveIcon, | |||||
| } from "./CategoryRemoveButton.styled"; | |||||
| const CategoryRemoveButton = () => { | |||||
| return ( | |||||
| <CategoryRemoveButtonContainer> | |||||
| <RemoveIcon /> | |||||
| </CategoryRemoveButtonContainer> | |||||
| ); | |||||
| }; | |||||
| CategoryRemoveButton.propTypes = { | |||||
| category: PropTypes.any, | |||||
| }; | |||||
| export default CategoryRemoveButton; |
| import styled from "styled-components"; | |||||
| import selectedTheme from "../../../../themes"; | |||||
| import { IconButton } from "../../../Buttons/IconButton/IconButton"; | |||||
| import { ReactComponent as Remove } from "../../../../assets/images/svg/trash.svg"; | |||||
| export const CategoryRemoveButtonContainer = styled(IconButton)` | |||||
| width: 40px; | |||||
| height: 40px; | |||||
| background-color: ${selectedTheme.colors.primaryIconBackgroundColor}; | |||||
| border-radius: 100%; | |||||
| position: relative; | |||||
| top: 22px; | |||||
| margin-right: 18px; | |||||
| padding-top: 2px; | |||||
| text-align: center; | |||||
| @media (max-width: 600px) { | |||||
| width: 30px; | |||||
| height: 30px; | |||||
| top: 16px; | |||||
| right: 16px; | |||||
| padding: 0; | |||||
| ${(props) => | |||||
| props.vertical && | |||||
| ` | |||||
| display: none; | |||||
| `} | |||||
| & button svg { | |||||
| width: 16px; | |||||
| height: 16px; | |||||
| position: relative; | |||||
| top: -3px; | |||||
| left: -3.5px; | |||||
| } | |||||
| } | |||||
| `; | |||||
| export const RemoveIcon = styled(Remove)` | |||||
| ` |
| const blockUser = () => {}; | const blockUser = () => {}; | ||||
| return ( | return ( | ||||
| <> | <> | ||||
| <ProfileCardContainer> | |||||
| <ProfileCardContainer halfwidth={props.halfwidth}> | |||||
| <ProfileCardWrapper variant="outlined"> | <ProfileCardWrapper variant="outlined"> | ||||
| <EditButton onClick={() => setEditProfileModal(true)}> | <EditButton onClick={() => setEditProfileModal(true)}> | ||||
| <EditIcon /> | <EditIcon /> | ||||
| <ProfileContact profile={props.profile} isAdmin /> | <ProfileContact profile={props.profile} isAdmin /> | ||||
| </ProfileInfoContainer> | </ProfileInfoContainer> | ||||
| <CheckButton | <CheckButton | ||||
| halfwidth={props.halfwidth} | |||||
| variant={"outlined"} | variant={"outlined"} | ||||
| buttoncolor={selectedTheme.colors.primaryPurple} | buttoncolor={selectedTheme.colors.primaryPurple} | ||||
| textcolor={selectedTheme.colors.primaryPurple} | textcolor={selectedTheme.colors.primaryPurple} | ||||
| BigProfileCard.propTypes = { | BigProfileCard.propTypes = { | ||||
| profile: PropTypes.any, | profile: PropTypes.any, | ||||
| halfwidth: PropTypes.bool, | |||||
| }; | }; | ||||
| export default BigProfileCard; | export default BigProfileCard; |
| // import { ReactComponent as Location } from "../../../assets/images/svg/location.svg"; | // import { ReactComponent as Location } from "../../../assets/images/svg/location.svg"; | ||||
| export const ProfileCardContainer = styled(Box)` | export const ProfileCardContainer = styled(Box)` | ||||
| width: 100%; | |||||
| width: ${(props) => (props.halfwidth ? `49%` : `100%`)}; | |||||
| box-sizing: border-box; | box-sizing: border-box; | ||||
| max-height: 184px; | max-height: 184px; | ||||
| margin-top: 34px; | margin-top: 34px; | ||||
| } | } | ||||
| `; | `; | ||||
| export const MessageButton = styled(IconButton)` | export const MessageButton = styled(IconButton)` | ||||
| width: 40px; | width: 40px; | ||||
| height: 40px; | height: 40px; | ||||
| position: absolute; | position: absolute; | ||||
| bottom: 25px; | bottom: 25px; | ||||
| right: 9px; | right: 9px; | ||||
| display: ${(props) => (props.halfwidth ? `none` : `block`)}; | |||||
| & button:hover { | & button:hover { | ||||
| background-color: ${selectedTheme.colors.primaryPurple} !important; | background-color: ${selectedTheme.colors.primaryPurple} !important; | ||||
| color: white !important; | color: white !important; |
| ButtonContainer, | ButtonContainer, | ||||
| // ButtonContainer, | // ButtonContainer, | ||||
| CategoryHeaderIcon, | CategoryHeaderIcon, | ||||
| CategoryIcon, | |||||
| HeaderAltLocation, | HeaderAltLocation, | ||||
| HeaderButton, | HeaderButton, | ||||
| HeaderButtons, | HeaderButtons, | ||||
| <> | <> | ||||
| <SkeletonHeader skeleton={props?.skeleton} myOffers={props?.myOffers} /> | <SkeletonHeader skeleton={props?.skeleton} myOffers={props?.myOffers} /> | ||||
| <HeaderWrapperContainer | <HeaderWrapperContainer | ||||
| className={props.className} | |||||
| skeleton={props?.skeleton} | skeleton={props?.skeleton} | ||||
| isAdmin={props?.isAdmin} | isAdmin={props?.isAdmin} | ||||
| > | > | ||||
| <> | <> | ||||
| {!isMobile ? ( | {!isMobile ? ( | ||||
| <HeaderTitleContainer> | <HeaderTitleContainer> | ||||
| {props.users ? <UserIcon /> : <SwapsHeaderIcon />} | |||||
| {props.users ? ( | |||||
| <UserIcon /> | |||||
| ) : props.categories ? ( | |||||
| <CategoryIcon /> | |||||
| ) : ( | |||||
| <SwapsHeaderIcon /> | |||||
| )} | |||||
| <HeaderTitleText> | <HeaderTitleText> | ||||
| {props.users | {props.users | ||||
| ? t("admin.users.headerTitle") | ? t("admin.users.headerTitle") | ||||
| : props.categories | |||||
| ? t("admin.categories.headerTitle") | |||||
| : t("header.myOffers")} | : t("header.myOffers")} | ||||
| </HeaderTitleText> | </HeaderTitleText> | ||||
| </HeaderTitleContainer> | </HeaderTitleContainer> | ||||
| {/* ^^^^^^ */} | {/* ^^^^^^ */} | ||||
| <HeaderOptions> | <HeaderOptions> | ||||
| <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> | |||||
| {/* ^^^^^^ */} | |||||
| {!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> | |||||
| {/* 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> | |||||
| )} | |||||
| {/* Select option to choose sorting */} | {/* Select option to choose sorting */} | ||||
| <HeaderSelect | <HeaderSelect | ||||
| setIsGrid: PropTypes.func, | setIsGrid: PropTypes.func, | ||||
| isGrid: PropTypes.bool, | isGrid: PropTypes.bool, | ||||
| offers: PropTypes.any, | offers: PropTypes.any, | ||||
| category: PropTypes.string, | |||||
| myOffers: PropTypes.bool, | myOffers: PropTypes.bool, | ||||
| skeleton: PropTypes.bool, | skeleton: PropTypes.bool, | ||||
| sorting: PropTypes.any, | sorting: PropTypes.any, | ||||
| isAdmin: PropTypes.bool, | isAdmin: PropTypes.bool, | ||||
| users: PropTypes.bool, | users: PropTypes.bool, | ||||
| categories: PropTypes.bool, | |||||
| hideGrid: PropTypes.bool, | |||||
| className: PropTypes.string, | |||||
| }; | }; | ||||
| Header.defaultProps = { | Header.defaultProps = { | ||||
| isGrid: false, | isGrid: false, |
| import { ReactComponent as Swaps } from "../../../assets/images/svg/swaps.svg"; | import { ReactComponent as Swaps } from "../../../assets/images/svg/swaps.svg"; | ||||
| 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"; | |||||
| export const HeaderWrapperContainer = styled(Box)` | export const HeaderWrapperContainer = styled(Box)` | ||||
| display: ${(props) => (props.skeleton ? "none" : "block")}; | display: ${(props) => (props.skeleton ? "none" : "block")}; | ||||
| top: 1px; | top: 1px; | ||||
| } | } | ||||
| `; | `; | ||||
| export const CategoryIcon = styled(Category)` | |||||
| position: relative; | |||||
| top: 4px; | |||||
| right: 2px; | |||||
| ` | |||||
| export const PageTitleContainer = styled(Box)` | export const PageTitleContainer = styled(Box)` | ||||
| position: relative; | position: relative; | ||||
| left: 6px; | left: 6px; |
| import { selectUserId } from "../../../store/selectors/loginSelectors"; | import { selectUserId } from "../../../store/selectors/loginSelectors"; | ||||
| import { startChat } from "../../../util/helpers/chatHelper"; | import { startChat } from "../../../util/helpers/chatHelper"; | ||||
| import OffersNotFound from "./OffersNotFound"; | import OffersNotFound from "./OffersNotFound"; | ||||
| import HeadersMyOffers from "./HeaderMyOffers.js/HeadersMyOffers"; | |||||
| // import HeadersMyOffers from "./SearchBar/SearchBar"; | |||||
| import SkeletonOfferCard from "../../Cards/OfferCard/SkeletonOfferCard/SkeletonOfferCard"; | import SkeletonOfferCard from "../../Cards/OfferCard/SkeletonOfferCard/SkeletonOfferCard"; | ||||
| import BigProfileCard from "../../Cards/ProfileCard/BigProfileCard/BigProfileCard"; | import BigProfileCard from "../../Cards/ProfileCard/BigProfileCard/BigProfileCard"; | ||||
| import SearchField from "../../TextFields/SearchField/SearchField"; | |||||
| import { useTranslation } from "react-i18next"; | |||||
| const Offers = (props) => { | const Offers = (props) => { | ||||
| const chats = useSelector(selectLatestChats); | const chats = useSelector(selectLatestChats); | ||||
| const offersRef = useRef(null); | const offersRef = useRef(null); | ||||
| const userId = useSelector(selectUserId); | const userId = useSelector(selectUserId); | ||||
| const { t } = useTranslation(); | |||||
| const offers = props?.offers; | const offers = props?.offers; | ||||
| // For skeleton screen | // For skeleton screen | ||||
| const arrayForMapping = Array.apply(null, Array(4)).map(() => {}); | const arrayForMapping = Array.apply(null, Array(4)).map(() => {}); | ||||
| <FilterIcon /> | <FilterIcon /> | ||||
| </FilterContainer> | </FilterContainer> | ||||
| {(props?.myOffers || props?.isAdmin) && ( | {(props?.myOffers || props?.isAdmin) && ( | ||||
| <HeadersMyOffers | |||||
| // <HeadersMyOffers | |||||
| <SearchField | |||||
| searchMyOffers={offers?.search?.searchOffers} | searchMyOffers={offers?.search?.searchOffers} | ||||
| handleSearch={offers?.apply} | handleSearch={offers?.apply} | ||||
| isAdmin={props?.isAdmin} | isAdmin={props?.isAdmin} | ||||
| offers={offers} | offers={offers} | ||||
| isUsers={props.isUsers} | isUsers={props.isUsers} | ||||
| placeholder={ | |||||
| props.isUsers | |||||
| ? t("admin.users.searchPlaceholder") | |||||
| : t("header.searchOffers") | |||||
| } | |||||
| /> | /> | ||||
| )} | )} | ||||
| {offers?.allOffersToShow?.length === 0 ? ( | {offers?.allOffersToShow?.length === 0 ? ( | ||||
| <OffersContainer ref={offersRef}> | <OffersContainer ref={offersRef}> | ||||
| {props.isUsers | {props.isUsers | ||||
| ? props.users?.map((item) => ( | ? props.users?.map((item) => ( | ||||
| <BigProfileCard key={item._id} profile={item} /> | |||||
| <BigProfileCard | |||||
| key={item._id} | |||||
| profile={item} | |||||
| halfwidth={props?.isGrid} | |||||
| /> | |||||
| )) | )) | ||||
| : offers?.allOffersToShow?.map((item) => { | : offers?.allOffersToShow?.map((item) => { | ||||
| return ( | return ( | ||||
| Offers.defaultProps = { | Offers.defaultProps = { | ||||
| myOffers: false, | myOffers: false, | ||||
| users: [] | |||||
| users: [], | |||||
| }; | }; | ||||
| export default Offers; | export default Offers; |
| import React, { useCallback, useEffect, useRef } from "react"; | import React, { useCallback, useEffect, useRef } from "react"; | ||||
| import PropTypes from "prop-types"; | import PropTypes from "prop-types"; | ||||
| import { EndIcon, SearchIcon, SearchInput } from "./HeadersMyOffers.styled"; | |||||
| import { useTranslation } from "react-i18next"; | |||||
| import useSearch from "../../../../hooks/useOffers/useSearch"; | |||||
| import { EndIcon, SearchIcon, SearchInput } from "./SearchField.styled"; | |||||
| import useSearch from "../../../hooks/useOffers/useSearch"; | |||||
| const HeadersMyOffers = (props) => { | |||||
| const SearchField = (props) => { | |||||
| const searchRef = useRef(null); | const searchRef = useRef(null); | ||||
| const search = useSearch(() => {}); | const search = useSearch(() => {}); | ||||
| const { t } = useTranslation(); | |||||
| let listener = useCallback( | let listener = useCallback( | ||||
| (event) => { | (event) => { | ||||
| // Event keycode 13 = ENTER keycode | // Event keycode 13 = ENTER keycode | ||||
| return ( | return ( | ||||
| <SearchInput | <SearchInput | ||||
| isAdmin={props.isAdmin} | isAdmin={props.isAdmin} | ||||
| fullWidth | |||||
| fullWidth={props.fullWidth} | |||||
| InputProps={{ | InputProps={{ | ||||
| endAdornment: ( | endAdornment: ( | ||||
| <EndIcon size="36px"> | <EndIcon size="36px"> | ||||
| </EndIcon> | </EndIcon> | ||||
| ), | ), | ||||
| }} | }} | ||||
| placeholder={ | |||||
| props.isUsers | |||||
| ? t("admin.users.searchPlaceholder") | |||||
| : t("header.searchOffers") | |||||
| } | |||||
| placeholder={props.placeholder} | |||||
| onFocus={handleFocusSearch} | onFocus={handleFocusSearch} | ||||
| onBlur={handleBlurSearch} | onBlur={handleBlurSearch} | ||||
| ref={searchRef} | ref={searchRef} | ||||
| className={props.className} | |||||
| /> | /> | ||||
| ); | ); | ||||
| }; | }; | ||||
| HeadersMyOffers.propTypes = { | |||||
| SearchField.propTypes = { | |||||
| children: PropTypes.node, | children: PropTypes.node, | ||||
| searchMyOffers: PropTypes.func, | searchMyOffers: PropTypes.func, | ||||
| handleSearch: PropTypes.func, | handleSearch: PropTypes.func, | ||||
| isAdmin: PropTypes.bool, | isAdmin: PropTypes.bool, | ||||
| offers: PropTypes.any, | offers: PropTypes.any, | ||||
| isUsers: PropTypes.bool, | isUsers: PropTypes.bool, | ||||
| fullWidth: PropTypes.bool, | |||||
| className: PropTypes.string, | |||||
| placeholder: PropTypes.string, | |||||
| }; | |||||
| SearchField.defaultProps = { | |||||
| fullWidth: true, | |||||
| }; | }; | ||||
| export default HeadersMyOffers; | |||||
| export default SearchField; |
| import { Box } from "@mui/material"; | |||||
| import styled from "styled-components"; | import styled from "styled-components"; | ||||
| import { Icon } from "../../../Icon/Icon"; | |||||
| import { ReactComponent as Search } from "../../../../assets/images/svg/magnifying-glass.svg"; | |||||
| import selectedTheme from "../../../../themes"; | |||||
| import { TextField } from "../../../TextFields/TextField/TextField"; | |||||
| import selectedTheme from "../../../themes"; | |||||
| import { Icon } from "../../Icon/Icon"; | |||||
| import { TextField } from "../TextField/TextField"; | |||||
| import { ReactComponent as Search } from "../../../assets/images/svg/magnifying-glass.svg"; | |||||
| export const HeadersMyOffersContainer = styled(Box)``; | |||||
| export const EndIcon = styled(Icon)``; | export const EndIcon = styled(Icon)``; | ||||
| export const SearchIcon = styled(Search)` | export const SearchIcon = styled(Search)` | ||||
| position: relative; | position: relative; |
| export const POLICY_PRIVACY_PAGE = "/policy"; | export const POLICY_PRIVACY_PAGE = "/policy"; | ||||
| 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"; |
| searchPlaceholder: "Pretražite korisnike....", | searchPlaceholder: "Pretražite korisnike....", | ||||
| checkProfile: "Pogledaj profil" | checkProfile: "Pogledaj profil" | ||||
| }, | }, | ||||
| categories: { | |||||
| checkCategory: "Pogledaj podkategorije", | |||||
| noOfOffers: "Broj objava: ", | |||||
| noOfSubcategories: "Broj potkategorija: ", | |||||
| headerTitle: "Kategorije", | |||||
| placeholder: "Pretražite kategorije..." | |||||
| } | |||||
| }, | }, | ||||
| }; | }; |
| import React from "react"; | |||||
| import PropTypes from "prop-types"; | |||||
| import CategoryCard from "../../components/Cards/CategoryCard/CategoryCard"; | |||||
| 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 { | |||||
| AdminCategoriesHeader, | |||||
| AdminCategoriesPageContainer, | |||||
| AdminCategoriesSearchField, | |||||
| } from "./AdminCategoriesPage.styled"; | |||||
| const AdminCategoriesPage = () => { | |||||
| const { t } = useTranslation(); | |||||
| const dispatch = useDispatch(); | |||||
| const categories = useSelector(selectCategories); | |||||
| useEffect(() => { | |||||
| dispatch(fetchCategories()); | |||||
| }, []); | |||||
| return ( | |||||
| <AdminCategoriesPageContainer> | |||||
| <AdminCategoriesSearchField | |||||
| isAdmin | |||||
| placeholder={t("admin.categories.placeholder")} | |||||
| /> | |||||
| <AdminCategoriesHeader myOffers categories hideGrid isAdmin /> | |||||
| {categories.map((category) => ( | |||||
| <CategoryCard | |||||
| key={category._id} | |||||
| category={category} | |||||
| secondLabel={t("admin.categories.noOfSubcategories")} | |||||
| /> | |||||
| ))} | |||||
| </AdminCategoriesPageContainer> | |||||
| ); | |||||
| }; | |||||
| AdminCategoriesPage.propTypes = { | |||||
| children: PropTypes.node, | |||||
| }; | |||||
| export default AdminCategoriesPage; |
| import { Box } from "@mui/material"; | |||||
| import styled from "styled-components"; | |||||
| import Header from "../../components/MarketPlace/Header/Header"; | |||||
| import SearchField from "../../components/TextFields/SearchField/SearchField"; | |||||
| export const AdminCategoriesPageContainer = styled(Box)` | |||||
| padding: 60px; | |||||
| `; | |||||
| export const AdminCategoriesHeader = styled(Header)` | |||||
| /* top: 40px; */ | |||||
| top: 0; | |||||
| ` | |||||
| export const AdminCategoriesSearchField = styled(SearchField)` | |||||
| top: -15px; | |||||
| ` |
| export const hexToRGB = (hex, opacity) => { | |||||
| var r = parseInt(hex.slice(1, 3), 16), | |||||
| g = parseInt(hex.slice(3, 5), 16), | |||||
| b = parseInt(hex.slice(5, 7), 16); | |||||
| if (opacity) { | |||||
| return `rgba(${r}, ${g}, ${b}, ${opacity})`; | |||||
| } else { | |||||
| return `rgb(${r}, ${g}, ${b})`; | |||||
| } | |||||
| } |
| import { | import { | ||||
| ADMIN_CATEGORIES_PAGE, | |||||
| ADMIN_HOME_PAGE, | ADMIN_HOME_PAGE, | ||||
| ADMIN_LOGIN_PAGE, | ADMIN_LOGIN_PAGE, | ||||
| ADMIN_USERS_PAGE, | ADMIN_USERS_PAGE, | ||||
| if ( | if ( | ||||
| 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) | |||||
| ) | ) | ||||
| return true; | return true; | ||||
| return false; | return false; |