Show spinner while creating BTC invoice

This commit is contained in:
Dorian
2026-05-15 16:23:08 -05:00
parent 030c84cc52
commit d6f621236f
2 changed files with 40 additions and 0 deletions

View File

@@ -175,6 +175,7 @@ const isPaymentOpen = ref(false)
const paymentModalInvoice = ref(null) const paymentModalInvoice = ref(null)
const paymentModalError = ref('') const paymentModalError = ref('')
const isPaymentModalLoading = ref(false) const isPaymentModalLoading = ref(false)
const paymentModalLoadingMethod = ref('')
const paymentInvoiceMethod = ref('lightning') const paymentInvoiceMethod = ref('lightning')
const paymentInvoiceQrUrl = ref('') const paymentInvoiceQrUrl = ref('')
const currentPath = ref(window.location.pathname) const currentPath = ref(window.location.pathname)
@@ -1547,20 +1548,24 @@ const closePayment = () => {
paymentModalError.value = '' paymentModalError.value = ''
paymentInvoiceMethod.value = 'lightning' paymentInvoiceMethod.value = 'lightning'
isPaymentModalLoading.value = false isPaymentModalLoading.value = false
paymentModalLoadingMethod.value = ''
} }
const takeCashPayment = async () => { const takeCashPayment = async () => {
if (!selectedPaymentMember.value) return if (!selectedPaymentMember.value) return
isPaymentModalLoading.value = true isPaymentModalLoading.value = true
paymentModalLoadingMethod.value = 'cash'
paymentModalError.value = '' paymentModalError.value = ''
await markManualPayment(selectedPaymentMember.value.membershipId) await markManualPayment(selectedPaymentMember.value.membershipId)
isPaymentModalLoading.value = false isPaymentModalLoading.value = false
paymentModalLoadingMethod.value = ''
if (!adminActionError.value) closePayment() if (!adminActionError.value) closePayment()
} }
const createBitcoinPayment = async () => { const createBitcoinPayment = async () => {
if (!selectedPaymentMember.value) return if (!selectedPaymentMember.value) return
isPaymentModalLoading.value = true isPaymentModalLoading.value = true
paymentModalLoadingMethod.value = 'bitcoin'
paymentModalError.value = '' paymentModalError.value = ''
adminActionError.value = '' adminActionError.value = ''
adminActionMessage.value = '' adminActionMessage.value = ''
@@ -1578,6 +1583,7 @@ const createBitcoinPayment = async () => {
paymentModalError.value = error instanceof Error ? error.message : 'Could not create Bitcoin invoice.' paymentModalError.value = error instanceof Error ? error.message : 'Could not create Bitcoin invoice.'
} finally { } finally {
isPaymentModalLoading.value = false isPaymentModalLoading.value = false
paymentModalLoadingMethod.value = ''
} }
} }
@@ -3401,6 +3407,9 @@ watch(mobileMenuOpen, (open) => {
<span> Bitcoin</span> <span> Bitcoin</span>
<strong>BTCPay invoice</strong> <strong>BTCPay invoice</strong>
<small>{{ appConfig.btcpayEnabled ? 'Create a Bitcoin checkout invoice.' : 'BTCPay is not configured.' }}</small> <small>{{ appConfig.btcpayEnabled ? 'Create a Bitcoin checkout invoice.' : 'BTCPay is not configured.' }}</small>
<span v-if="paymentModalLoadingMethod === 'bitcoin'" class="payment-choice-spinner" aria-label="Creating BTCPay invoice">
<img src="/images/small-logo.svg" alt="" />
</span>
</button> </button>
</template> </template>
<p v-if="paymentModalError" class="validation-message text-sm text-red-200">{{ paymentModalError }}</p> <p v-if="paymentModalError" class="validation-message text-sm text-red-200">{{ paymentModalError }}</p>

View File

@@ -1879,6 +1879,7 @@ body.menu-open {
.payment-choice-card { .payment-choice-card {
display: grid; display: grid;
grid-template-columns: minmax(0, 1fr) auto;
width: 100%; width: 100%;
gap: 0.35rem; gap: 0.35rem;
border: 1px solid rgba(250, 250, 250, 0.18); border: 1px solid rgba(250, 250, 250, 0.18);
@@ -1890,6 +1891,12 @@ body.menu-open {
transition: border-color 180ms ease, background 180ms ease, transform 180ms ease; transition: border-color 180ms ease, background 180ms ease, transform 180ms ease;
} }
.payment-choice-card > span:not(.payment-choice-spinner),
.payment-choice-card > strong,
.payment-choice-card > small {
grid-column: 1;
}
.payment-choice-card:hover:not(:disabled) { .payment-choice-card:hover:not(:disabled) {
border-color: rgba(250, 250, 250, 0.42); border-color: rgba(250, 250, 250, 0.42);
background: rgba(250, 250, 250, 0.09); background: rgba(250, 250, 250, 0.09);
@@ -1931,6 +1938,30 @@ body.menu-open {
line-height: 1.55; line-height: 1.55;
} }
.payment-choice-spinner {
grid-column: 2;
grid-row: 1 / span 3;
display: grid;
width: 2.75rem;
height: 2.75rem;
place-items: center;
align-self: center;
justify-self: end;
border: 1px solid rgba(242, 169, 0, 0.34);
border-radius: 999px;
background: rgba(0, 0, 0, 0.36);
box-shadow: 0 0 1.4rem rgba(242, 169, 0, 0.16);
}
.payment-choice-spinner img {
width: 1.45rem;
height: auto;
filter:
drop-shadow(0 0 0.4rem rgba(242, 169, 0, 0.62))
drop-shadow(0 0 1rem rgba(0, 0, 0, 0.8));
animation: card-logo-spin 900ms cubic-bezier(0.45, 0, 0.2, 1) infinite;
}
.bitcoin-invoice-panel { .bitcoin-invoice-panel {
display: grid; display: grid;
justify-items: center; justify-items: center;