solyanka iz fix for payout page design, ledger wallet now clickable
This commit is contained in:
@@ -2,9 +2,10 @@ import 'package:flutter/material.dart';
|
||||
|
||||
import 'package:provider/provider.dart';
|
||||
|
||||
import 'package:pshared/controllers/payment/source.dart';
|
||||
|
||||
import 'package:pweb/pages/payout_page/wallet/edit/buttons/send.dart';
|
||||
import 'package:pweb/pages/payout_page/wallet/edit/buttons/top_up.dart';
|
||||
import 'package:pshared/provider/payment/wallets.dart';
|
||||
|
||||
|
||||
class ButtonsWalletWidget extends StatelessWidget {
|
||||
@@ -12,25 +13,20 @@ class ButtonsWalletWidget extends StatelessWidget {
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
final provider = context.watch<WalletsProvider>();
|
||||
|
||||
if (provider.wallets.isEmpty) return const SizedBox.shrink();
|
||||
final source = context.watch<PaymentSourceController>();
|
||||
if (!source.hasSources) return const SizedBox.shrink();
|
||||
|
||||
return Row(
|
||||
mainAxisAlignment: MainAxisAlignment.spaceAround,
|
||||
children: [
|
||||
Expanded(
|
||||
child: SendPayoutButton(),
|
||||
),
|
||||
VerticalDivider(
|
||||
color: Theme.of(context).colorScheme.primary,
|
||||
thickness: 1,
|
||||
width: 10,
|
||||
),
|
||||
Expanded(
|
||||
child: TopUpButton(),
|
||||
),
|
||||
],
|
||||
mainAxisAlignment: MainAxisAlignment.spaceAround,
|
||||
children: [
|
||||
Expanded(child: SendPayoutButton()),
|
||||
VerticalDivider(
|
||||
color: Theme.of(context).colorScheme.primary,
|
||||
thickness: 1,
|
||||
width: 10,
|
||||
),
|
||||
Expanded(child: TopUpButton()),
|
||||
],
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -4,7 +4,8 @@ import 'package:go_router/go_router.dart';
|
||||
|
||||
import 'package:provider/provider.dart';
|
||||
|
||||
import 'package:pshared/controllers/balance_mask/wallets.dart';
|
||||
import 'package:pshared/controllers/payment/source.dart';
|
||||
import 'package:pshared/models/payment/source_type.dart';
|
||||
import 'package:pshared/models/payment/type.dart';
|
||||
|
||||
import 'package:pweb/app/router/payout_routes.dart';
|
||||
@@ -18,24 +19,27 @@ class SendPayoutButton extends StatelessWidget {
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
final loc = AppLocalizations.of(context)!;
|
||||
final source = context.watch<PaymentSourceController>();
|
||||
|
||||
final sourceType = source.selectedType;
|
||||
final paymentType = switch (sourceType) {
|
||||
PaymentSourceType.wallet => PaymentType.wallet,
|
||||
PaymentSourceType.ledger => PaymentType.ledger,
|
||||
_ => null,
|
||||
};
|
||||
|
||||
return ElevatedButton(
|
||||
style: ElevatedButton.styleFrom(
|
||||
shadowColor: null,
|
||||
elevation: 0,
|
||||
),
|
||||
onPressed: () {
|
||||
final wallets = context.read<WalletsController>();
|
||||
final wallet = wallets.selectedWallet;
|
||||
|
||||
if (wallet != null) {
|
||||
context.pushNamed(
|
||||
PayoutRoutes.payment,
|
||||
queryParameters: PayoutRoutes.buildQueryParameters(
|
||||
paymentType: PaymentType.wallet,
|
||||
),
|
||||
);
|
||||
}
|
||||
},
|
||||
style: ElevatedButton.styleFrom(shadowColor: null, elevation: 0),
|
||||
onPressed: paymentType == null
|
||||
? null
|
||||
: () {
|
||||
context.pushNamed(
|
||||
PayoutRoutes.payment,
|
||||
queryParameters: PayoutRoutes.buildQueryParameters(
|
||||
paymentType: paymentType,
|
||||
),
|
||||
);
|
||||
},
|
||||
child: Text(loc.payoutNavSendPayout),
|
||||
);
|
||||
}
|
||||
|
||||
@@ -2,34 +2,26 @@ import 'package:flutter/material.dart';
|
||||
|
||||
import 'package:provider/provider.dart';
|
||||
|
||||
import 'package:pshared/controllers/balance_mask/wallets.dart';
|
||||
import 'package:pshared/controllers/payment/source.dart';
|
||||
import 'package:pshared/models/payment/source_type.dart';
|
||||
|
||||
import 'package:pweb/app/router/payout_routes.dart';
|
||||
|
||||
import 'package:pweb/generated/i18n/app_localizations.dart';
|
||||
|
||||
|
||||
class TopUpButton extends StatelessWidget{
|
||||
class TopUpButton extends StatelessWidget {
|
||||
const TopUpButton({super.key});
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
final loc = AppLocalizations.of(context)!;
|
||||
final source = context.watch<PaymentSourceController>();
|
||||
final canTopUp = source.selectedType == PaymentSourceType.wallet;
|
||||
|
||||
return ElevatedButton(
|
||||
style: ElevatedButton.styleFrom(
|
||||
shadowColor: null,
|
||||
elevation: 0,
|
||||
),
|
||||
onPressed: () {
|
||||
final wallet = context.read<WalletsController>().selectedWallet;
|
||||
if (wallet == null) {
|
||||
ScaffoldMessenger.of(context).showSnackBar(
|
||||
SnackBar(content: Text(loc.noWalletSelected)),
|
||||
);
|
||||
return;
|
||||
}
|
||||
context.pushToWalletTopUp();
|
||||
},
|
||||
style: ElevatedButton.styleFrom(shadowColor: null, elevation: 0),
|
||||
onPressed: canTopUp ? () => context.pushToWalletTopUp() : null,
|
||||
child: Text(loc.topUpBalance),
|
||||
);
|
||||
}
|
||||
|
||||
@@ -1,55 +1,30 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter/services.dart';
|
||||
|
||||
import 'package:provider/provider.dart';
|
||||
|
||||
import 'package:pshared/controllers/balance_mask/wallets.dart';
|
||||
|
||||
import 'package:pweb/pages/dashboard/buttons/balance/amount.dart';
|
||||
import 'package:pweb/widgets/refresh_balance/wallet.dart';
|
||||
import 'package:pshared/controllers/payment/source.dart';
|
||||
|
||||
import 'package:pweb/pages/payout_page/wallet/edit/fields/ledger/section.dart';
|
||||
import 'package:pweb/pages/payout_page/wallet/edit/fields/wallet/wallet_section.dart';
|
||||
|
||||
class WalletEditFields extends StatelessWidget {
|
||||
const WalletEditFields({super.key});
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Consumer<WalletsController>(
|
||||
builder: (context, controller, _) {
|
||||
final wallet = controller.selectedWallet;
|
||||
|
||||
if (wallet == null) {
|
||||
return SizedBox.shrink();
|
||||
return Consumer<PaymentSourceController>(
|
||||
builder: (context, sourceController, _) {
|
||||
final wallet = sourceController.selectedWallet;
|
||||
if (wallet != null) {
|
||||
return WalletSection(wallet: wallet);
|
||||
}
|
||||
|
||||
return Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
Row(
|
||||
children: [
|
||||
Expanded(
|
||||
child: BalanceAmount(
|
||||
wallet: wallet,
|
||||
onToggleMask: () => controller.toggleBalanceMask(wallet.id),
|
||||
),
|
||||
),
|
||||
WalletBalanceRefreshButton(walletRef: wallet.id),
|
||||
],
|
||||
),
|
||||
const SizedBox(height: 8),
|
||||
Row(
|
||||
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||
children: [
|
||||
Text(wallet.walletUserID, style: Theme.of(context).textTheme.bodyLarge),
|
||||
IconButton(
|
||||
icon: Icon(Icons.copy),
|
||||
iconSize: 18,
|
||||
onPressed: () => Clipboard.setData(ClipboardData(text: wallet.walletUserID)),
|
||||
),
|
||||
],
|
||||
),
|
||||
],
|
||||
);
|
||||
final ledger = sourceController.selectedLedgerAccount;
|
||||
if (ledger != null) {
|
||||
return LedgerSection(ledger: ledger);
|
||||
}
|
||||
|
||||
return const SizedBox.shrink();
|
||||
},
|
||||
);
|
||||
}
|
||||
|
||||
@@ -0,0 +1,44 @@
|
||||
import 'package:pshared/models/ledger/account.dart';
|
||||
import 'package:pshared/utils/currency.dart';
|
||||
import 'package:pshared/utils/money.dart';
|
||||
|
||||
|
||||
class LedgerBalanceFormatter {
|
||||
const LedgerBalanceFormatter._();
|
||||
|
||||
static String format(LedgerAccount account) {
|
||||
final money = account.balance?.balance;
|
||||
if (money == null) return '--';
|
||||
|
||||
final amount = parseMoneyAmount(money.amount, fallback: double.nan);
|
||||
if (amount.isNaN) {
|
||||
return '${money.amount} ${money.currency}';
|
||||
}
|
||||
|
||||
try {
|
||||
final currency = currencyStringToCode(money.currency);
|
||||
final symbol = currencyCodeToSymbol(currency);
|
||||
if (symbol.trim().isEmpty) {
|
||||
return '${amountToString(amount)} ${money.currency}';
|
||||
}
|
||||
return '${amountToString(amount)} $symbol';
|
||||
} catch (_) {
|
||||
return '${amountToString(amount)} ${money.currency}';
|
||||
}
|
||||
}
|
||||
|
||||
static String formatMasked(LedgerAccount account) {
|
||||
final currency = account.currency.trim();
|
||||
if (currency.isEmpty) return '••••';
|
||||
|
||||
try {
|
||||
final symbol = currencyCodeToSymbol(currencyStringToCode(currency));
|
||||
if (symbol.trim().isEmpty) {
|
||||
return '•••• $currency';
|
||||
}
|
||||
return '•••• $symbol';
|
||||
} catch (_) {
|
||||
return '•••• $currency';
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,39 @@
|
||||
import 'package:flutter/material.dart';
|
||||
|
||||
|
||||
class LedgerBalanceRow extends StatelessWidget {
|
||||
final String balance;
|
||||
final bool isMasked;
|
||||
final VoidCallback onToggleMask;
|
||||
|
||||
const LedgerBalanceRow({
|
||||
super.key,
|
||||
required this.balance,
|
||||
required this.isMasked,
|
||||
required this.onToggleMask,
|
||||
});
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Row(
|
||||
children: [
|
||||
Flexible(
|
||||
child: Text(
|
||||
balance,
|
||||
style: Theme.of(
|
||||
context,
|
||||
).textTheme.headlineSmall?.copyWith(fontWeight: FontWeight.bold),
|
||||
),
|
||||
),
|
||||
const SizedBox(width: 8),
|
||||
GestureDetector(
|
||||
onTap: onToggleMask,
|
||||
child: Icon(
|
||||
isMasked ? Icons.visibility_off : Icons.visibility,
|
||||
size: 22,
|
||||
),
|
||||
),
|
||||
],
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,67 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter/services.dart';
|
||||
|
||||
import 'package:provider/provider.dart';
|
||||
|
||||
import 'package:pshared/controllers/balance_mask/ledger_accounts.dart';
|
||||
import 'package:pshared/models/ledger/account.dart';
|
||||
|
||||
import 'package:pweb/pages/payout_page/wallet/edit/fields/ledger/balance_formatter.dart';
|
||||
import 'package:pweb/pages/payout_page/wallet/edit/fields/ledger/balance_row.dart';
|
||||
import 'package:pweb/pages/payout_page/wallet/edit/fields/shared/copyable_value_row.dart';
|
||||
import 'package:pweb/widgets/refresh_balance/ledger.dart';
|
||||
|
||||
|
||||
class LedgerSection extends StatelessWidget {
|
||||
final LedgerAccount ledger;
|
||||
|
||||
const LedgerSection({super.key, required this.ledger});
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Consumer<LedgerBalanceMaskController>(
|
||||
builder: (context, balanceMask, _) {
|
||||
final isMasked = balanceMask.isBalanceMasked(ledger.ledgerAccountRef);
|
||||
final accountCode = ledger.accountCode.trim();
|
||||
final hasAccountCode = accountCode.isNotEmpty;
|
||||
final balance = isMasked
|
||||
? LedgerBalanceFormatter.formatMasked(ledger)
|
||||
: LedgerBalanceFormatter.format(ledger);
|
||||
|
||||
return Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
Row(
|
||||
children: [
|
||||
Expanded(
|
||||
child: LedgerBalanceRow(
|
||||
balance: balance,
|
||||
isMasked: isMasked,
|
||||
onToggleMask: () {
|
||||
balanceMask.toggleBalanceMask(ledger.ledgerAccountRef);
|
||||
},
|
||||
),
|
||||
),
|
||||
LedgerBalanceRefreshButton(
|
||||
ledgerAccountRef: ledger.ledgerAccountRef,
|
||||
),
|
||||
],
|
||||
),
|
||||
const SizedBox(height: 8),
|
||||
CopyableValueRow(
|
||||
value: hasAccountCode ? accountCode : '-',
|
||||
canCopy: hasAccountCode,
|
||||
onCopy: hasAccountCode
|
||||
? () {
|
||||
Clipboard.setData(ClipboardData(text: accountCode));
|
||||
}
|
||||
: null,
|
||||
overflow: TextOverflow.ellipsis,
|
||||
wrapValueWithFlexible: true,
|
||||
),
|
||||
],
|
||||
);
|
||||
},
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,40 @@
|
||||
import 'package:flutter/material.dart';
|
||||
|
||||
|
||||
class CopyableValueRow extends StatelessWidget {
|
||||
final String value;
|
||||
final bool canCopy;
|
||||
final VoidCallback? onCopy;
|
||||
final TextOverflow overflow;
|
||||
final bool wrapValueWithFlexible;
|
||||
|
||||
const CopyableValueRow({
|
||||
super.key,
|
||||
required this.value,
|
||||
required this.canCopy,
|
||||
required this.onCopy,
|
||||
this.overflow = TextOverflow.visible,
|
||||
this.wrapValueWithFlexible = false,
|
||||
});
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
final valueText = Text(
|
||||
value,
|
||||
style: Theme.of(context).textTheme.bodyLarge,
|
||||
overflow: overflow,
|
||||
);
|
||||
|
||||
return Row(
|
||||
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||
children: [
|
||||
if (wrapValueWithFlexible) Flexible(child: valueText) else valueText,
|
||||
IconButton(
|
||||
icon: const Icon(Icons.copy),
|
||||
iconSize: 18,
|
||||
onPressed: canCopy ? onCopy : null,
|
||||
),
|
||||
],
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,57 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter/services.dart';
|
||||
|
||||
import 'package:provider/provider.dart';
|
||||
|
||||
import 'package:pshared/controllers/balance_mask/wallets.dart';
|
||||
import 'package:pshared/models/payment/wallet.dart';
|
||||
|
||||
import 'package:pweb/pages/dashboard/buttons/balance/amount.dart';
|
||||
import 'package:pweb/pages/payout_page/wallet/edit/fields/shared/copyable_value_row.dart';
|
||||
import 'package:pweb/widgets/refresh_balance/wallet.dart';
|
||||
|
||||
|
||||
class WalletSection extends StatelessWidget {
|
||||
final Wallet wallet;
|
||||
|
||||
const WalletSection({super.key, required this.wallet});
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
final depositAddress = wallet.depositAddress?.trim();
|
||||
final hasDepositAddress =
|
||||
depositAddress != null && depositAddress.isNotEmpty;
|
||||
final copyAddress = hasDepositAddress ? depositAddress : '';
|
||||
|
||||
return Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
Row(
|
||||
children: [
|
||||
Expanded(
|
||||
child: BalanceAmount(
|
||||
wallet: wallet,
|
||||
onToggleMask: () {
|
||||
context.read<WalletsController>().toggleBalanceMask(
|
||||
wallet.id,
|
||||
);
|
||||
},
|
||||
),
|
||||
),
|
||||
WalletBalanceRefreshButton(walletRef: wallet.id),
|
||||
],
|
||||
),
|
||||
const SizedBox(height: 8),
|
||||
CopyableValueRow(
|
||||
value: hasDepositAddress ? depositAddress : '-',
|
||||
canCopy: hasDepositAddress,
|
||||
onCopy: hasDepositAddress
|
||||
? () {
|
||||
Clipboard.setData(ClipboardData(text: copyAddress));
|
||||
}
|
||||
: null,
|
||||
),
|
||||
],
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -2,7 +2,7 @@ import 'package:flutter/material.dart';
|
||||
|
||||
import 'package:provider/provider.dart';
|
||||
|
||||
import 'package:pshared/controllers/balance_mask/wallets.dart';
|
||||
import 'package:pshared/controllers/payment/source.dart';
|
||||
|
||||
import 'package:pweb/generated/i18n/app_localizations.dart';
|
||||
|
||||
@@ -12,15 +12,20 @@ class WalletEditHeader extends StatelessWidget {
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
final controller = context.watch<WalletsController>();
|
||||
final controller = context.watch<PaymentSourceController>();
|
||||
final wallet = controller.selectedWallet;
|
||||
final ledger = controller.selectedLedgerAccount;
|
||||
final loc = AppLocalizations.of(context)!;
|
||||
|
||||
if (wallet == null) {
|
||||
if (wallet == null && ledger == null) {
|
||||
return const SizedBox.shrink();
|
||||
}
|
||||
|
||||
final theme = Theme.of(context);
|
||||
final title = wallet != null
|
||||
? loc.paymentTypeCryptoWallet
|
||||
: loc.paymentTypeLedger;
|
||||
final subtitle = wallet?.tokenSymbol;
|
||||
|
||||
return Row(
|
||||
spacing: 8,
|
||||
@@ -32,14 +37,14 @@ class WalletEditHeader extends StatelessWidget {
|
||||
spacing: 4,
|
||||
children: [
|
||||
Text(
|
||||
loc.paymentTypeCryptoWallet,
|
||||
style: theme.textTheme.headlineMedium!.copyWith(
|
||||
title,
|
||||
style: theme.textTheme.headlineMedium?.copyWith(
|
||||
fontWeight: FontWeight.bold,
|
||||
),
|
||||
),
|
||||
if (wallet.tokenSymbol != null)
|
||||
if (subtitle != null && subtitle.trim().isNotEmpty)
|
||||
Text(
|
||||
wallet.tokenSymbol!,
|
||||
subtitle,
|
||||
style: theme.textTheme.bodyMedium?.copyWith(
|
||||
color: theme.colorScheme.onSurfaceVariant,
|
||||
),
|
||||
|
||||
@@ -2,17 +2,16 @@ import 'package:flutter/material.dart';
|
||||
|
||||
import 'package:provider/provider.dart';
|
||||
|
||||
import 'package:pshared/controllers/balance_mask/wallets.dart';
|
||||
import 'package:pshared/controllers/payment/source.dart';
|
||||
|
||||
import 'package:pweb/pages/payout_page/wallet/edit/buttons/buttons.dart';
|
||||
import 'package:pweb/pages/payout_page/wallet/edit/fields.dart';
|
||||
import 'package:pweb/pages/payout_page/wallet/edit/header.dart';
|
||||
import 'package:pweb/pages/payout_page/wallet/history/history.dart';
|
||||
import 'package:pweb/utils/dimensions.dart';
|
||||
|
||||
import 'package:pweb/generated/i18n/app_localizations.dart';
|
||||
|
||||
|
||||
//TODO make this page more generic and reusable
|
||||
class WalletEditPage extends StatelessWidget {
|
||||
final VoidCallback onBack;
|
||||
|
||||
@@ -23,11 +22,11 @@ class WalletEditPage extends StatelessWidget {
|
||||
final dimensions = AppDimensions();
|
||||
final loc = AppLocalizations.of(context)!;
|
||||
|
||||
return Consumer<WalletsController>(
|
||||
return Consumer<PaymentSourceController>(
|
||||
builder: (context, controller, child) {
|
||||
final wallet = controller.selectedWallet;
|
||||
|
||||
if (wallet == null) {
|
||||
final sourceType = controller.selectedType;
|
||||
|
||||
if (sourceType == null) {
|
||||
return Center(child: Text(loc.noWalletSelected));
|
||||
}
|
||||
|
||||
@@ -36,11 +35,15 @@ class WalletEditPage extends StatelessWidget {
|
||||
child: Column(
|
||||
children: [
|
||||
ConstrainedBox(
|
||||
constraints: BoxConstraints(maxWidth: dimensions.maxContentWidth),
|
||||
constraints: BoxConstraints(
|
||||
maxWidth: dimensions.maxContentWidth,
|
||||
),
|
||||
child: Material(
|
||||
elevation: dimensions.elevationSmall,
|
||||
color: Theme.of(context).colorScheme.onSecondary,
|
||||
borderRadius: BorderRadius.circular(dimensions.borderRadiusMedium),
|
||||
borderRadius: BorderRadius.circular(
|
||||
dimensions.borderRadiusMedium,
|
||||
),
|
||||
child: Padding(
|
||||
padding: EdgeInsets.all(dimensions.paddingLarge),
|
||||
child: SingleChildScrollView(
|
||||
@@ -55,19 +58,12 @@ class WalletEditPage extends StatelessWidget {
|
||||
WalletEditFields(),
|
||||
const SizedBox(height: 24),
|
||||
ButtonsWalletWidget(),
|
||||
const SizedBox(height: 24),
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
const SizedBox(height: 24),
|
||||
Expanded(
|
||||
child: SingleChildScrollView(
|
||||
child: WalletHistory(wallet: wallet),
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
);
|
||||
|
||||
@@ -2,118 +2,87 @@ import 'package:flutter/material.dart';
|
||||
|
||||
import 'package:provider/provider.dart';
|
||||
|
||||
import 'package:pshared/models/payment/wallet.dart';
|
||||
import 'package:pshared/models/payment/source_type.dart';
|
||||
import 'package:pshared/provider/payment/payments.dart';
|
||||
|
||||
import 'package:pweb/pages/payout_page/wallet/history/filters.dart';
|
||||
import 'package:pweb/pages/payout_page/wallet/history/table.dart';
|
||||
import 'package:pweb/controllers/operations/wallet_transactions.dart';
|
||||
import 'package:pweb/providers/wallet_transactions.dart';
|
||||
import 'package:pweb/controllers/operations/report_operations.dart';
|
||||
import 'package:pweb/models/state/load_more_state.dart';
|
||||
import 'package:pweb/pages/report/cards/list.dart';
|
||||
import 'package:pweb/pages/report/operations/actions.dart';
|
||||
import 'package:pweb/pages/report/operations/states/error.dart';
|
||||
import 'package:pweb/pages/report/operations/states/loading.dart';
|
||||
|
||||
import 'package:pweb/generated/i18n/app_localizations.dart';
|
||||
|
||||
|
||||
class WalletHistory extends StatefulWidget {
|
||||
final Wallet wallet;
|
||||
class WalletHistory extends StatelessWidget {
|
||||
final String sourceRef;
|
||||
final PaymentSourceType sourceType;
|
||||
final List<String> sourceRefs;
|
||||
|
||||
const WalletHistory({super.key, required this.wallet});
|
||||
|
||||
@override
|
||||
State<WalletHistory> createState() => _WalletHistoryState();
|
||||
}
|
||||
|
||||
class _WalletHistoryState extends State<WalletHistory> {
|
||||
@override
|
||||
void initState() {
|
||||
super.initState();
|
||||
_load();
|
||||
}
|
||||
|
||||
@override
|
||||
void didUpdateWidget(covariant WalletHistory oldWidget) {
|
||||
super.didUpdateWidget(oldWidget);
|
||||
if (oldWidget.wallet.id != widget.wallet.id) {
|
||||
_load();
|
||||
}
|
||||
}
|
||||
|
||||
void _load() {
|
||||
WidgetsBinding.instance.addPostFrameCallback((_) {
|
||||
context
|
||||
.read<WalletTransactionsProvider>()
|
||||
.load(walletId: widget.wallet.id);
|
||||
});
|
||||
}
|
||||
|
||||
Future<void> _pickRange() async {
|
||||
final provider = context.read<WalletTransactionsController>();
|
||||
final now = DateTime.now();
|
||||
final initial = provider.dateRange ??
|
||||
DateTimeRange(
|
||||
start: now.subtract(const Duration(days: 30)),
|
||||
end: now,
|
||||
);
|
||||
|
||||
final picked = await showDateRangePicker(
|
||||
context: context,
|
||||
firstDate: now.subtract(const Duration(days: 365)),
|
||||
lastDate: now.add(const Duration(days: 1)),
|
||||
initialDateRange: initial,
|
||||
);
|
||||
|
||||
if (picked != null) {
|
||||
provider.setDateRange(picked);
|
||||
}
|
||||
}
|
||||
const WalletHistory({
|
||||
super.key,
|
||||
required this.sourceRef,
|
||||
required this.sourceType,
|
||||
required this.sourceRefs,
|
||||
});
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return ChangeNotifierProxyProvider<
|
||||
PaymentsProvider,
|
||||
ReportOperationsController
|
||||
>(
|
||||
create: (_) => ReportOperationsController(),
|
||||
update: (_, payments, controller) => controller!
|
||||
..update(
|
||||
payments,
|
||||
sourceType: sourceType,
|
||||
sourceRef: sourceRef,
|
||||
sourceRefs: sourceRefs,
|
||||
),
|
||||
child: const _WalletHistoryContent(),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
class _WalletHistoryContent extends StatelessWidget {
|
||||
const _WalletHistoryContent();
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
final theme = Theme.of(context);
|
||||
final loc = AppLocalizations.of(context)!;
|
||||
|
||||
return Consumer<WalletTransactionsController>(
|
||||
builder: (context, provider, child) {
|
||||
if (provider.isLoading) {
|
||||
return const Padding(
|
||||
padding: EdgeInsets.all(16.0),
|
||||
child: Center(child: CircularProgressIndicator()),
|
||||
return Consumer<ReportOperationsController>(
|
||||
builder: (context, controller, child) {
|
||||
if (controller.isLoading) {
|
||||
return const OperationHistoryLoading();
|
||||
}
|
||||
|
||||
if (controller.error != null) {
|
||||
final message =
|
||||
controller.error?.toString() ?? loc.noErrorInformation;
|
||||
return OperationHistoryError(
|
||||
message: loc.notificationError(message),
|
||||
retryLabel: loc.retry,
|
||||
onRetry: controller.refresh,
|
||||
);
|
||||
}
|
||||
|
||||
if (provider.error != null) {
|
||||
return Padding(
|
||||
padding: const EdgeInsets.all(16.0),
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
Text(
|
||||
loc.failedToLoadHistory,
|
||||
style: theme.textTheme.titleMedium!
|
||||
.copyWith(color: theme.colorScheme.error),
|
||||
),
|
||||
const SizedBox(height: 8),
|
||||
Text(loc.notificationError(provider.error ?? loc.noErrorInformation)),
|
||||
const SizedBox(height: 8),
|
||||
OutlinedButton(
|
||||
onPressed: _load,
|
||||
child: Text(loc.retry),
|
||||
),
|
||||
],
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
final transactions = provider.filteredTransactions;
|
||||
|
||||
return Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.stretch,
|
||||
children: [
|
||||
WalletHistoryFilters(
|
||||
provider: provider,
|
||||
onPickRange: _pickRange,
|
||||
),
|
||||
const SizedBox(height: 12),
|
||||
WalletTransactionsTable(transactions: transactions),
|
||||
],
|
||||
final hasLoadMore = controller.loadMoreState != LoadMoreState.hidden;
|
||||
return Padding(
|
||||
padding: const EdgeInsets.symmetric(horizontal: 16.0),
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.stretch,
|
||||
children: [
|
||||
OperationsCardsList(
|
||||
operations: controller.filteredOperations,
|
||||
onTap: (operation) => openPaymentDetails(context, operation),
|
||||
loadMoreState: controller.loadMoreState,
|
||||
onLoadMore: hasLoadMore ? controller.loadMore : null,
|
||||
),
|
||||
],
|
||||
),
|
||||
);
|
||||
},
|
||||
);
|
||||
|
||||
Reference in New Issue
Block a user