fix: hover navbar, soporte sin spinner, RETHUS en formulario profesional
- 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>
This commit is contained in:
co-authored by
Claude Sonnet 4.6
parent
efbdaf2dbe
commit
7434bc8644
+1
-1
@@ -45,7 +45,7 @@ class AppState extends StatelessWidget {
|
|||||||
ChangeNotifierProvider(lazy: false, create: (_) => SideMenuProvider()),
|
ChangeNotifierProvider(lazy: false, create: (_) => SideMenuProvider()),
|
||||||
ChangeNotifierProvider(lazy: false, create: (_) => ProfessionalProvider()),
|
ChangeNotifierProvider(lazy: false, create: (_) => ProfessionalProvider()),
|
||||||
ChangeNotifierProvider(lazy: false, create: (_) => ThemeProvider()),
|
ChangeNotifierProvider(lazy: false, create: (_) => ThemeProvider()),
|
||||||
ChangeNotifierProvider(create: (_) => SettingsProvider()),
|
ChangeNotifierProvider(lazy: false, create: (_) => SettingsProvider()),
|
||||||
ChangeNotifierProvider(create: (_) => ProfileFormProvider()),
|
ChangeNotifierProvider(create: (_) => ProfileFormProvider()),
|
||||||
ChangeNotifierProvider(create: (_) => ProfessionalFormProvider()),
|
ChangeNotifierProvider(create: (_) => ProfessionalFormProvider()),
|
||||||
ChangeNotifierProvider(create: (_) => ProfessionalsProvider()),
|
ChangeNotifierProvider(create: (_) => ProfessionalsProvider()),
|
||||||
|
|||||||
@@ -6,6 +6,8 @@ import 'package:prosapp_web_app/models/schedules_entity.dart';
|
|||||||
class Profesional {
|
class Profesional {
|
||||||
final String id;
|
final String id;
|
||||||
final String identification;
|
final String identification;
|
||||||
|
final String rethusCode;
|
||||||
|
final bool rethusValidated;
|
||||||
final String address;
|
final String address;
|
||||||
final String aditionalAddress;
|
final String aditionalAddress;
|
||||||
final String profession;
|
final String profession;
|
||||||
@@ -25,6 +27,8 @@ class Profesional {
|
|||||||
const Profesional({
|
const Profesional({
|
||||||
required this.id,
|
required this.id,
|
||||||
required this.identification,
|
required this.identification,
|
||||||
|
required this.rethusCode,
|
||||||
|
required this.rethusValidated,
|
||||||
required this.address,
|
required this.address,
|
||||||
required this.aditionalAddress,
|
required this.aditionalAddress,
|
||||||
required this.profession,
|
required this.profession,
|
||||||
@@ -103,6 +107,8 @@ class Profesional {
|
|||||||
return Profesional(
|
return Profesional(
|
||||||
id: doc['id'] as String,
|
id: doc['id'] as String,
|
||||||
identification: (doc['identification'] as String?) ?? '',
|
identification: (doc['identification'] as String?) ?? '',
|
||||||
|
rethusCode: (doc['rethus_code'] as String?) ?? '',
|
||||||
|
rethusValidated: (doc['rethus_validated'] as bool?) ?? false,
|
||||||
address: (doc['address'] as String?) ?? '',
|
address: (doc['address'] as String?) ?? '',
|
||||||
aditionalAddress: (doc['aditional_address'] as String?) ?? '',
|
aditionalAddress: (doc['aditional_address'] as String?) ?? '',
|
||||||
profession: (doc['profession'] as String?) ?? '',
|
profession: (doc['profession'] as String?) ?? '',
|
||||||
@@ -124,6 +130,8 @@ class Profesional {
|
|||||||
Profesional copyWith({
|
Profesional copyWith({
|
||||||
String? id,
|
String? id,
|
||||||
String? identification,
|
String? identification,
|
||||||
|
String? rethusCode,
|
||||||
|
bool? rethusValidated,
|
||||||
String? address,
|
String? address,
|
||||||
String? aditionalAddress,
|
String? aditionalAddress,
|
||||||
String? profession,
|
String? profession,
|
||||||
@@ -143,6 +151,8 @@ class Profesional {
|
|||||||
return Profesional(
|
return Profesional(
|
||||||
id: id ?? this.id,
|
id: id ?? this.id,
|
||||||
identification: identification ?? this.identification,
|
identification: identification ?? this.identification,
|
||||||
|
rethusCode: rethusCode ?? this.rethusCode,
|
||||||
|
rethusValidated: rethusValidated ?? this.rethusValidated,
|
||||||
address: address ?? this.address,
|
address: address ?? this.address,
|
||||||
aditionalAddress: aditionalAddress ?? this.aditionalAddress,
|
aditionalAddress: aditionalAddress ?? this.aditionalAddress,
|
||||||
profession: profession ?? this.profession,
|
profession: profession ?? this.profession,
|
||||||
@@ -167,6 +177,8 @@ class Profesional {
|
|||||||
return {
|
return {
|
||||||
'id': id,
|
'id': id,
|
||||||
'identification': identification,
|
'identification': identification,
|
||||||
|
'rethus_code': rethusCode,
|
||||||
|
'rethus_validated': rethusValidated,
|
||||||
'address': address,
|
'address': address,
|
||||||
'aditional_address': aditionalAddress,
|
'aditional_address': aditionalAddress,
|
||||||
'profession': profession,
|
'profession': profession,
|
||||||
|
|||||||
@@ -16,6 +16,7 @@ class ProfessionalFormProvider with ChangeNotifier {
|
|||||||
copyProfesionalWith({
|
copyProfesionalWith({
|
||||||
String? id,
|
String? id,
|
||||||
String? identification,
|
String? identification,
|
||||||
|
String? rethusCode,
|
||||||
String? address,
|
String? address,
|
||||||
String? aditionalAddress,
|
String? aditionalAddress,
|
||||||
String? profession,
|
String? profession,
|
||||||
@@ -35,6 +36,7 @@ class ProfessionalFormProvider with ChangeNotifier {
|
|||||||
profesional = Profesional(
|
profesional = Profesional(
|
||||||
id: id ?? profesional!.id,
|
id: id ?? profesional!.id,
|
||||||
identification: identification ?? profesional!.identification,
|
identification: identification ?? profesional!.identification,
|
||||||
|
rethusCode: rethusCode ?? profesional!.rethusCode,
|
||||||
address: address ?? profesional!.address,
|
address: address ?? profesional!.address,
|
||||||
aditionalAddress: aditionalAddress ?? profesional!.aditionalAddress,
|
aditionalAddress: aditionalAddress ?? profesional!.aditionalAddress,
|
||||||
profession: profession ?? profesional!.profession,
|
profession: profession ?? profesional!.profession,
|
||||||
|
|||||||
@@ -13,7 +13,7 @@ class SettingsProvider extends ChangeNotifier {
|
|||||||
|
|
||||||
getSettings() async {
|
getSettings() async {
|
||||||
try {
|
try {
|
||||||
final data = await _api.get('/settings');
|
final data = await _api.get('/settings').timeout(const Duration(seconds: 10));
|
||||||
if (data != null) {
|
if (data != null) {
|
||||||
settings = Setting.fromDocument(data as Map<String, dynamic>);
|
settings = Setting.fromDocument(data as Map<String, dynamic>);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -38,6 +38,9 @@ class _NavbarState extends State<Navbar> {
|
|||||||
|
|
||||||
final iconColor = isDark ? Colors.white70 : const Color(0xFF475569);
|
final iconColor = isDark ? Colors.white70 : const Color(0xFF475569);
|
||||||
final bgColor = isDark ? const Color(0xFF1E293B) : Colors.white;
|
final bgColor = isDark ? const Color(0xFF1E293B) : Colors.white;
|
||||||
|
final hoverColor = isDark
|
||||||
|
? Colors.white.withOpacity(0.08)
|
||||||
|
: const Color(0xFF42A4EF).withOpacity(0.08);
|
||||||
|
|
||||||
final reputation = scoreProvider.reputation;
|
final reputation = scoreProvider.reputation;
|
||||||
final pendingCount =
|
final pendingCount =
|
||||||
@@ -60,6 +63,7 @@ class _NavbarState extends State<Navbar> {
|
|||||||
if (size.width <= 700)
|
if (size.width <= 700)
|
||||||
IconButton(
|
IconButton(
|
||||||
icon: Icon(Icons.menu, color: iconColor, size: 22),
|
icon: Icon(Icons.menu, color: iconColor, size: 22),
|
||||||
|
hoverColor: hoverColor,
|
||||||
onPressed: SideMenuProvider.openMenu,
|
onPressed: SideMenuProvider.openMenu,
|
||||||
),
|
),
|
||||||
|
|
||||||
@@ -85,6 +89,7 @@ class _NavbarState extends State<Navbar> {
|
|||||||
// Toggle día/noche
|
// Toggle día/noche
|
||||||
IconButton(
|
IconButton(
|
||||||
tooltip: isDark ? 'Modo día' : 'Modo noche',
|
tooltip: isDark ? 'Modo día' : 'Modo noche',
|
||||||
|
hoverColor: hoverColor,
|
||||||
icon: Icon(
|
icon: Icon(
|
||||||
isDark ? Icons.light_mode : Icons.dark_mode,
|
isDark ? Icons.light_mode : Icons.dark_mode,
|
||||||
color: isDark ? Colors.amber : iconColor,
|
color: isDark ? Colors.amber : iconColor,
|
||||||
@@ -99,6 +104,7 @@ class _NavbarState extends State<Navbar> {
|
|||||||
children: [
|
children: [
|
||||||
IconButton(
|
IconButton(
|
||||||
tooltip: 'Notificaciones',
|
tooltip: 'Notificaciones',
|
||||||
|
hoverColor: hoverColor,
|
||||||
icon: Icon(
|
icon: Icon(
|
||||||
pendingCount > 0
|
pendingCount > 0
|
||||||
? Icons.notifications_active
|
? Icons.notifications_active
|
||||||
|
|||||||
@@ -157,6 +157,19 @@ class _ProfileViewFormState extends State<_ProfileViewForm> {
|
|||||||
),
|
),
|
||||||
),
|
),
|
||||||
const SizedBox(height: 10),
|
const SizedBox(height: 10),
|
||||||
|
TextFormField(
|
||||||
|
initialValue: professional!.rethusCode,
|
||||||
|
onChanged: (value) {
|
||||||
|
professionalFormProvider.copyProfesionalWith(
|
||||||
|
rethusCode: value);
|
||||||
|
},
|
||||||
|
decoration: CustomInputs.formInputDecoration(
|
||||||
|
hint: 'Código RETHUS (opcional)',
|
||||||
|
label: 'Código RETHUS',
|
||||||
|
icon: Icons.health_and_safety_outlined,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
const SizedBox(height: 10),
|
||||||
ElevatedButton.icon(
|
ElevatedButton.icon(
|
||||||
onPressed: () async {
|
onPressed: () async {
|
||||||
try {
|
try {
|
||||||
@@ -210,13 +223,7 @@ class _ProfileViewFormState extends State<_ProfileViewForm> {
|
|||||||
items: professions.map((Profession profession) {
|
items: professions.map((Profession profession) {
|
||||||
return DropdownMenuItem<String>(
|
return DropdownMenuItem<String>(
|
||||||
value: profession.name,
|
value: profession.name,
|
||||||
child: Text(
|
child: Text(profession.name),
|
||||||
profession.name,
|
|
||||||
style: const TextStyle(
|
|
||||||
color: Colors.black,
|
|
||||||
fontWeight: FontWeight.normal,
|
|
||||||
),
|
|
||||||
),
|
|
||||||
);
|
);
|
||||||
}).toList(),
|
}).toList(),
|
||||||
onChanged: (value) {
|
onChanged: (value) {
|
||||||
|
|||||||
@@ -1,3 +1,4 @@
|
|||||||
|
import 'package:prosapp_web_app/models/setting.dart';
|
||||||
import 'package:prosapp_web_app/providers/settings_provider.dart';
|
import 'package:prosapp_web_app/providers/settings_provider.dart';
|
||||||
import 'package:prosapp_web_app/ui/cards/white_card.dart';
|
import 'package:prosapp_web_app/ui/cards/white_card.dart';
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
@@ -54,15 +55,7 @@ class SupportView extends StatelessWidget {
|
|||||||
|
|
||||||
return Consumer<SettingsProvider>(
|
return Consumer<SettingsProvider>(
|
||||||
builder: (context, settingsProvider, child) {
|
builder: (context, settingsProvider, child) {
|
||||||
if (settingsProvider.isLoading) {
|
final settings = settingsProvider.settings ?? Setting.fromDocument({});
|
||||||
return const Center(child: CircularProgressIndicator());
|
|
||||||
}
|
|
||||||
|
|
||||||
if (settingsProvider.settings == null) {
|
|
||||||
return const Center(child: Text('No se pudieron cargar los datos de soporte.'));
|
|
||||||
}
|
|
||||||
|
|
||||||
final settings = settingsProvider.settings!;
|
|
||||||
|
|
||||||
return ListView(
|
return ListView(
|
||||||
physics: const ClampingScrollPhysics(),
|
physics: const ClampingScrollPhysics(),
|
||||||
|
|||||||
Reference in New Issue
Block a user