Módulo: Mi Perfil
Scope
| Tipo de organización | Acceso |
|---|---|
| Empresa | ✅ |
| Agencia | ✅ |
| Reclutador independiente | ✅ |
Disponible para todos los usuarios independientemente de su tipo de organización.
Permisos por rol
Empresa (COMPANY)
| Acción | Disponible |
|---|---|
| Ver información personal | ✅ |
| Cambiar foto de perfil | ✅ |
| Ver tipo de cuenta | ✅ |
| Acceder a seguridad | ✅ |
| Acceder a sesiones activas | ✅ |
| Acceder a permisos | ✅ |
| Acceder a ayuda | ✅ |
Agencia (AGENCY)
| Acción | Disponible |
|---|---|
| Ver información personal | ✅ |
| Cambiar foto de perfil | ✅ |
| Ver tipo de cuenta | ✅ |
| Acceder a seguridad | ✅ |
| Acceder a sesiones activas | ✅ |
| Acceder a permisos | ✅ |
| Acceder a ayuda | ✅ |
Reclutador independiente (RECRUITER)
| Acción | Disponible |
|---|---|
| Ver información personal | ✅ |
| Cambiar foto de perfil | ✅ |
| Ver tipo de cuenta | ✅ |
| Acceder a seguridad | ✅ |
| Acceder a sesiones activas | ✅ |
| Acceder a permisos | ✅ |
| Acceder a ayuda | ✅ |
Todas las funciones de "Mi Perfil" son idénticas para los tres roles. No hay restricciones por tipo de organización.
¿Qué es?
"Mi Perfil" es la página personal del usuario dentro de Contratta. Muestra su información básica (nombre, email, tipo de cuenta), permite gestionar su foto de perfil y da acceso a configuraciones como seguridad, sesiones activas, permisos y ayuda.
Este módulo es accesible para todos los usuarios independientemente de su tipo de organización (Empresa, Agencia o Reclutador independiente).
¿Qué puede hacer el usuario?
Foto de perfil
- Subir una foto desde cámara o galería
- Eliminar la foto actual (con confirmación)
- Ver avatar con iniciales cuando no tiene foto
Ver su información
- Nombre completo (solo lectura)
- Correo electrónico (solo lectura)
- Estado de verificación del email (verificado / no verificado)
- Tipo de cuenta (Empresa, Agencia, Independiente)
Configuración
- Seguridad — cambio de contraseña y verificación de email
- Sesiones activas — ver dispositivos con sesión iniciada
- Permisos — cámara, galería y notificaciones
- Ayuda y soporte — FAQ, contacto y licencias
Cerrar sesión
- Botón de logout con diálogo de confirmación
Flujo del usuario
1. Navega a "Perfil" desde el bottom nav
2. Ve su card con avatar, nombre, email y tipo de cuenta
3. Toca el ícono de cámara en el avatar → abre sheet con opciones
4. Selecciona cámara/galería → se sube automáticamente
5. El avatar se actualiza en toda la app (header, drawer, etc.)
6. Puede navegar a sub-páginas de configuración
7. Puede cerrar sesión (con confirmación)
Reglas de negocio
- El nombre y email no son editables desde esta pantalla (se gestionan desde otra sección o backend)
- La foto se sube como multipart al endpoint
/users/me/avatar - Al subir o eliminar avatar, se refresca el contexto global (
AuthCubit.getUserContext()) para actualizar el avatar en toda la app - Los permisos de cámara se solicitan antes de abrir la cámara
- El logout limpia tokens y redirige al login
Arquitectura
lib/features/profile/
├── application/
│ └── user_profile_cubit.dart ← Lógica de avatar (upload/delete)
├── data/
│ ├── datasources/
│ │ └── user_profile_remote_datasource.dart ← Llamadas Dio aisladas
│ └── repositories/
│ └── user_profile_repository_impl.dart ← Catch → Failures tipados
├── domain/
│ ├── repositories/
│ │ └── user_profile_repository.dart ← Contrato abstracto
│ └── usecases/
│ └── upload_user_avatar_usecase.dart ← Upload + Delete
└── presentation/
├── pages/
│ ├── profile_page.dart ← Página principal
│ ├── security_page.dart ← Sub-página seguridad
│ ├── sessions_page.dart ← Sub-página sesiones
│ ├── permissions_page.dart ← Sub-página permisos
│ └── help_support_page.dart ← Sub-página ayuda
└── widgets/
├── profile_avatar_widget.dart ← Avatar reutilizable
├── profile_settings_section.dart ← Tiles de configuración
└── image_source_sheet.dart ← Bottom sheet cámara/galería
Flujo de datos
ProfilePage → UserProfileCubit → UseCase → UserProfileRepository → UserProfileRemoteDatasource → API
La información del usuario (nombre, email, org type) viene del AuthCubit que ya existe a nivel global. El UserProfileCubit solo gestiona las operaciones de avatar.
Estado (UserProfileState)
enum AvatarStatus { idle, uploading, deleting, success, error }
class UserProfileState {
final AvatarStatus status;
final Failure? failure;
}
Endpoints API
| Método | Endpoint | Descripción |
|---|---|---|
| POST | /users/me/avatar | Subir avatar (multipart/form-data) |
| DELETE | /users/me/avatar | Eliminar avatar |
| GET | /auth/context | Obtener contexto del usuario (nombre, email, avatar URL) — via AuthCubit |
Widgets principales
| Widget | Responsabilidad |
|---|---|
ProfileAvatarWidget | Avatar circular con badge de cámara, loader y fallback a iniciales |
ProfileSettingsSection | Lista de tiles de configuración con ícono, título y subtítulo |
ImageSourceSheet | Bottom sheet reutilizable para elegir cámara, galería o eliminar |
Dependencias
image_picker— Selección de imágenesflutter_bloc— Estado viaUserProfileCubit+AuthCubitConfirmDialog(core) — Confirmaciones reutilizablesAppNotification(core) — Alertas de éxito/error
Registro DI (get_it)
- Datasource:
LazySingleton - Repository:
LazySingleton - UseCases:
LazySingleton - Cubit:
Factory(nueva instancia por pantalla)
Manejo de errores
- Datasource — deja propagar
DioException - Repository — captura y mapea a
FailureviaNetworkErrorHandler - Cubit — emite
failureen el estado - UI —
BlocListenermuestraAppNotification.errorcon mensaje localizado
Localización
Todas las cadenas usan context.l10n.*. Claves relevantes con prefijo profile*:
profileMyTitle— "Mi Perfil"profilePersonalInfo— "Información Personal"profileFullName— "Nombre completo"profileEmailVerified/profileEmailNotVerifiedprofileChangePhoto/profileTakePhoto/profileChooseGallery/profileDeletePhotoprofileAvatarUpdated/profileAvatarDeletedprofileAvatarDeleteConfirm/profileAvatarDeleteMessageprofileSecurityTitle/profileSessionsTitle/profilePermissionsTitle/profileHelpTitle
Disponibles en español (app_es.arb) e inglés (app_en.arb).