import 'package:flutter/material.dart'; import 'package:flutter_form_builder/flutter_form_builder.dart'; import 'package:flutter_mobx/flutter_mobx.dart'; import 'package:form_builder_validators/form_builder_validators.dart'; import '../../../../core/theme/app_colors.dart'; import '../../../../core/widgets/medical_modal.dart'; import '../../../dashboard/data/models/doctor_info_model.dart'; import '../store/config_store.dart'; class ConfigModalView extends StatefulWidget { final ValueChanged? onSaved; final ConfigStore? store; const ConfigModalView({ super.key, this.onSaved, this.store, }); @override State createState() => _ConfigModalViewState(); } class _ConfigModalViewState extends State { late final ConfigStore _store; final _formKey = GlobalKey(); @override void initState() { super.initState(); _store = widget.store ?? ConfigStore(); if (widget.store == null) { _store.loadConfig(); } } Future _handleSave() async { if (_formKey.currentState?.saveAndValidate() ?? false) { final values = _formKey.currentState!.value; if (values['nombre_doctor'] != null) { _store.nombreDoctor = values['nombre_doctor'].toString(); } if (values['especialidad'] != null) { _store.especialidad = values['especialidad'].toString(); } if (values['descrip_especialidad'] != null) { _store.descripEspecialidad = values['descrip_especialidad'].toString(); } if (values['descrip_general'] != null) { _store.descripGeneral = values['descrip_general'].toString(); } final updated = await _store.saveConfig(); if (updated != null && mounted) { widget.onSaved?.call(updated); ScaffoldMessenger.of(context).showSnackBar( const SnackBar( content: Row( children: [ Icon(Icons.check_circle_rounded, color: Colors.white, size: 18), SizedBox(width: 8), Expanded( child: Text('Configuración del consultorio guardada correctamente'), ), ], ), backgroundColor: Color(0xFF00A65A), behavior: SnackBarBehavior.floating, duration: Duration(seconds: 3), ), ); Navigator.of(context).pop(); } } } InputDecoration _cleanDecoration({ required String label, IconData? icon, bool isRequired = false, String? hintText, }) { return InputDecoration( labelText: isRequired ? '$label *' : label, hintText: hintText, filled: true, fillColor: Colors.white, isDense: true, contentPadding: const EdgeInsets.symmetric(horizontal: 14, vertical: 13), prefixIcon: icon != null ? Icon(icon, size: 18, color: isRequired ? AppColors.primary : AppColors.textMuted) : null, prefixIconConstraints: const BoxConstraints(minWidth: 38, minHeight: 38), border: OutlineInputBorder( borderRadius: BorderRadius.circular(10), borderSide: const BorderSide(color: Color(0xFFE2E8F0)), ), enabledBorder: OutlineInputBorder( borderRadius: BorderRadius.circular(10), borderSide: const BorderSide(color: Color(0xFFE2E8F0)), ), focusedBorder: OutlineInputBorder( borderRadius: BorderRadius.circular(10), borderSide: const BorderSide(color: AppColors.primary, width: 1.5), ), errorBorder: OutlineInputBorder( borderRadius: BorderRadius.circular(10), borderSide: const BorderSide(color: AppColors.error), ), focusedErrorBorder: OutlineInputBorder( borderRadius: BorderRadius.circular(10), borderSide: const BorderSide(color: AppColors.error, width: 1.5), ), labelStyle: TextStyle( fontSize: 13, fontWeight: FontWeight.w600, color: isRequired ? AppColors.primary : AppColors.textSecondary, ), hintStyle: const TextStyle(fontSize: 12.5, color: Color(0xFF94A3B8)), ); } @override Widget build(BuildContext context) { return Observer( builder: (_) { return MedicalModalDialog( titleIcon: Container( padding: const EdgeInsets.all(8), decoration: BoxDecoration( color: AppColors.primaryContainer, borderRadius: BorderRadius.circular(10), ), child: const Icon(Icons.settings_suggest_rounded, color: AppColors.primary, size: 22), ), title: 'Configuración del Consultorio', subtitle: const Text( 'Actualice la información del doctor, especialidad y datos de contacto de la clínica', style: TextStyle(fontSize: 12, color: AppColors.textMuted), ), maxWidth: 780, maxHeight: 660, bottomBar: _buildBottomBar(), child: _store.isLoading ? const Center( child: Padding( padding: EdgeInsets.all(40), child: CircularProgressIndicator(), ), ) : _buildForm(), ); }, ); } Widget _buildBottomBar() { return Container( padding: const EdgeInsets.symmetric(horizontal: 20, vertical: 12), decoration: const BoxDecoration( color: Color(0xFFF8FAFC), border: Border(top: BorderSide(color: Color(0xFFE2E8F0))), ), child: Row( children: [ Container( padding: const EdgeInsets.symmetric(horizontal: 8, vertical: 4), decoration: BoxDecoration( color: Colors.white, borderRadius: BorderRadius.circular(6), border: Border.all(color: const Color(0xFFE2E8F0)), ), child: const Row( mainAxisSize: MainAxisSize.min, children: [ Icon(Icons.keyboard_outlined, size: 12, color: AppColors.textMuted), SizedBox(width: 4), Text( 'ESC para salir', style: TextStyle(fontSize: 11, color: AppColors.textMuted, fontWeight: FontWeight.w500), ), ], ), ), const Spacer(), TextButton( onPressed: _store.isSaving ? null : () => Navigator.of(context).pop(), style: TextButton.styleFrom( foregroundColor: AppColors.textSecondary, padding: const EdgeInsets.symmetric(horizontal: 16, vertical: 12), ), child: const Text('Cancelar', style: TextStyle(fontWeight: FontWeight.w600)), ), const SizedBox(width: 12), ElevatedButton( onPressed: _store.isSaving ? null : _handleSave, style: ElevatedButton.styleFrom( backgroundColor: const Color(0xFF00A65A), foregroundColor: Colors.white, padding: const EdgeInsets.symmetric(horizontal: 22, vertical: 12), elevation: 1, shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(8)), ), child: _store.isSaving ? const SizedBox( width: 18, height: 18, child: CircularProgressIndicator( strokeWidth: 2, valueColor: AlwaysStoppedAnimation(Colors.white), ), ) : const Row( mainAxisSize: MainAxisSize.min, children: [ Icon(Icons.check_circle_outline_rounded, size: 18), SizedBox(width: 8), Text( 'Guardar Configuración', style: TextStyle(fontSize: 13, fontWeight: FontWeight.w700), ), ], ), ), ], ), ); } Widget _buildForm() { return SingleChildScrollView( padding: const EdgeInsets.symmetric(horizontal: 24, vertical: 16), child: FormBuilder( key: _formKey, child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ if (_store.errorMessage != null) ...[ Container( padding: const EdgeInsets.all(12), margin: const EdgeInsets.only(bottom: 16), decoration: BoxDecoration( color: AppColors.error.withValues(alpha: 0.1), borderRadius: BorderRadius.circular(8), border: Border.all(color: AppColors.error.withValues(alpha: 0.3)), ), child: Row( children: [ const Icon(Icons.error_outline_rounded, color: AppColors.error, size: 20), const SizedBox(width: 10), Expanded( child: Text( _store.errorMessage!, style: const TextStyle(fontSize: 12.5, color: AppColors.error, fontWeight: FontWeight.w500), ), ), ], ), ), ], // Sección 1: Identidad Médica _buildSectionHeader( icon: Icons.person_pin_rounded, title: 'Identidad del Profesional', subtitle: 'Nombre y especialidad principal reflejados en el encabezado y recetas', ), const SizedBox(height: 12), Row( crossAxisAlignment: CrossAxisAlignment.start, children: [ Expanded( flex: 6, child: FormBuilderTextField( name: 'nombre_doctor', initialValue: _store.nombreDoctor, decoration: _cleanDecoration( label: 'Nombre del Doctor', icon: Icons.badge_outlined, isRequired: true, hintText: 'Ej. Dr. Luis A. Castro Sosa', ), validator: FormBuilderValidators.compose([ FormBuilderValidators.required(errorText: 'Requerido'), FormBuilderValidators.minLength(3, errorText: 'Mínimo 3 caracteres'), ]), onChanged: (v) => _store.nombreDoctor = v ?? '', ), ), const SizedBox(width: 14), Expanded( flex: 5, child: FormBuilderTextField( name: 'especialidad', initialValue: _store.especialidad, decoration: _cleanDecoration( label: 'Especialidad', icon: Icons.medical_services_outlined, isRequired: true, hintText: 'Ej. Cirujano Urólogo', ), validator: FormBuilderValidators.compose([ FormBuilderValidators.required(errorText: 'Requerido'), FormBuilderValidators.minLength(3, errorText: 'Mínimo 3 caracteres'), ]), onChanged: (v) => _store.especialidad = v ?? '', ), ), ], ), const SizedBox(height: 22), // Sección 2: Áreas de Enfoque y Subespecialidades _buildSectionHeader( icon: Icons.local_hospital_outlined, title: 'Áreas de Enfoque y Subespecialidades', subtitle: 'Enfermedades, órganos o áreas de tratamiento de su consulta', ), const SizedBox(height: 12), FormBuilderTextField( name: 'descrip_especialidad', initialValue: _store.descripEspecialidad, maxLines: 4, decoration: _cleanDecoration( label: 'Descripción de Especialidades', hintText: 'Ej. Enfermedades Vías Urinarias, Riñones, Vejiga, Próstata, Disfunción eréctil...', ), onChanged: (v) => _store.descripEspecialidad = v ?? '', ), const SizedBox(height: 22), // Sección 3: Datos de Contacto y Clínica _buildSectionHeader( icon: Icons.apartment_rounded, title: 'Datos del Consultorio y Contacto', subtitle: 'Dirección física de la clínica, edificio, teléfonos, celular y correo', ), const SizedBox(height: 12), FormBuilderTextField( name: 'descrip_general', initialValue: _store.descripGeneral, maxLines: 4, decoration: _cleanDecoration( label: 'Información General y Contacto', hintText: 'Ej. Instituto materno infantil, Av. Juan Pablo Duarte, Santiago. Tel: 809-583-2394...', ), onChanged: (v) => _store.descripGeneral = v ?? '', ), ], ), ), ); } Widget _buildSectionHeader({ required IconData icon, required String title, required String subtitle, }) { return Row( crossAxisAlignment: CrossAxisAlignment.start, children: [ Icon(icon, size: 18, color: AppColors.primary), const SizedBox(width: 8), Expanded( child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ Text( title, style: const TextStyle( fontSize: 13, fontWeight: FontWeight.w700, color: AppColors.textPrimary, ), ), const SizedBox(height: 2), Text( subtitle, style: const TextStyle( fontSize: 11.5, color: AppColors.textMuted, ), ), ], ), ), ], ); } }