import 'package:flutter/material.dart'; import 'package:provider/provider.dart'; import 'package:intl/intl.dart'; import 'package:table_calendar/table_calendar.dart'; import '../providers/factura_provider.dart'; import '../providers/servicio_provider.dart'; import '../providers/configuracion_provider.dart'; class CalendarioScreen extends StatefulWidget { const CalendarioScreen({super.key}); @override State createState() => _CalendarioScreenState(); } class _CalendarioScreenState extends State { DateTime _focusedDay = DateTime.now(); DateTime? _selectedDay; Map>> _eventos = {}; @override void initState() { super.initState(); _cargarEventos(); } void _cargarEventos() { final facturaProv = context.read(); final servicioProv = context.read(); facturaProv.cargarFacturas().then((_) { _construirEventos(facturaProv, servicioProv); }); } void _construirEventos(FacturaProvider facturaProv, ServicioProvider servicioProv) { final eventos = >>{}; for (final f in facturaProv.facturas) { final fecha = DateTime.tryParse(f.fechaVencimiento); if (fecha == null) continue; final servicio = servicioProv.servicios.where((s) => s.id == f.servicioId).firstOrNull; final day = DateTime(fecha.year, fecha.month, fecha.day); eventos.putIfAbsent(day, () => []).add({ 'servicio': servicio?.nombre ?? 'Desconocido', 'monto': f.monto, 'estado': f.estado, 'color': Color(servicio?.color ?? 0xFF6200EE), }); } setState(() => _eventos = eventos); } @override Widget build(BuildContext context) { context.watch(); context.watch(); final configProv = context.watch(); final symbol = configProv.config?.moneda == 'USD' ? '\$' : configProv.config?.moneda == 'EUR' ? '€' : 'MX\$'; return Scaffold( appBar: AppBar(title: const Text('Calendario de pagos')), body: Column( children: [ TableCalendar( firstDay: DateTime(2024), lastDay: DateTime(2035), focusedDay: _focusedDay, selectedDayPredicate: (day) => isSameDay(_selectedDay, day), eventLoader: (day) { final d = DateTime(day.year, day.month, day.day); return _eventos[d] ?? []; }, calendarStyle: CalendarStyle( todayDecoration: BoxDecoration(color: Theme.of(context).colorScheme.primary.withValues(alpha: 0.5), shape: BoxShape.circle), selectedDecoration: BoxDecoration(color: Theme.of(context).colorScheme.primary, shape: BoxShape.circle), markerDecoration: BoxDecoration(color: Theme.of(context).colorScheme.secondary, shape: BoxShape.circle), ), headerStyle: const HeaderStyle(formatButtonVisible: false, titleCentered: true), onDaySelected: (selected, focused) { setState(() { _selectedDay = selected; _focusedDay = focused; }); }, onPageChanged: (focused) => _focusedDay = focused, calendarBuilders: CalendarBuilders( markerBuilder: (context, date, events) { if (events.isEmpty) return null; final pendientes = events.where((e) => (e as Map)['estado'] == 'Pendiente').length; final pagadas = events.where((e) => (e as Map)['estado'] == 'Pagada').length; return Row( mainAxisSize: MainAxisSize.min, children: [ if (pendientes > 0) Container(margin: const EdgeInsets.only(right: 2), width: 6, height: 6, decoration: BoxDecoration(color: Colors.red, shape: BoxShape.circle)), if (pagadas > 0) Container(width: 6, height: 6, decoration: BoxDecoration(color: Colors.green, shape: BoxShape.circle)), ], ); }, ), ), const Divider(), Expanded( child: _selectedDay == null || (_eventos[DateTime(_selectedDay!.year, _selectedDay!.month, _selectedDay!.day)]?.isEmpty ?? true) ? Center(child: Text('Sin facturas en esta fecha', style: Theme.of(context).textTheme.bodyLarge)) : ListView( children: (_eventos[DateTime(_selectedDay!.year, _selectedDay!.month, _selectedDay!.day)] ?? []).map((e) { return Card( child: ListTile( leading: CircleAvatar(backgroundColor: e['color'] as Color, child: Text((e['servicio'] as String).substring(0, 2).toUpperCase(), style: const TextStyle(color: Colors.white, fontSize: 12))), title: Text(e['servicio'] as String), subtitle: Text('$symbol${NumberFormat('#,##0.00').format(e['monto'])}'), trailing: Chip(label: Text(e['estado'] as String, style: TextStyle(fontSize: 12, color: e['estado'] == 'Pagada' ? Colors.green : Colors.orange))), ), ); }).toList(), ), ), ], ), ); } }