import 'package:flutter/material.dart'; import 'package:flutter/services.dart'; import 'package:sizer/sizer.dart'; import '../../core/app_export.dart'; import '../../models/coupon_model.dart'; import '../../services/coupon_service.dart'; import '../../theme/app_theme.dart'; import '../../widgets/custom_bottom_bar.dart'; import './widgets/category_filter_chips.dart'; import './widgets/coupon_card_widget.dart'; import './widgets/coupon_detail_modal.dart'; import './widgets/empty_state_widget.dart'; import './widgets/sort_dropdown.dart'; class CouponsScreen extends StatefulWidget { const CouponsScreen({super.key}); @override State createState() => _CouponsScreenState(); } class _CouponsScreenState extends State { final ScrollController _scrollController = ScrollController(); bool _isLoading = true; bool _isRefreshing = false; String _selectedCategory = 'Todos'; String _selectedSort = 'Más recientes'; List _coupons = []; @override void initState() { super.initState(); _loadCoupons(); } @override void dispose() { _scrollController.dispose(); super.dispose(); } /// Load coupons with silent error handling - no user error messages Future _loadCoupons() async { try { setState(() { _isLoading = true; }); final coupons = await CouponService.getCoupons( selectedCategory: _selectedCategory, sort: _selectedSort, ); setState(() { _coupons = coupons; _isLoading = false; }); } catch (e) { // Silent failure - show empty state but don't show error to user setState(() { _coupons = []; _isLoading = false; }); } } /// Refresh coupons with silent error handling Future _refreshCoupons() async { setState(() { _isRefreshing = true; }); HapticFeedback.lightImpact(); try { final coupons = await CouponService.getCoupons( selectedCategory: _selectedCategory, sort: _selectedSort, ); setState(() { _coupons = coupons; }); } catch (e) { // Silent failure - keep existing coupons, don't show error } finally { setState(() { _isRefreshing = false; }); } } /// Handle category change and auto-refresh data void _onCategoryChanged(String category) { if (_selectedCategory != category) { setState(() { _selectedCategory = category; }); _loadCoupons(); // Automatically refresh when filters change } } /// Handle sort change and auto-refresh data void _onSortChanged(String sort) { if (_selectedSort != sort) { setState(() { _selectedSort = sort; }); _loadCoupons(); // Automatically refresh when sorting changes } } void _showCouponDetail(CouponModel coupon) { HapticFeedback.lightImpact(); showDialog( context: context, builder: (context) => CouponDetailModal(coupon: coupon), ); } @override Widget build(BuildContext context) { final theme = Theme.of(context); return Scaffold( backgroundColor: theme.scaffoldBackgroundColor, appBar: AppBar( title: Text( 'Cupones', style: theme.textTheme.titleLarge?.copyWith( fontWeight: FontWeight.w600, ), ), backgroundColor: theme.colorScheme.surface, elevation: 0, ), body: Column( children: [ // Category Filter Chips (Spanish UI) CategoryFilterChips( selectedCategory: _selectedCategory, onCategorySelected: _onCategoryChanged, ), // Sort Dropdown (Spanish UI) Container( padding: EdgeInsets.symmetric(vertical: 1.h), color: theme.colorScheme.surface, child: SortDropdown( selectedSort: _selectedSort, onSortChanged: _onSortChanged, ), ), // Content Expanded(child: _buildContent()), ], ), bottomNavigationBar: CustomBottomBar( currentIndex: 2, onTap: (index) { switch (index) { case 0: Navigator.pushReplacementNamed(context, '/map-screen'); break; case 1: Navigator.pushReplacementNamed(context, '/schedules-screen'); break; case 2: // Already on coupons screen break; } }, ), ); } Widget _buildContent() { final theme = Theme.of(context); if (_isLoading) { return Center( child: CircularProgressIndicator(color: AppTheme.accentYellow), ); } // No error states shown to user - only empty states if (_coupons.isEmpty) { final isFiltered = _selectedCategory != 'Todos'; return EmptyStateWidget( title: isFiltered ? 'No hay cupones disponibles para esta categoría.' : 'Aún no hay cupones registrados.', subtitle: isFiltered ? 'Intenta seleccionando otra categoría' : 'Vuelve pronto para ver nuevas ofertas', actionText: isFiltered ? 'Ver todos' : null, onActionPressed: isFiltered ? () => _onCategoryChanged('Todos') : null, ); } return RefreshIndicator( onRefresh: _refreshCoupons, color: AppTheme.accentYellow, backgroundColor: theme.colorScheme.surface, child: GridView.builder( controller: _scrollController, padding: EdgeInsets.all(4.w), gridDelegate: SliverGridDelegateWithFixedCrossAxisCount( crossAxisCount: _getGridCrossAxisCount(), crossAxisSpacing: 4.w, mainAxisSpacing: 4.w, childAspectRatio: 0.75, ), itemCount: _coupons.length + (_isRefreshing ? 2 : 0), itemBuilder: (context, index) { if (index >= _coupons.length) { return Card( elevation: 2, shape: RoundedRectangleBorder( borderRadius: BorderRadius.circular(12), ), child: Container( decoration: BoxDecoration( borderRadius: BorderRadius.circular(12), color: theme.colorScheme.surface, ), child: Center( child: CircularProgressIndicator( color: AppTheme.accentYellow, strokeWidth: 2, ), ), ), ); } final coupon = _coupons[index]; return CouponCardWidget( coupon: coupon, onTap: () => _showCouponDetail(coupon), ); }, ), ); } int _getGridCrossAxisCount() { if (MediaQuery.of(context).size.width > 768) { return 3; // Tablet } return 2; // Phone } }