import 'package:flutter/material.dart'; import '../models/models.dart'; import '../theme/app_theme.dart'; import '../widgets/widgets.dart' as w; import 'splash_screen.dart'; class AdminScreen extends StatefulWidget { final UserModel usuario; const AdminScreen({super.key, required this.usuario}); @override State createState() => _AdminScreenState(); } class _AdminScreenState extends State { int _currentTab = 1; int _selectedSection = 0; final List _usuarios = [ const UserModel( id: 'user-01', nombre: 'Ana', apellido: 'López', email: 'ana.lopez@rutaverde.com', telefono: '+52 461 111 2233', ), const UserModel( id: 'user-02', nombre: 'Luis', apellido: 'Ramírez', email: 'luis.ramirez@rutaverde.com', telefono: '+52 461 222 3344', ), ]; final List _conductores = [ const DriverModel( id: 'driver-01', nombre: 'María Pérez', telefono: '+52 461 333 4455', placa: 'TRD-451', rutaAsignada: 'Ruta Norte', ), const DriverModel( id: 'driver-02', nombre: 'Jorge Torres', telefono: '+52 461 444 5566', placa: 'TRD-752', rutaAsignada: 'Ruta Sur', ), ]; final List _camiones = [ const TruckModel( id: 'truck-01', placa: 'TRD-451', ruta: 'Ruta Norte', conductorId: 'driver-01', activo: true, ), const TruckModel( id: 'truck-02', placa: 'TRD-752', ruta: 'Ruta Sur', conductorId: 'driver-02', activo: false, ), ]; final List _rutas = [ 'Ruta Norte', 'Ruta Sur', ]; final List _reportes = [ ReportModel( id: 'report-01', truckId: 'truck-01', titulo: 'Reporte de ruta bloqueada', descripcion: 'El camión no puede continuar porque la ruta está obstruida.', fecha: DateTime.now().subtract(Duration(hours: 2)), estado: 'Pendiente', ), ReportModel( id: 'report-02', truckId: 'truck-01', titulo: 'Revisión mecánica urgente', descripcion: 'Se detectó una fuga de aceite en el motor.', fecha: DateTime.now().subtract(Duration(days: 1, hours: 3)), estado: 'En revisión', ), ReportModel( id: 'report-03', truckId: 'truck-02', titulo: 'Retraso en servicio', descripcion: 'El camión llegó tarde por un problema en la carretera.', fecha: DateTime.now().subtract(Duration(hours: 5)), estado: 'Resuelto', ), ]; void _selectSection(int index) { setState(() => _selectedSection = index); } void _onAddPressed() { switch (_selectedSection) { case 0: _showUserForm(); break; case 1: _showDriverForm(); break; case 2: _showTruckForm(); break; case 3: _showRouteForm(); break; } } void _showUserForm({UserModel? user}) { final nombre = TextEditingController(text: user?.nombre ?? ''); final apellido = TextEditingController(text: user?.apellido ?? ''); final email = TextEditingController(text: user?.email ?? ''); final telefono = TextEditingController(text: user?.telefono ?? ''); final formKey = GlobalKey(); showDialog( context: context, builder: (ctx) { return AlertDialog( title: Text(user == null ? 'Agregar usuario' : 'Editar usuario'), shape: RoundedRectangleBorder( borderRadius: BorderRadius.circular(AppTheme.radiusLg), ), content: Form( key: formKey, child: SingleChildScrollView( child: Column( mainAxisSize: MainAxisSize.min, children: [ _buildTextField('Nombre', nombre), const SizedBox(height: 12), _buildTextField('Apellido', apellido), const SizedBox(height: 12), _buildTextField('Email', email, keyboardType: TextInputType.emailAddress), const SizedBox(height: 12), _buildTextField('Teléfono', telefono, keyboardType: TextInputType.phone), ], ), ), ), actions: [ TextButton( onPressed: () => Navigator.pop(ctx), child: const Text('Cancelar'), ), ElevatedButton( onPressed: () { if (!formKey.currentState!.validate()) return; final nuevo = UserModel( id: user?.id ?? 'user-${DateTime.now().millisecondsSinceEpoch}', nombre: nombre.text.trim(), apellido: apellido.text.trim(), email: email.text.trim(), telefono: telefono.text.trim(), ); setState(() { if (user == null) { _usuarios.add(nuevo); } else { final index = _usuarios.indexWhere((u) => u.id == user.id); if (index != -1) { _usuarios[index] = nuevo; } } }); Navigator.pop(ctx); }, child: const Text('Guardar'), ), ], ); }, ); } void _showDriverForm({DriverModel? conductor}) { final nombre = TextEditingController(text: conductor?.nombre ?? ''); final telefono = TextEditingController(text: conductor?.telefono ?? ''); final placa = TextEditingController(text: conductor?.placa ?? ''); final ruta = TextEditingController(text: conductor?.rutaAsignada ?? ''); final formKey = GlobalKey(); showDialog( context: context, builder: (ctx) { return AlertDialog( title: Text(conductor == null ? 'Agregar conductor' : 'Editar conductor'), shape: RoundedRectangleBorder( borderRadius: BorderRadius.circular(AppTheme.radiusLg), ), content: Form( key: formKey, child: SingleChildScrollView( child: Column( mainAxisSize: MainAxisSize.min, children: [ _buildTextField('Nombre', nombre), const SizedBox(height: 12), _buildTextField('Teléfono', telefono, keyboardType: TextInputType.phone), const SizedBox(height: 12), _buildTextField('Placa', placa), const SizedBox(height: 12), _buildTextField('Ruta asignada', ruta), ], ), ), ), actions: [ TextButton( onPressed: () => Navigator.pop(ctx), child: const Text('Cancelar'), ), ElevatedButton( onPressed: () { if (!formKey.currentState!.validate()) return; final nuevo = DriverModel( id: conductor?.id ?? 'driver-${DateTime.now().millisecondsSinceEpoch}', nombre: nombre.text.trim(), telefono: telefono.text.trim(), placa: placa.text.trim(), rutaAsignada: ruta.text.trim(), ); setState(() { if (conductor == null) { _conductores.add(nuevo); } else { final index = _conductores.indexWhere((d) => d.id == conductor.id); if (index != -1) { _conductores[index] = nuevo; } } }); Navigator.pop(ctx); }, child: const Text('Guardar'), ), ], ); }, ); } void _showTruckForm({TruckModel? camion}) { final placa = TextEditingController(text: camion?.placa ?? ''); final ruta = TextEditingController(text: camion?.ruta ?? ''); var activo = camion?.activo ?? true; String conductorId = camion?.conductorId ?? _conductores.first.id; final formKey = GlobalKey(); showDialog( context: context, builder: (ctx) { return StatefulBuilder( builder: (ctx, setStateDialog) { return AlertDialog( title: Text(camion == null ? 'Agregar camión' : 'Editar camión'), shape: RoundedRectangleBorder( borderRadius: BorderRadius.circular(AppTheme.radiusLg), ), content: Form( key: formKey, child: SingleChildScrollView( child: Column( mainAxisSize: MainAxisSize.min, children: [ _buildTextField('Placa', placa), const SizedBox(height: 12), if (_rutas.isNotEmpty) DropdownButtonFormField( initialValue: _rutas.contains(ruta.text) ? ruta.text : _rutas.first, decoration: InputDecoration( labelText: 'Ruta', border: OutlineInputBorder( borderRadius: BorderRadius.circular(AppTheme.radiusMd), ), ), items: _rutas .map((rutaName) => DropdownMenuItem( value: rutaName, child: Text(rutaName), )) .toList(), onChanged: (value) { if (value != null) { ruta.text = value; } }, ) else _buildTextField('Ruta', ruta), const SizedBox(height: 12), DropdownButtonFormField( initialValue: conductorId, decoration: InputDecoration( labelText: 'Conductor', border: OutlineInputBorder( borderRadius: BorderRadius.circular(AppTheme.radiusMd), ), ), items: _conductores .map((d) => DropdownMenuItem( value: d.id, child: Text(d.nombre), )) .toList(), onChanged: (value) { if (value != null) { setStateDialog(() => conductorId = value); } }, ), const SizedBox(height: 16), Row( mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ const Text('Activo', style: TextStyle(fontWeight: FontWeight.w600)), Switch( value: activo, onChanged: (value) => setStateDialog(() => activo = value), ), ], ), ], ), ), ), actions: [ TextButton( onPressed: () => Navigator.pop(ctx), child: const Text('Cancelar'), ), ElevatedButton( onPressed: () { if (!formKey.currentState!.validate()) return; final nuevo = TruckModel( id: camion?.id ?? 'truck-${DateTime.now().millisecondsSinceEpoch}', placa: placa.text.trim(), ruta: ruta.text.trim(), conductorId: conductorId, activo: activo, ); setState(() { if (camion == null) { _camiones.add(nuevo); } else { final index = _camiones.indexWhere((t) => t.id == camion.id); if (index != -1) { _camiones[index] = nuevo; } } }); Navigator.pop(ctx); }, child: const Text('Guardar'), ), ], ); }, ); }, ); } void _showRouteForm({String? ruta}) { final nombreRuta = TextEditingController(text: ruta ?? ''); final formKey = GlobalKey(); showDialog( context: context, builder: (ctx) { return AlertDialog( title: Text(ruta == null ? 'Agregar ruta' : 'Editar ruta'), shape: RoundedRectangleBorder( borderRadius: BorderRadius.circular(AppTheme.radiusLg), ), content: Form( key: formKey, child: _buildTextField('Nombre de la ruta', nombreRuta), ), actions: [ TextButton( onPressed: () => Navigator.pop(ctx), child: const Text('Cancelar'), ), ElevatedButton( onPressed: () { if (!formKey.currentState!.validate()) return; final nuevoNombre = nombreRuta.text.trim(); setState(() { if (ruta == null) { _rutas.add(nuevoNombre); } else { final index = _rutas.indexOf(ruta); if (index != -1) { _rutas[index] = nuevoNombre; for (var i = 0; i < _camiones.length; i++) { if (_camiones[i].ruta == ruta) { _camiones[i] = TruckModel( id: _camiones[i].id, placa: _camiones[i].placa, ruta: nuevoNombre, conductorId: _camiones[i].conductorId, activo: _camiones[i].activo, ); } } for (var i = 0; i < _conductores.length; i++) { if (_conductores[i].rutaAsignada == ruta) { _conductores[i] = DriverModel( id: _conductores[i].id, nombre: _conductores[i].nombre, telefono: _conductores[i].telefono, placa: _conductores[i].placa, rutaAsignada: nuevoNombre, ); } } } } }); Navigator.pop(ctx); }, child: const Text('Guardar'), ), ], ); }, ); } void _showReportForm({ReportModel? reporte}) { final titulo = TextEditingController(text: reporte?.titulo ?? ''); final descripcion = TextEditingController(text: reporte?.descripcion ?? ''); String selectedTruckId = reporte?.truckId ?? _camiones.first.id; final formKey = GlobalKey(); showDialog( context: context, builder: (ctx) { return StatefulBuilder( builder: (ctx, setStateDialog) { return AlertDialog( title: Text(reporte == null ? 'Agregar reporte' : 'Editar reporte'), shape: RoundedRectangleBorder( borderRadius: BorderRadius.circular(AppTheme.radiusLg), ), content: Form( key: formKey, child: SingleChildScrollView( child: Column( mainAxisSize: MainAxisSize.min, children: [ DropdownButtonFormField( initialValue: selectedTruckId, decoration: InputDecoration( labelText: 'Unidad', border: OutlineInputBorder( borderRadius: BorderRadius.circular(AppTheme.radiusMd), ), ), items: _camiones .map((truck) => DropdownMenuItem( value: truck.id, child: Text('${truck.placa} · ${truck.ruta}'), )) .toList(), onChanged: (value) { if (value != null) { setStateDialog(() => selectedTruckId = value); } }, ), const SizedBox(height: 12), _buildTextField('Título', titulo), const SizedBox(height: 12), _buildTextField('Descripción', descripcion), ], ), ), ), actions: [ TextButton( onPressed: () => Navigator.pop(ctx), child: const Text('Cancelar'), ), ElevatedButton( onPressed: () { if (!formKey.currentState!.validate()) return; final nuevo = ReportModel( id: reporte?.id ?? 'report-${DateTime.now().millisecondsSinceEpoch}', truckId: selectedTruckId, titulo: titulo.text.trim(), descripcion: descripcion.text.trim(), fecha: DateTime.now(), ); setState(() { if (reporte == null) { _reportes.add(nuevo); } else { final index = _reportes.indexWhere((r) => r.id == reporte.id); if (index != -1) { _reportes[index] = nuevo; } } }); Navigator.pop(ctx); }, child: const Text('Guardar'), ), ], ); }, ); }, ); } Widget _buildReportSection() { final header = Padding( padding: const EdgeInsets.symmetric(horizontal: 4), child: Row( mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ const Text( 'Reportes de unidades', style: TextStyle(fontSize: 16, fontWeight: FontWeight.w700), ), TextButton.icon( icon: const Icon(Icons.add), label: const Text('Agregar reporte'), onPressed: _showReportForm, ), ], ), ); if (_camiones.isEmpty) { return Column( children: [ header, const SizedBox(height: 10), const Expanded(child: Center(child: Text('No hay unidades registradas.'))), ], ); } final Map> reportesPorUnidad = { for (var camion in _camiones) camion.id: [], }; for (var reporte in _reportes) { reportesPorUnidad[reporte.truckId]?.add(reporte); } final unidadesOrdenadas = List.from(_camiones) ..sort((a, b) => a.placa.compareTo(b.placa)); return Column( children: [ header, const SizedBox(height: 10), Expanded( child: ListView( padding: const EdgeInsets.only(bottom: 16), children: unidadesOrdenadas.map((camion) { final reportes = reportesPorUnidad[camion.id] ?? []; reportes.sort((a, b) => b.fecha.compareTo(a.fecha)); return w.AppCard( padding: const EdgeInsets.all(16), child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ Row( children: [ Expanded( child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ Text(camion.placa, style: const TextStyle( fontSize: 15, fontWeight: FontWeight.w700, )), const SizedBox(height: 6), Text(camion.ruta, style: const TextStyle(color: AppTheme.textSecondary)), ], ), ), w.StatusBadge.gray('${reportes.length} reporte(s)'), ], ), const SizedBox(height: 12), if (reportes.isEmpty) const Text('No hay reportes para esta unidad.', style: TextStyle(color: AppTheme.textSecondary)) else Column( children: reportes .map((reporte) => Padding( padding: const EdgeInsets.only(top: 12), child: Container( decoration: BoxDecoration( color: AppTheme.surface, borderRadius: BorderRadius.circular(AppTheme.radiusMd), border: Border.all(color: AppTheme.border), ), padding: const EdgeInsets.all(12), child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ Row( children: [ Expanded( child: Text(reporte.titulo, style: const TextStyle( fontSize: 14, fontWeight: FontWeight.w700, )), ), Text(reporte.fechaFormateada, style: const TextStyle( fontSize: 12, color: AppTheme.textSecondary)), ], ), const SizedBox(height: 6), Text(reporte.descripcion, style: const TextStyle(color: AppTheme.textSecondary)), const SizedBox(height: 8), Align( alignment: Alignment.centerRight, child: w.StatusBadge.amber(reporte.estado), ), ], ), ), )) .toList(), ), ], ), ); }).toList(), ), ), ], ); } Widget _buildTextField(String label, TextEditingController controller, {TextInputType keyboardType = TextInputType.text}) { return TextFormField( controller: controller, keyboardType: keyboardType, validator: (value) { if (value == null || value.trim().isEmpty) { return 'Debe completar este campo'; } return null; }, decoration: InputDecoration( labelText: label, border: OutlineInputBorder( borderRadius: BorderRadius.circular(AppTheme.radiusMd), ), ), ); } void _confirmDelete(T item, List lista, String tipo) { showDialog( context: context, builder: (ctx) { return AlertDialog( title: Text('Eliminar $tipo'), content: Text('¿Seguro que deseas eliminar este $tipo?'), actions: [ TextButton( onPressed: () => Navigator.pop(ctx), child: const Text('Cancelar'), ), TextButton( onPressed: () { setState(() { lista.remove(item); if (item is String && identical(lista, _rutas)) { for (var i = 0; i < _camiones.length; i++) { if (_camiones[i].ruta == item) { _camiones[i] = TruckModel( id: _camiones[i].id, placa: _camiones[i].placa, ruta: '', conductorId: _camiones[i].conductorId, activo: _camiones[i].activo, ); } } for (var i = 0; i < _conductores.length; i++) { if (_conductores[i].rutaAsignada == item) { _conductores[i] = DriverModel( id: _conductores[i].id, nombre: _conductores[i].nombre, telefono: _conductores[i].telefono, placa: _conductores[i].placa, rutaAsignada: '', ); } } } }); Navigator.pop(ctx); }, style: TextButton.styleFrom(foregroundColor: AppTheme.danger), child: const Text('Eliminar'), ), ], ); }, ); } @override Widget build(BuildContext context) { if (!widget.usuario.isAdmin) { return Scaffold( backgroundColor: AppTheme.background, appBar: AppBar(title: const Text('Acceso denegado')), body: Center( child: Padding( padding: const EdgeInsets.symmetric(horizontal: 24), child: Column( mainAxisSize: MainAxisSize.min, children: [ const Text( 'Este panel solo está disponible para administradores.', textAlign: TextAlign.center, style: TextStyle(fontSize: 16, color: AppTheme.textPrimary), ), const SizedBox(height: 18), ElevatedButton( onPressed: () { Navigator.pushAndRemoveUntil( context, MaterialPageRoute(builder: (_) => const SplashScreen()), (_) => false, ); }, child: const Text('Volver al inicio'), ), ], ), ), ), ); } return Scaffold( backgroundColor: AppTheme.background, appBar: AppBar( title: Text( _currentTab == 0 ? 'Mi perfil' : _currentTab == 1 ? 'Panel administrador' : 'Reportes por unidad', ), actions: _currentTab == 1 ? [ IconButton( icon: const Icon(Icons.add), onPressed: _onAddPressed, tooltip: 'Agregar', ), ] : _currentTab == 2 ? [ IconButton( icon: const Icon(Icons.add), onPressed: _showReportForm, tooltip: 'Agregar reporte', ), ] : null, ), body: IndexedStack( index: _currentTab, children: [ _buildAdminProfile(), _buildAdminBody(), _buildReportSection(), ], ), bottomNavigationBar: BottomNavigationBar( currentIndex: _currentTab, onTap: (value) => setState(() => _currentTab = value), items: const [ BottomNavigationBarItem( icon: Icon(Icons.person_outline), label: 'Perfil', ), BottomNavigationBarItem( icon: Icon(Icons.admin_panel_settings_outlined), label: 'Admin', ), BottomNavigationBarItem( icon: Icon(Icons.report_problem_outlined), label: 'Reportes', ), ], ), ); } Widget _buildAdminBody() { return Column( children: [ Padding( padding: const EdgeInsets.all(16), child: Row( mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ _buildSectionButton('Usuarios', 0), _buildSectionButton('Conductores', 1), _buildSectionButton('Camiones', 2), _buildSectionButton('Rutas', 3), ], ), ), Expanded( child: Padding( padding: const EdgeInsets.symmetric(horizontal: 16), child: _buildCurrentSection(), ), ), ], ); } Widget _buildAdminProfile() { return SingleChildScrollView( padding: const EdgeInsets.all(16), child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ w.AppCard( child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ Row( children: [ Container( width: 56, height: 56, decoration: BoxDecoration( color: AppTheme.primaryLight, shape: BoxShape.circle, ), child: Center( child: Text( widget.usuario.iniciales, style: const TextStyle( fontSize: 20, fontWeight: FontWeight.w700, color: AppTheme.primaryDark, ), ), ), ), const SizedBox(width: 16), Expanded( child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ Text(widget.usuario.nombreCompleto, style: const TextStyle( fontSize: 18, fontWeight: FontWeight.w700, )), const SizedBox(height: 6), Text(widget.usuario.email, style: const TextStyle(color: AppTheme.textSecondary)), const SizedBox(height: 2), Text(widget.usuario.telefono, style: const TextStyle(color: AppTheme.textSecondary)), ], ), ), ], ), const SizedBox(height: 16), Wrap( spacing: 8, children: [ w.StatusBadge.green('Administrador'), w.StatusBadge.gray(widget.usuario.role == UserRole.admin ? 'Admin' : 'Usuario'), ], ), ], ), ), const SizedBox(height: 20), w.SectionTitle(title: 'Cuenta'), w.MenuTile( icon: Icons.person_outline, title: 'Editar perfil', subtitle: widget.usuario.nombreCompleto, onTap: () {}, ), w.MenuTile( icon: Icons.email_outlined, title: 'Email', subtitle: widget.usuario.email, onTap: () {}, ), w.MenuTile( icon: Icons.phone_outlined, title: 'Teléfono', subtitle: widget.usuario.telefono, onTap: () {}, ), ], ), ); } Widget _buildSectionButton(String label, int index) { final selected = _selectedSection == index; return Expanded( child: Padding( padding: const EdgeInsets.symmetric(horizontal: 4), child: ElevatedButton( onPressed: () => _selectSection(index), style: ElevatedButton.styleFrom( backgroundColor: selected ? AppTheme.primary : AppTheme.surface, foregroundColor: selected ? Colors.white : AppTheme.textPrimary, padding: const EdgeInsets.symmetric(vertical: 12), shape: RoundedRectangleBorder( borderRadius: BorderRadius.circular(AppTheme.radiusMd), ), elevation: selected ? 2 : 0, ), child: Text(label, textAlign: TextAlign.center), ), ), ); } Widget _buildCurrentSection() { switch (_selectedSection) { case 0: return _buildUsuarioSection(); case 1: return _buildDriverSection(); case 2: return _buildTruckSection(); case 3: return _buildRouteSection(); default: return _buildReportSection(); } } Widget _buildRouteSection() { if (_rutas.isEmpty) { return Center( child: Column( mainAxisSize: MainAxisSize.min, children: [ const Text('No hay rutas registradas.'), const SizedBox(height: 12), ElevatedButton( onPressed: _showRouteForm, child: const Text('Agregar ruta'), ), ], ), ); } return ListView.builder( padding: const EdgeInsets.only(bottom: 16), itemCount: _rutas.length, itemBuilder: (context, index) { final ruta = _rutas[index]; final asignados = _camiones.where((camion) => camion.ruta == ruta).length; return w.AppCard( padding: const EdgeInsets.all(16), child: Row( children: [ Expanded( child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ Text(ruta, style: const TextStyle( fontSize: 15, fontWeight: FontWeight.w700, )), const SizedBox(height: 6), Text('$asignados camión(es) asignado(s)', style: const TextStyle(color: AppTheme.textSecondary)), ], ), ), IconButton( icon: const Icon(Icons.edit_outlined), onPressed: () => _showRouteForm(ruta: ruta), ), IconButton( icon: const Icon(Icons.delete_outline, color: AppTheme.danger), onPressed: () { _confirmDelete(ruta, _rutas, 'ruta'); }, ), ], ), ); }, ); } Widget _buildUsuarioSection() { if (_usuarios.isEmpty) { return const Center(child: Text('No hay usuarios registrados.')); } return ListView.builder( padding: const EdgeInsets.only(bottom: 16), itemCount: _usuarios.length, itemBuilder: (context, index) { final usuario = _usuarios[index]; return w.AppCard( padding: const EdgeInsets.all(16), child: Row( children: [ Expanded( child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ Text(usuario.nombreCompleto, style: const TextStyle( fontSize: 15, fontWeight: FontWeight.w700, )), const SizedBox(height: 6), Text(usuario.email, style: const TextStyle(color: AppTheme.textSecondary)), const SizedBox(height: 2), Text(usuario.telefono, style: const TextStyle(color: AppTheme.textSecondary)), ], ), ), IconButton( icon: const Icon(Icons.edit_outlined), onPressed: () => _showUserForm(user: usuario), ), IconButton( icon: const Icon(Icons.delete_outline, color: AppTheme.danger), onPressed: () => _confirmDelete(usuario, _usuarios, 'usuario'), ), ], ), ); }, ); } Widget _buildDriverSection() { if (_conductores.isEmpty) { return const Center(child: Text('No hay conductores registrados.')); } return ListView.builder( padding: const EdgeInsets.only(bottom: 16), itemCount: _conductores.length, itemBuilder: (context, index) { final conductor = _conductores[index]; return w.AppCard( padding: const EdgeInsets.all(16), child: Row( children: [ Expanded( child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ Text(conductor.nombre, style: const TextStyle( fontSize: 15, fontWeight: FontWeight.w700, )), const SizedBox(height: 6), Text(conductor.telefono, style: const TextStyle(color: AppTheme.textSecondary)), const SizedBox(height: 2), Text('${conductor.placa} · ${conductor.rutaAsignada}', style: const TextStyle(color: AppTheme.textSecondary)), ], ), ), IconButton( icon: const Icon(Icons.edit_outlined), onPressed: () => _showDriverForm(conductor: conductor), ), IconButton( icon: const Icon(Icons.delete_outline, color: AppTheme.danger), onPressed: () => _confirmDelete(conductor, _conductores, 'conductor'), ), ], ), ); }, ); } Widget _buildTruckSection() { if (_camiones.isEmpty) { return const Center(child: Text('No hay camiones registrados.')); } return ListView.builder( padding: const EdgeInsets.only(bottom: 16), itemCount: _camiones.length, itemBuilder: (context, index) { final camion = _camiones[index]; final conductor = _conductores.firstWhere( (d) => d.id == camion.conductorId, orElse: () => const DriverModel( id: 'none', nombre: 'Sin conductor', telefono: '-', placa: '-', rutaAsignada: '-', ), ); return w.AppCard( padding: const EdgeInsets.all(16), child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ Row( children: [ Expanded( child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ Text(camion.placa, style: const TextStyle( fontSize: 15, fontWeight: FontWeight.w700, )), const SizedBox(height: 6), Text(camion.ruta, style: const TextStyle(color: AppTheme.textSecondary)), ], ), ), w.StatusBadge.gray(camion.activo ? 'Activo' : 'Inactivo'), ], ), const SizedBox(height: 10), Text('Conductor: ${conductor.nombre}', style: const TextStyle(color: AppTheme.textSecondary)), const SizedBox(height: 8), Row( children: [ TextButton.icon( icon: const Icon(Icons.edit_outlined), label: const Text('Editar'), onPressed: () => _showTruckForm(camion: camion), ), const SizedBox(width: 8), TextButton.icon( icon: const Icon(Icons.delete_outline, color: AppTheme.danger), label: const Text('Eliminar', style: TextStyle(color: AppTheme.danger)), onPressed: () => _confirmDelete(camion, _camiones, 'camión'), ), ], ), ], ), ); }, ); } }