diff --git a/src/pages/05_quotation/ReceiptDialog.vue b/src/pages/05_quotation/ReceiptDialog.vue index 76e549b3..802a5b63 100644 --- a/src/pages/05_quotation/ReceiptDialog.vue +++ b/src/pages/05_quotation/ReceiptDialog.vue @@ -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({ default: false, required: true }); const data = defineModel('data', { required: true }); const fileManager = ref>(); const refQFile = ref[]>([]); +const refQMenu = ref[]>([]); const paymentData = ref([]); +const submitPaymentData = ref([]); const payAll = ref(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()" >
{{ 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( }} -
+ + + {{ $t(`quotation.receiptDialog.${p.paymentStatus}`) }} + + + + + + + +
{{ $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; +}