15
15
* limitations under the License.
16
16
*/
17
17
18
- import { Component } from 'react' ;
18
+ import { useState } from 'react' ;
19
+ import { useTranslation } from 'react-i18next' ;
19
20
import * as accountApi from '../../api/account' ;
20
- import { translate , TranslateProps } from '../../decorators/translate' ;
21
21
import { A } from '../anchor/anchor' ;
22
22
import { Dialog } from '../dialog/dialog' ;
23
23
import { CopyableInput } from '../copy/Copy' ;
@@ -30,176 +30,155 @@ import { Note } from './note';
30
30
import parentStyle from './transactions.module.css' ;
31
31
import style from './transaction.module.css' ;
32
32
33
- interface State {
34
- transactionDialog : boolean ;
35
- transactionInfo ?: accountApi . ITransaction ;
36
- }
33
+ type Props = {
34
+ accountCode : accountApi . AccountCode ;
35
+ index : number ;
36
+ explorerURL : string ;
37
+ } & accountApi . ITransaction ;
37
38
38
- interface TransactionProps extends accountApi . ITransaction {
39
- accountCode : accountApi . AccountCode ;
40
- index : number ;
41
- explorerURL : string ;
42
- }
39
+ export const Transaction = ( {
40
+ accountCode,
41
+ index,
42
+ internalID,
43
+ explorerURL,
44
+ type,
45
+ amount,
46
+ feeRatePerKb,
47
+ numConfirmations,
48
+ numConfirmationsComplete,
49
+ time,
50
+ addresses,
51
+ status,
52
+ note = '' ,
53
+ } : Props ) => {
54
+ const { i18n, t } = useTranslation ( ) ;
55
+ const [ transactionDialog , setTransactionDialog ] = useState < boolean > ( false ) ;
56
+ const [ transactionInfo , setTransactionInfo ] = useState < accountApi . ITransaction > ( ) ;
43
57
44
- type Props = TransactionProps & TranslateProps ;
45
-
46
- class Transaction extends Component < Props , State > {
47
- public readonly state : State = {
48
- transactionDialog : false ,
49
- } ;
50
-
51
- private parseTimeShort = ( time : string ) => {
58
+ const parseTimeShort = ( time : string ) => {
52
59
const options = {
53
60
year : 'numeric' ,
54
61
month : 'numeric' ,
55
62
day : 'numeric' ,
56
63
} as Intl . DateTimeFormatOptions ;
57
- return new Date ( Date . parse ( time ) ) . toLocaleString ( this . props . i18n . language , options ) ;
64
+ return new Date ( Date . parse ( time ) ) . toLocaleString ( i18n . language , options ) ;
58
65
} ;
59
66
60
- private showDetails = ( ) => {
61
- accountApi . getTransaction ( this . props . accountCode , this . props . internalID ) . then ( transaction => {
67
+ const showDetails = ( ) => {
68
+ accountApi . getTransaction ( accountCode , internalID ) . then ( transaction => {
62
69
if ( ! transaction ) {
63
- console . error ( 'Unable to retrieve transaction ' + this . props . internalID ) ;
70
+ console . error ( 'Unable to retrieve transaction ' + internalID ) ;
64
71
return null ;
65
72
}
66
- this . setState ( {
67
- transactionInfo : transaction ,
68
- transactionDialog : true ,
69
- } ) ;
73
+ setTransactionInfo ( transaction ) ;
74
+ setTransactionDialog ( true ) ;
70
75
} )
71
76
. catch ( console . error ) ;
72
77
} ;
73
78
74
- private hideDetails = ( ) => {
75
- this . setState ( { transactionDialog : false } ) ;
76
- } ;
79
+ const arrow = status === 'failed' ? (
80
+ < Warning style = { { maxWidth : '18px' } } />
81
+ ) : type === 'receive' ? (
82
+ < ArrowIn />
83
+ ) : type === 'send' ? (
84
+ < ArrowOut />
85
+ ) : (
86
+ < ArrowSelf />
87
+ ) ;
88
+ const sign = ( ( type === 'send' ) && '−' ) || ( ( type === 'receive' ) && '+' ) || '' ;
89
+ const typeClassName = ( status === 'failed' && style . failed ) || ( type === 'send' && style . send ) || ( type === 'receive' && style . receive ) || '' ;
90
+ const sDate = time ? parseTimeShort ( time ) : '---' ;
91
+ const statusText = t ( `transaction.status.${ status } ` ) ;
92
+ const progress = numConfirmations < numConfirmationsComplete ? ( numConfirmations / numConfirmationsComplete ) * 100 : 100 ;
77
93
78
- public render ( ) {
79
- const {
80
- t,
81
- index,
82
- explorerURL,
83
- type,
84
- amount,
85
- feeRatePerKb,
86
- numConfirmations,
87
- numConfirmationsComplete,
88
- time,
89
- addresses,
90
- status,
91
- note = '' ,
92
- } = this . props ;
93
- const {
94
- transactionDialog,
95
- transactionInfo,
96
- } = this . state ;
97
- const arrow = status === 'failed' ? (
98
- < Warning style = { { maxWidth : '18px' } } />
99
- ) : type === 'receive' ? (
100
- < ArrowIn />
101
- ) : type === 'send' ? (
102
- < ArrowOut />
103
- ) : (
104
- < ArrowSelf />
105
- ) ;
106
- const sign = ( ( type === 'send' ) && '−' ) || ( ( type === 'receive' ) && '+' ) || '' ;
107
- const typeClassName = ( status === 'failed' && style . failed ) || ( type === 'send' && style . send ) || ( type === 'receive' && style . receive ) || '' ;
108
- const sDate = time ? this . parseTimeShort ( time ) : '---' ;
109
- const statusText = {
110
- complete : t ( 'transaction.status.complete' ) ,
111
- pending : t ( 'transaction.status.pending' ) ,
112
- failed : t ( 'transaction.status.failed' ) ,
113
- } [ status ] ;
114
- const progress = numConfirmations < numConfirmationsComplete ? ( numConfirmations / numConfirmationsComplete ) * 100 : 100 ;
115
-
116
- return (
117
- < div className = { [ style . container , index === 0 ? style . first : '' ] . join ( ' ' ) } >
118
- < div className = { [ parentStyle . columns , style . row ] . join ( ' ' ) } >
119
- < div className = { parentStyle . columnGroup } >
120
- < div className = { parentStyle . type } > { arrow } </ div >
121
- < div className = { parentStyle . date } >
122
- < span className = { style . columnLabel } >
123
- { t ( 'transaction.details.date' ) } :
124
- </ span >
125
- < span className = { style . date } > { sDate } </ span >
126
- </ div >
127
- { note ? (
128
- < div className = { parentStyle . activity } >
129
- < span className = { style . address } >
130
- { note }
131
- </ span >
132
- </ div >
133
- ) : (
134
- < div className = { parentStyle . activity } >
135
- < span className = { style . label } >
136
- { t ( type === 'receive' ? 'transaction.tx.received' : 'transaction.tx.sent' ) }
137
- </ span >
138
- < span className = { style . address } >
139
- { addresses [ 0 ] }
140
- { addresses . length > 1 && (
141
- < span className = { style . badge } >
142
- (+{ addresses . length - 1 } )
143
- </ span >
144
- ) }
145
- </ span >
146
- </ div >
147
- ) }
148
- < div className = { [ parentStyle . action , parentStyle . hideOnMedium ] . join ( ' ' ) } >
149
- < button type = "button" className = { style . action } onClick = { this . showDetails } >
150
- < ExpandIcon expand = { ! transactionDialog } />
151
- </ button >
152
- </ div >
94
+ return (
95
+ < div className = { [ style . container , index === 0 ? style . first : '' ] . join ( ' ' ) } >
96
+ < div className = { [ parentStyle . columns , style . row ] . join ( ' ' ) } >
97
+ < div className = { parentStyle . columnGroup } >
98
+ < div className = { parentStyle . type } > { arrow } </ div >
99
+ < div className = { parentStyle . date } >
100
+ < span className = { style . columnLabel } >
101
+ { t ( 'transaction.details.date' ) } :
102
+ </ span >
103
+ < span className = { style . date } > { sDate } </ span >
153
104
</ div >
154
- < div className = { parentStyle . columnGroup } >
155
- < div className = { parentStyle . status } >
156
- < span className = { style . columnLabel } >
157
- { t ( 'transaction.details.status' ) } :
105
+ { note ? (
106
+ < div className = { parentStyle . activity } >
107
+ < span className = { style . address } >
108
+ { note }
158
109
</ span >
159
- < ProgressRing
160
- className = "m-right-quarter"
161
- width = { 14 }
162
- value = { progress }
163
- isComplete = { numConfirmations >= numConfirmationsComplete }
164
- />
165
- < span className = { style . status } > { statusText } </ span >
166
110
</ div >
167
- < div className = { parentStyle . fiat } >
168
- < span className = { `${ style . fiat } ${ typeClassName } ` } >
169
- < FiatConversion amount = { amount } sign = { sign } noAction />
111
+ ) : (
112
+ < div className = { parentStyle . activity } >
113
+ < span className = { style . label } >
114
+ { t ( type === 'receive' ? 'transaction.tx.received' : 'transaction.tx.sent' ) }
170
115
</ span >
171
- </ div >
172
- < div className = { `${ parentStyle . currency } ${ typeClassName } ` } >
173
- < span
174
- className = { `${ style . amount } ${ style . amountOverflow } ` }
175
- data-unit = { ` ${ amount . unit } ` } >
176
- { sign }
177
- < Amount amount = { amount . amount } unit = { amount . unit } />
178
- < span className = { style . currencyUnit } > { amount . unit } </ span >
116
+ < span className = { style . address } >
117
+ { addresses [ 0 ] }
118
+ { addresses . length > 1 && (
119
+ < span className = { style . badge } >
120
+ (+{ addresses . length - 1 } )
121
+ </ span >
122
+ ) }
179
123
</ span >
180
124
</ div >
181
- < div className = { [ parentStyle . action , parentStyle . showOnMedium ] . join ( ' ' ) } >
182
- < button type = "button" className = { style . action } onClick = { this . showDetails } >
183
- < ExpandIcon expand = { ! transactionDialog } />
184
- </ button >
185
- </ div >
125
+ ) }
126
+ < div className = { [ parentStyle . action , parentStyle . hideOnMedium ] . join ( ' ' ) } >
127
+ < button type = "button" className = { style . action } onClick = { showDetails } >
128
+ < ExpandIcon expand = { ! transactionDialog } />
129
+ </ button >
130
+ </ div >
131
+ </ div >
132
+ < div className = { parentStyle . columnGroup } >
133
+ < div className = { parentStyle . status } >
134
+ < span className = { style . columnLabel } >
135
+ { t ( 'transaction.details.status' ) } :
136
+ </ span >
137
+ < ProgressRing
138
+ className = "m-right-quarter"
139
+ width = { 14 }
140
+ value = { progress }
141
+ isComplete = { numConfirmations >= numConfirmationsComplete }
142
+ />
143
+ < span className = { style . status } > { statusText } </ span >
144
+ </ div >
145
+ < div className = { parentStyle . fiat } >
146
+ < span className = { `${ style . fiat } ${ typeClassName } ` } >
147
+ < FiatConversion amount = { amount } sign = { sign } noAction />
148
+ </ span >
149
+ </ div >
150
+ < div className = { `${ parentStyle . currency } ${ typeClassName } ` } >
151
+ < span
152
+ className = { `${ style . amount } ${ style . amountOverflow } ` }
153
+ data-unit = { ` ${ amount . unit } ` } >
154
+ { sign }
155
+ < Amount amount = { amount . amount } unit = { amount . unit } />
156
+ < span className = { style . currencyUnit } > { amount . unit } </ span >
157
+ </ span >
158
+ </ div >
159
+ < div className = { [ parentStyle . action , parentStyle . showOnMedium ] . join ( ' ' ) } >
160
+ < button type = "button" className = { style . action } onClick = { showDetails } >
161
+ < ExpandIcon expand = { ! transactionDialog } />
162
+ </ button >
186
163
</ div >
187
164
</ div >
188
- { /*
189
- Amount and Confirmations info are displayed using props data
190
- instead of transactionInfo because they are live updated.
191
- */ }
192
- < Dialog
193
- open = { transactionDialog }
194
- title = { t ( 'transaction.details.title' ) }
195
- onClose = { this . hideDetails }
196
- slim
197
- medium >
198
- { transactionInfo && < >
165
+ </ div >
166
+ { /*
167
+ Amount and Confirmations info are displayed using props data
168
+ instead of transactionInfo because they are live updated.
169
+ */ }
170
+ < Dialog
171
+ open = { transactionDialog }
172
+ title = { t ( 'transaction.details.title' ) }
173
+ onClose = { ( ) => setTransactionDialog ( false ) }
174
+ slim
175
+ medium >
176
+ { transactionInfo && (
177
+ < >
199
178
< Note
200
- accountCode = { this . props . accountCode }
201
- internalID = { this . props . internalID }
202
- note = { this . props . note }
179
+ accountCode = { accountCode }
180
+ internalID = { internalID }
181
+ note = { note }
203
182
/>
204
183
< div className = { style . detail } >
205
184
< label > { t ( 'transaction.details.type' ) } </ label >
@@ -360,13 +339,9 @@ class Transaction extends Component<Props, State> {
360
339
{ t ( 'transaction.explorerTitle' ) }
361
340
</ A >
362
341
</ div >
363
- </ > }
364
- </ Dialog >
365
- </ div >
366
- ) ;
367
- }
368
- }
369
-
370
- const HOC = translate ( ) ( Transaction ) ;
371
-
372
- export { HOC as Transaction } ;
342
+ </ >
343
+ ) }
344
+ </ Dialog >
345
+ </ div >
346
+ ) ;
347
+ } ;
0 commit comments