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, ), ]; void _selectSection(int index) { setState(() => _selectedSection = index); } void _onAddPressed() { switch (_selectedSection) { case 0: _showUserForm(); break; case 1: _showDriverForm(); break; case 2: _showTruckForm(); 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), _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'), ), ], ); }, ); }, ); } 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)); 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' : 'Panel administrador'), actions: _currentTab == 1 ? [ IconButton( icon: const Icon(Icons.add), onPressed: _onAddPressed, tooltip: 'Agregar', ), ] : null, ), body: IndexedStack( index: _currentTab, children: [ _buildAdminProfile(), _buildAdminBody(), ], ), 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', ), ], ), ); } 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), ], ), ), 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(); default: return _buildTruckSection(); } } 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'), ), ], ), ], ), ); }, ); } }