/// Promotion Detail Page /// /// Displays full details of a selected promotion including: /// - Banner image /// - Title and date range /// - Program content /// - Terms and conditions /// - Contact information library; import 'package:cached_network_image/cached_network_image.dart'; import 'package:worker/core/widgets/loading_indicator.dart'; import 'package:flutter/material.dart'; import 'package:flutter_riverpod/flutter_riverpod.dart'; import 'package:font_awesome_flutter/font_awesome_flutter.dart'; import 'package:go_router/go_router.dart'; import 'package:worker/core/constants/ui_constants.dart'; import 'package:worker/core/router/app_router.dart'; import 'package:worker/core/theme/colors.dart'; import 'package:worker/features/home/domain/entities/promotion.dart'; import 'package:worker/features/home/presentation/providers/promotions_provider.dart'; import 'package:worker/features/promotions/presentation/widgets/highlight_box.dart'; import 'package:worker/features/promotions/presentation/widgets/promotion_section.dart'; /// Promotion Detail Page /// /// Full-screen detail view of a promotion with scrollable content /// and fixed bottom action bar. class PromotionDetailPage extends ConsumerStatefulWidget { const PromotionDetailPage({this.promotionId, super.key}); /// Promotion ID final String? promotionId; @override ConsumerState createState() => _PromotionDetailPageState(); } class _PromotionDetailPageState extends ConsumerState { bool _isBookmarked = false; @override Widget build(BuildContext context) { // Watch promotions provider final promotionsAsync = ref.watch(promotionsProvider); return promotionsAsync.when( data: (promotions) { // Find promotion by ID final promotion = promotions.firstWhere( (p) => p.id == widget.promotionId, orElse: () => promotions.first, ); return _buildDetailContent(promotion); }, loading: () => Scaffold( appBar: AppBar( leading: IconButton( icon: const FaIcon(FontAwesomeIcons.arrowLeft, color: Colors.black, size: 20), onPressed: () => context.pop(), ), title: const Text( 'Chi tiết khuyến mãi', style: TextStyle(color: Colors.black), ), elevation: AppBarSpecs.elevation, backgroundColor: AppColors.white, foregroundColor: AppColors.grey900, centerTitle: false, ), body: const const CustomLoadingIndicator(), ), error: (error, stack) => Scaffold( appBar: AppBar( leading: IconButton( icon: const FaIcon(FontAwesomeIcons.arrowLeft, color: Colors.black, size: 20), onPressed: () => context.pop(), ), title: const Text( 'Chi tiết khuyến mãi', style: TextStyle(color: Colors.black), ), elevation: AppBarSpecs.elevation, backgroundColor: AppColors.white, foregroundColor: AppColors.grey900, centerTitle: false, ), body: Center( child: Column( mainAxisAlignment: MainAxisAlignment.center, children: [ const FaIcon( FontAwesomeIcons.circleExclamation, size: 64, color: AppColors.danger, ), const SizedBox(height: 16), const Text( 'Không thể tải thông tin khuyến mãi', style: TextStyle(fontSize: 16, fontWeight: FontWeight.w600), ), const SizedBox(height: 8), Text( error.toString(), style: const TextStyle(fontSize: 14, color: AppColors.grey500), textAlign: TextAlign.center, ), ], ), ), ), ); } Widget _buildDetailContent(Promotion promotion) { return Scaffold( backgroundColor: Colors.white, body: Stack( children: [ // Scrollable Content CustomScrollView( slivers: [ // App Bar SliverAppBar( pinned: true, backgroundColor: AppColors.white, foregroundColor: AppColors.grey900, elevation: AppBarSpecs.elevation, leading: IconButton( icon: const FaIcon(FontAwesomeIcons.arrowLeft, color: Colors.black, size: 20), onPressed: () => context.pop(), ), title: const Text( 'Chi tiết khuyến mãi', style: TextStyle(color: Colors.black), ), centerTitle: false, actions: [ // Share Button IconButton( icon: const FaIcon(FontAwesomeIcons.shareNodes, color: Colors.black, size: 20), onPressed: _handleShare, ), // Bookmark Button IconButton( icon: FaIcon( _isBookmarked ? FontAwesomeIcons.solidBookmark : FontAwesomeIcons.bookmark, color: Colors.black, size: 20, ), onPressed: _handleBookmark, ), const SizedBox(width: AppSpacing.sm), ], ), // Content SliverToBoxAdapter( child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ // Banner Image _buildBannerImage(promotion), // Promotion Header _buildPromotionHeader(promotion), // Program Content Section _buildProgramContentSection(), // Terms & Conditions Section _buildTermsSection(), // Contact Info Section _buildContactSection(), // Bottom padding for action bar const SizedBox(height: 100), ], ), ), ], ), // Fixed Bottom Action Bar Positioned(left: 0, right: 0, bottom: 0, child: _buildActionBar()), ], ), ); } /// Build banner image section Widget _buildBannerImage(Promotion promotion) { return CachedNetworkImage( imageUrl: promotion.imageUrl, width: double.infinity, height: 200, fit: BoxFit.cover, placeholder: (context, url) => Container( height: 200, color: AppColors.grey100, child: const const CustomLoadingIndicator(), ), errorWidget: (context, url, error) => Container( height: 200, color: AppColors.grey100, child: const Center( child: FaIcon( FontAwesomeIcons.image, size: 64, color: AppColors.grey500, ), ), ), ); } /// Build promotion header with title and date Widget _buildPromotionHeader(Promotion promotion) { return Container( padding: const EdgeInsets.fromLTRB(16, 24, 16, 16), decoration: const BoxDecoration( border: Border(bottom: BorderSide(color: Color(0xFFE2E8F0), width: 1)), ), child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ // Title Text( promotion.title, style: const TextStyle( fontSize: 20, fontWeight: FontWeight.w700, color: Color(0xFF1E293B), height: 1.3, ), ), const SizedBox(height: 12), // Date Range and Status Wrap( spacing: 8, crossAxisAlignment: WrapCrossAlignment.center, children: [ // Clock icon and date const FaIcon( FontAwesomeIcons.clock, size: 16, color: Color(0xFFF59E0B), // warning color ), Text( _formatDateRange(promotion), style: const TextStyle( fontSize: 14, fontWeight: FontWeight.w500, color: Color(0xFFF59E0B), ), ), // Status Badge Container( padding: const EdgeInsets.symmetric( horizontal: 12, vertical: 4, ), decoration: BoxDecoration( color: const Color(0xFF10B981), // success color borderRadius: BorderRadius.circular(16), ), child: const Row( mainAxisSize: MainAxisSize.min, children: [ FaIcon( FontAwesomeIcons.fire, size: 14, color: Colors.white, ), SizedBox(width: 4), Text( 'Đang diễn ra', style: TextStyle( fontSize: 14, fontWeight: FontWeight.w500, color: Colors.white, ), ), ], ), ), ], ), ], ), ); } /// Build program content section Widget _buildProgramContentSection() { return const PromotionSection( title: 'Nội dung chương trình', icon: FontAwesomeIcons.gift, content: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ PromotionContentText( 'Chương trình khuyến mãi đặc biệt dành cho các công trình xây dựng với mức giảm giá hấp dẫn nhất trong năm.', ), // Highlight Box HighlightBox( emoji: '🎉', text: 'Giảm giá lên đến 30% cho tất cả sản phẩm gạch men cao cấp', ), // Discount Details PromotionContentText('Ưu đãi chi tiết:', isBold: true), PromotionBulletList( items: [ 'Gạch men 60x60cm: Giảm 25% - 30%', 'Gạch men 80x80cm: Giảm 20% - 25%', 'Gạch men 120x60cm: Giảm 15% - 20%', 'Gạch granite 60x60cm: Giảm 20% - 25%', 'Gạch ốp tường: Giảm 15% - 20%', ], ), SizedBox(height: 16), // Additional Benefits PromotionContentText('Ưu đãi bổ sung:', isBold: true), PromotionBulletList( items: [ 'Miễn phí vận chuyển cho đơn hàng từ 500m²', 'Tặng keo dán gạch cho đơn hàng từ 200m²', 'Hỗ trợ thiết kế 3D miễn phí', 'Bảo hành sản phẩm lên đến 15 năm', ], ), ], ), ); } /// Build terms and conditions section Widget _buildTermsSection() { return const PromotionSection( title: 'Điều kiện áp dụng', icon: FontAwesomeIcons.fileLines, content: PromotionBulletList( items: [ 'Áp dụng cho tất cả khách hàng là thợ xây dựng đã đăng ký tài khoản', 'Đơn hàng tối thiểu: 50m² sản phẩm gạch men', 'Thanh toán tối thiểu 50% giá trị đơn hàng khi đặt', 'Không áp dụng đồng thời với các chương trình khuyến mãi khác', 'Giá đã bao gồm VAT, chưa bao gồm phí vận chuyển', 'Sản phẩm không áp dụng đổi trả sau khi đã cắt, gia công', 'Thời gian giao hàng: 3-7 ngày làm việc tùy theo khu vực', 'Khuyến mãi có thể kết thúc sớm nếu hết hàng', ], ), ); } /// Build contact information section Widget _buildContactSection() { return const PromotionSection( title: 'Thông tin liên hệ', icon: FontAwesomeIcons.phone, isLast: true, content: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ ContactInfo( label: 'Hotline', value: '1900-xxxx (8:00 - 18:00 hàng ngày)', ), ContactInfo(label: 'Email', value: 'promotion@company.com'), ContactInfo(label: 'Zalo', value: '0123.456.789'), ], ), ); } /// Build fixed bottom action bar Widget _buildActionBar() { return Container( decoration: BoxDecoration( color: Colors.white, border: const Border( top: BorderSide(color: Color(0xFFE2E8F0), width: 1), ), boxShadow: [ BoxShadow( color: Colors.black.withValues(alpha: 0.1), blurRadius: 10, offset: const Offset(0, -2), ), ], ), padding: const EdgeInsets.all(16), child: SafeArea( top: false, child: ElevatedButton( onPressed: _handleViewProducts, style: ElevatedButton.styleFrom( backgroundColor: AppColors.primaryBlue, foregroundColor: Colors.white, padding: const EdgeInsets.symmetric(vertical: 16), shape: RoundedRectangleBorder( borderRadius: BorderRadius.circular(12), ), elevation: 0, ), child: const Row( mainAxisAlignment: MainAxisAlignment.center, children: [ FaIcon(FontAwesomeIcons.eye, size: 18), SizedBox(width: 8), Text( 'Xem sản phẩm áp dụng', style: TextStyle(fontSize: 16, fontWeight: FontWeight.w600), ), ], ), ), ), ); } /// Format date range for display String _formatDateRange(Promotion promotion) { final startDay = promotion.startDate.day.toString().padLeft(2, '0'); final startMonth = promotion.startDate.month.toString().padLeft(2, '0'); final startYear = promotion.startDate.year; final endDay = promotion.endDate.day.toString().padLeft(2, '0'); final endMonth = promotion.endDate.month.toString().padLeft(2, '0'); final endYear = promotion.endDate.year; return '$startDay/$startMonth/$startYear - $endDay/$endMonth/$endYear'; } /// Handle share button press void _handleShare() { ScaffoldMessenger.of(context).showSnackBar( const SnackBar( content: Text('Tính năng chia sẻ đang phát triển'), duration: Duration(seconds: 2), ), ); } /// Handle bookmark button press void _handleBookmark() { setState(() { _isBookmarked = !_isBookmarked; }); ScaffoldMessenger.of(context).showSnackBar( SnackBar( content: Text( _isBookmarked ? 'Đã lưu khuyến mãi' : 'Đã bỏ lưu khuyến mãi', ), duration: const Duration(seconds: 2), ), ); } /// Handle view products button press void _handleViewProducts() { // Navigate to products page context.push(RouteNames.products); } }