diff --git a/src/actions/searchOffersActions.js b/src/actions/searchOffersActions.js index 10e839aea..ae03fcad9 100644 --- a/src/actions/searchOffersActions.js +++ b/src/actions/searchOffersActions.js @@ -7,6 +7,7 @@ export const OfferSearchTypes = Object.freeze({ SET_JOB_FIELDS: "SET_JOB_FIELDS", SET_JOB_TECHS: "SET_JOB_TECHS", SET_OFFERS_SEARCH_RESULT: "SET_OFFERS_SEARCH_RESULT", + SET_SEARCH_QUERY_TOKEN: "SET_SEARCH_QUERY_TOKEN", SET_OFFERS_LOADING: "SET_OFFERS_LOADING", SET_SEARCH_OFFERS_ERROR: "SET_SEARCH_OFFERS_ERROR", SET_JOB_DURATION_TOGGLE: "SET_JOB_DURATION_TOGGLE", @@ -26,6 +27,11 @@ export const setSearchOffers = (offers) => ({ offers, }); +export const setSearchQueryToken = (queryToken) => ({ + type: OfferSearchTypes.SET_SEARCH_QUERY_TOKEN, + queryToken, +}); + export const setOffersFetchError = (error) => ({ type: OfferSearchTypes.SET_SEARCH_OFFERS_ERROR, error, diff --git a/src/components/HomePage/SearchResultsArea/SearchResultsWidget/OfferItemsContainer.js b/src/components/HomePage/SearchResultsArea/SearchResultsWidget/OfferItemsContainer.js index bb78e5d91..9dc22d9e0 100644 --- a/src/components/HomePage/SearchResultsArea/SearchResultsWidget/OfferItemsContainer.js +++ b/src/components/HomePage/SearchResultsArea/SearchResultsWidget/OfferItemsContainer.js @@ -9,7 +9,6 @@ import OfferItem from "../Offer/OfferItem"; import useSearchResultsWidgetStyles from "./searchResultsWidgetStyles"; import LoadingOfferItem from "./LoadingOfferItem"; import { addSnackbar } from "../../../../actions/notificationActions"; -import { SearchResultsConstants } from "./SearchResultsUtils"; import Offer from "../Offer/Offer"; const useAdvancedSearchButtonStyles = makeStyles((theme) => ({ @@ -53,7 +52,6 @@ const OfferItemsContainer = ({ showSearchFilters, toggleShowSearchFilters, offers, - setOfferOffset, setShouldFetchMoreOffers, hasMoreOffers, infiniteScrollLoading, @@ -86,7 +84,6 @@ const OfferItemsContainer = ({ if (observer.current) observer.current.disconnect(); observer.current = new IntersectionObserver((entries) => { if (entries[0].isIntersecting && hasMoreOffers) { - setOfferOffset((previousOffset) => previousOffset + SearchResultsConstants.fetchNewOffersLimit); setShouldFetchMoreOffers(true); } else { setShouldFetchMoreOffers(false); @@ -95,7 +92,7 @@ const OfferItemsContainer = ({ if (lastOfferNode) observer.current.observe(lastOfferNode); }, [ addSnackbar, hasMoreOffers, infiniteScrollError, infiniteScrollLoading, - lastOfferNode, loading, setOfferOffset, setShouldFetchMoreOffers, + lastOfferNode, loading, setShouldFetchMoreOffers, ]); const handleOfferSelection = (...args) => { @@ -150,7 +147,6 @@ OfferItemsContainer.propTypes = { showSearchFilters: PropTypes.bool, toggleShowSearchFilters: PropTypes.func.isRequired, offers: PropTypes.arrayOf(PropTypes.instanceOf(Offer)), - setOfferOffset: PropTypes.func, setShouldFetchMoreOffers: PropTypes.func, hasMoreOffers: PropTypes.bool, infiniteScrollLoading: PropTypes.bool, diff --git a/src/components/HomePage/SearchResultsArea/SearchResultsWidget/SearchResultsDesktop.js b/src/components/HomePage/SearchResultsArea/SearchResultsWidget/SearchResultsDesktop.js index 8c57743d9..d3dff348e 100644 --- a/src/components/HomePage/SearchResultsArea/SearchResultsWidget/SearchResultsDesktop.js +++ b/src/components/HomePage/SearchResultsArea/SearchResultsWidget/SearchResultsDesktop.js @@ -12,8 +12,8 @@ import { SearchResultsControllerContext } from "./SearchResultsWidget"; const OffersList = ({ noOffers, classes, selectedOfferIdx, offersLoading, setSelectedOfferIdx, - showSearchFilters, toggleShowSearchFilters, offers, setOfferOffset, - setShouldFetchMoreOffers, hasMoreOffers, infiniteScrollLoading, infiniteScrollError, + showSearchFilters, toggleShowSearchFilters, offers, setShouldFetchMoreOffers, + hasMoreOffers, infiniteScrollLoading, infiniteScrollError, }) => ( @@ -32,7 +32,6 @@ const OffersList = ({ showSearchFilters={showSearchFilters} toggleShowSearchFilters={toggleShowSearchFilters} offers={offers} - setOfferOffset={setOfferOffset} setShouldFetchMoreOffers={setShouldFetchMoreOffers} hasMoreOffers={hasMoreOffers} infiniteScrollLoading={infiniteScrollLoading} @@ -64,7 +63,6 @@ OffersList.propTypes = { showSearchFilters: PropTypes.bool.isRequired, toggleShowSearchFilters: PropTypes.func.isRequired, offers: PropTypes.arrayOf(PropTypes.instanceOf(Offer)), - setOfferOffset: PropTypes.func, setShouldFetchMoreOffers: PropTypes.func, hasMoreOffers: PropTypes.bool, infiniteScrollLoading: PropTypes.bool, @@ -136,7 +134,6 @@ const SearchResultsDesktop = () => { handleAdminEnableOffer, showSearchFilters, toggleShowSearchFilters, - setOfferOffset, setShouldFetchMoreOffers, hasMoreOffers, infiniteScrollLoading, @@ -171,7 +168,6 @@ const SearchResultsDesktop = () => { showSearchFilters={showSearchFilters} toggleShowSearchFilters={toggleShowSearchFilters} offers={offers} - setOfferOffset={setOfferOffset} setShouldFetchMoreOffers={setShouldFetchMoreOffers} hasMoreOffers={hasMoreOffers} infiniteScrollLoading={infiniteScrollLoading} diff --git a/src/components/HomePage/SearchResultsArea/SearchResultsWidget/SearchResultsMobile.js b/src/components/HomePage/SearchResultsArea/SearchResultsWidget/SearchResultsMobile.js index 0af34f8f6..ee4919f70 100644 --- a/src/components/HomePage/SearchResultsArea/SearchResultsWidget/SearchResultsMobile.js +++ b/src/components/HomePage/SearchResultsArea/SearchResultsWidget/SearchResultsMobile.js @@ -12,7 +12,7 @@ import { SearchResultsControllerContext } from "./SearchResultsWidget"; const OffersList = ({ noOffers, classes, offersLoading, showOfferDetails, showSearchFilters, toggleShowSearchFilters, offers, - setOfferOffset, setShouldFetchMoreOffers, hasMoreOffers, infiniteScrollLoading, infiniteScrollError, + setShouldFetchMoreOffers, hasMoreOffers, infiniteScrollLoading, infiniteScrollError, }) => ( @@ -31,7 +31,6 @@ const OffersList = ({ showSearchFilters={showSearchFilters} toggleShowSearchFilters={toggleShowSearchFilters} offers={offers} - setOfferOffset={setOfferOffset} setShouldFetchMoreOffers={setShouldFetchMoreOffers} hasMoreOffers={hasMoreOffers} infiniteScrollLoading={infiniteScrollLoading} @@ -56,7 +55,6 @@ OffersList.propTypes = { showSearchFilters: PropTypes.bool.isRequired, toggleShowSearchFilters: PropTypes.func.isRequired, offers: PropTypes.arrayOf(PropTypes.instanceOf(Offer)), - setOfferOffset: PropTypes.func, setShouldFetchMoreOffers: PropTypes.func, hasMoreOffers: PropTypes.bool, infiniteScrollLoading: PropTypes.bool, diff --git a/src/components/HomePage/SearchResultsArea/SearchResultsWidget/SearchResultsWidget.js b/src/components/HomePage/SearchResultsArea/SearchResultsWidget/SearchResultsWidget.js index d1c5343fa..1b58a0dce 100644 --- a/src/components/HomePage/SearchResultsArea/SearchResultsWidget/SearchResultsWidget.js +++ b/src/components/HomePage/SearchResultsArea/SearchResultsWidget/SearchResultsWidget.js @@ -36,7 +36,6 @@ const SearchResultsController = ({ }) => { const [selectedOfferIdx, setSelectedOfferIdx] = useState(null); - const [offerOffset, setOfferOffset] = useState(0); const [shouldFetchMoreOffers, setShouldFetchMoreOffers] = useState(false); // Reset the selected offer on every "loading", so that it does not show up after finished loading @@ -49,7 +48,7 @@ const SearchResultsController = ({ hasMoreOffers, loading: infiniteScrollLoading, error: infiniteScrollError, - } = useLoadMoreOffers({ offerOffset, setOfferOffset, shouldFetchMoreOffers }); + } = useLoadMoreOffers({ shouldFetchMoreOffers }); const handleDisableOffer = useCallback(({ offer, adminReason, onSuccess, onError }) => { disableOfferService(offer._id, adminReason).then(() => { @@ -121,7 +120,6 @@ const SearchResultsController = ({ handleAdminEnableOffer, showSearchFilters, toggleShowSearchFilters, - setOfferOffset, setShouldFetchMoreOffers, hasMoreOffers, infiniteScrollLoading, diff --git a/src/components/HomePage/SearchResultsArea/SearchResultsWidget/useLoadMoreOffers.js b/src/components/HomePage/SearchResultsArea/SearchResultsWidget/useLoadMoreOffers.js index ce51ab7b5..858f41328 100644 --- a/src/components/HomePage/SearchResultsArea/SearchResultsWidget/useLoadMoreOffers.js +++ b/src/components/HomePage/SearchResultsArea/SearchResultsWidget/useLoadMoreOffers.js @@ -1,7 +1,7 @@ import { useEffect, useState } from "react"; import { useSelector, useDispatch } from "react-redux"; -import { setSearchOffers } from "../../../../actions/searchOffersActions"; +import { setSearchOffers, setSearchQueryToken } from "../../../../actions/searchOffersActions"; import Offer from "../Offer/Offer"; import { parseFiltersToURL } from "../../../../utils"; import config from "../../../../config"; @@ -10,10 +10,11 @@ import { SearchResultsConstants } from "./SearchResultsUtils"; const { API_HOSTNAME } = config; -export default ({ offerOffset, setOfferOffset, shouldFetchMoreOffers }) => { +export default ({ shouldFetchMoreOffers }) => { const dispatch = useDispatch(); const offerSearch = useSelector(({ offerSearch }) => ({ + queryToken: offerSearch.queryToken, value: offerSearch.searchValue, jobType: offerSearch.jobType, jobMinDuration: offerSearch.jobDuration[0], @@ -23,7 +24,6 @@ export default ({ offerOffset, setOfferOffset, shouldFetchMoreOffers }) => { })); const filters = { - offset: offerOffset, limit: SearchResultsConstants.fetchNewOffersLimit, ...offerSearch, }; @@ -34,24 +34,20 @@ export default ({ offerOffset, setOfferOffset, shouldFetchMoreOffers }) => { const [hasMoreOffers, setHasMoreOffers] = useState(true); const [loading, setLoading] = useState(false); const [error, setError] = useState(null); - const [fetchedOffsets, setFetchedOffsets] = useState([]); useEffect(() => { if (initialOffersLoading) { - setOfferOffset(0); setHasMoreOffers(true); setError(null); setLoading(false); - setFetchedOffsets([]); } - }, [setOfferOffset, initialOffersLoading]); + }, [initialOffersLoading]); useEffect(() => { const fetchOffers = async () => { try { - setFetchedOffsets((offsets) => [...offsets, filters.offset]); setLoading(true); const query = parseFiltersToURL(filters); const res = await fetch(`${API_HOSTNAME}/offers?${query}`, { @@ -66,7 +62,9 @@ export default ({ offerOffset, setOfferOffset, shouldFetchMoreOffers }) => { setLoading(false); return; } - const offersData = await res.json(); + const data = await res.json(); + const offersData = data.results; + const queryToken = data.queryToken; const offerIds = [...offers.map((offer) => offer._id)]; const newOffers = [...offers]; @@ -78,6 +76,7 @@ export default ({ offerOffset, setOfferOffset, shouldFetchMoreOffers }) => { setHasMoreOffers(offersData.length > 0); dispatch(setSearchOffers(newOffers)); + dispatch(setSearchQueryToken(queryToken)); setLoading(false); setError(null); @@ -91,7 +90,7 @@ export default ({ offerOffset, setOfferOffset, shouldFetchMoreOffers }) => { } }; - if (shouldFetchMoreOffers && !fetchedOffsets.includes(filters.offset) && !initialOffersLoading && !loading) { + if (shouldFetchMoreOffers && !initialOffersLoading && !loading) { fetchOffers().catch((error) => { setError({ cause: ErrorTypes.UNEXPECTED, @@ -102,7 +101,7 @@ export default ({ offerOffset, setOfferOffset, shouldFetchMoreOffers }) => { }, [ dispatch, shouldFetchMoreOffers, filters, initialOffersLoading, - fetchedOffsets, loading, offers, + loading, offers, ]); return { offers, hasMoreOffers, loading, error }; diff --git a/src/reducers/searchOffersReducer.js b/src/reducers/searchOffersReducer.js index 8a4becf71..00bf10e85 100644 --- a/src/reducers/searchOffersReducer.js +++ b/src/reducers/searchOffersReducer.js @@ -27,6 +27,11 @@ export default (state = initialState, action) => { ...state, offers: action.offers, }; + case OfferSearchTypes.SET_SEARCH_QUERY_TOKEN: + return { + ...state, + queryToken: action.queryToken, + }; case OfferSearchTypes.SET_OFFERS_LOADING: return { ...state, diff --git a/src/services/offerService.js b/src/services/offerService.js index 58a4f6245..abed8fbc0 100644 --- a/src/services/offerService.js +++ b/src/services/offerService.js @@ -1,4 +1,10 @@ -import { setLoadingOffers, setSearchOffers, setOffersFetchError, resetOffersFetchError } from "../actions/searchOffersActions"; +import { + setLoadingOffers, + setSearchOffers, + setSearchQueryToken, + setOffersFetchError, + resetOffersFetchError, +} from "../actions/searchOffersActions"; import Offer from "../components/HomePage/SearchResultsArea/Offer/Offer"; import config from "../config"; import { parseFiltersToURL, buildCancelableRequest } from "../utils"; @@ -38,8 +44,11 @@ export const searchOffers = (filters) => buildCancelableRequest( )); return; } - const offers = await res.json(); + const data = await res.json(); + const offers = data.results; + const queryToken = data.queryToken; dispatch(setSearchOffers(offers.map((offerData) => new Offer(offerData)))); + dispatch(setSearchQueryToken(queryToken)); dispatch(setLoadingOffers(false)); sendSearchReport(filters, `/offers?${query}`);