From 9a90e6a03b2550c90f984dc6bd15bcb822e65c17 Mon Sep 17 00:00:00 2001 From: Arseni Date: Tue, 16 Dec 2025 19:37:28 +0300 Subject: [PATCH] Wallet update for correct name and symbol appearance --- .../lib/data/mapper/wallet/wallet.dart | 5 + .../pshared/lib/models/wallet/wallet.dart | 13 ++- frontend/pweb/lib/data/mappers/wallet_ui.dart | 6 +- frontend/pweb/lib/l10n/en.arb | 1 + frontend/pweb/lib/l10n/ru.arb | 1 + frontend/pweb/lib/models/wallet.dart | 22 +++- .../pages/dashboard/buttons/balance/card.dart | 4 +- .../dashboard/buttons/balance/header.dart | 35 +++--- .../lib/pages/payout_page/wallet/card.dart | 19 ++- .../pages/payout_page/wallet/edit/header.dart | 108 ++++-------------- .../pweb/lib/pages/wallet_top_up/content.dart | 2 +- .../pweb/lib/pages/wallet_top_up/header.dart | 12 +- 12 files changed, 111 insertions(+), 117 deletions(-) diff --git a/frontend/pshared/lib/data/mapper/wallet/wallet.dart b/frontend/pshared/lib/data/mapper/wallet/wallet.dart index 9635fc4..da4352f 100644 --- a/frontend/pshared/lib/data/mapper/wallet/wallet.dart +++ b/frontend/pshared/lib/data/mapper/wallet/wallet.dart @@ -2,6 +2,7 @@ import 'package:pshared/data/dto/wallet/balance.dart'; import 'package:pshared/data/dto/wallet/wallet.dart'; import 'package:pshared/data/mapper/wallet/balance.dart'; import 'package:pshared/data/mapper/wallet/money.dart'; +import 'package:pshared/models/describable.dart'; import 'package:pshared/models/wallet/wallet.dart'; @@ -22,5 +23,9 @@ extension WalletDTOMapper on WalletDTO { updatedAt: (updatedAt == null || updatedAt!.isEmpty) ? null : DateTime.tryParse(updatedAt!), balance: balance?.toDomain(), availableMoney: balance?.available?.toDomain(), + describable: newDescribable( + name: metadata?['name'] ?? 'Crypto Wallet', + description: metadata?['description'], + ), ); } diff --git a/frontend/pshared/lib/models/wallet/wallet.dart b/frontend/pshared/lib/models/wallet/wallet.dart index 188e089..cf6efb0 100644 --- a/frontend/pshared/lib/models/wallet/wallet.dart +++ b/frontend/pshared/lib/models/wallet/wallet.dart @@ -1,5 +1,6 @@ import 'package:pshared/models/wallet/balance.dart'; import 'package:pshared/models/wallet/money.dart'; +import 'package:pshared/models/describable.dart'; class WalletAsset { @@ -14,7 +15,7 @@ class WalletAsset { }); } -class WalletModel { +class WalletModel implements Describable { final String walletRef; final String organizationRef; final String ownerRef; @@ -26,6 +27,13 @@ class WalletModel { final DateTime? updatedAt; final WalletBalance? balance; final WalletMoney? availableMoney; + final Describable describable; + + @override + String get name => describable.name; + + @override + String? get description => describable.description; const WalletModel({ required this.walletRef, @@ -39,11 +47,13 @@ class WalletModel { this.updatedAt, this.balance, this.availableMoney, + required this.describable, }); WalletModel copyWith({ WalletBalance? balance, WalletMoney? availableMoney, + Describable? describable, }) { return WalletModel( walletRef: walletRef, @@ -57,6 +67,7 @@ class WalletModel { updatedAt: updatedAt, balance: balance ?? this.balance, availableMoney: availableMoney ?? this.availableMoney, + describable: describable ?? this.describable, ); } } diff --git a/frontend/pweb/lib/data/mappers/wallet_ui.dart b/frontend/pweb/lib/data/mappers/wallet_ui.dart index a13f3b3..f938338 100644 --- a/frontend/pweb/lib/data/mappers/wallet_ui.dart +++ b/frontend/pweb/lib/data/mappers/wallet_ui.dart @@ -1,6 +1,7 @@ import 'package:pshared/models/wallet/wallet.dart' as domain; import 'package:pshared/models/currency.dart'; +import 'package:pshared/models/describable.dart'; import 'package:pweb/models/wallet.dart'; @@ -17,7 +18,6 @@ extension WalletUiMapper on domain.WalletModel { return Wallet( id: walletRef, walletUserID: walletRef, - name: metadata?['name'] ?? walletRef, balance: parsedAmount, currency: currency, isHidden: true, @@ -26,6 +26,10 @@ extension WalletUiMapper on domain.WalletModel { network: asset.chain, tokenSymbol: asset.tokenSymbol, contractAddress: asset.contractAddress, + describable: newDescribable( + name: metadata?['name'] ?? 'Crypto Wallet', + description: metadata?['description'], + ), ); } } diff --git a/frontend/pweb/lib/l10n/en.arb b/frontend/pweb/lib/l10n/en.arb index 22fd2f5..8dd3d8d 100644 --- a/frontend/pweb/lib/l10n/en.arb +++ b/frontend/pweb/lib/l10n/en.arb @@ -311,6 +311,7 @@ "paymentTypeBankAccount": "Russian Bank Account", "paymentTypeIban": "IBAN", "paymentTypeWallet": "Wallet", + "paymentTypeCryptoWallet": "Crypto Wallet", "paymentTypeCryptoAddress": "Crypto address", "paymentTypeLedger": "Ledger account", "paymentTypeManagedWallet": "Managed wallet", diff --git a/frontend/pweb/lib/l10n/ru.arb b/frontend/pweb/lib/l10n/ru.arb index e47f9dc..72718c0 100644 --- a/frontend/pweb/lib/l10n/ru.arb +++ b/frontend/pweb/lib/l10n/ru.arb @@ -311,6 +311,7 @@ "paymentTypeBankAccount": "Российский банковский счет", "paymentTypeIban": "IBAN", "paymentTypeWallet": "Кошелек", + "paymentTypeCryptoWallet": "Криптокошелек", "paymentTypeCryptoAddress": "Крипто-адрес", "paymentTypeLedger": "Леджер счет", "paymentTypeManagedWallet": "Управляемый кошелек", diff --git a/frontend/pweb/lib/models/wallet.dart b/frontend/pweb/lib/models/wallet.dart index ece57cf..cf1e362 100644 --- a/frontend/pweb/lib/models/wallet.dart +++ b/frontend/pweb/lib/models/wallet.dart @@ -1,10 +1,10 @@ import 'package:pshared/models/currency.dart'; +import 'package:pshared/models/describable.dart'; -class Wallet { +class Wallet implements Describable { final String id; final String walletUserID; // ID or number that we show the user - final String name; final double balance; final Currency currency; final bool isHidden; @@ -13,14 +13,21 @@ class Wallet { final String? network; final String? tokenSymbol; final String? contractAddress; + final Describable describable; + + @override + String get name => describable.name; + + @override + String? get description => describable.description; Wallet({ required this.id, required this.walletUserID, - required this.name, required this.balance, required this.currency, required this.calculatedAt, + required this.describable, this.isHidden = true, this.depositAddress, this.network, @@ -30,7 +37,6 @@ class Wallet { Wallet copyWith({ String? id, - String? name, double? balance, Currency? currency, String? walletUserID, @@ -39,9 +45,11 @@ class Wallet { String? network, String? tokenSymbol, String? contractAddress, + Describable? describable, + String? name, + String? Function()? description, }) => Wallet( id: id ?? this.id, - name: name ?? this.name, balance: balance ?? this.balance, currency: currency ?? this.currency, walletUserID: walletUserID ?? this.walletUserID, @@ -51,5 +59,9 @@ class Wallet { network: network ?? this.network, tokenSymbol: tokenSymbol ?? this.tokenSymbol, contractAddress: contractAddress ?? this.contractAddress, + describable: describable + ?? (name != null || description != null + ? this.describable.copyWith(name: name, description: description) + : this.describable), ); } diff --git a/frontend/pweb/lib/pages/dashboard/buttons/balance/card.dart b/frontend/pweb/lib/pages/dashboard/buttons/balance/card.dart index 70bf526..d3668fc 100644 --- a/frontend/pweb/lib/pages/dashboard/buttons/balance/card.dart +++ b/frontend/pweb/lib/pages/dashboard/buttons/balance/card.dart @@ -34,8 +34,8 @@ class WalletCard extends StatelessWidget { crossAxisAlignment: CrossAxisAlignment.start, children: [ BalanceHeader( - walletName: wallet.name, - walletId: wallet.walletUserID, + walletNetwork: wallet.network, + tokenSymbol: wallet.tokenSymbol, ), BalanceAmount( wallet: wallet, diff --git a/frontend/pweb/lib/pages/dashboard/buttons/balance/header.dart b/frontend/pweb/lib/pages/dashboard/buttons/balance/header.dart index 48c5090..4d6ef04 100644 --- a/frontend/pweb/lib/pages/dashboard/buttons/balance/header.dart +++ b/frontend/pweb/lib/pages/dashboard/buttons/balance/header.dart @@ -2,37 +2,46 @@ import 'package:flutter/material.dart'; class BalanceHeader extends StatelessWidget { - final String walletName; - final String walletId; + final String? walletNetwork; + final String? tokenSymbol; const BalanceHeader({ super.key, - required this.walletName, - required this.walletId, + this.walletNetwork, + this.tokenSymbol, }); - static const double _spacing = 8.0; - @override Widget build(BuildContext context) { final textTheme = Theme.of(context).textTheme; final colorScheme = Theme.of(context).colorScheme; + final symbol = tokenSymbol?.trim(); return Row( children: [ Text( - walletName, + 'Crypto Wallet', style: textTheme.titleMedium?.copyWith( color: colorScheme.onSurface, ), ), - const SizedBox(width: _spacing), - Text( - walletId, - style: textTheme.bodySmall?.copyWith( - color: colorScheme.onSurface, + if (symbol != null && symbol.isNotEmpty) ...[ + const SizedBox(width: 8), + Container( + padding: const EdgeInsets.symmetric(horizontal: 10, vertical: 6), + decoration: BoxDecoration( + color: colorScheme.primaryContainer, + borderRadius: BorderRadius.circular(999), + ), + child: Text( + symbol, + style: textTheme.bodyMedium?.copyWith( + color: colorScheme.onPrimaryContainer, + fontWeight: FontWeight.w600, + ), + ), ), - ), + ], ], ); } diff --git a/frontend/pweb/lib/pages/payout_page/wallet/card.dart b/frontend/pweb/lib/pages/payout_page/wallet/card.dart index ea0babf..9824794 100644 --- a/frontend/pweb/lib/pages/payout_page/wallet/card.dart +++ b/frontend/pweb/lib/pages/payout_page/wallet/card.dart @@ -3,6 +3,7 @@ import 'package:flutter/material.dart'; import 'package:provider/provider.dart'; import 'package:pshared/utils/currency.dart'; +import 'package:pweb/generated/i18n/app_localizations.dart'; import 'package:pweb/models/wallet.dart'; import 'package:pweb/pages/dashboard/buttons/balance/amount.dart'; @@ -48,9 +49,21 @@ class WalletCard extends StatelessWidget { }, ), Text( - wallet.name, - style: theme.textTheme.bodyLarge!.copyWith(fontWeight: FontWeight.w500), + AppLocalizations.of(context)!.paymentTypeCryptoWallet, + style: theme.textTheme.bodyLarge!.copyWith( + fontWeight: FontWeight.w600, + color: theme.colorScheme.onSurface, + ), ), + if (wallet.tokenSymbol != null) ...[ + const SizedBox(height: 4), + Text( + wallet.tokenSymbol!, + style: theme.textTheme.bodyMedium?.copyWith( + color: theme.colorScheme.onSurfaceVariant, + ), + ), + ], ], ), ), @@ -60,4 +73,4 @@ class WalletCard extends StatelessWidget { ), ); } -} \ No newline at end of file +} diff --git a/frontend/pweb/lib/pages/payout_page/wallet/edit/header.dart b/frontend/pweb/lib/pages/payout_page/wallet/edit/header.dart index d51db57..b5db274 100644 --- a/frontend/pweb/lib/pages/payout_page/wallet/edit/header.dart +++ b/frontend/pweb/lib/pages/payout_page/wallet/edit/header.dart @@ -3,114 +3,46 @@ import 'package:flutter/material.dart'; import 'package:provider/provider.dart'; import 'package:pweb/providers/wallets.dart'; -import 'package:pweb/widgets/error/snackbar.dart'; - -import 'package:pweb/generated/i18n/app_localizations.dart'; -class WalletEditHeader extends StatefulWidget { +class WalletEditHeader extends StatelessWidget { const WalletEditHeader({super.key}); - @override - State createState() => _WalletEditHeaderState(); -} - -class _WalletEditHeaderState extends State { - bool _isEditing = false; - late TextEditingController _controller; - - @override - void initState() { - super.initState(); - _controller = TextEditingController(); - } - - @override - void dispose() { - _controller.dispose(); - super.dispose(); - } - @override Widget build(BuildContext context) { final provider = context.watch(); final wallet = provider.selectedWallet; - final loc = AppLocalizations.of(context)!; if (wallet == null) { - return SizedBox.shrink(); + return const SizedBox.shrink(); } final theme = Theme.of(context); - if (!_isEditing) { - _controller.text = wallet.name; - } - return Row( spacing: 8, mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ Expanded( - child: !_isEditing - ? Row( - children: [ - Expanded( - child: Text( - wallet.name, - style: theme.textTheme.headlineMedium!.copyWith( - fontWeight: FontWeight.bold, - ), - ), - ), - IconButton( - icon: const Icon(Icons.edit), - onPressed: () { - setState(() { - _isEditing = true; - }); - }, - ), - ], - ) - : Row( - children: [ - Expanded( - child: TextFormField( - controller: _controller, - decoration: InputDecoration( - border: OutlineInputBorder(), - isDense: true, - hintText: loc.walletName, - ), - ), - ), - IconButton( - icon: const Icon(Icons.check), - color: theme.colorScheme.primary, - onPressed: () async { - await executeActionWithNotification( - context: context, - action: () async => await provider.updateWallet(wallet.copyWith(name: _controller.text)), - errorMessage: loc.walletNameUpdateFailed, - successMessage: loc.walletNameSaved, - ); - setState(() { - _isEditing = false; - }); - }, - ), - IconButton( - icon: const Icon(Icons.close), - onPressed: () { - _controller.text = wallet.name; - setState(() { - _isEditing = false; - }); - }, - ), - ], + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + spacing: 4, + children: [ + Text( + 'Crypto Wallet', + style: theme.textTheme.headlineMedium!.copyWith( + fontWeight: FontWeight.bold, ), + ), + if (wallet.tokenSymbol != null) + Text( + wallet.tokenSymbol!, + style: theme.textTheme.bodyMedium?.copyWith( + color: theme.colorScheme.onSurfaceVariant, + ), + ), + ], + ), ), ], ); diff --git a/frontend/pweb/lib/pages/wallet_top_up/content.dart b/frontend/pweb/lib/pages/wallet_top_up/content.dart index e472fda..9ed3784 100644 --- a/frontend/pweb/lib/pages/wallet_top_up/content.dart +++ b/frontend/pweb/lib/pages/wallet_top_up/content.dart @@ -46,7 +46,7 @@ class WalletTopUpContent extends StatelessWidget { children: [ WalletTopUpHeader( onBack: onBack, - walletName: wallet.name, + tokenSymbol: assetLabel, ), SizedBox(height: dimensions.paddingLarge), WalletTopUpMeta( diff --git a/frontend/pweb/lib/pages/wallet_top_up/header.dart b/frontend/pweb/lib/pages/wallet_top_up/header.dart index fa5a23e..e4263e2 100644 --- a/frontend/pweb/lib/pages/wallet_top_up/header.dart +++ b/frontend/pweb/lib/pages/wallet_top_up/header.dart @@ -5,18 +5,24 @@ import 'package:pweb/generated/i18n/app_localizations.dart'; class WalletTopUpHeader extends StatelessWidget { final VoidCallback onBack; - final String walletName; + final String? tokenSymbol; const WalletTopUpHeader({ super.key, required this.onBack, - required this.walletName, + this.tokenSymbol, }); @override Widget build(BuildContext context) { final theme = Theme.of(context); final loc = AppLocalizations.of(context)!; + final symbol = tokenSymbol?.trim(); + + final subtitle = [ + 'Crypto Wallet', + if (symbol != null && symbol.isNotEmpty) symbol, + ].join(' · '); return Row( children: [ @@ -34,7 +40,7 @@ class WalletTopUpHeader extends StatelessWidget { ), const SizedBox(height: 4), Text( - walletName, + subtitle, style: theme.textTheme.bodyMedium?.copyWith( color: theme.colorScheme.onSurfaceVariant, ),