11'use client' ;
22
33import { SpinnerIcon , UsersIcon } from '@phosphor-icons/react' ;
4+ import { useAtom } from 'jotai' ;
45import dynamic from 'next/dynamic' ;
5- import { useCallback , useEffect , useState } from 'react' ;
6+ import { useCallback , useEffect , useMemo , useState } from 'react' ;
67import { Card , CardContent } from '@/components/ui/card' ;
78import { useProfilesData } from '@/hooks/use-dynamic-query' ;
9+ import {
10+ dynamicQueryFiltersAtom ,
11+ formattedDateRangeAtom ,
12+ timeGranularityAtom ,
13+ } from '@/stores/jotai/filterAtoms' ;
814
915// Type adapter for the new profile data structure
1016type ProfileData = {
@@ -47,8 +53,7 @@ type ProfileData = {
4753 } > ;
4854} ;
4955
50- import { WebsitePageHeader } from '../../_components/website-page-header' ;
51- import { getDefaultDateRange } from './profile-utils' ;
56+
5257
5358const ProfileRow = dynamic (
5459 ( ) => import ( './profile-row' ) . then ( ( mod ) => ( { default : mod . ProfileRow } ) ) ,
@@ -66,7 +71,20 @@ interface ProfilesListProps {
6671}
6772
6873export function ProfilesList ( { websiteId } : ProfilesListProps ) {
69- const [ dateRange ] = useState ( ( ) => getDefaultDateRange ( ) ) ;
74+ // Use shared state atoms for consistency
75+ const [ formattedDateRangeState ] = useAtom ( formattedDateRangeAtom ) ;
76+ const [ currentGranularity ] = useAtom ( timeGranularityAtom ) ;
77+ const [ filters ] = useAtom ( dynamicQueryFiltersAtom ) ;
78+
79+ const dateRange = useMemo (
80+ ( ) => ( {
81+ start_date : formattedDateRangeState . startDate ,
82+ end_date : formattedDateRangeState . endDate ,
83+ granularity : currentGranularity ,
84+ } ) ,
85+ [ formattedDateRangeState , currentGranularity ]
86+ ) ;
87+
7088 const [ expandedProfileId , setExpandedProfileId ] = useState < string | null > (
7189 null
7290 ) ;
@@ -80,9 +98,17 @@ export function ProfilesList({ websiteId }: ProfilesListProps) {
8098 websiteId ,
8199 dateRange ,
82100 25 ,
83- page
101+ page ,
102+ filters
84103 ) ;
85104
105+ // Reset page and profiles when dateRange or filters change
106+ useEffect ( ( ) => {
107+ setPage ( 1 ) ;
108+ setAllProfiles ( [ ] ) ;
109+ setIsInitialLoad ( true ) ;
110+ } , [ dateRange . start_date , dateRange . end_date , dateRange . granularity , JSON . stringify ( filters ) ] ) ;
111+
86112 const toggleProfile = useCallback ( ( profileId : string ) => {
87113 setExpandedProfileId ( ( currentId ) =>
88114 currentId === profileId ? null : profileId
@@ -144,121 +170,93 @@ export function ProfilesList({ websiteId }: ProfilesListProps) {
144170
145171 if ( isLoading && isInitialLoad ) {
146172 return (
147- < div className = "space-y-6" >
148- < WebsitePageHeader
149- description = "Visitor profiles with session data and behavior patterns"
150- icon = { < UsersIcon className = "h-6 w-6 text-primary" /> }
151- title = "Recent Profiles"
152- variant = "minimal"
153- websiteId = { websiteId }
154- />
155- < Card >
156- < CardContent >
157- < div className = "space-y-3" >
158- { [ 1 , 2 , 3 , 4 , 5 , 6 , 7 , 8 ] . map ( ( i ) => (
159- < div
160- className = "h-16 animate-pulse rounded bg-muted/20"
161- key = { i }
162- />
163- ) ) }
164- </ div >
165- < div className = "flex items-center justify-center pt-4" >
166- < div className = "flex items-center gap-2 text-muted-foreground" >
167- < SpinnerIcon className = "h-4 w-4 animate-spin" />
168- < span className = "text-sm" > Loading profiles...</ span >
169- </ div >
173+ < Card >
174+ < CardContent >
175+ < div className = "space-y-3" >
176+ { [ 1 , 2 , 3 , 4 , 5 , 6 , 7 , 8 ] . map ( ( i ) => (
177+ < div
178+ className = "h-16 animate-pulse rounded bg-muted/20"
179+ key = { i }
180+ />
181+ ) ) }
182+ </ div >
183+ < div className = "flex items-center justify-center pt-4" >
184+ < div className = "flex items-center gap-2 text-muted-foreground" >
185+ < SpinnerIcon className = "h-4 w-4 animate-spin" />
186+ < span className = "text-sm" > Loading profiles...</ span >
170187 </ div >
171- </ CardContent >
172- </ Card >
173- </ div >
188+ </ div >
189+ </ CardContent >
190+ </ Card >
174191 ) ;
175192 }
176193
177194 if ( isError ) {
178195 return (
179- < div className = "space-y-6" >
180- < WebsitePageHeader
181- description = "Visitor profiles with session data and behavior patterns"
182- errorMessage = { error ?. message || 'Failed to load profiles' }
183- hasError = { true }
184- icon = { < UsersIcon className = "h-6 w-6 text-primary" /> }
185- title = "Recent Profiles"
186- variant = "minimal"
187- websiteId = { websiteId }
188- / >
189- </ div >
196+ < Card >
197+ < CardContent >
198+ < div className = "flex flex-col items-center py-12 text-center text-muted-foreground" >
199+ < UsersIcon className = "mb-4 h-12 w-12 opacity-50" />
200+ < p className = "mb-2 font-medium text-lg" > Failed to load profiles </ p >
201+ < p className = "text-sm" >
202+ { error ?. message || 'There was an error loading the profiles' }
203+ </ p >
204+ </ div >
205+ </ CardContent >
206+ </ Card >
190207 ) ;
191208 }
192209
193210 if ( ! allProfiles || allProfiles . length === 0 ) {
194211 return (
195- < div className = "space-y-6" >
196- < WebsitePageHeader
197- description = "Visitor profiles with session data and behavior patterns"
198- icon = { < UsersIcon className = "h-6 w-6 text-primary" /> }
199- title = "Recent Profiles"
200- variant = "minimal"
201- websiteId = { websiteId }
202- />
203- < Card >
204- < CardContent >
205- < div className = "flex flex-col items-center py-12 text-center text-muted-foreground" >
206- < UsersIcon className = "mb-4 h-12 w-12 opacity-50" />
207- < p className = "mb-2 font-medium text-lg" > No profiles found</ p >
208- < p className = "text-sm" >
209- Visitor profiles will appear here once users visit your website
210- </ p >
211- </ div >
212- </ CardContent >
213- </ Card >
214- </ div >
212+ < Card >
213+ < CardContent >
214+ < div className = "flex flex-col items-center py-12 text-center text-muted-foreground" >
215+ < UsersIcon className = "mb-4 h-12 w-12 opacity-50" />
216+ < p className = "mb-2 font-medium text-lg" > No profiles found</ p >
217+ < p className = "text-sm" >
218+ Visitor profiles will appear here once users visit your website
219+ </ p >
220+ </ div >
221+ </ CardContent >
222+ </ Card >
215223 ) ;
216224 }
217225
218226 return (
219- < div className = "space-y-6" >
220- < WebsitePageHeader
221- description = "Visitor profiles with session data and behavior patterns"
222- icon = { < UsersIcon className = "h-6 w-6 text-primary" /> }
223- subtitle = { `${ allProfiles . length } loaded` }
224- title = "Recent Profiles"
225- variant = "minimal"
226- websiteId = { websiteId }
227- />
228- < Card >
229- < CardContent className = "p-0" >
230- < div className = "divide-y divide-border" >
231- { allProfiles . map ( ( profile , index ) => (
232- < ProfileRow
233- index = { index }
234- isExpanded = { expandedProfileId === profile . visitor_id }
235- key = { `${ profile . visitor_id } -${ index } ` }
236- onToggle = { ( ) => toggleProfile ( profile . visitor_id ) }
237- profile = { profile }
238- />
239- ) ) }
240- </ div >
227+ < Card >
228+ < CardContent className = "p-0" >
229+ < div className = "divide-y divide-border" >
230+ { allProfiles . map ( ( profile , index ) => (
231+ < ProfileRow
232+ index = { index }
233+ isExpanded = { expandedProfileId === profile . visitor_id }
234+ key = { `${ profile . visitor_id } -${ index } ` }
235+ onToggle = { ( ) => toggleProfile ( profile . visitor_id ) }
236+ profile = { profile }
237+ />
238+ ) ) }
239+ </ div >
241240
242- < div className = "border-t p-4" ref = { setLoadMoreRef } >
243- { pagination . hasNext ? (
244- < div className = "flex justify-center" >
245- { isLoading ? (
246- < div className = "flex items-center gap-2 text-muted-foreground" >
247- < SpinnerIcon className = "h-4 w-4 animate-spin" />
248- < span className = "text-sm" > Loading more profiles...</ span >
249- </ div >
250- ) : null }
251- </ div >
252- ) : (
253- < div className = "text-center text-muted-foreground text-sm" >
254- { allProfiles . length > 0
255- ? 'All profiles loaded'
256- : 'No more profiles' }
257- </ div >
258- ) }
259- </ div >
260- </ CardContent >
261- </ Card >
262- </ div >
241+ < div className = "border-t p-4" ref = { setLoadMoreRef } >
242+ { pagination . hasNext ? (
243+ < div className = "flex justify-center" >
244+ { isLoading ? (
245+ < div className = "flex items-center gap-2 text-muted-foreground" >
246+ < SpinnerIcon className = "h-4 w-4 animate-spin" />
247+ < span className = "text-sm" > Loading more profiles...</ span >
248+ </ div >
249+ ) : null }
250+ </ div >
251+ ) : (
252+ < div className = "text-center text-muted-foreground text-sm" >
253+ { allProfiles . length > 0
254+ ? 'All profiles loaded'
255+ : 'No more profiles' }
256+ </ div >
257+ ) }
258+ </ div >
259+ </ CardContent >
260+ </ Card >
263261 ) ;
264262}
0 commit comments