saafe-redirection-flow 2.0.0 → 2.2.0
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 +23 -0
- package/aa-redirection-1607251826.zip +0 -0
- package/docs/features/account-discovery.md +803 -0
- package/docs/features/authentication.md +583 -0
- package/docs/features/consent-management.md +740 -0
- package/docs/features/index.md +206 -0
- package/docs/features/navigation-routing.md +846 -0
- package/docs/features/overview.md +554 -0
- package/docs/features/theming-internationalization.md +982 -0
- package/docs/index.md +1 -1
- package/package.json +1 -1
- package/src/components/AutoDiscoveryLoader.tsx +29 -0
- package/src/components/LinkedAccountTypeAccordion.tsx +154 -0
- package/src/components/alert/alert.tsx +10 -4
- package/src/components/modal/HelpModal.tsx +122 -0
- package/src/components/session/SessionTimer.tsx +20 -33
- package/src/components/title/AppBar.tsx +1 -1
- package/src/components/ui/bottom-sheet.tsx +1 -1
- package/src/components/ui/frosted-panel.tsx +0 -2
- package/src/components/ui/otp-input.tsx +38 -6
- package/src/hooks/use-account-discovery.ts +13 -6
- package/src/hooks/use-auto-discovery.ts +226 -0
- package/src/index.css +3 -0
- package/src/pages/accounts/AccountsToProceed.tsx +598 -59
- package/src/pages/accounts/Discover.tsx +127 -9
- package/src/pages/accounts/DiscoverAccount.tsx +195 -42
- package/src/pages/accounts/LinkSelectedAccounts.tsx +15 -9
- package/src/pages/accounts/OldUser.tsx +184 -79
- package/src/pages/accounts/link-accounts.tsx +19 -11
- package/src/pages/consent/ReviewConsent.tsx +19 -10
- package/src/pages/consent/rejected.tsx +17 -8
- package/src/pages/consent/success.tsx +125 -76
- package/src/services/api/account.service.ts +2 -2
- package/src/store/fip.store.ts +74 -28
- package/src/store/redirect.store.ts +19 -0
- package/src/utils/auto-discovery.ts +126 -0
- package/src/utils/toast-helpers.ts +5 -0
- package/stage-aa-2506251021.zip +0 -0
|
@@ -0,0 +1,803 @@
|
|
|
1
|
+
# Account Discovery Module Documentation
|
|
2
|
+
|
|
3
|
+
## Overview
|
|
4
|
+
|
|
5
|
+
The Account Discovery module is a core feature of the SAAFE Redirection Flow that enables users to discover, select, and link their financial accounts from various Financial Institution Providers (FIPs). This module provides both automatic discovery based on user identifiers and manual selection through a comprehensive Financial Institution listing.
|
|
6
|
+
|
|
7
|
+
## Core Components
|
|
8
|
+
|
|
9
|
+
### 1. Discover Page (`Discover.tsx`)
|
|
10
|
+
|
|
11
|
+
The main interface for account discovery and linking functionality.
|
|
12
|
+
|
|
13
|
+
**Location**: `src/pages/accounts/Discover.tsx`
|
|
14
|
+
|
|
15
|
+
**Multi-Purpose Component**:
|
|
16
|
+
The Discover component handles multiple account-related flows based on the current route:
|
|
17
|
+
- FIP category listing (`/link-accounts/:category`)
|
|
18
|
+
- Account discovery (`/link-accounts/discovery`)
|
|
19
|
+
- Account linking (`/link-accounts/link`)
|
|
20
|
+
- Account details (`/link-accounts/discover-account`)
|
|
21
|
+
|
|
22
|
+
**Key Features**:
|
|
23
|
+
- Dynamic FIP categorization and display
|
|
24
|
+
- Search functionality with real-time filtering
|
|
25
|
+
- Account auto-discovery integration
|
|
26
|
+
- Multi-account selection capability
|
|
27
|
+
- Progressive disclosure of account information
|
|
28
|
+
|
|
29
|
+
### 2. AccountsToProceed Component
|
|
30
|
+
|
|
31
|
+
**Location**: `src/pages/accounts/AccountsToProceed.tsx`
|
|
32
|
+
|
|
33
|
+
**Purpose**: Displays selected accounts before proceeding to consent review
|
|
34
|
+
|
|
35
|
+
**Features**:
|
|
36
|
+
- Account selection summary
|
|
37
|
+
- Individual account details
|
|
38
|
+
- Modification options
|
|
39
|
+
- Navigation to consent review
|
|
40
|
+
|
|
41
|
+
### 3. DiscoverAccount Component
|
|
42
|
+
|
|
43
|
+
**Location**: `src/pages/accounts/DiscoverAccount.tsx`
|
|
44
|
+
|
|
45
|
+
**Purpose**: Detailed view for specific account discovery
|
|
46
|
+
|
|
47
|
+
**Features**:
|
|
48
|
+
- Account-specific information display
|
|
49
|
+
- Discovery status tracking
|
|
50
|
+
- Error handling for discovery failures
|
|
51
|
+
- Retry mechanisms
|
|
52
|
+
|
|
53
|
+
### 4. LinkSelectedAccounts Component
|
|
54
|
+
|
|
55
|
+
**Location**: `src/pages/accounts/LinkSelectedAccounts.tsx`
|
|
56
|
+
|
|
57
|
+
**Purpose**: Final account linking interface
|
|
58
|
+
|
|
59
|
+
**Features**:
|
|
60
|
+
- Selected accounts confirmation
|
|
61
|
+
- Linking progress indication
|
|
62
|
+
- Success/failure handling
|
|
63
|
+
- Post-linking actions
|
|
64
|
+
|
|
65
|
+
### 5. OldUser Component
|
|
66
|
+
|
|
67
|
+
**Location**: `src/pages/accounts/OldUser.tsx`
|
|
68
|
+
|
|
69
|
+
**Purpose**: Interface for returning users with existing linked accounts
|
|
70
|
+
|
|
71
|
+
**Features**:
|
|
72
|
+
- Display of previously linked accounts
|
|
73
|
+
- Option to add new accounts
|
|
74
|
+
- Account unlinking functionality
|
|
75
|
+
- Account status management
|
|
76
|
+
|
|
77
|
+
## FIP (Financial Institution Provider) Management
|
|
78
|
+
|
|
79
|
+
### FIP Store (`fip.store.ts`)
|
|
80
|
+
|
|
81
|
+
**Location**: `src/store/fip.store.ts`
|
|
82
|
+
|
|
83
|
+
**State Structure**:
|
|
84
|
+
```typescript
|
|
85
|
+
interface FipState {
|
|
86
|
+
fips: FipData[];
|
|
87
|
+
groupedFips: Record<string, FipData[]>;
|
|
88
|
+
selectedFips: Record<string, string[]>;
|
|
89
|
+
activeCategory: string | null;
|
|
90
|
+
categories: string[];
|
|
91
|
+
completedCategories: string[];
|
|
92
|
+
currentCategoryStep: CategoryStepType;
|
|
93
|
+
selectedAccountToLink: AccountToLink[];
|
|
94
|
+
originalAccounts: AutoDiscoveryResponse['Accounts'];
|
|
95
|
+
accountsStatusArray: AccountStatus[];
|
|
96
|
+
identifiers: Identifier[];
|
|
97
|
+
accountForConsent: AccountForConsent[];
|
|
98
|
+
}
|
|
99
|
+
```
|
|
100
|
+
|
|
101
|
+
**Key Actions**:
|
|
102
|
+
- `setFips(fips, categories)` - Initialize FIP data
|
|
103
|
+
- `setSelectedFips(category, fipIds)` - Manage FIP selections
|
|
104
|
+
- `setActiveCategory(category)` - Set current category
|
|
105
|
+
- `setSelectedAccountToLink(accounts)` - Manage account selections
|
|
106
|
+
- `setOriginalAccounts(accounts)` - Store auto-discovery results
|
|
107
|
+
|
|
108
|
+
### FIP Categories
|
|
109
|
+
|
|
110
|
+
**Supported Categories**:
|
|
111
|
+
- **BANK**: Traditional banking institutions
|
|
112
|
+
- **NBFC**: Non-Banking Financial Companies
|
|
113
|
+
- **INSURANCE**: Insurance providers
|
|
114
|
+
- **GST**: GST-related financial data
|
|
115
|
+
- **INVESTMENTS**: Investment and mutual fund companies
|
|
116
|
+
|
|
117
|
+
**Category Configuration**:
|
|
118
|
+
```typescript
|
|
119
|
+
const CATEGORY_TYPES = {
|
|
120
|
+
BANK: 'Banks',
|
|
121
|
+
NBFC: 'NBFCs',
|
|
122
|
+
INSURANCE: 'Insurance',
|
|
123
|
+
GST: 'GST',
|
|
124
|
+
INVESTMENTS: 'Investments'
|
|
125
|
+
} as const;
|
|
126
|
+
```
|
|
127
|
+
|
|
128
|
+
## Auto-Discovery Feature
|
|
129
|
+
|
|
130
|
+
### Auto-Discovery Hook (`use-auto-discovery.ts`)
|
|
131
|
+
|
|
132
|
+
**Location**: `src/hooks/use-auto-discovery.ts`
|
|
133
|
+
|
|
134
|
+
**Purpose**: Automatically discover user accounts based on identifiers
|
|
135
|
+
|
|
136
|
+
**Key Features**:
|
|
137
|
+
- Multiple identifier support (mobile, email, PAN, etc.)
|
|
138
|
+
- Batch discovery across FIPs
|
|
139
|
+
- Real-time discovery status
|
|
140
|
+
- Error handling and retry logic
|
|
141
|
+
|
|
142
|
+
**Usage**:
|
|
143
|
+
```typescript
|
|
144
|
+
const {
|
|
145
|
+
discoverAccounts,
|
|
146
|
+
isDiscovering,
|
|
147
|
+
discoveryResults,
|
|
148
|
+
error
|
|
149
|
+
} = useAutoDiscovery();
|
|
150
|
+
|
|
151
|
+
// Trigger discovery
|
|
152
|
+
const results = await discoverAccounts({
|
|
153
|
+
identifiers: ['mobile:9876543210', 'email:user@example.com'],
|
|
154
|
+
categories: ['BANK', 'INSURANCE']
|
|
155
|
+
});
|
|
156
|
+
```
|
|
157
|
+
|
|
158
|
+
### Account Discovery Hook (`use-account-discovery.ts`)
|
|
159
|
+
|
|
160
|
+
**Location**: `src/hooks/use-account-discovery.ts`
|
|
161
|
+
|
|
162
|
+
**Purpose**: Enhanced account discovery with additional features
|
|
163
|
+
|
|
164
|
+
**Features**:
|
|
165
|
+
- Progressive discovery
|
|
166
|
+
- Cache management
|
|
167
|
+
- Background updates
|
|
168
|
+
- Discovery analytics
|
|
169
|
+
|
|
170
|
+
## Account Selection and Linking
|
|
171
|
+
|
|
172
|
+
### Account Data Structures
|
|
173
|
+
|
|
174
|
+
**Account Interface**:
|
|
175
|
+
```typescript
|
|
176
|
+
interface AccountToLink {
|
|
177
|
+
accountId: string;
|
|
178
|
+
accountNumber: string;
|
|
179
|
+
accountType: string;
|
|
180
|
+
fipId: string;
|
|
181
|
+
fipName: string;
|
|
182
|
+
maskedAccountNumber: string;
|
|
183
|
+
isSelected: boolean;
|
|
184
|
+
balance?: number;
|
|
185
|
+
currency?: string;
|
|
186
|
+
}
|
|
187
|
+
```
|
|
188
|
+
|
|
189
|
+
**Account Status Interface**:
|
|
190
|
+
```typescript
|
|
191
|
+
interface AccountStatus {
|
|
192
|
+
accountId: string;
|
|
193
|
+
status: 'PENDING' | 'LINKED' | 'FAILED' | 'EXPIRED';
|
|
194
|
+
lastUpdated: Date;
|
|
195
|
+
errorMessage?: string;
|
|
196
|
+
}
|
|
197
|
+
```
|
|
198
|
+
|
|
199
|
+
### Link Accounts Hook (`use-link-accounts.ts`)
|
|
200
|
+
|
|
201
|
+
**Purpose**: Manage the account linking process
|
|
202
|
+
|
|
203
|
+
**Features**:
|
|
204
|
+
- Multi-account linking
|
|
205
|
+
- Progress tracking
|
|
206
|
+
- Error handling
|
|
207
|
+
- Success confirmation
|
|
208
|
+
|
|
209
|
+
**Usage**:
|
|
210
|
+
```typescript
|
|
211
|
+
const {
|
|
212
|
+
linkAccounts,
|
|
213
|
+
isLinking,
|
|
214
|
+
progress,
|
|
215
|
+
linkedAccounts,
|
|
216
|
+
errors
|
|
217
|
+
} = useLinkAccounts();
|
|
218
|
+
|
|
219
|
+
// Link selected accounts
|
|
220
|
+
await linkAccounts(selectedAccounts);
|
|
221
|
+
```
|
|
222
|
+
|
|
223
|
+
## Search and Filtering
|
|
224
|
+
|
|
225
|
+
### FIP Search Functionality
|
|
226
|
+
|
|
227
|
+
**Search Features**:
|
|
228
|
+
- Real-time text search
|
|
229
|
+
- Category-based filtering
|
|
230
|
+
- Multi-criteria search
|
|
231
|
+
- Search result highlighting
|
|
232
|
+
|
|
233
|
+
**Search Implementation**:
|
|
234
|
+
```typescript
|
|
235
|
+
const filteredFips = useMemo(() => {
|
|
236
|
+
return fips.filter(fip => {
|
|
237
|
+
const matchesSearch = fip.name.toLowerCase().includes(searchTerm.toLowerCase());
|
|
238
|
+
const matchesCategory = !activeCategory || fip.category === activeCategory;
|
|
239
|
+
return matchesSearch && matchesCategory;
|
|
240
|
+
});
|
|
241
|
+
}, [fips, searchTerm, activeCategory]);
|
|
242
|
+
```
|
|
243
|
+
|
|
244
|
+
### Advanced Filtering
|
|
245
|
+
|
|
246
|
+
**Filter Options**:
|
|
247
|
+
- Institution type
|
|
248
|
+
- Availability status
|
|
249
|
+
- Onboarding status
|
|
250
|
+
- Popular institutions
|
|
251
|
+
|
|
252
|
+
**Filter Implementation**:
|
|
253
|
+
```typescript
|
|
254
|
+
const getFilteredFips = (fips: FipData[], filters: FilterOptions) => {
|
|
255
|
+
return fips.filter(fip => {
|
|
256
|
+
if (filters.type && fip.type !== filters.type) return false;
|
|
257
|
+
if (filters.onlyAvailable && !fip.isAvailable) return false;
|
|
258
|
+
if (filters.onlyOnboarded && !fip.isOnBoarded) return false;
|
|
259
|
+
return true;
|
|
260
|
+
});
|
|
261
|
+
};
|
|
262
|
+
```
|
|
263
|
+
|
|
264
|
+
## API Integration
|
|
265
|
+
|
|
266
|
+
### FIP Service (`fip.service.ts`)
|
|
267
|
+
|
|
268
|
+
**Location**: `src/services/api/fip.service.ts`
|
|
269
|
+
|
|
270
|
+
**API Endpoints**:
|
|
271
|
+
```typescript
|
|
272
|
+
// Get available FIPs
|
|
273
|
+
GET /fips
|
|
274
|
+
Query: { category?, search?, limit?, offset? }
|
|
275
|
+
|
|
276
|
+
// Discover accounts
|
|
277
|
+
POST /accounts/discover
|
|
278
|
+
Body: { identifiers: string[], fipIds: string[] }
|
|
279
|
+
|
|
280
|
+
// Link accounts
|
|
281
|
+
POST /accounts/link
|
|
282
|
+
Body: { accounts: AccountToLink[] }
|
|
283
|
+
|
|
284
|
+
// Get account details
|
|
285
|
+
GET /accounts/:accountId
|
|
286
|
+
```
|
|
287
|
+
|
|
288
|
+
**Service Methods**:
|
|
289
|
+
- `getFips(category?)` - Fetch available FIPs
|
|
290
|
+
- `discoverAccounts(identifiers, fipIds)` - Auto-discover accounts
|
|
291
|
+
- `linkAccounts(accounts)` - Link selected accounts
|
|
292
|
+
- `getAccountDetails(accountId)` - Get detailed account info
|
|
293
|
+
|
|
294
|
+
### Account Service (`account.service.ts`)
|
|
295
|
+
|
|
296
|
+
**Location**: `src/services/api/account.service.ts`
|
|
297
|
+
|
|
298
|
+
**Features**:
|
|
299
|
+
- Account CRUD operations
|
|
300
|
+
- Bulk account operations
|
|
301
|
+
- Account status management
|
|
302
|
+
- Account metadata handling
|
|
303
|
+
|
|
304
|
+
## User Interface Components
|
|
305
|
+
|
|
306
|
+
### FIP Category Cards
|
|
307
|
+
|
|
308
|
+
**Features**:
|
|
309
|
+
- Category-specific icons
|
|
310
|
+
- Institution counts
|
|
311
|
+
- Progress indicators
|
|
312
|
+
- Completion status
|
|
313
|
+
|
|
314
|
+
**Component Structure**:
|
|
315
|
+
```tsx
|
|
316
|
+
interface CategoryCardProps {
|
|
317
|
+
category: string;
|
|
318
|
+
institutionCount: number;
|
|
319
|
+
isCompleted: boolean;
|
|
320
|
+
isActive: boolean;
|
|
321
|
+
onClick: () => void;
|
|
322
|
+
}
|
|
323
|
+
```
|
|
324
|
+
|
|
325
|
+
### FIP Institution Cards
|
|
326
|
+
|
|
327
|
+
**Features**:
|
|
328
|
+
- Institution logos
|
|
329
|
+
- Availability status
|
|
330
|
+
- Selection indicators
|
|
331
|
+
- Quick actions
|
|
332
|
+
|
|
333
|
+
**Card Variants**:
|
|
334
|
+
- List view for mobile
|
|
335
|
+
- Grid view for desktop
|
|
336
|
+
- Compact view for selection
|
|
337
|
+
|
|
338
|
+
### Account Selection Interface
|
|
339
|
+
|
|
340
|
+
**Features**:
|
|
341
|
+
- Multi-select checkboxes
|
|
342
|
+
- Account detail cards
|
|
343
|
+
- Selection summary
|
|
344
|
+
- Bulk operations
|
|
345
|
+
|
|
346
|
+
**Selection Management**:
|
|
347
|
+
```typescript
|
|
348
|
+
const handleAccountSelection = (account: AccountToLink) => {
|
|
349
|
+
setSelectedAccounts(prev => {
|
|
350
|
+
const isSelected = prev.some(acc => acc.accountId === account.accountId);
|
|
351
|
+
if (isSelected) {
|
|
352
|
+
return prev.filter(acc => acc.accountId !== account.accountId);
|
|
353
|
+
} else {
|
|
354
|
+
return [...prev, account];
|
|
355
|
+
}
|
|
356
|
+
});
|
|
357
|
+
};
|
|
358
|
+
```
|
|
359
|
+
|
|
360
|
+
## Internationalization
|
|
361
|
+
|
|
362
|
+
### Multi-Language Support
|
|
363
|
+
|
|
364
|
+
**Supported Languages**:
|
|
365
|
+
- English (en)
|
|
366
|
+
- Hindi (hi)
|
|
367
|
+
- Tamil (ta)
|
|
368
|
+
- Malayalam (ml)
|
|
369
|
+
- Telugu (te)
|
|
370
|
+
- Kannada (kn)
|
|
371
|
+
- Urdu (ur)
|
|
372
|
+
|
|
373
|
+
**Translation Keys**:
|
|
374
|
+
```json
|
|
375
|
+
{
|
|
376
|
+
"categories": {
|
|
377
|
+
"bank": "Banks",
|
|
378
|
+
"nbfc": "NBFCs",
|
|
379
|
+
"insurance": "Insurance",
|
|
380
|
+
"gst": "GST",
|
|
381
|
+
"investments": "Investments"
|
|
382
|
+
},
|
|
383
|
+
"discovery": {
|
|
384
|
+
"searching": "Searching for accounts...",
|
|
385
|
+
"found": "Found {{count}} accounts",
|
|
386
|
+
"noResults": "No accounts found"
|
|
387
|
+
}
|
|
388
|
+
}
|
|
389
|
+
```
|
|
390
|
+
|
|
391
|
+
### RTL Support
|
|
392
|
+
|
|
393
|
+
**Features**:
|
|
394
|
+
- Right-to-left layout for Arabic/Urdu
|
|
395
|
+
- RTL-aware animations
|
|
396
|
+
- Direction-specific styling
|
|
397
|
+
- Icon orientation handling
|
|
398
|
+
|
|
399
|
+
## Platform-Specific Optimizations
|
|
400
|
+
|
|
401
|
+
### Mobile Platform
|
|
402
|
+
|
|
403
|
+
**Optimizations**:
|
|
404
|
+
- Touch-friendly interface
|
|
405
|
+
- Swipe gestures for navigation
|
|
406
|
+
- Bottom sheet for account details
|
|
407
|
+
- Mobile-specific layouts
|
|
408
|
+
|
|
409
|
+
**Mobile Components**:
|
|
410
|
+
```tsx
|
|
411
|
+
// Mobile-specific FIP grid
|
|
412
|
+
<div className="grid grid-cols-2 gap-4 md:grid-cols-3 lg:grid-cols-4">
|
|
413
|
+
{fips.map(fip => (
|
|
414
|
+
<FipCard key={fip.id} fip={fip} variant="mobile" />
|
|
415
|
+
))}
|
|
416
|
+
</div>
|
|
417
|
+
```
|
|
418
|
+
|
|
419
|
+
### Desktop Platform
|
|
420
|
+
|
|
421
|
+
**Optimizations**:
|
|
422
|
+
- Hover states and animations
|
|
423
|
+
- Keyboard navigation
|
|
424
|
+
- Multi-column layouts
|
|
425
|
+
- Advanced filtering UI
|
|
426
|
+
|
|
427
|
+
**Desktop Features**:
|
|
428
|
+
- Sidebar navigation
|
|
429
|
+
- Tabbed interface
|
|
430
|
+
- Advanced search
|
|
431
|
+
- Bulk operations
|
|
432
|
+
|
|
433
|
+
## Error Handling
|
|
434
|
+
|
|
435
|
+
### Discovery Errors
|
|
436
|
+
|
|
437
|
+
**Error Types**:
|
|
438
|
+
- Network connectivity issues
|
|
439
|
+
- FIP service unavailable
|
|
440
|
+
- Invalid credentials
|
|
441
|
+
- Account not found
|
|
442
|
+
- Rate limiting
|
|
443
|
+
|
|
444
|
+
**Error Recovery**:
|
|
445
|
+
```typescript
|
|
446
|
+
const handleDiscoveryError = (error: DiscoveryError) => {
|
|
447
|
+
switch (error.type) {
|
|
448
|
+
case 'NETWORK_ERROR':
|
|
449
|
+
// Retry with exponential backoff
|
|
450
|
+
scheduleRetry(error.context);
|
|
451
|
+
break;
|
|
452
|
+
case 'FIP_UNAVAILABLE':
|
|
453
|
+
// Skip FIP and continue
|
|
454
|
+
skipFipAndContinue(error.fipId);
|
|
455
|
+
break;
|
|
456
|
+
case 'RATE_LIMITED':
|
|
457
|
+
// Wait and retry
|
|
458
|
+
scheduleRetryAfterDelay(error.retryAfter);
|
|
459
|
+
break;
|
|
460
|
+
default:
|
|
461
|
+
// Show user-friendly error
|
|
462
|
+
showErrorMessage(error.message);
|
|
463
|
+
}
|
|
464
|
+
};
|
|
465
|
+
```
|
|
466
|
+
|
|
467
|
+
### User-Friendly Error Messages
|
|
468
|
+
|
|
469
|
+
**Error Message Mapping**:
|
|
470
|
+
```typescript
|
|
471
|
+
const ERROR_MESSAGES = {
|
|
472
|
+
NETWORK_ERROR: 'Please check your internet connection and try again.',
|
|
473
|
+
FIP_UNAVAILABLE: 'This institution is temporarily unavailable.',
|
|
474
|
+
ACCOUNT_NOT_FOUND: 'No accounts found with the provided information.',
|
|
475
|
+
INVALID_CREDENTIALS: 'Please verify your login credentials.',
|
|
476
|
+
};
|
|
477
|
+
```
|
|
478
|
+
|
|
479
|
+
## Performance Optimizations
|
|
480
|
+
|
|
481
|
+
### Virtual Scrolling
|
|
482
|
+
|
|
483
|
+
**Implementation**:
|
|
484
|
+
- Large FIP lists optimization
|
|
485
|
+
- Smooth scrolling performance
|
|
486
|
+
- Memory usage optimization
|
|
487
|
+
|
|
488
|
+
```tsx
|
|
489
|
+
import { FixedSizeList } from 'react-window';
|
|
490
|
+
|
|
491
|
+
const VirtualFipList = ({ fips }: { fips: FipData[] }) => (
|
|
492
|
+
<FixedSizeList
|
|
493
|
+
height={400}
|
|
494
|
+
itemCount={fips.length}
|
|
495
|
+
itemSize={80}
|
|
496
|
+
itemData={fips}
|
|
497
|
+
>
|
|
498
|
+
{FipListItem}
|
|
499
|
+
</FixedSizeList>
|
|
500
|
+
);
|
|
501
|
+
```
|
|
502
|
+
|
|
503
|
+
### Caching Strategy
|
|
504
|
+
|
|
505
|
+
**Cache Levels**:
|
|
506
|
+
- FIP list caching (24 hours)
|
|
507
|
+
- Discovery results caching (5 minutes)
|
|
508
|
+
- Account details caching (1 hour)
|
|
509
|
+
|
|
510
|
+
**Cache Implementation**:
|
|
511
|
+
```typescript
|
|
512
|
+
const useFipsWithCache = () => {
|
|
513
|
+
return useQuery({
|
|
514
|
+
queryKey: ['fips'],
|
|
515
|
+
queryFn: fetchFips,
|
|
516
|
+
staleTime: 24 * 60 * 60 * 1000, // 24 hours
|
|
517
|
+
cacheTime: 24 * 60 * 60 * 1000,
|
|
518
|
+
});
|
|
519
|
+
};
|
|
520
|
+
```
|
|
521
|
+
|
|
522
|
+
## Analytics and Tracking
|
|
523
|
+
|
|
524
|
+
### Discovery Analytics
|
|
525
|
+
|
|
526
|
+
**Tracked Events**:
|
|
527
|
+
- FIP category selection
|
|
528
|
+
- Institution selection
|
|
529
|
+
- Account discovery initiation
|
|
530
|
+
- Discovery success/failure
|
|
531
|
+
- Account linking actions
|
|
532
|
+
|
|
533
|
+
**Analytics Implementation**:
|
|
534
|
+
```typescript
|
|
535
|
+
// Track discovery events
|
|
536
|
+
trackEvent('ACCOUNT_DISCOVERY_STARTED', {
|
|
537
|
+
category: activeCategory,
|
|
538
|
+
fipCount: selectedFips.length,
|
|
539
|
+
identifierTypes: identifiers.map(id => id.type)
|
|
540
|
+
});
|
|
541
|
+
|
|
542
|
+
trackEvent('ACCOUNT_DISCOVERY_COMPLETED', {
|
|
543
|
+
category: activeCategory,
|
|
544
|
+
accountsFound: discoveredAccounts.length,
|
|
545
|
+
duration: discoveryDuration
|
|
546
|
+
});
|
|
547
|
+
```
|
|
548
|
+
|
|
549
|
+
### User Journey Tracking
|
|
550
|
+
|
|
551
|
+
**Journey Stages**:
|
|
552
|
+
1. Category selection
|
|
553
|
+
2. FIP browsing
|
|
554
|
+
3. Institution selection
|
|
555
|
+
4. Account discovery
|
|
556
|
+
5. Account selection
|
|
557
|
+
6. Linking confirmation
|
|
558
|
+
|
|
559
|
+
## Testing Strategy
|
|
560
|
+
|
|
561
|
+
### Unit Tests
|
|
562
|
+
|
|
563
|
+
**Test Coverage**:
|
|
564
|
+
- FIP filtering logic
|
|
565
|
+
- Account selection state
|
|
566
|
+
- Discovery hook functionality
|
|
567
|
+
- Error handling scenarios
|
|
568
|
+
|
|
569
|
+
**Example Tests**:
|
|
570
|
+
```typescript
|
|
571
|
+
describe('FIP Discovery', () => {
|
|
572
|
+
test('filters FIPs by category', () => {
|
|
573
|
+
const fips = mockFipData;
|
|
574
|
+
const filtered = filterFipsByCategory(fips, 'BANK');
|
|
575
|
+
expect(filtered).toHaveLength(5);
|
|
576
|
+
expect(filtered.every(fip => fip.category === 'BANK')).toBe(true);
|
|
577
|
+
});
|
|
578
|
+
|
|
579
|
+
test('handles discovery errors gracefully', async () => {
|
|
580
|
+
const mockError = new Error('Network error');
|
|
581
|
+
mockDiscoveryService.mockRejectedValue(mockError);
|
|
582
|
+
|
|
583
|
+
const { result } = renderHook(() => useAutoDiscovery());
|
|
584
|
+
await act(() => result.current.discoverAccounts(mockIdentifiers));
|
|
585
|
+
|
|
586
|
+
expect(result.current.error).toBe(mockError);
|
|
587
|
+
});
|
|
588
|
+
});
|
|
589
|
+
```
|
|
590
|
+
|
|
591
|
+
### Integration Tests
|
|
592
|
+
|
|
593
|
+
**Test Scenarios**:
|
|
594
|
+
- Complete discovery flow
|
|
595
|
+
- Multi-category selection
|
|
596
|
+
- Account linking process
|
|
597
|
+
- Error recovery flows
|
|
598
|
+
|
|
599
|
+
### End-to-End Tests
|
|
600
|
+
|
|
601
|
+
**E2E Scenarios**:
|
|
602
|
+
```typescript
|
|
603
|
+
test('complete account discovery and linking flow', async () => {
|
|
604
|
+
// Navigate to discovery page
|
|
605
|
+
await page.goto('/link-accounts/banks');
|
|
606
|
+
|
|
607
|
+
// Select a bank
|
|
608
|
+
await page.click('[data-testid="bank-card-hdfc"]');
|
|
609
|
+
|
|
610
|
+
// Wait for discovery
|
|
611
|
+
await page.waitForSelector('[data-testid="discovered-accounts"]');
|
|
612
|
+
|
|
613
|
+
// Select accounts
|
|
614
|
+
await page.check('[data-testid="account-checkbox-1"]');
|
|
615
|
+
await page.check('[data-testid="account-checkbox-2"]');
|
|
616
|
+
|
|
617
|
+
// Proceed to consent
|
|
618
|
+
await page.click('[data-testid="proceed-button"]');
|
|
619
|
+
|
|
620
|
+
// Verify navigation to consent page
|
|
621
|
+
expect(page.url()).toContain('/review');
|
|
622
|
+
});
|
|
623
|
+
```
|
|
624
|
+
|
|
625
|
+
## Configuration
|
|
626
|
+
|
|
627
|
+
### Discovery Configuration
|
|
628
|
+
|
|
629
|
+
```typescript
|
|
630
|
+
export const DISCOVERY_CONFIG = {
|
|
631
|
+
maxConcurrentDiscoveries: 5,
|
|
632
|
+
discoveryTimeout: 30000, // 30 seconds
|
|
633
|
+
retryAttempts: 3,
|
|
634
|
+
retryDelay: 1000, // 1 second
|
|
635
|
+
cacheTimeout: 5 * 60 * 1000, // 5 minutes
|
|
636
|
+
};
|
|
637
|
+
```
|
|
638
|
+
|
|
639
|
+
### FIP Display Configuration
|
|
640
|
+
|
|
641
|
+
```typescript
|
|
642
|
+
export const FIP_DISPLAY_CONFIG = {
|
|
643
|
+
itemsPerPage: 20,
|
|
644
|
+
enableVirtualScrolling: true,
|
|
645
|
+
showLogos: true,
|
|
646
|
+
enableSearch: true,
|
|
647
|
+
enableFiltering: true,
|
|
648
|
+
defaultSortBy: 'popularity',
|
|
649
|
+
};
|
|
650
|
+
```
|
|
651
|
+
|
|
652
|
+
## Future Enhancements
|
|
653
|
+
|
|
654
|
+
### Planned Features
|
|
655
|
+
|
|
656
|
+
1. **Smart Recommendations**
|
|
657
|
+
- AI-based FIP suggestions
|
|
658
|
+
- Popular institution highlighting
|
|
659
|
+
- User behavior analysis
|
|
660
|
+
|
|
661
|
+
2. **Enhanced Discovery**
|
|
662
|
+
- OCR-based document scanning
|
|
663
|
+
- QR code account linking
|
|
664
|
+
- Bulk import functionality
|
|
665
|
+
|
|
666
|
+
3. **Advanced Filtering**
|
|
667
|
+
- Geographic filtering
|
|
668
|
+
- Service-based filtering
|
|
669
|
+
- Custom filter presets
|
|
670
|
+
|
|
671
|
+
4. **Improved UX**
|
|
672
|
+
- Progressive web app features
|
|
673
|
+
- Offline support
|
|
674
|
+
- Voice navigation
|
|
675
|
+
|
|
676
|
+
### Performance Improvements
|
|
677
|
+
|
|
678
|
+
1. **Optimization**
|
|
679
|
+
- GraphQL integration
|
|
680
|
+
- Server-side rendering
|
|
681
|
+
- Edge caching
|
|
682
|
+
|
|
683
|
+
2. **Mobile Enhancements**
|
|
684
|
+
- Native app integration
|
|
685
|
+
- Biometric authentication
|
|
686
|
+
- Push notifications
|
|
687
|
+
|
|
688
|
+
## Troubleshooting
|
|
689
|
+
|
|
690
|
+
### Common Issues
|
|
691
|
+
|
|
692
|
+
1. **Discovery Timeout**
|
|
693
|
+
- **Symptom**: Discovery process hangs
|
|
694
|
+
- **Solution**: Increase timeout values
|
|
695
|
+
- **Prevention**: Implement progressive discovery
|
|
696
|
+
|
|
697
|
+
2. **No Accounts Found**
|
|
698
|
+
- **Symptom**: Discovery returns empty results
|
|
699
|
+
- **Solution**: Verify identifier formats
|
|
700
|
+
- **Prevention**: Add identifier validation
|
|
701
|
+
|
|
702
|
+
3. **FIP Loading Issues**
|
|
703
|
+
- **Symptom**: FIP list fails to load
|
|
704
|
+
- **Solution**: Check API connectivity
|
|
705
|
+
- **Prevention**: Implement offline fallback
|
|
706
|
+
|
|
707
|
+
### Debug Mode
|
|
708
|
+
|
|
709
|
+
**Enable Debug Logging**:
|
|
710
|
+
```typescript
|
|
711
|
+
localStorage.setItem('discovery-debug', 'true');
|
|
712
|
+
```
|
|
713
|
+
|
|
714
|
+
**Debug Information**:
|
|
715
|
+
- Discovery request/response logs
|
|
716
|
+
- FIP filtering operations
|
|
717
|
+
- Account selection changes
|
|
718
|
+
- Performance metrics
|
|
719
|
+
|
|
720
|
+
## API Documentation
|
|
721
|
+
|
|
722
|
+
### Discovery Endpoints
|
|
723
|
+
|
|
724
|
+
**Base URL**: `{API_URL}/discovery`
|
|
725
|
+
|
|
726
|
+
#### GET /fips
|
|
727
|
+
Get available Financial Institution Providers.
|
|
728
|
+
|
|
729
|
+
**Request**:
|
|
730
|
+
```
|
|
731
|
+
GET /fips?category=BANK&search=hdfc&limit=20&offset=0
|
|
732
|
+
```
|
|
733
|
+
|
|
734
|
+
**Response**:
|
|
735
|
+
```json
|
|
736
|
+
{
|
|
737
|
+
"success": true,
|
|
738
|
+
"data": {
|
|
739
|
+
"fips": [
|
|
740
|
+
{
|
|
741
|
+
"id": "fip_001",
|
|
742
|
+
"name": "HDFC Bank",
|
|
743
|
+
"category": "BANK",
|
|
744
|
+
"logo": "https://...",
|
|
745
|
+
"isAvailable": true,
|
|
746
|
+
"isOnBoarded": true
|
|
747
|
+
}
|
|
748
|
+
],
|
|
749
|
+
"total": 150,
|
|
750
|
+
"categories": ["BANK", "NBFC", "INSURANCE"]
|
|
751
|
+
}
|
|
752
|
+
}
|
|
753
|
+
```
|
|
754
|
+
|
|
755
|
+
#### POST /accounts/discover
|
|
756
|
+
Discover user accounts across FIPs.
|
|
757
|
+
|
|
758
|
+
**Request**:
|
|
759
|
+
```json
|
|
760
|
+
{
|
|
761
|
+
"identifiers": [
|
|
762
|
+
{
|
|
763
|
+
"type": "mobile",
|
|
764
|
+
"value": "9876543210"
|
|
765
|
+
},
|
|
766
|
+
{
|
|
767
|
+
"type": "email",
|
|
768
|
+
"value": "user@example.com"
|
|
769
|
+
}
|
|
770
|
+
],
|
|
771
|
+
"fipIds": ["fip_001", "fip_002"],
|
|
772
|
+
"categories": ["BANK", "INSURANCE"]
|
|
773
|
+
}
|
|
774
|
+
```
|
|
775
|
+
|
|
776
|
+
**Response**:
|
|
777
|
+
```json
|
|
778
|
+
{
|
|
779
|
+
"success": true,
|
|
780
|
+
"data": {
|
|
781
|
+
"accounts": [
|
|
782
|
+
{
|
|
783
|
+
"accountId": "acc_001",
|
|
784
|
+
"fipId": "fip_001",
|
|
785
|
+
"accountNumber": "****1234",
|
|
786
|
+
"accountType": "SAVINGS",
|
|
787
|
+
"balance": 25000.50,
|
|
788
|
+
"currency": "INR"
|
|
789
|
+
}
|
|
790
|
+
],
|
|
791
|
+
"discoveryStatus": {
|
|
792
|
+
"total": 2,
|
|
793
|
+
"successful": 1,
|
|
794
|
+
"failed": 1,
|
|
795
|
+
"errors": ["FIP_002: Service temporarily unavailable"]
|
|
796
|
+
}
|
|
797
|
+
}
|
|
798
|
+
}
|
|
799
|
+
```
|
|
800
|
+
|
|
801
|
+
## Conclusion
|
|
802
|
+
|
|
803
|
+
The Account Discovery module provides a comprehensive and user-friendly interface for discovering and linking financial accounts. It combines automatic discovery capabilities with manual selection options, ensuring users can connect all their relevant financial accounts efficiently and securely.
|