@@ -3,13 +3,13 @@ import dayjs from "dayjs";
33export interface DynamicQueryFilter {
44 field : string ;
55 operator :
6- | "eq"
7- | "ne"
8- | "contains"
9- | "not_contains"
10- | "starts_with"
11- | "in"
12- | "not_in" ;
6+ | "eq"
7+ | "ne"
8+ | "contains"
9+ | "not_contains"
10+ | "starts_with"
11+ | "in"
12+ | "not_in" ;
1313 value : string | number | ( string | number ) [ ] ;
1414}
1515
@@ -291,33 +291,57 @@ export const isAnalyticsRefreshingAtom = atom(false);
291291
292292// --- Dynamic Query Filters (for shared package compatibility) ---
293293/**
294- * Atom for storing DynamicQueryFilter[] from @databuddy/shared
295- * This is used for the analytics toolbar and shared across all website pages
294+ * Internal atom storing filters with their associated websiteId.
295+ * Filters are automatically cleared when accessing from a different website.
296+ */
297+ const dynamicQueryFiltersBaseAtom = atom < {
298+ websiteId : string | null ;
299+ filters : DynamicQueryFilter [ ] ;
300+ } > ( { websiteId : null , filters : [ ] } ) ;
301+
302+ /** Atom to track current website context for filter scoping */
303+ export const currentFilterWebsiteIdAtom = atom < string | null > ( null ) ;
304+
305+ /**
306+ * Derived atom that returns filters only if they belong to the current website.
307+ * Automatically clears stale filters from other websites.
296308 */
297- export const dynamicQueryFiltersAtom = atom < DynamicQueryFilter [ ] > ( [ ] ) ;
309+ export const dynamicQueryFiltersAtom = atom (
310+ ( get ) => {
311+ const { websiteId, filters } = get ( dynamicQueryFiltersBaseAtom ) ;
312+ const currentWebsiteId = get ( currentFilterWebsiteIdAtom ) ;
313+ if ( currentWebsiteId && websiteId && currentWebsiteId !== websiteId ) {
314+ return [ ] ;
315+ }
316+ return filters ;
317+ } ,
318+ ( get , set , newFilters : DynamicQueryFilter [ ] ) => {
319+ const currentWebsiteId = get ( currentFilterWebsiteIdAtom ) ;
320+ set ( dynamicQueryFiltersBaseAtom , {
321+ websiteId : currentWebsiteId ,
322+ filters : newFilters ,
323+ } ) ;
324+ }
325+ ) ;
298326
299327/**
300328 * Action atom for adding a new dynamic query filter.
301329 * Adds the filter if it doesn't already exist (based on field and value).
302330 */
303331export const addDynamicFilterAtom = atom (
304332 null ,
305- ( _get , set , filter : DynamicQueryFilter ) => {
306- set ( dynamicQueryFiltersAtom , ( prev ) => {
307- // Check if a filter with the same field and value already exists
308- const isDuplicate = prev . some (
309- ( existing ) =>
310- existing . field === filter . field &&
311- existing . value === filter . value &&
312- existing . operator === filter . operator
313- ) ;
314-
315- if ( isDuplicate ) {
316- return prev ; // Don't add duplicate filters
317- }
333+ ( get , set , filter : DynamicQueryFilter ) => {
334+ const prev = get ( dynamicQueryFiltersAtom ) ;
335+ const isDuplicate = prev . some (
336+ ( existing ) =>
337+ existing . field === filter . field &&
338+ existing . value === filter . value &&
339+ existing . operator === filter . operator
340+ ) ;
318341
319- return [ ...prev , filter ] ;
320- } ) ;
342+ if ( ! isDuplicate ) {
343+ set ( dynamicQueryFiltersAtom , [ ...prev , filter ] ) ;
344+ }
321345 }
322346) ;
323347
@@ -327,8 +351,10 @@ export const addDynamicFilterAtom = atom(
327351 */
328352export const removeDynamicFilterAtom = atom (
329353 null ,
330- ( _get , set , filter : Partial < DynamicQueryFilter > ) => {
331- set ( dynamicQueryFiltersAtom , ( prev ) =>
354+ ( get , set , filter : Partial < DynamicQueryFilter > ) => {
355+ const prev = get ( dynamicQueryFiltersAtom ) ;
356+ set (
357+ dynamicQueryFiltersAtom ,
332358 prev . filter (
333359 ( existing ) =>
334360 ! (
0 commit comments