# US-MGN002-002: Perfil de Usuario ## Identificacion | Campo | Valor | |-------|-------| | **ID** | US-MGN002-002 | | **Modulo** | MGN-002 Users | | **Sprint** | Sprint 2 | | **Prioridad** | P1 - Alta | | **Story Points** | 5 | | **Estado** | Ready | | **Autor** | System | | **Fecha** | 2025-12-05 | --- ## Historia de Usuario **Como** usuario autenticado del sistema **Quiero** poder ver y editar mi informacion personal **Para** mantener mis datos actualizados y personalizar mi experiencia --- ## Criterios de Aceptacion ### Escenario 1: Ver mi perfil ```gherkin Given un usuario autenticado When accede a GET /api/v1/users/me Then el sistema retorna su perfil completo And incluye firstName, lastName, email, phone And incluye avatarUrl, avatarThumbnailUrl And incluye createdAt, lastLoginAt And incluye sus roles asignados And NO incluye passwordHash ``` ### Escenario 2: Actualizar nombre ```gherkin Given un usuario autenticado con nombre "Juan" When actualiza su nombre a "Carlos" Then el sistema guarda el cambio And responde con el perfil actualizado And firstName es "Carlos" ``` ### Escenario 3: Subir avatar ```gherkin Given un usuario autenticado And una imagen JPG de 2MB When sube la imagen como avatar Then el sistema redimensiona a 200x200 px And genera thumbnail de 50x50 px And actualiza avatarUrl en su perfil And responde con las URLs generadas ``` ### Escenario 4: Avatar muy grande ```gherkin Given un usuario autenticado And una imagen de 15MB When intenta subir como avatar Then el sistema responde con status 400 And el mensaje es "Imagen excede tamaño maximo (10MB)" ``` ### Escenario 5: Eliminar avatar ```gherkin Given un usuario con avatar When elimina su avatar Then avatarUrl se establece a null And avatarThumbnailUrl se establece a null And el avatar anterior se marca como no actual ``` --- ## Mockup / Wireframe ``` +------------------------------------------------------------------+ | [Logo] Mi Perfil | +------------------------------------------------------------------+ | | | +-------+ | | | | Juan Perez | | | FOTO | juan@empresa.com | | | | Admin, Manager | | +-------+ | | [Cambiar foto] | | | | ┌─────────────────────────────────────────────────────────┐ | | │ INFORMACION PERSONAL │ | | ├─────────────────────────────────────────────────────────┤ | | │ Nombre [Juan ] │ | | │ Apellido [Perez ] │ | | │ Telefono [+521234567890 ] │ | | │ Email juan@empresa.com [Cambiar email] │ | | │ │ | | │ [ Cancelar ] [ Guardar Cambios ] │ | | └─────────────────────────────────────────────────────────┘ | | | | ┌─────────────────────────────────────────────────────────┐ | | │ SEGURIDAD │ | | ├─────────────────────────────────────────────────────────┤ | | │ Contraseña •••••••• [Cambiar contraseña] │ | | │ Ultimo login 05/12/2025 10:30 │ | | │ Miembro desde 01/01/2025 │ | | └─────────────────────────────────────────────────────────┘ | +------------------------------------------------------------------+ Modal: Subir Avatar ┌──────────────────────────────────────────────────────────────────┐ │ CAMBIAR FOTO │ ├──────────────────────────────────────────────────────────────────┤ │ │ │ +------------------+ │ │ | | Arrastra una imagen o │ │ | [ + ] | [Selecciona archivo] │ │ | | │ │ +------------------+ Formatos: JPG, PNG, WebP │ │ Tamaño max: 10MB │ │ │ │ [ Cancelar ] [ Subir ] │ └──────────────────────────────────────────────────────────────────┘ ``` --- ## Notas Tecnicas ### API Endpoints ```typescript // Obtener perfil GET /api/v1/users/me // Response 200 { "id": "user-uuid", "email": "juan@empresa.com", "firstName": "Juan", "lastName": "Perez", "phone": "+521234567890", "avatarUrl": "https://storage.../avatar-200.jpg", "avatarThumbnailUrl": "https://storage.../avatar-50.jpg", "status": "active", "emailVerifiedAt": "2025-01-01T00:00:00Z", "lastLoginAt": "2025-12-05T10:30:00Z", "createdAt": "2025-01-01T00:00:00Z", "roles": [{ "id": "...", "name": "admin" }] } // Actualizar perfil PATCH /api/v1/users/me { "firstName": "Carlos", "lastName": "Lopez", "phone": "+521234567890" } // Subir avatar POST /api/v1/users/me/avatar Content-Type: multipart/form-data avatar: [file] // Response 200 { "avatarUrl": "https://storage.../avatar-200.jpg", "avatarThumbnailUrl": "https://storage.../avatar-50.jpg" } ``` ### Validaciones de Avatar | Validacion | Valor | |------------|-------| | Formatos | image/jpeg, image/png, image/webp | | Tamaño max | 10MB | | Resize main | 200x200 px | | Resize thumb | 50x50 px | --- ## Definicion de Done - [ ] Endpoint GET /api/v1/users/me - [ ] Endpoint PATCH /api/v1/users/me - [ ] Endpoint POST /api/v1/users/me/avatar - [ ] Endpoint DELETE /api/v1/users/me/avatar - [ ] Procesamiento de imagen con Sharp - [ ] Upload a storage (S3/local) - [ ] Frontend: ProfilePage - [ ] Frontend: AvatarUploader component - [ ] Tests unitarios - [ ] Code review aprobado --- ## Estimacion | Tarea | Horas | |-------|-------| | Backend: Profile endpoints | 3h | | Backend: Avatar upload + resize | 4h | | Backend: Tests | 2h | | Frontend: ProfilePage | 4h | | Frontend: AvatarUploader | 3h | | Frontend: Tests | 2h | | **Total** | **18h** | --- ## Historial | Version | Fecha | Autor | Cambios | |---------|-------|-------|---------| | 1.0 | 2025-12-05 | System | Creacion inicial |