11import { Filter } from '@tryghost/shade/patterns' ;
22import { getMemberFields } from '../member-fields' ;
33import { hasTimezoneSensitiveMemberFilter , isPredicateEnabled , parseMemberFilter , serializeMemberFilters } from '../member-filter-query' ;
4+ import { isMultipleActiveStripeCustomersFilter } from '../multiple-active-stripe-customers' ;
45import { useCallback , useEffect , useMemo , useRef , useState } from 'react' ;
56import { useSearchParams } from 'react-router' ;
67import type { MemberFields } from '../member-fields' ;
@@ -26,6 +27,11 @@ interface ToSearchParamsOptions {
2627 search : string ;
2728 timezone : string ;
2829 fields : MemberFields ;
30+ rawFilter ?: string ;
31+ }
32+
33+ interface UseMembersFilterStateOptions {
34+ preserveMultipleActiveStripeCustomersFilter ?: boolean ;
2935}
3036
3137/**
@@ -43,10 +49,13 @@ export function shouldDelayMembersDateFilterHydration(
4349 return Boolean ( filterParam ) && isLoadingDependencies && ! hasResolvedDependencies && hasTimezoneSensitiveMemberFilter ( filterParam ) ;
4450}
4551
46- function toSearchParams ( { baseSearchParams, filters, search, timezone, fields} : ToSearchParamsOptions ) : URLSearchParams {
52+ function getEnabledFilters ( filters : Filter [ ] , fields : MemberFields ) : Filter [ ] {
53+ return filters . filter ( predicate => isPredicateEnabled ( predicate , fields ) ) ;
54+ }
55+
56+ function toSearchParams ( { baseSearchParams, filters, search, timezone, fields, rawFilter} : ToSearchParamsOptions ) : URLSearchParams {
4757 const params = new URLSearchParams ( baseSearchParams ) ;
48- const enabled = filters . filter ( predicate => isPredicateEnabled ( predicate , fields ) ) ;
49- const filter = serializeMemberFilters ( enabled , timezone ) ;
58+ const filter = rawFilter || serializeMemberFilters ( getEnabledFilters ( filters , fields ) , timezone ) ;
5059
5160 params . delete ( 'filter' ) ;
5261 params . delete ( 'search' ) ;
@@ -62,26 +71,35 @@ function toSearchParams({baseSearchParams, filters, search, timezone, fields}: T
6271 return params ;
6372}
6473
65- export function useMembersFilterState ( timezone : string ) : UseMembersFilterStateReturn {
74+ export function useMembersFilterState ( timezone : string , hookOptions : UseMembersFilterStateOptions = { } ) : UseMembersFilterStateReturn {
6675 const fields = useMemo ( ( ) => getMemberFields ( ) , [ ] ) ;
6776 const [ searchParams , setSearchParams ] = useSearchParams ( ) ;
6877 const lastWrittenQueryRef = useRef < string | null > ( null ) ;
6978 const filterParam = useMemo ( ( ) => searchParams . get ( 'filter' ) ?? undefined , [ searchParams ] ) ;
7079 const currentQuery = useMemo ( ( ) => searchParams . toString ( ) , [ searchParams ] ) ;
80+ const preserveMultipleActiveStripeCustomersFilter = hookOptions . preserveMultipleActiveStripeCustomersFilter === true ;
7181
7282 const parsedFilters = useMemo ( ( ) => {
73- return parseMemberFilter ( filterParam , timezone ) . filter ( predicate => isPredicateEnabled ( predicate , fields ) ) ;
83+ return getEnabledFilters ( parseMemberFilter ( filterParam , timezone ) , fields ) ;
7484 } , [ filterParam , timezone , fields ] ) ;
7585 const [ filters , setDraftFilters ] = useState < Filter [ ] > ( parsedFilters ) ;
86+ const preservedRawFilter = useMemo ( ( ) => {
87+ return preserveMultipleActiveStripeCustomersFilter && filters . length === 0 && isMultipleActiveStripeCustomersFilter ( filterParam )
88+ ? filterParam
89+ : undefined ;
90+ } , [ filterParam , filters . length , preserveMultipleActiveStripeCustomersFilter ] ) ;
7691
7792 const search = useMemo ( ( ) => {
7893 return searchParams . get ( 'search' ) ?? '' ;
7994 } , [ searchParams ] ) ;
8095
8196 const nql = useMemo ( ( ) => {
82- const enabled = filters . filter ( predicate => isPredicateEnabled ( predicate , fields ) ) ;
83- return serializeMemberFilters ( enabled , timezone ) ;
84- } , [ filters , timezone , fields ] ) ;
97+ if ( preservedRawFilter ) {
98+ return preservedRawFilter ;
99+ }
100+
101+ return serializeMemberFilters ( getEnabledFilters ( filters , fields ) , timezone ) ;
102+ } , [ filters , preservedRawFilter , timezone , fields ] ) ;
85103
86104 useEffect ( ( ) => {
87105 if ( currentQuery !== lastWrittenQueryRef . current ) {
@@ -100,15 +118,16 @@ export function useMembersFilterState(timezone: string): UseMembersFilterStateRe
100118 filters,
101119 search,
102120 timezone,
103- fields
121+ fields,
122+ rawFilter : preservedRawFilter
104123 } ) ;
105124 const nextQuery = nextParams . toString ( ) ;
106125
107126 if ( nextQuery !== currentQuery ) {
108127 lastWrittenQueryRef . current = nextQuery ;
109128 setSearchParams ( nextParams , { replace : true } ) ;
110129 }
111- } , [ currentQuery , filters , search , searchParams , setSearchParams , timezone , fields ] ) ;
130+ } , [ currentQuery , filters , preservedRawFilter , search , searchParams , setSearchParams , timezone , fields ] ) ;
112131
113132 const setFilters = useCallback ( ( nextFilters : Filter [ ] , setOptions : SetFiltersOptions = { } ) => {
114133 const replace = setOptions . replace ?? true ;
@@ -132,12 +151,13 @@ export function useMembersFilterState(timezone: string): UseMembersFilterStateRe
132151 filters,
133152 search : nextSearch ,
134153 timezone,
135- fields
154+ fields,
155+ rawFilter : preservedRawFilter
136156 } ) ;
137157
138158 lastWrittenQueryRef . current = nextParams . toString ( ) ;
139159 setSearchParams ( nextParams , { replace} ) ;
140- } , [ filters , searchParams , setSearchParams , timezone , fields ] ) ;
160+ } , [ filters , preservedRawFilter , searchParams , setSearchParams , timezone , fields ] ) ;
141161
142162 const clearFilters = useCallback ( ( { replace = true } : SetFiltersOptions = { } ) => {
143163 const nextParams = toSearchParams ( {
0 commit comments