From 4433a9463a880b080631c871b68c968ebcb03e84 Mon Sep 17 00:00:00 2001 From: Patryk Andrzejewski Date: Wed, 5 Jul 2023 16:32:34 +0200 Subject: [PATCH] Refactor filter container (#3867) * Refactor filter container * Changeset * Lint --- .changeset/plenty-deers-mate.md | 5 + .../ConditionalFilter/API/getAPIOptions.tsx | 3 +- .../FilterElement/FilterElement.ts | 3 + .../ConditionalFilter/FilterElement/index.ts | 2 +- .../ConditionalFilter/FilterValueProvider.ts | 2 +- .../ValueProvider/TokenArray/index.ts | 3 +- .../ValueProvider/useUrlValueProvider.ts | 2 +- .../ConditionalFilter/useContainerState.ts | 60 +++++++++++ .../ConditionalFilter/useFilterContainer.ts | 99 ++----------------- 9 files changed, 83 insertions(+), 96 deletions(-) create mode 100644 .changeset/plenty-deers-mate.md create mode 100644 src/components/ConditionalFilter/useContainerState.ts diff --git a/.changeset/plenty-deers-mate.md b/.changeset/plenty-deers-mate.md new file mode 100644 index 000000000..8a279020b --- /dev/null +++ b/.changeset/plenty-deers-mate.md @@ -0,0 +1,5 @@ +--- +"saleor-dashboard": patch +--- + +Refactoring FilterContainer in filter feature diff --git a/src/components/ConditionalFilter/API/getAPIOptions.tsx b/src/components/ConditionalFilter/API/getAPIOptions.tsx index 87c03b666..3b955ed36 100644 --- a/src/components/ConditionalFilter/API/getAPIOptions.tsx +++ b/src/components/ConditionalFilter/API/getAPIOptions.tsx @@ -1,7 +1,6 @@ import { ApolloClient } from "@apollo/client"; -import { FilterElement } from "../FilterElement"; -import { FilterContainer } from "../useFilterContainer"; +import { FilterContainer, FilterElement } from "../FilterElement"; import { AttributeChoicesHandler, AttributesHandler, diff --git a/src/components/ConditionalFilter/FilterElement/FilterElement.ts b/src/components/ConditionalFilter/FilterElement/FilterElement.ts index e0b45115c..0c36700a9 100644 --- a/src/components/ConditionalFilter/FilterElement/FilterElement.ts +++ b/src/components/ConditionalFilter/FilterElement/FilterElement.ts @@ -164,3 +164,6 @@ export class FilterElement { return null; } } + + +export type FilterContainer = Array; diff --git a/src/components/ConditionalFilter/FilterElement/index.ts b/src/components/ConditionalFilter/FilterElement/index.ts index 7c113fa62..446549341 100644 --- a/src/components/ConditionalFilter/FilterElement/index.ts +++ b/src/components/ConditionalFilter/FilterElement/index.ts @@ -1,2 +1,2 @@ export { Condition } from "./Condition" -export { FilterElement } from "./FilterElement" \ No newline at end of file +export { type FilterContainer,FilterElement } from "./FilterElement" \ No newline at end of file diff --git a/src/components/ConditionalFilter/FilterValueProvider.ts b/src/components/ConditionalFilter/FilterValueProvider.ts index 023819539..078c41ead 100644 --- a/src/components/ConditionalFilter/FilterValueProvider.ts +++ b/src/components/ConditionalFilter/FilterValueProvider.ts @@ -1,4 +1,4 @@ -import { FilterContainer } from "./useFilterContainer"; +import { FilterContainer } from "./FilterElement"; export interface FilterValueProvider { value: FilterContainer; diff --git a/src/components/ConditionalFilter/ValueProvider/TokenArray/index.ts b/src/components/ConditionalFilter/ValueProvider/TokenArray/index.ts index cc03facc2..7153b64e6 100644 --- a/src/components/ConditionalFilter/ValueProvider/TokenArray/index.ts +++ b/src/components/ConditionalFilter/ValueProvider/TokenArray/index.ts @@ -4,8 +4,7 @@ import { parse, ParsedQs } from "qs"; import { useRef } from "react"; import { InitialStateResponse } from "../../API/InitialStateResponse"; -import { FilterElement } from "../../FilterElement"; -import { FilterContainer } from "../../useFilterContainer"; +import { FilterContainer, FilterElement } from "../../FilterElement"; import { UrlEntry, UrlToken } from "../UrlToken"; import { emptyFetchingParams, diff --git a/src/components/ConditionalFilter/ValueProvider/useUrlValueProvider.ts b/src/components/ConditionalFilter/ValueProvider/useUrlValueProvider.ts index c13e803a4..ff100843a 100644 --- a/src/components/ConditionalFilter/ValueProvider/useUrlValueProvider.ts +++ b/src/components/ConditionalFilter/ValueProvider/useUrlValueProvider.ts @@ -4,8 +4,8 @@ import { stringify } from "qs"; import useRouter from "use-react-router"; import { useInitialAPIState } from "../API/initialState/useInitalAPIState"; +import { FilterContainer } from "../FilterElement"; import { FilterValueProvider } from "../FilterValueProvider"; -import { FilterContainer } from "../useFilterContainer"; import { useTokenArray } from "./TokenArray"; const prepareStructure = filterValue => diff --git a/src/components/ConditionalFilter/useContainerState.ts b/src/components/ConditionalFilter/useContainerState.ts new file mode 100644 index 000000000..e331db0da --- /dev/null +++ b/src/components/ConditionalFilter/useContainerState.ts @@ -0,0 +1,60 @@ +import { useState } from "react"; + +import { FilterContainer,FilterElement } from "./FilterElement"; + +type StateCallback = (el: FilterElement) => void +type Element = FilterContainer[number] + +export const useContainerState = (initialValue: FilterContainer) => { + const [value, setValue] = useState(initialValue); + + const isFilterElement = (elIndex: number, index: number, el: Element): el is FilterElement => { + return elIndex === index && typeof el !== "string" && !Array.isArray(el) + } + + const updateFilterElement = (index: number, cb: StateCallback) => (el: Element, elIndex: number) => { + if (isFilterElement(elIndex, index, el)) { + cb(el); + } + + return el; + } + + const updateAt = (position: string, cb: StateCallback) => { + const index = parseInt(position, 10); + setValue(v => v.map(updateFilterElement(index, cb))); + } + + const removeAt = (position: string) => { + const index = parseInt(position, 10); + + if (value.length > 0) { + setValue(v => + v.filter((_, elIndex) => ![index - 1, index].includes(elIndex)), + ); + return; + } + + setValue(v => v.filter((_, elIndex) => ![index].includes(elIndex))); + }; + + const createEmpty = () => { + const newValue: FilterContainer = []; + + if (value.length > 0) { + newValue.push("OR"); + } + + newValue.push(FilterElement.createEmpty()); + + setValue(v => v.concat(newValue)); + }; + + + return { + createEmpty, + updateAt, + removeAt, + value, + } +} diff --git a/src/components/ConditionalFilter/useFilterContainer.ts b/src/components/ConditionalFilter/useFilterContainer.ts index f93a90868..3e3ecfccb 100644 --- a/src/components/ConditionalFilter/useFilterContainer.ts +++ b/src/components/ConditionalFilter/useFilterContainer.ts @@ -1,115 +1,36 @@ -// @ts-strict-ignore -import { useState } from "react"; - -import { FilterElement } from "./FilterElement"; +import { FilterContainer } from "./FilterElement"; import { ConditionValue, ItemOption } from "./FilterElement/ConditionValue"; - -export type FilterContainer = Array; +import { useContainerState } from "./useContainerState"; export const useFilterContainer = (initialValue: FilterContainer) => { - const [value, setValue] = useState(initialValue); + const { value, updateAt, removeAt, createEmpty } = useContainerState(initialValue) const addEmpty = () => { - const newValue = []; - if (value.length > 0) { - newValue.push("OR"); - } - - newValue.push(FilterElement.createEmpty()); - - setValue(v => v.concat(newValue)); - }; - - const removeAt = (position: string) => { - const index = parseInt(position, 10); - - if (value.length > 0) { - setValue(v => - v.filter((_, elIndex) => ![index - 1, index].includes(elIndex)), - ); - return; - } - - setValue(v => v.filter((_, elIndex) => ![index].includes(elIndex))); + createEmpty() }; const updateLeftOperator = (position: string, leftOperator: any) => { - const index = parseInt(position, 10); - setValue(v => - v.map((el, elIndex) => { - if (elIndex === index && typeof el !== "string" && !Array.isArray(el)) { - el.updateLeftOperator(leftOperator); - } - - return el; - }), - ); + updateAt(position, (el) => el.updateLeftOperator(leftOperator)) }; const updateLeftLoadingState = (position: string, loading: boolean) => { - const index = parseInt(position, 10); - setValue(v => - v.map((el, elIndex) => { - if (elIndex === index && typeof el !== "string" && !Array.isArray(el)) { - el.updateLeftLoadingState(loading); - } - - return el; - }), - ); + updateAt(position, (el) => el.updateLeftLoadingState(loading)) }; const updateRightOperator = (position: string, rightOperator: ConditionValue) => { - const index = parseInt(position, 10); - setValue(v => - v.map((el, elIndex) => { - if (elIndex === index && typeof el !== "string" && !Array.isArray(el)) { - el.updateRightOperator(rightOperator); - } - - return el; - }), - ); + updateAt(position, (el) => el.updateRightOperator(rightOperator)) }; const updateRightOptions = (position: string, options: ItemOption[]) => { - const index = parseInt(position, 10); - setValue(v => - v.map((el, elIndex) => { - if (elIndex === index && typeof el !== "string" && !Array.isArray(el)) { - el.updateRightOptions(options); - } - - return el; - }), - ); + updateAt(position, (el) => el.updateRightOptions(options)) }; const updateRightLoadingState = (position: string, loading: boolean) => { - const index = parseInt(position, 10); - setValue(v => - v.map((el, elIndex) => { - if (elIndex === index && typeof el !== "string" && !Array.isArray(el)) { - el.updateRightLoadingState(loading); - } - - return el; - }), - ); + updateAt(position, (el) => el.updateRightLoadingState(loading)) }; const updateCondition = (position: string, conditionValue: any) => { - const index = parseInt(position, 10); - - setValue(v => - v.map((el, elIndex) => { - if (elIndex === index && typeof el !== "string" && !Array.isArray(el)) { - el.updateCondition(conditionValue); - } - - return el; - }), - ); + updateAt(position, (el) => el.updateCondition(conditionValue)) }; return {