From 4fede31e8c274955be7b595aeef67857a5aedceb Mon Sep 17 00:00:00 2001 From: George Date: Wed, 12 Jul 2023 14:12:49 +0300 Subject: [PATCH] RED-6408, rewrite service from scratch. --- .../search-screen-filtering/filter.service.ts | 66 +++++++++++++++++++ 1 file changed, 66 insertions(+) create mode 100644 src/lib/search-screen-filtering/filter.service.ts diff --git a/src/lib/search-screen-filtering/filter.service.ts b/src/lib/search-screen-filtering/filter.service.ts new file mode 100644 index 0000000..4fa57d0 --- /dev/null +++ b/src/lib/search-screen-filtering/filter.service.ts @@ -0,0 +1,66 @@ +import { computed, Injectable, signal } from '@angular/core'; + +const PARENT_PROPS = ['children', 'indeterminate', 'expanded'] as const; +const PARENT_FILTER_ID = 'parentFilterId'; +type ParentProps = (typeof PARENT_PROPS)[number]; +type ChildFilter = Omit & { [PARENT_FILTER_ID]: string }; + +interface Filter { + id: string; + label: string; + expanded: boolean; + indeterminate: boolean; + checked: boolean; + disabled: boolean; + meta: Record | undefined; + children: Record | undefined; +} +interface FilterGroup { + name: string; + label: string; + filters: Record; +} + +const safeObj = (obj: T | undefined) => obj ?? ({} as T); +const getFiltersWithChildren = (filters: Filter[]) => filters.flatMap(filter => [filter, ...Object.values(safeObj(filter.children))]); +const isChild = (filter: Filter | ChildFilter): filter is ChildFilter => PARENT_FILTER_ID in filter; + +@Injectable() +export class FilterService { + readonly #filterGroups = signal | undefined>(undefined); + readonly filterGroups = this.#filterGroups.asReadonly(); + + addFilterGroup(newFilterGroup: FilterGroup) { + this.#filterGroups.update(filterGroups => ({ ...safeObj(filterGroups), [newFilterGroup.name]: newFilterGroup })); + } + + updateFilterGroup(name: string, updates: Partial>) { + this.#filterGroups.update(filterGroups => { + const current = safeObj(filterGroups)[name]; + if (!current) { + console.warn('[Filter service] Cannot update non-existent group: ', name); + return filterGroups; + } + return { ...filterGroups, [name]: { ...current, ...updates } }; + }); + } + + removeFilterGroup(name: string) { + this.#filterGroups.update(filterGroups => { + if (!filterGroups) return undefined; + const { [name]: _, ...rest } = filterGroups; + return Object.keys(rest) ? rest : undefined; + }); + } + + addFilterToGroup(groupName: string, filter: Filter) { + this.#filterGroups.update(filterGroups => { + const current = safeObj(filterGroups)[groupName]; + if (!current) { + console.warn('[Filter service] Cannot add filter to non-existent group: ', groupName); + return filterGroups; + } + return { ...filterGroups, [groupName]: { ...current, filters: { ...current.filters, [filter.id]: filter } } }; + }); + } +}