initial
This commit is contained in:
210
apps/pay/pages/index.vue
Normal file
210
apps/pay/pages/index.vue
Normal file
@@ -0,0 +1,210 @@
|
||||
<template>
|
||||
<div class="invoice-form">
|
||||
<div class="invoice-form__header">
|
||||
<div>
|
||||
<h2>Payment details</h2>
|
||||
|
||||
<p class="invoice-form__order-id">
|
||||
# {{ invoice.orderId }}
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<InvoiceFormTimer
|
||||
:expiration-time="expirationTime"
|
||||
/>
|
||||
</div>
|
||||
|
||||
<div class="invoice-form__body">
|
||||
<Transition
|
||||
name="shift"
|
||||
mode="out-in"
|
||||
>
|
||||
<Component :is="stepComponent" />
|
||||
</Transition>
|
||||
</div>
|
||||
|
||||
<p class="invoice-form__network-alert">
|
||||
Адрес работает только для получения Tether (USDT) в сети TRC20
|
||||
</p>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { useSessionStorage } from '@vueuse/core'
|
||||
import {
|
||||
InvoiceFormStepExpired,
|
||||
InvoiceFormStepPending,
|
||||
InvoiceFormStepRequisites,
|
||||
InvoiceFormStepSuccess,
|
||||
InvoiceFormStepUnderpaid,
|
||||
InvoiceFormStepWaitingRequisites,
|
||||
} from '#components'
|
||||
|
||||
definePageMeta({
|
||||
validate: async (route) => {
|
||||
try {
|
||||
await $api(`/payments/${route.params.invoiceId}`, {
|
||||
method: 'get',
|
||||
})
|
||||
|
||||
return true
|
||||
}
|
||||
catch {
|
||||
return false
|
||||
}
|
||||
},
|
||||
})
|
||||
|
||||
const route = useRoute()
|
||||
const payedFlag = useSessionStorage(`invoice-${route.params.invoiceId}`, false, { initOnMounted: true })
|
||||
|
||||
interface InvoiceTransfer {
|
||||
txID: string
|
||||
recipient: string
|
||||
sender: string
|
||||
blockchainCode: string
|
||||
}
|
||||
|
||||
interface PublicInvoice {
|
||||
id: string
|
||||
orderId: string
|
||||
amount: number | string
|
||||
collectedAmount: number | string
|
||||
currencyCode: string
|
||||
expiresAt: string
|
||||
blockchainCode?: string
|
||||
availableBlockchains: string[]
|
||||
walletAddress?: string
|
||||
transfers?: InvoiceTransfer[]
|
||||
}
|
||||
|
||||
const { data: invoice, refresh } = await useAsyncData<PublicInvoice>('public-invoice', async () => {
|
||||
const nuxtApp = useNuxtApp()
|
||||
|
||||
const invoice = await $api<PublicInvoice>(`/payments/${route.params.invoiceId}`, {
|
||||
method: 'get',
|
||||
})
|
||||
|
||||
if (new Date(invoice.expiresAt) < new Date() || invoice.walletAddress)
|
||||
return invoice
|
||||
|
||||
try {
|
||||
const selectedBlockchain = await nuxtApp.runWithContext(async () => {
|
||||
return $api<Pick<PublicInvoice, 'expiresAt' | 'walletAddress'>>(`/payments/${route.params.invoiceId}`, {
|
||||
method: 'put',
|
||||
body: {
|
||||
blockchainCode: invoice!.availableBlockchains[0],
|
||||
},
|
||||
})
|
||||
})
|
||||
|
||||
return {
|
||||
...invoice,
|
||||
...selectedBlockchain,
|
||||
}
|
||||
}
|
||||
catch (e) {
|
||||
console.error(e)
|
||||
|
||||
return invoice
|
||||
}
|
||||
})
|
||||
|
||||
const expirationTime = computed(() => {
|
||||
return new Date(invoice.value?.expiresAt ?? 0).getTime()
|
||||
})
|
||||
|
||||
const { isPassed } = useTimer(expirationTime)
|
||||
|
||||
const stepComponent = computed(() => {
|
||||
const status = invoice.value?.status
|
||||
|
||||
switch (status) {
|
||||
case 'pending':
|
||||
return InvoiceFormStepWaitingRequisites
|
||||
|
||||
case 'awaiting_payment':
|
||||
if (!isPassed.value)
|
||||
return InvoiceFormStepRequisites
|
||||
else
|
||||
return InvoiceFormStepPending
|
||||
|
||||
case 'completed':
|
||||
return InvoiceFormStepSuccess
|
||||
|
||||
case 'underpaid':
|
||||
return InvoiceFormStepUnderpaid
|
||||
|
||||
case 'overpaid':
|
||||
return InvoiceFormStepSuccess
|
||||
// return InvoiceFormStepOverpaid
|
||||
|
||||
default:
|
||||
return InvoiceFormStepExpired
|
||||
}
|
||||
})
|
||||
|
||||
const intervalId = setInterval(refresh, 5000)
|
||||
|
||||
watch(payedFlag, () => {
|
||||
refresh()
|
||||
})
|
||||
|
||||
onUnmounted(() => {
|
||||
clearInterval(intervalId)
|
||||
})
|
||||
|
||||
provide('public-invoice', { invoice, expirationTime, payedFlag })
|
||||
</script>
|
||||
|
||||
<style lang="scss">
|
||||
.invoice-form {
|
||||
width: 532px;
|
||||
margin: 0 auto;
|
||||
|
||||
&__header {
|
||||
display: flex;
|
||||
align-items: flex-end;
|
||||
justify-content: space-between;
|
||||
padding: 0 16px;
|
||||
margin-bottom: 16px;
|
||||
}
|
||||
|
||||
&__order-id {
|
||||
@include txt-r-sb;
|
||||
|
||||
color: $clr-grey-500;
|
||||
margin-top: 4px;
|
||||
}
|
||||
|
||||
&__body {
|
||||
background: $clr-white;
|
||||
border-radius: 12px;
|
||||
padding: 16px;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
&__network-alert {
|
||||
@include txt-i-m;
|
||||
|
||||
text-align: center;
|
||||
color: $clr-grey-400;
|
||||
padding: 8px 24px;
|
||||
margin-top: 10px;
|
||||
}
|
||||
|
||||
[data-status-illustration] {
|
||||
animation: rotate .8s cubic-bezier(.25,.75,.5,1.25);
|
||||
}
|
||||
|
||||
@keyframes rotate {
|
||||
from {
|
||||
transform: rotateZ(0deg);
|
||||
}
|
||||
|
||||
to {
|
||||
transform: rotateZ(360deg);
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
||||
Reference in New Issue
Block a user