mirror of
https://github.com/koloideal/Casha.git
synced 2026-08-08 17:51:14 +03:00
step
big
This commit is contained in:
@@ -273,36 +273,6 @@ final totalExpenseProvider = Provider<double>((ref) {
|
||||
});
|
||||
});
|
||||
|
||||
final currentMonthExpenseProvider = Provider<double>((ref) {
|
||||
final now = DateTime.now();
|
||||
final txs = ref.watch(accountFilteredTransactionsProvider);
|
||||
final filtered = txs.where(
|
||||
(t) =>
|
||||
t.type == TransactionType.expense &&
|
||||
t.date.year == now.year &&
|
||||
t.date.month == now.month,
|
||||
);
|
||||
|
||||
final index = ref.watch(activeAccountIndexProvider);
|
||||
final accountsAsync = ref.watch(accountsProvider);
|
||||
final globalCurrency = ref.watch(currencyProvider).code;
|
||||
|
||||
String targetCurrency = globalCurrency;
|
||||
if (index > 0) {
|
||||
final accounts = accountsAsync.value ?? [];
|
||||
if (index <= accounts.length) {
|
||||
targetCurrency = accounts[index - 1].currency;
|
||||
}
|
||||
}
|
||||
|
||||
final exchangeService = ref.watch(exchangeRateServiceProvider);
|
||||
|
||||
return filtered.fold(0.0, (sum, t) {
|
||||
return sum +
|
||||
exchangeService.convert(t.amount, t.currencyCode, targetCurrency);
|
||||
});
|
||||
});
|
||||
|
||||
final filteredTransactionsProvider = Provider<List<Transaction>>((ref) {
|
||||
final txs = ref.watch(accountFilteredTransactionsProvider);
|
||||
final query = ref.watch(searchQueryProvider).toLowerCase();
|
||||
|
||||
@@ -10,7 +10,6 @@ import '../settings/provider.dart';
|
||||
import 'provider.dart';
|
||||
import 'widgets/account_editor_overlay/account_editor_overlay.dart';
|
||||
import 'widgets/balance_card_carousel.dart';
|
||||
import 'widgets/budget_progress.dart';
|
||||
import 'widgets/color_editor_overlay.dart';
|
||||
import 'widgets/filter_chips.dart';
|
||||
import 'widgets/search_bar.dart' as custom;
|
||||
@@ -266,8 +265,6 @@ class _DashboardScreenState extends ConsumerState<DashboardScreen> {
|
||||
final balance = ref.watch(totalBalanceProvider);
|
||||
final income = ref.watch(totalIncomeProvider);
|
||||
final expense = ref.watch(totalExpenseProvider);
|
||||
final monthExpense = ref.watch(currentMonthExpenseProvider);
|
||||
final budget = ref.watch(budgetProvider);
|
||||
final recent = ref.watch(recentTransactionsProvider);
|
||||
final activeAccount = ref.watch(activeAccountProvider);
|
||||
final globalCurrencyInfo = ref.watch(currencyProvider);
|
||||
@@ -376,15 +373,6 @@ class _DashboardScreenState extends ConsumerState<DashboardScreen> {
|
||||
currencyInfo: currencyInfo,
|
||||
strings: s,
|
||||
),
|
||||
if (budget != null) ...[
|
||||
const SizedBox(height: 16),
|
||||
BudgetProgress(
|
||||
spent: monthExpense,
|
||||
budget: budget,
|
||||
currencyInfo: currencyInfo,
|
||||
strings: s,
|
||||
),
|
||||
],
|
||||
const SizedBox(height: 24),
|
||||
custom.SearchBar(
|
||||
controller: _searchController,
|
||||
|
||||
@@ -1,187 +0,0 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_riverpod/flutter_riverpod.dart';
|
||||
import '../../../core/l10n/app_strings.dart';
|
||||
import '../../../shared/providers/amount_format_provider.dart';
|
||||
import '../../../shared/utils/currency_utils.dart';
|
||||
import '../../../shared/widgets/byn_sign.dart';
|
||||
import '../../settings/provider.dart';
|
||||
|
||||
class BudgetProgress extends ConsumerWidget {
|
||||
final double spent;
|
||||
final double budget;
|
||||
final CurrencyInfo currencyInfo;
|
||||
final AppStrings strings;
|
||||
const BudgetProgress({
|
||||
super.key,
|
||||
required this.spent,
|
||||
required this.budget,
|
||||
required this.currencyInfo,
|
||||
required this.strings,
|
||||
});
|
||||
|
||||
Border? _themeBorder(BuildContext context) {
|
||||
final isDark = Theme.of(context).brightness == Brightness.dark;
|
||||
return isDark ? null : Border.all(color: const Color(0xFFDDDDEE), width: 1);
|
||||
}
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context, WidgetRef ref) {
|
||||
final fmt = ref.watch(amountFormatProvider);
|
||||
final progress = budget > 0 ? spent / budget : 0.0;
|
||||
final isOver = progress > 1.0;
|
||||
final displayPercent = (progress * 100).toStringAsFixed(0);
|
||||
|
||||
return ClipRRect(
|
||||
borderRadius: BorderRadius.circular(16),
|
||||
child: Container(
|
||||
padding: const EdgeInsets.all(16),
|
||||
decoration: BoxDecoration(
|
||||
color: Theme.of(context).colorScheme.surface,
|
||||
border: Border(
|
||||
left: BorderSide(
|
||||
color: isOver ? const Color(0xFFE05C6B) : const Color(0xFF7C6DED),
|
||||
width: 3,
|
||||
),
|
||||
top: _themeBorder(context)?.top ?? BorderSide.none,
|
||||
right: _themeBorder(context)?.right ?? BorderSide.none,
|
||||
bottom: _themeBorder(context)?.bottom ?? BorderSide.none,
|
||||
),
|
||||
),
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
Row(
|
||||
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||
children: [
|
||||
Text(
|
||||
strings.monthlyBudget,
|
||||
style: Theme.of(context).textTheme.bodyMedium?.copyWith(
|
||||
color: Theme.of(
|
||||
context,
|
||||
).colorScheme.onSurface.withOpacity(0.6),
|
||||
),
|
||||
),
|
||||
Text(
|
||||
'$displayPercent%',
|
||||
style: TextStyle(
|
||||
color: isOver
|
||||
? const Color(0xFFE05C6B)
|
||||
: Theme.of(
|
||||
context,
|
||||
).colorScheme.onSurface.withOpacity(0.7),
|
||||
fontWeight: isOver ? FontWeight.w700 : FontWeight.normal,
|
||||
fontSize: 12,
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
const SizedBox(height: 8),
|
||||
ClipRRect(
|
||||
borderRadius: BorderRadius.circular(8),
|
||||
child: LinearProgressIndicator(
|
||||
value: isOver ? 1.0 : progress,
|
||||
backgroundColor: Theme.of(
|
||||
context,
|
||||
).colorScheme.onSurface.withOpacity(0.1),
|
||||
valueColor: AlwaysStoppedAnimation<Color>(
|
||||
isOver
|
||||
? const Color(0xFFE05C6B)
|
||||
: (progress > 0.8
|
||||
? Colors.orange
|
||||
: const Color(0xFF4CAF8C)),
|
||||
),
|
||||
minHeight: 8,
|
||||
),
|
||||
),
|
||||
const SizedBox(height: 8),
|
||||
Row(
|
||||
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||
children: [
|
||||
currencyInfo.code == 'BYN'
|
||||
? Row(
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
crossAxisAlignment: CrossAxisAlignment.center,
|
||||
children: [
|
||||
Text(
|
||||
'${strings.spent}: ',
|
||||
style: Theme.of(context).textTheme.bodySmall
|
||||
?.copyWith(
|
||||
color: Theme.of(
|
||||
context,
|
||||
).colorScheme.onSurface.withOpacity(0.6),
|
||||
),
|
||||
),
|
||||
BynSign(
|
||||
fontSize: 12,
|
||||
color: Theme.of(
|
||||
context,
|
||||
).colorScheme.onSurface.withOpacity(0.6),
|
||||
),
|
||||
const SizedBox(width: 2),
|
||||
Text(
|
||||
formatAmount('', spent, fmt),
|
||||
style: Theme.of(context).textTheme.bodySmall
|
||||
?.copyWith(
|
||||
color: Theme.of(
|
||||
context,
|
||||
).colorScheme.onSurface.withOpacity(0.6),
|
||||
),
|
||||
),
|
||||
],
|
||||
)
|
||||
: Text(
|
||||
'${strings.spent}: ${formatAmount(currencyInfo.symbol, spent, fmt)}',
|
||||
style: Theme.of(context).textTheme.bodySmall?.copyWith(
|
||||
color: Theme.of(
|
||||
context,
|
||||
).colorScheme.onSurface.withOpacity(0.6),
|
||||
),
|
||||
),
|
||||
currencyInfo.code == 'BYN'
|
||||
? Row(
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
crossAxisAlignment: CrossAxisAlignment.center,
|
||||
children: [
|
||||
Text(
|
||||
'${strings.limit}: ',
|
||||
style: Theme.of(context).textTheme.bodySmall
|
||||
?.copyWith(
|
||||
color: Theme.of(
|
||||
context,
|
||||
).colorScheme.onSurface.withOpacity(0.6),
|
||||
),
|
||||
),
|
||||
BynSign(
|
||||
fontSize: 12,
|
||||
color: Theme.of(
|
||||
context,
|
||||
).colorScheme.onSurface.withOpacity(0.6),
|
||||
),
|
||||
const SizedBox(width: 2),
|
||||
Text(
|
||||
formatAmount('', budget, fmt),
|
||||
style: Theme.of(context).textTheme.bodySmall
|
||||
?.copyWith(
|
||||
color: Theme.of(
|
||||
context,
|
||||
).colorScheme.onSurface.withOpacity(0.6),
|
||||
),
|
||||
),
|
||||
],
|
||||
)
|
||||
: Text(
|
||||
'${strings.limit}: ${formatAmount(currencyInfo.symbol, budget, fmt)}',
|
||||
style: Theme.of(context).textTheme.bodySmall?.copyWith(
|
||||
color: Theme.of(
|
||||
context,
|
||||
).colorScheme.onSurface.withOpacity(0.6),
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -9,6 +9,7 @@ import '../../../core/l10n/locale_provider.dart';
|
||||
import '../../../shared/models/transaction.dart';
|
||||
import '../../../shared/models/account.dart';
|
||||
import '../../../shared/providers/amount_format_provider.dart';
|
||||
import '../../../shared/providers/category_provider.dart';
|
||||
import '../../../shared/utils/currency_utils.dart';
|
||||
import '../../../shared/widgets/byn_sign.dart';
|
||||
import '../../settings/provider.dart';
|
||||
@@ -29,7 +30,9 @@ class TransactionTile extends ConsumerWidget {
|
||||
@override
|
||||
Widget build(BuildContext context, WidgetRef ref) {
|
||||
final s = ref.watch(stringsProvider);
|
||||
final isRu = s.locale == AppLocale.ru;
|
||||
final fmt = ref.watch(amountFormatProvider);
|
||||
final catalog = ref.watch(categoryCatalogProvider);
|
||||
final isTransfer = transaction.category == 'Transfer';
|
||||
final isIncome = transaction.type == TransactionType.income;
|
||||
final color = isTransfer
|
||||
@@ -37,10 +40,11 @@ class TransactionTile extends ConsumerWidget {
|
||||
: (isIncome ? AppColors.income : AppColors.expense);
|
||||
final catColor = isTransfer
|
||||
? const Color(0xFF7C6DED)
|
||||
: (AppCategories.colors[transaction.category] ?? AppColors.accent);
|
||||
: catalog.colorFor(transaction.category);
|
||||
final catIcon = isTransfer
|
||||
? Icons.swap_horiz_rounded
|
||||
: (AppCategories.icons[transaction.category] ?? Icons.category_rounded);
|
||||
: catalog.iconFor(transaction.category);
|
||||
final catLabel = catalog.labelFor(transaction.category, isRu);
|
||||
|
||||
final activeAccount = ref.watch(activeAccountProvider);
|
||||
final displayCurrency =
|
||||
@@ -105,7 +109,7 @@ class TransactionTile extends ConsumerWidget {
|
||||
activeAccount,
|
||||
)
|
||||
: Text(
|
||||
s.categoryLabel(transaction.category),
|
||||
catLabel,
|
||||
style: Theme.of(context).textTheme.bodyMedium
|
||||
?.copyWith(
|
||||
fontWeight: FontWeight.w600,
|
||||
|
||||
Reference in New Issue
Block a user