11'use client' ;
22
33import { type DynamicQueryFilter , filterOptions } from '@databuddy/shared' ;
4- import {
5- FloppyDiskIcon ,
6- FunnelIcon ,
7- PencilIcon ,
8- XIcon ,
9- } from '@phosphor-icons/react' ;
4+ import { FloppyDiskIcon , PencilIcon , XIcon } from '@phosphor-icons/react' ;
5+ import { useAtom } from 'jotai' ;
106import { useParams } from 'next/navigation' ;
117import { useCallback , useState } from 'react' ;
128import { Button } from '@/components/ui/button' ;
13- import { useFilters } from '@/hooks/use-filters' ;
9+
1410import { useSavedFilters } from '@/hooks/use-saved-filters' ;
11+ import {
12+ dynamicQueryFiltersAtom ,
13+ removeDynamicFilterAtom ,
14+ } from '@/stores/jotai/filterAtoms' ;
1515import { DeleteAllDialog } from './delete-all-dialog' ;
1616import { DeleteFilterDialog } from './delete-filter-dialog' ;
1717import { SaveFilterDialog } from './save-filter-dialog' ;
1818import { SavedFiltersMenu } from './saved-filters-menu' ;
19- import { AddFilterForm } from './utils/add-filters' ;
20-
21- interface FiltersSectionProps {
22- selectedFilters : DynamicQueryFilter [ ] ;
23- onFiltersChange : ( filters : DynamicQueryFilter [ ] ) => void ;
24- }
2519
2620function getOperatorSymbol ( operator : string ) : string {
2721 const operatorToSymbolMap : Record < string , string > = {
@@ -38,14 +32,25 @@ function getOperatorSymbol(operator: string): string {
3832 return operatorToSymbolMap [ operator ] || operator ;
3933}
4034
41- export function FiltersSection ( {
42- selectedFilters,
43- onFiltersChange,
44- } : FiltersSectionProps ) {
45- const { addFilter, removeFilter } = useFilters ( {
46- filters : selectedFilters ,
47- onFiltersChange,
48- } ) ;
35+ export function FiltersSection ( ) {
36+ const [ selectedFilters , setSelectedFilters ] = useAtom (
37+ dynamicQueryFiltersAtom
38+ ) ;
39+ const [ , removeFilter ] = useAtom ( removeDynamicFilterAtom ) ;
40+
41+ const handleRemoveFilter = useCallback (
42+ ( index : number ) => {
43+ if ( selectedFilters [ index ] ) {
44+ const filterToRemove = selectedFilters [ index ] ;
45+ removeFilter ( {
46+ field : filterToRemove . field ,
47+ operator : filterToRemove . operator ,
48+ value : filterToRemove . value ,
49+ } ) ;
50+ }
51+ } ,
52+ [ selectedFilters , removeFilter ]
53+ ) ;
4954
5055 const { id } = useParams ( ) ;
5156 const websiteId = id as string ;
@@ -82,8 +87,8 @@ export function FiltersSection({
8287 const [ isDeleteAllDialogOpen , setIsDeleteAllDialogOpen ] = useState ( false ) ;
8388
8489 const clearAllFilters = useCallback ( ( ) => {
85- onFiltersChange ( [ ] ) ;
86- } , [ onFiltersChange ] ) ;
90+ setSelectedFilters ( [ ] ) ;
91+ } , [ setSelectedFilters ] ) ;
8792
8893 const handleSaveFilter = useCallback (
8994 ( name : string ) => {
@@ -116,9 +121,9 @@ export function FiltersSection({
116121
117122 const handleApplyFilter = useCallback (
118123 ( filters : DynamicQueryFilter [ ] ) => {
119- onFiltersChange ( filters ) ;
124+ setSelectedFilters ( filters ) ;
120125 } ,
121- [ onFiltersChange ]
126+ [ setSelectedFilters ]
122127 ) ;
123128
124129 const handleDeleteSavedFilter = useCallback (
@@ -164,7 +169,7 @@ export function FiltersSection({
164169 }
165170
166171 // Apply the filter's configuration to current filters
167- onFiltersChange ( filterToEdit . filters ) ;
172+ setSelectedFilters ( filterToEdit . filters ) ;
168173
169174 // Set up editing mode with original filters stored
170175 setEditingFilter ( {
@@ -173,16 +178,16 @@ export function FiltersSection({
173178 originalFilters : [ ...filterToEdit . filters ] , // Store original state
174179 } ) ;
175180 } ,
176- [ savedFilters , onFiltersChange ]
181+ [ savedFilters , setSelectedFilters ]
177182 ) ;
178183
179184 const handleCancelEdit = useCallback ( ( ) => {
180185 if ( editingFilter ) {
181186 // Restore original filters
182- onFiltersChange ( editingFilter . originalFilters ) ;
187+ setSelectedFilters ( editingFilter . originalFilters ) ;
183188 }
184189 setEditingFilter ( null ) ;
185- } , [ editingFilter , onFiltersChange ] ) ;
190+ } , [ editingFilter , setSelectedFilters ] ) ;
186191
187192 const handleSaveEdit = useCallback ( ( ) => {
188193 if ( ! editingFilter || selectedFilters . length === 0 ) {
@@ -215,8 +220,12 @@ export function FiltersSection({
215220 setIsDeletingAll ( false ) ;
216221 } , [ deleteAllFilters ] ) ;
217222
223+ if ( selectedFilters . length === 0 ) {
224+ return null ;
225+ }
226+
218227 return (
219- < div className = "overflow-hidden rounded-lg border bg-card shadow-sm" >
228+ < div className = "slide-in-from-top-2 animate-in overflow-hidden rounded-lg border bg-card shadow-sm duration-300 " >
220229 { editingFilter && (
221230 < div className = "border-amber-200/50 border-b bg-gradient-to-r from-amber-50/80 to-amber-50/40 px-4 py-3 text-amber-900 text-sm" >
222231 < div className = "flex items-center justify-between" >
@@ -235,7 +244,7 @@ export function FiltersSection({
235244 </ div >
236245 < div className = "flex shrink-0 gap-2" >
237246 < Button
238- className = "h-7 font-medium text-xs "
247+ className = "h-8 font-medium text-sm "
239248 data-filter-id = { editingFilter . id }
240249 data-total-filters = { selectedFilters . length }
241250 data-track = "filter_edit_completed"
@@ -247,7 +256,7 @@ export function FiltersSection({
247256 { isSaving ? 'Saving...' : 'Save Changes' }
248257 </ Button >
249258 < Button
250- className = "h-7 text-xs "
259+ className = "h-8 text-sm "
251260 disabled = { isSaving }
252261 onClick = { handleCancelEdit }
253262 size = "sm"
@@ -256,7 +265,7 @@ export function FiltersSection({
256265 Cancel
257266 </ Button >
258267 < Button
259- className = "h-7 text-xs "
268+ className = "h-8 text-sm "
260269 onClick = { ( ) => {
261270 setIsSaveDialogOpen ( true ) ;
262271 } }
@@ -269,21 +278,7 @@ export function FiltersSection({
269278 </ div >
270279 </ div >
271280 ) }
272- < div className = "flex min-h-[52px] flex-wrap items-center gap-3 p-4" >
273- < div className = "flex items-center gap-3" >
274- < div className = "flex items-center gap-2" >
275- < FunnelIcon className = "h-4 w-4 text-primary" weight = "duotone" />
276- < h3 className = "font-semibold text-foreground text-sm" >
277- { editingFilter ? 'Edit Filters' : 'Filters' }
278- </ h3 >
279- </ div >
280- { selectedFilters . length > 0 && (
281- < span className = "text-muted-foreground text-xs" >
282- ({ selectedFilters . length } )
283- </ span >
284- ) }
285- </ div >
286-
281+ < div className = "flex min-h-[52px] flex-wrap items-center gap-2 p-4" >
287282 < div className = "flex flex-wrap items-center gap-2" >
288283 { selectedFilters . map ( ( filter , index ) => {
289284 const fieldLabel = filterOptions . find (
@@ -313,7 +308,7 @@ export function FiltersSection({
313308 < button
314309 aria-label = { `Remove filter ${ fieldLabel } ${ operatorSymbol } ${ valueLabel } ` }
315310 className = "rounded-full p-0.5 text-muted-foreground opacity-60 transition-all hover:bg-destructive/10 hover:text-destructive hover:opacity-100 group-hover:opacity-80"
316- onClick = { ( ) => removeFilter ( index ) }
311+ onClick = { ( ) => handleRemoveFilter ( index ) }
317312 type = "button"
318313 >
319314 < XIcon className = "h-3 w-3" weight = "bold" />
@@ -368,8 +363,6 @@ export function FiltersSection({
368363 </ span >
369364 </ div >
370365 ) }
371-
372- < AddFilterForm addFilter = { addFilter } buttonText = "Add filter" />
373366 </ div >
374367 </ div >
375368
0 commit comments