import 'package:flutter/material.dart'; import 'package:flutter_riverpod/flutter_riverpod.dart'; import 'theme/app_theme.dart'; import 'screens/dashboard_screen.dart'; import 'screens/budget_screen.dart'; import 'screens/accounts_screen.dart'; import 'screens/transactions_screen.dart'; import 'providers/db_provider.dart'; import 'data/db.dart'; final _selectedIndexProvider = StateProvider((ref) => 0); class YnabApp extends ConsumerStatefulWidget { const YnabApp({super.key}); @override ConsumerState createState() => _YnabAppState(); } class _YnabAppState extends ConsumerState { late final List _screens; late final List<_NavItem> _navItems; final _searchController = TextEditingController(); bool _searchActive = false; @override void initState() { super.initState(); _screens = const [ DashboardScreen(), BudgetScreen(), AccountsScreen(), TransactionsScreen(), ]; _navItems = const [ _NavItem(icon: Icons.dashboard_outlined, selectedIcon: Icons.dashboard, label: 'Tableau de bord'), _NavItem(icon: Icons.pie_chart_outline, selectedIcon: Icons.pie_chart, label: 'Budget'), _NavItem(icon: Icons.account_balance_outlined, selectedIcon: Icons.account_balance, label: 'Comptes'), _NavItem(icon: Icons.receipt_long_outlined, selectedIcon: Icons.receipt_long, label: 'Transactions'), ]; } @override void dispose() { _searchController.dispose(); super.dispose(); } Future _addTransaction() async { final accounts = ref.read(openAccountsProvider); final db = ref.read(dbProvider); if (accounts.isEmpty) { ScaffoldMessenger.of(context).showSnackBar( const SnackBar(content: Text('Créez d\'abord un compte')), ); return; } final payeeCtrl = TextEditingController(); final amountCtrl = TextEditingController(); int? accountId = accounts.first.id; DateTime date = DateTime.now(); await showDialog( context: context, builder: (ctx) => AlertDialog( title: const Text('Nouvelle transaction'), content: SingleChildScrollView( child: Column( mainAxisSize: MainAxisSize.min, children: [ TextField( controller: payeeCtrl, decoration: const InputDecoration(labelText: 'Bénéficiaire', hintText: 'Ex: Supermarché'), autofocus: true, ), const SizedBox(height: 12), TextField( controller: amountCtrl, decoration: const InputDecoration(labelText: 'Montant', hintText: '0,00'), keyboardType: const TextInputType.numberWithOptions(decimal: true), ), const SizedBox(height: 12), DropdownButtonFormField( value: accountId, decoration: const InputDecoration(labelText: 'Compte'), items: accounts .map((a) => DropdownMenuItem(value: a.id, child: Text(a.name))) .toList(), onChanged: (v) => accountId = v, ), ], ), ), actions: [ TextButton( onPressed: () => Navigator.pop(ctx), child: const Text('Annuler'), ), FilledButton( onPressed: () async { final payee = payeeCtrl.text.trim(); final amountStr = amountCtrl.text.trim().replaceAll(',', '.'); final amount = double.tryParse(amountStr); if (payee.isEmpty || amount == null || accountId == null) return; await db.into(db.transactions).insert(TransactionsCompanion.insert( accountId: accountId!, payee: payee, amount: amount, date: date, )); if (ctx.mounted) Navigator.pop(ctx); }, child: const Text('Ajouter'), ), ], ), ); payeeCtrl.dispose(); amountCtrl.dispose(); } void _toggleSearch() { setState(() { _searchActive = !_searchActive; if (!_searchActive) { _searchController.clear(); ref.read(searchQueryProvider.notifier).state = ''; } }); } @override Widget build(BuildContext context) { final selectedIndex = ref.watch(_selectedIndexProvider); final theme = Theme.of(context); final colorScheme = theme.colorScheme; return Scaffold( appBar: AppBar( title: _searchActive ? TextField( controller: _searchController, autofocus: true, decoration: const InputDecoration( hintText: 'Rechercher…', border: InputBorder.none, isDense: true, ), onChanged: (v) => ref.read(searchQueryProvider.notifier).state = v, ) : Text(_navItems[selectedIndex].label), actions: [ if (_searchActive) IconButton( icon: const Icon(Icons.close), onPressed: _toggleSearch, tooltip: 'Fermer la recherche', ) else ...[ IconButton( icon: Icon(Icons.add, color: colorScheme.primary), onPressed: _addTransaction, tooltip: 'Ajouter une transaction', ), IconButton( icon: Icon(Icons.search, color: colorScheme.onSurfaceVariant), onPressed: _toggleSearch, tooltip: 'Rechercher', ), ], ], ), body: AnimatedSwitcher( duration: const Duration(milliseconds: 200), child: _screens[selectedIndex], ), bottomNavigationBar: NavigationBar( selectedIndex: selectedIndex, onDestinationSelected: (int index) { setState(() { _searchActive = false; _searchController.clear(); ref.read(searchQueryProvider.notifier).state = ''; }); ref.read(_selectedIndexProvider.notifier).state = index; }, destinations: _navItems.map((item) { return NavigationDestination( icon: Icon(item.icon), selectedIcon: Icon(item.selectedIcon), label: item.label, ); }).toList(), ), ); } } class _NavItem { final IconData icon; final IconData selectedIcon; final String label; const _NavItem({required this.icon, required this.selectedIcon, required this.label}); }