Skip to content

Commit 8c68d1e

Browse files
committed
fixup! Fix RampBankFormScene UI & UX
Pass countryCode through workflow params instead of hardcoding 'US'. Apply US-specific bank validation only for US customers. TODO: Extend validation for other countries when internationalized.
1 parent d56b9b8 commit 8c68d1e

File tree

4 files changed

+57
-25
lines changed

4 files changed

+57
-25
lines changed

src/components/scenes/RampBankFormScene.tsx

Lines changed: 47 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,8 @@ export interface BankFormData {
2525
}
2626

2727
export interface RampBankFormParams {
28+
/** ISO country code for region-specific validation */
29+
countryCode: string
2830
onSubmit: (formData: BankFormData) => Promise<void>
2931
/**
3032
* Callback invoked when the user navigates away from the scene.
@@ -42,7 +44,7 @@ interface ValidationResult {
4244

4345
export const RampBankFormScene: React.FC<Props> = props => {
4446
const { navigation, route } = props
45-
const { onSubmit, onCancel } = route.params
47+
const { countryCode, onSubmit, onCancel } = route.params
4648

4749
const theme = useTheme()
4850
const styles = getStyles(theme)
@@ -71,12 +73,12 @@ export const RampBankFormScene: React.FC<Props> = props => {
7173
const routingNumberRef = React.useRef<TextInput>(null)
7274

7375
const handleAccountNumberBlur = useHandler(() => {
74-
const result = validateAccountNumber(accountNumber)
76+
const result = validateAccountNumber(accountNumber, countryCode)
7577
setFieldErrors(prev => ({ ...prev, accountNumber: result.errorMessage }))
7678
})
7779

7880
const handleRoutingNumberBlur = useHandler(() => {
79-
const result = validateRoutingNumber(routingNumber)
81+
const result = validateRoutingNumber(routingNumber, countryCode)
8082
setFieldErrors(prev => ({ ...prev, routingNumber: result.errorMessage }))
8183
})
8284

@@ -100,8 +102,14 @@ export const RampBankFormScene: React.FC<Props> = props => {
100102
ownerLastName.trim() !== ''
101103

102104
// Use the same validation functions for form validity
103-
const accountValid = validateAccountNumber(accountNumber).isValid
104-
const routingValid = validateRoutingNumber(routingNumber).isValid
105+
const accountValid = validateAccountNumber(
106+
accountNumber,
107+
countryCode
108+
).isValid
109+
const routingValid = validateRoutingNumber(
110+
routingNumber,
111+
countryCode
112+
).isValid
105113

106114
const hasNoFieldErrors =
107115
fieldErrors.accountNumber === '' && fieldErrors.routingNumber === ''
@@ -110,6 +118,7 @@ export const RampBankFormScene: React.FC<Props> = props => {
110118
}, [
111119
bankName,
112120
accountNumber,
121+
countryCode,
113122
routingNumber,
114123
accountName,
115124
ownerFirstName,
@@ -190,14 +199,15 @@ export const RampBankFormScene: React.FC<Props> = props => {
190199
onSubmitEditing={() => accountNumberRef.current?.focus()}
191200
/>
192201

202+
{/* TODO: Adjust maxLength for other countries when internationalized */}
193203
<FilledTextInput
194204
ref={accountNumberRef}
195205
value={accountNumber}
196206
onChangeText={handleAccountNumberChange}
197207
placeholder={lstrings.ramp_account_number_placeholder}
198208
keyboardType="number-pad"
199209
returnKeyType="next"
200-
maxLength={17}
210+
maxLength={countryCode === 'US' ? 17 : undefined}
201211
error={fieldErrors.accountNumber}
202212
aroundRem={0.5}
203213
onBlur={handleAccountNumberBlur}
@@ -211,7 +221,7 @@ export const RampBankFormScene: React.FC<Props> = props => {
211221
placeholder={lstrings.ramp_routing_number_placeholder}
212222
keyboardType="number-pad"
213223
returnKeyType="done"
214-
maxLength={9}
224+
maxLength={countryCode === 'US' ? 9 : undefined}
215225
error={fieldErrors.routingNumber}
216226
aroundRem={0.5}
217227
onBlur={handleRoutingNumberBlur}
@@ -240,33 +250,50 @@ const getStyles = cacheStyles((theme: Theme) => ({
240250
}))
241251

242252
// Single source of truth for field validation
243-
const validateAccountNumber = (value: string): ValidationResult => {
253+
// TODO: Extend validation for other countries when the form is internationalized
254+
const validateAccountNumber = (
255+
value: string,
256+
countryCode: string
257+
): ValidationResult => {
244258
const trimmed = value.trim()
245259
if (trimmed === '') {
246260
return { isValid: false, errorMessage: '' }
247261
}
248-
if (trimmed.length < 8) {
249-
return {
250-
isValid: false,
251-
errorMessage: sprintf(
252-
lstrings.ramp_account_number_error_min_length_1s,
253-
'8'
254-
)
262+
263+
// US bank account numbers typically range from 4-17 digits
264+
if (countryCode === 'US') {
265+
if (trimmed.length < 4) {
266+
return {
267+
isValid: false,
268+
errorMessage: sprintf(
269+
lstrings.ramp_account_number_error_min_length_1s,
270+
'4'
271+
)
272+
}
255273
}
256274
}
275+
257276
return { isValid: true, errorMessage: '' }
258277
}
259278

260-
const validateRoutingNumber = (value: string): ValidationResult => {
279+
const validateRoutingNumber = (
280+
value: string,
281+
countryCode: string
282+
): ValidationResult => {
261283
const trimmed = value.trim()
262284
if (trimmed === '') {
263285
return { isValid: false, errorMessage: '' }
264286
}
265-
if (trimmed.length !== 9) {
266-
return {
267-
isValid: false,
268-
errorMessage: sprintf(lstrings.ramp_routing_number_error_length_1s, '9')
287+
288+
// US ABA routing numbers are exactly 9 digits
289+
if (countryCode === 'US') {
290+
if (trimmed.length !== 9) {
291+
return {
292+
isValid: false,
293+
errorMessage: sprintf(lstrings.ramp_routing_number_error_length_1s, '9')
294+
}
269295
}
270296
}
297+
271298
return { isValid: true, errorMessage: '' }
272299
}

src/plugins/ramps/infinite/infiniteRampPlugin.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -660,6 +660,7 @@ export const infiniteRampPlugin: RampPluginFactory = (
660660

661661
// User needs to complete KYC
662662
await kycWorkflow({
663+
countryCode: request.regionCode.countryCode,
663664
infiniteApi,
664665
navigationFlow,
665666
pluginId,
@@ -668,6 +669,7 @@ export const infiniteRampPlugin: RampPluginFactory = (
668669

669670
// Ensure we have a bank account
670671
const bankAccountResult = await bankAccountWorkflow({
672+
countryCode: request.regionCode.countryCode,
671673
infiniteApi,
672674
navigationFlow,
673675
vault

src/plugins/ramps/infinite/workflows/bankAccountWorkflow.ts

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ import type { InfiniteApi } from '../infiniteApiTypes'
55
import type { NavigationFlow } from '../utils/navigationFlow'
66

77
interface Params {
8+
countryCode: string
89
infiniteApi: InfiniteApi
910
navigationFlow: NavigationFlow
1011
vault: EdgeVault
@@ -15,7 +16,7 @@ interface Result {
1516
}
1617

1718
export const bankAccountWorkflow = async (params: Params): Promise<Result> => {
18-
const { infiniteApi, navigationFlow, vault } = params
19+
const { countryCode, infiniteApi, navigationFlow, vault } = params
1920

2021
const authState = infiniteApi.getAuthState()
2122

@@ -37,6 +38,7 @@ export const bankAccountWorkflow = async (params: Params): Promise<Result> => {
3738

3839
const bankAccountId = await new Promise<string>((resolve, reject) => {
3940
navigationFlow.navigate('rampBankForm', {
41+
countryCode,
4042
onSubmit: async (formData: BankFormData) => {
4143
const bankAccount = await infiniteApi.addBankAccount({
4244
type: 'bank_account',

src/plugins/ramps/infinite/workflows/kycWorkflow.ts

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ import {
1414
import type { NavigationFlow } from '../utils/navigationFlow'
1515

1616
interface Params {
17+
countryCode: string
1718
infiniteApi: InfiniteApi
1819
navigationFlow: NavigationFlow
1920
pluginId: string
@@ -22,7 +23,7 @@ interface Params {
2223

2324
// Exports
2425
export const kycWorkflow = async (params: Params): Promise<void> => {
25-
const { infiniteApi, navigationFlow, pluginId, vault } = params
26+
const { countryCode, infiniteApi, navigationFlow, pluginId, vault } = params
2627

2728
let customerId = infiniteApi.getAuthState().customerId
2829

@@ -70,7 +71,7 @@ export const kycWorkflow = async (params: Params): Promise<void> => {
7071
const customerResponse = await infiniteApi
7172
.createCustomer({
7273
type: 'individual',
73-
countryCode: 'US',
74+
countryCode,
7475
contactInformation: {
7576
email: contactInfo.email
7677
},
@@ -84,7 +85,7 @@ export const kycWorkflow = async (params: Params): Promise<void> => {
8485
city: contactInfo.city,
8586
state: contactInfo.state,
8687
postalCode: contactInfo.postalCode,
87-
country: 'US'
88+
country: countryCode
8889
},
8990
companyInformation: undefined
9091
})
@@ -150,7 +151,7 @@ export const kycWorkflow = async (params: Params): Promise<void> => {
150151
city: contactInfo.city,
151152
state: contactInfo.state,
152153
postalCode: contactInfo.postalCode,
153-
countryCode: 'US'
154+
countryCode
154155
}
155156
if (addressInfoUuid != null) {
156157
await vault.updateAddressInfo(addressInfoUuid, addressInfo)

0 commit comments

Comments
 (0)