From 582e21a7e2ddecdef1dd56bf4d0afd6b21ac01fa Mon Sep 17 00:00:00 2001 From: kolo Date: Fri, 20 Mar 2026 16:56:24 +0300 Subject: [PATCH] update --- lib/features/dashboard/provider.dart | 6 +++ lib/features/dashboard/screen.dart | 28 +++++----- lib/features/settings/screen.dart | 80 ++++++++++++++++++++++++++++ 3 files changed, 100 insertions(+), 14 deletions(-) diff --git a/lib/features/dashboard/provider.dart b/lib/features/dashboard/provider.dart index 2b0fd5b..5fcfa79 100644 --- a/lib/features/dashboard/provider.dart +++ b/lib/features/dashboard/provider.dart @@ -42,6 +42,12 @@ class TransactionsNotifier extends StateNotifier> { state = [...state, transaction]; _storage.addTransaction(transaction); } + + void clearAll() { + state = []; + // also clear from SharedPreferences: + SharedPreferences.getInstance().then((prefs) => prefs.remove('transactions')); + } } // Search and filter state diff --git a/lib/features/dashboard/screen.dart b/lib/features/dashboard/screen.dart index 9a2357d..1f6834e 100644 --- a/lib/features/dashboard/screen.dart +++ b/lib/features/dashboard/screen.dart @@ -10,22 +10,22 @@ import '../settings/provider.dart'; import 'provider.dart'; // Helper for balance card only - hides .00 decimals -String _formatBalanceAmount(String symbol, double amount, AmountFormat fmt) { +String _smartBalance(double amount, AmountFormat fmt, String symbol) { const spaceAfter = {'Br', '₽'}; final sep = spaceAfter.contains(symbol) ? ' ' : ''; + final isWhole = amount == amount.floorToDouble(); - // Check if decimal part is zero - final hasDecimals = (amount - amount.truncate()) != 0; - - if (!hasDecimals) { - // Format integer part only using the selected format style - final intAmount = amount.truncate().toDouble(); - // Use fmt.format but strip the .00 - final full = fmt.format(intAmount); - final withoutDecimals = full.endsWith('.00') ? full.substring(0, full.length - 3) : full; - return '$symbol$sep$withoutDecimals'; + String formatted; + if (isWhole) { + // format the integer, then manually remove .00 + formatted = fmt.format(amount); + if (formatted.endsWith('.00')) { + formatted = formatted.substring(0, formatted.length - 3); + } + } else { + formatted = fmt.format(amount); } - return formatAmount(symbol, amount, fmt); // existing helper + return '$symbol$sep$formatted'; } class DashboardScreen extends ConsumerStatefulWidget { @@ -407,7 +407,7 @@ class _BalanceCard extends ConsumerWidget { fit: BoxFit.scaleDown, alignment: Alignment.centerLeft, child: Text( - _formatBalanceAmount(currencyInfo.symbol, balance, fmt), + _smartBalance(balance, fmt, currencyInfo.symbol), style: TextStyle( fontSize: 36, // max font size fontWeight: FontWeight.w700, @@ -444,7 +444,7 @@ class _BalanceCard extends ConsumerWidget { fit: BoxFit.scaleDown, alignment: Alignment.centerLeft, child: Text( - _formatBalanceAmount(c.$2, converted, fmt), + _smartBalance(converted, fmt, c.$2), style: TextStyle( fontSize: 13, fontWeight: FontWeight.w500, diff --git a/lib/features/settings/screen.dart b/lib/features/settings/screen.dart index e34f9f2..f7b7dc1 100644 --- a/lib/features/settings/screen.dart +++ b/lib/features/settings/screen.dart @@ -6,6 +6,7 @@ import 'package:intl/intl.dart'; import '../../core/constants.dart'; import '../../shared/utils/currency_utils.dart'; import '../../shared/providers/amount_format_provider.dart'; +import '../dashboard/provider.dart'; import 'provider.dart'; class SettingsScreen extends ConsumerStatefulWidget { @@ -50,6 +51,55 @@ class _SettingsScreenState extends ConsumerState { setState(() => _isEditing = false); } + void _confirmClearData(BuildContext context, WidgetRef ref) { + // First confirmation + showDialog( + context: context, + builder: (ctx) => AlertDialog( + title: const Text('Clear all transactions?'), + content: const Text('This will permanently delete all your transaction history. This cannot be undone.'), + actions: [ + TextButton( + onPressed: () => Navigator.pop(ctx), + child: const Text('Cancel'), + ), + TextButton( + onPressed: () { + Navigator.pop(ctx); + // Second confirmation + showDialog( + context: context, + builder: (ctx2) => AlertDialog( + title: const Text('Are you absolutely sure?'), + content: const Text('All transactions will be deleted forever. There is no way to recover them.'), + actions: [ + TextButton( + onPressed: () => Navigator.pop(ctx2), + child: const Text('No, keep them'), + ), + TextButton( + onPressed: () { + ref.read(transactionsProvider.notifier).clearAll(); + Navigator.pop(ctx2); + ScaffoldMessenger.of(context).showSnackBar( + const SnackBar(content: Text('All transactions deleted')), + ); + }, + style: TextButton.styleFrom(foregroundColor: const Color(0xFFE05C6B)), + child: const Text('Yes, delete everything'), + ), + ], + ), + ); + }, + style: TextButton.styleFrom(foregroundColor: const Color(0xFFE05C6B)), + child: const Text('Delete'), + ), + ], + ), + ); + } + @override Widget build(BuildContext context) { final budget = ref.watch(budgetProvider); @@ -434,6 +484,36 @@ class _SettingsScreenState extends ConsumerState { ], ), ), + const SizedBox(height: 24), + + // Danger Zone + Text( + 'Danger Zone', + style: TextStyle( + fontSize: 12, + letterSpacing: 1.2, + color: const Color(0xFFE05C6B).withOpacity(0.8), + fontWeight: FontWeight.w600, + ), + ), + const SizedBox(height: 8), + SizedBox( + width: double.infinity, + child: OutlinedButton.icon( + onPressed: () => _confirmClearData(context, ref), + icon: const Icon(Icons.delete_forever, color: Color(0xFFE05C6B)), + label: const Text( + 'Clear All Transactions', + style: TextStyle(color: Color(0xFFE05C6B)), + ), + style: OutlinedButton.styleFrom( + side: BorderSide(color: const Color(0xFFE05C6B).withOpacity(0.5)), + padding: const EdgeInsets.symmetric(vertical: 14), + shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(12)), + ), + ), + ), + const SizedBox(height: 32), ], ), ),