import 'package:flutter/material.dart'; import 'package:flutter_riverpod/flutter_riverpod.dart'; import 'package:lucide_icons/lucide_icons.dart'; import 'package:intl/intl.dart'; import '../../../transactions/providers/providers.dart'; import '../../../transactions/data/models.dart'; import '../../../../core/theme/nature_colors.dart'; class UpcomingDuesWidget extends ConsumerWidget { const UpcomingDuesWidget({super.key}); @override Widget build(BuildContext context, WidgetRef ref) { final walletsState = ref.watch(walletProvider); if (!walletsState.hasValue || walletsState.value == null) { return const SizedBox.shrink(); } final wallets = walletsState.value!; // Filter for payables that have a due date/amount final payables = wallets.where((w) => w.nature == 'PAYABLES').toList(); if (payables.isEmpty) { return const SizedBox.shrink(); } final now = DateTime.now(); // Calculate dues final List> dues = []; for (var w in payables) { double dueAmount = 0; DateTime? dueDate; String dueLabel = 'Upcoming Due'; if (w.subNature == 'CREDIT_CARD' || w.subNature == 'OD_LIMIT') { // Balance is negative if we owe money if (w.balance < 0) { dueAmount = w.balance.abs(); } } else if (w.subNature == 'LOAN_EMI' || w.subNature == 'POLICY_PREMIUM') { dueAmount = w.fixedAmount ?? 0; } if (dueAmount > 0 && w.cycleDate != null) { int year = now.year; int month = now.month; // Find next due date based on cycle if (w.paymentCycle == 'MONTHLY' || w.paymentCycle == null) { if (now.day > w.cycleDate!) { // Due date has passed for this month, next is next month month++; if (month > 12) { month = 1; year++; } } } else if (w.paymentCycle == 'YEARLY') { // Assume cycleDate is day of current month, this is simplistic if (now.day > w.cycleDate!) { year++; } } // Handle end of month issues (e.g. Feb 30th) int maxDays = DateTime(year, month + 1, 0).day; int day = w.cycleDate! > maxDays ? maxDays : w.cycleDate!; dueDate = DateTime(year, month, day); int daysLeft = dueDate.difference(DateTime(now.year, now.month, now.day)).inDays; if (daysLeft == 0) { dueLabel = 'Due Today'; } else if (daysLeft == 1) { dueLabel = 'Due Tomorrow'; } else { dueLabel = 'Due in $daysLeft days'; } dues.add({ 'wallet': w, 'amount': dueAmount, 'dueDate': dueDate, 'label': dueLabel, 'daysLeft': daysLeft, }); } } if (dues.isEmpty) { return const SizedBox.shrink(); } // Sort by nearest due date dues.sort((a, b) => (a['daysLeft'] as int).compareTo(b['daysLeft'] as int)); // Only show top 3 dues final displayDues = dues.take(3).toList(); return Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ Row( children: [ const Icon(LucideIcons.calendarClock, color: Color(0xFF6C63FF), size: 20), const SizedBox(width: 8), Text('Upcoming Dues', style: Theme.of(context).textTheme.bodyLarge?.copyWith(fontWeight: FontWeight.bold)), ], ), const SizedBox(height: 12), ...displayDues.map((due) { final w = due['wallet'] as Wallet; final amount = due['amount'] as double; final dueDate = due['dueDate'] as DateTime; final label = due['label'] as String; final daysLeft = due['daysLeft'] as int; final isUrgent = daysLeft <= 3; return Container( margin: const EdgeInsets.only(bottom: 12), padding: const EdgeInsets.all(16), decoration: BoxDecoration( color: isUrgent ? Colors.red.shade50 : Colors.white, borderRadius: BorderRadius.circular(16), border: Border.all(color: isUrgent ? Colors.red.shade200 : Colors.grey.shade200), boxShadow: [ if (!isUrgent) BoxShadow(color: Colors.black.withOpacity(0.02), blurRadius: 8, offset: const Offset(0, 2)) ], ), child: Row( children: [ Container( padding: const EdgeInsets.all(10), decoration: BoxDecoration( color: (isUrgent ? Colors.red : NatureColors.getColor('PAYABLES')).withOpacity(0.1), shape: BoxShape.circle, ), child: Icon( w.subNature == 'CREDIT_CARD' ? LucideIcons.creditCard : (w.subNature == 'LOAN_EMI' ? LucideIcons.home : LucideIcons.fileText), color: isUrgent ? Colors.red : NatureColors.getColor('PAYABLES'), size: 20, ), ), const SizedBox(width: 16), Expanded( child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ Text(w.name, style: const TextStyle(fontWeight: FontWeight.bold, fontSize: 15)), const SizedBox(height: 4), Text( '$label • ${DateFormat('MMM dd').format(dueDate)}', style: TextStyle( color: isUrgent ? Colors.red.shade700 : Colors.grey.shade600, fontSize: 12, fontWeight: isUrgent ? FontWeight.bold : FontWeight.normal ), ), ], ), ), Text( 'Rs. ${amount.toStringAsFixed(0)}', style: TextStyle( fontWeight: FontWeight.bold, fontSize: 16, color: isUrgent ? Colors.red.shade700 : Colors.black87 ), ), ], ), ); }), const SizedBox(height: 12), ], ); } }