Files
bakery-ia/frontend/src/pages/public/RegisterPage.tsx

376 lines
14 KiB
TypeScript
Raw Normal View History

2025-08-28 10:41:04 +02:00
import React, { useState } from 'react';
import { Link, useNavigate } from 'react-router-dom';
import { Button, Input, Card, Select } from '../../components/ui';
import { PublicLayout } from '../../components/layout';
const RegisterPage: React.FC = () => {
const [step, setStep] = useState(1);
const [loading, setLoading] = useState(false);
const [formData, setFormData] = useState({
// Personal info
firstName: '',
lastName: '',
email: '',
phone: '',
// Company info
companyName: '',
companyType: '',
employeeCount: '',
// Account info
password: '',
confirmPassword: '',
acceptTerms: false,
acceptMarketing: false,
});
const navigate = useNavigate();
const handleInputChange = (field: string, value: string | boolean) => {
setFormData(prev => ({ ...prev, [field]: value }));
};
const handleNextStep = () => {
setStep(prev => prev + 1);
};
const handlePrevStep = () => {
setStep(prev => prev - 1);
};
const handleSubmit = async (e: React.FormEvent) => {
e.preventDefault();
setLoading(true);
try {
// Simulate API call
await new Promise(resolve => setTimeout(resolve, 2000));
// Redirect to onboarding
navigate('/onboarding');
} catch (error) {
console.error('Registration failed:', error);
} finally {
setLoading(false);
}
};
const isStep1Valid = formData.firstName && formData.lastName && formData.email && formData.phone;
const isStep2Valid = formData.companyName && formData.companyType && formData.employeeCount;
const isStep3Valid = formData.password && formData.confirmPassword &&
formData.password === formData.confirmPassword && formData.acceptTerms;
return (
<PublicLayout
variant="centered"
maxWidth="md"
headerProps={{
showThemeToggle: true,
showAuthButtons: false,
variant: "minimal"
}}
>
<div className="w-full max-w-md mx-auto space-y-8">
<div>
<div className="flex justify-center">
<div className="w-12 h-12 bg-gradient-to-br from-[var(--color-primary)] to-[var(--color-primary-dark)] rounded-lg flex items-center justify-center text-white font-bold text-lg">
PI
</div>
</div>
<h2 className="mt-6 text-center text-3xl font-extrabold text-[var(--text-primary)]">
Crea tu cuenta
</h2>
<p className="mt-2 text-center text-sm text-[var(--text-secondary)]">
O{' '}
<Link
to="/login"
className="font-medium text-[var(--color-primary)] hover:text-[var(--color-primary-light)]"
>
inicia sesión si ya tienes una cuenta
</Link>
</p>
</div>
<Card className="p-8">
{/* Progress indicator */}
<div className="mb-8">
<div className="flex items-center">
{[1, 2, 3].map((stepNumber) => (
<div key={stepNumber} className="flex items-center">
<div
className={`flex items-center justify-center w-8 h-8 rounded-full ${
step >= stepNumber
? 'bg-[var(--color-primary)] text-white'
: 'bg-[var(--bg-quaternary)] text-[var(--text-tertiary)]'
}`}
>
{stepNumber}
</div>
{stepNumber < 3 && (
<div
className={`flex-1 h-0.5 mx-4 ${
step > stepNumber ? 'bg-[var(--color-primary)]' : 'bg-[var(--bg-quaternary)]'
}`}
/>
)}
</div>
))}
</div>
<div className="flex justify-between mt-2 text-xs text-[var(--text-secondary)]">
<span>Datos personales</span>
<span>Información empresarial</span>
<span>Crear cuenta</span>
</div>
</div>
<form onSubmit={handleSubmit} className="space-y-6">
{step === 1 && (
<>
<div className="space-y-4">
<div className="grid grid-cols-2 gap-4">
<div>
<label htmlFor="firstName" className="block text-sm font-medium text-[var(--text-primary)]">
Nombre *
</label>
<Input
id="firstName"
type="text"
required
value={formData.firstName}
onChange={(e) => handleInputChange('firstName', e.target.value)}
placeholder="Tu nombre"
/>
</div>
<div>
<label htmlFor="lastName" className="block text-sm font-medium text-[var(--text-primary)]">
Apellido *
</label>
<Input
id="lastName"
type="text"
required
value={formData.lastName}
onChange={(e) => handleInputChange('lastName', e.target.value)}
placeholder="Tu apellido"
/>
</div>
</div>
<div>
<label htmlFor="email" className="block text-sm font-medium text-[var(--text-primary)]">
Correo electrónico *
</label>
<Input
id="email"
type="email"
required
value={formData.email}
onChange={(e) => handleInputChange('email', e.target.value)}
placeholder="tu@email.com"
/>
</div>
<div>
<label htmlFor="phone" className="block text-sm font-medium text-[var(--text-primary)]">
Teléfono *
</label>
<Input
id="phone"
type="tel"
required
value={formData.phone}
onChange={(e) => handleInputChange('phone', e.target.value)}
placeholder="+34 600 000 000"
/>
</div>
</div>
<Button
type="button"
onClick={handleNextStep}
disabled={!isStep1Valid}
className="w-full"
>
Continuar
</Button>
</>
)}
{step === 2 && (
<>
<div className="space-y-4">
<div>
<label htmlFor="companyName" className="block text-sm font-medium text-[var(--text-primary)]">
Nombre de la panadería *
</label>
<Input
id="companyName"
type="text"
required
value={formData.companyName}
onChange={(e) => handleInputChange('companyName', e.target.value)}
placeholder="Panadería San Miguel"
/>
</div>
<div>
<label htmlFor="companyType" className="block text-sm font-medium text-[var(--text-primary)]">
Tipo de negocio *
</label>
<Select
value={formData.companyType}
onValueChange={(value) => handleInputChange('companyType', value)}
>
<option value="">Selecciona el tipo</option>
<option value="traditional">Panadería tradicional</option>
<option value="artisan">Panadería artesanal</option>
<option value="industrial">Panadería industrial</option>
<option value="bakery-cafe">Panadería-cafetería</option>
<option value="specialty">Panadería especializada</option>
</Select>
</div>
<div>
<label htmlFor="employeeCount" className="block text-sm font-medium text-[var(--text-primary)]">
Número de empleados *
</label>
<Select
value={formData.employeeCount}
onValueChange={(value) => handleInputChange('employeeCount', value)}
>
<option value="">Selecciona el rango</option>
<option value="1">Solo yo</option>
<option value="2-5">2-5 empleados</option>
<option value="6-15">6-15 empleados</option>
<option value="16-50">16-50 empleados</option>
<option value="51+">Más de 50 empleados</option>
</Select>
</div>
</div>
<div className="flex space-x-4">
<Button
type="button"
variant="outline"
onClick={handlePrevStep}
className="flex-1"
>
Atrás
</Button>
<Button
type="button"
onClick={handleNextStep}
disabled={!isStep2Valid}
className="flex-1"
>
Continuar
</Button>
</div>
</>
)}
{step === 3 && (
<>
<div className="space-y-4">
<div>
<label htmlFor="password" className="block text-sm font-medium text-[var(--text-primary)]">
Contraseña *
</label>
<Input
id="password"
type="password"
required
value={formData.password}
onChange={(e) => handleInputChange('password', e.target.value)}
placeholder="Mínimo 8 caracteres"
/>
</div>
<div>
<label htmlFor="confirmPassword" className="block text-sm font-medium text-[var(--text-primary)]">
Confirmar contraseña *
</label>
<Input
id="confirmPassword"
type="password"
required
value={formData.confirmPassword}
onChange={(e) => handleInputChange('confirmPassword', e.target.value)}
placeholder="Repite la contraseña"
/>
{formData.confirmPassword && formData.password !== formData.confirmPassword && (
<p className="mt-1 text-sm text-[var(--color-error)]">Las contraseñas no coinciden</p>
)}
</div>
</div>
<div className="space-y-4">
<div className="flex items-start">
<input
id="acceptTerms"
type="checkbox"
className="h-4 w-4 text-[var(--color-primary)] focus:ring-[var(--color-primary)] border-[var(--border-secondary)] rounded mt-0.5"
checked={formData.acceptTerms}
onChange={(e) => handleInputChange('acceptTerms', e.target.checked)}
/>
<label htmlFor="acceptTerms" className="ml-2 block text-sm text-[var(--text-primary)]">
Acepto los{' '}
<a href="#" className="text-[var(--color-primary)] hover:text-[var(--color-primary-light)]">
Términos de Servicio
</a>{' '}
y la{' '}
<a href="#" className="text-[var(--color-primary)] hover:text-[var(--color-primary-light)]">
Política de Privacidad
</a>
</label>
</div>
<div className="flex items-start">
<input
id="acceptMarketing"
type="checkbox"
className="h-4 w-4 text-[var(--color-primary)] focus:ring-[var(--color-primary)] border-[var(--border-secondary)] rounded mt-0.5"
checked={formData.acceptMarketing}
onChange={(e) => handleInputChange('acceptMarketing', e.target.checked)}
/>
<label htmlFor="acceptMarketing" className="ml-2 block text-sm text-[var(--text-primary)]">
Quiero recibir newsletters y novedades sobre el producto (opcional)
</label>
</div>
</div>
<div className="flex space-x-4">
<Button
type="button"
variant="outline"
onClick={handlePrevStep}
className="flex-1"
>
Atrás
</Button>
<Button
type="submit"
disabled={!isStep3Valid || loading}
className="flex-1"
>
{loading ? 'Creando cuenta...' : 'Crear cuenta'}
</Button>
</div>
</>
)}
</form>
<div className="mt-6 text-center text-xs text-[var(--text-secondary)]">
¿Necesitas ayuda?{' '}
<a href="#" className="text-[var(--color-primary)] hover:text-[var(--color-primary-light)]">
Contáctanos
</a>
</div>
</Card>
</div>
</PublicLayout>
);
};
export default RegisterPage;