- professional_profile_view: gradient header card with avatar overlay,
sectioned cards (service modality, address, rate, payment chips, schedule),
animated payment method chips, full-width save button with loading state
- sidebar: teal-dark background in pro mode vs navy in user mode,
animated mode indicator pill, muted toggle button in pro mode
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- Stop swallowing DELETE errors silently; show snackbar instead
- After successful reset, reload professional from server and notify providers
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- Add missing api_service.dart import (without it the file fails to compile)
- Initialize _loadingSettings = false so button renders before async settings load
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- Usuario model: proRejectedAt parsed from professionals.updated_at
- _StatusCard: shows countdown or retry button based on rejection_wait_days setting
- Retry clears the rejected record via DELETE /professionals/me
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Shows document type locked to 'Cédula de ciudadanía' and adds required
number input field above the photo upload.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
context.read doesn't subscribe to changes, so the form stayed visible
after submitForReview even though AuthProvider was updated.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- Add Profesional.empty() factory for users with no professional record
- initState: catch error from getProfessional and show empty form instead of infinite spinner
- Backend upsert: create professional record if none exists (no longer throws 404)
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Display: only prepend + if number doesn't already start with +
URL: strip + and spaces so WhatsApp API receives digits only
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- Profile view: gradient hero banner with overlapping avatar, status badges (phone verified, email, pro state), gender field, city from flat API endpoint, manual validation
- nginx: JS files use no-cache/must-revalidate instead of 1y immutable to prevent stale deploys
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- Solo se puede seleccionar de la lista de ciudades registradas
- GPS detecta ciudad → si está en la lista: preselecciona y muestra banner verde
- GPS detecta ciudad → si NO está en lista: banner amarillo con mensaje de no disponibilidad
- No hay campo de texto libre, solo selección de lista
- Botón muestra "Continuar con [Ciudad]" solo cuando hay selección
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- Carga ciudades de GET /locations/cities/all
- Detecta ciudad via GPS → Nominatim
- Muestra ciudad GPS detectada en banner verde
- Preselecciona automáticamente en la lista si coincide
- Buscador en tiempo real con filtro
- Ciudad GPS sin seleccionar muestra badge "GPS"
- Botón deshabilitado hasta seleccionar una ciudad
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>
- Grid responsivo (1-4 columnas según ancho)
- Tarjeta con header gradiente, avatar centrado superpuesto y badge de score
- Modo compacto (lista horizontal) en pantallas pequeñas
- Buscador en tiempo real por nombre, profesión o ciudad
- Chips de métodos de pago (Datáfono, Nequi, Transferencia)
- Dark mode completo, avatar con inicial como fallback
- Estado vacío con ícono y mensaje contextual
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- logo.dart: path correcto assets/prosapp-logo.png + errorBuilder
- services_view.dart: rediseño con tarjetas, dark mode, avatar con inicial, badges de estado
- services_history_view.dart: mismo rediseño + badges completado/cancelado/rechazado
- request_professional_view.dart: secciones con cards, botones de upload con estado visual,
estados pending/rejected mejorados, dark mode completo
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- Navbar: reemplaza hoverColor deprecated por IconButton.styleFrom(overlayColor)
- Support: rediseño completo con tarjetas, secciones y manejo correcto de URLs vacías
- Políticas/Términos: carga desde GET /settings/policies y muestra en dialog in-app
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>
- PhoneLoginView y LoginView: form envuelto en Card con sombra (blanca en claro, oscura en noche)
- Títulos: Color(0xFF0F172A) en claro, blanco en noche - siempre visible
- Subtítulos: Color(0xFF64748B) en claro (contraste 4.5:1+) vs Colors.grey anterior
- Inputs: fillColor, textColor y borderColor explícitos por tema
- AuthLayout desktop: fondo usa scaffoldBackgroundColor del tema
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- AuthLayout desktop: fondo usa scaffoldBackgroundColor en vez de Colors.white fijo
- PhoneLoginView y LoginView: todos los textos, inputs y bordes usan colores tema-aware
(titulos, subtítulos, fillColor, borderColor se adaptan a modo día/noche)
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>
- ProfileView vuelve a StatefulWidget para inicializar ProfileFormProvider
- Quitar import custom_inputs.dart sin usar
- DropdownButtonFormField con ValueKey para forzar rebuild cuando cargan ciudades
- Normalizacion de acentos en ciudad (cucuta == cucuta con/sin tilde)
- _EmailCard siempre muestra el formulario (no requiere expandir)
- Eliminado campo email read-only del formulario principal
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- Setting: lee support_title/description/days/hours/email/phone
- SettingsProvider: fallback a Setting vacio si no hay datos en DB
- SupportView: guard para settings null
- Avatar: ui-avatars.com como imagen por defecto (con nombre)
- Perfil: seccion correo como ExpansionTile (acordeon)
paso 1: email+contrasena+confirmar → Enviar codigo
paso 2: ingresar codigo de 6 digitos → Verificar (verde)
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>
- 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>
- Navbar: convertir a StatefulWidget, un solo nivel de build,
usa context.watch en lugar de Consumer anidados
- Iconos sol/luna y campana siempre visibles con color explicito
- Dashboard: barra busqueda, sugerencias y tarjeta inferior
ahora respetan isDark (cardBg, textColor, etc.)
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- Quitar AnimatedSwitcher/RotationTransition que ocultaba los iconos
- Icono sol/luna y campana con InkWell simple y colores explicitos
- Fondo navbar animado segun tema (isDark)
- DashboardLayout usa scaffoldBackgroundColor del tema
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- Icono sol/luna con animacion de rotacion en navbar
- Navbar cambia color segun el tema (animado)
- Quitar toggle del sidebar
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>
- Quitar replaceAll(' ', '_') que rompia la query
- Pasar coordenadas actuales del mapa como location bias
- Soportar formatted_address y description en respuesta
- Manejar results o predictions como clave raiz
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- hide ServiceStatus de geolocator para evitar conflicto con modelo propio
- usar _selectedHour! en getFormatTime (ya esta guardado por null-check previo)
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Mapa ocupa toda la pantalla, pin central fijo, barra de busqueda
flotante con autocomplete, tarjeta inferior para profesional/fecha.
Al mover el mapa hace geocodificacion inversa y actualiza la direccion.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- MapsService: obtiene la key via API e inyecta el script Maps JS en runtime
- LocationPickerDialog: muestra error descriptivo si la key no esta configurada
- index.html: eliminado script estatico de Maps
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- LocationPickerDialog: detecta ubicación del dispositivo, pin draggable,
reverse geocoding para obtener dirección y ciudad
- Dashboard: campo de dirección abre el mapa al tocar
- index.html: carga Maps JS API (key pendiente de configurar)
- pubspec: google_maps_flutter + geolocator
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- Logo: network image in white card + tagline
- Sidebar: deep navy gradient (#0D1B3E) with blue accent active states
- MenuItem: left accent bar indicator, cleaner hover, better contrast
- Mode toggle: gradient button matching brand colors
- TextSeparator: uppercase label with divider line
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
main.dart builder already wraps unauthenticated routes in AuthLayout.
Wrapping again in handlers caused double login screen on all viewports.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- Put logo inside white container on gradient so colors are correct
- Remove BlendMode.srcATop which was making logo invisible on gradient
- Simplify auth_layout mobile/desktop branches
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>