1
- import React , { useCallback , useRef } from 'react' ;
2
- import type { GestureResponderEvent , View } from 'react-native' ;
1
+ import React , { useCallback , useEffect , useRef , useState } from 'react' ;
2
+ import { Dimensions } from 'react-native' ;
3
+ import type { EmitterSubscription , GestureResponderEvent , View } from 'react-native' ;
3
4
import { withOnyx } from 'react-native-onyx' ;
4
5
import type { OnyxEntry } from 'react-native-onyx' ;
6
+ import AddPaymentMethodMenu from '@components/AddPaymentMethodMenu' ;
5
7
import * as BankAccounts from '@libs/actions/BankAccounts' ;
8
+ import getClickedTargetLocation from '@libs/getClickedTargetLocation' ;
6
9
import Log from '@libs/Log' ;
7
10
import Navigation from '@libs/Navigation/Navigation' ;
8
11
import * as PaymentUtils from '@libs/PaymentUtils' ;
9
12
import * as ReportUtils from '@libs/ReportUtils' ;
13
+ import * as PaymentMethods from '@userActions/PaymentMethods' ;
10
14
import * as Policy from '@userActions/Policy/Policy' ;
11
15
import * as Wallet from '@userActions/Wallet' ;
12
16
import CONST from '@src/CONST' ;
@@ -15,7 +19,10 @@ import ROUTES from '@src/ROUTES';
15
19
import type { BankAccountList , FundList , ReimbursementAccount , UserWallet , WalletTerms } from '@src/types/onyx' ;
16
20
import type { PaymentMethodType } from '@src/types/onyx/OriginalMessage' ;
17
21
import viewRef from '@src/types/utils/viewRef' ;
18
- import type { KYCWallProps , PaymentMethod } from './types' ;
22
+ import type { AnchorPosition , DomRect , KYCWallProps , PaymentMethod } from './types' ;
23
+
24
+ // This sets the Horizontal anchor position offset for POPOVER MENU.
25
+ const POPOVER_MENU_ANCHOR_POSITION_HORIZONTAL_OFFSET = 20 ;
19
26
20
27
type BaseKYCWallOnyxProps = {
21
28
/** The user's wallet */
@@ -42,6 +49,10 @@ type BaseKYCWallProps = KYCWallProps & BaseKYCWallOnyxProps;
42
49
function KYCWall ( {
43
50
addBankAccountRoute,
44
51
addDebitCardRoute,
52
+ anchorAlignment = {
53
+ horizontal : CONST . MODAL . ANCHOR_ORIGIN_HORIZONTAL . LEFT ,
54
+ vertical : CONST . MODAL . ANCHOR_ORIGIN_VERTICAL . BOTTOM ,
55
+ } ,
45
56
bankAccountList = { } ,
46
57
chatReportID = '' ,
47
58
children,
@@ -52,13 +63,60 @@ function KYCWall({
52
63
onSuccessfulKYC,
53
64
reimbursementAccount,
54
65
shouldIncludeDebitCard = true ,
66
+ shouldListenForResize = false ,
55
67
source,
56
68
userWallet,
57
69
walletTerms,
70
+ shouldShowPersonalBankAccountOption = false ,
58
71
} : BaseKYCWallProps ) {
59
72
const anchorRef = useRef < HTMLDivElement | View > ( null ) ;
60
73
const transferBalanceButtonRef = useRef < HTMLDivElement | View | null > ( null ) ;
61
74
75
+ const [ shouldShowAddPaymentMenu , setShouldShowAddPaymentMenu ] = useState ( false ) ;
76
+
77
+ const [ anchorPosition , setAnchorPosition ] = useState ( {
78
+ anchorPositionVertical : 0 ,
79
+ anchorPositionHorizontal : 0 ,
80
+ } ) ;
81
+
82
+ const getAnchorPosition = useCallback (
83
+ ( domRect : DomRect ) : AnchorPosition => {
84
+ if ( anchorAlignment . vertical === CONST . MODAL . ANCHOR_ORIGIN_VERTICAL . TOP ) {
85
+ return {
86
+ anchorPositionVertical : domRect . top + domRect . height + CONST . MODAL . POPOVER_MENU_PADDING ,
87
+ anchorPositionHorizontal : domRect . left + POPOVER_MENU_ANCHOR_POSITION_HORIZONTAL_OFFSET ,
88
+ } ;
89
+ }
90
+
91
+ return {
92
+ anchorPositionVertical : domRect . top - CONST . MODAL . POPOVER_MENU_PADDING ,
93
+ anchorPositionHorizontal : domRect . left ,
94
+ } ;
95
+ } ,
96
+ [ anchorAlignment . vertical ] ,
97
+ ) ;
98
+
99
+ /**
100
+ * Set position of the transfer payment menu
101
+ */
102
+ const setPositionAddPaymentMenu = ( { anchorPositionVertical, anchorPositionHorizontal} : AnchorPosition ) => {
103
+ setAnchorPosition ( {
104
+ anchorPositionVertical,
105
+ anchorPositionHorizontal,
106
+ } ) ;
107
+ } ;
108
+
109
+ const setMenuPosition = useCallback ( ( ) => {
110
+ if ( ! transferBalanceButtonRef . current ) {
111
+ return ;
112
+ }
113
+
114
+ const buttonPosition = getClickedTargetLocation ( transferBalanceButtonRef . current as HTMLDivElement ) ;
115
+ const position = getAnchorPosition ( buttonPosition ) ;
116
+
117
+ setPositionAddPaymentMenu ( position ) ;
118
+ } , [ getAnchorPosition ] ) ;
119
+
62
120
const selectPaymentMethod = useCallback (
63
121
( paymentMethod : PaymentMethod ) => {
64
122
onSelectPaymentMethod ( paymentMethod ) ;
@@ -101,6 +159,11 @@ function KYCWall({
101
159
*/
102
160
Wallet . setKYCWallSource ( source , chatReportID ) ;
103
161
162
+ if ( shouldShowAddPaymentMenu ) {
163
+ setShouldShowAddPaymentMenu ( false ) ;
164
+ return ;
165
+ }
166
+
104
167
// Use event target as fallback if anchorRef is null for safety
105
168
const targetElement = anchorRef . current ?? ( event ?. currentTarget as HTMLDivElement ) ;
106
169
@@ -121,19 +184,11 @@ function KYCWall({
121
184
return ;
122
185
}
123
186
124
- switch ( iouPaymentType ) {
125
- case CONST . PAYMENT_METHODS . PERSONAL_BANK_ACCOUNT :
126
- selectPaymentMethod ( CONST . PAYMENT_METHODS . PERSONAL_BANK_ACCOUNT ) ;
127
- break ;
128
- case CONST . PAYMENT_METHODS . DEBIT_CARD :
129
- selectPaymentMethod ( CONST . PAYMENT_METHODS . DEBIT_CARD ) ;
130
- break ;
131
- case CONST . PAYMENT_METHODS . BUSINESS_BANK_ACCOUNT :
132
- selectPaymentMethod ( CONST . PAYMENT_METHODS . BUSINESS_BANK_ACCOUNT ) ;
133
- break ;
134
- default :
135
- break ;
136
- }
187
+ const clickedElementLocation = getClickedTargetLocation ( targetElement as HTMLDivElement ) ;
188
+ const position = getAnchorPosition ( clickedElementLocation ) ;
189
+
190
+ setPositionAddPaymentMenu ( position ) ;
191
+ setShouldShowAddPaymentMenu ( true ) ;
137
192
138
193
return ;
139
194
}
@@ -159,18 +214,58 @@ function KYCWall({
159
214
chatReportID ,
160
215
enablePaymentsRoute ,
161
216
fundList ,
217
+ getAnchorPosition ,
162
218
iouReport ,
163
219
onSuccessfulKYC ,
164
220
reimbursementAccount ?. achData ?. state ,
165
221
selectPaymentMethod ,
166
222
shouldIncludeDebitCard ,
223
+ shouldShowAddPaymentMenu ,
167
224
source ,
168
225
userWallet ?. tierName ,
169
226
walletTerms ?. source ,
170
227
] ,
171
228
) ;
172
229
173
- return < > { children ( continueAction , viewRef ( anchorRef ) ) } </ > ;
230
+ useEffect ( ( ) => {
231
+ let dimensionsSubscription : EmitterSubscription | null = null ;
232
+
233
+ PaymentMethods . kycWallRef . current = { continueAction} ;
234
+
235
+ if ( shouldListenForResize ) {
236
+ dimensionsSubscription = Dimensions . addEventListener ( 'change' , setMenuPosition ) ;
237
+ }
238
+
239
+ return ( ) => {
240
+ if ( shouldListenForResize && dimensionsSubscription ) {
241
+ dimensionsSubscription . remove ( ) ;
242
+ }
243
+
244
+ PaymentMethods . kycWallRef . current = null ;
245
+ } ;
246
+ } , [ chatReportID , setMenuPosition , shouldListenForResize , continueAction ] ) ;
247
+
248
+ return (
249
+ < >
250
+ < AddPaymentMethodMenu
251
+ isVisible = { shouldShowAddPaymentMenu }
252
+ iouReport = { iouReport }
253
+ onClose = { ( ) => setShouldShowAddPaymentMenu ( false ) }
254
+ anchorRef = { anchorRef }
255
+ anchorPosition = { {
256
+ vertical : anchorPosition . anchorPositionVertical ,
257
+ horizontal : anchorPosition . anchorPositionHorizontal ,
258
+ } }
259
+ anchorAlignment = { anchorAlignment }
260
+ onItemSelected = { ( item : PaymentMethod ) => {
261
+ setShouldShowAddPaymentMenu ( false ) ;
262
+ selectPaymentMethod ( item ) ;
263
+ } }
264
+ shouldShowPersonalBankAccountOption = { shouldShowPersonalBankAccountOption }
265
+ />
266
+ { children ( continueAction , viewRef ( anchorRef ) ) }
267
+ </ >
268
+ ) ;
174
269
}
175
270
176
271
KYCWall . displayName = 'BaseKYCWall' ;
0 commit comments