Skip to content

Commit fca8151

Browse files
committed
chore: clean up
1 parent 47fdce7 commit fca8151

File tree

1 file changed

+145
-93
lines changed

1 file changed

+145
-93
lines changed

src/features/transactions/pages/group-page.tsx

Lines changed: 145 additions & 93 deletions
Original file line numberDiff line numberDiff line change
@@ -2,21 +2,15 @@ import SvgCircle from '@/features/common/components/svg/circle'
22
import SvgPointerLeft from '@/features/common/components/svg/pointer-left'
33
import SvgPointerRight from '@/features/common/components/svg/pointer-right'
44
import { cn } from '@/features/common/utils'
5-
import { useMemo, useState } from 'react'
5+
import { useMemo } from 'react'
66

7-
type AccountFoo = {
8-
account: string
9-
// the status for the arrow only
10-
status: 'from' | 'to' | 'middle' | 'outside'
11-
}
12-
13-
type TransactionFooDrawing = {
7+
type TransactionArrow = {
148
from: number
159
to: number
1610
direction: 'leftToRight' | 'rightToLeft' | 'toSelf'
1711
}
1812

19-
type TransactionTableRowProps = {
13+
type TransactionRowProps = {
2014
transaction: Transaction
2115
cellHeight?: number
2216
lineWidth?: number
@@ -27,66 +21,110 @@ type TransactionTableRowProps = {
2721
indentLevel?: number
2822
verticalBars?: number[]
2923
}
30-
function TransactionTableRow({
24+
function TransactionRow({
3125
transaction,
3226
accounts,
3327
hasParent = false,
3428
hasNextSibbling = false,
3529
hasChildren = false,
3630
indentLevel = 0,
3731
verticalBars,
38-
}: TransactionTableRowProps) {
39-
const foo = useMemo(() => calcTransactionFoo(transaction, accounts), [accounts, transaction])
32+
}: TransactionRowProps) {
33+
const transactionArrow = useMemo(() => calcTransactionArrow(transaction, accounts), [accounts, transaction])
4034

4135
return (
4236
<>
43-
<tr>
44-
<td className={cn('p-0 relative pr-8')}>
45-
{verticalBars &&
37+
<div className={cn('p-0 relative pr-8')}>
38+
{
39+
// The side vertical bars when there are nested items
40+
verticalBars &&
4641
verticalBars.length &&
4742
verticalBars
4843
.filter((b) => b > 0)
49-
.map((b, i) => <div key={i} className={cn('h-10 border-primary border-l-2 absolute')} style={{ marginLeft: b * 16 }}></div>)}
50-
<div className={cn(`relative h-10 p-0 flex items-center`, 'px-0')} style={{ marginLeft: indentLevel * 16 }}>
51-
{hasParent && (
52-
<div className={cn('w-8', `border-primary border-l-2 border-b-2 rounded-bl-lg`, `h-[50%]`, `absolute top-0 left-0`)}></div>
53-
)}
54-
<div className={cn('inline ml-8')}>{transaction.name}</div>
55-
{hasParent && hasNextSibbling && (
56-
<div className={cn('w-8', 'border-primary border-l-2', 'h-[22px]', 'absolute top-[18px] left-0')}></div>
57-
)}
58-
{hasChildren && (
44+
.map((b, i) => (
45+
<div
46+
key={i}
47+
className={cn('h-full border-primary absolute')}
48+
style={{ marginLeft: b * graphConfig.indentationWidth, borderLeftWidth: `${graphConfig.lineWidth}px` }}
49+
></div>
50+
))
51+
}
52+
<div
53+
className={cn(`relative h-full p-0 flex items-center`, 'px-0')}
54+
style={{ marginLeft: indentLevel * graphConfig.indentationWidth }}
55+
>
56+
{
57+
// The connection between this transaction and the parent
58+
hasParent && (
5959
<div
60-
className={cn('w-2 ml-4', 'border-primary border-l-2 border-t-2 rounded-tl-lg', 'h-[22px]', 'absolute top-[18px] left-0')}
60+
className={cn('w-8', `border-primary rounded-bl-lg`, `h-1/2`, `absolute top-0 left-0`)}
61+
style={{ borderLeftWidth: `${graphConfig.lineWidth}px`, borderBottomWidth: `${graphConfig.lineWidth}px` }}
62+
></div>
63+
)
64+
}
65+
<div className={cn('inline ml-8')}>{transaction.name}</div>
66+
{
67+
// The connection between this transaction and the next sibbling
68+
hasParent && hasNextSibbling && (
69+
<div
70+
className={cn('w-8', 'border-primary', 'absolute top-[18px] left-0')}
71+
style={{
72+
borderLeftWidth: `${graphConfig.lineWidth}px`,
73+
height: `calc(50% + ${graphConfig.lineWidth}px)`,
74+
top: `calc(50% - ${graphConfig.lineWidth}px)`,
75+
}}
76+
></div>
77+
)
78+
}
79+
{
80+
// The connection between this transaction and the children
81+
hasChildren && (
82+
<div
83+
className={cn('w-2 ml-4', 'border-primary rounded-tl-lg', 'absolute left-0')}
84+
style={{
85+
borderLeftWidth: `${graphConfig.lineWidth}px`,
86+
borderTopWidth: `${graphConfig.lineWidth}px`,
87+
height: `calc(50% + ${graphConfig.lineWidth}px)`,
88+
top: `calc(50% - ${graphConfig.lineWidth}px)`,
89+
}}
6190
></div>
62-
)}
63-
</div>
64-
</td>
65-
{accounts.map((account, index) => {
66-
if (index < foo.from || index > foo.to) return <td key={index}></td>
67-
if (index === foo.from)
68-
return (
69-
<td key={index} colSpan={foo.to - foo.from + 1}>
70-
<div className={cn('flex items-center justify-center')}>
71-
<SvgCircle width={20} height={20}></SvgCircle>
72-
<div
73-
style={{ width: `calc(${(100 - 100 / (foo.to - foo.from + 1)).toFixed(2)}% - 20px)`, height: '20px' }}
74-
className="relative text-primary"
75-
>
76-
{foo.direction === 'rightToLeft' && <SvgPointerLeft className={cn('absolute top-0 left-0')} />}
77-
<div className={cn('border-primary border-b-2 h-1/2')}></div>
78-
{foo.direction === 'leftToRight' && <SvgPointerRight className={cn('absolute top-0 right-0')} />}
79-
</div>
80-
<SvgCircle width={20} height={20}></SvgCircle>
81-
</div>
82-
</td>
8391
)
84-
else return null
85-
})}
86-
</tr>
92+
}
93+
</div>
94+
</div>
95+
{accounts.map((_, index) => {
96+
if (index < transactionArrow.from || index > transactionArrow.to) return <div key={index}></div>
97+
if (index === transactionArrow.from)
98+
return (
99+
<div
100+
className={cn('flex items-center justify-center')}
101+
style={{
102+
// 2 and 3 are the number to offset the name column
103+
gridColumnStart: transactionArrow.from + 2,
104+
gridColumnEnd: transactionArrow.to + 3,
105+
}}
106+
>
107+
<SvgCircle width={graphConfig.circleDimension} height={graphConfig.circleDimension}></SvgCircle>
108+
<div
109+
style={{
110+
width: `calc(${(100 - 100 / (transactionArrow.to - transactionArrow.from + 1)).toFixed(2)}% - ${graphConfig.circleDimension}px)`,
111+
height: `${graphConfig.circleDimension}px`,
112+
}}
113+
className="relative text-primary"
114+
>
115+
{transactionArrow.direction === 'rightToLeft' && <SvgPointerLeft className={cn('absolute top-0 left-0')} />}
116+
<div className={cn('border-primary border-b-2 h-1/2')}></div>
117+
{transactionArrow.direction === 'leftToRight' && <SvgPointerRight className={cn('absolute top-0 right-0')} />}
118+
</div>
119+
<SvgCircle width={graphConfig.circleDimension} height={graphConfig.circleDimension}></SvgCircle>
120+
</div>
121+
)
122+
else return null
123+
})}
124+
87125
{hasChildren &&
88126
transaction.transactions?.map((childTransaction, index, arr) => (
89-
<TransactionTableRow
127+
<TransactionRow
90128
transaction={childTransaction}
91129
hasChildren={childTransaction.transactions && childTransaction.transactions.length > 0}
92130
hasParent={true}
@@ -159,56 +197,55 @@ export function GroupPage() {
159197
},
160198
],
161199
}
162-
const accounts = extractSendersAndReceivers(group)
163-
const allTransactionCounts = 16
200+
const { transactionCount, accounts } = extractSendersAndReceivers(group)
164201

165202
return (
166-
<table className={cn('relative')}>
167-
<tr>
168-
<th></th>
169-
{accounts.map((account, index) => (
170-
<th className={cn('w-32 p-2 h-10')} key={index}>
171-
{account}
172-
</th>
173-
))}
174-
</tr>
175-
<tbody className={cn('absolute top-10 right-0 -z-10')}>
176-
<tr>
177-
<td className={cn('p-0')}></td>
178-
<td
203+
<div
204+
className={cn('relative grid')}
205+
style={{
206+
gridTemplateColumns: `minmax(${graphConfig.colWidth}px, 1fr) repeat(${accounts.length}, ${graphConfig.colWidth}px)`,
207+
gridTemplateRows: `repeat(${transactionCount + 1}, ${graphConfig.rowHeight}px)`,
208+
}}
209+
>
210+
<div>{/* The first header cell is empty */}</div>
211+
{accounts.map((account, index) => (
212+
<div className={cn('p-2 flex justify-center')} key={index}>
213+
{account}
214+
</div>
215+
))}
216+
<div className={cn('absolute right-0 -z-10')} style={{ top: `${graphConfig.rowHeight}px` }}>
217+
<div>
218+
<div className={cn('p-0')}></div>
219+
<div
179220
className={cn('p-0')}
180-
rowSpan={allTransactionCounts}
181-
colSpan={accounts.length}
182-
style={{ height: `${allTransactionCounts * 40}px`, width: `${128 * accounts.length}px` }}
221+
style={{ height: `${transactionCount * graphConfig.rowHeight}px`, width: `${graphConfig.colWidth * accounts.length}px` }}
183222
>
184223
<div
185224
className={cn('grid h-full')}
186225
style={{
187226
gridTemplateColumns: `repeat(${accounts.length}, minmax(0, 1fr))`,
188-
height: `${allTransactionCounts * 40}px`,
227+
height: `${transactionCount * graphConfig.rowHeight}px`,
189228
}}
190229
>
191-
{accounts.map((account, index) => (
230+
{accounts.map((_, index) => (
192231
<div key={index} className={cn('flex justify-center')}>
193232
<div className={cn('border-muted border-l-2 h-full border-dashed')}></div>
194233
</div>
195234
))}
196235
</div>
197-
</td>
198-
</tr>
199-
</tbody>
200-
<tbody>
201-
{group.transactions.map((transaction, index, arr) => (
202-
<TransactionTableRow
203-
transaction={transaction}
204-
hasChildren={transaction.transactions && transaction.transactions.length > 0}
205-
hasParent={false}
206-
hasNextSibbling={index < arr.length - 1}
207-
accounts={accounts}
208-
/>
209-
))}
210-
</tbody>
211-
</table>
236+
</div>
237+
</div>
238+
</div>
239+
{group.transactions.map((transaction, index, arr) => (
240+
<TransactionRow
241+
transaction={transaction}
242+
hasChildren={transaction.transactions && transaction.transactions.length > 0}
243+
hasParent={false}
244+
hasNextSibbling={index < arr.length - 1}
245+
accounts={accounts}
246+
/>
247+
))}
248+
</div>
212249
)
213250
}
214251

@@ -223,14 +260,16 @@ export type Transaction = {
223260
receiver: string
224261
}
225262

226-
function extractSendersAndReceivers(group: Group): string[] {
227-
let sendersAndReceivers: string[] = []
263+
function extractSendersAndReceivers(group: Group) {
264+
let transactionCount = 0
265+
let accounts: string[] = []
228266

229267
function extract(transactionArr: Transaction[]) {
230268
if (transactionArr) {
231269
transactionArr.forEach((transaction) => {
232-
sendersAndReceivers.push(transaction.sender)
233-
sendersAndReceivers.push(transaction.receiver)
270+
transactionCount++
271+
accounts.push(transaction.sender)
272+
accounts.push(transaction.receiver)
234273
if (transaction.transactions) {
235274
extract(transaction.transactions)
236275
}
@@ -241,12 +280,17 @@ function extractSendersAndReceivers(group: Group): string[] {
241280
extract(group.transactions)
242281

243282
// Remove duplicates
244-
sendersAndReceivers = Array.from(new Set(sendersAndReceivers))
283+
accounts = Array.from(new Set(accounts))
284+
// Sort
285+
accounts = accounts.sort((a, b) => (a > b ? 1 : a < b ? -1 : 0))
245286

246-
return sendersAndReceivers.sort((a, b) => (a > b ? 1 : a < b ? -1 : 0))
287+
return {
288+
transactionCount: transactionCount,
289+
accounts: accounts,
290+
}
247291
}
248292

249-
function calcTransactionFoo(transaction: Transaction, accounts: string[]): TransactionFooDrawing {
293+
function calcTransactionArrow(transaction: Transaction, accounts: string[]): TransactionArrow {
250294
const fromAccount = accounts.findIndex((a) => transaction.sender === a)
251295
const toAccount = accounts.findIndex((a) => transaction.receiver === a)
252296
const direction = fromAccount < toAccount ? 'leftToRight' : fromAccount > toAccount ? 'rightToLeft' : 'toSelf'
@@ -257,3 +301,11 @@ function calcTransactionFoo(transaction: Transaction, accounts: string[]): Trans
257301
direction: direction,
258302
}
259303
}
304+
305+
const graphConfig = {
306+
rowHeight: 40,
307+
colWidth: 128,
308+
indentationWidth: 16,
309+
lineWidth: 2,
310+
circleDimension: 20,
311+
}

0 commit comments

Comments
 (0)