From d140548e5faea5dbffb50b3e0369f87a90ba341c Mon Sep 17 00:00:00 2001 From: alexis Date: Sun, 12 Jul 2026 01:09:30 +0200 Subject: [PATCH] =?UTF-8?q?nouvelle=20transaction:=20fond=20dynamique=20ve?= =?UTF-8?q?rt/rouge=20+=20titre=20gras=20centr=C3=A9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- lib/app.dart | 152 +++++++++++++++++++++++---------------- lib/theme/app_theme.dart | 1 - 2 files changed, 89 insertions(+), 64 deletions(-) diff --git a/lib/app.dart b/lib/app.dart index 1c03dcd..61ce910 100644 --- a/lib/app.dart +++ b/lib/app.dart @@ -60,80 +60,106 @@ class _YnabAppState extends ConsumerState { DateTime date = DateTime.now(); bool isExpense = true; + final colorScheme = Theme.of(context).colorScheme; await showModalBottomSheet( context: context, isScrollControlled: true, useSafeArea: true, + backgroundColor: Colors.transparent, builder: (ctx) => StatefulBuilder( - builder: (context, setSheetState) => Padding( - padding: EdgeInsets.fromLTRB(24, 0, 24, MediaQuery.of(context).viewInsets.bottom + 24), - child: Column( - mainAxisSize: MainAxisSize.min, - crossAxisAlignment: CrossAxisAlignment.stretch, - children: [ - const SizedBox(height: 8), - Text('Nouvelle transaction', style: Theme.of(context).textTheme.titleLarge), - const SizedBox(height: 20), - 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), - SegmentedButton( - segments: const [ - ButtonSegment(value: true, label: Text('Dépense'), icon: Icon(Icons.arrow_upward)), - ButtonSegment(value: false, label: Text('Revenu'), icon: Icon(Icons.arrow_downward)), - ], - selected: {isExpense}, - onSelectionChanged: (v) => setSheetState(() => isExpense = v.first), - style: ButtonStyle( - visualDensity: VisualDensity.compact, + builder: (context, setSheetState) => Container( + decoration: BoxDecoration( + color: isExpense ? colorScheme.errorContainer : colorScheme.primaryContainer, + borderRadius: const BorderRadius.vertical(top: Radius.circular(20)), + ), + child: Padding( + padding: EdgeInsets.fromLTRB(24, 0, 24, MediaQuery.of(context).viewInsets.bottom + 24), + child: Column( + mainAxisSize: MainAxisSize.min, + crossAxisAlignment: CrossAxisAlignment.stretch, + children: [ + const SizedBox(height: 12), + Center( + child: Container( + width: 32, + height: 4, + decoration: BoxDecoration( + color: colorScheme.onSurfaceVariant.withAlpha(80), + borderRadius: BorderRadius.circular(2), + ), + ), ), - ), - const SizedBox(height: 12), - DropdownMenu( - initialSelection: accountId, - label: const Text('Compte'), - expandedInsets: EdgeInsets.zero, - dropdownMenuEntries: accounts - .map((a) => DropdownMenuEntry(value: a.id, label: a.name)) - .toList(), - onSelected: (v) { - if (v != null) accountId = v; - }, - ), - const SizedBox(height: 24), - FilledButton( - onPressed: () async { - final payee = payeeCtrl.text.trim(); - final amountStr = amountCtrl.text.trim().replaceAll(',', '.'); - final raw = double.tryParse(amountStr); - if (payee.isEmpty || raw == null || accountId == null) return; - final amount = isExpense ? -raw.abs() : raw.abs(); - await db.into(db.transactions).insert(TransactionsCompanion.insert( - accountId: accountId!, - payee: payee, - amount: amount, - date: date, - )); - if (context.mounted) Navigator.pop(context); - }, - child: const Text('Ajouter'), - ), - ], + const SizedBox(height: 16), + Text( + 'Nouvelle transaction', + textAlign: TextAlign.center, + style: Theme.of(context).textTheme.titleLarge?.copyWith( + fontWeight: FontWeight.bold, + ), + ), + const SizedBox(height: 20), + 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), + SegmentedButton( + segments: const [ + ButtonSegment(value: true, label: Text('Dépense'), icon: Icon(Icons.arrow_upward)), + ButtonSegment(value: false, label: Text('Revenu'), icon: Icon(Icons.arrow_downward)), + ], + selected: {isExpense}, + onSelectionChanged: (v) => setSheetState(() => isExpense = v.first), + style: ButtonStyle( + visualDensity: VisualDensity.compact, + ), + ), + const SizedBox(height: 12), + DropdownMenu( + initialSelection: accountId, + label: const Text('Compte'), + expandedInsets: EdgeInsets.zero, + dropdownMenuEntries: accounts + .map((a) => DropdownMenuEntry(value: a.id, label: a.name)) + .toList(), + onSelected: (v) { + if (v != null) accountId = v; + }, + ), + const SizedBox(height: 24), + FilledButton( + onPressed: () async { + final payee = payeeCtrl.text.trim(); + final amountStr = amountCtrl.text.trim().replaceAll(',', '.'); + final raw = double.tryParse(amountStr); + if (payee.isEmpty || raw == null || accountId == null) return; + final amount = isExpense ? -raw.abs() : raw.abs(); + await db.into(db.transactions).insert(TransactionsCompanion.insert( + accountId: accountId!, + payee: payee, + amount: amount, + date: date, + )); + if (context.mounted) Navigator.pop(context); + }, + child: const Text('Ajouter'), + ), + const SizedBox(height: 8), + ], + ), ), ), ), ); - } + } void _toggleSearch() { setState(() { _searchActive = !_searchActive; diff --git a/lib/theme/app_theme.dart b/lib/theme/app_theme.dart index 9cf4222..a20f920 100644 --- a/lib/theme/app_theme.dart +++ b/lib/theme/app_theme.dart @@ -109,7 +109,6 @@ final ThemeData ynabTheme = ThemeData( ), bottomSheetTheme: const BottomSheetThemeData( backgroundColor: kSurfaceCard, - showDragHandle: true, shape: RoundedRectangleBorder( borderRadius: BorderRadius.vertical(top: Radius.circular(20)), ),