1
+ import { readonly , ref , watchEffect } from 'vue'
2
+ import { UserAnalyticsData } from '@casimir/types'
3
+ import useEnvironment from '@/composables/environment'
4
+ import useTxData from '../mockData/mock_transaction_data'
5
+
6
+ const { usersUrl } = useEnvironment ( )
7
+ const { mockData, txData } = useTxData ( )
8
+
9
+ export default function useAnalytics ( ) {
10
+ const finishedComputingUerAnalytics = ref ( false )
11
+ const getUserAnalyticsError = ref ( null )
12
+ const rawUserAnalytics = ref < any > ( null )
13
+ const userAnalytics = ref < UserAnalyticsData > ( {
14
+ oneMonth : {
15
+ labels : [ ] ,
16
+ data : [ ]
17
+ } ,
18
+ sixMonth : {
19
+ labels : [ ] ,
20
+ data : [ ]
21
+ } ,
22
+ oneYear : {
23
+ labels : [ ] ,
24
+ data : [ ]
25
+ } ,
26
+ historical : {
27
+ labels : [ ] ,
28
+ data : [ ]
29
+ }
30
+ } )
31
+
32
+ function computeUserAnalytics ( ) {
33
+ finishedComputingUerAnalytics . value = false
34
+ const sortedTransactions = rawUserAnalytics . value . sort ( ( a : any , b : any ) => {
35
+ new Date ( a . receivedAt ) . getTime ( ) - new Date ( b . receivedAt ) . getTime ( )
36
+ } )
37
+
38
+ let earliest : any = null
39
+ const latest : any = new Date ( ) . getTime ( )
40
+ const oneYear = new Date ( ) . getTime ( ) - 31536000000
41
+ const sixMonths = new Date ( ) . getTime ( ) - 15768000000
42
+ const oneMonth = new Date ( ) . getTime ( ) - 2628000000
43
+ sortedTransactions . forEach ( ( tx : any ) => {
44
+ const receivedAt = new Date ( tx . receivedAt )
45
+ if ( ! earliest ) earliest = receivedAt . getTime ( )
46
+ if ( receivedAt . getTime ( ) < earliest ) earliest = receivedAt . getTime ( )
47
+ } )
48
+ const historicalInterval = ( latest - earliest ) / 11
49
+
50
+ sortedTransactions . forEach ( ( tx : any ) => {
51
+ const { receivedAt, walletAddress, walletBalance } = tx
52
+ /* Historical */
53
+ let historicalDataIndex = userAnalytics . value . historical . data . findIndex ( ( obj : any ) => obj . walletAddress === walletAddress )
54
+ if ( historicalDataIndex === - 1 ) {
55
+ const dataLength = userAnalytics . value . historical . data . push ( { walletAddress, walletBalance : Array ( 12 ) . fill ( 0 ) } )
56
+ historicalDataIndex = dataLength - 1
57
+ }
58
+ // Determine which interval the receivedAt falls into
59
+ const intervalIndex = Math . floor ( ( new Date ( receivedAt ) . getTime ( ) - earliest ) / historicalInterval )
60
+ // Set the value of the intervalIndex to the walletBalance
61
+ userAnalytics . value . historical . data [ historicalDataIndex ] . walletBalance [ intervalIndex ] = walletBalance
62
+
63
+ /* One Year */
64
+ if ( new Date ( receivedAt ) . getTime ( ) > oneYear ) {
65
+ let oneYearDataIndex = userAnalytics . value . oneYear . data . findIndex ( ( obj : any ) => obj . walletAddress === walletAddress )
66
+ if ( oneYearDataIndex === - 1 ) {
67
+ const dataLength = userAnalytics . value . oneYear . data . push ( { walletAddress, walletBalance : Array ( 12 ) . fill ( 0 ) } )
68
+ oneYearDataIndex = dataLength - 1
69
+ }
70
+ const monthsAgo = ( new Date ( ) . getFullYear ( ) - new Date ( receivedAt ) . getFullYear ( ) ) * 12 + ( new Date ( ) . getMonth ( ) - new Date ( receivedAt ) . getMonth ( ) )
71
+ const intervalIndex = 11 - monthsAgo
72
+ userAnalytics . value . oneYear . data [ oneYearDataIndex ] . walletBalance [ intervalIndex ] = walletBalance
73
+ }
74
+
75
+ /* Six Months */
76
+ if ( new Date ( receivedAt ) . getTime ( ) > sixMonths ) {
77
+ let sixMonthDataIndex = userAnalytics . value . sixMonth . data . findIndex ( ( obj : any ) => obj . walletAddress === walletAddress )
78
+ if ( sixMonthDataIndex === - 1 ) {
79
+ const dataLength = userAnalytics . value . sixMonth . data . push ( { walletAddress, walletBalance : Array ( 6 ) . fill ( 0 ) } )
80
+ sixMonthDataIndex = dataLength - 1
81
+ }
82
+ const monthsAgo = ( new Date ( ) . getFullYear ( ) - new Date ( receivedAt ) . getFullYear ( ) ) * 12 + ( new Date ( ) . getMonth ( ) - new Date ( receivedAt ) . getMonth ( ) )
83
+ const intervalIndex = 5 - monthsAgo
84
+ userAnalytics . value . sixMonth . data [ sixMonthDataIndex ] . walletBalance [ intervalIndex ] = walletBalance
85
+ }
86
+
87
+ /* One Month */
88
+ if ( new Date ( receivedAt ) . getTime ( ) > oneMonth ) {
89
+ let oneMonthDataIndex = userAnalytics . value . oneMonth . data . findIndex ( ( obj : any ) => obj . walletAddress === walletAddress )
90
+ if ( oneMonthDataIndex === - 1 ) {
91
+ const dataLength = userAnalytics . value . oneMonth . data . push ( { walletAddress, walletBalance : Array ( 30 ) . fill ( 0 ) } )
92
+ oneMonthDataIndex = dataLength - 1
93
+ }
94
+ const daysAgo = Math . floor ( ( new Date ( ) . getTime ( ) - new Date ( receivedAt ) . getTime ( ) ) / 86400000 )
95
+ const intervalIndex = 29 - daysAgo
96
+ userAnalytics . value . oneMonth . data [ oneMonthDataIndex ] . walletBalance [ intervalIndex ] = walletBalance
97
+ }
98
+ } )
99
+
100
+ const months = [ 'Jan' , 'Feb' , 'Mar' , 'Apr' , 'May' , 'Jun' , 'Jul' , 'Aug' , 'Sep' , 'Oct' , 'Nov' , 'Dec' ]
101
+
102
+ // Set the historical labels array to the interval labels
103
+ let previousMonth : any = null
104
+ userAnalytics . value . historical . labels = Array ( 12 ) . fill ( 0 ) . map ( ( _ , i ) => {
105
+ const date = new Date ( earliest + ( historicalInterval * i ) )
106
+ const currentMonth = date . getMonth ( )
107
+ if ( ! previousMonth ) {
108
+ previousMonth = currentMonth
109
+ return date . getMonth ( ) === 0 ? `${ date . getFullYear ( ) } ${ months [ date . getMonth ( ) ] } ${ date . getDate ( ) } ` : `${ months [ date . getMonth ( ) ] } ${ date . getDate ( ) } `
110
+ } else if ( currentMonth < previousMonth ) {
111
+ previousMonth = currentMonth
112
+ return `${ date . getFullYear ( ) } ${ months [ date . getMonth ( ) ] } ${ date . getDate ( ) } `
113
+ } else {
114
+ previousMonth = currentMonth
115
+ return `${ months [ date . getMonth ( ) ] } ${ date . getDate ( ) } `
116
+ }
117
+ } )
118
+
119
+ // Set the oneYear labels array to the interval labels
120
+ userAnalytics . value . oneYear . labels = Array ( 12 ) . fill ( 0 ) . map ( ( _ , i ) => {
121
+ const date = new Date ( new Date ( ) . setDate ( 1 ) )
122
+ const monthIndex = new Date ( date . setMonth ( date . getMonth ( ) - ( 11 - i ) ) )
123
+ return `${ months [ monthIndex . getMonth ( ) ] } ${ monthIndex . getFullYear ( ) } `
124
+ } )
125
+
126
+ // Set the sixMonth labels array to the interval labels
127
+ userAnalytics . value . sixMonth . labels = Array ( 6 ) . fill ( 0 ) . map ( ( _ , i ) => {
128
+ const date = new Date ( new Date ( ) . setDate ( 1 ) )
129
+ const monthIndex = new Date ( date . setMonth ( date . getMonth ( ) - ( 5 - i ) ) )
130
+ return `${ months [ monthIndex . getMonth ( ) ] } ${ monthIndex . getFullYear ( ) } `
131
+ } )
132
+
133
+ // Set the oneMonth labels array to the interval labels
134
+ userAnalytics . value . oneMonth . labels = [ ]
135
+ for ( let i = 30 ; i > 0 ; i -- ) {
136
+ const date = new Date ( ) . getTime ( ) - ( ( i - 1 ) * 86400000 )
137
+ userAnalytics . value . oneMonth . labels . push ( `${ new Date ( date ) . getMonth ( ) + 1 } /${ new Date ( date ) . getDate ( ) } ` )
138
+ }
139
+ // userAnalytics.value = result
140
+ finishedComputingUerAnalytics . value = true
141
+ }
142
+
143
+ async function getUserAnalytics ( ) {
144
+ try {
145
+ const requestOptions = {
146
+ method : 'GET' ,
147
+ headers : {
148
+ 'Content-Type' : 'application/json'
149
+ }
150
+ }
151
+ // TODO: Re-enable this when athena is ready
152
+ const response = await fetch ( `${ usersUrl } /analytics` , requestOptions )
153
+ const { error, message, data : athenaData } = await response . json ( )
154
+ // console.log('data from analytics :>> ', data)
155
+ // userAnalytics.value = athenaData
156
+ getUserAnalyticsError . value = error
157
+ if ( error ) throw new Error ( `Error in getUserAnalytics: ${ message } ` )
158
+
159
+ // TODO: Get events, actions, and contract data from the API
160
+ // Then format the data to be used in the charts (see computeUserAnalytics) and give to Steve.
161
+
162
+ // We get the user's analytics (wallet balance) data here.
163
+ mockData ( )
164
+ const data = txData . value
165
+
166
+ // TODO: Pass data from above when the API / data is ready
167
+ rawUserAnalytics . value = data
168
+
169
+ // This compute's the user's wallet balance over time
170
+ computeUserAnalytics ( )
171
+ return { error, message, data }
172
+ } catch ( error : any ) {
173
+ throw new Error ( error . message || 'Error getting user analytics' )
174
+ }
175
+ }
176
+
177
+ async function updateAnalytics ( ) {
178
+ await getUserAnalytics ( )
179
+ }
180
+
181
+ watchEffect ( async ( ) => {
182
+ resetUserAnalytics ( )
183
+ await getUserAnalytics ( )
184
+ } )
185
+
186
+ function resetUserAnalytics ( ) {
187
+ getUserAnalyticsError . value = null
188
+ userAnalytics . value = {
189
+ oneMonth : {
190
+ labels : [ ] ,
191
+ data : [ ]
192
+ } ,
193
+ sixMonth : {
194
+ labels : [ ] ,
195
+ data : [ ]
196
+ } ,
197
+ oneYear : {
198
+ labels : [ ] ,
199
+ data : [ ]
200
+ } ,
201
+ historical : {
202
+ labels : [ ] ,
203
+ data : [ ]
204
+ }
205
+ }
206
+ }
207
+
208
+ return {
209
+ finishedComputingUerAnalytics : readonly ( finishedComputingUerAnalytics ) ,
210
+ userAnalytics : readonly ( userAnalytics ) ,
211
+ getUserAnalyticsError : readonly ( getUserAnalyticsError ) ,
212
+ updateAnalytics,
213
+ rawUserAnalytics,
214
+ }
215
+ }
0 commit comments