This commit is contained in:
2026-03-20 16:50:08 +03:00
parent 1daeb1aa22
commit 9835206a78
+36 -60
View File
@@ -9,6 +9,25 @@ import '../../shared/providers/amount_format_provider.dart';
import '../settings/provider.dart'; import '../settings/provider.dart';
import 'provider.dart'; import 'provider.dart';
// Helper for balance card only - hides .00 decimals
String _formatBalanceAmount(String symbol, double amount, AmountFormat fmt) {
const spaceAfter = {'Br', ''};
final sep = spaceAfter.contains(symbol) ? ' ' : '';
// 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';
}
return formatAmount(symbol, amount, fmt); // existing helper
}
class DashboardScreen extends ConsumerStatefulWidget { class DashboardScreen extends ConsumerStatefulWidget {
const DashboardScreen({super.key}); const DashboardScreen({super.key});
@@ -42,8 +61,6 @@ class _DashboardScreenState extends ConsumerState<DashboardScreen> {
final currencyInfo = ref.watch(currencyProvider); final currencyInfo = ref.watch(currencyProvider);
final isDark = Theme.of(context).brightness == Brightness.dark; final isDark = Theme.of(context).brightness == Brightness.dark;
final budgetExceeded = budget != null && monthExpense > budget;
return Scaffold( return Scaffold(
backgroundColor: Theme.of(context).scaffoldBackgroundColor, backgroundColor: Theme.of(context).scaffoldBackgroundColor,
appBar: AppBar( appBar: AppBar(
@@ -97,10 +114,6 @@ class _DashboardScreenState extends ConsumerState<DashboardScreen> {
const SizedBox(height: 16), const SizedBox(height: 16),
_BudgetProgress(spent: monthExpense, budget: budget, currencyInfo: currencyInfo), _BudgetProgress(spent: monthExpense, budget: budget, currencyInfo: currencyInfo),
], ],
if (budgetExceeded) ...[
const SizedBox(height: 12),
_BudgetWarning(spent: monthExpense, budget: budget, currencyInfo: currencyInfo),
],
const SizedBox(height: 24), const SizedBox(height: 24),
_SearchBar(controller: _searchController, ref: ref), _SearchBar(controller: _searchController, ref: ref),
const SizedBox(height: 12), const SizedBox(height: 12),
@@ -260,12 +273,9 @@ class _BudgetProgress extends ConsumerWidget {
@override @override
Widget build(BuildContext context, WidgetRef ref) { Widget build(BuildContext context, WidgetRef ref) {
final fmt = ref.watch(amountFormatProvider); final fmt = ref.watch(amountFormatProvider);
final ratio = spent / budget; final progress = budget > 0 ? spent / budget : 0.0;
final color = ratio >= 1.0 final isOver = progress > 1.0;
? AppColors.expense final displayPercent = (progress * 100).toStringAsFixed(0);
: ratio >= 0.8
? AppColors.warning
: AppColors.income;
return Container( return Container(
padding: const EdgeInsets.all(16), padding: const EdgeInsets.all(16),
@@ -287,11 +297,12 @@ class _BudgetProgress extends ConsumerWidget {
), ),
), ),
Text( Text(
'${(ratio * 100).toStringAsFixed(0)}%', '$displayPercent%',
style: Theme.of(context).textTheme.bodyMedium?.copyWith( style: TextStyle(
color: color, color: isOver ? const Color(0xFFE05C6B) : Theme.of(context).colorScheme.onSurface.withOpacity(0.7),
fontWeight: FontWeight.w600, fontWeight: isOver ? FontWeight.w700 : FontWeight.normal,
), fontSize: 12,
),
), ),
], ],
), ),
@@ -299,9 +310,11 @@ class _BudgetProgress extends ConsumerWidget {
ClipRRect( ClipRRect(
borderRadius: BorderRadius.circular(8), borderRadius: BorderRadius.circular(8),
child: LinearProgressIndicator( child: LinearProgressIndicator(
value: ratio.clamp(0.0, 1.0), value: isOver ? 1.0 : progress,
backgroundColor: Theme.of(context).dividerColor, backgroundColor: Theme.of(context).colorScheme.onSurface.withOpacity(0.1),
valueColor: AlwaysStoppedAnimation<Color>(color), valueColor: AlwaysStoppedAnimation<Color>(
isOver ? const Color(0xFFE05C6B) : (progress > 0.8 ? Colors.orange : const Color(0xFF4CAF8C)),
),
minHeight: 8, minHeight: 8,
), ),
), ),
@@ -329,43 +342,6 @@ class _BudgetProgress extends ConsumerWidget {
} }
} }
class _BudgetWarning extends ConsumerWidget {
final double spent;
final double budget;
final CurrencyInfo currencyInfo;
const _BudgetWarning({required this.spent, required this.budget, required this.currencyInfo});
@override
Widget build(BuildContext context, WidgetRef ref) {
final fmt = ref.watch(amountFormatProvider);
final over = spent - budget;
final isDark = Theme.of(context).brightness == Brightness.dark;
return Container(
padding: const EdgeInsets.all(14),
decoration: BoxDecoration(
color: AppColors.expense.withOpacity(0.1),
borderRadius: BorderRadius.circular(12),
border: isDark ? null : Border.all(color: AppColors.expense.withOpacity(0.3), width: 1),
),
child: Row(
children: [
const Icon(Icons.warning_rounded, color: AppColors.expense, size: 20),
const SizedBox(width: 10),
Expanded(
child: Text(
'Budget exceeded by ${formatAmount(currencyInfo.symbol, over, fmt)}',
style: Theme.of(context).textTheme.bodySmall?.copyWith(
color: AppColors.expense,
fontWeight: FontWeight.w600,
),
),
),
],
),
);
}
}
class _BalanceCard extends ConsumerWidget { class _BalanceCard extends ConsumerWidget {
final double balance; final double balance;
final CurrencyInfo currencyInfo; final CurrencyInfo currencyInfo;
@@ -385,7 +361,7 @@ class _BalanceCard extends ConsumerWidget {
return Container( return Container(
width: double.infinity, width: double.infinity,
height: 140, height: 180,
padding: const EdgeInsets.symmetric(horizontal: 20, vertical: 16), padding: const EdgeInsets.symmetric(horizontal: 20, vertical: 16),
decoration: BoxDecoration( decoration: BoxDecoration(
gradient: LinearGradient( gradient: LinearGradient(
@@ -431,7 +407,7 @@ class _BalanceCard extends ConsumerWidget {
fit: BoxFit.scaleDown, fit: BoxFit.scaleDown,
alignment: Alignment.centerLeft, alignment: Alignment.centerLeft,
child: Text( child: Text(
formatAmount(currencyInfo.symbol, balance, fmt), _formatBalanceAmount(currencyInfo.symbol, balance, fmt),
style: TextStyle( style: TextStyle(
fontSize: 36, // max font size fontSize: 36, // max font size
fontWeight: FontWeight.w700, fontWeight: FontWeight.w700,
@@ -468,7 +444,7 @@ class _BalanceCard extends ConsumerWidget {
fit: BoxFit.scaleDown, fit: BoxFit.scaleDown,
alignment: Alignment.centerLeft, alignment: Alignment.centerLeft,
child: Text( child: Text(
formatAmount(c.$2, converted, fmt), _formatBalanceAmount(c.$2, converted, fmt),
style: TextStyle( style: TextStyle(
fontSize: 13, fontSize: 13,
fontWeight: FontWeight.w500, fontWeight: FontWeight.w500,