feat(app): экраны портфеля — позиции, аллокация и карточка инструмента
Позиции и аллокация сделаны вкладками одного экрана, а не двумя пунктами навигации: они отвечают на две половины одного вопроса, и десятый пункт в bottom bar оставил бы по сорок пикселей на подпись. Scope переключается один раз и сразу для всех трёх экранов — три экрана с разными scope были бы ловушкой. Позиция без цены показывается прочерком, никогда нулём: её стоимость не входит в итоги выше, и 0 ₽ читался бы как «ничего не стоит» вместо «неизвестно». То же для общей прибыли, когда в портфеле есть хоть одна неоценённая бумага. Подписи ключей берутся по .value, а не по .name: генератор придумывает Dart-имя (assetClass для asset_class), и словарь, ключёванный по .name, молча не совпадает никогда. Тесты пампят экран на высокой поверхности: вкладки это длинные списки, а ListView строит только видимое, и на дефолтных 800x600 таблица позиций просто не существует.
This commit is contained in:
@@ -12,6 +12,7 @@ class _Destination {
|
||||
const _destinations = [
|
||||
_Destination('/', Icons.dashboard_outlined, Icons.dashboard, 'Обзор'),
|
||||
_Destination('/accounts', Icons.account_balance_outlined, Icons.account_balance, 'Счета'),
|
||||
_Destination('/portfolio', Icons.pie_chart_outline, Icons.pie_chart, 'Портфель'),
|
||||
_Destination('/cashflow', Icons.swap_horiz_outlined, Icons.swap_horiz, 'Потоки'),
|
||||
_Destination('/categories', Icons.category_outlined, Icons.category, 'Категории'),
|
||||
_Destination(
|
||||
@@ -36,8 +37,14 @@ class AppShell extends StatelessWidget {
|
||||
final Widget child;
|
||||
|
||||
int get _selectedIndex {
|
||||
final i = _destinations.indexWhere((d) => d.path == location);
|
||||
return i == -1 ? 0 : i;
|
||||
// longest prefix wins, so /portfolio/instrument/311 keeps Портфель selected
|
||||
var best = -1;
|
||||
for (var i = 0; i < _destinations.length; i++) {
|
||||
final path = _destinations[i].path;
|
||||
final matches = path == '/' ? location == '/' : location.startsWith(path);
|
||||
if (matches && (best == -1 || path.length > _destinations[best].path.length)) best = i;
|
||||
}
|
||||
return best == -1 ? 0 : best;
|
||||
}
|
||||
|
||||
void _onSelect(BuildContext context, int index) {
|
||||
|
||||
Reference in New Issue
Block a user