@oxyhq/services 5.17.18 → 5.18.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (238) hide show
  1. package/lib/commonjs/core/mixins/OxyServices.features.js +372 -0
  2. package/lib/commonjs/core/mixins/OxyServices.features.js.map +1 -0
  3. package/lib/commonjs/core/mixins/index.js +3 -2
  4. package/lib/commonjs/core/mixins/index.js.map +1 -1
  5. package/lib/commonjs/ui/components/GroupedItem.js +11 -1
  6. package/lib/commonjs/ui/components/GroupedItem.js.map +1 -1
  7. package/lib/commonjs/ui/components/SettingRow.js +17 -4
  8. package/lib/commonjs/ui/components/SettingRow.js.map +1 -1
  9. package/lib/commonjs/ui/components/feedback/FormInput.js +72 -0
  10. package/lib/commonjs/ui/components/feedback/FormInput.js.map +1 -0
  11. package/lib/commonjs/ui/components/feedback/ProgressIndicator.js +33 -0
  12. package/lib/commonjs/ui/components/feedback/ProgressIndicator.js.map +1 -0
  13. package/lib/commonjs/ui/components/feedback/constants.js +59 -0
  14. package/lib/commonjs/ui/components/feedback/constants.js.map +1 -0
  15. package/lib/commonjs/ui/components/feedback/feedbackStyles.js +262 -0
  16. package/lib/commonjs/ui/components/feedback/feedbackStyles.js.map +1 -0
  17. package/lib/commonjs/ui/components/feedback/index.js +54 -0
  18. package/lib/commonjs/ui/components/feedback/index.js.map +1 -0
  19. package/lib/commonjs/ui/components/feedback/types.js +6 -0
  20. package/lib/commonjs/ui/components/feedback/types.js.map +1 -0
  21. package/lib/commonjs/ui/components/feedback/useFeedbackForm.js +52 -0
  22. package/lib/commonjs/ui/components/feedback/useFeedbackForm.js.map +1 -0
  23. package/lib/commonjs/ui/components/modals/DeleteAccountModal.js +282 -0
  24. package/lib/commonjs/ui/components/modals/DeleteAccountModal.js.map +1 -0
  25. package/lib/commonjs/ui/components/modals/index.js +14 -0
  26. package/lib/commonjs/ui/components/modals/index.js.map +1 -0
  27. package/lib/commonjs/ui/components/payment/PaymentDetailsStep.js +309 -0
  28. package/lib/commonjs/ui/components/payment/PaymentDetailsStep.js.map +1 -0
  29. package/lib/commonjs/ui/components/payment/PaymentMethodStep.js +79 -0
  30. package/lib/commonjs/ui/components/payment/PaymentMethodStep.js.map +1 -0
  31. package/lib/commonjs/ui/components/payment/PaymentReviewStep.js +108 -0
  32. package/lib/commonjs/ui/components/payment/PaymentReviewStep.js.map +1 -0
  33. package/lib/commonjs/ui/components/payment/PaymentSuccessStep.js +79 -0
  34. package/lib/commonjs/ui/components/payment/PaymentSuccessStep.js.map +1 -0
  35. package/lib/commonjs/ui/components/payment/PaymentSummaryStep.js +176 -0
  36. package/lib/commonjs/ui/components/payment/PaymentSummaryStep.js.map +1 -0
  37. package/lib/commonjs/ui/components/payment/constants.js +53 -0
  38. package/lib/commonjs/ui/components/payment/constants.js.map +1 -0
  39. package/lib/commonjs/ui/components/payment/index.js +80 -0
  40. package/lib/commonjs/ui/components/payment/index.js.map +1 -0
  41. package/lib/commonjs/ui/components/payment/paymentStyles.js +409 -0
  42. package/lib/commonjs/ui/components/payment/paymentStyles.js.map +1 -0
  43. package/lib/commonjs/ui/components/payment/types.js +6 -0
  44. package/lib/commonjs/ui/components/payment/types.js.map +1 -0
  45. package/lib/commonjs/ui/hooks/index.js +26 -0
  46. package/lib/commonjs/ui/hooks/index.js.map +1 -1
  47. package/lib/commonjs/ui/hooks/useAsyncAction.js +95 -0
  48. package/lib/commonjs/ui/hooks/useAsyncAction.js.map +1 -0
  49. package/lib/commonjs/ui/hooks/useSettingToggle.js +126 -0
  50. package/lib/commonjs/ui/hooks/useSettingToggle.js.map +1 -0
  51. package/lib/commonjs/ui/navigation/routes.js +1 -0
  52. package/lib/commonjs/ui/navigation/routes.js.map +1 -1
  53. package/lib/commonjs/ui/screens/AccountCenterScreen.js +4 -2
  54. package/lib/commonjs/ui/screens/AccountCenterScreen.js.map +1 -1
  55. package/lib/commonjs/ui/screens/AccountOverviewScreen.js +33 -30
  56. package/lib/commonjs/ui/screens/AccountOverviewScreen.js.map +1 -1
  57. package/lib/commonjs/ui/screens/FAQScreen.js +315 -0
  58. package/lib/commonjs/ui/screens/FAQScreen.js.map +1 -0
  59. package/lib/commonjs/ui/screens/FeedbackScreen.js +73 -590
  60. package/lib/commonjs/ui/screens/FeedbackScreen.js.map +1 -1
  61. package/lib/commonjs/ui/screens/HelpSupportScreen.js +8 -7
  62. package/lib/commonjs/ui/screens/HelpSupportScreen.js.map +1 -1
  63. package/lib/commonjs/ui/screens/PaymentGatewayScreen.js +67 -1395
  64. package/lib/commonjs/ui/screens/PaymentGatewayScreen.js.map +1 -1
  65. package/lib/commonjs/ui/screens/ProfileScreen.js +13 -5
  66. package/lib/commonjs/ui/screens/ProfileScreen.js.map +1 -1
  67. package/lib/commonjs/ui/screens/SavesCollectionsScreen.js +16 -10
  68. package/lib/commonjs/ui/screens/SavesCollectionsScreen.js.map +1 -1
  69. package/lib/commonjs/ui/screens/karma/KarmaCenterScreen.js +23 -11
  70. package/lib/commonjs/ui/screens/karma/KarmaCenterScreen.js.map +1 -1
  71. package/lib/module/core/mixins/OxyServices.features.js +369 -0
  72. package/lib/module/core/mixins/OxyServices.features.js.map +1 -0
  73. package/lib/module/core/mixins/index.js +3 -2
  74. package/lib/module/core/mixins/index.js.map +1 -1
  75. package/lib/module/ui/components/GroupedItem.js +11 -1
  76. package/lib/module/ui/components/GroupedItem.js.map +1 -1
  77. package/lib/module/ui/components/SettingRow.js +17 -4
  78. package/lib/module/ui/components/SettingRow.js.map +1 -1
  79. package/lib/module/ui/components/feedback/FormInput.js +67 -0
  80. package/lib/module/ui/components/feedback/FormInput.js.map +1 -0
  81. package/lib/module/ui/components/feedback/ProgressIndicator.js +28 -0
  82. package/lib/module/ui/components/feedback/ProgressIndicator.js.map +1 -0
  83. package/lib/module/ui/components/feedback/constants.js +55 -0
  84. package/lib/module/ui/components/feedback/constants.js.map +1 -0
  85. package/lib/module/ui/components/feedback/feedbackStyles.js +257 -0
  86. package/lib/module/ui/components/feedback/feedbackStyles.js.map +1 -0
  87. package/lib/module/ui/components/feedback/index.js +8 -0
  88. package/lib/module/ui/components/feedback/index.js.map +1 -0
  89. package/lib/module/ui/components/feedback/types.js +4 -0
  90. package/lib/module/ui/components/feedback/types.js.map +1 -0
  91. package/lib/module/ui/components/feedback/useFeedbackForm.js +47 -0
  92. package/lib/module/ui/components/feedback/useFeedbackForm.js.map +1 -0
  93. package/lib/module/ui/components/modals/DeleteAccountModal.js +276 -0
  94. package/lib/module/ui/components/modals/DeleteAccountModal.js.map +1 -0
  95. package/lib/module/ui/components/modals/index.js +4 -0
  96. package/lib/module/ui/components/modals/index.js.map +1 -0
  97. package/lib/module/ui/components/payment/PaymentDetailsStep.js +303 -0
  98. package/lib/module/ui/components/payment/PaymentDetailsStep.js.map +1 -0
  99. package/lib/module/ui/components/payment/PaymentMethodStep.js +73 -0
  100. package/lib/module/ui/components/payment/PaymentMethodStep.js.map +1 -0
  101. package/lib/module/ui/components/payment/PaymentReviewStep.js +102 -0
  102. package/lib/module/ui/components/payment/PaymentReviewStep.js.map +1 -0
  103. package/lib/module/ui/components/payment/PaymentSuccessStep.js +73 -0
  104. package/lib/module/ui/components/payment/PaymentSuccessStep.js.map +1 -0
  105. package/lib/module/ui/components/payment/PaymentSummaryStep.js +170 -0
  106. package/lib/module/ui/components/payment/PaymentSummaryStep.js.map +1 -0
  107. package/lib/module/ui/components/payment/constants.js +47 -0
  108. package/lib/module/ui/components/payment/constants.js.map +1 -0
  109. package/lib/module/ui/components/payment/index.js +10 -0
  110. package/lib/module/ui/components/payment/index.js.map +1 -0
  111. package/lib/module/ui/components/payment/paymentStyles.js +404 -0
  112. package/lib/module/ui/components/payment/paymentStyles.js.map +1 -0
  113. package/lib/module/ui/components/payment/types.js +4 -0
  114. package/lib/module/ui/components/payment/types.js.map +1 -0
  115. package/lib/module/ui/hooks/index.js +2 -0
  116. package/lib/module/ui/hooks/index.js.map +1 -1
  117. package/lib/module/ui/hooks/useAsyncAction.js +89 -0
  118. package/lib/module/ui/hooks/useAsyncAction.js.map +1 -0
  119. package/lib/module/ui/hooks/useSettingToggle.js +120 -0
  120. package/lib/module/ui/hooks/useSettingToggle.js.map +1 -0
  121. package/lib/module/ui/navigation/routes.js +1 -0
  122. package/lib/module/ui/navigation/routes.js.map +1 -1
  123. package/lib/module/ui/screens/AccountCenterScreen.js +4 -2
  124. package/lib/module/ui/screens/AccountCenterScreen.js.map +1 -1
  125. package/lib/module/ui/screens/AccountOverviewScreen.js +33 -30
  126. package/lib/module/ui/screens/AccountOverviewScreen.js.map +1 -1
  127. package/lib/module/ui/screens/FAQScreen.js +310 -0
  128. package/lib/module/ui/screens/FAQScreen.js.map +1 -0
  129. package/lib/module/ui/screens/FeedbackScreen.js +64 -581
  130. package/lib/module/ui/screens/FeedbackScreen.js.map +1 -1
  131. package/lib/module/ui/screens/HelpSupportScreen.js +8 -7
  132. package/lib/module/ui/screens/HelpSupportScreen.js.map +1 -1
  133. package/lib/module/ui/screens/PaymentGatewayScreen.js +67 -1397
  134. package/lib/module/ui/screens/PaymentGatewayScreen.js.map +1 -1
  135. package/lib/module/ui/screens/ProfileScreen.js +13 -5
  136. package/lib/module/ui/screens/ProfileScreen.js.map +1 -1
  137. package/lib/module/ui/screens/SavesCollectionsScreen.js +16 -10
  138. package/lib/module/ui/screens/SavesCollectionsScreen.js.map +1 -1
  139. package/lib/module/ui/screens/karma/KarmaCenterScreen.js +23 -11
  140. package/lib/module/ui/screens/karma/KarmaCenterScreen.js.map +1 -1
  141. package/lib/typescript/core/mixins/OxyServices.features.d.ts +229 -0
  142. package/lib/typescript/core/mixins/OxyServices.features.d.ts.map +1 -0
  143. package/lib/typescript/core/mixins/index.d.ts +71 -1
  144. package/lib/typescript/core/mixins/index.d.ts.map +1 -1
  145. package/lib/typescript/ui/components/GroupedItem.d.ts +5 -1
  146. package/lib/typescript/ui/components/GroupedItem.d.ts.map +1 -1
  147. package/lib/typescript/ui/components/SettingRow.d.ts +6 -0
  148. package/lib/typescript/ui/components/SettingRow.d.ts.map +1 -1
  149. package/lib/typescript/ui/components/feedback/FormInput.d.ts +20 -0
  150. package/lib/typescript/ui/components/feedback/FormInput.d.ts.map +1 -0
  151. package/lib/typescript/ui/components/feedback/ProgressIndicator.d.ts +11 -0
  152. package/lib/typescript/ui/components/feedback/ProgressIndicator.d.ts.map +1 -0
  153. package/lib/typescript/ui/components/feedback/constants.d.ts +5 -0
  154. package/lib/typescript/ui/components/feedback/constants.d.ts.map +1 -0
  155. package/lib/typescript/ui/components/feedback/feedbackStyles.d.ts +280 -0
  156. package/lib/typescript/ui/components/feedback/feedbackStyles.d.ts.map +1 -0
  157. package/lib/typescript/ui/components/feedback/index.d.ts +7 -0
  158. package/lib/typescript/ui/components/feedback/index.d.ts.map +1 -0
  159. package/lib/typescript/ui/components/feedback/types.d.ts +46 -0
  160. package/lib/typescript/ui/components/feedback/types.d.ts.map +1 -0
  161. package/lib/typescript/ui/components/feedback/useFeedbackForm.d.ts +9 -0
  162. package/lib/typescript/ui/components/feedback/useFeedbackForm.d.ts.map +1 -0
  163. package/lib/typescript/ui/components/modals/DeleteAccountModal.d.ts +19 -0
  164. package/lib/typescript/ui/components/modals/DeleteAccountModal.d.ts.map +1 -0
  165. package/lib/typescript/ui/components/modals/index.d.ts +2 -0
  166. package/lib/typescript/ui/components/modals/index.d.ts.map +1 -0
  167. package/lib/typescript/ui/components/payment/PaymentDetailsStep.d.ts +21 -0
  168. package/lib/typescript/ui/components/payment/PaymentDetailsStep.d.ts.map +1 -0
  169. package/lib/typescript/ui/components/payment/PaymentMethodStep.d.ts +14 -0
  170. package/lib/typescript/ui/components/payment/PaymentMethodStep.d.ts.map +1 -0
  171. package/lib/typescript/ui/components/payment/PaymentReviewStep.d.ts +16 -0
  172. package/lib/typescript/ui/components/payment/PaymentReviewStep.d.ts.map +1 -0
  173. package/lib/typescript/ui/components/payment/PaymentSuccessStep.d.ts +10 -0
  174. package/lib/typescript/ui/components/payment/PaymentSuccessStep.d.ts.map +1 -0
  175. package/lib/typescript/ui/components/payment/PaymentSummaryStep.d.ts +15 -0
  176. package/lib/typescript/ui/components/payment/PaymentSummaryStep.d.ts.map +1 -0
  177. package/lib/typescript/ui/components/payment/constants.d.ts +7 -0
  178. package/lib/typescript/ui/components/payment/constants.d.ts.map +1 -0
  179. package/lib/typescript/ui/components/payment/index.d.ts +9 -0
  180. package/lib/typescript/ui/components/payment/index.d.ts.map +1 -0
  181. package/lib/typescript/ui/components/payment/paymentStyles.d.ts +396 -0
  182. package/lib/typescript/ui/components/payment/paymentStyles.d.ts.map +1 -0
  183. package/lib/typescript/ui/components/payment/types.d.ts +40 -0
  184. package/lib/typescript/ui/components/payment/types.d.ts.map +1 -0
  185. package/lib/typescript/ui/hooks/index.d.ts +2 -0
  186. package/lib/typescript/ui/hooks/index.d.ts.map +1 -1
  187. package/lib/typescript/ui/hooks/useAsyncAction.d.ts +51 -0
  188. package/lib/typescript/ui/hooks/useAsyncAction.d.ts.map +1 -0
  189. package/lib/typescript/ui/hooks/useSettingToggle.d.ts +55 -0
  190. package/lib/typescript/ui/hooks/useSettingToggle.d.ts.map +1 -0
  191. package/lib/typescript/ui/navigation/routes.d.ts +1 -1
  192. package/lib/typescript/ui/navigation/routes.d.ts.map +1 -1
  193. package/lib/typescript/ui/screens/AccountOverviewScreen.d.ts.map +1 -1
  194. package/lib/typescript/ui/screens/FAQScreen.d.ts +5 -0
  195. package/lib/typescript/ui/screens/FAQScreen.d.ts.map +1 -0
  196. package/lib/typescript/ui/screens/FeedbackScreen.d.ts.map +1 -1
  197. package/lib/typescript/ui/screens/HelpSupportScreen.d.ts.map +1 -1
  198. package/lib/typescript/ui/screens/PaymentGatewayScreen.d.ts +3 -15
  199. package/lib/typescript/ui/screens/PaymentGatewayScreen.d.ts.map +1 -1
  200. package/lib/typescript/ui/screens/ProfileScreen.d.ts.map +1 -1
  201. package/lib/typescript/ui/screens/SavesCollectionsScreen.d.ts.map +1 -1
  202. package/lib/typescript/ui/screens/karma/KarmaCenterScreen.d.ts.map +1 -1
  203. package/package.json +1 -1
  204. package/src/core/mixins/OxyServices.features.ts +428 -0
  205. package/src/core/mixins/index.ts +20 -17
  206. package/src/ui/components/GroupedItem.tsx +19 -1
  207. package/src/ui/components/SettingRow.tsx +26 -4
  208. package/src/ui/components/feedback/FormInput.tsx +84 -0
  209. package/src/ui/components/feedback/ProgressIndicator.tsx +35 -0
  210. package/src/ui/components/feedback/constants.ts +22 -0
  211. package/src/ui/components/feedback/feedbackStyles.ts +247 -0
  212. package/src/ui/components/feedback/index.ts +6 -0
  213. package/src/ui/components/feedback/types.ts +52 -0
  214. package/src/ui/components/feedback/useFeedbackForm.ts +44 -0
  215. package/src/ui/components/modals/DeleteAccountModal.tsx +294 -0
  216. package/src/ui/components/modals/index.ts +1 -0
  217. package/src/ui/components/payment/PaymentDetailsStep.tsx +222 -0
  218. package/src/ui/components/payment/PaymentMethodStep.tsx +89 -0
  219. package/src/ui/components/payment/PaymentReviewStep.tsx +126 -0
  220. package/src/ui/components/payment/PaymentSuccessStep.tsx +71 -0
  221. package/src/ui/components/payment/PaymentSummaryStep.tsx +159 -0
  222. package/src/ui/components/payment/constants.ts +39 -0
  223. package/src/ui/components/payment/index.ts +9 -0
  224. package/src/ui/components/payment/paymentStyles.ts +397 -0
  225. package/src/ui/components/payment/types.ts +45 -0
  226. package/src/ui/hooks/index.ts +3 -1
  227. package/src/ui/hooks/useAsyncAction.ts +129 -0
  228. package/src/ui/hooks/useSettingToggle.ts +147 -0
  229. package/src/ui/navigation/routes.ts +2 -0
  230. package/src/ui/screens/AccountCenterScreen.tsx +2 -2
  231. package/src/ui/screens/AccountOverviewScreen.tsx +35 -37
  232. package/src/ui/screens/FAQScreen.tsx +332 -0
  233. package/src/ui/screens/FeedbackScreen.tsx +91 -626
  234. package/src/ui/screens/HelpSupportScreen.tsx +7 -5
  235. package/src/ui/screens/PaymentGatewayScreen.tsx +96 -1275
  236. package/src/ui/screens/ProfileScreen.tsx +11 -6
  237. package/src/ui/screens/SavesCollectionsScreen.tsx +19 -10
  238. package/src/ui/screens/karma/KarmaCenterScreen.tsx +10 -10
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@oxyhq/services",
3
- "version": "5.17.18",
3
+ "version": "5.18.0",
4
4
  "description": "Reusable OxyHQ module to handle authentication, user management, karma system, device-based session management and more 🚀",
5
5
  "main": "lib/commonjs/index.js",
6
6
  "module": "lib/module/index.js",
@@ -0,0 +1,428 @@
1
+ /**
2
+ * Features Methods Mixin
3
+ *
4
+ * Provides methods for various features:
5
+ * - Feedback submission
6
+ * - Subscription plans
7
+ * - Saves/Collections
8
+ * - User history
9
+ * - FAQ
10
+ * - User stats
11
+ * - Achievements
12
+ */
13
+ import type { OxyServicesBase } from '../OxyServices.base';
14
+ import { CACHE_TIMES } from './mixinHelpers';
15
+
16
+ // Types
17
+ export interface FeedbackPayload {
18
+ type: 'bug' | 'feature' | 'general' | 'support';
19
+ title: string;
20
+ description: string;
21
+ priority: 'low' | 'medium' | 'high' | 'critical';
22
+ category: string;
23
+ contactEmail?: string;
24
+ systemInfo?: {
25
+ platform: string;
26
+ version: string;
27
+ appVersion: string;
28
+ userId?: string;
29
+ username?: string;
30
+ timestamp: string;
31
+ };
32
+ }
33
+
34
+ export interface FeedbackResult {
35
+ id: string;
36
+ status: string;
37
+ createdAt: string;
38
+ }
39
+
40
+ export interface SubscriptionPlan {
41
+ id: string;
42
+ name: string;
43
+ description: string;
44
+ price: number;
45
+ currency: string;
46
+ interval: 'month' | 'year';
47
+ features: string[];
48
+ }
49
+
50
+ export interface SubscriptionResult {
51
+ subscriptionId: string;
52
+ status: string;
53
+ currentPeriodEnd: string;
54
+ }
55
+
56
+ export interface SavedItem {
57
+ id: string;
58
+ itemId: string;
59
+ itemType: string;
60
+ title: string;
61
+ createdAt: string;
62
+ }
63
+
64
+ export interface Collection {
65
+ id: string;
66
+ name: string;
67
+ description?: string;
68
+ itemCount: number;
69
+ createdAt: string;
70
+ }
71
+
72
+ export interface UserStats {
73
+ postCount: number;
74
+ commentCount: number;
75
+ followerCount: number;
76
+ followingCount: number;
77
+ karmaScore?: number;
78
+ }
79
+
80
+ export interface HistoryItem {
81
+ id: string;
82
+ type: string;
83
+ title: string;
84
+ timestamp: string;
85
+ metadata?: Record<string, any>;
86
+ }
87
+
88
+ export interface FAQ {
89
+ id: string;
90
+ question: string;
91
+ answer: string;
92
+ category: string;
93
+ }
94
+
95
+ export interface Achievement {
96
+ id: string;
97
+ name: string;
98
+ description: string;
99
+ icon: string;
100
+ unlockedAt?: string;
101
+ }
102
+
103
+ export function OxyServicesFeaturesMixin<T extends typeof OxyServicesBase>(Base: T) {
104
+ return class extends Base {
105
+ constructor(...args: any[]) {
106
+ super(...(args as [any]));
107
+ }
108
+
109
+ // ==================
110
+ // FEEDBACK METHODS
111
+ // ==================
112
+
113
+ /**
114
+ * Submit user feedback
115
+ */
116
+ async submitFeedback(payload: FeedbackPayload): Promise<FeedbackResult> {
117
+ try {
118
+ return await this.makeRequest<FeedbackResult>('POST', '/api/feedback', payload, {
119
+ cache: false,
120
+ });
121
+ } catch (error) {
122
+ throw this.handleError(error);
123
+ }
124
+ }
125
+
126
+ // ==================
127
+ // SUBSCRIPTION METHODS
128
+ // ==================
129
+
130
+ /**
131
+ * Get available subscription plans
132
+ */
133
+ async getSubscriptionPlans(): Promise<SubscriptionPlan[]> {
134
+ try {
135
+ return await this.makeRequest<SubscriptionPlan[]>('GET', '/api/subscriptions/plans', undefined, {
136
+ cache: true,
137
+ cacheTTL: CACHE_TIMES.LONG,
138
+ });
139
+ } catch (error) {
140
+ throw this.handleError(error);
141
+ }
142
+ }
143
+
144
+ /**
145
+ * Get individual purchasable features
146
+ */
147
+ async getIndividualFeatures(): Promise<any[]> {
148
+ try {
149
+ return await this.makeRequest<any[]>('GET', '/api/subscriptions/features', undefined, {
150
+ cache: true,
151
+ cacheTTL: CACHE_TIMES.LONG,
152
+ });
153
+ } catch (error) {
154
+ throw this.handleError(error);
155
+ }
156
+ }
157
+
158
+ /**
159
+ * Subscribe to a plan
160
+ */
161
+ async subscribe(planId: string, paymentMethodId?: string): Promise<SubscriptionResult> {
162
+ return this.withAuthRetry(async () => {
163
+ return await this.makeRequest<SubscriptionResult>('POST', '/api/subscriptions/subscribe', {
164
+ planId,
165
+ paymentMethodId,
166
+ }, { cache: false });
167
+ }, 'subscribe');
168
+ }
169
+
170
+ /**
171
+ * Subscribe to an individual feature
172
+ */
173
+ async subscribeToFeature(featureId: string, paymentMethodId?: string): Promise<SubscriptionResult> {
174
+ return this.withAuthRetry(async () => {
175
+ return await this.makeRequest<SubscriptionResult>('POST', '/api/subscriptions/features/subscribe', {
176
+ featureId,
177
+ paymentMethodId,
178
+ }, { cache: false });
179
+ }, 'subscribeToFeature');
180
+ }
181
+
182
+ /**
183
+ * Cancel subscription
184
+ */
185
+ async cancelSubscription(subscriptionId: string): Promise<void> {
186
+ return this.withAuthRetry(async () => {
187
+ await this.makeRequest('POST', `/api/subscriptions/${subscriptionId}/cancel`, undefined, {
188
+ cache: false,
189
+ });
190
+ }, 'cancelSubscription');
191
+ }
192
+
193
+ /**
194
+ * Reactivate subscription
195
+ */
196
+ async reactivateSubscription(subscriptionId: string): Promise<void> {
197
+ return this.withAuthRetry(async () => {
198
+ await this.makeRequest('POST', `/api/subscriptions/${subscriptionId}/reactivate`, undefined, {
199
+ cache: false,
200
+ });
201
+ }, 'reactivateSubscription');
202
+ }
203
+
204
+ /**
205
+ * Get current user's subscription
206
+ */
207
+ async getCurrentSubscription(): Promise<SubscriptionResult | null> {
208
+ return this.withAuthRetry(async () => {
209
+ try {
210
+ return await this.makeRequest<SubscriptionResult>('GET', '/api/subscriptions/current', undefined, {
211
+ cache: true,
212
+ cacheTTL: CACHE_TIMES.SHORT,
213
+ });
214
+ } catch (error: any) {
215
+ if (error.status === 404) return null;
216
+ throw error;
217
+ }
218
+ }, 'getCurrentSubscription');
219
+ }
220
+
221
+ // ==================
222
+ // SAVES/COLLECTIONS
223
+ // ==================
224
+
225
+ /**
226
+ * Get user's saved items
227
+ */
228
+ async getSavedItems(userId?: string): Promise<SavedItem[]> {
229
+ return this.withAuthRetry(async () => {
230
+ const endpoint = userId ? `/api/users/${userId}/saves` : '/api/saves';
231
+ return await this.makeRequest<SavedItem[]>('GET', endpoint, undefined, {
232
+ cache: true,
233
+ cacheTTL: CACHE_TIMES.SHORT,
234
+ });
235
+ }, 'getSavedItems');
236
+ }
237
+
238
+ /**
239
+ * Get user's collections
240
+ */
241
+ async getCollections(userId?: string): Promise<Collection[]> {
242
+ return this.withAuthRetry(async () => {
243
+ const endpoint = userId ? `/api/users/${userId}/collections` : '/api/collections';
244
+ return await this.makeRequest<Collection[]>('GET', endpoint, undefined, {
245
+ cache: true,
246
+ cacheTTL: CACHE_TIMES.SHORT,
247
+ });
248
+ }, 'getCollections');
249
+ }
250
+
251
+ /**
252
+ * Save an item
253
+ */
254
+ async saveItem(itemId: string, itemType: string, collectionId?: string): Promise<SavedItem> {
255
+ return this.withAuthRetry(async () => {
256
+ return await this.makeRequest<SavedItem>('POST', '/api/saves', {
257
+ itemId,
258
+ itemType,
259
+ collectionId,
260
+ }, { cache: false });
261
+ }, 'saveItem');
262
+ }
263
+
264
+ /**
265
+ * Remove an item from saves
266
+ */
267
+ async removeSavedItem(saveId: string): Promise<void> {
268
+ return this.withAuthRetry(async () => {
269
+ await this.makeRequest('DELETE', `/api/saves/${saveId}`, undefined, { cache: false });
270
+ }, 'removeSavedItem');
271
+ }
272
+
273
+ /**
274
+ * Create a collection
275
+ */
276
+ async createCollection(name: string, description?: string): Promise<Collection> {
277
+ return this.withAuthRetry(async () => {
278
+ return await this.makeRequest<Collection>('POST', '/api/collections', {
279
+ name,
280
+ description,
281
+ }, { cache: false });
282
+ }, 'createCollection');
283
+ }
284
+
285
+ /**
286
+ * Delete a collection
287
+ */
288
+ async deleteCollection(collectionId: string): Promise<void> {
289
+ return this.withAuthRetry(async () => {
290
+ await this.makeRequest('DELETE', `/api/collections/${collectionId}`, undefined, { cache: false });
291
+ }, 'deleteCollection');
292
+ }
293
+
294
+ // ==================
295
+ // USER STATS
296
+ // ==================
297
+
298
+ /**
299
+ * Get user statistics
300
+ */
301
+ async getUserStats(userId: string): Promise<UserStats> {
302
+ try {
303
+ return await this.makeRequest<UserStats>('GET', `/api/users/${userId}/stats`, undefined, {
304
+ cache: true,
305
+ cacheTTL: CACHE_TIMES.MEDIUM,
306
+ });
307
+ } catch (error) {
308
+ throw this.handleError(error);
309
+ }
310
+ }
311
+
312
+ // ==================
313
+ // HISTORY
314
+ // ==================
315
+
316
+ /**
317
+ * Get user history
318
+ */
319
+ async getUserHistory(userId?: string, limit?: number, offset?: number): Promise<HistoryItem[]> {
320
+ return this.withAuthRetry(async () => {
321
+ const params: any = {};
322
+ if (limit) params.limit = limit;
323
+ if (offset) params.offset = offset;
324
+
325
+ const endpoint = userId ? `/api/users/${userId}/history` : '/api/history';
326
+ return await this.makeRequest<HistoryItem[]>('GET', endpoint, params, {
327
+ cache: true,
328
+ cacheTTL: CACHE_TIMES.SHORT,
329
+ });
330
+ }, 'getUserHistory');
331
+ }
332
+
333
+ /**
334
+ * Clear user history
335
+ */
336
+ async clearUserHistory(): Promise<void> {
337
+ return this.withAuthRetry(async () => {
338
+ await this.makeRequest('DELETE', '/api/history', undefined, { cache: false });
339
+ }, 'clearUserHistory');
340
+ }
341
+
342
+ /**
343
+ * Delete a history item
344
+ */
345
+ async deleteHistoryItem(itemId: string): Promise<void> {
346
+ return this.withAuthRetry(async () => {
347
+ await this.makeRequest('DELETE', `/api/history/${itemId}`, undefined, { cache: false });
348
+ }, 'deleteHistoryItem');
349
+ }
350
+
351
+ // ==================
352
+ // FAQ
353
+ // ==================
354
+
355
+ /**
356
+ * Get FAQs
357
+ */
358
+ async getFAQs(category?: string): Promise<FAQ[]> {
359
+ try {
360
+ const params = category ? { category } : undefined;
361
+ return await this.makeRequest<FAQ[]>('GET', '/api/faqs', params, {
362
+ cache: true,
363
+ cacheTTL: CACHE_TIMES.LONG,
364
+ });
365
+ } catch (error) {
366
+ throw this.handleError(error);
367
+ }
368
+ }
369
+
370
+ /**
371
+ * Search FAQs
372
+ */
373
+ async searchFAQs(query: string): Promise<FAQ[]> {
374
+ try {
375
+ return await this.makeRequest<FAQ[]>('GET', '/api/faqs/search', { query }, {
376
+ cache: true,
377
+ cacheTTL: CACHE_TIMES.MEDIUM,
378
+ });
379
+ } catch (error) {
380
+ throw this.handleError(error);
381
+ }
382
+ }
383
+
384
+ // ==================
385
+ // ACHIEVEMENTS
386
+ // ==================
387
+
388
+ /**
389
+ * Get user achievements
390
+ */
391
+ async getUserAchievements(userId?: string): Promise<Achievement[]> {
392
+ return this.withAuthRetry(async () => {
393
+ const endpoint = userId ? `/api/users/${userId}/achievements` : '/api/achievements';
394
+ return await this.makeRequest<Achievement[]>('GET', endpoint, undefined, {
395
+ cache: true,
396
+ cacheTTL: CACHE_TIMES.MEDIUM,
397
+ });
398
+ }, 'getUserAchievements');
399
+ }
400
+
401
+ /**
402
+ * Get all available achievements
403
+ */
404
+ async getAllAchievements(): Promise<Achievement[]> {
405
+ try {
406
+ return await this.makeRequest<Achievement[]>('GET', '/api/achievements/all', undefined, {
407
+ cache: true,
408
+ cacheTTL: CACHE_TIMES.LONG,
409
+ });
410
+ } catch (error) {
411
+ throw this.handleError(error);
412
+ }
413
+ }
414
+
415
+ // ==================
416
+ // ACCOUNT
417
+ // ==================
418
+
419
+ /**
420
+ * Delete user account (requires password confirmation)
421
+ */
422
+ async deleteAccount(password: string): Promise<void> {
423
+ return this.withAuthRetry(async () => {
424
+ await this.makeRequest('DELETE', '/api/account', { password }, { cache: false });
425
+ }, 'deleteAccount');
426
+ }
427
+ };
428
+ }
@@ -22,6 +22,7 @@ import { OxyServicesAnalyticsMixin } from './OxyServices.analytics';
22
22
  import { OxyServicesDevicesMixin } from './OxyServices.devices';
23
23
  import { OxyServicesSecurityMixin } from './OxyServices.security';
24
24
  import { OxyServicesUtilityMixin } from './OxyServices.utility';
25
+ import { OxyServicesFeaturesMixin } from './OxyServices.features';
25
26
 
26
27
  /**
27
28
  * Composes all OxyServices mixins in the correct order
@@ -38,23 +39,25 @@ import { OxyServicesUtilityMixin } from './OxyServices.utility';
38
39
  */
39
40
  export function composeOxyServices() {
40
41
  return OxyServicesUtilityMixin(
41
- OxyServicesSecurityMixin(
42
- OxyServicesDevicesMixin(
43
- OxyServicesAnalyticsMixin(
44
- OxyServicesLocationMixin(
45
- OxyServicesDeveloperMixin(
46
- OxyServicesAssetsMixin(
47
- OxyServicesKarmaMixin(
48
- OxyServicesPaymentMixin(
49
- OxyServicesLanguageMixin(
50
- OxyServicesPrivacyMixin(
51
- OxyServicesUserMixin(
52
- // Cross-domain authentication mixins (web-only)
53
- OxyServicesRedirectAuthMixin(
54
- OxyServicesPopupAuthMixin(
55
- OxyServicesFedCMMixin(
56
- // Base authentication mixin
57
- OxyServicesAuthMixin(OxyServicesBase)
42
+ OxyServicesFeaturesMixin(
43
+ OxyServicesSecurityMixin(
44
+ OxyServicesDevicesMixin(
45
+ OxyServicesAnalyticsMixin(
46
+ OxyServicesLocationMixin(
47
+ OxyServicesDeveloperMixin(
48
+ OxyServicesAssetsMixin(
49
+ OxyServicesKarmaMixin(
50
+ OxyServicesPaymentMixin(
51
+ OxyServicesLanguageMixin(
52
+ OxyServicesPrivacyMixin(
53
+ OxyServicesUserMixin(
54
+ // Cross-domain authentication mixins (web-only)
55
+ OxyServicesRedirectAuthMixin(
56
+ OxyServicesPopupAuthMixin(
57
+ OxyServicesFedCMMixin(
58
+ // Base authentication mixin
59
+ OxyServicesAuthMixin(OxyServicesBase)
60
+ )
58
61
  )
59
62
  )
60
63
  )
@@ -22,6 +22,10 @@ interface GroupedItemProps {
22
22
  disabled?: boolean;
23
23
  customContent?: React.ReactNode;
24
24
  customIcon?: React.ReactNode;
25
+ /** Accessibility label (defaults to title) */
26
+ accessibilityLabel?: string;
27
+ /** Accessibility hint for what happens on press */
28
+ accessibilityHint?: string;
25
29
  }
26
30
 
27
31
  const GroupedItemComponent = ({
@@ -36,6 +40,8 @@ const GroupedItemComponent = ({
36
40
  disabled = false,
37
41
  customContent,
38
42
  customIcon,
43
+ accessibilityLabel,
44
+ accessibilityHint,
39
45
  }: GroupedItemProps) => {
40
46
  const hookColorScheme = useColorScheme();
41
47
  const colorScheme = normalizeColorScheme(hookColorScheme);
@@ -90,13 +96,25 @@ const GroupedItemComponent = ({
90
96
  onPressIn={disabled ? undefined : handlePressIn}
91
97
  onPress={onPress}
92
98
  activeOpacity={0.7}
99
+ accessibilityRole="button"
100
+ accessibilityLabel={accessibilityLabel || title}
101
+ accessibilityHint={accessibilityHint || subtitle}
102
+ accessibilityState={{ disabled }}
93
103
  >
94
104
  {content}
95
105
  </TouchableOpacity>
96
106
  );
97
107
  }
98
108
 
99
- return <View style={itemStyles}>{content}</View>;
109
+ return (
110
+ <View
111
+ style={itemStyles}
112
+ accessibilityRole="text"
113
+ accessibilityLabel={accessibilityLabel || title}
114
+ >
115
+ {content}
116
+ </View>
117
+ );
100
118
  };
101
119
 
102
120
  GroupedItemComponent.displayName = 'GroupedItem';
@@ -10,6 +10,12 @@ export interface SettingRowProps {
10
10
  textColor?: string;
11
11
  mutedTextColor?: string;
12
12
  borderColor?: string;
13
+ /** Active color for the switch track (default: #d169e5) */
14
+ activeColor?: string;
15
+ /** Inactive color for the switch track (default: #767577) */
16
+ inactiveColor?: string;
17
+ /** Accessibility label for the switch */
18
+ accessibilityLabel?: string;
13
19
  }
14
20
 
15
21
  /**
@@ -25,15 +31,27 @@ const SettingRow: React.FC<SettingRowProps> = ({
25
31
  textColor,
26
32
  mutedTextColor,
27
33
  borderColor,
34
+ activeColor = '#d169e5',
35
+ inactiveColor = '#767577',
36
+ accessibilityLabel,
28
37
  }) => {
29
38
  return (
30
- <View style={[styles.settingRow, borderColor ? { borderBottomColor: borderColor } : undefined]}>
39
+ <View
40
+ style={[styles.settingRow, borderColor ? { borderBottomColor: borderColor } : undefined]}
41
+ accessibilityRole="none"
42
+ >
31
43
  <View style={styles.settingInfo}>
32
- <Text style={[styles.settingTitle, textColor ? { color: textColor } : undefined]}>
44
+ <Text
45
+ style={[styles.settingTitle, textColor ? { color: textColor } : undefined]}
46
+ accessibilityRole="text"
47
+ >
33
48
  {title}
34
49
  </Text>
35
50
  {description && (
36
- <Text style={[styles.settingDescription, mutedTextColor ? { color: mutedTextColor } : undefined]}>
51
+ <Text
52
+ style={[styles.settingDescription, mutedTextColor ? { color: mutedTextColor } : undefined]}
53
+ accessibilityRole="text"
54
+ >
37
55
  {description}
38
56
  </Text>
39
57
  )}
@@ -42,8 +60,12 @@ const SettingRow: React.FC<SettingRowProps> = ({
42
60
  value={value}
43
61
  onValueChange={onValueChange}
44
62
  disabled={disabled}
45
- trackColor={{ false: '#767577', true: '#d169e5' }}
63
+ trackColor={{ false: inactiveColor, true: activeColor }}
46
64
  thumbColor={value ? '#fff' : '#f4f3f4'}
65
+ accessibilityRole="switch"
66
+ accessibilityLabel={accessibilityLabel || title}
67
+ accessibilityState={{ checked: value, disabled }}
68
+ accessibilityHint={description}
47
69
  />
48
70
  </View>
49
71
  );
@@ -0,0 +1,84 @@
1
+ import React from 'react';
2
+ import { View, Text, TextInput } from 'react-native';
3
+ import { Ionicons } from '@expo/vector-icons';
4
+ import type { FeedbackColors } from './types';
5
+
6
+ interface FormInputProps {
7
+ icon: string;
8
+ label: string;
9
+ value: string;
10
+ onChangeText: (text: string) => void;
11
+ placeholder?: string;
12
+ multiline?: boolean;
13
+ numberOfLines?: number;
14
+ testID?: string;
15
+ colors: FeedbackColors;
16
+ styles: any;
17
+ borderColor?: string;
18
+ accessibilityLabel?: string;
19
+ accessibilityHint?: string;
20
+ }
21
+
22
+ const FormInput: React.FC<FormInputProps> = React.memo(({
23
+ icon,
24
+ label,
25
+ value,
26
+ onChangeText,
27
+ placeholder,
28
+ multiline = false,
29
+ numberOfLines = 1,
30
+ testID,
31
+ colors,
32
+ styles,
33
+ borderColor,
34
+ accessibilityLabel,
35
+ accessibilityHint,
36
+ }) => (
37
+ <View style={styles.inputContainer}>
38
+ <View style={[
39
+ multiline ? styles.textAreaWrapper : styles.premiumInputWrapper,
40
+ {
41
+ borderColor: borderColor || colors.border,
42
+ backgroundColor: colors.inputBackground,
43
+ shadowColor: colors.primary,
44
+ shadowOffset: { width: 0, height: 4 },
45
+ shadowOpacity: 0.1,
46
+ shadowRadius: 12,
47
+ elevation: 3,
48
+ }
49
+ ]}>
50
+ {!multiline && (
51
+ <Ionicons
52
+ name={icon as any}
53
+ size={22}
54
+ color={colors.secondaryText}
55
+ style={styles.inputIcon}
56
+ />
57
+ )}
58
+ <View style={styles.inputContent}>
59
+ <Text style={[styles.modernLabel, { color: colors.secondaryText }]}>
60
+ {label}
61
+ </Text>
62
+ <TextInput
63
+ style={[
64
+ multiline ? styles.textArea : styles.modernInput,
65
+ { color: colors.text }
66
+ ]}
67
+ value={value}
68
+ onChangeText={onChangeText}
69
+ placeholder={placeholder}
70
+ placeholderTextColor={colors.secondaryText + '60'}
71
+ multiline={multiline}
72
+ numberOfLines={multiline ? numberOfLines : undefined}
73
+ testID={testID}
74
+ accessibilityLabel={accessibilityLabel || label}
75
+ accessibilityHint={accessibilityHint}
76
+ />
77
+ </View>
78
+ </View>
79
+ </View>
80
+ ));
81
+
82
+ FormInput.displayName = 'FormInput';
83
+
84
+ export default FormInput;