Files
enaklo-flutter/lib/presentation/pages/reward/reward_ui.dart
T
efrilmandClaude Opus 5.5 f5e3075205 EnakPoint & EnakCoin wallet, PIN, outlet, order, community, reward
- Wallet EnakPoint & EnakCoin: beranda, riwayat, saldo kedaluwarsa, kode
  bayar, tukar EnakCoin, transfer
- PIN (buat, ganti, lupa), outlet, riwayat order, game spin
- Halaman community, webview, coming soon, dan ikon menu beranda baru
- Redesign Reward Saya: kartu tiket, filter chip, detail kode + QR
- Hapus customer point loader, menu, dan checkout lama
- Base URL ke enaklo-pos-api.altru.id

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-01 01:43:22 +07:00

99 lines
2.9 KiB
Dart

import 'package:flutter/material.dart';
import 'package:intl/intl.dart';
import '../../../common/theme/theme.dart';
import '../../../sample/reward_sample_data.dart';
/// Reward aktif dengan sisa masa berlaku segini dianggap segera berakhir.
const int rewardExpiringSoonDays = 7;
extension RewardStatusUi on RewardStatus {
String get label => switch (this) {
RewardStatus.active => 'Aktif',
RewardStatus.used => 'Terpakai',
RewardStatus.expired => 'Kedaluwarsa',
};
Color get color => switch (this) {
RewardStatus.active => AppColor.success,
RewardStatus.used => AppColor.textSecondary,
RewardStatus.expired => AppColor.error,
};
}
/// Tanggal pendek: "1 Okt 2026".
String formatRewardDate(DateTime date) =>
DateFormat('d MMM yyyy', 'id_ID').format(date);
/// Sisa hari kalender sampai [Reward.validUntil]; 0 berarti berakhir hari ini.
int rewardDaysLeft(Reward reward) {
final now = DateTime.now();
final today = DateTime(now.year, now.month, now.day);
final end = DateTime(
reward.validUntil.year,
reward.validUntil.month,
reward.validUntil.day,
);
return end.difference(today).inDays;
}
bool isRewardExpiringSoon(Reward reward) =>
reward.status == RewardStatus.active &&
rewardDaysLeft(reward) <= rewardExpiringSoonDays;
/// "Berakhir hari ini" / "Berakhir 3 hari lagi" / "Berlaku s/d 25 Okt 2026".
String rewardValidityLabel(Reward reward) {
final daysLeft = rewardDaysLeft(reward);
if (daysLeft <= 0) return 'Berakhir hari ini';
if (daysLeft <= rewardExpiringSoonDays) {
return 'Berakhir $daysLeft hari lagi';
}
return 'Berlaku s/d ${formatRewardDate(reward.validUntil)}';
}
class RewardStatusBadge extends StatelessWidget {
const RewardStatusBadge({super.key, required this.status});
final RewardStatus status;
@override
Widget build(BuildContext context) {
return Container(
padding: const EdgeInsets.symmetric(horizontal: 8, vertical: 3),
decoration: BoxDecoration(
color: status.color.withOpacity(0.1),
borderRadius: BorderRadius.circular(20),
),
child: Text(
status.label,
style: AppStyle.xs.copyWith(
color: status.color,
fontWeight: FontWeight.w700,
),
),
);
}
}
/// Emoji reward; abu-abu untuk reward yang sudah tidak bisa dipakai.
class RewardEmoji extends StatelessWidget {
const RewardEmoji({super.key, required this.reward, required this.size});
final Reward reward;
final double size;
static const ColorFilter _greyscale = ColorFilter.matrix([
0.2126, 0.7152, 0.0722, 0, 0, //
0.2126, 0.7152, 0.0722, 0, 0, //
0.2126, 0.7152, 0.0722, 0, 0, //
0, 0, 0, 0.5, 0, //
]);
@override
Widget build(BuildContext context) {
final emoji = Text(reward.emoji, style: TextStyle(fontSize: size));
if (reward.status == RewardStatus.active) return emoji;
return ColorFiltered(colorFilter: _greyscale, child: emoji);
}
}