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:
Dmitry
2026-09-18 13:44:09 +03:00
parent b9c12fa1a1
commit ce0966fca2
99 changed files with 6284 additions and 0 deletions
+28
View File
@@ -0,0 +1,28 @@
import 'package:flutter/material.dart';
import 'package:flutter_riverpod/flutter_riverpod.dart';
import 'package:shared_preferences/shared_preferences.dart';
const _prefsKey = 'theme_mode';
final themeModeProvider = NotifierProvider<ThemeModeController, ThemeMode>(ThemeModeController.new);
/// Persists the chosen [ThemeMode] to this device via `shared_preferences`.
class ThemeModeController extends Notifier<ThemeMode> {
@override
ThemeMode build() {
Future.microtask(_restore);
return ThemeMode.system;
}
Future<void> _restore() async {
final prefs = await SharedPreferences.getInstance();
final saved = prefs.getString(_prefsKey);
state = ThemeMode.values.asNameMap()[saved] ?? ThemeMode.system;
}
Future<void> setMode(ThemeMode mode) async {
state = mode;
final prefs = await SharedPreferences.getInstance();
await prefs.setString(_prefsKey, mode.name);
}
}