refactor: quotation

This commit is contained in:
puriphatt 2024-09-27 16:11:16 +07:00
parent 57b5392bfe
commit f2d9507668
3 changed files with 935 additions and 148 deletions

View 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>

View file

@ -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>