11import type { UserOpStats , WalletStats } from "@3rdweb-sdk/react/hooks/useApi" ;
22import {
3- ActivityIcon ,
4- CableIcon ,
5- CoinsIcon ,
6- WalletCardsIcon ,
3+ ActivityIcon ,
4+ CableIcon ,
5+ CoinsIcon ,
6+ WalletCardsIcon ,
77} from "lucide-react" ;
88import type React from "react" ;
99import { useMemo } from "react" ;
@@ -14,112 +14,111 @@ import { WalletConnectorsChartCard } from "./_components/WalletConnectorsChartCa
1414import { WalletDistributionChartCard } from "./_components/WalletDistributionChartCard" ;
1515
1616export function ConnectAnalyticsDashboardUI ( props : {
17- walletUsage : WalletStats [ ] ;
18- aggregateWalletUsage : WalletStats [ ] ;
19- userOpUsage : UserOpStats [ ] ;
20- aggregateUserOpUsage : UserOpStats [ ] ;
21- isPending : boolean ;
17+ walletUsage : WalletStats [ ] ;
18+ aggregateWalletUsage : WalletStats [ ] ;
19+ userOpUsage : UserOpStats [ ] ;
20+ aggregateUserOpUsage : UserOpStats [ ] ;
21+ isPending : boolean ;
2222} ) {
23- // This hook aggregates wallets across wallet types, only one date is returned for the aggregate query
24- const { totalWallets, uniqueWallets } = useMemo ( ( ) => {
25- return props . aggregateWalletUsage . reduce (
26- ( acc , curr ) => {
27- acc . totalWallets += curr . totalConnections ;
28- acc . uniqueWallets += curr . uniqueWalletsConnected ;
29- return acc ;
30- } ,
31- { uniqueWallets : 0 , totalWallets : 0 } ,
32- ) ;
33- } , [ props . aggregateWalletUsage ] ) ;
23+ const { totalWallets, uniqueWallets } = useMemo ( ( ) => {
24+ return props . aggregateWalletUsage . reduce (
25+ ( acc , curr ) => {
26+ acc . totalWallets += curr . totalConnections ;
27+ acc . uniqueWallets += curr . uniqueWalletsConnected ;
28+ return acc ;
29+ } ,
30+ { uniqueWallets : 0 , totalWallets : 0 } ,
31+ ) ;
32+ } , [ props . aggregateWalletUsage ] ) ;
3433
35- const { totalSponsoredTransactions, totalSponsoredUsd } = useMemo ( ( ) => {
36- return props . aggregateUserOpUsage . reduce (
37- ( acc , curr ) => {
38- acc . totalSponsoredTransactions += curr . successful ;
39- acc . totalSponsoredUsd += curr . sponsoredUsd ;
40- return acc ;
41- } ,
42- { totalSponsoredTransactions : 0 , totalSponsoredUsd : 0 } ,
43- ) ;
44- } , [ props . aggregateUserOpUsage ] ) ;
34+ const { totalSponsoredTransactions, totalSponsoredUsd } = useMemo ( ( ) => {
35+ return props . aggregateUserOpUsage . reduce (
36+ ( acc , curr ) => {
37+ acc . totalSponsoredTransactions += curr . successful ;
38+ acc . totalSponsoredUsd += curr . sponsoredUsd ;
39+ return acc ;
40+ } ,
41+ { totalSponsoredTransactions : 0 , totalSponsoredUsd : 0 } ,
42+ ) ;
43+ } , [ props . aggregateUserOpUsage ] ) ;
4544
46- return (
47- < div className = "flex flex-col gap-4 lg:gap-6" >
48- { /* Connections */ }
49- < div className = "grid grid-cols-2 gap-4 lg:gap-6" >
50- < Stat label = "Connections" value = { totalWallets } icon = { CableIcon } />
51- < Stat
52- label = "Unique Wallets"
53- value = { uniqueWallets }
54- icon = { WalletCardsIcon }
55- />
56- </ div >
45+ return (
46+ < div className = "flex flex-col gap-4 lg:gap-6" >
47+ { /* Connections */ }
48+ < div className = "grid grid-cols-2 gap-4 lg:gap-6" >
49+ < Stat label = "Connections" value = { totalWallets } icon = { CableIcon } />
50+ < Stat
51+ label = "Unique Wallets"
52+ value = { uniqueWallets }
53+ icon = { WalletCardsIcon }
54+ />
55+ </ div >
5756
58- < DailyConnectionsChartCard
59- walletStats = { props . walletUsage }
60- isPending = { props . isPending }
61- />
57+ < DailyConnectionsChartCard
58+ walletStats = { props . walletUsage }
59+ isPending = { props . isPending }
60+ />
6261
63- < WalletConnectorsChartCard
64- walletStats = { props . walletUsage }
65- isPending = { props . isPending }
66- />
62+ < WalletConnectorsChartCard
63+ walletStats = { props . walletUsage }
64+ isPending = { props . isPending }
65+ />
6766
68- < WalletDistributionChartCard
69- walletStats = { props . walletUsage }
70- isPending = { props . isPending }
71- />
67+ < WalletDistributionChartCard
68+ walletStats = { props . walletUsage }
69+ isPending = { props . isPending }
70+ />
7271
73- { /* Connections */ }
74- < div className = "grid grid-cols-2 gap-4 lg:gap-6" >
75- < Stat
76- label = "Sponsored Transactions"
77- value = { totalSponsoredTransactions }
78- icon = { ActivityIcon }
79- />
80- < Stat
81- label = "Total Sponsored"
82- value = { totalSponsoredUsd }
83- formatter = { ( value ) =>
84- new Intl . NumberFormat ( "en-US" , {
85- style : "currency" ,
86- currency : "USD" ,
87- } ) . format ( value )
88- }
89- icon = { CoinsIcon }
90- />
91- </ div >
72+ { /* Connections */ }
73+ < div className = "grid grid-cols-2 gap-4 lg:gap-6" >
74+ < Stat
75+ label = "Sponsored Transactions"
76+ value = { totalSponsoredTransactions }
77+ icon = { ActivityIcon }
78+ />
79+ < Stat
80+ label = "Total Sponsored"
81+ value = { totalSponsoredUsd }
82+ formatter = { ( value ) =>
83+ new Intl . NumberFormat ( "en-US" , {
84+ style : "currency" ,
85+ currency : "USD" ,
86+ } ) . format ( value )
87+ }
88+ icon = { CoinsIcon }
89+ />
90+ </ div >
9291
93- < TotalSponsoredChartCard
94- userOpStats = { props . userOpUsage }
95- isPending = { props . isPending }
96- />
92+ < TotalSponsoredChartCard
93+ userOpStats = { props . userOpUsage }
94+ isPending = { props . isPending }
95+ />
9796
98- < SponsoredTransactionsChartCard
99- userOpStats = { props . userOpUsage }
100- isPending = { props . isPending }
101- />
102- </ div >
103- ) ;
97+ < SponsoredTransactionsChartCard
98+ userOpStats = { props . userOpUsage }
99+ isPending = { props . isPending }
100+ />
101+ </ div >
102+ ) ;
104103}
105104
106105const Stat : React . FC < {
107- label : string ;
108- value ?: number ;
109- icon : React . FC < { className ?: string } > ;
110- formatter ?: ( value : number ) => string ;
106+ label : string ;
107+ value ?: number ;
108+ icon : React . FC < { className ?: string } > ;
109+ formatter ?: ( value : number ) => string ;
111110} > = ( { label, value, formatter, icon : Icon } ) => {
112- return (
113- < dl className = "flex items-center justify-between gap-4 rounded-lg border border-border bg-muted/50 p-4 lg:p-6" >
114- < div >
115- < dd className = "font-semibold text-3xl tracking-tight lg:text-5xl" >
116- { value && formatter ? formatter ( value ) : value ?. toLocaleString ( ) }
117- </ dd >
118- < dt className = "font-medium text-muted-foreground text-sm tracking-tight lg:text-lg" >
119- { label }
120- </ dt >
121- </ div >
122- < Icon className = "hidden size-12 text-muted-foreground opacity-50 lg:block" />
123- </ dl >
124- ) ;
111+ return (
112+ < dl className = "flex items-center justify-between gap-4 rounded-lg border border-border bg-muted/50 p-4 lg:p-6" >
113+ < div >
114+ < dd className = "font-semibold text-3xl tracking-tight lg:text-5xl" >
115+ { value && formatter ? formatter ( value ) : value ?. toLocaleString ( ) }
116+ </ dd >
117+ < dt className = "font-medium text-muted-foreground text-sm tracking-tight lg:text-lg" >
118+ { label }
119+ </ dt >
120+ </ div >
121+ < Icon className = "hidden size-12 text-muted-foreground opacity-50 lg:block" />
122+ </ dl >
123+ ) ;
125124} ;
0 commit comments