@flixora/airxpay-sdk-init-ui 1.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE.md +21 -0
- package/README.md +623 -0
- package/dist/api/client.d.ts +2 -0
- package/dist/api/client.js +78 -0
- package/dist/api/merchantProxy.d.ts +11 -0
- package/dist/api/merchantProxy.js +170 -0
- package/dist/assets/images/airxpay.png +0 -0
- package/dist/assets/images/flixora.png +0 -0
- package/dist/components/common/CountryDropdown.d.ts +17 -0
- package/dist/components/common/CountryDropdown.js +138 -0
- package/dist/components/common/FileUploader.d.ts +16 -0
- package/dist/components/common/FileUploader.js +219 -0
- package/dist/components/common/StepIndicator.d.ts +11 -0
- package/dist/components/common/StepIndicator.js +269 -0
- package/dist/components/steps/BankDetails.d.ts +10 -0
- package/dist/components/steps/BankDetails.js +630 -0
- package/dist/components/steps/BasicDetailsForm.d.ts +10 -0
- package/dist/components/steps/BasicDetailsForm.js +569 -0
- package/dist/components/steps/KYCVerification.d.ts +11 -0
- package/dist/components/steps/KYCVerification.js +867 -0
- package/dist/components/steps/OnboardingComplete.d.ts +8 -0
- package/dist/components/steps/OnboardingComplete.js +566 -0
- package/dist/components/steps/onboarding/FinalStepScreen.d.ts +10 -0
- package/dist/components/steps/onboarding/FinalStepScreen.js +455 -0
- package/dist/components/steps/onboarding/MerchantOnboarding.d.ts +4 -0
- package/dist/components/steps/onboarding/MerchantOnboarding.js +678 -0
- package/dist/contexts/AirXPayProvider.d.ts +21 -0
- package/dist/contexts/AirXPayProvider.js +116 -0
- package/dist/error/errorHandler.d.ts +10 -0
- package/dist/error/errorHandler.js +87 -0
- package/dist/etc/constants.d.ts +37 -0
- package/dist/etc/constants.js +41 -0
- package/dist/hooks/useAirXPaySheet.d.ts +3 -0
- package/dist/hooks/useAirXPaySheet.js +20 -0
- package/dist/hooks/useMerchantOnboarding.d.ts +15 -0
- package/dist/hooks/useMerchantOnboarding.js +108 -0
- package/dist/index.d.ts +13 -0
- package/dist/index.js +41 -0
- package/dist/options/configOptions.d.ts +28 -0
- package/dist/options/configOptions.js +56 -0
- package/dist/plugins/tokenRefreshPlugin.d.ts +10 -0
- package/dist/plugins/tokenRefreshPlugin.js +91 -0
- package/dist/schema/validators.d.ts +9 -0
- package/dist/schema/validators.js +57 -0
- package/dist/sdk/airxpay.d.ts +9 -0
- package/dist/sdk/airxpay.js +26 -0
- package/dist/services/apiService.d.ts +34 -0
- package/dist/services/apiService.js +133 -0
- package/dist/types/dev.d.ts +1 -0
- package/dist/types/dev.js +4 -0
- package/dist/types/dev.ts +2 -0
- package/dist/types/merchantTypes.d.ts +111 -0
- package/dist/types/merchantTypes.js +2 -0
- package/dist/types/merchantTypes.ts +116 -0
- package/dist/types/type.d.ts +8 -0
- package/dist/types/type.js +3 -0
- package/dist/types/type.ts +11 -0
- package/dist/utils/jwt.d.ts +10 -0
- package/dist/utils/jwt.js +28 -0
- package/dist/utils/tokenStorage.d.ts +5 -0
- package/dist/utils/tokenStorage.js +69 -0
- package/package.json +52 -0
|
@@ -0,0 +1,678 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
// components/MerchantOnboardingSheet.tsx
|
|
3
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
4
|
+
if (k2 === undefined) k2 = k;
|
|
5
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
6
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
7
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
8
|
+
}
|
|
9
|
+
Object.defineProperty(o, k2, desc);
|
|
10
|
+
}) : (function(o, m, k, k2) {
|
|
11
|
+
if (k2 === undefined) k2 = k;
|
|
12
|
+
o[k2] = m[k];
|
|
13
|
+
}));
|
|
14
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
15
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
16
|
+
}) : function(o, v) {
|
|
17
|
+
o["default"] = v;
|
|
18
|
+
});
|
|
19
|
+
var __importStar = (this && this.__importStar) || (function () {
|
|
20
|
+
var ownKeys = function(o) {
|
|
21
|
+
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
22
|
+
var ar = [];
|
|
23
|
+
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
24
|
+
return ar;
|
|
25
|
+
};
|
|
26
|
+
return ownKeys(o);
|
|
27
|
+
};
|
|
28
|
+
return function (mod) {
|
|
29
|
+
if (mod && mod.__esModule) return mod;
|
|
30
|
+
var result = {};
|
|
31
|
+
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
32
|
+
__setModuleDefault(result, mod);
|
|
33
|
+
return result;
|
|
34
|
+
};
|
|
35
|
+
})();
|
|
36
|
+
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
|
|
37
|
+
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
|
38
|
+
return new (P || (P = Promise))(function (resolve, reject) {
|
|
39
|
+
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
|
40
|
+
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
|
41
|
+
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
|
|
42
|
+
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
|
43
|
+
});
|
|
44
|
+
};
|
|
45
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
46
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
47
|
+
};
|
|
48
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
49
|
+
const react_1 = __importStar(require("react"));
|
|
50
|
+
const react_native_1 = require("react-native");
|
|
51
|
+
const react_native_paper_1 = require("react-native-paper");
|
|
52
|
+
const expo_linear_gradient_1 = require("expo-linear-gradient");
|
|
53
|
+
const StepIndicator_1 = __importDefault(require("../../common/StepIndicator"));
|
|
54
|
+
const BasicDetailsForm_1 = __importDefault(require("../../steps/BasicDetailsForm"));
|
|
55
|
+
const KYCVerification_1 = __importDefault(require("../../steps/KYCVerification"));
|
|
56
|
+
const BankDetails_1 = __importDefault(require("../../steps/BankDetails"));
|
|
57
|
+
const FinalStepScreen_1 = require("./FinalStepScreen");
|
|
58
|
+
const OnboardingComplete_1 = require("../OnboardingComplete");
|
|
59
|
+
const AirXPayProvider_1 = require("../../../contexts/AirXPayProvider");
|
|
60
|
+
const merchantProxy_1 = require("../../../api/merchantProxy");
|
|
61
|
+
const { width } = react_native_1.Dimensions.get('window');
|
|
62
|
+
// ✅ 5 STEPS - Added Final Step
|
|
63
|
+
const STEPS = [
|
|
64
|
+
{ id: 1, name: 'Basic Details', key: 'basic', isRequired: true, icon: 'account' },
|
|
65
|
+
{ id: 2, name: 'KYC Verification', key: 'kyc', isRequired: true, icon: 'shield-account' },
|
|
66
|
+
{ id: 3, name: 'Bank Details', key: 'bank', isRequired: true, icon: 'bank' },
|
|
67
|
+
{ id: 4, name: 'Final Review', key: 'final', isRequired: true, icon: 'file-document' },
|
|
68
|
+
{ id: 5, name: 'Complete', key: 'complete', isRequired: false, icon: 'check-circle' },
|
|
69
|
+
];
|
|
70
|
+
// Default logo - can be overridden via props
|
|
71
|
+
const DEFAULT_LOGO = require('../../../assets/images/airxpay.png');
|
|
72
|
+
const MerchantOnboardingSheet = ({ merchantId, mode, isKycCompleted, isBankDetailsCompleted, kycStatus, status, initialStep = 1, initialData = {}, onNext, onBack, onComplete, loading: externalLoading = false, }) => {
|
|
73
|
+
// Get configuration from provider
|
|
74
|
+
const airXPay = (0, AirXPayProvider_1.useAirXPaySafe)();
|
|
75
|
+
// Local state for provider verification
|
|
76
|
+
const [isVerifying, setIsVerifying] = (0, react_1.useState)(true);
|
|
77
|
+
const [isValidProvider, setIsValidProvider] = (0, react_1.useState)(false);
|
|
78
|
+
const [verificationError, setVerificationError] = (0, react_1.useState)(null);
|
|
79
|
+
// Animation values
|
|
80
|
+
const fadeAnim = (0, react_1.useRef)(new react_native_1.Animated.Value(1)).current;
|
|
81
|
+
const slideAnim = (0, react_1.useRef)(new react_native_1.Animated.Value(0)).current;
|
|
82
|
+
const progressAnim = (0, react_1.useRef)(new react_native_1.Animated.Value(initialStep / STEPS.length)).current;
|
|
83
|
+
const scaleAnim = (0, react_1.useRef)(new react_native_1.Animated.Value(1)).current;
|
|
84
|
+
// State management
|
|
85
|
+
const [currentStep, setCurrentStep] = (0, react_1.useState)(initialStep);
|
|
86
|
+
const [merchantData, setMerchantData] = (0, react_1.useState)(Object.assign({ mode,
|
|
87
|
+
kycStatus,
|
|
88
|
+
isKycCompleted,
|
|
89
|
+
isBankDetailsCompleted,
|
|
90
|
+
status }, initialData));
|
|
91
|
+
const [errors, setErrors] = (0, react_1.useState)({});
|
|
92
|
+
const [showError, setShowError] = (0, react_1.useState)(false);
|
|
93
|
+
const [isAnimating, setIsAnimating] = (0, react_1.useState)(false);
|
|
94
|
+
const [isSubmitting, setIsSubmitting] = (0, react_1.useState)(false);
|
|
95
|
+
const [isWaitingForBackend, setIsWaitingForBackend] = (0, react_1.useState)(false);
|
|
96
|
+
// ✅ New state for merchant creation response
|
|
97
|
+
const [merchantResponse, setMerchantResponse] = (0, react_1.useState)(null);
|
|
98
|
+
// Track completion status of each step dynamically
|
|
99
|
+
const [stepCompletion, setStepCompletion] = (0, react_1.useState)(() => {
|
|
100
|
+
const basicCompleted = !!(initialData.merchantName &&
|
|
101
|
+
initialData.merchantName.trim() !== '' &&
|
|
102
|
+
initialData.merchantEmail &&
|
|
103
|
+
initialData.merchantEmail.trim() !== '');
|
|
104
|
+
return {
|
|
105
|
+
basic: basicCompleted,
|
|
106
|
+
kyc: isKycCompleted || false,
|
|
107
|
+
bank: isBankDetailsCompleted || false,
|
|
108
|
+
final: false, // ✅ Final step initially incomplete
|
|
109
|
+
};
|
|
110
|
+
});
|
|
111
|
+
// Verify public key on mount
|
|
112
|
+
(0, react_1.useEffect)(() => {
|
|
113
|
+
const verifyProviderConfig = () => __awaiter(void 0, void 0, void 0, function* () {
|
|
114
|
+
console.log('🔍 Starting AirXPay provider verification...');
|
|
115
|
+
if (!airXPay) {
|
|
116
|
+
console.error('❌ AirXPayProvider is undefined - context not found');
|
|
117
|
+
setVerificationError('AirXPay provider not found in component tree. Please wrap your app with <AirXPayProvider>.');
|
|
118
|
+
setIsValidProvider(false);
|
|
119
|
+
setIsVerifying(false);
|
|
120
|
+
return;
|
|
121
|
+
}
|
|
122
|
+
const { publicKey } = airXPay;
|
|
123
|
+
if (!publicKey) {
|
|
124
|
+
console.error('❌ AirXPay config missing:', { publicKey: !!publicKey });
|
|
125
|
+
setVerificationError('AirXPay configuration incomplete. publicKey is required.');
|
|
126
|
+
setIsValidProvider(false);
|
|
127
|
+
setIsVerifying(false);
|
|
128
|
+
return;
|
|
129
|
+
}
|
|
130
|
+
console.log('✅ AirXPay config found:', { publicKey: publicKey.substring(0, 8) + '...' });
|
|
131
|
+
try {
|
|
132
|
+
setIsVerifying(true);
|
|
133
|
+
console.log('🔑 Verifying public key:', publicKey.substring(0, 8) + '...');
|
|
134
|
+
yield (0, merchantProxy_1.verifyPublicKey)(publicKey);
|
|
135
|
+
console.log('✅ Public key verified successfully');
|
|
136
|
+
setIsValidProvider(true);
|
|
137
|
+
setVerificationError(null);
|
|
138
|
+
}
|
|
139
|
+
catch (err) {
|
|
140
|
+
console.error('❌ Public key verification failed:', err.message);
|
|
141
|
+
setVerificationError(err.message || 'Invalid AirXPay public key. Please check your configuration.');
|
|
142
|
+
setIsValidProvider(false);
|
|
143
|
+
}
|
|
144
|
+
finally {
|
|
145
|
+
setIsVerifying(false);
|
|
146
|
+
}
|
|
147
|
+
});
|
|
148
|
+
verifyProviderConfig();
|
|
149
|
+
}, [airXPay]);
|
|
150
|
+
// Log config status after verification
|
|
151
|
+
(0, react_1.useEffect)(() => {
|
|
152
|
+
if (!isVerifying) {
|
|
153
|
+
if (isValidProvider) {
|
|
154
|
+
console.log('🚀 AirXPay provider ready - rendering onboarding');
|
|
155
|
+
}
|
|
156
|
+
else {
|
|
157
|
+
console.warn('⚠️ AirXPay provider invalid - showing error state');
|
|
158
|
+
}
|
|
159
|
+
}
|
|
160
|
+
}, [isVerifying, isValidProvider]);
|
|
161
|
+
// Update progress bar animation when step changes
|
|
162
|
+
(0, react_1.useEffect)(() => {
|
|
163
|
+
react_native_1.Animated.timing(progressAnim, {
|
|
164
|
+
toValue: currentStep / STEPS.length,
|
|
165
|
+
duration: 300,
|
|
166
|
+
useNativeDriver: false,
|
|
167
|
+
}).start();
|
|
168
|
+
}, [currentStep]);
|
|
169
|
+
const animateStepTransition = (direction) => {
|
|
170
|
+
if (isAnimating)
|
|
171
|
+
return;
|
|
172
|
+
setIsAnimating(true);
|
|
173
|
+
// Fade out and slide
|
|
174
|
+
react_native_1.Animated.parallel([
|
|
175
|
+
react_native_1.Animated.timing(fadeAnim, {
|
|
176
|
+
toValue: 0,
|
|
177
|
+
duration: 150,
|
|
178
|
+
useNativeDriver: true,
|
|
179
|
+
}),
|
|
180
|
+
react_native_1.Animated.timing(slideAnim, {
|
|
181
|
+
toValue: direction === 'next' ? -50 : 50,
|
|
182
|
+
duration: 150,
|
|
183
|
+
useNativeDriver: true,
|
|
184
|
+
}),
|
|
185
|
+
]).start(() => {
|
|
186
|
+
// Reset slide position
|
|
187
|
+
slideAnim.setValue(direction === 'next' ? 50 : -50);
|
|
188
|
+
// Fade in and slide to center
|
|
189
|
+
react_native_1.Animated.parallel([
|
|
190
|
+
react_native_1.Animated.timing(fadeAnim, {
|
|
191
|
+
toValue: 1,
|
|
192
|
+
duration: 150,
|
|
193
|
+
useNativeDriver: true,
|
|
194
|
+
}),
|
|
195
|
+
react_native_1.Animated.timing(slideAnim, {
|
|
196
|
+
toValue: 0,
|
|
197
|
+
duration: 150,
|
|
198
|
+
useNativeDriver: true,
|
|
199
|
+
}),
|
|
200
|
+
]).start(() => {
|
|
201
|
+
setIsAnimating(false);
|
|
202
|
+
});
|
|
203
|
+
});
|
|
204
|
+
};
|
|
205
|
+
const handleNext = (stepData) => {
|
|
206
|
+
const updatedData = Object.assign(Object.assign({}, merchantData), stepData);
|
|
207
|
+
setMerchantData(updatedData);
|
|
208
|
+
// Update step completion status dynamically
|
|
209
|
+
if (currentStep === 1) {
|
|
210
|
+
const basicCompleted = !!(updatedData.merchantName &&
|
|
211
|
+
updatedData.merchantName.trim() !== '' &&
|
|
212
|
+
updatedData.merchantEmail &&
|
|
213
|
+
updatedData.merchantEmail.trim() !== '');
|
|
214
|
+
setStepCompletion(prev => (Object.assign(Object.assign({}, prev), { basic: basicCompleted })));
|
|
215
|
+
}
|
|
216
|
+
else if (currentStep === 2) {
|
|
217
|
+
const kycCompleted = stepData.isKycCompleted === true || stepData.kycStatus === 'verified';
|
|
218
|
+
setStepCompletion(prev => (Object.assign(Object.assign({}, prev), { kyc: kycCompleted })));
|
|
219
|
+
}
|
|
220
|
+
else if (currentStep === 3) {
|
|
221
|
+
const bankCompleted = stepData.isBankDetailsCompleted === true;
|
|
222
|
+
setStepCompletion(prev => (Object.assign(Object.assign({}, prev), { bank: bankCompleted })));
|
|
223
|
+
}
|
|
224
|
+
else if (currentStep === 4) {
|
|
225
|
+
// Final step - just mark as completed
|
|
226
|
+
setStepCompletion(prev => (Object.assign(Object.assign({}, prev), { final: true })));
|
|
227
|
+
}
|
|
228
|
+
// Call onNext callback with step data and current step
|
|
229
|
+
onNext(stepData, currentStep);
|
|
230
|
+
// Move to next step if not last step
|
|
231
|
+
if (currentStep < STEPS.length) {
|
|
232
|
+
animateStepTransition('next');
|
|
233
|
+
setTimeout(() => {
|
|
234
|
+
setCurrentStep(prev => {
|
|
235
|
+
const newStep = prev + 1;
|
|
236
|
+
return newStep;
|
|
237
|
+
});
|
|
238
|
+
}, 150);
|
|
239
|
+
}
|
|
240
|
+
};
|
|
241
|
+
const handleBack = () => {
|
|
242
|
+
if (currentStep > 1) {
|
|
243
|
+
animateStepTransition('back');
|
|
244
|
+
setTimeout(() => {
|
|
245
|
+
setCurrentStep(prev => {
|
|
246
|
+
const newStep = prev - 1;
|
|
247
|
+
// Pass the new step to parent
|
|
248
|
+
onBack(newStep);
|
|
249
|
+
return newStep;
|
|
250
|
+
});
|
|
251
|
+
}, 150);
|
|
252
|
+
}
|
|
253
|
+
};
|
|
254
|
+
const validateStepData = (0, react_1.useCallback)(() => {
|
|
255
|
+
// Validate required fields dynamically based on STEPS config
|
|
256
|
+
const requiredSteps = STEPS.filter(step => step.isRequired && step.id < 5); // Exclude complete step
|
|
257
|
+
const missingSteps = requiredSteps.filter(step => !stepCompletion[step.key]);
|
|
258
|
+
if (missingSteps.length > 0) {
|
|
259
|
+
const missingStepNames = missingSteps.map(s => s.name).join(', ');
|
|
260
|
+
// If missing basic details, show inline error
|
|
261
|
+
if (missingSteps.some(s => s.key === 'basic')) {
|
|
262
|
+
setErrors({ merchantName: 'Please complete all required fields' });
|
|
263
|
+
setShowError(true);
|
|
264
|
+
return false;
|
|
265
|
+
}
|
|
266
|
+
// For KYC or Bank, show alert with navigation
|
|
267
|
+
if (missingSteps.some(s => s.key === 'kyc')) {
|
|
268
|
+
react_native_1.Alert.alert('KYC Pending', 'Please complete KYC verification first', [
|
|
269
|
+
{ text: 'Cancel', style: 'cancel' },
|
|
270
|
+
{
|
|
271
|
+
text: 'Go to KYC',
|
|
272
|
+
onPress: () => {
|
|
273
|
+
animateStepTransition('next');
|
|
274
|
+
setCurrentStep(2);
|
|
275
|
+
}
|
|
276
|
+
}
|
|
277
|
+
]);
|
|
278
|
+
return false;
|
|
279
|
+
}
|
|
280
|
+
if (missingSteps.some(s => s.key === 'bank')) {
|
|
281
|
+
react_native_1.Alert.alert('Bank Details Pending', 'Please add bank details first', [
|
|
282
|
+
{ text: 'Cancel', style: 'cancel' },
|
|
283
|
+
{
|
|
284
|
+
text: 'Go to Bank Details',
|
|
285
|
+
onPress: () => {
|
|
286
|
+
animateStepTransition('next');
|
|
287
|
+
setCurrentStep(3);
|
|
288
|
+
}
|
|
289
|
+
}
|
|
290
|
+
]);
|
|
291
|
+
return false;
|
|
292
|
+
}
|
|
293
|
+
if (missingSteps.some(s => s.key === 'final')) {
|
|
294
|
+
react_native_1.Alert.alert('Review Pending', 'Please review your information on the final step', [
|
|
295
|
+
{ text: 'Cancel', style: 'cancel' },
|
|
296
|
+
{
|
|
297
|
+
text: 'Go to Final Step',
|
|
298
|
+
onPress: () => {
|
|
299
|
+
animateStepTransition('next');
|
|
300
|
+
setCurrentStep(4);
|
|
301
|
+
}
|
|
302
|
+
}
|
|
303
|
+
]);
|
|
304
|
+
return false;
|
|
305
|
+
}
|
|
306
|
+
setErrors({ general: `Please complete: ${missingStepNames}` });
|
|
307
|
+
setShowError(true);
|
|
308
|
+
return false;
|
|
309
|
+
}
|
|
310
|
+
return true;
|
|
311
|
+
}, [stepCompletion]);
|
|
312
|
+
// ✅ Handle final step success - merchant created
|
|
313
|
+
const handleFinalStepSuccess = (response) => {
|
|
314
|
+
setMerchantResponse(response);
|
|
315
|
+
setStepCompletion(prev => (Object.assign(Object.assign({}, prev), { final: true })));
|
|
316
|
+
// Move to complete screen after short delay
|
|
317
|
+
setTimeout(() => {
|
|
318
|
+
setCurrentStep(5); // Move to complete screen
|
|
319
|
+
}, 500);
|
|
320
|
+
};
|
|
321
|
+
// ✅ Handle final step error
|
|
322
|
+
const handleFinalStepError = (error) => {
|
|
323
|
+
react_native_1.Alert.alert('Error', error.userMessage || 'Failed to create merchant');
|
|
324
|
+
};
|
|
325
|
+
const handleComplete = (0, react_1.useCallback)(() => {
|
|
326
|
+
var _a, _b;
|
|
327
|
+
// Validate all required data before completing
|
|
328
|
+
if (!validateStepData()) {
|
|
329
|
+
return;
|
|
330
|
+
}
|
|
331
|
+
// Prepare complete merchant data
|
|
332
|
+
const completeMerchantData = {
|
|
333
|
+
merchantId: merchantData.merchantId || merchantData._id || ((_a = merchantResponse === null || merchantResponse === void 0 ? void 0 : merchantResponse.merchant) === null || _a === void 0 ? void 0 : _a.merchantId) || '',
|
|
334
|
+
merchantName: merchantData.merchantName || '',
|
|
335
|
+
merchantEmail: merchantData.merchantEmail || '',
|
|
336
|
+
merchantPhone: merchantData.merchantPhone || '',
|
|
337
|
+
merchantDID: merchantData.merchantDID || '',
|
|
338
|
+
businessName: merchantData.businessName,
|
|
339
|
+
businessType: merchantData.businessType || 'individual',
|
|
340
|
+
businessCategory: merchantData.businessCategory,
|
|
341
|
+
country: merchantData.country || 'India',
|
|
342
|
+
nationality: merchantData.nationality || 'Indian',
|
|
343
|
+
dob: merchantData.dob,
|
|
344
|
+
bankDetails: merchantData.bankDetails,
|
|
345
|
+
kycDetails: merchantData.kycDetails,
|
|
346
|
+
mode: mode || 'test',
|
|
347
|
+
kycStatus: stepCompletion.kyc ? 'verified' : (kycStatus || 'pending'),
|
|
348
|
+
isKycCompleted: stepCompletion.kyc,
|
|
349
|
+
isBankDetailsCompleted: stepCompletion.bank,
|
|
350
|
+
status: status || (mode === 'live' && stepCompletion.kyc && stepCompletion.bank ? 'active' : 'pending'),
|
|
351
|
+
createdAt: merchantData.createdAt || ((_b = merchantResponse === null || merchantResponse === void 0 ? void 0 : merchantResponse.merchant) === null || _b === void 0 ? void 0 : _b.createdAt) || new Date().toISOString(),
|
|
352
|
+
updatedAt: new Date().toISOString(),
|
|
353
|
+
};
|
|
354
|
+
// Call onComplete with merchant data
|
|
355
|
+
onComplete(completeMerchantData);
|
|
356
|
+
}, [merchantData, mode, status, kycStatus, stepCompletion, merchantResponse, onComplete, validateStepData]);
|
|
357
|
+
const getStepTitle = () => {
|
|
358
|
+
const step = STEPS.find(s => s.id === currentStep);
|
|
359
|
+
return (step === null || step === void 0 ? void 0 : step.name) || '';
|
|
360
|
+
};
|
|
361
|
+
const renderProviderVerification = () => {
|
|
362
|
+
if (isVerifying) {
|
|
363
|
+
return (<react_native_1.View style={styles.verificationContainer}>
|
|
364
|
+
<expo_linear_gradient_1.LinearGradient colors={['#0066CC', '#0099FF']} style={styles.verificationCircle} start={{ x: 0, y: 0 }} end={{ x: 1, y: 1 }}>
|
|
365
|
+
<react_native_paper_1.ActivityIndicator size="large" color="#FFFFFF"/>
|
|
366
|
+
</expo_linear_gradient_1.LinearGradient>
|
|
367
|
+
<react_native_paper_1.Text style={styles.verificationText}>
|
|
368
|
+
Verifying AirXPay configuration...
|
|
369
|
+
</react_native_paper_1.Text>
|
|
370
|
+
<react_native_paper_1.Text style={styles.verificationSubtext}>
|
|
371
|
+
Please wait while we validate your public key
|
|
372
|
+
</react_native_paper_1.Text>
|
|
373
|
+
</react_native_1.View>);
|
|
374
|
+
}
|
|
375
|
+
if (!isValidProvider) {
|
|
376
|
+
return (<react_native_1.View style={styles.verificationContainer}>
|
|
377
|
+
<react_native_1.View style={[styles.verificationCircle, { backgroundColor: '#FF4444' }]}>
|
|
378
|
+
<react_native_paper_1.IconButton icon="alert" size={40} iconColor="#FFFFFF" style={{ margin: 0 }}/>
|
|
379
|
+
</react_native_1.View>
|
|
380
|
+
<react_native_paper_1.Text style={[styles.verificationText, { color: '#FF4444' }]}>
|
|
381
|
+
Invalid AirXPay Configuration
|
|
382
|
+
</react_native_paper_1.Text>
|
|
383
|
+
<react_native_paper_1.Text style={styles.errorMessage}>
|
|
384
|
+
{verificationError || 'Invalid AirXPay public key. Please check your configuration.'}
|
|
385
|
+
</react_native_paper_1.Text>
|
|
386
|
+
</react_native_1.View>);
|
|
387
|
+
}
|
|
388
|
+
return null;
|
|
389
|
+
};
|
|
390
|
+
const renderStep = () => {
|
|
391
|
+
// Combine external loading and submitting states to prevent double loader
|
|
392
|
+
const isLoading = externalLoading || isSubmitting;
|
|
393
|
+
if (isLoading) {
|
|
394
|
+
return (<react_native_1.View style={styles.loadingContainer}>
|
|
395
|
+
<react_native_1.Animated.View style={{ transform: [{ scale: scaleAnim }] }}>
|
|
396
|
+
<expo_linear_gradient_1.LinearGradient colors={['#0066CC', '#0099FF']} style={styles.loadingCircle} start={{ x: 0, y: 0 }} end={{ x: 1, y: 1 }}>
|
|
397
|
+
<react_native_paper_1.ActivityIndicator size="large" color="#FFFFFF"/>
|
|
398
|
+
</expo_linear_gradient_1.LinearGradient>
|
|
399
|
+
</react_native_1.Animated.View>
|
|
400
|
+
<react_native_paper_1.Text style={styles.loadingText}>
|
|
401
|
+
{isSubmitting ? 'Processing...' : 'Loading your information...'}
|
|
402
|
+
</react_native_paper_1.Text>
|
|
403
|
+
</react_native_1.View>);
|
|
404
|
+
}
|
|
405
|
+
const stepContent = (() => {
|
|
406
|
+
switch (currentStep) {
|
|
407
|
+
case 1:
|
|
408
|
+
return (<BasicDetailsForm_1.default initialData={merchantData} onNext={(data) => handleNext(data)} errors={errors} setErrors={setErrors}/>);
|
|
409
|
+
case 2:
|
|
410
|
+
return (<KYCVerification_1.default initialData={merchantData} mode={mode} kycStatus={kycStatus} onNext={(data) => handleNext(data)} onBack={handleBack}/>);
|
|
411
|
+
case 3:
|
|
412
|
+
return (<BankDetails_1.default initialData={merchantData} mode={mode} onNext={(data) => handleNext(data)} onBack={handleBack}/>);
|
|
413
|
+
case 4:
|
|
414
|
+
return (<FinalStepScreen_1.FinalStepScreen publicKey={(airXPay === null || airXPay === void 0 ? void 0 : airXPay.publicKey) || ''} onSuccess={handleFinalStepSuccess} onError={handleFinalStepError} initialData={{
|
|
415
|
+
merchantName: merchantData.merchantName,
|
|
416
|
+
merchantEmail: merchantData.merchantEmail,
|
|
417
|
+
merchantPhone: merchantData.merchantPhone,
|
|
418
|
+
businessName: merchantData.businessName,
|
|
419
|
+
businessType: merchantData.businessType,
|
|
420
|
+
businessCategory: merchantData.businessCategory,
|
|
421
|
+
country: merchantData.country,
|
|
422
|
+
nationality: merchantData.nationality,
|
|
423
|
+
mode: mode,
|
|
424
|
+
}}/>);
|
|
425
|
+
case 5:
|
|
426
|
+
return (<OnboardingComplete_1.OnboardingCompleteScreen onContinue={handleComplete} onLogout={() => console.log('Logout')} autoFetch={true}/>);
|
|
427
|
+
default:
|
|
428
|
+
return null;
|
|
429
|
+
}
|
|
430
|
+
})();
|
|
431
|
+
return (<react_native_1.Animated.View style={[
|
|
432
|
+
styles.stepContentWrapper,
|
|
433
|
+
{
|
|
434
|
+
opacity: fadeAnim,
|
|
435
|
+
transform: [{ translateX: slideAnim }],
|
|
436
|
+
},
|
|
437
|
+
]}>
|
|
438
|
+
{stepContent}
|
|
439
|
+
</react_native_1.Animated.View>);
|
|
440
|
+
};
|
|
441
|
+
// Progress bar width interpolation
|
|
442
|
+
const progressWidth = progressAnim.interpolate({
|
|
443
|
+
inputRange: [0, 1],
|
|
444
|
+
outputRange: ['0%', '100%'],
|
|
445
|
+
});
|
|
446
|
+
// Check if we should show verification UI
|
|
447
|
+
if (isVerifying || !isValidProvider) {
|
|
448
|
+
return (<react_native_1.SafeAreaView style={styles.container}>
|
|
449
|
+
<react_native_1.StatusBar barStyle="dark-content" backgroundColor="#F8F9FA"/>
|
|
450
|
+
<expo_linear_gradient_1.LinearGradient colors={['#F8F9FA', '#FFFFFF']} style={styles.gradient} start={{ x: 0, y: 0 }} end={{ x: 0, y: 1 }}>
|
|
451
|
+
{renderProviderVerification()}
|
|
452
|
+
</expo_linear_gradient_1.LinearGradient>
|
|
453
|
+
</react_native_1.SafeAreaView>);
|
|
454
|
+
}
|
|
455
|
+
// Normal onboarding UI when provider is valid
|
|
456
|
+
return (<react_native_1.SafeAreaView style={styles.container}>
|
|
457
|
+
<react_native_1.StatusBar barStyle="dark-content" backgroundColor="#F8F9FA"/>
|
|
458
|
+
|
|
459
|
+
<expo_linear_gradient_1.LinearGradient colors={['#F8F9FA', '#FFFFFF']} style={styles.gradient} start={{ x: 0, y: 0 }} end={{ x: 0, y: 1 }}>
|
|
460
|
+
<react_native_1.KeyboardAvoidingView behavior={react_native_1.Platform.OS === 'ios' ? 'padding' : 'height'} style={styles.keyboardView}>
|
|
461
|
+
<react_native_paper_1.Surface style={styles.headerSurface}>
|
|
462
|
+
<react_native_1.View style={styles.header}>
|
|
463
|
+
<react_native_1.View style={styles.headerLeft}>
|
|
464
|
+
{currentStep > 1 && currentStep < 5 && (<react_native_1.TouchableOpacity onPress={handleBack} style={styles.backButton} disabled={isAnimating}>
|
|
465
|
+
<react_native_paper_1.IconButton icon="arrow-left" size={24} iconColor="#0066CC"/>
|
|
466
|
+
</react_native_1.TouchableOpacity>)}
|
|
467
|
+
<react_native_1.View>
|
|
468
|
+
<react_native_paper_1.Text style={styles.headerTitle}>
|
|
469
|
+
{getStepTitle()}
|
|
470
|
+
</react_native_paper_1.Text>
|
|
471
|
+
<react_native_paper_1.Text style={styles.headerSubtitle}>
|
|
472
|
+
Step {currentStep} of {STEPS.length}
|
|
473
|
+
</react_native_paper_1.Text>
|
|
474
|
+
</react_native_1.View>
|
|
475
|
+
</react_native_1.View>
|
|
476
|
+
|
|
477
|
+
{/* Logo Section - Fixed alignment */}
|
|
478
|
+
<react_native_1.View style={styles.logoContainer}>
|
|
479
|
+
<react_native_paper_1.Avatar.Image size={32} source={DEFAULT_LOGO}/>
|
|
480
|
+
</react_native_1.View>
|
|
481
|
+
</react_native_1.View>
|
|
482
|
+
|
|
483
|
+
{/* Progress Bar */}
|
|
484
|
+
<react_native_1.View style={styles.progressContainer}>
|
|
485
|
+
<react_native_1.View style={styles.progressBar}>
|
|
486
|
+
<react_native_1.Animated.View style={[
|
|
487
|
+
styles.progressFill,
|
|
488
|
+
{ width: progressWidth }
|
|
489
|
+
]}/>
|
|
490
|
+
</react_native_1.View>
|
|
491
|
+
</react_native_1.View>
|
|
492
|
+
</react_native_paper_1.Surface>
|
|
493
|
+
|
|
494
|
+
{/* Step Indicator */}
|
|
495
|
+
<react_native_1.View style={styles.stepIndicatorContainer}>
|
|
496
|
+
<StepIndicator_1.default currentStep={currentStep} steps={STEPS} mode={mode} isKycCompleted={stepCompletion.kyc} isBankDetailsCompleted={stepCompletion.bank}/>
|
|
497
|
+
</react_native_1.View>
|
|
498
|
+
|
|
499
|
+
{/* Current Step Content */}
|
|
500
|
+
<react_native_paper_1.Surface style={styles.contentSurface}>
|
|
501
|
+
<react_native_1.View style={styles.content}>
|
|
502
|
+
{renderStep()}
|
|
503
|
+
</react_native_1.View>
|
|
504
|
+
</react_native_paper_1.Surface>
|
|
505
|
+
|
|
506
|
+
{/* Error Snackbar */}
|
|
507
|
+
<react_native_paper_1.Snackbar visible={showError} onDismiss={() => setShowError(false)} duration={5000} action={{
|
|
508
|
+
label: 'DISMISS',
|
|
509
|
+
onPress: () => setShowError(false),
|
|
510
|
+
textColor: '#FFFFFF',
|
|
511
|
+
}} style={styles.snackbar} theme={{ colors: { accent: '#FFFFFF' } }}>
|
|
512
|
+
{Object.values(errors)[0] || 'An error occurred'}
|
|
513
|
+
</react_native_paper_1.Snackbar>
|
|
514
|
+
</react_native_1.KeyboardAvoidingView>
|
|
515
|
+
</expo_linear_gradient_1.LinearGradient>
|
|
516
|
+
</react_native_1.SafeAreaView>);
|
|
517
|
+
};
|
|
518
|
+
const styles = react_native_1.StyleSheet.create({
|
|
519
|
+
container: {
|
|
520
|
+
flex: 1,
|
|
521
|
+
backgroundColor: '#F8F9FA',
|
|
522
|
+
},
|
|
523
|
+
gradient: {
|
|
524
|
+
flex: 1,
|
|
525
|
+
},
|
|
526
|
+
keyboardView: {
|
|
527
|
+
flex: 1,
|
|
528
|
+
},
|
|
529
|
+
headerSurface: {
|
|
530
|
+
backgroundColor: '#FFFFFF',
|
|
531
|
+
borderBottomLeftRadius: 24,
|
|
532
|
+
borderBottomRightRadius: 24,
|
|
533
|
+
elevation: 4,
|
|
534
|
+
shadowColor: '#000',
|
|
535
|
+
shadowOffset: { width: 0, height: 2 },
|
|
536
|
+
shadowOpacity: 0.1,
|
|
537
|
+
shadowRadius: 8,
|
|
538
|
+
},
|
|
539
|
+
header: {
|
|
540
|
+
flexDirection: 'row',
|
|
541
|
+
justifyContent: 'space-between',
|
|
542
|
+
alignItems: 'center',
|
|
543
|
+
paddingHorizontal: 20,
|
|
544
|
+
paddingTop: 16,
|
|
545
|
+
paddingBottom: 12,
|
|
546
|
+
},
|
|
547
|
+
headerLeft: {
|
|
548
|
+
flexDirection: 'row',
|
|
549
|
+
alignItems: 'center',
|
|
550
|
+
},
|
|
551
|
+
backButton: {
|
|
552
|
+
marginRight: 8,
|
|
553
|
+
backgroundColor: '#F0F7FF',
|
|
554
|
+
borderRadius: 20,
|
|
555
|
+
},
|
|
556
|
+
headerTitle: {
|
|
557
|
+
fontSize: 20,
|
|
558
|
+
fontWeight: '700',
|
|
559
|
+
color: '#1A1A1A',
|
|
560
|
+
letterSpacing: 0.5,
|
|
561
|
+
},
|
|
562
|
+
headerSubtitle: {
|
|
563
|
+
fontSize: 13,
|
|
564
|
+
color: '#666666',
|
|
565
|
+
marginTop: 2,
|
|
566
|
+
fontWeight: '400',
|
|
567
|
+
},
|
|
568
|
+
logoContainer: {
|
|
569
|
+
width: 40,
|
|
570
|
+
height: 40,
|
|
571
|
+
justifyContent: 'center',
|
|
572
|
+
alignItems: 'center',
|
|
573
|
+
backgroundColor: '#FFFFFF',
|
|
574
|
+
borderRadius: 20,
|
|
575
|
+
elevation: 2,
|
|
576
|
+
shadowColor: '#000',
|
|
577
|
+
shadowOffset: { width: 0, height: 2 },
|
|
578
|
+
shadowOpacity: 0.1,
|
|
579
|
+
shadowRadius: 4,
|
|
580
|
+
},
|
|
581
|
+
progressContainer: {
|
|
582
|
+
paddingHorizontal: 20,
|
|
583
|
+
paddingBottom: 20,
|
|
584
|
+
},
|
|
585
|
+
progressBar: {
|
|
586
|
+
height: 4,
|
|
587
|
+
backgroundColor: '#E5E5E5',
|
|
588
|
+
borderRadius: 2,
|
|
589
|
+
overflow: 'hidden',
|
|
590
|
+
},
|
|
591
|
+
progressFill: {
|
|
592
|
+
height: '100%',
|
|
593
|
+
backgroundColor: '#0066CC',
|
|
594
|
+
borderRadius: 2,
|
|
595
|
+
},
|
|
596
|
+
stepIndicatorContainer: {
|
|
597
|
+
paddingVertical: 16,
|
|
598
|
+
paddingHorizontal: 20,
|
|
599
|
+
},
|
|
600
|
+
contentSurface: {
|
|
601
|
+
flex: 1,
|
|
602
|
+
marginHorizontal: 16,
|
|
603
|
+
marginBottom: 16,
|
|
604
|
+
backgroundColor: '#FFFFFF',
|
|
605
|
+
borderRadius: 24,
|
|
606
|
+
elevation: 2,
|
|
607
|
+
shadowColor: '#000',
|
|
608
|
+
shadowOffset: { width: 0, height: 2 },
|
|
609
|
+
shadowOpacity: 0.05,
|
|
610
|
+
shadowRadius: 8,
|
|
611
|
+
overflow: 'hidden',
|
|
612
|
+
},
|
|
613
|
+
content: {
|
|
614
|
+
flex: 1,
|
|
615
|
+
backgroundColor: 'transparent',
|
|
616
|
+
},
|
|
617
|
+
stepContentWrapper: {
|
|
618
|
+
flex: 1,
|
|
619
|
+
},
|
|
620
|
+
loadingContainer: {
|
|
621
|
+
flex: 1,
|
|
622
|
+
justifyContent: 'center',
|
|
623
|
+
alignItems: 'center',
|
|
624
|
+
padding: 20,
|
|
625
|
+
},
|
|
626
|
+
loadingCircle: {
|
|
627
|
+
width: 80,
|
|
628
|
+
height: 80,
|
|
629
|
+
borderRadius: 40,
|
|
630
|
+
justifyContent: 'center',
|
|
631
|
+
alignItems: 'center',
|
|
632
|
+
},
|
|
633
|
+
loadingText: {
|
|
634
|
+
marginTop: 16,
|
|
635
|
+
fontSize: 16,
|
|
636
|
+
color: '#666666',
|
|
637
|
+
fontWeight: '500',
|
|
638
|
+
},
|
|
639
|
+
snackbar: {
|
|
640
|
+
backgroundColor: '#FF4444',
|
|
641
|
+
marginBottom: 16,
|
|
642
|
+
borderRadius: 8,
|
|
643
|
+
},
|
|
644
|
+
verificationContainer: {
|
|
645
|
+
flex: 1,
|
|
646
|
+
justifyContent: 'center',
|
|
647
|
+
alignItems: 'center',
|
|
648
|
+
padding: 20,
|
|
649
|
+
},
|
|
650
|
+
verificationCircle: {
|
|
651
|
+
width: 100,
|
|
652
|
+
height: 100,
|
|
653
|
+
borderRadius: 50,
|
|
654
|
+
justifyContent: 'center',
|
|
655
|
+
alignItems: 'center',
|
|
656
|
+
marginBottom: 24,
|
|
657
|
+
},
|
|
658
|
+
verificationText: {
|
|
659
|
+
fontSize: 20,
|
|
660
|
+
fontWeight: '700',
|
|
661
|
+
color: '#1A1A1A',
|
|
662
|
+
marginBottom: 8,
|
|
663
|
+
textAlign: 'center',
|
|
664
|
+
},
|
|
665
|
+
verificationSubtext: {
|
|
666
|
+
fontSize: 14,
|
|
667
|
+
color: '#666666',
|
|
668
|
+
textAlign: 'center',
|
|
669
|
+
},
|
|
670
|
+
errorMessage: {
|
|
671
|
+
fontSize: 16,
|
|
672
|
+
color: '#666666',
|
|
673
|
+
textAlign: 'center',
|
|
674
|
+
marginTop: 8,
|
|
675
|
+
paddingHorizontal: 20,
|
|
676
|
+
},
|
|
677
|
+
});
|
|
678
|
+
exports.default = MerchantOnboardingSheet;
|