feat: payment view
This commit is contained in:
parent
639dc36d71
commit
d9f8d0f971
4 changed files with 53 additions and 76 deletions
|
|
@ -1,754 +0,0 @@
|
|||
<script setup lang="ts">
|
||||
import { baseUrl } from 'stores/utils';
|
||||
import { storeToRefs } from 'pinia';
|
||||
import { useConfigStore } from 'stores/config';
|
||||
import { formatNumberDecimal } from 'stores/utils';
|
||||
import DialogForm from 'src/components/DialogForm.vue';
|
||||
import { reactive, ref, watch } from 'vue';
|
||||
import { useQuotationPayment } from 'src/stores/quotations';
|
||||
import {
|
||||
PaymentPayload,
|
||||
Quotation,
|
||||
QuotationPaymentData,
|
||||
} from 'src/stores/quotations/types';
|
||||
import { dateFormat } from 'src/utils/datetime';
|
||||
import { QFile, QMenu } from 'quasar';
|
||||
import UploadFileCard from 'src/components/upload-file/UploadFileCard.vue';
|
||||
|
||||
const configStore = useConfigStore();
|
||||
const quotationPayment = useQuotationPayment();
|
||||
const { data: config } = storeToRefs(configStore);
|
||||
|
||||
const model = defineModel<boolean>({ default: false, required: true });
|
||||
const data = defineModel<Quotation | undefined>('data', { required: true });
|
||||
|
||||
const fileManager =
|
||||
ref<ReturnType<typeof quotationPayment.createPaymentFileManager>>();
|
||||
const refQFile = ref<InstanceType<typeof QFile>[]>([]);
|
||||
const refQMenu = ref<InstanceType<typeof QMenu>[]>([]);
|
||||
const paymentData = ref<QuotationPaymentData[]>([]);
|
||||
const submitPaymentData = ref<QuotationPaymentData[]>([]);
|
||||
const payAll = ref<boolean>(false);
|
||||
const paymentStatusOpts = [
|
||||
{
|
||||
status: 'PaymentInProcess',
|
||||
icon: 'mdi-credit-card-clock-outline',
|
||||
color: 'danger',
|
||||
name: 'quotation.receiptDialog.PaymentInProcess',
|
||||
},
|
||||
{
|
||||
status: 'PaymentRetry',
|
||||
icon: 'mdi-information-outline',
|
||||
color: 'negative',
|
||||
name: 'quotation.receiptDialog.PaymentRetry',
|
||||
},
|
||||
{
|
||||
status: 'PaymentSuccess',
|
||||
icon: 'mdi-check-decagram-outline',
|
||||
color: 'positive',
|
||||
name: 'quotation.receiptDialog.PaymentSuccess',
|
||||
},
|
||||
];
|
||||
const slipFile = ref<
|
||||
{
|
||||
quotationId: string;
|
||||
paymentId: string;
|
||||
data: { name: string; progress: number; loaded: number; total: number }[];
|
||||
file?: File;
|
||||
}[]
|
||||
>([]);
|
||||
|
||||
const state = reactive({
|
||||
waitExpansion: true,
|
||||
payExpansion: [] as boolean[],
|
||||
});
|
||||
|
||||
function monthDisplay(date: Date | string) {
|
||||
const arr = dateFormat(date, true).split(' ');
|
||||
arr.shift();
|
||||
return arr.join(' ');
|
||||
}
|
||||
|
||||
function pickFile(index: number) {
|
||||
refQFile.value[index].pickFiles();
|
||||
}
|
||||
|
||||
async function getSlipList(payment: QuotationPaymentData, index: number) {
|
||||
if (!fileManager.value) return;
|
||||
const slipList = await fileManager.value.listAttachment({
|
||||
parentId: payment.id,
|
||||
});
|
||||
|
||||
if (slipList && slipList.length > 0) {
|
||||
slipFile.value[index].data = slipFile.value[index].data.filter((item) =>
|
||||
slipList.includes(item.name),
|
||||
);
|
||||
|
||||
slipList.forEach((slip) => {
|
||||
const exists = slipFile.value[index].data.some(
|
||||
(item) => item.name === slip,
|
||||
);
|
||||
|
||||
if (!exists) {
|
||||
slipFile.value[index].data.push({
|
||||
name: slip,
|
||||
progress: 1,
|
||||
loaded: 0,
|
||||
total: 0,
|
||||
});
|
||||
}
|
||||
});
|
||||
} else slipFile.value[index].data = [];
|
||||
}
|
||||
|
||||
async function triggerUpload(
|
||||
payment: QuotationPaymentData,
|
||||
index: number,
|
||||
file?: File,
|
||||
) {
|
||||
if (!data.value || !fileManager.value || !file) return;
|
||||
slipFile.value[index].data.push({
|
||||
name: file.name,
|
||||
progress: 0,
|
||||
loaded: 0,
|
||||
total: 0,
|
||||
});
|
||||
const ret = await fileManager.value.putAttachment({
|
||||
parentId: payment.id,
|
||||
name: file.name,
|
||||
file: file,
|
||||
onUploadProgress: (e) => {
|
||||
console.log(e);
|
||||
slipFile.value[index].data[slipFile.value[index].data.length - 1] = {
|
||||
name: file.name,
|
||||
progress: e.progress || 0,
|
||||
loaded: e.loaded,
|
||||
total: e.total || 0,
|
||||
};
|
||||
},
|
||||
});
|
||||
if (ret) await getSlipList(payment, index);
|
||||
slipFile.value[index].file = undefined;
|
||||
}
|
||||
|
||||
async function triggerDelete(
|
||||
payment: QuotationPaymentData,
|
||||
name: string,
|
||||
index: number,
|
||||
) {
|
||||
if (!data.value || !fileManager.value) return;
|
||||
await fileManager.value.delAttachment({ parentId: payment.id, name });
|
||||
await getSlipList(payment, index);
|
||||
}
|
||||
|
||||
function triggerViewSlip(payment: QuotationPaymentData, name: string) {
|
||||
if (!data.value || !fileManager.value) return;
|
||||
const url = `${baseUrl}/quotation/${data.value.id}/payment/${payment.id}/attachment/${name}`;
|
||||
window.open(url, '_blank');
|
||||
}
|
||||
|
||||
function selectStatus(
|
||||
payment: QuotationPaymentData,
|
||||
status: string,
|
||||
index: number,
|
||||
) {
|
||||
const existingPayment = submitPaymentData.value.findIndex(
|
||||
(p: QuotationPaymentData) => p.id === payment.id,
|
||||
);
|
||||
|
||||
if (existingPayment !== -1) {
|
||||
submitPaymentData.value[existingPayment].paymentStatus = status;
|
||||
} else {
|
||||
payment.paymentStatus = status;
|
||||
submitPaymentData.value.push(payment);
|
||||
}
|
||||
|
||||
refQMenu.value[index].hide();
|
||||
}
|
||||
|
||||
async function triggerSubmit() {
|
||||
submitPaymentData.value.forEach(async (p) => {
|
||||
if (!data.value) return;
|
||||
|
||||
const payload: PaymentPayload = {
|
||||
paymentStatus: p.paymentStatus,
|
||||
remark: p.remark || '',
|
||||
date: new Date(p.date),
|
||||
amount: p.amount,
|
||||
};
|
||||
await quotationPayment.updateQuotationPayment(data.value.id, p.id, payload);
|
||||
});
|
||||
model.value = false;
|
||||
}
|
||||
|
||||
watch(
|
||||
() => model.value,
|
||||
async (open) => {
|
||||
if (!data.value) return;
|
||||
if (!open) {
|
||||
paymentData.value = [];
|
||||
state.payExpansion = [];
|
||||
slipFile.value = [];
|
||||
submitPaymentData.value = [];
|
||||
} else {
|
||||
fileManager.value = quotationPayment.createPaymentFileManager(
|
||||
data.value.id,
|
||||
);
|
||||
const ret = await quotationPayment.getQuotationPayment(data.value.id);
|
||||
if (ret) {
|
||||
paymentData.value = ret.quotationPaymentData;
|
||||
slipFile.value = paymentData.value.map((v) => ({
|
||||
quotationId: ret.id,
|
||||
paymentId: v.id,
|
||||
data: [],
|
||||
}));
|
||||
}
|
||||
}
|
||||
},
|
||||
);
|
||||
</script>
|
||||
<template>
|
||||
<DialogForm
|
||||
:title="$t('quotation.receipt')"
|
||||
v-model:modal="model"
|
||||
width="65%"
|
||||
:submit="() => triggerSubmit()"
|
||||
>
|
||||
<div
|
||||
v-if="data"
|
||||
class="col column no-wrap"
|
||||
:class="{
|
||||
'q-mx-lg q-my-md': $q.screen.gt.sm,
|
||||
'q-mx-md q-my-sm': !$q.screen.gt.sm,
|
||||
}"
|
||||
>
|
||||
<!-- PRICE DETAIL -->
|
||||
<section class="bordered rounded surface-1" style="overflow: hidden">
|
||||
<q-expansion-item
|
||||
hide-expand-icon
|
||||
v-model="state.waitExpansion"
|
||||
header-style="padding:0px"
|
||||
>
|
||||
<template v-slot:header>
|
||||
<div class="column full-width bordered-b">
|
||||
<header class="bg-color-orange text-bold text-body1 q-pa-sm">
|
||||
<q-avatar class="surface-1 q-mr-sm" size="10px" />
|
||||
{{ $t('quotation.receiptDialog.paymentWait') }}
|
||||
</header>
|
||||
<span class="q-pa-md row items-center">
|
||||
<q-img
|
||||
src="/images/quotation-avatar.png"
|
||||
width="3rem"
|
||||
class="q-mr-lg"
|
||||
/>
|
||||
<div class="column col">
|
||||
<span class="text-bold text-body1">
|
||||
{{ data.workName }}
|
||||
</span>
|
||||
<span
|
||||
class="row items-center"
|
||||
:class="data.urgent ? 'urgent' : 'app-text-muted'"
|
||||
>
|
||||
{{ data.code }}
|
||||
<q-icon
|
||||
v-if="data.urgent"
|
||||
class="q-pl-sm"
|
||||
name="mdi-fire"
|
||||
size="xs"
|
||||
/>
|
||||
<span class="q-ml-auto" style="color: var(--foreground)">
|
||||
฿ {{ formatNumberDecimal(data.finalPrice, 2) || '0.00' }}
|
||||
</span>
|
||||
</span>
|
||||
</div>
|
||||
</span>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<span class="app-text-muted-2 q-px-md q-py-sm column">
|
||||
<span class="row">
|
||||
{{ $t('general.total') }}
|
||||
<span class="q-ml-auto" style="color: var(--foreground)">
|
||||
฿
|
||||
{{ formatNumberDecimal(data.totalPrice, 2) || '0.00' }}
|
||||
</span>
|
||||
</span>
|
||||
<span class="row">
|
||||
{{ $t('quotation.discountList') }}
|
||||
<span class="q-ml-auto" style="color: var(--foreground)">
|
||||
฿
|
||||
{{ formatNumberDecimal(data.totalDiscount, 2) || '0.00' }}
|
||||
</span>
|
||||
</span>
|
||||
<span class="row">
|
||||
{{ $t('general.totalAfterDiscount') }}
|
||||
<span class="q-ml-auto" style="color: var(--foreground)">
|
||||
฿
|
||||
{{
|
||||
formatNumberDecimal(
|
||||
data.totalPrice - data.totalDiscount,
|
||||
2,
|
||||
) || '0.00'
|
||||
}}
|
||||
</span>
|
||||
</span>
|
||||
<span class="row">
|
||||
{{ $t('general.totalVatExcluded') }}
|
||||
<span class="q-ml-auto" style="color: var(--foreground)">
|
||||
฿ {{ formatNumberDecimal(data.vatExcluded, 2) || '0.00' }}
|
||||
</span>
|
||||
</span>
|
||||
<span class="row">
|
||||
{{
|
||||
$t('general.vat', {
|
||||
msg: `${config && Math.round(config.vat * 100)}%`,
|
||||
})
|
||||
}}
|
||||
<span class="q-ml-auto" style="color: var(--foreground)">
|
||||
฿ {{ formatNumberDecimal(data.vat, 2) || '0.00' }}
|
||||
</span>
|
||||
</span>
|
||||
<span class="row">
|
||||
{{ $t('general.totalVatIncluded') }}
|
||||
<span class="q-ml-auto" style="color: var(--foreground)">
|
||||
฿
|
||||
{{
|
||||
formatNumberDecimal(
|
||||
data.totalPrice - data.totalDiscount + data.vat,
|
||||
2,
|
||||
) || '0.00'
|
||||
}}
|
||||
</span>
|
||||
</span>
|
||||
<span class="row">
|
||||
{{ $t('general.discountAfterVat') }}
|
||||
<span class="q-ml-auto" style="color: var(--foreground)">
|
||||
฿ {{ formatNumberDecimal(data.discount, 2) || '0.00' }}
|
||||
</span>
|
||||
</span>
|
||||
</span>
|
||||
</q-expansion-item>
|
||||
<q-separator inset v-if="state.waitExpansion" />
|
||||
<div
|
||||
class="q-py-sm q-px-md row items-center justify-end app-text-muted-2"
|
||||
>
|
||||
{{ $t('quotation.totalPriceBaht') }}:
|
||||
<span class="q-px-sm" style="color: var(--foreground)">
|
||||
{{ formatNumberDecimal(data.finalPrice, 2) || '0.00' }}
|
||||
</span>
|
||||
<q-btn
|
||||
dense
|
||||
flat
|
||||
rounded
|
||||
padding="0"
|
||||
:icon="`mdi-chevron-${state.waitExpansion ? 'down' : 'up'}`"
|
||||
@click.stop="state.waitExpansion = !state.waitExpansion"
|
||||
/>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<!-- PAYMENT DETAIL -->
|
||||
<section
|
||||
class="surface-1 rounded bordered column q-mt-md q-pa-md col scroll no-wrap"
|
||||
>
|
||||
<span class="text-weight-bold text-body1">
|
||||
{{ $t('general.payment') }}
|
||||
</span>
|
||||
<div class="row items-center q-pb-md">
|
||||
<span class="app-text-muted-2">{{ $t('quotation.payType') }}</span>
|
||||
<div
|
||||
class="badge-card q-ml-auto rounded"
|
||||
:class="`badge-card__${data.payCondition}`"
|
||||
>
|
||||
{{ $t(`quotation.type.${data.payCondition}`) }}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- split summary -->
|
||||
<div
|
||||
v-if="
|
||||
data.payCondition === 'BillSplit' || data.payCondition === 'Split'
|
||||
"
|
||||
class="row items-center q-pb-sm"
|
||||
>
|
||||
<span class="app-text-muted-2">
|
||||
{{ $t('quotation.paySplitCount') }}
|
||||
</span>
|
||||
<span class="q-ml-auto">
|
||||
{{ $t('quotation.receiptDialog.total') }}
|
||||
</span>
|
||||
<span class="bordered rounded surface-2 number-box q-mx-sm">
|
||||
{{ data.paySplitCount }}
|
||||
</span>
|
||||
{{ $t('quotation.receiptDialog.installments') }}
|
||||
{{ $i18n.locale === 'eng' ? ',' : '' }}
|
||||
{{ $t('quotation.receiptDialog.paid') }}
|
||||
<span class="bordered rounded surface-2 number-box q-mx-sm">
|
||||
{{
|
||||
paymentData.reduce(
|
||||
(c, i) => (i.paymentStatus === 'PaymentSuccess' ? c + 1 : c),
|
||||
0,
|
||||
)
|
||||
}}
|
||||
</span>
|
||||
{{
|
||||
$i18n.locale === 'tha'
|
||||
? $t('quotation.receiptDialog.installments')
|
||||
: ','
|
||||
}}
|
||||
{{ $t('quotation.receiptDialog.remain') }}
|
||||
<span class="bordered rounded surface-2 number-box q-mx-sm">
|
||||
{{
|
||||
paymentData.reduce(
|
||||
(c, i) => (i.paymentStatus !== 'PaymentSuccess' ? c + 1 : c),
|
||||
0,
|
||||
)
|
||||
}}
|
||||
</span>
|
||||
{{
|
||||
$i18n.locale === 'tha'
|
||||
? $t('quotation.receiptDialog.installments')
|
||||
: ''
|
||||
}}
|
||||
</div>
|
||||
|
||||
<!-- summary total, paid, remain -->
|
||||
<div class="row items-center">
|
||||
<span
|
||||
class="row col rounded q-px-sm q-py-md"
|
||||
style="border: 1px solid hsl(var(--info-bg))"
|
||||
>
|
||||
{{ $t('quotation.receiptDialog.totalAmount') }}
|
||||
<span class="q-ml-auto">
|
||||
{{ formatNumberDecimal(data.finalPrice, 2) }}
|
||||
</span>
|
||||
</span>
|
||||
<span
|
||||
class="row col rounded q-px-sm q-py-md q-mx-md"
|
||||
style="border: 1px solid hsl(var(--positive-bg))"
|
||||
>
|
||||
{{ $t('quotation.receiptDialog.paid') }}
|
||||
<span class="q-ml-auto">
|
||||
{{
|
||||
formatNumberDecimal(
|
||||
paymentData.reduce(
|
||||
(c, i) =>
|
||||
i.paymentStatus === 'PaymentSuccess' ? c + i.amount : c,
|
||||
0,
|
||||
),
|
||||
2,
|
||||
)
|
||||
}}
|
||||
</span>
|
||||
</span>
|
||||
<span
|
||||
class="row col rounded q-px-sm q-py-md"
|
||||
style="border: 1px solid hsl(var(--warning-bg))"
|
||||
>
|
||||
{{ $t('quotation.receiptDialog.remain') }}
|
||||
<span class="q-ml-auto">
|
||||
{{
|
||||
formatNumberDecimal(
|
||||
paymentData.reduce(
|
||||
(c, i) =>
|
||||
i.paymentStatus !== 'PaymentSuccess' ? c + i.amount : c,
|
||||
0,
|
||||
),
|
||||
2,
|
||||
)
|
||||
}}
|
||||
</span>
|
||||
</span>
|
||||
</div>
|
||||
|
||||
<!-- bill -->
|
||||
<span class="app-text-muted-2 q-pt-md">
|
||||
{{ $t('quotation.receiptDialog.billOfPayment') }}
|
||||
</span>
|
||||
<q-checkbox
|
||||
v-if="
|
||||
data.payCondition === 'BillSplit' || data.payCondition === 'Split'
|
||||
"
|
||||
size="xs"
|
||||
v-model="payAll"
|
||||
:label="$t('quotation.receiptDialog.payAll')"
|
||||
/>
|
||||
|
||||
<!-- payment item -->
|
||||
<section class="row">
|
||||
<div
|
||||
v-for="(p, i) in paymentData"
|
||||
:key="i"
|
||||
class="bordered rounded surface-1 q-mb-md col-12"
|
||||
style="overflow: hidden"
|
||||
>
|
||||
<q-expansion-item
|
||||
hide-expand-icon
|
||||
v-model="state.payExpansion[i]"
|
||||
header-style="padding:0px"
|
||||
@before-show="getSlipList(p, i)"
|
||||
>
|
||||
<template v-slot:header>
|
||||
<div class="column full-width">
|
||||
<section
|
||||
class="row full-width items-center surface-2 bordered-b q-px-md q-py-sm"
|
||||
>
|
||||
<span class="text-weight-medium column">
|
||||
{{ $t('quotation.receiptDialog.allInstallments') }}
|
||||
{{ monthDisplay(p.date) }}
|
||||
<span
|
||||
class="text-caption app-text-muted-2"
|
||||
v-if="data.payCondition !== 'Full'"
|
||||
>
|
||||
{{ $t('quotation.receiptDialog.paymentDueDate') }}
|
||||
{{
|
||||
data.payCondition !== 'BillFull'
|
||||
? dateFormat(p.date, true)
|
||||
: dateFormat(data.payBillDate)
|
||||
}}
|
||||
</span>
|
||||
</span>
|
||||
|
||||
<q-btn
|
||||
@click.stop
|
||||
unelevated
|
||||
padding="4px 8px"
|
||||
class="q-ml-auto rounded text-capitalize text-weight-regular payment-wait row items-center"
|
||||
:class="{
|
||||
'payment-pending': p.paymentStatus === 'PaymentWait',
|
||||
'payment-process':
|
||||
p.paymentStatus === 'PaymentInProcess',
|
||||
'payment-retry': p.paymentStatus === 'PaymentRetry',
|
||||
'payment-success': p.paymentStatus === 'PaymentSuccess',
|
||||
}"
|
||||
>
|
||||
<q-icon
|
||||
size="xs"
|
||||
:name="
|
||||
paymentStatusOpts.find(
|
||||
(s) => s.status === p.paymentStatus,
|
||||
)?.icon || 'mdi-hand-coin-outline'
|
||||
"
|
||||
class="q-pr-sm"
|
||||
/>
|
||||
<span>
|
||||
{{ $t(`quotation.receiptDialog.${p.paymentStatus}`) }}
|
||||
</span>
|
||||
<q-icon name="mdi-chevron-down" class="q-pl-xs" />
|
||||
<q-menu
|
||||
ref="refQMenu"
|
||||
fit
|
||||
:offset="[0, 8]"
|
||||
class="rounded"
|
||||
>
|
||||
<q-list dense>
|
||||
<template
|
||||
v-for="opts in paymentStatusOpts"
|
||||
:key="opts.status"
|
||||
>
|
||||
<q-item
|
||||
v-if="
|
||||
(p.paymentStatus === 'PaymentWait' &&
|
||||
opts.status !== 'PaymentRetry') ||
|
||||
(p.paymentStatus === 'PaymentInProcess' &&
|
||||
opts.status !== 'PaymentInProcess') ||
|
||||
(p.paymentStatus === 'PaymentRetry' &&
|
||||
opts.status !== 'PaymentRetry')
|
||||
"
|
||||
clickable
|
||||
class="row items-center"
|
||||
@click="selectStatus(p, opts.status, i)"
|
||||
>
|
||||
<q-icon
|
||||
:name="opts.icon"
|
||||
:color="opts.color"
|
||||
class="q-pr-sm"
|
||||
size="xs"
|
||||
/>
|
||||
{{ $t(opts.name) }}
|
||||
</q-item>
|
||||
</template>
|
||||
</q-list>
|
||||
</q-menu>
|
||||
</q-btn>
|
||||
</section>
|
||||
<section class="row items-center q-px-md q-py-sm">
|
||||
{{ $t('quotation.receiptDialog.amountToBePaid') }}
|
||||
<span
|
||||
class="q-px-sm q-ml-auto"
|
||||
style="color: var(--foreground)"
|
||||
>
|
||||
{{ formatNumberDecimal(p.amount, 2) }}
|
||||
</span>
|
||||
<q-btn
|
||||
dense
|
||||
flat
|
||||
rounded
|
||||
padding="0"
|
||||
:icon="`mdi-chevron-${state.payExpansion[i] ? 'down' : 'up'}`"
|
||||
@click.stop="
|
||||
state.payExpansion[i] = !state.payExpansion[i]
|
||||
"
|
||||
/>
|
||||
</section>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<div
|
||||
class="q-px-md q-py-xs text-weight-medium row items-center"
|
||||
style="background-color: hsla(var(--info-bg) / 0.1)"
|
||||
>
|
||||
{{
|
||||
$t('general.upload', {
|
||||
msg: $t('quotation.receiptDialog.slip'),
|
||||
})
|
||||
}}
|
||||
</div>
|
||||
<div class="surface-2 q-pa-md">
|
||||
<div
|
||||
class="upload-section column rounded q-py-md full-height items-center justify-center no-wrap"
|
||||
>
|
||||
<q-img src="/images/upload.png" width="150px" />
|
||||
{{ $t('general.upload', { msg: ' E-slip' }) }}
|
||||
{{
|
||||
$t('general.or', {
|
||||
msg: $t('general.upload', {
|
||||
msg: $t('quotation.receiptDialog.paymentDocs'),
|
||||
}),
|
||||
})
|
||||
}}
|
||||
<q-btn
|
||||
unelevated
|
||||
:label="$t('general.upload')"
|
||||
rounded
|
||||
class="app-bg-info q-mt-sm"
|
||||
@click.stop="() => pickFile(i)"
|
||||
/>
|
||||
<q-file
|
||||
ref="refQFile"
|
||||
v-show="false"
|
||||
v-model="slipFile[i].file"
|
||||
@update:model-value="triggerUpload(p, i, slipFile[i].file)"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<section class="surface-2 row q-px-md">
|
||||
<!-- upload card -->
|
||||
<div
|
||||
v-for="(d, j) in slipFile[i].data"
|
||||
:key="j"
|
||||
class="col-12"
|
||||
:class="{
|
||||
'q-pb-md': j === slipFile[i].data.length - 1,
|
||||
'q-pb-sm': j < slipFile[i].data.length,
|
||||
}"
|
||||
>
|
||||
<UploadFileCard
|
||||
:name="d.name"
|
||||
:progress="d.progress"
|
||||
:uploading="{ loaded: d.loaded, total: d.total }"
|
||||
:url="`/quotation/${data.id}/payment/${p.id}/attachment/${d.name}`"
|
||||
icon="mdi-file-image-outline"
|
||||
color="hsl(var(--text-mute))"
|
||||
clickable
|
||||
@click="triggerViewSlip(p, d.name)"
|
||||
@close="triggerDelete(p, d.name, i)"
|
||||
/>
|
||||
</div>
|
||||
</section>
|
||||
</q-expansion-item>
|
||||
</div>
|
||||
</section>
|
||||
</section>
|
||||
</div>
|
||||
</DialogForm>
|
||||
</template>
|
||||
<style scoped>
|
||||
.bg-color-orange {
|
||||
--_color: var(--yellow-7-hsl);
|
||||
color: white;
|
||||
background: hsla(var(--_color));
|
||||
}
|
||||
|
||||
.dark .bg-color-orange {
|
||||
--_color: var(--orange-6-hsl);
|
||||
}
|
||||
|
||||
.bg-color-orange-light {
|
||||
--_color: var(--yellow-7-hsl);
|
||||
background: hsla(var(--_color) / 0.2);
|
||||
}
|
||||
.dark .bg-color-orange {
|
||||
--_color: var(--orange-6-hsl / 0.2);
|
||||
}
|
||||
|
||||
.payment-pending {
|
||||
color: hsl(var(--warning-bg));
|
||||
background: hsla(var(--warning-bg) / 0.15);
|
||||
}
|
||||
|
||||
.payment-process {
|
||||
color: hsl(var(--danger-bg));
|
||||
background: hsla(var(--danger-bg) / 0.15);
|
||||
}
|
||||
|
||||
.payment-retry {
|
||||
color: hsl(var(--negative-bg));
|
||||
background: hsla(var(--negative-bg) / 0.15);
|
||||
}
|
||||
|
||||
.payment-success {
|
||||
color: hsl(var(--positive-bg));
|
||||
background: hsla(var(--positive-bg) / 0.1);
|
||||
}
|
||||
|
||||
.urgent {
|
||||
color: hsl(var(--red-6-hsl));
|
||||
}
|
||||
|
||||
.number-box {
|
||||
text-align: center;
|
||||
width: 25px;
|
||||
height: 25px;
|
||||
}
|
||||
|
||||
.badge-card {
|
||||
padding: 4px 8px;
|
||||
color: hsla(var(--gray-0-hsl) / 1);
|
||||
background: hsla(var(--_color) / 1);
|
||||
}
|
||||
|
||||
.badge-card__Full {
|
||||
--_color: var(--red-6-hsl);
|
||||
}
|
||||
|
||||
.badge-card__Split {
|
||||
--_color: var(--blue-6-hsl);
|
||||
}
|
||||
|
||||
.badge-card__BillFull {
|
||||
--_color: var(--jungle-8-hsl);
|
||||
}
|
||||
|
||||
.badge-card__BillSplit {
|
||||
--_color: var(--purple-7-hsl);
|
||||
}
|
||||
|
||||
.dark .badge-card__Split {
|
||||
--_color: var(--blue-10-hsl);
|
||||
}
|
||||
|
||||
.upload-section {
|
||||
border: 3px solid var(--border-color);
|
||||
border-style: dashed;
|
||||
}
|
||||
|
||||
:deep(
|
||||
.q-expansion-item
|
||||
.q-item.q-item-type.row.no-wrap.q-item--clickable.q-link.cursor-pointer.q-focusable.q-hoverable
|
||||
.q-focus-helper
|
||||
) {
|
||||
visibility: hidden;
|
||||
}
|
||||
</style>
|
||||
Loading…
Add table
Add a link
Reference in a new issue