import { cloneDeep, isEqual, unset } from "lodash"; import { ReactNode, createContext, useEffect, useMemo, useState } from "react"; // form import { useLocation } from "react-router"; import { Dictionary } from "@types"; import useNavigateCustom from "hooks/useNavigateCustom"; // ---------------------------------------------------------------------- const _condition: Dictionary = {}; const initialState = { initialized: false, condition: _condition, get: (key: string): string => "", initializeCondition: () => {}, addCondition: (condition: Dictionary) => { console.log("not init SearchConditionContext"); }, clearCondition: () => {}, }; export const SearchConditionContext = createContext(initialState); type Props = { children: ReactNode; }; export function SearchConditionContextProvider({ children }: Props) { const [condition, _setCondition] = useState({}); const [initialized, setInitialized] = useState(false); const { pathname, search } = useLocation(); const { navigateWhenChanged } = useNavigateCustom(); const setCondition = (after: Dictionary, message?: any) => { if (message) { console.log("Contidion Change", { after, message }); } _setCondition(after); }; const initializeCondition = () => { const after: Dictionary = {}; const urlParam = new URLSearchParams(search); for (const [key, value] of urlParam.entries()) { after[key] = value; } if (!isEqual(after, condition)) { setCondition(after, "initializeCondition"); } setInitialized(true); }; const get = (key: string) => { return condition[key] ?? ""; }; const getCondition = useMemo(() => { return cloneDeep(condition); }, [condition]); const addCondition = (additional: Dictionary) => { if (!initialized) return; const before = cloneDeep(condition); const after = cloneDeep(condition); Object.keys(additional).forEach((key) => { unset(after, key); if (additional[key] !== "") { after[key] = additional[key]; } }); // console.log("compare condition", { // before, // after, // }); if (!isEqual(before, after)) { // console.log("add condition", { // before, // after, // }); setCondition(after, "addCondition"); } }; const searchParams = useMemo(() => { const params = new URLSearchParams(); if (!initialized) return params; Object.keys(condition).forEach((key) => { params.append(key, condition[key]); }); params.sort(); return params; }, [condition]); const applyToURL = () => { if (!initialized) return; navigateWhenChanged(pathname, condition, "applyToURL"); }; const clearCondition = () => { setCondition({}, "clearCondition"); setInitialized(false); }; useEffect(() => { if (initialized) { // console.log("call applyToURL", { condition, initialized }); applyToURL(); } }, [condition, initialized]); useEffect(() => { initializeCondition(); }, [pathname, search]); return ( {children} ); }