feat(proj): init
This commit is contained in:
@@ -0,0 +1,108 @@
|
||||
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<String, dynamic> 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<String, dynamic> 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<String, dynamic> json) {
|
||||
return BudgetsList(
|
||||
items: asList(json['items']).map(BudgetStatus.fromJson).toList(),
|
||||
);
|
||||
}
|
||||
|
||||
final List<BudgetStatus> items;
|
||||
}
|
||||
Reference in New Issue
Block a user