mirror of
https://github.com/koloideal/Casha.git
synced 2026-06-10 10:25:28 +03:00
stableee
This commit is contained in:
@@ -127,7 +127,7 @@ class AppCurrencies {
|
|||||||
CurrencyOption(symbol: '\$', name: 'US Dollar', code: 'USD'),
|
CurrencyOption(symbol: '\$', name: 'US Dollar', code: 'USD'),
|
||||||
CurrencyOption(symbol: '€', name: 'Euro', code: 'EUR'),
|
CurrencyOption(symbol: '€', name: 'Euro', code: 'EUR'),
|
||||||
CurrencyOption(symbol: '£', name: 'British Pound', code: 'GBP'),
|
CurrencyOption(symbol: '£', name: 'British Pound', code: 'GBP'),
|
||||||
CurrencyOption(symbol: 'Br', name: 'Belarusian Ruble', code: 'BYN'),
|
CurrencyOption(symbol: '', name: 'Belarusian Ruble', code: 'BYN'),
|
||||||
CurrencyOption(symbol: '₽', name: 'Russian Ruble', code: 'RUB'),
|
CurrencyOption(symbol: '₽', name: 'Russian Ruble', code: 'RUB'),
|
||||||
CurrencyOption(symbol: '₴', name: 'Ukrainian Hryvnia', code: 'UAH'),
|
CurrencyOption(symbol: '₴', name: 'Ukrainian Hryvnia', code: 'UAH'),
|
||||||
];
|
];
|
||||||
@@ -139,3 +139,11 @@ class AppCurrencies {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// `(code, textSymbol)` for pickers and conversion rows. BYN uses `''` — use BynSign in UI.
|
||||||
|
const List<(String, String)> kDisplayCurrencies = [
|
||||||
|
('USD', r'$'),
|
||||||
|
('EUR', '€'),
|
||||||
|
('BYN', ''),
|
||||||
|
('RUB', '₽'),
|
||||||
|
];
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
|
import '../../../core/constants.dart';
|
||||||
import '../../../shared/widgets/byn_sign.dart';
|
import '../../../shared/widgets/byn_sign.dart';
|
||||||
|
|
||||||
class CurrencyPicker extends StatelessWidget {
|
class CurrencyPicker extends StatelessWidget {
|
||||||
@@ -13,12 +14,7 @@ class CurrencyPicker extends StatelessWidget {
|
|||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
final currencies = [
|
final currencies = kDisplayCurrencies;
|
||||||
('USD', '\$'),
|
|
||||||
('EUR', '€'),
|
|
||||||
('BYN', 'Br'),
|
|
||||||
('RUB', '₽'),
|
|
||||||
];
|
|
||||||
final colorScheme = Theme.of(context).colorScheme;
|
final colorScheme = Theme.of(context).colorScheme;
|
||||||
|
|
||||||
return Row(
|
return Row(
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
import 'dart:ui';
|
import 'dart:ui';
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:flutter_riverpod/flutter_riverpod.dart';
|
import 'package:flutter_riverpod/flutter_riverpod.dart';
|
||||||
|
import '../../../../core/constants.dart';
|
||||||
import '../../../../shared/models/account.dart';
|
import '../../../../shared/models/account.dart';
|
||||||
import '../../../../shared/models/transaction.dart';
|
import '../../../../shared/models/transaction.dart';
|
||||||
import '../../../../shared/widgets/byn_sign.dart';
|
import '../../../../shared/widgets/byn_sign.dart';
|
||||||
@@ -281,13 +282,7 @@ class _AccountEditorOverlayState extends State<AccountEditorOverlay> {
|
|||||||
),
|
),
|
||||||
child: Column(
|
child: Column(
|
||||||
mainAxisSize: MainAxisSize.min,
|
mainAxisSize: MainAxisSize.min,
|
||||||
children:
|
children: kDisplayCurrencies.map((entry) {
|
||||||
[
|
|
||||||
('USD', '\$'),
|
|
||||||
('EUR', '€'),
|
|
||||||
('BYN', 'Br'),
|
|
||||||
('RUB', '₽'),
|
|
||||||
].map((entry) {
|
|
||||||
final isSelected = entry.$1 == _selectedCurrency;
|
final isSelected = entry.$1 == _selectedCurrency;
|
||||||
return InkWell(
|
return InkWell(
|
||||||
onTap: () {
|
onTap: () {
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:flutter_riverpod/flutter_riverpod.dart';
|
import 'package:flutter_riverpod/flutter_riverpod.dart';
|
||||||
|
import '../../../../core/constants.dart';
|
||||||
import '../../../../shared/widgets/byn_sign.dart';
|
import '../../../../shared/widgets/byn_sign.dart';
|
||||||
|
|
||||||
class AccountEditorPanel extends ConsumerWidget {
|
class AccountEditorPanel extends ConsumerWidget {
|
||||||
@@ -169,12 +170,7 @@ class AccountEditorPanel extends ConsumerWidget {
|
|||||||
).colorScheme.onSurface,
|
).colorScheme.onSurface,
|
||||||
)
|
)
|
||||||
: Text(
|
: Text(
|
||||||
[
|
kDisplayCurrencies
|
||||||
('USD', '\$'),
|
|
||||||
('EUR', '€'),
|
|
||||||
('BYN', 'Br'),
|
|
||||||
('RUB', '₽'),
|
|
||||||
]
|
|
||||||
.firstWhere(
|
.firstWhere(
|
||||||
(c) => c.$1 == selectedCurrency,
|
(c) => c.$1 == selectedCurrency,
|
||||||
)
|
)
|
||||||
|
|||||||
@@ -12,8 +12,6 @@ import '../../settings/provider.dart';
|
|||||||
import '../provider.dart';
|
import '../provider.dart';
|
||||||
|
|
||||||
String _smartBalance(double amount, AmountFormat fmt, String symbol) {
|
String _smartBalance(double amount, AmountFormat fmt, String symbol) {
|
||||||
const spaceAfter = {'Br'};
|
|
||||||
final sep = spaceAfter.contains(symbol) || symbol.isEmpty ? ' ' : '';
|
|
||||||
final isWhole = amount == amount.floorToDouble();
|
final isWhole = amount == amount.floorToDouble();
|
||||||
|
|
||||||
String formatted;
|
String formatted;
|
||||||
@@ -25,7 +23,7 @@ String _smartBalance(double amount, AmountFormat fmt, String symbol) {
|
|||||||
} else {
|
} else {
|
||||||
formatted = fmt.format(amount);
|
formatted = fmt.format(amount);
|
||||||
}
|
}
|
||||||
return symbol.isEmpty ? formatted : '$symbol$sep$formatted';
|
return symbol.isEmpty ? formatted : '$symbol$formatted';
|
||||||
}
|
}
|
||||||
|
|
||||||
class BalanceCard extends ConsumerStatefulWidget {
|
class BalanceCard extends ConsumerStatefulWidget {
|
||||||
@@ -139,13 +137,7 @@ class BalanceCardState extends ConsumerState<BalanceCard>
|
|||||||
final secondary = widget.previewSecondary ?? savedColors.secondary;
|
final secondary = widget.previewSecondary ?? savedColors.secondary;
|
||||||
final gradientType = widget.previewGradientType ?? savedColors.gradientType;
|
final gradientType = widget.previewGradientType ?? savedColors.gradientType;
|
||||||
|
|
||||||
final allCurrencies = [
|
final others = kDisplayCurrencies
|
||||||
('USD', r'$'),
|
|
||||||
('EUR', '€'),
|
|
||||||
('BYN', 'Br'),
|
|
||||||
('RUB', '₽'),
|
|
||||||
];
|
|
||||||
final others = allCurrencies
|
|
||||||
.where((c) => c.$1 != widget.currencyInfo.code)
|
.where((c) => c.$1 != widget.currencyInfo.code)
|
||||||
.toList();
|
.toList();
|
||||||
|
|
||||||
@@ -253,7 +245,7 @@ class BalanceCardState extends ConsumerState<BalanceCard>
|
|||||||
fontSize: 48,
|
fontSize: 48,
|
||||||
color: onCard,
|
color: onCard,
|
||||||
),
|
),
|
||||||
const SizedBox(width: 4),
|
const SizedBox(width: 2),
|
||||||
Text(
|
Text(
|
||||||
_smartBalance(
|
_smartBalance(
|
||||||
widget.balance,
|
widget.balance,
|
||||||
|
|||||||
@@ -199,7 +199,6 @@ class ExportService {
|
|||||||
Future<String> exportToCSV() async {
|
Future<String> exportToCSV() async {
|
||||||
final transactionsAsync = _ref.read(transactionsProvider);
|
final transactionsAsync = _ref.read(transactionsProvider);
|
||||||
final transactions = transactionsAsync.valueOrNull ?? [];
|
final transactions = transactionsAsync.valueOrNull ?? [];
|
||||||
final currency = _ref.read(currencyProvider);
|
|
||||||
final fmt = _ref.read(amountFormatProvider);
|
final fmt = _ref.read(amountFormatProvider);
|
||||||
|
|
||||||
final buffer = StringBuffer();
|
final buffer = StringBuffer();
|
||||||
@@ -209,7 +208,8 @@ class ExportService {
|
|||||||
final date = DateFormat('yyyy-MM-dd').format(tx.date);
|
final date = DateFormat('yyyy-MM-dd').format(tx.date);
|
||||||
final type = tx.type.name;
|
final type = tx.type.name;
|
||||||
final category = tx.category;
|
final category = tx.category;
|
||||||
final amount = formatAmount(tx.currency, tx.amount, fmt);
|
final sym = currencyMap[tx.currencyCode]?.symbol ?? '';
|
||||||
|
final amount = formatAmount(sym, tx.amount, fmt);
|
||||||
final note = tx.note?.replaceAll(',', ';') ?? '';
|
final note = tx.note?.replaceAll(',', ';') ?? '';
|
||||||
buffer.writeln('$date,$type,$category,$amount,${tx.currencyCode},$note');
|
buffer.writeln('$date,$type,$category,$amount,${tx.currencyCode},$note');
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -3,6 +3,7 @@ import 'package:flutter_riverpod/flutter_riverpod.dart';
|
|||||||
import '../../../core/constants.dart';
|
import '../../../core/constants.dart';
|
||||||
import '../../../core/l10n/locale_provider.dart';
|
import '../../../core/l10n/locale_provider.dart';
|
||||||
import '../../../shared/providers/amount_format_provider.dart';
|
import '../../../shared/providers/amount_format_provider.dart';
|
||||||
|
import '../../../shared/widgets/byn_sign.dart';
|
||||||
import '../provider.dart';
|
import '../provider.dart';
|
||||||
|
|
||||||
class AmountFormatSection extends ConsumerWidget {
|
class AmountFormatSection extends ConsumerWidget {
|
||||||
@@ -94,12 +95,37 @@ class AmountFormatSection extends ConsumerWidget {
|
|||||||
: FontWeight.w500,
|
: FontWeight.w500,
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
|
currencyInfo.code == 'BYN'
|
||||||
|
? Row(
|
||||||
|
mainAxisSize: MainAxisSize.min,
|
||||||
|
crossAxisAlignment: CrossAxisAlignment.center,
|
||||||
|
children: [
|
||||||
|
BynSign(
|
||||||
|
fontSize: 12,
|
||||||
|
color: Theme.of(context)
|
||||||
|
.colorScheme
|
||||||
|
.onSurface
|
||||||
|
.withOpacity(0.6),
|
||||||
|
),
|
||||||
Text(
|
Text(
|
||||||
|
format.example.replaceFirst(
|
||||||
|
RegExp(r'SYM\s*'),
|
||||||
|
'',
|
||||||
|
),
|
||||||
|
style: TextStyle(
|
||||||
|
color: Theme.of(context)
|
||||||
|
.colorScheme
|
||||||
|
.onSurface
|
||||||
|
.withOpacity(0.6),
|
||||||
|
fontSize: 12,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
)
|
||||||
|
: Text(
|
||||||
format.example.replaceFirst(
|
format.example.replaceFirst(
|
||||||
'SYM',
|
'SYM',
|
||||||
currencyInfo.symbol.isEmpty
|
currencyInfo.symbol,
|
||||||
? 'Br'
|
|
||||||
: currencyInfo.symbol,
|
|
||||||
),
|
),
|
||||||
style: TextStyle(
|
style: TextStyle(
|
||||||
color: Theme.of(
|
color: Theme.of(
|
||||||
|
|||||||
@@ -1,10 +1,7 @@
|
|||||||
import '../../core/constants.dart';
|
import '../../core/constants.dart';
|
||||||
|
|
||||||
String formatAmount(String symbol, double amount, AmountFormat fmt) {
|
String formatAmount(String symbol, double amount, AmountFormat fmt) {
|
||||||
const spaceAfter = {'Br'};
|
|
||||||
final formatted = fmt.format(amount);
|
final formatted = fmt.format(amount);
|
||||||
// For BYN, symbol is empty string, so we use 'Br' for text-only contexts like CSV
|
if (symbol.isEmpty) return formatted;
|
||||||
final displaySymbol = symbol.isEmpty ? 'Br' : symbol;
|
return '$symbol$formatted';
|
||||||
final sep = spaceAfter.contains(displaySymbol) ? ' ' : '';
|
|
||||||
return '$displaySymbol$sep$formatted';
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -14,9 +14,9 @@ class BynSign extends StatelessWidget {
|
|||||||
'\uE901',
|
'\uE901',
|
||||||
style: TextStyle(
|
style: TextStyle(
|
||||||
fontFamily: 'BynSymbol',
|
fontFamily: 'BynSymbol',
|
||||||
fontSize: fontSize,
|
fontSize: fontSize * 1.1,
|
||||||
color: color,
|
color: color,
|
||||||
fontWeight: FontWeight.w700,
|
fontWeight: FontWeight.w900,
|
||||||
height: 1.0,
|
height: 1.0,
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
|
|||||||
Reference in New Issue
Block a user