fix: perfil - dropdown ciudad con todas las opciones

- WhiteCard usa Theme.cardColor en lugar de Colors.white fijo
- Dropdown ciudad: normaliza valor guardado vs lista (evita mismatch)
- Muestra spinner mientras cargan las ciudades
- Texto de items adapta color segun el tema (isDark)

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
Lizandro Guarnizo
2026-06-27 09:22:10 -05:00
co-authored by Claude Sonnet 4.6
parent fac4135835
commit 7349d4e3fd
2 changed files with 39 additions and 15 deletions
+4 -3
View File
@@ -14,7 +14,7 @@ class WhiteCard extends StatelessWidget {
width: width, // width == null ? null : width, width: width, // width == null ? null : width,
margin: const EdgeInsets.all(8), margin: const EdgeInsets.all(8),
padding: const EdgeInsets.all(10), padding: const EdgeInsets.all(10),
decoration: buildBoxDecoration(), decoration: buildBoxDecoration(context),
child: Column( child: Column(
crossAxisAlignment: CrossAxisAlignment.start, crossAxisAlignment: CrossAxisAlignment.start,
children: [ children: [
@@ -37,9 +37,10 @@ class WhiteCard extends StatelessWidget {
); );
} }
BoxDecoration buildBoxDecoration() { BoxDecoration buildBoxDecoration(BuildContext context) {
final cardColor = Theme.of(context).cardColor;
return BoxDecoration( return BoxDecoration(
color: Colors.white, color: cardColor,
borderRadius: BorderRadius.circular(5), borderRadius: BorderRadius.circular(5),
boxShadow: [ boxShadow: [
BoxShadow(color: Colors.black.withOpacity(0.05), blurRadius: 5) BoxShadow(color: Colors.black.withOpacity(0.05), blurRadius: 5)
+35 -12
View File
@@ -109,6 +109,20 @@ class _ProfileViewForm extends StatelessWidget {
final citiesProvider = Provider.of<CitiesProvider>(context); final citiesProvider = Provider.of<CitiesProvider>(context);
final cities = citiesProvider.cities; final cities = citiesProvider.cities;
final user = profileFormProvider.user!; final user = profileFormProvider.user!;
final isDark = Theme.of(context).brightness == Brightness.dark;
final textColor = isDark ? Colors.white : Colors.black87;
// Normaliza el valor actual para que coincida exactamente con la lista
final cityNames = cities.map((c) => c.cityName).toList();
String? currentCity;
if (user.city != null && user.city!.isNotEmpty) {
final saved = user.city!.toLowerCase().trim();
currentCity = cityNames.firstWhere(
(n) => n.toLowerCase().trim() == saved,
orElse: () => '',
);
if (currentCity!.isEmpty) currentCity = null;
}
return WhiteCard( return WhiteCard(
title: 'Información general', title: 'Información general',
@@ -169,14 +183,19 @@ class _ProfileViewForm extends StatelessWidget {
), ),
), ),
const SizedBox(height: 20), const SizedBox(height: 20),
DropdownButtonFormField( if (citiesProvider.isLoading)
const Padding(
padding: EdgeInsets.symmetric(vertical: 16),
child: Center(child: CircularProgressIndicator()),
)
else
DropdownButtonFormField<String>(
validator: (value) { validator: (value) {
if (value == null) { if (value == null) return 'La ciudad es obligatoria';
return 'La ciudad es obligatoria';
}
return null; return null;
}, },
value: user.city == '' ? null : user.city, value: currentCity,
isExpanded: true,
decoration: CustomInputs.formInputDecoration( decoration: CustomInputs.formInputDecoration(
hint: 'Selecciona tu ciudad', hint: 'Selecciona tu ciudad',
label: 'Ciudad', label: 'Ciudad',
@@ -185,16 +204,20 @@ class _ProfileViewForm extends StatelessWidget {
items: cities.map((City ciudad) { items: cities.map((City ciudad) {
return DropdownMenuItem<String>( return DropdownMenuItem<String>(
value: ciudad.cityName, value: ciudad.cityName,
child: Text('${ciudad.cityName} - ${ciudad.stateOfCity}', child: Text(
style: const TextStyle( '${ciudad.cityName} - ${ciudad.stateOfCity}',
color: Colors.black, style: TextStyle(
fontWeight: FontWeight.normal, color: textColor,
)), fontWeight: FontWeight.normal,
),
overflow: TextOverflow.ellipsis,
),
); );
}).toList(), }).toList(),
onChanged: (value) { onChanged: (value) {
profileFormProvider.copyUserWith(city: value!); if (value != null) profileFormProvider.copyUserWith(city: value);
}), },
),
const SizedBox(height: 20), const SizedBox(height: 20),
ConstrainedBox( ConstrainedBox(
constraints: const BoxConstraints(maxWidth: 130), constraints: const BoxConstraints(maxWidth: 130),