modificaciones en el sistema

This commit is contained in:
Kimberly
2026-05-23 05:54:34 -06:00
parent 32fe398f4b
commit cca83f0012
8 changed files with 867 additions and 533 deletions

View File

@@ -1,112 +1,194 @@
import 'package:flutter/material.dart';
import 'camion_estado.dart';
class TarjetaEtaWidget extends StatelessWidget {
final String horaInicio;
final String horaFin;
final int minutosRestantes;
final String estadoCamion;
class TarjetaEtaWidget extends StatefulWidget {
const TarjetaEtaWidget({super.key});
const TarjetaEtaWidget({
super.key,
required this.horaInicio,
required this.horaFin,
required this.minutosRestantes,
required this.estadoCamion,
});
@override
State<TarjetaEtaWidget> createState() => _TarjetaEtaWidgetState();
}
Color _obtenerColorEstado() {
return estadoCamion == 'retrasado' ? Colors.amber[700]! : Colors.green[700]!;
class _TarjetaEtaWidgetState extends State<TarjetaEtaWidget> {
@override
void initState() {
super.initState();
// Escucha cambios del estado global
camionEstado.addListener(_actualizar);
}
String _generarMensajeAccion() {
if (estadoCamion == 'retrasado') {
return 'El servicio presenta un ligero retraso por tráfico.';
}
if (minutosRestantes <= 5) {
return '¡Saca tus residuos clasificados ahora mismo!';
}
return 'Prepara tus bolsas de residuos orgánicos e inorgánicos.';
void _actualizar() {
if (mounted) setState(() {});
}
@override
void dispose() {
camionEstado.removeListener(_actualizar);
super.dispose();
}
// Color según etapa
Color _colorEstado() {
final id = camionEstado.positionId;
if (id <= 1) return Colors.grey;
if (id <= 3) return Colors.blue;
if (id <= 5) return Colors.orange;
if (id == 6) return Colors.green;
return Colors.grey;
}
// Icono según etapa
IconData _iconoEstado() {
final id = camionEstado.positionId;
if (id <= 1) return Icons.schedule;
if (id <= 3) return Icons.local_shipping;
if (id <= 5) return Icons.directions_run;
if (id == 6) return Icons.check_circle;
return Icons.done_all;
}
@override
Widget build(BuildContext context) {
final Color colorTema = _obtenerColorEstado();
final id = camionEstado.positionId;
final eta = CamionEstado.etaInfo[id]!;
final etapa = CamionEstado.etapas[id]!;
final color = _colorEstado();
final minutos = eta['minutos'] as int;
final label = eta['label'] as String;
return Card(
elevation: 3,
shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(20)),
child: Container(
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(20),
gradient: LinearGradient(
begin: Alignment.topLeft,
end: Alignment.bottomRight,
colors: [
colorTema.withOpacity(0.05),
colorTema.withOpacity(0.12),
],
),
),
child: Padding(
padding: const EdgeInsets.all(16.0),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Row(
children: [
Icon(Icons.local_shipping_rounded, color: colorTema, size: 24),
const SizedBox(width: 8),
Text(
estadoCamion == 'retrasado' ? 'Estado: Demorado' : 'Ruta en Progreso',
style: TextStyle(
color: colorTema,
fontWeight: FontWeight.bold,
fontSize: 13,
),
),
const Spacer(),
Container(
width: 8,
height: 8,
decoration: BoxDecoration(color: colorTema, shape: BoxShape.circle),
),
],
elevation: 5,
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(20),
),
child: Padding(
padding: const EdgeInsets.all(20),
child: Column(
children: [
// Icono animado según estado
Icon(
_iconoEstado(),
size: 80,
color: color,
),
const SizedBox(height: 12),
const Text(
'Camión de Recolección',
style: TextStyle(
fontSize: 22,
fontWeight: FontWeight.bold,
),
const SizedBox(height: 12),
),
const SizedBox(height: 8),
// Etapa actual
Text(
etapa,
textAlign: TextAlign.center,
style: TextStyle(
fontSize: 15,
color: color,
fontWeight: FontWeight.w600,
),
),
const SizedBox(height: 8),
// Hora estimada
if (id > 1 && id < 7)
Text(
'Llega en aproximadamente $minutosRestantes minutos',
style: Theme.of(context).textTheme.titleMedium?.copyWith(
'Llega entre ${eta['horaInicio']} y ${eta['horaFin']}',
textAlign: TextAlign.center,
style: const TextStyle(fontSize: 14, color: Colors.grey),
),
const SizedBox(height: 16),
// Barra de progreso
ClipRRect(
borderRadius: BorderRadius.circular(8),
child: LinearProgressIndicator(
value: id / 8,
minHeight: 10,
backgroundColor: Colors.grey[200],
valueColor: AlwaysStoppedAnimation<Color>(color),
),
),
const SizedBox(height: 12),
// Badge de minutos
Container(
padding: const EdgeInsets.symmetric(
horizontal: 20,
vertical: 12,
),
decoration: BoxDecoration(
color: color.withOpacity(0.1),
borderRadius: BorderRadius.circular(15),
border: Border.all(color: color.withOpacity(0.3)),
),
child: Text(
minutos > 0
? 'Llega en aproximadamente $minutos minutos'
: label,
textAlign: TextAlign.center,
style: TextStyle(
color: color,
fontWeight: FontWeight.bold,
color: Colors.grey[800],
fontSize: 14,
),
),
const SizedBox(height: 4),
Text(
'El camión llegará a tu zona entre las $horaInicio y las $horaFin.',
style: TextStyle(fontSize: 14, color: Colors.grey[700]),
),
const Padding(
padding: EdgeInsets.symmetric(vertical: 10.0),
child: Divider(color: Colors.black),
),
Row(
children: [
Icon(Icons.info_outline_rounded, color: colorTema, size: 18),
const SizedBox(width: 6),
Expanded(
child: Text(
_generarMensajeAccion(),
style: TextStyle(
color: colorTema,
fontWeight: FontWeight.w600,
fontSize: 12,
),
const SizedBox(height: 16),
// Botones iniciar / reiniciar
Row(
children: [
Expanded(
child: ElevatedButton.icon(
style: ElevatedButton.styleFrom(
backgroundColor: camionEstado.corriendo
? Colors.grey
: Colors.green,
foregroundColor: Colors.white,
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(12),
),
),
onPressed: camionEstado.corriendo
? null
: camionEstado.iniciarTimer,
icon: const Icon(Icons.play_arrow),
label: const Text('Iniciar'),
),
],
),
],
),
),
const SizedBox(width: 12),
Expanded(
child: OutlinedButton.icon(
style: OutlinedButton.styleFrom(
foregroundColor: Colors.green,
side: const BorderSide(color: Colors.green),
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(12),
),
),
onPressed: camionEstado.reiniciar,
icon: const Icon(Icons.refresh),
label: const Text('Reiniciar'),
),
),
],
),
],
),
),
);