Módulo: Registro de Cuenta
Scope
| Tipo de organización | Acceso |
|---|---|
| Empresa | ✅ |
| Agencia | ✅ |
| Reclutador independiente | ✅ |
| Usuario sin organización | ✅ |
Permisos por rol
| Acción | Disponible | Permiso |
|---|---|---|
| Crear cuenta nueva | ✅ | Público (no requiere autenticación) |
| Reenviar correo de verificación | ✅ | Público |
| Ver términos y condiciones | ✅ | Público |
| Ver política de privacidad | ✅ | Público |
¿Qué es?
Flujo de registro de nuevos usuarios en Contratta. Permite crear una cuenta con nombre, email y contraseña. Tras el registro, se envía un correo de verificación que el usuario debe confirmar antes de iniciar sesión.
¿Qué puede hacer el usuario?
- Crear cuenta con nombre completo, email y contraseña
- Ver y aceptar términos y condiciones
- Ver política de privacidad
- Recibir correo de verificación automático post-registro
- Reenviar correo de verificación (con cooldown de 60s)
- Navegar al login si ya tiene cuenta
Flujo del usuario
1. Presiona "Regístrate ahora" desde la pantalla de login
2. Llena formulario:
- Nombre completo
- Email
- Contraseña (mínimo 8 caracteres)
- Confirmar contraseña
3. Lee y acepta términos y condiciones (obligatorio)
4. Presiona "Crear cuenta"
5. API registra usuario → envía correo de verificación
6. Navega a pantalla de éxito:
- Ícono de correo enviado
- Mensaje de éxito
- Chip con el email registrado
- Botón reenviar (cooldown 60s)
7. Presiona "Ir a iniciar sesión" → vuelve a login
8. Verifica email vía link del correo (fuera de Flutter)
9. Puede iniciar sesión normalmente
Reglas de negocio
- Nombre es obligatorio (no vacío)
- Email debe ser válido (validación regex)
- Contraseña mínima: 8 caracteres
- Confirmación de contraseña debe coincidir exactamente
- Aceptar términos y condiciones es obligatorio para enviar el formulario
- El botón de "Crear cuenta" se deshabilita si no se aceptan los términos
- Cooldown de 60 segundos entre reenvíos de correo de verificación
- El backend permite registro con email duplicado (devuelve error específico)
- Post-registro no se inicia sesión automáticamente — el usuario debe verificar email primero
Requisitos para registro
| Campo | Tipo | Requerido | Validación |
|---|---|---|---|
| name | String | ✅ | No vacío |
| String | ✅ | Regex email válido | |
| password | String | ✅ | Mínimo 8 caracteres |
| confirmPassword | String | ✅ | Debe coincidir con password (local) |
| acceptTerms | bool | ✅ | Debe ser true |
Requisitos para reenvío de verificación
| Campo | Tipo | Requerido | Notas |
|---|---|---|---|
| String | ✅ | El email con el que se registró |
Arquitectura
lib/features/auth/
├── application/
│ ├── register_cubit.dart # Lógica de registro
│ ├── register_state.dart # RegisterStatus enum
│ ├── verification_cubit.dart # Lógica de reenvío de verificación
│ └── verification_state.dart # VerificationStatus enum
├── domain/
│ └── usecases/
│ ├── register_usecase.dart
│ └── send_verification_email_usecase.dart
└── presentation/
└── pages/
├── register_page.dart # Formulario de registro
├── register_success_page.dart # Pantalla éxito + reenvío
├── terms_and_conditions_page.dart # Consume API legal-documents
└── privacy_policy_page.dart # Consume API legal-documents
lib/features/legal_documents/
├── application/
│ ├── legal_document_cubit.dart # Carga terms/privacy desde API
│ └── legal_document_state.dart
├── data/
│ ├── datasources/
│ │ └── legal_documents_remote_datasource.dart
│ ├── models/
│ │ └── legal_document_model.dart
│ └── repositories/
│ └── legal_documents_repository_impl.dart
└── domain/
├── entities/
│ └── legal_document.dart
├── repositories/
│ └── legal_documents_repository.dart
└── usecases/
├── get_terms_and_conditions_usecase.dart
└── get_privacy_policy_usecase.dart
Endpoints API
| Método | Endpoint | Autenticación | Descripción |
|---|---|---|---|
| POST | /api/auth/sign-up/email | Público | Crear cuenta |
| POST | /api/auth/send-verification-email | Público | Reenviar verificación |
Request body — Registro
{
"name": "Ana López",
"email": "ana@ejemplo.com",
"password": "miPassword123",
"rememberMe": true
}
Request body — Reenvío verificación
{
"email": "ana@ejemplo.com"
}
Registro DI
- UseCases:
LazySingletonRegisterUseCaseSendVerificationEmailUseCase
- Cubits:
Factory(nueva instancia por pantalla)RegisterCubitVerificationCubit
getIt.registerFactory<RegisterCubit>(
() => RegisterCubit(registerUseCase: getIt<RegisterUseCase>()),
);
getIt.registerFactory<VerificationCubit>(
() => VerificationCubit(
sendVerificationEmailUseCase: getIt<SendVerificationEmailUseCase>(),
),
);
Localización
✅ Completa — todos los strings usan context.l10n:
| Clave | Español | Inglés |
|---|---|---|
registerTitle | Crear cuenta | Create account |
registerSubtitle | Completa los siguientes datos para registrarte | Fill in the details below to sign up |
registerNameHint | Ej: Ana López | E.g. Ana López |
registerNameRequired | El nombre es requerido | Name is required |
registerPasswordHint | Mínimo 8 caracteres | Minimum 8 characters |
registerPasswordMin | Mínimo 8 caracteres | Minimum 8 characters |
registerConfirmPasswordHint | Repite tu contraseña | Repeat your password |
registerConfirmPasswordRequired | Confirma tu contraseña | Please confirm your password |
registerPasswordMismatch | Las contraseñas no coinciden | Passwords do not match |
registerAcceptTerms | Acepto los | I accept the |
registerTerms | términos y condiciones | terms and conditions |
registerAnd | y la | and the |
registerPrivacy | política de privacidad | privacy policy |
registerButton | Crear cuenta | Create account |
registerHaveAccount | ¿Ya tienes cuenta? | Already have an account? |
registerLogin | Iniciar sesión | Sign in |
registerAcceptTermsError | Debes aceptar los términos... | You must accept the terms... |
registerSuccessTitle | ¡Registro exitoso! | Registration successful! |
registerSuccessSubtitle | Hemos enviado un correo de verificación... | We've sent a verification email... |
registerGoToLogin | Ir a iniciar sesión | Go to login |
registerVerificationSent | Se ha reenviado el correo de verificación | Verification email has been resent |
registerVerificationDidntReceive | ¿No lo recibiste? | Didn't receive it? |
registerVerificationResend | Reenviar correo | Resend email |
registerVerificationResendIn | Reenviar en {seconds}s | Resend in {seconds}s |
Tests
| Archivo | Tests |
|---|---|
register_cubit_test.dart | 5 — initial state, success, ServerFailure, NetworkFailure, params verification |
register_usecase_test.dart | 3 — success, ServerFailure, NetworkFailure |
verification_cubit_test.dart | 5 — initial state, success, ServerFailure, NetworkFailure, email verification |
Estados de la UI
RegisterPage
| Estado | Comportamiento |
|---|---|
| Initial | Formulario visible, botón habilitado solo si terms aceptados |
| Loading | Botón muestra spinner, deshabilitado |
| Success | Navega a RegisterSuccessPage |
| Error | Muestra notificación con el mensaje del failure |
RegisterSuccessPage
| Estado | Comportamiento |
|---|---|
| Initial | Pantalla de éxito con cooldown activo |
| Loading (reenvío) | Botón de reenvío muestra spinner |
| Success (reenvío) | Muestra notificación de éxito, reinicia cooldown |
| Error (reenvío) | Muestra notificación de error |
| Cooldown activo | Muestra timer "Reenviar en Xs" |
Pendientes
| Tema | Estado | Notas |
|---|---|---|
| Términos y Condiciones localizado | ✅ | Consume GET /legal-documents/terms-and-conditions con locale |
| Política de Privacidad localizado | ✅ | Consume GET /legal-documents/privacy-policy con locale |
| Checkbox requiere lectura | ✅ | El checkbox se habilita solo después de leer ambos documentos |