feat(app): Flutter-клиент — логин, дашборд, потоки, категории, транзакции, правила
Riverpod + go_router с auth-guard, NavigationRail на широком экране и bottom bar на узком. Токены в flutter_secure_storage, на web access живёт в памяти. Интерцептор подставляет токен и делает ровно один refresh на 401. Деньги приходят строками и форматируются через Decimal: парсить их в double значило бы терять копейки ровно там, где бэкенд их бережёт.
This commit is contained in:
@@ -0,0 +1,56 @@
|
||||
/// Russian month/date helpers that avoid needing `initializeDateFormatting`
|
||||
/// (which `intl`'s locale-aware `DateFormat` symbols require) for the small
|
||||
/// set of formats this app needs.
|
||||
library;
|
||||
|
||||
const _monthsNominative = [
|
||||
'январь',
|
||||
'февраль',
|
||||
'март',
|
||||
'апрель',
|
||||
'май',
|
||||
'июнь',
|
||||
'июль',
|
||||
'август',
|
||||
'сентябрь',
|
||||
'октябрь',
|
||||
'ноябрь',
|
||||
'декабрь',
|
||||
];
|
||||
|
||||
const _monthsShort = [
|
||||
'янв',
|
||||
'фев',
|
||||
'мар',
|
||||
'апр',
|
||||
'май',
|
||||
'июн',
|
||||
'июл',
|
||||
'авг',
|
||||
'сен',
|
||||
'окт',
|
||||
'ноя',
|
||||
'дек',
|
||||
];
|
||||
|
||||
/// `'сентябрь 2026'`.
|
||||
String ruMonthYear(DateTime d) {
|
||||
final name = _monthsNominative[d.month - 1];
|
||||
return '${name[0].toUpperCase()}${name.substring(1)} ${d.year}';
|
||||
}
|
||||
|
||||
/// `'сен 2026'`, for compact chart/table labels.
|
||||
String ruMonthYearShort(DateTime d) => '${_monthsShort[d.month - 1]} ${d.year}';
|
||||
|
||||
/// `'2026-09'`, the `month` query parameter format the API expects.
|
||||
String monthKey(DateTime d) => '${d.year.toString().padLeft(4, '0')}-${d.month.toString().padLeft(2, '0')}';
|
||||
|
||||
/// Parses a `'YYYY-MM'` key back into a [DateTime] (first of month, UTC).
|
||||
DateTime parseMonthKey(String key) {
|
||||
final parts = key.split('-');
|
||||
return DateTime.utc(int.parse(parts[0]), int.parse(parts[1]));
|
||||
}
|
||||
|
||||
/// `'12.09.2026'`.
|
||||
String ruDate(DateTime d) =>
|
||||
'${d.day.toString().padLeft(2, '0')}.${d.month.toString().padLeft(2, '0')}.${d.year}';
|
||||
Reference in New Issue
Block a user