@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
@@ -1,116 +1,41 @@
1
- import type React from 'react';
2
- import { useState, useRef, useMemo, useCallback, useEffect } from 'react';
1
+ import React, { useState, useRef, useMemo, useCallback } from 'react';
3
2
  import {
4
3
  View,
5
4
  Text,
6
- TouchableOpacity,
7
- StyleSheet,
8
- Platform,
9
- KeyboardAvoidingView,
10
5
  ScrollView,
11
6
  Animated,
12
- StatusBar,
13
- ScrollView as RNScrollView,
14
- Dimensions,
15
- Linking,
16
- Clipboard,
7
+ Platform,
17
8
  useWindowDimensions,
18
9
  } from 'react-native';
19
10
  import type { BaseScreenProps } from '../types/navigation';
20
- import { fontFamilies, useThemeColors, createCommonStyles } from '../styles';
11
+ import { useThemeColors } from '../styles';
21
12
  import { normalizeTheme } from '../utils/themeUtils';
22
- import OxyLogo from '../components/OxyLogo';
23
13
  import GroupedPillButtons from '../components/internal/GroupedPillButtons';
24
- import TextField from '../components/TextField';
25
- import { Ionicons } from '@expo/vector-icons';
26
- import { FAIRWalletIcon } from '../components/icon';
27
- import { toast } from 'sonner';
28
- import QRCode from 'react-native-qrcode-svg';
29
-
30
- import { GroupedSection } from '../components';
31
14
  import { useThemeStyles } from '../hooks/useThemeStyles';
15
+ import QRCode from 'react-native-qrcode-svg';
32
16
 
33
- // Restrict payment methods to Card, Oxy Pay, and FairCoin (QR)
34
- const PAYMENT_METHODS = [
35
- { key: 'card', label: 'Credit/Debit Card', icon: 'card-outline', description: 'Pay securely with your credit or debit card.' },
36
- { key: 'oxy', label: 'Oxy Pay', icon: 'wallet-outline', description: 'Use your Oxy Pay in-app balance.' },
37
- { key: 'faircoin', label: 'FAIRWallet', icon: 'qr-code-outline', description: 'Pay with FairCoin by scanning a QR code.' },
38
- ];
39
-
40
-
41
-
42
- // Add PaymentItem type
43
- export type PaymentItem = {
44
- type: 'product' | 'subscription' | 'service' | 'fee' | string;
45
- name: string;
46
- description?: string;
47
- quantity?: number; // for products
48
- period?: string; // for subscriptions, e.g. 'Monthly'
49
- price: number;
50
- currency?: string; // fallback to main currency if not set
51
- };
52
-
53
- // Extend props to accept onPaymentResult, amount, and currency
54
- export interface PaymentGatewayResult {
55
- success: boolean;
56
- details?: Record<string, string | number | boolean | null>;
57
- error?: string;
58
- }
17
+ import {
18
+ PaymentSummaryStep,
19
+ PaymentMethodStep,
20
+ PaymentDetailsStep,
21
+ PaymentReviewStep,
22
+ PaymentSuccessStep,
23
+ PAYMENT_METHODS,
24
+ createPaymentStyles,
25
+ } from '../components/payment';
26
+ import type { PaymentItem, PaymentGatewayResult, CardDetails } from '../components/payment';
27
+
28
+ export type { PaymentItem, PaymentGatewayResult };
59
29
 
60
30
  interface PaymentGatewayScreenProps extends BaseScreenProps {
61
31
  onPaymentResult?: (result: PaymentGatewayResult) => void;
62
32
  amount: string | number;
63
- currency?: string; // e.g. 'FAIR', 'INR', 'USD', 'EUR', 'GBP', etc.
33
+ currency?: string;
64
34
  onClose?: () => void;
65
- paymentItems?: PaymentItem[]; // NEW: generic items
66
- description?: string; // NEW: fallback if no items
35
+ paymentItems?: PaymentItem[];
36
+ description?: string;
67
37
  }
68
38
 
69
- // Currency symbol map
70
- const CURRENCY_SYMBOLS: Record<string, string> = {
71
- FAIR: '⊜',
72
- INR: '₹',
73
- USD: '$',
74
- EUR: '€',
75
- GBP: '£',
76
- JPY: '¥',
77
- CNY: '¥',
78
- AUD: 'A$',
79
- CAD: 'C$',
80
- // Add more as needed
81
- };
82
-
83
- const CURRENCY_NAMES: Record<string, string> = {
84
- FAIR: 'FairCoin',
85
- INR: 'Indian Rupee',
86
- USD: 'US Dollar',
87
- EUR: 'Euro',
88
- GBP: 'British Pound',
89
- JPY: 'Japanese Yen',
90
- CNY: 'Chinese Yuan',
91
- AUD: 'Australian Dollar',
92
- CAD: 'Canadian Dollar',
93
- // Add more as needed
94
- };
95
-
96
- // Helper: icon for item type (Ionicons only)
97
- const getItemTypeIcon = (type: string, color: string) => {
98
- switch (type) {
99
- case 'product':
100
- return <Ionicons name="cart-outline" size={22} color={color} style={{ marginRight: 8 }} />;
101
- case 'subscription':
102
- return <Ionicons name="repeat-outline" size={22} color={color} style={{ marginRight: 8 }} />;
103
- case 'service':
104
- return <Ionicons name="construct-outline" size={22} color={color} style={{ marginRight: 8 }} />;
105
- case 'fee':
106
- return <Ionicons name="cash-outline" size={22} color={color} style={{ marginRight: 8 }} />;
107
- default:
108
- return <Ionicons name="pricetag-outline" size={22} color={color} style={{ marginRight: 8 }} />;
109
- }
110
- };
111
-
112
-
113
- // Helper to get unique item types (move to top-level, before component)
114
39
  const getUniqueItemTypes = (items: PaymentItem[]) => {
115
40
  const types = items.map(item => item.type);
116
41
  return Array.from(new Set(types));
@@ -125,8 +50,8 @@ const PaymentGatewayScreen: React.FC<PaymentGatewayScreenProps> = (props) => {
125
50
  amount,
126
51
  currency = 'FAIR',
127
52
  onClose,
128
- paymentItems = [], // NEW
129
- description = '', // NEW
53
+ paymentItems = [],
54
+ description = '',
130
55
  } = props;
131
56
 
132
57
  // DEV ENFORCEMENT: Only allow one type of payment item
@@ -142,12 +67,8 @@ const PaymentGatewayScreen: React.FC<PaymentGatewayScreenProps> = (props) => {
142
67
  // Step states
143
68
  const [currentStep, setCurrentStep] = useState(0);
144
69
  const [paymentMethod, setPaymentMethod] = useState('card');
145
- const [cardDetails, setCardDetails] = useState({ number: '', expiry: '', cvv: '' });
146
- const [upiId, setUpiId] = useState('');
70
+ const [cardDetails, setCardDetails] = useState<CardDetails>({ number: '', expiry: '', cvv: '' });
147
71
  const [isPaying, setIsPaying] = useState(false);
148
- const [success, setSuccess] = useState(false);
149
-
150
-
151
72
 
152
73
  // Animations
153
74
  const fadeAnim = useRef(new Animated.Value(1)).current;
@@ -157,23 +78,8 @@ const PaymentGatewayScreen: React.FC<PaymentGatewayScreenProps> = (props) => {
157
78
 
158
79
  const normalizedTheme = normalizeTheme(theme);
159
80
  const colors = useThemeColors(normalizedTheme);
160
- const commonStyles = createCommonStyles(normalizedTheme);
161
- const styles = useMemo(() => createStyles(colors, normalizedTheme), [colors, normalizedTheme]);
162
-
163
- // Get symbol and name for currency
164
- const currencySymbol = CURRENCY_SYMBOLS[currency.toUpperCase()] || currency;
165
- const currencyName = CURRENCY_NAMES[currency.toUpperCase()] || currency;
166
-
167
- // Calculate total from items if provided, else use amount
168
- const computedTotal = useMemo(() => {
169
- if (paymentItems && paymentItems.length > 0) {
170
- return paymentItems.reduce((sum, item) => {
171
- const qty = item.quantity ?? 1;
172
- return sum + (item.price * qty);
173
- }, 0);
174
- }
175
- return Number(amount) || 0;
176
- }, [paymentItems, amount]);
81
+ const themeStyles = useThemeStyles(normalizedTheme);
82
+ const styles = useMemo(() => createPaymentStyles(colors), [colors]);
177
83
 
178
84
  // Determine if the payment is for a recurring item (subscription)
179
85
  const isRecurring = paymentItems.length > 0 && paymentItems[0].type === 'subscription';
@@ -186,15 +92,6 @@ const PaymentGatewayScreen: React.FC<PaymentGatewayScreenProps> = (props) => {
186
92
  return PAYMENT_METHODS;
187
93
  }, [isRecurring]);
188
94
 
189
- // Add after useState declarations
190
- // Remove itemTypeError state, useEffect, and user-facing error in renderSummaryStep
191
-
192
- // Helper to get unique item types
193
- // Remove itemTypeError state, useEffect, and user-facing error in renderSummaryStep
194
-
195
- // Validate item types on paymentItems change
196
- // Remove itemTypeError state, useEffect, and user-facing error in renderSummaryStep
197
-
198
95
  // Animation transitions
199
96
  const animateTransition = useCallback((nextStep: number) => {
200
97
  Animated.timing(scaleAnim, {
@@ -230,7 +127,7 @@ const PaymentGatewayScreen: React.FC<PaymentGatewayScreenProps> = (props) => {
230
127
  })
231
128
  ]).start();
232
129
  });
233
- }, []);
130
+ }, [fadeAnim, slideAnim, scaleAnim]);
234
131
 
235
132
  const nextStep = useCallback(() => {
236
133
  if (currentStep < 4) {
@@ -254,17 +151,15 @@ const PaymentGatewayScreen: React.FC<PaymentGatewayScreenProps> = (props) => {
254
151
  }
255
152
  }, [currentStep, progressAnim, animateTransition]);
256
153
 
257
- // Dummy pay handler
154
+ // Pay handler - TODO: Replace with actual payment API
258
155
  const handlePay = useCallback(() => {
259
156
  setIsPaying(true);
260
157
  setTimeout(() => {
261
158
  setIsPaying(false);
262
- setSuccess(true);
263
159
  nextStep();
264
160
  }, 1500);
265
161
  }, [nextStep]);
266
162
 
267
- // Success handler for Done button
268
163
  const handleDone = useCallback(() => {
269
164
  if (onPaymentResult) {
270
165
  onPaymentResult({ success: true });
@@ -272,7 +167,6 @@ const PaymentGatewayScreen: React.FC<PaymentGatewayScreenProps> = (props) => {
272
167
  navigate?.('AccountOverview');
273
168
  }, [onPaymentResult, navigate]);
274
169
 
275
- // Handle close/cancel: return failure result if payment is not completed
276
170
  const handleClose = useCallback(() => {
277
171
  if (onPaymentResult) {
278
172
  onPaymentResult({ success: false, error: 'cancelled' });
@@ -284,10 +178,7 @@ const PaymentGatewayScreen: React.FC<PaymentGatewayScreenProps> = (props) => {
284
178
  }
285
179
  }, [onPaymentResult, onClose, goBack]);
286
180
 
287
- // Optionally, intercept goBack/onClose if user tries to close the screen
288
- // (You may want to use useEffect to listen for unmount or navigation away)
289
-
290
- // If amount is missing or invalid, show error
181
+ // Validate amount
291
182
  if (!amount || isNaN(Number(amount)) || Number(amount) <= 0) {
292
183
  return (
293
184
  <View style={styles.errorContainer}>
@@ -301,13 +192,13 @@ const PaymentGatewayScreen: React.FC<PaymentGatewayScreenProps> = (props) => {
301
192
  variant: 'primary',
302
193
  },
303
194
  ]}
304
- colors={useThemeColors(normalizedTheme)}
195
+ colors={colors}
305
196
  />
306
197
  </View>
307
198
  );
308
199
  }
309
200
 
310
- // Example FairCoin address (replace with real one)
201
+ // FairCoin address - TODO: Replace with dynamic address from backend
311
202
  const faircoinAddress = 'f1abc1234FAIRCOINADDRESS';
312
203
  const { width: windowWidth } = useWindowDimensions();
313
204
  const isMobile = windowWidth < 600;
@@ -315,508 +206,80 @@ const PaymentGatewayScreen: React.FC<PaymentGatewayScreenProps> = (props) => {
315
206
  ? Math.min(windowWidth * 0.3, 220)
316
207
  : Math.min(windowWidth * 0.8, 300);
317
208
 
318
- const handleCopyAddress = () => {
319
- Clipboard.setString(faircoinAddress);
320
- toast('Address copied to clipboard!');
321
- };
322
- const handleOpenFairWallet = () => {
323
- const url = `fairwallet://pay?address=${faircoinAddress}`;
324
- Linking.openURL(url);
325
- };
326
-
327
-
328
-
329
- // Helper for dynamic styles
330
- const getStepIndicatorStyle = (active: boolean) => [
331
- styles.stepIndicator,
332
- active ? styles.stepIndicatorActive : styles.stepIndicatorInactive,
333
- ];
334
-
335
- const getPaymentMethodButtonStyle = (active: boolean) => [
336
- styles.paymentMethodButton,
337
- active ? styles.paymentMethodButtonActive : styles.paymentMethodButtonInactive,
338
- ];
339
-
340
- const getPaymentMethodIconColor = (active: boolean) => (
341
- active ? colors.primary : colors.text
342
- );
343
-
344
- // Step indicator
345
- const renderStepIndicator = () => {
346
- const totalSteps = 5;
347
- const activeStep = currentStep + 1;
348
- return (
349
- <View style={styles.stepIndicatorContainer}>
350
- {Array.from({ length: totalSteps }).map((_, idx) => (
351
- <View
352
- key={idx}
353
- style={getStepIndicatorStyle(activeStep === idx + 1)}
354
- />
355
- ))}
356
- </View>
357
- );
358
- };
359
-
360
- // PaymentGatewayHeader component
361
- const stepTitles = [
362
- 'Complete Your Payment',
363
- 'Select Payment Method',
364
- 'Enter Payment Details',
365
- 'Review & Pay',
366
- 'Success',
367
- ];
368
-
369
-
370
-
371
-
372
-
373
-
374
- // Step 1: Summary step (new first step, no header/dots here)
375
- const renderSummaryStep = () => (
376
- <Animated.View style={[styles.stepContainer, {
377
- opacity: fadeAnim,
378
- transform: [
379
- { translateY: slideAnim },
380
- { scale: scaleAnim },
381
- ]
382
- }]}
383
- >
384
- <View style={styles.section}>
385
- <Text style={styles.sectionTitle}>Payment Summary</Text>
386
-
387
- <View style={styles.summaryCard}>
388
- <View style={styles.summaryCardContent}>
389
- <Ionicons name="receipt-outline" size={64} color={colors.primary} style={styles.summaryCardIcon} />
390
- <Text style={styles.summaryCardMainTitle}>
391
- {paymentItems && paymentItems.length > 0 ? 'Order Summary' : 'Payment'}
392
- </Text>
393
- <Text style={styles.summaryCardSubtitle}>
394
- {paymentItems && paymentItems.length > 0 ? 'Review your payment details' : 'Complete your payment'}
395
- </Text>
396
-
397
- {paymentItems && paymentItems.length > 0 ? (
398
- <>
399
- <View style={styles.summaryCardItems}>
400
- <GroupedSection
401
- items={paymentItems.map((item, idx) => ({
402
- id: `item-${idx}`,
403
- icon: getItemTypeIcon(item.type, colors.primary).props.name,
404
- iconColor: colors.primary,
405
- title: `${item.type === 'product' && item.quantity ? `${item.quantity} × ` : ''}${item.name}${item.type === 'subscription' && item.period ? ` (${item.period})` : ''}`,
406
- subtitle: item.description || `${(item.currency ? (CURRENCY_SYMBOLS[item.currency.toUpperCase()] || item.currency) : currencySymbol)} ${item.price * (item.quantity ?? 1)}`,
407
- customContent: (
408
- <Text style={styles.summaryItemPrice}>
409
- {(item.currency ? (CURRENCY_SYMBOLS[item.currency.toUpperCase()] || item.currency) : currencySymbol)} {item.price * (item.quantity ?? 1)}
410
- </Text>
411
- ),
412
- }))}
413
-
414
- />
415
- </View>
416
-
417
- <View style={styles.summaryCardDivider} />
418
-
419
- <View style={styles.summaryCardTotalSection}>
420
- <View style={styles.summaryCardTotalRow}>
421
- <Text style={styles.summaryCardTotalLabel}>Subtotal</Text>
422
- <Text style={styles.summaryCardTotalValue}>{(currencySymbol)} {amount}</Text>
423
- </View>
424
- <View style={styles.summaryCardTotalRow}>
425
- <Text style={styles.summaryCardTotalLabel}>Tax</Text>
426
- <Text style={styles.summaryCardTotalValue}>{(currencySymbol)} 0.00</Text>
427
- </View>
428
- <View style={styles.summaryCardTotalRow}>
429
- <Text style={styles.summaryCardTotalLabel}>Total</Text>
430
- <Text style={styles.summaryCardTotalValue}>{(currencySymbol)} {amount}</Text>
431
- </View>
432
- </View>
433
- </>
434
- ) : (
435
- <>
436
- <View style={styles.summaryCardAmount}>
437
- <Text style={styles.summaryCardAmountLabel}>Amount to Pay</Text>
438
- <Text style={styles.summaryCardAmountValue}>{(currencySymbol)} {amount}</Text>
439
- {description && (
440
- <Text style={styles.summaryCardAmountDescription}>{description}</Text>
441
- )}
442
- </View>
443
-
444
- <View style={styles.summaryCardDivider} />
445
-
446
- <View style={styles.summaryCardTotalSection}>
447
- <View style={styles.summaryCardTotalRow}>
448
- <Text style={styles.summaryCardTotalLabel}>Total</Text>
449
- <Text style={styles.summaryCardTotalValue}>{(currencySymbol)} {amount}</Text>
450
- </View>
451
- </View>
452
- </>
453
- )}
454
- </View>
455
- </View>
456
- </View>
457
-
458
- <GroupedPillButtons
459
- buttons={[
460
- {
461
- text: 'Close',
462
- onPress: handleClose,
463
- icon: 'close',
464
- variant: 'transparent',
465
- },
466
- {
467
- text: 'Continue',
468
- onPress: nextStep,
469
- icon: 'arrow-forward',
470
- variant: 'primary',
471
- },
472
- ]}
473
- colors={colors}
474
- />
475
- </Animated.View>
476
- );
477
-
478
- // Step 2: Choose Payment Method (now the second step, no header/dots here)
479
- const renderMethodStep = () => (
480
- <Animated.View style={[styles.stepContainer, {
481
- opacity: fadeAnim,
482
- transform: [
483
- { translateY: slideAnim },
484
- { scale: scaleAnim },
485
- ]
486
- }]}
487
- >
488
- <View style={styles.section}>
489
- <Text style={styles.sectionTitle}>Choose Payment Method</Text>
490
-
491
- <GroupedSection
492
- items={availablePaymentMethods.map(method => ({
493
- id: method.key,
494
- icon: method.key === 'faircoin' ? undefined : method.icon,
495
- iconColor: method.key === 'card' ? '#007AFF' :
496
- method.key === 'oxy' ? '#32D74B' :
497
- method.key === 'faircoin' ? '#9ffb50' : colors.primary,
498
- title: method.label,
499
- subtitle: method.description,
500
- onPress: () => setPaymentMethod(method.key),
501
- selected: paymentMethod === method.key,
502
- showChevron: false,
503
- customIcon: method.key === 'faircoin' ? (
504
- <FAIRWalletIcon size={20} />
505
- ) : undefined,
506
- }))}
507
-
508
- />
509
- </View>
510
-
511
- <GroupedPillButtons
512
- buttons={[
513
- {
514
- text: 'Back',
515
- onPress: prevStep,
516
- icon: 'arrow-back',
517
- variant: 'transparent',
518
- },
519
- {
520
- text: 'Continue',
521
- onPress: nextStep,
522
- icon: 'arrow-forward',
523
- variant: 'primary',
524
- },
525
- ]}
526
- colors={colors}
527
- />
528
- </Animated.View>
529
- );
530
-
531
- // Step 2: Enter Payment Details
532
- const renderDetailsStep = () => (
533
- <Animated.View style={[styles.stepContainer, {
534
- opacity: fadeAnim,
535
- transform: [
536
- { translateY: slideAnim },
537
- { scale: scaleAnim },
538
- ]
539
- }]}
540
- >
541
- <View style={styles.section}>
542
- <Text style={styles.sectionTitle}>
543
- {paymentMethod === 'card' ? 'Card Details' :
544
- paymentMethod === 'oxy' ? 'Oxy Pay' :
545
- paymentMethod === 'faircoin' ? 'FairCoin Payment' : 'Payment Details'}
546
- </Text>
547
-
548
- {paymentMethod === 'card' && (
549
- <View style={styles.cardPaymentCard}>
550
- <View style={styles.cardPaymentContent}>
551
- <Ionicons name="card-outline" size={64} color={colors.primary} style={styles.cardPaymentIcon} />
552
- <Text style={styles.cardPaymentMainTitle}>Credit Card</Text>
553
- <Text style={styles.cardPaymentSubtitle}>Enter your card details securely</Text>
554
-
555
- <View style={styles.cardPaymentFields}>
556
- <View style={styles.cardRowInfo}>
557
- <Ionicons name="card-outline" size={24} color={colors.primary} style={styles.cardRowIcon} />
558
- <Text style={styles.cardRowText}>We accept Visa, Mastercard, and more</Text>
559
- </View>
560
- <TextField
561
- value={cardDetails.number}
562
- onChangeText={text => {
563
- // Format card number with spaces
564
- const formatted = text.replace(/\s/g, '').replace(/(\d{4})/g, '$1 ').trim();
565
- setCardDetails({ ...cardDetails, number: formatted });
566
- }}
567
- placeholder="1234 5678 9012 3456"
568
- keyboardType="numeric"
569
- maxLength={19}
570
- style={styles.cardFieldContainer}
571
- left={<Ionicons name="card-outline" size={18} color={colors.primary} />}
572
- />
573
- <View style={styles.cardFieldRow}>
574
- <TextField
575
- value={cardDetails.expiry}
576
- onChangeText={text => {
577
- // Format expiry date
578
- const formatted = text.replace(/\D/g, '').replace(/(\d{2})(\d)/, '$1/$2');
579
- setCardDetails({ ...cardDetails, expiry: formatted });
580
- }}
581
- placeholder="MM/YY"
582
- maxLength={5}
583
- style={styles.cardFieldHalfLeft}
584
- left={<Ionicons name="calendar-outline" size={16} color={colors.primary} />}
585
- />
586
- <TextField
587
- value={cardDetails.cvv}
588
- onChangeText={text => {
589
- // Only allow numbers
590
- const formatted = text.replace(/\D/g, '');
591
- setCardDetails({ ...cardDetails, cvv: formatted });
592
- }}
593
- placeholder="123"
594
- keyboardType="numeric"
595
- maxLength={4}
596
- style={styles.cardFieldHalfRight}
597
- left={<Ionicons name="lock-closed-outline" size={16} color={colors.primary} />}
598
- />
599
- </View>
600
- </View>
601
-
602
- <View style={{ height: 18 }} />
603
- <Text style={styles.cardPaymentWaiting}>Ready to process payment...</Text>
604
- </View>
605
- </View>
606
- )}
607
- {paymentMethod === 'oxy' && (
608
- <View style={styles.oxyPayCard}>
609
- <View style={styles.oxyPayContent}>
610
- <Ionicons name="wallet-outline" size={64} color={colors.primary} style={styles.oxyPayIcon} />
611
- <Text style={styles.oxyPayMainTitle}>Oxy Pay</Text>
612
- <Text style={styles.oxyPaySubtitle}>Pay with your in-app wallet</Text>
613
- <View style={styles.oxyPayBalanceBox}>
614
- <Text style={styles.oxyPayBalanceText}>Balance: ⊜ 123.45</Text>
615
- </View>
616
- <View style={{ height: 18 }} />
617
- <Text style={styles.oxyPayWaiting}>Ready to process payment...</Text>
618
- </View>
619
- </View>
620
- )}
621
- {paymentMethod === 'faircoin' && (
622
- <View style={styles.faircoinCard}>
623
- <View style={styles.faircoinContent}>
624
- <FAIRWalletIcon size={64} style={styles.faircoinIcon} />
625
- <Text style={styles.faircoinMainTitle}>FAIRWallet</Text>
626
- <Text style={styles.faircoinSubtitle}>Pay with FairCoin</Text>
627
- {!isMobile ? (
628
- <>
629
- <Text style={styles.faircoinScanText}>Scan to Pay</Text>
630
- <View style={styles.faircoinQRCard}>
631
- <QRCode value={faircoinAddress} size={qrSize - 32} />
632
- <View style={styles.faircoinQRBadge}>
633
- <FAIRWalletIcon size={28} />
634
- </View>
635
- </View>
636
- </>
637
- ) : (
638
- <>
639
- <Text style={styles.faircoinTitle}>Use the options below to pay with FAIRWallet</Text>
640
- <Text style={styles.faircoinAddress}>{faircoinAddress}</Text>
641
- <TouchableOpacity style={[styles.faircoinButton, { backgroundColor: '#9ffb50', borderRadius: 18, marginTop: 12, width: '90%', flexDirection: 'row', alignItems: 'center', justifyContent: 'center' }]} onPress={handleOpenFairWallet}>
642
- <FAIRWalletIcon size={20} style={{ marginRight: 8 }} />
643
- <Text style={[styles.faircoinButtonText, { color: '#1b1f0a', fontWeight: 'bold', fontSize: 16 }]}>Open in FAIRWallet</Text>
644
- </TouchableOpacity>
645
- <TouchableOpacity style={[styles.faircoinButton, { backgroundColor: '#9ffb50', borderRadius: 18, marginTop: 10, width: '90%', flexDirection: 'row', alignItems: 'center', justifyContent: 'center' }]} onPress={handleCopyAddress}>
646
- <FAIRWalletIcon size={20} style={{ marginRight: 8 }} />
647
- <Text style={[styles.faircoinButtonText, { color: '#1b1f0a', fontWeight: 'bold', fontSize: 16 }]}>Copy Address</Text>
648
- </TouchableOpacity>
649
- </>
650
- )}
651
- <View style={{ height: 18 }} />
652
- <Text style={styles.faircoinWaiting}>Waiting for payment...</Text>
653
- {/* TODO: Integrate QR code generator for FAIRWallet payments */}
654
- <Text style={styles.faircoinPlaceholder}>(This is a placeholder. Integrate with a QR code generator for production.)</Text>
655
- </View>
656
- </View>
657
- )}
658
- </View>
659
- <GroupedPillButtons
660
- buttons={[
661
- {
662
- text: 'Back',
663
- onPress: prevStep,
664
- icon: 'arrow-back',
665
- variant: 'transparent',
666
- },
667
- {
668
- text: 'Continue',
669
- onPress: nextStep,
670
- icon: 'arrow-forward',
671
- variant: 'primary',
672
- disabled:
673
- (paymentMethod === 'card' && (!cardDetails.number || !cardDetails.expiry || !cardDetails.cvv)),
674
- },
675
- ]}
676
- colors={colors}
677
- />
678
- </Animated.View>
679
- );
680
-
681
- // Step 4: Review & Pay
682
- const renderReviewStep = () => (
683
- <Animated.View style={[styles.stepContainer, {
684
- opacity: fadeAnim,
685
- transform: [
686
- { translateY: slideAnim },
687
- { scale: scaleAnim },
688
- ]
689
- }]}
690
- >
691
- <View style={styles.section}>
692
- <Text style={styles.sectionTitle}>Review Payment</Text>
693
-
694
- <GroupedSection
695
- items={[
696
- {
697
- id: 'secure-payment',
698
- icon: 'shield-check',
699
- iconColor: colors.success || '#4BB543',
700
- title: 'Secure payment',
701
- subtitle: 'Your payment is protected by industry-standard encryption',
702
- },
703
- {
704
- id: 'amount',
705
- icon: 'cash',
706
- iconColor: colors.primary,
707
- title: 'Amount',
708
- subtitle: `${currencySymbol} ${amount}`,
709
- },
710
- {
711
- id: 'payment-method',
712
- icon: PAYMENT_METHODS.find(m => m.key === paymentMethod)?.icon as any,
713
- iconColor: colors.primary,
714
- title: 'Payment Method',
715
- subtitle: PAYMENT_METHODS.find(m => m.key === paymentMethod)?.label,
716
- },
717
- ...(paymentMethod === 'card' ? [{
718
- id: 'card-details',
719
- icon: 'card',
720
- iconColor: colors.primary,
721
- title: 'Card',
722
- subtitle: cardDetails.number.replace(/.(?=.{4})/g, '*'),
723
- }] : []),
724
- ...(paymentMethod === 'oxy' ? [{
725
- id: 'oxy-balance',
726
- icon: 'wallet',
727
- iconColor: colors.primary,
728
- title: 'Oxy Pay Account',
729
- subtitle: 'Balance: ⊜ 123.45',
730
- }] : []),
731
- ...(paymentMethod === 'faircoin' ? [{
732
- id: 'faircoin-wallet',
733
- icon: 'qr-code',
734
- iconColor: colors.primary,
735
- title: 'FairCoin Wallet',
736
- subtitle: 'Paid via QR',
737
- }] : []),
738
- ]}
739
-
740
- />
741
- </View>
742
- <GroupedPillButtons
743
- buttons={[
744
- {
745
- text: 'Back',
746
- onPress: prevStep,
747
- icon: 'arrow-back',
748
- variant: 'transparent',
749
- },
750
- {
751
- text: isPaying ? 'Processing...' : 'Pay Now',
752
- onPress: handlePay,
753
- icon: 'checkmark',
754
- variant: 'primary',
755
- loading: isPaying,
756
- },
757
- ]}
758
- colors={colors}
759
- />
760
- </Animated.View>
761
- );
762
-
763
- // Step 5: Success
764
- const renderSuccessStep = () => (
765
- <Animated.View style={[styles.stepContainer, {
766
- opacity: fadeAnim,
767
- transform: [
768
- { translateY: slideAnim },
769
- { scale: scaleAnim },
770
- ]
771
- }]}
772
- >
773
- <View style={styles.section}>
774
- <Text style={styles.sectionTitle}>Payment Complete</Text>
775
-
776
- <View style={styles.successCard}>
777
- <View style={styles.successContent}>
778
- <Ionicons name="checkmark-circle" size={64} color={colors.success || '#4BB543'} style={styles.successIcon} />
779
- <Text style={styles.successMainTitle}>Payment Successful!</Text>
780
- <Text style={styles.successSubtitle}>Thank you for your payment.</Text>
781
- <View style={{ height: 18 }} />
782
- <Text style={styles.successMessage}>Your transaction has been processed successfully.</Text>
783
- </View>
784
- </View>
785
- </View>
786
- <GroupedPillButtons
787
- buttons={[
788
- {
789
- text: 'Done',
790
- onPress: handleDone,
791
- icon: 'checkmark',
792
- variant: 'primary',
793
- },
794
- ]}
795
- colors={colors}
796
- />
797
- </Animated.View>
798
- );
799
-
800
-
209
+ const animations = { fadeAnim, slideAnim, scaleAnim };
801
210
 
802
211
  const renderCurrentStep = () => {
803
212
  switch (currentStep) {
804
- case 0: return renderSummaryStep();
805
- case 1: return renderMethodStep();
806
- case 2: return renderDetailsStep();
807
- case 3: return renderReviewStep();
808
- case 4: return renderSuccessStep();
809
- default: return renderSummaryStep();
213
+ case 0:
214
+ return (
215
+ <PaymentSummaryStep
216
+ paymentItems={paymentItems}
217
+ amount={amount}
218
+ currency={currency}
219
+ description={description}
220
+ colors={colors}
221
+ animations={animations}
222
+ onClose={handleClose}
223
+ onNext={nextStep}
224
+ />
225
+ );
226
+ case 1:
227
+ return (
228
+ <PaymentMethodStep
229
+ availablePaymentMethods={availablePaymentMethods}
230
+ selectedMethod={paymentMethod}
231
+ onSelectMethod={setPaymentMethod}
232
+ colors={colors}
233
+ animations={animations}
234
+ onBack={prevStep}
235
+ onNext={nextStep}
236
+ />
237
+ );
238
+ case 2:
239
+ return (
240
+ <PaymentDetailsStep
241
+ paymentMethod={paymentMethod}
242
+ cardDetails={cardDetails}
243
+ onCardDetailsChange={setCardDetails}
244
+ colors={colors}
245
+ animations={animations}
246
+ faircoinAddress={faircoinAddress}
247
+ isMobile={isMobile}
248
+ qrSize={qrSize}
249
+ onBack={prevStep}
250
+ onNext={nextStep}
251
+ QRCodeComponent={QRCode}
252
+ />
253
+ );
254
+ case 3:
255
+ return (
256
+ <PaymentReviewStep
257
+ amount={amount}
258
+ currency={currency}
259
+ paymentMethod={paymentMethod}
260
+ cardDetails={cardDetails}
261
+ colors={colors}
262
+ animations={animations}
263
+ isPaying={isPaying}
264
+ onBack={prevStep}
265
+ onPay={handlePay}
266
+ />
267
+ );
268
+ case 4:
269
+ return (
270
+ <PaymentSuccessStep
271
+ colors={colors}
272
+ animations={animations}
273
+ onDone={handleDone}
274
+ />
275
+ );
276
+ default:
277
+ return null;
810
278
  }
811
279
  };
812
280
 
813
- // Use centralized theme styles hook for consistency
814
- // primaryColor from hook (#007AFF) is already correct for this screen
815
- const themeStyles = useThemeStyles(normalizedTheme);
816
-
817
281
  return (
818
282
  <View style={[styles.container, { backgroundColor: themeStyles.backgroundColor }]}>
819
- {/* Content */}
820
283
  <ScrollView style={styles.content} showsVerticalScrollIndicator={false}>
821
284
  {renderCurrentStep()}
822
285
  </ScrollView>
@@ -824,646 +287,4 @@ const PaymentGatewayScreen: React.FC<PaymentGatewayScreenProps> = (props) => {
824
287
  );
825
288
  };
826
289
 
827
- const createStyles = (colors: any, theme: string) => StyleSheet.create({
828
- container: {
829
- flex: 1,
830
- },
831
- content: {
832
- flex: 1,
833
- padding: 16,
834
- },
835
- stepContainer: {
836
- justifyContent: 'flex-start',
837
- alignItems: 'flex-start',
838
- width: '100%',
839
- },
840
- section: {
841
- marginBottom: 24,
842
- width: '100%',
843
- },
844
- sectionTitle: {
845
- fontSize: 16,
846
- fontWeight: '600',
847
- color: colors.text,
848
- marginBottom: 12,
849
- fontFamily: fontFamilies.phuduSemiBold,
850
- },
851
- stepIndicatorContainer: {
852
- flexDirection: 'row',
853
- justifyContent: 'center',
854
- alignItems: 'center',
855
- marginVertical: 16,
856
- },
857
- stepIndicator: {
858
- height: 10,
859
- borderRadius: 5,
860
- marginHorizontal: 4,
861
- },
862
- stepIndicatorActive: {
863
- width: 28,
864
- backgroundColor: colors.primary,
865
- },
866
- stepIndicatorInactive: {
867
- width: 10,
868
- backgroundColor: colors.border,
869
- },
870
- logo: {
871
- width: 40,
872
- height: 20,
873
- alignSelf: 'center',
874
- resizeMode: 'contain',
875
- },
876
- headerTitle: {
877
- fontFamily: fontFamilies.phuduBold,
878
- fontSize: 22,
879
- fontWeight: Platform.OS === 'web' ? 'bold' : undefined,
880
- color: colors.text,
881
- letterSpacing: -0.5,
882
- },
883
-
884
- paymentMethodButton: {
885
- flexDirection: 'row',
886
- alignItems: 'center',
887
- borderRadius: 16,
888
- padding: 14,
889
- marginBottom: 10,
890
- width: '90%',
891
- alignSelf: 'center',
892
- borderWidth: 1,
893
- },
894
- paymentMethodButtonActive: {
895
- backgroundColor: colors.primary + '22',
896
- borderColor: colors.primary,
897
- borderWidth: 2,
898
- },
899
- paymentMethodButtonInactive: {
900
- backgroundColor: 'transparent',
901
- borderColor: colors.border,
902
- borderWidth: 1,
903
- },
904
- paymentMethodLabel: {
905
- fontFamily: fontFamilies.phudu,
906
- fontSize: 18,
907
- color: colors.text,
908
- fontWeight: '600',
909
- },
910
- paymentMethodDescription: {
911
- fontFamily: fontFamilies.phudu,
912
- fontSize: 15,
913
- color: colors.secondaryText,
914
- marginTop: 8,
915
- minHeight: 36,
916
- textAlign: 'center',
917
- },
918
- errorContainer: {
919
- flex: 1,
920
- justifyContent: 'center',
921
- alignItems: 'center',
922
- padding: 32,
923
- },
924
- errorText: {
925
- fontSize: 18,
926
- color: 'red',
927
- marginBottom: 24,
928
- },
929
- methodListContainer: {
930
- width: '100%',
931
- alignItems: 'center',
932
- },
933
- methodIcon: {
934
- marginRight: 12,
935
- },
936
- methodCheckIcon: {
937
- marginLeft: 'auto',
938
- },
939
- cardRowInfo: {
940
- flexDirection: 'row',
941
- alignItems: 'center',
942
- marginBottom: 16,
943
- },
944
- cardRowIcon: {
945
- marginRight: 8,
946
- },
947
- cardRowText: {
948
- fontSize: 15,
949
- color: colors.secondaryText,
950
- },
951
- cardFieldContainer: {
952
- marginBottom: 16,
953
- },
954
- cardFieldRow: {
955
- flexDirection: 'row',
956
- gap: 12,
957
- },
958
- cardFieldHalfLeft: {
959
- flex: 1,
960
- marginRight: 6,
961
- },
962
- cardFieldHalfRight: {
963
- flex: 1,
964
- marginLeft: 6,
965
- },
966
- oxyPayContainer: {
967
- alignItems: 'center',
968
- },
969
- oxyPayIcon: {
970
- marginBottom: 8,
971
- },
972
- oxyPayTitle: {
973
- fontSize: 16,
974
- marginBottom: 8,
975
- color: colors.text,
976
- fontWeight: '600',
977
- textAlign: 'center',
978
- },
979
- oxyPaySubtitle: {
980
- fontSize: 14,
981
- color: colors.secondaryText,
982
- marginBottom: 8,
983
- textAlign: 'center',
984
- },
985
- oxyPayBalanceBox: {
986
- backgroundColor: colors.primary + '22',
987
- borderRadius: 12,
988
- padding: 8,
989
- marginTop: 8,
990
- },
991
- oxyPayBalanceText: {
992
- color: colors.primary,
993
- fontWeight: '600',
994
- },
995
- oxyPayCard: {
996
- backgroundColor: '#fff',
997
- borderRadius: 16,
998
- padding: 24,
999
- marginBottom: 24,
1000
- alignItems: 'center',
1001
- width: '100%',
1002
- },
1003
- oxyPayContent: {
1004
- alignItems: 'center',
1005
- width: '100%',
1006
- },
1007
- oxyPayMainTitle: {
1008
- fontFamily: fontFamilies.phuduBold,
1009
- fontWeight: 'bold',
1010
- fontSize: 28,
1011
- color: colors.text,
1012
- marginBottom: 2,
1013
- textAlign: 'center',
1014
- letterSpacing: 0.5,
1015
- },
1016
- oxyPayWaiting: {
1017
- fontSize: 14,
1018
- color: colors.secondaryText,
1019
- textAlign: 'center',
1020
- marginBottom: 8,
1021
- },
1022
- faircoinContainer: {
1023
- alignItems: 'center',
1024
- marginBottom: 24,
1025
- width: '100%',
1026
- },
1027
- faircoinIcon: {
1028
- marginBottom: 8,
1029
- },
1030
- faircoinMainTitle: {
1031
- fontFamily: fontFamilies.phuduBold,
1032
- fontWeight: 'bold',
1033
- fontSize: 28,
1034
- color: '#1b1f0a',
1035
- marginBottom: 2,
1036
- textAlign: 'center',
1037
- letterSpacing: 0.5,
1038
- },
1039
- faircoinSubtitle: {
1040
- color: '#1b1f0a',
1041
- fontWeight: '700',
1042
- fontSize: 17,
1043
- marginBottom: 18,
1044
- textAlign: 'center',
1045
- letterSpacing: 0.2,
1046
- },
1047
- faircoinScanText: {
1048
- color: '#1b1f0a',
1049
- fontWeight: '600',
1050
- fontSize: 15,
1051
- marginBottom: 8,
1052
- },
1053
- faircoinQRCard: {
1054
- width: 200,
1055
- height: 200,
1056
- backgroundColor: '#fff',
1057
- borderRadius: 32,
1058
- justifyContent: 'center',
1059
- alignItems: 'center',
1060
- marginBottom: 16,
1061
- padding: 16,
1062
- borderWidth: 3,
1063
- borderColor: '#9ffb50',
1064
- shadowColor: '#9ffb50',
1065
- shadowOffset: { width: 0, height: 4 },
1066
- shadowOpacity: 0.25,
1067
- shadowRadius: 12,
1068
- elevation: 8,
1069
- position: 'relative',
1070
- },
1071
- faircoinQRBadge: {
1072
- position: 'absolute',
1073
- bottom: 12,
1074
- right: 12,
1075
- backgroundColor: '#fff',
1076
- borderRadius: 16,
1077
- padding: 4,
1078
- shadowColor: '#000',
1079
- shadowOffset: { width: 0, height: 2 },
1080
- shadowOpacity: 0.1,
1081
- shadowRadius: 4,
1082
- elevation: 2,
1083
- },
1084
- faircoinTitle: {
1085
- fontSize: 16,
1086
- marginBottom: 8,
1087
- color: colors.text,
1088
- fontWeight: '600',
1089
- textAlign: 'center',
1090
- },
1091
- faircoinQRBox: {
1092
- width: 160,
1093
- height: 160,
1094
- backgroundColor: '#eee',
1095
- borderRadius: 16,
1096
- justifyContent: 'center',
1097
- alignItems: 'center',
1098
- marginBottom: 12,
1099
- borderWidth: 2,
1100
- borderColor: colors.primary,
1101
- },
1102
- faircoinQRText: {
1103
- color: '#aaa',
1104
- },
1105
- faircoinWaiting: {
1106
- fontSize: 14,
1107
- color: colors.secondaryText,
1108
- textAlign: 'center',
1109
- marginBottom: 8,
1110
- },
1111
- faircoinPlaceholder: {
1112
- fontSize: 13,
1113
- color: colors.secondaryText,
1114
- textAlign: 'center',
1115
- },
1116
- faircoinCard: {
1117
- backgroundColor: '#fff',
1118
- borderRadius: 16,
1119
- padding: 24,
1120
- marginBottom: 24,
1121
- alignItems: 'center',
1122
- width: '100%',
1123
- },
1124
- faircoinContent: {
1125
- alignItems: 'center',
1126
- width: '100%',
1127
- },
1128
-
1129
- successCard: {
1130
- backgroundColor: '#fff',
1131
- borderRadius: 16,
1132
- padding: 24,
1133
- marginBottom: 24,
1134
- alignItems: 'center',
1135
- width: '100%',
1136
- },
1137
- successContent: {
1138
- alignItems: 'center',
1139
- width: '100%',
1140
- },
1141
- successIcon: {
1142
- marginBottom: 8,
1143
- },
1144
- successMainTitle: {
1145
- fontFamily: fontFamilies.phuduBold,
1146
- fontWeight: 'bold',
1147
- fontSize: 28,
1148
- color: colors.success || '#4BB543',
1149
- marginBottom: 2,
1150
- textAlign: 'center',
1151
- letterSpacing: 0.5,
1152
- },
1153
- successSubtitle: {
1154
- fontSize: 16,
1155
- color: colors.text,
1156
- textAlign: 'center',
1157
- marginBottom: 8,
1158
- width: '100%',
1159
- },
1160
- successMessage: {
1161
- fontSize: 14,
1162
- color: colors.secondaryText,
1163
- textAlign: 'center',
1164
- marginBottom: 8,
1165
- },
1166
- methodCard: {
1167
- flexDirection: 'row',
1168
- alignItems: 'center',
1169
- backgroundColor: '#fff',
1170
- borderRadius: 18,
1171
- paddingVertical: 18,
1172
- paddingHorizontal: 18,
1173
- marginBottom: 14,
1174
- borderWidth: 1.5,
1175
- borderColor: colors.border,
1176
- shadowColor: '#000',
1177
- shadowOffset: { width: 0, height: 2 },
1178
- shadowOpacity: 0.06,
1179
- shadowRadius: 6,
1180
- elevation: 2,
1181
- minHeight: 72,
1182
- },
1183
- methodCardSelected: {
1184
- backgroundColor: colors.primary + '11',
1185
- borderColor: colors.primary,
1186
- shadowOpacity: 0.13,
1187
- shadowRadius: 10,
1188
- elevation: 4,
1189
- },
1190
- methodCardContent: {
1191
- flexDirection: 'row',
1192
- alignItems: 'center',
1193
- flex: 1,
1194
- },
1195
- methodCardIcon: {
1196
- marginRight: 18,
1197
- marginLeft: 2,
1198
- },
1199
- methodCardTextContainer: {
1200
- flex: 1,
1201
- flexDirection: 'column',
1202
- justifyContent: 'center',
1203
- },
1204
- methodCardDescription: {
1205
- fontSize: 14,
1206
- color: colors.secondaryText,
1207
- marginTop: 2,
1208
- opacity: 0.85,
1209
- },
1210
- methodCardCheckIcon: {
1211
- marginLeft: 12,
1212
- },
1213
- paymentMethodLabelSelected: {
1214
- color: colors.primary,
1215
- },
1216
- circleListContainer: {
1217
- flexDirection: 'row',
1218
- flexWrap: 'nowrap',
1219
- justifyContent: 'center',
1220
- alignItems: 'flex-start',
1221
- paddingHorizontal: 4,
1222
- width: '100%',
1223
- marginBottom: 0,
1224
- },
1225
- circleMethod: {
1226
- alignItems: 'center',
1227
- marginHorizontal: 0,
1228
- flex: 1,
1229
- minWidth: 62,
1230
- paddingVertical: 2,
1231
- paddingHorizontal: 2,
1232
- },
1233
- circleMethodSelected: {
1234
- // No extra margin, but highlight below
1235
- },
1236
- circleIconWrapper: {
1237
- width: 48, // restored padding
1238
- height: 48, // restored padding
1239
- borderRadius: 24, // half of width/height
1240
- backgroundColor: '#fff',
1241
- borderWidth: 2,
1242
- borderColor: colors.border,
1243
- alignItems: 'center',
1244
- justifyContent: 'center',
1245
- marginBottom: 8, // spacing below icon
1246
- shadowColor: '#000',
1247
- shadowOffset: { width: 0, height: 2 },
1248
- shadowOpacity: 0.07,
1249
- shadowRadius: 6,
1250
- elevation: 2,
1251
- },
1252
- circleLabel: {
1253
- fontFamily: fontFamilies.phudu,
1254
- fontSize: 16,
1255
- color: colors.text,
1256
- fontWeight: '600',
1257
- textAlign: 'center',
1258
- marginBottom: 4,
1259
- marginTop: 2,
1260
- },
1261
- circleLabelSelected: {
1262
- color: colors.primary,
1263
- },
1264
- circleDescription: {
1265
- fontSize: 13,
1266
- color: colors.secondaryText,
1267
- textAlign: 'center',
1268
- opacity: 0.85,
1269
- minHeight: 36,
1270
- marginBottom: 2,
1271
- },
1272
-
1273
- headerStepIndicatorContainer: {
1274
- marginVertical: 2,
1275
- flexDirection: 'row',
1276
- justifyContent: 'center',
1277
- alignItems: 'center',
1278
- },
1279
- faircoinButton: {
1280
- flexDirection: 'row',
1281
- alignItems: 'center',
1282
- alignSelf: 'center',
1283
- backgroundColor: colors.primary + '11',
1284
- borderRadius: 16,
1285
- paddingHorizontal: 16,
1286
- paddingVertical: 8,
1287
- marginTop: 6,
1288
- marginBottom: 2,
1289
- },
1290
- faircoinButtonText: {
1291
- color: colors.primary,
1292
- fontWeight: '600',
1293
- fontSize: 15,
1294
- },
1295
- faircoinAddress: {
1296
- color: colors.secondaryText,
1297
- fontSize: 13,
1298
- textAlign: 'center',
1299
- marginTop: 6,
1300
- marginBottom: 2,
1301
- },
1302
-
1303
- // Summary step styles
1304
- summaryDescriptionContainer: {
1305
- marginBottom: 16,
1306
- },
1307
- summaryDescriptionText: {
1308
- color: colors.secondaryText,
1309
- fontSize: 15,
1310
- lineHeight: 20,
1311
- },
1312
- summaryItemPrice: {
1313
- color: colors.text,
1314
- fontWeight: '600',
1315
- fontSize: 16,
1316
- },
1317
- summaryFallbackContainer: {
1318
- padding: 16,
1319
- backgroundColor: '#fff',
1320
- borderRadius: 12,
1321
- borderWidth: 1,
1322
- borderColor: colors.border,
1323
- },
1324
- summaryFallbackText: {
1325
- color: colors.text,
1326
- fontSize: 16,
1327
- textAlign: 'center',
1328
- },
1329
- // Card payment styles
1330
- cardPaymentCard: {
1331
- backgroundColor: '#fff',
1332
- borderRadius: 16,
1333
- padding: 24,
1334
- marginBottom: 24,
1335
- alignItems: 'center',
1336
- width: '100%',
1337
- },
1338
- cardPaymentContent: {
1339
- alignItems: 'center',
1340
- width: '100%',
1341
- },
1342
- cardPaymentIcon: {
1343
- marginBottom: 8,
1344
- },
1345
- cardPaymentMainTitle: {
1346
- fontFamily: fontFamilies.phuduBold,
1347
- fontWeight: 'bold',
1348
- fontSize: 28,
1349
- color: colors.text,
1350
- marginBottom: 2,
1351
- textAlign: 'center',
1352
- letterSpacing: 0.5,
1353
- },
1354
- cardPaymentSubtitle: {
1355
- fontSize: 16,
1356
- color: colors.secondaryText,
1357
- textAlign: 'center',
1358
- marginBottom: 24,
1359
- width: '100%',
1360
- },
1361
- cardPaymentFields: {
1362
- width: '100%',
1363
- marginBottom: 16,
1364
- },
1365
- cardPaymentWaiting: {
1366
- fontSize: 14,
1367
- color: colors.secondaryText,
1368
- textAlign: 'center',
1369
- marginBottom: 8,
1370
- },
1371
- // Summary card styles
1372
- summaryCard: {
1373
- backgroundColor: '#fff',
1374
- borderRadius: 16,
1375
- padding: 24,
1376
- marginBottom: 24,
1377
- alignItems: 'center',
1378
- width: '100%',
1379
- },
1380
- summaryCardContent: {
1381
- alignItems: 'center',
1382
- width: '100%',
1383
- },
1384
- summaryCardIcon: {
1385
- marginBottom: 8,
1386
- },
1387
- summaryCardMainTitle: {
1388
- fontFamily: fontFamilies.phuduBold,
1389
- fontWeight: 'bold',
1390
- fontSize: 28,
1391
- color: colors.text,
1392
- marginBottom: 2,
1393
- textAlign: 'center',
1394
- letterSpacing: 0.5,
1395
- },
1396
- summaryCardSubtitle: {
1397
- fontSize: 16,
1398
- color: colors.secondaryText,
1399
- textAlign: 'center',
1400
- marginBottom: 24,
1401
- width: '100%',
1402
- },
1403
- summaryCardItems: {
1404
- width: '100%',
1405
- marginBottom: 16,
1406
- },
1407
- summaryCardTotal: {
1408
- fontSize: 18,
1409
- fontWeight: 'bold',
1410
- color: colors.text,
1411
- textAlign: 'center',
1412
- marginBottom: 8,
1413
- },
1414
- // Simple amount styles
1415
- summaryCardAmount: {
1416
- alignItems: 'center',
1417
- width: '100%',
1418
- marginBottom: 16,
1419
- },
1420
- summaryCardAmountLabel: {
1421
- fontSize: 16,
1422
- color: colors.secondaryText,
1423
- textAlign: 'center',
1424
- marginBottom: 8,
1425
- },
1426
- summaryCardAmountValue: {
1427
- fontSize: 32,
1428
- fontWeight: 'bold',
1429
- color: colors.text,
1430
- textAlign: 'center',
1431
- marginBottom: 8,
1432
- fontFamily: fontFamilies.phuduBold,
1433
- },
1434
- summaryCardAmountDescription: {
1435
- fontSize: 14,
1436
- color: colors.secondaryText,
1437
- textAlign: 'center',
1438
- lineHeight: 20,
1439
- },
1440
- // Enhanced summary styles
1441
- summaryCardDivider: {
1442
- height: 1,
1443
- backgroundColor: colors.border,
1444
- marginVertical: 16,
1445
- width: '100%',
1446
- },
1447
- summaryCardTotalSection: {
1448
- width: '100%',
1449
- marginBottom: 8,
1450
- },
1451
- summaryCardTotalRow: {
1452
- flexDirection: 'row',
1453
- justifyContent: 'space-between',
1454
- alignItems: 'center',
1455
- paddingVertical: 4,
1456
- },
1457
- summaryCardTotalLabel: {
1458
- fontSize: 16,
1459
- color: colors.secondaryText,
1460
- fontWeight: '500',
1461
- },
1462
- summaryCardTotalValue: {
1463
- fontSize: 16,
1464
- color: colors.text,
1465
- fontWeight: '600',
1466
- },
1467
- });
1468
-
1469
- export default PaymentGatewayScreen;
290
+ export default PaymentGatewayScreen;