@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
@@ -0,0 +1,1628 @@
1
+ import React, { useState, useEffect } from 'react';
2
+ import {
3
+ View,
4
+ Text,
5
+ TouchableOpacity,
6
+ StyleSheet,
7
+ ScrollView,
8
+ ActivityIndicator,
9
+ Alert,
10
+ Platform,
11
+ Animated,
12
+ Dimensions,
13
+ } from 'react-native';
14
+ import { BaseScreenProps } from '../navigation/types';
15
+ import { useOxy } from '../context/OxyContext';
16
+ import { fontFamilies } from '../styles/fonts';
17
+ import { toast } from '../../lib/sonner';
18
+ import { Ionicons } from '@expo/vector-icons';
19
+ import Avatar from '../components/Avatar';
20
+
21
+ interface SubscriptionPlan {
22
+ id: string;
23
+ name: string;
24
+ description: string;
25
+ price: number;
26
+ currency: string;
27
+ interval: 'month' | 'year';
28
+ features: string[];
29
+ appScope: 'ecosystem' | 'specific';
30
+ applicableApps: string[]; // ['mention', 'oxy-social', 'oxy-workspace', 'oxy-creator'] etc.
31
+ includedFeatures: string[]; // Feature IDs that are included in this plan
32
+ isPopular?: boolean;
33
+ isCurrentPlan?: boolean;
34
+ }
35
+
36
+ interface IndividualFeature {
37
+ id: string;
38
+ name: string;
39
+ description: string;
40
+ price: number;
41
+ currency: string;
42
+ interval: 'month' | 'year';
43
+ category: 'analytics' | 'customization' | 'content' | 'networking' | 'productivity';
44
+ appScope: 'ecosystem' | 'specific';
45
+ applicableApps: string[]; // Apps where this feature is available
46
+ canBePurchasedSeparately: boolean;
47
+ includedInPlans: string[]; // Plan IDs that include this feature
48
+ isSubscribed?: boolean;
49
+ isIncludedInCurrentPlan?: boolean;
50
+ }
51
+
52
+ interface UserSubscription {
53
+ id: string;
54
+ planId: string;
55
+ status: 'active' | 'canceled' | 'past_due' | 'trialing';
56
+ currentPeriodStart: string;
57
+ currentPeriodEnd: string;
58
+ cancelAtPeriodEnd: boolean;
59
+ trialEnd?: string;
60
+ }
61
+
62
+ const PremiumSubscriptionScreen: React.FC<BaseScreenProps> = ({
63
+ onClose,
64
+ theme,
65
+ navigate,
66
+ goBack,
67
+ }) => {
68
+ const { user, oxyServices } = useOxy();
69
+ const [loading, setLoading] = useState(true);
70
+ const [subscription, setSubscription] = useState<UserSubscription | null>(null);
71
+ const [plans, setPlans] = useState<SubscriptionPlan[]>([]);
72
+ const [individualFeatures, setIndividualFeatures] = useState<IndividualFeature[]>([]);
73
+ const [selectedPlan, setSelectedPlan] = useState<string | null>(null);
74
+ const [processingPayment, setProcessingPayment] = useState(false);
75
+ const [billingInterval, setBillingInterval] = useState<'month' | 'year'>('month');
76
+ const [activeTab, setActiveTab] = useState<'plans' | 'features'>('plans');
77
+ const [currentAppPackage, setCurrentAppPackage] = useState<string>('mention'); // Default to mention for demo
78
+
79
+ const isDarkTheme = theme === 'dark';
80
+ const textColor = isDarkTheme ? '#FFFFFF' : '#000000';
81
+ const backgroundColor = isDarkTheme ? '#121212' : '#FFFFFF';
82
+ const secondaryBackgroundColor = isDarkTheme ? '#222222' : '#F5F5F5';
83
+ const borderColor = isDarkTheme ? '#444444' : '#E0E0E0';
84
+ const primaryColor = '#007AFF';
85
+ const successColor = '#30D158';
86
+ const warningColor = '#FF9500';
87
+ const dangerColor = '#FF3B30';
88
+
89
+ // Oxy+ subscription plans
90
+ const mockPlans: SubscriptionPlan[] = [
91
+ {
92
+ id: 'mention-plus',
93
+ name: 'Mention+',
94
+ description: 'Enhanced features for better social experience',
95
+ price: 4.99,
96
+ currency: 'USD',
97
+ interval: 'month',
98
+ appScope: 'specific',
99
+ applicableApps: ['mention'], // Only available in mention app
100
+ features: [
101
+ 'Undo posts option',
102
+ 'Improved reading mode',
103
+ 'Organize bookmarks into folders',
104
+ 'Early access to select features',
105
+ 'Edit posts capability',
106
+ 'Enhanced customization options'
107
+ ],
108
+ includedFeatures: ['reading-mode-plus', 'custom-themes']
109
+ },
110
+ {
111
+ id: 'oxy-insider',
112
+ name: 'Oxy+ Insider',
113
+ description: 'Exclusive access to behind-the-scenes content',
114
+ price: 9.99,
115
+ currency: 'USD',
116
+ interval: 'month',
117
+ appScope: 'ecosystem',
118
+ applicableApps: ['mention', 'oxy-social', 'oxy-workspace', 'oxy-creator'],
119
+ features: [
120
+ 'Everything in Mention+',
121
+ 'Behind-the-scenes updates from creators',
122
+ 'Early access to new features',
123
+ 'Dedicated support team',
124
+ 'Exclusive content access',
125
+ 'Beta feature testing'
126
+ ],
127
+ includedFeatures: ['reading-mode-plus', 'custom-themes', 'analytics-basic'],
128
+ isPopular: true
129
+ },
130
+ {
131
+ id: 'oxy-connect',
132
+ name: 'Oxy+ Connect',
133
+ description: 'Advanced networking and community features',
134
+ price: 14.99,
135
+ currency: 'USD',
136
+ interval: 'month',
137
+ appScope: 'ecosystem',
138
+ applicableApps: ['mention', 'oxy-social', 'oxy-workspace', 'oxy-creator'],
139
+ features: [
140
+ 'Everything in Oxy+ Insider',
141
+ 'Create and join private groups',
142
+ 'Advanced search and filtering tools',
143
+ 'Customizable profile highlighting',
144
+ 'Enhanced connection features',
145
+ 'Priority in community events'
146
+ ],
147
+ includedFeatures: ['reading-mode-plus', 'custom-themes', 'analytics-basic', 'group-management']
148
+ },
149
+ {
150
+ id: 'oxy-premium',
151
+ name: 'Oxy+ Premium',
152
+ description: 'Complete premium experience with all perks',
153
+ price: 24.99,
154
+ currency: 'USD',
155
+ interval: 'month',
156
+ appScope: 'ecosystem',
157
+ applicableApps: ['mention', 'oxy-social', 'oxy-workspace', 'oxy-creator', 'oxy-analytics'],
158
+ features: [
159
+ 'Everything in Oxy+ Connect',
160
+ 'Priority customer support',
161
+ 'Access to premium content and events',
162
+ 'Advanced analytics dashboard',
163
+ 'VIP community status',
164
+ 'Exclusive premium events'
165
+ ],
166
+ includedFeatures: ['reading-mode-plus', 'custom-themes', 'analytics-basic', 'analytics-advanced', 'group-management']
167
+ },
168
+ {
169
+ id: 'oxy-creator',
170
+ name: 'Oxy+ Creator',
171
+ description: 'Professional tools for content creators',
172
+ price: 39.99,
173
+ currency: 'USD',
174
+ interval: 'month',
175
+ appScope: 'ecosystem',
176
+ applicableApps: ['mention', 'oxy-social', 'oxy-workspace', 'oxy-creator', 'oxy-analytics', 'oxy-studio'],
177
+ features: [
178
+ 'Everything in Oxy+ Premium',
179
+ 'Advanced analytics and insights',
180
+ 'Promotional tools and resources',
181
+ 'Content monetization features',
182
+ 'Creator support program',
183
+ 'Revenue sharing opportunities'
184
+ ],
185
+ includedFeatures: ['reading-mode-plus', 'custom-themes', 'analytics-basic', 'analytics-advanced', 'group-management', 'creator-tools', 'monetization-features']
186
+ }
187
+ ];
188
+
189
+ // Individual feature subscriptions
190
+ const mockIndividualFeatures: IndividualFeature[] = [
191
+ {
192
+ id: 'analytics-basic',
193
+ name: 'Basic Analytics',
194
+ description: 'View post performance and engagement metrics',
195
+ price: 2.99,
196
+ currency: 'USD',
197
+ interval: 'month',
198
+ category: 'analytics',
199
+ appScope: 'ecosystem',
200
+ applicableApps: ['mention', 'oxy-social', 'oxy-workspace'],
201
+ canBePurchasedSeparately: true,
202
+ includedInPlans: ['oxy-insider', 'oxy-connect', 'oxy-premium', 'oxy-creator']
203
+ },
204
+ {
205
+ id: 'analytics-advanced',
206
+ name: 'Advanced Analytics',
207
+ description: 'Detailed insights, trends, and audience demographics',
208
+ price: 7.99,
209
+ currency: 'USD',
210
+ interval: 'month',
211
+ category: 'analytics',
212
+ appScope: 'ecosystem',
213
+ applicableApps: ['mention', 'oxy-social', 'oxy-workspace', 'oxy-creator', 'oxy-analytics'],
214
+ canBePurchasedSeparately: true,
215
+ includedInPlans: ['oxy-premium', 'oxy-creator']
216
+ },
217
+ {
218
+ id: 'custom-themes',
219
+ name: 'Custom Themes',
220
+ description: 'Personalize your app with custom colors and layouts',
221
+ price: 1.99,
222
+ currency: 'USD',
223
+ interval: 'month',
224
+ category: 'customization',
225
+ appScope: 'ecosystem',
226
+ applicableApps: ['mention', 'oxy-social', 'oxy-workspace', 'oxy-creator'],
227
+ canBePurchasedSeparately: false, // Included in all plans
228
+ includedInPlans: ['mention-plus', 'oxy-insider', 'oxy-connect', 'oxy-premium', 'oxy-creator']
229
+ },
230
+ {
231
+ id: 'reading-mode-plus',
232
+ name: 'Reading Mode Plus',
233
+ description: 'Enhanced reading experience with focus modes',
234
+ price: 1.99,
235
+ currency: 'USD',
236
+ interval: 'month',
237
+ category: 'content',
238
+ appScope: 'specific',
239
+ applicableApps: ['mention', 'oxy-social'],
240
+ canBePurchasedSeparately: false, // Included in all plans
241
+ includedInPlans: ['mention-plus', 'oxy-insider', 'oxy-connect', 'oxy-premium', 'oxy-creator']
242
+ },
243
+ {
244
+ id: 'group-management',
245
+ name: 'Group Management',
246
+ description: 'Create and manage private groups and communities',
247
+ price: 4.99,
248
+ currency: 'USD',
249
+ interval: 'month',
250
+ category: 'networking',
251
+ appScope: 'ecosystem',
252
+ applicableApps: ['mention', 'oxy-social', 'oxy-workspace'],
253
+ canBePurchasedSeparately: true,
254
+ includedInPlans: ['oxy-connect', 'oxy-premium', 'oxy-creator']
255
+ },
256
+ {
257
+ id: 'creator-tools',
258
+ name: 'Creator Tools Suite',
259
+ description: 'Professional content creation and editing tools',
260
+ price: 9.99,
261
+ currency: 'USD',
262
+ interval: 'month',
263
+ category: 'productivity',
264
+ appScope: 'specific',
265
+ applicableApps: ['oxy-creator', 'oxy-studio'],
266
+ canBePurchasedSeparately: true,
267
+ includedInPlans: ['oxy-creator']
268
+ },
269
+ {
270
+ id: 'monetization-features',
271
+ name: 'Monetization Features',
272
+ description: 'Revenue sharing, sponsorship tools, and creator fund access',
273
+ price: 12.99,
274
+ currency: 'USD',
275
+ interval: 'month',
276
+ category: 'productivity',
277
+ appScope: 'specific',
278
+ applicableApps: ['oxy-creator'],
279
+ canBePurchasedSeparately: true,
280
+ includedInPlans: ['oxy-creator']
281
+ },
282
+ {
283
+ id: 'workspace-collaboration',
284
+ name: 'Workspace Collaboration',
285
+ description: 'Advanced team features and project management tools',
286
+ price: 6.99,
287
+ currency: 'USD',
288
+ interval: 'month',
289
+ category: 'productivity',
290
+ appScope: 'specific',
291
+ applicableApps: ['oxy-workspace'],
292
+ canBePurchasedSeparately: true,
293
+ includedInPlans: ['oxy-premium', 'oxy-creator']
294
+ }
295
+ ];
296
+
297
+ useEffect(() => {
298
+ detectCurrentApp();
299
+ }, []);
300
+
301
+ useEffect(() => {
302
+ if (currentAppPackage) {
303
+ loadSubscriptionData();
304
+ }
305
+ }, [currentAppPackage, user?.isPremium]);
306
+
307
+ const detectCurrentApp = () => {
308
+ // In a real implementation, this would detect the actual app package name
309
+ // For now, we'll use a mock detection based on available methods
310
+
311
+ // Real app detection methods you could use:
312
+ // 1. Check bundle identifier in React Native:
313
+ // import DeviceInfo from 'react-native-device-info';
314
+ // const bundleId = DeviceInfo.getBundleId();
315
+ // Example: com.oxy.mention -> 'mention'
316
+
317
+ // 2. Environment variables or build configuration
318
+ // const appPackage = __DEV__ ? process.env.APP_PACKAGE : 'mention';
319
+
320
+ // 3. Check specific app capabilities or modules
321
+ // if (typeof MentionModule !== 'undefined') return 'mention';
322
+ // if (typeof OxyWorkspaceModule !== 'undefined') return 'oxy-workspace';
323
+
324
+ // 4. Use build-time configuration with Metro or similar
325
+ // const appPackage = require('../config/app.json').packageName;
326
+
327
+ // For demo purposes, we'll simulate different apps
328
+ // You would replace this with actual app detection logic
329
+
330
+ // IMPORTANT: This ensures subscription restrictions work properly:
331
+ // - Mention+ plan can only be subscribed to when app package == 'mention'
332
+ // - Other app-specific plans follow the same pattern
333
+ // - Ecosystem plans work across all apps
334
+
335
+ const detectedApp = 'mention'; // This would be dynamic in real implementation
336
+
337
+ setCurrentAppPackage(detectedApp);
338
+
339
+ // Log for debugging
340
+ console.log('Detected app package:', detectedApp);
341
+ console.log('Available plans for this app will be filtered accordingly');
342
+ };
343
+
344
+ const loadSubscriptionData = async () => {
345
+ try {
346
+ setLoading(true);
347
+
348
+ // Filter plans available for current app
349
+ const availablePlans = mockPlans.filter(plan =>
350
+ plan.applicableApps.includes(currentAppPackage)
351
+ );
352
+ setPlans(availablePlans);
353
+
354
+ // Mock current subscription
355
+ let currentSubscription: UserSubscription | null = null;
356
+ if (user?.isPremium) {
357
+ currentSubscription = {
358
+ id: 'sub_12345',
359
+ planId: 'oxy-insider',
360
+ status: 'active',
361
+ currentPeriodStart: new Date().toISOString(),
362
+ currentPeriodEnd: new Date(Date.now() + 30 * 24 * 60 * 60 * 1000).toISOString(),
363
+ cancelAtPeriodEnd: false
364
+ };
365
+ setSubscription(currentSubscription);
366
+ }
367
+
368
+ // Filter features available for current app and update based on current subscription
369
+ const availableFeatures = mockIndividualFeatures.filter(feature =>
370
+ feature.applicableApps.includes(currentAppPackage)
371
+ );
372
+
373
+ const updatedFeatures = availableFeatures.map(feature => {
374
+ const isIncludedInCurrentPlan = !!(currentSubscription &&
375
+ feature.includedInPlans.includes(currentSubscription.planId));
376
+
377
+ return {
378
+ ...feature,
379
+ isIncludedInCurrentPlan,
380
+ isSubscribed: isIncludedInCurrentPlan ? true : false // Mock some individual subscriptions
381
+ };
382
+ });
383
+
384
+ setIndividualFeatures(updatedFeatures);
385
+
386
+ } catch (error) {
387
+ console.error('Failed to load subscription data:', error);
388
+ toast.error('Failed to load subscription information');
389
+ } finally {
390
+ setLoading(false);
391
+ }
392
+ };
393
+
394
+ const handlePlanSelection = (planId: string) => {
395
+ setSelectedPlan(planId);
396
+ };
397
+
398
+ const handleSubscribe = async (planId: string) => {
399
+ try {
400
+ // Check if plan is available for current app
401
+ const selectedPlan = mockPlans.find(plan => plan.id === planId);
402
+ if (!selectedPlan?.applicableApps.includes(currentAppPackage)) {
403
+ console.log(`❌ Subscription blocked: Plan "${selectedPlan?.name}" not available for app "${currentAppPackage}"`);
404
+ toast.error(`This plan is not available for the current app (${currentAppPackage})`);
405
+ return;
406
+ }
407
+
408
+ // Special restriction for Mention+ plan - only available in mention app
409
+ if (planId === 'mention-plus' && currentAppPackage !== 'mention') {
410
+ console.log(`❌ Subscription blocked: Mention+ plan requires app to be "mention", current app is "${currentAppPackage}"`);
411
+ toast.error('Mention+ is only available in the Mention app');
412
+ return;
413
+ }
414
+
415
+ console.log(`✅ Subscription allowed: Plan "${selectedPlan.name}" is available for app "${currentAppPackage}"`);
416
+
417
+ setProcessingPayment(true);
418
+
419
+ // Mock payment processing
420
+ await new Promise(resolve => setTimeout(resolve, 2000));
421
+
422
+ toast.success('Subscription activated successfully!');
423
+
424
+ // Mock subscription update
425
+ setSubscription({
426
+ id: 'sub_' + Date.now(),
427
+ planId,
428
+ status: 'active',
429
+ currentPeriodStart: new Date().toISOString(),
430
+ currentPeriodEnd: new Date(Date.now() + 30 * 24 * 60 * 60 * 1000).toISOString(),
431
+ cancelAtPeriodEnd: false
432
+ });
433
+
434
+ // Reload data to update feature states
435
+ loadSubscriptionData();
436
+
437
+ } catch (error) {
438
+ console.error('Payment failed:', error);
439
+ toast.error('Payment failed. Please try again.');
440
+ } finally {
441
+ setProcessingPayment(false);
442
+ }
443
+ };
444
+
445
+ const handleCancelSubscription = () => {
446
+ Alert.alert(
447
+ 'Cancel Subscription',
448
+ 'Are you sure you want to cancel your subscription? You will lose access to premium features at the end of your current billing period.',
449
+ [
450
+ { text: 'Keep Subscription', style: 'cancel' },
451
+ {
452
+ text: 'Cancel Subscription',
453
+ style: 'destructive',
454
+ onPress: async () => {
455
+ try {
456
+ // Mock cancellation
457
+ setSubscription(prev => prev ? {
458
+ ...prev,
459
+ cancelAtPeriodEnd: true
460
+ } : null);
461
+ toast.success('Subscription will be canceled at the end of the billing period');
462
+ } catch (error) {
463
+ toast.error('Failed to cancel subscription');
464
+ }
465
+ }
466
+ }
467
+ ]
468
+ );
469
+ };
470
+
471
+ const handleReactivateSubscription = async () => {
472
+ try {
473
+ setSubscription(prev => prev ? {
474
+ ...prev,
475
+ cancelAtPeriodEnd: false
476
+ } : null);
477
+ toast.success('Subscription reactivated successfully');
478
+ } catch (error) {
479
+ toast.error('Failed to reactivate subscription');
480
+ }
481
+ };
482
+
483
+ const formatPrice = (price: number, currency: string, interval: string) => {
484
+ const yearlyPrice = interval === 'year' ? price : price * 12 * 0.8; // 20% discount for yearly
485
+ const displayPrice = billingInterval === 'year' ? yearlyPrice : price;
486
+
487
+ return {
488
+ price: displayPrice,
489
+ formatted: `$${displayPrice.toFixed(2)}`,
490
+ interval: billingInterval === 'year' ? 'year' : 'month'
491
+ };
492
+ };
493
+
494
+ const getCurrentPlan = () => {
495
+ if (!subscription) return null;
496
+ return plans.find(plan => plan.id === subscription.planId);
497
+ };
498
+
499
+ const handleFeatureSubscribe = async (featureId: string) => {
500
+ try {
501
+ // Check if feature is available for current app
502
+ const selectedFeature = mockIndividualFeatures.find(feature => feature.id === featureId);
503
+ if (!selectedFeature?.applicableApps.includes(currentAppPackage)) {
504
+ toast.error(`This feature is not available for the current app (${currentAppPackage})`);
505
+ return;
506
+ }
507
+
508
+ // Special restrictions for app-specific features
509
+ if (selectedFeature.appScope === 'specific') {
510
+ // For features that are only available in specific apps, enforce strict matching
511
+ const hasExactMatch = selectedFeature.applicableApps.length === 1 &&
512
+ selectedFeature.applicableApps[0] === currentAppPackage;
513
+ if (!hasExactMatch && selectedFeature.applicableApps.length === 1) {
514
+ const requiredApp = selectedFeature.applicableApps[0];
515
+ toast.error(`${selectedFeature.name} is only available in the ${requiredApp} app`);
516
+ return;
517
+ }
518
+ }
519
+
520
+ setProcessingPayment(true);
521
+
522
+ // Mock feature subscription
523
+ await new Promise(resolve => setTimeout(resolve, 1500));
524
+
525
+ setIndividualFeatures(prev =>
526
+ prev.map(feature =>
527
+ feature.id === featureId
528
+ ? { ...feature, isSubscribed: true }
529
+ : feature
530
+ )
531
+ );
532
+
533
+ const feature = individualFeatures.find(f => f.id === featureId);
534
+ toast.success(`Subscribed to ${feature?.name} successfully!`);
535
+
536
+ } catch (error) {
537
+ console.error('Feature subscription failed:', error);
538
+ toast.error('Feature subscription failed. Please try again.');
539
+ } finally {
540
+ setProcessingPayment(false);
541
+ }
542
+ };
543
+
544
+ const handleFeatureUnsubscribe = async (featureId: string) => {
545
+ const feature = individualFeatures.find(f => f.id === featureId);
546
+ Alert.alert(
547
+ 'Unsubscribe Feature',
548
+ `Are you sure you want to unsubscribe from ${feature?.name}?`,
549
+ [
550
+ { text: 'Keep Feature', style: 'cancel' },
551
+ {
552
+ text: 'Unsubscribe',
553
+ style: 'destructive',
554
+ onPress: async () => {
555
+ try {
556
+ setIndividualFeatures(prev =>
557
+ prev.map(f =>
558
+ f.id === featureId
559
+ ? { ...f, isSubscribed: false }
560
+ : f
561
+ )
562
+ );
563
+ toast.success(`Unsubscribed from ${feature?.name}`);
564
+ } catch (error) {
565
+ toast.error('Failed to unsubscribe from feature');
566
+ }
567
+ }
568
+ }
569
+ ]
570
+ );
571
+ };
572
+
573
+ const renderHeader = () => {
574
+ const getAppDisplayName = (packageName: string) => {
575
+ const appNames: Record<string, string> = {
576
+ 'mention': 'Mention',
577
+ 'oxy-social': 'Oxy Social',
578
+ 'oxy-workspace': 'Oxy Workspace',
579
+ 'oxy-creator': 'Oxy Creator',
580
+ 'oxy-analytics': 'Oxy Analytics',
581
+ 'oxy-studio': 'Oxy Studio'
582
+ };
583
+ return appNames[packageName] || packageName;
584
+ };
585
+
586
+ return (
587
+ <View style={[styles.header, { borderBottomColor: borderColor }]}>
588
+ <TouchableOpacity style={styles.backButton} onPress={goBack}>
589
+ <Ionicons name="arrow-back" size={24} color={textColor} />
590
+ </TouchableOpacity>
591
+ <View style={styles.headerTitleContainer}>
592
+ <Text style={[styles.headerTitle, { color: textColor }]}>Oxy+ Subscriptions</Text>
593
+ <Text style={[styles.currentAppText, { color: isDarkTheme ? '#BBBBBB' : '#666666' }]}>
594
+ for {getAppDisplayName(currentAppPackage)}
595
+ </Text>
596
+ </View>
597
+ {onClose && (
598
+ <TouchableOpacity style={styles.closeButton} onPress={onClose}>
599
+ <Ionicons name="close" size={24} color={textColor} />
600
+ </TouchableOpacity>
601
+ )}
602
+ </View>
603
+ );
604
+ };
605
+
606
+ const renderCurrentSubscription = () => {
607
+ if (!subscription) return null;
608
+
609
+ const currentPlan = getCurrentPlan();
610
+ if (!currentPlan) return null;
611
+
612
+ const statusColor =
613
+ subscription.status === 'active' ? successColor :
614
+ subscription.status === 'trialing' ? warningColor :
615
+ dangerColor;
616
+
617
+ return (
618
+ <View style={styles.section}>
619
+ <Text style={[styles.sectionTitle, { color: textColor }]}>Current Subscription</Text>
620
+
621
+ <View style={[styles.currentSubscriptionCard, { backgroundColor: secondaryBackgroundColor, borderColor }]}>
622
+ <View style={styles.subscriptionHeader}>
623
+ <View>
624
+ <Text style={[styles.planName, { color: textColor }]}>{currentPlan.name}</Text>
625
+ <Text style={[styles.planPrice, { color: primaryColor }]}>
626
+ ${currentPlan.price}/month
627
+ </Text>
628
+ </View>
629
+ <View style={[styles.statusBadge, { backgroundColor: statusColor }]}>
630
+ <Text style={styles.statusText}>
631
+ {subscription.status.toUpperCase()}
632
+ </Text>
633
+ </View>
634
+ </View>
635
+
636
+ <Text style={[styles.subscriptionDetail, { color: isDarkTheme ? '#BBBBBB' : '#666666' }]}>
637
+ Renews on {new Date(subscription.currentPeriodEnd).toLocaleDateString()}
638
+ </Text>
639
+
640
+ {subscription.cancelAtPeriodEnd && (
641
+ <View style={styles.cancelNotice}>
642
+ <Ionicons name="warning" size={16} color={warningColor} />
643
+ <Text style={[styles.cancelText, { color: warningColor }]}>
644
+ Subscription will cancel on {new Date(subscription.currentPeriodEnd).toLocaleDateString()}
645
+ </Text>
646
+ </View>
647
+ )}
648
+
649
+ <View style={styles.subscriptionActions}>
650
+ {subscription.cancelAtPeriodEnd ? (
651
+ <TouchableOpacity
652
+ style={[styles.actionButton, { backgroundColor: successColor }]}
653
+ onPress={handleReactivateSubscription}
654
+ >
655
+ <Text style={styles.actionButtonText}>Reactivate</Text>
656
+ </TouchableOpacity>
657
+ ) : (
658
+ <TouchableOpacity
659
+ style={[styles.actionButton, { backgroundColor: dangerColor }]}
660
+ onPress={handleCancelSubscription}
661
+ >
662
+ <Text style={styles.actionButtonText}>Cancel Subscription</Text>
663
+ </TouchableOpacity>
664
+ )}
665
+
666
+ <TouchableOpacity
667
+ style={[styles.actionButton, styles.secondaryButton, { borderColor }]}
668
+ onPress={() => navigate && navigate('BillingManagement')}
669
+ >
670
+ <Text style={[styles.actionButtonText, { color: textColor }]}>Manage Billing</Text>
671
+ </TouchableOpacity>
672
+ </View>
673
+ </View>
674
+ </View>
675
+ );
676
+ };
677
+
678
+ const renderBillingToggle = () => (
679
+ <View style={styles.section}>
680
+ <View style={styles.billingToggle}>
681
+ <TouchableOpacity
682
+ style={[
683
+ styles.billingOption,
684
+ billingInterval === 'month' && { backgroundColor: primaryColor }
685
+ ]}
686
+ onPress={() => setBillingInterval('month')}
687
+ >
688
+ <Text style={[
689
+ styles.billingOptionText,
690
+ { color: billingInterval === 'month' ? '#FFFFFF' : textColor }
691
+ ]}>
692
+ Monthly
693
+ </Text>
694
+ </TouchableOpacity>
695
+
696
+ <TouchableOpacity
697
+ style={[
698
+ styles.billingOption,
699
+ billingInterval === 'year' && { backgroundColor: primaryColor }
700
+ ]}
701
+ onPress={() => setBillingInterval('year')}
702
+ >
703
+ <Text style={[
704
+ styles.billingOptionText,
705
+ { color: billingInterval === 'year' ? '#FFFFFF' : textColor }
706
+ ]}>
707
+ Yearly
708
+ </Text>
709
+ </TouchableOpacity>
710
+ </View>
711
+
712
+ {billingInterval === 'year' && (
713
+ <Text style={[styles.savingsText, { color: successColor }]}>
714
+ 💰 Save 20% with yearly billing
715
+ </Text>
716
+ )}
717
+ </View>
718
+ );
719
+
720
+ const renderPlanCard = (plan: SubscriptionPlan) => {
721
+ const pricing = formatPrice(plan.price, plan.currency, plan.interval);
722
+ const isSelected = selectedPlan === plan.id;
723
+ const isCurrentPlan = subscription?.planId === plan.id;
724
+ const isAppSpecific = plan.appScope === 'specific' && plan.applicableApps.length === 1;
725
+ const isAvailableForCurrentApp = plan.applicableApps.includes(currentAppPackage);
726
+
727
+ const getAppScopeText = () => {
728
+ if (plan.appScope === 'ecosystem') {
729
+ return 'Works across all Oxy apps';
730
+ } else if (isAppSpecific) {
731
+ const appName = plan.applicableApps[0];
732
+ return `Exclusive to ${appName} app`;
733
+ } else {
734
+ return `Available in: ${plan.applicableApps.join(', ')}`;
735
+ }
736
+ };
737
+
738
+ const getAvailabilityStatus = () => {
739
+ if (isAppSpecific && !isAvailableForCurrentApp) {
740
+ const requiredApp = plan.applicableApps[0];
741
+ return {
742
+ available: false,
743
+ reason: `Only available in ${requiredApp} app`
744
+ };
745
+ }
746
+ return { available: true, reason: null };
747
+ };
748
+
749
+ const availability = getAvailabilityStatus();
750
+
751
+ return (
752
+ <View
753
+ key={plan.id}
754
+ style={[
755
+ styles.planCard,
756
+ { backgroundColor: secondaryBackgroundColor, borderColor },
757
+ isSelected && { borderColor: primaryColor, borderWidth: 2 },
758
+ plan.isPopular && styles.popularPlan,
759
+ !availability.available && { opacity: 0.6 }
760
+ ]}
761
+ >
762
+ {plan.isPopular && (
763
+ <View style={[styles.popularBadge, { backgroundColor: primaryColor }]}>
764
+ <Text style={styles.popularText}>MOST POPULAR</Text>
765
+ </View>
766
+ )}
767
+
768
+ {isAppSpecific && (
769
+ <View style={[styles.appSpecificBadge, {
770
+ backgroundColor: isAvailableForCurrentApp ? successColor : warningColor
771
+ }]}>
772
+ <Text style={styles.appSpecificText}>
773
+ {isAvailableForCurrentApp ? 'App Exclusive' : 'Not Available'}
774
+ </Text>
775
+ </View>
776
+ )}
777
+
778
+ <View style={styles.planHeader}>
779
+ <Text style={[styles.planName, { color: textColor }]}>{plan.name}</Text>
780
+ <Text style={[styles.planDescription, { color: isDarkTheme ? '#BBBBBB' : '#666666' }]}>
781
+ {plan.description}
782
+ </Text>
783
+ <Text style={[styles.planAppScope, { color: isDarkTheme ? '#888888' : '#999999' }]}>
784
+ {getAppScopeText()}
785
+ </Text>
786
+ {!availability.available && (
787
+ <Text style={[styles.planRestrictionText, { color: dangerColor }]}>
788
+ {availability.reason}
789
+ </Text>
790
+ )}
791
+ </View>
792
+
793
+ <View style={styles.planPricing}>
794
+ <Text style={[styles.planPrice, { color: textColor }]}>
795
+ {pricing.formatted}
796
+ </Text>
797
+ <Text style={[styles.planInterval, { color: isDarkTheme ? '#BBBBBB' : '#666666' }]}>
798
+ per {pricing.interval}
799
+ </Text>
800
+ </View>
801
+
802
+ <View style={styles.planFeatures}>
803
+ {plan.features.map((feature, index) => (
804
+ <View key={index} style={styles.featureItem}>
805
+ <Ionicons name="checkmark" size={16} color={successColor} />
806
+ <Text style={[styles.featureText, { color: textColor }]}>{feature}</Text>
807
+ </View>
808
+ ))}
809
+ </View>
810
+
811
+ {isCurrentPlan ? (
812
+ <View style={[styles.currentPlanButton, { backgroundColor: successColor }]}>
813
+ <Text style={styles.currentPlanText}>Current Plan</Text>
814
+ </View>
815
+ ) : !availability.available ? (
816
+ <View style={[styles.unavailablePlanButton, { backgroundColor: isDarkTheme ? '#444444' : '#E0E0E0' }]}>
817
+ <Text style={[styles.unavailablePlanText, { color: isDarkTheme ? '#888888' : '#999999' }]}>
818
+ Not Available in Current App
819
+ </Text>
820
+ </View>
821
+ ) : (
822
+ <TouchableOpacity
823
+ style={[
824
+ styles.selectPlanButton,
825
+ { backgroundColor: plan.isPopular ? primaryColor : borderColor }
826
+ ]}
827
+ onPress={() => handleSubscribe(plan.id)}
828
+ disabled={processingPayment}
829
+ >
830
+ {processingPayment ? (
831
+ <ActivityIndicator color="#FFFFFF" size="small" />
832
+ ) : (
833
+ <Text style={[
834
+ styles.selectPlanText,
835
+ { color: plan.isPopular ? '#FFFFFF' : textColor }
836
+ ]}>
837
+ Subscribe to {plan.name}
838
+ </Text>
839
+ )}
840
+ </TouchableOpacity>
841
+ )}
842
+ </View>
843
+ );
844
+ };
845
+
846
+ const renderTabNavigation = () => (
847
+ <View style={styles.section}>
848
+ <View style={[styles.tabContainer, { borderBottomColor: borderColor }]}>
849
+ <TouchableOpacity
850
+ style={[
851
+ styles.tab,
852
+ activeTab === 'plans' && { borderBottomColor: primaryColor, borderBottomWidth: 2 }
853
+ ]}
854
+ onPress={() => setActiveTab('plans')}
855
+ >
856
+ <Text style={[
857
+ styles.tabText,
858
+ { color: activeTab === 'plans' ? primaryColor : textColor }
859
+ ]}>
860
+ Full Plans
861
+ </Text>
862
+ </TouchableOpacity>
863
+
864
+ <TouchableOpacity
865
+ style={[
866
+ styles.tab,
867
+ activeTab === 'features' && { borderBottomColor: primaryColor, borderBottomWidth: 2 }
868
+ ]}
869
+ onPress={() => setActiveTab('features')}
870
+ >
871
+ <Text style={[
872
+ styles.tabText,
873
+ { color: activeTab === 'features' ? primaryColor : textColor }
874
+ ]}>
875
+ Individual Features
876
+ </Text>
877
+ </TouchableOpacity>
878
+ </View>
879
+ </View>
880
+ );
881
+
882
+ const renderFeatureCard = (feature: IndividualFeature) => {
883
+ const pricing = formatPrice(feature.price, feature.currency, feature.interval);
884
+ const isSubscribed = feature.isSubscribed;
885
+ const isIncludedInCurrentPlan = feature.isIncludedInCurrentPlan;
886
+ const canPurchase = feature.canBePurchasedSeparately && !isIncludedInCurrentPlan;
887
+
888
+ const getCategoryColor = (category: string) => {
889
+ switch (category) {
890
+ case 'analytics': return '#FF9500';
891
+ case 'customization': return '#5856D6';
892
+ case 'content': return '#30D158';
893
+ case 'networking': return '#007AFF';
894
+ case 'productivity': return '#FF3B30';
895
+ default: return primaryColor;
896
+ }
897
+ };
898
+
899
+ const getCategoryIcon = (category: string) => {
900
+ switch (category) {
901
+ case 'analytics': return 'analytics';
902
+ case 'customization': return 'color-palette';
903
+ case 'content': return 'document-text';
904
+ case 'networking': return 'people';
905
+ case 'productivity': return 'briefcase';
906
+ default: return 'star';
907
+ }
908
+ };
909
+
910
+ const getAppScopeText = () => {
911
+ if (feature.appScope === 'ecosystem') {
912
+ return 'Available across all Oxy apps';
913
+ } else {
914
+ return `Available in: ${feature.applicableApps.join(', ')}`;
915
+ }
916
+ };
917
+
918
+ return (
919
+ <View
920
+ key={feature.id}
921
+ style={[
922
+ styles.featureCard,
923
+ { backgroundColor: secondaryBackgroundColor, borderColor },
924
+ isSubscribed && { borderColor: successColor, borderWidth: 2 },
925
+ isIncludedInCurrentPlan && { borderColor: primaryColor, borderWidth: 2 }
926
+ ]}
927
+ >
928
+ <View style={styles.featureHeader}>
929
+ <View style={styles.featureIconContainer}>
930
+ <Ionicons
931
+ name={getCategoryIcon(feature.category) as any}
932
+ size={24}
933
+ color={getCategoryColor(feature.category)}
934
+ />
935
+ </View>
936
+ <View style={styles.featureInfo}>
937
+ <View style={styles.featureNameRow}>
938
+ <Text style={[styles.featureName, { color: textColor }]}>{feature.name}</Text>
939
+ {isIncludedInCurrentPlan && (
940
+ <View style={[styles.includedBadge, { backgroundColor: primaryColor }]}>
941
+ <Text style={styles.includedBadgeText}>Included</Text>
942
+ </View>
943
+ )}
944
+ </View>
945
+ <Text style={[styles.featureDescription, { color: isDarkTheme ? '#BBBBBB' : '#666666' }]}>
946
+ {feature.description}
947
+ </Text>
948
+ <Text style={[styles.appScopeText, { color: isDarkTheme ? '#888888' : '#999999' }]}>
949
+ {getAppScopeText()}
950
+ </Text>
951
+ </View>
952
+ </View>
953
+
954
+ {!isIncludedInCurrentPlan && (
955
+ <View style={styles.featurePricing}>
956
+ <Text style={[styles.featurePrice, { color: textColor }]}>
957
+ {pricing.formatted}
958
+ </Text>
959
+ <Text style={[styles.featureInterval, { color: isDarkTheme ? '#BBBBBB' : '#666666' }]}>
960
+ per {pricing.interval}
961
+ </Text>
962
+ </View>
963
+ )}
964
+
965
+ {isIncludedInCurrentPlan ? (
966
+ <View style={[styles.includedInPlanButton, { backgroundColor: primaryColor }]}>
967
+ <Ionicons name="checkmark-circle" size={16} color="#FFFFFF" />
968
+ <Text style={styles.includedInPlanText}>Included in your plan</Text>
969
+ </View>
970
+ ) : isSubscribed ? (
971
+ <View style={styles.featureActions}>
972
+ <View style={[styles.subscribedButton, { backgroundColor: successColor }]}>
973
+ <Ionicons name="checkmark" size={16} color="#FFFFFF" />
974
+ <Text style={styles.subscribedText}>Subscribed</Text>
975
+ </View>
976
+ <TouchableOpacity
977
+ style={[styles.unsubscribeButton, { borderColor: dangerColor }]}
978
+ onPress={() => handleFeatureUnsubscribe(feature.id)}
979
+ >
980
+ <Text style={[styles.unsubscribeText, { color: dangerColor }]}>Unsubscribe</Text>
981
+ </TouchableOpacity>
982
+ </View>
983
+ ) : canPurchase ? (
984
+ <TouchableOpacity
985
+ style={[styles.subscribeFeatureButton, { backgroundColor: primaryColor }]}
986
+ onPress={() => handleFeatureSubscribe(feature.id)}
987
+ disabled={processingPayment}
988
+ >
989
+ {processingPayment ? (
990
+ <ActivityIndicator color="#FFFFFF" size="small" />
991
+ ) : (
992
+ <Text style={styles.subscribeFeatureText}>Subscribe</Text>
993
+ )}
994
+ </TouchableOpacity>
995
+ ) : (
996
+ <View style={[styles.unavailableButton, { backgroundColor: isDarkTheme ? '#444444' : '#E0E0E0' }]}>
997
+ <Text style={[styles.unavailableText, { color: isDarkTheme ? '#888888' : '#999999' }]}>
998
+ Only available in subscription plans
999
+ </Text>
1000
+ </View>
1001
+ )}
1002
+ </View>
1003
+ );
1004
+ };
1005
+
1006
+ const renderIndividualFeatures = () => {
1007
+ const categories = ['analytics', 'customization', 'content', 'networking', 'productivity'];
1008
+
1009
+ return (
1010
+ <View style={styles.section}>
1011
+ <Text style={[styles.sectionTitle, { color: textColor }]}>Individual Features</Text>
1012
+ <Text style={[styles.sectionSubtitle, { color: isDarkTheme ? '#BBBBBB' : '#666666' }]}>
1013
+ Subscribe to specific features you need. Some features are included in subscription plans.
1014
+ </Text>
1015
+
1016
+ {categories.map(category => {
1017
+ const categoryFeatures = individualFeatures.filter(f => f.category === category);
1018
+ if (categoryFeatures.length === 0) return null;
1019
+
1020
+ return (
1021
+ <View key={category} style={styles.categorySection}>
1022
+ <Text style={[styles.categoryTitle, { color: textColor }]}>
1023
+ {category.charAt(0).toUpperCase() + category.slice(1)}
1024
+ </Text>
1025
+ {categoryFeatures.map(renderFeatureCard)}
1026
+ </View>
1027
+ );
1028
+ })}
1029
+ </View>
1030
+ );
1031
+ };
1032
+
1033
+ // Add this for testing different app contexts (remove in production)
1034
+ const [showAppSwitcher, setShowAppSwitcher] = useState(__DEV__); // Only show in development
1035
+
1036
+ const renderAppSwitcher = () => {
1037
+ if (!showAppSwitcher) return null;
1038
+
1039
+ const testApps = ['mention', 'oxy-social', 'oxy-workspace', 'oxy-creator'];
1040
+
1041
+ return (
1042
+ <View style={[styles.appSwitcher, { backgroundColor: isDarkTheme ? '#333333' : '#F0F0F0', borderColor }]}>
1043
+ <Text style={[styles.appSwitcherTitle, { color: textColor }]}>
1044
+ 🧪 Test App Context (Dev Only)
1045
+ </Text>
1046
+ <ScrollView horizontal showsHorizontalScrollIndicator={false}>
1047
+ <View style={styles.appSwitcherButtons}>
1048
+ {testApps.map(app => (
1049
+ <TouchableOpacity
1050
+ key={app}
1051
+ style={[
1052
+ styles.appSwitcherButton,
1053
+ {
1054
+ backgroundColor: currentAppPackage === app ? primaryColor : 'transparent',
1055
+ borderColor: primaryColor,
1056
+ }
1057
+ ]}
1058
+ onPress={() => {
1059
+ setCurrentAppPackage(app);
1060
+ console.log('Switched to app context:', app);
1061
+ }}
1062
+ >
1063
+ <Text style={[
1064
+ styles.appSwitcherButtonText,
1065
+ { color: currentAppPackage === app ? '#FFFFFF' : textColor }
1066
+ ]}>
1067
+ {app}
1068
+ </Text>
1069
+ </TouchableOpacity>
1070
+ ))}
1071
+ </View>
1072
+ </ScrollView>
1073
+ </View>
1074
+ );
1075
+ };
1076
+
1077
+ if (loading) {
1078
+ return (
1079
+ <View style={[styles.container, { backgroundColor, justifyContent: 'center' }]}>
1080
+ <ActivityIndicator size="large" color={primaryColor} />
1081
+ <Text style={[styles.loadingText, { color: textColor }]}>Loading subscription plans...</Text>
1082
+ </View>
1083
+ );
1084
+ }
1085
+
1086
+ return (
1087
+ <View style={[styles.container, { backgroundColor }]}>
1088
+ {renderHeader()}
1089
+ {renderAppSwitcher()}
1090
+
1091
+ <ScrollView style={styles.content} showsVerticalScrollIndicator={false}>
1092
+ {subscription && renderCurrentSubscription()}
1093
+
1094
+ {!subscription && (
1095
+ <View style={styles.section}>
1096
+ <Text style={[styles.sectionTitle, { color: textColor }]}>Choose Your Plan</Text>
1097
+ <Text style={[styles.sectionSubtitle, { color: isDarkTheme ? '#BBBBBB' : '#666666' }]}>
1098
+ Unlock premium features and take your experience to the next level
1099
+ </Text>
1100
+ </View>
1101
+ )}
1102
+
1103
+ {!subscription && renderTabNavigation()}
1104
+
1105
+ {!subscription && activeTab === 'plans' && renderBillingToggle()}
1106
+
1107
+ {activeTab === 'plans' ? (
1108
+ <View style={styles.section}>
1109
+ {!subscription && (
1110
+ <Text style={[styles.sectionTitle, { color: textColor }]}>Available Plans</Text>
1111
+ )}
1112
+
1113
+ {plans.map(renderPlanCard)}
1114
+ </View>
1115
+ ) : (
1116
+ renderIndividualFeatures()
1117
+ )}
1118
+
1119
+ {/* Features Comparison */}
1120
+ <View style={styles.section}>
1121
+ <Text style={[styles.sectionTitle, { color: textColor }]}>Why Go Premium?</Text>
1122
+
1123
+ <View style={[styles.benefitsCard, { backgroundColor: secondaryBackgroundColor, borderColor }]}>
1124
+ <View style={styles.benefitItem}>
1125
+ <Ionicons name="flash" size={24} color={primaryColor} />
1126
+ <View style={styles.benefitContent}>
1127
+ <Text style={[styles.benefitTitle, { color: textColor }]}>Enhanced Performance</Text>
1128
+ <Text style={[styles.benefitDescription, { color: isDarkTheme ? '#BBBBBB' : '#666666' }]}>
1129
+ Faster processing and priority access to our servers
1130
+ </Text>
1131
+ </View>
1132
+ </View>
1133
+
1134
+ <View style={styles.benefitItem}>
1135
+ <Ionicons name="shield-checkmark" size={24} color={successColor} />
1136
+ <View style={styles.benefitContent}>
1137
+ <Text style={[styles.benefitTitle, { color: textColor }]}>Advanced Security</Text>
1138
+ <Text style={[styles.benefitDescription, { color: isDarkTheme ? '#BBBBBB' : '#666666' }]}>
1139
+ Enhanced encryption and security features
1140
+ </Text>
1141
+ </View>
1142
+ </View>
1143
+
1144
+ <View style={styles.benefitItem}>
1145
+ <Ionicons name="headset" size={24} color={warningColor} />
1146
+ <View style={styles.benefitContent}>
1147
+ <Text style={[styles.benefitTitle, { color: textColor }]}>Priority Support</Text>
1148
+ <Text style={[styles.benefitDescription, { color: isDarkTheme ? '#BBBBBB' : '#666666' }]}>
1149
+ Get help faster with our premium support team
1150
+ </Text>
1151
+ </View>
1152
+ </View>
1153
+ </View>
1154
+ </View>
1155
+
1156
+ <View style={styles.bottomSpacing} />
1157
+ </ScrollView>
1158
+ </View>
1159
+ );
1160
+ };
1161
+
1162
+ const styles = StyleSheet.create({
1163
+ container: {
1164
+ flex: 1,
1165
+ },
1166
+ header: {
1167
+ flexDirection: 'row',
1168
+ alignItems: 'center',
1169
+ justifyContent: 'space-between',
1170
+ paddingHorizontal: 20,
1171
+ paddingTop: 20,
1172
+ paddingBottom: 16,
1173
+ borderBottomWidth: 1,
1174
+ },
1175
+ backButton: {
1176
+ padding: 8,
1177
+ },
1178
+ headerTitle: {
1179
+ fontSize: 20,
1180
+ fontWeight: '600',
1181
+ fontFamily: fontFamilies.phuduSemiBold,
1182
+ },
1183
+ headerTitleContainer: {
1184
+ flex: 1,
1185
+ alignItems: 'center',
1186
+ },
1187
+ currentAppText: {
1188
+ fontSize: 14,
1189
+ marginTop: 2,
1190
+ fontStyle: 'italic',
1191
+ },
1192
+ closeButton: {
1193
+ padding: 8,
1194
+ },
1195
+ content: {
1196
+ flex: 1,
1197
+ },
1198
+ section: {
1199
+ padding: 20,
1200
+ },
1201
+ sectionTitle: {
1202
+ fontSize: 24,
1203
+ fontWeight: 'bold',
1204
+ fontFamily: fontFamilies.phuduBold,
1205
+ marginBottom: 8,
1206
+ },
1207
+ sectionSubtitle: {
1208
+ fontSize: 16,
1209
+ lineHeight: 22,
1210
+ marginBottom: 20,
1211
+ },
1212
+ loadingText: {
1213
+ fontSize: 16,
1214
+ textAlign: 'center',
1215
+ marginTop: 16,
1216
+ },
1217
+ currentSubscriptionCard: {
1218
+ borderRadius: 16,
1219
+ padding: 20,
1220
+ borderWidth: 1,
1221
+ },
1222
+ subscriptionHeader: {
1223
+ flexDirection: 'row',
1224
+ justifyContent: 'space-between',
1225
+ alignItems: 'flex-start',
1226
+ marginBottom: 12,
1227
+ },
1228
+ planName: {
1229
+ fontSize: 20,
1230
+ fontWeight: 'bold',
1231
+ marginBottom: 4,
1232
+ },
1233
+ planPrice: {
1234
+ fontSize: 16,
1235
+ fontWeight: '600',
1236
+ },
1237
+ statusBadge: {
1238
+ paddingHorizontal: 12,
1239
+ paddingVertical: 4,
1240
+ borderRadius: 12,
1241
+ },
1242
+ statusText: {
1243
+ color: '#FFFFFF',
1244
+ fontSize: 12,
1245
+ fontWeight: '600',
1246
+ },
1247
+ subscriptionDetail: {
1248
+ fontSize: 14,
1249
+ marginBottom: 16,
1250
+ },
1251
+ cancelNotice: {
1252
+ flexDirection: 'row',
1253
+ alignItems: 'center',
1254
+ padding: 12,
1255
+ backgroundColor: 'rgba(255, 149, 0, 0.1)',
1256
+ borderRadius: 8,
1257
+ marginBottom: 16,
1258
+ },
1259
+ cancelText: {
1260
+ fontSize: 14,
1261
+ marginLeft: 8,
1262
+ flex: 1,
1263
+ },
1264
+ subscriptionActions: {
1265
+ flexDirection: 'row',
1266
+ gap: 12,
1267
+ },
1268
+ actionButton: {
1269
+ flex: 1,
1270
+ paddingVertical: 12,
1271
+ paddingHorizontal: 16,
1272
+ borderRadius: 8,
1273
+ alignItems: 'center',
1274
+ },
1275
+ secondaryButton: {
1276
+ backgroundColor: 'transparent',
1277
+ borderWidth: 1,
1278
+ },
1279
+ actionButtonText: {
1280
+ color: '#FFFFFF',
1281
+ fontSize: 14,
1282
+ fontWeight: '600',
1283
+ },
1284
+ billingToggle: {
1285
+ flexDirection: 'row',
1286
+ backgroundColor: 'rgba(0, 0, 0, 0.05)',
1287
+ borderRadius: 8,
1288
+ padding: 4,
1289
+ marginBottom: 12,
1290
+ },
1291
+ billingOption: {
1292
+ flex: 1,
1293
+ paddingVertical: 12,
1294
+ borderRadius: 6,
1295
+ alignItems: 'center',
1296
+ },
1297
+ billingOptionText: {
1298
+ fontSize: 16,
1299
+ fontWeight: '600',
1300
+ },
1301
+ savingsText: {
1302
+ fontSize: 14,
1303
+ textAlign: 'center',
1304
+ fontWeight: '600',
1305
+ },
1306
+ planCard: {
1307
+ borderRadius: 16,
1308
+ padding: 20,
1309
+ marginBottom: 16,
1310
+ borderWidth: 1,
1311
+ position: 'relative',
1312
+ },
1313
+ popularPlan: {
1314
+ borderWidth: 2,
1315
+ },
1316
+ popularBadge: {
1317
+ position: 'absolute',
1318
+ top: -1,
1319
+ left: 20,
1320
+ right: 20,
1321
+ paddingVertical: 8,
1322
+ borderTopLeftRadius: 16,
1323
+ borderTopRightRadius: 16,
1324
+ alignItems: 'center',
1325
+ },
1326
+ popularText: {
1327
+ color: '#FFFFFF',
1328
+ fontSize: 12,
1329
+ fontWeight: 'bold',
1330
+ },
1331
+ planHeader: {
1332
+ marginBottom: 16,
1333
+ marginTop: 16,
1334
+ },
1335
+ planDescription: {
1336
+ fontSize: 14,
1337
+ lineHeight: 20,
1338
+ },
1339
+ planAppScope: {
1340
+ fontSize: 12,
1341
+ fontStyle: 'italic',
1342
+ marginTop: 4,
1343
+ },
1344
+ planPricing: {
1345
+ flexDirection: 'row',
1346
+ alignItems: 'baseline',
1347
+ marginBottom: 20,
1348
+ },
1349
+ planInterval: {
1350
+ fontSize: 14,
1351
+ marginLeft: 4,
1352
+ },
1353
+ planFeatures: {
1354
+ marginBottom: 24,
1355
+ },
1356
+ featureItem: {
1357
+ flexDirection: 'row',
1358
+ alignItems: 'center',
1359
+ marginBottom: 8,
1360
+ },
1361
+ featureText: {
1362
+ fontSize: 14,
1363
+ marginLeft: 8,
1364
+ flex: 1,
1365
+ },
1366
+ selectPlanButton: {
1367
+ paddingVertical: 16,
1368
+ borderRadius: 12,
1369
+ alignItems: 'center',
1370
+ },
1371
+ selectPlanText: {
1372
+ fontSize: 16,
1373
+ fontWeight: '600',
1374
+ },
1375
+ currentPlanButton: {
1376
+ paddingVertical: 16,
1377
+ borderRadius: 12,
1378
+ alignItems: 'center',
1379
+ },
1380
+ currentPlanText: {
1381
+ color: '#FFFFFF',
1382
+ fontSize: 16,
1383
+ fontWeight: '600',
1384
+ },
1385
+ benefitsCard: {
1386
+ borderRadius: 16,
1387
+ padding: 20,
1388
+ borderWidth: 1,
1389
+ },
1390
+ benefitItem: {
1391
+ flexDirection: 'row',
1392
+ alignItems: 'flex-start',
1393
+ marginBottom: 20,
1394
+ },
1395
+ benefitContent: {
1396
+ marginLeft: 16,
1397
+ flex: 1,
1398
+ },
1399
+ benefitTitle: {
1400
+ fontSize: 16,
1401
+ fontWeight: '600',
1402
+ marginBottom: 4,
1403
+ },
1404
+ benefitDescription: {
1405
+ fontSize: 14,
1406
+ lineHeight: 20,
1407
+ },
1408
+ bottomSpacing: {
1409
+ height: 40,
1410
+ },
1411
+ // Tab Navigation Styles
1412
+ tabContainer: {
1413
+ flexDirection: 'row',
1414
+ borderBottomWidth: 1,
1415
+ marginBottom: 20,
1416
+ },
1417
+ tab: {
1418
+ flex: 1,
1419
+ paddingVertical: 12,
1420
+ paddingHorizontal: 16,
1421
+ alignItems: 'center',
1422
+ },
1423
+ tabText: {
1424
+ fontSize: 16,
1425
+ fontWeight: '600',
1426
+ },
1427
+ // Individual Feature Styles
1428
+ featureCard: {
1429
+ borderRadius: 12,
1430
+ borderWidth: 1,
1431
+ padding: 16,
1432
+ marginBottom: 12,
1433
+ },
1434
+ featureHeader: {
1435
+ flexDirection: 'row',
1436
+ alignItems: 'flex-start',
1437
+ marginBottom: 12,
1438
+ },
1439
+ featureIconContainer: {
1440
+ width: 40,
1441
+ height: 40,
1442
+ borderRadius: 20,
1443
+ backgroundColor: 'rgba(0, 122, 255, 0.1)',
1444
+ justifyContent: 'center',
1445
+ alignItems: 'center',
1446
+ marginRight: 12,
1447
+ },
1448
+ featureInfo: {
1449
+ flex: 1,
1450
+ },
1451
+ featureName: {
1452
+ fontSize: 16,
1453
+ fontWeight: '600',
1454
+ marginBottom: 4,
1455
+ },
1456
+ featureDescription: {
1457
+ fontSize: 14,
1458
+ lineHeight: 20,
1459
+ },
1460
+ featurePricing: {
1461
+ alignItems: 'center',
1462
+ marginBottom: 16,
1463
+ },
1464
+ featurePrice: {
1465
+ fontSize: 20,
1466
+ fontWeight: 'bold',
1467
+ },
1468
+ featureInterval: {
1469
+ fontSize: 14,
1470
+ marginTop: 2,
1471
+ },
1472
+ featureActions: {
1473
+ flexDirection: 'row',
1474
+ gap: 8,
1475
+ },
1476
+ subscribedButton: {
1477
+ flex: 1,
1478
+ flexDirection: 'row',
1479
+ justifyContent: 'center',
1480
+ alignItems: 'center',
1481
+ paddingVertical: 12,
1482
+ borderRadius: 8,
1483
+ gap: 6,
1484
+ },
1485
+ subscribedText: {
1486
+ color: '#FFFFFF',
1487
+ fontSize: 16,
1488
+ fontWeight: '600',
1489
+ },
1490
+ unsubscribeButton: {
1491
+ flex: 1,
1492
+ justifyContent: 'center',
1493
+ alignItems: 'center',
1494
+ paddingVertical: 12,
1495
+ borderRadius: 8,
1496
+ borderWidth: 1,
1497
+ },
1498
+ unsubscribeText: {
1499
+ fontSize: 16,
1500
+ fontWeight: '600',
1501
+ },
1502
+ subscribeFeatureButton: {
1503
+ justifyContent: 'center',
1504
+ alignItems: 'center',
1505
+ paddingVertical: 12,
1506
+ borderRadius: 8,
1507
+ },
1508
+ subscribeFeatureText: {
1509
+ color: '#FFFFFF',
1510
+ fontSize: 16,
1511
+ fontWeight: '600',
1512
+ },
1513
+ categorySection: {
1514
+ marginBottom: 24,
1515
+ },
1516
+ categoryTitle: {
1517
+ fontSize: 18,
1518
+ fontWeight: '600',
1519
+ marginBottom: 12,
1520
+ },
1521
+ // New styles for enhanced feature cards
1522
+ featureNameRow: {
1523
+ flexDirection: 'row',
1524
+ alignItems: 'center',
1525
+ justifyContent: 'space-between',
1526
+ marginBottom: 4,
1527
+ },
1528
+ includedBadge: {
1529
+ paddingHorizontal: 8,
1530
+ paddingVertical: 2,
1531
+ borderRadius: 12,
1532
+ marginLeft: 8,
1533
+ },
1534
+ includedBadgeText: {
1535
+ color: '#FFFFFF',
1536
+ fontSize: 10,
1537
+ fontWeight: '600',
1538
+ textTransform: 'uppercase',
1539
+ },
1540
+ appScopeText: {
1541
+ fontSize: 12,
1542
+ marginTop: 4,
1543
+ fontStyle: 'italic',
1544
+ },
1545
+ includedInPlanButton: {
1546
+ flexDirection: 'row',
1547
+ justifyContent: 'center',
1548
+ alignItems: 'center',
1549
+ paddingVertical: 12,
1550
+ borderRadius: 8,
1551
+ gap: 6,
1552
+ },
1553
+ includedInPlanText: {
1554
+ color: '#FFFFFF',
1555
+ fontSize: 14,
1556
+ fontWeight: '600',
1557
+ },
1558
+ unavailableButton: {
1559
+ justifyContent: 'center',
1560
+ alignItems: 'center',
1561
+ paddingVertical: 12,
1562
+ borderRadius: 8,
1563
+ },
1564
+ unavailableText: {
1565
+ fontSize: 14,
1566
+ fontWeight: '500',
1567
+ textAlign: 'center',
1568
+ },
1569
+ // App-specific plan styles
1570
+ appSpecificBadge: {
1571
+ position: 'absolute',
1572
+ top: 16,
1573
+ right: 16,
1574
+ paddingHorizontal: 8,
1575
+ paddingVertical: 4,
1576
+ borderRadius: 12,
1577
+ zIndex: 1,
1578
+ },
1579
+ appSpecificText: {
1580
+ color: '#FFFFFF',
1581
+ fontSize: 12,
1582
+ fontWeight: '600',
1583
+ },
1584
+ planRestrictionText: {
1585
+ fontSize: 12,
1586
+ fontWeight: '500',
1587
+ marginTop: 4,
1588
+ fontStyle: 'italic',
1589
+ },
1590
+ unavailablePlanButton: {
1591
+ paddingVertical: 16,
1592
+ borderRadius: 12,
1593
+ alignItems: 'center',
1594
+ },
1595
+ unavailablePlanText: {
1596
+ fontSize: 16,
1597
+ fontWeight: '600',
1598
+ },
1599
+ // App switcher styles (for development/testing)
1600
+ appSwitcher: {
1601
+ padding: 16,
1602
+ borderBottomWidth: 1,
1603
+ margin: 16,
1604
+ borderRadius: 12,
1605
+ borderWidth: 1,
1606
+ },
1607
+ appSwitcherTitle: {
1608
+ fontSize: 14,
1609
+ fontWeight: '600',
1610
+ marginBottom: 12,
1611
+ },
1612
+ appSwitcherButtons: {
1613
+ flexDirection: 'row',
1614
+ gap: 8,
1615
+ },
1616
+ appSwitcherButton: {
1617
+ paddingHorizontal: 12,
1618
+ paddingVertical: 6,
1619
+ borderRadius: 8,
1620
+ borderWidth: 1,
1621
+ },
1622
+ appSwitcherButtonText: {
1623
+ fontSize: 12,
1624
+ fontWeight: '500',
1625
+ },
1626
+ });
1627
+
1628
+ export default PremiumSubscriptionScreen;