@finspringinnovations/fixeddepositsdk 1.0.2 → 1.0.3
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/components/PendingFDBottomSheet.js +27 -18
- package/lib/config/appDataConfig.js +3 -2
- package/lib/constants/strings/fd.d.ts +2 -2
- package/lib/constants/strings/fd.js +2 -2
- package/lib/navigation/RootNavigator.js +121 -131
- package/lib/screens/FDCalculator.js +1 -1
- package/lib/screens/FDList.js +34 -33
- package/lib/screens/PaymentStatus.js +13 -0
- package/lib/screens/ReviewKYC.js +2 -1
- package/package.json +50 -50
- package/src/components/PendingFDBottomSheet.tsx +151 -123
- package/src/config/appDataConfig.ts +245 -242
- package/src/constants/strings/fd.ts +2 -2
- package/src/navigation/RootNavigator.tsx +186 -153
- package/src/screens/FDCalculator.tsx +3 -3
- package/src/screens/FDList.tsx +35 -34
- package/src/screens/PaymentStatus.tsx +16 -4
- package/src/screens/ReviewKYC.tsx +1 -0
|
@@ -24,7 +24,7 @@ const PendingFDBottomSheet = ({ visible, onClose, onContinue, onBookNew, pending
|
|
|
24
24
|
return (react_1.default.createElement(react_native_1.Modal, { visible: visible, transparent: true, animationType: "slide", onRequestClose: onClose },
|
|
25
25
|
react_1.default.createElement(react_native_1.View, { style: styles.overlay },
|
|
26
26
|
react_1.default.createElement(react_native_1.View, { style: styles.bottomSheet },
|
|
27
|
-
react_1.default.createElement(react_native_1.SafeAreaView,
|
|
27
|
+
react_1.default.createElement(react_native_1.SafeAreaView, null,
|
|
28
28
|
react_1.default.createElement(react_native_1.View, { style: styles.header },
|
|
29
29
|
react_1.default.createElement(react_native_1.View, { style: styles.headerContent },
|
|
30
30
|
react_1.default.createElement(react_native_1.Text, { style: styles.title }, "Please Wait! You also have a pending journey with progress saved:"),
|
|
@@ -33,16 +33,20 @@ const PendingFDBottomSheet = ({ visible, onClose, onContinue, onBookNew, pending
|
|
|
33
33
|
react_1.default.createElement(react_native_1.View, { style: styles.content },
|
|
34
34
|
react_1.default.createElement(react_native_1.Text, { style: styles.sectionTitle }, "Pending FDs"),
|
|
35
35
|
react_1.default.createElement(ActiveFDCard_1.default, { name: pendingFDData.name, invested: pendingFDData.invested, value: pendingFDData.value, returns: pendingFDData.returns, maturityDate: pendingFDData.maturityDate, logoType: pendingFDData.logoType }),
|
|
36
|
-
react_1.default.createElement(react_native_1.
|
|
36
|
+
react_1.default.createElement(react_native_1.View, { style: { height: 24 } }),
|
|
37
|
+
react_1.default.createElement(react_native_1.TouchableOpacity, { style: [
|
|
38
|
+
styles.bookNewButton,
|
|
39
|
+
isBookingNewLoading && styles.disabledButton,
|
|
40
|
+
], onPress: onBookNew, disabled: isBookingNewLoading }, isBookingNewLoading ? (react_1.default.createElement(react_native_1.View, { style: styles.loadingContainer },
|
|
37
41
|
react_1.default.createElement(react_native_1.ActivityIndicator, { size: "small", color: colors.primary }),
|
|
38
42
|
react_1.default.createElement(react_native_1.Text, { style: [styles.bookNewText, { marginLeft: spacing.sm }] }, "Terminating workflow..."))) : (react_1.default.createElement(react_native_1.Text, { style: styles.bookNewText }, "No, I want to book a new FD"))),
|
|
39
|
-
themeName === 'dark' ? (react_1.default.createElement(ActionButton_1.default, { title: "Continue", onPress: onContinue, variant: "primary", style: styles.continueButtonWrapper })) : (react_1.default.createElement(react_native_1.TouchableOpacity, { style: styles.continueButton, onPress: onContinue },
|
|
40
|
-
react_1.default.createElement(react_native_1.Text, { style: styles.continueButtonText }, "Continue")))))))));
|
|
43
|
+
react_1.default.createElement(react_native_1.View, { style: styles.footer }, themeName === 'dark' ? (react_1.default.createElement(ActionButton_1.default, { title: "Continue", onPress: onContinue, variant: "primary", style: styles.continueButtonWrapper })) : (react_1.default.createElement(react_native_1.TouchableOpacity, { style: styles.continueButton, onPress: onContinue },
|
|
44
|
+
react_1.default.createElement(react_native_1.Text, { style: styles.continueButtonText }, "Continue"))))))))));
|
|
41
45
|
};
|
|
42
46
|
const createStyles = (colors, typography, spacing, themeName) => react_native_1.StyleSheet.create({
|
|
43
47
|
overlay: {
|
|
44
48
|
flex: 1,
|
|
45
|
-
backgroundColor: 'rgba(0,
|
|
49
|
+
backgroundColor: 'rgba(0,0,0,0.5)',
|
|
46
50
|
justifyContent: 'flex-end',
|
|
47
51
|
},
|
|
48
52
|
bottomSheet: {
|
|
@@ -53,10 +57,6 @@ const createStyles = (colors, typography, spacing, themeName) => react_native_1.
|
|
|
53
57
|
borderWidth: themeName === 'dark' ? 1 : 0,
|
|
54
58
|
borderColor: themeName === 'dark' ? '#ffffff' : 'transparent',
|
|
55
59
|
maxHeight: react_native_1.Dimensions.get('window').height * 0.8,
|
|
56
|
-
minHeight: react_native_1.Platform.OS === 'ios' ? 430 : 400,
|
|
57
|
-
},
|
|
58
|
-
safeArea: {
|
|
59
|
-
flex: 1,
|
|
60
60
|
},
|
|
61
61
|
header: {
|
|
62
62
|
paddingHorizontal: spacing.lg,
|
|
@@ -69,7 +69,7 @@ const createStyles = (colors, typography, spacing, themeName) => react_native_1.
|
|
|
69
69
|
alignItems: 'flex-start',
|
|
70
70
|
},
|
|
71
71
|
title: {
|
|
72
|
-
fontSize:
|
|
72
|
+
fontSize: 15,
|
|
73
73
|
fontWeight: '500',
|
|
74
74
|
color: themeName === 'dark' ? colors.labelColor : '#333',
|
|
75
75
|
flex: 1,
|
|
@@ -85,18 +85,25 @@ const createStyles = (colors, typography, spacing, themeName) => react_native_1.
|
|
|
85
85
|
alignItems: 'center',
|
|
86
86
|
},
|
|
87
87
|
content: {
|
|
88
|
-
flex: 1,
|
|
89
88
|
paddingHorizontal: spacing.lg,
|
|
90
89
|
paddingTop: spacing.lg,
|
|
91
|
-
paddingBottom: react_native_1.Platform.OS === 'ios' ? 20 :
|
|
90
|
+
paddingBottom: react_native_1.Platform.OS === 'ios' ? 20 : spacing.lg,
|
|
92
91
|
},
|
|
93
|
-
sectionTitle: Object.assign(Object.assign({}, typography.styles.
|
|
92
|
+
sectionTitle: Object.assign(Object.assign({}, typography.styles.h4), { color: themeName === 'dark' ? colors.labelColor : '#333', marginBottom: spacing.md }),
|
|
94
93
|
bookNewButton: {
|
|
95
|
-
marginTop: spacing.
|
|
96
|
-
marginBottom: spacing.
|
|
94
|
+
marginTop: spacing.xl,
|
|
95
|
+
marginBottom: spacing.xl,
|
|
97
96
|
alignItems: 'center',
|
|
97
|
+
justifyContent: 'center',
|
|
98
|
+
paddingVertical: 12,
|
|
99
|
+
paddingHorizontal: spacing.lg,
|
|
100
|
+
borderWidth: 1,
|
|
101
|
+
borderColor: themeName === 'dark' ? colors.labelColor : '#333',
|
|
102
|
+
borderRadius: themeName === 'dark' ? 10 : 30,
|
|
103
|
+
width: 330,
|
|
104
|
+
alignSelf: 'center',
|
|
98
105
|
},
|
|
99
|
-
bookNewText: Object.assign(Object.assign({}, typography.styles.
|
|
106
|
+
bookNewText: Object.assign(Object.assign({}, typography.styles.buttonSmall), { color: themeName === 'dark' ? colors.labelColor : '#000' }),
|
|
100
107
|
disabledButton: {
|
|
101
108
|
opacity: 0.6,
|
|
102
109
|
},
|
|
@@ -105,6 +112,9 @@ const createStyles = (colors, typography, spacing, themeName) => react_native_1.
|
|
|
105
112
|
alignItems: 'center',
|
|
106
113
|
justifyContent: 'center',
|
|
107
114
|
},
|
|
115
|
+
footer: {
|
|
116
|
+
paddingTop: spacing.sm,
|
|
117
|
+
},
|
|
108
118
|
continueButtonWrapper: {
|
|
109
119
|
marginBottom: react_native_1.Platform.OS === 'ios' ? spacing.lg + 20 : spacing.lg,
|
|
110
120
|
},
|
|
@@ -112,11 +122,10 @@ const createStyles = (colors, typography, spacing, themeName) => react_native_1.
|
|
|
112
122
|
height: 50,
|
|
113
123
|
backgroundColor: '#007AFF',
|
|
114
124
|
borderRadius: 25,
|
|
115
|
-
paddingHorizontal: spacing.lg,
|
|
116
125
|
alignItems: 'center',
|
|
117
126
|
justifyContent: 'center',
|
|
118
127
|
marginBottom: react_native_1.Platform.OS === 'ios' ? spacing.lg + 20 : spacing.lg,
|
|
119
128
|
},
|
|
120
|
-
continueButtonText: Object.assign(Object.assign({}, typography.styles.button), { color: '
|
|
129
|
+
continueButtonText: Object.assign(Object.assign({}, typography.styles.button), { color: '#fff', fontWeight: '600', fontSize: 16 }),
|
|
121
130
|
});
|
|
122
131
|
exports.default = PendingFDBottomSheet;
|
|
@@ -86,6 +86,7 @@ const initializeSDK = (appData, onValidationError) => {
|
|
|
86
86
|
// Import and call environment logging
|
|
87
87
|
Promise.resolve().then(() => __importStar(require('./apiConfig'))).then(({ logEnvironmentInfo }) => {
|
|
88
88
|
logEnvironmentInfo();
|
|
89
|
+
console.log('SDK initialized with app data:', { logEnvironmentInfo });
|
|
89
90
|
});
|
|
90
91
|
};
|
|
91
92
|
exports.initializeSDK = initializeSDK;
|
|
@@ -274,7 +275,7 @@ const setSDKColors = (customColors) => {
|
|
|
274
275
|
// Best-effort: propagate to external SDKs when they are available
|
|
275
276
|
try {
|
|
276
277
|
// eslint-disable-next-line @typescript-eslint/no-var-requires
|
|
277
|
-
const shriram = require('@finspringinnovations/
|
|
278
|
+
const shriram = require('@finspringinnovations/shriramfdsdk');
|
|
278
279
|
if (shriram && typeof shriram.setSDKColors === 'function') {
|
|
279
280
|
shriram.setSDKColors(customColors);
|
|
280
281
|
}
|
|
@@ -284,7 +285,7 @@ const setSDKColors = (customColors) => {
|
|
|
284
285
|
}
|
|
285
286
|
try {
|
|
286
287
|
// eslint-disable-next-line @typescript-eslint/no-var-requires
|
|
287
|
-
const mahindra = require('@finspringinnovations/
|
|
288
|
+
const mahindra = require('@finspringinnovations/mahindrafdsdk');
|
|
288
289
|
if (mahindra && typeof mahindra.setSDKColors === 'function') {
|
|
289
290
|
mahindra.setSDKColors(customColors);
|
|
290
291
|
}
|
|
@@ -86,7 +86,7 @@ export declare const FD_STRINGS: {
|
|
|
86
86
|
readonly AMOUNT_NOTE: "Note: The entered amount should be in multiples of ₹1000";
|
|
87
87
|
readonly AMOUNT_MIN_MAX: "Min: ₹5 K | Max: ₹5 Cr";
|
|
88
88
|
readonly AMOUNT_MULTIPLES_ERROR: "Amount must be in multiples of ₹1,000";
|
|
89
|
-
readonly SENIOR_CITIZEN_BENEFIT: "+0.
|
|
89
|
+
readonly SENIOR_CITIZEN_BENEFIT: "+0.5% p.a. more for senior citizens";
|
|
90
90
|
readonly TAX_RESIDENT_CONFIRMATION: "I confirm I am a tax resident of India";
|
|
91
91
|
readonly TAX_RESIDENT_ERROR: "Please confirm that you are a tax resident of India to proceed";
|
|
92
92
|
readonly WITHDRAWAL_INFO: "Withdrawal allowed after 3 months";
|
|
@@ -95,7 +95,7 @@ export declare const FD_STRINGS: {
|
|
|
95
95
|
readonly TRUSTED_BY: "Trusted By ";
|
|
96
96
|
readonly CRORES_INDIANS: "4.6 Crores Indians";
|
|
97
97
|
readonly AAA_RATING: "Stable Rating";
|
|
98
|
-
readonly RATING: "
|
|
98
|
+
readonly RATING: "AAA";
|
|
99
99
|
readonly TENURE_12_MONTHS: "12 Months";
|
|
100
100
|
readonly TENURE_24_MONTHS: "24 Months";
|
|
101
101
|
readonly TENURE_36_MONTHS: "36 Months";
|
|
@@ -106,7 +106,7 @@ exports.FD_STRINGS = {
|
|
|
106
106
|
AMOUNT_MIN_MAX: 'Min: ₹5 K | Max: ₹5 Cr',
|
|
107
107
|
AMOUNT_MULTIPLES_ERROR: 'Amount must be in multiples of ₹1,000',
|
|
108
108
|
// Senior citizen benefits
|
|
109
|
-
SENIOR_CITIZEN_BENEFIT: '+0.
|
|
109
|
+
SENIOR_CITIZEN_BENEFIT: '+0.5% p.a. more for senior citizens',
|
|
110
110
|
// Tax resident confirmation
|
|
111
111
|
TAX_RESIDENT_CONFIRMATION: 'I confirm I am a tax resident of India',
|
|
112
112
|
TAX_RESIDENT_ERROR: 'Please confirm that you are a tax resident of India to proceed',
|
|
@@ -119,7 +119,7 @@ exports.FD_STRINGS = {
|
|
|
119
119
|
TRUSTED_BY: 'Trusted By ',
|
|
120
120
|
CRORES_INDIANS: '4.6 Crores Indians',
|
|
121
121
|
AAA_RATING: 'Stable Rating',
|
|
122
|
-
RATING: '
|
|
122
|
+
RATING: 'AAA',
|
|
123
123
|
// Fallback tenure options
|
|
124
124
|
TENURE_12_MONTHS: '12 Months',
|
|
125
125
|
TENURE_24_MONTHS: '24 Months',
|
|
@@ -67,10 +67,129 @@ const MasterDataProvider_1 = require("../providers/MasterDataProvider");
|
|
|
67
67
|
const ThemeContext_1 = require("../theme/ThemeContext");
|
|
68
68
|
const Stack = (0, stack_1.createStackNavigator)();
|
|
69
69
|
const MahindraRootNavigatorAny = mahindrafdsdk_1.RootNavigator;
|
|
70
|
+
const ShriramSDKContent = ({ masterData, routeParams, onSDKExit, onSDKPanRequired, }) => {
|
|
71
|
+
const { setMasterData } = (0, shriramfdsdk_1.useMasterData)();
|
|
72
|
+
const shriramDispatch = (0, shriramfdsdk_1.useAppDispatch)();
|
|
73
|
+
react_1.default.useEffect(() => {
|
|
74
|
+
if (masterData) {
|
|
75
|
+
const dataToSet = masterData.data || masterData;
|
|
76
|
+
setMasterData(dataToSet);
|
|
77
|
+
}
|
|
78
|
+
}, [masterData, setMasterData]);
|
|
79
|
+
react_1.default.useEffect(() => {
|
|
80
|
+
if (routeParams.fdListSelectedData) {
|
|
81
|
+
try {
|
|
82
|
+
shriramDispatch((0, shriramfdsdk_1.setFDListSelected)(routeParams.fdListSelectedData));
|
|
83
|
+
}
|
|
84
|
+
catch (e) {
|
|
85
|
+
console.log('[RootNavigator] Error setting Shriram FDListSelected:', e);
|
|
86
|
+
}
|
|
87
|
+
}
|
|
88
|
+
}, [routeParams.fdListSelectedData, shriramDispatch]);
|
|
89
|
+
react_1.default.useEffect(() => {
|
|
90
|
+
var _a;
|
|
91
|
+
if (routeParams.onboardingIds) {
|
|
92
|
+
try {
|
|
93
|
+
shriramDispatch((0, shriramfdsdk_1.setOnboardingIds)(Object.assign(Object.assign({}, routeParams.onboardingIds), { providerId: routeParams.providerId || ((_a = routeParams.onboardingIds) === null || _a === void 0 ? void 0 : _a.providerId) })));
|
|
94
|
+
}
|
|
95
|
+
catch (e) {
|
|
96
|
+
console.log('[RootNavigator] Error setting Shriram OnboardingIds:', e);
|
|
97
|
+
}
|
|
98
|
+
}
|
|
99
|
+
}, [routeParams.onboardingIds, shriramDispatch]);
|
|
100
|
+
react_1.default.useEffect(() => {
|
|
101
|
+
if (routeParams.shriramSDKGlobalData) {
|
|
102
|
+
try {
|
|
103
|
+
const completeFDData = !!routeParams.shriramSDKGlobalData;
|
|
104
|
+
(0, shriramfdsdk_1.setGlobalData)({ completeFDData });
|
|
105
|
+
}
|
|
106
|
+
catch (e) {
|
|
107
|
+
console.log('[RootNavigator] Error setting Shriram GlobalData:', e);
|
|
108
|
+
}
|
|
109
|
+
}
|
|
110
|
+
}, [routeParams.shriramSDKGlobalData]);
|
|
111
|
+
return (react_1.default.createElement(shriramfdsdk_1.RootNavigator, { config: {
|
|
112
|
+
initialRouteName: routeParams.initialRouteName || 'FDCalculator',
|
|
113
|
+
initialPaymentStatusParams: routeParams.initialPaymentStatusParams,
|
|
114
|
+
initialFDContext: {
|
|
115
|
+
providerId: routeParams.providerId,
|
|
116
|
+
fdListSelectedData: routeParams.fdListSelectedData,
|
|
117
|
+
completeFDData: routeParams.completeFDData,
|
|
118
|
+
},
|
|
119
|
+
}, onExit: onSDKExit, onPanRequired: onSDKPanRequired }));
|
|
120
|
+
};
|
|
121
|
+
const MahindraSDKContent = ({ masterData, routeParams, onSDKExit, onSDKPanRequired, }) => {
|
|
122
|
+
const { setMasterData } = (0, mahindrafdsdk_1.useMasterData)();
|
|
123
|
+
const mahindraDispatch = (0, mahindrafdsdk_1.useAppDispatch)();
|
|
124
|
+
react_1.default.useEffect(() => {
|
|
125
|
+
if (masterData) {
|
|
126
|
+
const dataToSet = masterData.data || masterData;
|
|
127
|
+
setMasterData(dataToSet);
|
|
128
|
+
}
|
|
129
|
+
}, [masterData, setMasterData]);
|
|
130
|
+
react_1.default.useEffect(() => {
|
|
131
|
+
if (routeParams.fdListSelectedData) {
|
|
132
|
+
try {
|
|
133
|
+
mahindraDispatch((0, mahindrafdsdk_1.setFDListSelected)(routeParams.fdListSelectedData));
|
|
134
|
+
}
|
|
135
|
+
catch (e) {
|
|
136
|
+
console.log('[RootNavigator] Error setting Mahindra FDListSelected:', e);
|
|
137
|
+
}
|
|
138
|
+
}
|
|
139
|
+
}, [routeParams.fdListSelectedData, mahindraDispatch]);
|
|
140
|
+
react_1.default.useEffect(() => {
|
|
141
|
+
var _a;
|
|
142
|
+
if (routeParams.onboardingIds) {
|
|
143
|
+
try {
|
|
144
|
+
mahindraDispatch((0, mahindrafdsdk_1.setOnboardingIds)(Object.assign(Object.assign({}, routeParams.onboardingIds), { providerId: routeParams.providerId || ((_a = routeParams.onboardingIds) === null || _a === void 0 ? void 0 : _a.providerId) })));
|
|
145
|
+
}
|
|
146
|
+
catch (e) {
|
|
147
|
+
console.log('[RootNavigator] Error setting Mahindra OnboardingIds:', e);
|
|
148
|
+
}
|
|
149
|
+
}
|
|
150
|
+
}, [routeParams.onboardingIds, mahindraDispatch]);
|
|
151
|
+
return (react_1.default.createElement(MahindraRootNavigatorAny, { config: {
|
|
152
|
+
initialRouteName: routeParams.initialRouteName || 'FDCalculator',
|
|
153
|
+
forceFetchCustomerDetails: !!routeParams.forceFetchCustomerDetails,
|
|
154
|
+
initialFDContext: {
|
|
155
|
+
providerId: routeParams.providerId,
|
|
156
|
+
fdListSelectedData: routeParams.fdListSelectedData,
|
|
157
|
+
completeFDData: routeParams.completeFDData,
|
|
158
|
+
},
|
|
159
|
+
}, onExit: onSDKExit, onPanRequired: onSDKPanRequired }));
|
|
160
|
+
};
|
|
70
161
|
const RootNavigator = ({ config = {}, onExit, onPanRequired, }) => {
|
|
71
162
|
// State to track external SDK navigation
|
|
72
163
|
const [externalSDK, setExternalSDK] = react_1.default.useState(null);
|
|
73
164
|
const [externalSDKFDData, setExternalSDKFDData] = react_1.default.useState(null);
|
|
165
|
+
// Stable exit callbacks — defined here so they're memoized across renders
|
|
166
|
+
// and can be passed as stable props to the module-level SDK content components.
|
|
167
|
+
const handleShriramExit = react_1.default.useCallback((fdDetails) => {
|
|
168
|
+
setExternalSDK(null);
|
|
169
|
+
setExternalSDKFDData(null);
|
|
170
|
+
(0, helpers_2.navigate)('FDList');
|
|
171
|
+
if (fdDetails)
|
|
172
|
+
onExit === null || onExit === void 0 ? void 0 : onExit(fdDetails);
|
|
173
|
+
}, [onExit]);
|
|
174
|
+
const handleShriramPanRequired = react_1.default.useCallback(() => {
|
|
175
|
+
setExternalSDK(null);
|
|
176
|
+
setExternalSDKFDData(null);
|
|
177
|
+
onPanRequired === null || onPanRequired === void 0 ? void 0 : onPanRequired();
|
|
178
|
+
onExit === null || onExit === void 0 ? void 0 : onExit();
|
|
179
|
+
}, [onExit, onPanRequired]);
|
|
180
|
+
const handleMahindraExit = react_1.default.useCallback((fdDetails) => {
|
|
181
|
+
setExternalSDK(null);
|
|
182
|
+
setExternalSDKFDData(null);
|
|
183
|
+
(0, helpers_2.navigate)('FDList');
|
|
184
|
+
if (fdDetails)
|
|
185
|
+
onExit === null || onExit === void 0 ? void 0 : onExit(fdDetails);
|
|
186
|
+
}, [onExit]);
|
|
187
|
+
const handleMahindraPanRequired = react_1.default.useCallback(() => {
|
|
188
|
+
setExternalSDK(null);
|
|
189
|
+
setExternalSDKFDData(null);
|
|
190
|
+
onPanRequired === null || onPanRequired === void 0 ? void 0 : onPanRequired();
|
|
191
|
+
onExit === null || onExit === void 0 ? void 0 : onExit();
|
|
192
|
+
}, [onExit, onPanRequired]);
|
|
74
193
|
// Get master data and theme from fdsdk – same theme (and themeName for dark/primary) is passed to Shriram and Mahindra
|
|
75
194
|
const { masterData } = (0, MasterDataProvider_1.useMasterData)();
|
|
76
195
|
const { theme: fdsdkTheme, themeName: fdsdkThemeName } = (0, ThemeContext_1.useTheme)();
|
|
@@ -248,142 +367,13 @@ const RootNavigator = ({ config = {}, onExit, onPanRequired, }) => {
|
|
|
248
367
|
if (!ok)
|
|
249
368
|
return null;
|
|
250
369
|
}
|
|
251
|
-
// Component to set master data and initial FD context in external SDK
|
|
252
|
-
const ShriramSDKWithMasterData = ({ masterData }) => {
|
|
253
|
-
const { setMasterData } = (0, shriramfdsdk_1.useMasterData)();
|
|
254
|
-
const shriramDispatch = (0, shriramfdsdk_1.useAppDispatch)();
|
|
255
|
-
const routeParams = props.route.params || {};
|
|
256
|
-
// Set master data
|
|
257
|
-
react_1.default.useEffect(() => {
|
|
258
|
-
if (masterData) {
|
|
259
|
-
const dataToSet = masterData.data || masterData;
|
|
260
|
-
setMasterData(dataToSet);
|
|
261
|
-
}
|
|
262
|
-
}, [masterData, setMasterData]);
|
|
263
|
-
// Set FDListSelectedData using Shriram setter
|
|
264
|
-
react_1.default.useEffect(() => {
|
|
265
|
-
if (routeParams.fdListSelectedData) {
|
|
266
|
-
try {
|
|
267
|
-
shriramDispatch((0, shriramfdsdk_1.setFDListSelected)(routeParams.fdListSelectedData));
|
|
268
|
-
}
|
|
269
|
-
catch (e) {
|
|
270
|
-
console.log('[RootNavigator] Error setting Shriram FDListSelected:', e);
|
|
271
|
-
}
|
|
272
|
-
}
|
|
273
|
-
}, [routeParams.fdListSelectedData, shriramDispatch]);
|
|
274
|
-
// Set OnboardingIds using Shriram setter
|
|
275
|
-
react_1.default.useEffect(() => {
|
|
276
|
-
var _a;
|
|
277
|
-
if (routeParams.onboardingIds) {
|
|
278
|
-
try {
|
|
279
|
-
shriramDispatch((0, shriramfdsdk_1.setOnboardingIds)(Object.assign(Object.assign({}, routeParams.onboardingIds), { providerId: routeParams.providerId || ((_a = routeParams.onboardingIds) === null || _a === void 0 ? void 0 : _a.providerId) })));
|
|
280
|
-
}
|
|
281
|
-
catch (e) {
|
|
282
|
-
console.log('[RootNavigator] Error setting Shriram OnboardingIds:', e);
|
|
283
|
-
}
|
|
284
|
-
}
|
|
285
|
-
}, [routeParams.onboardingIds, shriramDispatch]);
|
|
286
|
-
// Set GlobalData using Shriram setter if present - only set completeFDData boolean
|
|
287
|
-
react_1.default.useEffect(() => {
|
|
288
|
-
if (routeParams.shriramSDKGlobalData) {
|
|
289
|
-
try {
|
|
290
|
-
const completeFDData = !!routeParams.shriramSDKGlobalData;
|
|
291
|
-
(0, shriramfdsdk_1.setGlobalData)({ completeFDData });
|
|
292
|
-
console.log('[RootNavigator] Set ShriramSDKGlobalData completeFDData:', completeFDData);
|
|
293
|
-
}
|
|
294
|
-
catch (e) {
|
|
295
|
-
console.log('[RootNavigator] Error setting Shriram GlobalData:', e);
|
|
296
|
-
}
|
|
297
|
-
}
|
|
298
|
-
}, [routeParams.shriramSDKGlobalData]);
|
|
299
|
-
return (react_1.default.createElement(shriramfdsdk_1.RootNavigator, { config: {
|
|
300
|
-
initialRouteName: routeParams.initialRouteName || 'FDCalculator',
|
|
301
|
-
initialPaymentStatusParams: routeParams.initialPaymentStatusParams,
|
|
302
|
-
initialFDContext: {
|
|
303
|
-
providerId: routeParams.providerId,
|
|
304
|
-
fdListSelectedData: routeParams.fdListSelectedData,
|
|
305
|
-
completeFDData: routeParams.completeFDData,
|
|
306
|
-
},
|
|
307
|
-
}, onExit: (fdDetails) => {
|
|
308
|
-
// When exiting external SDK, go back to FDList
|
|
309
|
-
setExternalSDK(null);
|
|
310
|
-
setExternalSDKFDData(null);
|
|
311
|
-
(0, helpers_2.navigate)('FDList');
|
|
312
|
-
if (fdDetails) {
|
|
313
|
-
onExit === null || onExit === void 0 ? void 0 : onExit(fdDetails);
|
|
314
|
-
}
|
|
315
|
-
}, onPanRequired: () => {
|
|
316
|
-
// Exit full SDK flow back to host app and notify callback
|
|
317
|
-
setExternalSDK(null);
|
|
318
|
-
setExternalSDKFDData(null);
|
|
319
|
-
onPanRequired === null || onPanRequired === void 0 ? void 0 : onPanRequired();
|
|
320
|
-
onExit === null || onExit === void 0 ? void 0 : onExit();
|
|
321
|
-
} }));
|
|
322
|
-
};
|
|
323
|
-
const MahindraSDKWithMasterData = ({ masterData }) => {
|
|
324
|
-
const { setMasterData } = (0, mahindrafdsdk_1.useMasterData)();
|
|
325
|
-
const mahindraDispatch = (0, mahindrafdsdk_1.useAppDispatch)();
|
|
326
|
-
// Set master data
|
|
327
|
-
react_1.default.useEffect(() => {
|
|
328
|
-
if (masterData) {
|
|
329
|
-
const dataToSet = masterData.data || masterData;
|
|
330
|
-
setMasterData(dataToSet);
|
|
331
|
-
}
|
|
332
|
-
}, [masterData, setMasterData]);
|
|
333
|
-
// Set FDListSelectedData using Mahindra setter
|
|
334
|
-
react_1.default.useEffect(() => {
|
|
335
|
-
if (routeParams.fdListSelectedData) {
|
|
336
|
-
try {
|
|
337
|
-
mahindraDispatch((0, mahindrafdsdk_1.setFDListSelected)(routeParams.fdListSelectedData));
|
|
338
|
-
}
|
|
339
|
-
catch (e) {
|
|
340
|
-
console.log('[RootNavigator] Error setting Mahindra FDListSelected:', e);
|
|
341
|
-
}
|
|
342
|
-
}
|
|
343
|
-
}, [routeParams.fdListSelectedData, mahindraDispatch]);
|
|
344
|
-
// Set OnboardingIds using Mahindra setter
|
|
345
|
-
react_1.default.useEffect(() => {
|
|
346
|
-
var _a;
|
|
347
|
-
if (routeParams.onboardingIds) {
|
|
348
|
-
try {
|
|
349
|
-
mahindraDispatch((0, mahindrafdsdk_1.setOnboardingIds)(Object.assign(Object.assign({}, routeParams.onboardingIds), { providerId: routeParams.providerId || ((_a = routeParams.onboardingIds) === null || _a === void 0 ? void 0 : _a.providerId) })));
|
|
350
|
-
}
|
|
351
|
-
catch (e) {
|
|
352
|
-
console.log('[RootNavigator] Error setting Mahindra OnboardingIds:', e);
|
|
353
|
-
}
|
|
354
|
-
}
|
|
355
|
-
}, [routeParams.onboardingIds, mahindraDispatch]);
|
|
356
|
-
return (react_1.default.createElement(MahindraRootNavigatorAny, { config: {
|
|
357
|
-
initialRouteName: routeParams.initialRouteName || 'FDCalculator',
|
|
358
|
-
forceFetchCustomerDetails: !!routeParams.forceFetchCustomerDetails,
|
|
359
|
-
initialFDContext: {
|
|
360
|
-
providerId: routeParams.providerId,
|
|
361
|
-
fdListSelectedData: routeParams.fdListSelectedData,
|
|
362
|
-
completeFDData: routeParams.completeFDData,
|
|
363
|
-
},
|
|
364
|
-
}, onExit: (fdDetails) => {
|
|
365
|
-
// When exiting external SDK, go back to FDList
|
|
366
|
-
setExternalSDK(null);
|
|
367
|
-
setExternalSDKFDData(null);
|
|
368
|
-
(0, helpers_2.navigate)('FDList');
|
|
369
|
-
if (fdDetails) {
|
|
370
|
-
onExit === null || onExit === void 0 ? void 0 : onExit(fdDetails);
|
|
371
|
-
}
|
|
372
|
-
}, onPanRequired: () => {
|
|
373
|
-
// Exit full SDK flow back to host app and notify callback
|
|
374
|
-
setExternalSDK(null);
|
|
375
|
-
setExternalSDKFDData(null);
|
|
376
|
-
onPanRequired === null || onPanRequired === void 0 ? void 0 : onPanRequired();
|
|
377
|
-
onExit === null || onExit === void 0 ? void 0 : onExit();
|
|
378
|
-
} }));
|
|
379
|
-
};
|
|
380
370
|
if (sdkType === 'shriram') {
|
|
381
371
|
return (react_1.default.createElement(shriramfdsdk_1.ApiProvider, null,
|
|
382
372
|
react_1.default.createElement(shriramfdsdk_1.MasterDataProvider, null,
|
|
383
373
|
react_1.default.createElement(shriramfdsdk_1.ThemeProvider, { theme: fdsdkTheme, initialTheme: fdsdkThemeName },
|
|
384
374
|
react_1.default.createElement(native_1.NavigationIndependentTree, null,
|
|
385
375
|
react_1.default.createElement(native_1.NavigationContainer, { ref: shriramfdsdk_1.navigationRef },
|
|
386
|
-
react_1.default.createElement(
|
|
376
|
+
react_1.default.createElement(ShriramSDKContent, { masterData: externalMasterData, routeParams: routeParams, onSDKExit: handleShriramExit, onSDKPanRequired: handleShriramPanRequired })))))));
|
|
387
377
|
}
|
|
388
378
|
if (sdkType === 'mahindra') {
|
|
389
379
|
return (react_1.default.createElement(mahindrafdsdk_1.ApiProvider, null,
|
|
@@ -391,7 +381,7 @@ const RootNavigator = ({ config = {}, onExit, onPanRequired, }) => {
|
|
|
391
381
|
react_1.default.createElement(mahindrafdsdk_1.ThemeProvider, { theme: fdsdkTheme, initialTheme: fdsdkThemeName },
|
|
392
382
|
react_1.default.createElement(native_1.NavigationIndependentTree, null,
|
|
393
383
|
react_1.default.createElement(native_1.NavigationContainer, { ref: mahindrafdsdk_1.navigationRef },
|
|
394
|
-
react_1.default.createElement(
|
|
384
|
+
react_1.default.createElement(MahindraSDKContent, { masterData: externalMasterData, routeParams: routeParams, onSDKExit: handleMahindraExit, onSDKPanRequired: handleMahindraPanRequired })))))));
|
|
395
385
|
}
|
|
396
386
|
return null;
|
|
397
387
|
}),
|
|
@@ -552,7 +552,7 @@ const FDCalculator = ({ onGoBack, onNavigateToReviewKYC, fdData }) => {
|
|
|
552
552
|
react_1.default.createElement(react_native_1.Image, { source: { uri: base64Images_1.base64Images.backArrow }, style: [styles.backIcon, { tintColor: themeName === 'dark' ? colors.headerText : undefined }], resizeMode: "contain", width: 24, height: 24 }))),
|
|
553
553
|
react_1.default.createElement(react_native_1.View, { style: { flex: 1, justifyContent: 'space-between' } },
|
|
554
554
|
react_1.default.createElement(react_native_1.ScrollView, { style: styles.scrollContainer, contentContainerStyle: styles.scrollContent, showsVerticalScrollIndicator: false, onScrollBeginDrag: closeAllMenus, scrollEnabled: !(isOnboarding || isBooking), keyboardShouldPersistTaps: "handled", bounces: true, alwaysBounceVertical: true },
|
|
555
|
-
react_1.default.createElement(components_1.CompanyHeader, { companyName: (effectiveFdData === null || effectiveFdData === void 0 ? void 0 : effectiveFdData.name) || '', rating:
|
|
555
|
+
react_1.default.createElement(components_1.CompanyHeader, { companyName: (effectiveFdData === null || effectiveFdData === void 0 ? void 0 : effectiveFdData.name) || '', rating: "AAA" }),
|
|
556
556
|
react_1.default.createElement(components_1.AmountInput, { label: strings_1.FD_STRINGS.INVESTMENT_AMOUNT_LABEL, value: amount, onChangeText: handleAmountChange, onFocus: closeAllMenus, placeholder: strings_1.FD_STRINGS.AMOUNT_PLACEHOLDER, noteText: strings_1.FD_STRINGS.AMOUNT_NOTE, minMaxText: strings_1.FD_STRINGS.AMOUNT_MIN_MAX, errorMessage: amountError }),
|
|
557
557
|
react_1.default.createElement(components_1.DropdownSelector, { label: strings_1.FD_STRINGS.TENURE_LABEL, value: tenureValue || strings_1.COMMON_STRINGS.SELECT, onPress: () => {
|
|
558
558
|
react_native_1.Keyboard.dismiss();
|
package/lib/screens/FDList.js
CHANGED
|
@@ -77,8 +77,8 @@ function getStaticCreditRatingForFD(fd) {
|
|
|
77
77
|
if (logoType === 'mahindra')
|
|
78
78
|
return 'AAA';
|
|
79
79
|
if (logoType === 'shriram')
|
|
80
|
-
return '
|
|
81
|
-
return '
|
|
80
|
+
return 'AAA';
|
|
81
|
+
return 'AAA';
|
|
82
82
|
}
|
|
83
83
|
/** Statuses that count as pending/active (in-progress) workflow. */
|
|
84
84
|
const PENDING_ACTIVE_STATUSES = ['active', 'pending', 'in_progress', 'in-progress'];
|
|
@@ -943,23 +943,23 @@ const FDList = ({ onGoBack, onSelectFD, onNavigateToFDCalculator, onNavigateToEx
|
|
|
943
943
|
if (shriramComplete)
|
|
944
944
|
ShriramSDKGlobalDataPayment = shriramComplete;
|
|
945
945
|
}
|
|
946
|
-
const fdListSelectedDataPayment =
|
|
946
|
+
const fdListSelectedDataPayment = fdDisplay ? {
|
|
947
947
|
id: appData.fd_id || appData.fdId || 'active-fd',
|
|
948
948
|
providerId: providerIdFromApp,
|
|
949
|
-
name:
|
|
949
|
+
name: fdDisplay.name,
|
|
950
950
|
accountNumber: appData.account_number || appData.accountNumber || '',
|
|
951
|
-
roi: `${
|
|
952
|
-
tenure:
|
|
953
|
-
amount: Number(
|
|
954
|
-
maturityDate:
|
|
951
|
+
roi: `${fdDisplay.returns}% p.a.`,
|
|
952
|
+
tenure: fdDisplay.maturityDate || '-',
|
|
953
|
+
amount: Number(fdDisplay.invested) || 0,
|
|
954
|
+
maturityDate: fdDisplay.maturityDate || '-',
|
|
955
955
|
status: 'active',
|
|
956
956
|
creditRating: getStaticCreditRatingForFD({
|
|
957
|
-
name:
|
|
957
|
+
name: fdDisplay.name,
|
|
958
958
|
providerId: providerIdFromApp,
|
|
959
959
|
}),
|
|
960
|
-
companyName:
|
|
961
|
-
fdRate: `${
|
|
962
|
-
interestPayout:
|
|
960
|
+
companyName: fdDisplay.name,
|
|
961
|
+
fdRate: `${fdDisplay.returns}% p.a.`,
|
|
962
|
+
interestPayout: fdDisplay.interestPayout || 'Yearly',
|
|
963
963
|
} : null;
|
|
964
964
|
const masterDataPayment = ShriramMasterData;
|
|
965
965
|
(0, helpers_1.navigate)('ExternalSDK', {
|
|
@@ -1019,23 +1019,23 @@ const FDList = ({ onGoBack, onSelectFD, onNavigateToFDCalculator, onNavigateToEx
|
|
|
1019
1019
|
if (shriramComplete)
|
|
1020
1020
|
ShriramSDKGlobalDataPayment = shriramComplete;
|
|
1021
1021
|
}
|
|
1022
|
-
const fdListSelectedDataPayment =
|
|
1022
|
+
const fdListSelectedDataPayment = fdDisplay ? {
|
|
1023
1023
|
id: appData.fd_id || appData.fdId || 'active-fd',
|
|
1024
1024
|
providerId: providerIdFromApp,
|
|
1025
|
-
name:
|
|
1025
|
+
name: fdDisplay.name,
|
|
1026
1026
|
accountNumber: appData.account_number || appData.accountNumber || '',
|
|
1027
|
-
roi: `${
|
|
1028
|
-
tenure:
|
|
1029
|
-
amount: Number(
|
|
1030
|
-
maturityDate:
|
|
1027
|
+
roi: `${fdDisplay.returns}% p.a.`,
|
|
1028
|
+
tenure: fdDisplay.maturityDate || '-',
|
|
1029
|
+
amount: Number(fdDisplay.invested) || 0,
|
|
1030
|
+
maturityDate: fdDisplay.maturityDate || '-',
|
|
1031
1031
|
status: 'active',
|
|
1032
1032
|
creditRating: getStaticCreditRatingForFD({
|
|
1033
|
-
name:
|
|
1033
|
+
name: fdDisplay.name,
|
|
1034
1034
|
providerId: providerIdFromApp,
|
|
1035
1035
|
}),
|
|
1036
|
-
companyName:
|
|
1037
|
-
fdRate: `${
|
|
1038
|
-
interestPayout:
|
|
1036
|
+
companyName: fdDisplay.name,
|
|
1037
|
+
fdRate: `${fdDisplay.returns}% p.a.`,
|
|
1038
|
+
interestPayout: fdDisplay.interestPayout || 'Yearly',
|
|
1039
1039
|
} : null;
|
|
1040
1040
|
const masterDataPayment = ShriramMasterData;
|
|
1041
1041
|
(0, helpers_1.navigate)('ExternalSDK', {
|
|
@@ -1151,25 +1151,26 @@ const FDList = ({ onGoBack, onSelectFD, onNavigateToFDCalculator, onNavigateToEx
|
|
|
1151
1151
|
// Get onboardingIds - use the one from appData if available, otherwise from Redux store
|
|
1152
1152
|
const onboardingIdsToPass = onboardingIdsFromApp || onboardingIds;
|
|
1153
1153
|
// Get fdListSelectedData (already set in Redux, but we need it for navigation)
|
|
1154
|
-
|
|
1154
|
+
// Use fdDisplay (derived from the tapped app) not activeFD (always first active app)
|
|
1155
|
+
const fdListSelectedDataToPass = fdDisplay ? {
|
|
1155
1156
|
id: appData.fd_id || appData.fdId || 'active-fd',
|
|
1156
1157
|
providerId: providerIdFromApp,
|
|
1157
|
-
name:
|
|
1158
|
+
name: fdDisplay.name,
|
|
1158
1159
|
accountNumber: appData.account_number || appData.accountNumber || '',
|
|
1159
|
-
roi: `${
|
|
1160
|
-
tenure:
|
|
1161
|
-
? `${
|
|
1160
|
+
roi: `${fdDisplay.returns}% p.a.`,
|
|
1161
|
+
tenure: appData.tenure_in_months
|
|
1162
|
+
? `${appData.tenure_in_months} Months`
|
|
1162
1163
|
: '-',
|
|
1163
|
-
amount: Number(
|
|
1164
|
-
maturityDate:
|
|
1164
|
+
amount: Number(fdDisplay.invested) || 0,
|
|
1165
|
+
maturityDate: fdDisplay.maturityDate || '-',
|
|
1165
1166
|
status: 'active',
|
|
1166
1167
|
creditRating: getStaticCreditRatingForFD({
|
|
1167
|
-
name:
|
|
1168
|
+
name: fdDisplay.name,
|
|
1168
1169
|
providerId: providerIdFromApp,
|
|
1169
1170
|
}),
|
|
1170
|
-
companyName:
|
|
1171
|
-
fdRate: `${
|
|
1172
|
-
interestPayout:
|
|
1171
|
+
companyName: fdDisplay.name,
|
|
1172
|
+
fdRate: `${fdDisplay.returns}% p.a.`,
|
|
1173
|
+
interestPayout: fdDisplay.interestPayout || '',
|
|
1173
1174
|
} : null;
|
|
1174
1175
|
// Navigate to appropriate SDK if provider is detected
|
|
1175
1176
|
if (isMahindra || isShriram) {
|
|
@@ -301,6 +301,10 @@ const PaymentStatus = ({ onRetry, onContinue, status, transactionId, fdData }) =
|
|
|
301
301
|
}
|
|
302
302
|
}
|
|
303
303
|
};
|
|
304
|
+
// Back button: navigate to FDList for all statuses
|
|
305
|
+
const handleNavigateToFDList = () => {
|
|
306
|
+
(0, helpers_1.navigate)('FDList');
|
|
307
|
+
};
|
|
304
308
|
// Disable hardware back button on PaymentStatus screen
|
|
305
309
|
(0, react_1.useEffect)(() => {
|
|
306
310
|
if (react_native_1.Platform.OS !== 'android')
|
|
@@ -315,6 +319,8 @@ const PaymentStatus = ({ onRetry, onContinue, status, transactionId, fdData }) =
|
|
|
315
319
|
return (react_1.default.createElement(SafeAreaWrapper_1.default, { includeTop: true, bottomPadding: 0, statusBarColor: "#000000", statusBarStyle: "light-content" },
|
|
316
320
|
react_native_1.Platform.OS === 'ios' && react_1.default.createElement(react_native_1.StatusBar, { barStyle: "light-content" }),
|
|
317
321
|
react_1.default.createElement(react_native_1.View, { style: styles.container },
|
|
322
|
+
react_1.default.createElement(react_native_1.TouchableOpacity, { onPress: handleNavigateToFDList, style: styles.backIconBtn },
|
|
323
|
+
react_1.default.createElement(Ionicons_1.default, { name: "arrow-back", size: 24, color: colors.text })),
|
|
318
324
|
react_1.default.createElement(react_native_1.ScrollView, { showsVerticalScrollIndicator: false, contentContainerStyle: styles.scrollContent },
|
|
319
325
|
react_1.default.createElement(react_native_1.View, { style: styles.iconContainer },
|
|
320
326
|
react_1.default.createElement(react_native_1.View, { style: styles.iconCircleOuter },
|
|
@@ -346,6 +352,13 @@ const createStyles = (colors, typography, status) => {
|
|
|
346
352
|
flex: 1,
|
|
347
353
|
backgroundColor: colors.background,
|
|
348
354
|
},
|
|
355
|
+
backIconBtn: {
|
|
356
|
+
position: 'absolute',
|
|
357
|
+
top: 16,
|
|
358
|
+
left: 16,
|
|
359
|
+
zIndex: 10,
|
|
360
|
+
padding: 8,
|
|
361
|
+
},
|
|
349
362
|
headerTitle: {
|
|
350
363
|
fontSize: 14,
|
|
351
364
|
fontWeight: '600',
|
package/lib/screens/ReviewKYC.js
CHANGED
|
@@ -631,7 +631,8 @@ const ReviewKYC = ({ onGoBack, onContinue, initialData, }) => {
|
|
|
631
631
|
] }, kycData.useExistingAddress ? (react_1.default.createElement(react_native_1.Image, { source: { uri: (themeName === 'dark') ? base64Images_1.base64Images.checkBoxDark : base64Images_1.base64Images.filledCheckBox }, resizeMode: "cover", width: 20, height: 20 })) : ((themeName === 'dark') ? (react_1.default.createElement(react_native_1.Image, { source: { uri: base64Images_1.base64Images.unCheckBoxDark }, resizeMode: "cover", width: 20, height: 20 })) : null))),
|
|
632
632
|
react_1.default.createElement(react_native_1.Text, { style: styles.checkboxText }, "For existing customers, we'll use the address from our records. For new customers, the address from your Aadhar card will be used. To update, please raise a service request with valid address proof.")))))),
|
|
633
633
|
react_1.default.createElement(ActionButton_1.default, { title: "Continue", onPress: handleContinue, disabled: !kycData.useExistingAddress || isLoadingPanRapid || !validateForm(), loading: isLoadingPanRapid }),
|
|
634
|
-
isLoadingPanRapid && (react_1.default.createElement(react_native_1.View, { style: styles.loadingOverlay, pointerEvents: "auto" }
|
|
634
|
+
isLoadingPanRapid && (react_1.default.createElement(react_native_1.View, { style: styles.loadingOverlay, pointerEvents: "auto" },
|
|
635
|
+
react_1.default.createElement(react_native_1.ActivityIndicator, { size: "large", color: colors.primary }))),
|
|
635
636
|
isGoingBack && (react_1.default.createElement(react_native_1.View, { style: styles.loadingOverlay, pointerEvents: "auto" },
|
|
636
637
|
react_1.default.createElement(react_native_1.ActivityIndicator, { size: "large", color: colors.primary })))));
|
|
637
638
|
};
|