refactor: quotation
This commit is contained in:
parent
57b5392bfe
commit
f2d9507668
3 changed files with 935 additions and 148 deletions
269
src/components/05_quotation/ProductItem.vue
Normal file
269
src/components/05_quotation/ProductItem.vue
Normal file
|
|
@ -0,0 +1,269 @@
|
|||
<script lang="ts" setup>
|
||||
import { QTableProps } from 'quasar';
|
||||
import TableComponents from 'src/components/TableComponents.vue';
|
||||
|
||||
const calTax = defineModel('calTax', { default: false });
|
||||
const priceData = defineModel<{
|
||||
productList: number;
|
||||
discount: number;
|
||||
tax: number;
|
||||
totalPrice: number;
|
||||
}>('priceData', {
|
||||
default: { productList: 0, discount: 0, tax: 0, totalPrice: 0 },
|
||||
});
|
||||
|
||||
defineEmits<{
|
||||
(e: 'delete'): void;
|
||||
}>();
|
||||
|
||||
withDefaults(
|
||||
defineProps<{
|
||||
rows: {
|
||||
code: string;
|
||||
list: string;
|
||||
type: string;
|
||||
amount: number;
|
||||
pricePerUnit: number;
|
||||
discount: number;
|
||||
tax: number;
|
||||
sumPrice: number;
|
||||
}[];
|
||||
}>(),
|
||||
{
|
||||
rows: () => [],
|
||||
},
|
||||
);
|
||||
|
||||
const columns = [
|
||||
{
|
||||
name: 'order',
|
||||
align: 'center',
|
||||
label: 'general.order',
|
||||
field: 'order',
|
||||
},
|
||||
{
|
||||
name: 'code',
|
||||
align: 'center',
|
||||
label: 'productService.group.code',
|
||||
field: 'code',
|
||||
},
|
||||
{
|
||||
name: 'list',
|
||||
align: 'left',
|
||||
label: 'productService.service.list',
|
||||
field: 'list',
|
||||
},
|
||||
{
|
||||
name: 'amount',
|
||||
align: 'center',
|
||||
label: 'general.amount',
|
||||
field: 'amount',
|
||||
},
|
||||
{
|
||||
name: 'pricePerUnit',
|
||||
align: 'center',
|
||||
label: 'quotation.pricePerUnit',
|
||||
field: 'pricePerUnit',
|
||||
},
|
||||
{
|
||||
name: 'discount',
|
||||
align: 'center',
|
||||
label: 'general.discount',
|
||||
field: 'discount',
|
||||
},
|
||||
{
|
||||
name: 'tax',
|
||||
align: 'center',
|
||||
label: 'quotation.tax',
|
||||
field: 'tax',
|
||||
},
|
||||
{
|
||||
name: 'sumPrice',
|
||||
align: 'center',
|
||||
label: 'quotation.sumPrice',
|
||||
field: 'sumPrice',
|
||||
},
|
||||
{
|
||||
name: 'action',
|
||||
align: 'left',
|
||||
label: '',
|
||||
field: 'action',
|
||||
},
|
||||
] satisfies QTableProps['columns'];
|
||||
</script>
|
||||
<template>
|
||||
<div class="column">
|
||||
<TableComponents
|
||||
flat
|
||||
bordered
|
||||
hidePagination
|
||||
button-delete
|
||||
:columns="columns"
|
||||
:rows="rows"
|
||||
imgColumn="list"
|
||||
:customColumn="['amount', 'pricePerUnit', 'discount', 'tax', 'sumPrice']"
|
||||
@delete="$emit('delete')"
|
||||
>
|
||||
<template v-slot:img-column="{ props }">
|
||||
<q-avatar class="q-mr-sm" size="md">
|
||||
<q-icon
|
||||
class="full-width full-height"
|
||||
:name="
|
||||
props.row.type === 'product'
|
||||
? 'mdi-shopping-outline'
|
||||
: 'mdi-server-outline'
|
||||
"
|
||||
:style="`color: var(--${props.row.type === 'product' ? 'teal-10' : 'orange-5'}); background: ${
|
||||
props.row.type === 'product'
|
||||
? `hsla(var(--teal-${$q.dark.isActive ? '8' : '10'}-hsl)/0.15)`
|
||||
: `hsla(var(--orange-${$q.dark.isActive ? '6' : '5'}-hsl)/0.15)`
|
||||
}`"
|
||||
/>
|
||||
</q-avatar>
|
||||
</template>
|
||||
|
||||
<template v-slot:body-cell-amount="{ props }">
|
||||
<q-td align="center">
|
||||
<q-input
|
||||
dense
|
||||
outlined
|
||||
type="number"
|
||||
style="width: 70px"
|
||||
min="0"
|
||||
:modelValue="props.row.amount"
|
||||
@update:modelValue="(v) => (props.row = v)"
|
||||
/>
|
||||
</q-td>
|
||||
</template>
|
||||
|
||||
<template v-slot:body-cell-pricePerUnit="{ props }">
|
||||
<q-td align="center">
|
||||
<q-input
|
||||
dense
|
||||
outlined
|
||||
type="number"
|
||||
style="width: 70px"
|
||||
:modelValue="props.row.pricePerUnit"
|
||||
min="0"
|
||||
@update:modelValue="(v) => (props.row = v)"
|
||||
/>
|
||||
</q-td>
|
||||
</template>
|
||||
|
||||
<template v-slot:body-cell-discount="{ props }">
|
||||
<q-td align="center">
|
||||
<q-input
|
||||
dense
|
||||
min="0"
|
||||
outlined
|
||||
type="number"
|
||||
style="width: 70px"
|
||||
:modelValue="props.row.discount"
|
||||
@update:modelValue="(v) => (props.row = v)"
|
||||
/>
|
||||
</q-td>
|
||||
</template>
|
||||
|
||||
<template v-slot:body-cell-tax="{ props }">
|
||||
<q-td align="center">
|
||||
<q-input
|
||||
dense
|
||||
min="0"
|
||||
outlined
|
||||
type="number"
|
||||
style="width: 70px"
|
||||
:modelValue="props.row.tax"
|
||||
@update:modelValue="(v) => (props.row = v)"
|
||||
>
|
||||
<template v-slot:append>
|
||||
<span class="text-caption no-padding">%</span>
|
||||
</template>
|
||||
</q-input>
|
||||
</q-td>
|
||||
</template>
|
||||
|
||||
<template v-slot:body-cell-sumPrice="{ props }">
|
||||
<q-td align="center">
|
||||
<q-input
|
||||
dense
|
||||
min="0"
|
||||
outlined
|
||||
type="number"
|
||||
style="width: 70px"
|
||||
:modelValue="props.row.sumPrice"
|
||||
@update:modelValue="(v) => (props.row = v)"
|
||||
/>
|
||||
</q-td>
|
||||
</template>
|
||||
|
||||
<template #button>
|
||||
<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));
|
||||
"
|
||||
/>
|
||||
</template>
|
||||
</TableComponents>
|
||||
<q-checkbox
|
||||
v-model="calTax"
|
||||
class="q-pt-md"
|
||||
size="xs"
|
||||
:label="$t('quotation.calTax')"
|
||||
/>
|
||||
<div
|
||||
class="column q-ml-auto text-caption app-text-muted"
|
||||
style="width: 15vw"
|
||||
>
|
||||
<div class="row">
|
||||
{{ $t('quotation.allProduct') }}
|
||||
<span class="q-ml-auto">{{ priceData.productList }} ฿</span>
|
||||
</div>
|
||||
<div class="row">
|
||||
{{ $t('general.discount') }}
|
||||
<span class="q-ml-auto">{{ priceData.discount }} ฿</span>
|
||||
</div>
|
||||
<div class="row">
|
||||
{{ $t('quotation.tax') }}
|
||||
<span class="q-ml-auto">{{ priceData.tax }} ฿</span>
|
||||
</div>
|
||||
<q-separator spaced="md" />
|
||||
<div class="row text-bold text-body2" style="color: var(--foreground)">
|
||||
Total Price
|
||||
<span class="q-ml-auto">{{ priceData.totalPrice }} ฿</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<style scoped>
|
||||
.worker-item {
|
||||
--side-color: var(--brand-1);
|
||||
position: relative;
|
||||
overflow-x: hidden;
|
||||
|
||||
&.worker-item__female {
|
||||
--side-color: hsl(var(--gender-female));
|
||||
}
|
||||
|
||||
&.worker-item__male {
|
||||
--side-color: hsl(var(--gender-male));
|
||||
}
|
||||
}
|
||||
|
||||
.worker-item::before {
|
||||
position: absolute;
|
||||
content: ' ';
|
||||
left: 0;
|
||||
width: 7px;
|
||||
top: 0;
|
||||
bottom: 0;
|
||||
background: var(--side-color);
|
||||
}
|
||||
</style>
|
||||
|
|
@ -1,44 +1,128 @@
|
|||
<script lang="ts" setup>
|
||||
defineProps<{
|
||||
data: {
|
||||
no: number;
|
||||
refNo: string;
|
||||
fullName: string;
|
||||
birthDate: string;
|
||||
age: string;
|
||||
nationality: string;
|
||||
docExpireDate: string;
|
||||
};
|
||||
color?: 'male' | 'female' | 'none';
|
||||
import { QTableProps } from 'quasar';
|
||||
import TableComponents from 'src/components/TableComponents.vue';
|
||||
|
||||
defineEmits<{
|
||||
(e: 'delete'): void;
|
||||
}>();
|
||||
|
||||
withDefaults(
|
||||
defineProps<{
|
||||
employeeAmount: number;
|
||||
rows: {
|
||||
foreignRefNo: string;
|
||||
employeeName: string;
|
||||
birthDate: string;
|
||||
gender: string;
|
||||
age: string;
|
||||
nationality: string;
|
||||
documentExpireDate: string;
|
||||
imgUrl: string;
|
||||
status: string;
|
||||
}[];
|
||||
}>(),
|
||||
{
|
||||
rows: () => [],
|
||||
employeeAmount: 0,
|
||||
},
|
||||
);
|
||||
|
||||
const columns = [
|
||||
{
|
||||
name: 'order',
|
||||
align: 'center',
|
||||
label: 'general.order',
|
||||
field: 'order',
|
||||
},
|
||||
{
|
||||
name: 'foreignRefNo',
|
||||
align: 'center',
|
||||
label: 'quotation.foreignRefNo',
|
||||
field: 'foreignRefNo',
|
||||
},
|
||||
{
|
||||
name: 'employeeName',
|
||||
align: 'left',
|
||||
label: 'quotation.employeeName',
|
||||
field: 'employeeName',
|
||||
},
|
||||
{
|
||||
name: 'birthDate',
|
||||
align: 'left',
|
||||
label: 'general.birthDate',
|
||||
field: 'birthDate',
|
||||
},
|
||||
{
|
||||
name: 'age',
|
||||
align: 'left',
|
||||
label: 'general.age',
|
||||
field: 'age',
|
||||
},
|
||||
{
|
||||
name: 'nationality',
|
||||
align: 'left',
|
||||
label: 'general.nationality',
|
||||
field: 'nationality',
|
||||
},
|
||||
{
|
||||
name: 'documentExpireDate',
|
||||
align: 'left',
|
||||
label: 'quotation.documentExpireDate',
|
||||
field: 'documentExpireDate',
|
||||
},
|
||||
{
|
||||
name: 'action',
|
||||
align: 'left',
|
||||
label: '',
|
||||
field: 'action',
|
||||
},
|
||||
] satisfies QTableProps['columns'];
|
||||
</script>
|
||||
<template>
|
||||
<div
|
||||
class="surface-1 rounded row bordered worker-item items-center"
|
||||
:class="{
|
||||
'worker-item__male': color === 'male',
|
||||
'worker-item__female': color === 'female',
|
||||
}"
|
||||
style="padding-block: var(--size-2)"
|
||||
>
|
||||
<div class="col-1 text-center">{{ data.no }}</div>
|
||||
<div class="col-2 text-center">{{ data.refNo }}</div>
|
||||
<div class="col-3">{{ data.fullName }}</div>
|
||||
<div class="col-1">{{ data.birthDate }}</div>
|
||||
<div class="col-1 text-center">{{ data.age }}</div>
|
||||
<div class="col-1 text-center">{{ data.nationality }}</div>
|
||||
<div class="col-2 text-center">{{ data.docExpireDate }}</div>
|
||||
<div class="col-1 text-center">
|
||||
<q-btn
|
||||
id="btn-delete-work"
|
||||
icon="mdi-trash-can-outline"
|
||||
dense
|
||||
flat
|
||||
round
|
||||
size="12px"
|
||||
color="negative"
|
||||
@click="$emit('delete')"
|
||||
/>
|
||||
<div>
|
||||
<TableComponents
|
||||
flat
|
||||
bordered
|
||||
button-delete
|
||||
img-column="employeeName"
|
||||
:columns
|
||||
:rows
|
||||
hidePagination
|
||||
@delete="$emit('delete')"
|
||||
>
|
||||
<template v-slot:img-column="{ props }">
|
||||
<q-avatar class="q-mr-sm" size="md">
|
||||
<q-img :src="props.row.imgUrl"></q-img>
|
||||
<div
|
||||
class="absolute-bottom-right"
|
||||
style="
|
||||
border-radius: 50%;
|
||||
width: 10px;
|
||||
height: 10px;
|
||||
z-index: 2;
|
||||
background: var(--surface-1);
|
||||
"
|
||||
>
|
||||
<div
|
||||
class="absolute-center"
|
||||
style="border-radius: 50%; width: 8px; height: 8px"
|
||||
:style="`background: hsl(var(${props.row.status !== 'INACTIVE' ? '--positive-bg' : '--text-mute'}))`"
|
||||
></div>
|
||||
</div>
|
||||
</q-avatar>
|
||||
</template>
|
||||
</TableComponents>
|
||||
|
||||
<div class="row q-pt-md items-center">
|
||||
<span class="q-ml-auto">
|
||||
{{ $t('general.numberOf', { msg: $t('quotation.employee') }) }}
|
||||
</span>
|
||||
<div
|
||||
class="surface-tab bordered rounded flex items-center justify-center q-mx-md"
|
||||
style="width: 30px; height: 30px"
|
||||
>
|
||||
{{ employeeAmount }}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue