@@ -7,89 +7,171 @@ type TransactionTrProps = {
77 hasParent ?: boolean
88 hasNextSibbling ?: boolean
99 hasChildren ?: boolean
10+ accounts : string [ ]
11+ indentLevel ?: number
12+ verticalBars ?: number [ ]
1013}
11- function TransactionTr ( { transaction, hasParent = false , hasNextSibbling = false , hasChildren = false } : TransactionTrProps ) {
14+ function TransactionTr ( {
15+ transaction,
16+ accounts,
17+ hasParent = false ,
18+ hasNextSibbling = false ,
19+ hasChildren = false ,
20+ indentLevel = 0 ,
21+ verticalBars,
22+ } : TransactionTrProps ) {
1223 return (
13- < tr >
14- < td className = "p-0" >
15- < div className = { cn ( `relative h-10 p-0 flex items-center` , 'px-0' ) } >
16- { hasParent && (
17- < div className = { cn ( 'w-8' , `border-primary border-l-2 border-b-2 rounded-bl-lg` , `h-[50%]` , `absolute top-0 left-0` ) } > </ div >
18- ) }
19- < div className = { cn ( 'inline ml-8' ) } > { transaction . name } </ div >
20- { hasParent && hasNextSibbling && (
21- < div className = { cn ( 'w-8' , 'border-primary border-l-2' , 'h-[22px]' , 'absolute top-[18px] left-0' ) } > </ div >
22- ) }
23- { hasChildren && ! hasParent && (
24- < div
25- className = { cn (
26- 'w-8' ,
27- `border-primary border-l-2 border-t-2 rounded-tl-lg` ,
28- `h-[calc(50%+2px)]` ,
29- `absolute top-[calc(50%-2px)] left-0`
30- ) }
31- > </ div >
32- ) }
33- { hasChildren && hasParent && (
34- < div
35- className = { cn ( 'w-2 ml-4' , 'border-primary border-l-2 border-t-2 rounded-tl-lg' , 'h-[22px]' , 'absolute top-[18px] left-0' ) }
36- > </ div >
37- ) }
38- </ div >
39- { hasChildren && (
40- < div className = { cn ( 'relative' , hasParent ? 'pl-4' : '' ) } >
41- { hasNextSibbling && < div className = { cn ( `border-primary border-l-2` , `h-full` , 'absolute top-0 left-0' ) } > </ div > }
42- < table >
43- { transaction . transactions ?. map ( ( childTransaction , index , arr ) => (
44- < TransactionTr
45- transaction = { childTransaction }
46- hasChildren = { childTransaction . transactions && childTransaction . transactions . length > 0 }
47- hasParent = { true }
48- hasNextSibbling = { index < arr . length - 1 }
49- />
50- ) ) }
51- </ table >
24+ < >
25+ < tr >
26+ < td className = { cn ( 'p-0 relative' ) } >
27+ { verticalBars &&
28+ verticalBars . length &&
29+ verticalBars
30+ . filter ( ( b ) => b > 0 )
31+ . map ( ( b , i ) => < div key = { i } className = { cn ( 'h-10 border-primary border-l-2 absolute' ) } style = { { marginLeft : b * 16 } } > </ div > ) }
32+ < div className = { cn ( `relative h-10 p-0 flex items-center` , 'px-0' ) } style = { { marginLeft : indentLevel * 16 } } >
33+ { hasParent && (
34+ < div className = { cn ( 'w-8' , `border-primary border-l-2 border-b-2 rounded-bl-lg` , `h-[50%]` , `absolute top-0 left-0` ) } > </ div >
35+ ) }
36+ < div className = { cn ( 'inline ml-8' ) } > { transaction . name } </ div >
37+ { hasParent && hasNextSibbling && (
38+ < div className = { cn ( 'w-8' , 'border-primary border-l-2' , 'h-[22px]' , 'absolute top-[18px] left-0' ) } > </ div >
39+ ) }
40+ { hasChildren && (
41+ < div
42+ className = { cn ( 'w-2 ml-4' , 'border-primary border-l-2 border-t-2 rounded-tl-lg' , 'h-[22px]' , 'absolute top-[18px] left-0' ) }
43+ > </ div >
44+ ) }
5245 </ div >
53- ) }
54- </ td >
55- < td > </ td >
56- </ tr >
46+ </ td >
47+ { accounts . map ( ( account , index ) => (
48+ < td key = { index } className = { cn ( 'p-0 relative' ) } >
49+ < div className = { cn ( 'h-10 border-l-2 border-muted border-dashed absolute left-[50%]' ) } > </ div >
50+ </ td >
51+ ) ) }
52+ </ tr >
53+
54+ { hasChildren &&
55+ transaction . transactions ?. map ( ( childTransaction , index , arr ) => (
56+ < TransactionTr
57+ transaction = { childTransaction }
58+ hasChildren = { childTransaction . transactions && childTransaction . transactions . length > 0 }
59+ hasParent = { true }
60+ hasNextSibbling = { index < arr . length - 1 }
61+ accounts = { accounts }
62+ indentLevel = { indentLevel + 1 }
63+ verticalBars = { [ ...( verticalBars ?? [ ] ) , hasNextSibbling ? indentLevel : 0 ] }
64+ />
65+ ) ) }
66+ </ >
5767 )
5868}
5969
6070export function GroupPage ( ) {
61- const group : Transaction = {
62- name : '' ,
71+ const group : Group = {
6372 transactions : [
64- { name : '7VSN...' } ,
73+ { name : '7VSN...' , sender : 'Account 1' , receiver : 'Account 2' } ,
6574 {
6675 name : 'NDQX...' ,
76+ sender : 'Account 1' ,
77+ receiver : 'Account 2' ,
6778 transactions : [
68- { name : 'Inner 1' } ,
69- { name : 'Inner 2' , transactions : [ { name : 'Inner 3' } , { name : 'Inner 5' } ] } ,
70- { name : 'Inner 9' } ,
71- { name : 'Inner 4' , transactions : [ { name : 'Inner 6' } , { name : 'Inner 7' } ] } ,
72- { name : 'Inner 8' } ,
79+ { name : 'Inner 1' , sender : 'Account 1' , receiver : 'Account 3' } ,
80+ {
81+ name : 'Inner 2' ,
82+ sender : 'Account 2' ,
83+ receiver : 'Account 5' ,
84+ transactions : [
85+ { name : 'Inner 3' , sender : 'Account 5' , receiver : 'Account 1' } ,
86+ {
87+ name : 'Inner 11' ,
88+ sender : 'Account 3' ,
89+ receiver : 'Account 1' ,
90+ transactions : [
91+ { name : 'Inner 10' , sender : 'Account 2' , receiver : 'Account 6' } ,
92+ { name : 'Inner 10' , sender : 'Account 2' , receiver : 'Account 6' } ,
93+ ] ,
94+ } ,
95+ {
96+ name : 'Inner 5' ,
97+ sender : 'Account 3' ,
98+ receiver : 'Account 1' ,
99+ transactions : [ { name : 'Inner 10' , sender : 'Account 2' , receiver : 'Account 6' } ] ,
100+ } ,
101+ ] ,
102+ } ,
103+ { name : 'Inner 9' , sender : 'Account 2' , receiver : 'Account 6' } ,
104+ {
105+ name : 'Inner 4' ,
106+ sender : 'Account 1' ,
107+ receiver : 'Account 1' ,
108+ transactions : [
109+ { name : 'Inner 6' , sender : 'Account 3' , receiver : 'Account 2' } ,
110+ {
111+ name : 'Inner 7' ,
112+ sender : 'Account 4' ,
113+ receiver : 'Account 2' ,
114+ } ,
115+ ] ,
116+ } ,
117+ { name : 'Inner 8' , sender : 'Account 5' , receiver : 'Account 3' } ,
73118 ] ,
74119 } ,
75120 ] ,
76121 }
122+ const accounts = extractSendersAndReceivers ( group )
77123
78124 return (
79- < table >
125+ < table className = { cn ( 'w-full' ) } >
126+ < tr >
127+ < th > </ th >
128+ { accounts . map ( ( account , index ) => (
129+ < th key = { index } > { account } </ th >
130+ ) ) }
131+ </ tr >
80132 { group . transactions ?. map ( ( transaction , index , arr ) => (
81133 < TransactionTr
82134 transaction = { transaction }
83135 hasChildren = { transaction . transactions && transaction . transactions . length > 0 }
84136 hasParent = { false }
85137 hasNextSibbling = { index < arr . length - 1 }
138+ accounts = { accounts }
86139 />
87140 ) ) }
88141 </ table >
89142 )
90143}
91144
145+ export type Group = {
146+ transactions ?: Transaction [ ]
147+ }
148+
92149export type Transaction = {
93150 name : string
94151 transactions ?: Transaction [ ]
152+ sender : string
153+ receiver : string
154+ }
155+
156+ function extractSendersAndReceivers ( group : Group ) : string [ ] {
157+ let sendersAndReceivers : string [ ] = [ ]
158+
159+ function extract ( transactionArr : Transaction [ ] | undefined ) {
160+ if ( transactionArr ) {
161+ transactionArr . forEach ( ( transaction ) => {
162+ sendersAndReceivers . push ( transaction . sender )
163+ sendersAndReceivers . push ( transaction . receiver )
164+ if ( transaction . transactions ) {
165+ extract ( transaction . transactions )
166+ }
167+ } )
168+ }
169+ }
170+
171+ extract ( group . transactions )
172+
173+ // Remove duplicates
174+ sendersAndReceivers = Array . from ( new Set ( sendersAndReceivers ) )
175+
176+ return sendersAndReceivers
95177}
0 commit comments