style(app): остальные экраны под новый визуальный язык и форматирование

Доходы, ребалансировка, налоги, импорт, цели, здоровье данных, правила, транзакции, категории, cashflow, pending: новые виджеты и токены темы, dart format. Тесты подстроены под новые модели.
This commit is contained in:
Dmitry
2026-09-19 22:14:27 +03:00
parent 62d36aa3e8
commit 322c60a359
55 changed files with 2158 additions and 1080 deletions
+51 -21
View File
@@ -18,16 +18,22 @@ class PendingInstrumentsPage extends ConsumerStatefulWidget {
const PendingInstrumentsPage({super.key});
@override
ConsumerState<PendingInstrumentsPage> createState() => _PendingInstrumentsPageState();
ConsumerState<PendingInstrumentsPage> createState() =>
_PendingInstrumentsPageState();
}
class _PendingInstrumentsPageState extends ConsumerState<PendingInstrumentsPage> {
class _PendingInstrumentsPageState
extends ConsumerState<PendingInstrumentsPage> {
int? _busyId;
void _snack(String message) =>
ScaffoldMessenger.of(context).showSnackBar(SnackBar(content: Text(message)));
ScaffoldMessenger.of(context)
.showSnackBar(SnackBar(content: Text(message)));
Future<void> _run(int id, Future<PendingResolveResult> Function() action) async {
Future<void> _run(
int id,
Future<PendingResolveResult> Function() action,
) async {
setState(() => _busyId = id);
try {
final result = await action();
@@ -36,10 +42,12 @@ class _PendingInstrumentsPageState extends ConsumerState<PendingInstrumentsPage>
ref.invalidate(pendingCountProvider);
// Events moved out of `pending`, so holdings, allocation and the event list changed.
invalidateLedgerDependents(ref);
_snack(result.status == 'ignored'
? 'Строка помечена как «не инструмент»'
: 'Привязано событий: ${result.eventsBound}'
'${result.aliasCreated ? ', добавлен алиас' : ''}');
_snack(
result.status == 'ignored'
? 'Строка помечена как «не инструмент»'
: 'Привязано событий: ${result.eventsBound}'
'${result.aliasCreated ? ', добавлен алиас' : ''}',
);
} catch (e) {
if (!mounted) return;
_snack(importErrorMessage(e));
@@ -56,7 +64,10 @@ class _PendingInstrumentsPageState extends ConsumerState<PendingInstrumentsPage>
),
);
if (instrumentId == null || !mounted) return;
await _run(p.id, () => ref.read(pendingApiProvider).link(p.id, instrumentId));
await _run(
p.id,
() => ref.read(pendingApiProvider).link(p.id, instrumentId),
);
}
Future<void> _create(PendingInstrument p) async {
@@ -65,7 +76,10 @@ class _PendingInstrumentsPageState extends ConsumerState<PendingInstrumentsPage>
builder: (_) => CreateInstrumentDialog(pending: p),
);
if (instrument == null || !mounted) return;
await _run(p.id, () => ref.read(pendingApiProvider).create(p.id, instrument));
await _run(
p.id,
() => ref.read(pendingApiProvider).create(p.id, instrument),
);
}
Future<void> _ignore(PendingInstrument p) async {
@@ -73,14 +87,19 @@ class _PendingInstrumentsPageState extends ConsumerState<PendingInstrumentsPage>
context: context,
builder: (context) => AlertDialog(
title: const Text('Игнорировать строку?'),
content: Text('«${p.title}» больше не будет предлагаться к резолву. '
'Её события останутся без инструмента.'),
content: Text(
'«${p.title}» больше не будет предлагаться к резолву. '
'Её события останутся без инструмента.',
),
actions: [
TextButton(
onPressed: () => Navigator.of(context).pop(false), child: const Text('Отмена')),
onPressed: () => Navigator.of(context).pop(false),
child: const Text('Отмена'),
),
FilledButton(
onPressed: () => Navigator.of(context).pop(true),
child: const Text('Игнорировать')),
onPressed: () => Navigator.of(context).pop(true),
child: const Text('Игнорировать'),
),
],
),
);
@@ -164,7 +183,8 @@ class _StatusFilter extends ConsumerWidget {
ChoiceChip(
label: Text(e.value),
selected: current == e.key,
onSelected: (_) => ref.read(pendingStatusFilterProvider.notifier).state = e.key,
onSelected: (_) =>
ref.read(pendingStatusFilterProvider.notifier).state = e.key,
),
],
);
@@ -197,7 +217,8 @@ class _PendingCard extends StatelessWidget {
if (p.ticker != null) 'тикер ${p.ticker}',
if (p.board != null) 'доска ${p.board}',
if (p.currency != null) p.currency!,
if (p.assetClassHint != null) 'в отчёте: ${assetClassLabel(p.assetClassHint)}',
if (p.assetClassHint != null)
'в отчёте: ${assetClassLabel(p.assetClassHint)}',
];
final sample = <String>[
'встречается ${p.occurrences} раз',
@@ -214,18 +235,25 @@ class _PendingCard extends StatelessWidget {
children: [
Row(
children: [
Expanded(child: Text(p.title, style: theme.textTheme.titleMedium)),
Expanded(
child: Text(p.title, style: theme.textTheme.titleMedium),
),
if (!open)
Chip(
visualDensity: VisualDensity.compact,
label: Text(p.status == 'ignored' ? 'игнорируется' : 'привязан'),
label: Text(
p.status == 'ignored' ? 'игнорируется' : 'привязан',
),
),
],
),
if (facts.isNotEmpty)
Padding(
padding: const EdgeInsets.only(top: 4),
child: Text(facts.join(' · '), style: theme.textTheme.bodySmall),
child: Text(
facts.join(' · '),
style: theme.textTheme.bodySmall,
),
),
Padding(
padding: const EdgeInsets.only(top: 2),
@@ -236,7 +264,9 @@ class _PendingCard extends StatelessWidget {
child: Text(
'источник ${p.source} · ключ ${p.sourceKey}'
'${p.firstSeenFileId != null ? ' · файл №${p.firstSeenFileId}' : ''}',
style: theme.textTheme.bodySmall?.copyWith(color: theme.colorScheme.outline),
style: theme.textTheme.bodySmall?.copyWith(
color: theme.colorScheme.outline,
),
),
),
if (open) ...[