// Author: fruit.com.cn import 'json_numbers.dart'; /// 奖励中心首屏数据。 class RewardOverview { const RewardOverview({ required this.serverDate, required this.timezone, required this.coinBalance, required this.checkin, this.sections = const [], this.activities = const [], }); final String serverDate; final String timezone; final int coinBalance; final RewardCheckinState checkin; final List sections; final List activities; factory RewardOverview.fromJson(Map json) { return RewardOverview( serverDate: json['serverDate'] as String? ?? '', timezone: json['timezone'] as String? ?? '', coinBalance: jsonToInt(json['coinBalance']), checkin: RewardCheckinState.fromJson(_map(json['checkin'])), sections: _maps(json['sections']).map(RewardSection.fromJson).toList(), activities: _maps( json['activities'], ).map(RewardActivity.fromJson).toList(), ); } } /// 七日签到状态。 class RewardCheckinState { const RewardCheckinState({ required this.taskId, required this.checkedInToday, required this.streak, required this.currentDay, this.days = const [], }); final String taskId; final bool checkedInToday; final int streak; final int currentDay; final List days; factory RewardCheckinState.fromJson(Map json) { return RewardCheckinState( taskId: (json['taskId'] ?? '').toString(), checkedInToday: json['checkedInToday'] == true, streak: jsonToInt(json['streak']), currentDay: jsonToInt(json['currentDay']), days: _maps(json['days']).map(RewardCheckinDay.fromJson).toList(), ); } } /// 签到周期中的一天。 class RewardCheckinDay { const RewardCheckinDay({ required this.dayIndex, required this.rewardCoin, required this.checked, required this.current, }); final int dayIndex; final int rewardCoin; final bool checked; final bool current; factory RewardCheckinDay.fromJson(Map json) { return RewardCheckinDay( dayIndex: jsonToInt(json['dayIndex']), rewardCoin: jsonToInt(json['rewardCoin']), checked: json['checked'] == true, current: json['current'] == true, ); } } /// 一组奖励任务。 class RewardSection { const RewardSection({ required this.code, required this.title, this.tasks = const [], }); final String code; final String title; final List tasks; factory RewardSection.fromJson(Map json) { return RewardSection( code: json['code'] as String? ?? '', title: json['title'] as String? ?? '', tasks: _maps(json['tasks']).map(RewardTask.fromJson).toList(), ); } } /// 奖励任务卡片。 class RewardTask { const RewardTask({ required this.id, required this.code, required this.type, required this.title, required this.subtitle, required this.ctaText, required this.actionType, required this.actionUrl, required this.progressValue, required this.targetValue, required this.rewardCoin, required this.status, this.iconUrl = '', }); final String id; final String code; final String type; final String title; final String subtitle; final String ctaText; final String actionType; final String actionUrl; final String iconUrl; final int progressValue; final int targetValue; final int rewardCoin; final String status; bool get claimable => status == 'COMPLETED'; bool get claimed => status == 'CLAIMED'; double get progress => targetValue <= 0 ? 0 : (progressValue / targetValue).clamp(0.0, 1.0); factory RewardTask.fromJson(Map json) { return RewardTask( id: (json['id'] ?? '').toString(), code: json['code'] as String? ?? '', type: json['type'] as String? ?? '', title: json['title'] as String? ?? '', subtitle: json['subtitle'] as String? ?? '', ctaText: json['ctaText'] as String? ?? '', actionType: json['actionType'] as String? ?? '', actionUrl: json['actionUrl'] as String? ?? '', iconUrl: json['iconUrl'] as String? ?? '', progressValue: jsonToInt(json['progressValue']), targetValue: jsonToInt(json['targetValue']), rewardCoin: jsonToInt(json['rewardCoin']), status: json['status'] as String? ?? 'IN_PROGRESS', ); } } /// 奖励活动展示卡片。 class RewardActivity { const RewardActivity({ required this.id, required this.code, required this.title, required this.summary, required this.ctaText, required this.actionType, required this.actionUrl, this.coverUrl = '', }); final String id; final String code; final String title; final String summary; final String ctaText; final String actionType; final String actionUrl; final String coverUrl; factory RewardActivity.fromJson(Map json) { return RewardActivity( id: (json['id'] ?? '').toString(), code: json['code'] as String? ?? '', title: json['title'] as String? ?? '', summary: json['summary'] as String? ?? '', ctaText: json['ctaText'] as String? ?? '', actionType: json['actionType'] as String? ?? '', actionUrl: json['actionUrl'] as String? ?? '', coverUrl: json['coverUrl'] as String? ?? '', ); } } /// 签到或任务领取后的余额变化结果。 class RewardActionResult { const RewardActionResult({ required this.rewardCoin, required this.coinBalance, required this.alreadyCompleted, }); final int rewardCoin; final int coinBalance; final bool alreadyCompleted; factory RewardActionResult.fromCheckin(Map json) { return RewardActionResult( rewardCoin: jsonToInt(json['rewardCoin']), coinBalance: jsonToInt(json['coinBalance']), alreadyCompleted: json['alreadyCheckedIn'] == true, ); } factory RewardActionResult.fromClaim(Map json) { return RewardActionResult( rewardCoin: jsonToInt(json['rewardCoin']), coinBalance: jsonToInt(json['coinBalance']), alreadyCompleted: json['alreadyGranted'] == true, ); } } Map _map(Object? value) { if (value is Map) return value; if (value is Map) return value.cast(); return const {}; } List> _maps(Object? value) { if (value is! List) return const []; return value .whereType() .map((item) => item.cast()) .toList(); }