import 'package:flutter/material.dart'; import 'package:nethive_neo/providers/nethive/componentes_provider.dart'; import 'package:nethive_neo/theme/theme.dart'; class AddComponenteDialog extends StatefulWidget { final ComponentesProvider provider; const AddComponenteDialog({ Key? key, required this.provider, }) : super(key: key); @override State createState() => _AddComponenteDialogState(); } class _AddComponenteDialogState extends State with TickerProviderStateMixin { final _formKey = GlobalKey(); late TextEditingController _nombreController; late TextEditingController _descripcionController; late TextEditingController _ubicacionController; bool _enUso = false; bool _activo = true; int? _categoriaSeleccionada; bool _isLoading = false; // Animaciones late AnimationController _slideController; late AnimationController _fadeController; late Animation _slideAnimation; late Animation _fadeAnimation; @override void initState() { super.initState(); _nombreController = TextEditingController(); _descripcionController = TextEditingController(); _ubicacionController = TextEditingController(); // Configurar animaciones _slideController = AnimationController( duration: const Duration(milliseconds: 600), vsync: this, ); _fadeController = AnimationController( duration: const Duration(milliseconds: 400), vsync: this, ); _slideAnimation = Tween( begin: const Offset(-1.0, 0.0), end: Offset.zero, ).animate(CurvedAnimation( parent: _slideController, curve: Curves.easeOutCubic, )); _fadeAnimation = Tween( begin: 0.0, end: 1.0, ).animate(CurvedAnimation( parent: _fadeController, curve: Curves.easeInOut, )); // Iniciar animaciones _slideController.forward(); _fadeController.forward(); } @override void dispose() { _nombreController.dispose(); _descripcionController.dispose(); _ubicacionController.dispose(); _slideController.dispose(); _fadeController.dispose(); super.dispose(); } @override Widget build(BuildContext context) { final screenSize = MediaQuery.of(context).size; final isDesktop = screenSize.width > 1024; final isMobile = screenSize.width <= 768; return Dialog( backgroundColor: Colors.transparent, insetPadding: EdgeInsets.all(isDesktop ? 40 : 20), child: Container( width: isDesktop ? 900 : (isMobile ? screenSize.width * 0.95 : 700), height: isDesktop ? 650 : (isMobile ? screenSize.height * 0.9 : 600), decoration: BoxDecoration( borderRadius: BorderRadius.circular(20), boxShadow: [ BoxShadow( color: Colors.black.withOpacity(0.3), blurRadius: 30, offset: const Offset(0, 15), spreadRadius: 5, ), BoxShadow( color: AppTheme.of(context).primaryColor.withOpacity(0.2), blurRadius: 40, offset: const Offset(0, 10), spreadRadius: 2, ), ], ), child: ClipRRect( borderRadius: BorderRadius.circular(20), child: Container( decoration: BoxDecoration( gradient: LinearGradient( begin: Alignment.topLeft, end: Alignment.bottomRight, colors: [ AppTheme.of(context).primaryBackground, AppTheme.of(context).secondaryBackground, AppTheme.of(context).tertiaryBackground, ], stops: const [0.0, 0.6, 1.0], ), ), child: FadeTransition( opacity: _fadeAnimation, child: isDesktop ? _buildDesktopLayout() : _buildMobileLayout(isMobile), ), ), ), ), ); } Widget _buildDesktopLayout() { return Row( children: [ // Panel lateral izquierdo con diseño espectacular Container( width: 300, decoration: BoxDecoration( gradient: LinearGradient( begin: Alignment.topCenter, end: Alignment.bottomCenter, colors: [ AppTheme.of(context).primaryColor, AppTheme.of(context).secondaryColor, AppTheme.of(context).tertiaryColor, ], ), boxShadow: [ BoxShadow( color: AppTheme.of(context).primaryColor.withOpacity(0.5), blurRadius: 25, offset: const Offset(5, 0), ), ], ), child: SlideTransition( position: _slideAnimation, child: Padding( padding: const EdgeInsets.symmetric(vertical: 30, horizontal: 25), child: Column( mainAxisAlignment: MainAxisAlignment.center, children: [ // Icono principal del componente Container( width: 140, height: 140, decoration: BoxDecoration( borderRadius: BorderRadius.circular(20), gradient: RadialGradient( colors: [ Colors.white.withOpacity(0.3), Colors.white.withOpacity(0.1), Colors.transparent, ], ), border: Border.all( color: Colors.white.withOpacity(0.4), width: 3, ), boxShadow: [ BoxShadow( color: Colors.white.withOpacity(0.3), blurRadius: 30, spreadRadius: 10, ), ], ), child: ClipRRect( borderRadius: BorderRadius.circular(17), child: widget.provider.imagenToUpload != null ? Image.memory( widget.provider.imagenToUpload!, fit: BoxFit.cover, ) : Container( decoration: BoxDecoration( color: Colors.white.withOpacity(0.1), borderRadius: BorderRadius.circular(17), ), child: const Icon( Icons.add_circle_outline, color: Colors.white, size: 60, ), ), ), ), const SizedBox(height: 24), // Botón para seleccionar imagen Container( width: double.infinity, child: ElevatedButton.icon( onPressed: () async { await widget.provider.selectImagen(); setState(() {}); }, icon: const Icon(Icons.image, color: Colors.white), label: Text( widget.provider.imagenToUpload != null ? 'Cambiar Imagen' : 'Seleccionar Imagen', style: const TextStyle( color: Colors.white, fontWeight: FontWeight.bold, ), ), style: ElevatedButton.styleFrom( backgroundColor: Colors.white.withOpacity(0.2), padding: const EdgeInsets.symmetric(vertical: 12), shape: RoundedRectangleBorder( borderRadius: BorderRadius.circular(12), side: BorderSide( color: Colors.white.withOpacity(0.3), ), ), ), ), ), const SizedBox(height: 20), // Título const Text( 'Nuevo Componente', style: TextStyle( color: Colors.white, fontSize: 24, fontWeight: FontWeight.bold, letterSpacing: 1.0, ), textAlign: TextAlign.center, ), const SizedBox(height: 12), // Subtítulo Text( 'Registra un nuevo componente\npara tu infraestructura', style: TextStyle( color: Colors.white.withOpacity(0.9), fontSize: 14, height: 1.4, ), textAlign: TextAlign.center, ), const SizedBox(height: 30), // Estados predeterminados Row( mainAxisAlignment: MainAxisAlignment.spaceEvenly, children: [ _buildStatusIndicator( _activo ? 'Activo' : 'Inactivo', _activo ? Icons.check_circle : Icons.cancel, _activo ? Colors.green : Colors.red, ), _buildStatusIndicator( _enUso ? 'En Uso' : 'Libre', _enUso ? Icons.trending_up : Icons.trending_flat, _enUso ? Colors.orange : Colors.grey, ), ], ), const SizedBox(height: 20), // Info del negocio if (widget.provider.negocioSeleccionadoNombre != null) Container( padding: const EdgeInsets.symmetric( horizontal: 12, vertical: 6), decoration: BoxDecoration( color: Colors.white.withOpacity(0.1), borderRadius: BorderRadius.circular(12), ), child: Text( 'Negocio: ${widget.provider.negocioSeleccionadoNombre}', style: TextStyle( color: Colors.white.withOpacity(0.8), fontSize: 12, ), textAlign: TextAlign.center, ), ), ], ), ), ), ), // Panel principal con formulario Expanded( child: Padding( padding: const EdgeInsets.all(30), child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ // Header del formulario Row( children: [ Icon( Icons.add_box_rounded, color: AppTheme.of(context).primaryColor, size: 28, ), const SizedBox(width: 12), Text( 'Información del Componente', style: TextStyle( color: AppTheme.of(context).primaryText, fontSize: 22, fontWeight: FontWeight.bold, ), ), const Spacer(), IconButton( onPressed: () => Navigator.of(context).pop(), icon: Icon( Icons.close, color: AppTheme.of(context).secondaryText, ), style: IconButton.styleFrom( backgroundColor: AppTheme.of(context).secondaryBackground, shape: RoundedRectangleBorder( borderRadius: BorderRadius.circular(8), ), ), ), ], ), const SizedBox(height: 30), // Formulario Expanded( child: Form( key: _formKey, child: SingleChildScrollView( child: Column( children: [ // Primera fila - Nombre y Categoría Row( children: [ Expanded( flex: 2, child: _buildCompactFormField( controller: _nombreController, label: 'Nombre del Componente', hint: 'Ej: Switch Principal MDF', icon: Icons.devices_rounded, validator: (value) { if (value == null || value.trim().isEmpty) { return 'El nombre es obligatorio'; } return null; }, ), ), const SizedBox(width: 16), Expanded( child: _buildCategoriaDropdown(), ), ], ), const SizedBox(height: 16), // Segunda fila - Ubicación _buildCompactFormField( controller: _ubicacionController, label: 'Ubicación', hint: 'Ej: MDF Principal - Rack 1', icon: Icons.location_on_rounded, validator: (value) { // La ubicación es opcional return null; }, ), const SizedBox(height: 16), // Tercera fila - Descripción _buildCompactFormField( controller: _descripcionController, label: 'Descripción', hint: 'Descripción detallada del componente', icon: Icons.description_rounded, maxLines: 3, validator: (value) { // La descripción es opcional return null; }, ), const SizedBox(height: 20), // Switches de estado Row( children: [ Expanded( child: _buildSwitchCard( title: 'Componente Activo', subtitle: 'El componente está operativo', value: _activo, onChanged: (value) { setState(() { _activo = value; }); }, icon: Icons.power_settings_new, activeColor: Colors.green, ), ), const SizedBox(width: 16), Expanded( child: _buildSwitchCard( title: 'En Uso', subtitle: 'El componente está siendo utilizado', value: _enUso, onChanged: (value) { setState(() { _enUso = value; }); }, icon: Icons.work, activeColor: Colors.orange, ), ), ], ), ], ), ), ), ), // Botones de acción const SizedBox(height: 20), Row( children: [ Expanded( child: OutlinedButton.icon( onPressed: _isLoading ? null : () => Navigator.of(context).pop(), icon: const Icon(Icons.close, size: 18), label: const Text('Cancelar'), style: OutlinedButton.styleFrom( foregroundColor: AppTheme.of(context).secondaryText, side: BorderSide( color: AppTheme.of(context) .secondaryText .withOpacity(0.5), ), padding: const EdgeInsets.symmetric(vertical: 14), shape: RoundedRectangleBorder( borderRadius: BorderRadius.circular(12), ), ), ), ), const SizedBox(width: 16), Expanded( flex: 2, child: Container( decoration: BoxDecoration( gradient: AppTheme.of(context).primaryGradient, borderRadius: BorderRadius.circular(12), boxShadow: [ BoxShadow( color: AppTheme.of(context) .primaryColor .withOpacity(0.4), blurRadius: 15, offset: const Offset(0, 5), ), ], ), child: ElevatedButton.icon( onPressed: _isLoading ? null : _guardarComponente, style: ElevatedButton.styleFrom( backgroundColor: Colors.transparent, shadowColor: Colors.transparent, padding: const EdgeInsets.symmetric(vertical: 14), shape: RoundedRectangleBorder( borderRadius: BorderRadius.circular(12), ), ), icon: _isLoading ? const SizedBox( width: 20, height: 20, child: CircularProgressIndicator( strokeWidth: 2, valueColor: AlwaysStoppedAnimation( Colors.white), ), ) : const Icon(Icons.save_rounded, color: Colors.white, size: 20), label: Text( _isLoading ? 'Guardando...' : 'Crear Componente', style: const TextStyle( color: Colors.white, fontSize: 15, fontWeight: FontWeight.bold, letterSpacing: 0.5, ), ), ), ), ), ], ), ], ), ), ), ], ); } Widget _buildMobileLayout(bool isMobile) { return Column( children: [ // Header móvil Container( width: double.infinity, padding: const EdgeInsets.all(20), decoration: BoxDecoration( gradient: LinearGradient( begin: Alignment.topLeft, end: Alignment.bottomRight, colors: [ AppTheme.of(context).primaryColor, AppTheme.of(context).secondaryColor, AppTheme.of(context).tertiaryColor, ], ), ), child: SafeArea( bottom: false, child: Column( children: [ Row( mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ const Text( 'Nuevo Componente', style: TextStyle( color: Colors.white, fontSize: 20, fontWeight: FontWeight.bold, ), ), IconButton( onPressed: () => Navigator.of(context).pop(), icon: const Icon(Icons.close, color: Colors.white), ), ], ), const SizedBox(height: 16), // Imagen/selector móvil GestureDetector( onTap: () async { await widget.provider.selectImagen(); setState(() {}); }, child: Container( width: 100, height: 100, decoration: BoxDecoration( borderRadius: BorderRadius.circular(15), border: Border.all( color: Colors.white.withOpacity(0.3), width: 2), ), child: ClipRRect( borderRadius: BorderRadius.circular(13), child: widget.provider.imagenToUpload != null ? Image.memory( widget.provider.imagenToUpload!, fit: BoxFit.cover, ) : Container( color: Colors.white.withOpacity(0.1), child: const Icon( Icons.add_photo_alternate, color: Colors.white, size: 40, ), ), ), ), ), const SizedBox(height: 8), Text( widget.provider.imagenToUpload != null ? 'Toca para cambiar imagen' : 'Toca para añadir imagen', style: TextStyle( color: Colors.white.withOpacity(0.8), fontSize: 12, ), ), ], ), ), ), // Contenido del formulario para móvil Expanded( child: Form( key: _formKey, child: SingleChildScrollView( padding: const EdgeInsets.all(20), child: Column( children: [ // Estados en móvil Row( children: [ Expanded( child: _buildStatusIndicator( _activo ? 'Activo' : 'Inactivo', _activo ? Icons.check_circle : Icons.cancel, _activo ? Colors.green : Colors.red, ), ), const SizedBox(width: 12), Expanded( child: _buildStatusIndicator( _enUso ? 'En Uso' : 'Libre', _enUso ? Icons.trending_up : Icons.trending_flat, _enUso ? Colors.orange : Colors.grey, ), ), ], ), const SizedBox(height: 20), // Campos del formulario _buildCompactFormField( controller: _nombreController, label: 'Nombre del Componente', hint: 'Ej: Switch Principal MDF', icon: Icons.devices_rounded, validator: (value) { if (value == null || value.trim().isEmpty) { return 'El nombre es obligatorio'; } return null; }, ), const SizedBox(height: 16), _buildCategoriaDropdown(), const SizedBox(height: 16), _buildCompactFormField( controller: _ubicacionController, label: 'Ubicación', hint: 'Ej: MDF Principal - Rack 1', icon: Icons.location_on_rounded, ), const SizedBox(height: 16), _buildCompactFormField( controller: _descripcionController, label: 'Descripción', hint: 'Descripción detallada del componente', icon: Icons.description_rounded, maxLines: 3, ), const SizedBox(height: 20), // Switches en móvil _buildSwitchCard( title: 'Componente Activo', subtitle: 'El componente está operativo', value: _activo, onChanged: (value) { setState(() { _activo = value; }); }, icon: Icons.power_settings_new, activeColor: Colors.green, ), const SizedBox(height: 12), _buildSwitchCard( title: 'En Uso', subtitle: 'El componente está siendo utilizado', value: _enUso, onChanged: (value) { setState(() { _enUso = value; }); }, icon: Icons.work, activeColor: Colors.orange, ), const SizedBox(height: 30), // Botones para móvil Column( children: [ Container( width: double.infinity, decoration: BoxDecoration( gradient: AppTheme.of(context).primaryGradient, borderRadius: BorderRadius.circular(12), boxShadow: [ BoxShadow( color: AppTheme.of(context) .primaryColor .withOpacity(0.4), blurRadius: 15, offset: const Offset(0, 5), ), ], ), child: ElevatedButton.icon( onPressed: _isLoading ? null : _guardarComponente, style: ElevatedButton.styleFrom( backgroundColor: Colors.transparent, shadowColor: Colors.transparent, padding: const EdgeInsets.symmetric(vertical: 14), shape: RoundedRectangleBorder( borderRadius: BorderRadius.circular(12), ), ), icon: _isLoading ? const SizedBox( width: 20, height: 20, child: CircularProgressIndicator( strokeWidth: 2, valueColor: AlwaysStoppedAnimation( Colors.white), ), ) : const Icon(Icons.save_rounded, color: Colors.white, size: 20), label: Text( _isLoading ? 'Guardando...' : 'Crear Componente', style: const TextStyle( color: Colors.white, fontSize: 15, fontWeight: FontWeight.bold, letterSpacing: 0.5, ), ), ), ), const SizedBox(height: 12), SizedBox( width: double.infinity, child: OutlinedButton.icon( onPressed: _isLoading ? null : () => Navigator.of(context).pop(), icon: const Icon(Icons.close, size: 18), label: const Text('Cancelar'), style: OutlinedButton.styleFrom( foregroundColor: AppTheme.of(context).secondaryText, side: BorderSide( color: AppTheme.of(context) .secondaryText .withOpacity(0.5), ), padding: const EdgeInsets.symmetric(vertical: 14), shape: RoundedRectangleBorder( borderRadius: BorderRadius.circular(12), ), ), ), ), ], ), ], ), ), ), ), ], ); } Widget _buildCompactFormField({ required TextEditingController controller, required String label, required String hint, required IconData icon, String? Function(String?)? validator, int? maxLines, }) { return Container( margin: const EdgeInsets.only(bottom: 4), child: TextFormField( controller: controller, validator: validator, maxLines: maxLines ?? 1, style: TextStyle( color: AppTheme.of(context).primaryText, fontSize: 14, ), decoration: InputDecoration( labelText: label, labelStyle: TextStyle( color: AppTheme.of(context).secondaryText, fontSize: 14, ), hintText: hint, hintStyle: TextStyle( color: AppTheme.of(context).secondaryText.withOpacity(0.7), fontSize: 13, ), prefixIcon: Container( margin: const EdgeInsets.all(8), padding: const EdgeInsets.all(8), decoration: BoxDecoration( gradient: AppTheme.of(context).primaryGradient, borderRadius: BorderRadius.circular(10), boxShadow: [ BoxShadow( color: AppTheme.of(context).primaryColor.withOpacity(0.3), blurRadius: 8, offset: const Offset(0, 2), ), ], ), child: Icon( icon, color: Colors.white, size: 20, ), ), filled: true, fillColor: AppTheme.of(context).secondaryBackground, border: OutlineInputBorder( borderRadius: BorderRadius.circular(15), borderSide: BorderSide.none, ), enabledBorder: OutlineInputBorder( borderRadius: BorderRadius.circular(15), borderSide: BorderSide( color: AppTheme.of(context).primaryColor.withOpacity(0.2), width: 1, ), ), focusedBorder: OutlineInputBorder( borderRadius: BorderRadius.circular(15), borderSide: BorderSide( color: AppTheme.of(context).primaryColor, width: 2, ), ), errorBorder: OutlineInputBorder( borderRadius: BorderRadius.circular(15), borderSide: const BorderSide(color: Colors.red, width: 1), ), contentPadding: const EdgeInsets.symmetric(horizontal: 20, vertical: 16), ), ), ); } Widget _buildCategoriaDropdown() { return Container( margin: const EdgeInsets.only(bottom: 4), child: Theme( data: Theme.of(context).copyWith( canvasColor: AppTheme.of(context).secondaryBackground, shadowColor: AppTheme.of(context).primaryColor.withOpacity(0.3), ), child: DropdownButtonFormField( value: _categoriaSeleccionada, onChanged: (value) { if (value != null) { setState(() { _categoriaSeleccionada = value; }); } }, validator: (value) { if (value == null) { return 'Seleccione una categoría'; } return null; }, style: TextStyle( color: AppTheme.of(context).primaryText, fontSize: 14, ), icon: Icon( Icons.arrow_drop_down, color: AppTheme.of(context).primaryColor, ), iconSize: 24, isExpanded: true, // Esto soluciona el overflow menuMaxHeight: 300, decoration: InputDecoration( labelText: 'Categoría', labelStyle: TextStyle( color: AppTheme.of(context).secondaryText, fontSize: 14, ), prefixIcon: Container( margin: const EdgeInsets.all(8), padding: const EdgeInsets.all(8), decoration: BoxDecoration( gradient: AppTheme.of(context).primaryGradient, borderRadius: BorderRadius.circular(10), boxShadow: [ BoxShadow( color: AppTheme.of(context).primaryColor.withOpacity(0.3), blurRadius: 8, offset: const Offset(0, 2), ), ], ), child: const Icon( Icons.category_rounded, color: Colors.white, size: 20, ), ), filled: true, fillColor: AppTheme.of(context).secondaryBackground, border: OutlineInputBorder( borderRadius: BorderRadius.circular(15), borderSide: BorderSide.none, ), enabledBorder: OutlineInputBorder( borderRadius: BorderRadius.circular(15), borderSide: BorderSide( color: AppTheme.of(context).primaryColor.withOpacity(0.2), width: 1, ), ), focusedBorder: OutlineInputBorder( borderRadius: BorderRadius.circular(15), borderSide: BorderSide( color: AppTheme.of(context).primaryColor, width: 2, ), ), contentPadding: const EdgeInsets.symmetric(horizontal: 20, vertical: 16), ), dropdownColor: AppTheme.of(context).secondaryBackground, items: widget.provider.categorias.map((categoria) { return DropdownMenuItem( value: categoria.id, child: Container( constraints: const BoxConstraints(minHeight: 48), child: Row( children: [ Container( width: 8, height: 8, decoration: BoxDecoration( color: AppTheme.of(context).primaryColor, shape: BoxShape.circle, ), ), const SizedBox(width: 12), Expanded( child: Text( categoria.nombre, style: TextStyle( color: AppTheme.of(context).primaryText, fontWeight: FontWeight.w500, fontSize: 14, ), overflow: TextOverflow.ellipsis, ), ), ], ), ), ); }).toList(), ), ), ); } Widget _buildSwitchCard({ required String title, required String subtitle, required bool value, required Function(bool) onChanged, required IconData icon, required Color activeColor, }) { return Container( padding: const EdgeInsets.all(16), decoration: BoxDecoration( color: AppTheme.of(context).secondaryBackground, borderRadius: BorderRadius.circular(12), border: Border.all( color: value ? activeColor.withOpacity(0.3) : AppTheme.of(context).primaryColor.withOpacity(0.1), ), boxShadow: [ BoxShadow( color: value ? activeColor.withOpacity(0.1) : Colors.black.withOpacity(0.02), blurRadius: 8, offset: const Offset(0, 2), ), ], ), child: Row( children: [ Container( padding: const EdgeInsets.all(8), decoration: BoxDecoration( color: (value ? activeColor : Colors.grey).withOpacity(0.1), borderRadius: BorderRadius.circular(8), ), child: Icon( icon, color: value ? activeColor : Colors.grey, size: 20, ), ), const SizedBox(width: 12), Expanded( child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ Text( title, style: TextStyle( color: AppTheme.of(context).primaryText, fontSize: 14, fontWeight: FontWeight.bold, ), ), Text( subtitle, style: TextStyle( color: AppTheme.of(context).secondaryText, fontSize: 12, ), ), ], ), ), Switch( value: value, onChanged: onChanged, activeColor: activeColor, activeTrackColor: activeColor.withOpacity(0.3), inactiveThumbColor: Colors.grey, inactiveTrackColor: Colors.grey.withOpacity(0.3), ), ], ), ); } Widget _buildStatusIndicator(String text, IconData icon, Color color) { return Container( padding: const EdgeInsets.symmetric(horizontal: 12, vertical: 8), decoration: BoxDecoration( color: color.withOpacity(0.1), borderRadius: BorderRadius.circular(12), border: Border.all(color: color.withOpacity(0.3)), ), child: Row( mainAxisSize: MainAxisSize.min, children: [ Icon(icon, color: color, size: 16), const SizedBox(width: 6), Text( text, style: TextStyle( color: color, fontSize: 12, fontWeight: FontWeight.bold, ), ), ], ), ); } Future _guardarComponente() async { if (!_formKey.currentState!.validate()) { return; } if (_categoriaSeleccionada == null) { ScaffoldMessenger.of(context).showSnackBar( const SnackBar( content: Text('Debe seleccionar una categoría'), backgroundColor: Colors.red, ), ); return; } if (widget.provider.negocioSeleccionadoId == null) { ScaffoldMessenger.of(context).showSnackBar( const SnackBar( content: Text('Error: No se ha seleccionado un negocio'), backgroundColor: Colors.red, ), ); return; } setState(() { _isLoading = true; }); try { final success = await widget.provider.crearComponente( negocioId: widget.provider.negocioSeleccionadoId!, categoriaId: _categoriaSeleccionada!, nombre: _nombreController.text.trim(), descripcion: _descripcionController.text.trim().isNotEmpty ? _descripcionController.text.trim() : null, enUso: _enUso, activo: _activo, ubicacion: _ubicacionController.text.trim().isNotEmpty ? _ubicacionController.text.trim() : null, ); if (success) { if (mounted) { Navigator.of(context).pop(); ScaffoldMessenger.of(context).showSnackBar( SnackBar( content: Row( children: const [ Icon(Icons.check_circle, color: Colors.white), SizedBox(width: 12), Text( 'Componente creado exitosamente', style: TextStyle(fontWeight: FontWeight.w600), ), ], ), backgroundColor: Colors.green, behavior: SnackBarBehavior.floating, shape: RoundedRectangleBorder( borderRadius: BorderRadius.circular(10), ), ), ); } } else { if (mounted) { ScaffoldMessenger.of(context).showSnackBar( SnackBar( content: Row( children: const [ Icon(Icons.error, color: Colors.white), SizedBox(width: 12), Text( 'Error al crear el componente', style: TextStyle(fontWeight: FontWeight.w600), ), ], ), backgroundColor: Colors.red, behavior: SnackBarBehavior.floating, shape: RoundedRectangleBorder( borderRadius: BorderRadius.circular(10), ), ), ); } } } catch (e) { if (mounted) { ScaffoldMessenger.of(context).showSnackBar( SnackBar( content: Row( children: [ const Icon(Icons.warning, color: Colors.white), const SizedBox(width: 12), Expanded( child: Text( 'Error: $e', style: const TextStyle(fontWeight: FontWeight.w600), ), ), ], ), backgroundColor: Colors.red, behavior: SnackBarBehavior.floating, shape: RoundedRectangleBorder( borderRadius: BorderRadius.circular(10), ), ), ); } } finally { if (mounted) { setState(() { _isLoading = false; }); } } } }