Files
Dmitry 322c60a359 style(app): остальные экраны под новый визуальный язык и форматирование
Доходы, ребалансировка, налоги, импорт, цели, здоровье данных, правила, транзакции, категории, cashflow, pending: новые виджеты и токены темы, dart format. Тесты подстроены под новые модели.
2026-09-19 22:14:27 +03:00

108 lines
3.3 KiB
Dart

import 'package:fintracker_api/fintracker_api.dart';
import 'package:flutter/material.dart';
import '../../core/utils/ru_date.dart';
import '../../core/widgets/money_text.dart';
/// The amount/currency/RUB-equivalent a transaction is shown with, chosen by
/// its [FlowType]: the outgoing leg for expenses and transfers out, the
/// incoming leg for income.
({String amount, String currency, String? rub}) primaryAmount(
TransactionOut t,
) {
switch (t.flowType) {
case FlowType.income:
return (
amount: t.income,
currency: t.incomeCurrency ?? 'RUB',
rub: t.incomeRub,
);
case FlowType.expense:
return (
amount: t.outcome,
currency: t.outcomeCurrency ?? 'RUB',
rub: t.outcomeRub,
);
case FlowType.internalTransfer:
case FlowType.savingsTransfer:
case FlowType.brokerExternalFlow:
case FlowType.other:
case FlowType.deleted:
case FlowType.unknownDefaultOpenApi:
if (t.outcome != '0' && t.outcomeCurrency != null) {
return (
amount: t.outcome,
currency: t.outcomeCurrency!,
rub: t.outcomeRub,
);
}
return (
amount: t.income,
currency: t.incomeCurrency ?? 'RUB',
rub: t.incomeRub,
);
}
}
(IconData, Color) flowTypeIcon(FlowType type, ColorScheme scheme) =>
switch (type) {
FlowType.income => (Icons.arrow_circle_down_outlined, Colors.green),
FlowType.expense => (Icons.arrow_circle_up_outlined, scheme.error),
FlowType.internalTransfer => (Icons.swap_horiz, scheme.primary),
FlowType.savingsTransfer => (
Icons.savings_outlined,
Colors.amber.shade800,
),
FlowType.brokerExternalFlow => (Icons.trending_up, Colors.deepPurple),
FlowType.other ||
FlowType.deleted ||
FlowType.unknownDefaultOpenApi => (Icons.help_outline, scheme.outline),
};
/// One row of the Операции list: date, payee, category, native amount with
/// its RUB equivalent when the currency differs, and a flow-type icon.
class TransactionRow extends StatelessWidget {
const TransactionRow({
required this.transaction,
required this.categoryName,
required this.onTap,
super.key,
});
final TransactionOut transaction;
final String? categoryName;
final VoidCallback onTap;
@override
Widget build(BuildContext context) {
final t = transaction;
final scheme = Theme.of(context).colorScheme;
final (icon, color) = flowTypeIcon(t.flowType, scheme);
final amount = primaryAmount(t);
final showRub = amount.currency != 'RUB' && amount.rub != null;
final payee = t.payeeCanonical?.isNotEmpty == true
? t.payeeCanonical!
: (t.payee ?? '—');
return ListTile(
onTap: onTap,
leading: Icon(icon, color: color),
title: Text(payee),
subtitle: Text([ruDate(t.date), ?categoryName].join(' · ')),
trailing: Column(
mainAxisAlignment: MainAxisAlignment.center,
crossAxisAlignment: CrossAxisAlignment.end,
children: [
MoneyText(amount.amount, currency: amount.currency),
if (showRub)
Text(
MoneyText.format(amount.rub!, 'RUB'),
style: Theme.of(context).textTheme.bodySmall
?.copyWith(color: scheme.outline),
),
],
),
);
}
}