|
1 | 1 | import { ThirdwebAreaChart } from "@/components/blocks/charts/area-chart"; |
2 | | -import {} from "@/components/ui/card"; |
3 | | -import {} from "@/components/ui/table"; |
4 | | -import { format } from "date-fns"; |
5 | | -import {} from "lucide-react"; |
6 | | -import type { ChainMetadata } from "thirdweb/chains"; |
7 | 2 | import type { TransactionDetails } from "../hooks/useGetRecentTransactions"; |
8 | 3 |
|
9 | 4 | interface TimelineOverviewProps { |
10 | 5 | transactions: TransactionDetails[]; |
11 | 6 | isLoading: boolean; |
12 | 7 | } |
13 | 8 |
|
14 | | -// function parseTransactions(args: { |
15 | | -// address: string; |
16 | | -// transactions: TransactionDetails[]; |
17 | | -// }) { |
18 | | -// const { address, transactions } = args; |
19 | | -// const addressLower = address.toLowerCase(); |
20 | | - |
21 | | -// const numTransactionsDaily: Record<string, number> = {}; |
22 | | -// const numContractsDaily: Record<string, number> = {}; |
23 | | -// const topContracts: Record<string, number> = {}; |
24 | | - |
25 | | -// for (const transaction of transactions) { |
26 | | -// const date = format(transaction.date, "yyyy-MM-dd"); |
27 | | -// numTransactionsDaily[date] = (numTransactionsDaily[date] || 0) + 1; |
28 | | -// numContractsDaily[date] = (numContractsDaily[date] || 0) + 1; |
29 | | - |
30 | | -// if (transaction.from === addressLower) { |
31 | | -// topContracts[transaction.from] = |
32 | | -// (topContracts[transaction.from] || 0) + 1; |
33 | | -// } |
34 | | -// } |
35 | | - |
36 | | -// return transactions.reduce( |
37 | | -// (acc, tx) => { |
38 | | -// const date = format(tx.date, "yyyy-MM-dd"); |
39 | | -// acc[date] = (acc[date] || 0) + 1; |
40 | | -// return acc; |
41 | | -// }, |
42 | | -// {} as Record<string, number>, |
43 | | -// ); |
44 | | -// } |
| 9 | +function getDayKey(date: Date) { |
| 10 | + return date.toDateString().split("T")[0]; |
| 11 | +} |
45 | 12 |
|
46 | 13 | export function TimelineOverview({ |
47 | 14 | transactions, |
48 | 15 | isLoading, |
49 | 16 | }: TimelineOverviewProps) { |
50 | | - // Process transactions into daily counts |
51 | | - const data = (() => { |
52 | | - const time = transactions.map((tx) => tx.date); |
| 17 | + const aggResults = transactions.reduce( |
| 18 | + ( |
| 19 | + agg: { |
| 20 | + [key: string]: { |
| 21 | + time: Date; |
| 22 | + transactions: number; |
| 23 | + wallets: Set<string>; |
| 24 | + }; |
| 25 | + }, |
| 26 | + val: TransactionDetails, |
| 27 | + ) => { |
| 28 | + const day = getDayKey(val.date); |
| 29 | + if (!day) return agg; |
| 30 | + if (agg[day] === undefined) { |
| 31 | + agg[day] = { |
| 32 | + time: val.date, |
| 33 | + transactions: 1, |
| 34 | + wallets: new Set([val.to as string]), |
| 35 | + }; |
| 36 | + } else { |
| 37 | + agg[day] = { |
| 38 | + time: val.date, |
| 39 | + transactions: agg[day].transactions + 1, |
| 40 | + wallets: agg[day].wallets.add(val.to as string), |
| 41 | + }; |
| 42 | + } |
| 43 | + return agg; |
| 44 | + }, |
| 45 | + {}, |
| 46 | + ); |
53 | 47 |
|
54 | | - return time.map((time) => { |
55 | | - const tx = transactions.find((tx) => tx.date === time); |
| 48 | + const data = Object.values(aggResults) |
| 49 | + .map((val) => { |
56 | 50 | return { |
57 | | - time, |
58 | | - total: tx ? 1 : 0, |
| 51 | + time: val.time, |
| 52 | + transactions: val.transactions, |
| 53 | + wallets: val.wallets.size, |
59 | 54 | }; |
60 | | - }); |
61 | | - |
62 | | - // Sum transactions by day. |
63 | | - // const txDates = transactions.reduce( |
64 | | - // (acc, tx) => { |
65 | | - // const date = format(tx.date, "yyyy-MM-dd"); |
66 | | - // const existingEntry = acc.find((entry) => entry.date === date); |
67 | | - // if (existingEntry) { |
68 | | - // existingEntry.total += 1; |
69 | | - // } else { |
70 | | - // acc.push({ date, total: 1 }); |
71 | | - // } |
72 | | - // return acc; |
73 | | - // }, |
74 | | - // [] as { date: string; total: number }[], |
75 | | - // ); |
76 | | - // return txDates; |
77 | | - // console.log("[DEBUG] txDates:", txDates); |
78 | | - |
79 | | - // // Get min and max dates. |
80 | | - // const dates = txDates.map((d) => new Date(d.date)); |
81 | | - // const minDate = new Date(Math.min(...dates.map((d) => d.getTime()))); |
82 | | - // const maxDate = new Date(Math.max(...dates.map((d) => d.getTime()))); |
83 | | - |
84 | | - // // Create array of all dates between min and max |
85 | | - // const allDates: { date: string; total: number }[] = []; |
86 | | - // const currentDate = new Date(minDate); |
87 | | - // while (currentDate <= maxDate) { |
88 | | - // const dateStr = format(currentDate, "yyyy-MM-dd"); |
89 | | - // const existingDate = txDates.find((d) => d.date === dateStr); |
90 | | - // allDates.push({ |
91 | | - // date: dateStr, |
92 | | - // total: existingDate?.total || 0, |
93 | | - // }); |
94 | | - // currentDate.setDate(currentDate.getDate() + 1); |
95 | | - // } |
96 | | - |
97 | | - // return allDates; |
98 | | - })(); |
99 | | - |
| 55 | + }) |
| 56 | + .sort((a, b) => a.time.getTime() - b.time.getTime()); |
100 | 57 | return ( |
101 | 58 | <ThirdwebAreaChart |
102 | | - chartConfig={{ |
103 | | - total: { |
| 59 | + config={{ |
| 60 | + transactions: { |
104 | 61 | label: "Transactions", |
105 | 62 | color: "hsl(var(--chart-1))", |
106 | 63 | }, |
| 64 | + wallets: { |
| 65 | + label: "Unique Wallets", |
| 66 | + color: "hsl(var(--chart-2))", |
| 67 | + }, |
107 | 68 | }} |
108 | 69 | data={data || []} |
109 | 70 | isPending={isLoading} |
110 | 71 | showLegend |
111 | 72 | chartClassName="aspect-[1.5] lg:aspect-[4.5]" |
112 | | - // activeKey="total" |
113 | | - // emptyChartContent={<>NO CONTENT</>} |
114 | 73 | /> |
115 | 74 | ); |
116 | 75 | } |
0 commit comments