feat(app): offline-кэш на остальных экранах — фаза 5
accounts, cashflow, categories, goals, income, portfolio (+instrument), rebalance, tax, rules переведены на Cached<T> по контракту docs/ai/offline-cache.md. Общие/второстепенные селекторы (scopesProvider, categoriesListProvider и т.п.) оставлены как есть — не основной контент экрана. sync_page.dart и settings_page.dart не тронуты (первый — заменён health-page отдельно, второй — чистые действия без списка для баннера).
This commit is contained in:
@@ -5,9 +5,11 @@ import 'package:flutter_riverpod/flutter_riverpod.dart';
|
||||
|
||||
import '../../core/api/api_client.dart';
|
||||
import '../../core/auth/auth_controller.dart';
|
||||
import '../../core/cache/cached.dart';
|
||||
import '../../core/widgets/async_value_view.dart';
|
||||
import '../../core/widgets/empty_state.dart';
|
||||
import '../../core/widgets/money_text.dart';
|
||||
import '../../core/widgets/stale_banner.dart';
|
||||
import 'providers.dart';
|
||||
|
||||
const _roleOrder = [AccountRole.liquid, AccountRole.savings, AccountRole.investment, AccountRole.debt];
|
||||
@@ -42,6 +44,7 @@ class AccountsPage extends ConsumerWidget {
|
||||
@override
|
||||
Widget build(BuildContext context, WidgetRef ref) {
|
||||
final accounts = ref.watch(accountsProvider);
|
||||
final stale = oldestFetch([accounts.valueOrNull?.fetchedAt]);
|
||||
|
||||
return Scaffold(
|
||||
appBar: AppBar(title: const Text('Счета')),
|
||||
@@ -50,7 +53,8 @@ class AccountsPage extends ConsumerWidget {
|
||||
child: AsyncValueView(
|
||||
value: accounts,
|
||||
onRetry: () => ref.invalidate(accountsProvider),
|
||||
data: (rows) {
|
||||
data: (cached) {
|
||||
final rows = cached.data;
|
||||
if (rows.isEmpty) {
|
||||
return ListView(
|
||||
children: const [
|
||||
@@ -66,6 +70,7 @@ class AccountsPage extends ConsumerWidget {
|
||||
return ListView(
|
||||
padding: const EdgeInsets.all(16),
|
||||
children: [
|
||||
if (stale != null) StaleBanner(fetchedAt: stale),
|
||||
for (final role in _roleOrder)
|
||||
if (active.any((a) => a.role == role))
|
||||
_RoleSection(
|
||||
|
||||
Reference in New Issue
Block a user