import 'package:collection/collection.dart'; import 'package:flutter/material.dart'; import 'package:flutter_animate/flutter_animate.dart'; // <-- این خط را اضافه کن import 'package:flutter_bloc/flutter_bloc.dart'; import 'package:flutter_svg/svg.dart'; import 'package:geolocator/geolocator.dart'; import 'package:proxibuy/core/config/app_colors.dart'; import 'package:proxibuy/core/gen/assets.gen.dart'; import 'package:proxibuy/data/models/offer_model.dart'; import 'package:proxibuy/presentation/notification_preferences/bloc/notification_preferences_bloc.dart'; import 'package:proxibuy/presentation/notification_preferences/bloc/notification_preferences_event.dart'; import 'package:proxibuy/presentation/offer/bloc/offer_bloc.dart'; import 'package:proxibuy/presentation/offer/bloc/offer_event.dart'; import 'package:proxibuy/presentation/offer/bloc/offer_state.dart'; import 'package:proxibuy/presentation/offer/bloc/widgets/category_offers_row.dart'; import 'package:proxibuy/presentation/pages/notification_preferences_page.dart'; import 'package:proxibuy/presentation/widgets/gps_dialog.dart'; import 'package:proxibuy/presentation/widgets/notification_permission_dialog.dart'; import 'package:shared_preferences/shared_preferences.dart'; class OffersPage extends StatefulWidget { final bool showDialogsOnLoad; const OffersPage({super.key, this.showDialogsOnLoad = false}); @override State createState() => _OffersPageState(); } class _OffersPageState extends State { List _selectedCategories = []; @override void initState() { super.initState(); _loadOffersAndPreferences(); if (widget.showDialogsOnLoad) { WidgetsBinding.instance.addPostFrameCallback((_) async { if (mounted) { await showGPSDialog(context); } if (mounted) { await showNotificationPermissionDialog(context); } }); } } Future _loadOffersAndPreferences() async { final prefs = await SharedPreferences.getInstance(); final savedCategories = prefs.getStringList('user_selected_categories') ?? []; if (mounted) { setState(() { _selectedCategories = savedCategories; }); context.read().add( OffersFetchRequested(selectedCategories: savedCategories), ); } } Widget _buildFavoriteCategoriesSection() { return Padding( padding: const EdgeInsets.fromLTRB(16.0, 16.0, 16.0, 0), child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ Row( mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ const Text( 'دسته‌بندی‌های مورد علاقه شما', style: TextStyle(fontSize: 19, fontWeight: FontWeight.bold), ), TextButton( onPressed: () async { final result = await Navigator.of(context).push( MaterialPageRoute( builder: (_) => BlocProvider.value( value: context.read() ..add(LoadCategories()), child: const NotificationPreferencesPage(), ), ), ); if (result == true) { _loadOffersAndPreferences(); } }, child: Row( children: [ // چون asset مربوط به ویرایش وجود نداشت، از آیکون فلاتر استفاده شد const Icon(Icons.edit, size: 18, color: AppColors.primary), const SizedBox(width: 4), const Text('ویرایش'), ], ), ), ], ), const Divider(height: 1), const SizedBox(height: 12), if (_selectedCategories.isEmpty) const Padding( padding: EdgeInsets.only(bottom: 8.0), child: Text( 'شما هنوز دسته‌بندی مورد علاقه خود را انتخاب نکرده‌اید.', style: TextStyle(color: Colors.grey), ), ) else Wrap( spacing: 8.0, runSpacing: 8.0, children: _selectedCategories.map((category) { return Container( padding: const EdgeInsets.symmetric( horizontal: 12.0, vertical: 6.0, ), decoration: BoxDecoration( border: Border.all(color: Colors.grey.shade300), borderRadius: BorderRadius.circular(20.0), ), child: Text(category), ); }).toList(), ), ], ), ); } @override Widget build(BuildContext context) { return Directionality( textDirection: TextDirection.rtl, child: Scaffold( appBar: AppBar( backgroundColor: Colors.white, automaticallyImplyLeading: false, title: Padding( padding: const EdgeInsets.symmetric( horizontal: 15.0, vertical: 0.0, ), child: Assets.icons.logoWithName.svg(height: 40, width: 200), ), actions: [ IconButton(onPressed: () {}, icon: Assets.icons.notification.svg()), IconButton(onPressed: () {}, icon: Assets.icons.scanBarcode.svg()), const SizedBox(width: 8), ], ), body: SingleChildScrollView( child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [_buildFavoriteCategoriesSection(), const OffersView()], ), ), ), ); } } class OffersView extends StatelessWidget { const OffersView({super.key}); @override Widget build(BuildContext context) { return BlocBuilder( builder: (context, state) { if (state is OffersLoadInProgress || state is OffersInitial) { return const SizedBox( height: 300, child: Center(child: CircularProgressIndicator()), ); } if (state is OffersLoadSuccess) { if (state.offers.isEmpty) { return Center( child: SizedBox( child: Center( child: Column( crossAxisAlignment: CrossAxisAlignment.center, children: [ const SizedBox(height: 85), SvgPicture.asset(Assets.images.emptyHome.path), const SizedBox(height: 60), ElevatedButton( onPressed: () async { await Geolocator.openLocationSettings(); }, style: ElevatedButton.styleFrom( backgroundColor: AppColors.confirm, foregroundColor: Colors.white, disabledBackgroundColor: Colors.grey, padding: const EdgeInsets.symmetric(vertical: 12,horizontal: 125), shape: RoundedRectangleBorder( borderRadius: BorderRadius.circular(50), ), ), child: const Text( 'فعال‌سازی GPS', style: TextStyle( fontFamily: 'Dana', fontSize: 16, fontWeight: FontWeight.normal, ), ), ), const SizedBox(height: 15), const Text('جست‌وجوی تصادفی') ], ), ), ), ); } final groupedOffers = groupBy( state.offers, (OfferModel offer) => offer.category, ); final categories = groupedOffers.keys.toList(); return ListView.builder( shrinkWrap: true, physics: const NeverScrollableScrollPhysics(), padding: const EdgeInsets.only(top: 16), itemCount: categories.length, itemBuilder: (context, index) { final category = categories[index]; final offersForCategory = groupedOffers[category]!; return CategoryOffersRow( categoryTitle: category, offers: offersForCategory, ) .animate() .fade(duration: 500.ms) .slideY(begin: 0.3, duration: 400.ms, curve: Curves.easeOut); }, ); } if (state is OffersLoadFailure) { return SizedBox( height: 200, child: Center(child: Text("خطا در بارگذاری: ${state.error}")), ); } return const SizedBox.shrink(); }, ); } }