jws-frontend/src/pages/11_credit-note/RefundInformation.vue
Methapon Metanipat 5e2100eb8d
feat: credit note (#171)
* feat: add main page credit note

* feat: enable credit note route and update menu item states

* refactor: add i18n

* refactor: edit i18n status

* feat: add action column

* feat: add empty form page

* feat: add get data

* feat: add type credit note status

* refactor: add type name en

* refactor: add type credit note status in type credit note

* feat: add hsla colors

* refactor: add slot grid

* refactor: handle  hide kebab edit show only tab tssued

* feat: show grid card

* feat: i18n

* feat: add credit note form and dialog

* refactor: add props hide kebab deelete

* refactor: hide kebab

* style: update color segments to indigo theme

* feat: i18n

* fix: update labels for credit note fields

* refactor: add type

* feat: new select quotation

* refactor: use new select quotation

* feat: navigate to

* refactor: function trigger and navigate to

* feat: i18n bank

* feat: add payment expansion component and integrate into credit note form

* refactor: bind i18n pay condition

* refactor: navigate to get quotation id

* feat: i18n

* fix: update label for createdBy field in credit note form

* feat: add credit note information expansion component

* feat: add Credit Note expansion component and update form layout

* refactor: bind quotation id and send

* refactor: deelete duplicate type

* refactor: show state button

* refactor: handle show status

* feat: add function update payback status

* feat: add return and canceled reasons to credit note translations

* feat: enhance SelectReadyRequestWork component with credit note handling and fetch parameters

* feat: type

* feat: add status handling and optional display for employee table

* refactor: rename selectedQuotationId to quotationId in FormCredit component

* feat: set default opened state for CreditNoteExpansion and add reason options

* feat: update PaymentExpansion to handle payback type selection and clear fields for cash payments

* feat: enhance ProductExpansion to support credit note handling and adjust price calculations

* feat: implement product handling and price calculation in CreditNote form

* feat: add manage attachment function to store

* refactor: bind delete credit note

* feat: add credit note status and reference fields to types

* refactor: update task step handling and simplify request work structure in credit note form

* feat: add navigation to quotation from credit note form

* feat: enhance upload section layout based on file data

* feat: add readonly functionality to credit note form and related components

* refactor: remove console log

* feat: update i18n

* style: add rounded corners to complete view container in quotation form

* feat: add RefundInformation component and update credit note form status handling

* feat: i18n

* feat: update payback status endpoint and add paybackStatus to CreditNote type

* feat: enhance QuotationFormReceipt component with optional props and slot support

* feat: integrate payback status handling in RefundInformation and FormPage components

* feat: add external file group

* feat: update API endpoint paths for credit note operations

* feat: improve layout and styling in UploadFile components

* feat: implement file upload and management in Credit Note

* refactor: update upload to check if it is redirect or not

* feat: upload file slips

* feat: add payback date dispaly

* refactor: change module no

* fix: icon link to main page instead

* feat: add file dialog with image download functionality

* fix: view slip

* feat: add download button to image viewer

* feat: handle after submit

* feat: conditionally render bank transfer information

* feat: handle upload file on create

* feat: handle change payback status

* feat: payback type in credit note form

* fix: correct reference to quotation data in goToQuotation function

---------

Co-authored-by: Methapon2001 <61303214+Methapon2001@users.noreply.github.com>
Co-authored-by: puriphatt <puriphat@frappet.com>
Co-authored-by: Thanaphon Frappet <thanaphon@frappet.com>
2025-01-14 09:08:31 +07:00

280 lines
7.6 KiB
Vue

<script setup lang="ts">
import useOptionStore from 'src/stores/options';
import { formatNumberDecimal } from 'src/stores/utils';
import UploadFileSection from 'src/components/upload-file/UploadFileSection.vue';
import { computed, ref } from 'vue';
import { CreditNotePaybackStatus } from 'src/stores/credit-note/types';
const props = withDefaults(
defineProps<{
paybackType: 'Cash' | 'BankTransfer';
paybackBank: string;
paybackAccount: string;
paybackAccountName: string;
paybackStatus: CreditNotePaybackStatus;
readonly?: boolean;
total?: number;
paid?: number;
remain?: number;
transformUrl?: (url: string) => string | Promise<string>;
}>(),
{
paybackStatus: CreditNotePaybackStatus.Pending,
paybackType: 'Cash',
total: 0,
paid: 0,
remain: 0,
},
);
defineEmits<{
(e: 'changeStatus', status: CreditNotePaybackStatus): void;
(e: 'upload', file: FileList): void;
(e: 'remove', name: string): void;
}>();
const fileData = defineModel<
{
name: string;
progress: number;
loaded: number;
total: number;
url?: string;
}[]
>('fileData', { default: [] });
const currStatus = computed(() =>
refundOpts.value.find((v) => v.value === props.paybackStatus),
);
const refundOpts = ref<
{
icon: string;
value: CreditNotePaybackStatus;
color: string;
}[]
>([
{
value: CreditNotePaybackStatus.Pending,
icon: 'mdi-hand-coin-outline',
color: 'warning',
},
{
value: CreditNotePaybackStatus.Verify,
icon: 'mdi-credit-card-clock-outline',
color: 'danger',
},
{
value: CreditNotePaybackStatus.Done,
icon: 'mdi-check-decagram-outline',
color: 'positive',
},
]);
</script>
<template>
<div class="surface-1 rounded q-px-md q-py-sm">
<span
class="row items-center justify-between full-width text-medium text-body1"
style="min-height: 31.01px"
>
{{ $t('general.information', { msg: $t('creditNote.label.refund') }) }}
</span>
<section :class="{ row: $q.screen.gt.sm }">
<article
class="col column q-pr-md"
:class="{
'bordered-r': $q.screen.gt.sm,
'bordered-b q-pb-sm': $q.screen.lt.md,
}"
>
<div class="row">
<span class="app-text-muted q-mr-auto">
{{ $t('creditNote.label.refundMethod') }}
</span>
<q-badge>
{{ $t(`creditNote.label.${paybackType}`) }}
</q-badge>
</div>
<div class="row" v-if="paybackType === 'BankTransfer'">
<span class="app-text-muted q-mr-auto">
{{ $t('branch.form.bank') }}
</span>
<span>
<q-img
:src="`/img/bank/${paybackBank}.png`"
class="bordered q-mr-xs"
style="border-radius: 50%; width: 20px"
/>
{{ useOptionStore().mapOption(paybackBank) }}
{{ paybackAccount }}
{{ `${$t('creditNote.label.accountName')} ${paybackAccountName}` }}
</span>
</div>
</article>
<article
class="col row"
:class="{ 'q-pl-md': $q.screen.gt.sm, 'q-pt-sm': $q.screen.lt.md }"
>
<span class="col-12 app-text-muted">
{{ $t('creditNote.label.totalRefund') }}
</span>
<article
class="row col-12 items-center surface-1 q-py-sm rounded gradient-stat"
>
<span
class="row col rounded q-px-sm q-py-md info"
style="border: 1px solid hsl(var(--info-bg))"
>
{{ $t('creditNote.label.totalAmount') }}
<span class="q-ml-auto">
{{ formatNumberDecimal(total) }}
</span>
</span>
<span
class="row col rounded q-px-sm q-mx-md q-py-md positive"
style="border: 1px solid hsl(var(--positive-bg))"
>
{{ $t('creditNote.label.paid') }}
<span class="q-ml-auto">
{{ formatNumberDecimal(paid) }}
</span>
</span>
<span
class="row col rounded q-px-sm q-py-md warning"
style="border: 1px solid hsl(var(--warning-bg))"
>
{{ $t('creditNote.label.remain') }}
<span class="q-ml-auto">
{{ formatNumberDecimal(remain) }}
</span>
</span>
</article>
</article>
</section>
</div>
<div class="surface-1 rounded">
<span
class="bordered-b q-px-md q-py-sm row items-center justify-between full-width text-medium text-body1"
style="min-height: 31.01px"
>
{{ $t('creditNote.label.refund') }}
<q-btn-dropdown
dense
unelevated
:label="$t(`creditNote.status.payback.${paybackStatus}`)"
class="text-capitalize text-weight-regular product-status rounded"
:class="{
warning: paybackStatus === CreditNotePaybackStatus.Pending,
danger: paybackStatus === CreditNotePaybackStatus.Verify,
'positive hide-dropdown q-pr-md':
paybackStatus === CreditNotePaybackStatus.Done,
}"
:menu-offset="[0, 8]"
dropdown-icon="mdi-chevron-down"
content-class="bordered rounded"
@click.stop
:icon="currStatus?.icon"
>
<q-list v-if="paybackStatus !== CreditNotePaybackStatus.Done" dense>
<q-item
v-for="(v, index) in paybackStatus ===
CreditNotePaybackStatus.Verify
? refundOpts.filter(
(v) => v.value === CreditNotePaybackStatus.Done,
)
: refundOpts.filter(
(v) => v.value !== CreditNotePaybackStatus.Pending,
)"
clickable
v-close-popup
class="items-center"
:key="index"
@click="$emit('changeStatus', v.value)"
>
<q-icon
:style="`color: hsl(var(--${v.color}-bg))`"
:name="v.icon"
class="q-pr-sm"
size="xs"
></q-icon>
{{ $t(`creditNote.status.payback.${v.value}`) }}
</q-item>
</q-list>
</q-btn-dropdown>
</span>
<section class="q-px-md q-py-sm">
<UploadFileSection
multiple
:layout="$q.screen.gt.sm ? 'column' : 'row'"
:readonly
:label="`${$t('general.upload', { msg: ' E-slip' })} ${$t(
'general.or',
{
msg: $t('general.upload', {
msg: $t('creditNote.label.refundDocs'),
}),
},
)}`"
:transform-url="transformUrl"
v-model:file-data="fileData"
@update:file="(f) => $emit('upload', f as unknown as FileList)"
@close="(v) => $emit('remove', v)"
/>
</section>
</div>
</template>
<style scoped>
.gradient-stat {
& .info {
background-image: linear-gradient(
to right,
hsl(var(--info-bg) / 0.15),
var(--surface-1)
);
}
& .positive {
background-image: linear-gradient(
to right,
hsl(var(--positive-bg) / 0.15),
var(--surface-1)
);
}
& .warning {
background-image: linear-gradient(
to right,
hsl(var(--warning-bg) / 0.15),
var(--surface-1)
);
}
}
.product-status {
padding-left: 8px;
border-radius: 20px;
color: hsl(var(--_color));
background: hsla(var(--_color) / 0.15);
&.warning {
--_color: var(--warning-bg);
}
&.danger {
--_color: var(--danger-bg);
}
&.positive {
--_color: var(--positive-bg);
}
}
:deep(
.hide-dropdown
i.q-icon.mdi.mdi-chevron-down.q-btn-dropdown__arrow.q-btn-dropdown__arrow-container
) {
display: none;
}
</style>