@oxyhq/services 5.11.12 → 5.12.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 (322) hide show
  1. package/README.md +48 -7
  2. package/lib/commonjs/core/OxyServices.js +168 -5
  3. package/lib/commonjs/core/OxyServices.js.map +1 -1
  4. package/lib/commonjs/i18n/index.js +40 -0
  5. package/lib/commonjs/i18n/index.js.map +1 -0
  6. package/lib/commonjs/i18n/locales/en-US.json +681 -0
  7. package/lib/commonjs/i18n/locales/es-ES.json +689 -0
  8. package/lib/commonjs/ui/components/GroupedItem.js +2 -1
  9. package/lib/commonjs/ui/components/GroupedItem.js.map +1 -1
  10. package/lib/commonjs/ui/components/Header.js +4 -3
  11. package/lib/commonjs/ui/components/Header.js.map +1 -1
  12. package/lib/commonjs/ui/components/OxyProvider.js +110 -103
  13. package/lib/commonjs/ui/components/OxyProvider.js.map +1 -1
  14. package/lib/commonjs/ui/components/ProfileCard.js +5 -1
  15. package/lib/commonjs/ui/components/ProfileCard.js.map +1 -1
  16. package/lib/commonjs/ui/components/Section.js +1 -1
  17. package/lib/commonjs/ui/components/StepBasedScreen.js +16 -16
  18. package/lib/commonjs/ui/components/StepBasedScreen.js.map +1 -1
  19. package/lib/commonjs/ui/components/internal/GroupedPillButtons.js +15 -3
  20. package/lib/commonjs/ui/components/internal/GroupedPillButtons.js.map +1 -1
  21. package/lib/commonjs/ui/components/internal/PinInput.js +10 -4
  22. package/lib/commonjs/ui/components/internal/PinInput.js.map +1 -1
  23. package/lib/commonjs/ui/context/OxyContext.js +128 -12
  24. package/lib/commonjs/ui/context/OxyContext.js.map +1 -1
  25. package/lib/commonjs/ui/hooks/useI18n.js +22 -0
  26. package/lib/commonjs/ui/hooks/useI18n.js.map +1 -0
  27. package/lib/commonjs/ui/navigation/OxyRouter.js +11 -131
  28. package/lib/commonjs/ui/navigation/OxyRouter.js.map +1 -1
  29. package/lib/commonjs/ui/navigation/routes.js +127 -0
  30. package/lib/commonjs/ui/navigation/routes.js.map +1 -0
  31. package/lib/commonjs/ui/navigation/types.js +7 -0
  32. package/lib/commonjs/ui/navigation/types.js.map +1 -1
  33. package/lib/commonjs/ui/screens/AccountCenterScreen.js +55 -47
  34. package/lib/commonjs/ui/screens/AccountCenterScreen.js.map +1 -1
  35. package/lib/commonjs/ui/screens/AccountOverviewScreen.js +69 -61
  36. package/lib/commonjs/ui/screens/AccountOverviewScreen.js.map +1 -1
  37. package/lib/commonjs/ui/screens/AccountSettingsScreen.js +378 -37
  38. package/lib/commonjs/ui/screens/AccountSettingsScreen.js.map +1 -1
  39. package/lib/commonjs/ui/screens/AccountSwitcherScreen.js +52 -34
  40. package/lib/commonjs/ui/screens/AccountSwitcherScreen.js.map +1 -1
  41. package/lib/commonjs/ui/screens/FeedbackScreen.js +40 -36
  42. package/lib/commonjs/ui/screens/FeedbackScreen.js.map +1 -1
  43. package/lib/commonjs/ui/screens/LanguageSelectorScreen.js +105 -78
  44. package/lib/commonjs/ui/screens/LanguageSelectorScreen.js.map +1 -1
  45. package/lib/commonjs/ui/screens/PaymentGatewayScreen.js +1 -1
  46. package/lib/commonjs/ui/screens/PaymentGatewayScreen.js.map +1 -1
  47. package/lib/commonjs/ui/screens/PremiumSubscriptionScreen.js +92 -60
  48. package/lib/commonjs/ui/screens/PremiumSubscriptionScreen.js.map +1 -1
  49. package/lib/commonjs/ui/screens/ProfileScreen.js +21 -11
  50. package/lib/commonjs/ui/screens/ProfileScreen.js.map +1 -1
  51. package/lib/commonjs/ui/screens/RecoverAccountScreen.js +30 -8
  52. package/lib/commonjs/ui/screens/RecoverAccountScreen.js.map +1 -1
  53. package/lib/commonjs/ui/screens/SignInScreen.js +47 -26
  54. package/lib/commonjs/ui/screens/SignInScreen.js.map +1 -1
  55. package/lib/commonjs/ui/screens/WelcomeNewUserScreen.js +31 -24
  56. package/lib/commonjs/ui/screens/WelcomeNewUserScreen.js.map +1 -1
  57. package/lib/commonjs/ui/screens/internal/SignInPasswordStep.js +11 -7
  58. package/lib/commonjs/ui/screens/internal/SignInPasswordStep.js.map +1 -1
  59. package/lib/commonjs/ui/screens/internal/SignInUsernameStep.js +12 -6
  60. package/lib/commonjs/ui/screens/internal/SignInUsernameStep.js.map +1 -1
  61. package/lib/commonjs/ui/screens/karma/KarmaAboutScreen.js +11 -7
  62. package/lib/commonjs/ui/screens/karma/KarmaAboutScreen.js.map +1 -1
  63. package/lib/commonjs/ui/screens/karma/KarmaCenterScreen.js +15 -11
  64. package/lib/commonjs/ui/screens/karma/KarmaCenterScreen.js.map +1 -1
  65. package/lib/commonjs/ui/screens/karma/KarmaFAQScreen.js +19 -27
  66. package/lib/commonjs/ui/screens/karma/KarmaFAQScreen.js.map +1 -1
  67. package/lib/commonjs/ui/screens/karma/KarmaLeaderboardScreen.js +8 -4
  68. package/lib/commonjs/ui/screens/karma/KarmaLeaderboardScreen.js.map +1 -1
  69. package/lib/commonjs/ui/screens/karma/KarmaRewardsScreen.js +14 -10
  70. package/lib/commonjs/ui/screens/karma/KarmaRewardsScreen.js.map +1 -1
  71. package/lib/commonjs/ui/screens/karma/KarmaRulesScreen.js +7 -3
  72. package/lib/commonjs/ui/screens/karma/KarmaRulesScreen.js.map +1 -1
  73. package/lib/commonjs/ui/screens/steps/RecoverRequestStep.js +19 -14
  74. package/lib/commonjs/ui/screens/steps/RecoverRequestStep.js.map +1 -1
  75. package/lib/commonjs/ui/screens/steps/RecoverResetPasswordStep.js +130 -0
  76. package/lib/commonjs/ui/screens/steps/RecoverResetPasswordStep.js.map +1 -0
  77. package/lib/commonjs/ui/screens/steps/RecoverSuccessStep.js +13 -13
  78. package/lib/commonjs/ui/screens/steps/RecoverSuccessStep.js.map +1 -1
  79. package/lib/commonjs/ui/screens/steps/RecoverVerifyStep.js +14 -20
  80. package/lib/commonjs/ui/screens/steps/RecoverVerifyStep.js.map +1 -1
  81. package/lib/commonjs/ui/screens/steps/SignInPasswordStep.js +22 -8
  82. package/lib/commonjs/ui/screens/steps/SignInPasswordStep.js.map +1 -1
  83. package/lib/commonjs/ui/screens/steps/SignInTotpStep.js +161 -0
  84. package/lib/commonjs/ui/screens/steps/SignInTotpStep.js.map +1 -0
  85. package/lib/commonjs/ui/screens/steps/SignInUsernameStep.js +12 -6
  86. package/lib/commonjs/ui/screens/steps/SignInUsernameStep.js.map +1 -1
  87. package/lib/commonjs/ui/screens/steps/SignUpIdentityStep.js +10 -6
  88. package/lib/commonjs/ui/screens/steps/SignUpIdentityStep.js.map +1 -1
  89. package/lib/commonjs/ui/screens/steps/SignUpSecurityStep.js +10 -6
  90. package/lib/commonjs/ui/screens/steps/SignUpSecurityStep.js.map +1 -1
  91. package/lib/commonjs/ui/screens/steps/SignUpSummaryStep.js +34 -4
  92. package/lib/commonjs/ui/screens/steps/SignUpSummaryStep.js.map +1 -1
  93. package/lib/commonjs/ui/screens/steps/SignUpWelcomeStep.js +9 -10
  94. package/lib/commonjs/ui/screens/steps/SignUpWelcomeStep.js.map +1 -1
  95. package/lib/commonjs/ui/styles/authStyles.js +1 -2
  96. package/lib/commonjs/ui/styles/authStyles.js.map +1 -1
  97. package/lib/commonjs/utils/deviceManager.js +1 -1
  98. package/lib/commonjs/utils/deviceManager.js.map +1 -1
  99. package/lib/commonjs/utils/validationUtils.js +4 -2
  100. package/lib/commonjs/utils/validationUtils.js.map +1 -1
  101. package/lib/module/core/OxyServices.js +168 -5
  102. package/lib/module/core/OxyServices.js.map +1 -1
  103. package/lib/module/i18n/index.js +35 -0
  104. package/lib/module/i18n/index.js.map +1 -0
  105. package/lib/module/i18n/locales/en-US.json +681 -0
  106. package/lib/module/i18n/locales/es-ES.json +689 -0
  107. package/lib/module/ui/components/GroupedItem.js +2 -1
  108. package/lib/module/ui/components/GroupedItem.js.map +1 -1
  109. package/lib/module/ui/components/Header.js +4 -3
  110. package/lib/module/ui/components/Header.js.map +1 -1
  111. package/lib/module/ui/components/OxyProvider.js +109 -103
  112. package/lib/module/ui/components/OxyProvider.js.map +1 -1
  113. package/lib/module/ui/components/ProfileCard.js +5 -1
  114. package/lib/module/ui/components/ProfileCard.js.map +1 -1
  115. package/lib/module/ui/components/Section.js +1 -1
  116. package/lib/module/ui/components/StepBasedScreen.js +16 -16
  117. package/lib/module/ui/components/StepBasedScreen.js.map +1 -1
  118. package/lib/module/ui/components/internal/GroupedPillButtons.js +15 -3
  119. package/lib/module/ui/components/internal/GroupedPillButtons.js.map +1 -1
  120. package/lib/module/ui/components/internal/PinInput.js +9 -4
  121. package/lib/module/ui/components/internal/PinInput.js.map +1 -1
  122. package/lib/module/ui/context/OxyContext.js +128 -12
  123. package/lib/module/ui/context/OxyContext.js.map +1 -1
  124. package/lib/module/ui/hooks/useI18n.js +18 -0
  125. package/lib/module/ui/hooks/useI18n.js.map +1 -0
  126. package/lib/module/ui/navigation/OxyRouter.js +7 -124
  127. package/lib/module/ui/navigation/OxyRouter.js.map +1 -1
  128. package/lib/module/ui/navigation/routes.js +122 -0
  129. package/lib/module/ui/navigation/routes.js.map +1 -0
  130. package/lib/module/ui/navigation/types.js +19 -1
  131. package/lib/module/ui/navigation/types.js.map +1 -1
  132. package/lib/module/ui/screens/AccountCenterScreen.js +55 -47
  133. package/lib/module/ui/screens/AccountCenterScreen.js.map +1 -1
  134. package/lib/module/ui/screens/AccountOverviewScreen.js +69 -61
  135. package/lib/module/ui/screens/AccountOverviewScreen.js.map +1 -1
  136. package/lib/module/ui/screens/AccountSettingsScreen.js +378 -37
  137. package/lib/module/ui/screens/AccountSettingsScreen.js.map +1 -1
  138. package/lib/module/ui/screens/AccountSwitcherScreen.js +52 -34
  139. package/lib/module/ui/screens/AccountSwitcherScreen.js.map +1 -1
  140. package/lib/module/ui/screens/FeedbackScreen.js +40 -36
  141. package/lib/module/ui/screens/FeedbackScreen.js.map +1 -1
  142. package/lib/module/ui/screens/LanguageSelectorScreen.js +107 -80
  143. package/lib/module/ui/screens/LanguageSelectorScreen.js.map +1 -1
  144. package/lib/module/ui/screens/PaymentGatewayScreen.js +1 -1
  145. package/lib/module/ui/screens/PaymentGatewayScreen.js.map +1 -1
  146. package/lib/module/ui/screens/PremiumSubscriptionScreen.js +92 -60
  147. package/lib/module/ui/screens/PremiumSubscriptionScreen.js.map +1 -1
  148. package/lib/module/ui/screens/ProfileScreen.js +21 -11
  149. package/lib/module/ui/screens/ProfileScreen.js.map +1 -1
  150. package/lib/module/ui/screens/RecoverAccountScreen.js +30 -8
  151. package/lib/module/ui/screens/RecoverAccountScreen.js.map +1 -1
  152. package/lib/module/ui/screens/SignInScreen.js +47 -26
  153. package/lib/module/ui/screens/SignInScreen.js.map +1 -1
  154. package/lib/module/ui/screens/WelcomeNewUserScreen.js +31 -24
  155. package/lib/module/ui/screens/WelcomeNewUserScreen.js.map +1 -1
  156. package/lib/module/ui/screens/internal/SignInPasswordStep.js +11 -7
  157. package/lib/module/ui/screens/internal/SignInPasswordStep.js.map +1 -1
  158. package/lib/module/ui/screens/internal/SignInUsernameStep.js +12 -6
  159. package/lib/module/ui/screens/internal/SignInUsernameStep.js.map +1 -1
  160. package/lib/module/ui/screens/karma/KarmaAboutScreen.js +11 -7
  161. package/lib/module/ui/screens/karma/KarmaAboutScreen.js.map +1 -1
  162. package/lib/module/ui/screens/karma/KarmaCenterScreen.js +15 -11
  163. package/lib/module/ui/screens/karma/KarmaCenterScreen.js.map +1 -1
  164. package/lib/module/ui/screens/karma/KarmaFAQScreen.js +19 -27
  165. package/lib/module/ui/screens/karma/KarmaFAQScreen.js.map +1 -1
  166. package/lib/module/ui/screens/karma/KarmaLeaderboardScreen.js +8 -4
  167. package/lib/module/ui/screens/karma/KarmaLeaderboardScreen.js.map +1 -1
  168. package/lib/module/ui/screens/karma/KarmaRewardsScreen.js +14 -10
  169. package/lib/module/ui/screens/karma/KarmaRewardsScreen.js.map +1 -1
  170. package/lib/module/ui/screens/karma/KarmaRulesScreen.js +7 -3
  171. package/lib/module/ui/screens/karma/KarmaRulesScreen.js.map +1 -1
  172. package/lib/module/ui/screens/steps/RecoverRequestStep.js +19 -14
  173. package/lib/module/ui/screens/steps/RecoverRequestStep.js.map +1 -1
  174. package/lib/module/ui/screens/steps/RecoverResetPasswordStep.js +125 -0
  175. package/lib/module/ui/screens/steps/RecoverResetPasswordStep.js.map +1 -0
  176. package/lib/module/ui/screens/steps/RecoverSuccessStep.js +13 -13
  177. package/lib/module/ui/screens/steps/RecoverSuccessStep.js.map +1 -1
  178. package/lib/module/ui/screens/steps/RecoverVerifyStep.js +14 -20
  179. package/lib/module/ui/screens/steps/RecoverVerifyStep.js.map +1 -1
  180. package/lib/module/ui/screens/steps/SignInPasswordStep.js +22 -8
  181. package/lib/module/ui/screens/steps/SignInPasswordStep.js.map +1 -1
  182. package/lib/module/ui/screens/steps/SignInTotpStep.js +156 -0
  183. package/lib/module/ui/screens/steps/SignInTotpStep.js.map +1 -0
  184. package/lib/module/ui/screens/steps/SignInUsernameStep.js +12 -6
  185. package/lib/module/ui/screens/steps/SignInUsernameStep.js.map +1 -1
  186. package/lib/module/ui/screens/steps/SignUpIdentityStep.js +10 -6
  187. package/lib/module/ui/screens/steps/SignUpIdentityStep.js.map +1 -1
  188. package/lib/module/ui/screens/steps/SignUpSecurityStep.js +10 -6
  189. package/lib/module/ui/screens/steps/SignUpSecurityStep.js.map +1 -1
  190. package/lib/module/ui/screens/steps/SignUpSummaryStep.js +34 -4
  191. package/lib/module/ui/screens/steps/SignUpSummaryStep.js.map +1 -1
  192. package/lib/module/ui/screens/steps/SignUpWelcomeStep.js +9 -10
  193. package/lib/module/ui/screens/steps/SignUpWelcomeStep.js.map +1 -1
  194. package/lib/module/ui/styles/authStyles.js +1 -2
  195. package/lib/module/ui/styles/authStyles.js.map +1 -1
  196. package/lib/module/utils/deviceManager.js +1 -1
  197. package/lib/module/utils/deviceManager.js.map +1 -1
  198. package/lib/module/utils/validationUtils.js +4 -2
  199. package/lib/module/utils/validationUtils.js.map +1 -1
  200. package/lib/typescript/core/OxyServices.d.ts +58 -3
  201. package/lib/typescript/core/OxyServices.d.ts.map +1 -1
  202. package/lib/typescript/i18n/index.d.ts +4 -0
  203. package/lib/typescript/i18n/index.d.ts.map +1 -0
  204. package/lib/typescript/models/interfaces.d.ts +4 -0
  205. package/lib/typescript/models/interfaces.d.ts.map +1 -1
  206. package/lib/typescript/ui/components/GroupedItem.d.ts.map +1 -1
  207. package/lib/typescript/ui/components/Header.d.ts.map +1 -1
  208. package/lib/typescript/ui/components/OxyProvider.d.ts +1 -1
  209. package/lib/typescript/ui/components/OxyProvider.d.ts.map +1 -1
  210. package/lib/typescript/ui/components/ProfileCard.d.ts.map +1 -1
  211. package/lib/typescript/ui/components/StepBasedScreen.d.ts +2 -1
  212. package/lib/typescript/ui/components/StepBasedScreen.d.ts.map +1 -1
  213. package/lib/typescript/ui/components/internal/GroupedPillButtons.d.ts.map +1 -1
  214. package/lib/typescript/ui/components/internal/PinInput.d.ts +6 -3
  215. package/lib/typescript/ui/components/internal/PinInput.d.ts.map +1 -1
  216. package/lib/typescript/ui/context/OxyContext.d.ts +7 -4
  217. package/lib/typescript/ui/context/OxyContext.d.ts.map +1 -1
  218. package/lib/typescript/ui/hooks/useI18n.d.ts +5 -0
  219. package/lib/typescript/ui/hooks/useI18n.d.ts.map +1 -0
  220. package/lib/typescript/ui/navigation/OxyRouter.d.ts.map +1 -1
  221. package/lib/typescript/ui/navigation/routes.d.ts +9 -0
  222. package/lib/typescript/ui/navigation/routes.d.ts.map +1 -0
  223. package/lib/typescript/ui/navigation/types.d.ts +24 -10
  224. package/lib/typescript/ui/navigation/types.d.ts.map +1 -1
  225. package/lib/typescript/ui/screens/AccountCenterScreen.d.ts.map +1 -1
  226. package/lib/typescript/ui/screens/AccountOverviewScreen.d.ts.map +1 -1
  227. package/lib/typescript/ui/screens/AccountSettingsScreen.d.ts.map +1 -1
  228. package/lib/typescript/ui/screens/AccountSwitcherScreen.d.ts.map +1 -1
  229. package/lib/typescript/ui/screens/FeedbackScreen.d.ts.map +1 -1
  230. package/lib/typescript/ui/screens/LanguageSelectorScreen.d.ts.map +1 -1
  231. package/lib/typescript/ui/screens/PremiumSubscriptionScreen.d.ts.map +1 -1
  232. package/lib/typescript/ui/screens/ProfileScreen.d.ts.map +1 -1
  233. package/lib/typescript/ui/screens/RecoverAccountScreen.d.ts.map +1 -1
  234. package/lib/typescript/ui/screens/SignInScreen.d.ts.map +1 -1
  235. package/lib/typescript/ui/screens/WelcomeNewUserScreen.d.ts.map +1 -1
  236. package/lib/typescript/ui/screens/internal/SignInPasswordStep.d.ts +2 -1
  237. package/lib/typescript/ui/screens/internal/SignInPasswordStep.d.ts.map +1 -1
  238. package/lib/typescript/ui/screens/internal/SignInUsernameStep.d.ts.map +1 -1
  239. package/lib/typescript/ui/screens/karma/KarmaAboutScreen.d.ts.map +1 -1
  240. package/lib/typescript/ui/screens/karma/KarmaCenterScreen.d.ts.map +1 -1
  241. package/lib/typescript/ui/screens/karma/KarmaFAQScreen.d.ts.map +1 -1
  242. package/lib/typescript/ui/screens/karma/KarmaLeaderboardScreen.d.ts.map +1 -1
  243. package/lib/typescript/ui/screens/karma/KarmaRewardsScreen.d.ts.map +1 -1
  244. package/lib/typescript/ui/screens/karma/KarmaRulesScreen.d.ts.map +1 -1
  245. package/lib/typescript/ui/screens/steps/RecoverRequestStep.d.ts +4 -1
  246. package/lib/typescript/ui/screens/steps/RecoverRequestStep.d.ts.map +1 -1
  247. package/lib/typescript/ui/screens/steps/RecoverResetPasswordStep.d.ts +24 -0
  248. package/lib/typescript/ui/screens/steps/RecoverResetPasswordStep.d.ts.map +1 -0
  249. package/lib/typescript/ui/screens/steps/RecoverSuccessStep.d.ts +2 -1
  250. package/lib/typescript/ui/screens/steps/RecoverSuccessStep.d.ts.map +1 -1
  251. package/lib/typescript/ui/screens/steps/RecoverVerifyStep.d.ts +3 -1
  252. package/lib/typescript/ui/screens/steps/RecoverVerifyStep.d.ts.map +1 -1
  253. package/lib/typescript/ui/screens/steps/SignInPasswordStep.d.ts +1 -0
  254. package/lib/typescript/ui/screens/steps/SignInPasswordStep.d.ts.map +1 -1
  255. package/lib/typescript/ui/screens/steps/SignInTotpStep.d.ts +19 -0
  256. package/lib/typescript/ui/screens/steps/SignInTotpStep.d.ts.map +1 -0
  257. package/lib/typescript/ui/screens/steps/SignInUsernameStep.d.ts +2 -1
  258. package/lib/typescript/ui/screens/steps/SignInUsernameStep.d.ts.map +1 -1
  259. package/lib/typescript/ui/screens/steps/SignUpIdentityStep.d.ts +2 -1
  260. package/lib/typescript/ui/screens/steps/SignUpIdentityStep.d.ts.map +1 -1
  261. package/lib/typescript/ui/screens/steps/SignUpSecurityStep.d.ts +2 -1
  262. package/lib/typescript/ui/screens/steps/SignUpSecurityStep.d.ts.map +1 -1
  263. package/lib/typescript/ui/screens/steps/SignUpSummaryStep.d.ts +2 -1
  264. package/lib/typescript/ui/screens/steps/SignUpSummaryStep.d.ts.map +1 -1
  265. package/lib/typescript/ui/screens/steps/SignUpWelcomeStep.d.ts +2 -1
  266. package/lib/typescript/ui/screens/steps/SignUpWelcomeStep.d.ts.map +1 -1
  267. package/lib/typescript/ui/styles/authStyles.d.ts +0 -1
  268. package/lib/typescript/ui/styles/authStyles.d.ts.map +1 -1
  269. package/lib/typescript/utils/validationUtils.d.ts.map +1 -1
  270. package/package.json +48 -14
  271. package/src/core/OxyServices.ts +143 -9
  272. package/src/i18n/index.ts +39 -0
  273. package/src/i18n/locales/en-US.json +681 -0
  274. package/src/i18n/locales/es-ES.json +689 -0
  275. package/src/models/interfaces.ts +6 -1
  276. package/src/ui/components/GroupedItem.tsx +2 -1
  277. package/src/ui/components/Header.tsx +4 -3
  278. package/src/ui/components/OxyProvider.tsx +105 -112
  279. package/src/ui/components/ProfileCard.tsx +5 -1
  280. package/src/ui/components/Section.tsx +1 -1
  281. package/src/ui/components/StepBasedScreen.tsx +16 -13
  282. package/src/ui/components/internal/GroupedPillButtons.tsx +10 -6
  283. package/src/ui/components/internal/PinInput.tsx +15 -6
  284. package/src/ui/context/OxyContext.tsx +123 -20
  285. package/src/ui/hooks/useI18n.ts +12 -0
  286. package/src/ui/navigation/OxyRouter.tsx +15 -134
  287. package/src/ui/navigation/routes.ts +153 -0
  288. package/src/ui/navigation/types.ts +28 -10
  289. package/src/ui/screens/AccountCenterScreen.tsx +47 -45
  290. package/src/ui/screens/AccountOverviewScreen.tsx +68 -70
  291. package/src/ui/screens/AccountSettingsScreen.tsx +265 -41
  292. package/src/ui/screens/AccountSwitcherScreen.tsx +35 -33
  293. package/src/ui/screens/FeedbackScreen.tsx +39 -37
  294. package/src/ui/screens/LanguageSelectorScreen.tsx +99 -70
  295. package/src/ui/screens/PaymentGatewayScreen.tsx +5 -5
  296. package/src/ui/screens/PremiumSubscriptionScreen.tsx +56 -54
  297. package/src/ui/screens/ProfileScreen.tsx +14 -8
  298. package/src/ui/screens/RecoverAccountScreen.tsx +29 -8
  299. package/src/ui/screens/SignInScreen.tsx +39 -30
  300. package/src/ui/screens/WelcomeNewUserScreen.tsx +31 -17
  301. package/src/ui/screens/internal/SignInPasswordStep.tsx +11 -8
  302. package/src/ui/screens/internal/SignInUsernameStep.tsx +10 -8
  303. package/src/ui/screens/karma/KarmaAboutScreen.tsx +23 -11
  304. package/src/ui/screens/karma/KarmaCenterScreen.tsx +21 -11
  305. package/src/ui/screens/karma/KarmaFAQScreen.tsx +15 -33
  306. package/src/ui/screens/karma/KarmaLeaderboardScreen.tsx +6 -4
  307. package/src/ui/screens/karma/KarmaRewardsScreen.tsx +28 -10
  308. package/src/ui/screens/karma/KarmaRulesScreen.tsx +5 -3
  309. package/src/ui/screens/steps/RecoverRequestStep.tsx +20 -17
  310. package/src/ui/screens/steps/RecoverResetPasswordStep.tsx +133 -0
  311. package/src/ui/screens/steps/RecoverSuccessStep.tsx +12 -19
  312. package/src/ui/screens/steps/RecoverVerifyStep.tsx +15 -24
  313. package/src/ui/screens/steps/SignInPasswordStep.tsx +19 -6
  314. package/src/ui/screens/steps/SignInTotpStep.tsx +129 -0
  315. package/src/ui/screens/steps/SignInUsernameStep.tsx +11 -10
  316. package/src/ui/screens/steps/SignUpIdentityStep.tsx +10 -11
  317. package/src/ui/screens/steps/SignUpSecurityStep.tsx +10 -11
  318. package/src/ui/screens/steps/SignUpSummaryStep.tsx +24 -9
  319. package/src/ui/screens/steps/SignUpWelcomeStep.tsx +8 -14
  320. package/src/ui/styles/authStyles.ts +0 -1
  321. package/src/utils/deviceManager.ts +1 -1
  322. package/src/utils/validationUtils.ts +5 -3
@@ -3,37 +3,13 @@ import { View, Text, StyleSheet, ScrollView, Platform, TouchableOpacity, TextInp
3
3
  import type { BaseScreenProps } from '../../navigation/types';
4
4
  import { Ionicons } from '@expo/vector-icons';
5
5
  import { Header } from '../../components';
6
+ import { useI18n } from '../../hooks/useI18n';
6
7
 
7
8
  if (Platform.OS === 'android' && UIManager.setLayoutAnimationEnabledExperimental) {
8
9
  UIManager.setLayoutAnimationEnabledExperimental(true);
9
10
  }
10
11
 
11
- const FAQS = [
12
- {
13
- q: 'What is karma?',
14
- a: 'Karma is a recognition of your positive actions in the Oxy Ecosystem. It cannot be sent or received directly.'
15
- },
16
- {
17
- q: 'How do I earn karma?',
18
- a: 'By helping others, reporting bugs, contributing content, and participating in community events.'
19
- },
20
- {
21
- q: 'Can I lose karma?',
22
- a: 'Karma may be reduced for negative actions or breaking community rules.'
23
- },
24
- {
25
- q: 'What can I do with karma?',
26
- a: 'Unlock rewards, badges, and special features as you earn more karma.'
27
- },
28
- {
29
- q: 'Can I transfer karma to others?',
30
- a: 'No, karma cannot be sent or received. It is only earned by your actions.'
31
- },
32
- {
33
- q: 'How do I get support?',
34
- a: 'Contact Oxy support via the app or website for any karma-related questions.'
35
- },
36
- ];
12
+ const FAQ_KEYS = ['what', 'earn', 'lose', 'use', 'transfer', 'support'] as const;
37
13
 
38
14
  /**
39
15
  * KarmaFAQScreen - Optimized for performance
@@ -45,6 +21,7 @@ const FAQS = [
45
21
  * - React.memo wrapper to prevent re-renders when props haven't changed
46
22
  */
47
23
  const KarmaFAQScreen: React.FC<BaseScreenProps> = ({ goBack, theme }) => {
24
+ const { t } = useI18n();
48
25
  const [expanded, setExpanded] = useState<number | null>(0);
49
26
  const [search, setSearch] = useState('');
50
27
 
@@ -63,14 +40,19 @@ const KarmaFAQScreen: React.FC<BaseScreenProps> = ({ goBack, theme }) => {
63
40
  }, [theme]);
64
41
 
65
42
  // Memoize filtered FAQs to prevent filtering on every render
43
+ const faqs = useMemo(() => FAQ_KEYS.map(key => ({
44
+ q: t(`karma.faq.items.${key}.q`) || '',
45
+ a: t(`karma.faq.items.${key}.a`) || '',
46
+ })), [t]);
47
+
66
48
  const filteredFaqs = useMemo(() => {
67
- if (!search.trim()) return FAQS;
49
+ if (!search.trim()) return faqs;
68
50
  const searchLower = search.toLowerCase();
69
- return FAQS.filter(faq =>
51
+ return faqs.filter(faq =>
70
52
  faq.q.toLowerCase().includes(searchLower) ||
71
53
  faq.a.toLowerCase().includes(searchLower)
72
54
  );
73
- }, [search]);
55
+ }, [search, faqs]);
74
56
 
75
57
  // Memoize toggle handler to prevent recreation on every render
76
58
  const handleToggle = useCallback((idx: number) => {
@@ -81,8 +63,8 @@ const KarmaFAQScreen: React.FC<BaseScreenProps> = ({ goBack, theme }) => {
81
63
  return (
82
64
  <View style={[styles.container, { backgroundColor: themeStyles.backgroundColor }]}>
83
65
  <Header
84
- title="Karma FAQ"
85
- subtitle="Frequently asked questions about karma"
66
+ title={t('karma.faq.title') || 'Karma FAQ'}
67
+ subtitle={t('karma.faq.subtitle') || 'Frequently asked questions about karma'}
86
68
  subtitleVariant="muted"
87
69
  theme={theme}
88
70
  onBack={goBack}
@@ -92,7 +74,7 @@ const KarmaFAQScreen: React.FC<BaseScreenProps> = ({ goBack, theme }) => {
92
74
  <Ionicons name="search-outline" size={20} color={themeStyles.primaryColor} style={{ marginRight: 8 }} />
93
75
  <TextInput
94
76
  style={[styles.searchInput, { color: themeStyles.textColor }]}
95
- placeholder="Search FAQ..."
77
+ placeholder={t('karma.faq.search') || 'Search FAQ...'}
96
78
  placeholderTextColor={themeStyles.isDarkTheme ? '#aaa' : '#888'}
97
79
  value={search}
98
80
  onChangeText={setSearch}
@@ -102,7 +84,7 @@ const KarmaFAQScreen: React.FC<BaseScreenProps> = ({ goBack, theme }) => {
102
84
  <ScrollView contentContainerStyle={styles.contentContainer}>
103
85
  {filteredFaqs.length === 0 ? (
104
86
  <Text style={[styles.noResults, { color: themeStyles.textColor }]}>
105
- No FAQ items found matching "{search}"
87
+ {t('karma.faq.noResults', { query: search }) || `No FAQ items found matching "${search}"`}
106
88
  </Text>
107
89
  ) : (
108
90
  filteredFaqs.map((faq, idx) => (
@@ -5,9 +5,11 @@ import type { BaseScreenProps } from '../../navigation/types';
5
5
  import { useOxy } from '../../context/OxyContext';
6
6
  import Avatar from '../../components/Avatar';
7
7
  import { Header } from '../../components';
8
+ import { useI18n } from '../../hooks/useI18n';
8
9
 
9
10
  const KarmaLeaderboardScreen: React.FC<BaseScreenProps> = ({ goBack, theme, navigate }) => {
10
11
  const { oxyServices } = useOxy();
12
+ const { t } = useI18n();
11
13
  const [leaderboard, setLeaderboard] = useState<any[]>([]);
12
14
  const [isLoading, setIsLoading] = useState(true);
13
15
  const [error, setError] = useState<string | null>(null);
@@ -29,8 +31,8 @@ const KarmaLeaderboardScreen: React.FC<BaseScreenProps> = ({ goBack, theme, navi
29
31
  return (
30
32
  <View style={[styles.container, { backgroundColor }]}>
31
33
  <Header
32
- title="Karma Leaderboard"
33
- subtitle="Top contributors in the community"
34
+ title={t('karma.leaderboard.title') || 'Karma Leaderboard'}
35
+ subtitle={t('karma.leaderboard.subtitle') || 'Top contributors in the community'}
34
36
  theme={theme}
35
37
  onBack={goBack}
36
38
  elevation="subtle"
@@ -42,13 +44,13 @@ const KarmaLeaderboardScreen: React.FC<BaseScreenProps> = ({ goBack, theme, navi
42
44
  ) : (
43
45
  <ScrollView contentContainerStyle={styles.listContainer}>
44
46
  {leaderboard.length === 0 ? (
45
- <Text style={[styles.placeholder, { color: textColor }]}>No leaderboard data.</Text>
47
+ <Text style={[styles.placeholder, { color: textColor }]}>{t('karma.leaderboard.empty') || 'No leaderboard data.'}</Text>
46
48
  ) : (
47
49
  leaderboard.map((entry, idx) => (
48
50
  <TouchableOpacity
49
51
  key={entry.userId}
50
52
  style={[styles.row, idx < 3 && { backgroundColor: '#f7eaff' }]}
51
- onPress={() => navigate && navigate('KarmaProfile', { userId: entry.userId, username: entry.username })}
53
+ onPress={() => navigate && navigate('Profile', { userId: entry.userId, username: entry.username })}
52
54
  activeOpacity={0.7}
53
55
  >
54
56
  <Text style={[styles.rank, { color: primaryColor }]}>{idx + 1}</Text>
@@ -2,8 +2,10 @@ import type React from 'react';
2
2
  import { View, Text, StyleSheet, ScrollView, Platform } from 'react-native';
3
3
  import type { BaseScreenProps } from '../../navigation/types';
4
4
  import { Header } from '../../components';
5
+ import { useI18n } from '../../hooks/useI18n';
5
6
 
6
7
  const KarmaRewardsScreen: React.FC<BaseScreenProps> = ({ goBack, theme }) => {
8
+ const { t } = useI18n();
7
9
  const isDarkTheme = theme === 'dark';
8
10
  const backgroundColor = isDarkTheme ? '#121212' : '#FFFFFF';
9
11
  const textColor = isDarkTheme ? '#FFFFFF' : '#000000';
@@ -13,27 +15,43 @@ const KarmaRewardsScreen: React.FC<BaseScreenProps> = ({ goBack, theme }) => {
13
15
  return (
14
16
  <View style={[styles.container, { backgroundColor }]}>
15
17
  <Header
16
- title="Karma Rewards"
17
- subtitle="Unlock special features and recognition"
18
+ title={t('karma.rewards.title') || 'Karma Rewards'}
19
+ subtitle={t('karma.rewards.subtitle') || 'Unlock special features and recognition'}
18
20
  theme={theme}
19
21
  onBack={goBack}
20
22
  elevation="subtle"
21
23
  />
22
24
  <ScrollView contentContainerStyle={styles.contentContainer}>
23
- <Text style={[styles.paragraph, { color: textColor }]}>Unlock special features and recognition by earning karma!</Text>
25
+ <Text style={[styles.paragraph, { color: textColor }]}>
26
+ {t('karma.rewards.intro') || 'Unlock special features and recognition by earning karma!'}
27
+ </Text>
24
28
  <View style={styles.rewardBox}>
25
- <Text style={[styles.rewardTitle, { color: primaryColor }]}>🎉 Early Access</Text>
26
- <Text style={[styles.rewardDesc, { color: textColor }]}>Get early access to new features with 100+ karma.</Text>
29
+ <Text style={[styles.rewardTitle, { color: primaryColor }]}>
30
+ {t('karma.rewards.earlyAccess.title') || '🎉 Early Access'}
31
+ </Text>
32
+ <Text style={[styles.rewardDesc, { color: textColor }]}>
33
+ {t('karma.rewards.earlyAccess.desc') || 'Get early access to new features with 100+ karma.'}
34
+ </Text>
27
35
  </View>
28
36
  <View style={styles.rewardBox}>
29
- <Text style={[styles.rewardTitle, { color: primaryColor }]}>🏅 Community Badge</Text>
30
- <Text style={[styles.rewardDesc, { color: textColor }]}>Earn a special badge for 500+ karma.</Text>
37
+ <Text style={[styles.rewardTitle, { color: primaryColor }]}>
38
+ {t('karma.rewards.badge.title') || '🏅 Community Badge'}
39
+ </Text>
40
+ <Text style={[styles.rewardDesc, { color: textColor }]}>
41
+ {t('karma.rewards.badge.desc') || 'Earn a special badge for 500+ karma.'}
42
+ </Text>
31
43
  </View>
32
44
  <View style={styles.rewardBox}>
33
- <Text style={[styles.rewardTitle, { color: primaryColor }]}>🌟 Featured Member</Text>
34
- <Text style={[styles.rewardDesc, { color: textColor }]}>Be featured in the community for 1000+ karma.</Text>
45
+ <Text style={[styles.rewardTitle, { color: primaryColor }]}>
46
+ {t('karma.rewards.featured.title') || '🌟 Featured Member'}
47
+ </Text>
48
+ <Text style={[styles.rewardDesc, { color: textColor }]}>
49
+ {t('karma.rewards.featured.desc') || 'Be featured in the community for 1000+ karma.'}
50
+ </Text>
35
51
  </View>
36
- <Text style={[styles.paragraph, { color: textColor, marginTop: 24 }]}>More rewards coming soon!</Text>
52
+ <Text style={[styles.paragraph, { color: textColor, marginTop: 24 }]}>
53
+ {t('karma.rewards.moreComing') || 'More rewards coming soon!'}
54
+ </Text>
37
55
  </ScrollView>
38
56
  </View>
39
57
  );
@@ -4,9 +4,11 @@ import { View, Text, StyleSheet, ScrollView, ActivityIndicator } from 'react-nat
4
4
  import type { BaseScreenProps } from '../../navigation/types';
5
5
  import { useOxy } from '../../context/OxyContext';
6
6
  import { Header } from '../../components';
7
+ import { useI18n } from '../../hooks/useI18n';
7
8
 
8
9
  const KarmaRulesScreen: React.FC<BaseScreenProps> = ({ goBack, theme }) => {
9
10
  const { oxyServices } = useOxy();
11
+ const { t } = useI18n();
10
12
  const [rules, setRules] = useState<any[]>([]);
11
13
  const [isLoading, setIsLoading] = useState(true);
12
14
  const [error, setError] = useState<string | null>(null);
@@ -28,8 +30,8 @@ const KarmaRulesScreen: React.FC<BaseScreenProps> = ({ goBack, theme }) => {
28
30
  return (
29
31
  <View style={[styles.container, { backgroundColor }]}>
30
32
  <Header
31
- title="Karma Rules"
32
- subtitle="How to earn karma points"
33
+ title={t('karma.rules.title') || 'Karma Rules'}
34
+ subtitle={t('karma.rules.subtitle') || 'How to earn karma points'}
33
35
  theme={theme}
34
36
  onBack={goBack}
35
37
  elevation="subtle"
@@ -41,7 +43,7 @@ const KarmaRulesScreen: React.FC<BaseScreenProps> = ({ goBack, theme }) => {
41
43
  ) : (
42
44
  <ScrollView contentContainerStyle={styles.listContainer}>
43
45
  {rules.length === 0 ? (
44
- <Text style={[styles.placeholder, { color: textColor }]}>No rules found.</Text>
46
+ <Text style={[styles.placeholder, { color: textColor }]}>{t('karma.rules.empty') || 'No rules found.'}</Text>
45
47
  ) : (
46
48
  rules.map((rule, idx) => (
47
49
  <View key={rule.id || idx} style={styles.ruleRow}>
@@ -1,17 +1,21 @@
1
1
  import type React from 'react';
2
+ import type { RouteName } from '../../navigation/routes';
2
3
  import { useRef } from 'react';
3
4
  import { View, Text } from 'react-native';
4
5
  import { Ionicons } from '@expo/vector-icons';
5
6
  import HighFive from '../../../assets/illustrations/HighFive';
6
7
  import TextField from '../../components/internal/TextField';
7
8
  import GroupedPillButtons from '../../components/internal/GroupedPillButtons';
9
+ import { toast } from '../../../lib/sonner';
10
+ import type { OxyServices } from '../../../core';
11
+ import { useI18n } from '../../hooks/useI18n';
8
12
 
9
13
  interface RecoverRequestStepProps {
10
14
  // Common props from StepBasedScreen
11
15
  colors: any;
12
16
  styles: any;
13
17
  theme: string;
14
- navigate: (screen: string, props?: Record<string, any>) => void;
18
+ navigate: (screen: RouteName, props?: Record<string, any>) => void;
15
19
 
16
20
  // Step navigation
17
21
  nextStep: () => void;
@@ -29,6 +33,7 @@ interface RecoverRequestStepProps {
29
33
  setErrorMessage: (message: string) => void;
30
34
  isLoading: boolean;
31
35
  setIsLoading: (loading: boolean) => void;
36
+ oxyServices?: OxyServices;
32
37
  }
33
38
 
34
39
  const RecoverRequestStep: React.FC<RecoverRequestStepProps> = ({
@@ -42,17 +47,19 @@ const RecoverRequestStep: React.FC<RecoverRequestStepProps> = ({
42
47
  setErrorMessage,
43
48
  isLoading,
44
49
  setIsLoading,
50
+ oxyServices,
45
51
  }) => {
46
52
  const inputRef = useRef<any>(null);
53
+ const { t } = useI18n();
47
54
 
48
55
  const handleIdentifierChange = (text: string) => {
49
56
  setIdentifier(text);
50
57
  if (errorMessage) setErrorMessage('');
51
58
  };
52
59
 
53
- const handleRequest = () => {
60
+ const handleRequest = async () => {
54
61
  if (!identifier || identifier.length < 3) {
55
- setErrorMessage('Please enter your email or username.');
62
+ setErrorMessage(t('recover.username.errorRequired') || 'Please enter your username.');
56
63
  setTimeout(() => inputRef.current?.focus(), 0);
57
64
  return;
58
65
  }
@@ -60,11 +67,11 @@ const RecoverRequestStep: React.FC<RecoverRequestStepProps> = ({
60
67
  setErrorMessage('');
61
68
  setIsLoading(true);
62
69
 
63
- // Simulate API call
64
- setTimeout(() => {
70
+ try {
71
+ toast.info(t('recover.noEmail'));
72
+ } finally {
65
73
  setIsLoading(false);
66
- nextStep(); // Move to verification step
67
- }, 1200);
74
+ }
68
75
  };
69
76
 
70
77
  const handleRequestWithFocus = () => {
@@ -78,18 +85,14 @@ const RecoverRequestStep: React.FC<RecoverRequestStepProps> = ({
78
85
  <>
79
86
  <HighFive width={100} height={100} />
80
87
  <View style={styles.modernHeader}>
81
- <Text style={[styles.modernTitle, { color: colors.text }]}>
82
- Recover Account
83
- </Text>
84
- <Text style={[styles.modernSubtitle, { color: colors.secondaryText }]}>
85
- Enter your email or username to receive a 6-digit code.
86
- </Text>
88
+ <Text style={[styles.modernTitle, { color: colors.text }]}>{t('recover.title')}</Text>
89
+ <Text style={[styles.modernSubtitle, { color: colors.secondaryText }]}>{t('recover.noEmail')}</Text>
87
90
  </View>
88
91
 
89
92
  <View style={styles.modernInputContainer}>
90
93
  <TextField
91
94
  ref={inputRef}
92
- label="Email or Username"
95
+ label={t('recover.username.label')}
93
96
  leading={<Ionicons name="mail-outline" size={24} color={colors.secondaryText} />}
94
97
  value={identifier}
95
98
  onChangeText={handleIdentifierChange}
@@ -107,15 +110,15 @@ const RecoverRequestStep: React.FC<RecoverRequestStepProps> = ({
107
110
  <GroupedPillButtons
108
111
  buttons={[
109
112
  {
110
- text: 'Back to Sign In',
113
+ text: t('common.actions.back'),
111
114
  onPress: () => navigate('SignIn'),
112
115
  icon: 'arrow-back',
113
116
  variant: 'transparent',
114
117
  },
115
118
  {
116
- text: 'Send Code',
119
+ text: t('common.actions.continue'),
117
120
  onPress: handleRequest,
118
- icon: 'mail-open-outline',
121
+ icon: 'information-circle-outline',
119
122
  variant: 'primary',
120
123
  loading: isLoading,
121
124
  disabled: isLoading,
@@ -0,0 +1,133 @@
1
+ import type React from 'react';
2
+ import type { RouteName } from '../../navigation/routes';
3
+ import { View, Text } from 'react-native';
4
+ import { Ionicons } from '@expo/vector-icons';
5
+ import GroupedPillButtons from '../../components/internal/GroupedPillButtons';
6
+ import TextField from '../../components/internal/TextField';
7
+ import { useI18n } from '../../hooks/useI18n';
8
+
9
+ interface RecoverResetPasswordStepProps {
10
+ // Common props
11
+ colors: any;
12
+ styles: any;
13
+ theme: string;
14
+ navigate: (screen: RouteName, props?: Record<string, any>) => void;
15
+
16
+ // Navigation
17
+ nextStep: () => void;
18
+ prevStep: () => void;
19
+
20
+ // From previous steps
21
+ identifier: string;
22
+ verificationCode: string;
23
+
24
+ // Local state
25
+ password: string;
26
+ confirmPassword: string;
27
+ setPassword: (s: string) => void;
28
+ setConfirmPassword: (s: string) => void;
29
+ errorMessage: string;
30
+ setErrorMessage: (s: string) => void;
31
+ isLoading: boolean;
32
+ setIsLoading: (b: boolean) => void;
33
+
34
+ // Services
35
+ oxyServices: any;
36
+ }
37
+
38
+ const RecoverResetPasswordStep: React.FC<RecoverResetPasswordStepProps> = ({
39
+ colors,
40
+ styles,
41
+ nextStep,
42
+ prevStep,
43
+ identifier,
44
+ verificationCode,
45
+ password,
46
+ confirmPassword,
47
+ setPassword,
48
+ setConfirmPassword,
49
+ errorMessage,
50
+ setErrorMessage,
51
+ isLoading,
52
+ setIsLoading,
53
+ oxyServices,
54
+ }) => {
55
+ const { t } = useI18n();
56
+ const handleReset = async () => {
57
+ if (!password || password.length < 8) {
58
+ setErrorMessage(t('recover.password.minLength') || 'Password must be at least 8 characters long');
59
+ return;
60
+ }
61
+ if (password !== confirmPassword) {
62
+ setErrorMessage(t('recover.password.mismatch') || 'Passwords do not match');
63
+ return;
64
+ }
65
+ setErrorMessage('');
66
+ setIsLoading(true);
67
+ try {
68
+ const code = verificationCode?.trim();
69
+ if (!code) throw new Error(t('recover.missingCode') || 'Missing code');
70
+
71
+ // Heuristic: recovery key starts with 'oxy-' or longer strings, backup codes have dashes of short format, else assume TOTP
72
+ if (code.toLowerCase().startsWith('oxy-') || code.length >= 16) {
73
+ await oxyServices.resetPasswordWithRecoveryKey(identifier, code, password);
74
+ } else if (/[A-Za-z0-9]+-[A-Za-z0-9]+/.test(code)) {
75
+ await oxyServices.resetPasswordWithBackupCode(identifier, code, password);
76
+ } else {
77
+ await oxyServices.resetPasswordWithTotp(identifier, code, password);
78
+ }
79
+ nextStep();
80
+ } catch (e: any) {
81
+ setErrorMessage(e?.message || t('recover.password.resetFailed') || 'Failed to reset password');
82
+ } finally {
83
+ setIsLoading(false);
84
+ }
85
+ };
86
+
87
+ return (
88
+ <>
89
+ <View style={styles.modernHeader}>
90
+ <Text style={[styles.modernTitle, { color: colors.text }]}>{t('recover.newPassword')}</Text>
91
+ <Text style={[styles.modernSubtitle, { color: colors.secondaryText }]}>{t('recover.title')} @{identifier}</Text>
92
+ </View>
93
+
94
+ <View style={styles.modernInputContainer}>
95
+ <TextField
96
+ label={t('common.labels.password')}
97
+ leading={<Ionicons name="lock-closed-outline" size={24} color={colors.secondaryText} />}
98
+ value={password}
99
+ onChangeText={setPassword}
100
+ secureTextEntry
101
+ autoCapitalize="none"
102
+ autoCorrect={false}
103
+ variant="filled"
104
+ error={errorMessage || undefined}
105
+ onSubmitEditing={handleReset}
106
+ autoFocus
107
+ />
108
+
109
+ <TextField
110
+ label={t('common.labels.confirmPassword')}
111
+ leading={<Ionicons name="lock-closed-outline" size={24} color={colors.secondaryText} />}
112
+ value={confirmPassword}
113
+ onChangeText={setConfirmPassword}
114
+ secureTextEntry
115
+ autoCapitalize="none"
116
+ autoCorrect={false}
117
+ variant="filled"
118
+ onSubmitEditing={handleReset}
119
+ />
120
+ </View>
121
+
122
+ <GroupedPillButtons
123
+ buttons={[
124
+ { text: t('common.actions.back'), onPress: prevStep, icon: 'arrow-back', variant: 'transparent' },
125
+ { text: t('common.actions.resetPassword'), onPress: handleReset, icon: 'key-outline', variant: 'primary', loading: isLoading, disabled: isLoading },
126
+ ]}
127
+ colors={colors}
128
+ />
129
+ </>
130
+ );
131
+ };
132
+
133
+ export default RecoverResetPasswordStep;
@@ -1,14 +1,16 @@
1
1
  import type React from 'react';
2
+ import type { RouteName } from '../../navigation/routes';
2
3
  import { View, Text } from 'react-native';
3
4
  import { Ionicons } from '@expo/vector-icons';
4
5
  import GroupedPillButtons from '../../components/internal/GroupedPillButtons';
6
+ import { useI18n } from '../../hooks/useI18n';
5
7
 
6
8
  interface RecoverSuccessStepProps {
7
9
  // Common props from StepBasedScreen
8
10
  colors: any;
9
11
  styles: any;
10
12
  theme: string;
11
- navigate: (screen: string, props?: Record<string, any>) => void;
13
+ navigate: (screen: RouteName, props?: Record<string, any>) => void;
12
14
 
13
15
  // Step navigation
14
16
  nextStep: () => void;
@@ -32,13 +34,14 @@ const RecoverSuccessStep: React.FC<RecoverSuccessStepProps> = ({
32
34
  allStepData,
33
35
  successMessage,
34
36
  }) => {
37
+ const { t } = useI18n();
35
38
  // Extract identifier from previous steps
36
39
  const requestData = allStepData[0] || {};
37
40
  const { identifier } = requestData;
38
41
 
39
42
  const handleContinueToReset = () => {
40
- // Navigate to password reset with the identifier
41
- navigate('ResetPassword', { identifier });
43
+ // Navigate back to SignIn and let host app open its reset flow
44
+ navigate('SignIn', { showReset: true, identifier });
42
45
  };
43
46
 
44
47
  const handleBackToSignIn = () => {
@@ -66,12 +69,8 @@ const RecoverSuccessStep: React.FC<RecoverSuccessStepProps> = ({
66
69
  </View>
67
70
 
68
71
  <View style={styles.modernHeader}>
69
- <Text style={[styles.modernTitle, { color: colors.text }]}>
70
- Account Verified!
71
- </Text>
72
- <Text style={[styles.modernSubtitle, { color: colors.secondaryText }]}>
73
- Your account has been successfully verified.
74
- </Text>
72
+ <Text style={[styles.modernTitle, { color: colors.text }]}>{t('recover.title')}</Text>
73
+ <Text style={[styles.modernSubtitle, { color: colors.secondaryText }]}>{successMessage || t('recover.resetSuccess')}</Text>
75
74
  </View>
76
75
 
77
76
  <View style={styles.modernInputContainer}>
@@ -84,10 +83,10 @@ const RecoverSuccessStep: React.FC<RecoverSuccessStepProps> = ({
84
83
  marginBottom: 24,
85
84
  }}>
86
85
  <Text style={[styles.footerText, { color: colors.text, fontSize: 16, marginBottom: 8 }]}>
87
- What's next?
86
+ {t('recover.whatsNextTitle') || "What's next?"}
88
87
  </Text>
89
88
  <Text style={[styles.footerText, { color: colors.secondaryText, fontSize: 14, lineHeight: 20 }]}>
90
- You can now reset your password or return to sign in with your existing credentials.
89
+ {t('recover.whatsNextBody') || 'You can now reset your password or return to sign in with your existing credentials.'}
91
90
  </Text>
92
91
  </View>
93
92
 
@@ -102,7 +101,7 @@ const RecoverSuccessStep: React.FC<RecoverSuccessStepProps> = ({
102
101
  }}>
103
102
  <Ionicons name="shield-checkmark" size={20} color={colors.success} style={{ marginRight: 8 }} />
104
103
  <Text style={[styles.footerText, { color: colors.success, fontSize: 14, flex: 1 }]}>
105
- {successMessage || 'Your account recovery is complete and secure.'}
104
+ {successMessage || t('recover.completeSecure') || 'Your account recovery is complete and secure.'}
106
105
  </Text>
107
106
  </View>
108
107
  </View>
@@ -110,17 +109,11 @@ const RecoverSuccessStep: React.FC<RecoverSuccessStepProps> = ({
110
109
  <GroupedPillButtons
111
110
  buttons={[
112
111
  {
113
- text: 'Back to Sign In',
112
+ text: t('common.actions.signIn'),
114
113
  onPress: handleBackToSignIn,
115
114
  icon: 'arrow-back',
116
115
  variant: 'transparent',
117
116
  },
118
- {
119
- text: 'Reset Password',
120
- onPress: handleContinueToReset,
121
- icon: 'key-outline',
122
- variant: 'primary',
123
- },
124
117
  ]}
125
118
  colors={colors}
126
119
  />
@@ -1,15 +1,18 @@
1
1
  import type React from 'react';
2
+ import type { RouteName } from '../../navigation/routes';
2
3
  import { View, Text } from 'react-native';
3
4
  import { Ionicons } from '@expo/vector-icons';
4
5
  import GroupedPillButtons from '../../components/internal/GroupedPillButtons';
5
6
  import PinInput from '../../components/internal/PinInput';
7
+ import { toast } from '../../../lib/sonner';
8
+ import { useI18n } from '../../hooks/useI18n';
6
9
 
7
10
  interface RecoverVerifyStepProps {
8
11
  // Common props from StepBasedScreen
9
12
  colors: any;
10
13
  styles: any;
11
14
  theme: string;
12
- navigate: (screen: string, props?: Record<string, any>) => void;
15
+ navigate: (screen: RouteName, props?: Record<string, any>) => void;
13
16
 
14
17
  // Step navigation
15
18
  nextStep: () => void;
@@ -30,6 +33,7 @@ interface RecoverVerifyStepProps {
30
33
  setSuccessMessage: (message: string) => void;
31
34
  isLoading: boolean;
32
35
  setIsLoading: (loading: boolean) => void;
36
+ identifier?: string;
33
37
  }
34
38
 
35
39
  const RecoverVerifyStep: React.FC<RecoverVerifyStepProps> = ({
@@ -45,39 +49,26 @@ const RecoverVerifyStep: React.FC<RecoverVerifyStepProps> = ({
45
49
  setSuccessMessage,
46
50
  isLoading,
47
51
  setIsLoading,
52
+ identifier,
48
53
  }) => {
49
- const handleVerifyCode = () => {
54
+ const { t } = useI18n();
55
+ const handleVerifyCode = async () => {
50
56
  setErrorMessage('');
51
57
  setSuccessMessage('');
52
58
 
53
59
  if (verificationCode.length !== 6) {
54
- setErrorMessage('Please enter the 6-digit code.');
60
+ setErrorMessage(t('recover.enterCode'));
55
61
  return;
56
62
  }
57
-
58
- setIsLoading(true);
59
-
60
- // Simulate verification
61
- setTimeout(() => {
62
- setIsLoading(false);
63
- if (verificationCode === '123456') { // Simulate correct code
64
- setSuccessMessage('Your account has been verified! You can now reset your password.');
65
- nextStep(); // Move to success step
66
- } else {
67
- setErrorMessage('Invalid code. Please try again.');
68
- }
69
- }, 1200);
63
+ // For recovery via TOTP, proceed to reset step; server will validate during reset
64
+ nextStep();
70
65
  };
71
66
 
72
67
  return (
73
68
  <>
74
69
  <View style={styles.modernHeader}>
75
- <Text style={[styles.modernTitle, { color: colors.text }]}>
76
- Verify Code
77
- </Text>
78
- <Text style={[styles.modernSubtitle, { color: colors.secondaryText }]}>
79
- Enter the 6-digit code sent to your email or phone.
80
- </Text>
70
+ <Text style={[styles.modernTitle, { color: colors.text }]}>{t('recover.verify.title')}</Text>
71
+ <Text style={[styles.modernSubtitle, { color: colors.secondaryText }]}>{t('recover.enterCode')}</Text>
81
72
  </View>
82
73
 
83
74
  <View style={styles.modernInputContainer}>
@@ -130,13 +121,13 @@ const RecoverVerifyStep: React.FC<RecoverVerifyStepProps> = ({
130
121
  <GroupedPillButtons
131
122
  buttons={[
132
123
  {
133
- text: 'Back',
124
+ text: t('common.actions.back'),
134
125
  onPress: prevStep,
135
126
  icon: 'arrow-back',
136
127
  variant: 'transparent',
137
128
  },
138
129
  {
139
- text: 'Verify Code',
130
+ text: t('recover.verify.action'),
140
131
  onPress: handleVerifyCode,
141
132
  icon: 'checkmark-circle-outline',
142
133
  variant: 'primary',