feat: 6 mejoras simultáneas en prosappweb

- web/index.html: lang=es (evita traductor) + cache busting con timestamp en flutter_bootstrap.js
- profesional.dart: rate → número, location_preferences → string para coincidir con backend DTO
- location_preferences.dart: funciones locationPrefsToString/locationPrefsFromValue
- auth_provider.dart: _navigateAfterAuth redirige a setup-city si user.city vacío, método updateCity y linkEmailWithOtp
- setup_city_view.dart: nueva vista con GPS + Nominatim para detectar ciudad, campo editable, omitir
- email_view.dart: rediseño completo con flujo OTP (paso 1: email+contraseña → paso 2: código recibido en correo)
- router + dashboard_handlers: ruta /dashboard/setup-city

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
Lizandro Guarnizo
2026-06-28 11:34:51 -05:00
co-authored by Claude Sonnet 4.6
parent f433bb2f6e
commit 0711d30f07
8 changed files with 716 additions and 148 deletions
+24
View File
@@ -24,6 +24,8 @@ class AuthProvider extends ChangeNotifier {
void _navigateAfterAuth() {
if (user?.isPhoneVerified == false) {
NavigationService.replaceTo(Flurorouter.phoneLoginRoute);
} else if (user?.city == null || user!.city!.isEmpty) {
NavigationService.replaceTo(Flurorouter.setupCityRoute);
} else {
NavigationService.replaceTo(Flurorouter.dashboardRoute);
}
@@ -107,6 +109,17 @@ class AuthProvider extends ChangeNotifier {
}
}
Future<void> updateCity(String city) async {
try {
await _api.patch('/users/me', {'city': city.trim()});
user = await _fetchMe();
notifyListeners();
} catch (_) {
NotificationsService.showSnackBarError('Error al guardar la ciudad');
rethrow;
}
}
Future<void> verifyPhoneNumberForLink(String phoneNumber) async {
try {
await _api.post('/auth/send-otp', {'phone': phoneNumber});
@@ -141,6 +154,17 @@ class AuthProvider extends ChangeNotifier {
}
}
Future<void> linkEmailWithOtp(String email, String password, String code) async {
await _api.post('/auth/link-email-otp', {
'email': email,
'password': password,
'code': code,
});
user = await _fetchMe();
notifyListeners();
NotificationsService.showSnackbar('Correo vinculado exitosamente');
}
Future<bool> isAuthenticated() async {
final token = await _api.getToken();
if (token == null) {