@@ -7,15 +7,22 @@ import {
7
7
useContractTransactionAnalytics ,
8
8
useContractUniqueWalletAnalytics ,
9
9
} from "data/analytics/hooks" ;
10
+ import { differenceInCalendarDays , formatDate } from "date-fns" ;
10
11
import { useTrack } from "hooks/analytics/useTrack" ;
11
12
import { ArrowRightIcon } from "lucide-react" ;
12
13
import Link from "next/link" ;
13
14
import { useMemo , useState } from "react" ;
14
15
import type { ProjectMeta } from "../../../../../../team/[team_slug]/[project_slug]/contract/[chainIdOrSlug]/[contractAddress]/types" ;
15
16
import { buildContractPagePath } from "../../_utils/contract-page-path" ;
16
17
17
- function getDayKey ( date : Date ) {
18
- return date . toISOString ( ) . split ( "T" ) [ 0 ] ;
18
+ function getDateKey ( date : Date , precision : "day" | "hour" ) {
19
+ const dayKey = date . toISOString ( ) . split ( "T" ) [ 0 ] ;
20
+ if ( precision === "day" ) {
21
+ return dayKey ;
22
+ }
23
+
24
+ const hourKey = date . getHours ( ) ;
25
+ return `${ dayKey } -${ hourKey } ` ;
19
26
}
20
27
21
28
export function ContractAnalyticsOverviewCard ( props : {
@@ -59,33 +66,59 @@ export function ContractAnalyticsOverviewCard(props: {
59
66
const isPending =
60
67
wallets . isPending || transactions . isPending || events . isPending ;
61
68
62
- const mergedData = useMemo ( ( ) => {
69
+ const { data , precision } = useMemo ( ( ) => {
63
70
if ( isPending ) {
64
- return undefined ;
71
+ return {
72
+ data : undefined ,
73
+ precision : "day" as const ,
74
+ } ;
65
75
}
66
76
67
77
const time = ( wallets . data || transactions . data || events . data || [ ] ) . map (
68
78
( wallet ) => wallet . time ,
69
79
) ;
70
80
71
- return time . map ( ( time ) => {
72
- const wallet = wallets . data ?. find (
73
- ( wallet ) => getDayKey ( wallet . time ) === getDayKey ( time ) ,
74
- ) ;
75
- const transaction = transactions . data ?. find (
76
- ( transaction ) => getDayKey ( transaction . time ) === getDayKey ( time ) ,
77
- ) ;
78
- const event = events . data ?. find ( ( event ) => {
79
- return getDayKey ( event . time ) === getDayKey ( time ) ;
80
- } ) ;
81
+ // if the time difference between the first and last time is less than 3 days - use hour precision
82
+ const firstTime = time [ 0 ] ;
83
+ const lastTime = time [ time . length - 1 ] ;
84
+ const timeDiff =
85
+ firstTime && lastTime
86
+ ? differenceInCalendarDays ( lastTime , firstTime )
87
+ : undefined ;
81
88
82
- return {
83
- time,
84
- wallets : wallet ?. count || 0 ,
85
- transactions : transaction ?. count || 0 ,
86
- events : event ?. count || 0 ,
87
- } ;
88
- } ) ;
89
+ const precision : "day" | "hour" = ! timeDiff
90
+ ? "hour"
91
+ : timeDiff < 3
92
+ ? "hour"
93
+ : "day" ;
94
+
95
+ return {
96
+ data : time . map ( ( time ) => {
97
+ const wallet = wallets . data ?. find (
98
+ ( wallet ) =>
99
+ getDateKey ( wallet . time , precision ) === getDateKey ( time , precision ) ,
100
+ ) ;
101
+ const transaction = transactions . data ?. find (
102
+ ( transaction ) =>
103
+ getDateKey ( transaction . time , precision ) ===
104
+ getDateKey ( time , precision ) ,
105
+ ) ;
106
+
107
+ const event = events . data ?. find ( ( event ) => {
108
+ return (
109
+ getDateKey ( event . time , precision ) === getDateKey ( time , precision )
110
+ ) ;
111
+ } ) ;
112
+
113
+ return {
114
+ time,
115
+ wallets : wallet ?. count || 0 ,
116
+ transactions : transaction ?. count || 0 ,
117
+ events : event ?. count || 0 ,
118
+ } ;
119
+ } ) ,
120
+ precision,
121
+ } ;
89
122
} , [ wallets . data , transactions . data , events . data , isPending ] ) ;
90
123
91
124
const analyticsPath = buildContractPagePath ( {
@@ -111,10 +144,11 @@ export function ContractAnalyticsOverviewCard(props: {
111
144
color : "hsl(var(--chart-3))" ,
112
145
} ,
113
146
} }
114
- data = { mergedData || [ ] }
147
+ data = { data || [ ] }
115
148
isPending = { isPending }
116
149
showLegend
117
150
chartClassName = "aspect-[1.5] lg:aspect-[3]"
151
+ toolTipLabelFormatter = { toolTipLabelFormatterWithPrecision ( precision ) }
118
152
customHeader = {
119
153
< div className = "flex items-center justify-between gap-4 border-b p-6 py-4" >
120
154
< h2 className = "font-semibold text-xl tracking-tight" > Analytics</ h2 >
@@ -141,3 +175,16 @@ export function ContractAnalyticsOverviewCard(props: {
141
175
/>
142
176
) ;
143
177
}
178
+
179
+ function toolTipLabelFormatterWithPrecision ( precision : "day" | "hour" ) {
180
+ return function toolTipLabelFormatter ( _v : string , item : unknown ) {
181
+ if ( Array . isArray ( item ) ) {
182
+ const time = item [ 0 ] . payload . time as number ;
183
+ return formatDate (
184
+ new Date ( time ) ,
185
+ precision === "day" ? "MMM d, yyyy" : "MMM d, yyyy hh:mm a" ,
186
+ ) ;
187
+ }
188
+ return undefined ;
189
+ } ;
190
+ }
0 commit comments