style(app): остальные экраны под новый визуальный язык и форматирование
Доходы, ребалансировка, налоги, импорт, цели, здоровье данных, правила, транзакции, категории, cashflow, pending: новые виджеты и токены темы, dart format. Тесты подстроены под новые модели.
This commit is contained in:
@@ -61,7 +61,10 @@ class CashflowPage extends ConsumerWidget {
|
||||
scrollDirection: Axis.horizontal,
|
||||
reverse: true,
|
||||
child: SizedBox(
|
||||
width: (rows.length * 56).toDouble().clamp(320, double.infinity),
|
||||
width: (rows.length * 56).toDouble().clamp(
|
||||
320,
|
||||
double.infinity,
|
||||
),
|
||||
child: _CashflowChart(rows: rows),
|
||||
),
|
||||
),
|
||||
@@ -102,7 +105,11 @@ class _LegendDot extends StatelessWidget {
|
||||
return Row(
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
children: [
|
||||
Container(width: 10, height: 10, decoration: BoxDecoration(color: color, shape: BoxShape.circle)),
|
||||
Container(
|
||||
width: 10,
|
||||
height: 10,
|
||||
decoration: BoxDecoration(color: color, shape: BoxShape.circle),
|
||||
),
|
||||
const SizedBox(width: 6),
|
||||
Text(label, style: Theme.of(context).textTheme.bodySmall),
|
||||
],
|
||||
@@ -119,7 +126,11 @@ class _CashflowChart extends StatelessWidget {
|
||||
Widget build(BuildContext context) {
|
||||
final maxY = rows.fold<double>(
|
||||
0,
|
||||
(m, r) => [m, _d(r.incomeRub), _d(r.expenseRub)].reduce((a, b) => a > b ? a : b),
|
||||
(m, r) => [
|
||||
m,
|
||||
_d(r.incomeRub),
|
||||
_d(r.expenseRub),
|
||||
].reduce((a, b) => a > b ? a : b),
|
||||
);
|
||||
return BarChart(
|
||||
BarChartData(
|
||||
@@ -127,9 +138,15 @@ class _CashflowChart extends StatelessWidget {
|
||||
gridData: const FlGridData(drawVerticalLine: false),
|
||||
borderData: FlBorderData(show: false),
|
||||
titlesData: FlTitlesData(
|
||||
topTitles: const AxisTitles(sideTitles: SideTitles(showTitles: false)),
|
||||
rightTitles: const AxisTitles(sideTitles: SideTitles(showTitles: false)),
|
||||
leftTitles: const AxisTitles(sideTitles: SideTitles(showTitles: false)),
|
||||
topTitles: const AxisTitles(
|
||||
sideTitles: SideTitles(showTitles: false),
|
||||
),
|
||||
rightTitles: const AxisTitles(
|
||||
sideTitles: SideTitles(showTitles: false),
|
||||
),
|
||||
leftTitles: const AxisTitles(
|
||||
sideTitles: SideTitles(showTitles: false),
|
||||
),
|
||||
bottomTitles: AxisTitles(
|
||||
sideTitles: SideTitles(
|
||||
showTitles: true,
|
||||
@@ -138,7 +155,10 @@ class _CashflowChart extends StatelessWidget {
|
||||
if (i < 0 || i >= rows.length) return const SizedBox.shrink();
|
||||
return Padding(
|
||||
padding: const EdgeInsets.only(top: 6),
|
||||
child: Text(ruMonthYearShort(rows[i].month), style: const TextStyle(fontSize: 10)),
|
||||
child: Text(
|
||||
ruMonthYearShort(rows[i].month),
|
||||
style: const TextStyle(fontSize: 10),
|
||||
),
|
||||
);
|
||||
},
|
||||
),
|
||||
@@ -160,8 +180,16 @@ class _CashflowChart extends StatelessWidget {
|
||||
BarChartGroupData(
|
||||
x: i,
|
||||
barRods: [
|
||||
BarChartRodData(toY: _d(rows[i].incomeRub), color: _incomeColor, width: 8),
|
||||
BarChartRodData(toY: _d(rows[i].expenseRub), color: _expenseColor, width: 8),
|
||||
BarChartRodData(
|
||||
toY: _d(rows[i].incomeRub),
|
||||
color: _incomeColor,
|
||||
width: 8,
|
||||
),
|
||||
BarChartRodData(
|
||||
toY: _d(rows[i].expenseRub),
|
||||
color: _expenseColor,
|
||||
width: 8,
|
||||
),
|
||||
],
|
||||
barsSpace: 2,
|
||||
),
|
||||
@@ -188,13 +216,20 @@ class _Table extends StatelessWidget {
|
||||
DataColumn(label: Text('Расход', style: headerStyle), numeric: true),
|
||||
DataColumn(label: Text('Базовые', style: headerStyle), numeric: true),
|
||||
DataColumn(label: Text('Разовые', style: headerStyle), numeric: true),
|
||||
DataColumn(label: Text('В сбережения', style: headerStyle), numeric: true),
|
||||
DataColumn(label: Text('Норма сбер., %', style: headerStyle), numeric: true),
|
||||
DataColumn(
|
||||
label: Text('В сбережения', style: headerStyle),
|
||||
numeric: true,
|
||||
),
|
||||
DataColumn(
|
||||
label: Text('Норма сбер., %', style: headerStyle),
|
||||
numeric: true,
|
||||
),
|
||||
],
|
||||
rows: [
|
||||
for (final r in rows.reversed)
|
||||
DataRow(
|
||||
onSelectChanged: (_) => context.go('/categories?month=${monthKey(r.month)}'),
|
||||
onSelectChanged: (_) =>
|
||||
context.go('/categories?month=${monthKey(r.month)}'),
|
||||
cells: [
|
||||
DataCell(Text(ruMonthYearShort(r.month))),
|
||||
DataCell(MoneyText(r.incomeRub, currency: 'RUB')),
|
||||
@@ -202,9 +237,13 @@ class _Table extends StatelessWidget {
|
||||
DataCell(MoneyText(r.baselineRub, currency: 'RUB')),
|
||||
DataCell(MoneyText(r.oneOffRub, currency: 'RUB')),
|
||||
DataCell(MoneyText(r.savingsTransferRub, currency: 'RUB')),
|
||||
DataCell(Text(r.savingsRate == null
|
||||
? '—'
|
||||
: '${(_d(r.savingsRate!) * 100).toStringAsFixed(1)}%')),
|
||||
DataCell(
|
||||
Text(
|
||||
r.savingsRate == null
|
||||
? '—'
|
||||
: '${(_d(r.savingsRate!) * 100).toStringAsFixed(1)}%',
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
],
|
||||
|
||||
@@ -5,7 +5,14 @@ import '../../core/api/api_client.dart';
|
||||
import '../../core/cache/cached.dart';
|
||||
|
||||
/// The last 24 months, oldest first (as the API returns them). See `docs/ai/offline-cache.md`.
|
||||
final cashflowMonthly24Provider = FutureProvider.autoDispose<Cached<List<CashFlowMonth>>>((ref) async {
|
||||
final r = await ref.watch(apiProvider).getCashflowApi().cashflowMonthly(months: 24);
|
||||
return Cached(r.data ?? const [], fetchedAt: r.extra['fetchedAt'] as DateTime?);
|
||||
});
|
||||
final cashflowMonthly24Provider =
|
||||
FutureProvider.autoDispose<Cached<List<CashFlowMonth>>>((ref) async {
|
||||
final r = await ref
|
||||
.watch(apiProvider)
|
||||
.getCashflowApi()
|
||||
.cashflowMonthly(months: 24);
|
||||
return Cached(
|
||||
r.data ?? const [],
|
||||
fetchedAt: r.extra['fetchedAt'] as DateTime?,
|
||||
);
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user