瀏覽代碼

Added useFilters custom hook

feature/code-cleanup-joca
Djordje Mitrovic 3 年之前
父節點
當前提交
9fcc692ce0

+ 13
- 93
src/components/Cards/FilterCard/FilterCard.js 查看文件

@@ -1,4 +1,4 @@
import React, { useState } from "react";
import React, { useEffect, useState } from "react";
import PropTypes from "prop-types";
import {
ContentContainer,
@@ -11,69 +11,32 @@ import { ReactComponent as Subcategory } from "../../../assets/images/svg/subcat
import { ReactComponent as Category } from "../../../assets/images/svg/category.svg";
import { ReactComponent as CategoryChosen } from "../../../assets/images/svg/category-chosen.svg";
import { ReactComponent as Location } from "../../../assets/images/svg/location.svg";

import Link from "../../Link/Link";
import { PrimaryButton } from "../../Buttons/PrimaryButton/PrimaryButton";
import FilterCheckboxDropdown from "./FilterDropdown/Checkbox/FilterCheckboxDropdown";
import Mockupdata from "./Mockupdata";
// import { useState } from "react";
import FilterRadioDropdown from "./FilterDropdown/Radio/FilterRadioDropdown";
import { useHistory } from "react-router-dom";
import { HOME_PAGE } from "../../../constants/pages";
import qs from "query-string";
import { useTranslation } from "react-i18next";
import selectedTheme from "../../../themes";
import useFilters from "../../../hooks/useFilters";

const FilterCard = () => {
const history = useHistory();
const { t } = useTranslation();
const [isOpened, setIsOpened] = useState(false);
const [isDisabled, setIsDisabled] = useState(true);

const filters = useFilters();

// useEffect(() => {
// const queryString = history.location.search.substring(1);
// const queryObject = qs.parse(queryString);
// if (queryObject.category) {
// setSelectedCategory(
// Mockupdata[1].find(
// (item) => item.string === queryObject.category.toString()
// ).id
// );
// }
// if (queryObject.subcategory) {
// setSelectedSubcategory(
// Mockupdata[1].find(
// (item) => item.string === queryObject.subcategory.toString()
// ).id
// );
// }
// if (queryObject.city) {
// let filters = [];
// if (Array.isArray(queryObject.city)) {
// queryObject.city.forEach((item) => {
// filters.push(Mockupdata[0].find((p) => p.string === item).id);
// });
// } else {
// filters.push(
// Mockupdata[0].find((p) => p.string === queryObject.city).id
// );
// }
// setfilters.selectedLocations([...filters]);
// }
// }, []);

const handleSelectCategory = (category) => {
filters.setSelectedCategory(category);
filters.setSelectedSubcategory();
if (category?._id === 0) {
useEffect(() => {
if (!filters.selectedCategory || filters.selectedCategory?._id === 0) {
setIsOpened(false);
setIsDisabled(true);
} else {
setIsDisabled(false);
}
}, [filters.selectedCategory])

const handleSelectCategory = (category) => {
filters.setSelectedCategory(category);
filters.setSelectedSubcategory();
}

const handleOpen = () => {
@@ -81,54 +44,10 @@ const FilterCard = () => {
}

const handleFilters = () => {
let queryObject = {};
if (filters.selectedCategory !== 0) {
queryObject = {
category: Mockupdata[1].find(
(item) => item.id.toString() === filters.selectedCategory.toString()
).string,
};
if (filters.selectedSubcategory !== 0) {
queryObject = {
...queryObject,
subcategory: Mockupdata[1].find(
(item) =>
item.id.toString() === filters.selectedSubcategory.toString()
).string,
};
}
}
if (filters.selectedLocations.length > 0) {
let arrayObject = [];
filters.selectedLocations.forEach((item) => {
arrayObject.push(
Mockupdata[0].find((p) => p.id.toString() === item.toString()).string
);
});
queryObject = { ...queryObject, city: arrayObject };
}
const queryString = qs.stringify(queryObject);
history.push({
pathname: HOME_PAGE,
search: "?" + queryString,
});
window.scrollTo({
top: 0,
behavior: "smooth",
});
filters.applyFilters();
};
const clearFilters = () => {
filters.setSelectedLocations([]);
filters.setSelectedCategory(0);
filters.setSelectedSubcategory(0);
history.push({
pathname: HOME_PAGE,
search: "",
});
window.scrollTo({
top: 0,
behavior: "smooth",
});
filters.clearFilters();
};

return (
@@ -147,7 +66,7 @@ const FilterCard = () => {
<ContentContainer>
{/* Categories */}
<FilterRadioDropdown
data={[...filters.categories]}
data={[...filters?.categories]}
icon={
filters.selectedCategory?.name ? <CategoryChosen /> : <Category />
}
@@ -186,7 +105,7 @@ const FilterCard = () => {
<FilterCheckboxDropdown
searchPlaceholder={t("filters.location.placeholder")}
data={[...filters.locations]}
filters={filters.selectedLocations}
filters={[...filters.selectedLocations]}
icon={<Location />}
title={t("filters.location.title")}
setItemsSelected={filters.setSelectedLocations}
@@ -215,6 +134,7 @@ const FilterCard = () => {

FilterCard.propTypes = {
children: PropTypes.node,
filters: PropTypes.any,
};

export default FilterCard;

+ 17
- 19
src/components/Cards/FilterCard/FilterDropdown/Checkbox/FilterCheckboxDropdown.js 查看文件

@@ -24,11 +24,7 @@ const FilterCheckboxDropdown = (props) => {

useEffect(() => {
setDataToShow([...data]);
}, []);
useEffect(() => {
console.log("props.filters: ", props.filters);
}, [props.filters])

}, [data]);
useEffect(() => {
if (toSearch.length > 0) {
setDataToShow(
@@ -38,7 +34,6 @@ const FilterCheckboxDropdown = (props) => {
);
} else {
setDataToShow([...data]);
}
}, [toSearch]);

@@ -46,12 +41,10 @@ const FilterCheckboxDropdown = (props) => {
if (props.oneValueAllowed) {
props.setItemsSelected[item.id];
} else {
if (props.filters.includes(item.id)) {
props.setItemsSelected((itemsSelected) => [
...itemsSelected.filter((p) => p !== item.id),
]);
if (props.filters.includes(item)) {
props.setItemsSelected([...props.filters.filter((p) => p !== item)]);
} else {
props.setItemsSelected((itemsSelected) => [...itemsSelected, item.id]);
props.setItemsSelected([...props.filters, item]);
}
}
};
@@ -80,14 +73,19 @@ const FilterCheckboxDropdown = (props) => {
fullWidth
setIsOpened={setIsOpened}
toggleIconStyles={{
backgroundColor: isOpened ? "white" : selectedTheme.primaryIconBackgroundColor,
backgroundColor: isOpened
? "white"
: selectedTheme.primaryIconBackgroundColor,
}}
headerOptions={
<React.Fragment>
<SelectedItemsContainer>
{props.filters.map((item) => (
<SelectedItem key={item} onClick={() => handleDelete(item)}>
{data.find((p) => p.id === item).string}
<SelectedItem key={item.city} onClick={() => handleDelete(item)}>
{
data.find((p) => p.city.toString() === item.city.toString())
?.city
}
<Close style={{ position: "relative", top: "3px" }} />
</SelectedItem>
))}
@@ -118,12 +116,12 @@ const FilterCheckboxDropdown = (props) => {
}
>
{dataToShow.map((item) => (
<DropdownItem key={item.id}>
<DropdownItem key={item.city}>
<CheckBox
leftText={item.string}
rightText={item.numberOfProducts}
value={item.id}
checked={props.filters.includes(item.id)}
leftText={item.city}
rightText={item.offerCount}
value={item}
checked={props.filters.includes(item)}
onChange={() => handleChange(item)}
fullWidth
/>

+ 8
- 5
src/components/Cards/FilterCard/FilterDropdown/Radio/FilterRadioDropdown.js 查看文件

@@ -95,7 +95,7 @@ const FilterRadioDropdown = (props) => {
>
<RadioGroup>
{props.firstOption && (
<DropdownItem key={0}>
<DropdownItem>
<RadioButton
value={props.firstOption.value}
label={props.firstOption.label}
@@ -107,13 +107,16 @@ const FilterRadioDropdown = (props) => {
</DropdownItem>
)}
{dataToShow.map((item) => {
console.log("item: ", item);
{/* console.log("item: ", item); */}
return (
<DropdownItem key={item.name} onClick={() => props.setSelected(item)}>
<DropdownItem
key={item.name}
onClick={() => props.setSelected(item)}
>
<RadioButton
value={item}
label={item.name ? item.name : item}
// number={item.numberOfProducts}
number={item.offerCount}
fullWidth
checked={
JSON.stringify(props.selected) === JSON.stringify(item)
@@ -137,7 +140,7 @@ FilterRadioDropdown.propTypes = {
fullWidth: PropTypes.bool,
searchPlaceholder: PropTypes.string,
setSelected: PropTypes.func,
selected: PropTypes.number,
selected: PropTypes.any,
firstOption: PropTypes.any,
disabled: PropTypes.bool,
open: PropTypes.bool,

+ 1
- 9
src/components/Cards/OfferCard/OfferCard.js 查看文件

@@ -17,12 +17,10 @@ import {
OfferImage,
OfferInfo,
OfferLocation,
OfferPackage,
OfferTitle,
OfferViews,
} from "./OfferCard.styled";
import { ReactComponent as Category } from "../../../assets/images/svg/category.svg";
import { ReactComponent as Quantity } from "../../../assets/images/svg/quantity.svg";
import { ReactComponent as Eye } from "../../../assets/images/svg/eye-striked.svg";
import { ReactComponent as Message } from "../../../assets/images/svg/mail.svg";
import selectedTheme from "../../../themes";
@@ -44,17 +42,11 @@ const OfferCard = (props) => {
</DetailIcon>
<DetailText>{props.offer.category.name}</DetailText>
</OfferCategory>
<OfferPackage>
<DetailIcon color="black" component="span" size="16px">
<Quantity width={"12px"} height={"12px"} />
</DetailIcon>
<DetailText>{props.offer.quantity} pakovanja</DetailText>
</OfferPackage>
<OfferViews>
<DetailIcon color="black" component="span" size="16px">
<Eye width={"12px"} height={"11px"} />
</DetailIcon>
<DetailText>{props.offer.views.viewers.length} pregleda</DetailText>
<DetailText>{props.offer.views.viewers.length}</DetailText>
</OfferViews>
</OfferDetails>
</OfferInfo>

+ 1
- 1
src/components/CheckBox/CheckBox.js 查看文件

@@ -55,7 +55,7 @@ CheckBox.propTypes = {
rightText: PropTypes.oneOfType([PropTypes.string, PropTypes.number]),
maxWidth: PropTypes.string,
checked: PropTypes.bool,
value: PropTypes.number,
value: PropTypes.any,
onChange: PropTypes.func,
containerStyle: PropTypes.any,
checkBoxStyle: PropTypes.any,

+ 1
- 1
src/components/CheckBox/Label.js 查看文件

@@ -11,7 +11,7 @@ export const Label = (props) => {
className={props.className}
>
<LeftLabel style={props.leftTextStyle}>{props.leftText}</LeftLabel>
{props.rightText && <RightLabel>{props.rightText}</RightLabel>}
{props.rightText !== null ? <RightLabel>{props.rightText}</RightLabel> : <></>}
</LabelContainer>
);
};

+ 58
- 56
src/components/MarketPlace/Header/Header.js 查看文件

@@ -1,10 +1,10 @@
import React, { useEffect, useState } from "react";
import React from "react";
import PropTypes from "prop-types";
import {
HeaderButton,
HeaderButtons,
HeaderContainer,
HeaderLocation,
// HeaderLocation,
HeaderOptions,
HeaderSelect,
IconStyled,
@@ -13,11 +13,11 @@ import { ReactComponent as GridSquare } from "../../../assets/images/svg/offer-g
import { ReactComponent as GridLine } from "../../../assets/images/svg/offer-grid-line.svg";
import { ReactComponent as Down } from "../../../assets/images/svg/down-arrow.svg";
import selectedTheme from "../../../themes";
import { useSelector } from "react-redux";
import { selectFilters } from "../../../store/selectors/filtersSelectors";
import Mockupdata from "../../Cards/FilterCard/Mockupdata";
// import { useSelector } from "react-redux";
// import { selectFilters } from "../../../store/selectors/filtersSelectors";
// import Mockupdata from "../../Cards/FilterCard/Mockupdata";
import Option from "../../Select/Option/Option";
import { useHistory, useLocation, useRouteMatch } from "react-router-dom";
// import { useHistory, useLocation, useRouteMatch } from "react-router-dom";
import { sortEnum } from "../../../enums/sortEnum";

const DownArrow = (props) => (
@@ -27,55 +27,53 @@ const DownArrow = (props) => (
);

const Header = (props) => {
const [categoryString, setCategoryString] = useState("");
const [filtersString, setFiltersString] = useState("");
const { category, cities } = useSelector(selectFilters);
const history = useHistory();
const location = useLocation();
const routeMatch = useRouteMatch();
// const [categoryString, setCategoryString] = useState("");
// const [filtersString, setFiltersString] = useState("");
// const { category, cities } = useSelector(selectFilters);
// const history = useHistory();
// const location = useLocation();
// const routeMatch = useRouteMatch();
const filters = props.filters;

useEffect(() => {
let categorystring = "";
if (category) {
categorystring = Mockupdata[1].find(
(item) => item.id === category
).string;
} else {
categorystring = "Sve kategorije";
}
let filtersstring = " | ";
if (cities) {
cities.forEach((item) => {
filtersstring = filtersstring.concat(
Mockupdata[0].find((p) => p.id === item).string + ", "
);
});
filtersstring = filtersstring.substring(0, filtersstring.length - 2);
}
console.log("categorysstring: ", categorystring);
console.log(filtersstring);
setCategoryString(categorystring);
setFiltersString(filtersstring);
}, [category, cities]);
// useEffect(() => {
// let categorystring = "";
// if (category) {
// categorystring = Mockupdata[1].find(
// (item) => item.id === category
// ).string;
// } else {
// categorystring = "Sve kategorije";
// }
// let filtersstring = " | ";
// if (cities) {
// cities.forEach((item) => {
// filtersstring = filtersstring.concat(
// Mockupdata[0].find((p) => p.id === item).string + ", "
// );
// });
// filtersstring = filtersstring.substring(0, filtersstring.length - 2);
// }
// console.log("categorysstring: ", categorystring);
// console.log(filtersstring);
// setCategoryString(categorystring);
// setFiltersString(filtersstring);
// }, [category, cities]);

const handleChangeSelect = (value) => {
const handleChangeSelect = (event) => {
let chosenOption;
for (const sortOption in sortEnum) {
console.log(sortEnum[sortOption])
if (sortEnum[sortOption].value === value) {
// console.log(sortEnum[sortOption])
if (sortEnum[sortOption].value === event.target.value) {
chosenOption = sortEnum[sortOption];
// console.log(chosenOption)
filters.setSelectedSortOption(chosenOption);
}
}

console.log(location);
console.log(history);
console.log(chosenOption);
console.log(routeMatch)
}
};

return (
<HeaderContainer>
<HeaderLocation>{categoryString + filtersString} </HeaderLocation>
{/* <HeaderLocation>{categoryString + filtersString} </HeaderLocation> */}
<HeaderOptions>
<HeaderButtons>
<HeaderButton
@@ -100,23 +98,27 @@ const Header = (props) => {
</HeaderButton>
</HeaderButtons>
<HeaderSelect
defaultValue={0}
defaultValue={filters.selectedSortOption ? filters.selectedSortOption.value : 0}
IconComponent={DownArrow}
width="209px"
height="34px"
onChange={handleChangeSelect}
>
{Object.keys(sortEnum).map((property) => {
console.log(sortEnum[property])
console.log(sortEnum[property]);
console.log(filters.selectedSortOption)
return (
<Option
value={sortEnum[property].value}
key={sortEnum[property].value}
style={{ display: sortEnum[property].value === 0 ? "none" : "flex" }}
>
{sortEnum[property].mainText}
</Option>
)})}
<Option
value={sortEnum[property].value}
key={sortEnum[property].value}
style={{
display: sortEnum[property].value === 0 ? "none" : "flex",
}}
>
{sortEnum[property].mainText}
</Option>
);
})}
</HeaderSelect>
</HeaderOptions>
</HeaderContainer>
@@ -127,7 +129,7 @@ Header.propTypes = {
children: PropTypes.node,
setIsGrid: PropTypes.func,
isGrid: PropTypes.bool,
filters: PropTypes.array,
filters: PropTypes.any,
category: PropTypes.string,
};
Header.defaultProps = {

+ 4
- 26
src/components/MarketPlace/MarketPlace.js 查看文件

@@ -1,39 +1,17 @@
import React, { useEffect, useState } from "react";
import React, { useState } from "react";
import PropTypes from "prop-types";
import { MarketPlaceContainer } from "./MarketPlace.styled";
import Header from "./Header/Header";
import Offers from "./Offers/Offers";
import { useDispatch, useSelector } from "react-redux";
import { fetchCategories } from "../../store/actions/categories/categoriesActions";
import { fetchLocations } from "../../store/actions/locations/locationsActions";
import { selectSubcategories } from "../../store/selectors/categoriesSelectors";
import useFilters from "../../hooks/useFilters";

const MarketPlace = () => {
const [isGrid, setIsGrid] = useState(false);
const dispatch = useDispatch();
const categories = useSelector(selectSubcategories("Automobili"));
useEffect(() => {
dispatch(fetchCategories());
dispatch(fetchLocations());
}, []);
useEffect(() => {
let newSubcategories = [];

if (categories) {
for (let i = 0; i < categories.length; i++) {
let subcategoryString = "";
Object.keys(categories[i]).forEach(item => {
subcategoryString += categories[i][item]
})
newSubcategories.push(subcategoryString)
}
}
console.log("selektor: ", newSubcategories);
}, [categories]);
const filters = useFilters();

return (
<MarketPlaceContainer>
<Header isGrid={isGrid} setIsGrid={setIsGrid} />
<Header isGrid={isGrid} setIsGrid={setIsGrid} filters={filters} />
<Offers isGrid={isGrid} />
</MarketPlaceContainer>
);

+ 20
- 4
src/components/MarketPlace/Offers/Offers.js 查看文件

@@ -1,4 +1,4 @@
import React, { useEffect } from "react";
import React, { useEffect, useRef} from "react";
import PropTypes from "prop-types";
import { OffersContainer } from "./Offers.styled";
import OfferCard from "../../Cards/OfferCard/OfferCard";
@@ -11,6 +11,20 @@ import { selectOffers } from "../../../store/selectors/offersSelectors";

const Offers = (props) => {

const offersRef = useRef(null);

useEffect(() => {
const listener = () => {
// console.log(window.scrollY);
// console.log(window.document.body.offsetHeight);
if (window.scrollY > window.document.body.offsetHeight * 0.7) {
console.log('sad treba')
}
}
window.addEventListener('scroll', listener)
return () => window.removeEventListener('scroll', listener);
}, [])

// Market place nije zavrsen
// Koriste se Mockup podaci
const dispatch = useDispatch();
@@ -18,12 +32,14 @@ const Offers = (props) => {

useEffect(() => {
dispatch(fetchOffers());
}, [])
}, []);

return (
<OffersContainer>
<OffersContainer ref={offersRef} onScroll={() => console.log('proba')} onClick={() => console.log(offersRef)}>
{offers.map((item) => {
return <OfferCard key={item._id} offer={item} halfwidth={props.isGrid} />;
return (
<OfferCard key={item._id} offer={item} halfwidth={props.isGrid} />
);
})}
</OffersContainer>
);

+ 1
- 1
src/components/Radio/Button/RadioButton.js 查看文件

@@ -37,7 +37,7 @@ const RadioButton = (props) => {

RadioButton.propTypes = {
children: PropTypes.node,
value: PropTypes.number,
value: PropTypes.any,
label: PropTypes.string,
number: PropTypes.number,
fullWidth: PropTypes.bool,

+ 6
- 1
src/components/Select/Option/Option.js 查看文件

@@ -5,7 +5,7 @@ import { OptionIcon, OptionStyled } from './Option.styled'
const Option = props => {
console.log(props)
return (
<OptionStyled {...props}>
<OptionStyled {...props} value={props.value} >
{props.startIcon ? (
<OptionIcon color={props.color}>
{props.startIcon}
@@ -22,6 +22,11 @@ Option.propTypes = {
children: PropTypes.node,
color: PropTypes.any,
startIcon: PropTypes.any,
value: PropTypes.any,
// selected: PropTypes.bool,
}
Option.defaultProps = {
// selected: true
}

export default Option

+ 8
- 4
src/enums/sortEnum.js 查看文件

@@ -1,18 +1,22 @@
export const sortEnum = {
INITIAL: {
value: 0,
mainText: "Sortiraj po"
mainText: "Sortiraj po",
queryString: ""
},
POPULAR: {
value: 1,
mainText: "Najpopularnije"
mainText: "Najpopularnije",
queryString: "popular"
},
NEW: {
value: 2,
mainText: "Najnovije"
mainText: "Najnovije",
queryString: "newest"
},
OLD: {
value: 3,
mainText: "Najstarije"
mainText: "Najstarije",
queryString: "oldest"
}
}

+ 168
- 45
src/hooks/useFilters.js 查看文件

@@ -1,69 +1,188 @@
import { useEffect, useState } from "react";
import { useDispatch } from "react-redux";
import { useSelector } from "react-redux";
import { useHistory } from "react-router-dom";
import { sortEnum } from "../enums/sortEnum";
import { fetchCategories } from "../store/actions/categories/categoriesActions";
import {
setFilteredCategory,
setFilteredLocations,
setFilteredSortOption,
setFilteredSubcategory,
} from "../store/actions/filters/filtersActions";
import { fetchLocations } from "../store/actions/locations/locationsActions";
import {
selectCategories,
selectSubcategories,
} from "../store/selectors/categoriesSelectors";
// import qs from "query-string";
import {
selectSelectedCategory,
selectSelectedLocations,
selectSelectedSortOption,
selectSelectedSubcategory,
} from "../store/selectors/filtersSelectors";
import qs from "query-string";
import { selectLocations } from "../store/selectors/locationsSelectors";
import { fetchOffers } from "../store/actions/offers/offersActions";
import { HOME_PAGE } from "../constants/pages";

const useFilters = () => {
const [selectedCategory, setSelectedCategory] = useState();
const [selectedSubcategory, setSelectedSubcategory] = useState();
const [selectedLocations, setSelectedLocations] = useState([]);
const [selectedSortOption, setSelectedSortOption] = useState({});
const [queryString, setQueryString] = useState();
const selectedCategory = useSelector(selectSelectedCategory);
const selectedSubcategory = useSelector(selectSelectedSubcategory);
const selectedLocations = useSelector(selectSelectedLocations);
const selectedSortOption = useSelector(selectSelectedSortOption);
const [loaded, setLoadedStatus] = useState(false);
const history = useHistory();
const categories = useSelector(selectCategories);
const subcategories = useSelector(
selectSubcategories(selectedCategory?.name)
);
const locations = useSelector(selectLocations);
const sortOptions = sortEnum;
const dispatch = useDispatch();
useEffect(() => {
dispatch(fetchCategories());
dispatch(fetchLocations());
}, []);
if (!loaded) {
dispatch(fetchCategories());
dispatch(fetchLocations());
setLoadedStatus(true);
}
}, [categories, locations]);
useEffect(() => {
console.log("selectedCategory changed: ", selectedCategory);
}, [selectedCategory])
// useEffect(() => {
// if (categories && locations) {
// const queryString = history.location.search.substring(1);
// const queryObject = qs.parse(queryString);
// let category;
// if (queryObject.category) {
// category = categories.find(
// (item) => item.mainText === queryObject.category.toString()
// );
// setSelectedCategory(category);
// }
// if (queryObject.subcategory) {
// setSelectedSubcategory(
// category.subcategories.find(
// (item) => item.mainText === queryObject.subcategory.toString()
// ).id
// );
// }
// if (queryObject.city) {
// let filters = [];
// if (Array.isArray(queryObject.city)) {
// queryObject.city.forEach((item) => {
// filters.push(Mockupdata[0].find((p) => p.string === item).id);
// });
// } else {
// filters.push(
// Mockupdata[0].find((p) => p.string === queryObject.city).id
// );
// }
// setAppliedFilters([...filters]);
// }
// }
// }, [categories, locations]);
if (categories && locations) {
const queryString = history.location.search.substring(1);
const queryObject = qs.parse(queryString);
let category;
if (queryObject.category) {
category = categories.find(
(item) => item.name === queryObject.category.toString()
);
setSelectedCategory(category);
}
if (queryObject.subcategory) {
setSelectedSubcategory(
category.subcategories.find(
(item) => item.toString() === queryObject.subcategory.toString()
)
);
}
if (queryObject.location) {
let locationsToPush = [];
if (Array.isArray(queryObject.location)) {
queryObject.location.forEach((item) => {
locationsToPush.push(locations.find((p) => p.city === item));
});
} else {
locationsToPush.push(
locations.find((p) => p.city === queryObject.location)
);
}
setSelectedLocations([...locationsToPush]);
}
// For future changes if needed
if (queryObject._des_date || queryObject._des_popular) {
if (queryObject._des_date === false) {
setSelectedSortOption(sortOptions.OLD);
}
if (queryObject._des_date === true) {
setSelectedSortOption(sortOptions.NEW);
}
if (queryObject._des_popular === true) {
setSelectedSortOption(sortOptions.POPULAR);
}
}
// if (queryObject.sortBy) {
// if (queryObject.sortBy === "oldest") {
// setSelectedSortOption(sortOptions.OLD);
// }
// if (queryObject.sortBy === "newest") {
// setSelectedSortOption(sortOptions.NEW);
// }
// if (queryObject.sortBy === "popular") {
// setSelectedSortOption(sortOptions.POPULAR);
// }
// }
}
}, [history.location.search]);

const clearFilters = () => {
setSelectedLocations([]);
setSelectedSubcategory();
setSelectedCategory();
// history.push({
// pathname: HOME_PAGE,
// search: "",
// });
// window.scrollTo({
// top: 0,
// behavior: "smooth",
// });
};

useEffect(() => {
console.log("subcategories: ", subcategories);
}, [subcategories]);
let qsArray = [];
if (selectedCategory && selectedCategory?._id !== 0) {
qsArray.push("category=" + encodeURIComponent(selectedCategory.name));
}
if (selectedSubcategory && selectedSubcategory?._id !== 0) {
qsArray.push("subcategory=" + encodeURIComponent(selectedSubcategory));
}
if (selectedLocations && selectedLocations?.length > 0) {
selectedLocations.forEach((location) => {
qsArray.push("location=" + encodeURIComponent(location.city));
});
}
if (selectedSortOption) {
let _des_date = null;
let _des_popular = null;
if (selectedSortOption === sortOptions.NEW) {
_des_date = true;
}
if (selectedSortOption === sortOptions.OLD) {
_des_date = false;
}
if (selectedSortOption === sortOptions.POPULAR) {
_des_popular = true;
}
if (_des_date !== null)
qsArray.push("_des_date=" + encodeURIComponent(_des_date));
if (_des_popular !== null)
qsArray.push("_des_popular=" + encodeURIComponent(_des_popular));
}
let qsStringFromArray = "?" + qsArray.join("&");
console.log(qsStringFromArray);
setQueryString(qsStringFromArray);
}, [
selectedCategory,
selectedLocations,
selectedSortOption,
selectedSubcategory,
]);

const applyFilters = () => {
dispatch(fetchOffers(queryString));
history.push({
pathname: HOME_PAGE,
search: queryString,
});
window.scrollTo({
top: 0,
behavior: "smooth",
});
};

const setSelectedCategory = (payload) => {
dispatch(setFilteredCategory(payload));
};
const setSelectedSubcategory = (payload) => {
dispatch(setFilteredSubcategory(payload));
};
const setSelectedLocations = (payload) => {
dispatch(setFilteredLocations(payload));
};
const setSelectedSortOption = (payload) => {
dispatch(setFilteredSortOption(payload));
};
return {
selectedCategory,
setSelectedCategory,
@@ -76,6 +195,10 @@ const useFilters = () => {
categories,
subcategories,
locations,
sortOptions,
queryString,
applyFilters,
clearFilters,
};
};


+ 47
- 47
src/pages/HomePage/HomePageMUI.js 查看文件

@@ -1,64 +1,64 @@
import React, { useEffect } from "react";
import React from "react";
import Navbar from "../../components/MUI/NavbarComponent";
// import FilterCard from "../../components/Cards/FilterCard/FilterCard";
import { HomePageContainer } from "./HomePage.styled";
// import MarketPlace from "../../components/MarketPlace/MarketPlace";
// import MainLayout from "../../layouts/MainLayout/MainLayout";
import { useDispatch } from "react-redux";
// import { logoutUser } from "../../store/actions/login/loginActions";
import Mockupdata from "../../components/Cards/FilterCard/Mockupdata";
import qs from "query-string";
import { useHistory } from "react-router-dom";
import { setFilters } from "../../store/actions/filters/filtersActions";
// import { useDispatch } from "react-redux";
// // import { logoutUser } from "../../store/actions/login/loginActions";
// import Mockupdata from "../../components/Cards/FilterCard/Mockupdata";
// import qs from "query-string";
// import { useHistory } from "react-router-dom";
// import { setFilters } from "../../store/actions/filters/filtersActions";
// import ProfileLayout from "../../layouts/ProfileLayout/ProfileLayout";
import FilterCard from "../../components/Cards/FilterCard/FilterCard";
import MainLayout from "../../layouts/MainLayout/MainLayout";
import MarketPlace from "../../components/MarketPlace/MarketPlace";

const HomePage = () => {
const dispatch = useDispatch();
// const dispatch = useDispatch();

const history = useHistory();
useEffect(() => {
let category = null, subcategory = null, cities = [], _des_date = false, _des_popular = false, page, size;
const queryString = history.location.search.substring(1);
const queryObject = qs.parse(queryString);
// const history = useHistory();
// useEffect(() => {
// let category = null, subcategory = null, cities = [], _des_date = false, _des_popular = false, page, size;
// const queryString = history.location.search.substring(1);
// const queryObject = qs.parse(queryString);

if (queryObject.category) {
category = Mockupdata[1].find(
(item) => item.string === queryObject.category.toString()
).id;
}
if (queryObject.subcategory) {
subcategory = Mockupdata[1].find(
(item) => item.string === queryObject.subcategory.toString()
).id;
}
if (queryObject.city) {
if (Array.isArray(queryObject.city)) {
queryObject.city.forEach((item) => {
cities.push(Mockupdata[0].find((p) => p.string === item).id);
});
} else {
cities.push(
Mockupdata[0].find((p) => p.string === queryObject.city).id
);
}
}
if (queryObject.sortBy) {
if (queryObject.sortBy === "dateAsc") _des_date = false;
if (queryObject.sortBy === "dateDesc") _des_date = true;
if (queryObject.sortBy === "popular") _des_popular = true;
}
if (queryObject.page) {
page = queryObject.page;
}
if (queryObject.size) {
size = queryObject.size;
}
// if (queryObject.category) {
// category = Mockupdata[1].find(
// (item) => item.string === queryObject.category.toString()
// ).id;
// }
// if (queryObject.subcategory) {
// subcategory = Mockupdata[1].find(
// (item) => item.string === queryObject.subcategory.toString()
// ).id;
// }
// if (queryObject.city) {
// if (Array.isArray(queryObject.city)) {
// queryObject.city.forEach((item) => {
// cities.push(Mockupdata[0].find((p) => p.string === item).id);
// });
// } else {
// cities.push(
// Mockupdata[0].find((p) => p.string === queryObject.city).id
// );
// }
// }
// if (queryObject.sortBy) {
// if (queryObject.sortBy === "dateAsc") _des_date = false;
// if (queryObject.sortBy === "dateDesc") _des_date = true;
// if (queryObject.sortBy === "popular") _des_popular = true;
// }
// if (queryObject.page) {
// page = queryObject.page;
// }
// if (queryObject.size) {
// size = queryObject.size;
// }

dispatch(setFilters({ category, subcategory, cities, _des_date, _des_popular, page, size }));
}, [history.location.search]);
// dispatch(setFilters({ category, subcategory, cities, _des_date, _des_popular, page, size }));
// }, [history.location.search]);

return (
<HomePageContainer>

+ 2
- 2
src/request/index.js 查看文件

@@ -3,7 +3,7 @@ import queryString from "qs";

const request = axios.create({
// baseURL: "http://192.168.88.150:3001/",
baseURL: "http://192.168.88.175:3005/",
baseURL: "http://192.168.88.176:3001/",
headers: {
"Content-Type": "application/json",
},
@@ -13,7 +13,7 @@ const request = axios.create({
});

export const getRequest = (url, params = null, options = null) => {
console.log('poziv')
console.log('url: ', url);
return request.get(url, { params, ...options });
}


+ 3
- 2
src/request/offersRequest.js 查看文件

@@ -1,8 +1,9 @@
import { getRequest, postRequest } from "."
import apiEndpoints from "./apiEndpoints"

export const attemptFetchOffers = () => {
return getRequest(apiEndpoints.offers.getOffers)
export const attemptFetchOffers = (payload) => {
if (payload) return getRequest(apiEndpoints.offers.getOffers + payload + "&size=10")
return getRequest(apiEndpoints.offers.getOffers + "?size=10")
}
export const attemptAddOffer = (payload) => {
return postRequest(apiEndpoints.offers.addOffer, payload)

+ 2
- 1
src/store/actions/filters/filtersActionConstants.js 查看文件

@@ -5,4 +5,5 @@ export const SET_FILTERS = createSetType(FILTERS_SCOPE);
export const CLEAR_FILTERS = createClearType(FILTERS_SCOPE);
export const SET_CATEGORY = "FILTERS_SET_CATEGORY";
export const SET_SUBCATEGORY = "FILTERS_SET_SUBCATEGORY";
export const SET_CITIES = "FILTERS_SET_CITIES";
export const SET_LOCATIONS = "FILTERS_SET_LOCATIONS";
export const SET_SORT_OPTION = "FILTERS_SET_SORT_OPTION";

+ 9
- 5
src/store/actions/filters/filtersActions.js 查看文件

@@ -1,4 +1,4 @@
import { CLEAR_FILTERS, SET_CATEGORY, SET_CITIES, SET_FILTERS, SET_SUBCATEGORY } from "./filtersActionConstants";
import { CLEAR_FILTERS, SET_CATEGORY, SET_FILTERS, SET_LOCATIONS, SET_SORT_OPTION, SET_SUBCATEGORY } from "./filtersActionConstants";

export const setFilters = (payload) => ({
type: SET_FILTERS,
@@ -7,15 +7,19 @@ export const setFilters = (payload) => ({
export const clearFilters = () => ({
type: CLEAR_FILTERS
})
export const setCategory = (payload) => ({
export const setFilteredCategory = (payload) => ({
type: SET_CATEGORY,
payload
})
export const setSubcategory = (payload) => ({
export const setFilteredSubcategory = (payload) => ({
type: SET_SUBCATEGORY,
payload
})
export const setCities = (payload) => ({
type: SET_CITIES,
export const setFilteredLocations = (payload) => ({
type: SET_LOCATIONS,
payload
})
export const setFilteredSortOption = (payload) => ({
type: SET_SORT_OPTION,
payload
})

+ 21
- 9
src/store/reducers/filters/filtersReducer.js 查看文件

@@ -1,8 +1,9 @@
import {
CLEAR_FILTERS,
SET_CATEGORY,
SET_CITIES,
SET_FILTERS,
SET_LOCATIONS,
SET_SORT_OPTION,
SET_SUBCATEGORY,
} from "../../actions/filters/filtersActionConstants";
import createReducer from "../../utils/createReducer";
@@ -11,7 +12,8 @@ const initialState = {
filters: {
category: null,
subcategory: null,
cities: [],
locations: [],
sortOption: null,
},
};

@@ -19,9 +21,10 @@ export default createReducer(
{
[SET_FILTERS]: setFilters,
[CLEAR_FILTERS]: clearFilters,
[SET_CATEGORY]: setCategory,
[SET_SUBCATEGORY]: setSubcategory,
[SET_CITIES]: setCities,
[SET_CATEGORY]: setFilteredCategory,
[SET_SUBCATEGORY]: setFilteredSubcategory,
[SET_LOCATIONS]: setFilteredLocations,
[SET_SORT_OPTION]: setFilteredSortOption,
},
initialState
);
@@ -37,7 +40,7 @@ function clearFilters() {
return initialState;
}

function setCategory(state, { payload }) {
function setFilteredCategory(state, { payload }) {
return {
...state,
filters: {
@@ -47,7 +50,7 @@ function setCategory(state, { payload }) {
};
}

function setSubcategory(state, { payload }) {
function setFilteredSubcategory(state, { payload }) {
return {
...state,
filters: {
@@ -57,12 +60,21 @@ function setSubcategory(state, { payload }) {
};
}

function setCities(state, { payload }) {
function setFilteredLocations(state, { payload }) {
return {
...state,
filters: {
...state.filters,
cities: payload,
locations: payload,
},
};
}
function setFilteredSortOption(state, {payload}) {
return {
...state,
filters: {
...state.filters,
sortOption: payload,
}
}
}

+ 6
- 1
src/store/reducers/index.js 查看文件

@@ -49,12 +49,17 @@ const locationsPersistConfig = {
storage: storage,
transform: [createFilter("locations", ["_id", "city"])],
};
const filtersPersistConfig = {
key: "filters",
storage: storage,
transform: [createFilter("filters", ["category", "subcategory", "locations", "sortOption"])]
}

export default combineReducers({
login: persistReducer(loginPersistConfig, loginReducer),
user: persistReducer(userPersistConfig, userReducer),
loading: loadingReducer,
filters: filtersReducer,
filters: persistReducer(filtersPersistConfig, filtersReducer),
randomData: persistReducer(randomDataPersistConfig, randomDataReducer),
offers: offersReducer,
categories: persistReducer(categoriesPersistConfig, categoriesReducer),

+ 11
- 2
src/store/saga/offersSaga.js 查看文件

@@ -3,15 +3,24 @@ import { attemptAddOffer, attemptFetchOffers } from "../../request/offersRequest
import { OFFERS_FETCH, OFFER_ADD } from "../actions/offers/offersActionConstants";
import { setOffers } from "../actions/offers/offersActions";

function* fetchOffers() {
function* fetchOffers(payload) {
try {
const data = yield call(attemptFetchOffers);
console.log(payload);
const data = yield call(attemptFetchOffers, payload.payload);
console.log(data.data.items)
yield put(setOffers(data.data.items))
} catch (e) {
console.log(e);
}
}
// function* fetchMoreOffers(payload) {
// try {
// const data = yield call(attemptFetchOffers,)
// }
// catch (e) {
// console.log(e);
// }
// }

function* createOffer(payload) {
try {

+ 16
- 1
src/store/selectors/filtersSelectors.js 查看文件

@@ -6,4 +6,19 @@ export const selectFilters = createSelector(
filtersSelector,
(state) => state.filters,
);

export const selectSelectedCategory = createSelector(
filtersSelector,
(state => state.filters.category)
)
export const selectSelectedSubcategory = createSelector(
filtersSelector,
(state) => state.filters.subcategory
)
export const selectSelectedLocations = createSelector(
filtersSelector,
(state) => state.filters.locations
)
export const selectSelectedSortOption = createSelector(
filtersSelector,
(state) => state.filters.sortOption
)

Loading…
取消
儲存