[accelerator] improve SCA UX

This commit is contained in:
Mononaut 2024-12-22 12:27:29 +00:00
parent ddcf745722
commit ba1ee15286
No known key found for this signature in database
GPG Key ID: A3F058E41374C04E
3 changed files with 135 additions and 102 deletions

View File

@ -1,4 +1,4 @@
<div class="box card w-100" style="background: var(--box-bg)" id=acceleratePreviewAnchor> <div class="box card w-100 accelerate-checkout-inner" [class.input-disabled]="checkoutLocked" style="background: var(--box-bg)" id=acceleratePreviewAnchor>
@if (accelerateError) { @if (accelerateError) {
<div class="row mb-1 text-center"> <div class="row mb-1 text-center">
<div class="col-sm"> <div class="col-sm">
@ -361,7 +361,7 @@
<div class="row text-center justify-content-center mx-2"> <div class="row text-center justify-content-center mx-2">
<p i18n="accelerator.payment-to-mempool-space">Payment to mempool.space for acceleration of txid <a [routerLink]="'/tx/' + tx.txid" target="_blank">{{ tx.txid.substr(0, 10) }}..{{ tx.txid.substr(-10) }}</a></p> <p i18n="accelerator.payment-to-mempool-space">Payment to mempool.space for acceleration of txid <a [routerLink]="'/tx/' + tx.txid" target="_blank">{{ tx.txid.substr(0, 10) }}..{{ tx.txid.substr(-10) }}</a></p>
</div> </div>
@if (canPayWithBalance || !(canPayWithBitcoin || canPayWithCashapp)) { @if (canPayWithBalance || !(canPayWithBitcoin || canPayWithCashapp || canPayWithApplePay || canPayWithGooglePay)) {
<div class="row"> <div class="row">
<div class="col-sm text-center d-flex flex-column justify-content-center align-items-center"> <div class="col-sm text-center d-flex flex-column justify-content-center align-items-center">
<p><ng-container i18n="accelerator.your-account-will-be-debited">Your account will be debited no more than</ng-container>&nbsp;<small style="font-family: monospace;">{{ cost | number }}</small>&nbsp;<span class="symbol" i18n="shared.sats">sats</span></p> <p><ng-container i18n="accelerator.your-account-will-be-debited">Your account will be debited no more than</ng-container>&nbsp;<small style="font-family: monospace;">{{ cost | number }}</small>&nbsp;<span class="symbol" i18n="shared.sats">sats</span></p>
@ -484,6 +484,11 @@
</div> </div>
} }
</div> </div>
@if (tokenizing) {
<div class="d-flex flex-row justify-content-center">
<div class="ml-2 spinner-border text-light" style="width: 25px; height: 25px"></div>
</div>
}
</div> </div>
</div> </div>

View File

@ -8,6 +8,13 @@
color: var(--green) color: var(--green)
} }
.accelerate-checkout-inner {
&.input-disabled {
pointer-events: none;
opacity: 0.75;
}
}
.paymentMethod { .paymentMethod {
padding: 10px; padding: 10px;
background-color: var(--secondary); background-color: var(--secondary);

View File

@ -76,6 +76,8 @@ export class AccelerateCheckout implements OnInit, OnDestroy {
calculating = true; calculating = true;
processing = false; processing = false;
checkoutLocked = false;
tokenizing = false;
selectedOption: 'wait' | 'accel'; selectedOption: 'wait' | 'accel';
cantPayReason = ''; cantPayReason = '';
quoteError = ''; // error fetching estimate or initial data quoteError = ''; // error fetching estimate or initial data
@ -504,6 +506,10 @@ export class AccelerateCheckout implements OnInit, OnDestroy {
this.loadingApplePay = false; this.loadingApplePay = false;
applePayButton.addEventListener('click', async event => { applePayButton.addEventListener('click', async event => {
event.preventDefault(); event.preventDefault();
try {
// lock the checkout UI and show a loading spinner until the square modals are finished
this.checkoutLocked = true;
this.tokenizing = true;
const tokenResult = await this.applePay.tokenize(); const tokenResult = await this.applePay.tokenize();
if (tokenResult?.status === 'OK') { if (tokenResult?.status === 'OK') {
const card = tokenResult.details?.card; const card = tokenResult.details?.card;
@ -554,6 +560,11 @@ export class AccelerateCheckout implements OnInit, OnDestroy {
} }
throw new Error(errorMessage); throw new Error(errorMessage);
} }
} finally {
// always unlock the checkout once we're finished
this.tokenizing = false;
this.checkoutLocked = false;
}
}); });
} catch (e) { } catch (e) {
this.processing = false; this.processing = false;
@ -603,7 +614,12 @@ export class AccelerateCheckout implements OnInit, OnDestroy {
document.getElementById('google-pay-button').addEventListener('click', async event => { document.getElementById('google-pay-button').addEventListener('click', async event => {
event.preventDefault(); event.preventDefault();
try {
// lock the checkout UI and show a loading spinner until the square modals are finished
this.checkoutLocked = true;
this.tokenizing = true;
const tokenResult = await this.googlePay.tokenize(); const tokenResult = await this.googlePay.tokenize();
tokenResult.token = 'ccof:customer-card-id-requires-verification';
if (tokenResult?.status === 'OK') { if (tokenResult?.status === 'OK') {
const card = tokenResult.details?.card; const card = tokenResult.details?.card;
if (!card || !card.brand || !card.expMonth || !card.expYear || !card.last4) { if (!card || !card.brand || !card.expMonth || !card.expYear || !card.last4) {
@ -661,6 +677,11 @@ export class AccelerateCheckout implements OnInit, OnDestroy {
} }
throw new Error(errorMessage); throw new Error(errorMessage);
} }
} finally {
// always unlock the checkout once we're finished
this.tokenizing = false;
this.checkoutLocked = false;
}
}); });
} }
); );