redesigned payment page + a lot of fixes
This commit is contained in:
@@ -1,81 +0,0 @@
|
||||
import 'package:flutter/material.dart';
|
||||
|
||||
import 'package:provider/provider.dart';
|
||||
|
||||
import 'package:pshared/provider/payment/amount.dart';
|
||||
import 'package:pshared/utils/currency.dart';
|
||||
import 'package:pshared/utils/money.dart';
|
||||
|
||||
import 'package:pweb/generated/i18n/app_localizations.dart';
|
||||
|
||||
|
||||
class PaymentAmountWidget extends StatefulWidget {
|
||||
const PaymentAmountWidget({super.key});
|
||||
|
||||
@override
|
||||
State<PaymentAmountWidget> createState() => _PaymentAmountWidgetState();
|
||||
}
|
||||
|
||||
class _PaymentAmountWidgetState extends State<PaymentAmountWidget> {
|
||||
late final TextEditingController _controller;
|
||||
bool _isSyncingText = false;
|
||||
|
||||
@override
|
||||
void initState() {
|
||||
super.initState();
|
||||
final initialAmount = context.read<PaymentAmountProvider>().amount;
|
||||
_controller = TextEditingController(text: amountToString(initialAmount));
|
||||
}
|
||||
|
||||
@override
|
||||
void dispose() {
|
||||
_controller.dispose();
|
||||
super.dispose();
|
||||
}
|
||||
|
||||
double? _parseAmount(String value) {
|
||||
final parsed = parseMoneyAmount(
|
||||
value.replaceAll(',', '.'),
|
||||
fallback: double.nan,
|
||||
);
|
||||
return parsed.isNaN ? null : parsed;
|
||||
}
|
||||
|
||||
void _syncTextWithAmount(double amount) {
|
||||
final parsedText = _parseAmount(_controller.text);
|
||||
if (parsedText != null && parsedText == amount) return;
|
||||
|
||||
final nextText = amountToString(amount);
|
||||
_isSyncingText = true;
|
||||
_controller.value = TextEditingValue(
|
||||
text: nextText,
|
||||
selection: TextSelection.collapsed(offset: nextText.length),
|
||||
);
|
||||
_isSyncingText = false;
|
||||
}
|
||||
|
||||
void _onChanged(String value) {
|
||||
if (_isSyncingText) return;
|
||||
|
||||
final parsed = _parseAmount(value);
|
||||
if (parsed != null) {
|
||||
context.read<PaymentAmountProvider>().setAmount(parsed);
|
||||
}
|
||||
}
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
final amount = context.select<PaymentAmountProvider, double>((provider) => provider.amount);
|
||||
_syncTextWithAmount(amount);
|
||||
|
||||
return TextField(
|
||||
controller: _controller,
|
||||
keyboardType: const TextInputType.numberWithOptions(decimal: true),
|
||||
decoration: InputDecoration(
|
||||
labelText: AppLocalizations.of(context)!.amount,
|
||||
border: const OutlineInputBorder(),
|
||||
),
|
||||
onChanged: _onChanged,
|
||||
);
|
||||
}
|
||||
}
|
||||
37
frontend/pweb/lib/pages/dashboard/payouts/amount/feild.dart
Normal file
37
frontend/pweb/lib/pages/dashboard/payouts/amount/feild.dart
Normal file
@@ -0,0 +1,37 @@
|
||||
import 'package:flutter/material.dart';
|
||||
|
||||
import 'package:provider/provider.dart';
|
||||
|
||||
import 'package:pshared/controllers/balance_mask/wallets.dart';
|
||||
import 'package:pshared/models/currency.dart';
|
||||
import 'package:pshared/utils/currency.dart';
|
||||
|
||||
import 'package:pweb/controllers/payments/amount_field.dart';
|
||||
|
||||
import 'package:pweb/generated/i18n/app_localizations.dart';
|
||||
|
||||
|
||||
class PaymentAmountField extends StatelessWidget {
|
||||
const PaymentAmountField();
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
final currency = context.select<WalletsController, Currency?>(
|
||||
(c) => c.selectedWallet?.currency,
|
||||
);
|
||||
final symbol = currency == null ? null : currencyCodeToSymbol(currency);
|
||||
|
||||
final ui = context.watch<PaymentAmountFieldController>();
|
||||
|
||||
return TextField(
|
||||
controller: ui.textController,
|
||||
keyboardType: const TextInputType.numberWithOptions(decimal: true),
|
||||
decoration: InputDecoration(
|
||||
labelText: AppLocalizations.of(context)!.amount,
|
||||
border: const OutlineInputBorder(),
|
||||
prefixText: symbol == null ? null : '$symbol\u00A0',
|
||||
),
|
||||
onChanged: ui.handleChanged,
|
||||
);
|
||||
}
|
||||
}
|
||||
28
frontend/pweb/lib/pages/dashboard/payouts/amount/widget.dart
Normal file
28
frontend/pweb/lib/pages/dashboard/payouts/amount/widget.dart
Normal file
@@ -0,0 +1,28 @@
|
||||
import 'package:flutter/material.dart';
|
||||
|
||||
import 'package:provider/provider.dart';
|
||||
|
||||
import 'package:pshared/provider/payment/amount.dart';
|
||||
|
||||
import 'package:pweb/controllers/payments/amount_field.dart';
|
||||
import 'package:pweb/pages/dashboard/payouts/amount/feild.dart';
|
||||
|
||||
|
||||
class PaymentAmountWidget extends StatelessWidget {
|
||||
const PaymentAmountWidget({super.key});
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return ChangeNotifierProxyProvider<PaymentAmountProvider, PaymentAmountFieldController>(
|
||||
create: (ctx) {
|
||||
final initialAmount = ctx.read<PaymentAmountProvider>().amount;
|
||||
return PaymentAmountFieldController(initialAmount: initialAmount);
|
||||
},
|
||||
update: (ctx, amountProvider, controller) {
|
||||
controller!.update(amountProvider);
|
||||
return controller;
|
||||
},
|
||||
child: const PaymentAmountField(),
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -15,15 +15,30 @@ class FeePayerSwitch extends StatelessWidget {
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) => Consumer<PaymentAmountProvider>(
|
||||
builder: (context, provider, _) => Row(
|
||||
spacing: spacing,
|
||||
children: [
|
||||
Text(AppLocalizations.of(context)!.recipientPaysFee, style: style),
|
||||
Switch(
|
||||
value: !provider.payerCoversFee,
|
||||
onChanged: (val) => provider.setPayerCoversFee(!val),
|
||||
builder: (context, provider, _) {
|
||||
final recipientPaysFee = !provider.payerCoversFee;
|
||||
final textStyle = style ?? Theme.of(context).textTheme.bodySmall;
|
||||
void updateRecipientPaysFee(bool value) {
|
||||
provider.setPayerCoversFee(!value);
|
||||
}
|
||||
|
||||
return InkWell(
|
||||
borderRadius: BorderRadius.circular(6),
|
||||
onTap: () => updateRecipientPaysFee(!recipientPaysFee),
|
||||
child: Row(
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
children: [
|
||||
Checkbox(
|
||||
value: recipientPaysFee,
|
||||
onChanged: (val) => updateRecipientPaysFee(val ?? false),
|
||||
visualDensity: VisualDensity.compact,
|
||||
materialTapTargetSize: MaterialTapTargetSize.shrinkWrap,
|
||||
),
|
||||
SizedBox(width: spacing),
|
||||
Text(AppLocalizations.of(context)!.recipientPaysFee, style: textStyle),
|
||||
],
|
||||
),
|
||||
],
|
||||
),
|
||||
);
|
||||
},
|
||||
);
|
||||
}
|
||||
|
||||
@@ -1,8 +1,13 @@
|
||||
import 'package:flutter/material.dart';
|
||||
|
||||
import 'package:pweb/pages/dashboard/payouts/amount.dart';
|
||||
import 'package:provider/provider.dart';
|
||||
|
||||
import 'package:pweb/controllers/payouts/quotation.dart';
|
||||
import 'package:pweb/models/dashboard/quote_status_data.dart';
|
||||
import 'package:pweb/pages/dashboard/payouts/amount/widget.dart';
|
||||
import 'package:pweb/pages/dashboard/payouts/fee_payer.dart';
|
||||
import 'package:pweb/pages/dashboard/payouts/quote_status/quote_status.dart';
|
||||
import 'package:pweb/pages/dashboard/payouts/quote_status/widgets/card.dart';
|
||||
import 'package:pweb/pages/dashboard/payouts/quote_status/widgets/refresh_section.dart';
|
||||
import 'package:pweb/pages/dashboard/payouts/summary/widget.dart';
|
||||
|
||||
import 'package:pweb/generated/i18n/app_localizations.dart';
|
||||
@@ -12,34 +17,134 @@ class PaymentFormWidget extends StatelessWidget {
|
||||
const PaymentFormWidget({super.key});
|
||||
|
||||
static const double _smallSpacing = 5;
|
||||
static const double _mediumSpacing = 10;
|
||||
static const double _largeSpacing = 16;
|
||||
static const double _mediumSpacing = 12;
|
||||
static const double _largeSpacing = 20;
|
||||
static const double _extraSpacing = 15;
|
||||
static const double _columnSpacing = 24;
|
||||
static const double _narrowWidth = 560;
|
||||
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
final theme = Theme.of(context);
|
||||
final loc = AppLocalizations.of(context)!;
|
||||
final controller = context.watch<QuotationController>();
|
||||
final quoteStatus = QuoteStatusData.resolve(
|
||||
controller: controller,
|
||||
loc: loc,
|
||||
);
|
||||
|
||||
return Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
Text(loc.details, style: theme.textTheme.titleMedium),
|
||||
const SizedBox(height: _smallSpacing),
|
||||
return LayoutBuilder(
|
||||
builder: (context, constraints) {
|
||||
final isNarrow = constraints.maxWidth < _narrowWidth;
|
||||
|
||||
const PaymentAmountWidget(),
|
||||
final detailsHeader = Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
Text(loc.details, style: theme.textTheme.titleMedium),
|
||||
const SizedBox(height: _smallSpacing),
|
||||
],
|
||||
);
|
||||
|
||||
const SizedBox(height: _mediumSpacing),
|
||||
final quoteCard = QuoteStatusCard(
|
||||
statusType: quoteStatus.statusType,
|
||||
isLoading: quoteStatus.isLoading,
|
||||
statusText: quoteStatus.statusText,
|
||||
helperText: quoteStatus.helperText,
|
||||
canRefresh: quoteStatus.canRefresh,
|
||||
showPrimaryRefresh: quoteStatus.showPrimaryRefresh,
|
||||
onRefresh: controller.refreshQuotation,
|
||||
);
|
||||
|
||||
FeePayerSwitch(spacing: _mediumSpacing, style: theme.textTheme.titleMedium),
|
||||
final autoRefreshSection = QuoteAutoRefreshSection(
|
||||
autoRefreshMode: quoteStatus.autoRefreshMode,
|
||||
canRefresh: quoteStatus.canRefresh,
|
||||
onModeChanged: controller.setAutoRefreshMode,
|
||||
);
|
||||
|
||||
const SizedBox(height: _largeSpacing),
|
||||
final leftColumn = Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
const PaymentAmountWidget(),
|
||||
const SizedBox(height: _smallSpacing),
|
||||
FeePayerSwitch(
|
||||
spacing: _smallSpacing,
|
||||
style: theme.textTheme.bodySmall,
|
||||
),
|
||||
const SizedBox(height: _mediumSpacing),
|
||||
const PaymentSummary(spacing: _extraSpacing),
|
||||
],
|
||||
);
|
||||
|
||||
const PaymentSummary(spacing: _extraSpacing),
|
||||
const SizedBox(height: _mediumSpacing),
|
||||
const QuoteStatus(spacing: _smallSpacing),
|
||||
],
|
||||
final rightColumn = Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
quoteCard,
|
||||
const SizedBox(height: _smallSpacing),
|
||||
autoRefreshSection,
|
||||
],
|
||||
);
|
||||
|
||||
if (isNarrow) {
|
||||
return Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
detailsHeader,
|
||||
leftColumn,
|
||||
const SizedBox(height: _largeSpacing),
|
||||
rightColumn,
|
||||
],
|
||||
);
|
||||
}
|
||||
|
||||
return Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
detailsHeader,
|
||||
Row(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
Expanded(
|
||||
flex: 3,
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
const PaymentAmountWidget(),
|
||||
const SizedBox(height: _smallSpacing),
|
||||
FeePayerSwitch(
|
||||
spacing: _smallSpacing,
|
||||
style: theme.textTheme.bodySmall,
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
const SizedBox(width: _columnSpacing),
|
||||
Expanded(flex: 2, child: quoteCard),
|
||||
],
|
||||
),
|
||||
const SizedBox(height: _mediumSpacing),
|
||||
Row(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
const Expanded(
|
||||
flex: 3,
|
||||
child: PaymentSummary(spacing: _extraSpacing),
|
||||
),
|
||||
const SizedBox(width: _columnSpacing),
|
||||
Expanded(
|
||||
flex: 2,
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
autoRefreshSection,
|
||||
],
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
],
|
||||
);
|
||||
},
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2,8 +2,10 @@ import 'package:flutter/material.dart';
|
||||
|
||||
import 'package:provider/provider.dart';
|
||||
|
||||
import 'package:pweb/controllers/multiple_payouts.dart';
|
||||
import 'package:pweb/controllers/payout_verification.dart';
|
||||
import 'package:pshared/provider/payment/multiple/quotation.dart';
|
||||
|
||||
import 'package:pweb/controllers/payouts/multiple_payouts.dart';
|
||||
import 'package:pweb/controllers/payouts/payout_verification.dart';
|
||||
import 'package:pweb/utils/payment/payout_verification_flow.dart';
|
||||
import 'package:pweb/widgets/dialogs/payment_status_dialog.dart';
|
||||
|
||||
@@ -13,9 +15,13 @@ Future<void> handleMultiplePayoutSend(
|
||||
MultiplePayoutsController controller,
|
||||
) async {
|
||||
final verificationController = context.read<PayoutVerificationController>();
|
||||
final quotationProvider = context.read<MultiQuotationProvider>();
|
||||
final verificationContextKey = quotationProvider.quotation?.quoteRef ??
|
||||
quotationProvider.quotation?.idempotencyKey;
|
||||
final verified = await runPayoutVerification(
|
||||
context: context,
|
||||
controller: verificationController,
|
||||
contextKey: verificationContextKey,
|
||||
);
|
||||
if (!verified) return;
|
||||
|
||||
|
||||
@@ -3,7 +3,7 @@ import 'package:pshared/models/money.dart';
|
||||
import 'package:pshared/utils/currency.dart';
|
||||
import 'package:pshared/utils/money.dart';
|
||||
|
||||
import 'package:pweb/controllers/multiple_payouts.dart';
|
||||
import 'package:pweb/controllers/payouts/multiple_payouts.dart';
|
||||
|
||||
|
||||
String moneyLabel(Money? money) {
|
||||
@@ -32,8 +32,5 @@ String sentAmountLabel(MultiplePayoutsController controller) {
|
||||
}
|
||||
|
||||
String feeLabel(MultiplePayoutsController controller) {
|
||||
final feeLabelText = moneyLabel(controller.aggregateFeeAmount);
|
||||
final percent = controller.aggregateFeePercent;
|
||||
if (percent == null) return feeLabelText;
|
||||
return '$feeLabelText (${percent.toStringAsFixed(2)}%)';
|
||||
return moneyLabel(controller.aggregateFeeAmount);
|
||||
}
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import 'package:flutter/material.dart';
|
||||
|
||||
import 'package:pweb/controllers/multiple_payouts.dart';
|
||||
import 'package:pweb/models/summary_values.dart';
|
||||
import 'package:pweb/controllers/payouts/multiple_payouts.dart';
|
||||
import 'package:pweb/models/dashboard/summary_values.dart';
|
||||
import 'package:pweb/pages/dashboard/payouts/multiple/panels/source_quote/helpers.dart';
|
||||
import 'package:pweb/pages/dashboard/payouts/summary/widget.dart';
|
||||
|
||||
@@ -21,7 +21,6 @@ class SourceQuoteSummary extends StatelessWidget {
|
||||
return PaymentSummary(
|
||||
spacing: spacing,
|
||||
values: PaymentSummaryValues(
|
||||
sentAmount: sentAmountLabel(controller),
|
||||
fee: feeLabel(controller),
|
||||
recipientReceives: moneyLabel(controller.aggregateSettlementAmount),
|
||||
total: moneyLabel(controller.aggregateDebitAmount),
|
||||
|
||||
@@ -1,19 +1,20 @@
|
||||
import 'package:flutter/material.dart';
|
||||
|
||||
import 'package:pshared/controllers/balance_mask/wallets.dart';
|
||||
import 'package:provider/provider.dart';
|
||||
|
||||
import 'package:pweb/controllers/multiple_payouts.dart';
|
||||
import 'package:pweb/controllers/payout_verification.dart';
|
||||
import 'package:pshared/controllers/balance_mask/wallets.dart';
|
||||
import 'package:pshared/provider/payment/multiple/quotation.dart';
|
||||
|
||||
import 'package:pweb/controllers/payouts/multiple_payouts.dart';
|
||||
import 'package:pweb/controllers/payouts/payout_verification.dart';
|
||||
import 'package:pweb/pages/dashboard/payouts/multiple/actions.dart';
|
||||
import 'package:pweb/pages/dashboard/payouts/multiple/panels/source_quote/header.dart';
|
||||
import 'package:pweb/pages/dashboard/payouts/multiple/panels/source_quote/summary.dart';
|
||||
import 'package:pweb/pages/dashboard/payouts/multiple/widgets/quote_status.dart';
|
||||
import 'package:pweb/pages/payment_methods/payment_page/send_button.dart';
|
||||
import 'package:pweb/pages/payout_page/send/widgets/send_button.dart';
|
||||
import 'package:pweb/widgets/payment/source_wallet_selector.dart';
|
||||
import 'package:pweb/widgets/cooldown_hint.dart';
|
||||
import 'package:pweb/models/control_state.dart';
|
||||
|
||||
import 'package:provider/provider.dart';
|
||||
import 'package:pweb/models/state/control_state.dart';
|
||||
|
||||
|
||||
class SourceQuotePanel extends StatelessWidget {
|
||||
@@ -31,7 +32,12 @@ class SourceQuotePanel extends StatelessWidget {
|
||||
final theme = Theme.of(context);
|
||||
final verificationController =
|
||||
context.watch<PayoutVerificationController>();
|
||||
final isCooldownActive = verificationController.isCooldownActive;
|
||||
final quotationProvider = context.watch<MultiQuotationProvider>();
|
||||
final verificationContextKey = quotationProvider.quotation?.quoteRef ??
|
||||
quotationProvider.quotation?.idempotencyKey;
|
||||
final isCooldownActive = verificationController.isCooldownActiveFor(
|
||||
verificationContextKey,
|
||||
);
|
||||
final canSend = controller.canSend && !isCooldownActive;
|
||||
return Container(
|
||||
width: double.infinity,
|
||||
@@ -72,7 +78,9 @@ class SourceQuotePanel extends StatelessWidget {
|
||||
if (isCooldownActive) ...[
|
||||
const SizedBox(height: 8),
|
||||
CooldownHint(
|
||||
seconds: verificationController.cooldownRemainingSeconds,
|
||||
seconds: verificationController.cooldownRemainingSecondsFor(
|
||||
verificationContextKey,
|
||||
),
|
||||
),
|
||||
],
|
||||
],
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import 'package:flutter/material.dart';
|
||||
|
||||
import 'package:pweb/controllers/multiple_payouts.dart';
|
||||
import 'package:pweb/controllers/payouts/multiple_payouts.dart';
|
||||
|
||||
import 'package:pweb/generated/i18n/app_localizations.dart';
|
||||
|
||||
|
||||
@@ -2,7 +2,7 @@ import 'package:flutter/material.dart';
|
||||
|
||||
import 'package:dotted_border/dotted_border.dart';
|
||||
|
||||
import 'package:pweb/controllers/multiple_payouts.dart';
|
||||
import 'package:pweb/controllers/payouts/multiple_payouts.dart';
|
||||
|
||||
import 'package:pweb/generated/i18n/app_localizations.dart';
|
||||
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import 'package:flutter/material.dart';
|
||||
|
||||
import 'package:pweb/controllers/multiple_payouts.dart';
|
||||
import 'package:pweb/controllers/payouts/multiple_payouts.dart';
|
||||
|
||||
import 'package:pweb/generated/i18n/app_localizations.dart';
|
||||
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import 'package:flutter/material.dart';
|
||||
|
||||
import 'package:pweb/controllers/multiple_payouts.dart';
|
||||
import 'package:pweb/controllers/payouts/multiple_payouts.dart';
|
||||
|
||||
import 'package:pweb/pages/dashboard/payouts/multiple/panels/upload_panel/drop_zone.dart';
|
||||
import 'package:pweb/pages/dashboard/payouts/multiple/panels/upload_panel/actions.dart';
|
||||
|
||||
@@ -6,7 +6,7 @@ import 'package:pshared/models/payment/operation.dart';
|
||||
import 'package:pshared/provider/payment/payments.dart';
|
||||
|
||||
import 'package:pweb/pages/dashboard/payouts/multiple/sections/history/header.dart';
|
||||
import 'package:pweb/controllers/recent_payments.dart';
|
||||
import 'package:pweb/controllers/payments/recent_payments.dart';
|
||||
import 'package:pweb/pages/report/cards/column.dart';
|
||||
import 'package:pweb/utils/report/payment_mapper.dart';
|
||||
import 'package:pweb/app/router/payout_routes.dart';
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import 'package:pweb/models/multiple_payouts/csv_row.dart';
|
||||
import 'package:pweb/models/payment/multiple_payouts/csv_row.dart';
|
||||
|
||||
|
||||
const String sampleFileName = 'sample.csv';
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import 'package:flutter/material.dart';
|
||||
|
||||
import 'package:pweb/models/multiple_payouts/csv_row.dart';
|
||||
import 'package:pweb/models/payment/multiple_payouts/csv_row.dart';
|
||||
|
||||
import 'package:pweb/generated/i18n/app_localizations.dart';
|
||||
|
||||
|
||||
@@ -2,7 +2,7 @@ import 'package:flutter/material.dart';
|
||||
|
||||
import 'package:pshared/controllers/balance_mask/wallets.dart';
|
||||
|
||||
import 'package:pweb/controllers/multiple_payouts.dart';
|
||||
import 'package:pweb/controllers/payouts/multiple_payouts.dart';
|
||||
import 'package:pweb/pages/dashboard/payouts/multiple/panels/source_quote/widget.dart';
|
||||
import 'package:pweb/pages/dashboard/payouts/multiple/panels/upload_panel/widget.dart';
|
||||
import 'package:pweb/pages/dashboard/payouts/multiple/sections/upload_csv/panel_card.dart';
|
||||
|
||||
@@ -2,7 +2,7 @@ import 'package:flutter/material.dart';
|
||||
|
||||
import 'package:provider/provider.dart';
|
||||
|
||||
import 'package:pweb/controllers/multiple_payouts.dart';
|
||||
import 'package:pweb/controllers/payouts/multiple_payouts.dart';
|
||||
import 'package:pweb/pages/dashboard/payouts/multiple/sections/upload_csv/header.dart';
|
||||
import 'package:pweb/pages/dashboard/payouts/multiple/sections/upload_csv/layout.dart';
|
||||
|
||||
|
||||
@@ -2,7 +2,7 @@ import 'package:flutter/material.dart';
|
||||
|
||||
import 'package:pshared/models/payment/quote/status_type.dart';
|
||||
|
||||
import 'package:pweb/controllers/multiple_payouts.dart';
|
||||
import 'package:pweb/controllers/payouts/multiple_payouts.dart';
|
||||
import 'package:pweb/pages/dashboard/payouts/quote_status/widgets/card.dart';
|
||||
import 'package:pweb/utils/quote_duration_format.dart';
|
||||
|
||||
|
||||
@@ -1,70 +0,0 @@
|
||||
import 'package:flutter/material.dart';
|
||||
|
||||
import 'package:provider/provider.dart';
|
||||
|
||||
import 'package:pshared/models/payment/quote/status_type.dart';
|
||||
|
||||
import 'package:pweb/pages/dashboard/payouts/quote_status/widgets/body.dart';
|
||||
import 'package:pweb/providers/quotation/quotation.dart';
|
||||
import 'package:pweb/utils/quote_duration_format.dart';
|
||||
|
||||
import 'package:pweb/generated/i18n/app_localizations.dart';
|
||||
|
||||
|
||||
class QuoteStatus extends StatelessWidget {
|
||||
final double spacing;
|
||||
|
||||
const QuoteStatus({super.key, required this.spacing});
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
final loc = AppLocalizations.of(context)!;
|
||||
final controller = context.watch<QuotationController>();
|
||||
final timeLeft = controller.timeLeft;
|
||||
final isLoading = controller.isLoading;
|
||||
final statusType = controller.quoteStatus;
|
||||
final autoRefreshMode = controller.autoRefreshMode;
|
||||
|
||||
String statusText;
|
||||
String? helperText;
|
||||
switch (statusType) {
|
||||
case QuoteStatusType.loading:
|
||||
statusText = loc.quoteUpdating;
|
||||
break;
|
||||
case QuoteStatusType.error:
|
||||
statusText = loc.quoteErrorGeneric;
|
||||
break;
|
||||
case QuoteStatusType.missing:
|
||||
statusText = loc.quoteUnavailable;
|
||||
break;
|
||||
case QuoteStatusType.expired:
|
||||
statusText = loc.quoteExpired;
|
||||
helperText = loc.quoteRefreshRequired;
|
||||
break;
|
||||
case QuoteStatusType.active:
|
||||
statusText = timeLeft == null
|
||||
? loc.quoteActive
|
||||
: loc.quoteExpiresIn(formatQuoteDuration(timeLeft));
|
||||
break;
|
||||
}
|
||||
|
||||
final canRefresh = controller.canRefresh && !isLoading;
|
||||
final showPrimaryRefresh = canRefresh &&
|
||||
(statusType == QuoteStatusType.expired ||
|
||||
statusType == QuoteStatusType.error ||
|
||||
statusType == QuoteStatusType.missing);
|
||||
|
||||
return QuoteStatusBody(
|
||||
spacing: spacing,
|
||||
statusType: statusType,
|
||||
statusText: statusText,
|
||||
helperText: helperText,
|
||||
isLoading: isLoading,
|
||||
canRefresh: canRefresh,
|
||||
showPrimaryRefresh: showPrimaryRefresh,
|
||||
autoRefreshMode: autoRefreshMode,
|
||||
onAutoRefreshModeChanged: controller.setAutoRefreshMode,
|
||||
onRefresh: controller.refreshQuotation,
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -48,34 +48,14 @@ class QuoteAutoRefreshSection extends StatelessWidget {
|
||||
),
|
||||
),
|
||||
const SizedBox(width: _autoRefreshSpacing),
|
||||
ToggleButtons(
|
||||
isSelected: [
|
||||
autoRefreshMode == AutoRefreshMode.off,
|
||||
autoRefreshMode == AutoRefreshMode.on,
|
||||
],
|
||||
onPressed: canRefresh
|
||||
? (index) {
|
||||
final nextMode =
|
||||
index == 1 ? AutoRefreshMode.on : AutoRefreshMode.off;
|
||||
if (nextMode == autoRefreshMode) return;
|
||||
onModeChanged(nextMode);
|
||||
}
|
||||
Switch.adaptive(
|
||||
activeTrackColor: theme.colorScheme.primary,
|
||||
value: autoRefreshMode == AutoRefreshMode.on,
|
||||
onChanged: canRefresh
|
||||
? (value) => onModeChanged(
|
||||
value ? AutoRefreshMode.on : AutoRefreshMode.off,
|
||||
)
|
||||
: null,
|
||||
borderRadius: BorderRadius.circular(999),
|
||||
constraints: const BoxConstraints(minHeight: 32, minWidth: 56),
|
||||
selectedColor: theme.colorScheme.onPrimary,
|
||||
fillColor: theme.colorScheme.primary,
|
||||
color: theme.colorScheme.onSurface,
|
||||
children: [
|
||||
Padding(
|
||||
padding: const EdgeInsets.symmetric(horizontal: 12),
|
||||
child: Text(loc.toggleOff),
|
||||
),
|
||||
Padding(
|
||||
padding: const EdgeInsets.symmetric(horizontal: 12),
|
||||
child: Text(loc.toggleOn),
|
||||
),
|
||||
],
|
||||
),
|
||||
],
|
||||
);
|
||||
|
||||
@@ -26,6 +26,7 @@ class RecipientAvatar extends StatelessWidget {
|
||||
final textColor = Theme.of(context).colorScheme.onPrimary;
|
||||
|
||||
return Column(
|
||||
mainAxisAlignment: MainAxisAlignment.center,
|
||||
children: [
|
||||
CircleAvatar(
|
||||
radius: avatarRadius,
|
||||
|
||||
@@ -7,11 +7,13 @@ import 'package:pweb/pages/dashboard/payouts/single/address_book/avatar.dart';
|
||||
class ShortListAddressBookPayout extends StatelessWidget {
|
||||
final List<Recipient> recipients;
|
||||
final ValueChanged<Recipient> onSelected;
|
||||
final Widget? trailing;
|
||||
|
||||
const ShortListAddressBookPayout({
|
||||
super.key,
|
||||
required this.recipients,
|
||||
required this.onSelected,
|
||||
this.trailing,
|
||||
});
|
||||
|
||||
static const double _avatarRadius = 20;
|
||||
@@ -21,10 +23,13 @@ class ShortListAddressBookPayout extends StatelessWidget {
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
final trailingWidget = trailing;
|
||||
|
||||
return SingleChildScrollView(
|
||||
scrollDirection: Axis.horizontal,
|
||||
child: Row(
|
||||
children: recipients.map((recipient) {
|
||||
children:
|
||||
recipients.map((recipient) {
|
||||
return Padding(
|
||||
padding: _padding,
|
||||
child: InkWell(
|
||||
@@ -44,8 +49,13 @@ class ShortListAddressBookPayout extends StatelessWidget {
|
||||
),
|
||||
),
|
||||
);
|
||||
}).toList(),
|
||||
}).toList()
|
||||
..addAll(
|
||||
trailingWidget == null
|
||||
? const []
|
||||
: [Padding(padding: _padding, child: trailingWidget)],
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,26 +0,0 @@
|
||||
import 'package:flutter/material.dart';
|
||||
|
||||
import 'package:provider/provider.dart';
|
||||
|
||||
import 'package:pshared/models/asset.dart';
|
||||
import 'package:pshared/models/currency.dart';
|
||||
import 'package:pshared/provider/payment/amount.dart';
|
||||
|
||||
import 'package:pweb/pages/dashboard/payouts/summary/row.dart';
|
||||
|
||||
import 'package:pweb/generated/i18n/app_localizations.dart';
|
||||
|
||||
|
||||
class PaymentSentAmountRow extends StatelessWidget {
|
||||
final Currency currency;
|
||||
const PaymentSentAmountRow({super.key, required this.currency});
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) => Consumer<PaymentAmountProvider>(
|
||||
builder: (context, provider, _) => PaymentSummaryRow(
|
||||
labelFactory: AppLocalizations.of(context)!.sentAmount,
|
||||
asset: Asset(currency: currency, amount: provider.amount),
|
||||
style: Theme.of(context).textTheme.titleMedium,
|
||||
),
|
||||
);
|
||||
}
|
||||
@@ -1,15 +1,9 @@
|
||||
import 'package:flutter/material.dart';
|
||||
|
||||
import 'package:provider/provider.dart';
|
||||
|
||||
import 'package:pshared/controllers/balance_mask/wallets.dart';
|
||||
import 'package:pshared/utils/currency.dart';
|
||||
|
||||
import 'package:pweb/models/summary_values.dart';
|
||||
import 'package:pweb/models/dashboard/summary_values.dart';
|
||||
import 'package:pweb/pages/dashboard/payouts/summary/fee.dart';
|
||||
import 'package:pweb/pages/dashboard/payouts/summary/recipient_receives.dart';
|
||||
import 'package:pweb/pages/dashboard/payouts/summary/row.dart';
|
||||
import 'package:pweb/pages/dashboard/payouts/summary/sent_amount.dart';
|
||||
import 'package:pweb/pages/dashboard/payouts/summary/total.dart';
|
||||
|
||||
import 'package:pweb/generated/i18n/app_localizations.dart';
|
||||
@@ -36,12 +30,6 @@ class PaymentSummary extends StatelessWidget {
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.stretch,
|
||||
children: [
|
||||
PaymentSummaryRow(
|
||||
labelFactory: loc.sentAmount,
|
||||
asset: null,
|
||||
value: resolvedValues.sentAmount,
|
||||
style: theme.textTheme.titleMedium,
|
||||
),
|
||||
PaymentSummaryRow(
|
||||
labelFactory: loc.fee,
|
||||
asset: null,
|
||||
@@ -73,12 +61,6 @@ class PaymentSummary extends StatelessWidget {
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.stretch,
|
||||
children: [
|
||||
PaymentSentAmountRow(
|
||||
currency: currencyStringToCode(
|
||||
context.read<WalletsController>().selectedWallet?.tokenSymbol ??
|
||||
'USDT',
|
||||
),
|
||||
),
|
||||
const PaymentFeeRow(),
|
||||
const PaymentRecipientReceivesRow(),
|
||||
SizedBox(height: spacing),
|
||||
|
||||
Reference in New Issue
Block a user