feat(app): новый визуальный язык, верхняя навигация, портфели, создание счетов и ручные события

Тема и общие виджеты (AssetIcon, ServiceMark, HelpTip, глоссарий), верхняя панель TopNav и вкладки Аналитики вместо NavSidebar, иконки PWA. Экраны: портфели, создание брокерского счёта, ручное событие, правка инструмента, Обзор карточками по скоупам и таблица активов, пересчёт метрик с опросом /metrics/status. design-system.md обновлён.
This commit is contained in:
Dmitry
2026-09-19 22:14:21 +03:00
parent a559d6de3e
commit 62d36aa3e8
73 changed files with 6406 additions and 1192 deletions
+149
View File
@@ -0,0 +1,149 @@
/// Plain-language explanations of the terms and abbreviations the screens print, looked up by
/// the label as it appears. One place, so a term means the same on every screen and a wording
/// fix is a one-line change. `TermLabel` (`widgets/help_tip.dart`) calls [glossaryHint] and
/// draws a «?» next to any label that has an entry.
library;
const _entries = <String, String>{
// returns
'xirr':
'XIRR — годовая доходность с учётом дат и сумм ваших пополнений и выводов '
'(денежно-взвешенная): сколько вы заработали на своих деньгах в пересчёте на год. '
'На очень коротких сроках может быть недоступна или сильно завышена.',
'xirr, год':
'XIRR за последние 12 месяцев — годовая доходность с учётом дат и сумм ваших '
'пополнений и выводов.',
'twr':
'TWR — доходность самого портфеля без влияния пополнений и выводов: дневные '
'доходности перемножаются. Подходит, чтобы честно сравнивать с индексом.',
'twr, год':
'TWR за последние 12 месяцев — доходность портфеля без влияния пополнений и '
'выводов. «Пропущено N дн.» — дни, когда часть бумаг была без цены.',
'доходность':
'Доходность — XIRR: годовая доходность с учётом дат и сумм ваших пополнений '
'и выводов. «—» — если посчитать нечего или срок слишком короткий.',
'прибыль':
'Прибыль — на сколько текущая стоимость больше (или меньше) вложенного. По позиции: '
'рыночная стоимость минус стоимость покупки, процент — от вложенного. Пока у части бумаг '
'нет цены, итог показывается как «—».',
'нереализованная':
'Нереализованная прибыль — на сколько бумага подорожала или подешевела '
'относительно покупки, пока вы её не продали.',
'нереализ.':
'Нереализованная прибыль — на сколько бумага подорожала или подешевела '
'относительно покупки, пока вы её не продали.',
'реализованная':
'Реализованная прибыль — результат по уже проданным бумагам (правило FIFO: '
'первыми продаются самые ранние покупки).',
'реализовано':
'Реализованный результат по уже проданным бумагам (правило FIFO: первыми '
'продаются самые ранние покупки).',
'за день':
'За день — изменение результата за последний торговый день. Пополнения и выводы '
'в него не входят, только движение цен и выплаты.',
'потоки': 'Внешние потоки за период: пополнения за вычетом выводов.',
// value
'вложено':
'Вложено — стоимость покупки (для всего портфеля — пополнения минус выводы). '
'Ниже — средняя цена покупки за штуку.',
'текущая стоимость':
'Количество × последняя цена. Ниже — цена за одну бумагу. «—» значит, '
'что цены нет и стоимость неизвестна.',
'доля': 'Доля позиции в общей стоимости выбранного набора счетов.',
'доля в портфеле': 'Доля позиции в общей стоимости выбранного набора счетов.',
'выплаты': 'Полученные дивиденды и купоны за всё время.',
'дивиденды': 'Полученные по бумаге дивиденды и купоны за всё время.',
'див. доходность':
'Полученные выплаты в процентах от вложенного в позицию за всё время '
'владения.',
'пассивный доход':
'Пассивный доход — ожидаемые дивиденды и купоны за ближайшие 12 месяцев: '
'по объявленным выплатам, графику купонов облигаций и (для дивидендов) по истории за два '
'года. Это оценка, а не обещание. Процент — от текущей стоимости.',
'нкд':
'НКД — накопленный купонный доход: часть очередного купона, набежавшая с даты '
'последней выплаты. Покупатель облигации доплачивает его продавцу.',
// capital and cash
'капитал сегодня':
'Капитал — всё, чем вы владеете, за вычетом долгов: деньги и сбережения на '
'счетах ZenMoney плюс стоимость активных брокерских счетов.',
'ликвидные': 'Деньги, доступные сразу: карты, наличные, расчётные счета.',
'сбережения':
'Накопления, которые вы отложили: вклады и накопительные счета. Роль счёта '
'задаётся на экране «Счета».',
'инвестиции': 'Стоимость брокерских счетов: бумаги по рыночным ценам плюс деньги на счёте.',
'долги': 'Кредиты и долги; входят в капитал со знаком минус.',
'запас хода (runway)':
'Запас хода — на сколько месяцев хватит ликвидных денег и сбережений '
'при вашем обычном расходе: (ликвидные + сбережения) ÷ средний «обычный» расход за три '
'последних полных месяца, без разовых трат. Инвестиции в запас не входят.',
'запас хода':
'Запас хода — на сколько месяцев хватит ликвидных денег и сбережений при вашем '
'обычном расходе (средний «обычный» расход за три последних полных месяца).',
'норма сбережений':
'Норма сбережений — доля дохода, которая осталась после расходов: '
'(доход − расход) ÷ доход за месяц.',
// events
'внешний поток':
'Внешний поток — событие, при котором деньги или бумаги пересекают границу '
'портфеля: пополнение, вывод, перевод бумаг. XIRR считается именно по внешним потокам.',
'внешние потоки':
'Показать только события, при которых деньги или бумаги пересекают границу '
'портфеля: пополнения, выводы, переводы бумаг. По ним считается XIRR.',
'статус':
'Подтверждено — событие учитывается в расчётах. Теневое — дубль из второстепенного '
'источника, нужен только для сверки. Ожидает — загружено, но ещё не записано в леджер. '
'Игнорируется — исключено.',
// portfolio tools
'сравнение с бенчмарками':
'Бенчмарк — индекс для сравнения (например, индекс Мосбиржи): '
'показывает, обгоняет ли ваш портфель рынок за тот же период.',
'целевые веса':
'Целевые веса — какую долю портфеля вы хотите держать в каждой категории. '
'Сумма по одному измерению должна быть 100 %.',
// accounts
'тип':
'Тип счёта — его роль в расчётах: ликвидные, сбережения, инвестиции или долги. От неё '
'зависит, в какую строку «Капитала» попадёт остаток.',
'в капитал':
'Входит ли остаток счёта в «Капитал» на Обзоре. Выключите для счетов-зеркал '
'(например, ZenMoney-копия брокерского счёта): иначе одни и те же деньги посчитаются дважды.',
'активен':
'Отключённый счёт не учитывается ни в капитале, ни в портфелях, ни в аналитике; его '
'история остаётся и вернётся при включении.',
// tax
'лдв':
'ЛДВ — льгота долгосрочного владения (ст. 219.1 НК РФ): при владении биржевой бумагой '
'три полных года и более налог с прибыли по ней уменьшается. В приложении это оценка.',
'дата лдв': 'Дата, с которой лот пробудет в портфеле три полных года и попадёт под ЛДВ.',
'дней до лдв': 'Сколько дней осталось до трёх лет владения этим лотом (ЛДВ).',
'освобождено по лдв':
'Часть прибыли, освобождённая от налога по ЛДВ (три года владения '
'биржевой бумагой). Оценка.',
'оценка налога':
'Приблизительный НДФЛ по вашим сделкам — для сверки со справкой брокера. '
'Окончательный расчёт делает брокер как налоговый агент.',
'налог (оценка)':
'Приблизительный НДФЛ по вашим сделкам — для сверки со справкой брокера. '
'Окончательный расчёт делает брокер.',
'налог при продаже':
'Сколько налога примерно придётся заплатить, если продать этот лот '
'сегодня. Оценка.',
'налоговая база':
'Сумма, с которой считается налог; приложение оценивает её по вашим '
'сделкам. Окончательный расчёт делает брокер.',
'база': 'Сумма, с которой считается налог; приложение оценивает её по вашим сделкам.',
'удержано брокером':
'Налог, который брокер уже удержал при выплате дивидендов и купонов.',
'удержано':
'Налог, который брокер уже удержал при выплате дивидендов и купонов.',
'убыток':
'Отрицательный результат по проданным бумагам; уменьшает налоговую базу.',
};
String _key(String label) => label.trim().toLowerCase().replaceAll('ё', 'е');
final _normalized = {for (final e in _entries.entries) _key(e.key): e.value};
/// The explanation for [label], or null when it is not a term worth explaining.
String? glossaryHint(String label) => _normalized[_key(label)];