| @@ -8,8 +8,6 @@ import { | |||
| NextButton, | |||
| TitleField, | |||
| } from "./FirstPartCreateOffer.styled"; | |||
| // import { TextField } from "../../../TextFields/TextField/TextField"; | |||
| // import { PrimaryButton } from "../../../Buttons/PrimaryButton/PrimaryButton"; | |||
| import * as Yup from "yup"; | |||
| import selectedTheme from "../../../../themes"; | |||
| import { useTranslation } from "react-i18next"; | |||
| @@ -88,7 +88,11 @@ const FilterCard = () => { | |||
| <FilterRadioDropdown | |||
| data={filters.subcategories ? [...filters.subcategories] : []} | |||
| icon={<Subcategory />} | |||
| title={t("filters.subcategories.title")} | |||
| title={ | |||
| filters.selectedSubcategory?.name | |||
| ? filters.selectedSubcategory?.name | |||
| : t("filters.subcategories.title") | |||
| } | |||
| searchPlaceholder={t("filters.subcategories.placeholder")} | |||
| setSelected={filters.setSelectedSubcategory} | |||
| selected={filters.selectedSubcategory} | |||
| @@ -39,10 +39,10 @@ const FilterCheckboxDropdown = (props) => { | |||
| const handleChange = (item) => { | |||
| if (props.oneValueAllowed) { | |||
| props.setItemsSelected[item.id]; | |||
| props.setItemsSelected([item]); | |||
| } else { | |||
| if (props.filters.includes(item)) { | |||
| props.setItemsSelected([...props.filters.filter((p) => p !== item)]); | |||
| if (props.filters.find(itemInList => itemInList.city.toString() === item.city.toString())) { | |||
| props.setItemsSelected([...props.filters.filter((p) => p.city.toString() !== item.city.toString())]); | |||
| } else { | |||
| props.setItemsSelected([...props.filters, item]); | |||
| } | |||
| @@ -115,18 +115,23 @@ const FilterCheckboxDropdown = (props) => { | |||
| </React.Fragment> | |||
| } | |||
| > | |||
| {dataToShow.map((item) => ( | |||
| <DropdownItem key={item.city}> | |||
| <CheckBox | |||
| leftText={item.city} | |||
| rightText={item.offerCount} | |||
| value={item} | |||
| checked={props.filters.includes(item)} | |||
| onChange={() => handleChange(item)} | |||
| fullWidth | |||
| /> | |||
| </DropdownItem> | |||
| ))} | |||
| {dataToShow.map((item) => { | |||
| return ( | |||
| <DropdownItem key={item.city}> | |||
| <CheckBox | |||
| leftText={item.city} | |||
| rightText={item.offerCount} | |||
| value={item} | |||
| checked={props.filters.find( | |||
| (itemInList) => | |||
| itemInList.city.toString() === item.city.toString() | |||
| ) ? true : false} | |||
| onChange={() => handleChange(item)} | |||
| fullWidth | |||
| /> | |||
| </DropdownItem> | |||
| ); | |||
| })} | |||
| </DropdownList> | |||
| ); | |||
| }; | |||
| @@ -1,9 +1,10 @@ | |||
| import React from "react"; | |||
| import React, { useEffect, useState } from "react"; | |||
| import PropTypes from "prop-types"; | |||
| import { | |||
| HeaderButton, | |||
| HeaderButtons, | |||
| HeaderContainer, | |||
| HeaderLocation, | |||
| // HeaderLocation, | |||
| HeaderOptions, | |||
| HeaderSelect, | |||
| @@ -19,6 +20,7 @@ import selectedTheme from "../../../themes"; | |||
| import Option from "../../Select/Option/Option"; | |||
| // import { useHistory, useLocation, useRouteMatch } from "react-router-dom"; | |||
| import { sortEnum } from "../../../enums/sortEnum"; | |||
| import useFilters from "../../../hooks/useFilters"; | |||
| const DownArrow = (props) => ( | |||
| <IconStyled {...props}> | |||
| @@ -27,45 +29,43 @@ 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 filters = props.filters; | |||
| const filters = useFilters(); | |||
| const [headerString, setHeaderString] = useState("SVE KATEGORIJE"); | |||
| // 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(() => { | |||
| if (filters.isApplied) { | |||
| let headerStringLocal = "SVE KATEGORIJE"; | |||
| if (filters.selectedCategory?.name) { | |||
| console.log(filters.selectedCategory); | |||
| headerStringLocal = filters.selectedCategory.name; | |||
| if (filters.selectedSubcategory?.name) { | |||
| headerStringLocal += ` | ${filters.selectedSubcategory.name}`; | |||
| } | |||
| } | |||
| if (filters.selectedLocations && filters.selectedLocations?.length > 0) { | |||
| headerStringLocal += " | "; | |||
| filters.selectedLocations.forEach((location, index) => { | |||
| if (index + 1 === filters.selectedLocations.length) { | |||
| headerStringLocal += location.city; | |||
| } else { | |||
| headerStringLocal += location.city + ", "; | |||
| } | |||
| }); | |||
| } | |||
| setHeaderString(headerStringLocal); | |||
| } | |||
| }, [ | |||
| filters.selectedCategory, | |||
| filters.selectedLocations, | |||
| filters.selectedSubcategory, | |||
| filters.isApplied, | |||
| ]); | |||
| const handleChangeSelect = (event) => { | |||
| let chosenOption; | |||
| for (const sortOption in sortEnum) { | |||
| // console.log(sortEnum[sortOption]) | |||
| if (sortEnum[sortOption].value === event.target.value) { | |||
| chosenOption = sortEnum[sortOption]; | |||
| // console.log(chosenOption) | |||
| filters.setSelectedSortOption(chosenOption); | |||
| } | |||
| } | |||
| @@ -73,7 +73,7 @@ const Header = (props) => { | |||
| return ( | |||
| <HeaderContainer> | |||
| {/* <HeaderLocation>{categoryString + filtersString} </HeaderLocation> */} | |||
| <HeaderLocation>{headerString}</HeaderLocation> | |||
| <HeaderOptions> | |||
| <HeaderButtons> | |||
| <HeaderButton | |||
| @@ -98,15 +98,15 @@ const Header = (props) => { | |||
| </HeaderButton> | |||
| </HeaderButtons> | |||
| <HeaderSelect | |||
| defaultValue={filters.selectedSortOption ? filters.selectedSortOption.value : 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(filters.selectedSortOption) | |||
| return ( | |||
| <Option | |||
| value={sortEnum[property].value} | |||
| @@ -1,46 +1,84 @@ | |||
| import React, { useEffect, useRef} from "react"; | |||
| import React, { useEffect, useRef, useState } from "react"; | |||
| import PropTypes from "prop-types"; | |||
| import { OffersContainer } from "./Offers.styled"; | |||
| import OfferCard from "../../Cards/OfferCard/OfferCard"; | |||
| import { fetchOffers } from "../../../store/actions/offers/offersActions"; | |||
| import { | |||
| fetchMoreOffers, | |||
| fetchOffers, | |||
| } from "../../../store/actions/offers/offersActions"; | |||
| import { useDispatch, useSelector } from "react-redux"; | |||
| import { selectOffers } from "../../../store/selectors/offersSelectors"; | |||
| // import { fetchOffers } from "../../../store/actions/offers/offersActions"; | |||
| // import { useDispatch, useSelector } from "react-redux"; | |||
| // import { selectOffers } from "../../../store/selectors/offersSelectors"; | |||
| import { | |||
| selectNoMoreOffers, | |||
| selectOffers, | |||
| } from "../../../store/selectors/offersSelectors"; | |||
| import useFilters from "../../../hooks/useFilters"; | |||
| const Offers = (props) => { | |||
| const filters = useFilters(); | |||
| const [page, setPage] = useState(2); | |||
| const [initialLoad, setInitialLoad] = useState(true); | |||
| const offers = useSelector(selectOffers); | |||
| const dispatch = useDispatch(); | |||
| const offersRef = useRef(null); | |||
| const noMoreOffersStatus = useSelector(selectNoMoreOffers); | |||
| let timeout = null; | |||
| let listener; | |||
| 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') | |||
| listener = () => { | |||
| if ( | |||
| !noMoreOffersStatus && | |||
| offers?.length > 0 && | |||
| window.scrollY + window.innerHeight > | |||
| window.document.body.offsetHeight * 0.8 | |||
| ) { | |||
| if (!timeout) { | |||
| timeout = setTimeout(() => { | |||
| timeout = null; | |||
| }, 5000); | |||
| dispatch( | |||
| fetchMoreOffers({ page: page, queryString: filters.queryString }) | |||
| ); | |||
| } | |||
| } | |||
| } | |||
| window.addEventListener('scroll', listener) | |||
| return () => window.removeEventListener('scroll', listener); | |||
| }, []) | |||
| }; | |||
| window.addEventListener("scroll", listener); | |||
| return () => window.removeEventListener("scroll", listener); | |||
| }, [page, noMoreOffersStatus, filters.queryString, timeout, offers]); | |||
| // Market place nije zavrsen | |||
| // Koriste se Mockup podaci | |||
| const dispatch = useDispatch(); | |||
| const offers = useSelector(selectOffers); | |||
| useEffect(() => { | |||
| setPage(Math.floor(offers.length / 10) + 1); | |||
| }, [offers]); | |||
| useEffect(() => { | |||
| dispatch(fetchOffers()); | |||
| dispatch(fetchOffers({ page: 1 })); | |||
| }, []); | |||
| useEffect(() => { | |||
| if (filters.queryString) { | |||
| if (filters.queryString.length > 1) { | |||
| if (initialLoad) { | |||
| dispatch(fetchOffers({ page: 1, queryString: filters.queryString })); | |||
| setInitialLoad(false); | |||
| } | |||
| } else { | |||
| setInitialLoad(false); | |||
| } | |||
| } | |||
| }, [filters.queryString, initialLoad]); | |||
| return ( | |||
| <OffersContainer ref={offersRef} onScroll={() => console.log('proba')} onClick={() => console.log(offersRef)}> | |||
| {offers.map((item) => { | |||
| return ( | |||
| <OfferCard key={item._id} offer={item} halfwidth={props.isGrid} /> | |||
| ); | |||
| })} | |||
| <OffersContainer | |||
| ref={offersRef} | |||
| onScroll={() => console.log("proba")} | |||
| onClick={() => console.log(offersRef)} | |||
| > | |||
| {offers != undefined && | |||
| offers.map((item) => { | |||
| return ( | |||
| <OfferCard key={item._id} offer={item} halfwidth={props.isGrid} /> | |||
| ); | |||
| })} | |||
| </OffersContainer> | |||
| ); | |||
| }; | |||
| @@ -9,6 +9,7 @@ import { | |||
| setFilteredLocations, | |||
| setFilteredSortOption, | |||
| setFilteredSubcategory, | |||
| setIsAppliedStatus, | |||
| } from "../store/actions/filters/filtersActions"; | |||
| import { fetchLocations } from "../store/actions/locations/locationsActions"; | |||
| import { | |||
| @@ -16,6 +17,7 @@ import { | |||
| selectSubcategories, | |||
| } from "../store/selectors/categoriesSelectors"; | |||
| import { | |||
| selectAppliedStatus, | |||
| selectSelectedCategory, | |||
| selectSelectedLocations, | |||
| selectSelectedSortOption, | |||
| @@ -32,7 +34,9 @@ const useFilters = () => { | |||
| const selectedSubcategory = useSelector(selectSelectedSubcategory); | |||
| const selectedLocations = useSelector(selectSelectedLocations); | |||
| const selectedSortOption = useSelector(selectSelectedSortOption); | |||
| const [loadedFromQS, setLoadedFromQS] = useState(false); | |||
| const [loaded, setLoadedStatus] = useState(false); | |||
| const isApplied = useSelector(selectAppliedStatus); | |||
| const history = useHistory(); | |||
| const categories = useSelector(selectCategories); | |||
| const subcategories = useSelector( | |||
| @@ -49,118 +53,108 @@ const useFilters = () => { | |||
| } | |||
| }, [categories, locations]); | |||
| 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.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) | |||
| if (!loadedFromQS) { | |||
| 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); | |||
| } | |||
| setSelectedLocations([...locationsToPush]); | |||
| } | |||
| // For future changes if needed | |||
| if (queryObject._des_date || queryObject._des_popular) { | |||
| if (queryObject._des_date === false) { | |||
| setSelectedSortOption(sortOptions.OLD); | |||
| if (queryObject.subcategory) { | |||
| setSelectedSubcategory( | |||
| category.subcategories.find( | |||
| (item) => | |||
| item.name.toString() === queryObject.subcategory.toString() | |||
| ) | |||
| ); | |||
| } | |||
| if (queryObject._des_date === true) { | |||
| setSelectedSortOption(sortOptions.NEW); | |||
| 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]); | |||
| } | |||
| if (queryObject._des_popular === true) { | |||
| setSelectedSortOption(sortOptions.POPULAR); | |||
| // 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); | |||
| } | |||
| } | |||
| setLoadedFromQS(true); | |||
| dispatch(setIsAppliedStatus(true)); | |||
| } | |||
| // 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(() => { | |||
| 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 (loadedFromQS) { | |||
| let qsArray = []; | |||
| if (selectedCategory && selectedCategory?._id !== 0) { | |||
| qsArray.push("category=" + encodeURIComponent(selectedCategory.name)); | |||
| } | |||
| if (selectedSubcategory && selectedSubcategory?._id !== 0) { | |||
| qsArray.push( | |||
| "subcategory=" + encodeURIComponent(selectedSubcategory.name) | |||
| ); | |||
| } | |||
| if (selectedSortOption === sortOptions.OLD) { | |||
| _des_date = false; | |||
| if (selectedLocations && selectedLocations?.length > 0) { | |||
| selectedLocations.forEach((location) => { | |||
| qsArray.push("location=" + encodeURIComponent(location.city)); | |||
| }); | |||
| } | |||
| if (selectedSortOption === sortOptions.POPULAR) { | |||
| _des_popular = true; | |||
| 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)); | |||
| } | |||
| 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); | |||
| } | |||
| let qsStringFromArray = "?" + qsArray.join("&"); | |||
| console.log(qsStringFromArray); | |||
| setQueryString(qsStringFromArray); | |||
| }, [ | |||
| selectedCategory, | |||
| selectedLocations, | |||
| selectedSortOption, | |||
| selectedSubcategory, | |||
| loadedFromQS, | |||
| ]); | |||
| useEffect(() => { | |||
| console.log("QS: ", queryString); | |||
| }, [queryString]); | |||
| const applyFilters = () => { | |||
| dispatch(fetchOffers(queryString)); | |||
| dispatch(setIsAppliedStatus(true)); | |||
| dispatch(fetchOffers({ queryString: queryString })); | |||
| history.push({ | |||
| pathname: HOME_PAGE, | |||
| search: queryString, | |||
| @@ -171,16 +165,34 @@ const useFilters = () => { | |||
| }); | |||
| }; | |||
| const clearFilters = () => { | |||
| setSelectedLocations([]); | |||
| setSelectedSubcategory(); | |||
| setSelectedCategory(); | |||
| }; | |||
| const setSelectedCategory = (payload) => { | |||
| if (isApplied !== false) { | |||
| dispatch(setIsAppliedStatus(false)); | |||
| } | |||
| dispatch(setFilteredCategory(payload)); | |||
| }; | |||
| const setSelectedSubcategory = (payload) => { | |||
| if (isApplied !== false) { | |||
| dispatch(setIsAppliedStatus(false)); | |||
| } | |||
| dispatch(setFilteredSubcategory(payload)); | |||
| }; | |||
| const setSelectedLocations = (payload) => { | |||
| if (isApplied !== false) { | |||
| dispatch(setIsAppliedStatus(false)); | |||
| } | |||
| dispatch(setFilteredLocations(payload)); | |||
| }; | |||
| const setSelectedSortOption = (payload) => { | |||
| if (isApplied !== false) { | |||
| dispatch(setIsAppliedStatus(false)); | |||
| } | |||
| dispatch(setFilteredSortOption(payload)); | |||
| }; | |||
| return { | |||
| @@ -199,6 +211,7 @@ const useFilters = () => { | |||
| queryString, | |||
| applyFilters, | |||
| clearFilters, | |||
| isApplied, | |||
| }; | |||
| }; | |||
| @@ -2,8 +2,8 @@ import axios from "axios"; | |||
| import queryString from "qs"; | |||
| const request = axios.create({ | |||
| // baseURL: "http://192.168.88.150:3001/", | |||
| baseURL: "http://192.168.88.176:3001/", | |||
| baseURL: "http://192.168.88.150:3001/", | |||
| // baseURL: "http://192.168.88.176:3001/", | |||
| headers: { | |||
| "Content-Type": "application/json", | |||
| }, | |||
| @@ -2,8 +2,12 @@ import { getRequest, postRequest } from "." | |||
| import apiEndpoints from "./apiEndpoints" | |||
| export const attemptFetchOffers = (payload) => { | |||
| if (payload) return getRequest(apiEndpoints.offers.getOffers + payload + "&size=10") | |||
| return getRequest(apiEndpoints.offers.getOffers + "?size=10") | |||
| if (payload) return getRequest(apiEndpoints.offers.getOffers + payload + "&size=10&page=1") | |||
| return getRequest(apiEndpoints.offers.getOffers + "?size=10&page=1") | |||
| } | |||
| export const attemptFetchMoreOffers = (page, payload) => { | |||
| if (payload) return getRequest(apiEndpoints.offers.getOffers + payload + `&size=10&page=${page}`); | |||
| return getRequest(apiEndpoints.offers.getOffers + `?size=10&page=${page}`); | |||
| } | |||
| export const attemptAddOffer = (payload) => { | |||
| return postRequest(apiEndpoints.offers.addOffer, payload) | |||
| @@ -7,3 +7,4 @@ export const SET_CATEGORY = "FILTERS_SET_CATEGORY"; | |||
| export const SET_SUBCATEGORY = "FILTERS_SET_SUBCATEGORY"; | |||
| export const SET_LOCATIONS = "FILTERS_SET_LOCATIONS"; | |||
| export const SET_SORT_OPTION = "FILTERS_SET_SORT_OPTION"; | |||
| export const SET_IS_APPLIED = "FILTERS_SET_IS_APPLIED"; | |||
| @@ -1,4 +1,4 @@ | |||
| import { CLEAR_FILTERS, SET_CATEGORY, SET_FILTERS, SET_LOCATIONS, SET_SORT_OPTION, SET_SUBCATEGORY } from "./filtersActionConstants"; | |||
| import { CLEAR_FILTERS, SET_CATEGORY, SET_FILTERS, SET_IS_APPLIED, SET_LOCATIONS, SET_SORT_OPTION, SET_SUBCATEGORY } from "./filtersActionConstants"; | |||
| export const setFilters = (payload) => ({ | |||
| type: SET_FILTERS, | |||
| @@ -22,4 +22,8 @@ export const setFilteredLocations = (payload) => ({ | |||
| export const setFilteredSortOption = (payload) => ({ | |||
| type: SET_SORT_OPTION, | |||
| payload | |||
| }) | |||
| export const setIsAppliedStatus = (payload) => ({ | |||
| type: SET_IS_APPLIED, | |||
| payload, | |||
| }) | |||
| @@ -1,6 +1,8 @@ | |||
| import { createClearType, createErrorType, createFetchType, createSuccessType } from "../actionHelpers"; | |||
| const OFFERS_SCOPE = "OFFERS_SCOPE"; | |||
| const OFFERS_MORE_SCOPE = "OFFERS_MORE_SCOPE"; | |||
| export const OFFERS_FETCH_MORE = createFetchType(OFFERS_MORE_SCOPE); | |||
| export const OFFERS_FETCH = createFetchType(OFFERS_SCOPE); | |||
| export const OFFERS_SUCCESS = createSuccessType(OFFERS_SCOPE); | |||
| @@ -9,4 +11,5 @@ export const OFFERS_CLEAR = createClearType(OFFERS_SCOPE); | |||
| export const OFFERS_SET = "OFFERS_SET"; | |||
| export const OFFERS_ADD = "OFFERS_ADD"; | |||
| export const OFFER_ADD = "OFFER_ADD"; | |||
| export const OFFER_ADD = "OFFER_ADD"; | |||
| export const OFFERS_NO_MORE = "OFFERS_NO_MORE"; | |||
| @@ -1,4 +1,4 @@ | |||
| import { OFFERS_ADD, OFFERS_CLEAR, OFFERS_ERROR, OFFERS_FETCH, OFFERS_SET, OFFERS_SUCCESS, OFFER_ADD } from "./offersActionConstants"; | |||
| import { OFFERS_ADD, OFFERS_CLEAR, OFFERS_ERROR, OFFERS_FETCH, OFFERS_FETCH_MORE, OFFERS_NO_MORE, OFFERS_SET, OFFERS_SUCCESS, OFFER_ADD } from "./offersActionConstants"; | |||
| export const fetchOffers = (payload) => ({ | |||
| type: OFFERS_FETCH, | |||
| @@ -26,4 +26,12 @@ export const addOffers = (payload) => ({ | |||
| export const addOffer = (payload) => ({ | |||
| type: OFFER_ADD, | |||
| payload | |||
| }) | |||
| }) | |||
| export const fetchMoreOffers = (payload) => ({ | |||
| type: OFFERS_FETCH_MORE, | |||
| payload | |||
| }) | |||
| export const setNoMoreOffersStatus = (payload) => ({ | |||
| type: OFFERS_NO_MORE, | |||
| payload | |||
| }) | |||
| @@ -13,8 +13,8 @@ import { logoutUser, refreshUserToken } from "../actions/login/loginActions"; | |||
| // import { setUserAccessToken } from "../actions/user/userActions"; | |||
| //Change URL with .env | |||
| //const baseURL = "http://192.168.88.150:3001/"; | |||
| const baseURL = "http://192.168.88.175:3005/"; | |||
| const baseURL = "http://192.168.88.150:3001/"; | |||
| // const baseURL = "http://192.168.88.175:3005/"; | |||
| //Interceptor unique name | |||
| export const accessTokensMiddlewareInterceptorName = "ACCESS_TOKEN_INTERCEPTOR"; | |||
| @@ -2,6 +2,7 @@ import { | |||
| CLEAR_FILTERS, | |||
| SET_CATEGORY, | |||
| SET_FILTERS, | |||
| SET_IS_APPLIED, | |||
| SET_LOCATIONS, | |||
| SET_SORT_OPTION, | |||
| SET_SUBCATEGORY, | |||
| @@ -14,6 +15,7 @@ const initialState = { | |||
| subcategory: null, | |||
| locations: [], | |||
| sortOption: null, | |||
| isApplied: false, | |||
| }, | |||
| }; | |||
| @@ -25,6 +27,7 @@ export default createReducer( | |||
| [SET_SUBCATEGORY]: setFilteredSubcategory, | |||
| [SET_LOCATIONS]: setFilteredLocations, | |||
| [SET_SORT_OPTION]: setFilteredSortOption, | |||
| [SET_IS_APPLIED]: setIsAppliedStatus, | |||
| }, | |||
| initialState | |||
| ); | |||
| @@ -78,3 +81,12 @@ function setFilteredSortOption(state, {payload}) { | |||
| } | |||
| } | |||
| } | |||
| function setIsAppliedStatus(state, {payload}) { | |||
| return { | |||
| ...state, | |||
| filters: { | |||
| ...state.filters, | |||
| isApplied: payload, | |||
| } | |||
| } | |||
| } | |||
| @@ -44,22 +44,18 @@ const categoriesPersistConfig = { | |||
| storage: storage, | |||
| transform: [createFilter("categories", ["_id", "name", "subcategories"])], | |||
| }; | |||
| const locationsPersistConfig = { | |||
| key: "locations", | |||
| 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: persistReducer(filtersPersistConfig, filtersReducer), | |||
| filters: filtersReducer, | |||
| randomData: persistReducer(randomDataPersistConfig, randomDataReducer), | |||
| offers: offersReducer, | |||
| categories: persistReducer(categoriesPersistConfig, categoriesReducer), | |||
| @@ -2,6 +2,7 @@ import { | |||
| OFFERS_ADD, | |||
| OFFERS_CLEAR, | |||
| OFFERS_ERROR, | |||
| OFFERS_NO_MORE, | |||
| OFFERS_SET, | |||
| OFFER_ADD, | |||
| } from "../../actions/offers/offersActionConstants"; | |||
| @@ -11,6 +12,7 @@ const initialState = { | |||
| offers: [], | |||
| error: "", | |||
| newOffer: "", | |||
| noMoreOffers: false, | |||
| }; | |||
| export default createReducer( | |||
| @@ -20,6 +22,7 @@ export default createReducer( | |||
| [OFFERS_SET]: setOffers, | |||
| [OFFERS_ADD]: addOffers, | |||
| [OFFER_ADD]: addOffer, | |||
| [OFFERS_NO_MORE]: setNoMoreOffersStatus | |||
| }, | |||
| initialState | |||
| ); | |||
| @@ -49,3 +52,9 @@ function addOffer(state, action) { | |||
| offer: action.payload | |||
| } | |||
| } | |||
| function setNoMoreOffersStatus(state, action) { | |||
| return { | |||
| ...state, | |||
| noMoreOffers: action.payload | |||
| } | |||
| } | |||
| @@ -1,39 +1,63 @@ | |||
| import { all, takeLatest, call, put } from "@redux-saga/core/effects"; | |||
| import { attemptAddOffer, attemptFetchOffers } from "../../request/offersRequest"; | |||
| import { OFFERS_FETCH, OFFER_ADD } from "../actions/offers/offersActionConstants"; | |||
| import { setOffers } from "../actions/offers/offersActions"; | |||
| import { | |||
| attemptAddOffer, | |||
| attemptFetchMoreOffers, | |||
| attemptFetchOffers, | |||
| } from "../../request/offersRequest"; | |||
| import { | |||
| OFFERS_FETCH, | |||
| OFFERS_FETCH_MORE, | |||
| OFFER_ADD, | |||
| } from "../actions/offers/offersActionConstants"; | |||
| import { | |||
| addOffers, | |||
| clearOffers, | |||
| setNoMoreOffersStatus, | |||
| setOffers, | |||
| } from "../actions/offers/offersActions"; | |||
| function* fetchOffers(payload) { | |||
| try { | |||
| console.log(payload); | |||
| const data = yield call(attemptFetchOffers, payload.payload); | |||
| console.log(data.data.items) | |||
| yield put(setOffers(data.data.items)) | |||
| yield put(clearOffers()); | |||
| yield put(setNoMoreOffersStatus(false)); | |||
| const data = yield call(attemptFetchOffers, payload.payload.queryString); | |||
| if (data.data.items.length < 10) { | |||
| yield put(setNoMoreOffersStatus(true)); | |||
| } | |||
| yield put(setOffers(data.data.items)); | |||
| } catch (e) { | |||
| console.log(e); | |||
| } | |||
| } | |||
| function* fetchMoreOffers(payload) { | |||
| try { | |||
| const data = yield call( | |||
| attemptFetchMoreOffers, | |||
| payload.payload?.page, | |||
| payload.payload?.queryString | |||
| ); | |||
| yield put(addOffers(data.data.items)); | |||
| if (data.data.items.length < 10) { | |||
| yield put(setNoMoreOffersStatus(true)); | |||
| } | |||
| } catch (e) { | |||
| console.log(e); | |||
| } | |||
| } | |||
| // function* fetchMoreOffers(payload) { | |||
| // try { | |||
| // const data = yield call(attemptFetchOffers,) | |||
| // } | |||
| // catch (e) { | |||
| // console.log(e); | |||
| // } | |||
| // } | |||
| function* createOffer(payload) { | |||
| try { | |||
| const data = yield call(attemptAddOffer, payload); | |||
| console.log(data); | |||
| } | |||
| catch (e) { | |||
| } catch (e) { | |||
| console.log(e); | |||
| } | |||
| } | |||
| export default function* offersSaga() { | |||
| yield all([takeLatest(OFFERS_FETCH, fetchOffers), | |||
| takeLatest(OFFER_ADD, createOffer)]); | |||
| yield all([ | |||
| takeLatest(OFFERS_FETCH, fetchOffers), | |||
| takeLatest(OFFERS_FETCH_MORE, fetchMoreOffers), | |||
| takeLatest(OFFER_ADD, createOffer), | |||
| ]); | |||
| } | |||
| @@ -22,3 +22,7 @@ export const selectSelectedSortOption = createSelector( | |||
| filtersSelector, | |||
| (state) => state.filters.sortOption | |||
| ) | |||
| export const selectAppliedStatus = createSelector( | |||
| filtersSelector, | |||
| (state) => state.filters.isApplied | |||
| ) | |||
| @@ -11,3 +11,7 @@ export const selectOffersError = createSelector( | |||
| offersSelector, | |||
| (state) => state.error, | |||
| ); | |||
| export const selectNoMoreOffers = createSelector( | |||
| offersSelector, | |||
| (state) => state.noMoreOffers | |||
| ) | |||