This commit is contained in:
2026-03-29 15:59:49 +03:00
parent 1f6d129fc2
commit bc8c272e63
21 changed files with 114 additions and 327 deletions
@@ -90,7 +90,6 @@ class _AccountEditorOverlayState extends State<AccountEditorOverlay> {
final editorPanelTop = cardTop + cardHeight + 20;
final colorPanelTop = editorPanelTop + editorPanelHeight + 12;
const colorPanelHeight = 410.0;
// Preview card in overlay should match BalanceCardCarousel sizing.
return Consumer(
builder: (context, ref, _) {
@@ -203,25 +202,24 @@ class _AccountEditorOverlayState extends State<AccountEditorOverlay> {
child: SizedBox(
height: cardHeight,
child: Padding(
padding: const EdgeInsets.symmetric(horizontal: 8),
child: BalanceCard(
balance: previewBalance,
currencyInfo: CurrencyInfo(
currencyMap[dash.tempAccountCurrency]?.symbol ??
'\$',
dash.tempAccountCurrency,
),
onLongPress: null,
accountName: dash.tempAccountName,
previewPrimary: dash.tempPrimary,
previewSecondary: dash.tempSecondary,
previewGradientType:
Theme.of(widget.context).brightness ==
Brightness.dark
? dash.tempDarkGradientType
: dash.tempLightGradientType,
padding: const EdgeInsets.symmetric(horizontal: 8),
child: BalanceCard(
balance: previewBalance,
currencyInfo: CurrencyInfo(
currencyMap[dash.tempAccountCurrency]?.symbol ?? '\$',
dash.tempAccountCurrency,
),
onLongPress: null,
accountName: dash.tempAccountName,
previewPrimary: dash.tempPrimary,
previewSecondary: dash.tempSecondary,
previewGradientType:
Theme.of(widget.context).brightness ==
Brightness.dark
? dash.tempDarkGradientType
: dash.tempLightGradientType,
),
),
),
),
),
@@ -299,75 +297,75 @@ class _AccountEditorOverlayState extends State<AccountEditorOverlay> {
child: Column(
mainAxisSize: MainAxisSize.min,
children: kDisplayCurrencies.map((entry) {
final isSelected = entry.$1 == _selectedCurrency;
return InkWell(
onTap: () {
setState(() {
_selectedCurrency = entry.$1;
dash.setState(() {
dash.tempAccountCurrency = entry.$1;
});
dash.overlayEntry?.markNeedsBuild();
_showCurrencyDropdown = false;
});
},
borderRadius: BorderRadius.circular(12),
child: Padding(
padding: const EdgeInsets.symmetric(
horizontal: 8,
vertical: 8,
),
child: Row(
mainAxisSize: MainAxisSize.min,
children: [
entry.$1 == 'BYN'
? BynSign(
fontSize: 14,
color: isSelected
? const Color(0xFF7C6DED)
: Theme.of(
widget.context,
).colorScheme.onSurface,
)
: Text(
entry.$2,
style: TextStyle(
fontSize: 14,
fontWeight: FontWeight.w600,
color: isSelected
? const Color(0xFF7C6DED)
: null,
),
),
const SizedBox(width: 4),
Flexible(
child: Text(
entry.$1,
final isSelected = entry.$1 == _selectedCurrency;
return InkWell(
onTap: () {
setState(() {
_selectedCurrency = entry.$1;
dash.setState(() {
dash.tempAccountCurrency = entry.$1;
});
dash.overlayEntry?.markNeedsBuild();
_showCurrencyDropdown = false;
});
},
borderRadius: BorderRadius.circular(12),
child: Padding(
padding: const EdgeInsets.symmetric(
horizontal: 8,
vertical: 8,
),
child: Row(
mainAxisSize: MainAxisSize.min,
children: [
entry.$1 == 'BYN'
? BynSign(
fontSize: 14,
color: isSelected
? const Color(0xFF7C6DED)
: Theme.of(
widget.context,
).colorScheme.onSurface,
)
: Text(
entry.$2,
style: TextStyle(
fontSize: 11,
fontSize: 14,
fontWeight: FontWeight.w600,
color: isSelected
? const Color(0xFF7C6DED)
: Theme.of(widget.context)
.colorScheme
.onSurface
.withOpacity(0.6),
: null,
),
overflow: TextOverflow.ellipsis,
),
const SizedBox(width: 4),
Flexible(
child: Text(
entry.$1,
style: TextStyle(
fontSize: 11,
color: isSelected
? const Color(0xFF7C6DED)
: Theme.of(widget.context)
.colorScheme
.onSurface
.withOpacity(0.6),
),
if (isSelected) ...[
const SizedBox(width: 4),
const Icon(
Icons.check_rounded,
size: 14,
color: Color(0xFF7C6DED),
),
],
],
overflow: TextOverflow.ellipsis,
),
),
),
);
}).toList(),
if (isSelected) ...[
const SizedBox(width: 4),
const Icon(
Icons.check_rounded,
size: 14,
color: Color(0xFF7C6DED),
),
],
],
),
),
);
}).toList(),
),
),
),
@@ -41,7 +41,6 @@ class _BalanceCardCarouselState extends ConsumerState<BalanceCardCarousel> {
@override
void initState() {
super.initState();
// 0.92 позволяет видеть края предыдущей/следующей карточки
final savedIndex = ref.read(activeAccountIndexProvider);
_pageController = PageController(
viewportFraction: 0.92,
@@ -68,14 +67,12 @@ class _BalanceCardCarouselState extends ConsumerState<BalanceCardCarousel> {
children: [
SizedBox(
height: 230,
// OverflowBox позволяет PageView игнорировать паддинги родителя (DashboardScreen)
// и растянуться на всю ширину экрана
child: OverflowBox(
maxWidth: MediaQuery.of(context).size.width,
child: PageView.builder(
controller: _pageController,
clipBehavior:
Clip.none, // Не обрезает карточку при 3D-наклоне
Clip.none,
itemCount: totalPages,
onPageChanged: (index) {
ref.read(activeAccountIndexProvider.notifier).state = index;
@@ -105,7 +102,6 @@ class _BalanceCardCarouselState extends ConsumerState<BalanceCardCarousel> {
accountCardColorsProvider(account.id),
);
// Calculate this specific account's balance
final txs =
ref.watch(transactionsProvider).valueOrNull ?? [];
final accountTxs = txs
@@ -119,7 +115,7 @@ class _BalanceCardCarouselState extends ConsumerState<BalanceCardCarousel> {
t.amount,
t.currencyCode,
account
.currency, // target is the account's own currency
.currency,
);
return t.type == TransactionType.income
? sum + converted
@@ -128,7 +124,7 @@ class _BalanceCardCarouselState extends ConsumerState<BalanceCardCarousel> {
cardWidget = BalanceCard(
balance:
accountBalance, // Use the dynamically calculated balance!
accountBalance,
currencyInfo: CurrencyInfo(
currencyMap[account.currency]?.symbol ?? '\$',
account.currency,
@@ -144,7 +140,6 @@ class _BalanceCardCarouselState extends ConsumerState<BalanceCardCarousel> {
);
}
// Отступ между карточками во время свайпа
return Padding(
padding: const EdgeInsets.symmetric(horizontal: 8),
child: cardWidget,
@@ -198,12 +193,12 @@ class AddAccountCard extends StatelessWidget {
margin: const EdgeInsets.symmetric(
horizontal: 10,
vertical: 10,
), // Reduced margins for larger size
),
child: CustomPaint(
painter: _DashedBorderPainter(),
child: Container(
width: double.infinity,
height: 205, // Increased height
height: 205,
decoration: BoxDecoration(
color: Theme.of(context).colorScheme.surface.withOpacity(0.4),
borderRadius: BorderRadius.circular(20),
@@ -213,7 +208,7 @@ class AddAccountCard extends StatelessWidget {
children: [
Icon(
Icons.add_rounded,
size: 36, // Slightly bigger icon
size: 36,
color: Theme.of(
context,
).colorScheme.onSurface.withOpacity(0.5),
@@ -94,7 +94,6 @@ class _FullScreenBlurOverlayState extends State<FullScreenBlurOverlay> {
child: _buildPanel(panelHeight),
),
),
// Close Button - Top Right
Positioned(
top: cardTop - 20,
right: 20,
@@ -367,7 +366,7 @@ class _FullScreenBlurOverlayState extends State<FullScreenBlurOverlay> {
),
const SizedBox(height: 8),
SizedBox(
height: 36, //
height: 36,
child: ColorPickerSlider(
TrackType.hue,
currentHSV,
@@ -42,7 +42,6 @@ class TransactionTile extends ConsumerWidget {
? Icons.swap_horiz_rounded
: (AppCategories.icons[transaction.category] ?? Icons.category_rounded);
// Check if we're on Total Balance page
final activeAccount = ref.watch(activeAccountProvider);
final displayCurrency =
activeAccount?.currency ?? ref.watch(currencyProvider).code;
@@ -57,19 +56,16 @@ class TransactionTile extends ConsumerWidget {
: 0.0;
final displaySymbol = currencyMap[displayCurrency]?.symbol ?? '';
// Look up the account name by matching transaction.accountId
final accounts = ref.watch(accountsProvider).valueOrNull ?? [];
final txAccount = accounts.firstWhereOrNull(
(a) => a.id == transaction.accountId,
);
// Build account label with 10-character limit
String accountLabel = txAccount?.name ?? '';
if (accountLabel.length > 10) {
accountLabel = '${accountLabel.substring(0, 10)}...';
}
// Transfer pairing logic
final pairs = ref.watch(transferPairsProvider);
final counterpart = pairs[transaction.id];
@@ -381,11 +377,9 @@ class TransactionTile extends ConsumerWidget {
bool isIncome,
Account? activeAccount,
) {
// Total Balance view with Transfer expense: no prefix
if (isTransfer && activeAccount == null && !isIncome) {
return '';
}
// All other cases: show + or
return isIncome ? '+ ' : '\u2212 ';
}
@@ -396,15 +390,12 @@ class TransactionTile extends ConsumerWidget {
Account? activeAccount,
Color defaultColor,
) {
// Total Balance view with Transfer expense: neutral color
if (isTransfer && activeAccount == null && !isIncome) {
return Theme.of(context).colorScheme.onSurface.withOpacity(0.8);
}
// Transfer in account view or Total Balance income: use income/expense colors
if (isTransfer) {
return isIncome ? AppColors.income : AppColors.expense;
}
// Non-transfer: use default color
return defaultColor;
}
}