fix: product worker

This commit is contained in:
puriphatt 2024-10-09 18:09:01 +07:00
parent f4802b6991
commit 7f0d006a7c
4 changed files with 176 additions and 248 deletions

View file

@ -5,6 +5,8 @@ import ThaiBahtText from 'thai-baht-text';
import { toWords } from 'number-to-words';
import { storeToRefs } from 'pinia';
import WorkerItem from './WorkerItem.vue';
import DeleteButton from '../button/DeleteButton.vue';
import { commaInput } from 'stores/utils';
import { precisionRound } from 'src/utils/arithmetic';
import TableComponents from 'components/TableComponents.vue';
@ -15,6 +17,17 @@ import { Product, Service, Work } from 'src/stores/product-service/types';
defineProps<{
agentPrice: boolean;
employeeRows?: {
foreignRefNo: string;
employeeName: string;
birthDate: string;
gender: string;
age: string;
nationality: string;
documentExpireDate: string;
imgUrl: string;
status: string;
}[];
}>();
defineEmits<{
@ -59,7 +72,9 @@ const summaryPrice = defineModel<{
},
});
const currentBtnOpen = ref<boolean[]>([]);
const currentBtnOpen = ref<{ title: string; opened: boolean[] }[]>([
{ title: '', opened: [] },
]);
const finalDiscount = ref<number>(0);
const finalDiscount4Show = ref<string>(finalDiscount.value.toString());
@ -104,7 +119,7 @@ const columns = [
},
{
name: 'code',
align: 'center',
align: 'left',
label: 'productService.group.code',
field: (v) => v.product.code,
},
@ -150,12 +165,6 @@ const columns = [
label: 'quotation.sumPrice',
field: 'sumPrice',
},
{
name: 'action',
align: 'left',
label: '',
field: 'action',
},
] satisfies QTableProps['columns'];
const EngBahtText = (number: number) => {
@ -167,14 +176,16 @@ const EngBahtText = (number: number) => {
return `${bahtText} Baht${satang ? ` and ${satangText} Satang` : ''}`;
};
function openEmployeeTable(index: number) {
currentBtnOpen.value.map((_, i) => {
function openEmployeeTable(title: string, index: number) {
currentBtnOpen.value[0].title = title;
currentBtnOpen.value[0].opened.map((_, i) => {
if (i !== index) {
currentBtnOpen.value[i] = false;
currentBtnOpen.value[0].opened[i] = false;
}
});
currentBtnOpen.value[index] = !currentBtnOpen.value[index];
currentBtnOpen.value[0].opened[index] =
!currentBtnOpen.value[0].opened[index];
}
watch(
@ -202,251 +213,144 @@ watch(
</q-avatar>
{{ item.title }}
</div>
<TableComponents
<q-table
flat
bordered
hidePagination
button-delete
hide-pagination
:columns="columns"
:rows="item.product"
:customColumn="[
'name',
'amount',
'pricePerUnit',
'discount',
'tax',
'sumPrice',
'priceBeforeVat',
]"
@delete="(i) => $emit('delete', i)"
class="full-width"
:no-data-label="$t('general.noDataTable')"
>
<template v-slot:body-cell-name="{ props }">
<q-td>
<q-avatar class="q-mr-sm" size="md">
<q-icon
class="full-width full-height"
name="mdi-shopping-outline"
:style="`color: var(--teal-10); background: hsla(var(--teal-${$q.dark.isActive ? '8' : '10'}-hsl)/0.15)`"
<template #header="{ cols }">
<q-tr style="background-color: hsla(var(--info-bg) / 0.07)">
<q-th v-for="(v, i) in cols" :key="v">
{{ $t(v.label) }}
</q-th>
<q-th auto-width />
</q-tr>
</template>
<template #body="props">
<q-tr>
<q-td class="text-center">{{ props.rowIndex + 1 }}</q-td>
<q-td>{{ props.row.product.code }}</q-td>
<q-td>
<q-avatar class="q-mr-sm" size="md">
<q-icon
class="full-width full-height"
name="mdi-shopping-outline"
:style="`color: var(--teal-10); background: hsla(var(--teal-${$q.dark.isActive ? '8' : '10'}-hsl)/0.15)`"
/>
</q-avatar>
{{ props.row.product.name }}
</q-td>
<q-td align="center">
<q-input
dense
outlined
type="number"
style="width: 70px"
min="0"
v-model="props.row.amount"
/>
</q-avatar>
{{ props.row.product.name }}
</q-td>
</template>
<template v-slot:body-cell-amount="{ props }">
<q-td align="center">
<q-input
dense
outlined
type="number"
style="width: 70px"
min="0"
v-model="props.row.amount"
/>
</q-td>
</template>
<template v-slot:body-cell-pricePerUnit="{ props }">
<q-td align="right">
{{
formatNumberDecimal(
props.row.pricePerUnit +
props.row.pricePerUnit * (config?.vat || 0.07),
2,
)
}}
</q-td>
</template>
<template v-slot:body-cell-discount="{ props }">
<q-td align="center">
<q-input
dense
min="0"
outlined
input-class="text-right"
type="number"
style="width: 90px"
v-model="props.row.discount"
/>
</q-td>
</template>
<template v-slot:body-cell-priceBeforeVat="{ props }">
<q-td align="right">
{{ formatNumberDecimal(props.row.pricePerUnit, 2) }}
</q-td>
</template>
<template v-slot:body-cell-tax="{ props }">
<q-td align="right">
{{
precisionRound(
(props.row.pricePerUnit * props.row.amount -
props.row.discount) *
(config?.vat || 0.07),
)
}}
</q-td>
</template>
<template v-slot:body-cell-sumPrice="{ props }">
<q-td align="right">
{{ formatNumberDecimal(calcPrice(props.row), 2) }}
</q-td>
</template>
<template #button="{ props }">
<q-btn
@click.stop="openEmployeeTable(props.rowIndex)"
dense
flat
size="sm"
class="rounded q-mr-xs"
>
<div class="row items-center no-wrap">
<q-icon name="mdi-account-group-outline" />
<q-icon
size="xs"
:name="`mdi-chevron-${currentBtnOpen[props.rowIndex] ? 'down' : 'up'}`"
</q-td>
<q-td align="right">
{{
formatNumberDecimal(
props.row.pricePerUnit +
props.row.pricePerUnit * (config?.vat || 0.07),
2,
)
}}
</q-td>
<q-td align="center">
<q-input
dense
min="0"
outlined
input-class="text-right"
type="number"
style="width: 90px"
v-model="props.row.discount"
/>
</div>
</q-btn>
<q-btn
icon="mdi-monitor"
size="sm"
class="rounded q-mr-xs"
padding="4px 8px"
dense
flat
style="
background-color: hsla(var(--positive-bg) / 0.1);
color: hsl(var(--positive-bg));
</q-td>
<q-td align="right">
{{ formatNumberDecimal(props.row.pricePerUnit, 2) }}
</q-td>
<q-td align="right">
{{
formatNumberDecimal(
precisionRound(
(props.row.pricePerUnit * props.row.amount -
props.row.discount) *
(config?.vat || 0.07),
),
2,
)
}}
</q-td>
<q-td align="right">
{{ formatNumberDecimal(calcPrice(props.row), 2) }}
</q-td>
<q-td>
<div class="row items-center full-width justify-end no-wrap">
<q-btn
@click.stop="openEmployeeTable(item.title, props.rowIndex)"
dense
flat
size="sm"
class="rounded q-mr-xs"
>
<div class="row items-center no-wrap">
<q-icon name="mdi-account-group-outline" />
<q-icon
size="xs"
:name="`mdi-chevron-${currentBtnOpen[0].title === item.title && currentBtnOpen[0].opened[props.rowIndex] ? 'down' : 'up'}`"
/>
</div>
</q-btn>
<q-btn
icon="mdi-monitor"
size="sm"
class="rounded q-mr-xs"
padding="4px 8px"
dense
flat
style="
background-color: hsla(var(--positive-bg) / 0.1);
color: hsl(var(--positive-bg));
"
/>
<DeleteButton
iconOnly
@click="$emit('delete', props.rowIndex)"
/>
</div>
</q-td>
</q-tr>
<q-tr
v-show="
currentBtnOpen[0].title === item.title &&
currentBtnOpen[0].opened[props.rowIndex]
"
/>
:props="props"
>
<q-td colspan="100%" style="padding: 16px">
<WorkerItem
fallback-img="/images/employee-avatar.png"
inTable
hideQuantity
:rows="employeeRows"
/>
</q-td>
</q-tr>
</template>
</TableComponents>
</q-table>
</section>
</div>
<div class="row items-start">
<span
class="col row items-center justify-between q-px-md q-py-xs q-mr-lg rounded app-text-muted-2 bg-color-orange-light"
>
<span class="text-weight-bold text-caption">
{{ $t('general.totalAmount') }}
</span>
<span v-if="summary.finalPrice + Number(finalDiscount)">
{{
$i18n.locale === 'eng'
? EngBahtText(summary.finalPrice)
: ThaiBahtText(summary.finalPrice)
}}
</span>
</span>
<div class="col column">
<div class="row q-py-xs q-pr-xs q-pl-md">
<span class="col-9 app-text-muted-2">
{{ $t('quotation.allProductPrice') }}
</span>
<q-input
dense
class="col price-tag"
readonly
outlined
input-class="text-right text-bold "
:model-value="
formatNumberDecimal(summary.finalPrice + Number(finalDiscount), 2)
"
/>
</div>
<div class="row q-py-xs q-pr-xs q-pl-md">
<span class="col-9 app-text-muted-2">
{{ $t('quotation.quotationDiscount') }}
</span>
<q-input
dense
class="col price-tag"
outlined
input-class="text-right text-bold"
:model-value="commaInput(finalDiscount.toString())"
@update:model-value="
(v) => {
if (typeof v === 'string') finalDiscount4Show = commaInput(v);
const x = parseFloat(
finalDiscount4Show && typeof finalDiscount4Show === 'string'
? finalDiscount4Show.replace(/,/g, '')
: '',
);
finalDiscount = x;
}
"
/>
</div>
<div
class="row text-bold bg-color-orange rounded q-py-xs q-pr-xs q-pl-md items-center"
style="color: var(--surface-1)"
>
<span class="col-9">
{{ $t('general.totalAmount') }}
</span>
<q-input
dense
class="col price-tag"
outlined
readonly
input-class="text-right text-bold "
:model-value="
formatNumberDecimal(Math.max(summary.finalPrice, 0), 2)
"
/>
</div>
</div>
</div>
<!-- <div
class="column q-ml-auto text-caption app-text-muted-2"
style="width: 15vw"
>
<div class="row">
{{ $t('quotation.allProductPrice') }}
<span class="q-ml-auto">
{{ formatNumberDecimal(summary.totalPrice, 2) }} ฿
</span>
</div>
<div class="row">
{{ $t('general.discount') }}
<span class="q-ml-auto">
{{ formatNumberDecimal(summary.totalDiscount, 2) }} ฿
</span>
</div>
<div class="row">
{{ $t('quotation.tax') }}
<span class="q-ml-auto">
{{ formatNumberDecimal(summary.vat, 2) }} ฿
</span>
</div>
<q-separator spaced="md" />
<div class="row text-bold text-body2" style="color: var(--foreground)">
{{ $t('quotation.totalPrice') }}
<span class="q-ml-auto">
{{ formatNumberDecimal(summary.finalPrice, 2) }} ฿
</span>
</div>
</div>
<span
v-if="summary.finalPrice"
class="text-caption app-text-muted-2 flex self-end"
>
({{
$i18n.locale === 'eng'
? EngBahtText(summary.finalPrice)
: ThaiBahtText(summary.finalPrice)
}})
</span> -->
</div>
</template>
@ -495,4 +399,8 @@ watch(
bottom: 0;
background: var(--side-color);
}
:deep(i.q-icon.mdi.mdi-alert.q-table__bottom-nodata-icon) {
color: #ffc224 !important;
}
</style>

View file

@ -10,6 +10,8 @@ withDefaults(
defineProps<{
employeeAmount: number;
fallbackImg?: string;
hideQuantity?: boolean;
inTable?: boolean;
rows: {
foreignRefNo: string;
employeeName: string;
@ -86,6 +88,7 @@ const columns = [
bordered
button-delete
img-column="employeeName"
:inTable
:columns
:rows
hidePagination
@ -118,7 +121,7 @@ const columns = [
</template>
</TableComponents>
<div class="row q-pt-md items-center">
<div v-if="!hideQuantity" class="row q-pt-md items-center">
<span class="q-ml-auto">
{{ $t('general.numberOf', { msg: $t('quotation.employee') }) }}
</span>

View file

@ -14,6 +14,7 @@ const props = withDefaults(
buttomDownload?: boolean;
buttonDelete?: boolean;
hidePagination?: boolean;
inTable?: boolean;
imgColumn?: string;
customColumn?: string[];
@ -52,7 +53,7 @@ defineEmits<{
>
<template v-slot:header="props">
<q-tr
style="background-color: hsla(var(--info-bg) / 0.07)"
:style="`background-color: ${inTable ? '#F0FFF1' : 'hsla(var(--info-bg) / 0.07'} `"
:props="props"
>
<q-th v-for="col in props.cols" :key="col.name" :props="props">

View file

@ -688,6 +688,22 @@ watch(
<ProductItem
:agent-price="agentPrice"
:employeeRows="
selectedWorker.map((e: Employee) => ({
foreignRefNo: '123456789',
employeeName:
$i18n.locale === 'eng'
? `${e.firstNameEN} ${e.lastNameEN}`
: `${e.firstName} ${e.lastName}`,
birthDate: dateFormat(e.dateOfBirth),
gender: e.gender,
age: calculateAge(e.dateOfBirth),
nationality: optionStore.mapOption(e.nationality),
documentExpireDate: '1234',
imgUrl: `${baseUrl}/customer/${e.id}/image/${e.selectedImage}`,
status: e.status,
}))
"
@delete="toggleDeleteProduct"
v-model:groupList="productServiceTableData"
v-model:rows="productServiceList"