You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134
  1. import { useEffect, useMemo } from "react";
  2. import { useDispatch, useSelector } from "react-redux";
  3. import {
  4. KEY_CATEGORY,
  5. KEY_LOCATION,
  6. KEY_PAGE,
  7. KEY_SEARCH,
  8. KEY_SORTBY,
  9. KEY_SUBCATEGORY,
  10. } from "../../constants/queryStringConstants";
  11. import { fetchCategories } from "../../store/actions/categories/categoriesActions";
  12. import { fetchLocations } from "../../store/actions/locations/locationsActions";
  13. import {
  14. selectOffers,
  15. selectTotalOffers,
  16. } from "../../store/selectors/offersSelectors";
  17. import useFilters from "./useFilters";
  18. import useQueryString from "./useQueryString";
  19. import { setQueryString } from "../../store/actions/queryString/queryStringActions";
  20. import {
  21. convertQueryStringForBackend,
  22. makeHeaderStringHelper,
  23. makeQueryStringHelper,
  24. } from "../../util/helpers/queryHelpers";
  25. import useSorting from "./useSorting";
  26. import useSearch from "./useSearch";
  27. import {
  28. setHeaderString,
  29. setSearchString,
  30. } from "../../store/actions/filters/filtersActions";
  31. import usePaging from "./usePaging";
  32. const useOffers = () => {
  33. const dispatch = useDispatch();
  34. const filters = useFilters();
  35. const queryStringHook = useQueryString();
  36. const offers = useSelector(selectOffers);
  37. const totalOffers = useSelector(selectTotalOffers);
  38. // Always fetch categories and locations,
  39. // becouse count of total offers change over time
  40. useEffect(() => {
  41. dispatch(fetchCategories());
  42. dispatch(fetchLocations());
  43. return () => clear();
  44. }, []);
  45. // On every change of query string, new header string should be created
  46. // Header string is shown on Home page above offers
  47. useEffect(() => {
  48. const headerStringLocal = makeHeaderStringHelper(filters);
  49. dispatch(setHeaderString(headerStringLocal));
  50. }, [queryStringHook.queryString]);
  51. // Initially set category, location and subcategory based on query string
  52. useEffect(() => {
  53. if (queryStringHook.isInitiallyLoaded) {
  54. const queryObject = queryStringHook.queryObject;
  55. if (KEY_CATEGORY in queryObject) {
  56. const category = filters.category.findCategory(
  57. queryObject[KEY_CATEGORY]
  58. );
  59. filters.category.setSelectedCategory(category);
  60. if (KEY_SUBCATEGORY in queryObject) {
  61. const subcategory = filters.category
  62. .getSubcategories(category?.name)
  63. .find(
  64. (subcategory) => subcategory.name === queryObject[KEY_SUBCATEGORY]
  65. );
  66. filters.subcategory.setSelectedSubcategory(subcategory);
  67. }
  68. }
  69. if (KEY_LOCATION in queryObject) {
  70. filters.locations.setSelectedLocationsFromArray(
  71. queryObject[KEY_LOCATION]
  72. );
  73. }
  74. if (KEY_SORTBY in queryObject) {
  75. sorting.changeSortingFromName(queryObject[KEY_SORTBY]);
  76. }
  77. if (KEY_PAGE in queryObject) {
  78. if (queryObject[KEY_PAGE] !== 1)
  79. paging.changePage(queryObject[KEY_PAGE]);
  80. }
  81. dispatch(setSearchString(queryObject[KEY_SEARCH]));
  82. }
  83. }, [queryStringHook.isInitiallyLoaded]);
  84. const allOffersToShow = useMemo(() => {
  85. return offers;
  86. }, [offers]);
  87. const apply = () => {
  88. filters.apply();
  89. const newQueryString = makeQueryStringHelper(
  90. filters,
  91. paging,
  92. search,
  93. sorting
  94. );
  95. dispatch(setQueryString(convertQueryStringForBackend(newQueryString)));
  96. };
  97. // Those hooks are below becouse function apply cannot be put on props before initialization
  98. const sorting = useSorting(apply);
  99. const paging = usePaging(apply);
  100. const search = useSearch(apply);
  101. // On every change of search string, offers should be immediately searched
  102. useEffect(() => {
  103. if (queryStringHook.isInitiallyLoaded) {
  104. search.searchOffers(search.searchString);
  105. }
  106. }, [search.searchString]);
  107. const clear = () => {
  108. filters.clear();
  109. sorting.clear();
  110. paging.changePage(1);
  111. };
  112. return {
  113. filters,
  114. sorting,
  115. paging,
  116. queryStringHook,
  117. allOffersToShow,
  118. totalOffers,
  119. apply,
  120. clear,
  121. };
  122. };
  123. export default useOffers;