| @@ -81,7 +81,8 @@ const CategoryCard = (props) => { | |||
| subcategory={props.subcategory} | |||
| type={props.type} | |||
| method="edit" | |||
| showSecondButton | |||
| firstOutlined={false} | |||
| // showSecondButton | |||
| /> | |||
| )} | |||
| </> | |||
| @@ -29,7 +29,7 @@ export const CategoryRemoveButtonContainer = styled(IconButton)` | |||
| height: 16px; | |||
| position: relative; | |||
| top: -3px; | |||
| left: -1.5px; | |||
| left: -2.5px; | |||
| } | |||
| } | |||
| `; | |||
| @@ -0,0 +1,49 @@ | |||
| import React, { | |||
| forwardRef, | |||
| useEffect, | |||
| useImperativeHandle, | |||
| useState, | |||
| } from "react"; | |||
| import PropTypes from "prop-types"; | |||
| import { CompanyIcon } from "./CompanyChoser.styled"; | |||
| import { useTranslation } from "react-i18next"; | |||
| import FilterSubDropdown from "../../FilterDropdown/Checkbox/FilterSubDropdown/FilterSubDropdown"; | |||
| const CompanyChoser = forwardRef((props, ref) => { | |||
| const [isOpened, setIsOpened] = useState(false); | |||
| const filters = props.filters; | |||
| const { t } = useTranslation(); | |||
| useImperativeHandle(ref, () => ({ | |||
| closeSection: () => { | |||
| setIsOpened(false); | |||
| }, | |||
| })); | |||
| useEffect(() => { | |||
| if (filters.companies.selectedCompaniesLocally.length > 0 && !isOpened) { | |||
| setIsOpened(true); | |||
| } | |||
| }, [filters.companies.selectedCompaniesLocally]); | |||
| return ( | |||
| <FilterSubDropdown | |||
| searchPlaceholder={t("filters.company.placeholder")} | |||
| data={[...filters.companies.allCompanies]} | |||
| filters={[...filters.companies.selectedCompaniesLocally]} | |||
| open={isOpened} | |||
| handleOpen={() => setIsOpened((prevIsOpened) => !prevIsOpened)} | |||
| icon={<CompanyIcon />} | |||
| title={t("filters.company.title")} | |||
| setItemsSelected={filters.companies.setSelectedCompanies} | |||
| companies | |||
| /> | |||
| ); | |||
| }); | |||
| CompanyChoser.displayName = "CompanyChoser"; | |||
| CompanyChoser.propTypes = { | |||
| filters: PropTypes.any, | |||
| }; | |||
| export default CompanyChoser; | |||
| @@ -0,0 +1,11 @@ | |||
| import styled from "styled-components"; | |||
| import { ReactComponent as Company } from "../../../../../assets/images/svg/user-gray.svg"; | |||
| export const CompanyIcon = styled(Company)` | |||
| @media (max-width: 600px) { | |||
| width: 16px; | |||
| height: 16px; | |||
| position: relative; | |||
| bottom: 2px; | |||
| } | |||
| `; | |||
| @@ -1,4 +1,4 @@ | |||
| import React, { forwardRef, useEffect, useImperativeHandle, useState } from "react"; | |||
| import React, { forwardRef, useEffect, useImperativeHandle, useMemo, useState } from "react"; | |||
| import PropTypes from "prop-types"; | |||
| import FilterCheckboxDropdown from "../../FilterDropdown/Checkbox/FilterCheckboxDropdown"; | |||
| import { LocationIcon } from "./LocationChoser.styled"; | |||
| @@ -9,6 +9,9 @@ const LocationChoser = forwardRef((props, ref) => { | |||
| const [isOpened, setIsOpened] = useState(false); | |||
| const filters = props.filters; | |||
| const allLocations = useMemo(() => filters.locations.allLocations || [], [filters.locations]) | |||
| console.log("allLocations", allLocations); | |||
| useImperativeHandle(ref, () => ({ | |||
| closeSection: () => { | |||
| setIsOpened(false); | |||
| @@ -23,7 +26,7 @@ const LocationChoser = forwardRef((props, ref) => { | |||
| return ( | |||
| <FilterCheckboxDropdown | |||
| searchPlaceholder={t("filters.location.placeholder")} | |||
| data={[...filters.locations.allLocations]} | |||
| data={[...allLocations]} | |||
| filters={[...filters.locations.selectedLocationsLocally]} | |||
| open={isOpened} | |||
| handleOpen={() => setIsOpened((prevIsOpened) => !prevIsOpened)} | |||
| @@ -7,6 +7,7 @@ import FilterFooter from "./FilterFooter/FilterFooter"; | |||
| import CategoryChoser from "./Choser/CategoryChoser/CategoryChoser"; | |||
| import SubcategoryChoser from "./Choser/SubcategoryChoser/SubcategoryChoser"; | |||
| import LocationChoser from "./Choser/LocationChoser/LocationChoser"; | |||
| import CompanyChoser from "./Choser/CompanyChoser/CompanyChoser"; | |||
| import SkeletonFilterCard from "./Skeleton/SkeletonFilterCard"; | |||
| const FilterCard = (props) => { | |||
| @@ -15,11 +16,14 @@ const FilterCard = (props) => { | |||
| const categoryRef = useRef(null); | |||
| const subcategoryRef = useRef(null); | |||
| const locationRef = useRef(null); | |||
| const companyRef = useRef(null); | |||
| const closeAllSections = () => { | |||
| categoryRef.current.closeSection(); | |||
| subcategoryRef.current.closeSection(); | |||
| locationRef.current.closeSection(); | |||
| companyRef.current.closeSection(); | |||
| }; | |||
| console.log(offers); | |||
| return ( | |||
| <FilterCardContainer | |||
| filtersOpened={props.filtersOpened} | |||
| @@ -54,6 +58,7 @@ const FilterCard = (props) => { | |||
| {!props.myOffers && ( | |||
| <LocationChoser filters={filters} ref={locationRef} /> | |||
| )} | |||
| <CompanyChoser filters={filters} ref={companyRef} /> | |||
| </ContentContainer> | |||
| <FilterFooter | |||
| @@ -4,15 +4,18 @@ import { CheckBox as CheckboxButton } from "../../../../../CheckBox/CheckBox"; | |||
| const Checkbox = (props) => { | |||
| const item = props.item; | |||
| return ( | |||
| <CheckboxButton | |||
| leftText={item.city} | |||
| leftText={props.companies ? item.company.name : item.city} | |||
| // rightText={item.offerCount} | |||
| value={item} | |||
| checked={ | |||
| props.filters.find( | |||
| (itemInList) => | |||
| itemInList?.city?.toString() === item?.city?.toString() | |||
| props.filters.find((itemInList) => | |||
| props.companies | |||
| ? itemInList?.company?.name?.toString() === | |||
| item?.company?.name?.toString() | |||
| : itemInList?.city?.toString() === item?.city?.toString() | |||
| ) | |||
| ? true | |||
| : false | |||
| @@ -27,6 +30,7 @@ Checkbox.propTypes = { | |||
| item: PropTypes.any, | |||
| filters: PropTypes.any, | |||
| onChange: PropTypes.func, | |||
| companies: PropTypes.bool, | |||
| }; | |||
| export default Checkbox; | |||
| @@ -31,9 +31,7 @@ const CheckboxDropdownList = (props) => { | |||
| : selectedTheme.colors.primaryText | |||
| } | |||
| dropdownIcon={ | |||
| <NumberedIcon number={props.filters.length}> | |||
| {props.icon} | |||
| </NumberedIcon> | |||
| <NumberedIcon number={props.filters.length}>{props.icon}</NumberedIcon> | |||
| } | |||
| toggleIconClosed={<DropdownDown />} | |||
| toggleIconOpened={<DropdownUp />} | |||
| @@ -49,12 +47,20 @@ const CheckboxDropdownList = (props) => { | |||
| <React.Fragment> | |||
| <SelectedItemsContainer> | |||
| {props.filters.map((item) => ( | |||
| <SelectedItem key={item.city} onClick={() => handleDelete(item)}> | |||
| { | |||
| data.find( | |||
| (p) => p?.city?.toString() === item?.city?.toString() | |||
| )?.city | |||
| } | |||
| <SelectedItem | |||
| key={props.companies ? item.company.name : item.city} | |||
| onClick={() => handleDelete(item)} | |||
| > | |||
| {props.companies | |||
| ? data.find( | |||
| (p) => | |||
| p?.company?.name?.toString() === | |||
| item?.company?.name?.toString() | |||
| )?.company?.name | |||
| : data.find( | |||
| (p) => p?.city?.toString() === item?.city?.toString() | |||
| )?.city} | |||
| <CloseIcon /> | |||
| </SelectedItem> | |||
| ))} | |||
| @@ -85,6 +91,7 @@ CheckboxDropdownList.propTypes = { | |||
| setIsOpened: PropTypes.func, | |||
| open: PropTypes.bool, | |||
| handleOpen: PropTypes.func, | |||
| companies: PropTypes.bool, | |||
| }; | |||
| export default CheckboxDropdownList; | |||
| @@ -18,7 +18,9 @@ const FilterCheckboxDropdown = (props) => { | |||
| if (toSearch.length > 0) { | |||
| setDataToShow( | |||
| data.filter((item) => | |||
| item.city.toLowerCase().includes(toSearch.toLowerCase()) | |||
| props.companies | |||
| ? item.company.name.toLowerCase().includes(toSearch.toLowerCase()) | |||
| : item.city.toLowerCase().includes(toSearch.toLowerCase()) | |||
| ) | |||
| ); | |||
| } else { | |||
| @@ -69,6 +71,7 @@ const FilterCheckboxDropdown = (props) => { | |||
| open={props?.open !== undefined ? props.open : isOpened} | |||
| handleOpen={handleOpen} | |||
| setItemsSelected={props.setItemsSelected} | |||
| companies={props.companies} | |||
| > | |||
| {dataToShow.map((item) => { | |||
| return ( | |||
| @@ -77,6 +80,7 @@ const FilterCheckboxDropdown = (props) => { | |||
| item={item} | |||
| filters={props.filters} | |||
| onChange={() => handleChange(item)} | |||
| companies={props.companies} | |||
| /> | |||
| </DropdownItem> | |||
| ); | |||
| @@ -96,6 +100,7 @@ FilterCheckboxDropdown.propTypes = { | |||
| filters: PropTypes.array, | |||
| open: PropTypes.bool, | |||
| handleOpen: PropTypes.func, | |||
| companies: PropTypes.bool, | |||
| }; | |||
| FilterCheckboxDropdown.defaultProps = { | |||
| oneValueAllowed: false, | |||
| @@ -0,0 +1,109 @@ | |||
| import React, { useState, useEffect } from "react"; | |||
| import PropTypes from "prop-types"; | |||
| import Checkbox from "../../Checkbox/Checkbox"; | |||
| import DropdownItem from "../../../../../../Dropdown/DropdownItem/DropdownItem"; | |||
| import { filterCompanies } from "../../../../../../../util/helpers/filterCompanies"; | |||
| import { | |||
| REGEXP_FIRST, | |||
| REGEXP_SECOND, | |||
| REGEXP_THIRD, | |||
| } from "../../../../../../../constants/filterCompanies"; | |||
| import { | |||
| SmallDropdownContainer, | |||
| SmallDropdownContent, | |||
| SmallDropdownIcon, | |||
| SmallDropdownText, | |||
| } from "./FilterSmallDropdown.styled"; | |||
| const FilterSmallDropdown = (props) => { | |||
| const [data, setData] = useState([]); | |||
| const [showDropdown, setShowDropdown] = useState(false); | |||
| useEffect(() => { | |||
| setData([...props.dataToShow]); | |||
| }, [props.dataToShow]); | |||
| let dataFiltered; | |||
| if (props.letters === "A-H") { | |||
| dataFiltered = filterCompanies(data, REGEXP_FIRST); | |||
| } else if (props.letters === "I-Q") { | |||
| dataFiltered = filterCompanies(data, REGEXP_SECOND); | |||
| } else if (props.letters === "R-Z") { | |||
| dataFiltered = filterCompanies(data, REGEXP_THIRD); | |||
| } | |||
| const handleChange = (item) => { | |||
| if (props.oneValueAllowed) { | |||
| props.setItemsSelected([item]); | |||
| } else { | |||
| if ( | |||
| props.filters.find( | |||
| (itemInList) => | |||
| itemInList?.company?.name?.toString() === | |||
| item?.company?.name?.toString() | |||
| ) | |||
| ) { | |||
| props.setItemsSelected([ | |||
| ...props.filters.filter( | |||
| (p) => | |||
| p?.company?.name?.toString() !== item?.company?.name?.toString() | |||
| ), | |||
| ]); | |||
| } else { | |||
| props.setItemsSelected([...props.filters, item]); | |||
| } | |||
| } | |||
| }; | |||
| const setDropdownHandler = () => { | |||
| setShowDropdown((prevState) => !prevState); | |||
| }; | |||
| return ( | |||
| <> | |||
| <SmallDropdownContainer> | |||
| <SmallDropdownText>{props.letters}</SmallDropdownText> | |||
| <SmallDropdownIcon | |||
| onClick={() => setDropdownHandler()} | |||
| dropdown={showDropdown} | |||
| /> | |||
| </SmallDropdownContainer> | |||
| <SmallDropdownContent dropdown={showDropdown}> | |||
| {dataFiltered.map((item) => { | |||
| return ( | |||
| <DropdownItem key={item.company._id}> | |||
| <Checkbox | |||
| item={item} | |||
| filters={props.filters} | |||
| onChange={() => handleChange(item)} | |||
| companies={props.companies} | |||
| /> | |||
| </DropdownItem> | |||
| ); | |||
| })} | |||
| </SmallDropdownContent> | |||
| </> | |||
| ); | |||
| }; | |||
| FilterSmallDropdown.propTypes = { | |||
| children: PropTypes.node, | |||
| icon: PropTypes.node, | |||
| data: PropTypes.array, | |||
| title: PropTypes.string, | |||
| oneValueAllowed: PropTypes.bool, | |||
| searchPlaceholder: PropTypes.string, | |||
| setItemsSelected: PropTypes.func, | |||
| filters: PropTypes.array, | |||
| open: PropTypes.bool, | |||
| handleOpen: PropTypes.func, | |||
| companies: PropTypes.bool, | |||
| letters: PropTypes.any, | |||
| dataToShow: PropTypes.array, | |||
| }; | |||
| FilterSmallDropdown.defaultProps = { | |||
| oneValueAllowed: false, | |||
| }; | |||
| export default FilterSmallDropdown; | |||
| @@ -0,0 +1,30 @@ | |||
| import styled from "styled-components"; | |||
| import { Box, Typography } from "@mui/material"; | |||
| import { ReactComponent as DropdownDown } from "../../../../../../../assets/images/svg/down-arrow.svg"; | |||
| export const SmallDropdownContainer = styled(Box)` | |||
| display: flex; | |||
| align-items: center; | |||
| gap: 8px; | |||
| margin-top: 20px; | |||
| margin-left: -20px; | |||
| margin-bottom: 14px; | |||
| `; | |||
| export const SmallDropdownText = styled(Typography)` | |||
| font-family: "DM Sans"; | |||
| font-size: 12px; | |||
| `; | |||
| export const SmallDropdownIcon = styled(DropdownDown)` | |||
| width: 12px; | |||
| ${(props) => | |||
| props.dropdown && | |||
| ` | |||
| transform: rotate(180deg); | |||
| `} | |||
| `; | |||
| export const SmallDropdownContent = styled(Box)` | |||
| display: ${(props) => (props.dropdown ? "block" : "none")}; | |||
| `; | |||
| @@ -0,0 +1,99 @@ | |||
| import React, { useState, useEffect } from "react"; | |||
| import PropTypes from "prop-types"; | |||
| import CheckboxDropdownList from "../CheckboxDropdownList/CheckboxDropdownList"; | |||
| import FilterSmallDropdown from "./FilterSmallDropdown/FilterSmallDropdown"; | |||
| import { useTranslation } from "react-i18next"; | |||
| const FilterSubDropdown = (props) => { | |||
| const [dataToShow, setDataToShow] = useState([]); | |||
| const [isOpened, setIsOpened] = useState(false); | |||
| const [toSearch, setToSearch] = useState(""); | |||
| const { t } = useTranslation(); | |||
| const { data } = props; | |||
| useEffect(() => { | |||
| setDataToShow([...data]); | |||
| }, [data]); | |||
| useEffect(() => { | |||
| if (toSearch.length > 0) { | |||
| setDataToShow( | |||
| data.filter((item) => | |||
| props.companies | |||
| ? item.company.name.toLowerCase().includes(toSearch.toLowerCase()) | |||
| : item.city.toLowerCase().includes(toSearch.toLowerCase()) | |||
| ) | |||
| ); | |||
| } else { | |||
| setDataToShow([...data]); | |||
| } | |||
| }, [toSearch]); | |||
| useEffect(() => { | |||
| if (props.filters?.length > 0) { | |||
| setIsOpened(true); | |||
| } | |||
| }, [props.filters]); | |||
| const handleOpen = () => { | |||
| setIsOpened((prevState) => !prevState); | |||
| if (props.handleOpen) props.handleOpen(); | |||
| }; | |||
| return ( | |||
| <CheckboxDropdownList | |||
| toSearch={toSearch} | |||
| setToSearch={setToSearch} | |||
| title={props.title} | |||
| filters={props.filters} | |||
| icon={props.icon} | |||
| data={data} | |||
| searchPlaceholder={props.searchPlaceholder} | |||
| open={props?.open !== undefined ? props.open : isOpened} | |||
| handleOpen={handleOpen} | |||
| setItemsSelected={props.setItemsSelected} | |||
| companies={props.companies} | |||
| > | |||
| <FilterSmallDropdown | |||
| letters={t("filters.company.firstSort")} | |||
| dataToShow={dataToShow} | |||
| filters={props.filters} | |||
| setItemsSelected={props.setItemsSelected} | |||
| companies={props.companies} | |||
| /> | |||
| <FilterSmallDropdown | |||
| letters={t("filters.company.secondSort")} | |||
| dataToShow={dataToShow} | |||
| filters={props.filters} | |||
| setItemsSelected={props.setItemsSelected} | |||
| companies={props.companies} | |||
| /> | |||
| <FilterSmallDropdown | |||
| letters={t("filters.company.thirdSort")} | |||
| dataToShow={dataToShow} | |||
| filters={props.filters} | |||
| setItemsSelected={props.setItemsSelected} | |||
| companies={props.companies} | |||
| /> | |||
| </CheckboxDropdownList> | |||
| ); | |||
| }; | |||
| FilterSubDropdown.propTypes = { | |||
| children: PropTypes.node, | |||
| icon: PropTypes.node, | |||
| data: PropTypes.array, | |||
| title: PropTypes.string, | |||
| oneValueAllowed: PropTypes.bool, | |||
| searchPlaceholder: PropTypes.string, | |||
| setItemsSelected: PropTypes.func, | |||
| filters: PropTypes.array, | |||
| open: PropTypes.bool, | |||
| handleOpen: PropTypes.func, | |||
| companies: PropTypes.bool, | |||
| }; | |||
| FilterSubDropdown.defaultProps = { | |||
| oneValueAllowed: false, | |||
| }; | |||
| export default FilterSubDropdown; | |||
| @@ -0,0 +1,43 @@ | |||
| import styled from "styled-components"; | |||
| import { Box, Typography } from "@mui/material"; | |||
| import { ReactComponent as DropdownDown } from "../../../../../../assets/images/svg/down-arrow.svg"; | |||
| export const SmallDropdownContainer = styled(Box)` | |||
| display: flex; | |||
| align-items: center; | |||
| gap: 8px; | |||
| margin-top: 20px; | |||
| margin-left: -20px; | |||
| margin-bottom: 14px; | |||
| `; | |||
| export const SmallDropdownText = styled(Typography)` | |||
| font-family: "DM Sans"; | |||
| font-size: 12px; | |||
| `; | |||
| export const SmallDropdownIcon = styled(DropdownDown)` | |||
| width: 12px; | |||
| ${(props) => | |||
| props.firstDropdown && | |||
| ` | |||
| transform: rotate(180deg); | |||
| `} | |||
| ${(props) => | |||
| props.secondDropdown && | |||
| ` | |||
| transform: rotate(180deg); | |||
| `} | |||
| ${(props) => | |||
| props.thirdDropdown && | |||
| ` | |||
| transform: rotate(180deg); | |||
| `} | |||
| `; | |||
| export const SmallDropdownContent = styled(Box)` | |||
| display: ${(props) => | |||
| props.firstDropdown || props.secondDropdown || props.thirdDropdown | |||
| ? "block" | |||
| : "none"}; | |||
| `; | |||
| @@ -3,7 +3,7 @@ import { PrimaryButton } from "../../../../Buttons/PrimaryButton/PrimaryButton"; | |||
| export const CancelButtonContainer = styled(PrimaryButton)` | |||
| @media screen and (max-width: 600px) { | |||
| width: 140px; | |||
| width: 147px; | |||
| height: 45px; | |||
| } | |||
| `; | |||
| @@ -9,6 +9,7 @@ import { | |||
| OfferImage, | |||
| RemoveIconContainer, | |||
| RemoveIcon, | |||
| PinIcon, | |||
| } from "./DeleteOffer.styled"; | |||
| import BackdropComponent from "../../../MUI/BackdropComponent"; | |||
| import { useDispatch, useSelector } from "react-redux"; | |||
| @@ -74,7 +75,7 @@ const DeleteOffer = (props) => { | |||
| categoryName={props.offer.category.name} | |||
| /> | |||
| <RemoveIconContainer> | |||
| <RemoveIcon /> | |||
| {props.pin ? <PinIcon /> : <RemoveIcon />} | |||
| </RemoveIconContainer> | |||
| </OfferInfo> | |||
| <DeleteQuestion> | |||
| @@ -2,6 +2,7 @@ import { Typography } from "@mui/material"; | |||
| import { Box } from "@mui/system"; | |||
| import styled from "styled-components"; | |||
| import { ReactComponent as Remove } from "../../../../assets/images/svg/trash-gold.svg"; | |||
| import { ReactComponent as Pin } from "../../../../assets/images/svg/pin-outlined.svg"; | |||
| import selectedTheme from "../../../../themes"; | |||
| import { Icon } from "../../../Icon/Icon"; | |||
| @@ -35,6 +36,8 @@ export const OfferInfo = styled(Box)` | |||
| align-items: center; | |||
| padding: 18px; | |||
| margin-top: 36px; | |||
| gap: 9px !important; | |||
| background-color: ${selectedTheme.colors.chatHeaderColor}; | |||
| @media screen and (max-width: 600px) { | |||
| margin-left: calc(50% - 105px) !important; | |||
| @@ -43,7 +46,9 @@ export const OfferInfo = styled(Box)` | |||
| export const OfferImageContainer = styled(Box)` | |||
| width: 54px; | |||
| min-width: 54px; | |||
| height: 54px; | |||
| min-height: 54px; | |||
| border-radius: 2px; | |||
| @media screen and (max-width: 600px) { | |||
| @@ -67,9 +72,10 @@ export const DeleteQuestion = styled(Typography)` | |||
| @media screen and (max-width: 600px) { | |||
| font-size: 14px; | |||
| margin: 27px 0; | |||
| display: block; | |||
| margin: 27px auto; | |||
| text-align: center; | |||
| width: 100%; | |||
| width: 220px; | |||
| } | |||
| `; | |||
| @@ -91,12 +97,24 @@ export const RemoveIconBorder = styled(Icon)` | |||
| export const RemoveIconContainer = styled(RemoveIconBorder)` | |||
| cursor: default; | |||
| & span { | |||
| position: relative; | |||
| top: 4px; | |||
| } | |||
| `; | |||
| export const RemoveIcon = styled(Remove)` | |||
| cursor: default; | |||
| position: relative; | |||
| top: 7px; | |||
| top: 2px; | |||
| `; | |||
| export const PinIcon = styled(Pin)` | |||
| cursor: default; | |||
| position: relative; | |||
| top: 3px; | |||
| & g path { | |||
| stroke: ${selectedTheme.colors.iconYellowColor}; | |||
| } | |||
| `; | |||
| export const ButtonsContainer = styled(Box)` | |||
| @@ -8,12 +8,21 @@ export const OfferDescriptionContainer = styled(Box)` | |||
| display: flex; | |||
| flex-direction: column; | |||
| margin-left: 9px; | |||
| gap: 0 !important; | |||
| `; | |||
| export const OfferDescriptionTitle = styled(Typography)` | |||
| font-size: 16px; | |||
| font-weight: 600; | |||
| color: ${selectedTheme.colors.primaryPurple}; | |||
| font-family: ${selectedTheme.fonts.textFont}; | |||
| overflow: hidden; | |||
| line-height: 19px; | |||
| display: -webkit-box; | |||
| -webkit-line-clamp: 2; | |||
| -webkit-box-orient: vertical; | |||
| text-overflow: ellipsis; | |||
| max-height: 38px; | |||
| @media screen and (max-width: 600px) { | |||
| font-size: 14px; | |||
| @@ -23,15 +32,18 @@ export const OfferDescriptionTitle = styled(Typography)` | |||
| export const OfferDescriptionCategory = styled(Typography)` | |||
| font-size: 12px; | |||
| letter-spacing: 2%; | |||
| font-family: ${selectedTheme.fonts.textFont}; | |||
| color: ${selectedTheme.colors.primaryDarkText}; | |||
| `; | |||
| export const CategoryIconContainer = styled(Icon)` | |||
| margin-right: 4px; | |||
| position: relative; | |||
| top: 2px; | |||
| & svg { | |||
| width: 14px; | |||
| position: relative; | |||
| top: -1px; | |||
| top: -6px; | |||
| } | |||
| `; | |||
| export const CategoryIcon = styled(Category)` | |||
| ` | |||
| export const CategoryIcon = styled(Category)``; | |||
| @@ -3,7 +3,7 @@ import { PrimaryButton } from "../../../../Buttons/PrimaryButton/PrimaryButton"; | |||
| export const SaveButtonContainer = styled(PrimaryButton)` | |||
| @media screen and (max-width: 600px) { | |||
| width: 140px; | |||
| width: 147px; | |||
| height: 45px; | |||
| } | |||
| `; | |||
| @@ -67,7 +67,10 @@ export const ButtonsContainer = styled(Box)` | |||
| right: 18px; | |||
| display: flex; | |||
| flex-direction: row; | |||
| gap: 12px; | |||
| gap: 18px; | |||
| @media (max-width: 600px) { | |||
| gap: 12px; | |||
| } | |||
| `; | |||
| export const MessageButton = styled(IconButton)` | |||
| @@ -121,7 +124,7 @@ export const CheckButton = styled(PrimaryButton)` | |||
| width: 180px; | |||
| height: 48px; | |||
| position: absolute; | |||
| bottom: 25px; | |||
| bottom: 11px; | |||
| right: 9px; | |||
| display: ${(props) => (props.halfwidth ? `none` : `block`)}; | |||
| & button:hover { | |||
| @@ -121,7 +121,7 @@ const ProfileCard = (props) => { | |||
| <SkeletonProfileCard /> | |||
| ) : ( | |||
| <> | |||
| <ProfileCardContainer> | |||
| <ProfileCardContainer isAdmin={props.isAdmin}> | |||
| <ProfileCardHeader> | |||
| <PersonOutlineIcon color="action" sx={{ mr: 0.9 }} /> | |||
| <HeaderTitle> | |||
| @@ -21,7 +21,7 @@ export const ProfileCardContainer = styled(Box)` | |||
| padding: 0 36px 0 0; | |||
| } | |||
| @media (max-width: 600px) { | |||
| padding: 0 18px; | |||
| padding: 0 ${props => props.isAdmin ? "18px" : "0"}; | |||
| } | |||
| `; | |||
| export const EditIcon = styled(Edit)` | |||
| @@ -7,7 +7,7 @@ import selectedTheme from "../../../../themes"; | |||
| export const ProfileContactContainer = styled(Grid)` | |||
| padding-top: ${(props) => (props.isAdmin ? `20px` : `2rem`)}; | |||
| padding-bottom: 2rem; | |||
| padding-bottom: ${(props) => (props.isAdmin ? "0" : "2rem")}; | |||
| @media (max-width: 600px) { | |||
| padding-bottom: 1rem; | |||
| padding-top: 88px; | |||
| @@ -47,7 +47,11 @@ const UserReviewsCard = (props) => { | |||
| return ( | |||
| <> | |||
| <UserReviewsSingleCard review={review} handleRemove={handleRemove} /> | |||
| <UserReviewsSingleCard | |||
| review={review} | |||
| showRemoveIcon={props.showRemoveIcon} | |||
| handleRemove={handleRemove} | |||
| /> | |||
| {removeModalOpened && ( | |||
| <DeleteReview | |||
| review={review} | |||
| @@ -66,6 +70,7 @@ UserReviewsCard.propTypes = { | |||
| className: PropTypes.string, | |||
| review: PropTypes.any, | |||
| givingReview: PropTypes.bool, | |||
| showRemoveIcon: PropTypes.bool, | |||
| }; | |||
| UserReviewsCard.defaultProps = { | |||
| isProfileReviews: false, | |||
| @@ -8,13 +8,15 @@ import { | |||
| ReviewOfferTitle, | |||
| } from "./ReviewOffer.styled"; | |||
| import { getImageUrl, variants } from "../../../../../util/helpers/imageUrlGetter"; | |||
| import { useTranslation } from "react-i18next"; | |||
| const ReviewOffer = (props) => { | |||
| const {t} = useTranslation(); | |||
| return ( | |||
| <ReviewOfferContainer> | |||
| <ReviewOfferImage src={getImageUrl(props.image, variants.reviewCard)} /> | |||
| <ReviewOfferDetails> | |||
| <ReviewOfferDescription>Proizvod: </ReviewOfferDescription> | |||
| <ReviewOfferDescription>{t("reviews.offerTitle")}</ReviewOfferDescription> | |||
| <ReviewOfferTitle>{props.name}</ReviewOfferTitle> | |||
| </ReviewOfferDetails> | |||
| </ReviewOfferContainer> | |||
| @@ -27,4 +27,17 @@ export const ReviewOfferTitle = styled(Typography)` | |||
| font-size: 16px; | |||
| font-weight: 600; | |||
| font-family: ${selectedTheme.fonts.textFont}; | |||
| overflow: hidden; | |||
| line-height: 19px; | |||
| display: -webkit-box; | |||
| -webkit-line-clamp: 1; | |||
| -webkit-box-orient: vertical; | |||
| text-overflow: ellipsis; | |||
| max-height: 19px; | |||
| @media (max-width: 600px) { | |||
| font-size: 12px; | |||
| line-height: 16px; | |||
| max-height: 16px; | |||
| } | |||
| `; | |||
| @@ -26,7 +26,9 @@ const UserReviewsSingleCard = (props) => { | |||
| isSuccessfulSwap={props.review?.isSuccessfulSwap} | |||
| isGoodCommunication={props.review?.isGoodCommunication} | |||
| /> | |||
| {!props.showRemoveIcon && <RemoveButton review={props.review} onClick={handleRemove} />} | |||
| {props.showRemoveIcon && ( | |||
| <RemoveButton review={props.review} onClick={handleRemove} /> | |||
| )} | |||
| <ReviewOffer | |||
| name={props.review?.offerName} | |||
| image={props.review?.offerImage} | |||
| @@ -12,7 +12,7 @@ export const OfferIconContainer = styled(Box)` | |||
| @media screen and (max-width: 600px) { | |||
| margin-left: 0; | |||
| margin-top: 310px; | |||
| margin-top: 345px; | |||
| svg { | |||
| width: 14px; | |||
| @@ -19,7 +19,7 @@ export const ItemDetailsHeaderContainer = styled(Box)` | |||
| position: relative; | |||
| @media screen and (max-width: 600px) { | |||
| width: 92%; | |||
| width: calc(100vw - 36px); | |||
| } | |||
| `; | |||
| export const HeaderTop = styled(Box)` | |||
| @@ -0,0 +1,27 @@ | |||
| import React from "react"; | |||
| import PropTypes from "prop-types"; | |||
| import { ButtonContainer, DeleteButtonContainer } from "./DeleteButton.styled"; | |||
| import selectedTheme from "../../../../themes"; | |||
| import { useTranslation } from "react-i18next"; | |||
| const DeleteButton = (props) => { | |||
| const {t} = useTranslation(); | |||
| return ( | |||
| <DeleteButtonContainer> | |||
| <ButtonContainer | |||
| variant="contained" | |||
| buttoncolor={selectedTheme.colors.primaryPurple} | |||
| onClick={props.onClick} | |||
| textcolor={selectedTheme.colors.primaryTextDisabled} | |||
| > | |||
| {t("admin.review.confirm")} | |||
| </ButtonContainer> | |||
| </DeleteButtonContainer> | |||
| ); | |||
| }; | |||
| DeleteButton.propTypes = { | |||
| onClick: PropTypes.func, | |||
| }; | |||
| export default DeleteButton; | |||
| @@ -0,0 +1,20 @@ | |||
| import { Box } from "@mui/material"; | |||
| import styled from "styled-components"; | |||
| import { PrimaryButton } from "../../../Buttons/PrimaryButton/PrimaryButton"; | |||
| export const DeleteButtonContainer = styled(Box)` | |||
| position: absolute; | |||
| bottom: 36px; | |||
| left: 18px; | |||
| background-color: white !important; | |||
| border: 0 !important; | |||
| padding: 0 !important; | |||
| `; | |||
| export const ButtonContainer = styled(PrimaryButton)` | |||
| height: 44px; | |||
| width: calc(100vw - 36px); | |||
| background-color: white !important; | |||
| & > button { | |||
| background-color: ${(props) => props.buttoncolor} !important; | |||
| } | |||
| `; | |||
| @@ -8,6 +8,7 @@ import { | |||
| import BackdropComponent from "../../MUI/BackdropComponent"; | |||
| import UserReviewsSingleCard from "../../Cards/UserReviewsCard/UserReviewsSingleCard/UserReviewsSingleCard"; | |||
| import { useTranslation } from "react-i18next"; | |||
| import DeleteButton from "./DeleteButton/DeleteButton"; | |||
| const DeleteReview = (props) => { | |||
| const { t } = useTranslation(); | |||
| @@ -25,7 +26,8 @@ const DeleteReview = (props) => { | |||
| deleteModal | |||
| review={props.review} | |||
| /> | |||
| <XIcon /> | |||
| <XIcon onClick={() => props.setOpenedDeleteModal(false)} /> | |||
| <DeleteButton /> | |||
| </DeleteReviewContainer> | |||
| </> | |||
| ); | |||
| @@ -25,12 +25,15 @@ const EditCategory = (props) => { | |||
| const title = useMemo(() => { | |||
| return t(`admin.${props.type}.${props.method}.title`); | |||
| }, [props.type, props.method]); | |||
| const placeholder = useMemo(() => { | |||
| return t(`admin.${props.type}.${props.method}.placeholder`); | |||
| }, [props.type, props.method]); | |||
| const fieldLabel = useMemo(() => { | |||
| return t(`admin.${props.type}.${props.method}.fieldTitle`); | |||
| }, [props.type, props.method]); | |||
| const firstButtonText = useMemo(() => { | |||
| return t(`admin.${props.type}.${props.method}.next`); | |||
| }, [props.type, props.method]); | |||
| @@ -48,7 +51,7 @@ const EditCategory = (props) => { | |||
| const formik = useFormik({ | |||
| initialValues: { | |||
| image: "", | |||
| title: props?.category?.name || "", | |||
| title: props?.category?.name || props?.category?.city || "", | |||
| }, | |||
| onSubmit: handleSubmit, | |||
| }); | |||
| @@ -121,6 +121,7 @@ export const InputContainer = styled(Box)` | |||
| `; | |||
| export const SaveButton = styled(PrimaryButton)` | |||
| max-width: 376px; | |||
| width: ${(props) => (props.showSecondButton ? "180px" : "376px")}; | |||
| height: 48px; | |||
| & button { | |||
| letter-spacing: 1.5px; | |||
| @@ -21,6 +21,7 @@ const Header = (props) => { | |||
| onClick={handleBackButton} | |||
| component="header" | |||
| className={props.className} | |||
| isAdmin={props.isAdmin} | |||
| > | |||
| <ButtonContainer> | |||
| <ArrowButton side={"left"}></ArrowButton> | |||
| @@ -6,8 +6,8 @@ export const HeaderContainer = styled(Box)` | |||
| margin-top: 20px; | |||
| @media (max-width: 600px) { | |||
| margin-top: 40px; | |||
| margin-left: 18px; | |||
| margin-top: 49px; | |||
| margin-left: ${props => props.isAdmin ? "18px" : "0"}; | |||
| } | |||
| `; | |||
| export const ButtonContainer = styled(Link)` | |||
| @@ -69,7 +69,7 @@ const ProfileOffers = (props) => { | |||
| }; | |||
| return ( | |||
| <ProfileOffersContainer> | |||
| <ProfileOffersContainer isAdmin={props.isAdmin}> | |||
| {isLoadingMineOffers || isLoadingMineOffers === undefined ? ( | |||
| <ProfileOffersHeaderSkeleton /> | |||
| ) : ( | |||
| @@ -14,7 +14,8 @@ export const ProfileOffersContainer = styled(Box)` | |||
| @media (max-width: 600px) { | |||
| padding: 0; | |||
| width: calc(100vw - 36px); | |||
| margin: 34px 18px; | |||
| margin: 34px ${props => props.isAdmin ? "18px" : "0"}; | |||
| margin-bottom: ${props => !props.isAdmin && '0'} | |||
| } | |||
| `; | |||
| export const OffersContainer = styled(Box)` | |||
| @@ -8,9 +8,10 @@ export const ProfileHeader = styled(Box)` | |||
| margin-top: 60px; | |||
| @media screen and (max-width: 600px) { | |||
| width: 100%; | |||
| width: calc(100vw - 18px); | |||
| position: absolute; | |||
| top: 25px; | |||
| left: 18px; | |||
| } | |||
| `; | |||
| export const ProfileHeaderIconContainer = styled(Box)` | |||
| @@ -45,6 +46,6 @@ export const ProfileMiniStats = styled(ProfileStats)` | |||
| border: 1px solid ${selectedTheme.colors.primaryPurple}; | |||
| @media (max-width: 600px) { | |||
| width: 92%; | |||
| width: calc(100vw - 36px); | |||
| } | |||
| `; | |||
| @@ -9,10 +9,12 @@ export const StepProgressContainer = styled(Box)` | |||
| position: relative; | |||
| left: 2px; | |||
| width: 332px; | |||
| gap: 0 !important; | |||
| ${(props) => props.current === 3 && `margin-bottom: 30px;`} | |||
| @media screen and (min-width: 468px) and (max-width: 600px) { | |||
| width: 80%; | |||
| gap: 0 !important; | |||
| } | |||
| @media (max-width: 600px) { | |||
| @@ -82,6 +82,7 @@ const UserReviews = (props) => { | |||
| <SkeletonUserReviews /> | |||
| ) : ( | |||
| <ReviewsBox | |||
| isAdmin={props.isAdmin} | |||
| profile={props.isProfileReviews} | |||
| numOfReviews={lastThreeReviews?.length} | |||
| > | |||
| @@ -111,6 +112,7 @@ const UserReviews = (props) => { | |||
| {lastThreeReviews?.length > 0 ? ( | |||
| lastThreeReviews?.map((review, index) => ( | |||
| <UserReviewsCard | |||
| showRemoveIcon={props.isAdmin} | |||
| review={review} | |||
| key={index} | |||
| hasGivenReview={sortRef.current?.hasGivenReview} | |||
| @@ -28,7 +28,7 @@ export const ReviewsBox = styled(Box)` | |||
| ? "450px" | |||
| : "350px"}; | |||
| padding: 0; | |||
| margin: 0 18px; | |||
| margin: 0 ${props => props.isAdmin ? "18px" : "0"}; | |||
| margin-top: 60px; | |||
| } | |||
| `; | |||
| @@ -0,0 +1,3 @@ | |||
| export const REGEXP_FIRST = /^[a-hA-H]/; | |||
| export const REGEXP_SECOND = /^[i-qI-Q]/; | |||
| export const REGEXP_THIRD = /^[r-zR-Z]/; | |||
| @@ -0,0 +1,62 @@ | |||
| import { useEffect, useMemo, useState } from "react"; | |||
| import { useDispatch, useSelector } from "react-redux"; | |||
| import { setFilteredCompany } from "../../store/actions/filters/filtersActions"; | |||
| import { fetchAllProfiles } from "../../store/actions/profile/profileActions"; | |||
| import { selectSelectedCompany } from "../../store/selectors/filtersSelectors"; | |||
| import { selectAllProfiles } from "../../store/selectors/profileSelectors"; | |||
| const useCompaniesFilter = () => { | |||
| const selectedCompaniesRedux = useSelector(selectSelectedCompany); | |||
| const dispatch = useDispatch(); | |||
| const allCompaniesRedux = useSelector(selectAllProfiles); | |||
| const [selectedCompaniesLocally, setSelectedCompaniesLocally] = useState([]); | |||
| useEffect(() => { | |||
| dispatch(fetchAllProfiles()); | |||
| }, []); | |||
| const selectedCompanies = useMemo(() => Array.isArray(selectedCompaniesRedux) ? selectedCompaniesRedux : []) | |||
| const allCompanies = useMemo(() => Array.isArray(allCompaniesRedux) ? selectedCompaniesRedux : []) | |||
| useEffect(() => { | |||
| setSelectedCompaniesLocally(selectedCompanies); | |||
| }, [selectedCompanies]); | |||
| const setSelectedCompanies = (companies, immediateApply = false) => { | |||
| setSelectedCompaniesLocally(companies); | |||
| if (immediateApply) { | |||
| dispatch(setFilteredCompany(companies)); | |||
| } | |||
| }; | |||
| const setSelectedCompaniesFromArray = (companies) => { | |||
| let companiesToPush = []; | |||
| companies.forEach((companyName) => { | |||
| companiesToPush.push( | |||
| allCompanies.find((p) => p.company.name === companyName) | |||
| ); | |||
| }); | |||
| setSelectedCompanies([...companiesToPush]); | |||
| }; | |||
| const apply = () => { | |||
| dispatch(setFilteredCompany(selectedCompaniesLocally)); | |||
| }; | |||
| const clear = () => { | |||
| setSelectedCompaniesLocally([]); | |||
| dispatch(setFilteredCompany([])); | |||
| }; | |||
| return { | |||
| selectedCompanies, | |||
| selectedCompaniesLocally, | |||
| setSelectedCompanies, | |||
| setSelectedCompaniesFromArray, | |||
| allCompanies, | |||
| apply, | |||
| clear, | |||
| }; | |||
| }; | |||
| export default useCompaniesFilter; | |||
| @@ -1,5 +1,6 @@ | |||
| import { useEffect, useMemo } from "react"; | |||
| import useCategoryFilter from "./useCategoryFilter"; | |||
| import useCompaniesFilter from "./useCompanyFilter"; | |||
| import useLocationsFilter from "./useLocationsFilter"; | |||
| import useSubcategoryFilter from "./useSubcategoryFilter"; | |||
| @@ -7,6 +8,7 @@ const useFilters = (clearAll = false) => { | |||
| const category = useCategoryFilter(); | |||
| const subcategory = useSubcategoryFilter(); | |||
| const locations = useLocationsFilter(); | |||
| const companies = useCompaniesFilter(); | |||
| useEffect(() => { | |||
| if (clearAll) { | |||
| @@ -24,12 +26,14 @@ const useFilters = (clearAll = false) => { | |||
| category.selectedCategoryLocally, | |||
| subcategory.selectedSubcategoryLocally, | |||
| locations.selectedLocationsLocally, | |||
| companies.selectedCompaniesLocally, | |||
| ]); | |||
| const apply = (immediatelyApply = false, applyAllFilters) => { | |||
| category.apply(); | |||
| subcategory.apply(); | |||
| locations.apply(); | |||
| companies.apply(); | |||
| if (immediatelyApply) applyAllFilters(); | |||
| }; | |||
| @@ -37,12 +41,14 @@ const useFilters = (clearAll = false) => { | |||
| category.clear(); | |||
| subcategory.clear(); | |||
| locations.clear(); | |||
| companies.clear(); | |||
| }; | |||
| return { | |||
| category, | |||
| subcategory, | |||
| locations, | |||
| companies, | |||
| numOfFiltersChosen, | |||
| apply, | |||
| clear, | |||
| @@ -28,7 +28,7 @@ const useLocationsFilter = () => { | |||
| locations.forEach((locationName) => { | |||
| locationsToPush.push(allLocations.find((p) => p.city === locationName)); | |||
| }); | |||
| setSelectedLocations([...locationsToPush]) | |||
| setSelectedLocations([...locationsToPush]); | |||
| }; | |||
| const apply = () => { | |||
| @@ -19,10 +19,10 @@ export default { | |||
| labelPassword: "Lozinka", | |||
| labelFirm: "Ime Firme", | |||
| labelPIB: "PIB", | |||
| labelPhone: "Telefon", | |||
| labelPhone: "Telefon (opciono)", | |||
| labelPhoneNumber: "Broj telefona", | |||
| labelLocation: "Lokacija", | |||
| labelWebsite: "Adresa Websajta", | |||
| labelLocation: "Lokacija (opciono)", | |||
| labelWebsite: "Adresa Websajta (opciono)", | |||
| logout: "Odjavi se", | |||
| next: "Sledeće", | |||
| nextPage: "Sledeća strana", | |||
| @@ -156,6 +156,13 @@ export default { | |||
| title: "Lokacija", | |||
| placeholder: "Pretraži gradove...", | |||
| }, | |||
| company: { | |||
| title: "Kompanija", | |||
| placeholder: "Pretraži kompanije...", | |||
| firstSort: "A-H", | |||
| secondSort: "I-Q", | |||
| thirdSort: "R-Z", | |||
| }, | |||
| }, | |||
| offer: { | |||
| title: "NASLOV", | |||
| @@ -220,6 +227,7 @@ export default { | |||
| finishedReviewTitle: "Hvala vam", | |||
| finishedReviewAltTitle: "na izdvojenom vremenu i datoj oceni!", | |||
| sortBy: "Sortiraj po", | |||
| offerTitle: "Proizvod:" | |||
| }, | |||
| messages: { | |||
| headerTitle: "Moje Ćaskanje", | |||
| @@ -455,7 +463,7 @@ export default { | |||
| fieldTitle: "Naslov", | |||
| placeholder: "Naziv kategorije...", | |||
| save: "Izmeni", | |||
| next: "Sledeća", | |||
| next: "Izmeni", | |||
| }, | |||
| add: { | |||
| title: "Nova Kategorija", | |||
| @@ -480,7 +488,7 @@ export default { | |||
| fieldTitle: "Naslov", | |||
| placeholder: "Naziv podkategorije...", | |||
| save: "Izmeni", | |||
| next: "Sledeća" | |||
| next: "Sledeća", | |||
| }, | |||
| add: { | |||
| title: "Nova Podkategorija", | |||
| @@ -495,6 +503,8 @@ export default { | |||
| noOfCompanies: "Broj firmi u gradu: ", | |||
| placeholder: "Pretražite lokacije...", | |||
| addLocation: "Dodaj lokaciju", | |||
| cancel: "Otkaži", | |||
| delete: "Obriši", | |||
| reassuranceDelete: | |||
| "Da li ste sigurni da želite da obrišete odabranu lokaciju?", | |||
| edit: { | |||
| @@ -502,6 +512,7 @@ export default { | |||
| fieldTitle: "Naslov", | |||
| placeholder: "Naziv lokacije...", | |||
| save: "Izmeni", | |||
| next: "Izmeni", | |||
| }, | |||
| add: { | |||
| title: "Nova Lokacija", | |||
| @@ -530,7 +541,7 @@ export default { | |||
| }, | |||
| review: { | |||
| title: "Brisanje Komentara", | |||
| confirm: "Obriši komentar" | |||
| } | |||
| confirm: "Obriši komentar", | |||
| }, | |||
| }, | |||
| }; | |||
| @@ -82,6 +82,7 @@ const AdminCategoriesPage = () => { | |||
| setOpenedEditModal={setOpenedAddModal} | |||
| type={"categories"} | |||
| method="add" | |||
| showSecondButton | |||
| /> | |||
| )} | |||
| </> | |||
| @@ -80,6 +80,7 @@ const AdminLocationsPage = () => { | |||
| setOpenedEditModal={setOpenedAddModal} | |||
| type={"locations"} | |||
| method="add" | |||
| showSecondButton | |||
| /> | |||
| )} | |||
| </> | |||
| @@ -121,6 +121,7 @@ const AdminSubcategoriesPage = () => { | |||
| setOpenedEditModal={setOpenedAddModal} | |||
| type="subcategories" | |||
| method="add" | |||
| showSecondButton | |||
| /> | |||
| )} | |||
| </> | |||
| @@ -6,6 +6,7 @@ export const CLEAR_FILTERS = createClearType(FILTERS_SCOPE); | |||
| export const SET_CATEGORY = createSetType("FILTERS_SET_CATEGORY"); | |||
| export const SET_SUBCATEGORY = createSetType("FILTERS_SET_SUBCATEGORY"); | |||
| export const SET_LOCATIONS = createSetType("FILTERS_SET_LOCATIONS"); | |||
| export const SET_COMPANY = createSetType("FILTERS_SET_COMPANY"); | |||
| export const SET_SORT_OPTION = createSetType("FILTERS_SET_SORT_OPTION"); | |||
| export const SET_IS_APPLIED = createSetType("FILTERS_SET_IS_APPLIED"); | |||
| export const SET_QUERY_STRING = createSetType("FILTERS_SET_QUERY_STRING"); | |||
| @@ -1,6 +1,7 @@ | |||
| import { | |||
| CLEAR_FILTERS, | |||
| SET_CATEGORY, | |||
| SET_COMPANY, | |||
| SET_FILTERS, | |||
| SET_HEADER_STRING, | |||
| SET_IS_APPLIED, | |||
| @@ -35,6 +36,10 @@ export const setFilteredLocations = (payload) => ({ | |||
| type: SET_LOCATIONS, | |||
| payload, | |||
| }); | |||
| export const setFilteredCompany = (payload) => ({ | |||
| type: SET_COMPANY, | |||
| payload, | |||
| }); | |||
| export const setFilteredSortOption = (payload) => ({ | |||
| type: SET_SORT_OPTION, | |||
| payload, | |||
| @@ -1,6 +1,7 @@ | |||
| import { | |||
| CLEAR_FILTERS, | |||
| SET_CATEGORY, | |||
| SET_COMPANY, | |||
| SET_FILTERS, | |||
| SET_HEADER_STRING, | |||
| SET_IS_APPLIED, | |||
| @@ -17,6 +18,7 @@ const initialState = { | |||
| category: null, | |||
| subcategory: null, | |||
| locations: [], | |||
| company: [], | |||
| sortOption: null, | |||
| isApplied: false, | |||
| queryString: "", | |||
| @@ -24,6 +26,7 @@ const initialState = { | |||
| categoryString: "", | |||
| subcategoryString: "", | |||
| locationsString: "", | |||
| companyString: "", | |||
| text: "", | |||
| }, | |||
| searchString: "", | |||
| @@ -38,6 +41,7 @@ export default createReducer( | |||
| [SET_CATEGORY]: setFilteredCategory, | |||
| [SET_SUBCATEGORY]: setFilteredSubcategory, | |||
| [SET_LOCATIONS]: setFilteredLocations, | |||
| [SET_COMPANY]: setFilteredCompany, | |||
| [SET_SORT_OPTION]: setFilteredSortOption, | |||
| [SET_IS_APPLIED]: setIsAppliedStatus, | |||
| [SET_HEADER_STRING]: setHeaderString, | |||
| @@ -97,6 +101,15 @@ function setFilteredLocations(state, { payload }) { | |||
| }, | |||
| }; | |||
| } | |||
| function setFilteredCompany(state, { payload }) { | |||
| return { | |||
| ...state, | |||
| filters: { | |||
| ...state.filters, | |||
| company: payload, | |||
| }, | |||
| }; | |||
| } | |||
| function setFilteredSortOption(state, { payload }) { | |||
| return { | |||
| ...state, | |||
| @@ -10,7 +10,7 @@ import { | |||
| function* fetchLocations() { | |||
| try { | |||
| const { data } = yield call(attemptFetchLocations); | |||
| yield put(setLocations(data)); | |||
| yield put(setLocations(data.value)); | |||
| yield put(fetchLocationsSuccess()); | |||
| } catch (e) { | |||
| yield put(fetchLocationsError()); | |||
| @@ -18,6 +18,10 @@ export const selectSelectedLocations = createSelector( | |||
| filtersSelector, | |||
| (state) => state.filters.locations | |||
| ); | |||
| export const selectSelectedCompany = createSelector( | |||
| filtersSelector, | |||
| (state) => state.filters.company | |||
| ); | |||
| export const selectSelectedSortOption = createSelector( | |||
| filtersSelector, | |||
| (state) => state.filters.sortOption | |||
| @@ -31,7 +31,7 @@ export function formatDateTimeLocale(date) { | |||
| const dayCreated = | |||
| date.getDate() < 10 ? "0" + date.getDate() : date.getDate(); | |||
| const monthCreated = | |||
| date.getMonth() < 10 ? "0" + (date.getMonth() + 1) : date.getMonth() + 1; | |||
| date.getMonth() < 9 ? "0" + (date.getMonth() + 1) : date.getMonth() + 1; | |||
| const yearCreated = date.getFullYear(); | |||
| const hourCreated = | |||
| date.getHours() < 10 ? "0" + date.getHours() : date.getHours(); | |||
| @@ -51,7 +51,7 @@ export function formatDateLocale(date) { | |||
| const dayCreated = | |||
| date.getDate() < 10 ? "0" + date.getDate() : date.getDate(); | |||
| const monthCreated = | |||
| date.getMonth() < 10 ? "0" + (date.getMonth() + 1) : date.getMonth() + 1; | |||
| date.getMonth() < 9 ? "0" + (date.getMonth() + 1) : date.getMonth() + 1; | |||
| const yearCreated = date.getFullYear(); | |||
| return `${dayCreated}.${monthCreated}.${yearCreated}.`; | |||
| } | |||
| @@ -0,0 +1,5 @@ | |||
| export const filterCompanies = (data, regexp) => { | |||
| return data.filter((company) => { | |||
| return regexp.test(company?.company?.name); | |||
| }); | |||
| }; | |||