Support multiple languages
This commit is contained in:
@@ -1,4 +1,5 @@
|
||||
import React, { useState, useRef, useEffect } from 'react';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
import { Button, Input, Card } from '../../ui';
|
||||
import { useAuthActions, useAuthLoading, useAuthError } from '../../../stores/auth.store';
|
||||
import { useToast } from '../../../hooks/ui/useToast';
|
||||
@@ -24,6 +25,7 @@ export const LoginForm: React.FC<LoginFormProps> = ({
|
||||
className,
|
||||
autoFocus = true
|
||||
}) => {
|
||||
const { t } = useTranslation();
|
||||
const [credentials, setCredentials] = useState<LoginCredentials>({
|
||||
email: '',
|
||||
password: '',
|
||||
@@ -32,7 +34,7 @@ export const LoginForm: React.FC<LoginFormProps> = ({
|
||||
const [errors, setErrors] = useState<Partial<LoginCredentials>>({});
|
||||
const [showPassword, setShowPassword] = useState(false);
|
||||
const emailInputRef = useRef<HTMLInputElement>(null);
|
||||
|
||||
|
||||
const { login } = useAuthActions();
|
||||
const isLoading = useAuthLoading();
|
||||
const error = useAuthError();
|
||||
@@ -49,13 +51,13 @@ export const LoginForm: React.FC<LoginFormProps> = ({
|
||||
const newErrors: Partial<LoginCredentials> = {};
|
||||
|
||||
if (!credentials.email.trim()) {
|
||||
newErrors.email = 'El email es requerido';
|
||||
newErrors.email = t('auth:validation.email_required', 'El email es requerido');
|
||||
} else if (!/^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}$/.test(credentials.email)) {
|
||||
newErrors.email = 'Por favor, ingrese un email válido';
|
||||
newErrors.email = t('auth:validation.email_invalid', 'Por favor, ingrese un email válido');
|
||||
}
|
||||
|
||||
if (!credentials.password) {
|
||||
newErrors.password = 'La contraseña es requerida';
|
||||
newErrors.password = t('auth:validation.password_required', 'La contraseña es requerida');
|
||||
}
|
||||
|
||||
setErrors(newErrors);
|
||||
@@ -114,10 +116,10 @@ export const LoginForm: React.FC<LoginFormProps> = ({
|
||||
<Card className={`p-8 w-full max-w-md ${className || ''}`} role="main">
|
||||
<div className="text-center mb-8">
|
||||
<h1 className="text-2xl font-bold text-text-primary mb-2">
|
||||
Iniciar Sesión
|
||||
{t('auth:login.title', 'Iniciar Sesión')}
|
||||
</h1>
|
||||
<p className="text-text-secondary">
|
||||
Accede al panel de control de tu panadería
|
||||
{t('auth:login.subtitle', 'Accede al panel de control de tu panadería')}
|
||||
</p>
|
||||
</div>
|
||||
|
||||
@@ -125,14 +127,14 @@ export const LoginForm: React.FC<LoginFormProps> = ({
|
||||
onSubmit={handleSubmit}
|
||||
className="space-y-6"
|
||||
noValidate
|
||||
aria-label="Formulario de inicio de sesión"
|
||||
aria-label={t('auth:login.title', 'Formulario de inicio de sesión')}
|
||||
onKeyDown={handleKeyDown}
|
||||
>
|
||||
<div>
|
||||
<Input
|
||||
ref={emailInputRef}
|
||||
type="email"
|
||||
label="Correo Electrónico"
|
||||
label={t('auth:login.email', 'Correo Electrónico')}
|
||||
placeholder="tu.email@panaderia.com"
|
||||
value={credentials.email}
|
||||
onChange={handleInputChange('email')}
|
||||
@@ -163,8 +165,8 @@ export const LoginForm: React.FC<LoginFormProps> = ({
|
||||
<div>
|
||||
<Input
|
||||
type={showPassword ? 'text' : 'password'}
|
||||
label="Contraseña"
|
||||
placeholder="Tu contraseña segura"
|
||||
label={t('auth:login.password', 'Contraseña')}
|
||||
placeholder={t('auth:login.password', 'Tu contraseña segura')}
|
||||
value={credentials.password}
|
||||
onChange={handleInputChange('password')}
|
||||
error={errors.password}
|
||||
|
||||
@@ -3,7 +3,6 @@ import { Button, Input, Card, Select, Avatar, Modal } from '../../ui';
|
||||
import { useAuthUser } from '../../../stores/auth.store';
|
||||
import { useToast } from '../../../hooks/ui/useToast';
|
||||
import { useUpdateProfile, useChangePassword, useAuthProfile } from '../../../api/hooks/auth';
|
||||
import { useEffect } from 'react';
|
||||
|
||||
interface ProfileSettingsProps {
|
||||
onSuccess?: () => void;
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
import React, { useState } from 'react';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
import { Button, Input, Card } from '../../ui';
|
||||
import { PasswordCriteria, validatePassword, getPasswordErrors } from '../../ui/PasswordCriteria';
|
||||
import { useAuthActions, useAuthLoading, useAuthError } from '../../../stores/auth.store';
|
||||
@@ -23,6 +24,7 @@ export const RegisterForm: React.FC<RegisterFormProps> = ({
|
||||
onLoginClick,
|
||||
className
|
||||
}) => {
|
||||
const { t } = useTranslation();
|
||||
const [formData, setFormData] = useState<SimpleUserRegistration>({
|
||||
full_name: '',
|
||||
email: '',
|
||||
@@ -53,19 +55,19 @@ export const RegisterForm: React.FC<RegisterFormProps> = ({
|
||||
const newErrors: Partial<SimpleUserRegistration> = {};
|
||||
|
||||
if (!formData.full_name.trim()) {
|
||||
newErrors.full_name = 'El nombre completo es requerido';
|
||||
newErrors.full_name = t('auth:validation.first_name_required', 'El nombre completo es requerido');
|
||||
} else if (formData.full_name.trim().length < 2) {
|
||||
newErrors.full_name = 'El nombre debe tener al menos 2 caracteres';
|
||||
newErrors.full_name = t('auth:validation.field_required', 'El nombre debe tener al menos 2 caracteres');
|
||||
}
|
||||
|
||||
if (!formData.email.trim()) {
|
||||
newErrors.email = 'El email es requerido';
|
||||
newErrors.email = t('auth:validation.email_required', 'El email es requerido');
|
||||
} else if (!/^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}$/.test(formData.email)) {
|
||||
newErrors.email = 'Por favor, ingrese un email válido';
|
||||
newErrors.email = t('auth:validation.email_invalid', 'Por favor, ingrese un email válido');
|
||||
}
|
||||
|
||||
if (!formData.password) {
|
||||
newErrors.password = 'La contraseña es requerida';
|
||||
newErrors.password = t('auth:validation.password_required', 'La contraseña es requerida');
|
||||
} else {
|
||||
const passwordErrors = getPasswordErrors(formData.password);
|
||||
if (passwordErrors.length > 0) {
|
||||
@@ -74,13 +76,13 @@ export const RegisterForm: React.FC<RegisterFormProps> = ({
|
||||
}
|
||||
|
||||
if (!formData.confirmPassword) {
|
||||
newErrors.confirmPassword = 'Confirma tu contraseña';
|
||||
newErrors.confirmPassword = t('auth:register.confirm_password', 'Confirma tu contraseña');
|
||||
} else if (formData.password !== formData.confirmPassword) {
|
||||
newErrors.confirmPassword = 'Las contraseñas no coinciden';
|
||||
newErrors.confirmPassword = t('auth:validation.passwords_must_match', 'Las contraseñas no coinciden');
|
||||
}
|
||||
|
||||
if (!formData.acceptTerms) {
|
||||
newErrors.acceptTerms = 'Debes aceptar los términos y condiciones';
|
||||
newErrors.acceptTerms = t('auth:validation.terms_required', 'Debes aceptar los términos y condiciones');
|
||||
}
|
||||
|
||||
setErrors(newErrors);
|
||||
@@ -104,13 +106,13 @@ export const RegisterForm: React.FC<RegisterFormProps> = ({
|
||||
|
||||
await register(registrationData);
|
||||
|
||||
showSuccessToast('¡Bienvenido! Tu cuenta ha sido creada correctamente.', {
|
||||
title: 'Cuenta creada exitosamente'
|
||||
showSuccessToast(t('auth:register.registering', '¡Bienvenido! Tu cuenta ha sido creada correctamente.'), {
|
||||
title: t('auth:alerts.success_create', 'Cuenta creada exitosamente')
|
||||
});
|
||||
onSuccess?.();
|
||||
} catch (err) {
|
||||
showErrorToast(error || 'No se pudo crear la cuenta. Verifica que el email no esté en uso.', {
|
||||
title: 'Error al crear la cuenta'
|
||||
showErrorToast(error || t('auth:register.register_button', 'No se pudo crear la cuenta. Verifica que el email no esté en uso.'), {
|
||||
title: t('auth:alerts.error_create', 'Error al crear la cuenta')
|
||||
});
|
||||
}
|
||||
};
|
||||
@@ -127,16 +129,16 @@ export const RegisterForm: React.FC<RegisterFormProps> = ({
|
||||
<Card className={`p-8 w-full max-w-md ${className || ''}`} role="main">
|
||||
<div className="text-center mb-8">
|
||||
<h1 className="text-3xl font-bold text-text-primary mb-2">
|
||||
Crear Cuenta
|
||||
{t('auth:register.title', 'Crear Cuenta')}
|
||||
</h1>
|
||||
<p className="text-text-secondary text-lg">
|
||||
Únete y comienza hoy mismo
|
||||
{t('auth:register.subtitle', 'Únete y comienza hoy mismo')}
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<form onSubmit={handleSubmit} className="space-y-6">
|
||||
<Input
|
||||
label="Nombre Completo"
|
||||
label={t('auth:register.first_name', 'Nombre Completo')}
|
||||
placeholder="Juan Pérez García"
|
||||
value={formData.full_name}
|
||||
onChange={handleInputChange('full_name')}
|
||||
@@ -153,7 +155,7 @@ export const RegisterForm: React.FC<RegisterFormProps> = ({
|
||||
|
||||
<Input
|
||||
type="email"
|
||||
label="Correo Electrónico"
|
||||
label={t('auth:register.email', 'Correo Electrónico')}
|
||||
placeholder="tu.email@ejemplo.com"
|
||||
value={formData.email}
|
||||
onChange={handleInputChange('email')}
|
||||
|
||||
Reference in New Issue
Block a user