import 'package:business_panel/core/config/app_colors.dart'; import 'package:business_panel/domain/entities/discount_entity.dart'; import 'package:business_panel/gen/assets.gen.dart'; import 'package:business_panel/presentation/home/bloc/home_bloc.dart'; import 'package:flutter/material.dart'; import 'package:flutter_bloc/flutter_bloc.dart'; import 'package:flutter_svg/svg.dart'; import 'package:slide_countdown/slide_countdown.dart'; import 'package:business_panel/presentation/pages/add_discount_page.dart'; class HomePage extends StatefulWidget { const HomePage({super.key}); @override State createState() => _HomePageState(); } class _HomePageState extends State { @override void initState() { super.initState(); context.read().add(FetchDiscounts()); } @override Widget build(BuildContext context) { return Scaffold( appBar: _buildCustomAppBar(context), body: BlocBuilder( builder: (context, state) { if (state is HomeLoading) { return const Center(child: CircularProgressIndicator()); } if (state is HomeError) { return Center( child: Padding( padding: const EdgeInsets.all(16.0), child: Text('خطا: ${state.message}', textAlign: TextAlign.center), ), ); } if (state is HomeLoaded) { if (state.discounts.isEmpty) { return _buildEmptyState(); } return RefreshIndicator( onRefresh: () async { context.read().add(FetchDiscounts()); }, child: ListView.builder( padding: const EdgeInsets.all(16), // تعداد آیتم‌ها یکی بیشتر از تعداد تخفیف‌هاست تا دکمه هم جا شود itemCount: state.discounts.length + 1, itemBuilder: (context, index) { // اگر ایندکس مربوط به آخرین آیتم بود، دکمه را نمایش بده if (index == state.discounts.length) { return _buildAddDiscountButton(); } // در غیر این صورت، کارت تخفیف را نمایش بده final discount = state.discounts[index]; return _buildDiscountCard(discount); }, ), ); } // حالت پیش‌فرض return _buildEmptyState(); }, ), ); } Widget _buildEmptyState() { return Center( child: Column( mainAxisAlignment: MainAxisAlignment.center, children: [ SvgPicture.asset(Assets.images.emptyHome, height: 200), const SizedBox(height: 20), const Text( "هنوز تخفیفی ثبت نکرده‌اید", style: TextStyle(fontSize: 18, fontWeight: FontWeight.bold), ), const SizedBox(height: 20), Padding( padding: const EdgeInsets.symmetric(horizontal: 24.0), child: _buildAddDiscountButton(), ), ], ), ); } Widget _buildAddDiscountButton() { return Padding( padding: const EdgeInsets.only(top: 16.0), child: SizedBox( width: double.infinity, child: ElevatedButton( style: ElevatedButton.styleFrom( backgroundColor: AppColors.confirm, padding: const EdgeInsets.symmetric(vertical: 14), shape: RoundedRectangleBorder( borderRadius: BorderRadius.circular(40), ), ), onPressed: () { Navigator.of(context) .push(MaterialPageRoute(builder: (_) => const AddDiscountPage())) .then((_) { // رفرش لیست بعد از بازگشت از صفحه افزودن context.read().add(FetchDiscounts()); }); }, child: const Row( mainAxisAlignment: MainAxisAlignment.center, children: [ Icon(Icons.add, color: Colors.white), SizedBox(width: 8), Text( "تعریف تخفیف جدید", style: TextStyle( fontSize: 18, fontWeight: FontWeight.normal, color: Colors.white, ), ), ], ), ), ), ); } Widget _buildDiscountCard(DiscountEntity discount) { final remaining = discount.endDate != null ? discount.endDate!.difference(DateTime.now()) : const Duration(seconds: -1); return Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ Row( mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ Padding( padding: const EdgeInsets.symmetric(horizontal: 8.0), child: Text( "تخفیف ${discount.type}", style: const TextStyle( fontSize: 18, fontWeight: FontWeight.bold, color: Colors.black, ), ), ), InkWell( onTap: () { // TODO: Implement edit functionality }, borderRadius: BorderRadius.circular(8), child: Padding( padding: const EdgeInsets.all(8.0), child: Row( children: [ SvgPicture.asset(Assets.icons.edit, width: 20, color: AppColors.active), const SizedBox(width: 5), const Text("ویرایش", style: TextStyle(color: AppColors.active)), ], ), ), ), ], ), const Divider(height: 1), const SizedBox(height: 10), Card( color: Colors.white, elevation: 0, margin: const EdgeInsets.only(bottom: 16), shape: RoundedRectangleBorder( borderRadius: BorderRadius.circular(25), side: BorderSide(color: Colors.grey.shade300, width: 1), ), child: Padding( padding: const EdgeInsets.all(16.0), child: Row( crossAxisAlignment: CrossAxisAlignment.start, children: [ if (discount.images.isNotEmpty && discount.images.first.isNotEmpty) ClipRRect( borderRadius: BorderRadius.circular(15), child: Image.network( discount.images.first, width: 100, height: 100, fit: BoxFit.cover, errorBuilder: (context, error, stackTrace) => Container( width: 100, height: 100, decoration: BoxDecoration( color: Colors.grey[200], borderRadius: BorderRadius.circular(15), ), child: const Icon(Icons.image_not_supported, color: Colors.grey), ), ), ) else Container( width: 100, height: 100, decoration: BoxDecoration( color: Colors.grey[200], borderRadius: BorderRadius.circular(15), ), child: const Icon(Icons.store, color: Colors.grey, size: 50), ), const SizedBox(width: 16), Expanded( child: Column( crossAxisAlignment: CrossAxisAlignment.start, mainAxisAlignment: MainAxisAlignment.start, children: [ Row( children: [ SvgPicture.asset(Assets.icons.shop, width: 18, color: Colors.grey.shade700), const SizedBox(width: 10), Expanded( child: Text( discount.shopName, style: const TextStyle(fontSize: 16), overflow: TextOverflow.ellipsis, ), ), ], ), const SizedBox(height: 8), Row( children: [ SvgPicture.asset(Assets.icons.shoppingCart, width: 18, color: Colors.grey.shade700), const SizedBox(width: 10), Expanded( child: Text( discount.name, style: TextStyle(fontSize: 15, color: Colors.grey.shade600), overflow: TextOverflow.ellipsis, ), ), ], ), const SizedBox(height: 12), if (discount.endDate == null) const Text( 'تاریخ نامعتبر', style: TextStyle(color: Colors.orange, fontWeight: FontWeight.bold), ) else if (remaining.isNegative) const Text( 'منقضی شده', style: TextStyle(color: AppColors.expiryReserve, fontWeight: FontWeight.bold), ) else Row( children: [ SvgPicture.asset(Assets.icons.timerPause, width: 18, color: Colors.grey.shade700), const SizedBox(width: 10), Expanded(child: _buildCountdownTimer(remaining)), ], ), ], ), ), ], ), ), ), ], ); } Widget _buildCountdownTimer(Duration remaining) { return Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ Localizations.override( context: context, locale: const Locale('en'), child: SlideCountdown( duration: remaining, slideDirection: SlideDirection.up, separator: ':', style: const TextStyle( fontSize: 15, fontWeight: FontWeight.bold, color: AppColors.countdown, ), separatorStyle: const TextStyle( fontSize: 15, color: AppColors.countdown, ), decoration: const BoxDecoration(color: Colors.transparent), shouldShowDays: (d) => d.inDays > 0, shouldShowHours: (d) => true, shouldShowMinutes: (d) => true, ), ), const SizedBox(height: 4), _buildTimerLabels(remaining), ], ); } Widget _buildTimerLabels(Duration duration) { const labelStyle = TextStyle(fontSize: 10, color: AppColors.selectedImg); List labels = []; if (duration.inDays > 0) { labels.add(const SizedBox(width: 30, child: Text("روز", style: labelStyle))); } if (duration.inHours > 0 || duration.inDays > 0) { labels.add(const SizedBox(width: 35, child: Text("ساعت", style: labelStyle))); } labels.add(const SizedBox(width: 30, child: Text("دقیقه", style: labelStyle))); labels.add(const SizedBox(width: 30, child: Text("ثانیه", style: labelStyle))); return Row( mainAxisAlignment: MainAxisAlignment.start, children: labels.reversed.toList(), ); } PreferredSizeWidget _buildCustomAppBar(BuildContext context) { return PreferredSize( preferredSize: const Size.fromHeight(70.0), child: Container( decoration: BoxDecoration( color: Colors.white, borderRadius: const BorderRadius.vertical( bottom: Radius.circular(15), ), boxShadow: [ BoxShadow( color: Colors.black.withOpacity(0.08), blurRadius: 10, offset: const Offset(0, 4), ), ], ), child: SafeArea( child: Padding( padding: const EdgeInsets.symmetric(horizontal: 10.0), child: Row( mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ SvgPicture.asset(Assets.icons.logoWithName), Row( children: [ IconButton( onPressed: () {}, icon: SvgPicture.asset( Assets.icons.discountShape, color: Colors.black, ), ), IconButton( onPressed: () {}, icon: SvgPicture.asset(Assets.icons.scanBarcode), ), ], ), ], ), ), ), ), ); } }