Месячная сетка с дивидендами, купонами, амортизациями и погашениями по дням, выплаченными и ожидаемыми, с сводкой за месяц и списком выплат выбранного дня. Раскладка без прокрутки страницы: высота ячеек подстраивается под окно, на широком экране список справа. Прежний список остался вторым режимом.
97 lines
3.4 KiB
Dart
97 lines
3.4 KiB
Dart
import 'package:flutter_riverpod/flutter_riverpod.dart';
|
|
|
|
import '../../core/api/api_client.dart';
|
|
import '../../core/cache/cached.dart';
|
|
import '../portfolio/providers.dart' show scopeProvider;
|
|
import 'data/income_api.dart';
|
|
|
|
final incomeApiProvider = Provider<IncomeApi>(
|
|
(ref) => IncomeApi(ref.watch(apiProvider).dio),
|
|
);
|
|
|
|
/// How far the calendar looks ahead, in months. 12 is the contract default.
|
|
final calendarMonthsProvider = StateProvider<int>((ref) => 12);
|
|
|
|
final calendarIncludePaidProvider = StateProvider<bool>((ref) => false);
|
|
|
|
/// Доходы shares the portfolio-wide [scopeProvider]: switching the scope on Портфель must
|
|
/// not leave the income calendar showing a different portfolio. See `docs/ai/offline-cache.md`.
|
|
final incomeCalendarProvider =
|
|
FutureProvider.autoDispose<Cached<IncomeCalendar>>((ref) async {
|
|
final scope = ref.watch(scopeProvider);
|
|
final months = ref.watch(calendarMonthsProvider);
|
|
final includePaid = ref.watch(calendarIncludePaidProvider);
|
|
final now = DateTime.now();
|
|
return ref
|
|
.watch(incomeApiProvider)
|
|
.calendar(
|
|
scope: scope,
|
|
dateFrom: DateTime(now.year, now.month, now.day),
|
|
dateTo: DateTime(now.year, now.month + months, now.day),
|
|
includePaid: includePaid,
|
|
);
|
|
});
|
|
|
|
enum CalendarView { month, list }
|
|
|
|
/// The calendar opens as a month grid; the list of the coming payments is the other view.
|
|
final calendarViewProvider = StateProvider<CalendarView>(
|
|
(ref) => CalendarView.month,
|
|
);
|
|
|
|
/// The month the grid shows, as the first day of it.
|
|
final calendarMonthProvider = StateProvider<DateTime>((ref) {
|
|
final now = DateTime.now();
|
|
return DateTime(now.year, now.month);
|
|
});
|
|
|
|
/// Every payment of one month, the paid ones included: a calendar of a month is the record of
|
|
/// it as well as the plan. Keyed by the first day of the month.
|
|
final incomeMonthProvider = FutureProvider.autoDispose
|
|
.family<Cached<IncomeCalendar>, DateTime>((ref, month) async {
|
|
final scope = ref.watch(scopeProvider);
|
|
return ref
|
|
.watch(incomeApiProvider)
|
|
.calendar(
|
|
scope: scope,
|
|
dateFrom: DateTime(month.year, month.month, 1),
|
|
dateTo: DateTime(month.year, month.month + 1, 0),
|
|
includePaid: true,
|
|
);
|
|
});
|
|
|
|
/// How far the history goes back, in months.
|
|
final historyMonthsProvider = StateProvider<int>((ref) => 24);
|
|
|
|
final incomeHistoryProvider = FutureProvider.autoDispose<Cached<IncomeHistory>>(
|
|
(ref) async {
|
|
final scope = ref.watch(scopeProvider);
|
|
final months = ref.watch(historyMonthsProvider);
|
|
final now = DateTime.now();
|
|
return ref
|
|
.watch(incomeApiProvider)
|
|
.history(
|
|
scope: scope,
|
|
dateFrom: DateTime(now.year, now.month - months + 1, 1),
|
|
dateTo: DateTime(now.year, now.month + 1, 0),
|
|
);
|
|
},
|
|
);
|
|
|
|
final forecastMonthsProvider = StateProvider<int>((ref) => 12);
|
|
|
|
final incomeForecastProvider =
|
|
FutureProvider.autoDispose<Cached<IncomeForecast>>((ref) async {
|
|
final scope = ref.watch(scopeProvider);
|
|
return ref
|
|
.watch(incomeApiProvider)
|
|
.forecast(scope: scope, months: ref.watch(forecastMonthsProvider));
|
|
});
|
|
|
|
void invalidateIncomeProviders(WidgetRef ref) {
|
|
ref.invalidate(incomeCalendarProvider);
|
|
ref.invalidate(incomeMonthProvider);
|
|
ref.invalidate(incomeHistoryProvider);
|
|
ref.invalidate(incomeForecastProvider);
|
|
}
|