import 'package:flutter/material.dart'; import 'package:intl/intl.dart'; import '../../../common/theme/theme.dart'; import '../../../domain/wallet/wallet.dart'; import '../../../sample/promo_sample_data.dart'; import '../../components/assets/assets.gen.dart'; import '../wallet/wallet_ui.dart'; /// Promo aktif dengan sisa hari segini dianggap segera berakhir. const int promoEndingSoonDays = 3; extension PromoTypeUi on PromoType { String get label => switch (this) { PromoType.point => 'EnakPoint', PromoType.coin => 'EnakCoin', PromoType.reward => 'Hadiah', }; /// Warna aksen untuk teks dan latar tipis; cukup gelap di atas putih. Color get color => switch (this) { PromoType.point => AppColor.primary, PromoType.coin => const Color(0xFFC26A00), PromoType.reward => AppColor.secondaryDark, }; /// Latar banner; teks putih di atasnya. List get gradient => switch (this) { PromoType.point => AppColor.primaryGradient, PromoType.coin => const [Color(0xFFF59E0B), Color(0xFFC2410C)], PromoType.reward => const [Color(0xFF43A047), Color(0xFF1B5E20)], }; } bool isPromoUpcoming(Promo promo) => promo.startDate.isAfter(DateTime.now()); /// Sisa hari kalender sampai [Promo.endDate]; 0 berarti berakhir hari ini. int promoDaysLeft(Promo promo) { final now = DateTime.now(); final today = DateTime(now.year, now.month, now.day); final end = DateTime( promo.endDate.year, promo.endDate.month, promo.endDate.day, ); return end.difference(today).inDays; } bool isPromoEndingSoon(Promo promo) => !isPromoUpcoming(promo) && promoDaysLeft(promo) <= promoEndingSoonDays; /// "12 Okt". String formatPromoDate(DateTime date) => DateFormat('d MMM', 'id_ID').format(date); /// "1 Okt – 25 Okt 2026". String promoPeriodLabel(Promo promo) => '${formatPromoDate(promo.startDate)} – ' '${DateFormat('d MMM yyyy', 'id_ID').format(promo.endDate)}'; String promoOutletLabel(Promo promo) => promo.outlets.isEmpty ? 'Semua outlet' : promo.outlets.join(', '); /// "Mulai 4 Okt" / "Berakhir 2 hari lagi" / "s/d 25 Okt". String promoTimeLabel(Promo promo) { if (isPromoUpcoming(promo)) { return 'Mulai ${formatPromoDate(promo.startDate)}'; } final daysLeft = promoDaysLeft(promo); if (daysLeft <= 0) return 'Berakhir hari ini'; if (daysLeft <= promoEndingSoonDays) return 'Berakhir $daysLeft hari lagi'; return 's/d ${formatPromoDate(promo.endDate)}'; } /// Ikon 3D sesuai hadiah promo. class PromoTypeIcon extends StatelessWidget { const PromoTypeIcon({super.key, required this.type, this.size = 32}); final PromoType type; final double size; @override Widget build(BuildContext context) { return switch (type) { PromoType.point => WalletCurrencyIcon( currency: WalletCurrency.point, size: size, ), PromoType.coin => WalletCurrencyIcon( currency: WalletCurrency.coin, size: size, ), PromoType.reward => Assets.icons.enakrewardIcon.image( width: size, height: size, fit: BoxFit.contain, // Aset aslinya besar; decode seukuran tampilan saja. cacheWidth: (size * MediaQuery.devicePixelRatioOf(context)).round(), ), }; } } /// Label waktu promo: biru bila belum mulai, oranye bila segera berakhir. class PromoTimeBadge extends StatelessWidget { const PromoTimeBadge({super.key, required this.promo}); final Promo promo; @override Widget build(BuildContext context) { final color = isPromoUpcoming(promo) ? AppColor.info : isPromoEndingSoon(promo) ? AppColor.warning : AppColor.textSecondary; return Container( padding: const EdgeInsets.symmetric(horizontal: 8, vertical: 3), decoration: BoxDecoration( color: color.withOpacity(0.1), borderRadius: BorderRadius.circular(20), ), child: Row( mainAxisSize: MainAxisSize.min, children: [ Icon(Icons.schedule, size: 12, color: color), const SizedBox(width: 4), Text( promoTimeLabel(promo), style: AppStyle.xs.copyWith( color: color, fontWeight: FontWeight.w700, ), ), ], ), ); } }