feat: pedir nombre al primer login + avatar con iniciales

- Detectar usuario nuevo (nombre == telefono) y redirigir
  a pantalla setup-name antes del dashboard
- SetupNameView: bienvenida con campo de nombre obligatorio
- AuthProvider.updateName() para guardar via PATCH /users/me
- NavbarAvatar: iniciales con color por inicial del nombre
  en lugar de no-image.jpg cuando no hay foto
- Perfil: mismo avatar de iniciales en la pantalla de perfil

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
Lizandro Guarnizo
2026-06-27 09:29:58 -05:00
co-authored by Claude Sonnet 4.6
parent 7349d4e3fd
commit bfa494b7fe
6 changed files with 272 additions and 20 deletions
+33 -8
View File
@@ -250,6 +250,27 @@ class _ProfileViewForm extends StatelessWidget {
}
}
Widget _buildInitials(String name) {
final parts = name.trim().split(RegExp(r'\s+'));
final initials = parts.length >= 2
? '${parts.first[0]}${parts.last[0]}'.toUpperCase()
: (parts.first.isEmpty ? '?' : parts.first[0].toUpperCase());
final colors = [
const Color(0xFF6366F1), const Color(0xFF8B5CF6),
const Color(0xFFEC4899), const Color(0xFF14B8A6),
const Color(0xFFF59E0B), const Color(0xFF10B981),
const Color(0xFFEF4444), const Color(0xFF3B82F6),
];
final bg = name.isEmpty ? colors[0] : colors[name.codeUnitAt(0) % colors.length];
return Container(
color: bg,
child: Center(
child: Text(initials,
style: const TextStyle(color: Colors.white, fontSize: 48, fontWeight: FontWeight.bold)),
),
);
}
class _AvatarContainer extends StatelessWidget {
final bool containerFull;
@@ -260,14 +281,18 @@ class _AvatarContainer extends StatelessWidget {
final user = Provider.of<AuthProvider>(context).user!;
final profileFormProvider = Provider.of<ProfileFormProvider>(context);
final image = (profileFormProvider.user!.picture == '' ||
profileFormProvider.user!.picture == null)
? const Image(image: AssetImage('no-image.jpg'))
: FadeInImage.assetNetwork(
placeholder: 'loader.gif',
fit: BoxFit.cover,
image: profileFormProvider.user!.picture!,
);
final picUrl = profileFormProvider.user!.picture;
final hasPicture = picUrl != null && picUrl.isNotEmpty;
final userName = profileFormProvider.user!.name;
Widget avatarImage;
if (hasPicture) {
avatarImage = Image.network(picUrl, fit: BoxFit.cover,
errorBuilder: (_, __, ___) => _buildInitials(userName));
} else {
avatarImage = _buildInitials(userName);
}
final image = avatarImage;
return WhiteCard(
width: containerFull ? null : 250,