@finspringinnovations/fixeddepositsdk 1.0.2 → 1.0.4
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/lib/api/customerApi.js +1 -0
- package/lib/api/fdApi.d.ts +401 -1
- package/lib/api/fdApi.js +24 -2
- package/lib/components/PendingFDBottomSheet.js +27 -18
- package/lib/config/appDataConfig.js +3 -2
- package/lib/config/workflowConstants.d.ts +40 -30
- package/lib/config/workflowConstants.js +35 -24
- package/lib/constants/strings/fd.d.ts +2 -2
- package/lib/constants/strings/fd.js +2 -2
- package/lib/navigation/RootNavigator.js +167 -196
- package/lib/navigation/types.d.ts +4 -1
- package/lib/navigation/workflowNavigator.d.ts +1 -1
- package/lib/navigation/workflowNavigator.js +107 -26
- package/lib/screens/AadhaarVerification.js +1 -11
- package/lib/screens/AddBankAccount.js +1 -11
- package/lib/screens/BankDetail.js +1 -11
- package/lib/screens/Employee.js +1 -11
- package/lib/screens/FDCalculator.js +2 -12
- package/lib/screens/FDList.js +531 -417
- package/lib/screens/FindIFSC.js +1 -11
- package/lib/screens/NomineeDetail.js +12 -22
- package/lib/screens/PayNow.js +1 -11
- package/lib/screens/Payment.js +2 -11
- package/lib/screens/PaymentStatus.js +24 -21
- package/lib/screens/ReviewKYC.js +3 -12
- package/lib/types/workflowTypes.d.ts +1 -1
- package/package.json +50 -50
- package/src/api/customerApi.ts +1 -0
- package/src/api/fdApi.ts +28 -1
- package/src/components/PendingFDBottomSheet.tsx +151 -123
- package/src/config/appDataConfig.ts +245 -242
- package/src/config/workflowConstants.ts +51 -39
- package/src/constants/strings/bank.ts +80 -80
- package/src/constants/strings/fd.ts +2 -2
- package/src/navigation/RootNavigator.tsx +667 -651
- package/src/navigation/types.ts +4 -1
- package/src/navigation/workflowNavigator.ts +170 -107
- package/src/screens/AadhaarVerification.tsx +1 -15
- package/src/screens/AddBankAccount.tsx +2 -16
- package/src/screens/BankDetail.tsx +1 -15
- package/src/screens/Employee.tsx +1 -15
- package/src/screens/FDCalculator.tsx +4 -18
- package/src/screens/FDList.tsx +2311 -2170
- package/src/screens/FindIFSC.tsx +2 -16
- package/src/screens/NomineeDetail.tsx +762 -775
- package/src/screens/PayNow.tsx +2 -16
- package/src/screens/Payment.tsx +190 -203
- package/src/screens/PaymentStatus.tsx +574 -576
- package/src/screens/ReviewKYC.tsx +2 -15
- package/src/types/workflowTypes.ts +1 -10
package/src/screens/FDList.tsx
CHANGED
|
@@ -1,2224 +1,2365 @@
|
|
|
1
|
-
import React, { useState, useEffect, useCallback } from 'react';
|
|
2
1
|
import {
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
StatusBar,
|
|
13
|
-
Image,
|
|
14
|
-
} from 'react-native';
|
|
2
|
+
initializeEnvironment as initializeMahindraEnvironment, initializeSDK as initializeMahindraSDK, setGlobalData as setMahindraGlobalData, type AppData as MahindraAppData,
|
|
3
|
+
type EnvironmentData as MahindraEnvironmentData
|
|
4
|
+
} from '@finspringinnovations/mahindrafdsdk';
|
|
5
|
+
import {
|
|
6
|
+
initializeEnvironment as initializeShriramEnvironment,
|
|
7
|
+
initializeSDK as initializeShriramSDK,
|
|
8
|
+
type AppData as ShriramAppData,
|
|
9
|
+
type EnvironmentData as ShriramEnvironmentData,
|
|
10
|
+
} from '@finspringinnovations/shriramfdsdk';
|
|
15
11
|
import { useFocusEffect } from '@react-navigation/native';
|
|
16
|
-
import {
|
|
17
|
-
import {
|
|
12
|
+
import React, { useCallback, useEffect, useState } from 'react';
|
|
13
|
+
import {
|
|
14
|
+
ActivityIndicator,
|
|
15
|
+
Alert,
|
|
16
|
+
Image,
|
|
17
|
+
Platform,
|
|
18
|
+
ScrollView,
|
|
19
|
+
StyleSheet,
|
|
20
|
+
Text,
|
|
21
|
+
TouchableOpacity,
|
|
22
|
+
View
|
|
23
|
+
} from 'react-native';
|
|
24
|
+
import { useGetCustomerApplicationDetailsMutation, useGetCustomerApplicationsMutation } from '../api/customerApi';
|
|
25
|
+
import { useLazyGetPaymentUrlQuery, usePaymentReverseFeedMutation } from '../api/fdApi';
|
|
18
26
|
import { useGetInterestRatesMutation } from '../api/interestRateApi';
|
|
19
|
-
import { useGetCustomerApplicationsMutation, useGetCustomerApplicationDetailsMutation } from '../api/customerApi';
|
|
20
27
|
import { useGetMasterDataQuery } from '../api/masterDataApi';
|
|
21
|
-
import { useMasterData } from '../providers/MasterDataProvider';
|
|
22
28
|
import { useTerminateWorkflowMutation } from '../api/workflowApi';
|
|
23
|
-
import {
|
|
24
|
-
import type { ColorScheme, ThemeName } from '../theme';
|
|
29
|
+
import { ActiveFDCard, FDCard, PendingFDBottomSheet } from '../components';
|
|
25
30
|
import SafeAreaWrapper from '../components/SafeAreaWrapper';
|
|
26
|
-
import {
|
|
31
|
+
import { getAppData, getEnvironmentData, getUserInfoForAPI } from '../config/appDataConfig';
|
|
32
|
+
import { MAHINDRA_WORKFLOW_STATES, SHRIRAM_WORKFLOW_STATES } from '../config/workflowConstants';
|
|
33
|
+
import { FD_STRINGS } from '../constants/strings';
|
|
34
|
+
import { base64Images } from '../constants/strings/base64Images';
|
|
27
35
|
import { navigate } from '../navigation/helpers';
|
|
36
|
+
import { handleWorkflowNavigation } from '../navigation/workflowNavigator';
|
|
37
|
+
import { useMasterData } from '../providers/MasterDataProvider';
|
|
28
38
|
import { useAppDispatch, useAppSelector } from '../store';
|
|
29
|
-
import { setOnboardingIds } from '../store/onboardingSlice';
|
|
30
39
|
import { setFDListSelected } from '../store/fdListSelectedSlice';
|
|
31
|
-
import {
|
|
32
|
-
import {
|
|
33
|
-
import {
|
|
34
|
-
import { setGlobalData
|
|
35
|
-
import { FD_STRINGS } from '../constants/strings';
|
|
36
|
-
import { base64Images } from '../constants/strings/base64Images';
|
|
37
|
-
import {
|
|
38
|
-
initializeSDK as initializeShriramSDK,
|
|
39
|
-
initializeEnvironment as initializeShriramEnvironment,
|
|
40
|
-
type AppData as ShriramAppData,
|
|
41
|
-
type EnvironmentData as ShriramEnvironmentData,
|
|
42
|
-
} from '@finspringinnovations/shriramfdsdk';
|
|
43
|
-
import {
|
|
44
|
-
initializeSDK as initializeMahindraSDK,
|
|
45
|
-
initializeEnvironment as initializeMahindraEnvironment,
|
|
46
|
-
type AppData as MahindraAppData,
|
|
47
|
-
type EnvironmentData as MahindraEnvironmentData,
|
|
48
|
-
} from '@finspringinnovations/mahindrafdsdk';
|
|
40
|
+
import { setOnboardingIds } from '../store/onboardingSlice';
|
|
41
|
+
import type { ColorScheme, ThemeName } from '../theme';
|
|
42
|
+
import { useColors, useSpacing, useTheme, useTypography } from '../theme/ThemeContext';
|
|
43
|
+
import { getGlobalData, setGlobalData } from '../utils/globalData';
|
|
49
44
|
var completeFDData: any = null;
|
|
50
45
|
|
|
51
46
|
/** Resolve company logo type for FD list card by name or provider. */
|
|
52
47
|
function getLogoTypeForFD(fd: { name?: string; providerId?: string }): 'shriram' | 'mahindra' | undefined {
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
48
|
+
const name = (fd.name || '').toLowerCase();
|
|
49
|
+
const providerId = (fd.providerId || '').toLowerCase();
|
|
50
|
+
if (name.includes('shriram') || providerId.includes('shriram')) return 'shriram';
|
|
51
|
+
if (name.includes('mahindra') || providerId.includes('mahindra') || providerId.includes('881d0b98')) return 'mahindra';
|
|
52
|
+
return undefined;
|
|
58
53
|
}
|
|
59
54
|
|
|
60
55
|
function getStaticCreditRatingForFD(fd: { name?: string; providerId?: string }): string {
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
56
|
+
const logoType = getLogoTypeForFD(fd);
|
|
57
|
+
if (logoType === 'mahindra') return 'AAA';
|
|
58
|
+
if (logoType === 'shriram') return 'AAA';
|
|
59
|
+
return 'AAA';
|
|
65
60
|
}
|
|
66
61
|
|
|
67
62
|
/** Statuses that count as pending/active (in-progress) workflow. */
|
|
68
63
|
const PENDING_ACTIVE_STATUSES = ['active', 'pending', 'in_progress', 'in-progress'];
|
|
69
64
|
|
|
70
65
|
function getSdkTypeFromProviderId(
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
66
|
+
providerId: string,
|
|
67
|
+
mahindraProviderId: string,
|
|
68
|
+
shriramProviderId: string
|
|
74
69
|
): 'mahindra' | 'shriram' | null {
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
70
|
+
const lower = (providerId || '').toLowerCase();
|
|
71
|
+
if (lower === mahindraProviderId.toLowerCase()) return 'mahindra';
|
|
72
|
+
if (lower === shriramProviderId.toLowerCase()) return 'shriram';
|
|
73
|
+
return null;
|
|
79
74
|
}
|
|
80
75
|
|
|
81
76
|
/** Get the pending/active application for a given provider, if any. */
|
|
82
77
|
function getPendingOrActiveAppForProvider(
|
|
83
|
-
|
|
84
|
-
|
|
78
|
+
applicationsData: any[],
|
|
79
|
+
providerId: string
|
|
85
80
|
): any | null {
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
81
|
+
const providerIdLower = (providerId || '').toLowerCase();
|
|
82
|
+
return applicationsData.find((a: any) => {
|
|
83
|
+
const appProviderId = (a.fd_provider_id || a.fdProviderId || a.provider_id || a.providerId || '').toLowerCase();
|
|
84
|
+
if (appProviderId !== providerIdLower) return false;
|
|
85
|
+
const s = (a.wf_status || a.status || '').toString().toLowerCase();
|
|
86
|
+
return PENDING_ACTIVE_STATUSES.includes(s);
|
|
87
|
+
}) || null;
|
|
93
88
|
}
|
|
94
89
|
|
|
95
90
|
/** Convert application to pending FD display data. */
|
|
96
91
|
function appToPendingFDData(app: any): {
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
92
|
+
name: string;
|
|
93
|
+
invested: number;
|
|
94
|
+
value: number;
|
|
95
|
+
returns: number;
|
|
96
|
+
maturityDate: string;
|
|
97
|
+
interestPayout: string;
|
|
98
|
+
tenure: string;
|
|
99
|
+
logoType?: 'shriram' | 'mahindra';
|
|
104
100
|
} {
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
101
|
+
const invested = Number(app.investment_amount ?? app.amount ?? app.investmentAmount ?? 0);
|
|
102
|
+
const rate = Number(app.interest_rate ?? app.interestRate ?? 0);
|
|
103
|
+
const value = Number(app.current_value ?? app.currentValue ?? app.maturity_amount ?? app.maturityAmount ?? 0);
|
|
104
|
+
const maturityDateStr: string = app.maturity_date || app.maturityDate || '';
|
|
105
|
+
const tenure: string = Number(app.tenure_in_months) ? app.tenure_in_months + " Months" : '';
|
|
106
|
+
let maturityDate = '--';
|
|
107
|
+
if (maturityDateStr) {
|
|
108
|
+
const d = new Date(maturityDateStr);
|
|
109
|
+
if (!isNaN(d.getTime())) {
|
|
110
|
+
const months = ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec'];
|
|
111
|
+
maturityDate = `${months[d.getMonth()]} ${d.getFullYear()}`;
|
|
112
|
+
}
|
|
113
|
+
}
|
|
114
|
+
const providerName = app.fd_provider_name || app.providerName || 'Mahindra Finance Ltd';
|
|
115
|
+
const logoType = getLogoTypeForFD({ name: providerName, providerId: app.fd_provider_id || app.fdProviderId || '' });
|
|
116
|
+
return {
|
|
117
|
+
name: providerName,
|
|
118
|
+
invested,
|
|
119
|
+
value,
|
|
120
|
+
returns: rate || 0,
|
|
121
|
+
maturityDate,
|
|
122
|
+
interestPayout: app.interest_payout_term || app.interestPayoutTerm || app.payout_term || 'Yearly',
|
|
123
|
+
logoType: logoType ?? undefined,
|
|
124
|
+
tenure: tenure
|
|
125
|
+
};
|
|
128
126
|
}
|
|
129
127
|
|
|
130
128
|
/** Resolve providerId from app payload robustly; infer from provider name when id key is missing. */
|
|
131
129
|
function resolveProviderIdFromApp(
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
130
|
+
app: any,
|
|
131
|
+
mahindraProviderId: string,
|
|
132
|
+
shriramProviderId: string
|
|
135
133
|
): string {
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
134
|
+
const direct =
|
|
135
|
+
app?.fd_provider_id ||
|
|
136
|
+
app?.fdProviderId ||
|
|
137
|
+
app?.provider_id ||
|
|
138
|
+
app?.providerId ||
|
|
139
|
+
app?.fd_provider ||
|
|
140
|
+
app?.fdProvider ||
|
|
141
|
+
app?.provider;
|
|
142
|
+
if (direct) return String(direct);
|
|
143
|
+
|
|
144
|
+
const providerName = String(
|
|
145
|
+
app?.fd_provider_name ||
|
|
146
|
+
app?.fdProviderName ||
|
|
147
|
+
app?.provider_name ||
|
|
148
|
+
app?.providerName ||
|
|
149
|
+
''
|
|
150
|
+
).toLowerCase();
|
|
151
|
+
|
|
152
|
+
if (providerName.includes('mahindra')) return mahindraProviderId;
|
|
153
|
+
if (providerName.includes('shriram')) return shriramProviderId;
|
|
154
|
+
return '';
|
|
157
155
|
}
|
|
158
156
|
|
|
159
157
|
export interface FDItem {
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
158
|
+
id: string;
|
|
159
|
+
providerId: string; // Added providerId field
|
|
160
|
+
name: string;
|
|
161
|
+
accountNumber: string;
|
|
162
|
+
roi: string;
|
|
163
|
+
tenure: string;
|
|
164
|
+
amount: number;
|
|
165
|
+
maturityDate: string;
|
|
166
|
+
status: 'active' | 'matured' | 'pending';
|
|
167
|
+
creditRating: string;
|
|
168
|
+
interestPayout?: string; // Optional interest payout field
|
|
171
169
|
}
|
|
172
170
|
|
|
173
171
|
export interface FDListProps {
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
172
|
+
onGoBack?: () => void;
|
|
173
|
+
onSelectFD?: (fdId: string) => void;
|
|
174
|
+
onNavigateToFDCalculator?: (fdData?: any, masterData?: any) => void;
|
|
175
|
+
onNavigateToExternalSDK?: (sdkType: any, fdData?: any, context?: any) => void;
|
|
176
|
+
customStyles?: {
|
|
177
|
+
container?: object;
|
|
178
|
+
header?: object;
|
|
179
|
+
title?: object;
|
|
180
|
+
fdCard?: object;
|
|
181
|
+
};
|
|
184
182
|
}
|
|
185
183
|
|
|
186
184
|
const FDList: React.FC<FDListProps> = ({
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
185
|
+
onGoBack,
|
|
186
|
+
onSelectFD,
|
|
187
|
+
onNavigateToFDCalculator,
|
|
188
|
+
onNavigateToExternalSDK,
|
|
189
|
+
customStyles = {},
|
|
192
190
|
}) => {
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
|
|
360
|
-
|
|
361
|
-
|
|
362
|
-
|
|
363
|
-
|
|
364
|
-
|
|
365
|
-
|
|
366
|
-
|
|
367
|
-
|
|
368
|
-
|
|
369
|
-
|
|
370
|
-
|
|
371
|
-
|
|
372
|
-
|
|
373
|
-
|
|
374
|
-
|
|
375
|
-
|
|
376
|
-
|
|
377
|
-
|
|
378
|
-
|
|
379
|
-
|
|
380
|
-
|
|
381
|
-
|
|
382
|
-
|
|
383
|
-
|
|
384
|
-
|
|
385
|
-
|
|
386
|
-
|
|
387
|
-
|
|
388
|
-
|
|
389
|
-
|
|
390
|
-
|
|
391
|
-
|
|
392
|
-
|
|
393
|
-
|
|
394
|
-
|
|
395
|
-
|
|
396
|
-
|
|
397
|
-
|
|
398
|
-
|
|
399
|
-
|
|
400
|
-
|
|
401
|
-
|
|
402
|
-
|
|
403
|
-
|
|
404
|
-
|
|
405
|
-
|
|
406
|
-
|
|
407
|
-
|
|
408
|
-
|
|
409
|
-
|
|
410
|
-
|
|
411
|
-
|
|
412
|
-
|
|
413
|
-
|
|
414
|
-
|
|
415
|
-
|
|
416
|
-
|
|
417
|
-
|
|
418
|
-
|
|
419
|
-
|
|
420
|
-
|
|
421
|
-
|
|
422
|
-
|
|
423
|
-
|
|
424
|
-
|
|
425
|
-
|
|
426
|
-
|
|
427
|
-
|
|
428
|
-
|
|
429
|
-
|
|
430
|
-
|
|
431
|
-
|
|
432
|
-
|
|
433
|
-
|
|
434
|
-
|
|
435
|
-
|
|
436
|
-
|
|
437
|
-
|
|
438
|
-
|
|
439
|
-
|
|
440
|
-
|
|
441
|
-
|
|
442
|
-
|
|
443
|
-
|
|
444
|
-
|
|
445
|
-
|
|
446
|
-
|
|
447
|
-
|
|
448
|
-
|
|
449
|
-
|
|
450
|
-
|
|
451
|
-
|
|
452
|
-
|
|
453
|
-
|
|
454
|
-
|
|
455
|
-
|
|
456
|
-
|
|
457
|
-
|
|
458
|
-
|
|
459
|
-
|
|
460
|
-
|
|
461
|
-
|
|
462
|
-
|
|
463
|
-
|
|
464
|
-
|
|
465
|
-
|
|
466
|
-
|
|
467
|
-
|
|
468
|
-
|
|
469
|
-
|
|
470
|
-
|
|
471
|
-
|
|
472
|
-
|
|
473
|
-
|
|
474
|
-
|
|
475
|
-
|
|
476
|
-
|
|
477
|
-
|
|
478
|
-
|
|
479
|
-
|
|
480
|
-
|
|
481
|
-
|
|
482
|
-
|
|
483
|
-
|
|
484
|
-
|
|
485
|
-
|
|
486
|
-
|
|
487
|
-
|
|
488
|
-
|
|
489
|
-
|
|
490
|
-
|
|
491
|
-
|
|
492
|
-
|
|
493
|
-
|
|
494
|
-
|
|
495
|
-
|
|
496
|
-
|
|
497
|
-
|
|
498
|
-
|
|
499
|
-
|
|
500
|
-
|
|
501
|
-
|
|
502
|
-
|
|
503
|
-
|
|
504
|
-
|
|
505
|
-
|
|
506
|
-
|
|
507
|
-
|
|
508
|
-
|
|
509
|
-
|
|
510
|
-
|
|
511
|
-
|
|
512
|
-
|
|
513
|
-
|
|
514
|
-
|
|
515
|
-
|
|
516
|
-
|
|
517
|
-
|
|
518
|
-
|
|
519
|
-
|
|
520
|
-
|
|
521
|
-
|
|
522
|
-
|
|
523
|
-
|
|
524
|
-
|
|
525
|
-
|
|
526
|
-
|
|
527
|
-
|
|
528
|
-
|
|
529
|
-
|
|
530
|
-
|
|
531
|
-
|
|
532
|
-
|
|
533
|
-
|
|
534
|
-
|
|
535
|
-
|
|
536
|
-
|
|
537
|
-
|
|
538
|
-
|
|
539
|
-
|
|
540
|
-
|
|
541
|
-
|
|
542
|
-
|
|
543
|
-
|
|
544
|
-
|
|
545
|
-
|
|
546
|
-
|
|
547
|
-
|
|
548
|
-
|
|
549
|
-
|
|
550
|
-
|
|
551
|
-
|
|
552
|
-
|
|
553
|
-
|
|
554
|
-
|
|
555
|
-
|
|
556
|
-
|
|
557
|
-
|
|
558
|
-
|
|
559
|
-
|
|
560
|
-
|
|
561
|
-
|
|
562
|
-
|
|
563
|
-
|
|
564
|
-
|
|
565
|
-
|
|
566
|
-
|
|
567
|
-
|
|
568
|
-
|
|
569
|
-
|
|
570
|
-
|
|
571
|
-
|
|
572
|
-
|
|
573
|
-
|
|
574
|
-
|
|
575
|
-
|
|
576
|
-
|
|
577
|
-
|
|
578
|
-
|
|
579
|
-
|
|
580
|
-
|
|
581
|
-
|
|
582
|
-
|
|
583
|
-
|
|
584
|
-
|
|
585
|
-
|
|
586
|
-
|
|
587
|
-
|
|
588
|
-
|
|
589
|
-
|
|
590
|
-
|
|
591
|
-
|
|
592
|
-
|
|
593
|
-
|
|
594
|
-
|
|
595
|
-
|
|
596
|
-
|
|
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
|
-
|
|
630
|
-
|
|
631
|
-
|
|
632
|
-
|
|
633
|
-
|
|
634
|
-
|
|
635
|
-
|
|
636
|
-
|
|
637
|
-
|
|
638
|
-
|
|
639
|
-
|
|
640
|
-
|
|
641
|
-
|
|
642
|
-
|
|
643
|
-
|
|
644
|
-
|
|
645
|
-
|
|
646
|
-
|
|
647
|
-
|
|
648
|
-
|
|
649
|
-
|
|
650
|
-
|
|
651
|
-
|
|
652
|
-
|
|
653
|
-
|
|
654
|
-
|
|
655
|
-
|
|
656
|
-
|
|
657
|
-
|
|
658
|
-
|
|
659
|
-
|
|
660
|
-
|
|
661
|
-
|
|
662
|
-
|
|
663
|
-
|
|
664
|
-
|
|
665
|
-
|
|
666
|
-
|
|
667
|
-
|
|
668
|
-
|
|
669
|
-
|
|
670
|
-
|
|
671
|
-
|
|
672
|
-
|
|
673
|
-
|
|
674
|
-
|
|
675
|
-
|
|
676
|
-
|
|
677
|
-
|
|
678
|
-
|
|
679
|
-
|
|
680
|
-
|
|
681
|
-
|
|
682
|
-
|
|
683
|
-
|
|
684
|
-
|
|
685
|
-
|
|
686
|
-
|
|
687
|
-
|
|
688
|
-
|
|
689
|
-
|
|
690
|
-
|
|
691
|
-
|
|
692
|
-
|
|
693
|
-
|
|
694
|
-
|
|
695
|
-
|
|
696
|
-
|
|
697
|
-
|
|
698
|
-
|
|
699
|
-
|
|
700
|
-
|
|
701
|
-
|
|
702
|
-
|
|
703
|
-
|
|
704
|
-
|
|
705
|
-
|
|
706
|
-
|
|
707
|
-
|
|
708
|
-
|
|
709
|
-
|
|
710
|
-
|
|
711
|
-
|
|
712
|
-
|
|
713
|
-
|
|
714
|
-
|
|
715
|
-
|
|
716
|
-
|
|
717
|
-
|
|
718
|
-
|
|
719
|
-
|
|
720
|
-
|
|
721
|
-
|
|
722
|
-
|
|
723
|
-
|
|
724
|
-
|
|
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
|
-
|
|
758
|
-
|
|
759
|
-
|
|
760
|
-
|
|
761
|
-
|
|
762
|
-
|
|
763
|
-
|
|
764
|
-
|
|
765
|
-
|
|
766
|
-
|
|
767
|
-
|
|
768
|
-
|
|
769
|
-
|
|
770
|
-
|
|
771
|
-
|
|
772
|
-
|
|
773
|
-
|
|
774
|
-
|
|
775
|
-
|
|
776
|
-
|
|
777
|
-
|
|
778
|
-
|
|
779
|
-
|
|
780
|
-
|
|
781
|
-
|
|
782
|
-
|
|
783
|
-
|
|
784
|
-
|
|
785
|
-
|
|
786
|
-
|
|
787
|
-
|
|
788
|
-
|
|
789
|
-
|
|
790
|
-
|
|
791
|
-
|
|
792
|
-
|
|
793
|
-
|
|
794
|
-
|
|
795
|
-
|
|
796
|
-
|
|
797
|
-
|
|
798
|
-
|
|
799
|
-
|
|
800
|
-
|
|
801
|
-
|
|
802
|
-
|
|
803
|
-
|
|
804
|
-
|
|
805
|
-
|
|
806
|
-
|
|
807
|
-
|
|
808
|
-
|
|
809
|
-
|
|
810
|
-
|
|
811
|
-
|
|
812
|
-
|
|
813
|
-
|
|
814
|
-
|
|
815
|
-
|
|
816
|
-
|
|
817
|
-
|
|
818
|
-
|
|
819
|
-
|
|
820
|
-
|
|
821
|
-
|
|
822
|
-
|
|
823
|
-
|
|
824
|
-
|
|
825
|
-
|
|
826
|
-
|
|
827
|
-
|
|
828
|
-
|
|
829
|
-
|
|
830
|
-
|
|
831
|
-
|
|
832
|
-
|
|
833
|
-
|
|
834
|
-
|
|
835
|
-
|
|
836
|
-
|
|
837
|
-
|
|
838
|
-
|
|
839
|
-
|
|
840
|
-
|
|
841
|
-
|
|
842
|
-
|
|
843
|
-
|
|
844
|
-
|
|
845
|
-
|
|
846
|
-
|
|
847
|
-
|
|
848
|
-
|
|
849
|
-
|
|
850
|
-
|
|
851
|
-
|
|
852
|
-
|
|
853
|
-
|
|
854
|
-
|
|
855
|
-
|
|
856
|
-
|
|
857
|
-
|
|
858
|
-
|
|
859
|
-
|
|
860
|
-
|
|
861
|
-
|
|
862
|
-
|
|
863
|
-
|
|
864
|
-
|
|
865
|
-
|
|
866
|
-
|
|
867
|
-
|
|
868
|
-
|
|
869
|
-
|
|
870
|
-
|
|
871
|
-
|
|
872
|
-
|
|
873
|
-
|
|
874
|
-
|
|
875
|
-
|
|
876
|
-
|
|
877
|
-
|
|
878
|
-
|
|
879
|
-
|
|
880
|
-
|
|
881
|
-
|
|
882
|
-
|
|
883
|
-
|
|
884
|
-
|
|
885
|
-
|
|
886
|
-
|
|
887
|
-
|
|
888
|
-
|
|
889
|
-
|
|
890
|
-
|
|
891
|
-
|
|
892
|
-
|
|
893
|
-
|
|
894
|
-
|
|
895
|
-
|
|
896
|
-
|
|
897
|
-
|
|
898
|
-
|
|
899
|
-
|
|
900
|
-
|
|
901
|
-
|
|
902
|
-
|
|
903
|
-
|
|
904
|
-
|
|
905
|
-
|
|
906
|
-
|
|
907
|
-
|
|
908
|
-
|
|
909
|
-
|
|
910
|
-
|
|
911
|
-
|
|
912
|
-
|
|
913
|
-
|
|
914
|
-
|
|
915
|
-
|
|
916
|
-
|
|
917
|
-
|
|
918
|
-
|
|
919
|
-
|
|
920
|
-
|
|
921
|
-
|
|
922
|
-
|
|
923
|
-
|
|
924
|
-
|
|
925
|
-
|
|
926
|
-
|
|
927
|
-
|
|
928
|
-
|
|
929
|
-
|
|
930
|
-
|
|
931
|
-
|
|
932
|
-
|
|
933
|
-
|
|
934
|
-
|
|
935
|
-
|
|
936
|
-
|
|
937
|
-
|
|
938
|
-
|
|
939
|
-
|
|
940
|
-
|
|
941
|
-
|
|
942
|
-
|
|
943
|
-
|
|
944
|
-
|
|
945
|
-
|
|
946
|
-
|
|
947
|
-
|
|
948
|
-
|
|
949
|
-
|
|
950
|
-
|
|
951
|
-
|
|
952
|
-
|
|
953
|
-
|
|
954
|
-
|
|
955
|
-
|
|
956
|
-
|
|
957
|
-
|
|
958
|
-
|
|
959
|
-
|
|
960
|
-
|
|
961
|
-
|
|
962
|
-
|
|
963
|
-
|
|
964
|
-
|
|
965
|
-
|
|
966
|
-
|
|
967
|
-
|
|
968
|
-
|
|
969
|
-
|
|
970
|
-
|
|
971
|
-
|
|
972
|
-
|
|
973
|
-
|
|
974
|
-
|
|
975
|
-
|
|
976
|
-
|
|
977
|
-
|
|
978
|
-
|
|
979
|
-
|
|
980
|
-
|
|
981
|
-
|
|
982
|
-
|
|
983
|
-
|
|
984
|
-
|
|
985
|
-
|
|
986
|
-
|
|
987
|
-
|
|
988
|
-
|
|
989
|
-
|
|
990
|
-
|
|
991
|
-
|
|
992
|
-
|
|
993
|
-
|
|
994
|
-
|
|
995
|
-
|
|
996
|
-
|
|
997
|
-
|
|
998
|
-
|
|
999
|
-
|
|
1000
|
-
|
|
1001
|
-
|
|
1002
|
-
|
|
1003
|
-
|
|
1004
|
-
|
|
1005
|
-
|
|
1006
|
-
|
|
1007
|
-
|
|
1008
|
-
|
|
1009
|
-
|
|
1010
|
-
|
|
1011
|
-
|
|
1012
|
-
|
|
1013
|
-
|
|
1014
|
-
|
|
1015
|
-
|
|
1016
|
-
|
|
1017
|
-
|
|
1018
|
-
|
|
1019
|
-
|
|
1020
|
-
|
|
1021
|
-
|
|
1022
|
-
|
|
1023
|
-
|
|
1024
|
-
|
|
1025
|
-
|
|
1026
|
-
|
|
1027
|
-
|
|
1028
|
-
|
|
1029
|
-
|
|
1030
|
-
|
|
1031
|
-
|
|
1032
|
-
|
|
1033
|
-
|
|
1034
|
-
|
|
1035
|
-
|
|
1036
|
-
|
|
1037
|
-
|
|
1038
|
-
|
|
1039
|
-
|
|
1040
|
-
|
|
1041
|
-
|
|
1042
|
-
|
|
1043
|
-
|
|
1044
|
-
|
|
1045
|
-
|
|
1046
|
-
|
|
1047
|
-
|
|
1048
|
-
|
|
1049
|
-
|
|
1050
|
-
|
|
1051
|
-
|
|
1052
|
-
|
|
1053
|
-
|
|
1054
|
-
|
|
1055
|
-
|
|
1056
|
-
|
|
1057
|
-
|
|
1058
|
-
|
|
1059
|
-
|
|
1060
|
-
|
|
1061
|
-
|
|
1062
|
-
|
|
1063
|
-
|
|
1064
|
-
|
|
1065
|
-
|
|
1066
|
-
|
|
1067
|
-
|
|
1068
|
-
|
|
1069
|
-
|
|
1070
|
-
|
|
1071
|
-
|
|
1072
|
-
|
|
1073
|
-
|
|
1074
|
-
|
|
1075
|
-
|
|
1076
|
-
|
|
1077
|
-
|
|
1078
|
-
|
|
1079
|
-
|
|
1080
|
-
|
|
1081
|
-
|
|
1082
|
-
|
|
1083
|
-
|
|
1084
|
-
|
|
1085
|
-
|
|
1086
|
-
|
|
1087
|
-
|
|
1088
|
-
|
|
1089
|
-
|
|
1090
|
-
|
|
1091
|
-
|
|
1092
|
-
|
|
1093
|
-
|
|
1094
|
-
|
|
1095
|
-
|
|
1096
|
-
|
|
1097
|
-
|
|
1098
|
-
|
|
1099
|
-
|
|
1100
|
-
|
|
1101
|
-
|
|
1102
|
-
|
|
1103
|
-
|
|
1104
|
-
|
|
1105
|
-
|
|
1106
|
-
|
|
1107
|
-
|
|
1108
|
-
|
|
1109
|
-
|
|
1110
|
-
|
|
1111
|
-
|
|
1112
|
-
|
|
1113
|
-
|
|
1114
|
-
|
|
1115
|
-
|
|
1116
|
-
|
|
1117
|
-
|
|
1118
|
-
|
|
1119
|
-
|
|
1120
|
-
|
|
1121
|
-
|
|
1122
|
-
|
|
1123
|
-
|
|
1124
|
-
|
|
1125
|
-
|
|
1126
|
-
|
|
1127
|
-
|
|
1128
|
-
|
|
1129
|
-
|
|
1130
|
-
|
|
1131
|
-
|
|
1132
|
-
|
|
1133
|
-
|
|
1134
|
-
|
|
1135
|
-
|
|
1136
|
-
|
|
1137
|
-
|
|
1138
|
-
|
|
1139
|
-
|
|
1140
|
-
|
|
1141
|
-
|
|
1142
|
-
|
|
1143
|
-
|
|
1144
|
-
|
|
1145
|
-
|
|
1146
|
-
|
|
1147
|
-
|
|
1148
|
-
|
|
1149
|
-
|
|
1150
|
-
|
|
1151
|
-
|
|
1152
|
-
|
|
1153
|
-
|
|
1154
|
-
|
|
1155
|
-
|
|
1156
|
-
|
|
1157
|
-
|
|
1158
|
-
|
|
1159
|
-
|
|
1160
|
-
|
|
1161
|
-
|
|
1162
|
-
|
|
1163
|
-
|
|
1164
|
-
|
|
1165
|
-
|
|
1166
|
-
|
|
1167
|
-
|
|
1168
|
-
|
|
1169
|
-
|
|
1170
|
-
|
|
1171
|
-
|
|
1172
|
-
|
|
1173
|
-
|
|
1174
|
-
|
|
1175
|
-
|
|
1176
|
-
|
|
1177
|
-
|
|
1178
|
-
|
|
1179
|
-
|
|
1180
|
-
|
|
1181
|
-
|
|
1182
|
-
|
|
1183
|
-
|
|
1184
|
-
|
|
1185
|
-
|
|
1186
|
-
|
|
1187
|
-
|
|
1188
|
-
|
|
1189
|
-
|
|
1190
|
-
|
|
1191
|
-
|
|
1192
|
-
|
|
1193
|
-
|
|
1194
|
-
|
|
1195
|
-
|
|
1196
|
-
|
|
1197
|
-
|
|
1198
|
-
|
|
1199
|
-
|
|
1200
|
-
|
|
1201
|
-
|
|
1202
|
-
|
|
1203
|
-
|
|
1204
|
-
|
|
1205
|
-
|
|
1206
|
-
|
|
1207
|
-
|
|
1208
|
-
|
|
1209
|
-
|
|
1210
|
-
|
|
1211
|
-
|
|
1212
|
-
|
|
1213
|
-
|
|
1214
|
-
|
|
1215
|
-
|
|
1216
|
-
|
|
1217
|
-
|
|
1218
|
-
|
|
1219
|
-
|
|
1220
|
-
|
|
1221
|
-
|
|
1222
|
-
|
|
1223
|
-
|
|
1224
|
-
|
|
1225
|
-
|
|
1226
|
-
|
|
1227
|
-
|
|
1228
|
-
|
|
1229
|
-
|
|
1230
|
-
|
|
1231
|
-
|
|
1232
|
-
|
|
1233
|
-
|
|
1234
|
-
|
|
1235
|
-
|
|
1236
|
-
|
|
1237
|
-
|
|
1238
|
-
|
|
1239
|
-
|
|
1240
|
-
|
|
1241
|
-
|
|
1242
|
-
|
|
1243
|
-
|
|
1244
|
-
|
|
1245
|
-
|
|
1246
|
-
|
|
1247
|
-
|
|
1248
|
-
|
|
1249
|
-
|
|
1250
|
-
|
|
1251
|
-
|
|
1252
|
-
|
|
1253
|
-
|
|
1254
|
-
|
|
1255
|
-
|
|
1256
|
-
|
|
1257
|
-
|
|
1258
|
-
|
|
1259
|
-
|
|
1260
|
-
|
|
1261
|
-
|
|
1262
|
-
|
|
1263
|
-
|
|
1264
|
-
|
|
1265
|
-
|
|
1266
|
-
|
|
1267
|
-
|
|
1268
|
-
|
|
1269
|
-
|
|
1270
|
-
|
|
1271
|
-
|
|
1272
|
-
|
|
1273
|
-
|
|
1274
|
-
|
|
1275
|
-
|
|
1276
|
-
|
|
1277
|
-
|
|
1278
|
-
|
|
1279
|
-
|
|
1280
|
-
|
|
1281
|
-
|
|
1282
|
-
|
|
1283
|
-
|
|
1284
|
-
|
|
1285
|
-
|
|
1286
|
-
|
|
1287
|
-
|
|
1288
|
-
|
|
1289
|
-
|
|
1290
|
-
|
|
1291
|
-
|
|
1292
|
-
|
|
1293
|
-
|
|
1294
|
-
|
|
1295
|
-
|
|
1296
|
-
|
|
1297
|
-
|
|
1298
|
-
|
|
1299
|
-
|
|
1300
|
-
|
|
1301
|
-
|
|
1302
|
-
|
|
1303
|
-
|
|
1304
|
-
|
|
1305
|
-
|
|
1306
|
-
|
|
1307
|
-
|
|
1308
|
-
|
|
1309
|
-
|
|
1310
|
-
|
|
1311
|
-
|
|
1312
|
-
|
|
1313
|
-
|
|
1314
|
-
|
|
1315
|
-
|
|
1316
|
-
|
|
1317
|
-
|
|
1318
|
-
|
|
1319
|
-
|
|
1320
|
-
|
|
1321
|
-
|
|
1322
|
-
|
|
1323
|
-
|
|
1324
|
-
|
|
1325
|
-
|
|
1326
|
-
|
|
1327
|
-
|
|
1328
|
-
|
|
1329
|
-
|
|
1330
|
-
|
|
1331
|
-
|
|
1332
|
-
|
|
1333
|
-
|
|
1334
|
-
|
|
1335
|
-
|
|
1336
|
-
|
|
1337
|
-
|
|
1338
|
-
|
|
1339
|
-
|
|
1340
|
-
|
|
1341
|
-
|
|
1342
|
-
|
|
1343
|
-
|
|
1344
|
-
|
|
1345
|
-
|
|
1346
|
-
|
|
1347
|
-
|
|
1348
|
-
|
|
1349
|
-
|
|
1350
|
-
|
|
1351
|
-
|
|
1352
|
-
|
|
1353
|
-
|
|
1354
|
-
|
|
1355
|
-
|
|
1356
|
-
|
|
1357
|
-
|
|
1358
|
-
|
|
1359
|
-
|
|
1360
|
-
|
|
1361
|
-
|
|
1362
|
-
|
|
1363
|
-
|
|
1364
|
-
|
|
1365
|
-
|
|
1366
|
-
|
|
1367
|
-
|
|
1368
|
-
|
|
1369
|
-
|
|
1370
|
-
|
|
1371
|
-
|
|
1372
|
-
|
|
1373
|
-
|
|
1374
|
-
|
|
1375
|
-
|
|
1376
|
-
|
|
1377
|
-
|
|
1378
|
-
|
|
1379
|
-
|
|
1380
|
-
|
|
1381
|
-
|
|
1382
|
-
|
|
1383
|
-
|
|
1384
|
-
|
|
1385
|
-
|
|
1386
|
-
|
|
1387
|
-
|
|
1388
|
-
|
|
1389
|
-
|
|
1390
|
-
|
|
1391
|
-
|
|
1392
|
-
|
|
1393
|
-
|
|
1394
|
-
|
|
1395
|
-
|
|
1396
|
-
|
|
1397
|
-
|
|
1398
|
-
|
|
1399
|
-
|
|
1400
|
-
|
|
1401
|
-
|
|
1402
|
-
|
|
1403
|
-
|
|
1404
|
-
|
|
1405
|
-
|
|
1406
|
-
|
|
1407
|
-
|
|
1408
|
-
|
|
1409
|
-
|
|
1410
|
-
|
|
1411
|
-
|
|
1412
|
-
|
|
1413
|
-
|
|
1414
|
-
|
|
1415
|
-
|
|
1416
|
-
|
|
1417
|
-
|
|
1418
|
-
|
|
1419
|
-
|
|
1420
|
-
|
|
1421
|
-
|
|
1422
|
-
|
|
1423
|
-
|
|
1424
|
-
|
|
1425
|
-
|
|
1426
|
-
|
|
1427
|
-
|
|
1428
|
-
|
|
1429
|
-
|
|
1430
|
-
|
|
1431
|
-
|
|
1432
|
-
|
|
1433
|
-
|
|
1434
|
-
|
|
1435
|
-
|
|
1436
|
-
|
|
1437
|
-
|
|
1438
|
-
|
|
1439
|
-
|
|
1440
|
-
|
|
1441
|
-
|
|
1442
|
-
|
|
1443
|
-
|
|
1444
|
-
|
|
1445
|
-
|
|
1446
|
-
|
|
1447
|
-
|
|
1448
|
-
|
|
1449
|
-
|
|
1450
|
-
|
|
1451
|
-
|
|
1452
|
-
|
|
1453
|
-
|
|
1454
|
-
|
|
1455
|
-
|
|
1456
|
-
|
|
1457
|
-
|
|
1458
|
-
|
|
1459
|
-
|
|
1460
|
-
|
|
1461
|
-
|
|
1462
|
-
|
|
1463
|
-
|
|
1464
|
-
|
|
1465
|
-
|
|
1466
|
-
|
|
1467
|
-
|
|
1468
|
-
|
|
1469
|
-
|
|
1470
|
-
|
|
1471
|
-
|
|
1472
|
-
|
|
1473
|
-
|
|
1474
|
-
|
|
1475
|
-
|
|
1476
|
-
|
|
1477
|
-
|
|
1478
|
-
|
|
1479
|
-
|
|
1480
|
-
|
|
1481
|
-
|
|
1482
|
-
|
|
1483
|
-
|
|
1484
|
-
|
|
1485
|
-
|
|
1486
|
-
|
|
1487
|
-
|
|
1488
|
-
|
|
1489
|
-
|
|
1490
|
-
|
|
1491
|
-
|
|
1492
|
-
|
|
1493
|
-
|
|
1494
|
-
|
|
1495
|
-
|
|
1496
|
-
|
|
1497
|
-
|
|
1498
|
-
|
|
1499
|
-
|
|
1500
|
-
|
|
1501
|
-
|
|
1502
|
-
|
|
1503
|
-
|
|
1504
|
-
|
|
1505
|
-
|
|
1506
|
-
|
|
1507
|
-
|
|
1508
|
-
|
|
1509
|
-
|
|
1510
|
-
|
|
1511
|
-
|
|
1512
|
-
|
|
1513
|
-
|
|
1514
|
-
|
|
1515
|
-
|
|
1516
|
-
|
|
1517
|
-
|
|
1518
|
-
|
|
1519
|
-
|
|
1520
|
-
|
|
1521
|
-
|
|
1522
|
-
|
|
1523
|
-
|
|
1524
|
-
|
|
1525
|
-
|
|
1526
|
-
|
|
1527
|
-
|
|
1528
|
-
|
|
1529
|
-
|
|
1530
|
-
|
|
1531
|
-
|
|
1532
|
-
|
|
1533
|
-
|
|
1534
|
-
|
|
1535
|
-
|
|
1536
|
-
|
|
1537
|
-
|
|
1538
|
-
|
|
1539
|
-
|
|
1540
|
-
|
|
1541
|
-
|
|
1542
|
-
|
|
1543
|
-
|
|
1544
|
-
|
|
1545
|
-
|
|
1546
|
-
|
|
1547
|
-
|
|
1548
|
-
|
|
1549
|
-
|
|
1550
|
-
|
|
1551
|
-
|
|
1552
|
-
|
|
1553
|
-
|
|
1554
|
-
|
|
1555
|
-
|
|
1556
|
-
|
|
1557
|
-
|
|
1558
|
-
|
|
1559
|
-
|
|
1560
|
-
|
|
1561
|
-
|
|
1562
|
-
|
|
1563
|
-
|
|
1564
|
-
|
|
1565
|
-
|
|
1566
|
-
|
|
1567
|
-
|
|
1568
|
-
|
|
1569
|
-
|
|
1570
|
-
|
|
1571
|
-
|
|
1572
|
-
|
|
1573
|
-
|
|
1574
|
-
|
|
1575
|
-
|
|
1576
|
-
|
|
1577
|
-
|
|
1578
|
-
|
|
1579
|
-
|
|
1580
|
-
|
|
1581
|
-
|
|
1582
|
-
|
|
1583
|
-
|
|
1584
|
-
|
|
1585
|
-
|
|
1586
|
-
|
|
1587
|
-
|
|
1588
|
-
|
|
1589
|
-
|
|
1590
|
-
|
|
1591
|
-
|
|
1592
|
-
|
|
1593
|
-
|
|
1594
|
-
|
|
1595
|
-
|
|
1596
|
-
|
|
1597
|
-
|
|
1598
|
-
|
|
1599
|
-
|
|
1600
|
-
|
|
1601
|
-
|
|
1602
|
-
|
|
1603
|
-
|
|
1604
|
-
|
|
1605
|
-
|
|
1606
|
-
|
|
1607
|
-
|
|
1608
|
-
|
|
1609
|
-
|
|
1610
|
-
|
|
1611
|
-
|
|
1612
|
-
|
|
1613
|
-
|
|
1614
|
-
|
|
1615
|
-
|
|
1616
|
-
|
|
1617
|
-
|
|
1618
|
-
|
|
1619
|
-
|
|
1620
|
-
|
|
1621
|
-
|
|
1622
|
-
|
|
1623
|
-
|
|
1624
|
-
|
|
1625
|
-
|
|
1626
|
-
|
|
1627
|
-
|
|
1628
|
-
|
|
1629
|
-
|
|
1630
|
-
|
|
1631
|
-
|
|
1632
|
-
|
|
1633
|
-
|
|
1634
|
-
|
|
1635
|
-
|
|
1636
|
-
|
|
1637
|
-
|
|
1638
|
-
|
|
1639
|
-
|
|
1640
|
-
|
|
1641
|
-
|
|
1642
|
-
|
|
1643
|
-
|
|
1644
|
-
|
|
1645
|
-
|
|
1646
|
-
|
|
1647
|
-
|
|
1648
|
-
|
|
1649
|
-
|
|
1650
|
-
|
|
1651
|
-
|
|
1652
|
-
|
|
1653
|
-
|
|
1654
|
-
|
|
1655
|
-
|
|
1656
|
-
|
|
1657
|
-
|
|
1658
|
-
|
|
1659
|
-
|
|
1660
|
-
|
|
1661
|
-
|
|
1662
|
-
|
|
1663
|
-
|
|
1664
|
-
|
|
1665
|
-
|
|
1666
|
-
|
|
1667
|
-
|
|
1668
|
-
|
|
1669
|
-
|
|
1670
|
-
|
|
1671
|
-
|
|
1672
|
-
|
|
1673
|
-
|
|
1674
|
-
|
|
1675
|
-
|
|
1676
|
-
|
|
1677
|
-
|
|
1678
|
-
|
|
1679
|
-
|
|
1680
|
-
|
|
1681
|
-
|
|
1682
|
-
|
|
1683
|
-
|
|
1684
|
-
|
|
1685
|
-
|
|
1686
|
-
|
|
1687
|
-
|
|
1688
|
-
|
|
1689
|
-
|
|
1690
|
-
|
|
1691
|
-
|
|
1692
|
-
|
|
1693
|
-
|
|
1694
|
-
|
|
1695
|
-
|
|
1696
|
-
|
|
1697
|
-
|
|
1698
|
-
|
|
1699
|
-
|
|
1700
|
-
|
|
1701
|
-
|
|
1702
|
-
|
|
1703
|
-
|
|
1704
|
-
|
|
1705
|
-
|
|
1706
|
-
|
|
1707
|
-
|
|
1708
|
-
|
|
1709
|
-
|
|
1710
|
-
|
|
1711
|
-
|
|
1712
|
-
|
|
1713
|
-
|
|
1714
|
-
|
|
1715
|
-
|
|
1716
|
-
|
|
1717
|
-
|
|
1718
|
-
|
|
1719
|
-
|
|
1720
|
-
|
|
1721
|
-
|
|
1722
|
-
|
|
1723
|
-
|
|
1724
|
-
|
|
1725
|
-
|
|
1726
|
-
|
|
1727
|
-
|
|
1728
|
-
|
|
1729
|
-
|
|
1730
|
-
|
|
1731
|
-
|
|
1732
|
-
|
|
1733
|
-
|
|
1734
|
-
|
|
1735
|
-
|
|
1736
|
-
|
|
1737
|
-
|
|
1738
|
-
|
|
1739
|
-
|
|
1740
|
-
|
|
1741
|
-
|
|
1742
|
-
|
|
1743
|
-
|
|
1744
|
-
|
|
1745
|
-
|
|
1746
|
-
|
|
1747
|
-
|
|
1748
|
-
|
|
1749
|
-
|
|
1750
|
-
|
|
1751
|
-
|
|
1752
|
-
|
|
1753
|
-
|
|
1754
|
-
|
|
1755
|
-
|
|
1756
|
-
|
|
1757
|
-
|
|
1758
|
-
|
|
1759
|
-
|
|
1760
|
-
|
|
1761
|
-
|
|
1762
|
-
|
|
1763
|
-
|
|
1764
|
-
|
|
1765
|
-
|
|
1766
|
-
|
|
1767
|
-
|
|
1768
|
-
|
|
1769
|
-
|
|
1770
|
-
|
|
1771
|
-
|
|
1772
|
-
|
|
1773
|
-
|
|
1774
|
-
|
|
1775
|
-
|
|
1776
|
-
|
|
1777
|
-
|
|
1778
|
-
|
|
1779
|
-
|
|
1780
|
-
|
|
1781
|
-
|
|
1782
|
-
|
|
1783
|
-
|
|
1784
|
-
|
|
1785
|
-
|
|
1786
|
-
|
|
1787
|
-
|
|
1788
|
-
|
|
1789
|
-
|
|
1790
|
-
|
|
1791
|
-
|
|
1792
|
-
|
|
1793
|
-
|
|
1794
|
-
|
|
1795
|
-
|
|
1796
|
-
|
|
1797
|
-
|
|
1798
|
-
|
|
1799
|
-
|
|
1800
|
-
|
|
1801
|
-
|
|
1802
|
-
|
|
1803
|
-
|
|
1804
|
-
|
|
1805
|
-
|
|
1806
|
-
|
|
1807
|
-
|
|
1808
|
-
|
|
1809
|
-
|
|
1810
|
-
|
|
1811
|
-
|
|
1812
|
-
|
|
1813
|
-
|
|
1814
|
-
|
|
1815
|
-
|
|
1816
|
-
|
|
1817
|
-
|
|
1818
|
-
|
|
1819
|
-
|
|
1820
|
-
|
|
1821
|
-
|
|
1822
|
-
|
|
1823
|
-
|
|
1824
|
-
|
|
1825
|
-
|
|
1826
|
-
|
|
1827
|
-
|
|
1828
|
-
|
|
1829
|
-
|
|
1830
|
-
|
|
1831
|
-
|
|
1832
|
-
|
|
1833
|
-
|
|
1834
|
-
|
|
1835
|
-
|
|
1836
|
-
|
|
1837
|
-
|
|
1838
|
-
|
|
1839
|
-
|
|
1840
|
-
|
|
1841
|
-
|
|
1842
|
-
|
|
1843
|
-
|
|
1844
|
-
|
|
1845
|
-
|
|
1846
|
-
|
|
1847
|
-
|
|
1848
|
-
|
|
1849
|
-
|
|
1850
|
-
|
|
1851
|
-
|
|
1852
|
-
|
|
1853
|
-
|
|
1854
|
-
|
|
1855
|
-
|
|
1856
|
-
|
|
1857
|
-
|
|
1858
|
-
|
|
1859
|
-
|
|
1860
|
-
|
|
1861
|
-
|
|
1862
|
-
|
|
1863
|
-
|
|
1864
|
-
|
|
1865
|
-
|
|
1866
|
-
|
|
1867
|
-
|
|
1868
|
-
|
|
1869
|
-
|
|
1870
|
-
|
|
1871
|
-
|
|
1872
|
-
|
|
1873
|
-
|
|
1874
|
-
|
|
1875
|
-
|
|
1876
|
-
|
|
1877
|
-
|
|
1878
|
-
|
|
1879
|
-
|
|
1880
|
-
|
|
1881
|
-
|
|
1882
|
-
|
|
1883
|
-
|
|
1884
|
-
|
|
1885
|
-
|
|
1886
|
-
|
|
1887
|
-
|
|
1888
|
-
|
|
1889
|
-
|
|
1890
|
-
|
|
1891
|
-
|
|
1892
|
-
|
|
1893
|
-
|
|
1894
|
-
|
|
1895
|
-
|
|
1896
|
-
|
|
1897
|
-
|
|
1898
|
-
|
|
1899
|
-
|
|
1900
|
-
|
|
1901
|
-
|
|
1902
|
-
|
|
1903
|
-
|
|
1904
|
-
|
|
1905
|
-
|
|
1906
|
-
|
|
1907
|
-
|
|
1908
|
-
|
|
1909
|
-
|
|
1910
|
-
|
|
1911
|
-
|
|
1912
|
-
|
|
1913
|
-
|
|
1914
|
-
|
|
1915
|
-
|
|
1916
|
-
|
|
1917
|
-
|
|
1918
|
-
|
|
1919
|
-
|
|
1920
|
-
|
|
1921
|
-
|
|
1922
|
-
|
|
1923
|
-
|
|
1924
|
-
|
|
1925
|
-
|
|
1926
|
-
|
|
1927
|
-
|
|
1928
|
-
|
|
1929
|
-
|
|
1930
|
-
|
|
1931
|
-
|
|
1932
|
-
|
|
1933
|
-
|
|
1934
|
-
|
|
1935
|
-
|
|
1936
|
-
|
|
1937
|
-
|
|
1938
|
-
|
|
1939
|
-
|
|
1940
|
-
|
|
1941
|
-
|
|
1942
|
-
|
|
1943
|
-
|
|
1944
|
-
|
|
1945
|
-
|
|
1946
|
-
|
|
1947
|
-
|
|
1948
|
-
|
|
1949
|
-
|
|
1950
|
-
|
|
1951
|
-
|
|
1952
|
-
|
|
1953
|
-
|
|
1954
|
-
|
|
1955
|
-
|
|
1956
|
-
|
|
1957
|
-
|
|
1958
|
-
|
|
1959
|
-
|
|
1960
|
-
|
|
1961
|
-
|
|
1962
|
-
|
|
1963
|
-
|
|
1964
|
-
|
|
1965
|
-
|
|
1966
|
-
|
|
1967
|
-
|
|
1968
|
-
|
|
1969
|
-
|
|
1970
|
-
|
|
1971
|
-
|
|
1972
|
-
|
|
1973
|
-
|
|
1974
|
-
|
|
1975
|
-
|
|
1976
|
-
|
|
1977
|
-
|
|
1978
|
-
|
|
1979
|
-
|
|
1980
|
-
|
|
1981
|
-
|
|
1982
|
-
|
|
1983
|
-
|
|
1984
|
-
|
|
1985
|
-
|
|
1986
|
-
|
|
1987
|
-
|
|
1988
|
-
|
|
1989
|
-
|
|
1990
|
-
|
|
1991
|
-
|
|
1992
|
-
|
|
1993
|
-
|
|
1994
|
-
|
|
1995
|
-
|
|
1996
|
-
|
|
1997
|
-
|
|
1998
|
-
|
|
1999
|
-
|
|
2000
|
-
|
|
2001
|
-
|
|
2002
|
-
|
|
2003
|
-
|
|
2004
|
-
|
|
2005
|
-
|
|
2006
|
-
|
|
2007
|
-
|
|
2008
|
-
|
|
2009
|
-
|
|
2010
|
-
|
|
2011
|
-
|
|
2012
|
-
|
|
2013
|
-
|
|
2014
|
-
|
|
2015
|
-
|
|
2016
|
-
|
|
2017
|
-
|
|
2018
|
-
|
|
2019
|
-
|
|
2020
|
-
|
|
2021
|
-
|
|
2022
|
-
|
|
2023
|
-
|
|
2024
|
-
|
|
2025
|
-
|
|
191
|
+
const [activeTab, setActiveTab] = useState < string > (FD_STRINGS.ALL_FDS_TAB);
|
|
192
|
+
const [showPendingFDBottomSheet, setShowPendingFDBottomSheet] = useState(false);
|
|
193
|
+
const [selectedFD, setSelectedFD] = useState < FDItem | null > (null);
|
|
194
|
+
/** Application for which the pending bottom sheet is shown (matches the FD list card provider they tapped). Used for terminate/continue. */
|
|
195
|
+
const [pendingContextApp, setPendingContextApp] = useState < any > (null);
|
|
196
|
+
const [isInitialized, setIsInitialized] = useState(false);
|
|
197
|
+
/** Loading state for Mahindra customer/application/details prefetch (used for pending FD continue). */
|
|
198
|
+
const [isLoadingMahindraCustomerDetails, setIsLoadingMahindraCustomerDetails] = useState(false);
|
|
199
|
+
/** True while handlePendingFDContinue is in-flight (tap → navigate). Blocks the UI with a loader. */
|
|
200
|
+
const [isPendingFDLoading, setIsPendingFDLoading] = useState(false);
|
|
201
|
+
const colors = useColors();
|
|
202
|
+
const typography = useTypography();
|
|
203
|
+
const spacing = useSpacing();
|
|
204
|
+
const { themeName } = useTheme();
|
|
205
|
+
const dispatch = useAppDispatch();
|
|
206
|
+
const hasFetchedRatesRef = React.useRef(false);
|
|
207
|
+
const isCallingInterestRatesRef = React.useRef(false);
|
|
208
|
+
const MahindraProviderId = '881d0b98-78d7-4668-931c-f4f47d753e9d';
|
|
209
|
+
const ShriramProviderId = '92d94e74-c5cb-4141-91ad-ffa05df7fbff';
|
|
210
|
+
|
|
211
|
+
// API calls to fetch
|
|
212
|
+
const [getInterestRates, {
|
|
213
|
+
data: interestRates,
|
|
214
|
+
error: interestRatesError,
|
|
215
|
+
isLoading: isLoadingRates,
|
|
216
|
+
}] = useGetInterestRatesMutation();
|
|
217
|
+
|
|
218
|
+
const [getCustomerApplications, {
|
|
219
|
+
data: customerApplications,
|
|
220
|
+
error: customerApplicationsError,
|
|
221
|
+
isLoading: isLoadingApplications,
|
|
222
|
+
}] = useGetCustomerApplicationsMutation();
|
|
223
|
+
const [getCustomerApplicationDetails] = useGetCustomerApplicationDetailsMutation();
|
|
224
|
+
|
|
225
|
+
const [terminateWorkflow, {
|
|
226
|
+
data: terminateWorkflowData,
|
|
227
|
+
error: terminateWorkflowError,
|
|
228
|
+
isLoading: isTerminatingWorkflow,
|
|
229
|
+
}] = useTerminateWorkflowMutation();
|
|
230
|
+
|
|
231
|
+
// Payment Reverse Feed API
|
|
232
|
+
const [paymentReverseFeed, {
|
|
233
|
+
data: paymentReverseFeedResponse,
|
|
234
|
+
error: paymentReverseFeedError,
|
|
235
|
+
isLoading: isLoadingPaymentReverseFeed,
|
|
236
|
+
}] = usePaymentReverseFeedMutation();
|
|
237
|
+
|
|
238
|
+
const [getPaymentUrl] = useLazyGetPaymentUrlQuery();
|
|
239
|
+
|
|
240
|
+
const styles = createStyles(colors, typography, spacing, themeName);
|
|
241
|
+
const { masterData: masterDataContext, setMasterData } = useMasterData();
|
|
242
|
+
|
|
243
|
+
// Redux selectors for workflow IDs
|
|
244
|
+
const workflowInstanceId = useAppSelector((state: any) => state?.onboarding?.workflowInstanceId);
|
|
245
|
+
const applicationId = useAppSelector((state: any) => state?.onboarding?.applicationId);
|
|
246
|
+
const entityId = useAppSelector((state: any) => state?.onboarding?.entityid);
|
|
247
|
+
const providerId = useAppSelector((state: any) => state?.onboarding?.providerId);
|
|
248
|
+
const onboardingIds = useAppSelector((state: any) => state?.onboarding);
|
|
249
|
+
|
|
250
|
+
// Shared promise ref so FDList pending-flow and eager prefetch can wait
|
|
251
|
+
// on the same Mahindra customer/application/details fetch.
|
|
252
|
+
const mahindraDetailsPrefetchPromiseRef = React.useRef < Promise < void> | null > (null);
|
|
253
|
+
|
|
254
|
+
const initializeExternalSDKFromFDList = useCallback((
|
|
255
|
+
sdkType: 'shriram' | 'mahindra',
|
|
256
|
+
options?: { silent?: boolean }
|
|
257
|
+
): boolean => {
|
|
258
|
+
const silent = options?.silent === true;
|
|
259
|
+
const currentAppData = getAppData();
|
|
260
|
+
const storedEnvData = getEnvironmentData();
|
|
261
|
+
const currentEnvData = storedEnvData as ShriramEnvironmentData & MahindraEnvironmentData | null;
|
|
262
|
+
|
|
263
|
+
if (!currentAppData) {
|
|
264
|
+
if (!silent) {
|
|
265
|
+
Alert.alert('Error', 'SDK app data not available. Please restart FD flow.');
|
|
266
|
+
}
|
|
267
|
+
return false;
|
|
268
|
+
}
|
|
269
|
+
if (!currentEnvData) {
|
|
270
|
+
if (!silent) {
|
|
271
|
+
Alert.alert('Error', 'SDK environment data not available. Please initialize environment from host app.');
|
|
272
|
+
}
|
|
273
|
+
return false;
|
|
274
|
+
}
|
|
275
|
+
|
|
276
|
+
try {
|
|
277
|
+
if (sdkType === 'shriram') {
|
|
278
|
+
initializeShriramEnvironment(currentEnvData as ShriramEnvironmentData);
|
|
279
|
+
initializeShriramSDK(currentAppData as ShriramAppData);
|
|
280
|
+
} else {
|
|
281
|
+
initializeMahindraEnvironment(currentEnvData as MahindraEnvironmentData);
|
|
282
|
+
initializeMahindraSDK(currentAppData as MahindraAppData);
|
|
283
|
+
}
|
|
284
|
+
return true;
|
|
285
|
+
} catch (error: any) {
|
|
286
|
+
if (!silent) {
|
|
287
|
+
Alert.alert(
|
|
288
|
+
'Error',
|
|
289
|
+
`Failed to initialize ${sdkType === 'shriram' ? 'Shriram' : 'Mahindra'} SDK: ${error?.message || 'Unknown error'}`
|
|
290
|
+
);
|
|
291
|
+
}
|
|
292
|
+
return false;
|
|
293
|
+
}
|
|
294
|
+
}, []);
|
|
295
|
+
|
|
296
|
+
// As soon as FDList mounts, warm-initialize embedded SDKs with the same FDSDK data/env.
|
|
297
|
+
useEffect(() => {
|
|
298
|
+
initializeExternalSDKFromFDList('shriram', { silent: true });
|
|
299
|
+
initializeExternalSDKFromFDList('mahindra', { silent: true });
|
|
300
|
+
}, [initializeExternalSDKFromFDList]);
|
|
301
|
+
|
|
302
|
+
// Helper function to check if customer applications is empty
|
|
303
|
+
const isCustomerApplicationsEmpty = () => {
|
|
304
|
+
if (!customerApplications) {
|
|
305
|
+
return true;
|
|
306
|
+
}
|
|
307
|
+
|
|
308
|
+
// Handle direct array response
|
|
309
|
+
if (Array.isArray(customerApplications)) {
|
|
310
|
+
const isEmpty = customerApplications.length === 0;
|
|
311
|
+
return isEmpty;
|
|
312
|
+
}
|
|
313
|
+
|
|
314
|
+
// Handle response with data property
|
|
315
|
+
if (customerApplications.data && Array.isArray(customerApplications.data)) {
|
|
316
|
+
const isEmpty = customerApplications.data.length === 0;
|
|
317
|
+
return isEmpty;
|
|
318
|
+
}
|
|
319
|
+
|
|
320
|
+
// Handle response with applications property
|
|
321
|
+
if (customerApplications.applications && Array.isArray(customerApplications.applications)) {
|
|
322
|
+
const isEmpty = customerApplications.applications.length === 0;
|
|
323
|
+
return isEmpty;
|
|
324
|
+
}
|
|
325
|
+
|
|
326
|
+
// If customerApplications exists but doesn't match expected structure, consider it not empty
|
|
327
|
+
return false;
|
|
328
|
+
};
|
|
329
|
+
|
|
330
|
+
// Helper function to get provider ID from interest rates response (robust to varying shapes)
|
|
331
|
+
const getProviderIdFromInterestRates = () => {
|
|
332
|
+
try {
|
|
333
|
+
const data = interestRates?.data;
|
|
334
|
+
if (!data) return undefined;
|
|
335
|
+
|
|
336
|
+
const extractId = (rate: any) => {
|
|
337
|
+
return (
|
|
338
|
+
rate?.providerId ||
|
|
339
|
+
rate?.provider_id ||
|
|
340
|
+
rate?.fd_provider_id ||
|
|
341
|
+
rate?.fdProviderId ||
|
|
342
|
+
rate?.provider?.id ||
|
|
343
|
+
undefined
|
|
344
|
+
);
|
|
345
|
+
};
|
|
346
|
+
|
|
347
|
+
// Prefer SDR
|
|
348
|
+
const sdr = Array.isArray(data?.sdrScheme) ? data.sdrScheme : [];
|
|
349
|
+
for (const r of sdr) {
|
|
350
|
+
const id = extractId(r);
|
|
351
|
+
if (id) {
|
|
352
|
+
return id;
|
|
353
|
+
}
|
|
354
|
+
}
|
|
355
|
+
|
|
356
|
+
// Fallback to FDR
|
|
357
|
+
const fdr = Array.isArray(data?.fdrScheme) ? data.fdrScheme : [];
|
|
358
|
+
for (const r of fdr) {
|
|
359
|
+
const id = extractId(r);
|
|
360
|
+
if (id) {
|
|
361
|
+
return id;
|
|
362
|
+
}
|
|
363
|
+
}
|
|
364
|
+
|
|
365
|
+
return undefined;
|
|
366
|
+
} catch (e) {
|
|
367
|
+
return undefined;
|
|
368
|
+
}
|
|
369
|
+
};
|
|
370
|
+
|
|
371
|
+
/**
|
|
372
|
+
* Prefetch Mahindra customer/application/details for the currently pending/active
|
|
373
|
+
* Mahindra FD application. This is used to ensure that when we navigate into
|
|
374
|
+
* Mahindra SDK screens (especially via "Continue" on a pending FD), all
|
|
375
|
+
* customer details are already available, and we show a loader while fetching.
|
|
376
|
+
*/
|
|
377
|
+
const prefetchMahindraCustomerApplicationDetails = useCallback(async (overrideMahindraApp?: any) => {
|
|
378
|
+
// Avoid duplicate fetches – reuse in-flight promise if any
|
|
379
|
+
if (mahindraDetailsPrefetchPromiseRef.current) {
|
|
380
|
+
return mahindraDetailsPrefetchPromiseRef.current;
|
|
381
|
+
}
|
|
382
|
+
|
|
383
|
+
const promise = (async () => {
|
|
384
|
+
try {
|
|
385
|
+
let mahindraApp: any = null;
|
|
386
|
+
const overrideProviderId = (
|
|
387
|
+
overrideMahindraApp?.fd_provider_id ||
|
|
388
|
+
overrideMahindraApp?.fdProviderId ||
|
|
389
|
+
overrideMahindraApp?.provider_id ||
|
|
390
|
+
overrideMahindraApp?.providerId ||
|
|
391
|
+
''
|
|
392
|
+
).toString();
|
|
393
|
+
|
|
394
|
+
if (overrideMahindraApp && overrideProviderId.toLowerCase() === MahindraProviderId.toLowerCase()) {
|
|
395
|
+
mahindraApp = overrideMahindraApp;
|
|
396
|
+
} else {
|
|
397
|
+
if (!customerApplications || isCustomerApplicationsEmpty()) {
|
|
398
|
+
return;
|
|
399
|
+
}
|
|
400
|
+
|
|
401
|
+
// Normalize list
|
|
402
|
+
let applicationsData: any[] = [];
|
|
403
|
+
if (Array.isArray(customerApplications)) {
|
|
404
|
+
applicationsData = customerApplications;
|
|
405
|
+
} else if (customerApplications.data && Array.isArray(customerApplications.data)) {
|
|
406
|
+
applicationsData = customerApplications.data;
|
|
407
|
+
} else if (customerApplications.applications && Array.isArray(customerApplications.applications)) {
|
|
408
|
+
applicationsData = customerApplications.applications;
|
|
409
|
+
}
|
|
410
|
+
|
|
411
|
+
if (!applicationsData.length) return;
|
|
412
|
+
|
|
413
|
+
// Find Mahindra pending/active app for MahindraProviderId
|
|
414
|
+
mahindraApp = getPendingOrActiveAppForProvider(applicationsData, MahindraProviderId);
|
|
415
|
+
}
|
|
416
|
+
if (!mahindraApp) return;
|
|
417
|
+
|
|
418
|
+
const ids = {
|
|
419
|
+
workflowInstanceId:
|
|
420
|
+
mahindraApp.workflow_instance_id ||
|
|
421
|
+
mahindraApp.workflowInstanceId ||
|
|
422
|
+
mahindraApp.workflowinstanceid ||
|
|
423
|
+
mahindraApp.workflow_instance ||
|
|
424
|
+
mahindraApp.workflowInstance ||
|
|
425
|
+
undefined,
|
|
426
|
+
applicationId:
|
|
427
|
+
mahindraApp.application_id ||
|
|
428
|
+
mahindraApp.applicationId ||
|
|
429
|
+
mahindraApp.applicationid ||
|
|
430
|
+
undefined,
|
|
431
|
+
entityid:
|
|
432
|
+
mahindraApp.entity_id ||
|
|
433
|
+
mahindraApp.entityId ||
|
|
434
|
+
mahindraApp.entityid ||
|
|
435
|
+
undefined,
|
|
436
|
+
customerId:
|
|
437
|
+
mahindraApp.customer_id ||
|
|
438
|
+
mahindraApp.customerId ||
|
|
439
|
+
mahindraApp.customerid ||
|
|
440
|
+
undefined,
|
|
441
|
+
providerId:
|
|
442
|
+
mahindraApp.fd_provider_id ||
|
|
443
|
+
mahindraApp.fdProviderId ||
|
|
444
|
+
mahindraApp.provider_id ||
|
|
445
|
+
mahindraApp.providerId ||
|
|
446
|
+
MahindraProviderId,
|
|
447
|
+
};
|
|
448
|
+
|
|
449
|
+
if (!ids.applicationId || !ids.customerId || !ids.providerId) {
|
|
450
|
+
return;
|
|
451
|
+
}
|
|
452
|
+
|
|
453
|
+
setIsLoadingMahindraCustomerDetails(true);
|
|
454
|
+
|
|
455
|
+
const userInfo = getUserInfoForAPI();
|
|
456
|
+
const detailsResp = await getCustomerApplicationDetails({
|
|
457
|
+
providerId: ids.providerId,
|
|
458
|
+
applicationId: ids.applicationId,
|
|
459
|
+
customerId: ids.customerId,
|
|
460
|
+
workflowInstanceId: ids.workflowInstanceId,
|
|
461
|
+
userreferenceid: userInfo.userReferenceId,
|
|
462
|
+
applicationid: ids.applicationId,
|
|
463
|
+
entityid: ids.entityid,
|
|
464
|
+
}).unwrap();
|
|
465
|
+
|
|
466
|
+
const detailsData = (detailsResp as any)?.data || detailsResp;
|
|
467
|
+
if (detailsData) {
|
|
468
|
+
setGlobalData({ mahindraCustomerDetails: detailsData });
|
|
469
|
+
setMahindraGlobalData({ mahindraCustomerDetails: detailsData });
|
|
470
|
+
}
|
|
471
|
+
} catch (err) {
|
|
472
|
+
} finally {
|
|
473
|
+
setIsLoadingMahindraCustomerDetails(false);
|
|
474
|
+
mahindraDetailsPrefetchPromiseRef.current = null;
|
|
475
|
+
}
|
|
476
|
+
})();
|
|
477
|
+
|
|
478
|
+
mahindraDetailsPrefetchPromiseRef.current = promise;
|
|
479
|
+
return promise;
|
|
480
|
+
}, [customerApplications, getCustomerApplicationDetails]);
|
|
481
|
+
|
|
482
|
+
// Helper function to filter FDs based on tenure
|
|
483
|
+
const filterFDsByTenure = (fdList: FDItem[], filter: string): FDItem[] => {
|
|
484
|
+
if (filter === FD_STRINGS.ALL_FDS_TAB) return fdList;
|
|
485
|
+
|
|
486
|
+
return fdList.filter(fd => {
|
|
487
|
+
// Extract tenure in months from the fd.tenure string (e.g., "12 Months" -> 12)
|
|
488
|
+
const tenureMatch = fd.tenure.match(/(\d+)\s*Months?/i);
|
|
489
|
+
if (!tenureMatch) return false;
|
|
490
|
+
|
|
491
|
+
const tenureMonths = parseInt(tenureMatch[1], 10);
|
|
492
|
+
const tenureYears = tenureMonths / 12;
|
|
493
|
+
|
|
494
|
+
switch (filter) {
|
|
495
|
+
case '<1Y':
|
|
496
|
+
return tenureYears <= 1;
|
|
497
|
+
case '<1-3Y':
|
|
498
|
+
return tenureYears > 1 && tenureYears <= 3;
|
|
499
|
+
case '<3-5Y':
|
|
500
|
+
return tenureYears > 3 && tenureYears <= 5;
|
|
501
|
+
case '>5Y':
|
|
502
|
+
return tenureYears > 5;
|
|
503
|
+
default:
|
|
504
|
+
return true;
|
|
505
|
+
}
|
|
506
|
+
});
|
|
507
|
+
};
|
|
508
|
+
|
|
509
|
+
|
|
510
|
+
|
|
511
|
+
// Derive identifiers for workflow termination from applications API (for active FD/provider)
|
|
512
|
+
const terminateIdentifiers = React.useMemo(() => {
|
|
513
|
+
try {
|
|
514
|
+
if (!customerApplications || isCustomerApplicationsEmpty()) {
|
|
515
|
+
return {
|
|
516
|
+
applicationId: undefined as string | undefined,
|
|
517
|
+
workflowInstanceId: undefined as string | undefined,
|
|
518
|
+
entityId: undefined as string | undefined,
|
|
519
|
+
providerIdFromApp: undefined as string | undefined,
|
|
520
|
+
};
|
|
521
|
+
}
|
|
522
|
+
|
|
523
|
+
// Normalize list
|
|
524
|
+
let applicationsData: any[] = [];
|
|
525
|
+
if (Array.isArray(customerApplications)) {
|
|
526
|
+
applicationsData = customerApplications;
|
|
527
|
+
} else if (customerApplications.data && Array.isArray(customerApplications.data)) {
|
|
528
|
+
applicationsData = customerApplications.data;
|
|
529
|
+
} else if (customerApplications.applications && Array.isArray(customerApplications.applications)) {
|
|
530
|
+
applicationsData = customerApplications.applications;
|
|
531
|
+
}
|
|
532
|
+
|
|
533
|
+
if (applicationsData.length === 0) {
|
|
534
|
+
return {
|
|
535
|
+
applicationId: undefined,
|
|
536
|
+
workflowInstanceId: undefined,
|
|
537
|
+
entityId: undefined,
|
|
538
|
+
providerIdFromApp: undefined,
|
|
539
|
+
};
|
|
540
|
+
}
|
|
541
|
+
|
|
542
|
+
// Prefer a pending/in-progress one for termination, else first
|
|
543
|
+
const appForTerminate = applicationsData.find((a: any) => {
|
|
544
|
+
const s = (a.wf_status || a.status || '').toString().toLowerCase();
|
|
545
|
+
return s === 'pending' || s === 'in_progress' || s === 'in-progress';
|
|
546
|
+
}) || applicationsData[0];
|
|
547
|
+
|
|
548
|
+
const applicationId: string | undefined =
|
|
549
|
+
appForTerminate.application_id || appForTerminate.applicationId || appForTerminate.id;
|
|
550
|
+
const workflowInstanceId: string | undefined =
|
|
551
|
+
appForTerminate.workflow_instance_id || appForTerminate.workflowInstanceId || appForTerminate.workflow?.instanceId;
|
|
552
|
+
const entityId: string | undefined =
|
|
553
|
+
appForTerminate.entity_id || appForTerminate.entityId || appForTerminate.entity?.id;
|
|
554
|
+
const providerIdFromApp: string | undefined =
|
|
555
|
+
appForTerminate.provider_id || appForTerminate.providerId || appForTerminate.fd_provider_id || appForTerminate.fdProviderId;
|
|
556
|
+
|
|
557
|
+
return { applicationId, workflowInstanceId, entityId, providerIdFromApp };
|
|
558
|
+
} catch (e) {
|
|
559
|
+
return {
|
|
560
|
+
applicationId: undefined,
|
|
561
|
+
workflowInstanceId: undefined,
|
|
562
|
+
entityId: undefined,
|
|
563
|
+
providerIdFromApp: undefined,
|
|
564
|
+
};
|
|
565
|
+
}
|
|
566
|
+
}, [customerApplications]);
|
|
567
|
+
|
|
568
|
+
const activeProviderId = terminateIdentifiers.providerIdFromApp;
|
|
569
|
+
|
|
570
|
+
// Master data fetch - prefer tapped FD provider, then active app provider, then rates
|
|
571
|
+
const defaultProviderId = ''; // Default provider ID for initial call
|
|
572
|
+
const inferredProviderId = React.useMemo(() => {
|
|
573
|
+
if (selectedFD?.providerId) return selectedFD.providerId;
|
|
574
|
+
if (activeProviderId) return activeProviderId;
|
|
575
|
+
if (interestRates?.data?.sdrScheme?.[0]?.providerId) return interestRates.data.sdrScheme[0].providerId;
|
|
576
|
+
if (interestRates?.data?.fdrScheme?.[0]?.providerId) return interestRates.data.fdrScheme[0].providerId;
|
|
577
|
+
return defaultProviderId;
|
|
578
|
+
}, [selectedFD, activeProviderId, interestRates]);
|
|
579
|
+
|
|
580
|
+
const { data: masterData, isLoading: isLoadingMaster } = useGetMasterDataQuery(
|
|
581
|
+
{ providerId: inferredProviderId },
|
|
582
|
+
{ skip: !inferredProviderId }
|
|
583
|
+
);
|
|
584
|
+
const { data: MahindraMasterData, refetch: refetchMahindraMasterData } = useGetMasterDataQuery(
|
|
585
|
+
{ providerId: MahindraProviderId },
|
|
586
|
+
{ skip: false }
|
|
587
|
+
);
|
|
588
|
+
const { data: ShriramMasterData, refetch: refetchShriramMasterData } = useGetMasterDataQuery(
|
|
589
|
+
{ providerId: ShriramProviderId },
|
|
590
|
+
{ skip: false }
|
|
591
|
+
);
|
|
592
|
+
|
|
593
|
+
// Only render once all three API calls have completed (success or error)
|
|
594
|
+
// Show loading initially until all APIs have completed
|
|
595
|
+
const isAllDataReady = React.useMemo(() => {
|
|
596
|
+
// If not initialized yet, show loading
|
|
597
|
+
if (!isInitialized) return false;
|
|
598
|
+
|
|
599
|
+
// Step 1: Check if interest rates API has been called and completed
|
|
600
|
+
// If currently loading, show loading
|
|
601
|
+
if (isLoadingRates) return false;
|
|
602
|
+
// If not loading but no data and no error, API hasn't been called yet - show loading
|
|
603
|
+
if (!interestRates && !interestRatesError) return false;
|
|
604
|
+
|
|
605
|
+
// Step 2: Once interest rates are done, customer applications should be called
|
|
606
|
+
// If currently loading, show loading
|
|
607
|
+
if (isLoadingApplications) return false;
|
|
608
|
+
// If interest rates succeeded, we must wait for customer applications
|
|
609
|
+
// If interest rates failed, we can still proceed (but applications might not be called)
|
|
610
|
+
if (interestRates) {
|
|
611
|
+
// Interest rates succeeded, so applications should be called
|
|
612
|
+
// If not loading but no data and no error, applications haven't been called yet - show loading
|
|
613
|
+
if (!customerApplications && !customerApplicationsError) return false;
|
|
614
|
+
}
|
|
615
|
+
|
|
616
|
+
// Step 3: Check master data - only required if providerId is available
|
|
617
|
+
const masterShouldRun = !!inferredProviderId;
|
|
618
|
+
if (masterShouldRun) {
|
|
619
|
+
// Master data should be done (either loaded or error, but not loading)
|
|
620
|
+
if (isLoadingMaster) return false;
|
|
621
|
+
}
|
|
622
|
+
|
|
623
|
+
return true;
|
|
624
|
+
}, [isInitialized, interestRates, interestRatesError, isLoadingRates, customerApplications, customerApplicationsError, isLoadingApplications, inferredProviderId, isLoadingMaster]);
|
|
625
|
+
|
|
626
|
+
useEffect(() => {
|
|
627
|
+
if (masterData) {
|
|
628
|
+
setMasterData(masterData);
|
|
629
|
+
}
|
|
630
|
+
}, [masterData, setMasterData]);
|
|
631
|
+
|
|
632
|
+
// Function to refresh all data - Required sequence: Interest -> Applications -> Master
|
|
633
|
+
const refreshData = useCallback(async () => {
|
|
634
|
+
if (!isInitialized) {
|
|
635
|
+
return;
|
|
636
|
+
}
|
|
637
|
+
|
|
638
|
+
// Prevent multiple simultaneous calls
|
|
639
|
+
if (isCallingInterestRatesRef.current || isLoadingRates) {
|
|
640
|
+
return;
|
|
641
|
+
}
|
|
642
|
+
|
|
643
|
+
try {
|
|
644
|
+
isCallingInterestRatesRef.current = true;
|
|
645
|
+
// Add 500ms delay before calling interest rate API
|
|
646
|
+
await new Promise(resolve => setTimeout(resolve, 500));
|
|
647
|
+
await getInterestRates({});
|
|
648
|
+
} catch (error) {
|
|
649
|
+
// Handle error silently
|
|
650
|
+
} finally {
|
|
651
|
+
isCallingInterestRatesRef.current = false;
|
|
652
|
+
}
|
|
653
|
+
}, [getInterestRates, isInitialized, isLoadingRates]);
|
|
654
|
+
|
|
655
|
+
// Initialize component after mount
|
|
656
|
+
useEffect(() => {
|
|
657
|
+
const initializeComponent = async () => {
|
|
658
|
+
// Validate required user data before proceeding
|
|
659
|
+
const appData = getAppData();
|
|
660
|
+
|
|
661
|
+
const requiredFields = [
|
|
662
|
+
{ field: 'id', label: 'User ID' },
|
|
663
|
+
{ field: 'name', label: 'User Name' },
|
|
664
|
+
{ field: 'dob', label: 'Date of Birth' },
|
|
665
|
+
{ field: 'gender', label: 'Gender' },
|
|
666
|
+
{ field: 'mobNo', label: 'Mobile Number' },
|
|
667
|
+
{ field: 'email', label: 'Email' },
|
|
668
|
+
];
|
|
669
|
+
|
|
670
|
+
const missingFields: string[] = [];
|
|
671
|
+
|
|
672
|
+
requiredFields.forEach(({ field, label }) => {
|
|
673
|
+
const value = appData?.[field as keyof typeof appData];
|
|
674
|
+
if (!value || (typeof value === 'string' && !value.trim())) {
|
|
675
|
+
missingFields.push(label);
|
|
676
|
+
}
|
|
677
|
+
});
|
|
678
|
+
|
|
679
|
+
// Show alert if required fields are missing
|
|
680
|
+
if (missingFields.length > 0) {
|
|
681
|
+
Alert.alert(
|
|
682
|
+
'Cannot Proceed with FD Booking',
|
|
683
|
+
`The following required information is missing from the main app:\n\n${missingFields.join('\n')}\n\nPlease provide all required user information to proceed.`,
|
|
684
|
+
[
|
|
685
|
+
{
|
|
686
|
+
text: 'Cancel FD Booking',
|
|
687
|
+
onPress: () => {
|
|
688
|
+
// Redirect back to main app
|
|
689
|
+
if (onGoBack) {
|
|
690
|
+
onGoBack();
|
|
691
|
+
} else {
|
|
692
|
+
// No-op when onGoBack is not provided
|
|
693
|
+
}
|
|
694
|
+
},
|
|
695
|
+
style: 'cancel',
|
|
696
|
+
},
|
|
697
|
+
],
|
|
698
|
+
{ cancelable: false }
|
|
699
|
+
);
|
|
700
|
+
return; // Don't initialize if validation fails
|
|
701
|
+
}
|
|
702
|
+
|
|
703
|
+
// Additional value validation (case-insensitive): gender, maritalStatus, typeOfAccount
|
|
704
|
+
const errors: string[] = [];
|
|
705
|
+
|
|
706
|
+
// Gender must be Male, Female, or Other (case-insensitive)
|
|
707
|
+
const gender = String(appData?.gender || '').trim().toLowerCase();
|
|
708
|
+
const allowedGenders = ['male', 'female', 'other'];
|
|
709
|
+
if (gender && !allowedGenders.includes(gender)) {
|
|
710
|
+
errors.push("Gender must be one of: Male, Female, Other");
|
|
711
|
+
}
|
|
712
|
+
|
|
713
|
+
// Marital status must be Married, Unmarried, or Other (case-insensitive)
|
|
714
|
+
const maritalStatus = String(appData?.maritalStatus || '').trim().toLowerCase();
|
|
715
|
+
const allowedMarital = ['married', 'unmarried', 'other'];
|
|
716
|
+
if (maritalStatus && !allowedMarital.includes(maritalStatus)) {
|
|
717
|
+
errors.push("Marital Status must be one of: Married, Unmarried, Other");
|
|
718
|
+
}
|
|
719
|
+
|
|
720
|
+
// Account type must be 'Saving A/c' or 'Current A/c' (support legacy codes like SB/CA)
|
|
721
|
+
const typeOfAccountRaw = String(appData?.typeOfAccount || '').trim();
|
|
722
|
+
const normalizeAccountType = (value: string) =>
|
|
723
|
+
value.replace(/[^a-z]/gi, '').toLowerCase();
|
|
724
|
+
const accountTypeMap: Record<string, 'Saving A/c' | 'Current A/c'> = {
|
|
725
|
+
savingac: 'Saving A/c',
|
|
726
|
+
savingaccount: 'Saving A/c',
|
|
727
|
+
savingsaccount: 'Saving A/c',
|
|
728
|
+
savings: 'Saving A/c',
|
|
729
|
+
saving: 'Saving A/c',
|
|
730
|
+
sb: 'Saving A/c',
|
|
731
|
+
currentac: 'Current A/c',
|
|
732
|
+
currentaccount: 'Current A/c',
|
|
733
|
+
current: 'Current A/c',
|
|
734
|
+
ca: 'Current A/c',
|
|
735
|
+
};
|
|
736
|
+
const normalizedAccountType = normalizeAccountType(typeOfAccountRaw);
|
|
737
|
+
const canonicalAccountType = accountTypeMap[normalizedAccountType];
|
|
738
|
+
if (typeOfAccountRaw && !canonicalAccountType) {
|
|
739
|
+
errors.push("Type of Account must be one of: 'Saving A/c', 'Current A/c'");
|
|
740
|
+
}
|
|
741
|
+
|
|
742
|
+
if (errors.length > 0) {
|
|
743
|
+
Alert.alert(
|
|
744
|
+
'Invalid User Data',
|
|
745
|
+
`${errors.join('\n')}`,
|
|
746
|
+
[
|
|
747
|
+
{
|
|
748
|
+
text: 'OK',
|
|
749
|
+
onPress: () => {
|
|
750
|
+
if (onGoBack) {
|
|
751
|
+
onGoBack();
|
|
752
|
+
}
|
|
753
|
+
},
|
|
754
|
+
style: 'cancel',
|
|
755
|
+
},
|
|
756
|
+
],
|
|
757
|
+
{ cancelable: false }
|
|
758
|
+
);
|
|
759
|
+
return; // Stop initialization on invalid values
|
|
760
|
+
}
|
|
761
|
+
|
|
762
|
+
// Small delay to ensure component is fully mounted
|
|
763
|
+
await new Promise(resolve => setTimeout(resolve, 100));
|
|
764
|
+
setIsInitialized(true);
|
|
765
|
+
};
|
|
766
|
+
|
|
767
|
+
initializeComponent();
|
|
768
|
+
}, [onGoBack]);
|
|
769
|
+
|
|
770
|
+
// Removed screen-level hardware back handler to allow only header back button navigation
|
|
771
|
+
|
|
772
|
+
|
|
773
|
+
// Removed init-time fetch to avoid duplicate calls; we'll fetch on first focus only
|
|
774
|
+
|
|
775
|
+
// Refresh data when screen comes into focus (only if initialized)
|
|
776
|
+
useFocusEffect(
|
|
777
|
+
useCallback(() => {
|
|
778
|
+
if (!isInitialized) return;
|
|
779
|
+
if (hasFetchedRatesRef.current) return; // ensure called only once when screen first shows
|
|
780
|
+
// Prevent multiple simultaneous calls
|
|
781
|
+
if (isCallingInterestRatesRef.current || isLoadingRates) return;
|
|
782
|
+
hasFetchedRatesRef.current = true;
|
|
783
|
+
refreshData();
|
|
784
|
+
}, [refreshData, isInitialized, isLoadingRates])
|
|
785
|
+
);
|
|
786
|
+
|
|
787
|
+
// As soon as FDList has customer applications, eagerly prefetch Mahindra
|
|
788
|
+
// customer/application/details so that if user taps a Mahindra pending FD,
|
|
789
|
+
// details are already cached (or at least being fetched with a loader).
|
|
790
|
+
useEffect(() => {
|
|
791
|
+
if (!isInitialized) return;
|
|
792
|
+
if (!customerApplications || isCustomerApplicationsEmpty()) return;
|
|
793
|
+
prefetchMahindraCustomerApplicationDetails();
|
|
794
|
+
}, [isInitialized, customerApplications, prefetchMahindraCustomerApplicationDetails]);
|
|
795
|
+
|
|
796
|
+
// After interest rates are received, call Customer Applications
|
|
797
|
+
useEffect(() => {
|
|
798
|
+
if (!interestRates) return;
|
|
799
|
+
try {
|
|
800
|
+
const userInfo = getUserInfoForAPI();
|
|
801
|
+
getCustomerApplications({ userReferenceId: userInfo.id });
|
|
802
|
+
} catch (e) {
|
|
803
|
+
}
|
|
804
|
+
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
805
|
+
}, [!!interestRates]);
|
|
806
|
+
|
|
807
|
+
// Handle API errors
|
|
808
|
+
useEffect(() => {
|
|
809
|
+
if (interestRatesError) {
|
|
810
|
+
Alert.alert(
|
|
811
|
+
'API Error',
|
|
812
|
+
'Failed to fetch interest rates. Please try again.',
|
|
813
|
+
[
|
|
814
|
+
{
|
|
815
|
+
text: 'Retry',
|
|
816
|
+
onPress: async () => {
|
|
817
|
+
// Prevent multiple simultaneous calls
|
|
818
|
+
if (isCallingInterestRatesRef.current || isLoadingRates) {
|
|
819
|
+
return;
|
|
820
|
+
}
|
|
821
|
+
try {
|
|
822
|
+
isCallingInterestRatesRef.current = true;
|
|
823
|
+
// Add 500ms delay before retrying interest rate API
|
|
824
|
+
await new Promise(resolve => setTimeout(resolve, 500));
|
|
825
|
+
await getInterestRates({});
|
|
826
|
+
} catch (error) {
|
|
827
|
+
// Handle error silently
|
|
828
|
+
} finally {
|
|
829
|
+
isCallingInterestRatesRef.current = false;
|
|
830
|
+
}
|
|
831
|
+
}
|
|
832
|
+
},
|
|
833
|
+
{ text: 'Continue', style: 'cancel' }
|
|
834
|
+
]
|
|
835
|
+
);
|
|
836
|
+
}
|
|
837
|
+
}, [interestRatesError, getInterestRates]);
|
|
838
|
+
|
|
839
|
+
// Log successful data fetch
|
|
840
|
+
useEffect(() => {
|
|
841
|
+
if (interestRates && interestRates.data?.sdrScheme?.length > 0) {
|
|
842
|
+
// Interest rates loaded successfully
|
|
843
|
+
}
|
|
844
|
+
}, [interestRates]);
|
|
845
|
+
|
|
846
|
+
// Persist providerId to onboarding store as soon as we have rates
|
|
847
|
+
// useEffect(() => {
|
|
848
|
+
// const pid = getProviderIdFromInterestRates();
|
|
849
|
+
// if (pid) {
|
|
850
|
+
// try {
|
|
851
|
+
// dispatch(setOnboardingIds({ providerId: pid }));
|
|
852
|
+
// } catch (e) {
|
|
853
|
+
// // Handle error silently
|
|
854
|
+
// }
|
|
855
|
+
// }
|
|
856
|
+
// }, [interestRates, dispatch]);
|
|
857
|
+
|
|
858
|
+
// useEffect(() => {
|
|
859
|
+
// if (customerApplications) {
|
|
860
|
+
// // Customer applications loaded successfully
|
|
861
|
+
|
|
862
|
+
// // Persist onboarding identifiers globally for subsequent API calls (like FDCalculator)
|
|
863
|
+
// try {
|
|
864
|
+
// // Extract workflow parameters from response
|
|
865
|
+
// const responseData = customerApplications?.data || customerApplications;
|
|
866
|
+
// let applicationData = Array.isArray(responseData) ? responseData[0] : responseData;
|
|
867
|
+
|
|
868
|
+
// // Prefer the application with wf_status === 'Active'
|
|
869
|
+
// if (Array.isArray(responseData)) {
|
|
870
|
+
// const activeOnly = responseData.find((app: any) => {
|
|
871
|
+
// const status = (app.wf_status || app.status || '').toString();
|
|
872
|
+
// return status === 'Active';
|
|
873
|
+
// });
|
|
874
|
+
// if (activeOnly) applicationData = activeOnly;
|
|
875
|
+
// }
|
|
876
|
+
|
|
877
|
+
// if (Array.isArray(responseData)) {
|
|
878
|
+
// completeFDData = responseData.find((app: any) => {
|
|
879
|
+
// const status = (app.wf_status || app.status || '').toString();
|
|
880
|
+
// return status === 'Completed';
|
|
881
|
+
// });
|
|
882
|
+
// setGlobalData({ completeFDData: !!completeFDData });
|
|
883
|
+
// }
|
|
884
|
+
// if (applicationData) {
|
|
885
|
+
// const ids = {
|
|
886
|
+
// workflowInstanceId: applicationData.workflow_instance_id,
|
|
887
|
+
// applicationId: applicationData.application_id,
|
|
888
|
+
// entityid: applicationData.entity_id,
|
|
889
|
+
// customerId: applicationData.customer_id,
|
|
890
|
+
// fdId: applicationData.fd_id,
|
|
891
|
+
// currentState: applicationData.current_state,
|
|
892
|
+
// currentTask: applicationData.current_task,
|
|
893
|
+
// // Persist providerId from interest-rate API (prefers SDR, fallback FDR)
|
|
894
|
+
// providerId: getProviderIdFromInterestRates(),
|
|
895
|
+
// wfStatus: applicationData.wf_status,
|
|
896
|
+
// };
|
|
897
|
+
// if (dispatch && setOnboardingIds) {
|
|
898
|
+
// dispatch(setOnboardingIds(ids));
|
|
899
|
+
// } else {
|
|
900
|
+
// // Dispatch or setOnboardingIds unavailable
|
|
901
|
+
// }
|
|
902
|
+
// }
|
|
903
|
+
// } catch (error) {
|
|
904
|
+
// // Handle error silently
|
|
905
|
+
// }
|
|
906
|
+
// }
|
|
907
|
+
// }, [customerApplications, dispatch]);
|
|
908
|
+
|
|
909
|
+
// Unified handler: behave like bottom sheet Continue flow
|
|
910
|
+
const handlePendingFDContinue = async (
|
|
911
|
+
overrideApp?: any,
|
|
912
|
+
forcedSdkType?: 'mahindra' | 'shriram'
|
|
913
|
+
) => {
|
|
914
|
+
setIsPendingFDLoading(true);
|
|
915
|
+
try {
|
|
916
|
+
// Get current state from customer applications for workflow navigation
|
|
917
|
+
let currentStateCaption: string = "";
|
|
918
|
+
let transactionId: string | undefined = undefined;
|
|
919
|
+
let appData: any = overrideApp || pendingContextApp;
|
|
920
|
+
|
|
921
|
+
let fdDisplay: ReturnType<typeof appToPendingFDData> | null = null;
|
|
922
|
+
let onboardingIdsFromApp: any = null;
|
|
923
|
+
|
|
924
|
+
try {
|
|
925
|
+
if (!appData && customerApplications && !isCustomerApplicationsEmpty()) {
|
|
926
|
+
// Normalize list
|
|
927
|
+
let applicationsData: any[] = [];
|
|
928
|
+
if (Array.isArray(customerApplications)) {
|
|
929
|
+
applicationsData = customerApplications;
|
|
930
|
+
} else if (customerApplications.data && Array.isArray(customerApplications.data)) {
|
|
931
|
+
applicationsData = customerApplications.data;
|
|
932
|
+
} else if (customerApplications.applications && Array.isArray(customerApplications.applications)) {
|
|
933
|
+
applicationsData = customerApplications.applications;
|
|
934
|
+
}
|
|
935
|
+
|
|
936
|
+
if (applicationsData.length > 0) {
|
|
937
|
+
// Fallback: find first Active application when no override/pendingContext
|
|
938
|
+
appData = applicationsData.find((a: any) => {
|
|
939
|
+
const s = (a.wf_status || a.status || '').toString();
|
|
940
|
+
return s === 'Active';
|
|
941
|
+
}) || applicationsData.find((a: any) => {
|
|
942
|
+
const s = (a.wf_status || a.status || '').toString().toLowerCase();
|
|
943
|
+
return PENDING_ACTIVE_STATUSES.includes(s);
|
|
944
|
+
}) || applicationsData[0];
|
|
945
|
+
}
|
|
946
|
+
}
|
|
947
|
+
if (appData) {
|
|
948
|
+
currentStateCaption = appData.current_state_caption;
|
|
949
|
+
transactionId = appData.transaction_id || appData.transactionId || appData.Transactionid || appData.TransactionId;
|
|
950
|
+
fdDisplay = appToPendingFDData(appData);
|
|
951
|
+
let providerIdFromApp = resolveProviderIdFromApp(appData, MahindraProviderId, ShriramProviderId);
|
|
952
|
+
if (forcedSdkType === 'mahindra') {
|
|
953
|
+
providerIdFromApp = MahindraProviderId;
|
|
954
|
+
} else if (forcedSdkType === 'shriram') {
|
|
955
|
+
providerIdFromApp = ShriramProviderId;
|
|
956
|
+
}
|
|
957
|
+
const providerIdLower = (providerIdFromApp || '').toLowerCase();
|
|
958
|
+
const isMahindra = providerIdLower === MahindraProviderId.toLowerCase();
|
|
959
|
+
|
|
960
|
+
// For Mahindra flows, ensure customer/application/details are fully loaded
|
|
961
|
+
// before navigating into ExternalSDK so downstream screens see complete
|
|
962
|
+
// nominee/bank/KYC/guardian data. Show a loader while we wait.
|
|
963
|
+
if (isMahindra) {
|
|
964
|
+
await prefetchMahindraCustomerApplicationDetails(appData);
|
|
965
|
+
}
|
|
966
|
+
|
|
967
|
+
console.log("fdDisplay===>", fdDisplay);
|
|
968
|
+
|
|
969
|
+
try {
|
|
970
|
+
const fdListSelectedData = {
|
|
971
|
+
id: appData.fd_id || appData.fdId || 'active-fd',
|
|
972
|
+
providerId: providerIdFromApp,
|
|
973
|
+
name: fdDisplay.name,
|
|
974
|
+
accountNumber: appData.account_number || appData.accountNumber || '',
|
|
975
|
+
roi: `${fdDisplay.returns}% p.a.`,
|
|
976
|
+
tenure: fdDisplay.tenure || '-',
|
|
977
|
+
amount: Number(fdDisplay.invested) || 0,
|
|
978
|
+
maturityDate: fdDisplay.maturityDate || '-',
|
|
979
|
+
status: 'active' as const,
|
|
980
|
+
creditRating: getStaticCreditRatingForFD({
|
|
981
|
+
name: fdDisplay.name,
|
|
982
|
+
providerId: providerIdFromApp,
|
|
983
|
+
}),
|
|
984
|
+
companyName: fdDisplay.name,
|
|
985
|
+
fdRate: `${fdDisplay.returns}% p.a.`,
|
|
986
|
+
interestPayout: fdDisplay.interestPayout || '',
|
|
987
|
+
};
|
|
988
|
+
dispatch(setFDListSelected(fdListSelectedData));
|
|
989
|
+
} catch (e) {
|
|
990
|
+
// Handle error silently
|
|
991
|
+
}
|
|
992
|
+
|
|
993
|
+
try {
|
|
994
|
+
const ids = {
|
|
995
|
+
workflowInstanceId: appData.workflow_instance_id || appData.workflowInstanceId,
|
|
996
|
+
applicationId: appData.application_id || appData.applicationId,
|
|
997
|
+
entityid: appData.entity_id || appData.entityId,
|
|
998
|
+
customerId: appData.customer_id || appData.customerId,
|
|
999
|
+
fdId: appData.fd_id || appData.fdId,
|
|
1000
|
+
currentState: appData.current_state || appData.currentState,
|
|
1001
|
+
currentTask: appData.current_task || appData.currentTask,
|
|
1002
|
+
providerId: providerIdFromApp || undefined,
|
|
1003
|
+
wfStatus: appData.wf_status || appData.wfStatus,
|
|
1004
|
+
};
|
|
1005
|
+
onboardingIdsFromApp = ids;
|
|
1006
|
+
dispatch(setOnboardingIds(ids));
|
|
1007
|
+
} catch (e) {
|
|
1008
|
+
}
|
|
1009
|
+
}
|
|
1010
|
+
} catch (error) {
|
|
1011
|
+
// Handle error silently
|
|
1012
|
+
}
|
|
1013
|
+
|
|
1014
|
+
if (!fdDisplay && appData) fdDisplay = appToPendingFDData(appData);
|
|
1015
|
+
|
|
1016
|
+
// If current state is payment and transactionId is available, call payment reverse feed API
|
|
1017
|
+
// Check for both Mahindra and Shriram payment states
|
|
1018
|
+
const isPaymentState =
|
|
1019
|
+
currentStateCaption === MAHINDRA_WORKFLOW_STATES.PAYMENT ||
|
|
1020
|
+
currentStateCaption === SHRIRAM_WORKFLOW_STATES.PAYMENT;
|
|
1021
|
+
|
|
1022
|
+
if (isPaymentState && transactionId) {
|
|
1023
|
+
try {
|
|
1024
|
+
// Get user info and required IDs (prefer appData from continue context)
|
|
1025
|
+
const userInfo = getUserInfoForAPI();
|
|
1026
|
+
let providerIdFromApp = resolveProviderIdFromApp(appData, MahindraProviderId, ShriramProviderId);
|
|
1027
|
+
if (forcedSdkType === 'mahindra') providerIdFromApp = MahindraProviderId;
|
|
1028
|
+
if (forcedSdkType === 'shriram') providerIdFromApp = ShriramProviderId;
|
|
1029
|
+
const paymentReverseFeedRequest = {
|
|
1030
|
+
providerId: providerIdFromApp || providerId,
|
|
1031
|
+
workflowInstanceId: appData?.workflow_instance_id || appData?.workflowInstanceId || workflowInstanceId,
|
|
1032
|
+
userreferenceid: userInfo.id,
|
|
1033
|
+
applicationid: appData?.application_id || appData?.applicationId || applicationId,
|
|
1034
|
+
entityid: appData?.entity_id || appData?.entityId || entityId,
|
|
1035
|
+
transactionId: transactionId,
|
|
1036
|
+
};
|
|
1037
|
+
|
|
1038
|
+
const response = await paymentReverseFeed(paymentReverseFeedRequest).unwrap();
|
|
1039
|
+
|
|
1040
|
+
// Handle the response based on payment status (normalize to uppercase)
|
|
1041
|
+
const paymentStatus = (response?.data?.paymentStatus || response?.paymentStatus || '').toUpperCase();
|
|
1042
|
+
const statusParam = paymentStatus === 'SUCCESS' ? 'success' : paymentStatus === 'FAILED' ? 'failed' : 'pending';
|
|
1043
|
+
|
|
1044
|
+
const fdDataParam = fdDisplay ? {
|
|
1045
|
+
companyName: fdDisplay.name,
|
|
1046
|
+
amount: Number(fdDisplay.invested) || 0,
|
|
1047
|
+
fdRate: `${fdDisplay.returns}% p.a.`,
|
|
1048
|
+
tenure: fdDisplay.tenure ? `${fdDisplay.tenure}` : '-',
|
|
1049
|
+
interestPayout: fdDisplay.interestPayout || 'Yearly',
|
|
1050
|
+
} : activeFD ? {
|
|
1051
|
+
companyName: activeFD.name,
|
|
1052
|
+
amount: Number(activeFD.invested) || 0,
|
|
1053
|
+
fdRate: `${activeFD.returns}% p.a.`,
|
|
1054
|
+
tenure: activeFD.maturityDate ? `${activeFD.maturityDate}` : '-',
|
|
1055
|
+
interestPayout: activeFD.interestPayout || 'Yearly',
|
|
1056
|
+
} : undefined;
|
|
1057
|
+
|
|
1058
|
+
// Shriram: always navigate to Shriram SDK PaymentStatus, never FDSDK PaymentStatus
|
|
1059
|
+
let paymentProviderId = resolveProviderIdFromApp(appData, MahindraProviderId, ShriramProviderId).toLowerCase();
|
|
1060
|
+
if (forcedSdkType === 'mahindra') paymentProviderId = MahindraProviderId.toLowerCase();
|
|
1061
|
+
if (forcedSdkType === 'shriram') paymentProviderId = ShriramProviderId.toLowerCase();
|
|
1062
|
+
const isShriramPayment = paymentProviderId === ShriramProviderId.toLowerCase();
|
|
1063
|
+
const isMahindraPayment = paymentProviderId === MahindraProviderId.toLowerCase();
|
|
1064
|
+
|
|
1065
|
+
if (isShriramPayment && appData) {
|
|
1066
|
+
if (!initializeExternalSDKFromFDList('shriram')) return;
|
|
1067
|
+
let ShriramSDKGlobalDataPayment: any = null;
|
|
1068
|
+
if (customerApplications && !isCustomerApplicationsEmpty()) {
|
|
1069
|
+
let applicationsData: any[] = [];
|
|
1070
|
+
if (Array.isArray(customerApplications)) applicationsData = customerApplications;
|
|
1071
|
+
else if (customerApplications?.data && Array.isArray(customerApplications.data)) applicationsData = customerApplications.data;
|
|
1072
|
+
else if (customerApplications?.applications && Array.isArray(customerApplications.applications)) applicationsData = customerApplications.applications;
|
|
1073
|
+
const completeApplications = applicationsData.filter((app: any) => {
|
|
1074
|
+
const s = (app.wf_status || app.status || '').toString().toLowerCase();
|
|
1075
|
+
return s === 'completed' || s === 'complete';
|
|
1076
|
+
});
|
|
1077
|
+
const shriramComplete = completeApplications.find((app: any) => (app.fd_provider_id || app.fdProviderId || app.provider_id || app.providerId || '').toLowerCase() === ShriramProviderId.toLowerCase());
|
|
1078
|
+
if (shriramComplete) ShriramSDKGlobalDataPayment = shriramComplete;
|
|
1079
|
+
}
|
|
1080
|
+
const fdListSelectedDataPayment = fdDisplay ? {
|
|
1081
|
+
id: appData.fd_id || appData.fdId || 'active-fd',
|
|
1082
|
+
providerId: providerIdFromApp,
|
|
1083
|
+
name: fdDisplay.name,
|
|
1084
|
+
accountNumber: appData.account_number || appData.accountNumber || '',
|
|
1085
|
+
roi: `${fdDisplay.returns}% p.a.`,
|
|
1086
|
+
tenure: fdDisplay.tenure || '-',
|
|
1087
|
+
amount: Number(fdDisplay.invested) || 0,
|
|
1088
|
+
maturityDate: fdDisplay.maturityDate || '-',
|
|
1089
|
+
status: 'active' as const,
|
|
1090
|
+
creditRating: getStaticCreditRatingForFD({
|
|
1091
|
+
name: fdDisplay.name,
|
|
1092
|
+
providerId: providerIdFromApp,
|
|
1093
|
+
}),
|
|
1094
|
+
companyName: fdDisplay.name,
|
|
1095
|
+
fdRate: `${fdDisplay.returns}% p.a.`,
|
|
1096
|
+
interestPayout: fdDisplay.interestPayout || 'Yearly',
|
|
1097
|
+
} : null;
|
|
1098
|
+
const masterDataPayment = ShriramMasterData;
|
|
1099
|
+
|
|
1100
|
+
navigate('ExternalSDK', {
|
|
1101
|
+
sdkType: 'shriram',
|
|
1102
|
+
providerId: providerIdFromApp,
|
|
1103
|
+
fdListSelectedData: fdListSelectedDataPayment,
|
|
1104
|
+
masterData: masterDataPayment,
|
|
1105
|
+
onboardingIds: onboardingIdsFromApp || onboardingIds,
|
|
1106
|
+
initialRouteName: 'PaymentStatus',
|
|
1107
|
+
initialPaymentStatusParams: { status: statusParam, transactionId, fdData: fdDataParam },
|
|
1108
|
+
shriramSDKGlobalData: ShriramSDKGlobalDataPayment,
|
|
1109
|
+
} as any);
|
|
1110
|
+
return;
|
|
1111
|
+
}
|
|
1112
|
+
|
|
1113
|
+
if (isMahindraPayment && appData) {
|
|
1114
|
+
if (!initializeExternalSDKFromFDList('mahindra')) return;
|
|
1115
|
+
const fdListSelectedDataPayment = fdDisplay ? {
|
|
1116
|
+
id: appData.fd_id || appData.fdId || 'active-fd',
|
|
1117
|
+
providerId: providerIdFromApp,
|
|
1118
|
+
name: fdDisplay.name,
|
|
1119
|
+
accountNumber: appData.account_number || appData.accountNumber || '',
|
|
1120
|
+
roi: `${fdDisplay.returns}% p.a.`,
|
|
1121
|
+
tenure: fdDisplay.tenure || '-',
|
|
1122
|
+
amount: Number(fdDisplay.invested) || 0,
|
|
1123
|
+
maturityDate: fdDisplay.maturityDate || '-',
|
|
1124
|
+
status: 'active' as const,
|
|
1125
|
+
creditRating: getStaticCreditRatingForFD({
|
|
1126
|
+
name: fdDisplay.name,
|
|
1127
|
+
providerId: providerIdFromApp,
|
|
1128
|
+
}),
|
|
1129
|
+
companyName: fdDisplay.name,
|
|
1130
|
+
fdRate: `${fdDisplay.returns}% p.a.`,
|
|
1131
|
+
interestPayout: fdDisplay.interestPayout || 'Yearly',
|
|
1132
|
+
} : null;
|
|
1133
|
+
const masterDataPayment = MahindraMasterData;
|
|
1134
|
+
|
|
1135
|
+
console.log("paymentStatus===>", paymentStatus);
|
|
1136
|
+
|
|
1137
|
+
if (paymentStatus === 'IN_PROGRESS') {
|
|
1138
|
+
const userInfo = getUserInfoForAPI();
|
|
1139
|
+
const mahindraDetails = (getGlobalData() as any)?.mahindraCustomerDetails;
|
|
1140
|
+
|
|
1141
|
+
// PAN is optional at SDK init — collect it from every available source
|
|
1142
|
+
const panNo = (
|
|
1143
|
+
userInfo?.panNumber ??
|
|
1144
|
+
(userInfo as any)?.panNo ??
|
|
1145
|
+
(userInfo as any)?.pan ??
|
|
1146
|
+
mahindraDetails?.pan_number ??
|
|
1147
|
+
mahindraDetails?.panNumber ??
|
|
1148
|
+
mahindraDetails?.pan ??
|
|
1149
|
+
mahindraDetails?.kyc_pan ??
|
|
1150
|
+
mahindraDetails?.kycPan ??
|
|
1151
|
+
appData?.pan_number ??
|
|
1152
|
+
appData?.panNumber ??
|
|
1153
|
+
appData?.pan ??
|
|
1154
|
+
''
|
|
1155
|
+
).trim();
|
|
1156
|
+
|
|
1157
|
+
const appIdForUrl = appData?.application_id || appData?.applicationId || '';
|
|
1158
|
+
|
|
1159
|
+
if (__DEV__) {
|
|
1160
|
+
console.log('[FDList][IN_PROGRESS] panNo:', panNo, '| appId:', appIdForUrl, '| provider:', providerIdFromApp);
|
|
1161
|
+
}
|
|
1162
|
+
|
|
1163
|
+
let resolvedPaymentUrl: string | undefined;
|
|
1164
|
+
let resolvedTransactionId: string | undefined = transactionId;
|
|
1165
|
+
|
|
1166
|
+
try {
|
|
1167
|
+
const urlResult = await getPaymentUrl({
|
|
1168
|
+
providerId: providerIdFromApp,
|
|
1169
|
+
workflowInstanceId: appData?.workflow_instance_id || appData?.workflowInstanceId || workflowInstanceId,
|
|
1170
|
+
userreferenceid: userInfo.id,
|
|
1171
|
+
applicationid: appIdForUrl,
|
|
1172
|
+
entityid: appData?.entity_id || appData?.entityId || entityId,
|
|
1173
|
+
applicationId: appIdForUrl,
|
|
1174
|
+
panNo,
|
|
1175
|
+
isRetry: true,
|
|
1176
|
+
}).unwrap();
|
|
1177
|
+
|
|
1178
|
+
if (__DEV__) {
|
|
1179
|
+
console.log('[FDList][IN_PROGRESS] getPaymentUrl result:', urlResult);
|
|
1180
|
+
}
|
|
1181
|
+
|
|
1182
|
+
resolvedPaymentUrl = urlResult?.data?.[0]?.paymentUrl;
|
|
1183
|
+
resolvedTransactionId = urlResult?.data?.[0]?.transactionId || transactionId;
|
|
1184
|
+
} catch (err) {
|
|
1185
|
+
if (__DEV__) {
|
|
1186
|
+
console.log('[FDList][IN_PROGRESS] getPaymentUrl error — navigating to Payment with existing session:', err);
|
|
1187
|
+
}
|
|
1188
|
+
}
|
|
1189
|
+
|
|
1190
|
+
// Always navigate to Payment for IN_PROGRESS.
|
|
1191
|
+
// Pass initialPaymentUrl only when getPaymentUrl returned one;
|
|
1192
|
+
// otherwise Payment screen reads from mahindra's existing paymentSession.
|
|
1193
|
+
navigate('ExternalSDK', {
|
|
1194
|
+
sdkType: 'mahindra',
|
|
1195
|
+
providerId: providerIdFromApp,
|
|
1196
|
+
fdListSelectedData: fdListSelectedDataPayment,
|
|
1197
|
+
masterData: masterDataPayment,
|
|
1198
|
+
onboardingIds: onboardingIdsFromApp || onboardingIds,
|
|
1199
|
+
initialRouteName: 'Payment',
|
|
1200
|
+
...(resolvedPaymentUrl ? {
|
|
1201
|
+
initialPaymentUrl: resolvedPaymentUrl,
|
|
1202
|
+
initialPaymentTransactionId: resolvedTransactionId,
|
|
1203
|
+
} : {}),
|
|
1204
|
+
} as any);
|
|
1205
|
+
return;
|
|
1206
|
+
} else {
|
|
1207
|
+
navigate('ExternalSDK', {
|
|
1208
|
+
sdkType: 'mahindra',
|
|
1209
|
+
providerId: providerIdFromApp,
|
|
1210
|
+
fdListSelectedData: fdListSelectedDataPayment,
|
|
1211
|
+
masterData: masterDataPayment,
|
|
1212
|
+
onboardingIds: onboardingIdsFromApp || onboardingIds,
|
|
1213
|
+
initialRouteName: 'PaymentStatus',
|
|
1214
|
+
initialPaymentStatusParams: { status: statusParam, transactionId, fdData: fdDataParam },
|
|
1215
|
+
} as any);
|
|
1216
|
+
}
|
|
1217
|
+
|
|
1218
|
+
|
|
1219
|
+
return;
|
|
1220
|
+
}
|
|
1221
|
+
|
|
1222
|
+
navigate('PaymentStatus', { status: statusParam, transactionId, fdData: fdDataParam } as any);
|
|
1223
|
+
return;
|
|
1224
|
+
|
|
1225
|
+
} catch (error) {
|
|
1226
|
+
// Handle error silently
|
|
1227
|
+
const fdDataParam = fdDisplay ? {
|
|
1228
|
+
companyName: fdDisplay.name,
|
|
1229
|
+
amount: Number(fdDisplay.invested) || 0,
|
|
1230
|
+
fdRate: `${fdDisplay.returns}% p.a.`,
|
|
1231
|
+
tenure: fdDisplay.tenure ? `${fdDisplay.tenure}` : '-',
|
|
1232
|
+
interestPayout: fdDisplay.interestPayout || 'Yearly',
|
|
1233
|
+
} : activeFD ? {
|
|
1234
|
+
companyName: activeFD.name,
|
|
1235
|
+
amount: Number(activeFD.invested) || 0,
|
|
1236
|
+
fdRate: `${activeFD.returns}% p.a.`,
|
|
1237
|
+
tenure: activeFD.maturityDate ? `${activeFD.maturityDate}` : '-',
|
|
1238
|
+
interestPayout: activeFD.interestPayout || 'Yearly',
|
|
1239
|
+
} : undefined;
|
|
1240
|
+
let providerIdFromApp = resolveProviderIdFromApp(appData, MahindraProviderId, ShriramProviderId);
|
|
1241
|
+
if (forcedSdkType === 'mahindra') providerIdFromApp = MahindraProviderId;
|
|
1242
|
+
if (forcedSdkType === 'shriram') providerIdFromApp = ShriramProviderId;
|
|
1243
|
+
const paymentProviderIdCatch = providerIdFromApp.toLowerCase();
|
|
1244
|
+
const isShriramPaymentCatch = paymentProviderIdCatch === ShriramProviderId.toLowerCase();
|
|
1245
|
+
const isMahindraPaymentCatch = paymentProviderIdCatch === MahindraProviderId.toLowerCase();
|
|
1246
|
+
|
|
1247
|
+
if (isShriramPaymentCatch && appData) {
|
|
1248
|
+
if (!initializeExternalSDKFromFDList('shriram')) return;
|
|
1249
|
+
let ShriramSDKGlobalDataPayment: any = null;
|
|
1250
|
+
if (customerApplications && !isCustomerApplicationsEmpty()) {
|
|
1251
|
+
let applicationsData: any[] = [];
|
|
1252
|
+
if (Array.isArray(customerApplications)) applicationsData = customerApplications;
|
|
1253
|
+
else if (customerApplications?.data && Array.isArray(customerApplications.data)) applicationsData = customerApplications.data;
|
|
1254
|
+
else if (customerApplications?.applications && Array.isArray(customerApplications.applications)) applicationsData = customerApplications.applications;
|
|
1255
|
+
const completeApplications = applicationsData.filter((app: any) => {
|
|
1256
|
+
const s = (app.wf_status || app.status || '').toString().toLowerCase();
|
|
1257
|
+
return s === 'completed' || s === 'complete';
|
|
1258
|
+
});
|
|
1259
|
+
const shriramComplete = completeApplications.find((app: any) => (app.fd_provider_id || app.fdProviderId || app.provider_id || app.providerId || '').toLowerCase() === ShriramProviderId.toLowerCase());
|
|
1260
|
+
if (shriramComplete) ShriramSDKGlobalDataPayment = shriramComplete;
|
|
1261
|
+
}
|
|
1262
|
+
const fdListSelectedDataPayment = fdDisplay ? {
|
|
1263
|
+
id: appData.fd_id || appData.fdId || 'active-fd',
|
|
1264
|
+
providerId: providerIdFromApp,
|
|
1265
|
+
name: fdDisplay.name,
|
|
1266
|
+
accountNumber: appData.account_number || appData.accountNumber || '',
|
|
1267
|
+
roi: `${fdDisplay.returns}% p.a.`,
|
|
1268
|
+
tenure: fdDisplay.tenure || '-',
|
|
1269
|
+
amount: Number(fdDisplay.invested) || 0,
|
|
1270
|
+
maturityDate: fdDisplay.maturityDate || '-',
|
|
1271
|
+
status: 'active' as const,
|
|
1272
|
+
creditRating: getStaticCreditRatingForFD({
|
|
1273
|
+
name: fdDisplay.name,
|
|
1274
|
+
providerId: providerIdFromApp,
|
|
1275
|
+
}),
|
|
1276
|
+
companyName: fdDisplay.name,
|
|
1277
|
+
fdRate: `${fdDisplay.returns}% p.a.`,
|
|
1278
|
+
interestPayout: fdDisplay.interestPayout || 'Yearly',
|
|
1279
|
+
} : null;
|
|
1280
|
+
const masterDataPayment = ShriramMasterData;
|
|
1281
|
+
navigate('ExternalSDK', {
|
|
1282
|
+
sdkType: 'shriram',
|
|
1283
|
+
providerId: providerIdFromApp,
|
|
1284
|
+
fdListSelectedData: fdListSelectedDataPayment,
|
|
1285
|
+
masterData: masterDataPayment,
|
|
1286
|
+
onboardingIds: onboardingIdsFromApp || onboardingIds,
|
|
1287
|
+
initialRouteName: 'PaymentStatus',
|
|
1288
|
+
initialPaymentStatusParams: { status: 'pending', transactionId, fdData: fdDataParam },
|
|
1289
|
+
shriramSDKGlobalData: ShriramSDKGlobalDataPayment,
|
|
1290
|
+
} as any);
|
|
1291
|
+
return;
|
|
1292
|
+
}
|
|
1293
|
+
|
|
1294
|
+
if (isMahindraPaymentCatch && appData) {
|
|
1295
|
+
if (!initializeExternalSDKFromFDList('mahindra')) return;
|
|
1296
|
+
const fdListSelectedDataPayment = fdDisplay ? {
|
|
1297
|
+
id: appData.fd_id || appData.fdId || 'active-fd',
|
|
1298
|
+
providerId: providerIdFromApp,
|
|
1299
|
+
name: fdDisplay.name,
|
|
1300
|
+
accountNumber: appData.account_number || appData.accountNumber || '',
|
|
1301
|
+
roi: `${fdDisplay.returns}% p.a.`,
|
|
1302
|
+
tenure: fdDisplay.tenure || '-',
|
|
1303
|
+
amount: Number(fdDisplay.invested) || 0,
|
|
1304
|
+
maturityDate: fdDisplay.maturityDate || '-',
|
|
1305
|
+
status: 'active' as const,
|
|
1306
|
+
creditRating: getStaticCreditRatingForFD({
|
|
1307
|
+
name: fdDisplay.name,
|
|
1308
|
+
providerId: providerIdFromApp,
|
|
1309
|
+
}),
|
|
1310
|
+
companyName: fdDisplay.name,
|
|
1311
|
+
fdRate: `${fdDisplay.returns}% p.a.`,
|
|
1312
|
+
interestPayout: fdDisplay.interestPayout || 'Yearly',
|
|
1313
|
+
} : null;
|
|
1314
|
+
const masterDataPayment = MahindraMasterData;
|
|
1315
|
+
navigate('ExternalSDK', {
|
|
1316
|
+
sdkType: 'mahindra',
|
|
1317
|
+
providerId: providerIdFromApp,
|
|
1318
|
+
fdListSelectedData: fdListSelectedDataPayment,
|
|
1319
|
+
masterData: masterDataPayment,
|
|
1320
|
+
onboardingIds: onboardingIdsFromApp || onboardingIds,
|
|
1321
|
+
initialRouteName: 'PaymentStatus',
|
|
1322
|
+
initialPaymentStatusParams: { status: 'pending', transactionId, fdData: fdDataParam },
|
|
1323
|
+
} as any);
|
|
1324
|
+
return;
|
|
1325
|
+
}
|
|
1326
|
+
|
|
1327
|
+
navigate('PaymentStatus', { status: 'pending', transactionId, fdData: fdDataParam } as any);
|
|
1328
|
+
return;
|
|
1329
|
+
;
|
|
1330
|
+
}
|
|
1331
|
+
}
|
|
1332
|
+
|
|
1333
|
+
// Determine provider and navigate to appropriate SDK
|
|
1334
|
+
if (appData) {
|
|
1335
|
+
let providerIdFromApp = resolveProviderIdFromApp(appData, MahindraProviderId, ShriramProviderId);
|
|
1336
|
+
if (forcedSdkType === 'mahindra') providerIdFromApp = MahindraProviderId;
|
|
1337
|
+
if (forcedSdkType === 'shriram') providerIdFromApp = ShriramProviderId;
|
|
1338
|
+
const providerIdLower = (providerIdFromApp || '').toLowerCase();
|
|
1339
|
+
const isMahindra = providerIdLower === MahindraProviderId.toLowerCase();
|
|
1340
|
+
const isShriram = providerIdLower === ShriramProviderId.toLowerCase();
|
|
1341
|
+
|
|
1342
|
+
// Check for complete applications and create global data constants
|
|
1343
|
+
let ShriramSDKGlobalData: any = null;
|
|
1344
|
+
let MahindraSDKGlobalData: any = null;
|
|
1345
|
+
|
|
1346
|
+
if (customerApplications && !isCustomerApplicationsEmpty()) {
|
|
1347
|
+
let applicationsData: any[] = [];
|
|
1348
|
+
if (Array.isArray(customerApplications)) {
|
|
1349
|
+
applicationsData = customerApplications;
|
|
1350
|
+
} else if (customerApplications.data && Array.isArray(customerApplications.data)) {
|
|
1351
|
+
applicationsData = customerApplications.data;
|
|
1352
|
+
} else if (customerApplications.applications && Array.isArray(customerApplications.applications)) {
|
|
1353
|
+
applicationsData = customerApplications.applications;
|
|
1354
|
+
}
|
|
1355
|
+
|
|
1356
|
+
// Find complete applications
|
|
1357
|
+
const completeApplications = applicationsData.filter((app: any) => {
|
|
1358
|
+
const status = (app.wf_status || app.status || '').toString().toLowerCase();
|
|
1359
|
+
return status === 'completed' || status === 'complete';
|
|
1360
|
+
});
|
|
1361
|
+
|
|
1362
|
+
// Separate by provider
|
|
1363
|
+
completeApplications.forEach((app: any) => {
|
|
1364
|
+
const appProviderId = (app.fd_provider_id || app.fdProviderId || app.provider_id || app.providerId || '').toLowerCase();
|
|
1365
|
+
if (appProviderId === ShriramProviderId.toLowerCase()) {
|
|
1366
|
+
ShriramSDKGlobalData = app;
|
|
1367
|
+
} else if (appProviderId === MahindraProviderId.toLowerCase()) {
|
|
1368
|
+
MahindraSDKGlobalData = app;
|
|
1369
|
+
}
|
|
1370
|
+
});
|
|
1371
|
+
}
|
|
1372
|
+
|
|
1373
|
+
// Helper function to map workflow state to screen name
|
|
1374
|
+
const getScreenNameFromState = (state: string, isMahindraSDK: boolean, isShriramSDK: boolean): string => {
|
|
1375
|
+
if (isMahindraSDK) {
|
|
1376
|
+
if (state === MAHINDRA_WORKFLOW_STATES.KYC) return 'AadhaarVerification';
|
|
1377
|
+
if (state === MAHINDRA_WORKFLOW_STATES.DEMOGRAPHIC_INFO) return 'ReviewKYC';
|
|
1378
|
+
if (state === MAHINDRA_WORKFLOW_STATES.OCCUPATION) return 'Employee';
|
|
1379
|
+
if (state === MAHINDRA_WORKFLOW_STATES.NOMINEE) return 'NomineeDetail';
|
|
1380
|
+
if (state === MAHINDRA_WORKFLOW_STATES.BANK_DETAILS) return 'BankDetail';
|
|
1381
|
+
if (state === MAHINDRA_WORKFLOW_STATES.AADHAAR_VERIFICATION) return 'AadhaarVerification';
|
|
1382
|
+
if (state === MAHINDRA_WORKFLOW_STATES.PAYMENT) return 'KYCSuccess';
|
|
1383
|
+
if (state === MAHINDRA_WORKFLOW_STATES.CREATE_FD) return 'PayNow';
|
|
1384
|
+
} else if (isShriramSDK) {
|
|
1385
|
+
if (state === SHRIRAM_WORKFLOW_STATES.KYC) return 'ReviewKYC';
|
|
1386
|
+
if (state === SHRIRAM_WORKFLOW_STATES.OCCUPATION) return 'Employee';
|
|
1387
|
+
if (state === SHRIRAM_WORKFLOW_STATES.NOMINEE) return 'NomineeDetail';
|
|
1388
|
+
if (state === SHRIRAM_WORKFLOW_STATES.BANK_DETAILS) return 'BankDetail';
|
|
1389
|
+
if (state === SHRIRAM_WORKFLOW_STATES.PAYMENT) return 'PayNow';
|
|
1390
|
+
// State 411 (CREATE_FD): user has completed up to FD creation; next step is payment → open PayNow
|
|
1391
|
+
if (state === SHRIRAM_WORKFLOW_STATES.CREATE_FD) return 'PayNow';
|
|
1392
|
+
if (state === SHRIRAM_WORKFLOW_STATES.END) return 'PayNow';
|
|
1393
|
+
}
|
|
1394
|
+
// Default fallback
|
|
1395
|
+
return 'FDCalculator';
|
|
1396
|
+
};
|
|
1397
|
+
|
|
1398
|
+
// Align pending flow with new-FD reliability: fetch provider-scoped master data right before navigation.
|
|
1399
|
+
let providerMasterData = isMahindra ? MahindraMasterData : isShriram ? ShriramMasterData : undefined;
|
|
1400
|
+
try {
|
|
1401
|
+
if (isMahindra) {
|
|
1402
|
+
const refreshed = await refetchMahindraMasterData();
|
|
1403
|
+
providerMasterData = refreshed?.data ?? providerMasterData;
|
|
1404
|
+
} else if (isShriram) {
|
|
1405
|
+
const refreshed = await refetchShriramMasterData();
|
|
1406
|
+
providerMasterData = refreshed?.data ?? providerMasterData;
|
|
1407
|
+
}
|
|
1408
|
+
} catch {
|
|
1409
|
+
// keep previously cached provider-specific master data
|
|
1410
|
+
}
|
|
1411
|
+
|
|
1412
|
+
const masterDataToPass = providerMasterData || (masterData || masterDataContext);
|
|
1413
|
+
|
|
1414
|
+
// Get onboardingIds - use the one from appData if available, otherwise from Redux store
|
|
1415
|
+
const onboardingIdsToPass = onboardingIdsFromApp || onboardingIds;
|
|
1416
|
+
|
|
1417
|
+
// Get fdListSelectedData (already set in Redux, but we need it for navigation)
|
|
1418
|
+
// Use fdDisplay (derived from the tapped app) not activeFD (always first active app)
|
|
1419
|
+
const fdListSelectedDataToPass = fdDisplay ? {
|
|
1420
|
+
id: appData.fd_id || appData.fdId || 'active-fd',
|
|
1421
|
+
providerId: providerIdFromApp,
|
|
1422
|
+
name: fdDisplay.name,
|
|
1423
|
+
accountNumber: appData.account_number || appData.accountNumber || '',
|
|
1424
|
+
roi: `${fdDisplay.returns}% p.a.`,
|
|
1425
|
+
tenure: appData.tenure_in_months
|
|
1426
|
+
? `${appData.tenure_in_months} Months`
|
|
1427
|
+
: '-',
|
|
1428
|
+
amount: Number(fdDisplay.invested) || 0,
|
|
1429
|
+
maturityDate: fdDisplay.maturityDate || '-',
|
|
1430
|
+
status: 'active' as const,
|
|
1431
|
+
creditRating: getStaticCreditRatingForFD({
|
|
1432
|
+
name: fdDisplay.name,
|
|
1433
|
+
providerId: providerIdFromApp,
|
|
1434
|
+
}),
|
|
1435
|
+
companyName: fdDisplay.name,
|
|
1436
|
+
fdRate: `${fdDisplay.returns}% p.a.`,
|
|
1437
|
+
interestPayout: fdDisplay.interestPayout || '',
|
|
1438
|
+
} : null;
|
|
1439
|
+
|
|
1440
|
+
// Navigate to appropriate SDK if provider is detected
|
|
1441
|
+
if (isMahindra || isShriram) {
|
|
1442
|
+
const screenName = getScreenNameFromState(currentStateCaption, isMahindra, isShriram);
|
|
1443
|
+
const sdkType = isMahindra ? 'mahindra' : 'shriram';
|
|
1444
|
+
if (!initializeExternalSDKFromFDList(sdkType)) return;
|
|
1445
|
+
// #region agent log
|
|
1446
|
+
fetch('http://127.0.0.1:7653/ingest/94b18a39-caf3-48fd-98f5-bf1838d9491a', { method: 'POST', headers: { 'Content-Type': 'application/json', 'X-Debug-Session-Id': '04da7c' }, body: JSON.stringify({ sessionId: '04da7c', runId: 'pending-masterdata-trace', hypothesisId: 'H2', location: 'fdsdk/screens/FDList.tsx:1315', message: 'Pending continue pre-navigation payload', data: { forcedSdkType: forcedSdkType || null, resolvedSdkType: sdkType, providerIdFromApp: providerIdFromApp || null, onboardingProviderId: onboardingIdsToPass?.providerId || null, fdListSelectedProviderId: fdListSelectedDataToPass?.providerId || null, usingMahindraMasterData: !!(sdkType === 'mahindra' && masterDataToPass), usingShriramMasterData: !!(sdkType === 'shriram' && masterDataToPass), masterDataHasDataKey: !!masterDataToPass?.data }, timestamp: Date.now() }) }).catch(() => { });
|
|
1447
|
+
// #endregion agent log
|
|
1448
|
+
|
|
1449
|
+
navigate('ExternalSDK', {
|
|
1450
|
+
sdkType,
|
|
1451
|
+
providerId: providerIdFromApp,
|
|
1452
|
+
fdListSelectedData: fdListSelectedDataToPass,
|
|
1453
|
+
masterData: masterDataToPass,
|
|
1454
|
+
onboardingIds: onboardingIdsToPass,
|
|
1455
|
+
initialRouteName: screenName, // Pass the screen name to navigate to
|
|
1456
|
+
shriramSDKGlobalData: ShriramSDKGlobalData, // Pass complete Shriram application data
|
|
1457
|
+
mahindraSDKGlobalData: MahindraSDKGlobalData, // Pass complete Mahindra application data
|
|
1458
|
+
// Let Mahindra SDK fetch details itself when launched from host (Mahindra only)
|
|
1459
|
+
...(isMahindra ? { forceFetchCustomerDetails: true } : {}),
|
|
1460
|
+
});
|
|
1461
|
+
return;
|
|
1462
|
+
}
|
|
1463
|
+
}
|
|
1464
|
+
|
|
1465
|
+
// Fallback: Use workflow navigation based on current state (non-payment states or no transactionId)
|
|
1466
|
+
if (currentStateCaption) {
|
|
1467
|
+
handleWorkflowNavigation({
|
|
1468
|
+
workflowState: currentStateCaption,
|
|
1469
|
+
investmentData: undefined,
|
|
1470
|
+
customerData: undefined,
|
|
1471
|
+
appData: undefined,
|
|
1472
|
+
fdData: undefined,
|
|
1473
|
+
completedApplications: [],
|
|
1474
|
+
transactionId,
|
|
1475
|
+
});
|
|
1476
|
+
} else {
|
|
1477
|
+
navigate('Employee');
|
|
1478
|
+
}
|
|
1479
|
+
} finally {
|
|
1480
|
+
setIsPendingFDLoading(false);
|
|
1481
|
+
}
|
|
1482
|
+
};
|
|
1483
|
+
|
|
1484
|
+
// Derive identifiers for workflow termination from applications API
|
|
1485
|
+
// Derive Active FD card data from customer applications response
|
|
1486
|
+
const activeFD = React.useMemo(() => {
|
|
1487
|
+
try {
|
|
1488
|
+
if (!customerApplications || isCustomerApplicationsEmpty()) {
|
|
1489
|
+
return {
|
|
1490
|
+
name: 'Mahindra Finance Ltd',
|
|
1491
|
+
invested: 0,
|
|
1492
|
+
value: 0,
|
|
1493
|
+
returns: 0,
|
|
1494
|
+
maturityDate: '--',
|
|
1495
|
+
tenure_in_months: 0,
|
|
1496
|
+
interestPayout: 'Yearly',
|
|
1497
|
+
logoType: 'mahindra' as const,
|
|
1498
|
+
};
|
|
1499
|
+
}
|
|
1500
|
+
|
|
1501
|
+
// Normalize list
|
|
1502
|
+
let applicationsData: any[] = [];
|
|
1503
|
+
if (Array.isArray(customerApplications)) {
|
|
1504
|
+
applicationsData = customerApplications;
|
|
1505
|
+
} else if (customerApplications.data && Array.isArray(customerApplications.data)) {
|
|
1506
|
+
applicationsData = customerApplications.data;
|
|
1507
|
+
} else if (customerApplications.applications && Array.isArray(customerApplications.applications)) {
|
|
1508
|
+
applicationsData = customerApplications.applications;
|
|
1509
|
+
}
|
|
1510
|
+
|
|
1511
|
+
if (applicationsData.length === 0) {
|
|
1512
|
+
return {
|
|
1513
|
+
name: 'Mahindra Finance Ltd',
|
|
1514
|
+
invested: 0,
|
|
1515
|
+
value: 0,
|
|
1516
|
+
returns: 0,
|
|
1517
|
+
maturityDate: '--',
|
|
1518
|
+
tenure_in_months: 0,
|
|
1519
|
+
interestPayout: 'Yearly',
|
|
1520
|
+
logoType: 'mahindra' as const,
|
|
1521
|
+
};
|
|
1522
|
+
}
|
|
1523
|
+
|
|
1524
|
+
// Pick an active application if available, otherwise first
|
|
1525
|
+
const activeApp = applicationsData.find((a: any) => {
|
|
1526
|
+
const s = (a.wf_status || a.status || '').toString();
|
|
1527
|
+
return s === 'Active';
|
|
1528
|
+
}) || applicationsData[0];
|
|
1529
|
+
|
|
1530
|
+
const invested = Number(
|
|
1531
|
+
activeApp.investment_amount ?? activeApp.amount ?? activeApp.investmentAmount ?? 0
|
|
1532
|
+
);
|
|
1533
|
+
const rate = Number(
|
|
1534
|
+
activeApp.interest_rate ?? activeApp.interestRate ?? 0
|
|
1535
|
+
);
|
|
1536
|
+
|
|
1537
|
+
// Prefer a provided current value, then maturity amount
|
|
1538
|
+
const value = Number(
|
|
1539
|
+
activeApp.current_value ?? activeApp.currentValue ?? activeApp.maturity_amount ?? activeApp.maturityAmount ?? 0
|
|
1540
|
+
);
|
|
1541
|
+
|
|
1542
|
+
const returns = rate || 0; // display interest rate as returns %
|
|
1543
|
+
|
|
1544
|
+
// Format maturity date to 'Mon YYYY'
|
|
1545
|
+
const maturityDateStr: string = activeApp.maturity_date || activeApp.maturityDate || '';
|
|
1546
|
+
let maturityDate = '--';
|
|
1547
|
+
if (maturityDateStr) {
|
|
1548
|
+
const d = new Date(maturityDateStr);
|
|
1549
|
+
if (!isNaN(d.getTime())) {
|
|
1550
|
+
const months = ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec'];
|
|
1551
|
+
maturityDate = `${months[d.getMonth()]} ${d.getFullYear()}`;
|
|
1552
|
+
}
|
|
1553
|
+
}
|
|
1554
|
+
|
|
1555
|
+
// Get interest payout term from activeApp
|
|
1556
|
+
const interestPayout = activeApp.interest_payout_term || activeApp.interestPayoutTerm || activeApp.payout_term || 'Yearly';
|
|
1557
|
+
|
|
1558
|
+
const providerName = activeApp.fd_provider_name || activeApp.providerName || 'Mahindra Finance Ltd';
|
|
1559
|
+
const logoType = getLogoTypeForFD({ name: providerName, providerId: activeApp.fd_provider_id || activeApp.fdProviderId || '' });
|
|
1560
|
+
|
|
1561
|
+
return {
|
|
1562
|
+
name: providerName,
|
|
1563
|
+
invested,
|
|
1564
|
+
value,
|
|
1565
|
+
returns,
|
|
1566
|
+
maturityDate,
|
|
1567
|
+
tenure_in_months: activeApp.tenure_in_months ?? 0,
|
|
1568
|
+
interestPayout,
|
|
1569
|
+
logoType,
|
|
1570
|
+
};
|
|
1571
|
+
} catch (e) {
|
|
1572
|
+
return {
|
|
1573
|
+
name: 'Mahindra Finance Ltd',
|
|
1574
|
+
invested: 0,
|
|
1575
|
+
value: 0,
|
|
1576
|
+
returns: 0,
|
|
1577
|
+
maturityDate: '--',
|
|
1578
|
+
tenure_in_months: 0,
|
|
1579
|
+
interestPayout: 'Yearly',
|
|
1580
|
+
logoType: 'mahindra' as const,
|
|
1581
|
+
};
|
|
1582
|
+
}
|
|
1583
|
+
}, [customerApplications]);
|
|
1584
|
+
|
|
1585
|
+
// All pending/active FDs (one per application with Active or pending/in_progress) – for multiple providers
|
|
1586
|
+
const activeFDs = React.useMemo(() => {
|
|
1587
|
+
try {
|
|
1588
|
+
if (!customerApplications || isCustomerApplicationsEmpty()) return [];
|
|
1589
|
+
let applicationsData: any[] = [];
|
|
1590
|
+
if (Array.isArray(customerApplications)) {
|
|
1591
|
+
applicationsData = customerApplications;
|
|
1592
|
+
} else if (customerApplications.data && Array.isArray(customerApplications.data)) {
|
|
1593
|
+
applicationsData = customerApplications.data;
|
|
1594
|
+
} else if (customerApplications.applications && Array.isArray(customerApplications.applications)) {
|
|
1595
|
+
applicationsData = customerApplications.applications;
|
|
1596
|
+
}
|
|
1597
|
+
const pendingActive = applicationsData.filter((a: any) => {
|
|
1598
|
+
const s = (a.wf_status || a.status || '').toString().toLowerCase();
|
|
1599
|
+
return PENDING_ACTIVE_STATUSES.includes(s);
|
|
1600
|
+
});
|
|
1601
|
+
return pendingActive.map((app: any) => ({
|
|
1602
|
+
...appToPendingFDData(app),
|
|
1603
|
+
app,
|
|
1604
|
+
}));
|
|
1605
|
+
} catch (e) {
|
|
1606
|
+
return [];
|
|
1607
|
+
}
|
|
1608
|
+
}, [customerApplications]);
|
|
1609
|
+
|
|
1610
|
+
// Normalized applications list for provider-scoped lookups
|
|
1611
|
+
const applicationsDataNormalized = React.useMemo(() => {
|
|
1612
|
+
if (!customerApplications || isCustomerApplicationsEmpty()) return [];
|
|
1613
|
+
if (Array.isArray(customerApplications)) return customerApplications;
|
|
1614
|
+
if (customerApplications.data && Array.isArray(customerApplications.data)) return customerApplications.data;
|
|
1615
|
+
if (customerApplications.applications && Array.isArray(customerApplications.applications)) return customerApplications.applications;
|
|
1616
|
+
return [];
|
|
1617
|
+
}, [customerApplications]);
|
|
1618
|
+
|
|
1619
|
+
// Helper function to check if there's any active/pending FD
|
|
1620
|
+
const hasActiveFD = React.useMemo(() => activeFDs.length > 0, [activeFDs]);
|
|
1621
|
+
|
|
1622
|
+
// Pending FD data for bottom sheet: from the app we're showing (provider they tapped), or fallback to first active
|
|
1623
|
+
const pendingFDDataForSheet = React.useMemo(() => {
|
|
1624
|
+
if (pendingContextApp) return appToPendingFDData(pendingContextApp);
|
|
1625
|
+
if (activeFDs.length > 0) return activeFDs[0]; // fallback: first card data (no app ref needed for display)
|
|
1626
|
+
return activeFD;
|
|
1627
|
+
}, [pendingContextApp, activeFDs, activeFD]);
|
|
1628
|
+
|
|
1629
|
+
// Build FD options list from interest-rate API (show all FDs)
|
|
1630
|
+
const fdList = React.useMemo(() => {
|
|
1631
|
+
if (interestRates && (interestRates.data?.sdrScheme?.length > 0 || interestRates.data?.fdrScheme?.length > 0)) {
|
|
1632
|
+
const sdr = Array.isArray(interestRates.data?.sdrScheme) ? interestRates.data.sdrScheme : [];
|
|
1633
|
+
const fdr = Array.isArray(interestRates.data?.fdrScheme) ? interestRates.data.fdrScheme : [];
|
|
1634
|
+
const combined = [...sdr, ...fdr];
|
|
1635
|
+
|
|
1636
|
+
// Building FD options from rates
|
|
1637
|
+
|
|
1638
|
+
return combined.map((rate: any, index: number) => ({
|
|
1639
|
+
id: `${rate.providerId || 'provider'}-${rate.perdMonth || index}`,
|
|
1640
|
+
providerId: rate.providerId || `provider-${index}`,
|
|
1641
|
+
name: rate.providerName || '', // Use actual provider name from API
|
|
1642
|
+
accountNumber: `FD${String(index + 1).padStart(9, '0')}`,
|
|
1643
|
+
roi: `${Number(rate.rate ?? rate.interestRate ?? 0).toFixed(2)}% p.a.`,
|
|
1644
|
+
tenure: `${rate.perdMonth} Months`,
|
|
1645
|
+
amount: 5000,
|
|
1646
|
+
maturityDate: '2025-12-31',
|
|
1647
|
+
status: 'active' as const,
|
|
1648
|
+
creditRating: getStaticCreditRatingForFD({
|
|
1649
|
+
name: rate.providerName || '',
|
|
1650
|
+
providerId: rate.providerId || `provider-${index}`,
|
|
1651
|
+
}),
|
|
1652
|
+
interestPayout: rate.interestPayout || rate.interest_payout_term || rate.payout_term || 'Yearly'
|
|
1653
|
+
}));
|
|
1654
|
+
}
|
|
1655
|
+
|
|
1656
|
+
// If rates are not available yet, show empty list
|
|
1657
|
+
return [];
|
|
1658
|
+
}, [interestRates]);
|
|
1659
|
+
|
|
1660
|
+
|
|
1661
|
+
// Get filtered FD list based on active tab
|
|
1662
|
+
const filteredFDList = React.useMemo(() => {
|
|
1663
|
+
if (!fdList || fdList.length === 0) return [];
|
|
1664
|
+
|
|
1665
|
+
// Always create a new filtered array
|
|
1666
|
+
const filtered = filterFDsByTenure([...fdList], activeTab); // spread to ensure new array
|
|
1667
|
+
|
|
1668
|
+
return filtered;
|
|
1669
|
+
}, [fdList, activeTab]);
|
|
1670
|
+
|
|
1671
|
+
|
|
1672
|
+
const tabs = [FD_STRINGS.ALL_FDS_TAB, FD_STRINGS.LESS_THAN_1Y_TAB, FD_STRINGS.LESS_THAN_1_3Y_TAB, FD_STRINGS.LESS_THAN_3_5Y_TAB, FD_STRINGS.GREATER_THAN_5Y_TAB];
|
|
1673
|
+
const poweredByLogo = (getAppData()?.poweredByLogo || '').trim();
|
|
1674
|
+
|
|
1675
|
+
if (!isAllDataReady) {
|
|
1676
|
+
return (
|
|
1677
|
+
<SafeAreaWrapper
|
|
1678
|
+
style={customStyles.container}
|
|
1679
|
+
includeTop={false}
|
|
1680
|
+
statusBarColor={colors.headerBg}
|
|
1681
|
+
statusBarStyle="light-content"
|
|
1682
|
+
>
|
|
1683
|
+
<View style={{ flex: 1, alignItems: 'center', justifyContent: 'center' }}>
|
|
1684
|
+
<ActivityIndicator size="large" color={colors.primary} />
|
|
1685
|
+
<Text style={{ marginTop: 12, color: colors.textSecondary }}>{FD_STRINGS.LOADING_FD_DATA}</Text>
|
|
1686
|
+
</View>
|
|
1687
|
+
</SafeAreaWrapper>
|
|
1688
|
+
);
|
|
1689
|
+
}
|
|
1690
|
+
|
|
1691
|
+
return (
|
|
1692
|
+
<SafeAreaWrapper
|
|
1693
|
+
style={customStyles.container}
|
|
1694
|
+
includeTop={false}
|
|
1695
|
+
statusBarColor={colors.headerBg}
|
|
1696
|
+
statusBarStyle="light-content"
|
|
1697
|
+
>
|
|
1698
|
+
{/* Custom FDList Header - same structure as Shriram FDList */}
|
|
1699
|
+
<View style={styles.customHeader}>
|
|
1700
|
+
<TouchableOpacity
|
|
1701
|
+
style={styles.backButton}
|
|
1702
|
+
onPress={onGoBack}
|
|
1703
|
+
activeOpacity={0.7}
|
|
1704
|
+
>
|
|
1705
|
+
<Image
|
|
1706
|
+
source={{ uri: base64Images.backArrow }}
|
|
1707
|
+
style={styles.backIcon}
|
|
1708
|
+
resizeMode="contain"
|
|
1709
|
+
/>
|
|
1710
|
+
</TouchableOpacity>
|
|
1711
|
+
|
|
1712
|
+
<View style={styles.headerContent}>
|
|
1713
|
+
<Text style={styles.headerTitle}>{FD_STRINGS.CORPORATE_FDS_TITLE}</Text>
|
|
1714
|
+
{poweredByLogo ? (
|
|
1715
|
+
<View style={styles.poweredByContainer}>
|
|
1716
|
+
<Text style={styles.poweredByText}>Powered by</Text>
|
|
1717
|
+
<Image
|
|
1718
|
+
source={{ uri: poweredByLogo }}
|
|
1719
|
+
style={styles.simplifyLogo}
|
|
1720
|
+
resizeMode="contain"
|
|
1721
|
+
/>
|
|
1722
|
+
</View>
|
|
1723
|
+
) : null}
|
|
1724
|
+
</View>
|
|
1725
|
+
</View>
|
|
1726
|
+
|
|
1727
|
+
<ScrollView style={styles.content}>
|
|
1728
|
+
|
|
1729
|
+
{/* Active FDs Section - One card per pending/active FD (e.g. one Mahindra, one Shriram) */}
|
|
1730
|
+
{hasActiveFD && (
|
|
1731
|
+
<View style={styles.section}>
|
|
1732
|
+
<Text style={styles.sectionTitle}>{FD_STRINGS.ACTIVE_FDS_SECTION}</Text>
|
|
1733
|
+
{activeFDs.map((item, index) => (
|
|
1734
|
+
<TouchableOpacity
|
|
1735
|
+
key={item.app?.application_id || item.app?.applicationId || index}
|
|
1736
|
+
activeOpacity={0.8}
|
|
1737
|
+
onPress={() => handlePendingFDContinue(item.app, item.logoType)}
|
|
1738
|
+
style={index > 0 ? styles.activeFDCardSpacer : undefined}
|
|
1739
|
+
>
|
|
1740
|
+
<ActiveFDCard
|
|
1741
|
+
name={item.name}
|
|
1742
|
+
invested={item.invested}
|
|
1743
|
+
value={item.value}
|
|
1744
|
+
returns={item.returns}
|
|
1745
|
+
maturityDate={item.maturityDate}
|
|
1746
|
+
logoType={item.logoType}
|
|
1747
|
+
/>
|
|
1748
|
+
</TouchableOpacity>
|
|
1749
|
+
))}
|
|
1750
|
+
</View>
|
|
1751
|
+
)}
|
|
1752
|
+
|
|
1753
|
+
{/* Tabs */}
|
|
1754
|
+
<View style={styles.tabsContainer}>
|
|
1755
|
+
<View style={styles.tabsRow}>
|
|
1756
|
+
{tabs.map((tab) => (
|
|
1757
|
+
<TouchableOpacity
|
|
1758
|
+
key={tab}
|
|
1759
|
+
style={[
|
|
1760
|
+
styles.tab,
|
|
1761
|
+
activeTab === tab && styles.activeTab
|
|
1762
|
+
]}
|
|
1763
|
+
onPress={() => {
|
|
1764
|
+
// Other tabs filter the data
|
|
1765
|
+
setActiveTab(tab);
|
|
1766
|
+
}}
|
|
1767
|
+
>
|
|
1768
|
+
<Text style={[
|
|
1769
|
+
styles.tabText,
|
|
1770
|
+
activeTab === tab && styles.activeTabText
|
|
1771
|
+
]}>
|
|
1772
|
+
{tab}
|
|
1773
|
+
</Text>
|
|
1774
|
+
</TouchableOpacity>
|
|
1775
|
+
))}
|
|
1776
|
+
</View>
|
|
1777
|
+
</View>
|
|
1778
|
+
|
|
1779
|
+
{/* Filter Status removed as requested */}
|
|
1780
|
+
|
|
1781
|
+
{/* FD List */}
|
|
1782
|
+
<View style={styles.fdOptionsContainer}>
|
|
1783
|
+
{filteredFDList.length > 0 ? (
|
|
1784
|
+
filteredFDList.map((fd: FDItem) => (
|
|
1785
|
+
<FDCard
|
|
1786
|
+
key={fd.id}
|
|
1787
|
+
id={fd.id}
|
|
1788
|
+
name={fd.name}
|
|
1789
|
+
accountNumber={fd.accountNumber}
|
|
1790
|
+
roi={fd.roi}
|
|
1791
|
+
tenure={fd.tenure}
|
|
1792
|
+
amount={fd.amount}
|
|
1793
|
+
maturityDate={fd.maturityDate}
|
|
1794
|
+
status={fd.status as 'active' | 'matured' | 'pending'}
|
|
1795
|
+
creditRating={fd.creditRating}
|
|
1796
|
+
logoType={getLogoTypeForFD(fd)}
|
|
1797
|
+
onPress={(fdId) => {
|
|
1798
|
+
|
|
1799
|
+
|
|
1800
|
+
// Log the selection
|
|
1801
|
+
onSelectFD?.(fdId);
|
|
1802
|
+
|
|
1803
|
+
// Store the selected FD data locally
|
|
1804
|
+
setSelectedFD(fd);
|
|
1805
|
+
|
|
1806
|
+
// Store the selected FD data in Redux for PayNow screen
|
|
1807
|
+
const fdListSelectedData = {
|
|
1808
|
+
id: fd.id,
|
|
1809
|
+
providerId: fd.providerId,
|
|
1810
|
+
name: fd.name,
|
|
1811
|
+
accountNumber: fd.accountNumber,
|
|
1812
|
+
roi: fd.roi,
|
|
1813
|
+
tenure: fd.tenure,
|
|
1814
|
+
amount: fd.amount,
|
|
1815
|
+
maturityDate: fd.maturityDate,
|
|
1816
|
+
status: fd.status as 'active' | 'matured' | 'pending',
|
|
1817
|
+
creditRating: fd.creditRating,
|
|
1818
|
+
// Additional fields for PayNow display
|
|
1819
|
+
companyName: fd.name,
|
|
1820
|
+
fdRate: fd.roi,
|
|
1821
|
+
interestPayout: fd.interestPayout || 'Yearly', // Use FD's interest payout or default
|
|
1822
|
+
};
|
|
1823
|
+
|
|
1824
|
+
dispatch(setFDListSelected(fdListSelectedData));
|
|
1825
|
+
|
|
1826
|
+
// 1st Place: Set onboardingIds when customer taps on any FD from FDList
|
|
1827
|
+
// Start with existing onboardingIds, but prefer the freshly computed ones for this tap.
|
|
1828
|
+
let onboardingIdsForNav: any = onboardingIds;
|
|
1829
|
+
try {
|
|
1830
|
+
let idsToSet: any = { providerId: fd.providerId };
|
|
1831
|
+
|
|
1832
|
+
// If we already have customer applications, enrich onboardingIds
|
|
1833
|
+
try {
|
|
1834
|
+
if (customerApplications && !isCustomerApplicationsEmpty()) {
|
|
1835
|
+
// Normalize list
|
|
1836
|
+
let applicationsData: any[] = [];
|
|
1837
|
+
if (Array.isArray(customerApplications)) {
|
|
1838
|
+
applicationsData = customerApplications;
|
|
1839
|
+
} else if (customerApplications.data && Array.isArray(customerApplications.data)) {
|
|
1840
|
+
applicationsData = customerApplications.data;
|
|
1841
|
+
} else if (customerApplications.applications && Array.isArray(customerApplications.applications)) {
|
|
1842
|
+
applicationsData = customerApplications.applications;
|
|
1843
|
+
}
|
|
1844
|
+
|
|
1845
|
+
if (applicationsData.length > 0) {
|
|
1846
|
+
// Prefer applications that belong to the same provider as the tapped FD
|
|
1847
|
+
const fdProviderIdLower = (fd.providerId || '').toLowerCase();
|
|
1848
|
+
const appsForProvider = applicationsData.filter((a: any) => {
|
|
1849
|
+
const appProviderId =
|
|
1850
|
+
(a.fd_provider_id ||
|
|
1851
|
+
a.fdProviderId ||
|
|
1852
|
+
a.provider_id ||
|
|
1853
|
+
a.providerId ||
|
|
1854
|
+
'').toLowerCase();
|
|
1855
|
+
return appProviderId === fdProviderIdLower;
|
|
1856
|
+
});
|
|
1857
|
+
|
|
1858
|
+
const scopedApplications =
|
|
1859
|
+
appsForProvider.length > 0 ? appsForProvider : applicationsData;
|
|
1860
|
+
|
|
1861
|
+
// Within the scoped list, still prefer the Active application
|
|
1862
|
+
const appData = scopedApplications.find((a: any) => {
|
|
1863
|
+
const s = (a.wf_status || a.status || '').toString();
|
|
1864
|
+
return s === 'Active';
|
|
1865
|
+
}) || scopedApplications[0];
|
|
1866
|
+
|
|
1867
|
+
idsToSet = {
|
|
1868
|
+
workflowInstanceId: appData.workflow_instance_id || appData.workflowInstanceId,
|
|
1869
|
+
applicationId: appData.application_id || appData.applicationId,
|
|
1870
|
+
entityid: appData.entity_id || appData.entityId,
|
|
1871
|
+
customerId: appData.customer_id || appData.customerId,
|
|
1872
|
+
fdId: appData.fd_id || appData.fdId,
|
|
1873
|
+
currentState: appData.current_state || appData.currentState,
|
|
1874
|
+
currentTask: appData.current_task || appData.currentTask,
|
|
1875
|
+
// Check both snake_case (fd_provider_id) and camelCase (fdProviderId) variants
|
|
1876
|
+
providerId: fd.providerId,
|
|
1877
|
+
wfStatus: appData.wf_status || appData.wfStatus,
|
|
1878
|
+
};
|
|
1879
|
+
}
|
|
1880
|
+
}
|
|
1881
|
+
} catch (innerError) {
|
|
1882
|
+
// If enrichment fails, fall back to providerId only
|
|
1883
|
+
}
|
|
1884
|
+
|
|
1885
|
+
dispatch(setOnboardingIds(idsToSet));
|
|
1886
|
+
onboardingIdsForNav = idsToSet;
|
|
1887
|
+
} catch (e) {
|
|
1888
|
+
}
|
|
1889
|
+
|
|
1890
|
+
// Check if this provider has a pending/active FD – show sheet only for that provider
|
|
1891
|
+
const pendingAppForProvider = getPendingOrActiveAppForProvider(applicationsDataNormalized, fd.providerId || '');
|
|
1892
|
+
if (pendingAppForProvider) {
|
|
1893
|
+
setPendingContextApp(pendingAppForProvider);
|
|
1894
|
+
setShowPendingFDBottomSheet(true);
|
|
1895
|
+
} else {
|
|
1896
|
+
// If no active FD, navigate to appropriate SDK FD calculator
|
|
1897
|
+
const fdProviderId = (fd.providerId || '').toLowerCase();
|
|
1898
|
+
const isMahindra = fdProviderId === MahindraProviderId.toLowerCase();
|
|
1899
|
+
const isShriram = fdProviderId === ShriramProviderId.toLowerCase();
|
|
1900
|
+
|
|
1901
|
+
// Check for complete applications and create global data constants
|
|
1902
|
+
let ShriramSDKGlobalData: any = null;
|
|
1903
|
+
let MahindraSDKGlobalData: any = null;
|
|
1904
|
+
|
|
1905
|
+
if (customerApplications && !isCustomerApplicationsEmpty()) {
|
|
1906
|
+
let applicationsData: any[] = [];
|
|
1907
|
+
if (Array.isArray(customerApplications)) {
|
|
1908
|
+
applicationsData = customerApplications;
|
|
1909
|
+
} else if (customerApplications.data && Array.isArray(customerApplications.data)) {
|
|
1910
|
+
applicationsData = customerApplications.data;
|
|
1911
|
+
} else if (customerApplications.applications && Array.isArray(customerApplications.applications)) {
|
|
1912
|
+
applicationsData = customerApplications.applications;
|
|
1913
|
+
}
|
|
1914
|
+
|
|
1915
|
+
// Find complete applications
|
|
1916
|
+
const completeApplications = applicationsData.filter((app: any) => {
|
|
1917
|
+
const status = (app.wf_status || app.status || '').toString().toLowerCase();
|
|
1918
|
+
return status === 'completed' || status === 'complete';
|
|
1919
|
+
});
|
|
1920
|
+
|
|
1921
|
+
// Separate by provider
|
|
1922
|
+
completeApplications.forEach((app: any) => {
|
|
1923
|
+
const appProviderId = (app.fd_provider_id || app.fdProviderId || app.provider_id || app.providerId || '').toLowerCase();
|
|
1924
|
+
if (appProviderId === ShriramProviderId.toLowerCase()) {
|
|
1925
|
+
ShriramSDKGlobalData = app;
|
|
1926
|
+
} else if (appProviderId === MahindraProviderId.toLowerCase()) {
|
|
1927
|
+
MahindraSDKGlobalData = app;
|
|
1928
|
+
}
|
|
1929
|
+
});
|
|
1930
|
+
}
|
|
1931
|
+
|
|
1932
|
+
if (isShriram) {
|
|
1933
|
+
navigate('ExternalSDK', {
|
|
1934
|
+
sdkType: 'shriram',
|
|
1935
|
+
providerId: fd.providerId,
|
|
1936
|
+
fdListSelectedData: fdListSelectedData,
|
|
1937
|
+
masterData: ShriramMasterData,
|
|
1938
|
+
// Use the freshest onboardingIds (from this tap if available)
|
|
1939
|
+
onboardingIds: onboardingIdsForNav,
|
|
1940
|
+
shriramSDKGlobalData: ShriramSDKGlobalData, // Pass complete Shriram application data
|
|
1941
|
+
mahindraSDKGlobalData: MahindraSDKGlobalData, // Pass complete Mahindra application data
|
|
1942
|
+
});
|
|
1943
|
+
} else if (isMahindra) {
|
|
1944
|
+
// Navigate to Mahindra SDK FD calculator
|
|
1945
|
+
navigate('ExternalSDK', {
|
|
1946
|
+
sdkType: 'mahindra',
|
|
1947
|
+
providerId: fd.providerId,
|
|
1948
|
+
fdListSelectedData: fdListSelectedData,
|
|
1949
|
+
masterData: MahindraMasterData,
|
|
1950
|
+
// Use the freshest onboardingIds (from this tap if available)
|
|
1951
|
+
onboardingIds: onboardingIdsForNav,
|
|
1952
|
+
shriramSDKGlobalData: ShriramSDKGlobalData, // Pass complete Shriram application data
|
|
1953
|
+
mahindraSDKGlobalData: MahindraSDKGlobalData, // Pass complete Mahindra application data
|
|
1954
|
+
});
|
|
1955
|
+
} else {
|
|
1956
|
+
// Fallback to default FD calculator
|
|
1957
|
+
onNavigateToFDCalculator?.(fd, masterData);
|
|
1958
|
+
}
|
|
1959
|
+
}
|
|
1960
|
+
}}
|
|
1961
|
+
// onPress={(fdId) => {
|
|
1962
|
+
// const fdProviderId = (fd.providerId || '').toLowerCase();
|
|
1963
|
+
// const isMahindra = fdProviderId === MahindraProviderId.toLowerCase();
|
|
1964
|
+
// const isShriram = fdProviderId === ShriramProviderId.toLowerCase();
|
|
1965
|
+
|
|
1966
|
+
// // Construct FDListSelectedData object
|
|
1967
|
+
// const fdListSelectedData = {
|
|
1968
|
+
// id: fd.id,
|
|
1969
|
+
// providerId: fd.providerId,
|
|
1970
|
+
// name: fd.name,
|
|
1971
|
+
// accountNumber: fd.accountNumber,
|
|
1972
|
+
// roi: fd.roi,
|
|
1973
|
+
// tenure: fd.tenure,
|
|
1974
|
+
// amount: fd.amount,
|
|
1975
|
+
// maturityDate: fd.maturityDate,
|
|
1976
|
+
// status: fd.status as 'active' | 'matured' | 'pending',
|
|
1977
|
+
// creditRating: fd.creditRating,
|
|
1978
|
+
// // Additional fields for PayNow display
|
|
1979
|
+
// companyName: fd.name,
|
|
1980
|
+
// fdRate: fd.roi,
|
|
1981
|
+
// interestPayout: fd.interestPayout || 'Yearly', // Use FD's interest payout or default
|
|
1982
|
+
// };
|
|
1983
|
+
|
|
1984
|
+
// console.log('[FDList][onPress] ===== FD Tapped - Data Logs =====');
|
|
1985
|
+
// console.log('[FDList][onPress] FDListSelectedData:', fdListSelectedData);
|
|
1986
|
+
// console.log('[FDList][onPress] OnboardingIds:', onboardingIds);
|
|
1987
|
+
|
|
1988
|
+
// if (isMahindra) {
|
|
1989
|
+
// console.log('[FDList][onPress] Mahindra MasterData:', MahindraMasterData);
|
|
1990
|
+
// } else if (isShriram) {
|
|
1991
|
+
// console.log('[FDList][onPress] Shriram MasterData:', ShriramMasterData);
|
|
1992
|
+
// } else {
|
|
1993
|
+
// console.log('[FDList][onPress] MasterData (fallback):', masterData || masterDataContext);
|
|
1994
|
+
// }
|
|
1995
|
+
|
|
1996
|
+
// console.log('[FDList][onPress] ====================================');
|
|
1997
|
+
// }}
|
|
1998
|
+
customStyles={customStyles}
|
|
1999
|
+
/>
|
|
2000
|
+
))
|
|
2001
|
+
) : (
|
|
2002
|
+
<View style={styles.noDataContainer}>
|
|
2003
|
+
<Text style={styles.noDataText}>
|
|
2004
|
+
{isLoadingRates || isLoadingApplications ? FD_STRINGS.LOADING_FD_DATA :
|
|
2005
|
+
interestRatesError || customerApplicationsError ? FD_STRINGS.FAILED_TO_LOAD_FD_DATA :
|
|
2006
|
+
fdList.length === 0 ? (!isCustomerApplicationsEmpty() ? FD_STRINGS.NO_CUSTOMER_FDS_FOUND : FD_STRINGS.NO_FD_OPTIONS_AVAILABLE) :
|
|
2007
|
+
`${FD_STRINGS.NO_FDS_FOUND_FOR_TENURE} "${activeTab}" tenure range.`}
|
|
2008
|
+
</Text>
|
|
2009
|
+
|
|
2010
|
+
</View>
|
|
2011
|
+
)}
|
|
2012
|
+
</View>
|
|
2013
|
+
</ScrollView>
|
|
2014
|
+
|
|
2015
|
+
{/* Pending FD Bottom Sheet - shows pending/active FD for the provider they tapped */}
|
|
2016
|
+
<PendingFDBottomSheet
|
|
2017
|
+
visible={showPendingFDBottomSheet}
|
|
2018
|
+
onClose={() => {
|
|
2019
|
+
setShowPendingFDBottomSheet(false);
|
|
2020
|
+
setPendingContextApp(null);
|
|
2021
|
+
}}
|
|
2022
|
+
pendingFDData={pendingFDDataForSheet}
|
|
2023
|
+
isBookingNewLoading={isTerminatingWorkflow}
|
|
2024
|
+
onContinue={async () => {
|
|
2025
|
+
setShowPendingFDBottomSheet(false);
|
|
2026
|
+
const forcedFromSelected = getSdkTypeFromProviderId(
|
|
2027
|
+
selectedFD?.providerId || '',
|
|
2028
|
+
MahindraProviderId,
|
|
2029
|
+
ShriramProviderId
|
|
2030
|
+
) || undefined;
|
|
2031
|
+
await handlePendingFDContinue(undefined, forcedFromSelected);
|
|
2032
|
+
}}
|
|
2033
|
+
onBookNew={async () => {
|
|
2034
|
+
try {
|
|
2035
|
+
// Terminate only the workflow for the provider we're showing (the one they tapped)
|
|
2036
|
+
const appToTerminate = pendingContextApp || (activeFDs.length > 0 ? activeFDs[0].app : null);
|
|
2037
|
+
const providerIdForTerminate = appToTerminate
|
|
2038
|
+
? (appToTerminate.fd_provider_id || appToTerminate.fdProviderId || appToTerminate.provider_id || appToTerminate.providerId)
|
|
2039
|
+
: (selectedFD?.providerId || inferredProviderId);
|
|
2040
|
+
const requestParams = {
|
|
2041
|
+
providerId: providerIdForTerminate,
|
|
2042
|
+
workflowInstanceId: appToTerminate?.workflow_instance_id || appToTerminate?.workflowInstanceId || terminateIdentifiers.workflowInstanceId || 'wf-instance-unknown',
|
|
2043
|
+
entityId: appToTerminate?.entity_id || appToTerminate?.entityId || terminateIdentifiers.entityId || 'entity-unknown',
|
|
2044
|
+
applicationId: appToTerminate?.application_id || appToTerminate?.applicationId || terminateIdentifiers.applicationId || 'application-unknown',
|
|
2045
|
+
} as const;
|
|
2046
|
+
|
|
2047
|
+
// Call workflow terminate API (only for this provider's workflow)
|
|
2048
|
+
await terminateWorkflow(requestParams);
|
|
2049
|
+
|
|
2050
|
+
// 2nd Place: Set onboardingIds when user taps "I want to create new"
|
|
2051
|
+
try {
|
|
2052
|
+
const providerIdToSet = selectedFD?.providerId || inferredProviderId || getProviderIdFromInterestRates();
|
|
2053
|
+
if (providerIdToSet) {
|
|
2054
|
+
const idsToSet = { providerId: providerIdToSet };
|
|
2055
|
+
dispatch(setOnboardingIds(idsToSet));
|
|
2056
|
+
} else {
|
|
2057
|
+
}
|
|
2058
|
+
} catch (e) {
|
|
2059
|
+
}
|
|
2060
|
+
|
|
2061
|
+
// Dismiss bottom sheet
|
|
2062
|
+
setShowPendingFDBottomSheet(false);
|
|
2063
|
+
|
|
2064
|
+
// Navigate to provider-specific SDK (Mahindra/Shriram) just like new FD tap
|
|
2065
|
+
const providerIdToUse = (selectedFD?.providerId || inferredProviderId || getProviderIdFromInterestRates() || '').toLowerCase();
|
|
2066
|
+
const isMahindra = providerIdToUse === MahindraProviderId.toLowerCase();
|
|
2067
|
+
const isShriram = providerIdToUse === ShriramProviderId.toLowerCase();
|
|
2068
|
+
|
|
2069
|
+
// Build fdListSelectedData from selectedFD when available (best effort)
|
|
2070
|
+
const fdListSelectedDataToPass = selectedFD ? {
|
|
2071
|
+
id: selectedFD.id || 'new-fd',
|
|
2072
|
+
providerId: selectedFD.providerId,
|
|
2073
|
+
name: selectedFD.name,
|
|
2074
|
+
accountNumber: selectedFD.accountNumber,
|
|
2075
|
+
roi: selectedFD.roi,
|
|
2076
|
+
tenure: selectedFD.tenure,
|
|
2077
|
+
amount: selectedFD.amount,
|
|
2078
|
+
maturityDate: selectedFD.maturityDate,
|
|
2079
|
+
status: selectedFD.status as 'active' | 'matured' | 'pending' | undefined,
|
|
2080
|
+
creditRating: getStaticCreditRatingForFD({
|
|
2081
|
+
name: selectedFD.name,
|
|
2082
|
+
providerId: selectedFD.providerId,
|
|
2083
|
+
}),
|
|
2084
|
+
companyName: selectedFD.name,
|
|
2085
|
+
fdRate: selectedFD.roi,
|
|
2086
|
+
interestPayout: selectedFD.interestPayout || 'Yearly',
|
|
2087
|
+
} : undefined;
|
|
2088
|
+
|
|
2089
|
+
const masterDataToPass = isMahindra
|
|
2090
|
+
? MahindraMasterData
|
|
2091
|
+
: isShriram
|
|
2092
|
+
? ShriramMasterData
|
|
2093
|
+
: (masterData || masterDataContext);
|
|
2094
|
+
|
|
2095
|
+
// Recompute complete application global data constants (same as tap flow)
|
|
2096
|
+
let ShriramSDKGlobalData: any = null;
|
|
2097
|
+
let MahindraSDKGlobalData: any = null;
|
|
2098
|
+
try {
|
|
2099
|
+
if (customerApplications && !isCustomerApplicationsEmpty()) {
|
|
2100
|
+
let applicationsData: any[] = [];
|
|
2101
|
+
if (Array.isArray(customerApplications)) {
|
|
2102
|
+
applicationsData = customerApplications;
|
|
2103
|
+
} else if (customerApplications.data && Array.isArray(customerApplications.data)) {
|
|
2104
|
+
applicationsData = customerApplications.data;
|
|
2105
|
+
} else if (customerApplications.applications && Array.isArray(customerApplications.applications)) {
|
|
2106
|
+
applicationsData = customerApplications.applications;
|
|
2107
|
+
}
|
|
2108
|
+
|
|
2109
|
+
const completeApplications = applicationsData.filter((app: any) => {
|
|
2110
|
+
const status = (app.wf_status || app.status || '').toString().toLowerCase();
|
|
2111
|
+
return status === 'completed' || status === 'complete';
|
|
2112
|
+
});
|
|
2113
|
+
|
|
2114
|
+
completeApplications.forEach((app: any) => {
|
|
2115
|
+
const appProviderId = (app.fd_provider_id || app.fdProviderId || app.provider_id || app.providerId || '').toLowerCase();
|
|
2116
|
+
if (appProviderId === ShriramProviderId.toLowerCase()) {
|
|
2117
|
+
ShriramSDKGlobalData = app;
|
|
2118
|
+
} else if (appProviderId === MahindraProviderId.toLowerCase()) {
|
|
2119
|
+
MahindraSDKGlobalData = app;
|
|
2120
|
+
}
|
|
2121
|
+
});
|
|
2122
|
+
}
|
|
2123
|
+
} catch (e) {
|
|
2124
|
+
// ignore errors
|
|
2125
|
+
}
|
|
2126
|
+
|
|
2127
|
+
if (isMahindra || isShriram) {
|
|
2128
|
+
navigate('ExternalSDK', {
|
|
2129
|
+
sdkType: isMahindra ? 'mahindra' : 'shriram',
|
|
2130
|
+
providerId: selectedFD?.providerId || inferredProviderId,
|
|
2131
|
+
fdListSelectedData: fdListSelectedDataToPass,
|
|
2132
|
+
masterData: masterDataToPass,
|
|
2133
|
+
onboardingIds: onboardingIds,
|
|
2134
|
+
shriramSDKGlobalData: ShriramSDKGlobalData,
|
|
2135
|
+
mahindraSDKGlobalData: MahindraSDKGlobalData,
|
|
2136
|
+
});
|
|
2137
|
+
} else {
|
|
2138
|
+
// Fallback to host FD calculator
|
|
2139
|
+
onNavigateToFDCalculator?.();
|
|
2140
|
+
}
|
|
2141
|
+
|
|
2142
|
+
} catch (error) {
|
|
2143
|
+
// Handle error silently
|
|
2144
|
+
|
|
2145
|
+
// Still dismiss bottom sheet and navigate even if API fails
|
|
2146
|
+
// setShowPendingFDBottomSheet(false);
|
|
2147
|
+
// onNavigateToFDCalculator?.();
|
|
2148
|
+
|
|
2149
|
+
// Show error alert
|
|
2150
|
+
Alert.alert(
|
|
2151
|
+
'Warning',
|
|
2152
|
+
'Failed to terminate existing workflow, but continuing with new FD booking.',
|
|
2153
|
+
[{ text: 'OK' }]
|
|
2154
|
+
);
|
|
2155
|
+
}
|
|
2156
|
+
}}
|
|
2157
|
+
/>
|
|
2158
|
+
|
|
2159
|
+
{/* Full-screen loader: shown from pending FD tap until navigation completes */}
|
|
2160
|
+
{(isPendingFDLoading || isLoadingMahindraCustomerDetails) && (
|
|
2161
|
+
<View style={styles.loadingOverlay} pointerEvents="auto">
|
|
2162
|
+
<ActivityIndicator size="large" color={colors.primary} />
|
|
2163
|
+
</View>
|
|
2164
|
+
)}
|
|
2165
|
+
</SafeAreaWrapper>
|
|
2166
|
+
);
|
|
2026
2167
|
};
|
|
2027
2168
|
|
|
2028
2169
|
const createStyles = (colors: ColorScheme, typography: any, spacing: any, themeName: ThemeName) => StyleSheet.create({
|
|
2029
|
-
|
|
2030
|
-
|
|
2031
|
-
|
|
2032
|
-
|
|
2033
|
-
|
|
2034
|
-
|
|
2035
|
-
|
|
2036
|
-
|
|
2037
|
-
|
|
2038
|
-
|
|
2039
|
-
|
|
2040
|
-
|
|
2041
|
-
|
|
2042
|
-
|
|
2043
|
-
|
|
2044
|
-
|
|
2045
|
-
|
|
2046
|
-
|
|
2047
|
-
|
|
2048
|
-
|
|
2049
|
-
|
|
2050
|
-
|
|
2051
|
-
|
|
2052
|
-
|
|
2053
|
-
|
|
2054
|
-
|
|
2055
|
-
|
|
2056
|
-
|
|
2057
|
-
|
|
2058
|
-
|
|
2059
|
-
|
|
2060
|
-
|
|
2061
|
-
|
|
2062
|
-
|
|
2063
|
-
|
|
2064
|
-
|
|
2065
|
-
|
|
2066
|
-
|
|
2067
|
-
|
|
2068
|
-
|
|
2069
|
-
|
|
2070
|
-
|
|
2071
|
-
|
|
2072
|
-
|
|
2073
|
-
|
|
2074
|
-
|
|
2075
|
-
|
|
2076
|
-
|
|
2077
|
-
|
|
2078
|
-
|
|
2079
|
-
|
|
2080
|
-
|
|
2081
|
-
|
|
2082
|
-
|
|
2083
|
-
|
|
2084
|
-
|
|
2085
|
-
|
|
2086
|
-
|
|
2087
|
-
|
|
2088
|
-
|
|
2089
|
-
|
|
2090
|
-
|
|
2091
|
-
|
|
2092
|
-
|
|
2093
|
-
|
|
2094
|
-
|
|
2095
|
-
|
|
2096
|
-
|
|
2097
|
-
|
|
2098
|
-
|
|
2099
|
-
|
|
2100
|
-
|
|
2101
|
-
|
|
2102
|
-
|
|
2103
|
-
|
|
2104
|
-
|
|
2105
|
-
|
|
2106
|
-
|
|
2107
|
-
|
|
2108
|
-
|
|
2109
|
-
|
|
2110
|
-
|
|
2111
|
-
|
|
2112
|
-
|
|
2113
|
-
|
|
2114
|
-
|
|
2115
|
-
|
|
2116
|
-
|
|
2117
|
-
|
|
2118
|
-
|
|
2119
|
-
|
|
2120
|
-
|
|
2121
|
-
|
|
2122
|
-
|
|
2123
|
-
|
|
2124
|
-
|
|
2125
|
-
|
|
2126
|
-
|
|
2127
|
-
|
|
2128
|
-
|
|
2129
|
-
|
|
2130
|
-
|
|
2131
|
-
|
|
2132
|
-
|
|
2133
|
-
|
|
2134
|
-
|
|
2135
|
-
|
|
2136
|
-
|
|
2137
|
-
|
|
2138
|
-
|
|
2139
|
-
|
|
2140
|
-
|
|
2141
|
-
|
|
2142
|
-
|
|
2143
|
-
|
|
2144
|
-
|
|
2145
|
-
|
|
2146
|
-
|
|
2147
|
-
|
|
2148
|
-
|
|
2149
|
-
|
|
2150
|
-
|
|
2151
|
-
|
|
2152
|
-
|
|
2153
|
-
|
|
2154
|
-
|
|
2155
|
-
|
|
2156
|
-
|
|
2157
|
-
|
|
2158
|
-
|
|
2159
|
-
|
|
2160
|
-
|
|
2161
|
-
|
|
2162
|
-
|
|
2163
|
-
|
|
2164
|
-
|
|
2165
|
-
|
|
2166
|
-
|
|
2167
|
-
|
|
2168
|
-
|
|
2169
|
-
|
|
2170
|
-
|
|
2171
|
-
|
|
2172
|
-
|
|
2173
|
-
|
|
2174
|
-
|
|
2175
|
-
|
|
2176
|
-
|
|
2177
|
-
|
|
2178
|
-
|
|
2179
|
-
|
|
2180
|
-
|
|
2181
|
-
|
|
2182
|
-
|
|
2183
|
-
|
|
2184
|
-
|
|
2185
|
-
|
|
2186
|
-
|
|
2187
|
-
|
|
2188
|
-
|
|
2189
|
-
|
|
2190
|
-
|
|
2191
|
-
|
|
2192
|
-
|
|
2193
|
-
|
|
2194
|
-
|
|
2195
|
-
|
|
2196
|
-
|
|
2197
|
-
|
|
2198
|
-
|
|
2199
|
-
|
|
2200
|
-
|
|
2201
|
-
|
|
2202
|
-
|
|
2203
|
-
|
|
2204
|
-
|
|
2205
|
-
|
|
2206
|
-
|
|
2207
|
-
|
|
2208
|
-
|
|
2209
|
-
|
|
2210
|
-
|
|
2211
|
-
|
|
2212
|
-
|
|
2213
|
-
|
|
2214
|
-
|
|
2215
|
-
|
|
2216
|
-
|
|
2217
|
-
|
|
2218
|
-
|
|
2219
|
-
|
|
2220
|
-
|
|
2221
|
-
|
|
2170
|
+
container: {
|
|
2171
|
+
flex: 1,
|
|
2172
|
+
backgroundColor: colors.surface,
|
|
2173
|
+
},
|
|
2174
|
+
customHeader: {
|
|
2175
|
+
backgroundColor: colors.headerBg,
|
|
2176
|
+
paddingTop: Platform.OS === 'ios' ? 50 : 20,
|
|
2177
|
+
paddingBottom: spacing.md,
|
|
2178
|
+
paddingHorizontal: spacing.lg,
|
|
2179
|
+
flexDirection: 'row',
|
|
2180
|
+
alignItems: 'center',
|
|
2181
|
+
},
|
|
2182
|
+
backButton: {
|
|
2183
|
+
width: 40,
|
|
2184
|
+
height: 40,
|
|
2185
|
+
alignItems: 'center',
|
|
2186
|
+
justifyContent: 'center',
|
|
2187
|
+
},
|
|
2188
|
+
backIcon: {
|
|
2189
|
+
width: 24,
|
|
2190
|
+
height: 24,
|
|
2191
|
+
tintColor: colors.headerText,
|
|
2192
|
+
},
|
|
2193
|
+
headerContent: {
|
|
2194
|
+
flex: 1,
|
|
2195
|
+
alignItems: 'flex-start',
|
|
2196
|
+
marginRight: 40, // Balance the back button width
|
|
2197
|
+
},
|
|
2198
|
+
headerTitle: {
|
|
2199
|
+
...typography.styles.h3,
|
|
2200
|
+
color: colors.headerText,
|
|
2201
|
+
marginBottom: spacing.xs,
|
|
2202
|
+
},
|
|
2203
|
+
poweredByContainer: {
|
|
2204
|
+
flexDirection: 'row',
|
|
2205
|
+
alignItems: 'center',
|
|
2206
|
+
},
|
|
2207
|
+
poweredByText: {
|
|
2208
|
+
...typography.styles.text10Regular,
|
|
2209
|
+
color: colors.headerText,
|
|
2210
|
+
opacity: 0.7,
|
|
2211
|
+
marginRight: 0,
|
|
2212
|
+
},
|
|
2213
|
+
simplifyLogo: {
|
|
2214
|
+
width: 70,
|
|
2215
|
+
height: 20,
|
|
2216
|
+
},
|
|
2217
|
+
content: {
|
|
2218
|
+
flex: 1,
|
|
2219
|
+
},
|
|
2220
|
+
section: {
|
|
2221
|
+
paddingHorizontal: spacing.lg,
|
|
2222
|
+
paddingTop: spacing.xl,
|
|
2223
|
+
},
|
|
2224
|
+
sectionTitle: {
|
|
2225
|
+
...typography.styles.h3,
|
|
2226
|
+
color: colors.text,
|
|
2227
|
+
marginBottom: spacing.lg,
|
|
2228
|
+
},
|
|
2229
|
+
activeFDCardSpacer: {
|
|
2230
|
+
marginTop: spacing.md,
|
|
2231
|
+
},
|
|
2232
|
+
tabsContainer: {
|
|
2233
|
+
paddingHorizontal: spacing.lg,
|
|
2234
|
+
paddingTop: spacing.xxl,
|
|
2235
|
+
paddingBottom: spacing.lg,
|
|
2236
|
+
},
|
|
2237
|
+
tabsRow: {
|
|
2238
|
+
flexDirection: 'row',
|
|
2239
|
+
justifyContent: 'space-around',
|
|
2240
|
+
alignItems: 'center',
|
|
2241
|
+
},
|
|
2242
|
+
tab: {
|
|
2243
|
+
flex: 1,
|
|
2244
|
+
paddingHorizontal: spacing.sm,
|
|
2245
|
+
paddingVertical: spacing.md,
|
|
2246
|
+
marginHorizontal: 2,
|
|
2247
|
+
borderBottomWidth: 3,
|
|
2248
|
+
borderBottomColor: colors.surface,
|
|
2249
|
+
borderBottomLeftRadius: 8,
|
|
2250
|
+
borderBottomRightRadius: 8,
|
|
2251
|
+
backgroundColor: 'transparent',
|
|
2252
|
+
},
|
|
2253
|
+
activeTab: {
|
|
2254
|
+
borderBottomColor: colors.tabSelected,
|
|
2255
|
+
backgroundColor: colors.background,
|
|
2256
|
+
borderBottomLeftRadius: 12,
|
|
2257
|
+
borderBottomRightRadius: 12,
|
|
2258
|
+
},
|
|
2259
|
+
tabText: {
|
|
2260
|
+
...typography.styles.text12Medium,
|
|
2261
|
+
color: colors.textSecondary,
|
|
2262
|
+
textAlign: 'center',
|
|
2263
|
+
},
|
|
2264
|
+
activeTabText: {
|
|
2265
|
+
color: colors.tabSelected,
|
|
2266
|
+
fontWeight: '600',
|
|
2267
|
+
textAlign: 'center',
|
|
2268
|
+
},
|
|
2269
|
+
filterStatusContainer: {
|
|
2270
|
+
paddingHorizontal: spacing.lg,
|
|
2271
|
+
paddingVertical: spacing.sm,
|
|
2272
|
+
backgroundColor: colors.background + '80', // 50% opacity
|
|
2273
|
+
borderBottomWidth: 1,
|
|
2274
|
+
borderBottomColor: colors.border + '20', // 20% opacity
|
|
2275
|
+
},
|
|
2276
|
+
filterStatusText: {
|
|
2277
|
+
...typography.styles.text12Regular,
|
|
2278
|
+
color: colors.textSecondary,
|
|
2279
|
+
textAlign: 'center',
|
|
2280
|
+
fontStyle: 'italic',
|
|
2281
|
+
},
|
|
2282
|
+
fdOptionsContainer: {
|
|
2283
|
+
paddingHorizontal: spacing.lg,
|
|
2284
|
+
paddingBottom: spacing.xl,
|
|
2285
|
+
},
|
|
2286
|
+
// API Status Styles
|
|
2287
|
+
apiStatusContainer: {
|
|
2288
|
+
flexDirection: 'row',
|
|
2289
|
+
justifyContent: 'space-between',
|
|
2290
|
+
alignItems: 'center',
|
|
2291
|
+
paddingHorizontal: spacing.lg,
|
|
2292
|
+
paddingVertical: spacing.sm,
|
|
2293
|
+
backgroundColor: colors.background,
|
|
2294
|
+
borderBottomWidth: 1,
|
|
2295
|
+
borderBottomColor: colors.border + '20', // 20% opacity
|
|
2296
|
+
},
|
|
2297
|
+
apiStatusIndicator: {
|
|
2298
|
+
flexDirection: 'row',
|
|
2299
|
+
alignItems: 'center',
|
|
2300
|
+
flex: 1,
|
|
2301
|
+
},
|
|
2302
|
+
apiStatusText: {
|
|
2303
|
+
...typography.styles.text10Regular,
|
|
2304
|
+
color: colors.textSecondary,
|
|
2305
|
+
marginLeft: spacing.xs,
|
|
2306
|
+
},
|
|
2307
|
+
apiSuccessText: {
|
|
2308
|
+
...typography.styles.text10Regular,
|
|
2309
|
+
color: colors.success,
|
|
2310
|
+
marginLeft: spacing.xs,
|
|
2311
|
+
},
|
|
2312
|
+
apiErrorText: {
|
|
2313
|
+
...typography.styles.text10Regular,
|
|
2314
|
+
color: colors.error,
|
|
2315
|
+
marginLeft: spacing.xs,
|
|
2316
|
+
},
|
|
2317
|
+
refreshButton: {
|
|
2318
|
+
paddingHorizontal: spacing.sm,
|
|
2319
|
+
paddingVertical: spacing.xs,
|
|
2320
|
+
backgroundColor: colors.primary + '20', // 20% opacity
|
|
2321
|
+
borderRadius: spacing.xs,
|
|
2322
|
+
},
|
|
2323
|
+
refreshButtonText: {
|
|
2324
|
+
...typography.styles.text10Medium,
|
|
2325
|
+
color: colors.primary,
|
|
2326
|
+
},
|
|
2327
|
+
noDataContainer: {
|
|
2328
|
+
padding: spacing.lg,
|
|
2329
|
+
alignItems: 'center',
|
|
2330
|
+
justifyContent: 'center',
|
|
2331
|
+
minHeight: 200,
|
|
2332
|
+
},
|
|
2333
|
+
noDataText: {
|
|
2334
|
+
...typography.styles.text14Regular,
|
|
2335
|
+
color: colors.textSecondary,
|
|
2336
|
+
textAlign: 'center',
|
|
2337
|
+
lineHeight: 20,
|
|
2338
|
+
marginBottom: spacing.md,
|
|
2339
|
+
},
|
|
2340
|
+
showAllButton: {
|
|
2341
|
+
backgroundColor: colors.primary,
|
|
2342
|
+
paddingHorizontal: spacing.lg,
|
|
2343
|
+
paddingVertical: spacing.sm,
|
|
2344
|
+
borderRadius: spacing.sm,
|
|
2345
|
+
marginTop: spacing.md,
|
|
2346
|
+
},
|
|
2347
|
+
showAllButtonText: {
|
|
2348
|
+
...typography.styles.text14Medium,
|
|
2349
|
+
color: colors.headerText,
|
|
2350
|
+
textAlign: 'center',
|
|
2351
|
+
},
|
|
2352
|
+
loadingOverlay: {
|
|
2353
|
+
position: 'absolute',
|
|
2354
|
+
top: 0,
|
|
2355
|
+
left: 0,
|
|
2356
|
+
right: 0,
|
|
2357
|
+
bottom: 0,
|
|
2358
|
+
backgroundColor: 'rgba(0, 0, 0, 0.3)',
|
|
2359
|
+
justifyContent: 'center',
|
|
2360
|
+
alignItems: 'center',
|
|
2361
|
+
zIndex: 1000,
|
|
2362
|
+
},
|
|
2222
2363
|
});
|
|
2223
2364
|
|
|
2224
2365
|
export default FDList;
|