import 'package:flutter/material.dart'; import 'package:provider/provider.dart'; import 'package:share_plus/share_plus.dart'; import '../../core/app_colors.dart'; import '../../database/db_helper.dart'; import '../../models/models.dart'; import '../../services/auth_service.dart'; class CollectionCalendarScreen extends StatefulWidget { const CollectionCalendarScreen({super.key}); @override State createState() => _CollectionCalendarScreenState(); } class _CollectionCalendarScreenState extends State { RouteDefinitionModel? _routeDef; List _myReviews = []; bool _loading = true; @override void initState() { super.initState(); _load(); } Future _load() async { final auth = context.read(); final dom = auth.primaryDomicilio; if (dom != null) { final rd = await DbHelper.getRouteDefinitionById(dom.routeId); final rv = await DbHelper.getAllReviews(); final mine = rv.where((r) => r.userId == auth.currentUser?.id).toList(); if (mounted) setState(() { _routeDef = rd; _myReviews = mine; _loading = false; }); } else { if (mounted) setState(() => _loading = false); } } void _shareSchedule() { final auth = context.read(); final dom = auth.primaryDomicilio; if (dom == null) return; final rd = _routeDef; final diasStr = rd?.dias.map(_diaLabel).join(', ') ?? 'Lunes, Miércoles y Viernes'; final horario = rd != null ? '${rd.horaInicio}–${rd.horaFin}' : dom.horarioEstimado; Share.share( '🗑️ Horario de recolección de basura\n' '📍 Colonia: ${dom.colonia}\n' '📅 Días: $diasStr\n' '⏰ Horario: $horario\n' '🚛 Ruta: ${dom.routeId}\n\n' 'Descarga Celaya Limpia para recibir avisos en tiempo real.', ); } String _diaLabel(String d) { const m = {'LUNES':'Lu','MARTES':'Ma','MIERCOLES':'Mi', 'JUEVES':'Ju','VIERNES':'Vi','SABADO':'Sa','DOMINGO':'Do'}; return m[d] ?? d; } // Días del mes actual con marcas de recolección List _buildCalendar() { final now = DateTime.now(); final first = DateTime(now.year, now.month, 1); final days = DateTime(now.year, now.month + 1, 0).day; final dias = _routeDef?.dias ?? []; const weekDays = ['LUNES','MARTES','MIERCOLES','JUEVES','VIERNES','SABADO','DOMINGO']; final monthName = ['','Enero','Febrero','Marzo','Abril','Mayo','Junio', 'Julio','Agosto','Septiembre','Octubre','Noviembre','Diciembre'][now.month]; return [ Padding( padding: const EdgeInsets.symmetric(horizontal: 4), child: Text('$monthName ${now.year}', style: const TextStyle(fontWeight: FontWeight.bold, fontSize: 16, color: AppColors.guindaPrimary)), ), const SizedBox(height: 8), // Cabeceras días Row(children: ['Lu','Ma','Mi','Ju','Vi','Sa','Do'].map((d) => Expanded(child: Center(child: Text(d, style: const TextStyle( fontWeight: FontWeight.bold, fontSize: 11, color: AppColors.grisTexto))))).toList()), const SizedBox(height: 4), // Grilla de días GridView.builder( shrinkWrap: true, physics: const NeverScrollableScrollPhysics(), gridDelegate: const SliverGridDelegateWithFixedCrossAxisCount( crossAxisCount: 7, childAspectRatio: 1), itemCount: (first.weekday - 1) + days, itemBuilder: (_, i) { if (i < first.weekday - 1) return const SizedBox(); final day = i - (first.weekday - 1) + 1; final date = DateTime(now.year, now.month, day); final diaSem = weekDays[date.weekday - 1]; final isCollection = dias.contains(diaSem); final isToday = day == now.day; final isPast = date.isBefore(DateTime(now.year, now.month, now.day)); return Container( margin: const EdgeInsets.all(2), decoration: BoxDecoration( color: isCollection ? (isPast ? AppColors.guindaPrimary.withOpacity(0.4) : AppColors.guindaPrimary) : (isToday ? Colors.grey.shade200 : null), shape: BoxShape.circle, border: isToday ? Border.all(color: AppColors.dorado, width: 2) : null, ), child: Stack(alignment: Alignment.center, children: [ Text('$day', style: TextStyle( fontSize: 12, fontWeight: isToday ? FontWeight.bold : FontWeight.normal, color: isCollection ? Colors.white : AppColors.negroTexto, )), if (isCollection) Positioned(bottom: 2, child: Container( width: 4, height: 4, decoration: const BoxDecoration(color: AppColors.dorado, shape: BoxShape.circle), )), ]), ); }, ), ]; } @override Widget build(BuildContext context) { final auth = context.read(); final dom = auth.primaryDomicilio; return Scaffold( backgroundColor: AppColors.grisFondo, appBar: AppBar( backgroundColor: AppColors.guindaPrimary, foregroundColor: Colors.white, title: const Text('Calendario de Recoleccion'), bottom: PreferredSize(preferredSize: const Size.fromHeight(4), child: Container(height: 4, color: AppColors.dorado)), actions: [ IconButton(icon: const Icon(Icons.share), tooltip: 'Compartir horario', onPressed: _shareSchedule), ], ), body: _loading ? const Center(child: CircularProgressIndicator()) : SingleChildScrollView(padding: const EdgeInsets.all(16), child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ // Info de la ruta if (dom != null) Card(child: Padding(padding: const EdgeInsets.all(14), child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ const Row(children: [ Icon(Icons.local_shipping, color: AppColors.guindaPrimary, size: 18), SizedBox(width: 6), Text('Tu servicio de recoleccion', style: TextStyle( fontWeight: FontWeight.bold, color: AppColors.guindaPrimary)), ]), const Divider(), Text('Colonia: ${dom.colonia}', style: const TextStyle(fontWeight: FontWeight.w600, fontSize: 13)), Text('Ruta: ${dom.routeId}', style: const TextStyle(color: AppColors.grisTexto, fontSize: 12)), if (_routeDef != null) ...[ Text('Dias: ${_routeDef!.dias.map(_diaLabel).join(" · ")}', style: const TextStyle(fontSize: 12)), Text('Horario: ${_routeDef!.horaInicio} - ${_routeDef!.horaFin}', style: const TextStyle(fontSize: 12)), ] else Text(dom.horarioEstimado, style: const TextStyle(color: AppColors.grisTexto, fontSize: 12)), ]))), const SizedBox(height: 16), // Leyenda Row(children: [ _Legend(color: AppColors.guindaPrimary, label: 'Dia de recoleccion'), const SizedBox(width: 12), _Legend(color: AppColors.dorado, label: 'Punto en dia activo'), const SizedBox(width: 12), _Legend(color: Colors.grey.shade200, label: 'Hoy'), ]), const SizedBox(height: 12), // Calendario Card(child: Padding(padding: const EdgeInsets.all(14), child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: _buildCalendar()))), const SizedBox(height: 16), // Consejos semanales Card(color: Colors.blue.shade50, shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(10), side: BorderSide(color: Colors.blue.shade200)), child: Padding(padding: const EdgeInsets.all(14), child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ const Row(children: [ Icon(Icons.tips_and_updates, color: AppColors.azulInfo), SizedBox(width: 8), Text('Consejo de la semana', style: TextStyle( fontWeight: FontWeight.bold, color: AppColors.azulInfo, fontSize: 14)), ]), const SizedBox(height: 8), Text(_weeklyTip(), style: const TextStyle(fontSize: 13, color: AppColors.negroTexto)), ])), ), const SizedBox(height: 16), // Mis calificaciones if (_myReviews.isNotEmpty) ...[ const Text('Mis calificaciones', style: TextStyle( fontWeight: FontWeight.bold, fontSize: 15, color: AppColors.guindaPrimary)), const SizedBox(height: 8), ..._myReviews.take(3).map((r) => Card(margin: const EdgeInsets.only(bottom: 8), child: ListTile(dense: true, leading: CircleAvatar(backgroundColor: Colors.amber.shade100, child: Text('${r.estrellas}', style: const TextStyle( fontWeight: FontWeight.bold, color: Colors.amber))), title: Text(r.colonia, style: const TextStyle(fontSize: 12, fontWeight: FontWeight.w600)), subtitle: Text(r.comentario, maxLines: 1, overflow: TextOverflow.ellipsis, style: const TextStyle(fontSize: 11)), trailing: Text( '${DateTime.tryParse(r.fecha)?.day}/${DateTime.tryParse(r.fecha)?.month}', style: const TextStyle(fontSize: 10, color: AppColors.grisTexto)), ))), ], const SizedBox(height: 30), ])), ); } String _weeklyTip() { final tips = [ 'Separa tus residuos en organicos (restos de comida) e inorganicos (plasticos, metales). Facilita el reciclaje y reduce la contaminacion.', 'Coloca tus bolsas en la acera SOLO cuando recibas el aviso de 15 minutos. Sacarlas antes atrae fauna nociva.', 'El reciclaje de 1 tonelada de papel salva 17 arboles. Dobla tus cajas y periodicos antes de depositarlos.', 'Los aceites usados de cocina NO van a la basura. Llevalos a los puntos de acopio del municipio.', 'Composta tus restos organicos si tienes jardin. Reduce hasta un 40% tu basura y mejora tu suelo.', 'Las pilas y baterias son residuos peligrosos. Depositalas en los contenedores especiales de tiendas.', 'Un celular viejo contiene oro, plata y cobre. Llevalo a un punto RAEE para su reciclaje correcto.', ]; return tips[DateTime.now().weekday % tips.length]; } } class _Legend extends StatelessWidget { final Color color; final String label; const _Legend({required this.color, required this.label}); @override Widget build(BuildContext context) => Row(mainAxisSize: MainAxisSize.min, children: [ Container(width: 12, height: 12, decoration: BoxDecoration(color: color, shape: BoxShape.circle)), const SizedBox(width: 4), Text(label, style: const TextStyle(fontSize: 10, color: AppColors.grisTexto)), ]); }