@oxyhq/services 5.3.11 → 5.4.1

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 (213) hide show
  1. package/README.md +21 -0
  2. package/lib/commonjs/assets/assets/icons/OxyServices.tsx +67 -0
  3. package/lib/commonjs/assets/assets/icons/logo_OxyServices.svg +1 -0
  4. package/lib/commonjs/assets/icons/OxyServices.js +53 -0
  5. package/lib/commonjs/assets/icons/OxyServices.js.map +1 -0
  6. package/lib/commonjs/assets/icons/logo_OxyServices.svg +1 -0
  7. package/lib/commonjs/core/index.js +119 -23
  8. package/lib/commonjs/core/index.js.map +1 -1
  9. package/lib/commonjs/index.js +2 -0
  10. package/lib/commonjs/index.js.map +1 -1
  11. package/lib/commonjs/lib/sonner.js +15 -11
  12. package/lib/commonjs/lib/sonner.js.map +1 -1
  13. package/lib/commonjs/node/index.js +2 -0
  14. package/lib/commonjs/node/index.js.map +1 -1
  15. package/lib/commonjs/ui/components/GroupedItem.js +109 -0
  16. package/lib/commonjs/ui/components/GroupedItem.js.map +1 -0
  17. package/lib/commonjs/ui/components/GroupedSection.js +33 -0
  18. package/lib/commonjs/ui/components/GroupedSection.js.map +1 -0
  19. package/lib/commonjs/ui/components/OxyProvider.js +95 -112
  20. package/lib/commonjs/ui/components/OxyProvider.js.map +1 -1
  21. package/lib/commonjs/ui/components/ProfileCard.js +124 -0
  22. package/lib/commonjs/ui/components/ProfileCard.js.map +1 -0
  23. package/lib/commonjs/ui/components/QuickActions.js +87 -0
  24. package/lib/commonjs/ui/components/QuickActions.js.map +1 -0
  25. package/lib/commonjs/ui/components/Section.js +36 -0
  26. package/lib/commonjs/ui/components/Section.js.map +1 -0
  27. package/lib/commonjs/ui/components/SectionTitle.js +35 -0
  28. package/lib/commonjs/ui/components/SectionTitle.js.map +1 -0
  29. package/lib/commonjs/ui/components/bottomSheet/index.js +6 -6
  30. package/lib/commonjs/ui/components/index.js +97 -0
  31. package/lib/commonjs/ui/components/index.js.map +1 -0
  32. package/lib/commonjs/ui/navigation/OxyRouter.js +20 -3
  33. package/lib/commonjs/ui/navigation/OxyRouter.js.map +1 -1
  34. package/lib/commonjs/ui/screens/AccountCenterScreen.js +190 -207
  35. package/lib/commonjs/ui/screens/AccountCenterScreen.js.map +1 -1
  36. package/lib/commonjs/ui/screens/AccountManagementDemo.js +299 -0
  37. package/lib/commonjs/ui/screens/AccountManagementDemo.js.map +1 -0
  38. package/lib/commonjs/ui/screens/AccountOverviewScreen.js +669 -401
  39. package/lib/commonjs/ui/screens/AccountOverviewScreen.js.map +1 -1
  40. package/lib/commonjs/ui/screens/AccountSettingsScreen.js +695 -498
  41. package/lib/commonjs/ui/screens/AccountSettingsScreen.js.map +1 -1
  42. package/lib/commonjs/ui/screens/AccountSwitcherScreen.js +451 -488
  43. package/lib/commonjs/ui/screens/AccountSwitcherScreen.js.map +1 -1
  44. package/lib/commonjs/ui/screens/AppInfoScreen.js +498 -185
  45. package/lib/commonjs/ui/screens/AppInfoScreen.js.map +1 -1
  46. package/lib/commonjs/ui/screens/BillingManagementScreen.js +636 -0
  47. package/lib/commonjs/ui/screens/BillingManagementScreen.js.map +1 -0
  48. package/lib/commonjs/ui/screens/FileManagementScreen.js +2497 -0
  49. package/lib/commonjs/ui/screens/FileManagementScreen.js.map +1 -0
  50. package/lib/commonjs/ui/screens/PremiumSubscriptionScreen.js +1620 -0
  51. package/lib/commonjs/ui/screens/PremiumSubscriptionScreen.js.map +1 -0
  52. package/lib/commonjs/ui/screens/ProfileScreen.js +117 -13
  53. package/lib/commonjs/ui/screens/ProfileScreen.js.map +1 -1
  54. package/lib/commonjs/ui/screens/SessionManagementScreen.js.map +1 -1
  55. package/lib/commonjs/ui/screens/SignInScreen.js +1 -1
  56. package/lib/commonjs/ui/screens/SignUpScreen.js +1 -1
  57. package/lib/commonjs/utils/polyfills.js +42 -0
  58. package/lib/commonjs/utils/polyfills.js.map +1 -0
  59. package/lib/module/assets/assets/icons/OxyServices.tsx +67 -0
  60. package/lib/module/assets/assets/icons/logo_OxyServices.svg +1 -0
  61. package/lib/module/assets/icons/OxyServices.js +46 -0
  62. package/lib/module/assets/icons/OxyServices.js.map +1 -0
  63. package/lib/module/assets/icons/logo_OxyServices.svg +1 -0
  64. package/lib/module/core/index.js +119 -23
  65. package/lib/module/core/index.js.map +1 -1
  66. package/lib/module/index.js +3 -0
  67. package/lib/module/index.js.map +1 -1
  68. package/lib/module/lib/sonner.js +13 -1
  69. package/lib/module/lib/sonner.js.map +1 -1
  70. package/lib/module/node/index.js +3 -0
  71. package/lib/module/node/index.js.map +1 -1
  72. package/lib/module/ui/components/GroupedItem.js +104 -0
  73. package/lib/module/ui/components/GroupedItem.js.map +1 -0
  74. package/lib/module/ui/components/GroupedSection.js +28 -0
  75. package/lib/module/ui/components/GroupedSection.js.map +1 -0
  76. package/lib/module/ui/components/OxyProvider.js +97 -114
  77. package/lib/module/ui/components/OxyProvider.js.map +1 -1
  78. package/lib/module/ui/components/ProfileCard.js +119 -0
  79. package/lib/module/ui/components/ProfileCard.js.map +1 -0
  80. package/lib/module/ui/components/QuickActions.js +82 -0
  81. package/lib/module/ui/components/QuickActions.js.map +1 -0
  82. package/lib/module/ui/components/Section.js +31 -0
  83. package/lib/module/ui/components/Section.js.map +1 -0
  84. package/lib/module/ui/components/SectionTitle.js +30 -0
  85. package/lib/module/ui/components/SectionTitle.js.map +1 -0
  86. package/lib/module/ui/components/bottomSheet/index.js +2 -5
  87. package/lib/module/ui/components/bottomSheet/index.js.map +1 -1
  88. package/lib/module/ui/components/index.js +18 -0
  89. package/lib/module/ui/components/index.js.map +1 -0
  90. package/lib/module/ui/navigation/OxyRouter.js +20 -3
  91. package/lib/module/ui/navigation/OxyRouter.js.map +1 -1
  92. package/lib/module/ui/screens/AccountCenterScreen.js +191 -208
  93. package/lib/module/ui/screens/AccountCenterScreen.js.map +1 -1
  94. package/lib/module/ui/screens/AccountManagementDemo.js +296 -0
  95. package/lib/module/ui/screens/AccountManagementDemo.js.map +1 -0
  96. package/lib/module/ui/screens/AccountOverviewScreen.js +671 -403
  97. package/lib/module/ui/screens/AccountOverviewScreen.js.map +1 -1
  98. package/lib/module/ui/screens/AccountSettingsScreen.js +698 -501
  99. package/lib/module/ui/screens/AccountSettingsScreen.js.map +1 -1
  100. package/lib/module/ui/screens/AccountSwitcherScreen.js +450 -488
  101. package/lib/module/ui/screens/AccountSwitcherScreen.js.map +1 -1
  102. package/lib/module/ui/screens/AppInfoScreen.js +498 -186
  103. package/lib/module/ui/screens/AppInfoScreen.js.map +1 -1
  104. package/lib/module/ui/screens/BillingManagementScreen.js +631 -0
  105. package/lib/module/ui/screens/BillingManagementScreen.js.map +1 -0
  106. package/lib/module/ui/screens/FileManagementScreen.js +2492 -0
  107. package/lib/module/ui/screens/FileManagementScreen.js.map +1 -0
  108. package/lib/module/ui/screens/PremiumSubscriptionScreen.js +1615 -0
  109. package/lib/module/ui/screens/PremiumSubscriptionScreen.js.map +1 -0
  110. package/lib/module/ui/screens/ProfileScreen.js +118 -14
  111. package/lib/module/ui/screens/ProfileScreen.js.map +1 -1
  112. package/lib/module/ui/screens/SessionManagementScreen.js.map +1 -1
  113. package/lib/module/ui/screens/SignInScreen.js +1 -1
  114. package/lib/module/ui/screens/SignInScreen.js.map +1 -1
  115. package/lib/module/ui/screens/SignUpScreen.js +1 -1
  116. package/lib/module/ui/screens/SignUpScreen.js.map +1 -1
  117. package/lib/module/utils/polyfills.js +36 -0
  118. package/lib/module/utils/polyfills.js.map +1 -0
  119. package/lib/typescript/assets/icons/OxyServices.d.ts +29 -0
  120. package/lib/typescript/assets/icons/OxyServices.d.ts.map +1 -0
  121. package/lib/typescript/core/index.d.ts +26 -1
  122. package/lib/typescript/core/index.d.ts.map +1 -1
  123. package/lib/typescript/index.d.ts +1 -0
  124. package/lib/typescript/index.d.ts.map +1 -1
  125. package/lib/typescript/lib/sonner.d.ts +5 -1
  126. package/lib/typescript/lib/sonner.d.ts.map +1 -1
  127. package/lib/typescript/models/interfaces.d.ts +1 -2
  128. package/lib/typescript/models/interfaces.d.ts.map +1 -1
  129. package/lib/typescript/node/index.d.ts +1 -0
  130. package/lib/typescript/node/index.d.ts.map +1 -1
  131. package/lib/typescript/ui/components/GroupedItem.d.ts +17 -0
  132. package/lib/typescript/ui/components/GroupedItem.d.ts.map +1 -0
  133. package/lib/typescript/ui/components/GroupedSection.d.ts +19 -0
  134. package/lib/typescript/ui/components/GroupedSection.d.ts.map +1 -0
  135. package/lib/typescript/ui/components/OxyProvider.d.ts.map +1 -1
  136. package/lib/typescript/ui/components/ProfileCard.d.ts +20 -0
  137. package/lib/typescript/ui/components/ProfileCard.d.ts.map +1 -0
  138. package/lib/typescript/ui/components/QuickActions.d.ts +15 -0
  139. package/lib/typescript/ui/components/QuickActions.d.ts.map +1 -0
  140. package/lib/typescript/ui/components/Section.d.ts +11 -0
  141. package/lib/typescript/ui/components/Section.d.ts.map +1 -0
  142. package/lib/typescript/ui/components/SectionTitle.d.ts +9 -0
  143. package/lib/typescript/ui/components/SectionTitle.d.ts.map +1 -0
  144. package/lib/typescript/ui/components/bottomSheet/index.d.ts +3 -2
  145. package/lib/typescript/ui/components/bottomSheet/index.d.ts.map +1 -1
  146. package/lib/typescript/ui/components/index.d.ts +13 -0
  147. package/lib/typescript/ui/components/index.d.ts.map +1 -0
  148. package/lib/typescript/ui/navigation/OxyRouter.d.ts.map +1 -1
  149. package/lib/typescript/ui/navigation/types.d.ts +8 -0
  150. package/lib/typescript/ui/navigation/types.d.ts.map +1 -1
  151. package/lib/typescript/ui/screens/AccountCenterScreen.d.ts.map +1 -1
  152. package/lib/typescript/ui/screens/AccountManagementDemo.d.ts +8 -0
  153. package/lib/typescript/ui/screens/AccountManagementDemo.d.ts.map +1 -0
  154. package/lib/typescript/ui/screens/AccountOverviewScreen.d.ts.map +1 -1
  155. package/lib/typescript/ui/screens/AccountSettingsScreen.d.ts +1 -4
  156. package/lib/typescript/ui/screens/AccountSettingsScreen.d.ts.map +1 -1
  157. package/lib/typescript/ui/screens/AccountSwitcherScreen.d.ts.map +1 -1
  158. package/lib/typescript/ui/screens/AppInfoScreen.d.ts.map +1 -1
  159. package/lib/typescript/ui/screens/BillingManagementScreen.d.ts +5 -0
  160. package/lib/typescript/ui/screens/BillingManagementScreen.d.ts.map +1 -0
  161. package/lib/typescript/ui/screens/FileManagementScreen.d.ts +8 -0
  162. package/lib/typescript/ui/screens/FileManagementScreen.d.ts.map +1 -0
  163. package/lib/typescript/ui/screens/PremiumSubscriptionScreen.d.ts +5 -0
  164. package/lib/typescript/ui/screens/PremiumSubscriptionScreen.d.ts.map +1 -0
  165. package/lib/typescript/ui/screens/ProfileScreen.d.ts.map +1 -1
  166. package/lib/typescript/ui/screens/SessionManagementScreen.d.ts.map +1 -1
  167. package/lib/typescript/utils/polyfills.d.ts +6 -0
  168. package/lib/typescript/utils/polyfills.d.ts.map +1 -0
  169. package/package.json +11 -3
  170. package/src/__tests__/polyfills.test.ts +30 -0
  171. package/src/__tests__/setup.ts +43 -0
  172. package/src/__tests__/ui/screens/AccountSettingsScreen.test.tsx +8 -8
  173. package/src/assets/icons/OxyServices.tsx +67 -0
  174. package/src/assets/icons/logo_OxyServices.svg +1 -0
  175. package/src/core/index.ts +127 -19
  176. package/src/index.ts +3 -0
  177. package/src/lib/sonner.ts +10 -1
  178. package/src/models/interfaces.ts +1 -2
  179. package/src/node/index.ts +3 -0
  180. package/src/ui/components/GroupedItem.tsx +118 -0
  181. package/src/ui/components/GroupedSection.tsx +45 -0
  182. package/src/ui/components/OxyProvider.tsx +95 -120
  183. package/src/ui/components/ProfileCard.tsx +129 -0
  184. package/src/ui/components/QuickActions.tsx +90 -0
  185. package/src/ui/components/Section.tsx +37 -0
  186. package/src/ui/components/SectionTitle.tsx +31 -0
  187. package/src/ui/components/bottomSheet/index.tsx +13 -11
  188. package/src/ui/components/index.ts +15 -0
  189. package/src/ui/navigation/OxyRouter.tsx +20 -3
  190. package/src/ui/navigation/types.ts +10 -1
  191. package/src/ui/screens/AccountCenterScreen.tsx +188 -159
  192. package/src/ui/screens/AccountManagementDemo.tsx +297 -0
  193. package/src/ui/screens/AccountOverviewScreen.tsx +474 -310
  194. package/src/ui/screens/AccountSettingsScreen.tsx +648 -463
  195. package/src/ui/screens/AccountSwitcherScreen.tsx +385 -449
  196. package/src/ui/screens/AppInfoScreen.tsx +571 -140
  197. package/src/ui/screens/BillingManagementScreen.tsx +589 -0
  198. package/src/ui/screens/FileManagementScreen.tsx +2513 -0
  199. package/src/ui/screens/PremiumSubscriptionScreen.tsx +1628 -0
  200. package/src/ui/screens/ProfileScreen.tsx +101 -7
  201. package/src/ui/screens/SessionManagementScreen.tsx +1 -0
  202. package/src/ui/screens/SignInScreen.tsx +1 -1
  203. package/src/ui/screens/SignUpScreen.tsx +1 -1
  204. package/src/utils/polyfills.ts +34 -0
  205. package/lib/commonjs/lib/sonner.web.js +0 -17
  206. package/lib/commonjs/lib/sonner.web.js.map +0 -1
  207. package/lib/module/lib/sonner.web.js +0 -4
  208. package/lib/module/lib/sonner.web.js.map +0 -1
  209. package/lib/typescript/__tests__/ui/screens/AccountSettingsScreen.test.d.ts +0 -2
  210. package/lib/typescript/__tests__/ui/screens/AccountSettingsScreen.test.d.ts.map +0 -1
  211. package/lib/typescript/lib/sonner.web.d.ts +0 -2
  212. package/lib/typescript/lib/sonner.web.d.ts.map +0 -1
  213. package/src/lib/sonner.web.ts +0 -1
@@ -8,173 +8,388 @@ var _react = _interopRequireWildcard(require("react"));
8
8
  var _reactNative = require("react-native");
9
9
  var _OxyContext = require("../context/OxyContext");
10
10
  var _Avatar = _interopRequireDefault(require("../components/Avatar"));
11
+ var _OxyIcon = _interopRequireDefault(require("../components/icon/OxyIcon"));
12
+ var _vectorIcons = require("@expo/vector-icons");
11
13
  var _sonner = require("../../lib/sonner");
14
+ var _fonts = require("../styles/fonts");
12
15
  var _jsxRuntime = require("react/jsx-runtime");
13
16
  function _interopRequireDefault(e) { return e && e.__esModule ? e : { default: e }; }
14
17
  function _interopRequireWildcard(e, t) { if ("function" == typeof WeakMap) var r = new WeakMap(), n = new WeakMap(); return (_interopRequireWildcard = function (e, t) { if (!t && e && e.__esModule) return e; var o, i, f = { __proto__: null, default: e }; if (null === e || "object" != typeof e && "function" != typeof e) return f; if (o = t ? n : r) { if (o.has(e)) return o.get(e); o.set(e, f); } for (const t in e) "default" !== t && {}.hasOwnProperty.call(e, t) && ((i = (o = Object.defineProperty) && Object.getOwnPropertyDescriptor(e, t)) && (i.get || i.set) ? o(f, t, i) : f[t] = e[t]); return f; })(e, t); }
15
18
  const AccountSettingsScreen = ({
16
- goBack,
19
+ onClose,
17
20
  theme,
18
- activeTab = 'profile'
21
+ goBack,
22
+ navigate
19
23
  }) => {
20
24
  const {
21
25
  user,
22
26
  oxyServices,
23
27
  isLoading: authLoading
24
28
  } = (0, _OxyContext.useOxy)();
25
- const [currentTab, setCurrentTab] = (0, _react.useState)(activeTab);
26
29
  const [isLoading, setIsLoading] = (0, _react.useState)(false);
27
- const [errorMessage, setErrorMessage] = (0, _react.useState)('');
28
- const [successMessage, setSuccessMessage] = (0, _react.useState)('');
30
+ const [isSaving, setIsSaving] = (0, _react.useState)(false);
31
+
32
+ // Animation refs
33
+ const saveButtonScale = (0, _react.useRef)(new _reactNative.Animated.Value(1)).current;
29
34
 
30
- // Profile form state
35
+ // Form state
36
+ const [displayName, setDisplayName] = (0, _react.useState)('');
31
37
  const [username, setUsername] = (0, _react.useState)('');
32
38
  const [email, setEmail] = (0, _react.useState)('');
33
39
  const [bio, setBio] = (0, _react.useState)('');
40
+ const [location, setLocation] = (0, _react.useState)('');
41
+ const [website, setWebsite] = (0, _react.useState)('');
34
42
  const [avatarUrl, setAvatarUrl] = (0, _react.useState)('');
35
43
 
36
- // Password form state
37
- const [currentPassword, setCurrentPassword] = (0, _react.useState)('');
38
- const [newPassword, setNewPassword] = (0, _react.useState)('');
39
- const [confirmPassword, setConfirmPassword] = (0, _react.useState)('');
44
+ // Editing states
45
+ const [editingField, setEditingField] = (0, _react.useState)(null);
40
46
 
41
- // Notification preferences
42
- const [emailNotifications, setEmailNotifications] = (0, _react.useState)(true);
43
- const [pushNotifications, setPushNotifications] = (0, _react.useState)(true);
44
-
45
- // Theme and styling
47
+ // Temporary input states for inline editing
48
+ const [tempDisplayName, setTempDisplayName] = (0, _react.useState)('');
49
+ const [tempUsername, setTempUsername] = (0, _react.useState)('');
50
+ const [tempEmail, setTempEmail] = (0, _react.useState)('');
51
+ const [tempBio, setTempBio] = (0, _react.useState)('');
52
+ const [tempLocation, setTempLocation] = (0, _react.useState)('');
53
+ const [tempWebsite, setTempWebsite] = (0, _react.useState)('');
46
54
  const isDarkTheme = theme === 'dark';
47
- const textColor = isDarkTheme ? '#FFFFFF' : '#000000';
48
- const backgroundColor = isDarkTheme ? '#121212' : '#FFFFFF';
49
- const secondaryBackgroundColor = isDarkTheme ? '#222222' : '#F5F5F5';
50
- const inputBackgroundColor = isDarkTheme ? '#333333' : '#F5F5F5';
51
- const borderColor = isDarkTheme ? '#444444' : '#E0E0E0';
52
- const primaryColor = '#0066CC';
53
- const placeholderColor = isDarkTheme ? '#AAAAAA' : '#999999';
55
+ const backgroundColor = isDarkTheme ? '#121212' : '#f2f2f2';
56
+ const primaryColor = '#007AFF';
57
+
58
+ // Animation functions
59
+ const animateSaveButton = toValue => {
60
+ _reactNative.Animated.spring(saveButtonScale, {
61
+ toValue,
62
+ useNativeDriver: true,
63
+ tension: 150,
64
+ friction: 8
65
+ }).start();
66
+ };
54
67
 
55
68
  // Load user data
56
69
  (0, _react.useEffect)(() => {
57
70
  if (user) {
71
+ const userDisplayName = typeof user.name === 'string' ? user.name : user.name?.full || user.name?.first || '';
72
+ setDisplayName(userDisplayName);
58
73
  setUsername(user.username || '');
59
74
  setEmail(user.email || '');
60
75
  setBio(user.bio || '');
76
+ setLocation(user.location || '');
77
+ setWebsite(user.website || '');
61
78
  setAvatarUrl(user.avatar?.url || '');
62
79
  }
63
80
  }, [user]);
64
- const validateEmail = email => {
65
- const emailRegex = /^[^\s@]+@[^\s@]+\.[^\s@]+$/;
66
- return emailRegex.test(email);
67
- };
68
- const handleSaveProfile = async () => {
69
- // Validate inputs
70
- if (!username) {
71
- setErrorMessage('Username is required');
72
- return;
73
- }
74
- if (email && !validateEmail(email)) {
75
- setErrorMessage('Please enter a valid email address');
76
- return;
77
- }
81
+ const handleSave = async () => {
82
+ if (!user) return;
78
83
  try {
79
- setIsLoading(true);
80
- setErrorMessage('');
81
- setSuccessMessage('');
84
+ setIsSaving(true);
85
+ animateSaveButton(0.95); // Scale down slightly for animation
82
86
 
83
- // Prepare updates object
84
87
  const updates = {
85
88
  username,
86
- bio
89
+ email,
90
+ bio,
91
+ location,
92
+ website
87
93
  };
88
- if (email) {
89
- updates.email = email;
94
+
95
+ // Handle name field
96
+ if (displayName) {
97
+ updates.name = displayName;
90
98
  }
91
99
 
92
- // Only include avatar if it's been changed
93
- if (avatarUrl !== user?.avatar?.url) {
100
+ // Handle avatar
101
+ if (avatarUrl !== user.avatar?.url) {
94
102
  updates.avatar = {
95
103
  url: avatarUrl
96
104
  };
97
105
  }
98
-
99
- // Call API to update user
100
- await oxyServices.updateUser(user.id, updates);
106
+ await oxyServices.updateProfile(updates);
101
107
  _sonner.toast.success('Profile updated successfully');
102
- } catch (error) {
103
- _sonner.toast.error(error.message || 'Failed to update profile');
104
- } finally {
105
- setIsLoading(false);
106
- }
107
- };
108
- const handleChangePassword = async () => {
109
- // Validate inputs
110
- if (!currentPassword || !newPassword || !confirmPassword) {
111
- _sonner.toast.error('Please fill in all password fields');
112
- return;
113
- }
114
- if (newPassword !== confirmPassword) {
115
- _sonner.toast.error('New passwords do not match');
116
- return;
117
- }
118
- if (newPassword.length < 8) {
119
- _sonner.toast.error('Password must be at least 8 characters long');
120
- return;
121
- }
122
- try {
123
- setIsLoading(true);
124
- setErrorMessage('');
125
- setSuccessMessage('');
126
-
127
- // Call API to update password
128
- await oxyServices.updateUser(user.id, {
129
- currentPassword,
130
- password: newPassword
131
- });
108
+ animateSaveButton(1); // Scale back to normal
132
109
 
133
- // Clear form fields after successful update
134
- setCurrentPassword('');
135
- setNewPassword('');
136
- setConfirmPassword('');
137
- _sonner.toast.success('Password updated successfully');
138
- } catch (error) {
139
- _sonner.toast.error(error.message || 'Failed to update password');
140
- } finally {
141
- setIsLoading(false);
142
- }
143
- };
144
- const handleSaveNotifications = async () => {
145
- try {
146
- setIsLoading(true);
147
- setErrorMessage('');
148
- setSuccessMessage('');
149
-
150
- // Call API to update notification preferences
151
- await oxyServices.updateUser(user.id, {
152
- notificationPreferences: {
153
- email: emailNotifications,
154
- push: pushNotifications
155
- }
156
- });
157
- _sonner.toast.success('Notification preferences updated successfully');
110
+ if (onClose) {
111
+ onClose();
112
+ } else if (goBack) {
113
+ goBack();
114
+ }
158
115
  } catch (error) {
159
- _sonner.toast.error(error.message || 'Failed to update notification preferences');
116
+ _sonner.toast.error(error.message || 'Failed to update profile');
117
+ animateSaveButton(1); // Scale back to normal on error
160
118
  } finally {
161
- setIsLoading(false);
119
+ setIsSaving(false);
162
120
  }
163
121
  };
164
122
  const handleAvatarUpdate = () => {
165
- // In a real app, this would open an image picker
166
- // For now, we'll use a mock URL to demonstrate the concept
167
- _reactNative.Alert.alert('Update Avatar', 'This would open an image picker in a real app. For now, we\'ll use a mock URL.', [{
123
+ _reactNative.Alert.alert('Update Avatar', 'Choose how you want to update your profile picture', [{
168
124
  text: 'Cancel',
169
125
  style: 'cancel'
170
126
  }, {
171
127
  text: 'Use Mock URL',
172
128
  onPress: () => {
173
- const mockUrl = `https://ui-avatars.com/api/?name=${username}&background=random`;
129
+ const mockUrl = `https://ui-avatars.com/api/?name=${displayName || username}&background=random`;
174
130
  setAvatarUrl(mockUrl);
175
131
  }
132
+ }, {
133
+ text: 'Remove Avatar',
134
+ onPress: () => setAvatarUrl(''),
135
+ style: 'destructive'
176
136
  }]);
177
137
  };
138
+ const startEditing = (type, currentValue) => {
139
+ switch (type) {
140
+ case 'displayName':
141
+ setTempDisplayName(currentValue);
142
+ break;
143
+ case 'username':
144
+ setTempUsername(currentValue);
145
+ break;
146
+ case 'email':
147
+ setTempEmail(currentValue);
148
+ break;
149
+ case 'bio':
150
+ setTempBio(currentValue);
151
+ break;
152
+ case 'location':
153
+ setTempLocation(currentValue);
154
+ break;
155
+ case 'website':
156
+ setTempWebsite(currentValue);
157
+ break;
158
+ }
159
+ setEditingField(type);
160
+ };
161
+ const saveField = type => {
162
+ animateSaveButton(0.95); // Scale down slightly for animation
163
+
164
+ switch (type) {
165
+ case 'displayName':
166
+ setDisplayName(tempDisplayName);
167
+ break;
168
+ case 'username':
169
+ setUsername(tempUsername);
170
+ break;
171
+ case 'email':
172
+ setEmail(tempEmail);
173
+ break;
174
+ case 'bio':
175
+ setBio(tempBio);
176
+ break;
177
+ case 'location':
178
+ setLocation(tempLocation);
179
+ break;
180
+ case 'website':
181
+ setWebsite(tempWebsite);
182
+ break;
183
+ }
184
+
185
+ // Brief delay for animation, then reset and close editing
186
+ setTimeout(() => {
187
+ animateSaveButton(1);
188
+ setEditingField(null);
189
+ }, 150);
190
+ };
191
+ const cancelEditing = () => {
192
+ setEditingField(null);
193
+ };
194
+ const getFieldLabel = type => {
195
+ const labels = {
196
+ displayName: 'Display Name',
197
+ username: 'Username',
198
+ email: 'Email',
199
+ bio: 'Bio',
200
+ location: 'Location',
201
+ website: 'Website'
202
+ };
203
+ return labels[type] || 'Field';
204
+ };
205
+ const getFieldIcon = type => {
206
+ const icons = {
207
+ displayName: {
208
+ name: 'person',
209
+ color: '#007AFF'
210
+ },
211
+ username: {
212
+ name: 'at',
213
+ color: '#5856D6'
214
+ },
215
+ email: {
216
+ name: 'mail',
217
+ color: '#FF9500'
218
+ },
219
+ bio: {
220
+ name: 'document-text',
221
+ color: '#34C759'
222
+ },
223
+ location: {
224
+ name: 'location',
225
+ color: '#FF3B30'
226
+ },
227
+ website: {
228
+ name: 'link',
229
+ color: '#32D74B'
230
+ }
231
+ };
232
+ return icons[type] || {
233
+ name: 'person',
234
+ color: '#007AFF'
235
+ };
236
+ };
237
+ const renderEditingField = type => {
238
+ const fieldConfig = {
239
+ displayName: {
240
+ label: 'Display Name',
241
+ value: displayName,
242
+ placeholder: 'Enter your display name',
243
+ icon: 'person',
244
+ color: '#007AFF',
245
+ multiline: false,
246
+ keyboardType: 'default'
247
+ },
248
+ username: {
249
+ label: 'Username',
250
+ value: username,
251
+ placeholder: 'Choose a username',
252
+ icon: 'at',
253
+ color: '#5856D6',
254
+ multiline: false,
255
+ keyboardType: 'default'
256
+ },
257
+ email: {
258
+ label: 'Email',
259
+ value: email,
260
+ placeholder: 'Enter your email address',
261
+ icon: 'mail',
262
+ color: '#FF9500',
263
+ multiline: false,
264
+ keyboardType: 'email-address'
265
+ },
266
+ bio: {
267
+ label: 'Bio',
268
+ value: bio,
269
+ placeholder: 'Tell people about yourself...',
270
+ icon: 'document-text',
271
+ color: '#34C759',
272
+ multiline: true,
273
+ keyboardType: 'default'
274
+ },
275
+ location: {
276
+ label: 'Location',
277
+ value: location,
278
+ placeholder: 'Enter your location',
279
+ icon: 'location',
280
+ color: '#FF3B30',
281
+ multiline: false,
282
+ keyboardType: 'default'
283
+ },
284
+ website: {
285
+ label: 'Website',
286
+ value: website,
287
+ placeholder: 'Enter your website URL',
288
+ icon: 'link',
289
+ color: '#32D74B',
290
+ multiline: false,
291
+ keyboardType: 'url'
292
+ }
293
+ };
294
+ const config = fieldConfig[type];
295
+ if (!config) return null;
296
+ const tempValue = (() => {
297
+ switch (type) {
298
+ case 'displayName':
299
+ return tempDisplayName;
300
+ case 'username':
301
+ return tempUsername;
302
+ case 'email':
303
+ return tempEmail;
304
+ case 'bio':
305
+ return tempBio;
306
+ case 'location':
307
+ return tempLocation;
308
+ case 'website':
309
+ return tempWebsite;
310
+ default:
311
+ return '';
312
+ }
313
+ })();
314
+ const setTempValue = text => {
315
+ switch (type) {
316
+ case 'displayName':
317
+ setTempDisplayName(text);
318
+ break;
319
+ case 'username':
320
+ setTempUsername(text);
321
+ break;
322
+ case 'email':
323
+ setTempEmail(text);
324
+ break;
325
+ case 'bio':
326
+ setTempBio(text);
327
+ break;
328
+ case 'location':
329
+ setTempLocation(text);
330
+ break;
331
+ case 'website':
332
+ setTempWebsite(text);
333
+ break;
334
+ }
335
+ };
336
+ return /*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.View, {
337
+ style: styles.editingFieldContainer,
338
+ children: /*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.View, {
339
+ style: styles.editingFieldContent,
340
+ children: /*#__PURE__*/(0, _jsxRuntime.jsxs)(_reactNative.View, {
341
+ style: styles.newValueSection,
342
+ children: [/*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.Text, {
343
+ style: styles.editingFieldLabel,
344
+ children: `Enter ${config.label.toLowerCase()}:`
345
+ }), /*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.TextInput, {
346
+ style: [config.multiline ? styles.editingFieldTextArea : styles.editingFieldInput, {
347
+ backgroundColor: isDarkTheme ? '#333' : '#fff',
348
+ color: isDarkTheme ? '#fff' : '#000',
349
+ borderColor: primaryColor
350
+ }],
351
+ value: tempValue,
352
+ onChangeText: setTempValue,
353
+ placeholder: config.placeholder,
354
+ placeholderTextColor: isDarkTheme ? '#aaa' : '#999',
355
+ multiline: config.multiline,
356
+ numberOfLines: config.multiline ? 6 : 1,
357
+ keyboardType: config.keyboardType,
358
+ autoFocus: true,
359
+ selectionColor: primaryColor
360
+ })]
361
+ })
362
+ })
363
+ });
364
+ };
365
+ const renderField = (type, label, value, placeholder, icon, iconColor, multiline = false, keyboardType = 'default', isFirst = false, isLast = false) => {
366
+ const itemStyles = [styles.settingItem, isFirst && styles.firstSettingItem, isLast && styles.lastSettingItem];
367
+ return /*#__PURE__*/(0, _jsxRuntime.jsxs)(_reactNative.TouchableOpacity, {
368
+ style: itemStyles,
369
+ onPress: () => startEditing(type, value),
370
+ children: [/*#__PURE__*/(0, _jsxRuntime.jsxs)(_reactNative.View, {
371
+ style: styles.settingInfo,
372
+ children: [/*#__PURE__*/(0, _jsxRuntime.jsx)(_OxyIcon.default, {
373
+ name: icon,
374
+ size: 20,
375
+ color: iconColor,
376
+ style: styles.settingIcon
377
+ }), /*#__PURE__*/(0, _jsxRuntime.jsxs)(_reactNative.View, {
378
+ children: [/*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.Text, {
379
+ style: styles.settingLabel,
380
+ children: label
381
+ }), /*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.Text, {
382
+ style: styles.settingDescription,
383
+ children: value || placeholder
384
+ })]
385
+ })]
386
+ }), /*#__PURE__*/(0, _jsxRuntime.jsx)(_OxyIcon.default, {
387
+ name: "chevron-forward",
388
+ size: 16,
389
+ color: "#ccc"
390
+ })]
391
+ });
392
+ };
178
393
  if (authLoading || !user) {
179
394
  return /*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.View, {
180
395
  style: [styles.container, {
@@ -187,452 +402,434 @@ const AccountSettingsScreen = ({
187
402
  })
188
403
  });
189
404
  }
190
- const renderProfileTab = () => /*#__PURE__*/(0, _jsxRuntime.jsxs)(_reactNative.View, {
191
- style: styles.tabContent,
192
- children: [/*#__PURE__*/(0, _jsxRuntime.jsxs)(_reactNative.View, {
193
- style: styles.avatarSection,
194
- children: [/*#__PURE__*/(0, _jsxRuntime.jsx)(_Avatar.default, {
195
- uri: avatarUrl,
196
- name: username,
197
- size: 100,
198
- theme: theme
199
- }), /*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.TouchableOpacity, {
200
- style: [styles.changeAvatarButton, {
201
- backgroundColor: primaryColor
202
- }],
203
- onPress: handleAvatarUpdate,
204
- children: /*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.Text, {
205
- style: styles.changeAvatarText,
206
- children: "Change Avatar"
207
- })
208
- })]
209
- }), /*#__PURE__*/(0, _jsxRuntime.jsxs)(_reactNative.View, {
210
- style: styles.inputContainer,
211
- children: [/*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.Text, {
212
- style: [styles.label, {
213
- color: textColor
214
- }],
215
- children: "Username"
216
- }), /*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.TextInput, {
217
- style: [styles.input, {
218
- backgroundColor: inputBackgroundColor,
219
- borderColor,
220
- color: textColor
221
- }],
222
- placeholder: "Enter your username",
223
- placeholderTextColor: placeholderColor,
224
- value: username,
225
- onChangeText: setUsername,
226
- testID: "username-input"
227
- })]
228
- }), /*#__PURE__*/(0, _jsxRuntime.jsxs)(_reactNative.View, {
229
- style: styles.inputContainer,
230
- children: [/*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.Text, {
231
- style: [styles.label, {
232
- color: textColor
233
- }],
234
- children: "Email"
235
- }), /*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.TextInput, {
236
- style: [styles.input, {
237
- backgroundColor: inputBackgroundColor,
238
- borderColor,
239
- color: textColor
240
- }],
241
- placeholder: "Enter your email",
242
- placeholderTextColor: placeholderColor,
243
- value: email,
244
- onChangeText: setEmail,
245
- keyboardType: "email-address",
246
- testID: "email-input"
247
- })]
248
- }), /*#__PURE__*/(0, _jsxRuntime.jsxs)(_reactNative.View, {
249
- style: styles.inputContainer,
250
- children: [/*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.Text, {
251
- style: [styles.label, {
252
- color: textColor
253
- }],
254
- children: "Bio"
255
- }), /*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.TextInput, {
256
- style: [styles.textArea, {
257
- backgroundColor: inputBackgroundColor,
258
- borderColor,
259
- color: textColor
260
- }],
261
- placeholder: "Tell us about yourself",
262
- placeholderTextColor: placeholderColor,
263
- value: bio,
264
- onChangeText: setBio,
265
- multiline: true,
266
- numberOfLines: 4,
267
- testID: "bio-input"
268
- })]
269
- }), /*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.TouchableOpacity, {
270
- style: [styles.saveButton, {
271
- backgroundColor: primaryColor,
272
- opacity: isLoading ? 0.7 : 1
273
- }],
274
- onPress: handleSaveProfile,
275
- disabled: isLoading,
276
- testID: "save-profile-button",
277
- children: isLoading ? /*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.ActivityIndicator, {
278
- color: "#FFFFFF",
279
- size: "small"
280
- }) : /*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.Text, {
281
- style: styles.saveButtonText,
282
- children: "Save Profile"
283
- })
284
- })]
285
- });
286
- const renderPasswordTab = () => /*#__PURE__*/(0, _jsxRuntime.jsxs)(_reactNative.View, {
287
- style: styles.tabContent,
288
- children: [/*#__PURE__*/(0, _jsxRuntime.jsxs)(_reactNative.View, {
289
- style: styles.inputContainer,
290
- children: [/*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.Text, {
291
- style: [styles.label, {
292
- color: textColor
293
- }],
294
- children: "Current Password"
295
- }), /*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.TextInput, {
296
- style: [styles.input, {
297
- backgroundColor: inputBackgroundColor,
298
- borderColor,
299
- color: textColor
300
- }],
301
- placeholder: "Enter your current password",
302
- placeholderTextColor: placeholderColor,
303
- value: currentPassword,
304
- onChangeText: setCurrentPassword,
305
- secureTextEntry: true,
306
- testID: "current-password-input"
307
- })]
308
- }), /*#__PURE__*/(0, _jsxRuntime.jsxs)(_reactNative.View, {
309
- style: styles.inputContainer,
310
- children: [/*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.Text, {
311
- style: [styles.label, {
312
- color: textColor
313
- }],
314
- children: "New Password"
315
- }), /*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.TextInput, {
316
- style: [styles.input, {
317
- backgroundColor: inputBackgroundColor,
318
- borderColor,
319
- color: textColor
320
- }],
321
- placeholder: "Enter your new password",
322
- placeholderTextColor: placeholderColor,
323
- value: newPassword,
324
- onChangeText: setNewPassword,
325
- secureTextEntry: true,
326
- testID: "new-password-input"
327
- }), /*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.Text, {
328
- style: [styles.passwordHint, {
329
- color: isDarkTheme ? '#AAAAAA' : '#666666'
330
- }],
331
- children: "Password must be at least 8 characters long"
332
- })]
333
- }), /*#__PURE__*/(0, _jsxRuntime.jsxs)(_reactNative.View, {
334
- style: styles.inputContainer,
335
- children: [/*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.Text, {
336
- style: [styles.label, {
337
- color: textColor
338
- }],
339
- children: "Confirm New Password"
340
- }), /*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.TextInput, {
341
- style: [styles.input, {
342
- backgroundColor: inputBackgroundColor,
343
- borderColor,
344
- color: textColor
345
- }],
346
- placeholder: "Confirm your new password",
347
- placeholderTextColor: placeholderColor,
348
- value: confirmPassword,
349
- onChangeText: setConfirmPassword,
350
- secureTextEntry: true,
351
- testID: "confirm-password-input"
352
- })]
353
- }), /*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.TouchableOpacity, {
354
- style: [styles.saveButton, {
355
- backgroundColor: primaryColor,
356
- opacity: isLoading ? 0.7 : 1
357
- }],
358
- onPress: handleChangePassword,
359
- disabled: isLoading,
360
- testID: "change-password-button",
361
- children: isLoading ? /*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.ActivityIndicator, {
362
- color: "#FFFFFF",
363
- size: "small"
364
- }) : /*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.Text, {
365
- style: styles.saveButtonText,
366
- children: "Change Password"
367
- })
368
- })]
369
- });
370
- const renderNotificationsTab = () => /*#__PURE__*/(0, _jsxRuntime.jsxs)(_reactNative.View, {
371
- style: styles.tabContent,
372
- children: [/*#__PURE__*/(0, _jsxRuntime.jsxs)(_reactNative.View, {
373
- style: styles.settingRow,
374
- children: [/*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.Text, {
375
- style: [styles.settingLabel, {
376
- color: textColor
377
- }],
378
- children: "Email Notifications"
379
- }), /*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.Switch, {
380
- value: emailNotifications,
381
- onValueChange: setEmailNotifications,
382
- trackColor: {
383
- false: '#767577',
384
- true: primaryColor
385
- },
386
- thumbColor: "#f4f3f4",
387
- testID: "email-notifications-switch"
388
- })]
389
- }), /*#__PURE__*/(0, _jsxRuntime.jsxs)(_reactNative.View, {
390
- style: styles.settingRow,
391
- children: [/*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.Text, {
392
- style: [styles.settingLabel, {
393
- color: textColor
394
- }],
395
- children: "Push Notifications"
396
- }), /*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.Switch, {
397
- value: pushNotifications,
398
- onValueChange: setPushNotifications,
399
- trackColor: {
400
- false: '#767577',
401
- true: primaryColor
402
- },
403
- thumbColor: "#f4f3f4",
404
- testID: "push-notifications-switch"
405
- })]
406
- }), /*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.TouchableOpacity, {
407
- style: [styles.saveButton, {
408
- backgroundColor: primaryColor,
409
- opacity: isLoading ? 0.7 : 1
410
- }],
411
- onPress: handleSaveNotifications,
412
- disabled: isLoading,
413
- testID: "save-notifications-button",
414
- children: isLoading ? /*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.ActivityIndicator, {
415
- color: "#FFFFFF",
416
- size: "small"
417
- }) : /*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.Text, {
418
- style: styles.saveButtonText,
419
- children: "Save Preferences"
420
- })
421
- })]
422
- });
423
- return /*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.View, {
405
+ return /*#__PURE__*/(0, _jsxRuntime.jsxs)(_reactNative.View, {
424
406
  style: [styles.container, {
425
407
  backgroundColor
426
408
  }],
427
- children: /*#__PURE__*/(0, _jsxRuntime.jsxs)(_reactNative.ScrollView, {
428
- style: styles.scrollView,
429
- contentContainerStyle: styles.scrollContainer,
430
- children: [/*#__PURE__*/(0, _jsxRuntime.jsxs)(_reactNative.View, {
431
- style: styles.header,
432
- children: [/*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.TouchableOpacity, {
433
- style: styles.backButton,
434
- onPress: goBack,
435
- children: /*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.Text, {
436
- style: [styles.backButtonText, {
437
- color: primaryColor
438
- }],
439
- children: "Back"
440
- })
441
- }), /*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.Text, {
442
- style: [styles.title, {
443
- color: textColor
444
- }],
445
- children: "Account Settings"
409
+ children: [/*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.View, {
410
+ style: styles.header,
411
+ children: editingField ? /*#__PURE__*/(0, _jsxRuntime.jsxs)(_reactNative.View, {
412
+ style: styles.editingHeader,
413
+ children: [/*#__PURE__*/(0, _jsxRuntime.jsxs)(_reactNative.View, {
414
+ style: styles.editingHeaderTop,
415
+ children: [/*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.TouchableOpacity, {
416
+ style: styles.cancelButton,
417
+ onPress: cancelEditing,
418
+ children: /*#__PURE__*/(0, _jsxRuntime.jsx)(_vectorIcons.Ionicons, {
419
+ name: "close",
420
+ size: 24,
421
+ color: "#666"
422
+ })
423
+ }), /*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.Animated.View, {
424
+ style: {
425
+ transform: [{
426
+ scale: saveButtonScale
427
+ }]
428
+ },
429
+ children: /*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.TouchableOpacity, {
430
+ style: [styles.saveHeaderButton, {
431
+ opacity: isSaving ? 0.7 : 1,
432
+ backgroundColor: editingField ? getFieldIcon(editingField).color : '#007AFF'
433
+ }],
434
+ onPress: () => saveField(editingField),
435
+ disabled: isSaving,
436
+ children: isSaving ? /*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.ActivityIndicator, {
437
+ size: "small",
438
+ color: "#fff"
439
+ }) : /*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.Text, {
440
+ style: styles.saveButtonText,
441
+ children: "Save"
442
+ })
443
+ })
444
+ })]
446
445
  }), /*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.View, {
447
- style: styles.backButtonPlaceholder
446
+ style: styles.editingHeaderBottom,
447
+ children: /*#__PURE__*/(0, _jsxRuntime.jsxs)(_reactNative.View, {
448
+ style: styles.headerTitleWithIcon,
449
+ children: [/*#__PURE__*/(0, _jsxRuntime.jsx)(_OxyIcon.default, {
450
+ name: getFieldIcon(editingField).name,
451
+ size: 50,
452
+ color: getFieldIcon(editingField).color,
453
+ style: styles.headerIcon
454
+ }), /*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.Text, {
455
+ style: styles.headerTitleLarge,
456
+ children: getFieldLabel(editingField)
457
+ })]
458
+ })
448
459
  })]
449
- }), /*#__PURE__*/(0, _jsxRuntime.jsxs)(_reactNative.View, {
450
- style: [styles.tabsContainer, {
451
- borderColor
452
- }],
460
+ }) : /*#__PURE__*/(0, _jsxRuntime.jsxs)(_reactNative.View, {
461
+ style: styles.normalHeader,
453
462
  children: [/*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.TouchableOpacity, {
454
- style: [styles.tabButton, currentTab === 'profile' && [styles.activeTabButton, {
455
- borderColor: primaryColor
456
- }]],
457
- onPress: () => setCurrentTab('profile'),
458
- children: /*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.Text, {
459
- style: [styles.tabButtonText, {
460
- color: currentTab === 'profile' ? primaryColor : textColor
461
- }],
462
- children: "Profile"
463
- })
464
- }), /*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.TouchableOpacity, {
465
- style: [styles.tabButton, currentTab === 'password' && [styles.activeTabButton, {
466
- borderColor: primaryColor
467
- }]],
468
- onPress: () => setCurrentTab('password'),
469
- children: /*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.Text, {
470
- style: [styles.tabButtonText, {
471
- color: currentTab === 'password' ? primaryColor : textColor
472
- }],
473
- children: "Password"
463
+ style: styles.cancelButton,
464
+ onPress: onClose || goBack,
465
+ children: /*#__PURE__*/(0, _jsxRuntime.jsx)(_vectorIcons.Ionicons, {
466
+ name: "close",
467
+ size: 24,
468
+ color: "#666"
474
469
  })
475
- }), /*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.TouchableOpacity, {
476
- style: [styles.tabButton, currentTab === 'notifications' && [styles.activeTabButton, {
477
- borderColor: primaryColor
478
- }]],
479
- onPress: () => setCurrentTab('notifications'),
480
- children: /*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.Text, {
481
- style: [styles.tabButtonText, {
482
- color: currentTab === 'notifications' ? primaryColor : textColor
470
+ }), /*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.Text, {
471
+ style: styles.headerTitle,
472
+ children: "Account Settings"
473
+ }), /*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.Animated.View, {
474
+ style: {
475
+ transform: [{
476
+ scale: saveButtonScale
477
+ }]
478
+ },
479
+ children: /*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.TouchableOpacity, {
480
+ style: [styles.saveIconButton, {
481
+ opacity: isSaving ? 0.7 : 1
483
482
  }],
484
- children: "Notifications"
483
+ onPress: handleSave,
484
+ disabled: isSaving,
485
+ children: isSaving ? /*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.ActivityIndicator, {
486
+ size: "small",
487
+ color: primaryColor
488
+ }) : /*#__PURE__*/(0, _jsxRuntime.jsx)(_vectorIcons.Ionicons, {
489
+ name: "checkmark",
490
+ size: 24,
491
+ color: primaryColor
492
+ })
485
493
  })
486
494
  })]
487
- }), errorMessage ? /*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.View, {
488
- style: styles.errorContainer,
489
- children: /*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.Text, {
490
- style: styles.errorText,
491
- children: errorMessage
492
- })
493
- }) : null, successMessage ? /*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.View, {
494
- style: styles.successContainer,
495
- children: /*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.Text, {
496
- style: styles.successText,
497
- children: successMessage
498
- })
499
- }) : null, currentTab === 'profile' && renderProfileTab(), currentTab === 'password' && renderPasswordTab(), currentTab === 'notifications' && renderNotificationsTab()]
500
- })
495
+ })
496
+ }), /*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.ScrollView, {
497
+ style: editingField ? styles.contentEditing : styles.content,
498
+ children: editingField ?
499
+ /*#__PURE__*/
500
+ // Show only the editing interface when editing
501
+ (0, _jsxRuntime.jsx)(_reactNative.View, {
502
+ style: styles.editingOnlyContainer,
503
+ children: renderEditingField(editingField)
504
+ }) :
505
+ /*#__PURE__*/
506
+ // Show all settings when not editing
507
+ (0, _jsxRuntime.jsxs)(_jsxRuntime.Fragment, {
508
+ children: [/*#__PURE__*/(0, _jsxRuntime.jsxs)(_reactNative.View, {
509
+ style: styles.section,
510
+ children: [/*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.Text, {
511
+ style: styles.sectionTitle,
512
+ children: "Profile Picture"
513
+ }), /*#__PURE__*/(0, _jsxRuntime.jsxs)(_reactNative.TouchableOpacity, {
514
+ style: [styles.settingItem, styles.firstSettingItem, styles.lastSettingItem],
515
+ onPress: handleAvatarUpdate,
516
+ children: [/*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.View, {
517
+ style: styles.userIcon,
518
+ children: /*#__PURE__*/(0, _jsxRuntime.jsx)(_Avatar.default, {
519
+ uri: avatarUrl,
520
+ name: displayName || username,
521
+ size: 50,
522
+ theme: theme
523
+ })
524
+ }), /*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.View, {
525
+ style: styles.settingInfo,
526
+ children: /*#__PURE__*/(0, _jsxRuntime.jsxs)(_reactNative.View, {
527
+ children: [/*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.Text, {
528
+ style: styles.settingLabel,
529
+ children: "Profile Photo"
530
+ }), /*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.Text, {
531
+ style: styles.settingDescription,
532
+ children: avatarUrl ? 'Tap to change your profile picture' : 'Tap to add a profile picture'
533
+ })]
534
+ })
535
+ }), /*#__PURE__*/(0, _jsxRuntime.jsx)(_OxyIcon.default, {
536
+ name: "chevron-forward",
537
+ size: 16,
538
+ color: "#ccc"
539
+ })]
540
+ })]
541
+ }), /*#__PURE__*/(0, _jsxRuntime.jsxs)(_reactNative.View, {
542
+ style: styles.section,
543
+ children: [/*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.Text, {
544
+ style: styles.sectionTitle,
545
+ children: "Basic Information"
546
+ }), renderField('displayName', 'Display Name', displayName, 'Add your display name', 'person', '#007AFF', false, 'default', true, false), renderField('username', 'Username', username, 'Choose a username', 'at', '#5856D6', false, 'default', false, false), renderField('email', 'Email', email, 'Add your email address', 'mail', '#FF9500', false, 'email-address', false, true)]
547
+ }), /*#__PURE__*/(0, _jsxRuntime.jsxs)(_reactNative.View, {
548
+ style: styles.section,
549
+ children: [/*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.Text, {
550
+ style: styles.sectionTitle,
551
+ children: "About You"
552
+ }), renderField('bio', 'Bio', bio, 'Tell people about yourself', 'document-text', '#34C759', true, 'default', true, false), renderField('location', 'Location', location, 'Add your location', 'location', '#FF3B30', false, 'default', false, false), renderField('website', 'Website', website, 'Add your website', 'link', '#32D74B', false, 'url', false, true)]
553
+ }), /*#__PURE__*/(0, _jsxRuntime.jsxs)(_reactNative.View, {
554
+ style: styles.section,
555
+ children: [/*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.Text, {
556
+ style: styles.sectionTitle,
557
+ children: "Quick Actions"
558
+ }), /*#__PURE__*/(0, _jsxRuntime.jsxs)(_reactNative.TouchableOpacity, {
559
+ style: [styles.settingItem, styles.firstSettingItem],
560
+ onPress: () => _sonner.toast.info('Privacy settings coming soon!'),
561
+ children: [/*#__PURE__*/(0, _jsxRuntime.jsxs)(_reactNative.View, {
562
+ style: styles.settingInfo,
563
+ children: [/*#__PURE__*/(0, _jsxRuntime.jsx)(_OxyIcon.default, {
564
+ name: "shield-checkmark",
565
+ size: 20,
566
+ color: "#8E8E93",
567
+ style: styles.settingIcon
568
+ }), /*#__PURE__*/(0, _jsxRuntime.jsxs)(_reactNative.View, {
569
+ children: [/*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.Text, {
570
+ style: styles.settingLabel,
571
+ children: "Privacy Settings"
572
+ }), /*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.Text, {
573
+ style: styles.settingDescription,
574
+ children: "Control who can see your profile"
575
+ })]
576
+ })]
577
+ }), /*#__PURE__*/(0, _jsxRuntime.jsx)(_OxyIcon.default, {
578
+ name: "chevron-forward",
579
+ size: 16,
580
+ color: "#ccc"
581
+ })]
582
+ }), /*#__PURE__*/(0, _jsxRuntime.jsxs)(_reactNative.TouchableOpacity, {
583
+ style: [styles.settingItem, styles.lastSettingItem],
584
+ onPress: () => _sonner.toast.info('Account verification coming soon!'),
585
+ children: [/*#__PURE__*/(0, _jsxRuntime.jsxs)(_reactNative.View, {
586
+ style: styles.settingInfo,
587
+ children: [/*#__PURE__*/(0, _jsxRuntime.jsx)(_OxyIcon.default, {
588
+ name: "checkmark-circle",
589
+ size: 20,
590
+ color: "#30D158",
591
+ style: styles.settingIcon
592
+ }), /*#__PURE__*/(0, _jsxRuntime.jsxs)(_reactNative.View, {
593
+ children: [/*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.Text, {
594
+ style: styles.settingLabel,
595
+ children: "Verify Account"
596
+ }), /*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.Text, {
597
+ style: styles.settingDescription,
598
+ children: "Get a verified badge"
599
+ })]
600
+ })]
601
+ }), /*#__PURE__*/(0, _jsxRuntime.jsx)(_OxyIcon.default, {
602
+ name: "chevron-forward",
603
+ size: 16,
604
+ color: "#ccc"
605
+ })]
606
+ })]
607
+ })]
608
+ })
609
+ })]
501
610
  });
502
611
  };
503
612
  const styles = _reactNative.StyleSheet.create({
504
613
  container: {
505
- flex: 1
614
+ flex: 1,
615
+ backgroundColor: '#f2f2f2'
506
616
  },
507
- scrollView: {
508
- flex: 1
617
+ header: {
618
+ paddingHorizontal: 20,
619
+ paddingVertical: 10,
620
+ backgroundColor: '#fff',
621
+ borderBottomWidth: 1,
622
+ borderBottomColor: '#e0e0e0'
623
+ },
624
+ normalHeader: {
625
+ flexDirection: 'row',
626
+ justifyContent: 'space-between',
627
+ alignItems: 'center'
509
628
  },
510
- scrollContainer: {
511
- padding: 20
629
+ editingHeader: {
630
+ flexDirection: 'column'
512
631
  },
513
- header: {
632
+ editingHeaderTop: {
514
633
  flexDirection: 'row',
515
634
  justifyContent: 'space-between',
516
635
  alignItems: 'center',
517
- marginBottom: 24
636
+ marginBottom: 16
518
637
  },
519
- title: {
638
+ editingHeaderBottom: {
639
+ flexDirection: 'row',
640
+ alignItems: 'center',
641
+ justifyContent: 'flex-start'
642
+ },
643
+ headerTitle: {
520
644
  fontSize: 24,
521
- fontWeight: 'bold'
645
+ fontWeight: 'bold',
646
+ color: '#000',
647
+ fontFamily: _fonts.fontFamilies.phuduBold
522
648
  },
523
- backButton: {
524
- padding: 10
649
+ headerTitleWithIcon: {
650
+ flexDirection: 'column',
651
+ alignItems: 'flex-start',
652
+ flex: 1,
653
+ justifyContent: 'flex-start',
654
+ maxWidth: '90%'
525
655
  },
526
- backButtonText: {
527
- fontSize: 16,
528
- fontWeight: '600'
656
+ headerTitleLarge: {
657
+ fontSize: 48,
658
+ fontWeight: '800',
659
+ color: '#000',
660
+ fontFamily: _fonts.fontFamilies.phuduExtraBold,
661
+ textAlign: 'left'
529
662
  },
530
- backButtonPlaceholder: {
531
- width: 40
663
+ headerIcon: {
664
+ marginBottom: 2
532
665
  },
533
- tabsContainer: {
534
- flexDirection: 'row',
535
- marginBottom: 24,
536
- borderBottomWidth: 1
666
+ cancelButton: {
667
+ padding: 5
537
668
  },
538
- tabButton: {
539
- flex: 1,
669
+ saveHeaderButton: {
670
+ paddingHorizontal: 16,
671
+ paddingVertical: 8,
672
+ borderRadius: 20,
673
+ minWidth: 60,
540
674
  alignItems: 'center',
541
- paddingVertical: 12
675
+ justifyContent: 'center'
542
676
  },
543
- activeTabButton: {
544
- borderBottomWidth: 2
677
+ saveIconButton: {
678
+ padding: 5
545
679
  },
546
- tabButtonText: {
680
+ saveButtonText: {
681
+ color: '#fff',
547
682
  fontSize: 16,
548
- fontWeight: '500'
683
+ fontWeight: '600',
684
+ fontFamily: _fonts.fontFamilies.phuduSemiBold
549
685
  },
550
- tabContent: {
686
+ content: {
687
+ flex: 1,
688
+ padding: 16
689
+ },
690
+ contentEditing: {
691
+ flex: 1,
692
+ padding: 0
693
+ },
694
+ section: {
551
695
  marginBottom: 24
552
696
  },
553
- avatarSection: {
697
+ sectionTitle: {
698
+ fontSize: 16,
699
+ fontWeight: '600',
700
+ color: '#333',
701
+ marginBottom: 12,
702
+ fontFamily: _fonts.fontFamilies.phuduSemiBold
703
+ },
704
+ settingItem: {
705
+ backgroundColor: '#fff',
706
+ padding: 16,
707
+ flexDirection: 'row',
554
708
  alignItems: 'center',
555
- marginBottom: 24
709
+ justifyContent: 'space-between',
710
+ marginBottom: 2
556
711
  },
557
- changeAvatarButton: {
558
- marginTop: 12,
559
- paddingVertical: 8,
560
- paddingHorizontal: 16,
561
- borderRadius: 20
712
+ firstSettingItem: {
713
+ borderTopLeftRadius: 24,
714
+ borderTopRightRadius: 24
562
715
  },
563
- changeAvatarText: {
564
- color: '#FFFFFF',
565
- fontWeight: '600'
716
+ lastSettingItem: {
717
+ borderBottomLeftRadius: 24,
718
+ borderBottomRightRadius: 24,
719
+ marginBottom: 8
566
720
  },
567
- inputContainer: {
568
- marginBottom: 16
721
+ settingInfo: {
722
+ flexDirection: 'row',
723
+ alignItems: 'center',
724
+ flex: 1
569
725
  },
570
- label: {
726
+ settingIcon: {
727
+ marginRight: 12
728
+ },
729
+ settingLabel: {
571
730
  fontSize: 16,
572
- marginBottom: 8
731
+ fontWeight: '500',
732
+ color: '#333',
733
+ marginBottom: 2
573
734
  },
574
- input: {
575
- height: 50,
576
- borderRadius: 8,
577
- borderWidth: 1,
578
- paddingHorizontal: 12,
579
- fontSize: 16
735
+ settingDescription: {
736
+ fontSize: 14,
737
+ color: '#666'
580
738
  },
581
- textArea: {
582
- minHeight: 100,
739
+ userIcon: {
740
+ marginRight: 12
741
+ },
742
+ // Inline editing styles
743
+ editingContainer: {
744
+ flex: 1
745
+ },
746
+ editingActions: {
747
+ flexDirection: 'row',
748
+ alignItems: 'center'
749
+ },
750
+ editingButton: {
751
+ padding: 8
752
+ },
753
+ editingButtonText: {
754
+ fontSize: 16,
755
+ fontWeight: '500'
756
+ },
757
+ inlineInput: {
758
+ backgroundColor: '#f8f8f8',
759
+ borderWidth: 1,
760
+ borderColor: '#e0e0e0',
583
761
  borderRadius: 8,
762
+ padding: 12,
763
+ fontSize: 16,
764
+ minHeight: 44
765
+ },
766
+ inlineTextArea: {
767
+ backgroundColor: '#f8f8f8',
584
768
  borderWidth: 1,
585
- paddingHorizontal: 12,
586
- paddingTop: 12,
769
+ borderColor: '#e0e0e0',
770
+ borderRadius: 8,
771
+ padding: 12,
587
772
  fontSize: 16,
773
+ minHeight: 100,
588
774
  textAlignVertical: 'top'
589
775
  },
590
- passwordHint: {
591
- fontSize: 14,
592
- marginTop: 4
776
+ // Editing-only mode styles
777
+ editingOnlyContainer: {
778
+ flex: 1
593
779
  },
594
- saveButton: {
595
- height: 50,
596
- borderRadius: 25,
597
- alignItems: 'center',
598
- justifyContent: 'center',
599
- marginTop: 16
780
+ editingFieldContainer: {
781
+ backgroundColor: '#fff',
782
+ padding: 16,
783
+ flex: 1
600
784
  },
601
- saveButtonText: {
602
- color: '#FFFFFF',
603
- fontSize: 16,
604
- fontWeight: '600'
785
+ editingFieldHeader: {
786
+ marginBottom: 16
605
787
  },
606
- settingRow: {
788
+ editingFieldTitleContainer: {
607
789
  flexDirection: 'row',
608
- justifyContent: 'space-between',
609
- alignItems: 'center',
610
- paddingVertical: 16,
611
- borderBottomWidth: 1,
612
- borderBottomColor: '#E0E0E0'
790
+ alignItems: 'center'
613
791
  },
614
- settingLabel: {
615
- fontSize: 16
792
+ editingFieldIcon: {
793
+ marginRight: 12
616
794
  },
617
- errorContainer: {
618
- backgroundColor: '#FFEBEE',
619
- padding: 16,
620
- borderRadius: 8,
621
- marginBottom: 16
795
+ editingFieldTitle: {
796
+ fontSize: 20,
797
+ fontWeight: '600',
798
+ color: '#000'
622
799
  },
623
- errorText: {
624
- color: '#D32F2F',
625
- fontSize: 14
800
+ editingFieldContent: {
801
+ flex: 1
802
+ },
803
+ newValueSection: {
804
+ flex: 1
626
805
  },
627
- successContainer: {
628
- backgroundColor: '#E8F5E9',
806
+ editingFieldLabel: {
807
+ fontSize: 16,
808
+ fontWeight: '600',
809
+ color: '#333',
810
+ marginBottom: 12,
811
+ fontFamily: _fonts.fontFamilies.phuduSemiBold
812
+ },
813
+ editingFieldInput: {
814
+ backgroundColor: '#fff',
815
+ borderWidth: 2,
816
+ borderColor: '#e0e0e0',
817
+ borderRadius: 12,
629
818
  padding: 16,
630
- borderRadius: 8,
631
- marginBottom: 16
819
+ fontSize: 17,
820
+ minHeight: 52,
821
+ fontWeight: '400'
632
822
  },
633
- successText: {
634
- color: '#2E7D32',
635
- fontSize: 14
823
+ editingFieldTextArea: {
824
+ backgroundColor: '#fff',
825
+ borderWidth: 2,
826
+ borderColor: '#e0e0e0',
827
+ borderRadius: 12,
828
+ padding: 16,
829
+ fontSize: 17,
830
+ minHeight: 120,
831
+ textAlignVertical: 'top',
832
+ fontWeight: '400'
636
833
  }
637
834
  });
638
835
  var _default = exports.default = AccountSettingsScreen;