saafe-redirection-flow 2.2.0 → 2.2.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +8 -0
- package/package.json +1 -1
- package/prod-aa-2307251430.zip +0 -0
- package/src/components/LinkedAccountTypeAccordion.tsx +73 -62
- package/src/components/auth/AuthGuard.tsx +4 -3
- package/src/components/title/AppBar.tsx +4 -1
- package/src/components/title/SectionTitle.tsx +2 -2
- package/src/hooks/use-fip-query.ts +1 -1
- package/src/pages/accounts/AccountsToProceed.tsx +517 -412
- package/src/pages/accounts/DiscoverAccount.tsx +127 -100
- package/src/store/fip.store.ts +1 -0
- package/src/utils/removeUnderscore.ts +3 -0
- package/stage-aa-2307251430.zip +0 -0
- package/stage-aa-2407251347.zip +0 -0
- package/aa-redirection-1607251826.zip +0 -0
|
@@ -7,7 +7,7 @@ import { Button } from '@/components/ui/button'
|
|
|
7
7
|
import { Checkbox } from '@/components/ui/checkbox'
|
|
8
8
|
import { MobileFooter } from '@/components/ui/mobile-footer'
|
|
9
9
|
import WebFooter from '@/components/ui/web-footer'
|
|
10
|
-
import { useFipStore } from '@/store/fip.store'
|
|
10
|
+
import { FipData, useFipStore } from '@/store/fip.store'
|
|
11
11
|
import { AlertCircle, PlusIcon } from 'lucide-react'
|
|
12
12
|
import { useNavigate } from 'react-router-dom'
|
|
13
13
|
import {
|
|
@@ -30,6 +30,10 @@ import { accountService } from '@/services/api'
|
|
|
30
30
|
import { useQuery } from '@tanstack/react-query'
|
|
31
31
|
import { BankAccount } from '@/pages/accounts/OldUser'
|
|
32
32
|
import AutoDiscoveryLoader from '@/components/AutoDiscoveryLoader'
|
|
33
|
+
import removeUnderscores from '@/utils/removeUnderscore'
|
|
34
|
+
import { extractCategoriesFromResponse, useFipQuery } from '@/hooks/use-fip-query'
|
|
35
|
+
import { fipService } from '@/services/api/fip.service'
|
|
36
|
+
|
|
33
37
|
|
|
34
38
|
interface LinkedAccount extends BankAccount {
|
|
35
39
|
fipName: string;
|
|
@@ -60,17 +64,23 @@ const AccountsToProceed = ({
|
|
|
60
64
|
activeCategory,
|
|
61
65
|
setSelectedAccountToLink,
|
|
62
66
|
setOriginalAccounts,
|
|
63
|
-
originalAccounts
|
|
67
|
+
originalAccounts,
|
|
68
|
+
setIdentifiers,
|
|
64
69
|
} = useFipStore()
|
|
65
70
|
const fipIds = state?.selectedFips || selectedFips[category] || []
|
|
66
71
|
useSetPageTitle(`Select accounts you want to link`)
|
|
67
72
|
const [discoveryResult, setDiscoveryResult] =
|
|
68
73
|
useState<ProcessedDiscoveryResult | null>(null)
|
|
74
|
+
console.log("🚀 ~ discoveryResult:", discoveryResult)
|
|
69
75
|
const [selectedAccounts, setSelectedAccounts] = useState<string[]>([])
|
|
76
|
+
const [linkedAccountCount, setLinkedAccountCount] = useState<number>(0)
|
|
77
|
+
console.log("🚀 ~ selectedAccounts:", selectedAccounts)
|
|
70
78
|
const [isLoading, setIsLoading] = useState(false)
|
|
71
79
|
const { decodedInfo } = useRedirectStore()
|
|
80
|
+
console.log("🚀 ~ decodedInfo:", decodedInfo)
|
|
72
81
|
const isUserPresent = decodedInfo?.isUserPresent || false
|
|
73
|
-
|
|
82
|
+
console.log("🚀 ~ isUserPresent:", isUserPresent)
|
|
83
|
+
|
|
74
84
|
// State for collapsible UI
|
|
75
85
|
const [openItemId, setOpenItemId] = useState<number | null>(0)
|
|
76
86
|
const [tabOpen, setTabOpen] = useState(false)
|
|
@@ -79,7 +89,6 @@ const AccountsToProceed = ({
|
|
|
79
89
|
// Account discovery with enhanced error handling
|
|
80
90
|
const { mutate, errorMessage, clearError } = useAccountDiscovery()
|
|
81
91
|
const autoDiscovery = useAutoDiscovery()
|
|
82
|
-
|
|
83
92
|
// Fetch linked accounts for returning users
|
|
84
93
|
const consentHandle = decodedInfo?.srcref || '';
|
|
85
94
|
const getLinkedAccountsList = useQuery({
|
|
@@ -98,12 +107,13 @@ const AccountsToProceed = ({
|
|
|
98
107
|
}))
|
|
99
108
|
}
|
|
100
109
|
})
|
|
101
|
-
|
|
110
|
+
|
|
102
111
|
// Process linked accounts for display
|
|
103
112
|
const activeLinkedAccount = React.useMemo(() => {
|
|
104
113
|
if (!getLinkedAccountsList?.data) return {};
|
|
105
|
-
|
|
114
|
+
|
|
106
115
|
const accounts: LinkedAccount[] = getLinkedAccountsList.data;
|
|
116
|
+
setLinkedAccountCount(accounts?.length)
|
|
107
117
|
return accounts.reduce((acc: Record<string, LinkedAccount[]>, account) => {
|
|
108
118
|
const fiType = account.fiType || 'Other';
|
|
109
119
|
if (!acc[fiType]) {
|
|
@@ -113,34 +123,34 @@ const AccountsToProceed = ({
|
|
|
113
123
|
return acc;
|
|
114
124
|
}, {});
|
|
115
125
|
}, [getLinkedAccountsList?.data]);
|
|
116
|
-
|
|
126
|
+
|
|
117
127
|
// Count selected accounts for UI
|
|
118
128
|
const selectedFIPCount = React.useMemo(() => {
|
|
119
129
|
if (!discoveryResult?.groupedAccounts) return { totalCount: 0, groupedCount: {} };
|
|
120
|
-
|
|
130
|
+
|
|
121
131
|
const groupedCount: Record<string, number> = {};
|
|
122
132
|
let totalCount = 0;
|
|
123
|
-
|
|
133
|
+
|
|
124
134
|
Object.entries(discoveryResult.groupedAccounts).forEach(([fiType, accounts]) => {
|
|
125
|
-
const selectedInType = accounts.filter(account =>
|
|
135
|
+
const selectedInType = accounts.filter(account =>
|
|
126
136
|
selectedAccounts.includes(account.id)
|
|
127
137
|
).length;
|
|
128
138
|
groupedCount[fiType] = selectedInType;
|
|
129
139
|
totalCount += selectedInType;
|
|
130
140
|
});
|
|
131
|
-
|
|
141
|
+
|
|
132
142
|
return { totalCount, groupedCount };
|
|
133
143
|
}, [discoveryResult?.groupedAccounts, selectedAccounts]);
|
|
134
|
-
|
|
144
|
+
|
|
135
145
|
// Count linked accounts for UI
|
|
136
146
|
const linkedAccountsCount = React.useMemo(() => {
|
|
137
147
|
if (!activeLinkedAccount) return { totalCount: 0 };
|
|
138
|
-
|
|
148
|
+
|
|
139
149
|
const totalCount = Object.values(activeLinkedAccount as Record<string, LinkedAccount[]>)
|
|
140
150
|
.flat()
|
|
141
151
|
.filter(account => selectedAccounts.includes(account.accountRefNumber))
|
|
142
152
|
.length;
|
|
143
|
-
|
|
153
|
+
|
|
144
154
|
return { totalCount };
|
|
145
155
|
}, [activeLinkedAccount, selectedAccounts]);
|
|
146
156
|
|
|
@@ -164,7 +174,7 @@ const AccountsToProceed = ({
|
|
|
164
174
|
|
|
165
175
|
// Check if "Discover More" should be shown based on auto discovery configuration
|
|
166
176
|
const autoDiscoveryConfig = parseAutoDiscoveryConfig(decodedInfo?.customization?.otherAppCustomization)
|
|
167
|
-
const shouldShowDiscoverMore = state?.isAutoDiscovery
|
|
177
|
+
const shouldShowDiscoverMore = state?.isAutoDiscovery
|
|
168
178
|
? autoDiscoveryConfig[activeCategory?.toUpperCase() as keyof typeof autoDiscoveryConfig]?.showDiscoverMore
|
|
169
179
|
: true // Always show for manual discovery
|
|
170
180
|
|
|
@@ -180,163 +190,157 @@ const AccountsToProceed = ({
|
|
|
180
190
|
|
|
181
191
|
// Discover accounts when component loads
|
|
182
192
|
useEffect(() => {
|
|
183
|
-
|
|
184
|
-
isAutoDiscovery: state?.isAutoDiscovery,
|
|
185
|
-
category,
|
|
186
|
-
fipIds: fipIds.length,
|
|
187
|
-
groupedFipsKeys: Object.keys(groupedFips || {})
|
|
188
|
-
});
|
|
189
|
-
|
|
190
|
-
let mounted = true
|
|
193
|
+
let mounted = true;
|
|
191
194
|
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
) && fip.isEnabled && fip.isOnBoarded
|
|
208
|
-
);
|
|
209
|
-
|
|
210
|
-
// Collect required identifiers from category FIPs
|
|
211
|
-
categoryFips.forEach(fip => {
|
|
212
|
-
fip.Identifiers?.forEach(identifier => {
|
|
213
|
-
if (!identifiersList.find(i => i.type === identifier.type)) {
|
|
214
|
-
// First check if we already have this identifier in store
|
|
215
|
-
const storeIdentifier = storeIdentifiers.find(i => i.type === identifier.type);
|
|
216
|
-
let value: string | undefined = undefined;
|
|
217
|
-
if (storeIdentifier?.value !== undefined) {
|
|
218
|
-
value = storeIdentifier.value;
|
|
219
|
-
}
|
|
220
|
-
|
|
221
|
-
// If not in store, fall back to decodedInfo
|
|
222
|
-
if (!value) {
|
|
223
|
-
value = identifier.type === 'PAN'
|
|
224
|
-
? (decodedInfo?.pan || undefined)
|
|
225
|
-
: identifier.type === 'MOBILE'
|
|
226
|
-
? (decodedInfo?.phoneNumber || undefined)
|
|
227
|
-
: identifier.type === 'DOB'
|
|
228
|
-
? (decodedInfo?.dob || undefined)
|
|
229
|
-
: undefined;
|
|
195
|
+
const fetchAndProceed = async () => {
|
|
196
|
+
let { fips, identifiers: storeIdentifiers } = useFipStore.getState();
|
|
197
|
+
const { decodedInfo } = useRedirectStore.getState();
|
|
198
|
+
|
|
199
|
+
if (fips.length === 0) {
|
|
200
|
+
console.log('🔄 No FIPs in store, fetching now...');
|
|
201
|
+
try {
|
|
202
|
+
const response = await fipService.getRawFipResponse();
|
|
203
|
+
const categories = extractCategoriesFromResponse(response);
|
|
204
|
+
const categorizedFips: Record<string, FipData[]> = {};
|
|
205
|
+
|
|
206
|
+
categories.forEach(category => {
|
|
207
|
+
const categoryData = response[category];
|
|
208
|
+
if (Array.isArray(categoryData)) {
|
|
209
|
+
categorizedFips[category] = categoryData as FipData[];
|
|
230
210
|
}
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
value,
|
|
235
|
-
category: identifier.category
|
|
236
|
-
});
|
|
237
|
-
}
|
|
238
|
-
});
|
|
239
|
-
});
|
|
211
|
+
});
|
|
212
|
+
|
|
213
|
+
const allFips = Object.values(categorizedFips).flat();
|
|
240
214
|
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
// Redirect to DiscoverAccount to collect missing identifiers
|
|
252
|
-
navigate(`/link-accounts/discover-account`, {
|
|
253
|
-
state: {
|
|
254
|
-
category,
|
|
255
|
-
selectedFips: fipIds, // Use the auto discovery FIP IDs
|
|
256
|
-
fromAutoDiscovery: true
|
|
215
|
+
if (allFips.length > 0) {
|
|
216
|
+
useFipStore.getState().setFips(
|
|
217
|
+
allFips,
|
|
218
|
+
decodedInfo?.fiTypesRequiredForConsent,
|
|
219
|
+
categorizedFips
|
|
220
|
+
);
|
|
221
|
+
fips = allFips;
|
|
222
|
+
} else {
|
|
223
|
+
console.error("No FIPs returned after fetch");
|
|
224
|
+
return;
|
|
257
225
|
}
|
|
258
|
-
})
|
|
259
|
-
|
|
226
|
+
} catch (err) {
|
|
227
|
+
console.error("Failed to fetch FIPs:", err);
|
|
228
|
+
return;
|
|
229
|
+
}
|
|
260
230
|
}
|
|
261
231
|
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
autoDiscovery.clearError()
|
|
232
|
+
// Auto-Discovery
|
|
233
|
+
console.log('AccountsToProceed useEffect:', {
|
|
234
|
+
isAutoDiscovery: state?.isAutoDiscovery,
|
|
235
|
+
category,
|
|
236
|
+
fipIds: fipIds.length,
|
|
237
|
+
groupedFipsKeys: Object.keys(groupedFips || {})
|
|
238
|
+
});
|
|
270
239
|
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
(
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
240
|
+
if (state?.isAutoDiscovery) {
|
|
241
|
+
console.log('Using AUTO DISCOVERY for category:', category);
|
|
242
|
+
const identifiersList: Array<{ type: string; value: string | undefined; category: string }> = [];
|
|
243
|
+
const categoryFips = fips.filter(fip =>
|
|
244
|
+
fip.fiTypeList.some(fiType =>
|
|
245
|
+
fiTypeCategoryMap[category]?.includes(fiType)
|
|
246
|
+
) && fip.isEnabled && fip.isOnBoarded
|
|
247
|
+
);
|
|
248
|
+
categoryFips.forEach(fip => {
|
|
249
|
+
fip.Identifiers?.forEach(identifier => {
|
|
250
|
+
if (!identifiersList.find(i => i.type === identifier.type)) {
|
|
251
|
+
const storeIdentifier = storeIdentifiers.find(i => i.type === identifier.type);
|
|
252
|
+
let value = storeIdentifier?.value;
|
|
253
|
+
if (!value) {
|
|
254
|
+
value = identifier.type === 'PAN'
|
|
255
|
+
? (decodedInfo?.pan || undefined)
|
|
256
|
+
: identifier.type === 'MOBILE'
|
|
257
|
+
? (decodedInfo?.phoneNumber || undefined)
|
|
258
|
+
: identifier.type === 'DOB'
|
|
259
|
+
? (decodedInfo?.dob || undefined)
|
|
260
|
+
: undefined;
|
|
280
261
|
}
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
)
|
|
286
|
-
setDiscoveryResult({ ...result, groupedAccounts })
|
|
287
|
-
setOriginalAccounts(result.originalAccounts)
|
|
262
|
+
identifiersList.push({ type: identifier.type, value, category: identifier.category });
|
|
263
|
+
}
|
|
264
|
+
});
|
|
265
|
+
});
|
|
288
266
|
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
267
|
+
const missingIdentifiers = identifiersList.filter(identifier =>
|
|
268
|
+
!identifier.value || identifier.value.trim() === ''
|
|
269
|
+
);
|
|
270
|
+
|
|
271
|
+
if (missingIdentifiers.length > 0) {
|
|
272
|
+
navigate(`/link-accounts/discover-account`, {
|
|
273
|
+
state: {
|
|
274
|
+
category,
|
|
275
|
+
selectedFips: fipIds,
|
|
276
|
+
fromAutoDiscovery: true
|
|
277
|
+
}
|
|
278
|
+
});
|
|
279
|
+
return;
|
|
295
280
|
}
|
|
296
|
-
})
|
|
297
|
-
} else if (fipIds.length > 0) {
|
|
298
|
-
console.log('Using MANUAL DISCOVERY for FIPs:', fipIds);
|
|
299
|
-
// Use manual discovery
|
|
300
|
-
setIsLoading(true)
|
|
301
|
-
clearError()
|
|
302
281
|
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
const groupedAccounts = result.accounts.reduce(
|
|
307
|
-
(acc: Record<string, typeof result.accounts>, account) => {
|
|
308
|
-
const key = account.type
|
|
309
|
-
if (!acc[key]) {
|
|
310
|
-
acc[key] = []
|
|
311
|
-
}
|
|
312
|
-
acc[key].push(account)
|
|
313
|
-
return acc
|
|
314
|
-
},
|
|
315
|
-
{}
|
|
316
|
-
)
|
|
317
|
-
setDiscoveryResult({ ...result, groupedAccounts })
|
|
318
|
-
setOriginalAccounts(result.originalAccounts)
|
|
282
|
+
setIdentifiers(identifiersList);
|
|
283
|
+
setIsLoading(true);
|
|
284
|
+
autoDiscovery.clearError();
|
|
319
285
|
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
286
|
+
autoDiscovery.mutate(category, {
|
|
287
|
+
onSuccess: result => {
|
|
288
|
+
if (!mounted) return;
|
|
289
|
+
const groupedAccounts = result.accounts.reduce((acc, account) => {
|
|
290
|
+
const key = account.type;
|
|
291
|
+
if (!acc[key]) acc[key] = [];
|
|
292
|
+
acc[key].push(account);
|
|
293
|
+
return acc;
|
|
294
|
+
}, {} as Record<string, typeof result.accounts>);
|
|
295
|
+
|
|
296
|
+
setDiscoveryResult({ ...result, groupedAccounts });
|
|
297
|
+
setOriginalAccounts(result.originalAccounts);
|
|
298
|
+
setIsLoading(false);
|
|
299
|
+
},
|
|
300
|
+
onError: (error) => {
|
|
301
|
+
if (!mounted) return;
|
|
302
|
+
console.error('Auto discovery error:', error);
|
|
303
|
+
setIsLoading(false);
|
|
304
|
+
}
|
|
305
|
+
});
|
|
306
|
+
} else if (fipIds.length > 0) {
|
|
307
|
+
setIsLoading(true);
|
|
308
|
+
clearError();
|
|
309
|
+
|
|
310
|
+
mutate(fipIds, {
|
|
311
|
+
onSuccess: result => {
|
|
312
|
+
if (!mounted) return;
|
|
313
|
+
const groupedAccounts = result.accounts.reduce((acc, account) => {
|
|
314
|
+
const key = account.type;
|
|
315
|
+
if (!acc[key]) acc[key] = [];
|
|
316
|
+
acc[key].push(account);
|
|
317
|
+
return acc;
|
|
318
|
+
}, {} as Record<string, typeof result.accounts>);
|
|
319
|
+
|
|
320
|
+
setDiscoveryResult({ ...result, groupedAccounts });
|
|
321
|
+
setOriginalAccounts(result.originalAccounts);
|
|
322
|
+
setIsLoading(false);
|
|
323
|
+
},
|
|
324
|
+
onError: () => {
|
|
325
|
+
if (!mounted) return;
|
|
326
|
+
setIsLoading(false);
|
|
327
|
+
}
|
|
328
|
+
});
|
|
329
|
+
} else {
|
|
330
|
+
console.log('No discovery triggered - no FIPs and not auto discovery');
|
|
331
|
+
}
|
|
332
|
+
};
|
|
333
|
+
|
|
334
|
+
fetchAndProceed();
|
|
330
335
|
|
|
331
|
-
// Cleanup function to handle unmounting
|
|
332
336
|
return () => {
|
|
333
|
-
mounted = false
|
|
334
|
-
}
|
|
335
|
-
}, [fipIds, state?.isAutoDiscovery, category])
|
|
337
|
+
mounted = false;
|
|
338
|
+
};
|
|
339
|
+
}, [fipIds, state?.isAutoDiscovery, category]);
|
|
336
340
|
|
|
337
341
|
const handleProceed = () => {
|
|
338
342
|
console.log('handleProceed called with:', { selectedAccounts, originalAccounts })
|
|
339
|
-
|
|
343
|
+
|
|
340
344
|
const result: Array<{
|
|
341
345
|
id: string;
|
|
342
346
|
fipId: string;
|
|
@@ -347,24 +351,24 @@ const AccountsToProceed = ({
|
|
|
347
351
|
bankName: string;
|
|
348
352
|
logoUrl?: string;
|
|
349
353
|
isNew?: boolean;
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
|
|
354
|
+
DiscoveredAccounts: Array<{
|
|
355
|
+
FIType: string;
|
|
356
|
+
accType: string;
|
|
357
|
+
accRefNumber: string;
|
|
358
|
+
maskedAccNumber: string;
|
|
359
|
+
state: string | null;
|
|
360
|
+
amcName: string | null;
|
|
361
|
+
logoUrl: string | null;
|
|
362
|
+
}>;
|
|
359
363
|
}> = []
|
|
360
|
-
|
|
364
|
+
|
|
361
365
|
originalAccounts.forEach((item, index) => {
|
|
362
|
-
const data = item?.["DiscoveredAccounts"].filter(account =>
|
|
366
|
+
const data = item?.["DiscoveredAccounts"].filter(account =>
|
|
363
367
|
selectedAccounts.includes(account.accRefNumber)
|
|
364
368
|
)
|
|
365
369
|
if (data.length > 0) {
|
|
366
370
|
// For each FIP with selected accounts, create one entry
|
|
367
|
-
result.push({
|
|
371
|
+
result.push({
|
|
368
372
|
id: `${index} - ${item.fipName}`,
|
|
369
373
|
fipId: item.fipId,
|
|
370
374
|
fipName: item.fipName,
|
|
@@ -382,7 +386,7 @@ const AccountsToProceed = ({
|
|
|
382
386
|
console.log('handleProceed result:', result)
|
|
383
387
|
console.log('Setting selectedAccountToLink with result length:', result.length)
|
|
384
388
|
setSelectedAccountToLink(result)
|
|
385
|
-
|
|
389
|
+
|
|
386
390
|
// Navigate to account linking screen with selected accounts and signature
|
|
387
391
|
navigate('/link-accounts/link', {
|
|
388
392
|
state: {
|
|
@@ -407,8 +411,13 @@ const AccountsToProceed = ({
|
|
|
407
411
|
return updatedSelection;
|
|
408
412
|
});
|
|
409
413
|
};
|
|
410
|
-
|
|
411
|
-
const toggleBankSelection = (bankId: string) => {
|
|
414
|
+
|
|
415
|
+
const toggleBankSelection = (bankId: string, event?: React.MouseEvent) => {
|
|
416
|
+
|
|
417
|
+
if (event) {
|
|
418
|
+
event.stopPropagation();
|
|
419
|
+
}
|
|
420
|
+
|
|
412
421
|
setSelectedAccounts(prev => {
|
|
413
422
|
let updatedSelection;
|
|
414
423
|
if (prev.includes(bankId)) {
|
|
@@ -505,17 +514,17 @@ const AccountsToProceed = ({
|
|
|
505
514
|
const validateIdentifiersBeforeDiscoverMore = () => {
|
|
506
515
|
// Get the FIP store state to access fips data
|
|
507
516
|
const { fips } = useFipStore.getState();
|
|
508
|
-
|
|
517
|
+
|
|
509
518
|
if (!fipIds || fipIds.length === 0) {
|
|
510
519
|
return true; // No FIPs selected, can't validate
|
|
511
520
|
}
|
|
512
|
-
|
|
521
|
+
|
|
513
522
|
const identifiersList: Array<{
|
|
514
523
|
type: string;
|
|
515
524
|
value: string | null | undefined;
|
|
516
525
|
categoryType: string;
|
|
517
526
|
}> = [];
|
|
518
|
-
|
|
527
|
+
|
|
519
528
|
// Collect required identifiers from selected FIPs
|
|
520
529
|
fips
|
|
521
530
|
.filter(fip => fipIds.includes(fip.id))
|
|
@@ -528,12 +537,12 @@ const AccountsToProceed = ({
|
|
|
528
537
|
: identifier.type === 'MOBILE'
|
|
529
538
|
? decodedInfo?.phoneNumber
|
|
530
539
|
: identifier.type === 'DOB'
|
|
531
|
-
|
|
532
|
-
|
|
533
|
-
identifiersList.push({
|
|
540
|
+
? decodedInfo?.dob
|
|
541
|
+
: null;
|
|
542
|
+
identifiersList.push({
|
|
534
543
|
type: identifier.type,
|
|
535
|
-
value,
|
|
536
|
-
categoryType: identifier.category
|
|
544
|
+
value,
|
|
545
|
+
categoryType: identifier.category
|
|
537
546
|
});
|
|
538
547
|
}
|
|
539
548
|
});
|
|
@@ -542,7 +551,7 @@ const AccountsToProceed = ({
|
|
|
542
551
|
console.log('AccountsToProceed - Checking identifiers for discover more:', identifiersList);
|
|
543
552
|
|
|
544
553
|
// Check if any required identifiers are missing
|
|
545
|
-
const missingIdentifiers = identifiersList.filter(identifier =>
|
|
554
|
+
const missingIdentifiers = identifiersList.filter(identifier =>
|
|
546
555
|
!identifier.value || identifier.value.trim() === ''
|
|
547
556
|
);
|
|
548
557
|
|
|
@@ -591,85 +600,161 @@ const AccountsToProceed = ({
|
|
|
591
600
|
))
|
|
592
601
|
}
|
|
593
602
|
|
|
594
|
-
|
|
603
|
+
const hasDiscoveredAccounts =
|
|
595
604
|
discoveryResult?.groupedAccounts &&
|
|
596
|
-
Object.keys(discoveryResult.groupedAccounts).length > 0
|
|
597
|
-
|
|
598
|
-
|
|
599
|
-
|
|
600
|
-
|
|
601
|
-
|
|
602
|
-
|
|
603
|
-
|
|
604
|
-
|
|
605
|
-
|
|
606
|
-
|
|
607
|
-
|
|
608
|
-
|
|
609
|
-
|
|
610
|
-
|
|
611
|
-
|
|
612
|
-
|
|
613
|
-
|
|
614
|
-
|
|
615
|
-
|
|
616
|
-
|
|
617
|
-
|
|
618
|
-
|
|
619
|
-
|
|
620
|
-
|
|
621
|
-
|
|
622
|
-
|
|
623
|
-
|
|
624
|
-
|
|
625
|
-
|
|
626
|
-
|
|
627
|
-
|
|
628
|
-
|
|
629
|
-
|
|
605
|
+
Object.keys(discoveryResult.groupedAccounts).length > 0;
|
|
606
|
+
|
|
607
|
+
return (
|
|
608
|
+
<>
|
|
609
|
+
{/* Discovered Accounts Section */}
|
|
610
|
+
{hasDiscoveredAccounts && (
|
|
611
|
+
<div>
|
|
612
|
+
<div className='mt-2 shadow-sm shadow-black/5 rounded-md'>
|
|
613
|
+
<div className='py-5 px-5 rounded-t-md text-primary border-primary bg-ring dark:text-primary'>
|
|
614
|
+
<h1 className='flex justify-start items-center gap-1 text-md font-semibold'>
|
|
615
|
+
{"Discovered for you"}
|
|
616
|
+
<Sparkles size={18} fill={'#008e9a'} />
|
|
617
|
+
</h1>
|
|
618
|
+
<p className='text-sm md:text-lg'>
|
|
619
|
+
{selectedFIPCount.totalCount > 0
|
|
620
|
+
? `${selectedFIPCount.totalCount} of ${discoveryResult?.accounts?.length || 0} accounts selected`
|
|
621
|
+
: `No accounts selected`}
|
|
622
|
+
</p>
|
|
623
|
+
</div>
|
|
624
|
+
<div className='flex flex-col rounded-b-2xl bg-card'>
|
|
625
|
+
{Object.entries(discoveryResult.groupedAccounts as Record<string, any[]>).map(([fiType, accounts], index) => {
|
|
626
|
+
const isOpen = openItemId === index;
|
|
627
|
+
|
|
628
|
+
return (
|
|
629
|
+
<Collapsible
|
|
630
|
+
key={fiType}
|
|
631
|
+
open={isOpen}
|
|
632
|
+
onOpenChange={() => setOpenItemId(isOpen ? null : index)}
|
|
633
|
+
>
|
|
634
|
+
<CollapsibleTrigger className="flex justify-between w-full items-center p-4">
|
|
635
|
+
<SectionTitle
|
|
636
|
+
title={fiType}
|
|
637
|
+
className='text-sm md:text-sm'
|
|
638
|
+
rightSection={(
|
|
639
|
+
<ChevronDownIcon
|
|
640
|
+
size={20}
|
|
641
|
+
className={`h-5 w-5 transition-transform duration-300 ${isOpen ? "rotate-180" : "rotate-0"
|
|
642
|
+
}`}
|
|
643
|
+
/>
|
|
644
|
+
)}
|
|
645
|
+
/>
|
|
646
|
+
</CollapsibleTrigger>
|
|
647
|
+
<CollapsibleContent open={isOpen} className="px-4 pb-4">
|
|
648
|
+
{accounts.map(account => (
|
|
649
|
+
<div className='mt-2 flex flex-col gap-2' key={account.id}>
|
|
650
|
+
<OuterCard
|
|
651
|
+
selected={selectedAccounts.includes(account.id)}
|
|
652
|
+
onSelect={() => toggleBankSelection(account.id)}
|
|
653
|
+
>
|
|
654
|
+
<BankCard
|
|
655
|
+
bankName={account.bankName}
|
|
656
|
+
image={account.logoUrl}
|
|
657
|
+
subText={`${account.type} | **${formatAccountNumber(account.maskedAccountNumber || "0")}`}
|
|
658
|
+
onClick={() => toggleBankSelection(account.id)}
|
|
659
|
+
rightSection={
|
|
660
|
+
<Checkbox
|
|
661
|
+
id={`checkbox-${account.id}`}
|
|
662
|
+
checked={selectedAccounts.includes(account.id)}
|
|
663
|
+
onCheckedChange={() => toggleBankSelection(account.id)}
|
|
630
664
|
/>
|
|
631
|
-
|
|
665
|
+
}
|
|
632
666
|
/>
|
|
633
|
-
</
|
|
634
|
-
|
|
635
|
-
|
|
636
|
-
|
|
637
|
-
|
|
638
|
-
|
|
639
|
-
|
|
640
|
-
|
|
641
|
-
|
|
642
|
-
|
|
643
|
-
|
|
644
|
-
subText={`${account.type} | **${formatAccountNumber(account.maskedAccountNumber || "0")}`}
|
|
645
|
-
onClick={() => toggleBankSelection(account.id)}
|
|
646
|
-
rightSection={
|
|
647
|
-
<Checkbox
|
|
648
|
-
id={`checkbox-${account.id}`}
|
|
649
|
-
checked={selectedAccounts.includes(account.id)}
|
|
650
|
-
onCheckedChange={() => toggleBankSelection(account.id)}
|
|
651
|
-
/>
|
|
652
|
-
}
|
|
653
|
-
/>
|
|
654
|
-
</OuterCard>
|
|
655
|
-
</div>
|
|
656
|
-
))}
|
|
657
|
-
</CollapsibleContent>
|
|
658
|
-
</Collapsible>
|
|
659
|
-
);
|
|
660
|
-
})}
|
|
661
|
-
</div>
|
|
662
|
-
</div>
|
|
663
|
-
)
|
|
664
|
-
}
|
|
667
|
+
</OuterCard>
|
|
668
|
+
</div>
|
|
669
|
+
))}
|
|
670
|
+
</CollapsibleContent>
|
|
671
|
+
</Collapsible>
|
|
672
|
+
);
|
|
673
|
+
})}
|
|
674
|
+
</div>
|
|
675
|
+
</div>
|
|
676
|
+
</div>
|
|
677
|
+
)}
|
|
665
678
|
|
|
666
|
-
|
|
667
|
-
|
|
668
|
-
|
|
669
|
-
|
|
670
|
-
|
|
671
|
-
|
|
672
|
-
|
|
679
|
+
{/* Linked Accounts Section - Always show */}
|
|
680
|
+
<div className='flex flex-col rounded-2xl bg-card mt-6'>
|
|
681
|
+
<Collapsible open={tabOpen} onOpenChange={setTabOpen} className="border-none">
|
|
682
|
+
<CollapsibleTrigger asChild>
|
|
683
|
+
<div className='flex items-center bg-card py-4 px-5 pr-4 rounded-xl justify-between gap-2 cursor-pointer shadow-sm shadow-black/5'>
|
|
684
|
+
<div className='flex flex-col justify-center relative'>
|
|
685
|
+
<p className="text-md text-stone-500 dark:text-gray-200 font-semibold ">Linked accounts</p>
|
|
686
|
+
<p className="text-sm text-stone-700 dark:text-gray-400">
|
|
687
|
+
{linkedAccountCount || 0} linked account{linkedAccountCount > 1 ? "s" : ""} across {Object.keys(activeLinkedAccount).length} FI Type{Object.keys(activeLinkedAccount).length > 1 ? "s" : ""}
|
|
688
|
+
</p>
|
|
689
|
+
</div>
|
|
690
|
+
<div>
|
|
691
|
+
<ChevronDownIcon
|
|
692
|
+
size={18}
|
|
693
|
+
className={`h-5 w-5 transition-transform duration-300 ${tabOpen ? "rotate-180" : "rotate-0"
|
|
694
|
+
}`}
|
|
695
|
+
/>
|
|
696
|
+
</div>
|
|
697
|
+
</div>
|
|
698
|
+
</CollapsibleTrigger>
|
|
699
|
+
<CollapsibleContent open={tabOpen} className="pb-4 bg-card rounded-b-xl">
|
|
700
|
+
{Object.entries(activeLinkedAccount as Record<string, LinkedAccount[]>).map(([f, accounts], index) => {
|
|
701
|
+
const isOpen = openLinkAcc === index;
|
|
702
|
+
const fiType = removeUnderscores(f) || f
|
|
703
|
+
return (
|
|
704
|
+
<Collapsible
|
|
705
|
+
key={fiType}
|
|
706
|
+
open={isOpen}
|
|
707
|
+
onOpenChange={() => setOpenLinkAcc(isOpen ? null : index)}
|
|
708
|
+
>
|
|
709
|
+
<CollapsibleTrigger className="flex justify-between items-center p-4 w-[100%]">
|
|
710
|
+
<SectionTitle
|
|
711
|
+
title={fiType}
|
|
712
|
+
className='text-sm md:text-sm'
|
|
713
|
+
rightSection={(
|
|
714
|
+
<ChevronDownIcon
|
|
715
|
+
size={18}
|
|
716
|
+
className={`h-5 w-5 transition-transform duration-300 ${isOpen ? "rotate-180" : "rotate-0"
|
|
717
|
+
}`}
|
|
718
|
+
/>
|
|
719
|
+
)}
|
|
720
|
+
/>
|
|
721
|
+
</CollapsibleTrigger>
|
|
722
|
+
<CollapsibleContent open={isOpen} className="px-4 pb-4">
|
|
723
|
+
{accounts.map(account => (
|
|
724
|
+
<div className='mt-2 flex flex-col gap-2' key={account.id}>
|
|
725
|
+
<OuterCard
|
|
726
|
+
selected={true}
|
|
727
|
+
>
|
|
728
|
+
<BankCard
|
|
729
|
+
bankName={account.bankName}
|
|
730
|
+
image={account.logoUrl}
|
|
731
|
+
subText={`${account.type} | **${formatAccountNumber(account.maskedAccountNumber || "0")}`}
|
|
732
|
+
/>
|
|
733
|
+
</OuterCard>
|
|
734
|
+
</div>
|
|
735
|
+
))}
|
|
736
|
+
</CollapsibleContent>
|
|
737
|
+
</Collapsible>
|
|
738
|
+
);
|
|
739
|
+
})}
|
|
740
|
+
</CollapsibleContent>
|
|
741
|
+
</Collapsible>
|
|
742
|
+
</div>
|
|
743
|
+
|
|
744
|
+
{/* No discovered accounts message */}
|
|
745
|
+
{!hasDiscoveredAccounts && (
|
|
746
|
+
<Alert className='flex items-center mt-2'>
|
|
747
|
+
<AlertCircle className='w-4 h-4' />
|
|
748
|
+
<AlertDescription className='flex items-center justify-between'>
|
|
749
|
+
{/* {"Do not refresh the page while we fetch your accounts."} */}
|
|
750
|
+
{(errorMessage || autoDiscovery.errorMessage)
|
|
751
|
+
? 'Failed to discover accounts'
|
|
752
|
+
: 'No new accounts discovered, kindly skip'}
|
|
753
|
+
</AlertDescription>
|
|
754
|
+
</Alert>
|
|
755
|
+
)}
|
|
756
|
+
</>
|
|
757
|
+
);
|
|
673
758
|
}
|
|
674
759
|
|
|
675
760
|
return (
|
|
@@ -684,22 +769,24 @@ const AccountsToProceed = ({
|
|
|
684
769
|
)} ${discoveryResult?.accounts?.length === 1 ? t('keywords.account') : t('keywords.accounts')}`}
|
|
685
770
|
|
|
686
771
|
rightSection={
|
|
687
|
-
|
|
688
|
-
|
|
689
|
-
|
|
690
|
-
|
|
691
|
-
|
|
692
|
-
|
|
693
|
-
|
|
694
|
-
|
|
695
|
-
|
|
696
|
-
|
|
697
|
-
|
|
698
|
-
|
|
699
|
-
|
|
700
|
-
|
|
701
|
-
|
|
702
|
-
|
|
772
|
+
discoveryResult?.accounts && discoveryResult.accounts.length > 0 ? (
|
|
773
|
+
<AnimatedButton
|
|
774
|
+
variant={'ghost'}
|
|
775
|
+
onClick={handleSelectAll}
|
|
776
|
+
disabled={
|
|
777
|
+
!discoveryResult?.accounts ||
|
|
778
|
+
discoveryResult.accounts.length === 0
|
|
779
|
+
}
|
|
780
|
+
>
|
|
781
|
+
<p className='text-primary'>
|
|
782
|
+
{discoveryResult?.accounts &&
|
|
783
|
+
selectedAccounts.length === discoveryResult.accounts.length &&
|
|
784
|
+
discoveryResult.accounts.length > 0
|
|
785
|
+
? t('unselectAll')
|
|
786
|
+
: t('selectAll')}
|
|
787
|
+
</p>
|
|
788
|
+
</AnimatedButton>
|
|
789
|
+
) : null
|
|
703
790
|
}
|
|
704
791
|
/>
|
|
705
792
|
|
|
@@ -708,169 +795,187 @@ const AccountsToProceed = ({
|
|
|
708
795
|
<AlertCircle className='w-4 h-4' />
|
|
709
796
|
<AlertDescription className='flex items-center justify-between'>
|
|
710
797
|
{errorMessage || autoDiscovery.errorMessage}
|
|
711
|
-
|
|
712
|
-
|
|
713
|
-
|
|
714
|
-
|
|
715
|
-
|
|
716
|
-
|
|
717
|
-
|
|
718
|
-
|
|
798
|
+
{
|
|
799
|
+
!isLoading && (
|
|
800
|
+
<Button
|
|
801
|
+
variant='outline'
|
|
802
|
+
size='sm'
|
|
803
|
+
onClick={retryDiscovery}
|
|
804
|
+
className='ml-2'
|
|
805
|
+
>
|
|
806
|
+
Retry
|
|
807
|
+
</Button>
|
|
808
|
+
)
|
|
809
|
+
}
|
|
810
|
+
</AlertDescription>
|
|
811
|
+
</Alert>
|
|
812
|
+
)}
|
|
813
|
+
|
|
814
|
+
{isLoading && (
|
|
815
|
+
<Alert className='flex items-center mb-2'>
|
|
816
|
+
<AlertCircle className='w-4 h-4' />
|
|
817
|
+
<AlertDescription className='flex items-center justify-between'>
|
|
818
|
+
{"Do not refresh the page while we fetch your accounts."}
|
|
819
|
+
|
|
719
820
|
</AlertDescription>
|
|
720
821
|
</Alert>
|
|
721
822
|
)}
|
|
722
823
|
|
|
723
824
|
<div className='flex flex-col gap-2'>
|
|
724
825
|
<div className='flex flex-col gap-2 mb-4'>
|
|
725
|
-
|
|
726
|
-
|
|
727
|
-
|
|
728
|
-
|
|
729
|
-
|
|
730
|
-
|
|
731
|
-
|
|
732
|
-
|
|
733
|
-
|
|
734
|
-
|
|
735
|
-
|
|
736
|
-
|
|
737
|
-
|
|
738
|
-
|
|
739
|
-
|
|
740
|
-
|
|
741
|
-
|
|
742
|
-
|
|
743
|
-
|
|
744
|
-
|
|
745
|
-
|
|
746
|
-
|
|
747
|
-
|
|
748
|
-
|
|
749
|
-
|
|
750
|
-
|
|
751
|
-
|
|
752
|
-
|
|
753
|
-
|
|
754
|
-
|
|
755
|
-
|
|
756
|
-
|
|
757
|
-
|
|
826
|
+
{state?.isAutoDiscovery && discoveryResult?.groupedAccounts ? (
|
|
827
|
+
<>
|
|
828
|
+
{/* Auto Discovery Section */}
|
|
829
|
+
<div className='mt-2 shadow-sm shadow-black/5 rounded-xl'>
|
|
830
|
+
<div className='py-5 px-5 rounded-t-xl text-primary border-primary bg-ring dark:text-primary'>
|
|
831
|
+
<h1 className='flex justify-start items-center gap-1 text-md font-semibold'>
|
|
832
|
+
{"Discovered for you"}
|
|
833
|
+
<Sparkles size={18} fill={'#008e9a'} />
|
|
834
|
+
</h1>
|
|
835
|
+
<p className='text-sm'>
|
|
836
|
+
{selectedFIPCount.totalCount > 0
|
|
837
|
+
? `${selectedFIPCount.totalCount} of ${discoveryResult?.accounts?.length || 0} accounts selected`
|
|
838
|
+
: `No accounts selected`}
|
|
839
|
+
</p>
|
|
840
|
+
</div>
|
|
841
|
+
<div className='flex flex-col rounded-b-2xl bg-card'>
|
|
842
|
+
{Object.entries(discoveryResult.groupedAccounts as Record<string, any[]>).map(([f, accounts], index) => {
|
|
843
|
+
const isOpen = openItemId === index;
|
|
844
|
+
const fiType = removeUnderscores(f)
|
|
845
|
+
|
|
846
|
+
return (
|
|
847
|
+
<Collapsible
|
|
848
|
+
key={fiType}
|
|
849
|
+
open={isOpen}
|
|
850
|
+
onOpenChange={() => setOpenItemId(isOpen ? null : index)}
|
|
851
|
+
>
|
|
852
|
+
<CollapsibleTrigger className="flex justify-between w-full items-center p-4">
|
|
853
|
+
<SectionTitle
|
|
854
|
+
className='text-sm md:text-sm'
|
|
855
|
+
title={fiType}
|
|
856
|
+
rightSection={(
|
|
857
|
+
<ChevronDownIcon
|
|
858
|
+
size={18}
|
|
859
|
+
className={`h-5 w-5 transition-transform duration-300 ${isOpen ? "rotate-180" : "rotate-0"
|
|
758
860
|
}`}
|
|
759
|
-
|
|
760
|
-
|
|
761
|
-
|
|
762
|
-
|
|
763
|
-
|
|
764
|
-
|
|
765
|
-
|
|
766
|
-
|
|
767
|
-
|
|
768
|
-
|
|
769
|
-
|
|
770
|
-
|
|
771
|
-
|
|
772
|
-
|
|
773
|
-
|
|
774
|
-
|
|
775
|
-
|
|
861
|
+
/>
|
|
862
|
+
)}
|
|
863
|
+
/>
|
|
864
|
+
</CollapsibleTrigger>
|
|
865
|
+
<CollapsibleContent open={isOpen} className="px-4 pb-4">
|
|
866
|
+
{accounts.map(account => (
|
|
867
|
+
<div className='mt-2 flex flex-col gap-2' key={account.id}>
|
|
868
|
+
<OuterCard
|
|
869
|
+
selected={selectedAccounts.includes(account.id)}
|
|
870
|
+
onSelect={() => toggleBankSelection(account.id)}
|
|
871
|
+
>
|
|
872
|
+
<BankCard
|
|
873
|
+
bankName={account.bankName}
|
|
874
|
+
image={account.logoUrl}
|
|
875
|
+
subText={`${account.type} | **${formatAccountNumber(account.maskedAccountNumber || "0")}`}
|
|
876
|
+
onClick={() => toggleBankSelection(account.id)}
|
|
877
|
+
rightSection={
|
|
878
|
+
<div onClick={(e) => e.stopPropagation()}>
|
|
776
879
|
<Checkbox
|
|
777
880
|
id={`checkbox-${account.id}`}
|
|
778
881
|
checked={selectedAccounts.includes(account.id)}
|
|
779
882
|
onCheckedChange={() => toggleBankSelection(account.id)}
|
|
780
883
|
/>
|
|
781
|
-
|
|
782
|
-
|
|
783
|
-
|
|
784
|
-
</
|
|
785
|
-
|
|
786
|
-
|
|
787
|
-
</
|
|
788
|
-
|
|
789
|
-
|
|
790
|
-
|
|
884
|
+
</div>
|
|
885
|
+
}
|
|
886
|
+
/>
|
|
887
|
+
</OuterCard>
|
|
888
|
+
</div>
|
|
889
|
+
))}
|
|
890
|
+
</CollapsibleContent>
|
|
891
|
+
</Collapsible>
|
|
892
|
+
);
|
|
893
|
+
})}
|
|
791
894
|
</div>
|
|
895
|
+
</div>
|
|
792
896
|
|
|
793
|
-
|
|
794
|
-
|
|
795
|
-
|
|
796
|
-
|
|
797
|
-
|
|
798
|
-
|
|
799
|
-
|
|
800
|
-
|
|
801
|
-
|
|
802
|
-
|
|
803
|
-
|
|
804
|
-
</
|
|
805
|
-
|
|
806
|
-
|
|
807
|
-
|
|
808
|
-
|
|
809
|
-
|
|
897
|
+
{/* Linked Accounts Section - Only for returning users */}
|
|
898
|
+
{isUserPresent && Object.keys(activeLinkedAccount).length > 0 && (
|
|
899
|
+
<div className='mt-6'>
|
|
900
|
+
<Collapsible open={tabOpen} onOpenChange={setTabOpen} className="border-none">
|
|
901
|
+
<CollapsibleTrigger asChild>
|
|
902
|
+
<div className='flex items-center bg-card py-4 px-5 pr-4 rounded-t-xl justify-between gap-2 cursor-pointer shadow-sm shadow-black/5'>
|
|
903
|
+
<div className='flex flex-col justify-center relative'>
|
|
904
|
+
<p className="text-md text-stone-500 dark:text-gray-200 font-semibold ">Linked accounts</p>
|
|
905
|
+
<p className="text-sm text-stone-700 dark:text-gray-400">
|
|
906
|
+
{/* {Object.keys(activeLinkedAccount).length} {Object.keys(activeLinkedAccount).length > 1 ? "linked accounts" : "linked account"} */}
|
|
907
|
+
{linkedAccountCount || 0} linked account{linkedAccountCount > 1 ? "s" : ""} across {Object.keys(activeLinkedAccount).length} FI Type{Object.keys(activeLinkedAccount).length > 1 ? "s" : ""}
|
|
908
|
+
</p>
|
|
909
|
+
</div>
|
|
910
|
+
<div>
|
|
911
|
+
<ChevronDownIcon
|
|
912
|
+
size={18}
|
|
913
|
+
className={`h-5 w-5 transition-transform duration-300 ${tabOpen ? "rotate-180" : "rotate-0"
|
|
810
914
|
}`}
|
|
811
|
-
|
|
812
|
-
</div>
|
|
915
|
+
/>
|
|
813
916
|
</div>
|
|
814
|
-
</
|
|
815
|
-
|
|
816
|
-
|
|
817
|
-
|
|
818
|
-
|
|
819
|
-
|
|
820
|
-
|
|
821
|
-
|
|
822
|
-
|
|
823
|
-
|
|
824
|
-
|
|
825
|
-
|
|
826
|
-
|
|
827
|
-
|
|
828
|
-
|
|
829
|
-
|
|
830
|
-
|
|
831
|
-
|
|
917
|
+
</div>
|
|
918
|
+
</CollapsibleTrigger>
|
|
919
|
+
<CollapsibleContent open={tabOpen} className="pb-4 bg-card rounded-b-xl">
|
|
920
|
+
{Object.entries(activeLinkedAccount as Record<string, LinkedAccount[]>).map(([f, accounts], index) => {
|
|
921
|
+
const isOpen = openLinkAcc === index;
|
|
922
|
+
const fiType = removeUnderscores(f) || f
|
|
923
|
+
return (
|
|
924
|
+
<Collapsible
|
|
925
|
+
key={fiType}
|
|
926
|
+
open={isOpen}
|
|
927
|
+
onOpenChange={() => setOpenLinkAcc(isOpen ? null : index)}
|
|
928
|
+
>
|
|
929
|
+
<CollapsibleTrigger className="flex justify-between items-center p-4 w-[100%]">
|
|
930
|
+
<SectionTitle
|
|
931
|
+
title={fiType}
|
|
932
|
+
className='text-sm md:text-sm'
|
|
933
|
+
rightSection={(
|
|
934
|
+
<ChevronDownIcon
|
|
935
|
+
size={18}
|
|
936
|
+
className={`h-5 w-5 transition-transform duration-300 ${isOpen ? "rotate-180" : "rotate-0"
|
|
832
937
|
}`}
|
|
938
|
+
/>
|
|
939
|
+
)}
|
|
940
|
+
/>
|
|
941
|
+
</CollapsibleTrigger>
|
|
942
|
+
<CollapsibleContent open={isOpen} className="px-4 pb-4">
|
|
943
|
+
{accounts.map(account => (
|
|
944
|
+
<div className='mt-2 flex flex-col gap-2' key={account.id}>
|
|
945
|
+
<OuterCard
|
|
946
|
+
selected={true}
|
|
947
|
+
// onSelect={() => toggleBankSelection(account.accountRefNumber)}
|
|
948
|
+
>
|
|
949
|
+
<BankCard
|
|
950
|
+
bankName={account.bankName}
|
|
951
|
+
image={account.logoUrl}
|
|
952
|
+
subText={`${account.type} | **${formatAccountNumber(account.maskedAccountNumber || "0")}`}
|
|
953
|
+
// onClick={() => toggleBankSelection(account.accountRefNumber)}
|
|
954
|
+
// rightSection={
|
|
955
|
+
// <Checkbox
|
|
956
|
+
// id={`checkbox-${account.id}`}
|
|
957
|
+
// checked={selectedAccounts.includes(account.accountRefNumber)}
|
|
958
|
+
// onCheckedChange={() => toggleBankSelection(account.accountRefNumber)}
|
|
959
|
+
// />
|
|
960
|
+
// }
|
|
833
961
|
/>
|
|
834
|
-
|
|
835
|
-
|
|
836
|
-
|
|
837
|
-
|
|
838
|
-
|
|
839
|
-
|
|
840
|
-
|
|
841
|
-
|
|
842
|
-
|
|
843
|
-
|
|
844
|
-
|
|
845
|
-
|
|
846
|
-
|
|
847
|
-
subText={`${account.type} | **${formatAccountNumber(account.maskedAccountNumber || "0")}`}
|
|
848
|
-
// onClick={() => toggleBankSelection(account.accountRefNumber)}
|
|
849
|
-
// rightSection={
|
|
850
|
-
// <Checkbox
|
|
851
|
-
// id={`checkbox-${account.id}`}
|
|
852
|
-
// checked={selectedAccounts.includes(account.accountRefNumber)}
|
|
853
|
-
// onCheckedChange={() => toggleBankSelection(account.accountRefNumber)}
|
|
854
|
-
// />
|
|
855
|
-
// }
|
|
856
|
-
/>
|
|
857
|
-
</OuterCard>
|
|
858
|
-
</div>
|
|
859
|
-
))}
|
|
860
|
-
</CollapsibleContent>
|
|
861
|
-
</Collapsible>
|
|
862
|
-
);
|
|
863
|
-
})}
|
|
864
|
-
</CollapsibleContent>
|
|
865
|
-
</Collapsible>
|
|
866
|
-
</div>
|
|
867
|
-
)}
|
|
868
|
-
</>
|
|
869
|
-
) : (
|
|
962
|
+
</OuterCard>
|
|
963
|
+
</div>
|
|
964
|
+
))}
|
|
965
|
+
</CollapsibleContent>
|
|
966
|
+
</Collapsible>
|
|
967
|
+
);
|
|
968
|
+
})}
|
|
969
|
+
</CollapsibleContent>
|
|
970
|
+
</Collapsible>
|
|
971
|
+
</div>
|
|
972
|
+
)}
|
|
973
|
+
</>
|
|
974
|
+
) : (
|
|
870
975
|
renderAccountGroups()
|
|
871
976
|
)}
|
|
872
977
|
</div>
|
|
873
|
-
{(requiredCategory?.every(fiType => totalCategory?.includes(fiType)) || state?.isAutoDiscovery
|
|
978
|
+
{(requiredCategory?.every(fiType => totalCategory?.includes(fiType)) || state?.isAutoDiscovery || !shouldShowDiscoverMore) ? null :
|
|
874
979
|
<Button
|
|
875
980
|
variant={'outline'}
|
|
876
981
|
className='bg-primary-foreground text-primary border-primary hover:bg-primary/10 h-[50px] dark:bg-ring'
|