// lib/presentation/pages/discount_manegment_page.dart import 'dart:async'; import 'package:business_panel/core/config/app_colors.dart'; import 'package:business_panel/domain/entities/discount_entity.dart'; import 'package:business_panel/presentation/discount_management/bloc/discount_management_bloc.dart'; import 'package:business_panel/presentation/widgets/analytics_discount_card.dart'; import 'package:business_panel/presentation/widgets/custom_app_bar_single.dart'; import 'package:flutter/material.dart'; import 'package:flutter_bloc/flutter_bloc.dart'; import 'package:flutter_svg/flutter_svg.dart'; import 'package:business_panel/gen/assets.gen.dart'; class DiscountManegmentPage extends StatelessWidget { const DiscountManegmentPage({super.key}); @override Widget build(BuildContext context) { return BlocProvider( create: (context) => DiscountManagementBloc(), child: const _DiscountManegmentView(), ); } } class _DiscountManegmentView extends StatefulWidget { const _DiscountManegmentView(); @override State<_DiscountManegmentView> createState() => _DiscountManegmentPageState(); } class _DiscountManegmentPageState extends State<_DiscountManegmentView> { final TextEditingController _searchController = TextEditingController(); Timer? _debounce; int _selectedStatus = 1; // 1 for active, 0 for inactive @override void initState() { super.initState(); WidgetsBinding.instance.addPostFrameCallback((_) { if (mounted) { context .read() .add(FetchManagedDiscounts(status: _selectedStatus)); } }); } @override void dispose() { _searchController.dispose(); _debounce?.cancel(); super.dispose(); } void _onSearchChanged(String query) { if (_debounce?.isActive ?? false) _debounce!.cancel(); _debounce = Timer(const Duration(milliseconds: 500), () { if (mounted) { context.read().add( SearchManagedDiscounts(query: query, status: _selectedStatus)); } }); } @override Widget build(BuildContext context) { return Scaffold( appBar: CustomAppBarSingle( page: "تخفیف ها", ), body: BlocListener( listener: (context, state) { if (state is DiscountDeleteSuccess) { ScaffoldMessenger.of(context) ..hideCurrentSnackBar() ..showSnackBar( SnackBar( content: Text(state.message), backgroundColor: Colors.green), ); context .read() .add(FetchManagedDiscounts(status: _selectedStatus)); } else if (state is DiscountDeleteFailure) { ScaffoldMessenger.of(context) ..hideCurrentSnackBar() ..showSnackBar( SnackBar( content: Text(state.error), backgroundColor: Colors.red), ); } }, child: Column( children: [ _buildSearchBar(), _buildStatusFilters(), _buildDiscountList(), ], ), ), ); } Widget _buildSearchBar() { return Padding( padding: const EdgeInsets.all(16.0), child: TextField( controller: _searchController, decoration: InputDecoration( hintText: 'دنبال چی می‌گردی؟', hintStyle: const TextStyle(color: Color.fromARGB(255, 157, 157, 157)), prefixIcon: Padding( padding: const EdgeInsets.all(12.0), child: SvgPicture.asset(Assets.icons.riSearch2Line), ), fillColor: const Color.fromARGB(255, 244, 244, 244), filled: true, border: OutlineInputBorder( borderRadius: BorderRadius.circular(50), borderSide: BorderSide.none, ), contentPadding: const EdgeInsets.symmetric(vertical: 0), ), onChanged: _onSearchChanged, ), ); } Widget _buildStatusFilters() { return Padding( padding: const EdgeInsets.symmetric(vertical: 8.0, horizontal: 16.0), child: Row( children: [ _buildStatusSelector(context, text: "تخفیف‌های فعال", status: 1), const SizedBox(width: 16), _buildStatusSelector(context, text: "تخفیف‌های غیر فعال", status: 0), ], ), ); } Widget _buildStatusSelector(BuildContext context, {required String text, required int status}) { final bool isSelected = _selectedStatus == status; return Expanded( child: InkWell( onTap: () { setState(() => _selectedStatus = status); context .read() .add(FetchManagedDiscounts(status: _selectedStatus)); _searchController.clear(); }, borderRadius: BorderRadius.circular(50), child: Padding( padding: const EdgeInsets.symmetric(vertical: 12.0), child: Row( mainAxisAlignment: MainAxisAlignment.center, children: [ Container( width: 22, height: 22, decoration: BoxDecoration( shape: BoxShape.circle, color: isSelected ? Colors.white : Colors.transparent, border: Border.all( color: isSelected ? AppColors.active : Colors.grey.shade400, width: 2, ), ), child: isSelected ? Center( child: Container( width: 12, height: 12, decoration: const BoxDecoration( shape: BoxShape.circle, color: AppColors.active, ), ), ) : null, ), const SizedBox(width: 10), Text( text, style: const TextStyle( color: AppColors.hint, fontWeight: FontWeight.bold, fontSize: 15), ), ], ), ), ), ); } Widget _buildDiscountList() { return Expanded( child: BlocBuilder( builder: (context, state) { if (state is DiscountManagementLoading) { return const Center(child: CircularProgressIndicator()); } if (state is DiscountManagementError) { return Center(child: Text('خطا: ${state.message}')); } if (state is DiscountManagementLoaded) { if (state.discounts.isEmpty) { return const Center( child: Text("هیچ تخفیفی با این مشخصات یافت نشد.")); } // Group discounts final Map> groupedDiscounts = {}; for (var discount in state.discounts) { if (groupedDiscounts.containsKey(discount.type)) { groupedDiscounts[discount.type]!.add(discount); } else { groupedDiscounts[discount.type] = [discount]; } } final groupKeys = groupedDiscounts.keys.toList(); return RefreshIndicator( onRefresh: () async { context .read() .add(FetchManagedDiscounts(status: _selectedStatus)); _searchController.clear(); }, child: ListView.builder( padding: const EdgeInsets.symmetric(horizontal: 16), itemCount: groupKeys.length, itemBuilder: (context, index) { final type = groupKeys[index]; final discountsOfType = groupedDiscounts[type]!; return Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ Padding( padding: const EdgeInsets.fromLTRB(0, 24, 0, 8), child: Text( "تخفیف $type", style: const TextStyle( fontSize: 18, fontWeight: FontWeight.bold, ), ), ), ...discountsOfType.map((discount) { return BlocProvider.value( value: context.read(), child: AnalyticsDiscountCard(discount: discount), ); }).toList(), ], ); }, ), ); } return const Center(child: CircularProgressIndicator()); }, ), ); } }