@@ -6,9 +6,11 @@ import { useGlobalRangeDate } from '../../hooks/useGlobalRangeDate';
6
6
import { Card , CardContent , CardHeader , CardTitle } from '../ui/card' ;
7
7
import { DateFilter } from '../DateFilter' ;
8
8
import { Button } from '../ui/button' ;
9
- import { LuRefreshCw , LuArrowUp , LuArrowDown } from 'react-icons/lu' ;
9
+ import { LuRefreshCw } from 'react-icons/lu' ;
10
10
import { trpc } from '@/api/trpc' ;
11
11
import { useCurrentWorkspaceId } from '@/store/user' ;
12
+ import { StatCard } from './StatCard' ;
13
+ import prettyMilliseconds from 'pretty-ms' ;
12
14
13
15
interface ApplicationStatsChartProps {
14
16
applicationId : string ;
@@ -40,8 +42,6 @@ export const ApplicationStatsChart: React.FC<ApplicationStatsChartProps> =
40
42
date : item . date ,
41
43
events : item . eventCount ,
42
44
sessions : item . sessionCount ,
43
- avgEventsPerSession : item . avgEventsPerSession ,
44
- avgScreensPerSession : item . avgScreensPerSession ,
45
45
} ) ) ;
46
46
} , [ data ] ) ;
47
47
@@ -54,16 +54,8 @@ export const ApplicationStatsChart: React.FC<ApplicationStatsChartProps> =
54
54
} ,
55
55
sessions : {
56
56
label : t ( 'Sessions' ) ,
57
- color : 'hsl(var(--chart-3))' ,
58
- } ,
59
- avgEventsPerSession : {
60
- label : t ( 'Unique Events' ) ,
61
57
color : 'hsl(var(--chart-2))' ,
62
58
} ,
63
- avgScreensPerSession : {
64
- label : t ( 'Unique Screens' ) ,
65
- color : 'hsl(var(--chart-4))' ,
66
- } ,
67
59
} ;
68
60
} , [ t ] ) ;
69
61
@@ -73,6 +65,7 @@ export const ApplicationStatsChart: React.FC<ApplicationStatsChartProps> =
73
65
return {
74
66
events : { total : 0 , diff : 0 } ,
75
67
sessions : { total : 0 , diff : 0 } ,
68
+ avgTime : { total : 0 , diff : 0 } ,
76
69
avgEventsPerSession : { total : 0 , diff : 0 } ,
77
70
avgScreensPerSession : { total : 0 , diff : 0 } ,
78
71
} ;
@@ -83,13 +76,16 @@ export const ApplicationStatsChart: React.FC<ApplicationStatsChartProps> =
83
76
( acc , item ) => {
84
77
acc . events += item . eventCount ;
85
78
acc . sessions += item . sessionCount ;
79
+ acc . avgTime +=
80
+ item . sessionCount > 0 ? item . totalTime / item . sessionCount : 0 ;
86
81
acc . avgEventsPerSession += item . avgEventsPerSession ;
87
82
acc . avgScreensPerSession += item . avgScreensPerSession ;
88
83
return acc ;
89
84
} ,
90
85
{
91
86
events : 0 ,
92
87
sessions : 0 ,
88
+ avgTime : 0 ,
93
89
avgEventsPerSession : 0 ,
94
90
avgScreensPerSession : 0 ,
95
91
}
@@ -100,13 +96,16 @@ export const ApplicationStatsChart: React.FC<ApplicationStatsChartProps> =
100
96
( acc , item ) => {
101
97
acc . events += item . eventCount ;
102
98
acc . sessions += item . sessionCount ;
99
+ acc . avgTime +=
100
+ item . sessionCount > 0 ? item . totalTime / item . sessionCount : 0 ;
103
101
acc . avgEventsPerSession += item . avgEventsPerSession ;
104
102
acc . avgScreensPerSession += item . avgScreensPerSession ;
105
103
return acc ;
106
104
} ,
107
105
{
108
106
events : 0 ,
109
107
sessions : 0 ,
108
+ avgTime : 0 ,
110
109
avgEventsPerSession : 0 ,
111
110
avgScreensPerSession : 0 ,
112
111
}
@@ -122,6 +121,10 @@ export const ApplicationStatsChart: React.FC<ApplicationStatsChartProps> =
122
121
total : currentTotals . sessions ,
123
122
diff : currentTotals . sessions - previousTotals . sessions ,
124
123
} ,
124
+ avgTime : {
125
+ total : currentTotals . avgTime ,
126
+ diff : currentTotals . avgTime - previousTotals . avgTime ,
127
+ } ,
125
128
avgEventsPerSession : {
126
129
total : currentTotals . avgEventsPerSession ,
127
130
diff :
@@ -163,118 +166,38 @@ export const ApplicationStatsChart: React.FC<ApplicationStatsChartProps> =
163
166
/>
164
167
</ CardContent >
165
168
166
- < div className = "grid grid-cols-2 border-t md:grid-cols-4" >
167
- < div className = "border-border border-r p-4" >
168
- < div className = "flex flex-col" >
169
- < span className = "text-muted-foreground text-sm" >
170
- { t ( 'Events' ) }
171
- </ span >
172
- < div className = "mt-1 flex items-center justify-between" >
173
- < span className = "text-2xl font-bold" >
174
- { statsData . events . total . toLocaleString ( ) }
175
- </ span >
176
- { statsData . events . diff !== 0 && (
177
- < div
178
- className = { `flex items-center ${ statsData . events . diff > 0 ? 'text-green-500' : 'text-red-500' } ` }
179
- >
180
- { statsData . events . diff > 0 ? (
181
- < LuArrowUp className = "mr-1" />
182
- ) : (
183
- < LuArrowDown className = "mr-1" />
184
- ) }
185
- < span >
186
- { Math . abs ( statsData . events . diff ) . toLocaleString ( ) }
187
- </ span >
188
- </ div >
189
- ) }
190
- </ div >
191
- </ div >
192
- </ div >
169
+ < div className = "flex flex-wrap" >
170
+ < StatCard
171
+ label = { t ( 'Events' ) }
172
+ curr = { statsData . events . total }
173
+ diff = { statsData . events . diff }
174
+ />
193
175
194
- < div className = "border-border border-r p-4" >
195
- < div className = "flex flex-col" >
196
- < span className = "text-muted-foreground text-sm" >
197
- { t ( 'Sessions' ) }
198
- </ span >
199
- < div className = "mt-1 flex items-center justify-between" >
200
- < span className = "text-2xl font-bold" >
201
- { statsData . sessions . total . toLocaleString ( ) }
202
- </ span >
203
- { statsData . sessions . diff !== 0 && (
204
- < div
205
- className = { `flex items-center ${ statsData . sessions . diff > 0 ? 'text-green-500' : 'text-red-500' } ` }
206
- >
207
- { statsData . sessions . diff > 0 ? (
208
- < LuArrowUp className = "mr-1" />
209
- ) : (
210
- < LuArrowDown className = "mr-1" />
211
- ) }
212
- < span >
213
- { Math . abs ( statsData . sessions . diff ) . toLocaleString ( ) }
214
- </ span >
215
- </ div >
216
- ) }
217
- </ div >
218
- </ div >
219
- </ div >
176
+ < StatCard
177
+ label = { t ( 'Sessions' ) }
178
+ curr = { statsData . sessions . total }
179
+ diff = { statsData . sessions . diff }
180
+ />
220
181
221
- < div className = "border-border border-r p-4" >
222
- < div className = "flex flex-col" >
223
- < span className = "text-muted-foreground text-sm" >
224
- { t ( 'Avg Events / Session' ) }
225
- </ span >
226
- < div className = "mt-1 flex items-center justify-between" >
227
- < span className = "text-2xl font-bold" >
228
- { statsData . avgEventsPerSession . total . toLocaleString ( ) }
229
- </ span >
230
- { statsData . avgEventsPerSession . diff !== 0 && (
231
- < div
232
- className = { `flex items-center ${ statsData . avgEventsPerSession . diff > 0 ? 'text-green-500' : 'text-red-500' } ` }
233
- >
234
- { statsData . avgEventsPerSession . diff > 0 ? (
235
- < LuArrowUp className = "mr-1" />
236
- ) : (
237
- < LuArrowDown className = "mr-1" />
238
- ) }
239
- < span >
240
- { Math . abs (
241
- statsData . avgEventsPerSession . diff
242
- ) . toLocaleString ( ) }
243
- </ span >
244
- </ div >
245
- ) }
246
- </ div >
247
- </ div >
248
- </ div >
182
+ < StatCard
183
+ label = { t ( 'Avg. Time' ) }
184
+ curr = { statsData . avgTime . total }
185
+ diff = { statsData . avgTime . diff }
186
+ formatter = { ( value ) => prettyMilliseconds ( value ) }
187
+ />
249
188
250
- < div className = "border-border p-4" >
251
- < div className = "flex flex-col" >
252
- < span className = "text-muted-foreground text-sm" >
253
- { t ( 'Avg Screens / Session' ) }
254
- </ span >
255
- < div className = "mt-1 flex items-center justify-between" >
256
- < span className = "text-2xl font-bold" >
257
- { statsData . avgScreensPerSession . total . toLocaleString ( ) }
258
- </ span >
259
- { statsData . avgScreensPerSession . diff !== 0 && (
260
- < div
261
- className = { `flex items-center ${ statsData . avgScreensPerSession . diff > 0 ? 'text-green-500' : 'text-red-500' } ` }
262
- >
263
- { statsData . avgScreensPerSession . diff > 0 ? (
264
- < LuArrowUp className = "mr-1" />
265
- ) : (
266
- < LuArrowDown className = "mr-1" />
267
- ) }
268
- < span >
269
- { Math . abs (
270
- statsData . avgScreensPerSession . diff
271
- ) . toLocaleString ( ) }
272
- </ span >
273
- </ div >
274
- ) }
275
- </ div >
276
- </ div >
277
- </ div >
189
+ < StatCard
190
+ label = { t ( 'Avg. Events / Session' ) }
191
+ curr = { statsData . avgEventsPerSession . total }
192
+ diff = { statsData . avgEventsPerSession . diff }
193
+ />
194
+
195
+ < StatCard
196
+ label = { t ( 'Avg. Screens / Session' ) }
197
+ curr = { statsData . avgScreensPerSession . total }
198
+ diff = { statsData . avgScreensPerSession . diff }
199
+ borderRight = { false }
200
+ />
278
201
</ div >
279
202
</ Card >
280
203
) ;
0 commit comments