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 SellerReportScreen extends ConsumerStatefulWidget { const SellerReportScreen({super.key}); @override ConsumerState createState() => _SellerReportScreenState(); } class _SellerReportScreenState extends ConsumerState { String _period = 'month'; 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) .bySellerReport(period: _period); if (!mounted) return; setState(() { _data = response.data ?? const {}; _isLoading = false; }); } void _setPeriod(String p) { if (p == _period) return; setState(() => _period = p); _refresh(); } String _fmtCurrency(Object? value) { if (value == null) return 'S/ 0.00'; final n = double.tryParse(value.toString()) ?? 0.0; return 'S/ ${n.toStringAsFixed(2)}'; } @override Widget build(BuildContext context) { final sellers = List>.from(_data['sellers'] as List? ?? const []); final totalGlobal = sellers.fold(0, (sum, s) => sum + (double.tryParse('${s['total']}') ?? 0)); return SafeArea( child: RefreshIndicator( onRefresh: _refresh, child: ListView( padding: AppTokens.pagePadding, children: [ Row( children: [ Expanded(child: _PeriodChip(label: 'Hoy', selected: _period == 'date', onTap: () => _setPeriod('date'))), const SizedBox(width: 8), Expanded(child: _PeriodChip(label: 'Mes', selected: _period == 'month', onTap: () => _setPeriod('month'))), ], ), const SizedBox(height: 14), if (_isLoading) const Padding( padding: EdgeInsets.symmetric(vertical: 32), child: Center(child: CircularProgressIndicator()), ) else if (sellers.isEmpty) const EmptyStatePanel( icon: Icons.person_off_rounded, title: 'Sin ventas', subtitle: 'No hay registros en el período.', ) else AppPanel( title: 'Vendedores', trailing: Text(_fmtCurrency(totalGlobal), style: Theme.of(context).textTheme.titleMedium?.copyWith( color: AppTokens.primary, fontWeight: FontWeight.w800)), child: Column( children: [ for (var i = 0; i < sellers.length; i++) ...[ _SellerRow(rank: i + 1, seller: sellers[i], formatter: _fmtCurrency, total: totalGlobal), if (i < sellers.length - 1) const Divider(height: 16), ], ], ), ), ], ), ), ); } } class _PeriodChip extends StatelessWidget { const _PeriodChip({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 _SellerRow extends StatelessWidget { const _SellerRow({ required this.rank, required this.seller, required this.formatter, required this.total, }); final int rank; final Map seller; final String Function(Object?) formatter; final double total; @override Widget build(BuildContext context) { final mine = double.tryParse('${seller['total']}') ?? 0; final pct = total > 0 ? (mine / total) : 0; return Padding( padding: const EdgeInsets.symmetric(vertical: 4), child: Column( crossAxisAlignment: CrossAxisAlignment.stretch, children: [ Row( children: [ SizedBox( width: 22, child: Text( '$rank.', style: Theme.of(context).textTheme.titleSmall?.copyWith( color: AppTokens.secondary, fontWeight: FontWeight.w700, ), ), ), Expanded( child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ Text( seller['name']?.toString() ?? '-', maxLines: 1, overflow: TextOverflow.ellipsis, style: Theme.of(context).textTheme.titleSmall, ), const SizedBox(height: 2), Text( '${seller['count'] ?? 0} operación(es)', style: Theme.of(context).textTheme.labelSmall?.copyWith( color: AppTokens.secondary, ), ), ], ), ), Text( formatter(seller['total']), style: Theme.of(context).textTheme.titleSmall?.copyWith( color: AppTokens.primary, fontWeight: FontWeight.w800, ), ), ], ), const SizedBox(height: 6), ClipRRect( borderRadius: BorderRadius.circular(999), child: LinearProgressIndicator( value: pct.toDouble(), minHeight: 4, backgroundColor: AppTokens.border, valueColor: const AlwaysStoppedAnimation(AppTokens.primary), ), ), ], ), ); } }