/// Promotion Card Widget /// /// Displays an individual promotion with image, title, description, /// date range, and action button. library; import 'package:cached_network_image/cached_network_image.dart'; import 'package:flutter/material.dart'; import 'package:font_awesome_flutter/font_awesome_flutter.dart'; import 'package:go_router/go_router.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'; /// Promotion Card /// /// Shows: /// - Promotion image (150px height) /// - Title and description /// - Date range with calendar icon /// - "Chi tiết" button class PromotionCard extends StatelessWidget { /// Promotion data final Promotion promotion; /// Callback when card or detail button is tapped final VoidCallback? onTap; const PromotionCard({required this.promotion, this.onTap, super.key}); @override Widget build(BuildContext context) { return Container( margin: const EdgeInsets.only(bottom: 16), decoration: BoxDecoration( color: Colors.white, borderRadius: BorderRadius.circular(12), boxShadow: [ BoxShadow( color: Colors.black.withValues(alpha: 0.08), blurRadius: 8, offset: const Offset(0, 2), ), ], ), child: ClipRRect( borderRadius: BorderRadius.circular(12), child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ // Image CachedNetworkImage( imageUrl: promotion.imageUrl, height: 150, width: double.infinity, fit: BoxFit.cover, placeholder: (context, url) => Container( height: 150, color: AppColors.grey100, child: const Center(child: CircularProgressIndicator()), ), errorWidget: (context, url, error) => Container( height: 150, color: AppColors.grey100, child: const Center( child: FaIcon( FontAwesomeIcons.image, size: 48, color: AppColors.grey500, ), ), ), ), // Content Padding( padding: const EdgeInsets.all(16), child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ // Title Text( promotion.title, style: const TextStyle( fontSize: 14, fontWeight: FontWeight.bold, color: Color(0xFF212121), ), ), const SizedBox(height: 8), // Description Text( promotion.description, style: const TextStyle( fontSize: 12, color: Color(0xFF666666), ), maxLines: 2, overflow: TextOverflow.ellipsis, ), const SizedBox(height: 8), // Bottom row: Date and button Row( mainAxisAlignment: MainAxisAlignment.spaceBetween, crossAxisAlignment: CrossAxisAlignment.center, children: [ // Date range Expanded( child: Row( children: [ const FaIcon( FontAwesomeIcons.calendar, size: 12, color: AppColors.primaryBlue, ), const SizedBox(width: 4), Expanded( child: Text( _formatDateRange(), style: const TextStyle( fontSize: 12, color: AppColors.primaryBlue, ), maxLines: 1, overflow: TextOverflow.ellipsis, ), ), ], ), ), const SizedBox(width: 8), // Detail button ElevatedButton( onPressed: () { if (onTap != null) { onTap!(); } else { // Navigate to promotion detail page context.pushNamed( RouteNames.promotionDetail, extra: promotion, ); } }, style: ElevatedButton.styleFrom( backgroundColor: AppColors.primaryBlue, foregroundColor: Colors.white, padding: const EdgeInsets.symmetric( horizontal: 16, vertical: 8, ), minimumSize: Size.zero, tapTargetSize: MaterialTapTargetSize.shrinkWrap, shape: RoundedRectangleBorder( borderRadius: BorderRadius.circular(8), ), elevation: 0, ), child: const Text( 'Chi tiết', style: TextStyle( fontSize: 12, fontWeight: FontWeight.w500, ), ), ), ], ), ], ), ), ], ), ), ); } /// Format date range for display String _formatDateRange() { final startDay = promotion.startDate.day.toString().padLeft(2, '0'); final startMonth = promotion.startDate.month.toString().padLeft(2, '0'); final endDay = promotion.endDate.day.toString().padLeft(2, '0'); final endMonth = promotion.endDate.month.toString().padLeft(2, '0'); final year = promotion.endDate.year; return '$startDay/$startMonth - $endDay/$endMonth/$year'; } }