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/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/pages/reserved_list_page.dart'; import 'package:proxibuy/presentation/reservation/cubit/reservation_cubit.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: (_) => const NotificationPreferencesPage(), ), ); if (result == true && mounted) { _loadOffersAndPreferences(); } }, child: Row( children: [ SvgPicture.asset(Assets.icons.edit.path), const SizedBox(width: 4), const Text( 'ویرایش', style: TextStyle(color: AppColors.active), ), ], ), ), ], ), 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()), BlocBuilder( builder: (context, state) { final reservedCount = state.reservedProductIds.length; return Stack( alignment: Alignment.center, children: [ IconButton( onPressed: () { Navigator.of(context).push( MaterialPageRoute( builder: (_) => const ReservedListPage(), ), ); }, icon: Assets.icons.scanBarcode.svg(), ), if (reservedCount > 0) Positioned( top: 0, right: 2, child: GestureDetector( onTap: () { Navigator.of(context).push( MaterialPageRoute( builder: (_) => const ReservedListPage(), ), ); }, child: Container( padding: const EdgeInsets.all(4), decoration: BoxDecoration( color: Colors.green, shape: BoxShape.circle, border: Border.all( color: Colors.white, width: 1.5, ), ), constraints: const BoxConstraints( minWidth: 18, minHeight: 18, ), child: Padding( padding: const EdgeInsets.fromLTRB(2, 4, 2, 2), child: Text( '$reservedCount', style: const TextStyle( color: Colors.white, fontSize: 11, fontWeight: FontWeight.bold, ), textAlign: TextAlign.center, ), ), ), ), ), ], ); }, ), 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(); }, ); } }