Files
fin-tracker/app/lib/features/events/labels.dart
T
Dmitry 62d36aa3e8 feat(app): новый визуальный язык, верхняя навигация, портфели, создание счетов и ручные события
Тема и общие виджеты (AssetIcon, ServiceMark, HelpTip, глоссарий), верхняя панель TopNav и вкладки Аналитики вместо NavSidebar, иконки PWA. Экраны: портфели, создание брокерского счёта, ручное событие, правка инструмента, Обзор карточками по скоупам и таблица активов, пересчёт метрик с опросом /metrics/status. design-system.md обновлён.
2026-09-19 22:14:21 +03:00

82 lines
3.2 KiB
Dart

import 'package:fintracker_api/fintracker_api.dart';
import 'package:flutter/material.dart';
import '../portfolio/labels.dart' show eventKindLabel;
export '../portfolio/labels.dart' show eventKindLabel, eventKindLabels;
/// The kinds worth offering as a filter, in the order a person scans for them: the two
/// trades first, then the payouts, then the money moving in and out. The wire enum has
/// more members (splits, amortization, the generated `unknown_default_open_api`), but a
/// dropdown listing every one of them is a worse filter than a short one.
const filterableEventKinds = [
EventKind.buy,
EventKind.sell,
EventKind.dividend,
EventKind.coupon,
EventKind.interest,
EventKind.commission,
EventKind.tax,
EventKind.deposit,
EventKind.withdrawal,
EventKind.transferIn,
EventKind.transferOut,
EventKind.fxExchange,
EventKind.repayment,
EventKind.other,
];
/// Statuses as a person reads them. Only `confirmed` feeds analytics, so which of these a
/// row carries is the answer to "why isn't this event in my numbers".
const eventStatusLabels = {
'confirmed': 'Подтверждено',
'pending': 'Ожидает',
'shadow': 'Теневое',
'ignored': 'Игнорируется',
};
String eventStatusLabel(EventStatus status) =>
eventStatusLabels[status.value] ?? status.value;
/// Icon and colour per kind, on the same principle as the transaction list: money coming
/// in is green, money leaving is the error colour, everything structural is neutral.
(IconData, Color) eventKindIcon(EventKind kind, ColorScheme scheme) =>
switch (kind) {
EventKind.buy => (Icons.add_shopping_cart, scheme.primary),
EventKind.sell => (Icons.sell_outlined, Colors.deepPurple),
EventKind.dividend ||
EventKind.coupon ||
EventKind.interest => (Icons.payments_outlined, Colors.green),
EventKind.taxRefund => (Icons.assignment_return_outlined, Colors.green),
EventKind.tax ||
EventKind.commission => (Icons.receipt_outlined, scheme.error),
EventKind.deposit => (Icons.arrow_circle_down_outlined, Colors.green),
EventKind.withdrawal => (Icons.arrow_circle_up_outlined, scheme.error),
EventKind.transferIn ||
EventKind.transferOut => (Icons.swap_horiz, scheme.primary),
EventKind.fxExchange => (Icons.currency_exchange, Colors.amber),
EventKind.split ||
EventKind.amortization ||
EventKind.repayment => (Icons.call_split, scheme.outline),
EventKind.other ||
EventKind.unknownDefaultOpenApi => (Icons.help_outline, scheme.outline),
};
/// `'Покупка · SBER'`, the one-line identity of a row. Events with no instrument behind
/// them (deposits, fees) keep just the kind.
String eventTitle(EventKind kind, String? ticker) =>
ticker == null || ticker.isEmpty
? eventKindLabel(kind)
: '${eventKindLabel(kind)} · $ticker';
/// Where a ledger event came from, as a person reads it.
const eventSourceLabels = {
'tinvest': 'T-Invest',
'report_sber': 'Отчёт Сбера',
'report_vtb': 'Отчёт ВТБ',
'csv': 'CSV',
'manual': 'Введено вручную',
};
String eventSourceLabel(String source) => eventSourceLabels[source] ?? source;