@oxyhq/services 5.11.12 → 5.12.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.
- package/README.md +48 -7
- package/lib/commonjs/core/OxyServices.js +162 -12
- package/lib/commonjs/core/OxyServices.js.map +1 -1
- package/lib/commonjs/i18n/index.js +40 -0
- package/lib/commonjs/i18n/index.js.map +1 -0
- package/lib/commonjs/i18n/locales/en-US.json +681 -0
- package/lib/commonjs/i18n/locales/es-ES.json +689 -0
- package/lib/commonjs/ui/components/GroupedItem.js +2 -1
- package/lib/commonjs/ui/components/GroupedItem.js.map +1 -1
- package/lib/commonjs/ui/components/Header.js +4 -3
- package/lib/commonjs/ui/components/Header.js.map +1 -1
- package/lib/commonjs/ui/components/OxyProvider.js +110 -103
- package/lib/commonjs/ui/components/OxyProvider.js.map +1 -1
- package/lib/commonjs/ui/components/ProfileCard.js +5 -1
- package/lib/commonjs/ui/components/ProfileCard.js.map +1 -1
- package/lib/commonjs/ui/components/Section.js +1 -1
- package/lib/commonjs/ui/components/StepBasedScreen.js +16 -16
- package/lib/commonjs/ui/components/StepBasedScreen.js.map +1 -1
- package/lib/commonjs/ui/components/internal/GroupedPillButtons.js +15 -3
- package/lib/commonjs/ui/components/internal/GroupedPillButtons.js.map +1 -1
- package/lib/commonjs/ui/components/internal/PinInput.js +10 -4
- package/lib/commonjs/ui/components/internal/PinInput.js.map +1 -1
- package/lib/commonjs/ui/context/OxyContext.js +128 -12
- package/lib/commonjs/ui/context/OxyContext.js.map +1 -1
- package/lib/commonjs/ui/hooks/useI18n.js +22 -0
- package/lib/commonjs/ui/hooks/useI18n.js.map +1 -0
- package/lib/commonjs/ui/navigation/OxyRouter.js +11 -131
- package/lib/commonjs/ui/navigation/OxyRouter.js.map +1 -1
- package/lib/commonjs/ui/navigation/routes.js +127 -0
- package/lib/commonjs/ui/navigation/routes.js.map +1 -0
- package/lib/commonjs/ui/navigation/types.js +7 -0
- package/lib/commonjs/ui/navigation/types.js.map +1 -1
- package/lib/commonjs/ui/screens/AccountCenterScreen.js +55 -47
- package/lib/commonjs/ui/screens/AccountCenterScreen.js.map +1 -1
- package/lib/commonjs/ui/screens/AccountOverviewScreen.js +69 -61
- package/lib/commonjs/ui/screens/AccountOverviewScreen.js.map +1 -1
- package/lib/commonjs/ui/screens/AccountSettingsScreen.js +378 -37
- package/lib/commonjs/ui/screens/AccountSettingsScreen.js.map +1 -1
- package/lib/commonjs/ui/screens/AccountSwitcherScreen.js +52 -34
- package/lib/commonjs/ui/screens/AccountSwitcherScreen.js.map +1 -1
- package/lib/commonjs/ui/screens/FeedbackScreen.js +40 -36
- package/lib/commonjs/ui/screens/FeedbackScreen.js.map +1 -1
- package/lib/commonjs/ui/screens/LanguageSelectorScreen.js +105 -78
- package/lib/commonjs/ui/screens/LanguageSelectorScreen.js.map +1 -1
- package/lib/commonjs/ui/screens/PaymentGatewayScreen.js +1 -1
- package/lib/commonjs/ui/screens/PaymentGatewayScreen.js.map +1 -1
- package/lib/commonjs/ui/screens/PremiumSubscriptionScreen.js +92 -60
- package/lib/commonjs/ui/screens/PremiumSubscriptionScreen.js.map +1 -1
- package/lib/commonjs/ui/screens/ProfileScreen.js +21 -11
- package/lib/commonjs/ui/screens/ProfileScreen.js.map +1 -1
- package/lib/commonjs/ui/screens/RecoverAccountScreen.js +30 -8
- package/lib/commonjs/ui/screens/RecoverAccountScreen.js.map +1 -1
- package/lib/commonjs/ui/screens/SignInScreen.js +47 -26
- package/lib/commonjs/ui/screens/SignInScreen.js.map +1 -1
- package/lib/commonjs/ui/screens/WelcomeNewUserScreen.js +31 -24
- package/lib/commonjs/ui/screens/WelcomeNewUserScreen.js.map +1 -1
- package/lib/commonjs/ui/screens/internal/SignInPasswordStep.js +11 -7
- package/lib/commonjs/ui/screens/internal/SignInPasswordStep.js.map +1 -1
- package/lib/commonjs/ui/screens/internal/SignInUsernameStep.js +12 -6
- package/lib/commonjs/ui/screens/internal/SignInUsernameStep.js.map +1 -1
- package/lib/commonjs/ui/screens/karma/KarmaAboutScreen.js +11 -7
- package/lib/commonjs/ui/screens/karma/KarmaAboutScreen.js.map +1 -1
- package/lib/commonjs/ui/screens/karma/KarmaCenterScreen.js +15 -11
- package/lib/commonjs/ui/screens/karma/KarmaCenterScreen.js.map +1 -1
- package/lib/commonjs/ui/screens/karma/KarmaFAQScreen.js +19 -27
- package/lib/commonjs/ui/screens/karma/KarmaFAQScreen.js.map +1 -1
- package/lib/commonjs/ui/screens/karma/KarmaLeaderboardScreen.js +8 -4
- package/lib/commonjs/ui/screens/karma/KarmaLeaderboardScreen.js.map +1 -1
- package/lib/commonjs/ui/screens/karma/KarmaRewardsScreen.js +14 -10
- package/lib/commonjs/ui/screens/karma/KarmaRewardsScreen.js.map +1 -1
- package/lib/commonjs/ui/screens/karma/KarmaRulesScreen.js +7 -3
- package/lib/commonjs/ui/screens/karma/KarmaRulesScreen.js.map +1 -1
- package/lib/commonjs/ui/screens/steps/RecoverRequestStep.js +19 -14
- package/lib/commonjs/ui/screens/steps/RecoverRequestStep.js.map +1 -1
- package/lib/commonjs/ui/screens/steps/RecoverResetPasswordStep.js +130 -0
- package/lib/commonjs/ui/screens/steps/RecoverResetPasswordStep.js.map +1 -0
- package/lib/commonjs/ui/screens/steps/RecoverSuccessStep.js +13 -13
- package/lib/commonjs/ui/screens/steps/RecoverSuccessStep.js.map +1 -1
- package/lib/commonjs/ui/screens/steps/RecoverVerifyStep.js +14 -20
- package/lib/commonjs/ui/screens/steps/RecoverVerifyStep.js.map +1 -1
- package/lib/commonjs/ui/screens/steps/SignInPasswordStep.js +22 -8
- package/lib/commonjs/ui/screens/steps/SignInPasswordStep.js.map +1 -1
- package/lib/commonjs/ui/screens/steps/SignInTotpStep.js +161 -0
- package/lib/commonjs/ui/screens/steps/SignInTotpStep.js.map +1 -0
- package/lib/commonjs/ui/screens/steps/SignInUsernameStep.js +12 -6
- package/lib/commonjs/ui/screens/steps/SignInUsernameStep.js.map +1 -1
- package/lib/commonjs/ui/screens/steps/SignUpIdentityStep.js +10 -6
- package/lib/commonjs/ui/screens/steps/SignUpIdentityStep.js.map +1 -1
- package/lib/commonjs/ui/screens/steps/SignUpSecurityStep.js +10 -6
- package/lib/commonjs/ui/screens/steps/SignUpSecurityStep.js.map +1 -1
- package/lib/commonjs/ui/screens/steps/SignUpSummaryStep.js +34 -4
- package/lib/commonjs/ui/screens/steps/SignUpSummaryStep.js.map +1 -1
- package/lib/commonjs/ui/screens/steps/SignUpWelcomeStep.js +9 -10
- package/lib/commonjs/ui/screens/steps/SignUpWelcomeStep.js.map +1 -1
- package/lib/commonjs/ui/styles/authStyles.js +1 -2
- package/lib/commonjs/ui/styles/authStyles.js.map +1 -1
- package/lib/commonjs/utils/deviceManager.js +1 -1
- package/lib/commonjs/utils/deviceManager.js.map +1 -1
- package/lib/commonjs/utils/validationUtils.js +4 -2
- package/lib/commonjs/utils/validationUtils.js.map +1 -1
- package/lib/module/core/OxyServices.js +162 -12
- package/lib/module/core/OxyServices.js.map +1 -1
- package/lib/module/i18n/index.js +35 -0
- package/lib/module/i18n/index.js.map +1 -0
- package/lib/module/i18n/locales/en-US.json +681 -0
- package/lib/module/i18n/locales/es-ES.json +689 -0
- package/lib/module/ui/components/GroupedItem.js +2 -1
- package/lib/module/ui/components/GroupedItem.js.map +1 -1
- package/lib/module/ui/components/Header.js +4 -3
- package/lib/module/ui/components/Header.js.map +1 -1
- package/lib/module/ui/components/OxyProvider.js +109 -103
- package/lib/module/ui/components/OxyProvider.js.map +1 -1
- package/lib/module/ui/components/ProfileCard.js +5 -1
- package/lib/module/ui/components/ProfileCard.js.map +1 -1
- package/lib/module/ui/components/Section.js +1 -1
- package/lib/module/ui/components/StepBasedScreen.js +16 -16
- package/lib/module/ui/components/StepBasedScreen.js.map +1 -1
- package/lib/module/ui/components/internal/GroupedPillButtons.js +15 -3
- package/lib/module/ui/components/internal/GroupedPillButtons.js.map +1 -1
- package/lib/module/ui/components/internal/PinInput.js +9 -4
- package/lib/module/ui/components/internal/PinInput.js.map +1 -1
- package/lib/module/ui/context/OxyContext.js +128 -12
- package/lib/module/ui/context/OxyContext.js.map +1 -1
- package/lib/module/ui/hooks/useI18n.js +18 -0
- package/lib/module/ui/hooks/useI18n.js.map +1 -0
- package/lib/module/ui/navigation/OxyRouter.js +7 -124
- package/lib/module/ui/navigation/OxyRouter.js.map +1 -1
- package/lib/module/ui/navigation/routes.js +122 -0
- package/lib/module/ui/navigation/routes.js.map +1 -0
- package/lib/module/ui/navigation/types.js +19 -1
- package/lib/module/ui/navigation/types.js.map +1 -1
- package/lib/module/ui/screens/AccountCenterScreen.js +55 -47
- package/lib/module/ui/screens/AccountCenterScreen.js.map +1 -1
- package/lib/module/ui/screens/AccountOverviewScreen.js +69 -61
- package/lib/module/ui/screens/AccountOverviewScreen.js.map +1 -1
- package/lib/module/ui/screens/AccountSettingsScreen.js +378 -37
- package/lib/module/ui/screens/AccountSettingsScreen.js.map +1 -1
- package/lib/module/ui/screens/AccountSwitcherScreen.js +52 -34
- package/lib/module/ui/screens/AccountSwitcherScreen.js.map +1 -1
- package/lib/module/ui/screens/FeedbackScreen.js +40 -36
- package/lib/module/ui/screens/FeedbackScreen.js.map +1 -1
- package/lib/module/ui/screens/LanguageSelectorScreen.js +107 -80
- package/lib/module/ui/screens/LanguageSelectorScreen.js.map +1 -1
- package/lib/module/ui/screens/PaymentGatewayScreen.js +1 -1
- package/lib/module/ui/screens/PaymentGatewayScreen.js.map +1 -1
- package/lib/module/ui/screens/PremiumSubscriptionScreen.js +92 -60
- package/lib/module/ui/screens/PremiumSubscriptionScreen.js.map +1 -1
- package/lib/module/ui/screens/ProfileScreen.js +21 -11
- package/lib/module/ui/screens/ProfileScreen.js.map +1 -1
- package/lib/module/ui/screens/RecoverAccountScreen.js +30 -8
- package/lib/module/ui/screens/RecoverAccountScreen.js.map +1 -1
- package/lib/module/ui/screens/SignInScreen.js +47 -26
- package/lib/module/ui/screens/SignInScreen.js.map +1 -1
- package/lib/module/ui/screens/WelcomeNewUserScreen.js +31 -24
- package/lib/module/ui/screens/WelcomeNewUserScreen.js.map +1 -1
- package/lib/module/ui/screens/internal/SignInPasswordStep.js +11 -7
- package/lib/module/ui/screens/internal/SignInPasswordStep.js.map +1 -1
- package/lib/module/ui/screens/internal/SignInUsernameStep.js +12 -6
- package/lib/module/ui/screens/internal/SignInUsernameStep.js.map +1 -1
- package/lib/module/ui/screens/karma/KarmaAboutScreen.js +11 -7
- package/lib/module/ui/screens/karma/KarmaAboutScreen.js.map +1 -1
- package/lib/module/ui/screens/karma/KarmaCenterScreen.js +15 -11
- package/lib/module/ui/screens/karma/KarmaCenterScreen.js.map +1 -1
- package/lib/module/ui/screens/karma/KarmaFAQScreen.js +19 -27
- package/lib/module/ui/screens/karma/KarmaFAQScreen.js.map +1 -1
- package/lib/module/ui/screens/karma/KarmaLeaderboardScreen.js +8 -4
- package/lib/module/ui/screens/karma/KarmaLeaderboardScreen.js.map +1 -1
- package/lib/module/ui/screens/karma/KarmaRewardsScreen.js +14 -10
- package/lib/module/ui/screens/karma/KarmaRewardsScreen.js.map +1 -1
- package/lib/module/ui/screens/karma/KarmaRulesScreen.js +7 -3
- package/lib/module/ui/screens/karma/KarmaRulesScreen.js.map +1 -1
- package/lib/module/ui/screens/steps/RecoverRequestStep.js +19 -14
- package/lib/module/ui/screens/steps/RecoverRequestStep.js.map +1 -1
- package/lib/module/ui/screens/steps/RecoverResetPasswordStep.js +125 -0
- package/lib/module/ui/screens/steps/RecoverResetPasswordStep.js.map +1 -0
- package/lib/module/ui/screens/steps/RecoverSuccessStep.js +13 -13
- package/lib/module/ui/screens/steps/RecoverSuccessStep.js.map +1 -1
- package/lib/module/ui/screens/steps/RecoverVerifyStep.js +14 -20
- package/lib/module/ui/screens/steps/RecoverVerifyStep.js.map +1 -1
- package/lib/module/ui/screens/steps/SignInPasswordStep.js +22 -8
- package/lib/module/ui/screens/steps/SignInPasswordStep.js.map +1 -1
- package/lib/module/ui/screens/steps/SignInTotpStep.js +156 -0
- package/lib/module/ui/screens/steps/SignInTotpStep.js.map +1 -0
- package/lib/module/ui/screens/steps/SignInUsernameStep.js +12 -6
- package/lib/module/ui/screens/steps/SignInUsernameStep.js.map +1 -1
- package/lib/module/ui/screens/steps/SignUpIdentityStep.js +10 -6
- package/lib/module/ui/screens/steps/SignUpIdentityStep.js.map +1 -1
- package/lib/module/ui/screens/steps/SignUpSecurityStep.js +10 -6
- package/lib/module/ui/screens/steps/SignUpSecurityStep.js.map +1 -1
- package/lib/module/ui/screens/steps/SignUpSummaryStep.js +34 -4
- package/lib/module/ui/screens/steps/SignUpSummaryStep.js.map +1 -1
- package/lib/module/ui/screens/steps/SignUpWelcomeStep.js +9 -10
- package/lib/module/ui/screens/steps/SignUpWelcomeStep.js.map +1 -1
- package/lib/module/ui/styles/authStyles.js +1 -2
- package/lib/module/ui/styles/authStyles.js.map +1 -1
- package/lib/module/utils/deviceManager.js +1 -1
- package/lib/module/utils/deviceManager.js.map +1 -1
- package/lib/module/utils/validationUtils.js +4 -2
- package/lib/module/utils/validationUtils.js.map +1 -1
- package/lib/typescript/core/OxyServices.d.ts +57 -3
- package/lib/typescript/core/OxyServices.d.ts.map +1 -1
- package/lib/typescript/i18n/index.d.ts +4 -0
- package/lib/typescript/i18n/index.d.ts.map +1 -0
- package/lib/typescript/models/interfaces.d.ts +4 -0
- package/lib/typescript/models/interfaces.d.ts.map +1 -1
- package/lib/typescript/ui/components/GroupedItem.d.ts.map +1 -1
- package/lib/typescript/ui/components/Header.d.ts.map +1 -1
- package/lib/typescript/ui/components/OxyProvider.d.ts +1 -1
- package/lib/typescript/ui/components/OxyProvider.d.ts.map +1 -1
- package/lib/typescript/ui/components/ProfileCard.d.ts.map +1 -1
- package/lib/typescript/ui/components/StepBasedScreen.d.ts +2 -1
- package/lib/typescript/ui/components/StepBasedScreen.d.ts.map +1 -1
- package/lib/typescript/ui/components/internal/GroupedPillButtons.d.ts.map +1 -1
- package/lib/typescript/ui/components/internal/PinInput.d.ts +6 -3
- package/lib/typescript/ui/components/internal/PinInput.d.ts.map +1 -1
- package/lib/typescript/ui/context/OxyContext.d.ts +7 -4
- package/lib/typescript/ui/context/OxyContext.d.ts.map +1 -1
- package/lib/typescript/ui/hooks/useI18n.d.ts +5 -0
- package/lib/typescript/ui/hooks/useI18n.d.ts.map +1 -0
- package/lib/typescript/ui/navigation/OxyRouter.d.ts.map +1 -1
- package/lib/typescript/ui/navigation/routes.d.ts +9 -0
- package/lib/typescript/ui/navigation/routes.d.ts.map +1 -0
- package/lib/typescript/ui/navigation/types.d.ts +24 -10
- package/lib/typescript/ui/navigation/types.d.ts.map +1 -1
- package/lib/typescript/ui/screens/AccountCenterScreen.d.ts.map +1 -1
- package/lib/typescript/ui/screens/AccountOverviewScreen.d.ts.map +1 -1
- package/lib/typescript/ui/screens/AccountSettingsScreen.d.ts.map +1 -1
- package/lib/typescript/ui/screens/AccountSwitcherScreen.d.ts.map +1 -1
- package/lib/typescript/ui/screens/FeedbackScreen.d.ts.map +1 -1
- package/lib/typescript/ui/screens/LanguageSelectorScreen.d.ts.map +1 -1
- package/lib/typescript/ui/screens/PremiumSubscriptionScreen.d.ts.map +1 -1
- package/lib/typescript/ui/screens/ProfileScreen.d.ts.map +1 -1
- package/lib/typescript/ui/screens/RecoverAccountScreen.d.ts.map +1 -1
- package/lib/typescript/ui/screens/SignInScreen.d.ts.map +1 -1
- package/lib/typescript/ui/screens/WelcomeNewUserScreen.d.ts.map +1 -1
- package/lib/typescript/ui/screens/internal/SignInPasswordStep.d.ts +2 -1
- package/lib/typescript/ui/screens/internal/SignInPasswordStep.d.ts.map +1 -1
- package/lib/typescript/ui/screens/internal/SignInUsernameStep.d.ts.map +1 -1
- package/lib/typescript/ui/screens/karma/KarmaAboutScreen.d.ts.map +1 -1
- package/lib/typescript/ui/screens/karma/KarmaCenterScreen.d.ts.map +1 -1
- package/lib/typescript/ui/screens/karma/KarmaFAQScreen.d.ts.map +1 -1
- package/lib/typescript/ui/screens/karma/KarmaLeaderboardScreen.d.ts.map +1 -1
- package/lib/typescript/ui/screens/karma/KarmaRewardsScreen.d.ts.map +1 -1
- package/lib/typescript/ui/screens/karma/KarmaRulesScreen.d.ts.map +1 -1
- package/lib/typescript/ui/screens/steps/RecoverRequestStep.d.ts +4 -1
- package/lib/typescript/ui/screens/steps/RecoverRequestStep.d.ts.map +1 -1
- package/lib/typescript/ui/screens/steps/RecoverResetPasswordStep.d.ts +24 -0
- package/lib/typescript/ui/screens/steps/RecoverResetPasswordStep.d.ts.map +1 -0
- package/lib/typescript/ui/screens/steps/RecoverSuccessStep.d.ts +2 -1
- package/lib/typescript/ui/screens/steps/RecoverSuccessStep.d.ts.map +1 -1
- package/lib/typescript/ui/screens/steps/RecoverVerifyStep.d.ts +3 -1
- package/lib/typescript/ui/screens/steps/RecoverVerifyStep.d.ts.map +1 -1
- package/lib/typescript/ui/screens/steps/SignInPasswordStep.d.ts +1 -0
- package/lib/typescript/ui/screens/steps/SignInPasswordStep.d.ts.map +1 -1
- package/lib/typescript/ui/screens/steps/SignInTotpStep.d.ts +19 -0
- package/lib/typescript/ui/screens/steps/SignInTotpStep.d.ts.map +1 -0
- package/lib/typescript/ui/screens/steps/SignInUsernameStep.d.ts +2 -1
- package/lib/typescript/ui/screens/steps/SignInUsernameStep.d.ts.map +1 -1
- package/lib/typescript/ui/screens/steps/SignUpIdentityStep.d.ts +2 -1
- package/lib/typescript/ui/screens/steps/SignUpIdentityStep.d.ts.map +1 -1
- package/lib/typescript/ui/screens/steps/SignUpSecurityStep.d.ts +2 -1
- package/lib/typescript/ui/screens/steps/SignUpSecurityStep.d.ts.map +1 -1
- package/lib/typescript/ui/screens/steps/SignUpSummaryStep.d.ts +2 -1
- package/lib/typescript/ui/screens/steps/SignUpSummaryStep.d.ts.map +1 -1
- package/lib/typescript/ui/screens/steps/SignUpWelcomeStep.d.ts +2 -1
- package/lib/typescript/ui/screens/steps/SignUpWelcomeStep.d.ts.map +1 -1
- package/lib/typescript/ui/styles/authStyles.d.ts +0 -1
- package/lib/typescript/ui/styles/authStyles.d.ts.map +1 -1
- package/lib/typescript/utils/validationUtils.d.ts.map +1 -1
- package/package.json +49 -15
- package/src/core/OxyServices.ts +138 -19
- package/src/i18n/index.ts +39 -0
- package/src/i18n/locales/en-US.json +681 -0
- package/src/i18n/locales/es-ES.json +689 -0
- package/src/models/interfaces.ts +6 -1
- package/src/ui/components/GroupedItem.tsx +2 -1
- package/src/ui/components/Header.tsx +4 -3
- package/src/ui/components/OxyProvider.tsx +105 -112
- package/src/ui/components/ProfileCard.tsx +5 -1
- package/src/ui/components/Section.tsx +1 -1
- package/src/ui/components/StepBasedScreen.tsx +16 -13
- package/src/ui/components/internal/GroupedPillButtons.tsx +10 -6
- package/src/ui/components/internal/PinInput.tsx +15 -6
- package/src/ui/context/OxyContext.tsx +123 -20
- package/src/ui/hooks/useI18n.ts +12 -0
- package/src/ui/navigation/OxyRouter.tsx +15 -134
- package/src/ui/navigation/routes.ts +153 -0
- package/src/ui/navigation/types.ts +28 -10
- package/src/ui/screens/AccountCenterScreen.tsx +47 -45
- package/src/ui/screens/AccountOverviewScreen.tsx +68 -70
- package/src/ui/screens/AccountSettingsScreen.tsx +265 -41
- package/src/ui/screens/AccountSwitcherScreen.tsx +35 -33
- package/src/ui/screens/FeedbackScreen.tsx +39 -37
- package/src/ui/screens/LanguageSelectorScreen.tsx +99 -70
- package/src/ui/screens/PaymentGatewayScreen.tsx +5 -5
- package/src/ui/screens/PremiumSubscriptionScreen.tsx +56 -54
- package/src/ui/screens/ProfileScreen.tsx +14 -8
- package/src/ui/screens/RecoverAccountScreen.tsx +29 -8
- package/src/ui/screens/SignInScreen.tsx +39 -30
- package/src/ui/screens/WelcomeNewUserScreen.tsx +31 -17
- package/src/ui/screens/internal/SignInPasswordStep.tsx +11 -8
- package/src/ui/screens/internal/SignInUsernameStep.tsx +10 -8
- package/src/ui/screens/karma/KarmaAboutScreen.tsx +23 -11
- package/src/ui/screens/karma/KarmaCenterScreen.tsx +21 -11
- package/src/ui/screens/karma/KarmaFAQScreen.tsx +15 -33
- package/src/ui/screens/karma/KarmaLeaderboardScreen.tsx +6 -4
- package/src/ui/screens/karma/KarmaRewardsScreen.tsx +28 -10
- package/src/ui/screens/karma/KarmaRulesScreen.tsx +5 -3
- package/src/ui/screens/steps/RecoverRequestStep.tsx +20 -17
- package/src/ui/screens/steps/RecoverResetPasswordStep.tsx +133 -0
- package/src/ui/screens/steps/RecoverSuccessStep.tsx +12 -19
- package/src/ui/screens/steps/RecoverVerifyStep.tsx +15 -24
- package/src/ui/screens/steps/SignInPasswordStep.tsx +19 -6
- package/src/ui/screens/steps/SignInTotpStep.tsx +129 -0
- package/src/ui/screens/steps/SignInUsernameStep.tsx +11 -10
- package/src/ui/screens/steps/SignUpIdentityStep.tsx +10 -11
- package/src/ui/screens/steps/SignUpSecurityStep.tsx +10 -11
- package/src/ui/screens/steps/SignUpSummaryStep.tsx +24 -9
- package/src/ui/screens/steps/SignUpWelcomeStep.tsx +8 -14
- package/src/ui/styles/authStyles.ts +0 -1
- package/src/utils/deviceManager.ts +1 -1
- package/src/utils/validationUtils.ts +5 -3
|
@@ -7,6 +7,7 @@ import { toast } from '../../lib/sonner';
|
|
|
7
7
|
import StepBasedScreen, { type StepConfig } from '../components/StepBasedScreen';
|
|
8
8
|
import SignInUsernameStep from './steps/SignInUsernameStep';
|
|
9
9
|
import SignInPasswordStep from './steps/SignInPasswordStep';
|
|
10
|
+
import SignInTotpStep from './steps/SignInTotpStep';
|
|
10
11
|
|
|
11
12
|
const SignInScreen: React.FC<BaseScreenProps> = ({
|
|
12
13
|
navigate,
|
|
@@ -29,15 +30,10 @@ const SignInScreen: React.FC<BaseScreenProps> = ({
|
|
|
29
30
|
initialUserProfile ? 'valid' : 'idle'
|
|
30
31
|
);
|
|
31
32
|
|
|
32
|
-
// Monitor username state changes
|
|
33
|
-
useEffect(() => {
|
|
34
|
-
console.log('👀 SignInScreen username state changed:', username);
|
|
35
|
-
}, [username]);
|
|
36
|
-
|
|
37
33
|
// Cache for validation results to prevent repeated API calls
|
|
38
34
|
const validationCache = useRef<Map<string, { profile: any }>>(new Map());
|
|
39
35
|
|
|
40
|
-
const { login, isLoading, user, isAuthenticated, sessions, oxyServices } = useOxy();
|
|
36
|
+
const { login, completeMfaLogin, isLoading, user, isAuthenticated, sessions, oxyServices } = useOxy();
|
|
41
37
|
|
|
42
38
|
// Only log props in development mode to reduce console noise
|
|
43
39
|
if (__DEV__) {
|
|
@@ -55,10 +51,10 @@ const SignInScreen: React.FC<BaseScreenProps> = ({
|
|
|
55
51
|
|
|
56
52
|
// Username validation using core services with caching
|
|
57
53
|
const validateUsername = useCallback(async (usernameToValidate: string) => {
|
|
58
|
-
console.log('🔍 Validating username:', usernameToValidate);
|
|
54
|
+
if (__DEV__) console.log('🔍 Validating username:', usernameToValidate);
|
|
59
55
|
|
|
60
56
|
if (!usernameToValidate || usernameToValidate.length < 3) {
|
|
61
|
-
console.log('❌ Username too short');
|
|
57
|
+
if (__DEV__) console.log('❌ Username too short');
|
|
62
58
|
setValidationStatus('invalid');
|
|
63
59
|
setErrorMessage('Username must be at least 3 characters.');
|
|
64
60
|
return false;
|
|
@@ -75,21 +71,21 @@ const SignInScreen: React.FC<BaseScreenProps> = ({
|
|
|
75
71
|
// Check cache first
|
|
76
72
|
const cached = validationCache.current.get(usernameToValidate);
|
|
77
73
|
if (cached) {
|
|
78
|
-
console.log('✅ Username found in cache:', cached.profile);
|
|
74
|
+
if (__DEV__) console.log('✅ Username found in cache:', cached.profile);
|
|
79
75
|
setUserProfile(cached.profile);
|
|
80
76
|
setValidationStatus('valid');
|
|
81
77
|
setErrorMessage('');
|
|
82
78
|
return true;
|
|
83
79
|
}
|
|
84
80
|
|
|
85
|
-
console.log('🔄 Validating username with API...');
|
|
81
|
+
if (__DEV__) console.log('🔄 Validating username with API...');
|
|
86
82
|
setIsValidating(true);
|
|
87
83
|
setValidationStatus('validating');
|
|
88
84
|
|
|
89
85
|
try {
|
|
90
86
|
// Check if username exists
|
|
91
87
|
const profile = await oxyServices.getProfileByUsername(usernameToValidate);
|
|
92
|
-
console.log('📋 Profile response:', profile);
|
|
88
|
+
if (__DEV__) console.log('📋 Profile response:', profile);
|
|
93
89
|
|
|
94
90
|
if (profile && profile.username) {
|
|
95
91
|
const profileData = {
|
|
@@ -99,7 +95,7 @@ const SignInScreen: React.FC<BaseScreenProps> = ({
|
|
|
99
95
|
id: profile.id
|
|
100
96
|
};
|
|
101
97
|
|
|
102
|
-
console.log('✅ Username is valid:', profileData);
|
|
98
|
+
if (__DEV__) console.log('✅ Username is valid:', profileData);
|
|
103
99
|
setUserProfile(profileData);
|
|
104
100
|
setValidationStatus('valid');
|
|
105
101
|
setErrorMessage('');
|
|
@@ -111,13 +107,13 @@ const SignInScreen: React.FC<BaseScreenProps> = ({
|
|
|
111
107
|
|
|
112
108
|
return true;
|
|
113
109
|
} else {
|
|
114
|
-
console.log('❌ Username not found');
|
|
110
|
+
if (__DEV__) console.log('❌ Username not found');
|
|
115
111
|
setValidationStatus('invalid');
|
|
116
112
|
setErrorMessage('Username not found.');
|
|
117
113
|
return false;
|
|
118
114
|
}
|
|
119
115
|
} catch (error: any) {
|
|
120
|
-
console.log('🚨 Validation error:', error);
|
|
116
|
+
if (__DEV__) console.log('🚨 Validation error:', error);
|
|
121
117
|
|
|
122
118
|
// If user not found (404), username doesn't exist
|
|
123
119
|
if (error.status === 404 || error.code === 'USER_NOT_FOUND') {
|
|
@@ -129,7 +125,7 @@ const SignInScreen: React.FC<BaseScreenProps> = ({
|
|
|
129
125
|
|
|
130
126
|
// For development/testing: if API fails, allow any 3+ character username
|
|
131
127
|
if (__DEV__) {
|
|
132
|
-
console.log('⚠️ Development mode: allowing username due to API error');
|
|
128
|
+
if (__DEV__) console.log('⚠️ Development mode: allowing username due to API error');
|
|
133
129
|
setValidationStatus('valid');
|
|
134
130
|
setErrorMessage('');
|
|
135
131
|
return true;
|
|
@@ -179,6 +175,8 @@ const SignInScreen: React.FC<BaseScreenProps> = ({
|
|
|
179
175
|
return valid;
|
|
180
176
|
}, [username, validateUsername]);
|
|
181
177
|
|
|
178
|
+
const [mfaToken, setMfaToken] = useState<string | null>(null);
|
|
179
|
+
|
|
182
180
|
const handleSignIn = useCallback(async () => {
|
|
183
181
|
if (!password) {
|
|
184
182
|
setErrorMessage('Please enter your password.');
|
|
@@ -195,6 +193,10 @@ const SignInScreen: React.FC<BaseScreenProps> = ({
|
|
|
195
193
|
onAuthenticated(user);
|
|
196
194
|
}
|
|
197
195
|
} catch (error: any) {
|
|
196
|
+
if (error?.code === 'MFA_REQUIRED' && error?.mfaToken) {
|
|
197
|
+
setMfaToken(error.mfaToken);
|
|
198
|
+
return; // Password step will auto-advance when MFA token is set
|
|
199
|
+
}
|
|
198
200
|
setErrorMessage(error.message || 'Login failed');
|
|
199
201
|
}
|
|
200
202
|
}, [username, password, login, onAuthenticated, userProfile]);
|
|
@@ -207,24 +209,22 @@ const SignInScreen: React.FC<BaseScreenProps> = ({
|
|
|
207
209
|
}, []);
|
|
208
210
|
|
|
209
211
|
// Step configurations
|
|
210
|
-
const steps: StepConfig[] = useMemo(() =>
|
|
211
|
-
|
|
212
|
-
id: 'username',
|
|
213
|
-
component:
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
},
|
|
221
|
-
], [username, password, validationStatus, validateUsername, handleSignIn]);
|
|
212
|
+
const steps: StepConfig[] = useMemo(() => {
|
|
213
|
+
const base: StepConfig[] = [
|
|
214
|
+
{ id: 'username', component: SignInUsernameStep, canProceed: () => true },
|
|
215
|
+
{ id: 'password', component: SignInPasswordStep, canProceed: () => true },
|
|
216
|
+
];
|
|
217
|
+
if (mfaToken) {
|
|
218
|
+
base.push({ id: 'totp', component: SignInTotpStep, canProceed: () => true });
|
|
219
|
+
}
|
|
220
|
+
return base;
|
|
221
|
+
}, [mfaToken, username, password, validationStatus, validateUsername, handleSignIn]);
|
|
222
222
|
|
|
223
223
|
// Handle step completion (final step)
|
|
224
224
|
const handleComplete = useCallback(async (stepData: any[]) => {
|
|
225
225
|
// The sign-in is handled by the password step component
|
|
226
226
|
// This callback is here for interface compatibility
|
|
227
|
-
console.log('Sign-in flow completed');
|
|
227
|
+
if (__DEV__) console.log('Sign-in flow completed');
|
|
228
228
|
}, []);
|
|
229
229
|
|
|
230
230
|
// Step data for the reusable component
|
|
@@ -258,12 +258,21 @@ const SignInScreen: React.FC<BaseScreenProps> = ({
|
|
|
258
258
|
handleInputFocus,
|
|
259
259
|
handleInputBlur,
|
|
260
260
|
handleSignIn, // Add sign-in function for password step
|
|
261
|
+
mfaToken,
|
|
261
262
|
},
|
|
263
|
+
...(mfaToken ? [{
|
|
264
|
+
username,
|
|
265
|
+
mfaToken,
|
|
266
|
+
completeMfaLogin,
|
|
267
|
+
errorMessage,
|
|
268
|
+
setErrorMessage,
|
|
269
|
+
isLoading,
|
|
270
|
+
}] : []),
|
|
262
271
|
], [
|
|
263
|
-
username, password, errorMessage, validationStatus, userProfile,
|
|
272
|
+
username, password, errorMessage, validationStatus, userProfile, mfaToken,
|
|
264
273
|
isValidating, isInputFocused, isAddAccountMode, user, showPassword,
|
|
265
274
|
isLoading, handleUsernameChange, handlePasswordChange, handleInputFocus, handleInputBlur,
|
|
266
|
-
validateUsername, handleSignIn
|
|
275
|
+
validateUsername, handleSignIn, completeMfaLogin
|
|
267
276
|
]);
|
|
268
277
|
|
|
269
278
|
return (
|
|
@@ -8,6 +8,7 @@ import { toast } from '../../lib/sonner';
|
|
|
8
8
|
import { useAuthStore } from '../stores/authStore';
|
|
9
9
|
import { useThemeColors } from '../styles';
|
|
10
10
|
import GroupedPillButtons from '../components/internal/GroupedPillButtons';
|
|
11
|
+
import { useI18n } from '../hooks/useI18n';
|
|
11
12
|
|
|
12
13
|
/**
|
|
13
14
|
* Post-signup welcome & onboarding screen.
|
|
@@ -22,6 +23,7 @@ const WelcomeNewUserScreen: React.FC<BaseScreenProps & { newUser?: any }> = ({
|
|
|
22
23
|
newUser,
|
|
23
24
|
}) => {
|
|
24
25
|
const { user, oxyServices } = useOxy();
|
|
26
|
+
const { t } = useI18n();
|
|
25
27
|
const updateUser = useAuthStore(s => s.updateUser);
|
|
26
28
|
const currentUser = user || newUser; // fallback
|
|
27
29
|
const colors = useThemeColors(theme);
|
|
@@ -35,13 +37,25 @@ const WelcomeNewUserScreen: React.FC<BaseScreenProps & { newUser?: any }> = ({
|
|
|
35
37
|
const avatarUri = currentUser?.avatar ? oxyServices.getFileDownloadUrl(currentUser.avatar as string, 'thumb') : undefined;
|
|
36
38
|
|
|
37
39
|
// Steps content
|
|
40
|
+
const welcomeTitle = currentUser?.username
|
|
41
|
+
? (t('welcomeNew.welcome.titleWithName', { username: currentUser.username }) || `Welcome, ${currentUser.username} 👋`)
|
|
42
|
+
: (t('welcomeNew.welcome.title') || 'Welcome 👋');
|
|
38
43
|
const steps: Array<{ key: string; title: string; bullets?: string[]; body?: string; showAvatar?: boolean; }> = [
|
|
39
|
-
{ key: 'welcome', title:
|
|
40
|
-
{ key: 'account', title: 'One Account. Simple.', bullets: [
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
44
|
+
{ key: 'welcome', title: welcomeTitle, body: t('welcomeNew.welcome.body') || "You just created an account in a calm, ethical space. A few quick things — then you're in." },
|
|
45
|
+
{ key: 'account', title: t('welcomeNew.account.title') || 'One Account. Simple.', bullets: [
|
|
46
|
+
t('welcomeNew.account.bullets.0') || 'One identity across everything',
|
|
47
|
+
t('welcomeNew.account.bullets.1') || 'No re‑signing in all the time',
|
|
48
|
+
t('welcomeNew.account.bullets.2') || 'Your preferences stay with you',
|
|
49
|
+
] },
|
|
50
|
+
{ key: 'principles', title: t('welcomeNew.principles.title') || 'What We Stand For', bullets: [
|
|
51
|
+
t('welcomeNew.principles.bullets.0') || 'Privacy by default',
|
|
52
|
+
t('welcomeNew.principles.bullets.1') || 'No manipulative feeds',
|
|
53
|
+
t('welcomeNew.principles.bullets.2') || 'You decide what to share',
|
|
54
|
+
t('welcomeNew.principles.bullets.3') || 'No selling your data',
|
|
55
|
+
] },
|
|
56
|
+
{ key: 'karma', title: t('welcomeNew.karma.title') || 'Karma = Trust & Growth', body: t('welcomeNew.karma.body') || 'Oxy Karma is a points system that reacts to what you do. Helpful, respectful, constructive actions earn it. Harmful or low‑effort stuff chips it away. More karma can unlock benefits; low karma can limit features. It keeps things fair and rewards real contribution.' },
|
|
57
|
+
{ key: 'avatar', title: t('welcomeNew.avatar.title') || 'Make It Yours', body: t('welcomeNew.avatar.body') || 'Add an avatar so people recognize you. It will show anywhere you show up here. Skip if you want — you can add it later.', showAvatar: true },
|
|
58
|
+
{ key: 'ready', title: t('welcomeNew.ready.title') || "You're Ready", body: t('welcomeNew.ready.body') || 'Explore. Contribute. Earn karma. Stay in control.' }
|
|
45
59
|
];
|
|
46
60
|
const totalSteps = steps.length;
|
|
47
61
|
const avatarStepIndex = steps.findIndex(s => s.showAvatar);
|
|
@@ -68,8 +82,8 @@ const WelcomeNewUserScreen: React.FC<BaseScreenProps & { newUser?: any }> = ({
|
|
|
68
82
|
disabledMimeTypes: ['video/', 'audio/', 'application/pdf'],
|
|
69
83
|
afterSelect: 'back',
|
|
70
84
|
onSelect: async (file: any) => {
|
|
71
|
-
if (!file.contentType.startsWith('image/')) { toast.error('Please select an image file'); return; }
|
|
72
|
-
try { await updateUser({ avatar: file.id }, oxyServices); toast.success('Avatar updated'); } catch (e: any) { toast.error(e.message || 'Failed to update avatar'); }
|
|
85
|
+
if (!file.contentType.startsWith('image/')) { toast.error(t('editProfile.toasts.selectImage') || 'Please select an image file'); return; }
|
|
86
|
+
try { await updateUser({ avatar: file.id }, oxyServices); toast.success(t('editProfile.toasts.avatarUpdated') || 'Avatar updated'); } catch (e: any) { toast.error(e.message || t('editProfile.toasts.updateAvatarFailed') || 'Failed to update avatar'); }
|
|
73
87
|
}
|
|
74
88
|
});
|
|
75
89
|
}, [navigate, updateUser, oxyServices]);
|
|
@@ -78,25 +92,25 @@ const WelcomeNewUserScreen: React.FC<BaseScreenProps & { newUser?: any }> = ({
|
|
|
78
92
|
const pillButtons = useMemo(() => {
|
|
79
93
|
if (currentStep === totalSteps - 1) {
|
|
80
94
|
return [
|
|
81
|
-
{ text: 'Back', onPress: prevStep, icon: 'arrow-back', variant: 'transparent' },
|
|
82
|
-
{ text: 'Enter', onPress: finish, icon: 'log-in-outline', variant: 'primary' },
|
|
95
|
+
{ text: t('welcomeNew.actions.back') || 'Back', onPress: prevStep, icon: 'arrow-back', variant: 'transparent' },
|
|
96
|
+
{ text: t('welcomeNew.actions.enter') || 'Enter', onPress: finish, icon: 'log-in-outline', variant: 'primary' },
|
|
83
97
|
];
|
|
84
98
|
}
|
|
85
99
|
if (currentStep === 0) {
|
|
86
100
|
const arr: any[] = [];
|
|
87
|
-
if (avatarStepIndex > 0) arr.push({ text: 'Skip', onPress: skipToAvatar, icon: 'play-skip-forward', variant: 'transparent' });
|
|
88
|
-
arr.push({ text: 'Next', onPress: nextStep, icon: 'arrow-forward', variant: 'primary' });
|
|
101
|
+
if (avatarStepIndex > 0) arr.push({ text: t('welcomeNew.actions.skip') || 'Skip', onPress: skipToAvatar, icon: 'play-skip-forward', variant: 'transparent' });
|
|
102
|
+
arr.push({ text: t('welcomeNew.actions.next') || 'Next', onPress: nextStep, icon: 'arrow-forward', variant: 'primary' });
|
|
89
103
|
return arr;
|
|
90
104
|
}
|
|
91
105
|
if (step.showAvatar) {
|
|
92
106
|
return [
|
|
93
|
-
{ text: 'Back', onPress: prevStep, icon: 'arrow-back', variant: 'transparent' },
|
|
94
|
-
{ text: avatarUri ? 'Continue' : 'Skip', onPress: nextStep, icon: 'arrow-forward', variant: 'primary' },
|
|
107
|
+
{ text: t('welcomeNew.actions.back') || 'Back', onPress: prevStep, icon: 'arrow-back', variant: 'transparent' },
|
|
108
|
+
{ text: avatarUri ? (t('welcomeNew.actions.continue') || 'Continue') : (t('welcomeNew.actions.skip') || 'Skip'), onPress: nextStep, icon: 'arrow-forward', variant: 'primary' },
|
|
95
109
|
];
|
|
96
110
|
}
|
|
97
111
|
return [
|
|
98
|
-
{ text: 'Back', onPress: prevStep, icon: 'arrow-back', variant: 'transparent' },
|
|
99
|
-
{ text: 'Next', onPress: nextStep, icon: 'arrow-forward', variant: 'primary' },
|
|
112
|
+
{ text: t('welcomeNew.actions.back') || 'Back', onPress: prevStep, icon: 'arrow-back', variant: 'transparent' },
|
|
113
|
+
{ text: t('welcomeNew.actions.next') || 'Next', onPress: nextStep, icon: 'arrow-forward', variant: 'primary' },
|
|
100
114
|
];
|
|
101
115
|
}, [currentStep, totalSteps, prevStep, nextStep, finish, skipToAvatar, avatarStepIndex, step.showAvatar, avatarUri]);
|
|
102
116
|
|
|
@@ -126,7 +140,7 @@ const WelcomeNewUserScreen: React.FC<BaseScreenProps & { newUser?: any }> = ({
|
|
|
126
140
|
<Avatar size={120} name={currentUser?.username} uri={avatarUri} theme={theme} style={styles.avatar} />
|
|
127
141
|
<TouchableOpacity style={styles.changeAvatarButton} onPress={openAvatarPicker}>
|
|
128
142
|
<Ionicons name="image-outline" size={18} color="#FFFFFF" />
|
|
129
|
-
<Text style={styles.changeAvatarText}>{avatarUri ? 'Change Avatar' : 'Add Avatar'}</Text>
|
|
143
|
+
<Text style={styles.changeAvatarText}>{avatarUri ? (t('welcomeNew.avatar.change') || 'Change Avatar') : (t('welcomeNew.avatar.add') || 'Add Avatar')}</Text>
|
|
130
144
|
</TouchableOpacity>
|
|
131
145
|
</View>
|
|
132
146
|
)}
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import type React from 'react';
|
|
2
|
+
import type { RouteName } from '../../navigation/routes';
|
|
2
3
|
import { useRef, useCallback, useEffect } from 'react';
|
|
3
4
|
import { View, Text, TouchableOpacity, type TextInput, StatusBar } from 'react-native';
|
|
4
5
|
import Animated, {
|
|
@@ -7,6 +8,7 @@ import Animated, {
|
|
|
7
8
|
} from 'react-native-reanimated';
|
|
8
9
|
import { Ionicons } from '@expo/vector-icons';
|
|
9
10
|
import Avatar from '../../components/Avatar';
|
|
11
|
+
import { useI18n } from '../../hooks/useI18n';
|
|
10
12
|
import GroupedPillButtons from '../../components/internal/GroupedPillButtons';
|
|
11
13
|
import TextField from '../../components/internal/TextField';
|
|
12
14
|
|
|
@@ -30,7 +32,7 @@ interface SignInPasswordStepProps {
|
|
|
30
32
|
handleSignIn: () => void;
|
|
31
33
|
isLoading: boolean;
|
|
32
34
|
prevStep: () => void;
|
|
33
|
-
navigate: (screen:
|
|
35
|
+
navigate: (screen: RouteName, props?: Record<string, any>) => void;
|
|
34
36
|
}
|
|
35
37
|
|
|
36
38
|
const SignInPasswordStep: React.FC<SignInPasswordStepProps> = ({
|
|
@@ -56,6 +58,7 @@ const SignInPasswordStep: React.FC<SignInPasswordStepProps> = ({
|
|
|
56
58
|
navigate,
|
|
57
59
|
}) => {
|
|
58
60
|
const inputRef = useRef<TextInput>(null);
|
|
61
|
+
const { t } = useI18n();
|
|
59
62
|
|
|
60
63
|
// Animated styles - properly memoized to prevent re-renders
|
|
61
64
|
const containerAnimatedStyle = useAnimatedStyle(() => {
|
|
@@ -121,7 +124,7 @@ const SignInPasswordStep: React.FC<SignInPasswordStepProps> = ({
|
|
|
121
124
|
<View style={styles.modernInputContainer}>
|
|
122
125
|
<TextField
|
|
123
126
|
ref={inputRef}
|
|
124
|
-
label=
|
|
127
|
+
label={t('common.labels.password')}
|
|
125
128
|
leading={<Ionicons name="lock-closed-outline" size={24} color={colors.secondaryText} />}
|
|
126
129
|
value={password}
|
|
127
130
|
onChangeText={handlePasswordChange}
|
|
@@ -137,26 +140,26 @@ const SignInPasswordStep: React.FC<SignInPasswordStepProps> = ({
|
|
|
137
140
|
autoFocus
|
|
138
141
|
/>
|
|
139
142
|
<View style={{ flexDirection: 'row', alignItems: 'center', marginBottom: 16 }}>
|
|
140
|
-
<Text style={[styles.footerText, { color: colors.text }]}>Forgot your password? </Text>
|
|
143
|
+
<Text style={[styles.footerText, { color: colors.text }]}>{t('signin.forgotPrompt') || 'Forgot your password?'} </Text>
|
|
141
144
|
<TouchableOpacity onPress={() => navigate('RecoverAccount', {
|
|
142
145
|
returnTo: 'SignIn',
|
|
143
146
|
returnStep: 1,
|
|
144
147
|
returnData: { username, userProfile }
|
|
145
148
|
})}>
|
|
146
|
-
<Text style={[styles.modernLinkText, { color: colors.primary }]}>
|
|
149
|
+
<Text style={[styles.modernLinkText, { color: colors.primary }]}>{t('common.links.recoverAccount')}</Text>
|
|
147
150
|
</TouchableOpacity>
|
|
148
151
|
</View>
|
|
149
152
|
</View>
|
|
150
153
|
<GroupedPillButtons
|
|
151
154
|
buttons={[
|
|
152
155
|
{
|
|
153
|
-
text: '
|
|
156
|
+
text: t('common.actions.back'),
|
|
154
157
|
onPress: prevStep,
|
|
155
158
|
icon: 'arrow-back',
|
|
156
159
|
variant: 'transparent',
|
|
157
160
|
},
|
|
158
161
|
{
|
|
159
|
-
text: '
|
|
162
|
+
text: t('common.actions.signIn'),
|
|
160
163
|
onPress: handleSignIn,
|
|
161
164
|
icon: 'log-in',
|
|
162
165
|
variant: 'primary',
|
|
@@ -169,7 +172,7 @@ const SignInPasswordStep: React.FC<SignInPasswordStepProps> = ({
|
|
|
169
172
|
<View style={styles.securityNotice}>
|
|
170
173
|
<Ionicons name="shield-checkmark" size={14} color={colors.secondaryText} />
|
|
171
174
|
<Text style={[styles.securityText, { color: colors.secondaryText }]}>
|
|
172
|
-
Your data is encrypted and secure
|
|
175
|
+
{t('signin.security.dataSecure') || 'Your data is encrypted and secure'}
|
|
173
176
|
</Text>
|
|
174
177
|
</View>
|
|
175
178
|
<StatusBar
|
|
@@ -180,4 +183,4 @@ const SignInPasswordStep: React.FC<SignInPasswordStepProps> = ({
|
|
|
180
183
|
);
|
|
181
184
|
};
|
|
182
185
|
|
|
183
|
-
export default SignInPasswordStep;
|
|
186
|
+
export default SignInPasswordStep;
|
|
@@ -6,6 +6,7 @@ import Animated, {
|
|
|
6
6
|
SharedValue,
|
|
7
7
|
} from 'react-native-reanimated';
|
|
8
8
|
import { Ionicons } from '@expo/vector-icons';
|
|
9
|
+
import { useI18n } from '../../hooks/useI18n';
|
|
9
10
|
import HighFive from '../../../assets/illustrations/HighFive';
|
|
10
11
|
import GroupedPillButtons from '../../components/internal/GroupedPillButtons';
|
|
11
12
|
import TextField from '../../components/internal/TextField';
|
|
@@ -52,6 +53,7 @@ const SignInUsernameStep: React.FC<SignInUsernameStepProps> = ({
|
|
|
52
53
|
navigate,
|
|
53
54
|
}) => {
|
|
54
55
|
const inputRef = useRef<TextInput>(null);
|
|
56
|
+
const { t } = useI18n();
|
|
55
57
|
|
|
56
58
|
// Animated styles - properly memoized to prevent re-renders
|
|
57
59
|
const animatedStyle = useAnimatedStyle(() => {
|
|
@@ -80,12 +82,12 @@ const SignInUsernameStep: React.FC<SignInUsernameStepProps> = ({
|
|
|
80
82
|
<HighFive width={100} height={100} />
|
|
81
83
|
<View style={styles.modernHeader}>
|
|
82
84
|
<Text style={[styles.modernTitle, { color: colors.text }]}>
|
|
83
|
-
{isAddAccountMode ? 'Add Another Account' : 'Sign In'}
|
|
85
|
+
{isAddAccountMode ? (t('signin.addAccountTitle') || 'Add Another Account') : (t('signin.title') || 'Sign In')}
|
|
84
86
|
</Text>
|
|
85
87
|
<Text style={[styles.modernSubtitle, { color: colors.secondaryText }]}>
|
|
86
88
|
{isAddAccountMode
|
|
87
|
-
? 'Sign in with another account'
|
|
88
|
-
: 'Sign in to continue your journey'
|
|
89
|
+
? (t('signin.addAccountSubtitle') || 'Sign in with another account')
|
|
90
|
+
: (t('signin.subtitle') || 'Sign in to continue your journey')
|
|
89
91
|
}
|
|
90
92
|
</Text>
|
|
91
93
|
</View>
|
|
@@ -93,14 +95,14 @@ const SignInUsernameStep: React.FC<SignInUsernameStepProps> = ({
|
|
|
93
95
|
<View style={[styles.modernInfoCard, { backgroundColor: colors.inputBackground }]}>
|
|
94
96
|
<Ionicons name="information-circle" size={20} color={colors.primary} />
|
|
95
97
|
<Text style={[styles.modernInfoText, { color: colors.text }]}>
|
|
96
|
-
Currently signed in as <Text style={{ fontWeight: 'bold' }}>{user?.username}</Text>
|
|
98
|
+
{t('signin.currentlySignedInAs', { username: user?.username }) || 'Currently signed in as '}<Text style={{ fontWeight: 'bold' }}>{user?.username}</Text>
|
|
97
99
|
</Text>
|
|
98
100
|
</View>
|
|
99
101
|
)}
|
|
100
102
|
<View style={styles.modernInputContainer}>
|
|
101
103
|
<TextField
|
|
102
104
|
ref={inputRef}
|
|
103
|
-
label=
|
|
105
|
+
label={t('common.labels.username')}
|
|
104
106
|
leading={<Ionicons name="person-outline" size={24} color={colors.secondaryText} />}
|
|
105
107
|
value={username}
|
|
106
108
|
onChangeText={handleUsernameChange}
|
|
@@ -120,13 +122,13 @@ const SignInUsernameStep: React.FC<SignInUsernameStepProps> = ({
|
|
|
120
122
|
<GroupedPillButtons
|
|
121
123
|
buttons={[
|
|
122
124
|
{
|
|
123
|
-
text: 'Sign Up',
|
|
125
|
+
text: t('common.links.signUp') || 'Sign Up',
|
|
124
126
|
onPress: () => navigate('SignUp'),
|
|
125
127
|
icon: 'person-add',
|
|
126
128
|
variant: 'transparent',
|
|
127
129
|
},
|
|
128
130
|
{
|
|
129
|
-
text: '
|
|
131
|
+
text: t('common.actions.continue'),
|
|
130
132
|
onPress: handleUsernameContinue,
|
|
131
133
|
icon: 'arrow-forward',
|
|
132
134
|
variant: 'primary',
|
|
@@ -140,4 +142,4 @@ const SignInUsernameStep: React.FC<SignInUsernameStepProps> = ({
|
|
|
140
142
|
);
|
|
141
143
|
};
|
|
142
144
|
|
|
143
|
-
export default SignInUsernameStep;
|
|
145
|
+
export default SignInUsernameStep;
|
|
@@ -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 KarmaAboutScreen: 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';
|
|
@@ -12,22 +14,32 @@ const KarmaAboutScreen: React.FC<BaseScreenProps> = ({ goBack, theme }) => {
|
|
|
12
14
|
return (
|
|
13
15
|
<View style={[styles.container, { backgroundColor }]}>
|
|
14
16
|
<Header
|
|
15
|
-
title=
|
|
16
|
-
subtitle=
|
|
17
|
+
title={t('karma.about.title') || 'About Karma'}
|
|
18
|
+
subtitle={t('karma.about.subtitle') || 'Learn about the karma system'}
|
|
17
19
|
theme={theme}
|
|
18
20
|
onBack={goBack}
|
|
19
21
|
elevation="subtle"
|
|
20
22
|
/>
|
|
21
23
|
<ScrollView contentContainerStyle={styles.contentContainer}>
|
|
22
|
-
<Text style={[styles.paragraph, { color: textColor }]}>
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
24
|
+
<Text style={[styles.paragraph, { color: textColor }]}>
|
|
25
|
+
{t('karma.about.intro') || 'Karma is a recognition of your positive actions in the Oxy Ecosystem. It cannot be sent or received directly, only earned by contributing to the community.'}
|
|
26
|
+
</Text>
|
|
27
|
+
<Text style={[styles.section, { color: primaryColor }]}>
|
|
28
|
+
{t('karma.about.how.title') || 'How to Earn Karma'}
|
|
29
|
+
</Text>
|
|
30
|
+
<Text style={[styles.paragraph, { color: textColor }]}>
|
|
31
|
+
• {t('karma.about.how.help') || 'Helping other users'}{'\n'}
|
|
32
|
+
• {t('karma.about.how.report') || 'Reporting bugs'}{'\n'}
|
|
33
|
+
• {t('karma.about.how.contribute') || 'Contributing content'}{'\n'}
|
|
34
|
+
• {t('karma.about.how.participate') || 'Participating in events'}{'\n'}
|
|
35
|
+
• {t('karma.about.how.other') || 'Other positive actions'}
|
|
36
|
+
</Text>
|
|
37
|
+
<Text style={[styles.section, { color: primaryColor }]}>
|
|
38
|
+
{t('karma.about.why.title') || 'Why Karma?'}
|
|
39
|
+
</Text>
|
|
40
|
+
<Text style={[styles.paragraph, { color: textColor }]}>
|
|
41
|
+
{t('karma.about.why.text') || 'Karma unlocks special features and recognition in the Oxy Ecosystem. The more you contribute, the more you earn!'}
|
|
42
|
+
</Text>
|
|
31
43
|
</ScrollView>
|
|
32
44
|
</View>
|
|
33
45
|
);
|
|
@@ -15,6 +15,7 @@ import { useOxy } from '../../context/OxyContext';
|
|
|
15
15
|
import { fontFamilies } from '../../styles/fonts';
|
|
16
16
|
import Avatar from '../../components/Avatar';
|
|
17
17
|
import { Ionicons } from '@expo/vector-icons';
|
|
18
|
+
import { useI18n } from '../../hooks/useI18n';
|
|
18
19
|
|
|
19
20
|
const KarmaCenterScreen: React.FC<BaseScreenProps> = ({
|
|
20
21
|
theme,
|
|
@@ -22,6 +23,7 @@ const KarmaCenterScreen: React.FC<BaseScreenProps> = ({
|
|
|
22
23
|
goBack,
|
|
23
24
|
}) => {
|
|
24
25
|
const { user, oxyServices, isAuthenticated } = useOxy();
|
|
26
|
+
const { t } = useI18n();
|
|
25
27
|
const [karmaTotal, setKarmaTotal] = useState<number | null>(null);
|
|
26
28
|
const [karmaHistory, setKarmaHistory] = useState<any[]>([]);
|
|
27
29
|
const [isLoading, setIsLoading] = useState(true);
|
|
@@ -55,7 +57,7 @@ const KarmaCenterScreen: React.FC<BaseScreenProps> = ({
|
|
|
55
57
|
if (!isAuthenticated) {
|
|
56
58
|
return (
|
|
57
59
|
<View style={[styles.container, { backgroundColor }]}>
|
|
58
|
-
<Text style={[styles.message, { color: textColor }]}>Not signed in</Text>
|
|
60
|
+
<Text style={[styles.message, { color: textColor }]}>{t('common.status.notSignedIn') || 'Not signed in'}</Text>
|
|
59
61
|
</View>
|
|
60
62
|
);
|
|
61
63
|
}
|
|
@@ -79,46 +81,54 @@ const KarmaCenterScreen: React.FC<BaseScreenProps> = ({
|
|
|
79
81
|
theme={theme}
|
|
80
82
|
style={styles.avatar}
|
|
81
83
|
/>
|
|
82
|
-
<Text style={[styles.karmaLabel, { color: isDarkTheme ? '#BBBBBB' : '#888888' }]}>
|
|
84
|
+
<Text style={[styles.karmaLabel, { color: isDarkTheme ? '#BBBBBB' : '#888888' }]}>
|
|
85
|
+
{t('karma.center.balance') || 'Karma Balance'}
|
|
86
|
+
</Text>
|
|
83
87
|
<Text style={[styles.karmaAmount, { color: primaryColor }]}>{karmaTotal ?? 0}</Text>
|
|
84
88
|
<View style={styles.actionRow}>
|
|
85
89
|
<TouchableOpacity style={styles.actionIconWrapper} onPress={() => navigate && navigate('KarmaLeaderboard')}>
|
|
86
90
|
<View style={[styles.actionIcon, { backgroundColor: '#E0E0E0' }]}>
|
|
87
91
|
<Ionicons name="trophy-outline" size={28} color="#888" />
|
|
88
92
|
</View>
|
|
89
|
-
<Text style={styles.actionLabel}>Leaderboard</Text>
|
|
93
|
+
<Text style={styles.actionLabel}>{t('karma.center.actions.leaderboard') || 'Leaderboard'}</Text>
|
|
90
94
|
</TouchableOpacity>
|
|
91
95
|
<TouchableOpacity style={styles.actionIconWrapper} onPress={() => navigate && navigate('KarmaRules')}>
|
|
92
96
|
<View style={[styles.actionIcon, { backgroundColor: '#E0E0E0' }]}>
|
|
93
97
|
<Ionicons name="document-text-outline" size={28} color="#888" />
|
|
94
98
|
</View>
|
|
95
|
-
<Text style={styles.actionLabel}>Rules</Text>
|
|
99
|
+
<Text style={styles.actionLabel}>{t('karma.center.actions.rules') || 'Rules'}</Text>
|
|
96
100
|
</TouchableOpacity>
|
|
97
101
|
<TouchableOpacity style={styles.actionIconWrapper} onPress={() => navigate && navigate('AboutKarma')}>
|
|
98
102
|
<View style={[styles.actionIcon, { backgroundColor: '#E0E0E0' }]}>
|
|
99
103
|
<Ionicons name="star-outline" size={28} color="#888" />
|
|
100
104
|
</View>
|
|
101
|
-
<Text style={styles.actionLabel}>About</Text>
|
|
105
|
+
<Text style={styles.actionLabel}>{t('karma.center.actions.about') || 'About'}</Text>
|
|
102
106
|
</TouchableOpacity>
|
|
103
107
|
<TouchableOpacity style={styles.actionIconWrapper} onPress={() => navigate && navigate('KarmaRewards')}>
|
|
104
108
|
<View style={[styles.actionIcon, { backgroundColor: '#E0E0E0' }]}>
|
|
105
109
|
<Ionicons name="gift-outline" size={28} color="#888" />
|
|
106
110
|
</View>
|
|
107
|
-
<Text style={styles.actionLabel}>Rewards</Text>
|
|
111
|
+
<Text style={styles.actionLabel}>{t('karma.center.actions.rewards') || 'Rewards'}</Text>
|
|
108
112
|
</TouchableOpacity>
|
|
109
113
|
<TouchableOpacity style={styles.actionIconWrapper} onPress={() => navigate && navigate('KarmaFAQ')}>
|
|
110
114
|
<View style={[styles.actionIcon, { backgroundColor: '#E0E0E0' }]}>
|
|
111
115
|
<Ionicons name="help-circle-outline" size={28} color="#888" />
|
|
112
116
|
</View>
|
|
113
|
-
<Text style={styles.actionLabel}>FAQ</Text>
|
|
117
|
+
<Text style={styles.actionLabel}>{t('karma.center.actions.faq') || 'FAQ'}</Text>
|
|
114
118
|
</TouchableOpacity>
|
|
115
119
|
</View>
|
|
116
|
-
<Text style={styles.infoText}>
|
|
120
|
+
<Text style={styles.infoText}>
|
|
121
|
+
{t('karma.center.info') || 'Karma can only be earned by positive actions in the Oxy Ecosystem. It cannot be sent or received directly.'}
|
|
122
|
+
</Text>
|
|
117
123
|
</View>
|
|
118
|
-
<Text style={[styles.sectionTitle, { color: textColor }]}>
|
|
124
|
+
<Text style={[styles.sectionTitle, { color: textColor }]}>
|
|
125
|
+
{t('karma.center.history') || 'Karma History'}
|
|
126
|
+
</Text>
|
|
119
127
|
<View style={styles.historyContainer}>
|
|
120
128
|
{karmaHistory.length === 0 ? (
|
|
121
|
-
<Text style={{ color: textColor, textAlign: 'center', marginTop: 16 }}>
|
|
129
|
+
<Text style={{ color: textColor, textAlign: 'center', marginTop: 16 }}>
|
|
130
|
+
{t('karma.center.noHistory') || 'No karma history yet.'}
|
|
131
|
+
</Text>
|
|
122
132
|
) : (
|
|
123
133
|
karmaHistory.map((entry: any) => (
|
|
124
134
|
<View key={entry.id} style={[styles.historyItem, { borderColor }]}>
|
|
@@ -126,7 +136,7 @@ const KarmaCenterScreen: React.FC<BaseScreenProps> = ({
|
|
|
126
136
|
{entry.points > 0 ? '+' : ''}{entry.points}
|
|
127
137
|
</Text>
|
|
128
138
|
<Text style={[styles.historyDesc, { color: textColor }]}>
|
|
129
|
-
{entry.reason || 'No description'}
|
|
139
|
+
{entry.reason || (t('karma.center.noDescription') || 'No description')}
|
|
130
140
|
</Text>
|
|
131
141
|
<Text style={[styles.historyDate, { color: isDarkTheme ? '#BBBBBB' : '#888888' }]}>
|
|
132
142
|
{entry.createdAt ? new Date(entry.createdAt).toLocaleString() : ''}
|