@oxyhq/services 5.1.29 → 5.1.30

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.
Files changed (73) hide show
  1. package/README.md +71 -24
  2. package/UI_COMPONENTS.md +48 -0
  3. package/lib/commonjs/core/index.js +17 -4
  4. package/lib/commonjs/core/index.js.map +1 -1
  5. package/lib/commonjs/index.js +0 -3
  6. package/lib/commonjs/index.js.map +1 -1
  7. package/lib/commonjs/node/index.js +52 -0
  8. package/lib/commonjs/node/index.js.map +1 -0
  9. package/lib/commonjs/ui/index.js +9 -1
  10. package/lib/commonjs/ui/index.js.map +1 -1
  11. package/lib/commonjs/ui/navigation/OxyRouter.js +5 -0
  12. package/lib/commonjs/ui/navigation/OxyRouter.js.map +1 -1
  13. package/lib/commonjs/ui/screens/AccountCenterScreen.js +6 -3
  14. package/lib/commonjs/ui/screens/AccountCenterScreen.js.map +1 -1
  15. package/lib/commonjs/ui/screens/AccountSettingsScreen.js +638 -0
  16. package/lib/commonjs/ui/screens/AccountSettingsScreen.js.map +1 -0
  17. package/lib/module/core/index.js +17 -4
  18. package/lib/module/core/index.js.map +1 -1
  19. package/lib/module/index.js +0 -3
  20. package/lib/module/index.js.map +1 -1
  21. package/lib/module/node/index.js +20 -0
  22. package/lib/module/node/index.js.map +1 -0
  23. package/lib/module/ui/index.js +1 -0
  24. package/lib/module/ui/index.js.map +1 -1
  25. package/lib/module/ui/navigation/OxyRouter.js +5 -0
  26. package/lib/module/ui/navigation/OxyRouter.js.map +1 -1
  27. package/lib/module/ui/screens/AccountCenterScreen.js +6 -3
  28. package/lib/module/ui/screens/AccountCenterScreen.js.map +1 -1
  29. package/lib/module/ui/screens/AccountSettingsScreen.js +632 -0
  30. package/lib/module/ui/screens/AccountSettingsScreen.js.map +1 -0
  31. package/lib/typescript/__tests__/ui/screens/AccountSettingsScreen.test.d.ts +2 -0
  32. package/lib/typescript/__tests__/ui/screens/AccountSettingsScreen.test.d.ts.map +1 -0
  33. package/lib/typescript/core/index.d.ts.map +1 -1
  34. package/lib/typescript/index.d.ts +0 -3
  35. package/lib/typescript/index.d.ts.map +1 -1
  36. package/lib/typescript/node/index.d.ts +10 -0
  37. package/lib/typescript/node/index.d.ts.map +1 -0
  38. package/lib/typescript/ui/index.d.ts +1 -0
  39. package/lib/typescript/ui/index.d.ts.map +1 -1
  40. package/lib/typescript/ui/navigation/OxyRouter.d.ts.map +1 -1
  41. package/lib/typescript/ui/screens/AccountCenterScreen.d.ts.map +1 -1
  42. package/lib/typescript/ui/screens/AccountSettingsScreen.d.ts +8 -0
  43. package/lib/typescript/ui/screens/AccountSettingsScreen.d.ts.map +1 -0
  44. package/package.json +5 -22
  45. package/src/__tests__/ui/screens/AccountSettingsScreen.test.tsx +112 -0
  46. package/src/core/index.ts +16 -4
  47. package/src/index.ts +0 -3
  48. package/src/node/index.ts +17 -0
  49. package/src/ui/index.ts +1 -0
  50. package/src/ui/navigation/OxyRouter.tsx +5 -0
  51. package/src/ui/screens/AccountCenterScreen.tsx +3 -2
  52. package/src/ui/screens/AccountSettingsScreen.tsx +616 -0
  53. package/lib/commonjs/backend.js +0 -44
  54. package/lib/commonjs/backend.js.map +0 -1
  55. package/lib/commonjs/core-only.js +0 -44
  56. package/lib/commonjs/core-only.js.map +0 -1
  57. package/lib/commonjs/test-backend.js +0 -21
  58. package/lib/commonjs/test-backend.js.map +0 -1
  59. package/lib/module/backend.js +0 -17
  60. package/lib/module/backend.js.map +0 -1
  61. package/lib/module/core-only.js +0 -17
  62. package/lib/module/core-only.js.map +0 -1
  63. package/lib/module/test-backend.js +0 -18
  64. package/lib/module/test-backend.js.map +0 -1
  65. package/lib/typescript/backend.d.ts +0 -9
  66. package/lib/typescript/backend.d.ts.map +0 -1
  67. package/lib/typescript/core-only.d.ts +0 -9
  68. package/lib/typescript/core-only.d.ts.map +0 -1
  69. package/lib/typescript/test-backend.d.ts +0 -8
  70. package/lib/typescript/test-backend.d.ts.map +0 -1
  71. package/src/backend.ts +0 -14
  72. package/src/core-only.ts +0 -14
  73. package/src/test-backend.ts +0 -17
@@ -0,0 +1,616 @@
1
+ import React, { useEffect, useState } from 'react';
2
+ import {
3
+ View,
4
+ Text,
5
+ TextInput,
6
+ TouchableOpacity,
7
+ StyleSheet,
8
+ ActivityIndicator,
9
+ ScrollView,
10
+ Alert,
11
+ Platform,
12
+ Switch,
13
+ } from 'react-native';
14
+ import { BaseScreenProps } from '../navigation/types';
15
+ import { useOxy } from '../context/OxyContext';
16
+ import Avatar from '../components/Avatar';
17
+
18
+ interface AccountSettingsScreenProps extends BaseScreenProps {
19
+ activeTab?: 'profile' | 'password' | 'notifications';
20
+ }
21
+
22
+ const AccountSettingsScreen: React.FC<AccountSettingsScreenProps> = ({
23
+ goBack,
24
+ theme,
25
+ activeTab = 'profile',
26
+ }) => {
27
+ const { user, oxyServices, isLoading: authLoading } = useOxy();
28
+ const [currentTab, setCurrentTab] = useState<'profile' | 'password' | 'notifications'>(activeTab);
29
+ const [isLoading, setIsLoading] = useState(false);
30
+ const [errorMessage, setErrorMessage] = useState('');
31
+ const [successMessage, setSuccessMessage] = useState('');
32
+
33
+ // Profile form state
34
+ const [username, setUsername] = useState('');
35
+ const [email, setEmail] = useState('');
36
+ const [bio, setBio] = useState('');
37
+ const [avatarUrl, setAvatarUrl] = useState('');
38
+
39
+ // Password form state
40
+ const [currentPassword, setCurrentPassword] = useState('');
41
+ const [newPassword, setNewPassword] = useState('');
42
+ const [confirmPassword, setConfirmPassword] = useState('');
43
+
44
+ // Notification preferences
45
+ const [emailNotifications, setEmailNotifications] = useState(true);
46
+ const [pushNotifications, setPushNotifications] = useState(true);
47
+
48
+ // Theme and styling
49
+ const isDarkTheme = theme === 'dark';
50
+ const textColor = isDarkTheme ? '#FFFFFF' : '#000000';
51
+ const backgroundColor = isDarkTheme ? '#121212' : '#FFFFFF';
52
+ const secondaryBackgroundColor = isDarkTheme ? '#222222' : '#F5F5F5';
53
+ const inputBackgroundColor = isDarkTheme ? '#333333' : '#F5F5F5';
54
+ const borderColor = isDarkTheme ? '#444444' : '#E0E0E0';
55
+ const primaryColor = '#0066CC';
56
+ const placeholderColor = isDarkTheme ? '#AAAAAA' : '#999999';
57
+
58
+ // Load user data
59
+ useEffect(() => {
60
+ if (user) {
61
+ setUsername(user.username || '');
62
+ setEmail(user.email || '');
63
+ setBio(user.bio || '');
64
+ setAvatarUrl(user.avatar?.url || '');
65
+ }
66
+ }, [user]);
67
+
68
+ const validateEmail = (email: string) => {
69
+ const emailRegex = /^[^\s@]+@[^\s@]+\.[^\s@]+$/;
70
+ return emailRegex.test(email);
71
+ };
72
+
73
+ const handleSaveProfile = async () => {
74
+ // Validate inputs
75
+ if (!username) {
76
+ setErrorMessage('Username is required');
77
+ return;
78
+ }
79
+
80
+ if (email && !validateEmail(email)) {
81
+ setErrorMessage('Please enter a valid email address');
82
+ return;
83
+ }
84
+
85
+ try {
86
+ setIsLoading(true);
87
+ setErrorMessage('');
88
+ setSuccessMessage('');
89
+
90
+ // Prepare updates object
91
+ const updates: Record<string, any> = {
92
+ username,
93
+ bio,
94
+ };
95
+
96
+ if (email) {
97
+ updates.email = email;
98
+ }
99
+
100
+ // Only include avatar if it's been changed
101
+ if (avatarUrl !== user?.avatar?.url) {
102
+ updates.avatar = { url: avatarUrl };
103
+ }
104
+
105
+ // Call API to update user
106
+ await oxyServices.updateUser(user!.id, updates);
107
+ setSuccessMessage('Profile updated successfully');
108
+ } catch (error: any) {
109
+ setErrorMessage(error.message || 'Failed to update profile');
110
+ } finally {
111
+ setIsLoading(false);
112
+ }
113
+ };
114
+
115
+ const handleChangePassword = async () => {
116
+ // Validate inputs
117
+ if (!currentPassword || !newPassword || !confirmPassword) {
118
+ setErrorMessage('Please fill in all password fields');
119
+ return;
120
+ }
121
+
122
+ if (newPassword !== confirmPassword) {
123
+ setErrorMessage('New passwords do not match');
124
+ return;
125
+ }
126
+
127
+ if (newPassword.length < 8) {
128
+ setErrorMessage('Password must be at least 8 characters long');
129
+ return;
130
+ }
131
+
132
+ try {
133
+ setIsLoading(true);
134
+ setErrorMessage('');
135
+ setSuccessMessage('');
136
+
137
+ // Call API to update password
138
+ await oxyServices.updateUser(user!.id, {
139
+ currentPassword,
140
+ password: newPassword,
141
+ });
142
+
143
+ // Clear form fields after successful update
144
+ setCurrentPassword('');
145
+ setNewPassword('');
146
+ setConfirmPassword('');
147
+ setSuccessMessage('Password updated successfully');
148
+ } catch (error: any) {
149
+ setErrorMessage(error.message || 'Failed to update password');
150
+ } finally {
151
+ setIsLoading(false);
152
+ }
153
+ };
154
+
155
+ const handleSaveNotifications = async () => {
156
+ try {
157
+ setIsLoading(true);
158
+ setErrorMessage('');
159
+ setSuccessMessage('');
160
+
161
+ // Call API to update notification preferences
162
+ await oxyServices.updateUser(user!.id, {
163
+ notificationPreferences: {
164
+ email: emailNotifications,
165
+ push: pushNotifications,
166
+ },
167
+ });
168
+ setSuccessMessage('Notification preferences updated successfully');
169
+ } catch (error: any) {
170
+ setErrorMessage(error.message || 'Failed to update notification preferences');
171
+ } finally {
172
+ setIsLoading(false);
173
+ }
174
+ };
175
+
176
+ const handleAvatarUpdate = () => {
177
+ // In a real app, this would open an image picker
178
+ // For now, we'll use a mock URL to demonstrate the concept
179
+ Alert.alert(
180
+ 'Update Avatar',
181
+ 'This would open an image picker in a real app. For now, we\'ll use a mock URL.',
182
+ [
183
+ {
184
+ text: 'Cancel',
185
+ style: 'cancel',
186
+ },
187
+ {
188
+ text: 'Use Mock URL',
189
+ onPress: () => {
190
+ const mockUrl = `https://ui-avatars.com/api/?name=${username}&background=random`;
191
+ setAvatarUrl(mockUrl);
192
+ },
193
+ },
194
+ ]
195
+ );
196
+ };
197
+
198
+ if (authLoading || !user) {
199
+ return (
200
+ <View style={[styles.container, { backgroundColor, justifyContent: 'center' }]}>
201
+ <ActivityIndicator size="large" color={primaryColor} />
202
+ </View>
203
+ );
204
+ }
205
+
206
+ const renderProfileTab = () => (
207
+ <View style={styles.tabContent}>
208
+ <View style={styles.avatarSection}>
209
+ <Avatar
210
+ uri={avatarUrl}
211
+ name={username}
212
+ size={100}
213
+ theme={theme}
214
+ />
215
+ <TouchableOpacity
216
+ style={[styles.changeAvatarButton, { backgroundColor: primaryColor }]}
217
+ onPress={handleAvatarUpdate}
218
+ >
219
+ <Text style={styles.changeAvatarText}>Change Avatar</Text>
220
+ </TouchableOpacity>
221
+ </View>
222
+
223
+ <View style={styles.inputContainer}>
224
+ <Text style={[styles.label, { color: textColor }]}>Username</Text>
225
+ <TextInput
226
+ style={[
227
+ styles.input,
228
+ { backgroundColor: inputBackgroundColor, borderColor, color: textColor }
229
+ ]}
230
+ placeholder="Enter your username"
231
+ placeholderTextColor={placeholderColor}
232
+ value={username}
233
+ onChangeText={setUsername}
234
+ testID="username-input"
235
+ />
236
+ </View>
237
+
238
+ <View style={styles.inputContainer}>
239
+ <Text style={[styles.label, { color: textColor }]}>Email</Text>
240
+ <TextInput
241
+ style={[
242
+ styles.input,
243
+ { backgroundColor: inputBackgroundColor, borderColor, color: textColor }
244
+ ]}
245
+ placeholder="Enter your email"
246
+ placeholderTextColor={placeholderColor}
247
+ value={email}
248
+ onChangeText={setEmail}
249
+ keyboardType="email-address"
250
+ testID="email-input"
251
+ />
252
+ </View>
253
+
254
+ <View style={styles.inputContainer}>
255
+ <Text style={[styles.label, { color: textColor }]}>Bio</Text>
256
+ <TextInput
257
+ style={[
258
+ styles.textArea,
259
+ { backgroundColor: inputBackgroundColor, borderColor, color: textColor }
260
+ ]}
261
+ placeholder="Tell us about yourself"
262
+ placeholderTextColor={placeholderColor}
263
+ value={bio}
264
+ onChangeText={setBio}
265
+ multiline
266
+ numberOfLines={4}
267
+ testID="bio-input"
268
+ />
269
+ </View>
270
+
271
+ <TouchableOpacity
272
+ style={[styles.saveButton, { backgroundColor: primaryColor, opacity: isLoading ? 0.7 : 1 }]}
273
+ onPress={handleSaveProfile}
274
+ disabled={isLoading}
275
+ testID="save-profile-button"
276
+ >
277
+ {isLoading ? (
278
+ <ActivityIndicator color="#FFFFFF" size="small" />
279
+ ) : (
280
+ <Text style={styles.saveButtonText}>Save Profile</Text>
281
+ )}
282
+ </TouchableOpacity>
283
+ </View>
284
+ );
285
+
286
+ const renderPasswordTab = () => (
287
+ <View style={styles.tabContent}>
288
+ <View style={styles.inputContainer}>
289
+ <Text style={[styles.label, { color: textColor }]}>Current Password</Text>
290
+ <TextInput
291
+ style={[
292
+ styles.input,
293
+ { backgroundColor: inputBackgroundColor, borderColor, color: textColor }
294
+ ]}
295
+ placeholder="Enter your current password"
296
+ placeholderTextColor={placeholderColor}
297
+ value={currentPassword}
298
+ onChangeText={setCurrentPassword}
299
+ secureTextEntry
300
+ testID="current-password-input"
301
+ />
302
+ </View>
303
+
304
+ <View style={styles.inputContainer}>
305
+ <Text style={[styles.label, { color: textColor }]}>New Password</Text>
306
+ <TextInput
307
+ style={[
308
+ styles.input,
309
+ { backgroundColor: inputBackgroundColor, borderColor, color: textColor }
310
+ ]}
311
+ placeholder="Enter your new password"
312
+ placeholderTextColor={placeholderColor}
313
+ value={newPassword}
314
+ onChangeText={setNewPassword}
315
+ secureTextEntry
316
+ testID="new-password-input"
317
+ />
318
+ <Text style={[styles.passwordHint, { color: isDarkTheme ? '#AAAAAA' : '#666666' }]}>
319
+ Password must be at least 8 characters long
320
+ </Text>
321
+ </View>
322
+
323
+ <View style={styles.inputContainer}>
324
+ <Text style={[styles.label, { color: textColor }]}>Confirm New Password</Text>
325
+ <TextInput
326
+ style={[
327
+ styles.input,
328
+ { backgroundColor: inputBackgroundColor, borderColor, color: textColor }
329
+ ]}
330
+ placeholder="Confirm your new password"
331
+ placeholderTextColor={placeholderColor}
332
+ value={confirmPassword}
333
+ onChangeText={setConfirmPassword}
334
+ secureTextEntry
335
+ testID="confirm-password-input"
336
+ />
337
+ </View>
338
+
339
+ <TouchableOpacity
340
+ style={[styles.saveButton, { backgroundColor: primaryColor, opacity: isLoading ? 0.7 : 1 }]}
341
+ onPress={handleChangePassword}
342
+ disabled={isLoading}
343
+ testID="change-password-button"
344
+ >
345
+ {isLoading ? (
346
+ <ActivityIndicator color="#FFFFFF" size="small" />
347
+ ) : (
348
+ <Text style={styles.saveButtonText}>Change Password</Text>
349
+ )}
350
+ </TouchableOpacity>
351
+ </View>
352
+ );
353
+
354
+ const renderNotificationsTab = () => (
355
+ <View style={styles.tabContent}>
356
+ <View style={styles.settingRow}>
357
+ <Text style={[styles.settingLabel, { color: textColor }]}>Email Notifications</Text>
358
+ <Switch
359
+ value={emailNotifications}
360
+ onValueChange={setEmailNotifications}
361
+ trackColor={{ false: '#767577', true: primaryColor }}
362
+ thumbColor="#f4f3f4"
363
+ testID="email-notifications-switch"
364
+ />
365
+ </View>
366
+
367
+ <View style={styles.settingRow}>
368
+ <Text style={[styles.settingLabel, { color: textColor }]}>Push Notifications</Text>
369
+ <Switch
370
+ value={pushNotifications}
371
+ onValueChange={setPushNotifications}
372
+ trackColor={{ false: '#767577', true: primaryColor }}
373
+ thumbColor="#f4f3f4"
374
+ testID="push-notifications-switch"
375
+ />
376
+ </View>
377
+
378
+ <TouchableOpacity
379
+ style={[styles.saveButton, { backgroundColor: primaryColor, opacity: isLoading ? 0.7 : 1 }]}
380
+ onPress={handleSaveNotifications}
381
+ disabled={isLoading}
382
+ testID="save-notifications-button"
383
+ >
384
+ {isLoading ? (
385
+ <ActivityIndicator color="#FFFFFF" size="small" />
386
+ ) : (
387
+ <Text style={styles.saveButtonText}>Save Preferences</Text>
388
+ )}
389
+ </TouchableOpacity>
390
+ </View>
391
+ );
392
+
393
+ return (
394
+ <View style={[styles.container, { backgroundColor }]}>
395
+ <ScrollView style={styles.scrollView} contentContainerStyle={styles.scrollContainer}>
396
+ <View style={styles.header}>
397
+ <TouchableOpacity
398
+ style={styles.backButton}
399
+ onPress={goBack}
400
+ >
401
+ <Text style={[styles.backButtonText, { color: primaryColor }]}>Back</Text>
402
+ </TouchableOpacity>
403
+ <Text style={[styles.title, { color: textColor }]}>Account Settings</Text>
404
+ <View style={styles.backButtonPlaceholder} />
405
+ </View>
406
+
407
+ <View style={[styles.tabsContainer, { borderColor }]}>
408
+ <TouchableOpacity
409
+ style={[
410
+ styles.tabButton,
411
+ currentTab === 'profile' && [styles.activeTabButton, { borderColor: primaryColor }]
412
+ ]}
413
+ onPress={() => setCurrentTab('profile')}
414
+ >
415
+ <Text
416
+ style={[
417
+ styles.tabButtonText,
418
+ { color: currentTab === 'profile' ? primaryColor : textColor }
419
+ ]}
420
+ >
421
+ Profile
422
+ </Text>
423
+ </TouchableOpacity>
424
+
425
+ <TouchableOpacity
426
+ style={[
427
+ styles.tabButton,
428
+ currentTab === 'password' && [styles.activeTabButton, { borderColor: primaryColor }]
429
+ ]}
430
+ onPress={() => setCurrentTab('password')}
431
+ >
432
+ <Text
433
+ style={[
434
+ styles.tabButtonText,
435
+ { color: currentTab === 'password' ? primaryColor : textColor }
436
+ ]}
437
+ >
438
+ Password
439
+ </Text>
440
+ </TouchableOpacity>
441
+
442
+ <TouchableOpacity
443
+ style={[
444
+ styles.tabButton,
445
+ currentTab === 'notifications' && [styles.activeTabButton, { borderColor: primaryColor }]
446
+ ]}
447
+ onPress={() => setCurrentTab('notifications')}
448
+ >
449
+ <Text
450
+ style={[
451
+ styles.tabButtonText,
452
+ { color: currentTab === 'notifications' ? primaryColor : textColor }
453
+ ]}
454
+ >
455
+ Notifications
456
+ </Text>
457
+ </TouchableOpacity>
458
+ </View>
459
+
460
+ {errorMessage ? (
461
+ <View style={styles.errorContainer}>
462
+ <Text style={styles.errorText}>{errorMessage}</Text>
463
+ </View>
464
+ ) : null}
465
+
466
+ {successMessage ? (
467
+ <View style={styles.successContainer}>
468
+ <Text style={styles.successText}>{successMessage}</Text>
469
+ </View>
470
+ ) : null}
471
+
472
+ {currentTab === 'profile' && renderProfileTab()}
473
+ {currentTab === 'password' && renderPasswordTab()}
474
+ {currentTab === 'notifications' && renderNotificationsTab()}
475
+ </ScrollView>
476
+ </View>
477
+ );
478
+ };
479
+
480
+ const styles = StyleSheet.create({
481
+ container: {
482
+ flex: 1,
483
+ },
484
+ scrollView: {
485
+ flex: 1,
486
+ },
487
+ scrollContainer: {
488
+ padding: 20,
489
+ },
490
+ header: {
491
+ flexDirection: 'row',
492
+ justifyContent: 'space-between',
493
+ alignItems: 'center',
494
+ marginBottom: 24,
495
+ },
496
+ title: {
497
+ fontSize: 24,
498
+ fontWeight: 'bold',
499
+ },
500
+ backButton: {
501
+ padding: 10,
502
+ },
503
+ backButtonText: {
504
+ fontSize: 16,
505
+ fontWeight: '600',
506
+ },
507
+ backButtonPlaceholder: {
508
+ width: 40,
509
+ },
510
+ tabsContainer: {
511
+ flexDirection: 'row',
512
+ marginBottom: 24,
513
+ borderBottomWidth: 1,
514
+ },
515
+ tabButton: {
516
+ flex: 1,
517
+ alignItems: 'center',
518
+ paddingVertical: 12,
519
+ },
520
+ activeTabButton: {
521
+ borderBottomWidth: 2,
522
+ },
523
+ tabButtonText: {
524
+ fontSize: 16,
525
+ fontWeight: '500',
526
+ },
527
+ tabContent: {
528
+ marginBottom: 24,
529
+ },
530
+ avatarSection: {
531
+ alignItems: 'center',
532
+ marginBottom: 24,
533
+ },
534
+ changeAvatarButton: {
535
+ marginTop: 12,
536
+ paddingVertical: 8,
537
+ paddingHorizontal: 16,
538
+ borderRadius: 20,
539
+ },
540
+ changeAvatarText: {
541
+ color: '#FFFFFF',
542
+ fontWeight: '600',
543
+ },
544
+ inputContainer: {
545
+ marginBottom: 16,
546
+ },
547
+ label: {
548
+ fontSize: 16,
549
+ marginBottom: 8,
550
+ },
551
+ input: {
552
+ height: 50,
553
+ borderRadius: 8,
554
+ borderWidth: 1,
555
+ paddingHorizontal: 12,
556
+ fontSize: 16,
557
+ },
558
+ textArea: {
559
+ minHeight: 100,
560
+ borderRadius: 8,
561
+ borderWidth: 1,
562
+ paddingHorizontal: 12,
563
+ paddingTop: 12,
564
+ fontSize: 16,
565
+ textAlignVertical: 'top',
566
+ },
567
+ passwordHint: {
568
+ fontSize: 14,
569
+ marginTop: 4,
570
+ },
571
+ saveButton: {
572
+ height: 50,
573
+ borderRadius: 25,
574
+ alignItems: 'center',
575
+ justifyContent: 'center',
576
+ marginTop: 16,
577
+ },
578
+ saveButtonText: {
579
+ color: '#FFFFFF',
580
+ fontSize: 16,
581
+ fontWeight: '600',
582
+ },
583
+ settingRow: {
584
+ flexDirection: 'row',
585
+ justifyContent: 'space-between',
586
+ alignItems: 'center',
587
+ paddingVertical: 16,
588
+ borderBottomWidth: 1,
589
+ borderBottomColor: '#E0E0E0',
590
+ },
591
+ settingLabel: {
592
+ fontSize: 16,
593
+ },
594
+ errorContainer: {
595
+ backgroundColor: '#FFEBEE',
596
+ padding: 16,
597
+ borderRadius: 8,
598
+ marginBottom: 16,
599
+ },
600
+ errorText: {
601
+ color: '#D32F2F',
602
+ fontSize: 14,
603
+ },
604
+ successContainer: {
605
+ backgroundColor: '#E8F5E9',
606
+ padding: 16,
607
+ borderRadius: 8,
608
+ marginBottom: 16,
609
+ },
610
+ successText: {
611
+ color: '#2E7D32',
612
+ fontSize: 14,
613
+ },
614
+ });
615
+
616
+ export default AccountSettingsScreen;
@@ -1,44 +0,0 @@
1
- "use strict";
2
-
3
- Object.defineProperty(exports, "__esModule", {
4
- value: true
5
- });
6
- var _exportNames = {
7
- OxyServices: true,
8
- OXY_CLOUD_URL: true
9
- };
10
- Object.defineProperty(exports, "OXY_CLOUD_URL", {
11
- enumerable: true,
12
- get: function () {
13
- return _core.OXY_CLOUD_URL;
14
- }
15
- });
16
- Object.defineProperty(exports, "OxyServices", {
17
- enumerable: true,
18
- get: function () {
19
- return _core.OxyServices;
20
- }
21
- });
22
- exports.default = void 0;
23
- var _core = require("./core");
24
- var _interfaces = require("./models/interfaces");
25
- Object.keys(_interfaces).forEach(function (key) {
26
- if (key === "default" || key === "__esModule") return;
27
- if (Object.prototype.hasOwnProperty.call(_exportNames, key)) return;
28
- if (key in exports && exports[key] === _interfaces[key]) return;
29
- Object.defineProperty(exports, key, {
30
- enumerable: true,
31
- get: function () {
32
- return _interfaces[key];
33
- }
34
- });
35
- });
36
- /**
37
- * Backend-only exports for Node.js environments
38
- * This file exports only the core functionality without React Native dependencies
39
- */
40
- // Export core services
41
- // Export models/interfaces
42
- // Default export for backward compatibility
43
- var _default = exports.default = _core.OxyServices;
44
- //# sourceMappingURL=backend.js.map
@@ -1 +0,0 @@
1
- {"version":3,"names":["_core","require","_interfaces","Object","keys","forEach","key","prototype","hasOwnProperty","call","_exportNames","exports","defineProperty","enumerable","get","_default","default","OxyServices"],"sourceRoot":"../../src","sources":["backend.ts"],"mappings":";;;;;;;;;;;;;;;;;;;;;;AAMA,IAAAA,KAAA,GAAAC,OAAA;AAIA,IAAAC,WAAA,GAAAD,OAAA;AAAAE,MAAA,CAAAC,IAAA,CAAAF,WAAA,EAAAG,OAAA,WAAAC,GAAA;EAAA,IAAAA,GAAA,kBAAAA,GAAA;EAAA,IAAAH,MAAA,CAAAI,SAAA,CAAAC,cAAA,CAAAC,IAAA,CAAAC,YAAA,EAAAJ,GAAA;EAAA,IAAAA,GAAA,IAAAK,OAAA,IAAAA,OAAA,CAAAL,GAAA,MAAAJ,WAAA,CAAAI,GAAA;EAAAH,MAAA,CAAAS,cAAA,CAAAD,OAAA,EAAAL,GAAA;IAAAO,UAAA;IAAAC,GAAA,WAAAA,CAAA;MAAA,OAAAZ,WAAA,CAAAI,GAAA;IAAA;EAAA;AAAA;AAVA;AACA;AACA;AACA;AAEA;AAIA;AAGA;AAAA,IAAAS,QAAA,GAAAJ,OAAA,CAAAK,OAAA,GACeC,iBAAW","ignoreList":[]}