@airxpay/sdk-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 +21 -0
- package/README.md +400 -0
- package/dist/api/seller.js +17 -0
- package/dist/components/common/CountryDropdown.js +138 -0
- package/dist/components/common/FileUploader.js +210 -0
- package/dist/components/common/StepIndicator.js +269 -0
- package/dist/components/steps/BankDetails.js +562 -0
- package/dist/components/steps/BasicDetailsForm.js +581 -0
- package/dist/components/steps/KYCVerification.js +510 -0
- package/dist/components/steps/OnboardingComplete.js +752 -0
- package/dist/components/ui/SellerOnboard/CustomSegmentedButtons.js +64 -0
- package/dist/components/ui/SellerOnboard/SellerOnboarding.js +490 -0
- package/dist/contexts/AirXPayProvider.js +154 -0
- package/dist/hooks/SellerOnboarding.js +11 -0
- package/dist/index.js +12 -0
- package/dist/sdk/airxpay.js +18 -0
- package/dist/types/sellertypes.js +4 -0
- package/dist/types/type.js +2 -0
- package/package.json +58 -0
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
const react_1 = __importDefault(require("react"));
|
|
7
|
+
const react_native_1 = require("react-native");
|
|
8
|
+
const styles = react_native_1.StyleSheet.create({
|
|
9
|
+
segmentedContainer: {
|
|
10
|
+
flexDirection: 'row',
|
|
11
|
+
backgroundColor: '#f0f0f0',
|
|
12
|
+
borderRadius: 8,
|
|
13
|
+
padding: 4,
|
|
14
|
+
},
|
|
15
|
+
segmentedButton: {
|
|
16
|
+
flex: 1,
|
|
17
|
+
flexDirection: 'row',
|
|
18
|
+
justifyContent: 'center',
|
|
19
|
+
alignItems: 'center',
|
|
20
|
+
paddingVertical: 8,
|
|
21
|
+
paddingHorizontal: 12,
|
|
22
|
+
borderRadius: 6,
|
|
23
|
+
backgroundColor: 'transparent',
|
|
24
|
+
},
|
|
25
|
+
segmentedButtonActive: {
|
|
26
|
+
backgroundColor: '#6200ee',
|
|
27
|
+
elevation: 2,
|
|
28
|
+
shadowColor: '#000',
|
|
29
|
+
shadowOffset: { width: 0, height: 1 },
|
|
30
|
+
shadowOpacity: 0.2,
|
|
31
|
+
shadowRadius: 1,
|
|
32
|
+
},
|
|
33
|
+
segmentedButtonText: {
|
|
34
|
+
fontSize: 14,
|
|
35
|
+
fontWeight: '500',
|
|
36
|
+
color: '#666',
|
|
37
|
+
},
|
|
38
|
+
segmentedButtonTextActive: {
|
|
39
|
+
color: 'white',
|
|
40
|
+
},
|
|
41
|
+
segmentedButtonCheck: {
|
|
42
|
+
color: 'white',
|
|
43
|
+
marginLeft: 4,
|
|
44
|
+
fontSize: 14,
|
|
45
|
+
fontWeight: 'bold',
|
|
46
|
+
},
|
|
47
|
+
});
|
|
48
|
+
const CustomSegmentedButtons = ({ value, onValueChange, buttons, style, }) => {
|
|
49
|
+
return (<react_native_1.View style={[styles.segmentedContainer, style]}>
|
|
50
|
+
{buttons.map((button) => (<react_native_1.TouchableOpacity key={button.value} style={[
|
|
51
|
+
styles.segmentedButton,
|
|
52
|
+
value === button.value && styles.segmentedButtonActive
|
|
53
|
+
]} onPress={() => onValueChange(button.value)}>
|
|
54
|
+
<react_native_1.Text style={[
|
|
55
|
+
styles.segmentedButtonText,
|
|
56
|
+
value === button.value && styles.segmentedButtonTextActive
|
|
57
|
+
]}>
|
|
58
|
+
{button.label}
|
|
59
|
+
</react_native_1.Text>
|
|
60
|
+
{button.showSelectedCheck && value === button.value && (<react_native_1.Text style={styles.segmentedButtonCheck}>✓</react_native_1.Text>)}
|
|
61
|
+
</react_native_1.TouchableOpacity>))}
|
|
62
|
+
</react_native_1.View>);
|
|
63
|
+
};
|
|
64
|
+
exports.default = CustomSegmentedButtons;
|
|
@@ -0,0 +1,490 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
// components/SellerOnboardingSheet.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 __importDefault = (this && this.__importDefault) || function (mod) {
|
|
37
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
38
|
+
};
|
|
39
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
40
|
+
const react_1 = __importStar(require("react"));
|
|
41
|
+
const react_native_1 = require("react-native");
|
|
42
|
+
const react_native_paper_1 = require("react-native-paper");
|
|
43
|
+
const expo_linear_gradient_1 = require("expo-linear-gradient");
|
|
44
|
+
const StepIndicator_1 = __importDefault(require("../../common/StepIndicator"));
|
|
45
|
+
const BasicDetailsForm_1 = __importDefault(require("../../steps/BasicDetailsForm"));
|
|
46
|
+
const KYCVerification_1 = __importDefault(require("../../steps/KYCVerification"));
|
|
47
|
+
const BankDetails_1 = __importDefault(require("../../steps/BankDetails"));
|
|
48
|
+
const OnboardingComplete_1 = __importDefault(require("../../steps/OnboardingComplete"));
|
|
49
|
+
const AirXPayProvider_1 = require("../../../contexts/AirXPayProvider");
|
|
50
|
+
const { width } = react_native_1.Dimensions.get('window');
|
|
51
|
+
const STEPS = [
|
|
52
|
+
{ id: 1, name: 'Basic Details', key: 'basic', isRequired: true, icon: 'account' },
|
|
53
|
+
{ id: 2, name: 'KYC Verification', key: 'kyc', isRequired: true, icon: 'shield-account' },
|
|
54
|
+
{ id: 3, name: 'Bank Details', key: 'bank', isRequired: true, icon: 'bank' },
|
|
55
|
+
{ id: 4, name: 'Complete', key: 'complete', isRequired: false, icon: 'check-circle' },
|
|
56
|
+
];
|
|
57
|
+
// Default logo - can be overridden via props
|
|
58
|
+
const DEFAULT_LOGO = require('../../../../../../assets/images/airxpay.png');
|
|
59
|
+
const SellerOnboardingSheet = ({ sellerId, mode, isKycCompleted, isBankDetailsCompleted, kycStatus, status, initialStep = 1, initialData = {}, onNext, onBack, onComplete, loading: externalLoading = false, }) => {
|
|
60
|
+
// Get configuration from provider (keep intact as required)
|
|
61
|
+
const airXPay = (0, AirXPayProvider_1.useAirXPaySafe)();
|
|
62
|
+
if (!airXPay) {
|
|
63
|
+
console.warn('AirXPayProvider is undefined. ' +
|
|
64
|
+
'Provider not found in component tree. ' +
|
|
65
|
+
'Value is undefined where provider should be. ' +
|
|
66
|
+
'This undefined provider will cause issues. ' +
|
|
67
|
+
'Undefined context from missing provider. ' +
|
|
68
|
+
'Wrap your app with <AirXPayProvider>. ' +
|
|
69
|
+
'AirXPayProvider cannot be undefined. ' +
|
|
70
|
+
'Undefined provider at root level missing. ' +
|
|
71
|
+
'Add <AirXPayProvider> around your app. ' +
|
|
72
|
+
'Fix this undefined provider immediately.');
|
|
73
|
+
}
|
|
74
|
+
// Access config safely
|
|
75
|
+
const baseUrl = airXPay?.baseUrl;
|
|
76
|
+
const publicKey = airXPay?.publicKey;
|
|
77
|
+
// Properly use variables so TS doesn't complain
|
|
78
|
+
(0, react_1.useEffect)(() => {
|
|
79
|
+
if (!baseUrl || !publicKey) {
|
|
80
|
+
console.warn('AirXPay config is missing baseUrl or publicKey');
|
|
81
|
+
}
|
|
82
|
+
else {
|
|
83
|
+
console.log('✅ AirXPay ready with baseUrl and publicKey');
|
|
84
|
+
}
|
|
85
|
+
}, [baseUrl, publicKey]);
|
|
86
|
+
// Animation values
|
|
87
|
+
const fadeAnim = (0, react_1.useRef)(new react_native_1.Animated.Value(1)).current;
|
|
88
|
+
const slideAnim = (0, react_1.useRef)(new react_native_1.Animated.Value(0)).current;
|
|
89
|
+
const progressAnim = (0, react_1.useRef)(new react_native_1.Animated.Value(initialStep / STEPS.length)).current;
|
|
90
|
+
const scaleAnim = (0, react_1.useRef)(new react_native_1.Animated.Value(1)).current;
|
|
91
|
+
// State management
|
|
92
|
+
const [currentStep, setCurrentStep] = (0, react_1.useState)(initialStep);
|
|
93
|
+
const [sellerData, setSellerData] = (0, react_1.useState)({
|
|
94
|
+
mode,
|
|
95
|
+
kycStatus,
|
|
96
|
+
isKycCompleted,
|
|
97
|
+
isBankDetailsCompleted,
|
|
98
|
+
status,
|
|
99
|
+
...initialData,
|
|
100
|
+
});
|
|
101
|
+
const [errors, setErrors] = (0, react_1.useState)({});
|
|
102
|
+
const [showError, setShowError] = (0, react_1.useState)(false);
|
|
103
|
+
const [isAnimating, setIsAnimating] = (0, react_1.useState)(false);
|
|
104
|
+
const [isSubmitting, setIsSubmitting] = (0, react_1.useState)(false);
|
|
105
|
+
const [isWaitingForBackend, setIsWaitingForBackend] = (0, react_1.useState)(false);
|
|
106
|
+
// Track completion status of each step
|
|
107
|
+
const [stepCompletion, setStepCompletion] = (0, react_1.useState)({
|
|
108
|
+
basic: !!initialData.sellerName && !!initialData.sellerEmail,
|
|
109
|
+
kyc: isKycCompleted || false,
|
|
110
|
+
bank: isBankDetailsCompleted || false,
|
|
111
|
+
});
|
|
112
|
+
// Update progress bar animation when step changes
|
|
113
|
+
(0, react_1.useEffect)(() => {
|
|
114
|
+
react_native_1.Animated.timing(progressAnim, {
|
|
115
|
+
toValue: currentStep / STEPS.length,
|
|
116
|
+
duration: 300,
|
|
117
|
+
useNativeDriver: false,
|
|
118
|
+
}).start();
|
|
119
|
+
}, [currentStep]);
|
|
120
|
+
const animateStepTransition = (direction) => {
|
|
121
|
+
if (isAnimating)
|
|
122
|
+
return;
|
|
123
|
+
setIsAnimating(true);
|
|
124
|
+
// Fade out and slide
|
|
125
|
+
react_native_1.Animated.parallel([
|
|
126
|
+
react_native_1.Animated.timing(fadeAnim, {
|
|
127
|
+
toValue: 0,
|
|
128
|
+
duration: 150,
|
|
129
|
+
useNativeDriver: true,
|
|
130
|
+
}),
|
|
131
|
+
react_native_1.Animated.timing(slideAnim, {
|
|
132
|
+
toValue: direction === 'next' ? -50 : 50,
|
|
133
|
+
duration: 150,
|
|
134
|
+
useNativeDriver: true,
|
|
135
|
+
}),
|
|
136
|
+
]).start(() => {
|
|
137
|
+
// Reset slide position
|
|
138
|
+
slideAnim.setValue(direction === 'next' ? 50 : -50);
|
|
139
|
+
// Fade in and slide to center
|
|
140
|
+
react_native_1.Animated.parallel([
|
|
141
|
+
react_native_1.Animated.timing(fadeAnim, {
|
|
142
|
+
toValue: 1,
|
|
143
|
+
duration: 150,
|
|
144
|
+
useNativeDriver: true,
|
|
145
|
+
}),
|
|
146
|
+
react_native_1.Animated.timing(slideAnim, {
|
|
147
|
+
toValue: 0,
|
|
148
|
+
duration: 150,
|
|
149
|
+
useNativeDriver: true,
|
|
150
|
+
}),
|
|
151
|
+
]).start(() => {
|
|
152
|
+
setIsAnimating(false);
|
|
153
|
+
});
|
|
154
|
+
});
|
|
155
|
+
};
|
|
156
|
+
const handleNext = (stepData) => {
|
|
157
|
+
const updatedData = { ...sellerData, ...stepData };
|
|
158
|
+
setSellerData(updatedData);
|
|
159
|
+
// Update step completion status
|
|
160
|
+
if (currentStep === 1) {
|
|
161
|
+
setStepCompletion(prev => ({
|
|
162
|
+
...prev,
|
|
163
|
+
basic: !!(updatedData.sellerName && updatedData.sellerEmail)
|
|
164
|
+
}));
|
|
165
|
+
}
|
|
166
|
+
else if (currentStep === 2) {
|
|
167
|
+
setStepCompletion(prev => ({ ...prev, kyc: true }));
|
|
168
|
+
}
|
|
169
|
+
else if (currentStep === 3) {
|
|
170
|
+
setStepCompletion(prev => ({ ...prev, bank: true }));
|
|
171
|
+
}
|
|
172
|
+
// Call onNext callback with step data and current step
|
|
173
|
+
onNext(stepData, currentStep);
|
|
174
|
+
// Move to next step if not last step
|
|
175
|
+
if (currentStep < STEPS.length) {
|
|
176
|
+
animateStepTransition('next');
|
|
177
|
+
setTimeout(() => {
|
|
178
|
+
setCurrentStep(prev => prev + 1);
|
|
179
|
+
}, 150);
|
|
180
|
+
}
|
|
181
|
+
};
|
|
182
|
+
const handleBack = () => {
|
|
183
|
+
if (currentStep > 1) {
|
|
184
|
+
animateStepTransition('back');
|
|
185
|
+
setTimeout(() => {
|
|
186
|
+
setCurrentStep(prev => prev - 1);
|
|
187
|
+
onBack(currentStep);
|
|
188
|
+
}, 150);
|
|
189
|
+
}
|
|
190
|
+
};
|
|
191
|
+
const validateStepData = (0, react_1.useCallback)(() => {
|
|
192
|
+
// Validate required fields
|
|
193
|
+
if (!sellerData.sellerName || !sellerData.sellerEmail) {
|
|
194
|
+
setErrors({ sellerName: 'Seller name and email are required' });
|
|
195
|
+
setShowError(true);
|
|
196
|
+
return false;
|
|
197
|
+
}
|
|
198
|
+
if (mode === 'live') {
|
|
199
|
+
if (!stepCompletion.kyc) {
|
|
200
|
+
react_native_1.Alert.alert('KYC Pending', 'Please complete KYC verification first', [
|
|
201
|
+
{ text: 'Cancel', style: 'cancel' },
|
|
202
|
+
{ text: 'Go to KYC', onPress: () => setCurrentStep(2) }
|
|
203
|
+
]);
|
|
204
|
+
return false;
|
|
205
|
+
}
|
|
206
|
+
if (!stepCompletion.bank) {
|
|
207
|
+
react_native_1.Alert.alert('Bank Details Pending', 'Please add bank details first', [
|
|
208
|
+
{ text: 'Cancel', style: 'cancel' },
|
|
209
|
+
{ text: 'Go to Bank Details', onPress: () => setCurrentStep(3) }
|
|
210
|
+
]);
|
|
211
|
+
return false;
|
|
212
|
+
}
|
|
213
|
+
}
|
|
214
|
+
return true;
|
|
215
|
+
}, [sellerData, mode, stepCompletion]);
|
|
216
|
+
const handleComplete = (0, react_1.useCallback)(() => {
|
|
217
|
+
// Validate all required data before completing
|
|
218
|
+
if (!validateStepData()) {
|
|
219
|
+
return;
|
|
220
|
+
}
|
|
221
|
+
if (!baseUrl || !publicKey) {
|
|
222
|
+
react_native_1.Alert.alert('Configuration Error', 'AirXPay baseUrl or publicKey is missing. Please check provider setup.');
|
|
223
|
+
return;
|
|
224
|
+
}
|
|
225
|
+
// Show loading state while waiting for backend confirmation
|
|
226
|
+
setIsWaitingForBackend(true);
|
|
227
|
+
// Success animation
|
|
228
|
+
react_native_1.Animated.sequence([
|
|
229
|
+
react_native_1.Animated.timing(scaleAnim, {
|
|
230
|
+
toValue: 1.1,
|
|
231
|
+
duration: 200,
|
|
232
|
+
useNativeDriver: true,
|
|
233
|
+
}),
|
|
234
|
+
react_native_1.Animated.timing(scaleAnim, {
|
|
235
|
+
toValue: 1,
|
|
236
|
+
duration: 200,
|
|
237
|
+
useNativeDriver: true,
|
|
238
|
+
}),
|
|
239
|
+
]).start();
|
|
240
|
+
// Prepare complete seller data
|
|
241
|
+
const completeSellerData = {
|
|
242
|
+
...sellerData,
|
|
243
|
+
mode,
|
|
244
|
+
kycStatus: stepCompletion.kyc ? 'verified' : kycStatus,
|
|
245
|
+
isKycCompleted: stepCompletion.kyc,
|
|
246
|
+
isBankDetailsCompleted: stepCompletion.bank,
|
|
247
|
+
status: status || (mode === 'live' && stepCompletion.kyc && stepCompletion.bank ? 'active' : 'pending'),
|
|
248
|
+
};
|
|
249
|
+
// Call onComplete with seller data
|
|
250
|
+
// The developer's backend will handle actual seller creation
|
|
251
|
+
// and should call a callback or update state when complete
|
|
252
|
+
onComplete(completeSellerData);
|
|
253
|
+
}, [sellerData, mode, status, kycStatus, stepCompletion, onComplete, validateStepData]);
|
|
254
|
+
// This function would be called by the parent when backend confirms creation
|
|
255
|
+
const handleBackendConfirmation = (0, react_1.useCallback)(() => {
|
|
256
|
+
setIsWaitingForBackend(false);
|
|
257
|
+
// The OnboardingComplete component will now show success state
|
|
258
|
+
}, []);
|
|
259
|
+
const getStepTitle = () => {
|
|
260
|
+
const step = STEPS.find(s => s.id === currentStep);
|
|
261
|
+
return step?.name || '';
|
|
262
|
+
};
|
|
263
|
+
const renderStep = () => {
|
|
264
|
+
const isLoading = externalLoading || isSubmitting;
|
|
265
|
+
if (isLoading) {
|
|
266
|
+
return (<react_native_1.View style={styles.loadingContainer}>
|
|
267
|
+
<react_native_1.Animated.View style={{ transform: [{ scale: scaleAnim }] }}>
|
|
268
|
+
<expo_linear_gradient_1.LinearGradient colors={['#0066CC', '#0099FF']} style={styles.loadingCircle} start={{ x: 0, y: 0 }} end={{ x: 1, y: 1 }}>
|
|
269
|
+
<react_native_paper_1.ActivityIndicator size="large" color="#FFFFFF"/>
|
|
270
|
+
</expo_linear_gradient_1.LinearGradient>
|
|
271
|
+
</react_native_1.Animated.View>
|
|
272
|
+
<react_native_paper_1.Text style={styles.loadingText}>
|
|
273
|
+
{isSubmitting ? 'Processing...' : 'Loading your information...'}
|
|
274
|
+
</react_native_paper_1.Text>
|
|
275
|
+
</react_native_1.View>);
|
|
276
|
+
}
|
|
277
|
+
const stepContent = (() => {
|
|
278
|
+
switch (currentStep) {
|
|
279
|
+
case 1:
|
|
280
|
+
return (<BasicDetailsForm_1.default initialData={sellerData} onNext={(data) => handleNext(data)} errors={errors} setErrors={setErrors}/>);
|
|
281
|
+
case 2:
|
|
282
|
+
return (<KYCVerification_1.default initialData={sellerData} mode={mode} kycStatus={kycStatus} onNext={(data) => handleNext(data)} onBack={handleBack}/>);
|
|
283
|
+
case 3:
|
|
284
|
+
return (<BankDetails_1.default initialData={sellerData} mode={mode} onNext={(data) => handleNext(data)} onBack={handleBack}/>);
|
|
285
|
+
case 4:
|
|
286
|
+
return (<OnboardingComplete_1.default sellerData={sellerData} mode={mode} status={status} kycStatus={kycStatus} isBankDetailsCompleted={stepCompletion.bank} isKycCompleted={stepCompletion.kyc} isBasicCompleted={stepCompletion.basic} onComplete={handleComplete} isWaitingForBackend={isWaitingForBackend} onBackendConfirmed={handleBackendConfirmation}/>);
|
|
287
|
+
default:
|
|
288
|
+
return null;
|
|
289
|
+
}
|
|
290
|
+
})();
|
|
291
|
+
return (<react_native_1.Animated.View style={[
|
|
292
|
+
styles.stepContentWrapper,
|
|
293
|
+
{
|
|
294
|
+
opacity: fadeAnim,
|
|
295
|
+
transform: [{ translateX: slideAnim }],
|
|
296
|
+
},
|
|
297
|
+
]}>
|
|
298
|
+
{stepContent}
|
|
299
|
+
</react_native_1.Animated.View>);
|
|
300
|
+
};
|
|
301
|
+
// Progress bar width interpolation
|
|
302
|
+
const progressWidth = progressAnim.interpolate({
|
|
303
|
+
inputRange: [0, 1],
|
|
304
|
+
outputRange: ['0%', '100%'],
|
|
305
|
+
});
|
|
306
|
+
return (<react_native_1.SafeAreaView style={styles.container}>
|
|
307
|
+
<react_native_1.StatusBar barStyle="dark-content" backgroundColor="#F8F9FA"/>
|
|
308
|
+
|
|
309
|
+
<expo_linear_gradient_1.LinearGradient colors={['#F8F9FA', '#FFFFFF']} style={styles.gradient} start={{ x: 0, y: 0 }} end={{ x: 0, y: 1 }}>
|
|
310
|
+
<react_native_1.KeyboardAvoidingView behavior={react_native_1.Platform.OS === 'ios' ? 'padding' : 'height'} style={styles.keyboardView}>
|
|
311
|
+
<react_native_paper_1.Surface style={styles.headerSurface}>
|
|
312
|
+
<react_native_1.View style={styles.header}>
|
|
313
|
+
<react_native_1.View style={styles.headerLeft}>
|
|
314
|
+
{currentStep > 1 && currentStep < 4 && (<react_native_1.TouchableOpacity onPress={handleBack} style={styles.backButton} disabled={isAnimating}>
|
|
315
|
+
<react_native_paper_1.IconButton icon="arrow-left" size={24} iconColor="#0066CC"/>
|
|
316
|
+
</react_native_1.TouchableOpacity>)}
|
|
317
|
+
<react_native_1.View>
|
|
318
|
+
<react_native_paper_1.Text style={styles.headerTitle}>
|
|
319
|
+
{getStepTitle()}
|
|
320
|
+
</react_native_paper_1.Text>
|
|
321
|
+
<react_native_paper_1.Text style={styles.headerSubtitle}>
|
|
322
|
+
Step {currentStep} of {STEPS.length}
|
|
323
|
+
</react_native_paper_1.Text>
|
|
324
|
+
</react_native_1.View>
|
|
325
|
+
</react_native_1.View>
|
|
326
|
+
|
|
327
|
+
{/* Logo Section - Now configurable */}
|
|
328
|
+
<react_native_1.View style={styles.logoContainer}>
|
|
329
|
+
<react_native_paper_1.Avatar.Image size={40} source={DEFAULT_LOGO} style={styles.avatar}/>
|
|
330
|
+
</react_native_1.View>
|
|
331
|
+
</react_native_1.View>
|
|
332
|
+
|
|
333
|
+
{/* Progress Bar */}
|
|
334
|
+
<react_native_1.View style={styles.progressContainer}>
|
|
335
|
+
<react_native_1.View style={styles.progressBar}>
|
|
336
|
+
<react_native_1.Animated.View style={[
|
|
337
|
+
styles.progressFill,
|
|
338
|
+
{ width: progressWidth }
|
|
339
|
+
]}/>
|
|
340
|
+
</react_native_1.View>
|
|
341
|
+
</react_native_1.View>
|
|
342
|
+
</react_native_paper_1.Surface>
|
|
343
|
+
|
|
344
|
+
{/* Step Indicator */}
|
|
345
|
+
<react_native_1.View style={styles.stepIndicatorContainer}>
|
|
346
|
+
<StepIndicator_1.default currentStep={currentStep} steps={STEPS} mode={mode} isKycCompleted={stepCompletion.kyc} isBankDetailsCompleted={stepCompletion.bank}/>
|
|
347
|
+
</react_native_1.View>
|
|
348
|
+
|
|
349
|
+
{/* Current Step Content */}
|
|
350
|
+
<react_native_paper_1.Surface style={styles.contentSurface}>
|
|
351
|
+
<react_native_1.View style={styles.content}>
|
|
352
|
+
{renderStep()}
|
|
353
|
+
</react_native_1.View>
|
|
354
|
+
</react_native_paper_1.Surface>
|
|
355
|
+
|
|
356
|
+
{/* Error Snackbar */}
|
|
357
|
+
<react_native_paper_1.Snackbar visible={showError} onDismiss={() => setShowError(false)} duration={5000} action={{
|
|
358
|
+
label: 'DISMISS',
|
|
359
|
+
onPress: () => setShowError(false),
|
|
360
|
+
textColor: '#FFFFFF',
|
|
361
|
+
}} style={styles.snackbar} theme={{ colors: { accent: '#FFFFFF' } }}>
|
|
362
|
+
{Object.values(errors)[0] || 'An error occurred'}
|
|
363
|
+
</react_native_paper_1.Snackbar>
|
|
364
|
+
</react_native_1.KeyboardAvoidingView>
|
|
365
|
+
</expo_linear_gradient_1.LinearGradient>
|
|
366
|
+
</react_native_1.SafeAreaView>);
|
|
367
|
+
};
|
|
368
|
+
const styles = react_native_1.StyleSheet.create({
|
|
369
|
+
container: {
|
|
370
|
+
flex: 1,
|
|
371
|
+
backgroundColor: '#F8F9FA',
|
|
372
|
+
},
|
|
373
|
+
gradient: {
|
|
374
|
+
flex: 1,
|
|
375
|
+
},
|
|
376
|
+
keyboardView: {
|
|
377
|
+
flex: 1,
|
|
378
|
+
},
|
|
379
|
+
headerSurface: {
|
|
380
|
+
backgroundColor: '#FFFFFF',
|
|
381
|
+
borderBottomLeftRadius: 24,
|
|
382
|
+
borderBottomRightRadius: 24,
|
|
383
|
+
elevation: 4,
|
|
384
|
+
shadowColor: '#000',
|
|
385
|
+
shadowOffset: { width: 0, height: 2 },
|
|
386
|
+
shadowOpacity: 0.1,
|
|
387
|
+
shadowRadius: 8,
|
|
388
|
+
},
|
|
389
|
+
header: {
|
|
390
|
+
flexDirection: 'row',
|
|
391
|
+
justifyContent: 'space-between',
|
|
392
|
+
alignItems: 'center',
|
|
393
|
+
paddingHorizontal: 20,
|
|
394
|
+
paddingTop: 16,
|
|
395
|
+
paddingBottom: 12,
|
|
396
|
+
},
|
|
397
|
+
headerLeft: {
|
|
398
|
+
flexDirection: 'row',
|
|
399
|
+
alignItems: 'center',
|
|
400
|
+
},
|
|
401
|
+
backButton: {
|
|
402
|
+
marginRight: 8,
|
|
403
|
+
backgroundColor: '#F0F7FF',
|
|
404
|
+
borderRadius: 20,
|
|
405
|
+
},
|
|
406
|
+
headerTitle: {
|
|
407
|
+
fontSize: 20,
|
|
408
|
+
fontWeight: '700',
|
|
409
|
+
color: '#1A1A1A',
|
|
410
|
+
letterSpacing: 0.5,
|
|
411
|
+
},
|
|
412
|
+
headerSubtitle: {
|
|
413
|
+
fontSize: 13,
|
|
414
|
+
color: '#666666',
|
|
415
|
+
marginTop: 2,
|
|
416
|
+
fontWeight: '400',
|
|
417
|
+
},
|
|
418
|
+
avatar: {
|
|
419
|
+
backgroundColor: '#ffffff',
|
|
420
|
+
},
|
|
421
|
+
logoContainer: {
|
|
422
|
+
width: 16,
|
|
423
|
+
height: 16,
|
|
424
|
+
left: -24,
|
|
425
|
+
},
|
|
426
|
+
progressContainer: {
|
|
427
|
+
paddingHorizontal: 20,
|
|
428
|
+
paddingBottom: 20,
|
|
429
|
+
},
|
|
430
|
+
progressBar: {
|
|
431
|
+
height: 4,
|
|
432
|
+
backgroundColor: '#E5E5E5',
|
|
433
|
+
borderRadius: 2,
|
|
434
|
+
overflow: 'hidden',
|
|
435
|
+
},
|
|
436
|
+
progressFill: {
|
|
437
|
+
height: '100%',
|
|
438
|
+
backgroundColor: '#0066CC',
|
|
439
|
+
borderRadius: 2,
|
|
440
|
+
},
|
|
441
|
+
stepIndicatorContainer: {
|
|
442
|
+
paddingVertical: 16,
|
|
443
|
+
paddingHorizontal: 20,
|
|
444
|
+
},
|
|
445
|
+
contentSurface: {
|
|
446
|
+
flex: 1,
|
|
447
|
+
marginHorizontal: 16,
|
|
448
|
+
marginBottom: 16,
|
|
449
|
+
backgroundColor: '#FFFFFF',
|
|
450
|
+
borderRadius: 24,
|
|
451
|
+
elevation: 2,
|
|
452
|
+
shadowColor: '#000',
|
|
453
|
+
shadowOffset: { width: 0, height: 2 },
|
|
454
|
+
shadowOpacity: 0.05,
|
|
455
|
+
shadowRadius: 8,
|
|
456
|
+
overflow: 'hidden',
|
|
457
|
+
},
|
|
458
|
+
content: {
|
|
459
|
+
flex: 1,
|
|
460
|
+
backgroundColor: 'transparent',
|
|
461
|
+
},
|
|
462
|
+
stepContentWrapper: {
|
|
463
|
+
flex: 1,
|
|
464
|
+
},
|
|
465
|
+
loadingContainer: {
|
|
466
|
+
flex: 1,
|
|
467
|
+
justifyContent: 'center',
|
|
468
|
+
alignItems: 'center',
|
|
469
|
+
padding: 20,
|
|
470
|
+
},
|
|
471
|
+
loadingCircle: {
|
|
472
|
+
width: 80,
|
|
473
|
+
height: 80,
|
|
474
|
+
borderRadius: 40,
|
|
475
|
+
justifyContent: 'center',
|
|
476
|
+
alignItems: 'center',
|
|
477
|
+
},
|
|
478
|
+
loadingText: {
|
|
479
|
+
marginTop: 16,
|
|
480
|
+
fontSize: 16,
|
|
481
|
+
color: '#666666',
|
|
482
|
+
fontWeight: '500',
|
|
483
|
+
},
|
|
484
|
+
snackbar: {
|
|
485
|
+
backgroundColor: '#FF4444',
|
|
486
|
+
marginBottom: 16,
|
|
487
|
+
borderRadius: 8,
|
|
488
|
+
},
|
|
489
|
+
});
|
|
490
|
+
exports.default = SellerOnboardingSheet;
|