import 'package:please_pay_me/data/models/json.dart'; class Budget { const Budget({ required this.id, required this.userId, required this.name, required this.totalAmount, required this.startDate, required this.endDate, required this.currency, required this.isActive, }); factory Budget.fromJson(Map json) { return Budget( id: asInt(json['id']), userId: asInt(json['user_id']), name: asString(json['name']), totalAmount: asDouble(json['total_amount']), startDate: asDate(json['start_date']), endDate: asDate(json['end_date']), currency: asString(json['currency'], fallback: 'RUB'), isActive: asBool(json['is_active']), ); } final int id; final int userId; final String name; final double totalAmount; final DateTime startDate; final DateTime endDate; final String currency; final bool isActive; } /// Budget plus the server-computed daily envelope math. class BudgetStatus { const BudgetStatus({ required this.budget, required this.today, required this.daysLeft, required this.totalSpent, required this.remaining, required this.dailyLimit, required this.spentToday, required this.remainingToday, required this.isOverDaily, required this.isOverBudget, required this.isExpired, required this.selected, }); factory BudgetStatus.fromJson(Map json) { return BudgetStatus( budget: Budget.fromJson(asMap(json['budget'])), today: asDate(json['today']), daysLeft: asInt(json['days_left']), totalSpent: asDouble(json['total_spent']), remaining: asDouble(json['remaining']), dailyLimit: asDouble(json['daily_limit']), spentToday: asDouble(json['spent_today']), remainingToday: asDouble(json['remaining_today']), isOverDaily: asBool(json['is_over_daily']), isOverBudget: asBool(json['is_over_budget']), isExpired: asBool(json['is_expired']), selected: asBool(json['selected']), ); } final Budget budget; final DateTime today; final int daysLeft; final double totalSpent; final double remaining; final double dailyLimit; final double spentToday; final double remainingToday; final bool isOverDaily; final bool isOverBudget; final bool isExpired; final bool selected; /// 0..1 — share of the budget already spent. double get spentProgress { if (budget.totalAmount <= 0) return 0; return (totalSpent / budget.totalAmount).clamp(0.0, 1.0); } /// 0..1 — share of today's envelope already spent. double get dailyProgress { if (dailyLimit <= 0) return spentToday > 0 ? 1 : 0; return (spentToday / dailyLimit).clamp(0.0, 1.0); } } class BudgetsList { const BudgetsList({required this.items}); factory BudgetsList.fromJson(Map json) { return BudgetsList( items: asList(json['items']).map(BudgetStatus.fromJson).toList(), ); } final List items; }