import 'package:sysfarma_mobile/src/app/widgets/app_panel.dart'; import 'package:sysfarma_mobile/src/app/widgets/empty_state_panel.dart'; import 'package:sysfarma_mobile/src/core/network/api_client.dart'; import 'package:sysfarma_mobile/src/core/theme/app_tokens.dart'; import 'package:flutter/material.dart'; import 'package:flutter_riverpod/flutter_riverpod.dart'; class ExpiringLotsReportScreen extends ConsumerStatefulWidget { const ExpiringLotsReportScreen({super.key}); @override ConsumerState createState() => _ExpiringLotsReportScreenState(); } class _ExpiringLotsReportScreenState extends ConsumerState { int _days = 60; bool _isLoading = true; Map _data = const {}; @override void initState() { super.initState(); _refresh(); } Future _refresh() async { if (mounted) setState(() => _isLoading = true); final response = await ref.read(apiClientProvider).expiringLotsReport(days: _days); if (!mounted) return; setState(() { _data = response.data ?? const {}; _isLoading = false; }); } void _setDays(int d) { if (d == _days) return; setState(() => _days = d); _refresh(); } @override Widget build(BuildContext context) { final items = List>.from(_data['items'] as List? ?? const []); return SafeArea( child: RefreshIndicator( onRefresh: _refresh, child: ListView( padding: AppTokens.pagePadding, children: [ Row( children: [ Expanded( child: _DaysChip(label: '30 días', selected: _days == 30, onTap: () => _setDays(30)), ), const SizedBox(width: 8), Expanded( child: _DaysChip(label: '60 días', selected: _days == 60, onTap: () => _setDays(60)), ), const SizedBox(width: 8), Expanded( child: _DaysChip(label: '90 días', selected: _days == 90, onTap: () => _setDays(90)), ), ], ), const SizedBox(height: 14), if (_isLoading) const Padding( padding: EdgeInsets.symmetric(vertical: 32), child: Center(child: CircularProgressIndicator()), ) else if (items.isEmpty) const EmptyStatePanel( icon: Icons.check_circle_outline_rounded, title: 'Sin lotes por vencer', subtitle: 'Ningún lote vence en este rango.', ) else AppPanel( title: 'Lotes', trailing: Text('${items.length}', style: Theme.of(context).textTheme.titleMedium?.copyWith( color: AppTokens.primary, fontWeight: FontWeight.w700)), child: Column( children: [ for (final item in items) ...[ _LotRow(item: item), if (item != items.last) const Divider(height: 16), ], ], ), ), ], ), ), ); } } class _DaysChip extends StatelessWidget { const _DaysChip({required this.label, required this.selected, required this.onTap}); final String label; final bool selected; final VoidCallback onTap; @override Widget build(BuildContext context) { return Material( color: Colors.transparent, child: InkWell( borderRadius: BorderRadius.circular(AppTokens.radiusSmall), onTap: onTap, child: Container( padding: const EdgeInsets.symmetric(vertical: 10), decoration: BoxDecoration( color: selected ? AppTokens.primary.withValues(alpha: 0.10) : AppTokens.surface, borderRadius: BorderRadius.circular(AppTokens.radiusSmall), border: Border.all( color: selected ? AppTokens.primary : AppTokens.border, ), ), child: Center( child: Text( label, style: Theme.of(context).textTheme.labelLarge?.copyWith( color: selected ? AppTokens.primary : AppTokens.secondary, fontWeight: selected ? FontWeight.w700 : FontWeight.w500, ), ), ), ), ), ); } } class _LotRow extends StatelessWidget { const _LotRow({required this.item}); final Map item; @override Widget build(BuildContext context) { final daysLeft = item['days_left'] ?? 0; final isExpired = item['is_expired'] == true; final color = isExpired ? AppTokens.danger : (daysLeft is num && daysLeft <= 15) ? AppTokens.danger : (daysLeft is num && daysLeft <= 30) ? AppTokens.warning : AppTokens.secondary; return Padding( padding: const EdgeInsets.symmetric(vertical: 4), child: Row( children: [ Container( width: 8, height: 40, decoration: BoxDecoration( color: color, borderRadius: BorderRadius.circular(4), ), ), const SizedBox(width: 12), Expanded( child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ Text( item['description']?.toString() ?? '-', maxLines: 1, overflow: TextOverflow.ellipsis, style: Theme.of(context).textTheme.titleSmall, ), const SizedBox(height: 2), Text( 'Lote: ${item['lot_code'] ?? '-'} · ${item['date_of_due'] ?? '-'}', style: Theme.of(context).textTheme.labelSmall?.copyWith( color: AppTokens.secondary, ), ), ], ), ), Column( crossAxisAlignment: CrossAxisAlignment.end, children: [ Text( '${item['quantity'] ?? 0} u', style: Theme.of(context).textTheme.titleSmall?.copyWith( fontWeight: FontWeight.w700, ), ), Text( isExpired ? 'Vencido hace ${daysLeft.abs()}d' : 'Vence en ${daysLeft}d', style: Theme.of(context).textTheme.labelSmall?.copyWith( color: color, fontWeight: FontWeight.w600, ), ), ], ), ], ), ); } }