Connect customer quotations and payment execution to Sendico (#50)

This commit is contained in:
Stephan D committed 2026-10-16 09:57:28 +02:00
1 parent 5d67c25c8e
commit 7a6510d1a8
45 files changed
+2696 -45

No files matched your search

+19 -11
View File
@@ -28,17 +28,25 @@ String statusText(AppLocalizations l, OperationStatus s) => switch (s) {
OperationStatus.completed => l.wCompleted,
OperationStatus.failed => l.wFailed,
};
String fundsText(AppLocalizations l, WalletOperation o) =>
switch ((o.status, o.quote.request.kind)) {
(OperationStatus.pending, TransferKind.topUp) => l.wPendingTopUp,
(OperationStatus.pending, TransferKind.exchange) => l.wPendingExchange,
(OperationStatus.pending, TransferKind.payout) => l.wPendingPayout,
(OperationStatus.completed, TransferKind.topUp) => l.wCompleteTopUp,
(OperationStatus.completed, TransferKind.exchange) => l.wCompleteExchange,
(OperationStatus.completed, TransferKind.payout) => l.wCompletePayout,
(OperationStatus.failed, TransferKind.topUp) => l.wFailedTopUp,
_ => l.wFailedOutgoing,
};
String fundsText(
AppLocalizations l,
WalletOperation o, {
bool simulated = true,
}) => !simulated && o.status == OperationStatus.pending
? l.wLivePending
: !simulated && o.status == OperationStatus.failed
? l.wLiveFailed
: switch ((o.status, o.quote.request.kind)) {
(OperationStatus.pending, TransferKind.topUp) => l.wPendingTopUp,
(OperationStatus.pending, TransferKind.exchange) => l.wPendingExchange,
(OperationStatus.pending, TransferKind.payout) => l.wPendingPayout,
(OperationStatus.completed, TransferKind.topUp) => l.wCompleteTopUp,
(OperationStatus.completed, TransferKind.exchange) =>
l.wCompleteExchange,
(OperationStatus.completed, TransferKind.payout) => l.wCompletePayout,
(OperationStatus.failed, TransferKind.topUp) => l.wFailedTopUp,
_ => l.wFailedOutgoing,
};
String walletError(AppLocalizations l, WalletError e) => switch (e) {
WalletError.invalidAmount => l.wInvalidAmount,
WalletError.insufficientFunds => l.wInsufficient,
+1 -1
View File
@@ -97,7 +97,7 @@ class _OperationPageState extends State<OperationPage> {
),
const SizedBox(height: 16),
Text(
fundsText(l, o),
fundsText(l, o, simulated: p.service.isSimulated),
style: TextStyle(
color: o.status == OperationStatus.failed
? c.onErrorContainer
+45 -10
View File
@@ -133,6 +133,15 @@ class TransferPageState extends State<TransferPage> {
final t = Theme.of(context);
final accounts = wallet.data?.accounts ?? [];
final source = wallet.account(p.source);
final live = !wallet.service.isSimulated;
final expiresIn =
p.quote?.expiresAt.difference(DateTime.now()).inSeconds ?? 0;
final unavailableMethod =
live &&
((widget.kind == TransferKind.payout &&
(source?.payoutMethod.isEmpty ?? true)) ||
(widget.kind == TransferKind.topUp &&
!(source?.canFund ?? false)));
return SingleChildScrollView(
padding: const EdgeInsets.all(24),
child: Center(
@@ -207,7 +216,15 @@ class TransferPageState extends State<TransferPage> {
] else if (p.quote != null) ...[
TransferSummary(quote: p.quote!),
const SizedBox(height: 16),
Text(p.expired ? l.wExpired : l.wQuoteNotice),
Text(
p.expired
? l.wExpired
: live
? l.wLiveQuoteNotice(
expiresIn < 0 ? 0 : expiresIn,
)
: l.wQuoteNotice,
),
const SizedBox(height: 20),
if (p.expired)
FilledButton(
@@ -299,21 +316,39 @@ class TransferPageState extends State<TransferPage> {
),
if (widget.kind == TransferKind.payout) ...[
const SizedBox(height: 20),
TextField(
key: const ValueKey('transfer-recipient'),
controller: _recipient,
enabled: !p.busy,
decoration: InputDecoration(
labelText: l.wRecipient,
hintText: l.wRecipientHint,
if (live && source?.payoutMethod.isNotEmpty == true)
InputDecorator(
decoration: InputDecoration(
labelText: l.wRecipient,
),
child: Text(source!.payoutLabel),
),
onChanged: (v) => p.change(recipient: v),
if (!live)
TextField(
key: const ValueKey('transfer-recipient'),
controller: _recipient,
enabled: !p.busy,
decoration: InputDecoration(
labelText: l.wRecipient,
hintText: l.wRecipientHint,
),
onChanged: (v) => p.change(recipient: v),
),
],
if (unavailableMethod) ...[
const SizedBox(height: 12),
Text(
widget.kind == TransferKind.payout
? l.wNoPayoutMethod
: l.wNoFundingMethod,
),
],
const SizedBox(height: 28),
FilledButton(
key: const ValueKey('transfer-review'),
onPressed: p.busy ? null : p.review,
onPressed: p.busy || unavailableMethod
? null
: p.review,
child: Text(l.wReview),
),
if (p.error == WalletError.limitExceeded)