refactor: receiptDialog

This commit is contained in:
puriphatt 2024-10-24 11:32:42 +07:00
parent fddc0341c5
commit 200cce9e7e

View file

@ -6,27 +6,49 @@ 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 { Quotation, QuotationPaymentData } from 'src/stores/quotations/types';
import {
PaymentPayload,
Quotation,
QuotationPaymentData,
} from 'src/stores/quotations/types';
import { dateFormat } from 'src/utils/datetime';
import { QFile } from 'quasar';
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);
defineEmits<{
(e: 'upload', index: number): void;
}>();
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;
@ -119,12 +141,46 @@ async function triggerDelete(
await getSlipList(payment, index);
}
async function triggerViewSlip(payment: QuotationPaymentData, name: string) {
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) => {
@ -133,6 +189,7 @@ watch(
paymentData.value = [];
state.payExpansion = [];
slipFile.value = [];
submitPaymentData.value = [];
} else {
fileManager.value = quotationPayment.createPaymentFileManager(
data.value.id,
@ -155,7 +212,7 @@ watch(
:title="$t('quotation.receipt')"
v-model:modal="model"
width="65%"
hideFooter
:submit="() => triggerSubmit()"
>
<div
v-if="data"
@ -343,7 +400,7 @@ watch(
<span class="bordered rounded surface-2 number-box q-mx-sm">
{{
paymentData.reduce(
(c, i) => (i.paymentStatus === 'PaymentWait' ? c + 1 : c),
(c, i) => (i.paymentStatus !== 'PaymentSuccess' ? c + 1 : c),
0,
)
}}
@ -396,7 +453,9 @@ watch(
? formatNumberDecimal(
paymentData.reduce(
(c, i) =>
i.paymentStatus === 'PaymentWait' ? c + i.amount : c,
i.paymentStatus !== 'PaymentSuccess'
? c + i.amount
: c,
0,
),
2,
@ -457,7 +516,7 @@ watch(
}}
</span>
</span>
<div
<!-- <div
class="q-ml-auto items-center flex q-py-xs q-px-sm rounded"
:class="{
'payment-success': p.paymentStatus === 'PaymentSuccess',
@ -473,7 +532,70 @@ watch(
? $t('quotation.receiptDialog.notYetPaid')
: $t('quotation.receiptDialog.alreadyPaid')
}}
</div>
</div> -->
<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') }}
@ -586,16 +708,26 @@ watch(
--_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);
}
.payment-wait {
color: hsl(var(--warning-bg));
background: hsla(var(--warning-bg) / 0.15);
}
.urgent {
color: hsl(var(--red-6-hsl));
}
@ -636,4 +768,12 @@ watch(
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>