@umituz/react-native-auth 3.6.44 → 3.6.45

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.
@@ -1,15 +1,19 @@
1
- /**
2
- * useLoginForm Hook
3
- * Single Responsibility: Handle login form logic
4
- */
5
-
6
1
  import { useState, useCallback } from "react";
7
- import { useLocalization } from "@umituz/react-native-localization";
8
2
  import { useAuth } from "./useAuth";
9
3
  import { getAuthErrorLocalizationKey } from "../utils/getAuthErrorMessage";
10
4
  import { validateEmail, validatePasswordForLogin } from "../../infrastructure/utils/AuthValidation";
11
5
  import { alertService } from "@umituz/react-native-design-system";
12
6
 
7
+ export interface LoginFormTranslations {
8
+ successTitle: string;
9
+ signInSuccess: string;
10
+ errors: Record<string, string>;
11
+ }
12
+
13
+ export interface UseLoginFormConfig {
14
+ translations: LoginFormTranslations;
15
+ }
16
+
13
17
  export interface UseLoginFormResult {
14
18
  email: string;
15
19
  password: string;
@@ -24,9 +28,9 @@ export interface UseLoginFormResult {
24
28
  displayError: string | null;
25
29
  }
26
30
 
27
- export function useLoginForm(): UseLoginFormResult {
28
- const { t } = useLocalization();
31
+ export function useLoginForm(config?: UseLoginFormConfig): UseLoginFormResult {
29
32
  const { signIn, loading, error, continueAnonymously } = useAuth();
33
+ const translations = config?.translations;
30
34
 
31
35
  const [email, setEmail] = useState("");
32
36
  const [password, setPassword] = useState("");
@@ -34,6 +38,10 @@ export function useLoginForm(): UseLoginFormResult {
34
38
  const [passwordError, setPasswordError] = useState<string | null>(null);
35
39
  const [localError, setLocalError] = useState<string | null>(null);
36
40
 
41
+ const getErrorMessage = useCallback((key: string) => {
42
+ return translations?.errors?.[key] || key;
43
+ }, [translations]);
44
+
37
45
  const handleEmailChange = useCallback(
38
46
  (text: string) => {
39
47
  setEmail(text);
@@ -61,13 +69,13 @@ export function useLoginForm(): UseLoginFormResult {
61
69
 
62
70
  const emailResult = validateEmail(email.trim());
63
71
  if (!emailResult.isValid && emailResult.error) {
64
- setEmailError(t(emailResult.error));
72
+ setEmailError(getErrorMessage(emailResult.error));
65
73
  hasError = true;
66
74
  }
67
75
 
68
76
  const passwordResult = validatePasswordForLogin(password);
69
77
  if (!passwordResult.isValid && passwordResult.error) {
70
- setPasswordError(t(passwordResult.error));
78
+ setPasswordError(getErrorMessage(passwordResult.error));
71
79
  hasError = true;
72
80
  }
73
81
 
@@ -75,23 +83,25 @@ export function useLoginForm(): UseLoginFormResult {
75
83
 
76
84
  try {
77
85
  await signIn(email.trim(), password);
78
-
79
- alertService.success(
80
- t("auth.successTitle"),
81
- t("auth.signInSuccess")
82
- );
86
+
87
+ if (translations) {
88
+ alertService.success(
89
+ translations.successTitle,
90
+ translations.signInSuccess
91
+ );
92
+ }
83
93
  } catch (err: unknown) {
84
94
  const localizationKey = getAuthErrorLocalizationKey(err);
85
- const errorMessage = t(localizationKey);
95
+ const errorMessage = getErrorMessage(localizationKey);
86
96
  setLocalError(errorMessage);
87
97
  }
88
- }, [email, password, t, signIn]);
98
+ }, [email, password, signIn, translations, getErrorMessage]);
89
99
 
90
100
  const handleContinueAnonymously = useCallback(async () => {
91
101
  try {
92
102
  await continueAnonymously();
93
103
  } catch {
94
- // Silent fail - anonymous mode should always work
104
+ // Silent fail
95
105
  }
96
106
  }, [continueAnonymously]);
97
107
 
@@ -1,10 +1,4 @@
1
- /**
2
- * useRegisterForm Hook
3
- * Single Responsibility: Handle register form logic
4
- */
5
-
6
1
  import { useState, useCallback, useMemo } from "react";
7
- import { useLocalization } from "@umituz/react-native-localization";
8
2
  import {
9
3
  validateEmail,
10
4
  validatePasswordForRegister,
@@ -16,6 +10,16 @@ import { getAuthErrorLocalizationKey } from "../utils/getAuthErrorMessage";
16
10
  import type { PasswordRequirements } from "../../infrastructure/utils/AuthValidation";
17
11
  import { alertService } from "@umituz/react-native-design-system";
18
12
 
13
+ export interface RegisterFormTranslations {
14
+ successTitle: string;
15
+ signUpSuccess: string;
16
+ errors: Record<string, string>;
17
+ }
18
+
19
+ export interface UseRegisterFormConfig {
20
+ translations: RegisterFormTranslations;
21
+ }
22
+
19
23
  export interface UseRegisterFormResult {
20
24
  displayName: string;
21
25
  email: string;
@@ -39,12 +43,9 @@ export interface UseRegisterFormResult {
39
43
  displayError: string | null;
40
44
  }
41
45
 
42
- /**
43
- * Hook for register form logic
44
- */
45
- export function useRegisterForm(): UseRegisterFormResult {
46
- const { t } = useLocalization();
46
+ export function useRegisterForm(config?: UseRegisterFormConfig): UseRegisterFormResult {
47
47
  const { signUp, loading, error } = useAuth();
48
+ const translations = config?.translations;
48
49
 
49
50
  const [displayName, setDisplayName] = useState("");
50
51
  const [email, setEmail] = useState("");
@@ -58,11 +59,13 @@ export function useRegisterForm(): UseRegisterFormResult {
58
59
  confirmPassword?: string;
59
60
  }>({});
60
61
 
62
+ const getErrorMessage = useCallback((key: string) => {
63
+ return translations?.errors?.[key] || key;
64
+ }, [translations]);
65
+
61
66
  const passwordRequirements = useMemo((): PasswordRequirements => {
62
67
  if (!password) {
63
- return {
64
- hasMinLength: false,
65
- };
68
+ return { hasMinLength: false };
66
69
  }
67
70
  const result = validatePasswordForRegister(password, DEFAULT_PASSWORD_CONFIG);
68
71
  return result.requirements;
@@ -76,9 +79,7 @@ export function useRegisterForm(): UseRegisterFormResult {
76
79
  setDisplayName(text);
77
80
  setFieldErrors((prev) => {
78
81
  const next = { ...prev };
79
- if (next.displayName) {
80
- delete next.displayName;
81
- }
82
+ if (next.displayName) delete next.displayName;
82
83
  return next;
83
84
  });
84
85
  setLocalError(null);
@@ -88,9 +89,7 @@ export function useRegisterForm(): UseRegisterFormResult {
88
89
  setEmail(text);
89
90
  setFieldErrors((prev) => {
90
91
  const next = { ...prev };
91
- if (next.email) {
92
- delete next.email;
93
- }
92
+ if (next.email) delete next.email;
94
93
  return next;
95
94
  });
96
95
  setLocalError(null);
@@ -100,12 +99,8 @@ export function useRegisterForm(): UseRegisterFormResult {
100
99
  setPassword(text);
101
100
  setFieldErrors((prev) => {
102
101
  const next = { ...prev };
103
- if (next.password) {
104
- delete next.password;
105
- }
106
- if (next.confirmPassword) {
107
- delete next.confirmPassword;
108
- }
102
+ if (next.password) delete next.password;
103
+ if (next.confirmPassword) delete next.confirmPassword;
109
104
  return next;
110
105
  });
111
106
  setLocalError(null);
@@ -115,9 +110,7 @@ export function useRegisterForm(): UseRegisterFormResult {
115
110
  setConfirmPassword(text);
116
111
  setFieldErrors((prev) => {
117
112
  const next = { ...prev };
118
- if (next.confirmPassword) {
119
- delete next.confirmPassword;
120
- }
113
+ if (next.confirmPassword) delete next.confirmPassword;
121
114
  return next;
122
115
  });
123
116
  setLocalError(null);
@@ -129,39 +122,34 @@ export function useRegisterForm(): UseRegisterFormResult {
129
122
 
130
123
  const emailResult = validateEmail(email.trim());
131
124
  if (!emailResult.isValid && emailResult.error) {
132
- setFieldErrors((prev) => ({ ...prev, email: t(emailResult.error as string) }));
125
+ setFieldErrors((prev) => ({ ...prev, email: getErrorMessage(emailResult.error as string) }));
133
126
  return;
134
127
  }
135
128
 
136
129
  const passwordResult = validatePasswordForRegister(password, DEFAULT_PASSWORD_CONFIG);
137
130
  if (!passwordResult.isValid && passwordResult.error) {
138
- setFieldErrors((prev) => ({ ...prev, password: t(passwordResult.error as string) }));
131
+ setFieldErrors((prev) => ({ ...prev, password: getErrorMessage(passwordResult.error as string) }));
139
132
  return;
140
133
  }
141
134
 
142
135
  const confirmResult = validatePasswordConfirmation(password, confirmPassword);
143
136
  if (!confirmResult.isValid && confirmResult.error) {
144
- setFieldErrors((prev) => ({ ...prev, confirmPassword: t(confirmResult.error as string) }));
137
+ setFieldErrors((prev) => ({ ...prev, confirmPassword: getErrorMessage(confirmResult.error as string) }));
145
138
  return;
146
139
  }
147
140
 
148
141
  try {
149
- await signUp(
150
- email.trim(),
151
- password,
152
- displayName.trim() || undefined,
153
- );
154
-
155
- alertService.success(
156
- t("auth.successTitle"),
157
- t("auth.signUpSuccess")
158
- );
142
+ await signUp(email.trim(), password, displayName.trim() || undefined);
143
+
144
+ if (translations) {
145
+ alertService.success(translations.successTitle, translations.signUpSuccess);
146
+ }
159
147
  } catch (err: unknown) {
160
148
  const localizationKey = getAuthErrorLocalizationKey(err);
161
- const errorMessage = t(localizationKey);
149
+ const errorMessage = getErrorMessage(localizationKey);
162
150
  setLocalError(errorMessage);
163
151
  }
164
- }, [displayName, email, password, confirmPassword, signUp, t]);
152
+ }, [displayName, email, password, confirmPassword, signUp, translations, getErrorMessage]);
165
153
 
166
154
  const displayError = localError || error;
167
155
 
@@ -183,5 +171,3 @@ export function useRegisterForm(): UseRegisterFormResult {
183
171
  displayError,
184
172
  };
185
173
  }
186
-
187
-
@@ -1,8 +1,3 @@
1
- /**
2
- * Auth Navigator
3
- * Stack navigator for authentication screens (Login, Register)
4
- */
5
-
6
1
  import React, { useEffect, useState } from "react";
7
2
  import {
8
3
  StackNavigator,
@@ -12,8 +7,8 @@ import {
12
7
  type StackNavigatorConfig,
13
8
  type StackScreenProps,
14
9
  } from "@umituz/react-native-design-system";
15
- import { LoginScreen } from "../screens/LoginScreen";
16
- import { RegisterScreen } from "../screens/RegisterScreen";
10
+ import { LoginScreen, type LoginScreenTranslations } from "../screens/LoginScreen";
11
+ import { RegisterScreen, type RegisterScreenTranslations } from "../screens/RegisterScreen";
17
12
 
18
13
  export type AuthStackParamList = {
19
14
  Login: undefined;
@@ -22,26 +17,21 @@ export type AuthStackParamList = {
22
17
 
23
18
  const SHOW_REGISTER_KEY = "auth_show_register";
24
19
 
20
+ export interface AuthNavigatorTranslations {
21
+ login: LoginScreenTranslations;
22
+ register: RegisterScreenTranslations;
23
+ }
24
+
25
25
  export interface AuthNavigatorProps {
26
- /**
27
- * Terms of Service URL
28
- */
26
+ translations: AuthNavigatorTranslations;
29
27
  termsUrl?: string;
30
- /**
31
- * Privacy Policy URL
32
- */
33
28
  privacyUrl?: string;
34
- /**
35
- * Callback when Terms of Service is pressed
36
- */
37
29
  onTermsPress?: () => void;
38
- /**
39
- * Callback when Privacy Policy is pressed
40
- */
41
30
  onPrivacyPress?: () => void;
42
31
  }
43
32
 
44
33
  export const AuthNavigator: React.FC<AuthNavigatorProps> = ({
34
+ translations,
45
35
  termsUrl,
46
36
  privacyUrl,
47
37
  onTermsPress,
@@ -71,11 +61,21 @@ export const AuthNavigator: React.FC<AuthNavigatorProps> = ({
71
61
  return null;
72
62
  }
73
63
 
64
+ const LoginScreenWrapper = (
65
+ props: StackScreenProps<AuthStackParamList, "Login">
66
+ ) => (
67
+ <LoginScreen
68
+ {...props}
69
+ translations={translations.login}
70
+ />
71
+ );
72
+
74
73
  const RegisterScreenWrapper = (
75
74
  props: StackScreenProps<AuthStackParamList, "Register">
76
75
  ) => (
77
76
  <RegisterScreen
78
77
  {...props}
78
+ translations={translations.register}
79
79
  termsUrl={termsUrl}
80
80
  privacyUrl={privacyUrl}
81
81
  onTermsPress={onTermsPress}
@@ -90,7 +90,7 @@ export const AuthNavigator: React.FC<AuthNavigatorProps> = ({
90
90
  cardStyle: { backgroundColor: tokens.colors.backgroundPrimary },
91
91
  },
92
92
  screens: [
93
- { name: "Login", component: LoginScreen },
93
+ { name: "Login", component: LoginScreenWrapper },
94
94
  { name: "Register", component: RegisterScreenWrapper },
95
95
  ],
96
96
  };
@@ -1,13 +1,3 @@
1
- /**
2
- * Change Password Screen
3
- * Screen for users to update their password
4
- *
5
- * Features:
6
- * - Current password validation via re-authentication
7
- * - New password validation (strength, match)
8
- * - Secure error handling
9
- */
10
-
11
1
  import React, { useState } from "react";
12
2
  import { View, StyleSheet, Alert } from "react-native";
13
3
  import {
@@ -18,23 +8,49 @@ import {
18
8
  AtomicText,
19
9
  useAppDesignTokens,
20
10
  } from "@umituz/react-native-design-system";
21
- import { useLocalization } from "@umituz/react-native-localization";
22
11
  import {
23
12
  updateUserPassword,
24
13
  reauthenticateWithPassword,
25
14
  getCurrentUserFromGlobal,
26
15
  } from "@umituz/react-native-firebase";
27
16
 
17
+ export interface ChangePasswordTranslations {
18
+ title: string;
19
+ description: string;
20
+ currentPassword: string;
21
+ enterCurrentPassword: string;
22
+ newPassword: string;
23
+ enterNewPassword: string;
24
+ confirmPassword: string;
25
+ enterConfirmPassword: string;
26
+ requirements: string;
27
+ minLength: string;
28
+ uppercase: string;
29
+ lowercase: string;
30
+ number: string;
31
+ specialChar: string;
32
+ passwordsMatch: string;
33
+ changePassword: string;
34
+ changing: string;
35
+ cancel: string;
36
+ success: string;
37
+ error: string;
38
+ fillAllFields: string;
39
+ unauthorized: string;
40
+ signInFailed: string;
41
+ }
42
+
28
43
  export interface ChangePasswordScreenProps {
44
+ translations: ChangePasswordTranslations;
29
45
  onSuccess?: () => void;
30
46
  onCancel?: () => void;
31
47
  }
32
48
 
33
49
  export const ChangePasswordScreen: React.FC<ChangePasswordScreenProps> = ({
50
+ translations,
34
51
  onSuccess,
35
52
  onCancel,
36
53
  }) => {
37
- const { t } = useLocalization();
38
54
  const tokens = useAppDesignTokens();
39
55
 
40
56
  const [currentPassword, setCurrentPassword] = useState("");
@@ -43,12 +59,6 @@ export const ChangePasswordScreen: React.FC<ChangePasswordScreenProps> = ({
43
59
  const [loading, setLoading] = useState(false);
44
60
  const [error, setError] = useState<string | null>(null);
45
61
 
46
- /* Removed manual visibility states */
47
- /* const [showCurrentPassword, setShowCurrentPassword] = useState(false); */
48
- /* const [showNewPassword, setShowNewPassword] = useState(false); */
49
- /* const [showConfirmPassword, setShowConfirmPassword] = useState(false); */
50
-
51
- // Validation state
52
62
  const isLengthValid = newPassword.length >= 8;
53
63
  const hasUppercase = /[A-Z]/.test(newPassword);
54
64
  const hasLowercase = /[a-z]/.test(newPassword);
@@ -67,13 +77,13 @@ export const ChangePasswordScreen: React.FC<ChangePasswordScreenProps> = ({
67
77
 
68
78
  const handleChangePassword = async () => {
69
79
  if (!isValid) {
70
- Alert.alert(t("common.error"), t("auth.passwordChange.fillAllFields"));
71
- return;
80
+ Alert.alert("Error", translations.fillAllFields);
81
+ return;
72
82
  }
73
83
 
74
84
  const user = getCurrentUserFromGlobal();
75
85
  if (!user) {
76
- setError(t("auth.errors.unauthorized"));
86
+ setError(translations.unauthorized);
77
87
  return;
78
88
  }
79
89
 
@@ -81,45 +91,29 @@ export const ChangePasswordScreen: React.FC<ChangePasswordScreenProps> = ({
81
91
  setError(null);
82
92
 
83
93
  try {
84
- // 1. Re-authenticate
85
94
  const reauthResult = await reauthenticateWithPassword(user, currentPassword);
86
95
  if (!reauthResult.success) {
87
- setError(reauthResult.error?.message || t("auth.alerts.error.signInFailed"));
96
+ setError(reauthResult.error?.message || translations.signInFailed);
88
97
  setLoading(false);
89
98
  return;
90
99
  }
91
100
 
92
- // 2. Update Password
93
101
  const updateResult = await updateUserPassword(user, newPassword);
94
102
  if (updateResult.success) {
95
- Alert.alert(t("common.success"), t("auth.passwordChange.success"), [
96
- { text: "OK", onPress: onSuccess }
103
+ Alert.alert("Success", translations.success, [
104
+ { text: "OK", onPress: onSuccess }
97
105
  ]);
98
106
  } else {
99
- setError(updateResult.error?.message || t("auth.passwordChange.error"));
107
+ setError(updateResult.error?.message || translations.error);
100
108
  }
101
109
  } catch (e: unknown) {
102
- const errorMessage = e instanceof Error ? e.message : t("auth.passwordChange.error");
110
+ const errorMessage = e instanceof Error ? e.message : translations.error;
103
111
  setError(errorMessage);
104
112
  } finally {
105
113
  setLoading(false);
106
114
  }
107
115
  };
108
116
 
109
- const RequirementsList = () => (
110
- <View style={[styles.requirementsContainer, { backgroundColor: tokens.colors.surfaceSecondary }]}>
111
- <AtomicText type="labelMedium" style={{ color: tokens.colors.textSecondary, marginBottom: 8 }}>
112
- {t("auth.passwordChange.requirements")}
113
- </AtomicText>
114
- <RequirementItem label={t("auth.passwordChange.minLength")} met={isLengthValid} />
115
- <RequirementItem label={t("auth.passwordChange.uppercase")} met={hasUppercase} />
116
- <RequirementItem label={t("auth.passwordChange.lowercase")} met={hasLowercase} />
117
- <RequirementItem label={t("auth.passwordChange.number")} met={hasNumber} />
118
- <RequirementItem label={t("auth.passwordChange.specialChar")} met={hasSpecialChar} />
119
- <RequirementItem label={t("auth.passwordChange.passwordsMatch")} met={passwordsMatch} />
120
- </View>
121
- );
122
-
123
117
  const RequirementItem = ({ label, met }: { label: string; met: boolean }) => (
124
118
  <View style={styles.requirementItem}>
125
119
  <View
@@ -140,20 +134,19 @@ export const ChangePasswordScreen: React.FC<ChangePasswordScreenProps> = ({
140
134
  return (
141
135
  <ScreenLayout
142
136
  scrollable
143
- header={<ScreenHeader title={t("auth.passwordChange.title")} />}
137
+ header={<ScreenHeader title={translations.title} />}
144
138
  backgroundColor={tokens.colors.backgroundPrimary}
145
139
  edges={["bottom"]}
146
140
  >
147
141
  <View style={styles.content}>
148
142
  <AtomicText type="bodyMedium" style={{ color: tokens.colors.textSecondary, marginBottom: 24 }}>
149
- {t("auth.passwordChange.description")}
143
+ {translations.description}
150
144
  </AtomicText>
151
145
 
152
146
  <View style={styles.form}>
153
- {/* Current Password */}
154
147
  <AtomicInput
155
- label={t("auth.passwordChange.currentPassword")}
156
- placeholder={t("auth.passwordChange.enterCurrentPassword")}
148
+ label={translations.currentPassword}
149
+ placeholder={translations.enterCurrentPassword}
157
150
  value={currentPassword}
158
151
  onChangeText={setCurrentPassword}
159
152
  secureTextEntry
@@ -161,10 +154,9 @@ export const ChangePasswordScreen: React.FC<ChangePasswordScreenProps> = ({
161
154
  variant="filled"
162
155
  />
163
156
 
164
- {/* New Password */}
165
157
  <AtomicInput
166
- label={t("auth.passwordChange.newPassword")}
167
- placeholder={t("auth.passwordChange.enterNewPassword")}
158
+ label={translations.newPassword}
159
+ placeholder={translations.enterNewPassword}
168
160
  value={newPassword}
169
161
  onChangeText={setNewPassword}
170
162
  secureTextEntry
@@ -172,10 +164,9 @@ export const ChangePasswordScreen: React.FC<ChangePasswordScreenProps> = ({
172
164
  variant="filled"
173
165
  />
174
166
 
175
- {/* Confirm Password */}
176
167
  <AtomicInput
177
- label={t("auth.passwordChange.confirmPassword")}
178
- placeholder={t("auth.passwordChange.enterConfirmPassword")}
168
+ label={translations.confirmPassword}
169
+ placeholder={translations.enterConfirmPassword}
179
170
  value={confirmPassword}
180
171
  onChangeText={setConfirmPassword}
181
172
  secureTextEntry
@@ -183,7 +174,17 @@ export const ChangePasswordScreen: React.FC<ChangePasswordScreenProps> = ({
183
174
  variant="filled"
184
175
  />
185
176
 
186
- <RequirementsList />
177
+ <View style={[styles.requirementsContainer, { backgroundColor: tokens.colors.surfaceSecondary }]}>
178
+ <AtomicText type="labelMedium" style={{ color: tokens.colors.textSecondary, marginBottom: 8 }}>
179
+ {translations.requirements}
180
+ </AtomicText>
181
+ <RequirementItem label={translations.minLength} met={isLengthValid} />
182
+ <RequirementItem label={translations.uppercase} met={hasUppercase} />
183
+ <RequirementItem label={translations.lowercase} met={hasLowercase} />
184
+ <RequirementItem label={translations.number} met={hasNumber} />
185
+ <RequirementItem label={translations.specialChar} met={hasSpecialChar} />
186
+ <RequirementItem label={translations.passwordsMatch} met={passwordsMatch} />
187
+ </View>
187
188
 
188
189
  {error && (
189
190
  <AtomicText style={{ color: tokens.colors.error, marginTop: 16 }}>
@@ -192,14 +193,14 @@ export const ChangePasswordScreen: React.FC<ChangePasswordScreenProps> = ({
192
193
  )}
193
194
 
194
195
  <View style={styles.actions}>
195
- <AtomicButton
196
- title={t("common.cancel")}
196
+ <AtomicButton
197
+ title={translations.cancel}
197
198
  onPress={onCancel || (() => {})}
198
199
  variant="outline"
199
200
  style={{ flex: 1 }}
200
201
  />
201
202
  <AtomicButton
202
- title={loading ? t("auth.passwordChange.changing") : t("auth.passwordChange.changePassword")}
203
+ title={loading ? translations.changing : translations.changePassword}
203
204
  onPress={() => { void handleChangePassword(); }}
204
205
  loading={loading}
205
206
  disabled={!isValid || loading}
@@ -1,16 +1,19 @@
1
- /**
2
- * Login Screen
3
- * Beautiful, production-ready login screen with email/password and guest mode
4
- */
5
-
6
1
  import React from "react";
7
2
  import { useAppNavigation, AtomicCard, ScreenLayout, useAppDesignTokens } from "@umituz/react-native-design-system";
8
- import { useLocalization } from "@umituz/react-native-localization";
9
3
  import { AuthHeader } from "../components/AuthHeader";
10
- import { LoginForm } from "../components/LoginForm";
4
+ import { LoginForm, type LoginFormTranslations } from "../components/LoginForm";
5
+
6
+ export interface LoginScreenTranslations {
7
+ title: string;
8
+ subtitle?: string;
9
+ form: LoginFormTranslations;
10
+ }
11
11
 
12
- export const LoginScreen: React.FC = () => {
13
- const { t } = useLocalization();
12
+ export interface LoginScreenProps {
13
+ translations: LoginScreenTranslations;
14
+ }
15
+
16
+ export const LoginScreen: React.FC<LoginScreenProps> = ({ translations }) => {
14
17
  const navigation = useAppNavigation();
15
18
  const tokens = useAppDesignTokens();
16
19
 
@@ -26,11 +29,13 @@ export const LoginScreen: React.FC = () => {
26
29
  contentContainerStyle={{ justifyContent: "center" }}
27
30
  backgroundColor={tokens.colors.backgroundPrimary}
28
31
  >
29
- <AuthHeader title={t("auth.title")} />
32
+ <AuthHeader title={translations.title} subtitle={translations.subtitle} />
30
33
  <AtomicCard variant="elevated" padding="lg">
31
- <LoginForm onNavigateToRegister={handleNavigateToRegister} />
34
+ <LoginForm
35
+ translations={translations.form}
36
+ onNavigateToRegister={handleNavigateToRegister}
37
+ />
32
38
  </AtomicCard>
33
39
  </ScreenLayout>
34
40
  );
35
41
  };
36
-
@@ -1,15 +1,16 @@
1
- /**
2
- * Register Screen
3
- * Beautiful, production-ready registration screen with validation
4
- */
5
-
6
1
  import React from "react";
7
2
  import { useAppNavigation, AtomicCard, ScreenLayout, useAppDesignTokens } from "@umituz/react-native-design-system";
8
- import { useLocalization } from "@umituz/react-native-localization";
9
3
  import { AuthHeader } from "../components/AuthHeader";
10
- import { RegisterForm } from "../components/RegisterForm";
4
+ import { RegisterForm, type RegisterFormTranslations } from "../components/RegisterForm";
5
+
6
+ export interface RegisterScreenTranslations {
7
+ title: string;
8
+ subtitle?: string;
9
+ form: RegisterFormTranslations;
10
+ }
11
11
 
12
12
  export interface RegisterScreenProps {
13
+ translations: RegisterScreenTranslations;
13
14
  termsUrl?: string;
14
15
  privacyUrl?: string;
15
16
  onTermsPress?: () => void;
@@ -17,12 +18,12 @@ export interface RegisterScreenProps {
17
18
  }
18
19
 
19
20
  export const RegisterScreen: React.FC<RegisterScreenProps> = ({
21
+ translations,
20
22
  termsUrl,
21
23
  privacyUrl,
22
24
  onTermsPress,
23
25
  onPrivacyPress,
24
26
  }) => {
25
- const { t } = useLocalization();
26
27
  const navigation = useAppNavigation();
27
28
  const tokens = useAppDesignTokens();
28
29
 
@@ -32,15 +33,16 @@ export const RegisterScreen: React.FC<RegisterScreenProps> = ({
32
33
 
33
34
  return (
34
35
  <ScreenLayout
35
- scrollable
36
- keyboardAvoiding
37
- maxWidth={440}
38
- contentContainerStyle={{ justifyContent: "center" }}
39
- backgroundColor={tokens.colors.backgroundPrimary}
36
+ scrollable
37
+ keyboardAvoiding
38
+ maxWidth={440}
39
+ contentContainerStyle={{ justifyContent: "center" }}
40
+ backgroundColor={tokens.colors.backgroundPrimary}
40
41
  >
41
- <AuthHeader title={t("auth.createAccount")} />
42
+ <AuthHeader title={translations.title} subtitle={translations.subtitle} />
42
43
  <AtomicCard variant="elevated" padding="lg">
43
44
  <RegisterForm
45
+ translations={translations.form}
44
46
  onNavigateToLogin={handleNavigateToLogin}
45
47
  termsUrl={termsUrl}
46
48
  privacyUrl={privacyUrl}
@@ -51,4 +53,3 @@ export const RegisterScreen: React.FC<RegisterScreenProps> = ({
51
53
  </ScreenLayout>
52
54
  );
53
55
  };
54
-