refactor: workerIndex

This commit is contained in:
puriphatt 2024-10-10 17:49:28 +07:00
parent 85b108a9b2
commit 7760f0f15a
4 changed files with 88 additions and 12 deletions

View file

@ -1,7 +1,6 @@
<script lang="ts" setup> <script lang="ts" setup>
import { computed, onMounted, ref, watch } from 'vue'; import { computed, ref, watch } from 'vue';
import { QTableProps } from 'quasar'; import { QTableProps } from 'quasar';
import ThaiBahtText from 'thai-baht-text';
import { toWords } from 'number-to-words'; import { toWords } from 'number-to-words';
import { storeToRefs } from 'pinia'; import { storeToRefs } from 'pinia';
@ -9,14 +8,12 @@ import WorkerItem from './WorkerItem.vue';
import DeleteButton from '../button/DeleteButton.vue'; import DeleteButton from '../button/DeleteButton.vue';
import { commaInput } from 'stores/utils'; import { commaInput } from 'stores/utils';
import { precisionRound } from 'src/utils/arithmetic'; import { precisionRound } from 'src/utils/arithmetic';
import TableComponents from 'components/TableComponents.vue';
import { QuotationPayload } from 'stores/quotations/types'; import { QuotationPayload } from 'stores/quotations/types';
import { formatNumberDecimal } from 'stores/utils'; import { formatNumberDecimal } from 'stores/utils';
import { useConfigStore } from 'stores/config'; import { useConfigStore } from 'stores/config';
import { Product, Service, Work } from 'src/stores/product-service/types'; import { Product, Service, Work } from 'src/stores/product-service/types';
import { read } from 'fs';
defineProps<{ const props = defineProps<{
readonly?: boolean; readonly?: boolean;
agentPrice: boolean; agentPrice: boolean;
employeeRows?: { employeeRows?: {
@ -250,10 +247,22 @@ function groupByServiceId() {
groupList.value = groupedItems; groupList.value = groupedItems;
} }
function handleCheck(
index: number,
data: QuotationPayload['productServiceList'][number],
) {
const target = data.workerIndex.indexOf(index);
if (target > -1) {
data.workerIndex.splice(target, 1);
} else {
data.workerIndex.push(index);
}
}
watch( watch(
() => rows.value, () => rows.value,
() => { () => {
groupByServiceId(); if (rows.value.length > 0) groupByServiceId();
}, },
); );
@ -263,6 +272,19 @@ watch(
summaryPrice.value = summary.value; summaryPrice.value = summary.value;
}, },
); );
watch(
() => props.employeeRows,
(a, b) => {
if (a === undefined || b === undefined) return;
if (a.length < b.length) {
rows.value.forEach((p) => {
const maxValue = Math.max(...p.workerIndex);
p.workerIndex = p.workerIndex.filter((i) => i !== maxValue);
});
}
},
);
</script> </script>
<template> <template>
<div class="column"> <div class="column">
@ -278,7 +300,7 @@ watch(
style="background: var(--orange-5); color: var(--surface-1)" style="background: var(--orange-5); color: var(--surface-1)"
size="sm" size="sm"
> >
{{ i + 1 }} <q-icon size="xs" name="mdi-server-outline" />
</q-avatar> </q-avatar>
{{ item.title }} {{ item.title }}
</div> </div>
@ -419,9 +441,12 @@ watch(
> >
<q-td colspan="100%" style="padding: 16px"> <q-td colspan="100%" style="padding: 16px">
<WorkerItem <WorkerItem
@check="(wokerIndex) => handleCheck(wokerIndex, props.row)"
checkable
fallback-img="/images/employee-avatar.png" fallback-img="/images/employee-avatar.png"
inTable inTable
hideQuantity hideQuantity
:check-list="props.row.workerIndex"
:rows="employeeRows" :rows="employeeRows"
/> />
</q-td> </q-td>

View file

@ -1,9 +1,11 @@
<script lang="ts" setup> <script lang="ts" setup>
import { QTableProps } from 'quasar'; import { QTableProps } from 'quasar';
import TableComponents from 'src/components/TableComponents.vue'; import TableComponents from 'src/components/TableComponents.vue';
import { onMounted } from 'vue';
defineEmits<{ defineEmits<{
(e: 'delete', index: number): void; (e: 'delete', index: number): void;
(e: 'check', index: number): void;
}>(); }>();
withDefaults( withDefaults(
@ -12,6 +14,7 @@ withDefaults(
employeeAmount?: number; employeeAmount?: number;
fallbackImg?: string; fallbackImg?: string;
hideQuantity?: boolean; hideQuantity?: boolean;
checkable?: boolean;
inTable?: boolean; inTable?: boolean;
rows: { rows: {
foreignRefNo: string; foreignRefNo: string;
@ -31,6 +34,8 @@ withDefaults(
}, },
); );
const checkList = defineModel<number[]>('checkList', { default: [] });
const columns = [ const columns = [
{ {
name: 'order', name: 'order',
@ -87,13 +92,26 @@ const columns = [
<TableComponents <TableComponents
flat flat
bordered bordered
button-delete :button-delete="!checkable"
img-column="employeeName" img-column="employeeName"
:readonly="readonly" :readonly="readonly"
:inTable :inTable
:columns :columns="
checkable
? [
{
name: 'check',
align: 'center',
label: '',
field: 'check',
},
...columns.filter((c) => c.name !== 'action'),
]
: columns
"
:rows :rows
hidePagination hidePagination
:customColumn="['check']"
@delete="(i) => $emit('delete', i)" @delete="(i) => $emit('delete', i)"
> >
<template v-slot:img-column="{ props }"> <template v-slot:img-column="{ props }">
@ -121,6 +139,20 @@ const columns = [
</div> </div>
</q-avatar> </q-avatar>
</template> </template>
<template v-slot:body-cell-check="{ props }">
<q-td class="text-center">
<q-checkbox
size="xs"
@click.stop="
() => {
$emit('check', props.rowIndex);
}
"
:model-value="checkList.includes(props.rowIndex)"
></q-checkbox>
</q-td>
</template>
</TableComponents> </TableComponents>
<div v-if="!hideQuantity" class="row q-pt-md items-center"> <div v-if="!hideQuantity" class="row q-pt-md items-center">

View file

@ -222,6 +222,7 @@ function mapNode() {
detail: p.product.detail, detail: p.product.detail,
remark: p.product.remark, remark: p.product.remark,
value: { value: {
workerIndex: [],
vat: 0, vat: 0,
pricePerUnit, pricePerUnit,
discount: 0, discount: 0,
@ -258,6 +259,7 @@ function mapNode() {
subtitle: p.product.code || ' ', subtitle: p.product.code || ' ',
checked: true, checked: true,
value: { value: {
workerIndex: [],
vat: 0, vat: 0,
pricePerUnit, pricePerUnit,
discount: 0, discount: 0,
@ -282,6 +284,7 @@ function mapNode() {
title: v.name, title: v.name,
subtitle: v.code, subtitle: v.code,
value: { value: {
workerIndex: [],
vat: 0, vat: 0,
pricePerUnit, pricePerUnit,
discount: 0, discount: 0,

View file

@ -52,7 +52,13 @@ import ToggleButton from 'components/button/ToggleButton.vue';
import FormAbout from 'components/05_quotation/FormAbout.vue'; import FormAbout from 'components/05_quotation/FormAbout.vue';
import SelectZone from 'components/shared/SelectZone.vue'; import SelectZone from 'components/shared/SelectZone.vue';
import PersonCard from 'components/shared/PersonCard.vue'; import PersonCard from 'components/shared/PersonCard.vue';
import { AddButton, SaveButton, EditButton } from 'components/button'; import {
AddButton,
SaveButton,
EditButton,
UndoButton,
DeleteButton,
} from 'components/button';
import ProductServiceForm from './ProductServiceForm.vue'; import ProductServiceForm from './ProductServiceForm.vue';
import QuotationFormInfo from './QuotationFormInfo.vue'; import QuotationFormInfo from './QuotationFormInfo.vue';
import ProfileBanner from 'components/ProfileBanner.vue'; import ProfileBanner from 'components/ProfileBanner.vue';
@ -250,7 +256,7 @@ async function assignToProductServiceList() {
}), }),
); );
selectedProductGroup.value = selectedProductGroup.value =
quotationFormData.value.productServiceList[0].product.productGroup?.id || quotationFormData.value.productServiceList[0]?.product.productGroup?.id ||
''; '';
} }
} }
@ -424,6 +430,9 @@ function convertToTable(nodes: Node[]) {
list.forEach((v) => { list.forEach((v) => {
v.amount = Math.max(selectedWorker.value.length, 1); v.amount = Math.max(selectedWorker.value.length, 1);
for (let i = 0; i < selectedWorker.value.length; i++) {
v.workerIndex.push(i);
}
}); });
productServiceList.value = list; productServiceList.value = list;
@ -437,6 +446,14 @@ function convertEmployeeToTable() {
v.amount + preSelectedWorker.value.length - selectedWorker.value.length, v.amount + preSelectedWorker.value.length - selectedWorker.value.length,
1, 1,
); );
for (
let i = 0;
i < preSelectedWorker.value.length - selectedWorker.value.length;
i++
) {
v.workerIndex.push(selectedWorker.value.length + i);
}
return v; return v;
}); });
refSelectZoneEmployee.value?.assignSelect( refSelectZoneEmployee.value?.assignSelect(
@ -715,7 +732,6 @@ watch(
productGroup.find((g) => g.id === selectedProductGroup) productGroup.find((g) => g.id === selectedProductGroup)
?.name || '-' ?.name || '-'
}} }}
<q-icon name="mdi-chevron-right" class="q-pl-sm" size="xs" />
</span> </span>
<ProductItem <ProductItem