This commit is contained in:
Nadar
2026-03-17 13:24:22 +03:00
commit 82e5ac9d81
554 changed files with 29637 additions and 0 deletions

View File

@@ -0,0 +1,88 @@
<template>
<div :class="cn.b()">
<p :class="cn.e('label')">
To pay:
</p>
<div :class="cn.e('left')">
<span :class="cn.e('amount')">{{ amount }}</span>
<UiCopyButton
:class="cn.e('copy')"
:title="null"
:pressed-title="null"
:value="amount"
/>
</div>
<div :class="cn.e('right')">
<UiCoin
:class="cn.e('coin')"
:code="invoice.currencyCode"
/>
<span :class="cn.e('code')">{{ invoice.currencyCode }}</span>
<span :class="cn.e('network')">TRC20</span>
</div>
</div>
</template>
<script setup>
const { invoice } = inject('public-invoice')
const amount = computed(() => $money.format(invoice.value.amount, invoice.value.code))
const cn = useClassname('invoice-form-amount')
</script>
<style lang="scss">
.invoice-form-amount {
display: grid;
grid-template-areas: 'label label' 'left right';
text-align: left;
padding-inline: 16px;
&__label {
@include txt-r-m;
grid-area: label;
margin-bottom: 3px;
color: $clr-grey-500;
}
&__left {
display: flex;
align-items: center;
grid-area: left;
}
&__amount {
@include h2;
}
&__copy {
margin-left: 8px;
}
&__right {
display: flex;
align-items: center;
grid-area: right;
justify-self: flex-end;
}
&__code {
@include font(16px, 600, 20px);
margin-left: 8px;
}
&__network {
@include txt-i-m;
padding: 3px 5px;
border-radius: 6px;
background-color: $clr-cyan-500;
color: $clr-white;
margin-left: 8px;
}
}
</style>

View File

@@ -0,0 +1,122 @@
<template>
<UiAccordion
active-icon="disclosure-up"
inactive-icon="disclosure-down"
:model-value="accordion ? undefined : 'details'"
:disabled="!accordion"
>
<UiAccordionItem id="details" :class="cn.b()">
<template #title>
<p :class="cn.e('title')">
Payment details
</p>
</template>
<template #default>
<dl :class="cn.e('list')">
<!-- <dt>Date</dt> -->
<!-- <dd>22 сент. 2022г., 11:27</dd> -->
<dt>Status</dt>
<dd :class="[cn.e('status-text'), invoice.status]">
{{ statusText }}
</dd>
<dt>Blockchain</dt>
<dd>
TRON
</dd>
<dt>Sender</dt>
<dd>
<TextShortener :text="invoice.transfers?.[0]?.sender" />
</dd>
<dt>Recipient</dt>
<dd>
<TextShortener :text="invoice.transfers?.[0]?.recipient" />
</dd>
<dt>TXID</dt>
<dd>
<TextShortener :text="invoice.transfers?.[0]?.txID" />
</dd>
</dl>
</template>
</UiAccordionItem>
</UiAccordion>
</template>
<script setup>
defineProps({
accordion: Boolean,
})
const { invoice } = inject('public-invoice')
const cn = useClassname('invoice-form-details')
const statusText = computed(() => {
switch (invoice.value.status) {
case 'completed':
return 'Payment success'
case 'underpaid':
return 'Invoice has been partially paid'
case 'overpaid':
return 'Invoice has been over paid'
}
})
</script>
<style lang="scss">
.invoice-form-details {
$self: &;
--accordion-head-padding: 16px;
--accordion-head-active-padding: 16px;
--accordion-content-padding: 0 16px 16px;
text-align: left;
outline: none !important;
&:hover,
&.is-active {
background-color: $clr-grey-100;
}
&__title {
@include txt-l-m;
}
&__list {
@include txt-r-m;
@include txt-r-m('text-shortener', true);
display: grid;
grid-template-columns: repeat(2, 1fr);
row-gap: 16px;
margin: 0;
color: $clr-grey-500;
dt, dd {
margin: 0;
}
dt {
color: $clr-grey-600;
}
dd {
text-align: right;
}
}
&__status-text {
color: $clr-warn-500;
&.completed {
color: $clr-green-500;
}
}
}
</style>

View File

@@ -0,0 +1,61 @@
<template>
<div :class="cn.b()">
<div :class="cn.e('header')">
<p :class="cn.e('title')">
Инструкция для оплаты
</p>
<UiIconExclamationFilled :class="cn.e('icon')" />
</div>
<p :class="cn.e('text')">
Для оплаты скопируйте адрес в Ваш кошелек <br>
или отсканируйте QR-код в приложении.
<br><br>
Далее введите в кошельке необходимую сумму <br>
и подтвердите в этой форме зачисление.
</p>
</div>
</template>
<script setup>
const cn = useClassname('invoice-form-instructions')
</script>
<style lang="scss">
.invoice-form-instructions {
$self: &;
display: flex;
flex-direction: column;
justify-content: center;
background-color: $clr-grey-100;
border-radius: 12px;
width: 100%;
text-align: left;
padding: 8px 16px;
&__header {
display: flex;
align-items: center;
justify-content: space-between;
margin-bottom: 8px;
}
&__title {
@include txt-i-b;
color: $clr-black;
}
&__icon {
color: $clr-grey-500;
}
&__text {
@include txt-r-m;
color: $clr-grey-600;
}
}
</style>

View File

@@ -0,0 +1,35 @@
<template>
<div class="invoice-form-separator" />
</template>
<style lang="scss">
.invoice-form-separator {
position: relative;
margin: 40px 20px;
border: 0 dashed $clr-grey-300;
border-top-width: 2px;
&:last-child {
margin-bottom: -16px;
}
&::before,
&::after {
content: '';
position: absolute;
top: -24px;
width: 48px;
height: 48px;
border-radius: 50%;
background-color: $clr-grey-100;
}
&::before {
left: -60px;
}
&::after {
right: -60px;
}
}
</style>

View File

@@ -0,0 +1,51 @@
<template>
<div :class="cn.m('expired')">
<div class="p-16">
<img
src="/expired.svg"
alt="Expired"
class="mb-16"
data-status-illustration
>
<h2 class="text-clr-grey-600">
Payment has expired
</h2>
<h4 class="text-clr-grey-400 mt-16">
Your invoice has expired. If you want to make a payment, <br> please return to the site and create the invoice again.
</h4>
</div>
<InvoiceFormSeparator />
<InvoiceFormAmount />
<UiButton
:class="cn.e('back-to-store')"
size="large"
:href="invoice.redirectUrl"
>
Back to store
</UiButton>
</div>
</template>
<script setup>
const { invoice } = inject('public-invoice')
const cn = useClassname('invoice-form')
</script>
<style lang="scss">
.invoice-form {
$self: &;
&--expired {
#{$self}__back-to-store {
width: 100%;
margin-top: 32px;
}
}
}
</style>

View File

@@ -0,0 +1,95 @@
<template>
<div :class="cn.m('success')">
<img
src="/partially.svg"
alt="Success"
class="mb-16"
data-status-illustration
>
<h2 class="text-clr-green-500">
Invoice has been over paid
</h2>
<div class="mt-16">
<UiCoin :code="invoice.currencyCode" />
<MoneyAmount
:class="cn.e('amount')"
:value="invoice.amount"
:currency="invoice.currencyCode"
/>
</div>
<InvoiceFormDetails :class="cn.e('details')" accordion />
<UiButton
:class="cn.e('back-to-store')"
size="large"
:href="invoice.redirectUrl"
>
Back to store
</UiButton>
<UiButton
:class="cn.e('explorer')"
type="link"
color="secondary"
:href="explorerLink"
target="_blank"
>
Просмотреть в обозревателе блоков
</UiButton>
<InvoiceFormSeparator />
</div>
</template>
<script setup>
const { invoice } = inject('public-invoice')
const cn = useClassname('invoice-form')
const explorerLink = computed(() => {
return `https://nile.tronscan.org/#/address/${invoice.value.walletAddress}`
})
</script>
<style lang="scss">
.invoice-form {
$self: &;
&--success {
#{$self}__amount {
@include h2('money-amount-value', true);
margin-left: 8px;
}
#{$self}__transaction-id {
text-align: center;
color: $clr-grey-400;
margin-top: 16px;
strong {
font-weight: 600;
color: $clr-grey-500;
}
}
#{$self}__details {
margin-top: 32px;
}
#{$self}__back-to-store {
width: 100%;
margin-top: 32px;
}
#{$self}__explorer {
width: 100%;
margin-top: 24px;
}
}
}
</style>

View File

@@ -0,0 +1,49 @@
<template>
<div :class="cn.m('pending')">
<div class="p-16">
<img
src="/pending.svg"
alt="Pending"
class="mb-16"
data-status-illustration
>
<h2 class="text-clr-grey-600">
Waiting
</h2>
<h4 class="text-clr-grey-400 mt-16">
Searching for transaction in the Blockchain network
</h4>
</div>
<InvoiceFormSeparator />
<InvoiceFormAmount />
<UiButton
:class="cn.e('action')"
size="large"
disabled
>
I have paid
</UiButton>
</div>
</template>
<script setup>
const cn = useClassname('invoice-form')
</script>
<style lang="scss">
.invoice-form {
$self: &;
&--pending {
#{$self}__action {
width: 100%;
margin-top: 32px;
}
}
}
</style>

View File

@@ -0,0 +1,67 @@
<template>
<div :class="cn.m('requisites')">
<div
class="d-flex"
style="gap: 16px"
>
<InvoiceFormInstructions />
<UiQrCode
:class="cn.e('qr')"
:value="invoice.walletAddress"
:size="139"
/>
</div>
<UiInput
id="address"
:class="cn.e('address')"
label="Адрес кошелька для оплаты"
:model-value="invoice.walletAddress"
readonly
copyable
/>
<InvoiceFormSeparator />
<InvoiceFormAmount />
<UiButton
class="action"
size="large"
:class="cn.e('action')"
:disabled="payedFlag"
@click="payedFlag = true"
>
I have paid
</UiButton>
</div>
</template>
<script setup>
const { invoice, payedFlag } = inject('public-invoice')
const cn = useClassname('invoice-form')
</script>
<style lang="scss">
.invoice-form {
$self: &;
&--requisites {
#{$self}__qr {
width: 139px;
height: 139px;
}
#{$self}__address {
margin-top: 8px;
}
#{$self}__action {
width: 100%;
margin-top: 32px;
}
}
}
</style>

View File

@@ -0,0 +1,84 @@
<template>
<div :class="cn.m('success')">
<img
src="/success.svg"
alt="Success"
class="mb-16"
data-status-illustration
>
<h2 class="text-clr-green-500">
Payment success
</h2>
<div class="mt-16">
<UiCoin :code="invoice.currencyCode" />
<MoneyAmount
:class="cn.e('amount')"
:value="invoice.amount"
:currency="invoice.currencyCode"
/>
</div>
<InvoiceFormDetails :class="cn.e('details')" />
<UiButton
:class="cn.e('back-to-store')"
size="large"
:href="invoice.redirectUrl"
>
Back to store
</UiButton>
<UiButton
:class="cn.e('explorer')"
type="link"
color="secondary"
:href="explorerLink"
target="_blank"
>
Просмотреть в обозревателе блоков
</UiButton>
<InvoiceFormSeparator />
</div>
</template>
<script setup>
const { invoice } = inject('public-invoice')
const cn = useClassname('invoice-form')
const explorerLink = computed(() => {
return `https://nile.tronscan.org/#/address/${invoice.value.walletAddress}`
})
</script>
<style lang="scss">
.invoice-form {
$self: &;
&--success {
#{$self}__amount {
@include h2('money-amount-value', true);
margin-left: 8px;
}
#{$self}__details {
margin-top: 32px;
}
#{$self}__back-to-store {
width: 100%;
margin-top: 32px;
}
#{$self}__explorer {
width: 100%;
margin-top: 24px;
}
}
}
</style>

View File

@@ -0,0 +1,126 @@
<template>
<div :class="cn.m('underpaid')">
<img
src="/partially.svg"
alt="Success"
class="mb-16"
data-status-illustration
>
<h2 class="text-clr-grey-600">
Invoice has been partially paid
</h2>
<p :class="cn.e('total')">
Total amount to be paid - <strong>{{ total }}</strong>
</p>
<div class="mt-32">
<UiCoin :code="invoice.currencyCode" />
<div :class="cn.e('collected-amount')">
<span>Funds received</span>
<MoneyAmount
:value="invoice.collectedAmount"
:currency="invoice.currencyCode"
/>
</div>
</div>
<UiAlert type="warning" :class="cn.e('alert')">
You need to deposit the missing part of the funds - <span style="white-space: nowrap">{{ missingAmount }}</span>, otherwise the bill will not be paid
</UiAlert>
<InvoiceFormDetails :class="cn.e('details')" accordion />
<UiButton
:class="cn.e('pay-additional')"
size="large"
@click="notify({ type: 'warning', id: 'wip', text: 'Work in progress' })"
>
Pay in addition
</UiButton>
<UiButton
:class="cn.e('explorer')"
type="link"
color="secondary"
:href="explorerLink"
target="_blank"
>
Просмотреть в обозревателе блоков
</UiButton>
<InvoiceFormSeparator />
</div>
</template>
<script setup>
import Decimal from 'decimal.js'
const { invoice } = inject('public-invoice')
const cn = useClassname('invoice-form')
const notify = useNotify()
const total = computed(() => $money.fullFormat(invoice.value.amount, invoice.value.currencyCode))
const missingAmount = computed(() => $money.fullFormat(Decimal.sub(invoice.value.amount, invoice.value.collectedAmount), invoice.value.currencyCode))
const explorerLink = computed(() => {
return `https://nile.tronscan.org/#/address/${invoice.value.walletAddress}`
})
</script>
<style lang="scss">
.invoice-form {
$self: &;
&--underpaid {
#{$self}__total {
@include h4;
color: $clr-grey-400;
margin-top: 4px;
strong {
color: $clr-grey-500;
}
}
#{$self}__collected-amount {
@include h3('money-amount-value', true);
display: inline-flex;
flex-direction: column;
text-align: left;
margin-left: 8px;
vertical-align: middle;
> span {
@include txt-r-m;
color: $clr-grey-500;
}
}
#{$self}__alert {
margin-top: 32px;
padding-block: 16px;
}
#{$self}__details {
margin-top: 32px;
}
#{$self}__pay-additional {
width: 100%;
margin-top: 32px;
}
#{$self}__explorer {
width: 100%;
margin-top: 24px;
}
}
}
</style>

View File

@@ -0,0 +1,49 @@
<template>
<div :class="cn.m('waiting-requisites')">
<div class="p-16">
<img
src="/pending.svg"
alt="Waiting requisites"
class="mb-16"
data-status-illustration
>
<h2 class="text-clr-grey-600">
Waiting
</h2>
<h4 class="text-clr-grey-400 mt-16">
It may take several minutes to receive payment details
</h4>
</div>
<InvoiceFormSeparator />
<InvoiceFormAmount />
<UiButton
:class="cn.e('action')"
size="large"
disabled
>
I have paid
</UiButton>
</div>
</template>
<script setup>
const cn = useClassname('invoice-form')
</script>
<style lang="scss">
.invoice-form {
$self: &;
&--waiting-requisites {
#{$self}__action {
width: 100%;
margin-top: 32px;
}
}
}
</style>

View File

@@ -0,0 +1,53 @@
<template>
<div :class="[cn.b(), cn.is('expired', isPassed)]">
<UiIconClock :class="cn.e('icon')" />
<ClientOnly>
<span :class="cn.e('time')">{{ formattedTime }}</span>
<template #fallback>
<span :class="cn.e('time')">--:--</span>
</template>
</ClientOnly>
</div>
</template>
<script setup>
const { expirationTime } = inject('public-invoice')
const cn = useClassname('invoice-form-timer')
const { isPassed, remainingTime } = useTimer(expirationTime)
const formattedTime = computed(() => {
return new Date(remainingTime.value * 1000).toISOString().slice(14, 19)
})
</script>
<style lang="scss">
.invoice-form-timer {
$self: &;
display: flex;
align-items: center;
&__icon {
color: $clr-grey-400;
margin-right: 8px;
#{$self}.is-expired & {
color: $clr-red-500;
}
}
&__time {
@include txt-m-sb;
color: $clr-grey-600;
#{$self}.is-expired & {
color: $clr-red-500;
}
}
}
</style>