Тема и общие виджеты (AssetIcon, ServiceMark, HelpTip, глоссарий), верхняя панель TopNav и вкладки Аналитики вместо NavSidebar, иконки PWA. Экраны: портфели, создание брокерского счёта, ручное событие, правка инструмента, Обзор карточками по скоупам и таблица активов, пересчёт метрик с опросом /metrics/status. design-system.md обновлён.
64 lines
2.2 KiB
Dart
64 lines
2.2 KiB
Dart
import 'package:dio/dio.dart';
|
|
import 'package:fintracker_api/fintracker_api.dart';
|
|
import 'package:flutter_riverpod/flutter_riverpod.dart';
|
|
|
|
import '../../core/api/api_client.dart';
|
|
import '../../core/auth/auth_controller.dart';
|
|
import '../portfolio/providers.dart' show scopesProvider;
|
|
import '../portfolios/providers.dart' show portfolioListProvider;
|
|
import '../rebalance/providers.dart' show portfoliosProvider;
|
|
import 'providers.dart';
|
|
|
|
/// Changes to accounts: one place for a single switch and for a bulk edit.
|
|
abstract class AccountActions {
|
|
/// Applies [patch] to every account in [ids]. Returns null on success, or a message naming
|
|
/// how many failed and why. One failure does not stop the rest: a bulk «отключить» that
|
|
/// stalls on the 20th of 30 accounts would leave the list half changed and silent.
|
|
Future<String?> patch(Iterable<int> ids, AccountPatch patch);
|
|
}
|
|
|
|
final accountActionsProvider = Provider<AccountActions>(
|
|
(ref) => _ApiAccountActions(ref),
|
|
);
|
|
|
|
class _ApiAccountActions implements AccountActions {
|
|
_ApiAccountActions(this._ref);
|
|
|
|
final Ref _ref;
|
|
|
|
@override
|
|
Future<String?> patch(Iterable<int> ids, AccountPatch patch) async {
|
|
final list = ids.toList();
|
|
final api = _ref.read(apiProvider).getAccountsApi();
|
|
var failed = 0;
|
|
String? reason;
|
|
for (final id in list) {
|
|
try {
|
|
await api.accountsPatch(accountId: id, accountPatch: patch);
|
|
} on DioException catch (e) {
|
|
failed++;
|
|
reason ??= problemMessage(e);
|
|
}
|
|
}
|
|
_ref.invalidate(accountsProvider);
|
|
if (patch.disabled != null ||
|
|
patch.includeInNetWorth != null ||
|
|
patch.role != null) {
|
|
// net worth, scopes and portfolios all follow these switches: refetch what is derived
|
|
// from them and rebuild the metrics once, however many accounts changed
|
|
_ref
|
|
..invalidate(scopesProvider)
|
|
..invalidate(portfolioListProvider)
|
|
..invalidate(portfoliosProvider);
|
|
try {
|
|
await _ref.read(apiProvider).getMetricsApi().metricsRefresh();
|
|
} on DioException {
|
|
// the next scheduled or manual refresh picks the change up
|
|
}
|
|
}
|
|
return failed == 0
|
|
? null
|
|
: 'Не удалось изменить $failed из ${list.length}: $reason';
|
|
}
|
|
}
|