After logout or on app start with no/invalid token, the browser URL
might be #/dashboard or #/auth/login. Using addPostFrameCallback to
navigate to phoneLoginRoute once the navigator is ready ensures the
user always lands on the phone login screen.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- Eliminado Flutter Form widget, validación manual por campo
- submitForReview() en provider sin depender de formKey
- Errores inline visibles (cédula obligatoria, profesión obligatoria)
- Loading spinner en el botón mientras envía
- try/catch con snackbar de error si falla la API
- Orden de campos: foto cédula, profesión, RETHUS (opcional), especializaciones (opcional)
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- professional_form_provider: agregar rethusValidated al constructor Profesional
- professional_provider: agregar rethusCode y rethusValidated al fallback del constructor
- profile_view: quitar await de refreshUser() que retorna void
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- Navbar: hoverColor tenue por tema (azul/blanco) en vez del gris por defecto de Flutter web
- SettingsProvider: lazy:false + timeout 10s para evitar spinner gris permanente en soporte
- SupportView: muestra contenido con defaults inmediatamente sin bloquear en isLoading
- Modelo Profesional: campos rethus_code y rethus_validated
- ProfessionalFormProvider: soporte para rethus_code en copyProfesionalWith
- RequestProfessionalView: campo RETHUS opcional en formulario + fix color dropdown profesión
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- 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>
- CitiesProvider.isCityAvailable() y findMatchingCity() con comparacion flexible
- Al mover el mapa extrae la ciudad del geocodificado inverso
- Si la ciudad no esta en la lista muestra aviso amarillo y bloquea solicitud
- Boton de solicitar deshabilitado cuando ciudad no esta disponible
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- ThemeProvider con persistencia en SharedPreferences
- Toggle animado en sidebar (sol/luna con switch visual)
- Temas light y dark completos en MaterialApp
- Campana en navbar con badge rojo y panel inferior de notificaciones
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- Service.fromJson: string status/location enums, ISO8601 time parsing, additional_address field name
- _loadServices: unwrap {data:[...]} paginated response; extract embedded user from response instead of extra API calls
- calendar_services_provider: same response unwrap; fallback user when not embedded
- Add ProState import where needed
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>