No puede seleccionar más de 25 temas Los temas deben comenzar con una letra o número, pueden incluir guiones ('-') y pueden tener hasta 35 caracteres de largo.

137 líneas
3.3KB

  1. import { cloneDeep, isEqual, unset } from "lodash";
  2. import { ReactNode, createContext, useEffect, useMemo, useState } from "react";
  3. // form
  4. import { useLocation } from "react-router";
  5. import { Dictionary } from "@types";
  6. import useNavigateCustom from "hooks/useNavigateCustom";
  7. // ----------------------------------------------------------------------
  8. const _condition: Dictionary = {};
  9. const initialState = {
  10. initialized: false,
  11. condition: _condition,
  12. get: (key: string): string => "",
  13. initializeCondition: () => {},
  14. addCondition: (condition: Dictionary) => {
  15. console.log("not init SearchConditionContext");
  16. },
  17. clearCondition: () => {},
  18. };
  19. export const SearchConditionContext = createContext(initialState);
  20. type Props = {
  21. children: ReactNode;
  22. };
  23. export function SearchConditionContextProvider({ children }: Props) {
  24. const [condition, _setCondition] = useState<Dictionary>({});
  25. const [initialized, setInitialized] = useState(false);
  26. const { pathname, search } = useLocation();
  27. const { navigateWhenChanged } = useNavigateCustom();
  28. const setCondition = (after: Dictionary, message?: any) => {
  29. if (message) {
  30. console.log("Contidion Change", { after, message });
  31. }
  32. _setCondition(after);
  33. };
  34. const initializeCondition = () => {
  35. const after: Dictionary = {};
  36. const urlParam = new URLSearchParams(search);
  37. for (const [key, value] of urlParam.entries()) {
  38. after[key] = value;
  39. }
  40. if (!isEqual(after, condition)) {
  41. setCondition(after, "initializeCondition");
  42. }
  43. setInitialized(true);
  44. };
  45. const get = (key: string) => {
  46. return condition[key] ?? "";
  47. };
  48. const getCondition = useMemo(() => {
  49. return cloneDeep(condition);
  50. }, [condition]);
  51. const addCondition = (additional: Dictionary) => {
  52. if (!initialized) return;
  53. const before = cloneDeep(condition);
  54. const after = cloneDeep(condition);
  55. Object.keys(additional).forEach((key) => {
  56. unset(after, key);
  57. if (additional[key] !== "") {
  58. after[key] = additional[key];
  59. }
  60. });
  61. console.log("compare condition", {
  62. before,
  63. after,
  64. });
  65. if (!isEqual(before, after)) {
  66. console.log("add condition", {
  67. before,
  68. after,
  69. });
  70. setCondition(after, "addCondition");
  71. }
  72. };
  73. const searchParams = useMemo(() => {
  74. const params = new URLSearchParams();
  75. if (!initialized) return params;
  76. Object.keys(condition).forEach((key) => {
  77. params.append(key, condition[key]);
  78. });
  79. params.sort();
  80. return params;
  81. }, [condition]);
  82. const applyToURL = () => {
  83. if (!initialized) return;
  84. navigateWhenChanged(pathname, condition, "applyToURL");
  85. };
  86. const clearCondition = () => {
  87. setCondition({}, "clearCondition");
  88. setInitialized(false);
  89. console.log("clearCondition");
  90. };
  91. useEffect(() => {
  92. if (initialized) {
  93. console.log("call applyToURL", { condition, initialized });
  94. applyToURL();
  95. }
  96. }, [condition, initialized]);
  97. useEffect(() => {
  98. initializeCondition();
  99. }, [pathname, search]);
  100. return (
  101. <SearchConditionContext.Provider
  102. value={{
  103. condition: getCondition,
  104. initialized,
  105. get,
  106. initializeCondition,
  107. addCondition,
  108. clearCondition,
  109. }}
  110. >
  111. {children}
  112. </SearchConditionContext.Provider>
  113. );
  114. }