@jimrising/easymerchantsdk-react-native 2.0.4 → 2.0.6
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/README.md +1003 -406
- package/android/.gradle/8.10/checksums/checksums.lock +0 -0
- package/android/.gradle/8.10/dependencies-accessors/gc.properties +0 -0
- package/android/.gradle/8.10/fileChanges/last-build.bin +0 -0
- package/android/.gradle/8.10/fileHashes/fileHashes.bin +0 -0
- package/android/.gradle/8.10/fileHashes/fileHashes.lock +0 -0
- package/android/.gradle/8.10/gc.properties +0 -0
- package/android/.gradle/8.9/checksums/checksums.lock +0 -0
- package/android/.gradle/8.9/dependencies-accessors/gc.properties +0 -0
- package/android/.gradle/8.9/fileChanges/last-build.bin +0 -0
- package/android/.gradle/8.9/fileHashes/fileHashes.lock +0 -0
- package/android/.gradle/8.9/gc.properties +0 -0
- package/android/.gradle/buildOutputCleanup/buildOutputCleanup.lock +0 -0
- package/android/.gradle/buildOutputCleanup/cache.properties +2 -0
- package/android/.gradle/nb-cache/trust/0B5D6BE682AD6AEE9815EC13516BF075752CAE5AD5BECDCC00315C37622C2FD3 +1 -0
- package/android/.gradle/vcs-1/gc.properties +0 -0
- package/android/build/.transforms/664c2535aec304a21f4de38c6fe405c3/results.bin +1 -0
- package/android/build/.transforms/664c2535aec304a21f4de38c6fe405c3/transformed/classes/classes_dex/classes.dex +0 -0
- package/android/build/.transforms/8b9a31b6d3889f12f1bd8cedf6c6f513/results.bin +1 -0
- package/android/build/.transforms/8b9a31b6d3889f12f1bd8cedf6c6f513/transformed/bundleLibRuntimeToDirDebug/bundleLibRuntimeToDirDebug_dex/com/reactlibrary/BuildConfig.dex +0 -0
- package/android/build/.transforms/8b9a31b6d3889f12f1bd8cedf6c6f513/transformed/bundleLibRuntimeToDirDebug/bundleLibRuntimeToDirDebug_dex/com/reactlibrary/RNEasymerchantsdkModule$1$1.dex +0 -0
- package/android/build/.transforms/8b9a31b6d3889f12f1bd8cedf6c6f513/transformed/bundleLibRuntimeToDirDebug/bundleLibRuntimeToDirDebug_dex/com/reactlibrary/RNEasymerchantsdkModule$1.dex +0 -0
- package/android/build/.transforms/8b9a31b6d3889f12f1bd8cedf6c6f513/transformed/bundleLibRuntimeToDirDebug/bundleLibRuntimeToDirDebug_dex/com/reactlibrary/RNEasymerchantsdkModule$2.dex +0 -0
- package/android/build/.transforms/8b9a31b6d3889f12f1bd8cedf6c6f513/transformed/bundleLibRuntimeToDirDebug/bundleLibRuntimeToDirDebug_dex/com/reactlibrary/RNEasymerchantsdkModule.dex +0 -0
- package/android/build/.transforms/8b9a31b6d3889f12f1bd8cedf6c6f513/transformed/bundleLibRuntimeToDirDebug/bundleLibRuntimeToDirDebug_dex/com/reactlibrary/RNEasymerchantsdkPackage.dex +0 -0
- package/android/build/.transforms/8b9a31b6d3889f12f1bd8cedf6c6f513/transformed/bundleLibRuntimeToDirDebug/desugar_graph.bin +0 -0
- package/android/build/intermediates/compile_library_classes_jar/debug/bundleLibCompileToJarDebug/classes.jar +0 -0
- package/android/build/intermediates/incremental/debug/packageDebugResources/compile-file-map.properties +1 -1
- package/android/build/intermediates/incremental/debug/packageDebugResources/merger.xml +1 -1
- package/android/build/intermediates/javac/debug/compileDebugJavaWithJavac/classes/com/reactlibrary/RNEasymerchantsdkModule$1$1.class +0 -0
- package/android/build/intermediates/javac/debug/compileDebugJavaWithJavac/classes/com/reactlibrary/RNEasymerchantsdkModule$1.class +0 -0
- package/android/build/intermediates/javac/debug/compileDebugJavaWithJavac/classes/com/reactlibrary/RNEasymerchantsdkModule$2.class +0 -0
- package/android/build/intermediates/javac/debug/compileDebugJavaWithJavac/classes/com/reactlibrary/RNEasymerchantsdkModule.class +0 -0
- package/android/build/intermediates/runtime_library_classes_dir/debug/bundleLibRuntimeToDirDebug/com/reactlibrary/RNEasymerchantsdkModule$1$1.class +0 -0
- package/android/build/intermediates/runtime_library_classes_dir/debug/bundleLibRuntimeToDirDebug/com/reactlibrary/RNEasymerchantsdkModule$1.class +0 -0
- package/android/build/intermediates/runtime_library_classes_dir/debug/bundleLibRuntimeToDirDebug/com/reactlibrary/RNEasymerchantsdkModule$2.class +0 -0
- package/android/build/intermediates/runtime_library_classes_dir/debug/bundleLibRuntimeToDirDebug/com/reactlibrary/RNEasymerchantsdkModule.class +0 -0
- package/android/build/intermediates/runtime_library_classes_jar/debug/bundleLibRuntimeToJarDebug/classes.jar +0 -0
- package/android/build/outputs/logs/manifest-merger-debug-report.txt +10 -10
- package/android/build/tmp/compileDebugJavaWithJavac/previous-compilation-data.bin +0 -0
- package/android/build.gradle +1 -1
- package/android/src/main/java/com/reactlibrary/RNEasymerchantsdkModule.java +9 -0
- package/ios/Classes/EasyMerchantSdk.m +2 -0
- package/ios/Classes/EasyMerchantSdk.swift +3 -1
- package/ios/Models/Request.swift +50 -3
- package/ios/Pods/ViewControllers/AdditionalInfoVC.swift +74 -6
- package/ios/Pods/ViewControllers/BillingInfoVC/BillingInfoVC.swift +92 -20
- package/ios/Pods/ViewControllers/OTPVerificationVC.swift +28 -2
- package/ios/Pods/ViewControllers/PaymentInformation/PaymentInfoVC.swift +73 -564
- package/ios/easymerchantsdk.podspec +1 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -7,7 +7,7 @@ To add the path of sdk in your project. Open your `package.json` file and inside
|
|
|
7
7
|
|
|
8
8
|
```json
|
|
9
9
|
"dependencies": {
|
|
10
|
-
"@jimrising/easymerchantsdk-react-native": "^2.0.
|
|
10
|
+
"@jimrising/easymerchantsdk-react-native": "^2.0.6"
|
|
11
11
|
},
|
|
12
12
|
```
|
|
13
13
|
|
|
@@ -129,10 +129,121 @@ import {
|
|
|
129
129
|
Switch,
|
|
130
130
|
TouchableOpacity,
|
|
131
131
|
NativeEventEmitter,
|
|
132
|
+
KeyboardAvoidingView,
|
|
133
|
+
Keyboard,
|
|
134
|
+
TouchableWithoutFeedback,
|
|
135
|
+
Modal,
|
|
132
136
|
} from 'react-native';
|
|
133
137
|
|
|
134
138
|
const { RNEasymerchantsdk, EasyMerchantSdk } = NativeModules;
|
|
135
139
|
|
|
140
|
+
// Dropdown Component
|
|
141
|
+
const Dropdown = ({ value, onValueChange, options, placeholder }) => {
|
|
142
|
+
const [isOpen, setIsOpen] = useState(false);
|
|
143
|
+
|
|
144
|
+
// Handler to close modal when tapping outside
|
|
145
|
+
const handleClose = () => setIsOpen(false);
|
|
146
|
+
|
|
147
|
+
return (
|
|
148
|
+
<View style={styles.dropdownContainer} pointerEvents="box-none">
|
|
149
|
+
<TouchableOpacity
|
|
150
|
+
style={styles.dropdownButton}
|
|
151
|
+
onPress={() => setIsOpen(!isOpen)}
|
|
152
|
+
>
|
|
153
|
+
<Text style={styles.dropdownButtonText}>
|
|
154
|
+
{value || placeholder}
|
|
155
|
+
</Text>
|
|
156
|
+
<Text style={styles.dropdownArrow}>
|
|
157
|
+
{isOpen ? '▲' : '▼'}
|
|
158
|
+
</Text>
|
|
159
|
+
</TouchableOpacity>
|
|
160
|
+
{Platform.OS === 'android' ? (
|
|
161
|
+
<Modal
|
|
162
|
+
visible={isOpen}
|
|
163
|
+
transparent={true}
|
|
164
|
+
animationType="fade"
|
|
165
|
+
onRequestClose={handleClose}
|
|
166
|
+
>
|
|
167
|
+
<TouchableWithoutFeedback onPress={handleClose}>
|
|
168
|
+
<View style={{ flex: 1, backgroundColor: 'rgba(0,0,0,0.2)' }}>
|
|
169
|
+
<View style={[styles.dropdownOptions, { position: 'absolute', top: '30%', left: 20, right: 20, maxHeight: 300, elevation: 20 }]}>
|
|
170
|
+
<ScrollView
|
|
171
|
+
style={[styles.dropdownScrollView, { maxHeight: 280 }]}
|
|
172
|
+
showsVerticalScrollIndicator={true}
|
|
173
|
+
persistentScrollbar={true}
|
|
174
|
+
nestedScrollEnabled={true}
|
|
175
|
+
keyboardShouldPersistTaps="handled"
|
|
176
|
+
>
|
|
177
|
+
{options.map((option, index) => (
|
|
178
|
+
<TouchableOpacity
|
|
179
|
+
key={index}
|
|
180
|
+
style={styles.dropdownOption}
|
|
181
|
+
onPress={() => {
|
|
182
|
+
onValueChange(option);
|
|
183
|
+
setIsOpen(false);
|
|
184
|
+
}}
|
|
185
|
+
>
|
|
186
|
+
<Text style={styles.dropdownOptionText}>{option}</Text>
|
|
187
|
+
</TouchableOpacity>
|
|
188
|
+
))}
|
|
189
|
+
</ScrollView>
|
|
190
|
+
</View>
|
|
191
|
+
</View>
|
|
192
|
+
</TouchableWithoutFeedback>
|
|
193
|
+
</Modal>
|
|
194
|
+
) : (
|
|
195
|
+
isOpen && (
|
|
196
|
+
<View style={styles.dropdownOptions}>
|
|
197
|
+
<ScrollView
|
|
198
|
+
style={styles.dropdownScrollView}
|
|
199
|
+
showsVerticalScrollIndicator={true}
|
|
200
|
+
persistentScrollbar={true}
|
|
201
|
+
nestedScrollEnabled={true}
|
|
202
|
+
keyboardShouldPersistTaps="handled"
|
|
203
|
+
>
|
|
204
|
+
{options.map((option, index) => (
|
|
205
|
+
<TouchableOpacity
|
|
206
|
+
key={index}
|
|
207
|
+
style={styles.dropdownOption}
|
|
208
|
+
onPress={() => {
|
|
209
|
+
onValueChange(option);
|
|
210
|
+
setIsOpen(false);
|
|
211
|
+
}}
|
|
212
|
+
>
|
|
213
|
+
<Text style={styles.dropdownOptionText}>{option}</Text>
|
|
214
|
+
</TouchableOpacity>
|
|
215
|
+
))}
|
|
216
|
+
</ScrollView>
|
|
217
|
+
</View>
|
|
218
|
+
)
|
|
219
|
+
)}
|
|
220
|
+
</View>
|
|
221
|
+
);
|
|
222
|
+
};
|
|
223
|
+
|
|
224
|
+
// Custom Filled Button Component
|
|
225
|
+
const FilledButton = ({ title, onPress, disabled = false, style = {}, textStyle = {} }) => {
|
|
226
|
+
return (
|
|
227
|
+
<TouchableOpacity
|
|
228
|
+
style={[
|
|
229
|
+
styles.filledButton,
|
|
230
|
+
disabled && styles.filledButtonDisabled,
|
|
231
|
+
style,
|
|
232
|
+
]}
|
|
233
|
+
onPress={onPress}
|
|
234
|
+
disabled={disabled}
|
|
235
|
+
>
|
|
236
|
+
<Text style={[
|
|
237
|
+
styles.filledButtonText,
|
|
238
|
+
disabled && styles.filledButtonTextDisabled,
|
|
239
|
+
textStyle,
|
|
240
|
+
]}>
|
|
241
|
+
{title}
|
|
242
|
+
</Text>
|
|
243
|
+
</TouchableOpacity>
|
|
244
|
+
);
|
|
245
|
+
};
|
|
246
|
+
|
|
136
247
|
const externalConfig = {
|
|
137
248
|
amount: '',
|
|
138
249
|
email: '',
|
|
@@ -141,8 +252,8 @@ const externalConfig = {
|
|
|
141
252
|
isSecureAuthentication: false,
|
|
142
253
|
isBillingVisible: false,
|
|
143
254
|
isAdditionalVisible: false,
|
|
144
|
-
emailEditable: true,
|
|
145
|
-
isEmail: true,
|
|
255
|
+
emailEditable: true,
|
|
256
|
+
isEmail: true,
|
|
146
257
|
billingInfo: {
|
|
147
258
|
visibility: { billing: false, additional: false },
|
|
148
259
|
billing: {
|
|
@@ -160,34 +271,30 @@ const externalConfig = {
|
|
|
160
271
|
postal_code: true,
|
|
161
272
|
},
|
|
162
273
|
additional: {
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
phone_number: '21408713290',
|
|
274
|
+
|
|
275
|
+
phone_number: '2140871329',
|
|
166
276
|
description: 'Test',
|
|
167
277
|
},
|
|
168
278
|
additionalRequired: {
|
|
169
|
-
|
|
170
|
-
email_address: true,
|
|
279
|
+
|
|
171
280
|
phone_number: true,
|
|
172
281
|
description: false,
|
|
173
282
|
},
|
|
174
283
|
},
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
fontFamily: '"Inter", sans-serif',
|
|
190
|
-
},
|
|
284
|
+
themeConfiguration: {
|
|
285
|
+
bodyBackgroundColor: '#1E3A8A',
|
|
286
|
+
containerBackgroundColor: '#1E40AF',
|
|
287
|
+
primaryFontColor: '#FFFFFF',
|
|
288
|
+
secondaryFontColor: '#BFDBFE',
|
|
289
|
+
primaryButtonBackgroundColor: '#3B82F6',
|
|
290
|
+
primaryButtonHoverColor: '#2563EB',
|
|
291
|
+
primaryButtonFontColor: '#FFFFFF',
|
|
292
|
+
secondaryButtonBackgroundColor: '#1D4ED8',
|
|
293
|
+
secondaryButtonHoverColor: '#1E40AF',
|
|
294
|
+
secondaryButtonFontColor: '#FFFFFF',
|
|
295
|
+
borderRadius: '8',
|
|
296
|
+
fontSize: '14',
|
|
297
|
+
},
|
|
191
298
|
grailPayParams: {
|
|
192
299
|
role: 'business',
|
|
193
300
|
timeout: 10,
|
|
@@ -198,9 +305,9 @@ const externalConfig = {
|
|
|
198
305
|
},
|
|
199
306
|
recurringData: {
|
|
200
307
|
allowCycles: 2,
|
|
201
|
-
intervals: ['daily','weekly', 'monthly'],
|
|
308
|
+
intervals: ['daily', 'weekly', 'monthly'],
|
|
202
309
|
recurringStartType: 'custom',
|
|
203
|
-
recurringStartDate: '
|
|
310
|
+
recurringStartDate: new Date().toLocaleDateString('en-US', { month: '2-digit', day: '2-digit', year: 'numeric' }),
|
|
204
311
|
},
|
|
205
312
|
androidConfig: {
|
|
206
313
|
currency: 'usd',
|
|
@@ -211,7 +318,7 @@ const externalConfig = {
|
|
|
211
318
|
showTotal: true,
|
|
212
319
|
showSubmitButton: true,
|
|
213
320
|
paymentMethod: ['card', 'ach'],
|
|
214
|
-
name: '
|
|
321
|
+
name: '',
|
|
215
322
|
fields: {
|
|
216
323
|
visibility: { billing: false, additional: false },
|
|
217
324
|
billing: [
|
|
@@ -222,28 +329,27 @@ const externalConfig = {
|
|
|
222
329
|
{ name: 'postal_code', required: true, value: '1432456' },
|
|
223
330
|
],
|
|
224
331
|
additional: [
|
|
225
|
-
|
|
226
|
-
{ name: 'email_address', required: true, value: 'usertest@gmail.com' },
|
|
332
|
+
|
|
227
333
|
{ name: 'phone_number', required: true, value: '8978967895' },
|
|
228
334
|
{ name: 'description', required: true, value: 'Hi This is description' },
|
|
229
335
|
],
|
|
230
336
|
},
|
|
231
337
|
appearanceSettings: {
|
|
232
338
|
theme: 'dark',
|
|
233
|
-
bodyBackgroundColor: '#
|
|
234
|
-
containerBackgroundColor: '#
|
|
339
|
+
bodyBackgroundColor: '#0F5132',
|
|
340
|
+
containerBackgroundColor: '#166534',
|
|
235
341
|
primaryFontColor: '#FFFFFF',
|
|
236
|
-
secondaryFontColor: '#
|
|
237
|
-
primaryButtonBackgroundColor: '#
|
|
238
|
-
primaryButtonHoverColor: '#
|
|
342
|
+
secondaryFontColor: '#D1FAE5',
|
|
343
|
+
primaryButtonBackgroundColor: '#059669',
|
|
344
|
+
primaryButtonHoverColor: '#047857',
|
|
239
345
|
primaryButtonFontColor: '#FFFFFF',
|
|
240
|
-
secondaryButtonBackgroundColor: '#
|
|
241
|
-
secondaryButtonHoverColor: '#
|
|
242
|
-
secondaryButtonFontColor: '#
|
|
346
|
+
secondaryButtonBackgroundColor: '#065F46',
|
|
347
|
+
secondaryButtonHoverColor: '#064E3B',
|
|
348
|
+
secondaryButtonFontColor: '#FFFFFF',
|
|
243
349
|
borderRadius: '8',
|
|
244
350
|
fontSize: '14',
|
|
245
|
-
fontWeight:
|
|
246
|
-
fontFamily: 'Inter, sans-serif',
|
|
351
|
+
fontWeight: 500,
|
|
352
|
+
fontFamily: '"Inter", sans-serif',
|
|
247
353
|
},
|
|
248
354
|
},
|
|
249
355
|
};
|
|
@@ -251,6 +357,7 @@ const externalConfig = {
|
|
|
251
357
|
const App = () => {
|
|
252
358
|
const [amount, setAmount] = useState(externalConfig.amount);
|
|
253
359
|
const [email, setEmail] = useState(externalConfig.email);
|
|
360
|
+
const [name, setName] = useState('');
|
|
254
361
|
const [environment, setEnvironment] = useState('sandbox');
|
|
255
362
|
const [isRecurring, setIsRecurring] = useState(externalConfig.isRecurring);
|
|
256
363
|
const [isAuthenticatedACH, setAuthenticatedACH] = useState(externalConfig.isAuthenticatedACH);
|
|
@@ -268,6 +375,13 @@ const App = () => {
|
|
|
268
375
|
const [referenceToken, setReferenceToken] = useState('');
|
|
269
376
|
const [loading, setLoading] = useState(false);
|
|
270
377
|
const [showSecretKey, setShowSecretKey] = useState(false);
|
|
378
|
+
const metadata = {
|
|
379
|
+
metaKey: 'metaValue',
|
|
380
|
+
metaKLey1: 'metaValue1',
|
|
381
|
+
metaKLey2: 'metaValue2',
|
|
382
|
+
metaKLey3: 'metaValue3',
|
|
383
|
+
metaKLey4: 'metaValue4',
|
|
384
|
+
};
|
|
271
385
|
|
|
272
386
|
const [apiKeys, setApiKeys] = useState({
|
|
273
387
|
sandbox: {
|
|
@@ -282,6 +396,21 @@ const [apiKeys, setApiKeys] = useState({
|
|
|
282
396
|
const [isEnvironmentLoading, setIsEnvironmentLoading] = useState(false);
|
|
283
397
|
const [showConfig, setShowConfig] = useState(true);
|
|
284
398
|
|
|
399
|
+
// Debug useEffect to track payment method changes
|
|
400
|
+
useEffect(() => {
|
|
401
|
+
console.log('Payment methods state changed:', androidConfig.paymentMethod);
|
|
402
|
+
}, [androidConfig.paymentMethod]);
|
|
403
|
+
|
|
404
|
+
// Debug useEffect to track theme configuration changes
|
|
405
|
+
useEffect(() => {
|
|
406
|
+
console.log('Theme configuration changed:', themeConfiguration);
|
|
407
|
+
}, [themeConfiguration]);
|
|
408
|
+
|
|
409
|
+
// Debug useEffect to track Android appearance settings changes
|
|
410
|
+
useEffect(() => {
|
|
411
|
+
console.log('Android appearance settings changed:', androidConfig.appearanceSettings);
|
|
412
|
+
}, [androidConfig.appearanceSettings]);
|
|
413
|
+
|
|
285
414
|
|
|
286
415
|
useEffect(() => {
|
|
287
416
|
const updateEnvironment = async () => {
|
|
@@ -450,12 +579,36 @@ const safeParseMaybeJSON = (value) => {
|
|
|
450
579
|
};
|
|
451
580
|
|
|
452
581
|
const togglePaymentMethod = (method) => {
|
|
453
|
-
|
|
454
|
-
|
|
455
|
-
|
|
456
|
-
|
|
457
|
-
|
|
458
|
-
|
|
582
|
+
console.log('Toggling payment method:', method);
|
|
583
|
+
setAndroidConfig(prev => {
|
|
584
|
+
const currentMethods = prev.paymentMethod;
|
|
585
|
+
console.log('Current payment methods before toggle:', currentMethods);
|
|
586
|
+
const isCurrentlySelected = currentMethods.includes(method);
|
|
587
|
+
console.log('Is currently selected:', isCurrentlySelected);
|
|
588
|
+
|
|
589
|
+
let newMethods;
|
|
590
|
+
if (isCurrentlySelected) {
|
|
591
|
+
// If deselecting and it's the only method, don't allow deselection
|
|
592
|
+
if (currentMethods.length === 1) {
|
|
593
|
+
console.log('Cannot deselect last payment method, keeping current state');
|
|
594
|
+
return prev; // Keep the current state
|
|
595
|
+
}
|
|
596
|
+
// Remove the method
|
|
597
|
+
newMethods = currentMethods.filter(m => m !== method);
|
|
598
|
+
console.log('Removing method, new methods:', newMethods);
|
|
599
|
+
} else {
|
|
600
|
+
// Add the method
|
|
601
|
+
newMethods = [...currentMethods, method];
|
|
602
|
+
console.log('Adding method, new methods:', newMethods);
|
|
603
|
+
}
|
|
604
|
+
|
|
605
|
+
const updatedConfig = {
|
|
606
|
+
...prev,
|
|
607
|
+
paymentMethod: newMethods,
|
|
608
|
+
};
|
|
609
|
+
console.log('Updated android config payment methods:', updatedConfig.paymentMethod);
|
|
610
|
+
return updatedConfig;
|
|
611
|
+
});
|
|
459
612
|
};
|
|
460
613
|
|
|
461
614
|
const toggleInterval = (interval) => {
|
|
@@ -471,58 +624,126 @@ const safeParseMaybeJSON = (value) => {
|
|
|
471
624
|
if (!amount || isNaN(parseFloat(amount)) || parseFloat(amount) <= 0) {
|
|
472
625
|
return Alert.alert('Error', 'Please enter a valid amount');
|
|
473
626
|
}
|
|
474
|
-
|
|
475
|
-
|
|
627
|
+
|
|
628
|
+
// Validate that at least one interval is selected when recurring payment is enabled
|
|
629
|
+
if (isRecurring && (!recurringData.intervals || recurringData.intervals.length === 0)) {
|
|
630
|
+
return Alert.alert('Error', 'Please select at least one interval for recurring payment');
|
|
476
631
|
}
|
|
477
632
|
|
|
478
633
|
setLoading(true);
|
|
479
|
-
|
|
480
|
-
|
|
481
|
-
|
|
482
|
-
|
|
634
|
+
|
|
635
|
+
// Add a timeout to ensure loading state is reset even if SDK blocks execution
|
|
636
|
+
const timeoutId = setTimeout(() => {
|
|
637
|
+
setLoading(false);
|
|
638
|
+
}, 3000); // 3 second timeout
|
|
639
|
+
|
|
640
|
+
try {
|
|
641
|
+
if (Platform.OS === 'android') {
|
|
642
|
+
await handleAndroidBilling();
|
|
643
|
+
} else {
|
|
644
|
+
await handleIosBilling();
|
|
645
|
+
}
|
|
646
|
+
} finally {
|
|
647
|
+
clearTimeout(timeoutId);
|
|
648
|
+
setLoading(false);
|
|
483
649
|
}
|
|
484
650
|
};
|
|
485
651
|
|
|
486
652
|
const handleAndroidBilling = async () => {
|
|
653
|
+
|
|
487
654
|
const { apiKey, secretKey } = apiKeys[environment];
|
|
488
|
-
|
|
489
|
-
|
|
490
|
-
|
|
491
|
-
|
|
492
|
-
|
|
493
|
-
|
|
494
|
-
|
|
495
|
-
|
|
496
|
-
|
|
497
|
-
|
|
498
|
-
|
|
499
|
-
|
|
500
|
-
|
|
501
|
-
|
|
502
|
-
|
|
503
|
-
|
|
504
|
-
|
|
505
|
-
|
|
506
|
-
|
|
507
|
-
|
|
508
|
-
|
|
509
|
-
|
|
510
|
-
|
|
511
|
-
|
|
512
|
-
|
|
513
|
-
|
|
514
|
-
|
|
515
|
-
|
|
516
|
-
|
|
517
|
-
|
|
518
|
-
|
|
519
|
-
|
|
520
|
-
|
|
521
|
-
|
|
522
|
-
|
|
523
|
-
|
|
524
|
-
|
|
525
|
-
|
|
655
|
+
|
|
656
|
+
console.log('Selected payment methods for Android:', androidConfig.paymentMethod);
|
|
657
|
+
console.log('Full androidConfig.paymentMethod:', JSON.stringify(androidConfig.paymentMethod));
|
|
658
|
+
|
|
659
|
+
// Create a fresh copy of payment methods to ensure no reference issues
|
|
660
|
+
const selectedPaymentMethods = [...androidConfig.paymentMethod];
|
|
661
|
+
console.log('Fresh copy of payment methods:', selectedPaymentMethods);
|
|
662
|
+
console.log('Payment method contains "ach":', selectedPaymentMethods.includes('ach'));
|
|
663
|
+
console.log('Payment method contains "card":', selectedPaymentMethods.includes('card'));
|
|
664
|
+
|
|
665
|
+
// Log ACH-specific configurations when ACH is selected
|
|
666
|
+
if (selectedPaymentMethods.includes('ach')) {
|
|
667
|
+
console.log('=== ACH CONFIGURATION DEBUG ===');
|
|
668
|
+
console.log('authenticatedACH setting:', isAuthenticatedACH);
|
|
669
|
+
console.log('secureAuthentication setting:', isSecureAuthentication);
|
|
670
|
+
console.log('saveAccount setting:', androidConfig.saveAccount);
|
|
671
|
+
}
|
|
672
|
+
|
|
673
|
+
// Try different payment method format for ACH-only scenario
|
|
674
|
+
let finalPaymentMethods = selectedPaymentMethods;
|
|
675
|
+
if (selectedPaymentMethods.length === 1 && selectedPaymentMethods.includes('ach')) {
|
|
676
|
+
// Try using a different format for ACH-only
|
|
677
|
+
finalPaymentMethods = ['ach'];
|
|
678
|
+
console.log('Using ACH-only format:', finalPaymentMethods);
|
|
679
|
+
}
|
|
680
|
+
|
|
681
|
+
const config = {
|
|
682
|
+
amount,
|
|
683
|
+
apiKey: apiKey,
|
|
684
|
+
secretKey: secretKey,
|
|
685
|
+
jsonConfig: {
|
|
686
|
+
environment,
|
|
687
|
+
amount,
|
|
688
|
+
tokenOnly: false,
|
|
689
|
+
currency: androidConfig.currency,
|
|
690
|
+
saveCard: androidConfig.saveCard,
|
|
691
|
+
saveAccount: androidConfig.saveAccount,
|
|
692
|
+
authenticatedACH: isAuthenticatedACH,
|
|
693
|
+
secureAuthentication: isSecureAuthentication,
|
|
694
|
+
|
|
695
|
+
showReceipt: androidConfig.showReceipt,
|
|
696
|
+
showDonate: androidConfig.showDonate,
|
|
697
|
+
showTotal: androidConfig.showTotal,
|
|
698
|
+
showSubmitButton: androidConfig.showSubmitButton,
|
|
699
|
+
paymentMethod: finalPaymentMethods,
|
|
700
|
+
// Try different configuration approaches for ACH-only
|
|
701
|
+
...(finalPaymentMethods.length === 1 && finalPaymentMethods.includes('ach') && {
|
|
702
|
+
paymentMethods: ['ach'],
|
|
703
|
+
allowedPaymentMethods: ['ach'],
|
|
704
|
+
disableCard: true,
|
|
705
|
+
}),
|
|
706
|
+
|
|
707
|
+
emailEditable,
|
|
708
|
+
email,
|
|
709
|
+
name: name,
|
|
710
|
+
fields: {
|
|
711
|
+
...androidConfig.fields,
|
|
712
|
+
visibility: {
|
|
713
|
+
billing: isBillingVisible,
|
|
714
|
+
additional: isAdditionalVisible,
|
|
715
|
+
},
|
|
716
|
+
},
|
|
717
|
+
|
|
718
|
+
metadata,
|
|
719
|
+
|
|
720
|
+
|
|
721
|
+
...(isRecurring && {
|
|
722
|
+
recurring: {
|
|
723
|
+
enableRecurring: true,
|
|
724
|
+
recurringData,
|
|
725
|
+
},
|
|
726
|
+
}),
|
|
727
|
+
grailPayParams,
|
|
728
|
+
appearanceSettings: androidConfig.appearanceSettings,
|
|
729
|
+
|
|
730
|
+
|
|
731
|
+
},
|
|
732
|
+
};
|
|
733
|
+
|
|
734
|
+
console.log('ENV API Keys =>', {
|
|
735
|
+
env: environment,
|
|
736
|
+
apiKeyFromEnv: apiKey,
|
|
737
|
+
secretKeyFromEnv: secretKey,
|
|
738
|
+
});
|
|
739
|
+
|
|
740
|
+
console.log('Config API Key =>', config.apiKey);
|
|
741
|
+
console.log('Config Secret Key =>', config.secretKey);
|
|
742
|
+
console.log('Full config being sent to Android SDK:', JSON.stringify(config, null, 2));
|
|
743
|
+
console.log('=== THEME CONFIGURATION DEBUG ===');
|
|
744
|
+
console.log('Android appearanceSettings:', JSON.stringify(androidConfig.appearanceSettings, null, 2));
|
|
745
|
+
|
|
746
|
+
|
|
526
747
|
|
|
527
748
|
try {
|
|
528
749
|
const response = await RNEasymerchantsdk.makePayment(config);
|
|
@@ -546,12 +767,33 @@ setResult(JSON.stringify(parsedResponse, null, 2));
|
|
|
546
767
|
};
|
|
547
768
|
|
|
548
769
|
const handleIosBilling = async () => {
|
|
770
|
+
|
|
771
|
+
console.log('Selected payment methods for iOS:', androidConfig.paymentMethod);
|
|
772
|
+
console.log('Full androidConfig.paymentMethod for iOS:', JSON.stringify(androidConfig.paymentMethod));
|
|
773
|
+
|
|
774
|
+
// Create a fresh copy of payment methods for iOS and convert to iOS format
|
|
775
|
+
const selectedPaymentMethodsIOS = [...androidConfig.paymentMethod];
|
|
776
|
+
console.log('Fresh copy of payment methods for iOS:', selectedPaymentMethodsIOS);
|
|
777
|
+
console.log('Payment method contains "ach" (iOS):', selectedPaymentMethodsIOS.includes('ach'));
|
|
778
|
+
console.log('Payment method contains "card" (iOS):', selectedPaymentMethodsIOS.includes('card'));
|
|
779
|
+
|
|
780
|
+
// Convert Android payment method names to iOS format
|
|
781
|
+
let finalPaymentMethodsIOS = selectedPaymentMethodsIOS.map(method => {
|
|
782
|
+
if (method === 'card') return 'Card';
|
|
783
|
+
if (method === 'ach') return 'Bank';
|
|
784
|
+
return method;
|
|
785
|
+
});
|
|
786
|
+
|
|
787
|
+
console.log('Converted payment methods for iOS:', finalPaymentMethodsIOS);
|
|
788
|
+
console.log('=== iOS THEME CONFIGURATION DEBUG ===');
|
|
789
|
+
console.log('iOS themeConfiguration:', JSON.stringify(themeConfiguration, null, 2));
|
|
790
|
+
|
|
549
791
|
try {
|
|
550
792
|
const result = await EasyMerchantSdk.billing(
|
|
551
793
|
amount,
|
|
552
794
|
androidConfig.currency || 'usd',
|
|
553
795
|
billingInfo,
|
|
554
|
-
|
|
796
|
+
finalPaymentMethodsIOS,
|
|
555
797
|
themeConfiguration,
|
|
556
798
|
false, // tokenOnly
|
|
557
799
|
androidConfig.saveCard,
|
|
@@ -570,7 +812,8 @@ setResult(JSON.stringify(parsedResponse, null, 2));
|
|
|
570
812
|
androidConfig.showSubmitButton,
|
|
571
813
|
isEmail,
|
|
572
814
|
email,
|
|
573
|
-
|
|
815
|
+
name,
|
|
816
|
+
metadata
|
|
574
817
|
);
|
|
575
818
|
|
|
576
819
|
const refToken = result?.additionalInfo?.threeDSecureStatus?.data?.ref_token;
|
|
@@ -603,10 +846,6 @@ setResult(JSON.stringify(parsedResponse, null, 2));
|
|
|
603
846
|
setResult('Payment Reference not supported on Android');
|
|
604
847
|
return;
|
|
605
848
|
}
|
|
606
|
-
if (!referenceToken) {
|
|
607
|
-
setResult('No reference token available');
|
|
608
|
-
return;
|
|
609
|
-
}
|
|
610
849
|
try {
|
|
611
850
|
const response = await EasyMerchantSdk.paymentReference(referenceToken);
|
|
612
851
|
setResult(`Payment Reference:\n${JSON.stringify(response, null, 2)}`);
|
|
@@ -618,8 +857,16 @@ setResult(JSON.stringify(parsedResponse, null, 2));
|
|
|
618
857
|
};
|
|
619
858
|
|
|
620
859
|
return (
|
|
621
|
-
<
|
|
622
|
-
|
|
860
|
+
<KeyboardAvoidingView
|
|
861
|
+
style={styles.container}
|
|
862
|
+
behavior={Platform.OS === 'ios' ? 'padding' : 'height'}
|
|
863
|
+
keyboardVerticalOffset={Platform.OS === 'ios' ? 0 : 20}
|
|
864
|
+
>
|
|
865
|
+
<ScrollView
|
|
866
|
+
contentContainerStyle={styles.scrollContent}
|
|
867
|
+
keyboardShouldPersistTaps="handled"
|
|
868
|
+
showsVerticalScrollIndicator={false}
|
|
869
|
+
>
|
|
623
870
|
<Text style={styles.title}>EasyMerchant SDK</Text>
|
|
624
871
|
|
|
625
872
|
|
|
@@ -629,6 +876,7 @@ setResult(JSON.stringify(parsedResponse, null, 2));
|
|
|
629
876
|
<TextInput
|
|
630
877
|
style={styles.input}
|
|
631
878
|
placeholder="Enter amount (e.g., 10.00)"
|
|
879
|
+
placeholderTextColor="#999999"
|
|
632
880
|
keyboardType="decimal-pad"
|
|
633
881
|
value={amount}
|
|
634
882
|
onChangeText={setAmount}
|
|
@@ -637,18 +885,39 @@ setResult(JSON.stringify(parsedResponse, null, 2));
|
|
|
637
885
|
<TextInput
|
|
638
886
|
style={styles.input}
|
|
639
887
|
placeholder="Enter email"
|
|
888
|
+
placeholderTextColor="#999999"
|
|
640
889
|
keyboardType="email-address"
|
|
641
890
|
value={email}
|
|
642
891
|
onChangeText={setEmail}
|
|
643
892
|
/>
|
|
893
|
+
<Text style={styles.label}>Name</Text>
|
|
894
|
+
<TextInput
|
|
895
|
+
style={styles.input}
|
|
896
|
+
placeholder="Enter name"
|
|
897
|
+
placeholderTextColor="#999999"
|
|
898
|
+
value={name}
|
|
899
|
+
onChangeText={setName}
|
|
900
|
+
/>
|
|
644
901
|
|
|
645
|
-
<View style={styles.buttonGroup}>
|
|
646
|
-
<
|
|
902
|
+
<View style={styles.buttonGroup}>
|
|
903
|
+
<FilledButton
|
|
904
|
+
title="Pay"
|
|
905
|
+
onPress={handlePayment}
|
|
906
|
+
disabled={loading}
|
|
907
|
+
/>
|
|
647
908
|
{Platform.OS === 'ios' && (
|
|
648
|
-
<
|
|
909
|
+
<FilledButton
|
|
910
|
+
title="Payment Ref"
|
|
911
|
+
onPress={handlePaymentReference}
|
|
912
|
+
disabled={loading}
|
|
913
|
+
/>
|
|
649
914
|
)}
|
|
650
915
|
</View>
|
|
651
916
|
|
|
917
|
+
|
|
918
|
+
|
|
919
|
+
|
|
920
|
+
|
|
652
921
|
<View style={styles.toggleContainer}>
|
|
653
922
|
<Text style={styles.label}>Show Configurations</Text>
|
|
654
923
|
<Switch
|
|
@@ -706,6 +975,7 @@ setResult(JSON.stringify(parsedResponse, null, 2));
|
|
|
706
975
|
}))
|
|
707
976
|
}
|
|
708
977
|
placeholder={`Enter ${environment === 'sandbox' ? 'Sandbox' : 'Staging'} API Key`}
|
|
978
|
+
placeholderTextColor="#999999"
|
|
709
979
|
/>
|
|
710
980
|
<Text style={styles.label}>Secret Key</Text>
|
|
711
981
|
<View style={styles.inputContainer}>
|
|
@@ -719,6 +989,7 @@ setResult(JSON.stringify(parsedResponse, null, 2));
|
|
|
719
989
|
}))
|
|
720
990
|
}
|
|
721
991
|
placeholder={`Enter ${environment === 'sandbox' ? 'Sandbox' : 'Staging'} Secret Key`}
|
|
992
|
+
placeholderTextColor="#999999"
|
|
722
993
|
secureTextEntry={!showSecretKey}
|
|
723
994
|
/>
|
|
724
995
|
<TouchableOpacity
|
|
@@ -779,22 +1050,45 @@ setResult(JSON.stringify(parsedResponse, null, 2));
|
|
|
779
1050
|
thumbColor={isAdditionalVisible ? '#fff' : '#f4f3f4'}
|
|
780
1051
|
/>
|
|
781
1052
|
</View>
|
|
782
|
-
|
|
1053
|
+
<Text style={styles.label}>Payment Methods (Shared)</Text>
|
|
1054
|
+
<Text style={styles.debugText}>
|
|
1055
|
+
Selected: {androidConfig.paymentMethod.join(', ') || 'None'}
|
|
1056
|
+
</Text>
|
|
783
1057
|
<View style={styles.buttonGroup}>
|
|
784
|
-
<
|
|
1058
|
+
<FilledButton
|
|
785
1059
|
title="Card"
|
|
786
1060
|
onPress={() => togglePaymentMethod('card')}
|
|
787
|
-
|
|
1061
|
+
disabled={loading}
|
|
1062
|
+
style={[
|
|
1063
|
+
{ flex: 1 },
|
|
1064
|
+
androidConfig.paymentMethod.includes('card')
|
|
1065
|
+
? { backgroundColor: '#2563EB' }
|
|
1066
|
+
: { backgroundColor: '#E5E7EB' }
|
|
1067
|
+
]}
|
|
1068
|
+
textStyle={androidConfig.paymentMethod.includes('card')
|
|
1069
|
+
? { color: '#fff' }
|
|
1070
|
+
: { color: '#374151' }
|
|
1071
|
+
}
|
|
788
1072
|
/>
|
|
789
|
-
<
|
|
1073
|
+
<FilledButton
|
|
790
1074
|
title="ACH"
|
|
791
1075
|
onPress={() => togglePaymentMethod('ach')}
|
|
792
|
-
|
|
1076
|
+
disabled={loading}
|
|
1077
|
+
style={[
|
|
1078
|
+
{ flex: 1 },
|
|
1079
|
+
androidConfig.paymentMethod.includes('ach')
|
|
1080
|
+
? { backgroundColor: '#2563EB' }
|
|
1081
|
+
: { backgroundColor: '#E5E7EB' }
|
|
1082
|
+
]}
|
|
1083
|
+
textStyle={androidConfig.paymentMethod.includes('ach')
|
|
1084
|
+
? { color: '#fff' }
|
|
1085
|
+
: { color: '#374151' }
|
|
1086
|
+
}
|
|
793
1087
|
/>
|
|
794
1088
|
</View>
|
|
795
1089
|
{Platform.OS === 'android' && (
|
|
796
1090
|
<View style={styles.toggleContainer}>
|
|
797
|
-
<Text style={styles.label}>Email Editable
|
|
1091
|
+
<Text style={styles.label}>Email Editable</Text>
|
|
798
1092
|
<Switch
|
|
799
1093
|
value={emailEditable}
|
|
800
1094
|
onValueChange={setEmailEditable}
|
|
@@ -805,7 +1099,7 @@ setResult(JSON.stringify(parsedResponse, null, 2));
|
|
|
805
1099
|
)}
|
|
806
1100
|
{Platform.OS === 'ios' && (
|
|
807
1101
|
<View style={styles.toggleContainer}>
|
|
808
|
-
<Text style={styles.label}>Allow Email
|
|
1102
|
+
<Text style={styles.label}>Allow Email Editable</Text>
|
|
809
1103
|
<Switch
|
|
810
1104
|
value={isEmail}
|
|
811
1105
|
onValueChange={setIsEmail}
|
|
@@ -816,36 +1110,9 @@ setResult(JSON.stringify(parsedResponse, null, 2));
|
|
|
816
1110
|
)}
|
|
817
1111
|
|
|
818
1112
|
<Text style={styles.sectionTitle}>Billing Info</Text>
|
|
819
|
-
|
|
820
|
-
|
|
821
|
-
|
|
822
|
-
value={billingInfo.billing.address}
|
|
823
|
-
onChangeText={value => updateBillingInfo('billing', 'address', value)}
|
|
824
|
-
/>
|
|
825
|
-
<Text style={styles.label}>Billing Country</Text>
|
|
826
|
-
<TextInput
|
|
827
|
-
style={styles.input}
|
|
828
|
-
value={billingInfo.billing.country}
|
|
829
|
-
onChangeText={value => updateBillingInfo('billing', 'country', value)}
|
|
830
|
-
/>
|
|
831
|
-
<Text style={styles.label}>Billing State</Text>
|
|
832
|
-
<TextInput
|
|
833
|
-
style={styles.input}
|
|
834
|
-
value={billingInfo.billing.state}
|
|
835
|
-
onChangeText={value => updateBillingInfo('billing', 'state', value)}
|
|
836
|
-
/>
|
|
837
|
-
<Text style={styles.label}>Billing City</Text>
|
|
838
|
-
<TextInput
|
|
839
|
-
style={styles.input}
|
|
840
|
-
value={billingInfo.billing.city}
|
|
841
|
-
onChangeText={value => updateBillingInfo('billing', 'city', value)}
|
|
842
|
-
/>
|
|
843
|
-
<Text style={styles.label}>Billing Postal Code</Text>
|
|
844
|
-
<TextInput
|
|
845
|
-
style={styles.input}
|
|
846
|
-
value={billingInfo.billing.postal_code}
|
|
847
|
-
onChangeText={value => updateBillingInfo('billing', 'postal_code', value)}
|
|
848
|
-
/>
|
|
1113
|
+
|
|
1114
|
+
{/* Billing Required Switches */}
|
|
1115
|
+
<Text style={styles.subsectionTitle}>Billing Required Fields</Text>
|
|
849
1116
|
<Text style={styles.label}>Billing Required: Address</Text>
|
|
850
1117
|
<Switch
|
|
851
1118
|
value={billingInfo.billingRequired.address}
|
|
@@ -863,7 +1130,7 @@ setResult(JSON.stringify(parsedResponse, null, 2));
|
|
|
863
1130
|
<Text style={styles.label}>Billing Required: State</Text>
|
|
864
1131
|
<Switch
|
|
865
1132
|
value={billingInfo.billingRequired.state}
|
|
866
|
-
|
|
1133
|
+
onValueChange={value => updateBillingInfo('billingRequired', 'state', value)}
|
|
867
1134
|
trackColor={{ false: '#ccc', true: '#2563EB' }}
|
|
868
1135
|
thumbColor={billingInfo.billingRequired.state ? '#fff' : '#f4f3f4'}
|
|
869
1136
|
/>
|
|
@@ -881,44 +1148,125 @@ setResult(JSON.stringify(parsedResponse, null, 2));
|
|
|
881
1148
|
trackColor={{ false: '#ccc', true: '#2563EB' }}
|
|
882
1149
|
thumbColor={billingInfo.billingRequired.postal_code ? '#fff' : '#f4f3f4'}
|
|
883
1150
|
/>
|
|
884
|
-
|
|
885
|
-
|
|
886
|
-
|
|
887
|
-
|
|
888
|
-
|
|
889
|
-
|
|
890
|
-
|
|
891
|
-
|
|
892
|
-
|
|
893
|
-
|
|
894
|
-
|
|
895
|
-
|
|
896
|
-
|
|
897
|
-
|
|
898
|
-
|
|
899
|
-
|
|
900
|
-
|
|
901
|
-
|
|
902
|
-
|
|
903
|
-
|
|
904
|
-
|
|
905
|
-
|
|
906
|
-
|
|
907
|
-
|
|
908
|
-
|
|
909
|
-
|
|
910
|
-
|
|
911
|
-
|
|
912
|
-
|
|
913
|
-
|
|
914
|
-
|
|
915
|
-
|
|
916
|
-
|
|
917
|
-
|
|
918
|
-
|
|
919
|
-
|
|
920
|
-
|
|
921
|
-
|
|
1151
|
+
|
|
1152
|
+
{/* Billing Fields Section */}
|
|
1153
|
+
<Text style={styles.subsectionTitle}>Billing Fields</Text>
|
|
1154
|
+
{billingInfo.billingRequired.address && (
|
|
1155
|
+
<>
|
|
1156
|
+
<Text style={styles.label}>Billing Address</Text>
|
|
1157
|
+
<TextInput
|
|
1158
|
+
style={styles.input}
|
|
1159
|
+
value={billingInfo.billing.address}
|
|
1160
|
+
onChangeText={value => updateBillingInfo('billing', 'address', value)}
|
|
1161
|
+
placeholder="Enter billing address"
|
|
1162
|
+
placeholderTextColor="#999999"
|
|
1163
|
+
/>
|
|
1164
|
+
</>
|
|
1165
|
+
)}
|
|
1166
|
+
{billingInfo.billingRequired.country && (
|
|
1167
|
+
<>
|
|
1168
|
+
<Text style={styles.label}>Billing Country</Text>
|
|
1169
|
+
<Dropdown
|
|
1170
|
+
value={billingInfo.billing.country}
|
|
1171
|
+
onValueChange={value => updateBillingInfo('billing', 'country', value)}
|
|
1172
|
+
options={[
|
|
1173
|
+
"Afghanistan", "Albania", "Algeria", "American Samoa", "Andorra",
|
|
1174
|
+
"Angola", "Anguilla", "Antarctica", "Antigua and Barbuda", "Argentina",
|
|
1175
|
+
"Armenia", "Aruba", "Australia", "Austria", "Azerbaijan",
|
|
1176
|
+
"Bahamas", "Bahrain", "Bangladesh", "Barbados", "Belarus",
|
|
1177
|
+
"Belgium", "Belize", "Benin", "Bermuda", "Bhutan",
|
|
1178
|
+
"Bolivia", "Bosnia and Herzegovina", "Botswana", "Bouvet Island", "Brazil",
|
|
1179
|
+
"British Indian Ocean Territory", "Brunei Darussalam", "Bulgaria", "Burkina Faso", "Burundi",
|
|
1180
|
+
"Cabo Verde", "Cambodia", "Cameroon", "Canada", "Cayman Islands",
|
|
1181
|
+
"Central African Republic", "Chad", "Chile", "China", "Christmas Island",
|
|
1182
|
+
"Cocos (Keeling) Islands", "Colombia", "Comoros", "Congo", "Congo, Democratic Republic of the",
|
|
1183
|
+
"Cook Islands", "Costa Rica", "Croatia", "Cuba", "Curaçao",
|
|
1184
|
+
"Cyprus", "Czech Republic", "Côte d'Ivoire", "Denmark", "Djibouti",
|
|
1185
|
+
"Dominica", "Dominican Republic", "Ecuador", "Egypt", "El Salvador",
|
|
1186
|
+
"Equatorial Guinea", "Eritrea", "Estonia", "Eswatini", "Ethiopia",
|
|
1187
|
+
"Falkland Islands (Malvinas)", "Faroe Islands", "Fiji", "Finland", "France",
|
|
1188
|
+
"French Guiana", "French Polynesia", "French Southern Territories", "Gabon", "Gambia",
|
|
1189
|
+
"Georgia", "Germany", "Ghana", "Gibraltar", "Greece",
|
|
1190
|
+
"Greenland", "Grenada", "Guadeloupe", "Guam", "Guatemala",
|
|
1191
|
+
"Guernsey", "Guinea", "Guinea-Bissau", "Guyana", "Haiti",
|
|
1192
|
+
"Heard Island and McDonald Islands", "Holy See", "Honduras", "Hong Kong", "Hungary",
|
|
1193
|
+
"Iceland", "India", "Indonesia", "Iran", "Iraq",
|
|
1194
|
+
"Ireland", "Isle of Man", "Israel", "Italy", "Jamaica",
|
|
1195
|
+
"Japan", "Jersey", "Jordan", "Kazakhstan", "Kenya",
|
|
1196
|
+
"Kiribati", "Korea (Democratic People's Republic of)", "Korea, Republic of", "Kuwait", "Kyrgyzstan",
|
|
1197
|
+
"Lao People's Democratic Republic", "Latvia", "Lebanon", "Lesotho", "Liberia",
|
|
1198
|
+
"Libya", "Liechtenstein", "Lithuania", "Luxembourg", "Macao",
|
|
1199
|
+
"Madagascar", "Malawi", "Malaysia", "Maldives", "Mali",
|
|
1200
|
+
"Malta", "Marshall Islands", "Martinique", "Mauritania", "Mauritius",
|
|
1201
|
+
"Mayotte", "Mexico", "Micronesia (Federated States of)", "Moldova", "Monaco",
|
|
1202
|
+
"Mongolia", "Montenegro", "Montserrat", "Morocco", "Mozambique",
|
|
1203
|
+
"Myanmar", "Namibia", "Nauru", "Nepal", "Netherlands",
|
|
1204
|
+
"New Caledonia", "New Zealand", "Nicaragua", "Niger", "Nigeria",
|
|
1205
|
+
"Niue", "Norfolk Island", "North Macedonia", "Northern Mariana Islands", "Norway",
|
|
1206
|
+
"Oman", "Pakistan", "Palau", "Palestine, State of", "Panama",
|
|
1207
|
+
"Papua New Guinea", "Paraguay", "Peru", "Philippines", "Pitcairn",
|
|
1208
|
+
"Poland", "Portugal", "Puerto Rico", "Qatar", "Romania",
|
|
1209
|
+
"Russian Federation", "Rwanda", "Réunion", "Saint Barthélemy", "Saint Helena, Ascension and Tristan da Cunha",
|
|
1210
|
+
"Saint Kitts and Nevis", "Saint Lucia", "Saint Martin (French part)", "Saint Pierre and Miquelon", "Saint Vincent and the Grenadines",
|
|
1211
|
+
"Samoa", "San Marino", "Sao Tome and Principe", "Saudi Arabia", "Senegal",
|
|
1212
|
+
"Serbia", "Seychelles", "Sierra Leone", "Singapore", "Sint Maarten (Dutch part)",
|
|
1213
|
+
"Slovakia", "Slovenia", "Solomon Islands", "Somalia", "South Africa",
|
|
1214
|
+
"South Georgia and the South Sandwich Islands", "South Sudan", "Spain", "Sri Lanka", "Sudan",
|
|
1215
|
+
"Suriname", "Svalbard and Jan Mayen", "Sweden", "Switzerland", "Syrian Arab Republic",
|
|
1216
|
+
"Taiwan, Province of China", "Tajikistan", "Tanzania", "Thailand", "Timor-Leste",
|
|
1217
|
+
"Togo", "Tokelau", "Tonga", "Trinidad and Tobago", "Tunisia",
|
|
1218
|
+
"Turkey", "Turkmenistan", "Tuvalu", "Uganda", "Ukraine",
|
|
1219
|
+
"United Arab Emirates", "United Kingdom", "United States", "Uruguay", "Uzbekistan",
|
|
1220
|
+
"Vanuatu", "Venezuela", "Viet Nam", "Western Sahara", "Yemen",
|
|
1221
|
+
"Zambia", "Zimbabwe", "Åland Islands"
|
|
1222
|
+
]}
|
|
1223
|
+
placeholder="Select country"
|
|
1224
|
+
/>
|
|
1225
|
+
</>
|
|
1226
|
+
)}
|
|
1227
|
+
{billingInfo.billingRequired.state && (
|
|
1228
|
+
<>
|
|
1229
|
+
<Text style={styles.label}>Billing State</Text>
|
|
1230
|
+
<TextInput
|
|
1231
|
+
style={styles.input}
|
|
1232
|
+
value={billingInfo.billing.state}
|
|
1233
|
+
onChangeText={value => updateBillingInfo('billing', 'state', value)}
|
|
1234
|
+
placeholder="Enter state"
|
|
1235
|
+
placeholderTextColor="#999999"
|
|
1236
|
+
/>
|
|
1237
|
+
</>
|
|
1238
|
+
)}
|
|
1239
|
+
{billingInfo.billingRequired.city && (
|
|
1240
|
+
<>
|
|
1241
|
+
<Text style={styles.label}>Billing City</Text>
|
|
1242
|
+
<TextInput
|
|
1243
|
+
style={styles.input}
|
|
1244
|
+
value={billingInfo.billing.city}
|
|
1245
|
+
onChangeText={value => updateBillingInfo('billing', 'city', value)}
|
|
1246
|
+
placeholder="Enter city"
|
|
1247
|
+
placeholderTextColor="#999999"
|
|
1248
|
+
/>
|
|
1249
|
+
</>
|
|
1250
|
+
)}
|
|
1251
|
+
{billingInfo.billingRequired.postal_code && (
|
|
1252
|
+
<>
|
|
1253
|
+
<Text style={styles.label}>Billing Postal Code</Text>
|
|
1254
|
+
<TextInput
|
|
1255
|
+
style={styles.input}
|
|
1256
|
+
value={billingInfo.billing.postal_code}
|
|
1257
|
+
onChangeText={value => updateBillingInfo('billing', 'postal_code', value)}
|
|
1258
|
+
placeholder="Enter postal code"
|
|
1259
|
+
placeholderTextColor="#999999"
|
|
1260
|
+
/>
|
|
1261
|
+
</>
|
|
1262
|
+
)}
|
|
1263
|
+
|
|
1264
|
+
<Text style={styles.sectionTitle}>Additional Info</Text>
|
|
1265
|
+
|
|
1266
|
+
{/* Additional Required Switches */}
|
|
1267
|
+
<Text style={styles.subsectionTitle}>Additional Required Fields</Text>
|
|
1268
|
+
|
|
1269
|
+
|
|
922
1270
|
<Text style={styles.label}>Additional Required: Phone Number</Text>
|
|
923
1271
|
<Switch
|
|
924
1272
|
value={billingInfo.additionalRequired.phone_number}
|
|
@@ -934,190 +1282,194 @@ setResult(JSON.stringify(parsedResponse, null, 2));
|
|
|
934
1282
|
thumbColor={billingInfo.additionalRequired.description ? '#fff' : '#f4f3f4'}
|
|
935
1283
|
/>
|
|
936
1284
|
|
|
937
|
-
{/*
|
|
938
|
-
{
|
|
1285
|
+
{/* Additional Fields Section */}
|
|
1286
|
+
<Text style={styles.subsectionTitle}>Additional Fields</Text>
|
|
1287
|
+
|
|
1288
|
+
{billingInfo.additionalRequired.phone_number && (
|
|
939
1289
|
<>
|
|
940
|
-
<Text style={styles.
|
|
941
|
-
<
|
|
942
|
-
|
|
943
|
-
|
|
944
|
-
|
|
945
|
-
|
|
946
|
-
|
|
947
|
-
|
|
948
|
-
|
|
949
|
-
|
|
950
|
-
|
|
951
|
-
|
|
952
|
-
|
|
953
|
-
|
|
954
|
-
|
|
955
|
-
|
|
956
|
-
|
|
957
|
-
|
|
958
|
-
|
|
959
|
-
|
|
960
|
-
|
|
961
|
-
|
|
962
|
-
|
|
963
|
-
|
|
964
|
-
|
|
965
|
-
|
|
966
|
-
|
|
967
|
-
|
|
968
|
-
|
|
969
|
-
|
|
970
|
-
|
|
971
|
-
|
|
972
|
-
|
|
973
|
-
|
|
974
|
-
|
|
975
|
-
|
|
976
|
-
|
|
977
|
-
|
|
978
|
-
|
|
979
|
-
|
|
980
|
-
|
|
981
|
-
|
|
982
|
-
<Text style={styles.label}>Show Submit Button</Text>
|
|
983
|
-
<Switch
|
|
984
|
-
value={androidConfig.showSubmitButton}
|
|
985
|
-
onValueChange={value => updateAndroidConfig('showSubmitButton', value)}
|
|
986
|
-
trackColor={{ false: '#ccc', true: '#2563EB' }}
|
|
987
|
-
thumbColor={androidConfig.showSubmitButton ? '#fff' : '#f4f3f4'}
|
|
988
|
-
/>
|
|
989
|
-
<Text style={styles.label}>Name</Text>
|
|
1290
|
+
<Text style={styles.label}>Additional: Phone Number</Text>
|
|
1291
|
+
<View style={styles.phoneRow}>
|
|
1292
|
+
<TextInput
|
|
1293
|
+
style={styles.countryCodeInput}
|
|
1294
|
+
value={billingInfo.additional.country_code || '+1'}
|
|
1295
|
+
onChangeText={value => {
|
|
1296
|
+
// Only allow a '+' at the start, followed by up to 4 digits
|
|
1297
|
+
let filtered = value.replace(/[^+0-9]/g, '');
|
|
1298
|
+
if (!filtered.startsWith('+')) filtered = '+' + filtered.replace(/\+/g, '');
|
|
1299
|
+
filtered = filtered.slice(0, 5);
|
|
1300
|
+
// Update country code and combined phone number
|
|
1301
|
+
const phone = billingInfo.additional.phone_number || '';
|
|
1302
|
+
const phoneOnly = phone.slice((billingInfo.additional.country_code || '+1').replace('+', '').length);
|
|
1303
|
+
const combined = filtered.replace('+', '') + phoneOnly;
|
|
1304
|
+
updateBillingInfo('additional', 'country_code', filtered);
|
|
1305
|
+
updateBillingInfo('additional', 'phone_number', combined);
|
|
1306
|
+
}}
|
|
1307
|
+
placeholder="+1"
|
|
1308
|
+
placeholderTextColor="#999999"
|
|
1309
|
+
keyboardType="phone-pad"
|
|
1310
|
+
maxLength={5}
|
|
1311
|
+
/>
|
|
1312
|
+
<TextInput
|
|
1313
|
+
style={[styles.input, { flex: 1, marginBottom: 0 }]}
|
|
1314
|
+
value={(billingInfo.additional.phone_number || '').slice((billingInfo.additional.country_code || '+1').replace('+', '').length)}
|
|
1315
|
+
onChangeText={value => {
|
|
1316
|
+
// Only allow digits and limit to 10 characters
|
|
1317
|
+
const numericValue = value.replace(/[^0-9]/g, '').slice(0, 10);
|
|
1318
|
+
const code = (billingInfo.additional.country_code || '+1').replace('+', '');
|
|
1319
|
+
updateBillingInfo('additional', 'phone_number', code + numericValue);
|
|
1320
|
+
}}
|
|
1321
|
+
placeholder="Enter phone number"
|
|
1322
|
+
placeholderTextColor="#999999"
|
|
1323
|
+
keyboardType="phone-pad"
|
|
1324
|
+
maxLength={10}
|
|
1325
|
+
/>
|
|
1326
|
+
</View>
|
|
1327
|
+
</>
|
|
1328
|
+
)}
|
|
1329
|
+
{billingInfo.additionalRequired.description && (
|
|
1330
|
+
<>
|
|
1331
|
+
<Text style={styles.label}>Additional: Description</Text>
|
|
990
1332
|
<TextInput
|
|
991
1333
|
style={styles.input}
|
|
992
|
-
value={
|
|
993
|
-
onChangeText={value =>
|
|
1334
|
+
value={billingInfo.additional.description}
|
|
1335
|
+
onChangeText={value => updateBillingInfo('additional', 'description', value)}
|
|
1336
|
+
placeholder="Enter description"
|
|
1337
|
+
placeholderTextColor="#999999"
|
|
994
1338
|
/>
|
|
995
|
-
|
|
996
|
-
|
|
997
|
-
|
|
998
|
-
|
|
999
|
-
|
|
1000
|
-
|
|
1001
|
-
value={field.value}
|
|
1002
|
-
onChangeText={value => updateAndroidConfigFields('billing', index, 'value', value)}
|
|
1003
|
-
/>
|
|
1004
|
-
<Text style={styles.label}>{`Billing ${field.name} Required`}</Text>
|
|
1005
|
-
<Switch
|
|
1006
|
-
value={field.required}
|
|
1007
|
-
onValueChange={value => updateAndroidConfigFields('billing', index, 'required', value)}
|
|
1008
|
-
trackColor={{ false: '#ccc', true: '#2563EB' }}
|
|
1009
|
-
thumbColor={field.required ? '#fff' : '#f4f3f4'}
|
|
1010
|
-
/>
|
|
1011
|
-
</View>
|
|
1012
|
-
))}
|
|
1013
|
-
{androidConfig.fields.additional.map((field, index) => (
|
|
1014
|
-
<View key={`additional-${index}`}>
|
|
1015
|
-
<Text style={styles.label}>{`Additional ${field.name}`}</Text>
|
|
1016
|
-
<TextInput
|
|
1017
|
-
style={styles.input}
|
|
1018
|
-
value={field.value}
|
|
1019
|
-
onChangeText={value => updateAndroidConfigFields('additional', index, 'value', value)}
|
|
1020
|
-
/>
|
|
1021
|
-
<Text style={styles.label}>{`Additional ${field.name} Required`}</Text>
|
|
1022
|
-
<Switch
|
|
1023
|
-
value={field.required}
|
|
1024
|
-
onValueChange={value => updateAndroidConfigFields('additional', index, 'required', value)}
|
|
1025
|
-
trackColor={{ false: '#ccc', true: '#2563EB' }}
|
|
1026
|
-
thumbColor={field.required ? '#fff' : '#f4f3f4'}
|
|
1027
|
-
/>
|
|
1028
|
-
</View>
|
|
1029
|
-
))}
|
|
1339
|
+
</>
|
|
1340
|
+
)}
|
|
1341
|
+
|
|
1342
|
+
{/* Android Appearance Settings */}
|
|
1343
|
+
{Platform.OS === 'android' && (
|
|
1344
|
+
<>
|
|
1030
1345
|
<Text style={styles.sectionTitle}>Android Appearance Settings</Text>
|
|
1031
|
-
<Text style={styles.label}>Theme</Text>
|
|
1032
|
-
<TextInput
|
|
1033
|
-
style={styles.input}
|
|
1034
|
-
value={androidConfig.appearanceSettings.theme}
|
|
1035
|
-
onChangeText={value => updateAndroidConfigAppearanceSettings('theme', value)}
|
|
1036
|
-
/>
|
|
1037
1346
|
<Text style={styles.label}>Body Background Color</Text>
|
|
1038
|
-
<
|
|
1039
|
-
|
|
1040
|
-
|
|
1041
|
-
|
|
1042
|
-
|
|
1347
|
+
<View style={styles.colorInputContainer}>
|
|
1348
|
+
<TextInput
|
|
1349
|
+
style={[styles.input, { flex: 1 }]}
|
|
1350
|
+
value={androidConfig.appearanceSettings.bodyBackgroundColor}
|
|
1351
|
+
onChangeText={value => updateAndroidConfigAppearanceSettings('bodyBackgroundColor', value)}
|
|
1352
|
+
placeholder="Enter body background color"
|
|
1353
|
+
placeholderTextColor="#999999"
|
|
1354
|
+
/>
|
|
1355
|
+
<View style={[styles.colorPreview, { backgroundColor: androidConfig.appearanceSettings.bodyBackgroundColor }]} />
|
|
1356
|
+
</View>
|
|
1043
1357
|
<Text style={styles.label}>Container Background Color</Text>
|
|
1044
|
-
<
|
|
1045
|
-
|
|
1046
|
-
|
|
1047
|
-
|
|
1048
|
-
|
|
1358
|
+
<View style={styles.colorInputContainer}>
|
|
1359
|
+
<TextInput
|
|
1360
|
+
style={[styles.input, { flex: 1 }]}
|
|
1361
|
+
value={androidConfig.appearanceSettings.containerBackgroundColor}
|
|
1362
|
+
onChangeText={value => updateAndroidConfigAppearanceSettings('containerBackgroundColor', value)}
|
|
1363
|
+
placeholder="Enter container background color"
|
|
1364
|
+
placeholderTextColor="#999999"
|
|
1365
|
+
/>
|
|
1366
|
+
<View style={[styles.colorPreview, { backgroundColor: androidConfig.appearanceSettings.containerBackgroundColor }]} />
|
|
1367
|
+
</View>
|
|
1049
1368
|
<Text style={styles.label}>Primary Font Color</Text>
|
|
1050
|
-
<
|
|
1051
|
-
|
|
1052
|
-
|
|
1053
|
-
|
|
1054
|
-
|
|
1369
|
+
<View style={styles.colorInputContainer}>
|
|
1370
|
+
<TextInput
|
|
1371
|
+
style={[styles.input, { flex: 1 }]}
|
|
1372
|
+
value={androidConfig.appearanceSettings.primaryFontColor}
|
|
1373
|
+
onChangeText={value => updateAndroidConfigAppearanceSettings('primaryFontColor', value)}
|
|
1374
|
+
placeholder="Enter primary font color"
|
|
1375
|
+
placeholderTextColor="#999999"
|
|
1376
|
+
/>
|
|
1377
|
+
<View style={[styles.colorPreview, { backgroundColor: androidConfig.appearanceSettings.primaryFontColor }]} />
|
|
1378
|
+
</View>
|
|
1055
1379
|
<Text style={styles.label}>Secondary Font Color</Text>
|
|
1056
|
-
<
|
|
1057
|
-
|
|
1058
|
-
|
|
1059
|
-
|
|
1060
|
-
|
|
1380
|
+
<View style={styles.colorInputContainer}>
|
|
1381
|
+
<TextInput
|
|
1382
|
+
style={[styles.input, { flex: 1 }]}
|
|
1383
|
+
value={androidConfig.appearanceSettings.secondaryFontColor}
|
|
1384
|
+
onChangeText={value => updateAndroidConfigAppearanceSettings('secondaryFontColor', value)}
|
|
1385
|
+
placeholder="Enter secondary font color"
|
|
1386
|
+
placeholderTextColor="#999999"
|
|
1387
|
+
/>
|
|
1388
|
+
<View style={[styles.colorPreview, { backgroundColor: androidConfig.appearanceSettings.secondaryFontColor }]} />
|
|
1389
|
+
</View>
|
|
1061
1390
|
<Text style={styles.label}>Primary Button Background Color</Text>
|
|
1062
|
-
<
|
|
1063
|
-
|
|
1064
|
-
|
|
1065
|
-
|
|
1066
|
-
|
|
1391
|
+
<View style={styles.colorInputContainer}>
|
|
1392
|
+
<TextInput
|
|
1393
|
+
style={[styles.input, { flex: 1 }]}
|
|
1394
|
+
value={androidConfig.appearanceSettings.primaryButtonBackgroundColor}
|
|
1395
|
+
onChangeText={value => updateAndroidConfigAppearanceSettings('primaryButtonBackgroundColor', value)}
|
|
1396
|
+
placeholder="Enter primary button background color"
|
|
1397
|
+
placeholderTextColor="#999999"
|
|
1398
|
+
/>
|
|
1399
|
+
<View style={[styles.colorPreview, { backgroundColor: androidConfig.appearanceSettings.primaryButtonBackgroundColor }]} />
|
|
1400
|
+
</View>
|
|
1067
1401
|
<Text style={styles.label}>Primary Button Hover Color</Text>
|
|
1068
|
-
<
|
|
1069
|
-
|
|
1070
|
-
|
|
1071
|
-
|
|
1072
|
-
|
|
1402
|
+
<View style={styles.colorInputContainer}>
|
|
1403
|
+
<TextInput
|
|
1404
|
+
style={[styles.input, { flex: 1 }]}
|
|
1405
|
+
value={androidConfig.appearanceSettings.primaryButtonHoverColor}
|
|
1406
|
+
onChangeText={value => updateAndroidConfigAppearanceSettings('primaryButtonHoverColor', value)}
|
|
1407
|
+
placeholder="Enter primary button hover color"
|
|
1408
|
+
placeholderTextColor="#999999"
|
|
1409
|
+
/>
|
|
1410
|
+
<View style={[styles.colorPreview, { backgroundColor: androidConfig.appearanceSettings.primaryButtonHoverColor }]} />
|
|
1411
|
+
</View>
|
|
1073
1412
|
<Text style={styles.label}>Primary Button Font Color</Text>
|
|
1074
|
-
<
|
|
1075
|
-
|
|
1076
|
-
|
|
1077
|
-
|
|
1078
|
-
|
|
1413
|
+
<View style={styles.colorInputContainer}>
|
|
1414
|
+
<TextInput
|
|
1415
|
+
style={[styles.input, { flex: 1 }]}
|
|
1416
|
+
value={androidConfig.appearanceSettings.primaryButtonFontColor}
|
|
1417
|
+
onChangeText={value => updateAndroidConfigAppearanceSettings('primaryButtonFontColor', value)}
|
|
1418
|
+
placeholder="Enter primary button font color"
|
|
1419
|
+
placeholderTextColor="#999999"
|
|
1420
|
+
/>
|
|
1421
|
+
<View style={[styles.colorPreview, { backgroundColor: androidConfig.appearanceSettings.primaryButtonFontColor }]} />
|
|
1422
|
+
</View>
|
|
1079
1423
|
<Text style={styles.label}>Secondary Button Background Color</Text>
|
|
1080
|
-
<
|
|
1081
|
-
|
|
1082
|
-
|
|
1083
|
-
|
|
1084
|
-
|
|
1424
|
+
<View style={styles.colorInputContainer}>
|
|
1425
|
+
<TextInput
|
|
1426
|
+
style={[styles.input, { flex: 1 }]}
|
|
1427
|
+
value={androidConfig.appearanceSettings.secondaryButtonBackgroundColor}
|
|
1428
|
+
onChangeText={value => updateAndroidConfigAppearanceSettings('secondaryButtonBackgroundColor', value)}
|
|
1429
|
+
placeholder="Enter secondary button background color"
|
|
1430
|
+
placeholderTextColor="#999999"
|
|
1431
|
+
/>
|
|
1432
|
+
<View style={[styles.colorPreview, { backgroundColor: androidConfig.appearanceSettings.secondaryButtonBackgroundColor }]} />
|
|
1433
|
+
</View>
|
|
1085
1434
|
<Text style={styles.label}>Secondary Button Hover Color</Text>
|
|
1086
|
-
<
|
|
1087
|
-
|
|
1088
|
-
|
|
1089
|
-
|
|
1090
|
-
|
|
1435
|
+
<View style={styles.colorInputContainer}>
|
|
1436
|
+
<TextInput
|
|
1437
|
+
style={[styles.input, { flex: 1 }]}
|
|
1438
|
+
value={androidConfig.appearanceSettings.secondaryButtonHoverColor}
|
|
1439
|
+
onChangeText={value => updateAndroidConfigAppearanceSettings('secondaryButtonHoverColor', value)}
|
|
1440
|
+
placeholder="Enter secondary button hover color"
|
|
1441
|
+
placeholderTextColor="#999999"
|
|
1442
|
+
/>
|
|
1443
|
+
<View style={[styles.colorPreview, { backgroundColor: androidConfig.appearanceSettings.secondaryButtonHoverColor }]} />
|
|
1444
|
+
</View>
|
|
1091
1445
|
<Text style={styles.label}>Secondary Button Font Color</Text>
|
|
1092
|
-
<
|
|
1093
|
-
|
|
1094
|
-
|
|
1095
|
-
|
|
1096
|
-
|
|
1446
|
+
<View style={styles.colorInputContainer}>
|
|
1447
|
+
<TextInput
|
|
1448
|
+
style={[styles.input, { flex: 1 }]}
|
|
1449
|
+
value={androidConfig.appearanceSettings.secondaryButtonFontColor}
|
|
1450
|
+
onChangeText={value => updateAndroidConfigAppearanceSettings('secondaryButtonFontColor', value)}
|
|
1451
|
+
placeholder="Enter secondary button font color"
|
|
1452
|
+
placeholderTextColor="#999999"
|
|
1453
|
+
/>
|
|
1454
|
+
<View style={[styles.colorPreview, { backgroundColor: androidConfig.appearanceSettings.secondaryButtonFontColor }]} />
|
|
1455
|
+
</View>
|
|
1097
1456
|
<Text style={styles.label}>Border Radius</Text>
|
|
1098
1457
|
<TextInput
|
|
1099
1458
|
style={styles.input}
|
|
1100
1459
|
value={androidConfig.appearanceSettings.borderRadius}
|
|
1101
1460
|
onChangeText={value => updateAndroidConfigAppearanceSettings('borderRadius', value)}
|
|
1461
|
+
placeholder="Enter border radius"
|
|
1462
|
+
placeholderTextColor="#999999"
|
|
1102
1463
|
/>
|
|
1103
1464
|
<Text style={styles.label}>Font Size</Text>
|
|
1104
1465
|
<TextInput
|
|
1105
1466
|
style={styles.input}
|
|
1106
1467
|
value={androidConfig.appearanceSettings.fontSize}
|
|
1107
1468
|
onChangeText={value => updateAndroidConfigAppearanceSettings('fontSize', value)}
|
|
1469
|
+
placeholder="Enter font size"
|
|
1470
|
+
placeholderTextColor="#999999"
|
|
1108
1471
|
/>
|
|
1109
|
-
|
|
1110
|
-
<TextInput
|
|
1111
|
-
style={styles.input}
|
|
1112
|
-
value={String(androidConfig.appearanceSettings.fontWeight)}
|
|
1113
|
-
onChangeText={value => updateAndroidConfigAppearanceSettings('fontWeight', parseInt(value) || '500')}
|
|
1114
|
-
/>
|
|
1115
|
-
<Text style={styles.label}>Font Family</Text>
|
|
1116
|
-
<TextInput
|
|
1117
|
-
style={styles.input}
|
|
1118
|
-
value={androidConfig.appearanceSettings.fontFamily}
|
|
1119
|
-
onChangeText={value => updateAndroidConfigAppearanceSettings('fontFamily', value)}
|
|
1120
|
-
/>
|
|
1472
|
+
|
|
1121
1473
|
</>
|
|
1122
1474
|
)}
|
|
1123
1475
|
|
|
@@ -1126,89 +1478,132 @@ setResult(JSON.stringify(parsedResponse, null, 2));
|
|
|
1126
1478
|
<>
|
|
1127
1479
|
<Text style={styles.sectionTitle}>Theme Configuration (iOS)</Text>
|
|
1128
1480
|
<Text style={styles.label}>Body Background Color</Text>
|
|
1129
|
-
<
|
|
1130
|
-
|
|
1131
|
-
|
|
1132
|
-
|
|
1133
|
-
|
|
1481
|
+
<View style={styles.colorInputContainer}>
|
|
1482
|
+
<TextInput
|
|
1483
|
+
style={[styles.input, { flex: 1 }]}
|
|
1484
|
+
value={themeConfiguration.bodyBackgroundColor}
|
|
1485
|
+
onChangeText={value => updateThemeConfiguration('bodyBackgroundColor', value)}
|
|
1486
|
+
placeholder="Enter body background color"
|
|
1487
|
+
placeholderTextColor="#999999"
|
|
1488
|
+
/>
|
|
1489
|
+
<View style={[styles.colorPreview, { backgroundColor: themeConfiguration.bodyBackgroundColor }]} />
|
|
1490
|
+
</View>
|
|
1134
1491
|
<Text style={styles.label}>Container Background Color</Text>
|
|
1135
|
-
<
|
|
1136
|
-
|
|
1137
|
-
|
|
1138
|
-
|
|
1139
|
-
|
|
1492
|
+
<View style={styles.colorInputContainer}>
|
|
1493
|
+
<TextInput
|
|
1494
|
+
style={[styles.input, { flex: 1 }]}
|
|
1495
|
+
value={themeConfiguration.containerBackgroundColor}
|
|
1496
|
+
onChangeText={value => updateThemeConfiguration('containerBackgroundColor', value)}
|
|
1497
|
+
placeholder="Enter container background color"
|
|
1498
|
+
placeholderTextColor="#999999"
|
|
1499
|
+
/>
|
|
1500
|
+
<View style={[styles.colorPreview, { backgroundColor: themeConfiguration.containerBackgroundColor }]} />
|
|
1501
|
+
</View>
|
|
1140
1502
|
<Text style={styles.label}>Primary Font Color</Text>
|
|
1141
|
-
<
|
|
1142
|
-
|
|
1143
|
-
|
|
1144
|
-
|
|
1145
|
-
|
|
1503
|
+
<View style={styles.colorInputContainer}>
|
|
1504
|
+
<TextInput
|
|
1505
|
+
style={[styles.input, { flex: 1 }]}
|
|
1506
|
+
value={themeConfiguration.primaryFontColor}
|
|
1507
|
+
onChangeText={value => updateThemeConfiguration('primaryFontColor', value)}
|
|
1508
|
+
placeholder="Enter primary font color"
|
|
1509
|
+
placeholderTextColor="#999999"
|
|
1510
|
+
/>
|
|
1511
|
+
<View style={[styles.colorPreview, { backgroundColor: themeConfiguration.primaryFontColor }]} />
|
|
1512
|
+
</View>
|
|
1146
1513
|
<Text style={styles.label}>Secondary Font Color</Text>
|
|
1147
|
-
<
|
|
1148
|
-
|
|
1149
|
-
|
|
1150
|
-
|
|
1151
|
-
|
|
1514
|
+
<View style={styles.colorInputContainer}>
|
|
1515
|
+
<TextInput
|
|
1516
|
+
style={[styles.input, { flex: 1 }]}
|
|
1517
|
+
value={themeConfiguration.secondaryFontColor}
|
|
1518
|
+
onChangeText={value => updateThemeConfiguration('secondaryFontColor', value)}
|
|
1519
|
+
placeholder="Enter secondary font color"
|
|
1520
|
+
placeholderTextColor="#999999"
|
|
1521
|
+
/>
|
|
1522
|
+
<View style={[styles.colorPreview, { backgroundColor: themeConfiguration.secondaryFontColor }]} />
|
|
1523
|
+
</View>
|
|
1152
1524
|
<Text style={styles.label}>Primary Button Background Color</Text>
|
|
1153
|
-
<
|
|
1154
|
-
|
|
1155
|
-
|
|
1156
|
-
|
|
1157
|
-
|
|
1525
|
+
<View style={styles.colorInputContainer}>
|
|
1526
|
+
<TextInput
|
|
1527
|
+
style={[styles.input, { flex: 1 }]}
|
|
1528
|
+
value={themeConfiguration.primaryButtonBackgroundColor}
|
|
1529
|
+
onChangeText={value => updateThemeConfiguration('primaryButtonBackgroundColor', value)}
|
|
1530
|
+
placeholder="Enter primary button background color"
|
|
1531
|
+
placeholderTextColor="#999999"
|
|
1532
|
+
/>
|
|
1533
|
+
<View style={[styles.colorPreview, { backgroundColor: themeConfiguration.primaryButtonBackgroundColor }]} />
|
|
1534
|
+
</View>
|
|
1158
1535
|
<Text style={styles.label}>Primary Button Hover Color</Text>
|
|
1159
|
-
<
|
|
1160
|
-
|
|
1161
|
-
|
|
1162
|
-
|
|
1163
|
-
|
|
1536
|
+
<View style={styles.colorInputContainer}>
|
|
1537
|
+
<TextInput
|
|
1538
|
+
style={[styles.input, { flex: 1 }]}
|
|
1539
|
+
value={themeConfiguration.primaryButtonHoverColor}
|
|
1540
|
+
onChangeText={value => updateThemeConfiguration('primaryButtonHoverColor', value)}
|
|
1541
|
+
placeholder="Enter primary button hover color"
|
|
1542
|
+
placeholderTextColor="#999999"
|
|
1543
|
+
/>
|
|
1544
|
+
<View style={[styles.colorPreview, { backgroundColor: themeConfiguration.primaryButtonHoverColor }]} />
|
|
1545
|
+
</View>
|
|
1164
1546
|
<Text style={styles.label}>Primary Button Font Color</Text>
|
|
1165
|
-
<
|
|
1166
|
-
|
|
1167
|
-
|
|
1168
|
-
|
|
1169
|
-
|
|
1547
|
+
<View style={styles.colorInputContainer}>
|
|
1548
|
+
<TextInput
|
|
1549
|
+
style={[styles.input, { flex: 1 }]}
|
|
1550
|
+
value={themeConfiguration.primaryButtonFontColor}
|
|
1551
|
+
onChangeText={value => updateThemeConfiguration('primaryButtonFontColor', value)}
|
|
1552
|
+
placeholder="Enter primary button font color"
|
|
1553
|
+
placeholderTextColor="#999999"
|
|
1554
|
+
/>
|
|
1555
|
+
<View style={[styles.colorPreview, { backgroundColor: themeConfiguration.primaryButtonFontColor }]} />
|
|
1556
|
+
</View>
|
|
1170
1557
|
<Text style={styles.label}>Secondary Button Background Color</Text>
|
|
1171
|
-
<
|
|
1172
|
-
|
|
1173
|
-
|
|
1174
|
-
|
|
1175
|
-
|
|
1558
|
+
<View style={styles.colorInputContainer}>
|
|
1559
|
+
<TextInput
|
|
1560
|
+
style={[styles.input, { flex: 1 }]}
|
|
1561
|
+
value={themeConfiguration.secondaryButtonBackgroundColor}
|
|
1562
|
+
onChangeText={value => updateThemeConfiguration('secondaryButtonBackgroundColor', value)}
|
|
1563
|
+
placeholder="Enter secondary button background color"
|
|
1564
|
+
placeholderTextColor="#999999"
|
|
1565
|
+
/>
|
|
1566
|
+
<View style={[styles.colorPreview, { backgroundColor: themeConfiguration.secondaryButtonBackgroundColor }]} />
|
|
1567
|
+
</View>
|
|
1176
1568
|
<Text style={styles.label}>Secondary Button Hover Color</Text>
|
|
1177
|
-
<
|
|
1178
|
-
|
|
1179
|
-
|
|
1180
|
-
|
|
1181
|
-
|
|
1569
|
+
<View style={styles.colorInputContainer}>
|
|
1570
|
+
<TextInput
|
|
1571
|
+
style={[styles.input, { flex: 1 }]}
|
|
1572
|
+
value={themeConfiguration.secondaryButtonHoverColor}
|
|
1573
|
+
onChangeText={value => updateThemeConfiguration('secondaryButtonHoverColor', value)}
|
|
1574
|
+
placeholder="Enter secondary button hover color"
|
|
1575
|
+
placeholderTextColor="#999999"
|
|
1576
|
+
/>
|
|
1577
|
+
<View style={[styles.colorPreview, { backgroundColor: themeConfiguration.secondaryButtonHoverColor }]} />
|
|
1578
|
+
</View>
|
|
1182
1579
|
<Text style={styles.label}>Secondary Button Font Color</Text>
|
|
1183
|
-
<
|
|
1184
|
-
|
|
1185
|
-
|
|
1186
|
-
|
|
1187
|
-
|
|
1580
|
+
<View style={styles.colorInputContainer}>
|
|
1581
|
+
<TextInput
|
|
1582
|
+
style={[styles.input, { flex: 1 }]}
|
|
1583
|
+
value={themeConfiguration.secondaryButtonFontColor}
|
|
1584
|
+
onChangeText={value => updateThemeConfiguration('secondaryButtonFontColor', value)}
|
|
1585
|
+
placeholder="Enter secondary button font color"
|
|
1586
|
+
placeholderTextColor="#999999"
|
|
1587
|
+
/>
|
|
1588
|
+
<View style={[styles.colorPreview, { backgroundColor: themeConfiguration.secondaryButtonFontColor }]} />
|
|
1589
|
+
</View>
|
|
1188
1590
|
<Text style={styles.label}>Border Radius</Text>
|
|
1189
1591
|
<TextInput
|
|
1190
1592
|
style={styles.input}
|
|
1191
1593
|
value={themeConfiguration.borderRadius}
|
|
1192
1594
|
onChangeText={value => updateThemeConfiguration('borderRadius', value)}
|
|
1595
|
+
placeholder="Enter border radius"
|
|
1596
|
+
placeholderTextColor="#999999"
|
|
1193
1597
|
/>
|
|
1194
1598
|
<Text style={styles.label}>Font Size</Text>
|
|
1195
1599
|
<TextInput
|
|
1196
1600
|
style={styles.input}
|
|
1197
1601
|
value={themeConfiguration.fontSize}
|
|
1198
1602
|
onChangeText={value => updateThemeConfiguration('fontSize', value)}
|
|
1603
|
+
placeholder="Enter font size"
|
|
1604
|
+
placeholderTextColor="#999999"
|
|
1199
1605
|
/>
|
|
1200
|
-
|
|
1201
|
-
<TextInput
|
|
1202
|
-
style={styles.input}
|
|
1203
|
-
value={String(themeConfiguration.fontWeight)}
|
|
1204
|
-
onChangeText={value => updateThemeConfiguration('fontWeight', parseInt(value) || 500)}
|
|
1205
|
-
/>
|
|
1206
|
-
<Text style={styles.label}>Font Family</Text>
|
|
1207
|
-
<TextInput
|
|
1208
|
-
style={styles.input}
|
|
1209
|
-
value={themeConfiguration.fontFamily}
|
|
1210
|
-
onChangeText={value => updateThemeConfiguration('fontFamily', value)}
|
|
1211
|
-
/>
|
|
1606
|
+
|
|
1212
1607
|
</>
|
|
1213
1608
|
)}
|
|
1214
1609
|
|
|
@@ -1219,12 +1614,16 @@ setResult(JSON.stringify(parsedResponse, null, 2));
|
|
|
1219
1614
|
style={styles.input}
|
|
1220
1615
|
value={grailPayParams.role}
|
|
1221
1616
|
onChangeText={value => updateGrailPayParams('role', value)}
|
|
1617
|
+
placeholder="Enter role"
|
|
1618
|
+
placeholderTextColor="#999999"
|
|
1222
1619
|
/>
|
|
1223
1620
|
<Text style={styles.label}>Timeout</Text>
|
|
1224
1621
|
<TextInput
|
|
1225
1622
|
style={styles.input}
|
|
1226
1623
|
value={String(grailPayParams.timeout)}
|
|
1227
1624
|
onChangeText={value => updateGrailPayParams('timeout', parseInt(value) || 10)}
|
|
1625
|
+
placeholder="Enter timeout"
|
|
1626
|
+
placeholderTextColor="#999999"
|
|
1228
1627
|
/>
|
|
1229
1628
|
<Text style={styles.label}>Is Sandbox</Text>
|
|
1230
1629
|
<Switch
|
|
@@ -1238,52 +1637,106 @@ setResult(JSON.stringify(parsedResponse, null, 2));
|
|
|
1238
1637
|
style={styles.input}
|
|
1239
1638
|
value={grailPayParams.brandingName}
|
|
1240
1639
|
onChangeText={value => updateGrailPayParams('brandingName', value)}
|
|
1640
|
+
placeholder="Enter branding name"
|
|
1641
|
+
placeholderTextColor="#999999"
|
|
1241
1642
|
/>
|
|
1242
1643
|
<Text style={styles.label}>Finder Subtitle</Text>
|
|
1243
1644
|
<TextInput
|
|
1244
1645
|
style={styles.input}
|
|
1245
1646
|
value={grailPayParams.finderSubtitle}
|
|
1246
1647
|
onChangeText={value => updateGrailPayParams('finderSubtitle', value)}
|
|
1648
|
+
placeholder="Enter finder subtitle"
|
|
1649
|
+
placeholderTextColor="#999999"
|
|
1247
1650
|
/>
|
|
1248
1651
|
<Text style={styles.label}>Search Placeholder</Text>
|
|
1249
1652
|
<TextInput
|
|
1250
1653
|
style={styles.input}
|
|
1251
1654
|
value={grailPayParams.searchPlaceholder}
|
|
1252
1655
|
onChangeText={value => updateGrailPayParams('searchPlaceholder', value)}
|
|
1656
|
+
placeholder="Enter search placeholder"
|
|
1657
|
+
placeholderTextColor="#999999"
|
|
1253
1658
|
/>
|
|
1254
1659
|
|
|
1255
1660
|
{/* Recurring Data */}
|
|
1256
1661
|
<Text style={styles.sectionTitle}>Recurring Data</Text>
|
|
1257
|
-
<Text style={styles.label}>Allow Cycles</Text>
|
|
1662
|
+
<Text style={styles.label}>Allow Cycles (Minimum 2)</Text>
|
|
1258
1663
|
<TextInput
|
|
1259
1664
|
style={styles.input}
|
|
1260
1665
|
value={String(recurringData.allowCycles)}
|
|
1261
1666
|
onChangeText={value => updateRecurringData('allowCycles', parseInt(value) || 2)}
|
|
1667
|
+
placeholder="Enter allowed cycles"
|
|
1668
|
+
placeholderTextColor="#999999"
|
|
1262
1669
|
/>
|
|
1263
|
-
|
|
1670
|
+
<Text style={styles.label}>Intervals</Text>
|
|
1264
1671
|
<View style={styles.buttonGroup}>
|
|
1265
|
-
<
|
|
1672
|
+
<FilledButton
|
|
1673
|
+
title="Daily"
|
|
1674
|
+
onPress={() => toggleInterval('daily')}
|
|
1675
|
+
disabled={loading}
|
|
1676
|
+
style={[
|
|
1677
|
+
{ flex: 1 },
|
|
1678
|
+
recurringData.intervals.includes('daily')
|
|
1679
|
+
? { backgroundColor: '#2563EB' }
|
|
1680
|
+
: { backgroundColor: '#E5E7EB' }
|
|
1681
|
+
]}
|
|
1682
|
+
textStyle={[
|
|
1683
|
+
{ fontSize: 14 },
|
|
1684
|
+
recurringData.intervals.includes('daily')
|
|
1685
|
+
? { color: '#fff' }
|
|
1686
|
+
: { color: '#374151' }
|
|
1687
|
+
]}
|
|
1688
|
+
/>
|
|
1689
|
+
<FilledButton
|
|
1266
1690
|
title="Weekly"
|
|
1267
1691
|
onPress={() => toggleInterval('weekly')}
|
|
1268
|
-
|
|
1692
|
+
disabled={loading}
|
|
1693
|
+
style={[
|
|
1694
|
+
{ flex: 1 },
|
|
1695
|
+
recurringData.intervals.includes('weekly')
|
|
1696
|
+
? { backgroundColor: '#2563EB' }
|
|
1697
|
+
: { backgroundColor: '#E5E7EB' }
|
|
1698
|
+
]}
|
|
1699
|
+
textStyle={[
|
|
1700
|
+
{ fontSize: 14 },
|
|
1701
|
+
recurringData.intervals.includes('weekly')
|
|
1702
|
+
? { color: '#fff' }
|
|
1703
|
+
: { color: '#374151' }
|
|
1704
|
+
]}
|
|
1269
1705
|
/>
|
|
1270
|
-
<
|
|
1706
|
+
<FilledButton
|
|
1271
1707
|
title="Monthly"
|
|
1272
1708
|
onPress={() => toggleInterval('monthly')}
|
|
1273
|
-
|
|
1709
|
+
disabled={loading}
|
|
1710
|
+
style={[
|
|
1711
|
+
{ flex: 1 },
|
|
1712
|
+
recurringData.intervals.includes('monthly')
|
|
1713
|
+
? { backgroundColor: '#2563EB' }
|
|
1714
|
+
: { backgroundColor: '#E5E7EB' }
|
|
1715
|
+
]}
|
|
1716
|
+
textStyle={[
|
|
1717
|
+
{ fontSize: 14 },
|
|
1718
|
+
recurringData.intervals.includes('monthly')
|
|
1719
|
+
? { color: '#fff' }
|
|
1720
|
+
: { color: '#374151' }
|
|
1721
|
+
]}
|
|
1274
1722
|
/>
|
|
1275
1723
|
</View>
|
|
1276
1724
|
<Text style={styles.label}>Recurring Start Type</Text>
|
|
1277
|
-
<
|
|
1278
|
-
style={styles.input}
|
|
1725
|
+
<Dropdown
|
|
1279
1726
|
value={recurringData.recurringStartType}
|
|
1280
|
-
|
|
1727
|
+
onValueChange={value => updateRecurringData('recurringStartType', value)}
|
|
1728
|
+
options={Platform.OS === 'android' ? ['Custom', 'Fixed'] : ['custom', 'fixed']}
|
|
1729
|
+
placeholder="Select start type"
|
|
1281
1730
|
/>
|
|
1282
1731
|
<Text style={styles.label}>Recurring Start Date</Text>
|
|
1283
1732
|
<TextInput
|
|
1284
|
-
style={styles.input}
|
|
1733
|
+
style={[styles.input, styles.dateInput]}
|
|
1285
1734
|
value={recurringData.recurringStartDate}
|
|
1286
1735
|
onChangeText={value => updateRecurringData('recurringStartDate', value)}
|
|
1736
|
+
placeholder="MM/DD/YYYY"
|
|
1737
|
+
placeholderTextColor="#999999"
|
|
1738
|
+
returnKeyType="done"
|
|
1739
|
+
onSubmitEditing={() => Keyboard.dismiss()}
|
|
1287
1740
|
/>
|
|
1288
1741
|
</>
|
|
1289
1742
|
)}
|
|
@@ -1291,7 +1744,7 @@ setResult(JSON.stringify(parsedResponse, null, 2));
|
|
|
1291
1744
|
<Text style={styles.sectionTitle}>SDK Response</Text>
|
|
1292
1745
|
<Text selectable style={styles.result}>{result || 'No response yet'}</Text>
|
|
1293
1746
|
</ScrollView>
|
|
1294
|
-
</
|
|
1747
|
+
</KeyboardAvoidingView>
|
|
1295
1748
|
);
|
|
1296
1749
|
|
|
1297
1750
|
};
|
|
@@ -1314,6 +1767,13 @@ const styles = StyleSheet.create({
|
|
|
1314
1767
|
marginTop: 20,
|
|
1315
1768
|
marginBottom: 10,
|
|
1316
1769
|
},
|
|
1770
|
+
subsectionTitle: {
|
|
1771
|
+
fontSize: 16,
|
|
1772
|
+
fontWeight: '600',
|
|
1773
|
+
marginTop: 15,
|
|
1774
|
+
marginBottom: 8,
|
|
1775
|
+
color: '#374151',
|
|
1776
|
+
},
|
|
1317
1777
|
input: {
|
|
1318
1778
|
height: 40,
|
|
1319
1779
|
borderColor: '#ccc',
|
|
@@ -1321,6 +1781,19 @@ const styles = StyleSheet.create({
|
|
|
1321
1781
|
borderRadius: 5,
|
|
1322
1782
|
paddingHorizontal: 10,
|
|
1323
1783
|
marginBottom: 10,
|
|
1784
|
+
backgroundColor: '#FFFFFF',
|
|
1785
|
+
color: '#000000',
|
|
1786
|
+
},
|
|
1787
|
+
dateInput: {
|
|
1788
|
+
backgroundColor: '#fff',
|
|
1789
|
+
shadowColor: '#000',
|
|
1790
|
+
shadowOffset: {
|
|
1791
|
+
width: 0,
|
|
1792
|
+
height: 1,
|
|
1793
|
+
},
|
|
1794
|
+
shadowOpacity: 0.1,
|
|
1795
|
+
shadowRadius: 2,
|
|
1796
|
+
elevation: 2,
|
|
1324
1797
|
},
|
|
1325
1798
|
pickerContainer: {
|
|
1326
1799
|
marginBottom: 20,
|
|
@@ -1379,8 +1852,132 @@ const styles = StyleSheet.create({
|
|
|
1379
1852
|
fontSize: 20,
|
|
1380
1853
|
color: '#333',
|
|
1381
1854
|
},
|
|
1855
|
+
// New styles for FilledButton
|
|
1856
|
+
filledButton: {
|
|
1857
|
+
flex: 1,
|
|
1858
|
+
paddingVertical: 10,
|
|
1859
|
+
paddingHorizontal: 20,
|
|
1860
|
+
borderRadius: 5,
|
|
1861
|
+
marginHorizontal: 5,
|
|
1862
|
+
alignItems: 'center',
|
|
1863
|
+
justifyContent: 'center',
|
|
1864
|
+
backgroundColor: '#2563EB', // Primary color for filled buttons
|
|
1865
|
+
},
|
|
1866
|
+
filledButtonDisabled: {
|
|
1867
|
+
backgroundColor: '#ccc',
|
|
1868
|
+
opacity: 0.7,
|
|
1869
|
+
},
|
|
1870
|
+
filledButtonText: {
|
|
1871
|
+
color: '#fff',
|
|
1872
|
+
fontSize: 16,
|
|
1873
|
+
fontWeight: '500',
|
|
1874
|
+
},
|
|
1875
|
+
filledButtonTextDisabled: {
|
|
1876
|
+
color: '#888',
|
|
1877
|
+
},
|
|
1878
|
+
debugText: {
|
|
1879
|
+
fontSize: 12,
|
|
1880
|
+
color: '#666',
|
|
1881
|
+
fontStyle: 'italic',
|
|
1882
|
+
marginBottom: 5,
|
|
1883
|
+
},
|
|
1884
|
+
// Dropdown Styles
|
|
1885
|
+
dropdownContainer: {
|
|
1886
|
+
position: 'relative',
|
|
1887
|
+
marginBottom: 20,
|
|
1888
|
+
zIndex: 9998,
|
|
1889
|
+
},
|
|
1890
|
+
dropdownButton: {
|
|
1891
|
+
height: 40,
|
|
1892
|
+
borderColor: '#ccc',
|
|
1893
|
+
borderWidth: 1,
|
|
1894
|
+
borderRadius: 5,
|
|
1895
|
+
paddingHorizontal: 10,
|
|
1896
|
+
flexDirection: 'row',
|
|
1897
|
+
justifyContent: 'space-between',
|
|
1898
|
+
alignItems: 'center',
|
|
1899
|
+
backgroundColor: '#fff',
|
|
1900
|
+
},
|
|
1901
|
+
dropdownButtonText: {
|
|
1902
|
+
fontSize: 16,
|
|
1903
|
+
color: '#333',
|
|
1904
|
+
},
|
|
1905
|
+
dropdownArrow: {
|
|
1906
|
+
fontSize: 12,
|
|
1907
|
+
color: '#666',
|
|
1908
|
+
},
|
|
1909
|
+
dropdownOptions: {
|
|
1910
|
+
position: 'absolute',
|
|
1911
|
+
top: 45,
|
|
1912
|
+
left: 0,
|
|
1913
|
+
right: 0,
|
|
1914
|
+
backgroundColor: '#fff',
|
|
1915
|
+
borderColor: '#ccc',
|
|
1916
|
+
borderWidth: 1,
|
|
1917
|
+
borderRadius: 5,
|
|
1918
|
+
zIndex: 9999,
|
|
1919
|
+
maxHeight: 200,
|
|
1920
|
+
elevation: 5,
|
|
1921
|
+
shadowColor: '#000',
|
|
1922
|
+
shadowOffset: {
|
|
1923
|
+
width: 0,
|
|
1924
|
+
height: 2,
|
|
1925
|
+
},
|
|
1926
|
+
shadowOpacity: 0.25,
|
|
1927
|
+
shadowRadius: 3.84,
|
|
1928
|
+
},
|
|
1929
|
+
dropdownScrollView: {
|
|
1930
|
+
maxHeight: 180,
|
|
1931
|
+
},
|
|
1932
|
+
dropdownOption: {
|
|
1933
|
+
paddingVertical: 12,
|
|
1934
|
+
paddingHorizontal: 15,
|
|
1935
|
+
borderBottomWidth: 1,
|
|
1936
|
+
borderBottomColor: '#f0f0f0',
|
|
1937
|
+
backgroundColor: '#fff',
|
|
1938
|
+
},
|
|
1939
|
+
dropdownOptionText: {
|
|
1940
|
+
fontSize: 16,
|
|
1941
|
+
color: '#333',
|
|
1942
|
+
},
|
|
1943
|
+
// Color preview styles
|
|
1944
|
+
colorInputContainer: {
|
|
1945
|
+
flexDirection: 'row',
|
|
1946
|
+
alignItems: 'center',
|
|
1947
|
+
marginBottom: 10,
|
|
1948
|
+
gap: 10,
|
|
1949
|
+
},
|
|
1950
|
+
colorPreview: {
|
|
1951
|
+
width: 30,
|
|
1952
|
+
height: 30,
|
|
1953
|
+
borderRadius: 4,
|
|
1954
|
+
borderWidth: 1,
|
|
1955
|
+
borderColor: '#ccc',
|
|
1956
|
+
},
|
|
1957
|
+
phoneRow: {
|
|
1958
|
+
flexDirection: 'row',
|
|
1959
|
+
alignItems: 'center',
|
|
1960
|
+
marginBottom: 10,
|
|
1961
|
+
gap: 8,
|
|
1962
|
+
},
|
|
1963
|
+
countryCodeInput: {
|
|
1964
|
+
width: 70,
|
|
1965
|
+
height: 40,
|
|
1966
|
+
borderColor: '#ccc',
|
|
1967
|
+
borderWidth: 1,
|
|
1968
|
+
borderRadius: 5,
|
|
1969
|
+
paddingHorizontal: 10,
|
|
1970
|
+
backgroundColor: '#FFFFFF',
|
|
1971
|
+
color: '#000000',
|
|
1972
|
+
textAlign: 'center',
|
|
1973
|
+
alignSelf: 'stretch',
|
|
1974
|
+
marginBottom: 0,
|
|
1975
|
+
},
|
|
1382
1976
|
});
|
|
1383
1977
|
|
|
1978
|
+
|
|
1979
|
+
|
|
1980
|
+
|
|
1384
1981
|
```
|
|
1385
1982
|
|
|
1386
1983
|
You can send `null` if billing info not available.
|