Merge branch 'develop'
This commit is contained in:
commit
5a0663b94b
53 changed files with 932 additions and 541 deletions
|
|
@ -199,7 +199,7 @@ onMounted(async () => {
|
||||||
outlined
|
outlined
|
||||||
dense
|
dense
|
||||||
class="col"
|
class="col"
|
||||||
id="input-flow-template-name"
|
for="input-flow-template-name"
|
||||||
v-model="flowData.name"
|
v-model="flowData.name"
|
||||||
hide-bottom-space
|
hide-bottom-space
|
||||||
:label="$t(`general.name`, { msg: $t('flow.step') })"
|
:label="$t(`general.name`, { msg: $t('flow.step') })"
|
||||||
|
|
@ -255,8 +255,8 @@ onMounted(async () => {
|
||||||
<div class="row items-center q-py-sm full-width">
|
<div class="row items-center q-py-sm full-width">
|
||||||
<q-btn
|
<q-btn
|
||||||
v-if="!readonly"
|
v-if="!readonly"
|
||||||
id="btn-work-up-product"
|
:id="`btn-work-up-product-${step.name || index}-${onDrawer ? 'drawer' : 'dialog'}`"
|
||||||
for="btn-work-up-product"
|
:for="`btn-work-up-product-${step.name || index}-${onDrawer ? 'drawer' : 'dialog'}`"
|
||||||
icon="mdi-arrow-up"
|
icon="mdi-arrow-up"
|
||||||
dense
|
dense
|
||||||
flat
|
flat
|
||||||
|
|
@ -270,8 +270,8 @@ onMounted(async () => {
|
||||||
/>
|
/>
|
||||||
<q-btn
|
<q-btn
|
||||||
v-if="!readonly"
|
v-if="!readonly"
|
||||||
id="btn-work-down-product"
|
:id="`btn-work-down-product-${step.name || index}-${onDrawer ? 'drawer' : 'dialog'}`"
|
||||||
for="btn-work-down-product"
|
:for="`btn-work-down-product-${step.name || index}-${onDrawer ? 'drawer' : 'dialog'}`"
|
||||||
icon="mdi-arrow-down"
|
icon="mdi-arrow-down"
|
||||||
dense
|
dense
|
||||||
flat
|
flat
|
||||||
|
|
@ -376,7 +376,7 @@ onMounted(async () => {
|
||||||
</div> -->
|
</div> -->
|
||||||
<q-btn
|
<q-btn
|
||||||
v-if="!readonly"
|
v-if="!readonly"
|
||||||
id="btn-delete-work"
|
:id="`btn-delete-work-${step.name || index}-${onDrawer ? 'drawer' : 'dialog'}`"
|
||||||
icon="mdi-trash-can-outline"
|
icon="mdi-trash-can-outline"
|
||||||
dense
|
dense
|
||||||
flat
|
flat
|
||||||
|
|
@ -399,6 +399,7 @@ onMounted(async () => {
|
||||||
>
|
>
|
||||||
<div class="row q-col-gutter-sm">
|
<div class="row q-col-gutter-sm">
|
||||||
<q-input
|
<q-input
|
||||||
|
:for="`textarea-detail-${index}-${onDrawer ? 'drawer' : 'dialog'}`"
|
||||||
:bg-color="readonly ? 'transparent' : ''"
|
:bg-color="readonly ? 'transparent' : ''"
|
||||||
:readonly
|
:readonly
|
||||||
class="col-md-6 col-12"
|
class="col-md-6 col-12"
|
||||||
|
|
@ -411,7 +412,6 @@ onMounted(async () => {
|
||||||
(v) => (step.detail = v?.toString() || '')
|
(v) => (step.detail = v?.toString() || '')
|
||||||
"
|
"
|
||||||
/>
|
/>
|
||||||
|
|
||||||
<div class="col-md-6 col-12">
|
<div class="col-md-6 col-12">
|
||||||
<div
|
<div
|
||||||
class="surface-1 rounded bordered full-height"
|
class="surface-1 rounded bordered full-height"
|
||||||
|
|
@ -434,7 +434,7 @@ onMounted(async () => {
|
||||||
</div>
|
</div>
|
||||||
<q-btn
|
<q-btn
|
||||||
v-if="!readonly"
|
v-if="!readonly"
|
||||||
id="btn-add-work-product"
|
:id="`btn-add-work-product-${index}-${onDrawer ? 'drawer' : 'dialog'}`"
|
||||||
class="text-capitalize rounded absolute-top-right"
|
class="text-capitalize rounded absolute-top-right"
|
||||||
flat
|
flat
|
||||||
dense
|
dense
|
||||||
|
|
@ -465,6 +465,7 @@ onMounted(async () => {
|
||||||
<q-select
|
<q-select
|
||||||
v-if="step.responsiblePersonId"
|
v-if="step.responsiblePersonId"
|
||||||
behavior="menu"
|
behavior="menu"
|
||||||
|
:for="`select-responsible-person-${index}-${onDrawer ? 'drawer' : 'dialog'}`"
|
||||||
:bg-color="readonly ? 'transparent' : ''"
|
:bg-color="readonly ? 'transparent' : ''"
|
||||||
:readonly
|
:readonly
|
||||||
outlined
|
outlined
|
||||||
|
|
@ -550,7 +551,7 @@ onMounted(async () => {
|
||||||
<q-list>
|
<q-list>
|
||||||
<q-item>
|
<q-item>
|
||||||
<q-input
|
<q-input
|
||||||
for="input-search"
|
:for="`input-search-${index}-${onDrawer ? 'drawer' : 'dialog'}`"
|
||||||
outlined
|
outlined
|
||||||
dense
|
dense
|
||||||
:label="$t('general.search')"
|
:label="$t('general.search')"
|
||||||
|
|
@ -582,7 +583,10 @@ onMounted(async () => {
|
||||||
class="column"
|
class="column"
|
||||||
@click.stop="selectResponsiblePerson(index, person)"
|
@click.stop="selectResponsiblePerson(index, person)"
|
||||||
>
|
>
|
||||||
<div class="row items-center no-wrap">
|
<div
|
||||||
|
class="row items-center no-wrap"
|
||||||
|
:id="`select-responsible-person-${index}-${person.firstName || person.firstNameEN}-${onDrawer ? 'drawer' : 'dialog'}`"
|
||||||
|
>
|
||||||
<q-checkbox
|
<q-checkbox
|
||||||
size="xs"
|
size="xs"
|
||||||
:model-value="
|
:model-value="
|
||||||
|
|
@ -652,6 +656,7 @@ onMounted(async () => {
|
||||||
>
|
>
|
||||||
<div class="row items-center">
|
<div class="row items-center">
|
||||||
<q-checkbox
|
<q-checkbox
|
||||||
|
:id="`select-area-${index}`"
|
||||||
v-model="step.messengerByArea"
|
v-model="step.messengerByArea"
|
||||||
size="xs"
|
size="xs"
|
||||||
></q-checkbox>
|
></q-checkbox>
|
||||||
|
|
@ -667,6 +672,7 @@ onMounted(async () => {
|
||||||
<!-- RESPONSIBLE-AGENCIES, RESPONSIBLE-INSTITUTION -->
|
<!-- RESPONSIBLE-AGENCIES, RESPONSIBLE-INSTITUTION -->
|
||||||
<q-select
|
<q-select
|
||||||
behavior="menu"
|
behavior="menu"
|
||||||
|
:for="`select-responsible-institution-${index}-${onDrawer ? 'drawer' : 'dialog'}`"
|
||||||
:bg-color="readonly ? 'transparent' : ''"
|
:bg-color="readonly ? 'transparent' : ''"
|
||||||
:readonly
|
:readonly
|
||||||
outlined
|
outlined
|
||||||
|
|
@ -737,6 +743,7 @@ onMounted(async () => {
|
||||||
v-if="step.responsibleInstitution"
|
v-if="step.responsibleInstitution"
|
||||||
>
|
>
|
||||||
<q-checkbox
|
<q-checkbox
|
||||||
|
:id="`select-responsible-institution-${index}-${opt.value}-${onDrawer ? 'drawer' : 'dialog'}`"
|
||||||
:model-value="
|
:model-value="
|
||||||
step.responsibleInstitution.some(
|
step.responsibleInstitution.some(
|
||||||
(v: string) => v === opt.value,
|
(v: string) => v === opt.value,
|
||||||
|
|
|
||||||
|
|
@ -222,6 +222,7 @@ const detailEditorImageDrop = createEditorImageDrop(detail);
|
||||||
dense
|
dense
|
||||||
>
|
>
|
||||||
<q-editor
|
<q-editor
|
||||||
|
id="input-detail"
|
||||||
dense
|
dense
|
||||||
:model-value="readonly ? detail || '-' : detail"
|
:model-value="readonly ? detail || '-' : detail"
|
||||||
@update:model-value="
|
@update:model-value="
|
||||||
|
|
|
||||||
|
|
@ -106,6 +106,7 @@ function optionSearch(val: string | null) {
|
||||||
|
|
||||||
<div class="col-12 row q-col-gutter-sm">
|
<div class="col-12 row q-col-gutter-sm">
|
||||||
<q-select
|
<q-select
|
||||||
|
for="select-attachment"
|
||||||
behavior="menu"
|
behavior="menu"
|
||||||
:readonly
|
:readonly
|
||||||
outlined
|
outlined
|
||||||
|
|
@ -150,6 +151,7 @@ function optionSearch(val: string | null) {
|
||||||
{{ $t('general.add', { text: $t('general.attachment') }) }}
|
{{ $t('general.add', { text: $t('general.attachment') }) }}
|
||||||
</q-item> -->
|
</q-item> -->
|
||||||
<q-item
|
<q-item
|
||||||
|
for="select-all"
|
||||||
dense
|
dense
|
||||||
clickable
|
clickable
|
||||||
class="flex items-center"
|
class="flex items-center"
|
||||||
|
|
@ -172,6 +174,7 @@ function optionSearch(val: string | null) {
|
||||||
</template>
|
</template>
|
||||||
<template #option="{ opt }">
|
<template #option="{ opt }">
|
||||||
<q-checkbox
|
<q-checkbox
|
||||||
|
:id="`select-${opt.label}`"
|
||||||
:model-value="attachment.some((v) => v === opt.value)"
|
:model-value="attachment.some((v) => v === opt.value)"
|
||||||
class="q-pr-sm"
|
class="q-pr-sm"
|
||||||
size="xs"
|
size="xs"
|
||||||
|
|
|
||||||
|
|
@ -260,6 +260,7 @@ withDefaults(
|
||||||
</template>
|
</template>
|
||||||
<template v-if="col.name === '#vatIncluded'">
|
<template v-if="col.name === '#vatIncluded'">
|
||||||
<q-select
|
<q-select
|
||||||
|
for="select-vat-included"
|
||||||
:options="[
|
:options="[
|
||||||
{ label: $t('general.included'), value: true },
|
{ label: $t('general.included'), value: true },
|
||||||
{ label: $t('general.notIncluded'), value: false },
|
{ label: $t('general.notIncluded'), value: false },
|
||||||
|
|
@ -278,6 +279,7 @@ withDefaults(
|
||||||
{ label: $t('general.notIncluded'), value: false },
|
{ label: $t('general.notIncluded'), value: false },
|
||||||
]"
|
]"
|
||||||
v-if="priceDisplay?.agentPrice && props.rowIndex === 1"
|
v-if="priceDisplay?.agentPrice && props.rowIndex === 1"
|
||||||
|
for="select-vat-included"
|
||||||
map-options
|
map-options
|
||||||
emit-value
|
emit-value
|
||||||
flat
|
flat
|
||||||
|
|
@ -291,6 +293,7 @@ withDefaults(
|
||||||
{ label: $t('general.notIncluded'), value: false },
|
{ label: $t('general.notIncluded'), value: false },
|
||||||
]"
|
]"
|
||||||
v-if="priceDisplay?.serviceCharge && props.rowIndex === 2"
|
v-if="priceDisplay?.serviceCharge && props.rowIndex === 2"
|
||||||
|
for="select-vat-included"
|
||||||
map-options
|
map-options
|
||||||
emit-value
|
emit-value
|
||||||
flat
|
flat
|
||||||
|
|
|
||||||
|
|
@ -127,8 +127,8 @@ watch(
|
||||||
<div class="row items-center q-py-sm full-width" @click.stop>
|
<div class="row items-center q-py-sm full-width" @click.stop>
|
||||||
<q-btn
|
<q-btn
|
||||||
v-if="!readonly"
|
v-if="!readonly"
|
||||||
id="btn-work-up-product"
|
:id="`btn-work-up-product-${workIndex}`"
|
||||||
for="btn-work-up-product"
|
:for="`btn-work-up-product-${workIndex}`"
|
||||||
icon="mdi-arrow-up"
|
icon="mdi-arrow-up"
|
||||||
dense
|
dense
|
||||||
flat
|
flat
|
||||||
|
|
@ -139,8 +139,8 @@ watch(
|
||||||
/>
|
/>
|
||||||
<q-btn
|
<q-btn
|
||||||
v-if="!readonly"
|
v-if="!readonly"
|
||||||
id="btn-work-down-product"
|
:id="`btn-work-down-product-${workIndex}`"
|
||||||
for="btn-work-down-product"
|
:for="`btn-work-down-product-${workIndex}`"
|
||||||
icon="mdi-arrow-down"
|
icon="mdi-arrow-down"
|
||||||
dense
|
dense
|
||||||
flat
|
flat
|
||||||
|
|
@ -244,7 +244,7 @@ watch(
|
||||||
<div :class="{ 'col-12 row justify-end q-mt-sm': $q.screen.lt.md }">
|
<div :class="{ 'col-12 row justify-end q-mt-sm': $q.screen.lt.md }">
|
||||||
<q-btn
|
<q-btn
|
||||||
v-if="!readonly"
|
v-if="!readonly"
|
||||||
id="btn-delete-work"
|
:id="`btn-delete-work-${workIndex}`"
|
||||||
icon="mdi-trash-can-outline"
|
icon="mdi-trash-can-outline"
|
||||||
dense
|
dense
|
||||||
flat
|
flat
|
||||||
|
|
@ -290,8 +290,8 @@ watch(
|
||||||
<AddButton
|
<AddButton
|
||||||
v-if="!readonly"
|
v-if="!readonly"
|
||||||
icon-only
|
icon-only
|
||||||
id="btn-add-work-product"
|
:id="`btn-add-work-product-${workIndex}`"
|
||||||
for="btn-add-work-product"
|
:for="`btn-add-work-product-${workIndex}`"
|
||||||
@click.stop="$emit('addProduct')"
|
@click.stop="$emit('addProduct')"
|
||||||
/>
|
/>
|
||||||
</span>
|
</span>
|
||||||
|
|
@ -317,7 +317,7 @@ watch(
|
||||||
>
|
>
|
||||||
<q-btn
|
<q-btn
|
||||||
v-if="!readonly"
|
v-if="!readonly"
|
||||||
id="btn-product-up"
|
:id="`btn-product-up-${index}`"
|
||||||
icon="mdi-arrow-up"
|
icon="mdi-arrow-up"
|
||||||
dense
|
dense
|
||||||
flat
|
flat
|
||||||
|
|
@ -329,8 +329,8 @@ watch(
|
||||||
/>
|
/>
|
||||||
<q-btn
|
<q-btn
|
||||||
v-if="!readonly"
|
v-if="!readonly"
|
||||||
id="btn-product-down"
|
:id="`btn-product-down-${index}`"
|
||||||
for="btn-product-down"
|
:for="`btn-product-down-${index}`"
|
||||||
icon="mdi-arrow-down"
|
icon="mdi-arrow-down"
|
||||||
dense
|
dense
|
||||||
flat
|
flat
|
||||||
|
|
@ -482,8 +482,8 @@ watch(
|
||||||
<q-btn
|
<q-btn
|
||||||
v-if="!readonly"
|
v-if="!readonly"
|
||||||
class="q-ml-md"
|
class="q-ml-md"
|
||||||
id="btn-delete-work-product"
|
:id="`btn-delete-work-product-${index}`"
|
||||||
for="btn-delete-work-product"
|
:for="`btn-delete-work-product-${index}`"
|
||||||
icon="mdi-trash-can-outline"
|
icon="mdi-trash-can-outline"
|
||||||
padding="0"
|
padding="0"
|
||||||
dense
|
dense
|
||||||
|
|
@ -521,7 +521,7 @@ watch(
|
||||||
</span>
|
</span>
|
||||||
<q-btn
|
<q-btn
|
||||||
v-if="!readonly"
|
v-if="!readonly"
|
||||||
id="btn-add-work-product"
|
:id="`btn-add-work-product-${workIndex}`"
|
||||||
class="text-capitalize rounded"
|
class="text-capitalize rounded"
|
||||||
flat
|
flat
|
||||||
dense
|
dense
|
||||||
|
|
|
||||||
|
|
@ -127,7 +127,7 @@ defineEmits<{
|
||||||
|
|
||||||
<q-td class="text-right">
|
<q-td class="text-right">
|
||||||
<q-btn
|
<q-btn
|
||||||
:id="`btn-eye-${props.row.firstName}`"
|
:id="`btn-preview-${props.row.workName}`"
|
||||||
icon="mdi-play-box-outline"
|
icon="mdi-play-box-outline"
|
||||||
size="sm"
|
size="sm"
|
||||||
dense
|
dense
|
||||||
|
|
@ -137,7 +137,7 @@ defineEmits<{
|
||||||
/>
|
/>
|
||||||
|
|
||||||
<q-btn
|
<q-btn
|
||||||
:id="`btn-eye-${props.row.firstName}`"
|
:id="`btn-eye-${props.row.workName}`"
|
||||||
icon="mdi-eye-outline"
|
icon="mdi-eye-outline"
|
||||||
size="sm"
|
size="sm"
|
||||||
dense
|
dense
|
||||||
|
|
@ -147,7 +147,7 @@ defineEmits<{
|
||||||
/>
|
/>
|
||||||
|
|
||||||
<KebabAction
|
<KebabAction
|
||||||
:idName="`btn-kebab-${props.row.firstName}`"
|
:idName="`btn-kebab-${props.row.workName}`"
|
||||||
status="'ACTIVE'"
|
status="'ACTIVE'"
|
||||||
hide-toggle
|
hide-toggle
|
||||||
hide-delete
|
hide-delete
|
||||||
|
|
|
||||||
|
|
@ -46,6 +46,7 @@ type Options = { label: string; value: string };
|
||||||
(lhs: Options, rhs: Options) => lhs.value.localeCompare(rhs.value),
|
(lhs: Options, rhs: Options) => lhs.value.localeCompare(rhs.value),
|
||||||
)
|
)
|
||||||
"
|
"
|
||||||
|
:rules="[(val: string) => !!val || $t('form.error.required')]"
|
||||||
v-model="group"
|
v-model="group"
|
||||||
>
|
>
|
||||||
<template v-slot:option="{ scope, opt }">
|
<template v-slot:option="{ scope, opt }">
|
||||||
|
|
|
||||||
|
|
@ -29,6 +29,7 @@ const quotationId = defineModel<string>('quotationId', {
|
||||||
<section class="col-12 row q-col-gutter-sm">
|
<section class="col-12 row q-col-gutter-sm">
|
||||||
<SelectQuotation
|
<SelectQuotation
|
||||||
for="select-quotation"
|
for="select-quotation"
|
||||||
|
required
|
||||||
class="col"
|
class="col"
|
||||||
v-model:value="quotationId"
|
v-model:value="quotationId"
|
||||||
:label="$t('general.select', { msg: $t('quotation.title') })"
|
:label="$t('general.select', { msg: $t('quotation.title') })"
|
||||||
|
|
|
||||||
|
|
@ -29,6 +29,7 @@ const quotationId = defineModel<string>('quotationId', {
|
||||||
<section class="col-12 row q-col-gutter-sm">
|
<section class="col-12 row q-col-gutter-sm">
|
||||||
<SelectQuotation
|
<SelectQuotation
|
||||||
for="select-quotation"
|
for="select-quotation"
|
||||||
|
required
|
||||||
class="col"
|
class="col"
|
||||||
v-model:value="quotationId"
|
v-model:value="quotationId"
|
||||||
:label="$t('general.select', { msg: $t('quotation.title') })"
|
:label="$t('general.select', { msg: $t('quotation.title') })"
|
||||||
|
|
|
||||||
|
|
@ -18,7 +18,12 @@ function handleClick() {
|
||||||
</script>
|
</script>
|
||||||
<template>
|
<template>
|
||||||
<label class="switch" @click.stop="handleClick">
|
<label class="switch" @click.stop="handleClick">
|
||||||
<input type="checkbox" :disabled="twoWay || disable" v-model="model" />
|
<input
|
||||||
|
id="btn-toggle"
|
||||||
|
type="checkbox"
|
||||||
|
:disabled="twoWay || disable"
|
||||||
|
v-model="model"
|
||||||
|
/>
|
||||||
<div class="slider round" :class="{ disable: disable }"></div>
|
<div class="slider round" :class="{ disable: disable }"></div>
|
||||||
</label>
|
</label>
|
||||||
</template>
|
</template>
|
||||||
|
|
|
||||||
|
|
@ -365,6 +365,8 @@ watch(
|
||||||
{{ $t('flow.stepNo', { msg: (props.stepIndex || stepIndex) + 1 }) }}
|
{{ $t('flow.stepNo', { msg: (props.stepIndex || stepIndex) + 1 }) }}
|
||||||
<span class="app-text-muted">: {{ step.name }}</span>
|
<span class="app-text-muted">: {{ step.name }}</span>
|
||||||
<q-btn-dropdown
|
<q-btn-dropdown
|
||||||
|
for="select-step"
|
||||||
|
id="select-step"
|
||||||
unelevated
|
unelevated
|
||||||
no-icon-animation
|
no-icon-animation
|
||||||
size="sm"
|
size="sm"
|
||||||
|
|
@ -463,7 +465,7 @@ watch(
|
||||||
>
|
>
|
||||||
<div class="col-md col-12 row items-center">
|
<div class="col-md col-12 row items-center">
|
||||||
<q-btn
|
<q-btn
|
||||||
id="btn-move-up-product"
|
:id="`btn-move-up-product-${propIndex}`"
|
||||||
icon="mdi-arrow-up"
|
icon="mdi-arrow-up"
|
||||||
dense
|
dense
|
||||||
flat
|
flat
|
||||||
|
|
@ -479,7 +481,7 @@ watch(
|
||||||
"
|
"
|
||||||
/>
|
/>
|
||||||
<q-btn
|
<q-btn
|
||||||
id="btn-move-down-product"
|
:id="`btn-move-down-product-${propIndex}`"
|
||||||
icon="mdi-arrow-down"
|
icon="mdi-arrow-down"
|
||||||
dense
|
dense
|
||||||
flat
|
flat
|
||||||
|
|
@ -513,7 +515,7 @@ watch(
|
||||||
emit-value
|
emit-value
|
||||||
map-options
|
map-options
|
||||||
hide-bottom-space
|
hide-bottom-space
|
||||||
for="input-properties-name"
|
:for="`input-properties-name-${propIndex}`"
|
||||||
class="col-md col-12 q-mr-md"
|
class="col-md col-12 q-mr-md"
|
||||||
:class="{ 'q-my-sm': $q.screen.lt.md }"
|
:class="{ 'q-my-sm': $q.screen.lt.md }"
|
||||||
:label="$t('productService.service.propertiesName')"
|
:label="$t('productService.service.propertiesName')"
|
||||||
|
|
@ -552,8 +554,8 @@ watch(
|
||||||
emit-value
|
emit-value
|
||||||
map-options
|
map-options
|
||||||
hide-bottom-space
|
hide-bottom-space
|
||||||
for="input-properties-type"
|
:for="`input-properties-type-${propIndex}`"
|
||||||
id="input-properties-type"
|
:id="`input-properties-type-${propIndex}`"
|
||||||
:label="$t('general.type')"
|
:label="$t('general.type')"
|
||||||
option-value="value"
|
option-value="value"
|
||||||
@update:model-value="
|
@update:model-value="
|
||||||
|
|
|
||||||
|
|
@ -27,6 +27,7 @@ const props = withDefaults(
|
||||||
fillInput?: boolean;
|
fillInput?: boolean;
|
||||||
disable?: boolean;
|
disable?: boolean;
|
||||||
multiple?: boolean;
|
multiple?: boolean;
|
||||||
|
hideInput?: boolean;
|
||||||
|
|
||||||
rules?: ((value: string) => string | true)[];
|
rules?: ((value: string) => string | true)[];
|
||||||
}>(),
|
}>(),
|
||||||
|
|
@ -73,7 +74,7 @@ watch(
|
||||||
outlined
|
outlined
|
||||||
:clearable
|
:clearable
|
||||||
:disable
|
:disable
|
||||||
use-input
|
:use-input="!hideInput"
|
||||||
emit-value
|
emit-value
|
||||||
map-options
|
map-options
|
||||||
:multiple
|
:multiple
|
||||||
|
|
|
||||||
|
|
@ -75,6 +75,7 @@ function setDefaultValue() {
|
||||||
</script>
|
</script>
|
||||||
<template>
|
<template>
|
||||||
<SelectInput
|
<SelectInput
|
||||||
|
for="select-hq-id"
|
||||||
v-model="value"
|
v-model="value"
|
||||||
incremental
|
incremental
|
||||||
:label
|
:label
|
||||||
|
|
|
||||||
|
|
@ -72,6 +72,7 @@ onMounted(async () => {
|
||||||
v-model="value"
|
v-model="value"
|
||||||
option-value="id"
|
option-value="id"
|
||||||
incremental
|
incremental
|
||||||
|
for="select-customer"
|
||||||
:label
|
:label
|
||||||
:placeholder
|
:placeholder
|
||||||
:readonly
|
:readonly
|
||||||
|
|
@ -129,6 +130,8 @@ onMounted(async () => {
|
||||||
clickable
|
clickable
|
||||||
v-close-popup
|
v-close-popup
|
||||||
@click.stop="$emit('create')"
|
@click.stop="$emit('create')"
|
||||||
|
for="select-customer-add-new"
|
||||||
|
id="select-customer-add-new"
|
||||||
>
|
>
|
||||||
<q-item-section>
|
<q-item-section>
|
||||||
<span class="row items-center">
|
<span class="row items-center">
|
||||||
|
|
|
||||||
|
|
@ -73,6 +73,7 @@ function setDefaultValue() {
|
||||||
</script>
|
</script>
|
||||||
<template>
|
<template>
|
||||||
<SelectInput
|
<SelectInput
|
||||||
|
for="select-work-flow-template"
|
||||||
v-model="value"
|
v-model="value"
|
||||||
incremental
|
incremental
|
||||||
:label
|
:label
|
||||||
|
|
|
||||||
|
|
@ -108,6 +108,7 @@ function setDefaultValue() {
|
||||||
:label
|
:label
|
||||||
:placeholder
|
:placeholder
|
||||||
:readonly
|
:readonly
|
||||||
|
:hide-input="value !== ''"
|
||||||
:disable="disabled"
|
:disable="disabled"
|
||||||
:option="selectOptions"
|
:option="selectOptions"
|
||||||
:hide-selected="false"
|
:hide-selected="false"
|
||||||
|
|
|
||||||
|
|
@ -142,6 +142,7 @@ function selectedIndex(item: Employee) {
|
||||||
</template>
|
</template>
|
||||||
<template v-if="col.name === '#check'">
|
<template v-if="col.name === '#check'">
|
||||||
<q-checkbox
|
<q-checkbox
|
||||||
|
id="select-worker-all"
|
||||||
v-model="props.selected"
|
v-model="props.selected"
|
||||||
@update:model-value="(v) => handleUpdate()"
|
@update:model-value="(v) => handleUpdate()"
|
||||||
size="sm"
|
size="sm"
|
||||||
|
|
@ -193,7 +194,11 @@ function selectedIndex(item: Employee) {
|
||||||
!disabledWorkerId?.some((id) => id === props.row.id)
|
!disabledWorkerId?.some((id) => id === props.row.id)
|
||||||
"
|
"
|
||||||
>
|
>
|
||||||
<q-checkbox v-model="props.selected" size="sm" />
|
<q-checkbox
|
||||||
|
v-model="props.selected"
|
||||||
|
size="sm"
|
||||||
|
:id="`select-worker-${props.row.firstName}`"
|
||||||
|
/>
|
||||||
</template>
|
</template>
|
||||||
</q-td>
|
</q-td>
|
||||||
</q-tr>
|
</q-tr>
|
||||||
|
|
|
||||||
135
src/i18n/eng.ts
135
src/i18n/eng.ts
|
|
@ -147,6 +147,7 @@ export default {
|
||||||
ofPage: '{current} of {total}',
|
ofPage: '{current} of {total}',
|
||||||
included: 'Included',
|
included: 'Included',
|
||||||
notIncluded: 'Not Included',
|
notIncluded: 'Not Included',
|
||||||
|
dueDate: 'Due date',
|
||||||
},
|
},
|
||||||
|
|
||||||
menu: {
|
menu: {
|
||||||
|
|
@ -1057,65 +1058,102 @@ export default {
|
||||||
cancel: 'Cancel',
|
cancel: 'Cancel',
|
||||||
},
|
},
|
||||||
backend: {
|
backend: {
|
||||||
productGroupNotFound: 'Product group cannot be found.',
|
|
||||||
productGroupIsUsed: 'Product group is in used.',
|
|
||||||
productNotFound: 'Product cannot be found.',
|
|
||||||
productIsUsed: 'Product is in used.',
|
|
||||||
productTypeNotFound: 'Product type cannot be found.',
|
|
||||||
productGroupAssociatedBadReq: 'Product group associated cannot be found.',
|
productGroupAssociatedBadReq: 'Product group associated cannot be found.',
|
||||||
productTypeIsUsed: 'Product type is in used.',
|
|
||||||
productGroupBadReq: 'Product group cannot be found.',
|
productGroupBadReq: 'Product group cannot be found.',
|
||||||
serviceNotFound: 'Service cannot be found.',
|
|
||||||
someProductBadReq: 'Some product not found.',
|
someProductBadReq: 'Some product not found.',
|
||||||
serviceIsUsed: 'Service is in used.',
|
|
||||||
workNotFound: 'Work cannot be found.',
|
|
||||||
workIsUsed: 'Work is in used.',
|
|
||||||
branchContactNotFound: 'Branch contact cannot be found.',
|
|
||||||
branchBadReq: 'Branch cannot be found.',
|
branchBadReq: 'Branch cannot be found.',
|
||||||
branchNotFound: 'Branch cannot be found.',
|
|
||||||
cantMakeHQAndBranchSameTime:
|
|
||||||
'Cannot make this as headquaters and branch at the same time.',
|
|
||||||
branchIsUsed: 'Branch is in used.',
|
|
||||||
oneOrMoreUserBadReq: 'One or more user cannot be found.',
|
oneOrMoreUserBadReq: 'One or more user cannot be found.',
|
||||||
oneOrMoreBranchBadReq: 'One or more branch cannot be found.',
|
oneOrMoreBranchBadReq: 'One or more branch cannot be found.',
|
||||||
customerBranchNotFound: 'Customer branch cannot be found.',
|
employeeBadReq: 'Employee cannot be found.',
|
||||||
customerBranchIsUsed: 'Customer branch is in used.',
|
parentMenuBadReq: 'Parent menu not found.',
|
||||||
customerNotFound: 'Customer cannot be found.',
|
menuBadReq: 'Menu cannot be found.',
|
||||||
customerIsUsed: 'Customer is in used.',
|
|
||||||
oneOrMoreBranchMissing:
|
oneOrMoreBranchMissing:
|
||||||
'One or more branch cannot be delete and is missing.',
|
'One or more branch cannot be delete and is missing.',
|
||||||
employeeCheckupNotFound: 'Employee checkup cannot be found.',
|
cantMakeHQAndBranchSameTime:
|
||||||
provinceNotFound: 'Province cannot be found.',
|
'Cannot make this as headquaters and branch at the same time.',
|
||||||
employeeNotFound: 'Employee cannot be found.',
|
|
||||||
employeeBadReq: 'Employee cannot be found.',
|
|
||||||
employeeIsUsed: 'Employee is in used.',
|
|
||||||
someProvinceNotFound: 'Some province cannot be found.',
|
|
||||||
employeeOtherNotFound: 'Employee other info cannot be found.',
|
|
||||||
employeeWorkNotFound: 'Employee work cannot be found.',
|
|
||||||
parentMenuBadReq: 'Parent menu not found.',
|
|
||||||
menuNotFound: 'Menu cannot be found.',
|
|
||||||
menuBadReq: 'Menu cannot be found.',
|
|
||||||
menuComponentNotFound: 'Menu component cannot be found.',
|
|
||||||
roleMenuNotFound: 'Role menu cannot be found.',
|
|
||||||
userNotFound: 'User cannot be found.',
|
|
||||||
userIsUsed: 'User is in used.',
|
|
||||||
unknowHowToVerify: 'Unknown how to verify identity.',
|
unknowHowToVerify: 'Unknown how to verify identity.',
|
||||||
noPermission:
|
noPermission:
|
||||||
'You do not have permission to access or perform with this resource.',
|
'You do not have permission to access or perform with this resource.',
|
||||||
noPermissionToAccess:
|
noPermissionToAccess:
|
||||||
'You do not have permission to access or perform with this resource.',
|
'You do not have permission to access or perform with this resource.',
|
||||||
|
|
||||||
relationProvinceNotFound: 'Province cannot be found.',
|
relationProvinceNotFound: 'Province cannot be found.',
|
||||||
relationDistrictNotFound: 'District cannot be found.',
|
relationDistrictNotFound: 'District cannot be found.',
|
||||||
relationSubDistrictNotFound: 'Sub-district cannot be found.',
|
relationSubDistrictNotFound: 'Sub-district cannot be found.',
|
||||||
relationHQNotFound: 'Headquarters cannot be found.',
|
relationHQNotFound: 'Headquarters cannot be found.',
|
||||||
|
relationBranchNotFound: 'Branch cannot be found.',
|
||||||
relationCustomerNotFound: 'Customer cannot be found.',
|
relationCustomerNotFound: 'Customer cannot be found.',
|
||||||
relationCustomerBranchNotFound: 'Customer Branch cannot be found.',
|
relationCustomerBranchNotFound: 'Customer Branch cannot be found.',
|
||||||
|
relationUserNotFound: 'User cannot be found.',
|
||||||
|
relationProductGroupNotFound: 'Product group cannot be found.',
|
||||||
|
relationProductTypeNotFound: 'Product type cannot be found.',
|
||||||
|
relationServiceNotFound: 'Service cannot be found.',
|
||||||
|
relationProductNotFound: 'Product cannot be found.',
|
||||||
|
relationQuotationNotFound: 'Quotation cannot be found.',
|
||||||
|
relationWorkerNotFound: 'Worker cannot be found.',
|
||||||
|
relationWorkNotFound: 'Work cannot be found.',
|
||||||
|
|
||||||
|
dataNotFound: 'Data not found.',
|
||||||
|
employmentOfficeNotFound: 'Employment office not found.',
|
||||||
|
branchNotFound: 'Branch cannot be found.',
|
||||||
|
productGroupNotFound: 'Product group cannot be found.',
|
||||||
|
productNotFound: 'Product cannot be found.',
|
||||||
|
productTypeNotFound: 'Product type cannot be found.',
|
||||||
|
serviceNotFound: 'Service cannot be found.',
|
||||||
|
workNotFound: 'Work cannot be found.',
|
||||||
|
branchContactNotFound: 'Branch contact cannot be found.',
|
||||||
|
customerBranchNotFound: 'Customer branch cannot be found.',
|
||||||
|
customerNotFound: 'Customer cannot be found.',
|
||||||
|
employeeCheckupNotFound: 'Employee checkup cannot be found.',
|
||||||
|
provinceNotFound: 'Province cannot be found.',
|
||||||
|
employeeNotFound: 'Employee cannot be found.',
|
||||||
|
someProvinceNotFound: 'Some province cannot be found.',
|
||||||
|
employeeOtherNotFound: 'Employee other info cannot be found.',
|
||||||
|
employeeWorkNotFound: 'Employee work cannot be found.',
|
||||||
|
menuNotFound: 'Menu cannot be found.',
|
||||||
|
menuComponentNotFound: 'Menu component cannot be found.',
|
||||||
|
roleMenuNotFound: 'Role menu cannot be found.',
|
||||||
|
userNotFound: 'User cannot be found.',
|
||||||
|
flowTemplateNotFound: 'Workflow template cannot be found.',
|
||||||
|
taskOrderNotFound: 'Task order cannot be found.',
|
||||||
|
quotationNotFound: 'Quotation cannot be found.',
|
||||||
|
citizenNotFound: 'Citizen cannot be found.',
|
||||||
|
employeeOtherInfoNotFound: 'Employee other info cannot be found.',
|
||||||
|
passportNotFound: 'Passport cannot be found.',
|
||||||
|
visaNotFound: 'Visa cannot be found.',
|
||||||
|
workflowNotFound: 'Workflow cannot be found.',
|
||||||
|
institutionNotFound: 'Agencies cannot be found.',
|
||||||
|
invoiceNotFound: 'Invoice cannot be found.',
|
||||||
|
receiptNotFound: 'Receipt cannot be found.',
|
||||||
|
paymentNotFound: 'Payment cannot be found.',
|
||||||
|
requestDataNotFound: 'Request data cannot be found.',
|
||||||
|
requestWorkNotFound: 'Request work cannot be found.',
|
||||||
|
taskListNotFound: 'Task list cannot be found.',
|
||||||
|
creditNoteNotFound: 'Credit note cannot be found.',
|
||||||
|
debitNoteNotFound: 'Debit note cannot be found.',
|
||||||
|
|
||||||
|
productGroupIsUsed: 'Product group is in used.',
|
||||||
|
productIsUsed: 'Product is in used.',
|
||||||
|
productTypeIsUsed: 'Product type is in used.',
|
||||||
|
serviceIsUsed: 'Service is in used.',
|
||||||
|
workIsUsed: 'Work is in used.',
|
||||||
|
branchIsUsed: 'Branch is in used.',
|
||||||
|
customerBranchIsUsed: 'Customer branch is in used.',
|
||||||
|
customerIsUsed: 'Customer is in used.',
|
||||||
|
employeeIsUsed: 'Employee is in used.',
|
||||||
|
userIsUsed: 'User is in used.',
|
||||||
|
institutionIsUsed: 'Agencies is in used.',
|
||||||
|
quotationIsUsed: 'Quotation is in used.',
|
||||||
|
debitNoteIsUsed: 'Debit note is in used.',
|
||||||
|
|
||||||
sameBranchCodeExists: 'This Head Office Abbreviation is already in use.',
|
sameBranchCodeExists: 'This Head Office Abbreviation is already in use.',
|
||||||
productNameExists:
|
productNameExists:
|
||||||
'Product with the same name already exists. If you want to create with this name please select another code.',
|
'Product with the same name already exists. If you want to create with this name please select another code.',
|
||||||
|
userExists: 'User already exits.',
|
||||||
|
sameNameExists: 'Same name exists.',
|
||||||
|
|
||||||
validateError: 'Validate Error',
|
validateError: 'Validate Error',
|
||||||
codeMisMatch: 'Code Mismatch',
|
codeMisMatch: 'Code Mismatch',
|
||||||
userExists: 'User already exits.',
|
|
||||||
crossCompanyNotPermit: 'Cannot move between different headoffice',
|
crossCompanyNotPermit: 'Cannot move between different headoffice',
|
||||||
errorOccure:
|
errorOccure:
|
||||||
'An error has occurred, causing the system to be unable to function. Please try again later.',
|
'An error has occurred, causing the system to be unable to function. Please try again later.',
|
||||||
|
|
@ -1123,11 +1161,20 @@ export default {
|
||||||
authFailed: 'Authentication Failed. Please try again later. ',
|
authFailed: 'Authentication Failed. Please try again later. ',
|
||||||
installmentsValidateFailed:
|
installmentsValidateFailed:
|
||||||
'Validation failed. Each installment must include at least one product. Please review and update the installments accordingly.',
|
'Validation failed. Each installment must include at least one product. Please review and update the installments accordingly.',
|
||||||
flowTemplateNotFound: 'Workflow template cannot be found.',
|
|
||||||
taskOrderNotFound: 'Task order cannot be found.',
|
|
||||||
quotationNotFound: 'Quotation cannot be found.',
|
|
||||||
sameNameExists: 'Same name exists.',
|
|
||||||
requestWorkMustReady: 'Request work must ready.',
|
requestWorkMustReady: 'Request work must ready.',
|
||||||
|
|
||||||
|
notValidImage: 'Not a valid image.',
|
||||||
|
minimumBranchNotMet: 'Require at least one branch for a user.',
|
||||||
|
requireOneMinBranch: 'Require at least one branch as headoffice.',
|
||||||
|
reqMinAffilatedBranch:
|
||||||
|
'You must be affilated with at least one branch or specify branch to be registered (System permission required).',
|
||||||
|
paymentNotSuccess: 'Payment not success.',
|
||||||
|
flowAccountError: 'FlowAccount error.',
|
||||||
|
InvoiceReceiptIssueFailed: 'Failed to issue invoice/receipt document.',
|
||||||
|
QuotationWorkerExceed: 'Worker exceed current quotation max worker.',
|
||||||
|
taskListNotPending: 'One or more task is not pending.',
|
||||||
|
reqNotMet: 'Not Match',
|
||||||
|
systemError: 'A system error occurred.',
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
|
||||||
|
|
@ -1260,11 +1307,11 @@ export default {
|
||||||
},
|
},
|
||||||
|
|
||||||
stats: {
|
stats: {
|
||||||
Pending: 'Debit Note',
|
Issued: 'Debit Note',
|
||||||
Expire: 'Expired',
|
Expired: 'Expired',
|
||||||
Payment: 'Payment',
|
PaymentPending: 'Payment',
|
||||||
Receipt: 'Receipt',
|
PaymentSuccess: 'Receipt',
|
||||||
Succeed: 'Completed',
|
ProcessComplete: 'Completed',
|
||||||
},
|
},
|
||||||
|
|
||||||
viewMode: {
|
viewMode: {
|
||||||
|
|
|
||||||
134
src/i18n/tha.ts
134
src/i18n/tha.ts
|
|
@ -149,6 +149,7 @@ export default {
|
||||||
ofPage: '{current} จาก {total}',
|
ofPage: '{current} จาก {total}',
|
||||||
included: 'รวม',
|
included: 'รวม',
|
||||||
notIncluded: 'ไม่รวม',
|
notIncluded: 'ไม่รวม',
|
||||||
|
dueDate: 'วันครบกำหนด',
|
||||||
},
|
},
|
||||||
|
|
||||||
menu: {
|
menu: {
|
||||||
|
|
@ -712,7 +713,7 @@ export default {
|
||||||
product: {
|
product: {
|
||||||
title: 'สินค้าและบริการ',
|
title: 'สินค้าและบริการ',
|
||||||
code: 'รหัสสินค้าและบริการ',
|
code: 'รหัสสินค้าและบริการ',
|
||||||
name: 'ชื่อกลุ่มสินค้าและบริการ',
|
name: 'ชื่อสินค้าและบริการ',
|
||||||
registeredBranch: 'สาขาที่ลงทะเบียน',
|
registeredBranch: 'สาขาที่ลงทะเบียน',
|
||||||
noProduct: 'ยังไม่มีสินค้าและบริการ',
|
noProduct: 'ยังไม่มีสินค้าและบริการ',
|
||||||
allProduct: 'สินค้าและบริการทั้งหมด',
|
allProduct: 'สินค้าและบริการทั้งหมด',
|
||||||
|
|
@ -1041,62 +1042,99 @@ export default {
|
||||||
cancel: 'ยกเลิก',
|
cancel: 'ยกเลิก',
|
||||||
},
|
},
|
||||||
backend: {
|
backend: {
|
||||||
productGroupNotFound: 'ไม่พบกลุ่มสินค้าและบริการ',
|
|
||||||
productGroupIsUsed: 'กลุ่มสินค้าและบริการที่ใช้งานอยู่',
|
|
||||||
productNotFound: 'ไม่พบสินค้าและบริการ',
|
|
||||||
productIsUsed: 'สินค้าและบริการใช้งานอยู่',
|
|
||||||
productTypeNotFound: 'ไม่พบประเภทสินค้าและบริการ',
|
|
||||||
productGroupAssociatedBadReq: 'ไม่พบกลุ่มสินค้าและบริการที่เกี่ยวข้อง',
|
productGroupAssociatedBadReq: 'ไม่พบกลุ่มสินค้าและบริการที่เกี่ยวข้อง',
|
||||||
productTypeIsUsed: 'ประเภทสินค้าและบริการใช้งานอยู่',
|
|
||||||
productGroupBadReq: 'ไม่พบกลุ่มสินค้าและบริการ',
|
productGroupBadReq: 'ไม่พบกลุ่มสินค้าและบริการ',
|
||||||
serviceNotFound: 'ไม่พบบริการ',
|
|
||||||
someProductBadReq: 'ไม่พบสินค้าและบริการบางส่วน',
|
someProductBadReq: 'ไม่พบสินค้าและบริการบางส่วน',
|
||||||
serviceIsUsed: 'บริการใช้งานอยู่',
|
|
||||||
workNotFound: 'ไม่พบงาน',
|
|
||||||
workIsUsed: 'งานที่ใช้งานอยู่',
|
|
||||||
branchContactNotFound: 'ไม่พบผู้ติดต่อสาขา',
|
|
||||||
branchBadReq: 'ไม่พบสาขา',
|
branchBadReq: 'ไม่พบสาขา',
|
||||||
branchNotFound: 'ไม่พบสาขา',
|
|
||||||
cantMakeHQAndBranchSameTime:
|
|
||||||
'ไม่สามารถทำให้เป็นสำนักงานใหญ่และสาขาพร้อมกันได้',
|
|
||||||
branchIsUsed: 'สาขาใช้งานอยู่',
|
|
||||||
oneOrMoreUserBadReq: 'ไม่พบผู้ใช้หนึ่งคนหรือมากกว่า',
|
oneOrMoreUserBadReq: 'ไม่พบผู้ใช้หนึ่งคนหรือมากกว่า',
|
||||||
oneOrMoreBranchBadReq: 'ไม่พบสาขาหนึ่งสาขาหรือมากกว่า',
|
oneOrMoreBranchBadReq: 'ไม่พบสาขาหนึ่งสาขาหรือมากกว่า',
|
||||||
customerBranchNotFound: 'ไม่พบสาขาลูกค้า',
|
|
||||||
customerBranchIsUsed: 'สาขาลูกค้าที่ใช้งานอยู่',
|
|
||||||
customerNotFound: 'ไม่พบลูกค้า',
|
|
||||||
customerIsUsed: 'ลูกค้าใช้งานอยู่',
|
|
||||||
oneOrMoreBranchMissing: 'ไม่สามารถลบสาขาหนึ่งหรือมากกว่าได้และสูญหาย',
|
|
||||||
employeeCheckupNotFound: 'ไม่พบการตรวจสอบพนักงาน',
|
|
||||||
provinceNotFound: 'ไม่พบจังหวัด',
|
|
||||||
employeeNotFound: 'ไม่พบพนักงาน',
|
|
||||||
employeeBadReq: 'ไม่พบพนักงาน',
|
employeeBadReq: 'ไม่พบพนักงาน',
|
||||||
employeeIsUsed: 'พนักงานใช้งานอยู่',
|
|
||||||
someProvinceNotFound: 'ไม่พบจังหวัดบางส่วน',
|
|
||||||
employeeOtherNotFound: 'ไม่พบข้อมูลอื่นของพนักงาน',
|
|
||||||
employeeWorkNotFound: 'ไม่พบงานของพนักงาน',
|
|
||||||
parentMenuBadReq: 'ไม่พบเมนูหลัก',
|
parentMenuBadReq: 'ไม่พบเมนูหลัก',
|
||||||
menuNotFound: 'ไม่พบเมนู',
|
|
||||||
menuBadReq: 'ไม่พบเมนู',
|
menuBadReq: 'ไม่พบเมนู',
|
||||||
menuComponentNotFound: 'ไม่พบส่วนประกอบเมนู',
|
oneOrMoreBranchMissing: 'ไม่สามารถลบสาขาหนึ่งหรือมากกว่าได้และสูญหาย',
|
||||||
roleMenuNotFound: 'ไม่พบเมนูบทบาท',
|
cantMakeHQAndBranchSameTime:
|
||||||
userNotFound: 'ไม่พบผู้ใช้',
|
'ไม่สามารถทำให้เป็นสำนักงานใหญ่และสาขาพร้อมกันได้',
|
||||||
userIsUsed: 'ผู้ใช้ใช้งานอยู่',
|
|
||||||
unknowHowToVerify: 'ไม่ทราบวิธียืนยันตัวตน',
|
unknowHowToVerify: 'ไม่ทราบวิธียืนยันตัวตน',
|
||||||
noPermission: 'คุณไม่มีสิทธิในการเข้าถึงหรือดำเนินการใดๆ กับข้อมูลนี้',
|
noPermission: 'คุณไม่มีสิทธิในการเข้าถึงหรือดำเนินการใดๆ กับข้อมูลนี้',
|
||||||
noPermissionToAccess: 'คุณไม่มีสิทธิในการเข้าถึงข้อมูลนี้',
|
noPermissionToAccess: 'คุณไม่มีสิทธิในการเข้าถึงข้อมูลนี้',
|
||||||
|
|
||||||
relationProvinceNotFound: 'ไม่พบจังหวัด',
|
relationProvinceNotFound: 'ไม่พบจังหวัด',
|
||||||
relationDistrictNotFound: 'ไม่พบอำเภอ',
|
relationDistrictNotFound: 'ไม่พบอำเภอ',
|
||||||
relationSubDistrictNotFound: 'ไม่พบตำบล',
|
relationSubDistrictNotFound: 'ไม่พบตำบล',
|
||||||
relationHQNotFound: 'ไม่พบสำนักงานใหญ่',
|
relationHQNotFound: 'ไม่พบสำนักงานใหญ่',
|
||||||
|
relationBranchNotFound: 'ไม่พบสาขา',
|
||||||
relationCustomerNotFound: 'ไม่พบลูกค้า',
|
relationCustomerNotFound: 'ไม่พบลูกค้า',
|
||||||
relationCustomerBranchNotFound: 'ไม่พบสาขาลูกค้า',
|
relationCustomerBranchNotFound: 'ไม่พบสาขาลูกค้า',
|
||||||
|
relationUserNotFound: 'ไม่พบผู้ใช้',
|
||||||
|
relationProductGroupNotFound: 'ไม่พบกลุ่มสินค้า',
|
||||||
|
relationProductTypeNotFound: 'ไม่พบประเภทสินค้า',
|
||||||
|
relationServiceNotFound: 'ไม่พบบริการ',
|
||||||
|
relationProductNotFound: 'ไม่พบสินค้า',
|
||||||
|
relationQuotationNotFound: 'ไม่พบใบเสนอราคา',
|
||||||
|
relationWorkerNotFound: 'ไม่พบแรงงาน',
|
||||||
|
relationWorkNotFound: 'ไม่พบงาน',
|
||||||
|
|
||||||
|
dataNotFound: 'ไม่พบข้อมูล',
|
||||||
|
employmentOfficeNotFound: 'ไม่พบสำนักงานจัดหางาน',
|
||||||
|
branchNotFound: 'ไม่พบสาขา',
|
||||||
|
productGroupNotFound: 'ไม่พบกลุ่มสินค้าและบริการ',
|
||||||
|
productNotFound: 'ไม่พบสินค้าและบริการ',
|
||||||
|
productTypeNotFound: 'ไม่พบประเภทสินค้าและบริการ',
|
||||||
|
serviceNotFound: 'ไม่พบบริการ',
|
||||||
|
workNotFound: 'ไม่พบงาน',
|
||||||
|
branchContactNotFound: 'ไม่พบผู้ติดต่อสาขา',
|
||||||
|
customerBranchNotFound: 'ไม่พบสาขาลูกค้า',
|
||||||
|
customerNotFound: 'ไม่พบลูกค้า',
|
||||||
|
employeeCheckupNotFound: 'ไม่พบการตรวจสอบพนักงาน',
|
||||||
|
provinceNotFound: 'ไม่พบจังหวัด',
|
||||||
|
employeeNotFound: 'ไม่พบพนักงาน',
|
||||||
|
someProvinceNotFound: 'ไม่พบจังหวัดบางส่วน',
|
||||||
|
employeeOtherNotFound: 'ไม่พบข้อมูลอื่นของพนักงาน',
|
||||||
|
employeeWorkNotFound: 'ไม่พบงานของพนักงาน',
|
||||||
|
menuNotFound: 'ไม่พบเมนู',
|
||||||
|
menuComponentNotFound: 'ไม่พบส่วนประกอบเมนู',
|
||||||
|
roleMenuNotFound: 'ไม่พบเมนูสิทธิ์',
|
||||||
|
userNotFound: 'ไม่พบผู้ใช้',
|
||||||
|
flowTemplateNotFound: 'ไม่พบขั้นตอนการทำงาน',
|
||||||
|
taskOrderNotFound: 'ไม่พบใบสั่งงาน',
|
||||||
|
quotationNotFound: 'ไม่พบใบเสนอราคา',
|
||||||
|
citizenNotFound: 'ไม่พบข้อมูลพลเมือง',
|
||||||
|
employeeOtherInfoNotFound: 'ไม่พบข้อมูลอื่น ๆ ของพนักงาน',
|
||||||
|
passportNotFound: 'ไม่พบหนังสือเดินทาง',
|
||||||
|
visaNotFound: 'ไม่พบวีซ่า',
|
||||||
|
workflowNotFound: 'ไม่พบขั้นตอนการทำงาน',
|
||||||
|
institutionNotFound: 'ไม่พบหน่วยงาน',
|
||||||
|
invoiceNotFound: 'ไม่พบใบแจ้งหนี้',
|
||||||
|
receiptNotFound: 'ไม่พบใบเสร็จรับเงิน',
|
||||||
|
paymentNotFound: 'ไม่พบการชำระเงิน',
|
||||||
|
requestDataNotFound: 'ไม่พบใบรายการคำขอ',
|
||||||
|
requestWorkNotFound: 'ไม่พบรายการคำขอ',
|
||||||
|
taskListNotFound: 'ไม่พบใบสั่งงาน',
|
||||||
|
creditNoteNotFound: 'ไม่พบใบลดหนี้',
|
||||||
|
debitNoteNotFound: 'ไม่พบใบเพิ่มหนี้',
|
||||||
|
|
||||||
|
productGroupIsUsed: 'กลุ่มสินค้าและบริการที่ใช้งานอยู่',
|
||||||
|
productIsUsed: 'สินค้าและบริการใช้งานอยู่',
|
||||||
|
productTypeIsUsed: 'ประเภทสินค้าและบริการใช้งานอยู่',
|
||||||
|
serviceIsUsed: 'บริการใช้งานอยู่',
|
||||||
|
workIsUsed: 'งานที่ใช้งานอยู่',
|
||||||
|
branchIsUsed: 'สาขาใช้งานอยู่',
|
||||||
|
customerBranchIsUsed: 'สาขาลูกค้าที่ใช้งานอยู่',
|
||||||
|
customerIsUsed: 'ลูกค้าใช้งานอยู่',
|
||||||
|
employeeIsUsed: 'พนักงานใช้งานอยู่',
|
||||||
|
userIsUsed: 'ผู้ใช้ใช้งานอยู่',
|
||||||
|
institutionIsUsed: 'หน่วยงานใช้งานอยู่.',
|
||||||
|
quotationIsUsed: 'ใบเสนอราคาใช้งานอยู่.',
|
||||||
|
debitNoteIsUsed: 'ใบเพิ่มหนี้ใช้งานอยู่.',
|
||||||
|
|
||||||
sameBranchCodeExists: 'ตัวย่อสำนักงานใหญ่นี้ถูกใช้แล้ว',
|
sameBranchCodeExists: 'ตัวย่อสำนักงานใหญ่นี้ถูกใช้แล้ว',
|
||||||
productNameExists:
|
productNameExists:
|
||||||
'สินค้าที่มีชื่อเดียวกันมีในระบบแล้ว หากคุณต้องการสร้างด้วยชื่อนี้โปรดเลือกรหัสอื่น',
|
'สินค้าที่มีชื่อเดียวกันมีในระบบแล้ว หากคุณต้องการสร้างด้วยชื่อนี้โปรดเลือกรหัสอื่น',
|
||||||
|
userExists: 'ชื่อผู้ใช้นี้มีอยู่ในระบบอยู่แล้ว',
|
||||||
|
sameNameExists: 'ชื่อนี้ถูกใช้ไปแล้ว',
|
||||||
|
|
||||||
validateError: 'เกิดข้อผิดพลาดจากการตรวจสอบ',
|
validateError: 'เกิดข้อผิดพลาดจากการตรวจสอบ',
|
||||||
codeMisMatch: 'รหัสไม่ตรงกัน',
|
codeMisMatch: 'รหัสไม่ตรงกัน',
|
||||||
userExists: 'ชื่อผู้ใช้นี้มีอยู่ในระบบอยู่แล้ว',
|
|
||||||
crossCompanyNotPermit: 'ไม่สามารถดำเนินการระหว่างสำนักงานใหญ่อื่นได้',
|
crossCompanyNotPermit: 'ไม่สามารถดำเนินการระหว่างสำนักงานใหญ่อื่นได้',
|
||||||
errorOccure:
|
errorOccure:
|
||||||
'เกิดข้อผิดพลาดทำให้ระบบไม่สามารถทำงานได้ กรุณาลองใหม่ในภายหลัง',
|
'เกิดข้อผิดพลาดทำให้ระบบไม่สามารถทำงานได้ กรุณาลองใหม่ในภายหลัง',
|
||||||
|
|
@ -1104,11 +1142,21 @@ export default {
|
||||||
authFailed: 'การยืนยันตัวตนล้มเหลว กรุณาลองใหม่ในภายหลัง',
|
authFailed: 'การยืนยันตัวตนล้มเหลว กรุณาลองใหม่ในภายหลัง',
|
||||||
installmentsValidateFailed:
|
installmentsValidateFailed:
|
||||||
'ข้อมูลงวดไม่ถูกต้อง กรุณาตรวจสอบและยืนยันว่าแต่ละงวดมีสินค้าอย่างน้อยหนึ่งรายการ',
|
'ข้อมูลงวดไม่ถูกต้อง กรุณาตรวจสอบและยืนยันว่าแต่ละงวดมีสินค้าอย่างน้อยหนึ่งรายการ',
|
||||||
flowTemplateNotFound: 'ไม่พบขั้นตอนการทำงาน',
|
|
||||||
taskOrderNotFound: 'ไม่พบใบสั่งงาน',
|
|
||||||
quotationNotFound: 'ไม่พบใบเสนอราคา',
|
|
||||||
sameNameExists: 'ชื่อนี้ถูกใช้ไปแล้ว',
|
|
||||||
requestWorkMustReady: 'ใบรายการคำขอต้องพร้อมดำเนินการ',
|
requestWorkMustReady: 'ใบรายการคำขอต้องพร้อมดำเนินการ',
|
||||||
|
|
||||||
|
notValidImage: 'รูปภาพไม่ถูกต้อง',
|
||||||
|
minimumBranchNotMet: 'ต้องมีอย่างน้อยหนึ่งสาขาสำหรับผู้ใช้',
|
||||||
|
requireOneMinBranch: 'ต้องมีอย่างน้อยหนึ่งสาขาเป็นสำนักงานใหญ่',
|
||||||
|
reqMinAffilatedBranch:
|
||||||
|
'คุณต้องมีสาขาที่เกี่ยวข้องอย่างน้อยหนึ่งสาขา หรือระบุสาขาที่จะลงทะเบียน (ต้องมีสิทธิ์ระบบ)',
|
||||||
|
paymentNotSuccess: 'การชำระเงินไม่สำเร็จ',
|
||||||
|
flowAccountError: 'เกิดข้อผิดพลาดใน FlowAccount',
|
||||||
|
InvoiceReceiptIssueFailed: 'ไม่สามารถออกใบแจ้งหนี้/ใบเสร็จรับเงินได้',
|
||||||
|
QuotationWorkerExceed: 'จำนวนพนักงานเกินขีดจำกัดสูงสุดของใบเสนอราคา',
|
||||||
|
taskListNotPending:
|
||||||
|
'มีงานหนึ่งงานหรือมากกว่าที่ไม่อยู่ในสถานะรอดำเนินการ',
|
||||||
|
reqNotMet: 'ไม่ตรงกัน',
|
||||||
|
systemError: 'ระบบเกิดข้อผิดพลาด',
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
|
||||||
|
|
@ -1241,11 +1289,11 @@ export default {
|
||||||
},
|
},
|
||||||
|
|
||||||
stats: {
|
stats: {
|
||||||
Pending: 'ใบเพิ่มหนี้',
|
Issued: 'ใบเพิ่มหนี้',
|
||||||
Expire: 'พ้นกำหนด',
|
Expired: 'พ้นกำหนด',
|
||||||
Payment: 'ชำระเงิน',
|
PaymentPending: 'ชำระเงิน',
|
||||||
Receipt: 'ใบเสร็จรับเงิน',
|
PaymentSuccess: 'ใบเสร็จรับเงิน',
|
||||||
Succeed: 'เสร็จสิ้น',
|
ProcessComplete: 'เสร็จสิ้น',
|
||||||
},
|
},
|
||||||
|
|
||||||
viewMode: {
|
viewMode: {
|
||||||
|
|
|
||||||
|
|
@ -83,292 +83,283 @@ onMounted(async () => {
|
||||||
});
|
});
|
||||||
</script>
|
</script>
|
||||||
<template>
|
<template>
|
||||||
<div>
|
<q-btn
|
||||||
<q-btn
|
rounded
|
||||||
rounded
|
dense
|
||||||
dense
|
flat
|
||||||
flat
|
no-caps
|
||||||
no-caps
|
color="dark"
|
||||||
color="dark"
|
class="q-pa-none account-menu-down dropdown-menu"
|
||||||
class="q-pa-none account-menu-down dropdown-menu"
|
>
|
||||||
>
|
<div class="row items-center">
|
||||||
<div class="row items-center">
|
<div class="q-pa-none">
|
||||||
<div class="q-pa-none">
|
<q-avatar
|
||||||
<q-avatar
|
class="surface-1 bordered"
|
||||||
class="surface-1 bordered"
|
:size="$q.screen.lt.sm ? '30px' : '40px'"
|
||||||
:size="$q.screen.lt.sm ? '30px' : '40px'"
|
|
||||||
>
|
|
||||||
<q-img
|
|
||||||
:ratio="1"
|
|
||||||
class="text-center"
|
|
||||||
:src="userImage"
|
|
||||||
v-if="userImage"
|
|
||||||
>
|
|
||||||
<template #error>
|
|
||||||
<div
|
|
||||||
class="no-padding full-width full-height flex items-center justify-center"
|
|
||||||
style="
|
|
||||||
background: linear-gradient(
|
|
||||||
135deg,
|
|
||||||
rgba(43, 137, 223, 1) 0%,
|
|
||||||
rgba(230, 51, 81, 1) 100%
|
|
||||||
);
|
|
||||||
"
|
|
||||||
>
|
|
||||||
<q-img
|
|
||||||
v-if="gender"
|
|
||||||
:ratio="1"
|
|
||||||
:src="`/no-img-${gender === 'female' ? 'female' : 'man'}.png`"
|
|
||||||
></q-img>
|
|
||||||
<q-icon
|
|
||||||
v-else
|
|
||||||
name="mdi-account-outline"
|
|
||||||
color="white"
|
|
||||||
:size="$q.screen.lt.sm ? 'xs' : 'sm'"
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
</template>
|
|
||||||
</q-img>
|
|
||||||
<q-icon
|
|
||||||
v-else
|
|
||||||
name="mdi-account-outline"
|
|
||||||
:size="$q.screen.lt.sm ? 'xs' : 'sm'"
|
|
||||||
/>
|
|
||||||
</q-avatar>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div
|
|
||||||
class="text-left q-px-md"
|
|
||||||
v-if="$q.screen.gt.sm"
|
|
||||||
style="color: var(--foreground)"
|
|
||||||
>
|
>
|
||||||
<div class="text-caption column">
|
<q-img
|
||||||
<span
|
:ratio="1"
|
||||||
v-if="isLoggedIn()"
|
class="text-center"
|
||||||
class="text-weight-bold ellipsis"
|
:src="userImage"
|
||||||
style="max-width: 9vw"
|
v-if="userImage"
|
||||||
>
|
>
|
||||||
|
<template #error>
|
||||||
|
<div
|
||||||
|
class="no-padding full-width full-height flex items-center justify-center"
|
||||||
|
style="
|
||||||
|
background: linear-gradient(
|
||||||
|
135deg,
|
||||||
|
rgba(43, 137, 223, 1) 0%,
|
||||||
|
rgba(230, 51, 81, 1) 100%
|
||||||
|
);
|
||||||
|
"
|
||||||
|
>
|
||||||
|
<q-img
|
||||||
|
v-if="gender"
|
||||||
|
:ratio="1"
|
||||||
|
:src="`/no-img-${gender === 'female' ? 'female' : 'man'}.png`"
|
||||||
|
></q-img>
|
||||||
|
<q-icon
|
||||||
|
v-else
|
||||||
|
name="mdi-account-outline"
|
||||||
|
color="white"
|
||||||
|
:size="$q.screen.lt.sm ? 'xs' : 'sm'"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
</q-img>
|
||||||
|
<q-icon
|
||||||
|
v-else
|
||||||
|
name="mdi-account-outline"
|
||||||
|
:size="$q.screen.lt.sm ? 'xs' : 'sm'"
|
||||||
|
/>
|
||||||
|
</q-avatar>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div
|
||||||
|
class="text-left q-px-md"
|
||||||
|
v-if="$q.screen.gt.sm"
|
||||||
|
style="color: var(--foreground)"
|
||||||
|
>
|
||||||
|
<div class="text-caption column">
|
||||||
|
<span
|
||||||
|
v-if="isLoggedIn()"
|
||||||
|
class="text-weight-bold ellipsis"
|
||||||
|
style="max-width: 9vw"
|
||||||
|
>
|
||||||
|
{{ getName() }}
|
||||||
|
<q-tooltip>
|
||||||
{{ getName() }}
|
{{ getName() }}
|
||||||
<q-tooltip>
|
</q-tooltip>
|
||||||
{{ getName() }}
|
</span>
|
||||||
</q-tooltip>
|
<span
|
||||||
</span>
|
v-else
|
||||||
<span
|
class="text-weight-bold q-pb-xs ellipsis"
|
||||||
v-else
|
style="max-width: 9vw"
|
||||||
class="text-weight-bold q-pb-xs ellipsis"
|
>
|
||||||
style="max-width: 9vw"
|
{{ 'Guest' }}
|
||||||
>
|
<q-tooltip>
|
||||||
{{ 'Guest' }}
|
{{ 'Guest' }}
|
||||||
<q-tooltip>
|
</q-tooltip>
|
||||||
{{ 'Guest' }}
|
</span>
|
||||||
</q-tooltip>
|
|
||||||
</span>
|
|
||||||
|
|
||||||
<div style="font-size: 11px">
|
<div style="font-size: 11px">
|
||||||
{{ filterRole?.join(' | ') }}
|
{{ filterRole?.join(' | ') }}
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div v-if="$q.screen.gt.sm" class="text-right">
|
|
||||||
<q-icon name="mdi-chevron-down" />
|
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<q-menu :offset="[5, 10]" max-width="300px">
|
<div v-if="$q.screen.gt.sm" class="text-right">
|
||||||
<div
|
<q-icon name="mdi-chevron-down" />
|
||||||
no-padding
|
</div>
|
||||||
class="row justify-center bordered rounded"
|
</div>
|
||||||
style="overflow: hidden"
|
|
||||||
>
|
|
||||||
<div class="column col-12 items-center">
|
|
||||||
<div
|
|
||||||
class="full-width row justify-center"
|
|
||||||
style="position: relative"
|
|
||||||
>
|
|
||||||
<div
|
|
||||||
class="full-width account-cover"
|
|
||||||
:class="{ dark: $q.dark.isActive }"
|
|
||||||
></div>
|
|
||||||
<div class="avartar-border">
|
|
||||||
<q-avatar
|
|
||||||
id="changeAvatar"
|
|
||||||
size="72px"
|
|
||||||
class="surface-1 bordered"
|
|
||||||
:class="{ 'hover-profile': isLoggedIn() }"
|
|
||||||
@click="
|
|
||||||
() => {
|
|
||||||
isLoggedIn() ? inputFile.click() : '';
|
|
||||||
}
|
|
||||||
"
|
|
||||||
>
|
|
||||||
<q-img
|
|
||||||
:ratio="1"
|
|
||||||
class="text-center"
|
|
||||||
:src="userImage"
|
|
||||||
v-if="userImage"
|
|
||||||
>
|
|
||||||
<template #error>
|
|
||||||
<div
|
|
||||||
class="no-padding full-width full-height flex items-center justify-center"
|
|
||||||
style="
|
|
||||||
background: linear-gradient(
|
|
||||||
135deg,
|
|
||||||
rgba(43, 137, 223, 1) 0%,
|
|
||||||
rgba(230, 51, 81, 1) 100%
|
|
||||||
);
|
|
||||||
"
|
|
||||||
>
|
|
||||||
<q-img
|
|
||||||
v-if="gender"
|
|
||||||
:ratio="1"
|
|
||||||
:src="`/no-img-${gender === 'female' ? 'female' : 'man'}.png`"
|
|
||||||
></q-img>
|
|
||||||
<q-icon
|
|
||||||
v-else
|
|
||||||
name="mdi-account-outline"
|
|
||||||
color="white"
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
</template>
|
|
||||||
</q-img>
|
|
||||||
<q-icon name="mdi-account-outline" v-else />
|
|
||||||
</q-avatar>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
|
<q-menu :offset="[5, 10]" max-width="300px">
|
||||||
|
<div
|
||||||
|
no-padding
|
||||||
|
class="row justify-center bordered rounded"
|
||||||
|
style="overflow: hidden"
|
||||||
|
>
|
||||||
|
<div class="column col-12 items-center">
|
||||||
|
<div class="full-width row justify-center" style="position: relative">
|
||||||
<div
|
<div
|
||||||
class="text-subtitle2 q-mb-xs text-center full-width ellipsis q-px-md"
|
class="full-width account-cover"
|
||||||
style="margin-top: 58px"
|
:class="{ dark: $q.dark.isActive }"
|
||||||
>
|
></div>
|
||||||
|
<div class="avartar-border">
|
||||||
|
<q-avatar
|
||||||
|
id="changeAvatar"
|
||||||
|
size="72px"
|
||||||
|
class="surface-1 bordered"
|
||||||
|
:class="{ 'hover-profile': isLoggedIn() }"
|
||||||
|
@click="
|
||||||
|
() => {
|
||||||
|
isLoggedIn() ? inputFile.click() : '';
|
||||||
|
}
|
||||||
|
"
|
||||||
|
>
|
||||||
|
<q-img
|
||||||
|
:ratio="1"
|
||||||
|
class="text-center"
|
||||||
|
:src="userImage"
|
||||||
|
v-if="userImage"
|
||||||
|
>
|
||||||
|
<template #error>
|
||||||
|
<div
|
||||||
|
class="no-padding full-width full-height flex items-center justify-center"
|
||||||
|
style="
|
||||||
|
background: linear-gradient(
|
||||||
|
135deg,
|
||||||
|
rgba(43, 137, 223, 1) 0%,
|
||||||
|
rgba(230, 51, 81, 1) 100%
|
||||||
|
);
|
||||||
|
"
|
||||||
|
>
|
||||||
|
<q-img
|
||||||
|
v-if="gender"
|
||||||
|
:ratio="1"
|
||||||
|
:src="`/no-img-${gender === 'female' ? 'female' : 'man'}.png`"
|
||||||
|
></q-img>
|
||||||
|
<q-icon v-else name="mdi-account-outline" color="white" />
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
</q-img>
|
||||||
|
<q-icon name="mdi-account-outline" v-else />
|
||||||
|
</q-avatar>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div
|
||||||
|
class="text-subtitle2 q-mb-xs text-center full-width ellipsis q-px-md"
|
||||||
|
style="margin-top: 58px"
|
||||||
|
>
|
||||||
|
<span v-if="isLoggedIn()">
|
||||||
|
{{ getName() }}
|
||||||
|
</span>
|
||||||
|
<span v-else>{{ 'Guest' }}</span>
|
||||||
|
<q-tooltip>
|
||||||
<span v-if="isLoggedIn()">
|
<span v-if="isLoggedIn()">
|
||||||
{{ getName() }}
|
{{ getName() }}
|
||||||
</span>
|
</span>
|
||||||
<span v-else>{{ 'Guest' }}</span>
|
<span v-else>{{ 'Guest' }}</span>
|
||||||
<q-tooltip>
|
</q-tooltip>
|
||||||
<span v-if="isLoggedIn()">
|
|
||||||
{{ getName() }}
|
|
||||||
</span>
|
|
||||||
<span v-else>{{ 'Guest' }}</span>
|
|
||||||
</q-tooltip>
|
|
||||||
</div>
|
|
||||||
<div
|
|
||||||
class="badge q-px-sm q-mb-md text-caption"
|
|
||||||
:class="{ dark: $q.dark.isActive }"
|
|
||||||
>
|
|
||||||
{{ filterRole?.join(' | ') }}
|
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
|
<div
|
||||||
<div class="column col-12">
|
class="badge q-px-sm q-mb-md text-caption"
|
||||||
<q-separator />
|
:class="{ dark: $q.dark.isActive }"
|
||||||
<div class="column justify-center">
|
>
|
||||||
<q-list
|
{{ filterRole?.join(' | ') }}
|
||||||
:dense="true"
|
|
||||||
v-for="op in options"
|
|
||||||
:key="op.value"
|
|
||||||
:id="op.value"
|
|
||||||
>
|
|
||||||
<q-item
|
|
||||||
v-if="op.value !== 'mode'"
|
|
||||||
clickable
|
|
||||||
:disable="op.disabled"
|
|
||||||
:id="`btn-${op.value}`"
|
|
||||||
@click="$emit(op.value)"
|
|
||||||
>
|
|
||||||
<q-item-section avatar>
|
|
||||||
<q-icon :name="op.icon" :color="op.color" size="20px" />
|
|
||||||
</q-item-section>
|
|
||||||
<q-item-section class="q-py-sm">
|
|
||||||
{{ $t(op.label) }}
|
|
||||||
</q-item-section>
|
|
||||||
</q-item>
|
|
||||||
|
|
||||||
<q-separator v-if="op.value === 'mode'" />
|
|
||||||
<q-item
|
|
||||||
v-if="op.value === 'mode'"
|
|
||||||
clickable
|
|
||||||
:id="`btn-${op.value}`"
|
|
||||||
@click="$emit(op.value)"
|
|
||||||
>
|
|
||||||
<q-item-section avatar>
|
|
||||||
<q-icon :name="op.icon" :color="op.color" size="20px" />
|
|
||||||
</q-item-section>
|
|
||||||
<q-item-section class="q-py-sm">
|
|
||||||
<div class="row justify-between">
|
|
||||||
<span>
|
|
||||||
{{ $t(op.label) }}
|
|
||||||
</span>
|
|
||||||
<span class="app-text-muted-2">
|
|
||||||
{{
|
|
||||||
$t(
|
|
||||||
`general.${theme === Theme.Auto ? 'baseOnDevice' : theme}`,
|
|
||||||
)
|
|
||||||
}}
|
|
||||||
<q-icon name="mdi-chevron-right" />
|
|
||||||
</span>
|
|
||||||
</div>
|
|
||||||
</q-item-section>
|
|
||||||
|
|
||||||
<q-menu
|
|
||||||
class="bordered rounded"
|
|
||||||
anchor="top right"
|
|
||||||
self="top left"
|
|
||||||
max-width="200"
|
|
||||||
:offset="[10, 0]"
|
|
||||||
style="width: 160px"
|
|
||||||
:touch-position="$q.screen.lt.sm"
|
|
||||||
>
|
|
||||||
<div v-for="(mode, index) in themeMode" :key="index">
|
|
||||||
<q-item clickable @click="theme = setTheme(mode.value)">
|
|
||||||
<q-item-section>
|
|
||||||
<div class="row justify-between">
|
|
||||||
<span>
|
|
||||||
{{ $t(`general.${mode.label}`) }}
|
|
||||||
</span>
|
|
||||||
<q-icon
|
|
||||||
v-if="mode.value === theme"
|
|
||||||
name="mdi-check"
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
</q-item-section>
|
|
||||||
</q-item>
|
|
||||||
</div>
|
|
||||||
</q-menu>
|
|
||||||
</q-item>
|
|
||||||
</q-list>
|
|
||||||
</div>
|
|
||||||
<q-separator />
|
|
||||||
<q-btn
|
|
||||||
v-if="isLoggedIn()"
|
|
||||||
no-caps
|
|
||||||
dense
|
|
||||||
unelevated
|
|
||||||
class="q-ma-md app-text-negative"
|
|
||||||
:class="{ dark: $q.dark.isActive }"
|
|
||||||
:label="$t('general.logout')"
|
|
||||||
@click="$emit('logout')"
|
|
||||||
id="btn-logout"
|
|
||||||
style="background-color: hsla(var(--negative-bg) / 0.1)"
|
|
||||||
v-close-popup
|
|
||||||
/>
|
|
||||||
<q-btn
|
|
||||||
v-else
|
|
||||||
no-caps
|
|
||||||
dense
|
|
||||||
color="primary"
|
|
||||||
unelevated
|
|
||||||
class="q-ma-md app-text-negative"
|
|
||||||
:label="$t('general.login')"
|
|
||||||
@click="$emit('login')"
|
|
||||||
id="btn-login"
|
|
||||||
v-close-popup
|
|
||||||
/>
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</q-menu>
|
|
||||||
</q-btn>
|
<div class="column col-12">
|
||||||
</div>
|
<q-separator />
|
||||||
|
<div class="column justify-center">
|
||||||
|
<q-list
|
||||||
|
:dense="true"
|
||||||
|
v-for="op in options"
|
||||||
|
:key="op.value"
|
||||||
|
:id="op.value"
|
||||||
|
>
|
||||||
|
<q-item
|
||||||
|
v-if="op.value !== 'mode'"
|
||||||
|
clickable
|
||||||
|
:disable="op.disabled"
|
||||||
|
:id="`btn-${op.value}`"
|
||||||
|
@click="$emit(op.value)"
|
||||||
|
>
|
||||||
|
<q-item-section avatar>
|
||||||
|
<q-icon :name="op.icon" :color="op.color" size="20px" />
|
||||||
|
</q-item-section>
|
||||||
|
<q-item-section class="q-py-sm">
|
||||||
|
{{ $t(op.label) }}
|
||||||
|
</q-item-section>
|
||||||
|
</q-item>
|
||||||
|
|
||||||
|
<q-separator v-if="op.value === 'mode'" />
|
||||||
|
<q-item
|
||||||
|
v-if="op.value === 'mode'"
|
||||||
|
clickable
|
||||||
|
:id="`btn-${op.value}`"
|
||||||
|
@click="$emit(op.value)"
|
||||||
|
>
|
||||||
|
<q-item-section avatar>
|
||||||
|
<q-icon :name="op.icon" :color="op.color" size="20px" />
|
||||||
|
</q-item-section>
|
||||||
|
<q-item-section class="q-py-sm">
|
||||||
|
<div class="row justify-between">
|
||||||
|
<span>
|
||||||
|
{{ $t(op.label) }}
|
||||||
|
</span>
|
||||||
|
<span class="app-text-muted-2">
|
||||||
|
{{
|
||||||
|
$t(
|
||||||
|
`general.${theme === Theme.Auto ? 'baseOnDevice' : theme}`,
|
||||||
|
)
|
||||||
|
}}
|
||||||
|
<q-icon name="mdi-chevron-right" />
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
</q-item-section>
|
||||||
|
|
||||||
|
<q-menu
|
||||||
|
class="bordered rounded"
|
||||||
|
anchor="top right"
|
||||||
|
self="top left"
|
||||||
|
max-width="200"
|
||||||
|
:offset="[10, 0]"
|
||||||
|
style="width: 160px"
|
||||||
|
:touch-position="$q.screen.lt.sm"
|
||||||
|
>
|
||||||
|
<div v-for="(mode, index) in themeMode" :key="index">
|
||||||
|
<q-item clickable @click="theme = setTheme(mode.value)">
|
||||||
|
<q-item-section>
|
||||||
|
<div class="row justify-between">
|
||||||
|
<span>
|
||||||
|
{{ $t(`general.${mode.label}`) }}
|
||||||
|
</span>
|
||||||
|
<q-icon
|
||||||
|
v-if="mode.value === theme"
|
||||||
|
name="mdi-check"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
</q-item-section>
|
||||||
|
</q-item>
|
||||||
|
</div>
|
||||||
|
</q-menu>
|
||||||
|
</q-item>
|
||||||
|
</q-list>
|
||||||
|
</div>
|
||||||
|
<q-separator />
|
||||||
|
<q-btn
|
||||||
|
v-if="isLoggedIn()"
|
||||||
|
no-caps
|
||||||
|
dense
|
||||||
|
unelevated
|
||||||
|
class="q-ma-md app-text-negative"
|
||||||
|
:class="{ dark: $q.dark.isActive }"
|
||||||
|
:label="$t('general.logout')"
|
||||||
|
@click="$emit('logout')"
|
||||||
|
id="btn-logout"
|
||||||
|
style="background-color: hsla(var(--negative-bg) / 0.1)"
|
||||||
|
v-close-popup
|
||||||
|
/>
|
||||||
|
<q-btn
|
||||||
|
v-else
|
||||||
|
no-caps
|
||||||
|
dense
|
||||||
|
color="primary"
|
||||||
|
unelevated
|
||||||
|
class="q-ma-md app-text-negative"
|
||||||
|
:label="$t('general.login')"
|
||||||
|
@click="$emit('login')"
|
||||||
|
id="btn-login"
|
||||||
|
v-close-popup
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</q-menu>
|
||||||
|
</q-btn>
|
||||||
</template>
|
</template>
|
||||||
<style scoped lang="scss">
|
<style scoped lang="scss">
|
||||||
.account-menu-down {
|
.account-menu-down {
|
||||||
|
|
|
||||||
|
|
@ -2649,7 +2649,7 @@ const emptyCreateDialog = ref(false);
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: $t('general.uploadFile'),
|
name: $t('general.uploadFile'),
|
||||||
anchor: 'drawer-info-file-upload',
|
anchor: 'form-info-file-upload',
|
||||||
tab: 'personalInfo',
|
tab: 'personalInfo',
|
||||||
},
|
},
|
||||||
|
|
||||||
|
|
@ -2672,14 +2672,14 @@ const emptyCreateDialog = ref(false);
|
||||||
},
|
},
|
||||||
...(currentFromDataEmployee.employeePassport?.map((v, i) => ({
|
...(currentFromDataEmployee.employeePassport?.map((v, i) => ({
|
||||||
name: dateFormat(v.expireDate),
|
name: dateFormat(v.expireDate),
|
||||||
anchor: `drawer-employee-employeePassport-${i}`,
|
anchor: `form-employee-employeePassport-${i}`,
|
||||||
tab: 'passport',
|
tab: 'passport',
|
||||||
sub: true,
|
sub: true,
|
||||||
})) || []),
|
})) || []),
|
||||||
|
|
||||||
{
|
{
|
||||||
name: $t('customerEmployee.form.group.visa'),
|
name: $t('customerEmployee.form.group.visa'),
|
||||||
anchor: 'drawer-visa',
|
anchor: 'form-visa',
|
||||||
tab: 'visa',
|
tab: 'visa',
|
||||||
useBtn:
|
useBtn:
|
||||||
currentFromDataEmployee.employeeVisa?.filter((item) => {
|
currentFromDataEmployee.employeeVisa?.filter((item) => {
|
||||||
|
|
@ -2695,7 +2695,7 @@ const emptyCreateDialog = ref(false);
|
||||||
|
|
||||||
...(currentFromDataEmployee.employeeVisa?.map((v, i) => ({
|
...(currentFromDataEmployee.employeeVisa?.map((v, i) => ({
|
||||||
name: dateFormat(v.expireDate),
|
name: dateFormat(v.expireDate),
|
||||||
anchor: `drawer-employee-visa-${i}`,
|
anchor: `form-employee-visa-${i}`,
|
||||||
tab: 'visa',
|
tab: 'visa',
|
||||||
sub: true,
|
sub: true,
|
||||||
})) || []),
|
})) || []),
|
||||||
|
|
@ -2774,7 +2774,7 @@ const emptyCreateDialog = ref(false);
|
||||||
/>
|
/>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<template v-slot:btn-drawer-visa>
|
<template v-slot:btn-form-visa>
|
||||||
<q-btn
|
<q-btn
|
||||||
id="form-add-visa"
|
id="form-add-visa"
|
||||||
dense
|
dense
|
||||||
|
|
@ -2787,7 +2787,7 @@ const emptyCreateDialog = ref(false);
|
||||||
/>
|
/>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<template v-slot:btn-drawer-employee-checkup>
|
<template v-slot:btn-form-employee-checkup>
|
||||||
<q-btn
|
<q-btn
|
||||||
id="form-add-checkup"
|
id="form-add-checkup"
|
||||||
dense
|
dense
|
||||||
|
|
@ -2800,7 +2800,7 @@ const emptyCreateDialog = ref(false);
|
||||||
/>
|
/>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<template v-slot:btn-drawer-employee-work-history>
|
<template v-slot:btn-form-employee-work-history>
|
||||||
<q-btn
|
<q-btn
|
||||||
id="form-add-work-history"
|
id="form-add-work-history"
|
||||||
dense
|
dense
|
||||||
|
|
|
||||||
|
|
@ -101,6 +101,12 @@ const columns = [
|
||||||
|
|
||||||
function triggerDialog(type: 'add' | 'edit' | 'view') {
|
function triggerDialog(type: 'add' | 'edit' | 'view') {
|
||||||
if (type === 'add') {
|
if (type === 'add') {
|
||||||
|
registeredBranchId.value = '';
|
||||||
|
formDataWorkflow.value = {
|
||||||
|
status: 'CREATED',
|
||||||
|
name: '',
|
||||||
|
step: [],
|
||||||
|
};
|
||||||
pageState.addModal = true;
|
pageState.addModal = true;
|
||||||
pageState.isDrawerEdit = true;
|
pageState.isDrawerEdit = true;
|
||||||
}
|
}
|
||||||
|
|
@ -630,6 +636,7 @@ watch([() => pageState.inputSearch, workflowPageSize], () => {
|
||||||
<q-td style="width: 20%" class="text-right">
|
<q-td style="width: 20%" class="text-right">
|
||||||
<q-btn
|
<q-btn
|
||||||
icon="mdi-eye-outline"
|
icon="mdi-eye-outline"
|
||||||
|
:id="`btn-eye-${props.row.name}`"
|
||||||
size="sm"
|
size="sm"
|
||||||
dense
|
dense
|
||||||
round
|
round
|
||||||
|
|
@ -642,7 +649,7 @@ watch([() => pageState.inputSearch, workflowPageSize], () => {
|
||||||
"
|
"
|
||||||
/>
|
/>
|
||||||
<KebabAction
|
<KebabAction
|
||||||
:id-name="props.row.id"
|
:id-name="props.row.name"
|
||||||
:status="props.row.status"
|
:status="props.row.status"
|
||||||
@view="
|
@view="
|
||||||
() => {
|
() => {
|
||||||
|
|
|
||||||
|
|
@ -1262,6 +1262,11 @@ async function submitService(notClose = false) {
|
||||||
onCreateImageList.value,
|
onCreateImageList.value,
|
||||||
);
|
);
|
||||||
if (res) {
|
if (res) {
|
||||||
|
const group = productGroup.value?.find(
|
||||||
|
(g) => g.id === currentIdGroup.value,
|
||||||
|
);
|
||||||
|
if (group) group.status = 'ACTIVE';
|
||||||
|
|
||||||
allStat.value[1].count = allStat.value[1].count + 1;
|
allStat.value[1].count = allStat.value[1].count + 1;
|
||||||
stat.value[1].count = stat.value[1].count + 1;
|
stat.value[1].count = stat.value[1].count + 1;
|
||||||
} else {
|
} else {
|
||||||
|
|
@ -1306,6 +1311,11 @@ async function submitProduct(notClose = false) {
|
||||||
);
|
);
|
||||||
|
|
||||||
if (res) {
|
if (res) {
|
||||||
|
const group = productGroup.value?.find(
|
||||||
|
(g) => g.id === currentIdGroup.value,
|
||||||
|
);
|
||||||
|
if (group) group.status = 'ACTIVE';
|
||||||
|
|
||||||
allStat.value[2].count = allStat.value[2].count + 1;
|
allStat.value[2].count = allStat.value[2].count + 1;
|
||||||
stat.value[2].count = stat.value[2].count + 1;
|
stat.value[2].count = stat.value[2].count + 1;
|
||||||
} else {
|
} else {
|
||||||
|
|
@ -4337,6 +4347,7 @@ watch(
|
||||||
class="split-pay q-mx-sm"
|
class="split-pay q-mx-sm"
|
||||||
input-class="text-caption text-right"
|
input-class="text-caption text-right"
|
||||||
type="number"
|
type="number"
|
||||||
|
for="dialog-input-installments"
|
||||||
v-model="formService.installments"
|
v-model="formService.installments"
|
||||||
/>
|
/>
|
||||||
{{ $t('quotation.receiptDialog.installments') }}
|
{{ $t('quotation.receiptDialog.installments') }}
|
||||||
|
|
|
||||||
|
|
@ -12,6 +12,7 @@ import useMyBranch from 'stores/my-branch';
|
||||||
import { useQuotationForm } from './form';
|
import { useQuotationForm } from './form';
|
||||||
import { hslaColors } from './constants';
|
import { hslaColors } from './constants';
|
||||||
import { pageTabs, columnQuotation } from './constants';
|
import { pageTabs, columnQuotation } from './constants';
|
||||||
|
import { toCamelCase } from 'stores/utils';
|
||||||
|
|
||||||
// NOTE Import Types
|
// NOTE Import Types
|
||||||
import { CustomerBranchCreate, CustomerType } from 'stores/customer/types';
|
import { CustomerBranchCreate, CustomerType } from 'stores/customer/types';
|
||||||
|
|
@ -389,13 +390,7 @@ async function storeDataLocal(id: string) {
|
||||||
color: hsl(var(--info-bg));
|
color: hsl(var(--info-bg));
|
||||||
"
|
"
|
||||||
>
|
>
|
||||||
{{
|
{{ Object.values(quotationStats).reduce((a, c) => a + c, 0) }}
|
||||||
quotationStats[
|
|
||||||
pageState.currentTab === 'Invoice'
|
|
||||||
? 'paymentInProcess'
|
|
||||||
: (pageState.currentTab.toLowerCase() as keyof typeof quotationStats)
|
|
||||||
]
|
|
||||||
}}
|
|
||||||
</q-badge>
|
</q-badge>
|
||||||
<q-btn
|
<q-btn
|
||||||
class="q-ml-sm"
|
class="q-ml-sm"
|
||||||
|
|
@ -894,6 +889,7 @@ async function storeDataLocal(id: string) {
|
||||||
:text="value.text"
|
:text="value.text"
|
||||||
:icon-color="value.iconColor"
|
:icon-color="value.iconColor"
|
||||||
:bg-color="value.color"
|
:bg-color="value.color"
|
||||||
|
:id="`btn-add-new-${value.text}`"
|
||||||
@trigger="
|
@trigger="
|
||||||
() => {
|
() => {
|
||||||
triggerCreateCustomerd({
|
triggerCreateCustomerd({
|
||||||
|
|
|
||||||
|
|
@ -514,6 +514,7 @@ onMounted(async () => {
|
||||||
|
|
||||||
<div class="q-ml-auto row" style="gap: 10px">
|
<div class="q-ml-auto row" style="gap: 10px">
|
||||||
<q-btn
|
<q-btn
|
||||||
|
id="btn-payment"
|
||||||
@click.stop
|
@click.stop
|
||||||
unelevated
|
unelevated
|
||||||
padding="4px 8px"
|
padding="4px 8px"
|
||||||
|
|
@ -552,6 +553,7 @@ onMounted(async () => {
|
||||||
:key="opts.status"
|
:key="opts.status"
|
||||||
>
|
>
|
||||||
<q-item
|
<q-item
|
||||||
|
:id="`btn-payment-${opts.status}`"
|
||||||
v-if="
|
v-if="
|
||||||
(p.paymentStatus === 'PaymentWait' &&
|
(p.paymentStatus === 'PaymentWait' &&
|
||||||
opts.status !== 'PaymentRetry') ||
|
opts.status !== 'PaymentRetry') ||
|
||||||
|
|
@ -591,6 +593,7 @@ onMounted(async () => {
|
||||||
flat
|
flat
|
||||||
rounded
|
rounded
|
||||||
padding="0"
|
padding="0"
|
||||||
|
id="btn-show-file"
|
||||||
:icon="`mdi-chevron-${state.payExpansion[i] ? 'down' : 'up'}`"
|
:icon="`mdi-chevron-${state.payExpansion[i] ? 'down' : 'up'}`"
|
||||||
@click.stop="
|
@click.stop="
|
||||||
state.payExpansion[i] = !state.payExpansion[i]
|
state.payExpansion[i] = !state.payExpansion[i]
|
||||||
|
|
@ -625,6 +628,7 @@ onMounted(async () => {
|
||||||
}}
|
}}
|
||||||
<q-btn
|
<q-btn
|
||||||
unelevated
|
unelevated
|
||||||
|
id="btn-upload-file"
|
||||||
:label="$t('general.upload')"
|
:label="$t('general.upload')"
|
||||||
rounded
|
rounded
|
||||||
class="app-bg-info q-mt-sm"
|
class="app-bg-info q-mt-sm"
|
||||||
|
|
|
||||||
|
|
@ -1421,6 +1421,7 @@ async function formDownload() {
|
||||||
>
|
>
|
||||||
<button
|
<button
|
||||||
v-for="value in statusQuotationForm"
|
v-for="value in statusQuotationForm"
|
||||||
|
:id="`btn-status-${value.title}`"
|
||||||
:key="value.title"
|
:key="value.title"
|
||||||
class="q-pa-sm bordered status-color row items-center"
|
class="q-pa-sm bordered status-color row items-center"
|
||||||
:class="{
|
:class="{
|
||||||
|
|
@ -1553,6 +1554,8 @@ async function formDownload() {
|
||||||
</div>
|
</div>
|
||||||
<nav class="q-ml-auto">
|
<nav class="q-ml-auto">
|
||||||
<AddButton
|
<AddButton
|
||||||
|
id="btn-add-worker"
|
||||||
|
for="btn-add-worker"
|
||||||
v-if="
|
v-if="
|
||||||
!readonly &&
|
!readonly &&
|
||||||
(!quotationFormState.source ||
|
(!quotationFormState.source ||
|
||||||
|
|
@ -1565,6 +1568,8 @@ async function formDownload() {
|
||||||
@click.stop="triggerSelectEmployeeDialog"
|
@click.stop="triggerSelectEmployeeDialog"
|
||||||
/>
|
/>
|
||||||
<AddButton
|
<AddButton
|
||||||
|
id="btn-add-worker"
|
||||||
|
for="btn-add-worker"
|
||||||
v-if="
|
v-if="
|
||||||
!!quotationFormState.source &&
|
!!quotationFormState.source &&
|
||||||
quotationFormState.source.quotationStatus !==
|
quotationFormState.source.quotationStatus !==
|
||||||
|
|
@ -1621,6 +1626,7 @@ async function formDownload() {
|
||||||
v-if="!readonly"
|
v-if="!readonly"
|
||||||
icon-only
|
icon-only
|
||||||
class="q-ml-auto"
|
class="q-ml-auto"
|
||||||
|
id="trigger-product-service-dialog"
|
||||||
@click.stop="triggerProductServiceDialog"
|
@click.stop="triggerProductServiceDialog"
|
||||||
/>
|
/>
|
||||||
</nav>
|
</nav>
|
||||||
|
|
@ -2243,6 +2249,7 @@ async function formDownload() {
|
||||||
outlined
|
outlined
|
||||||
icon="mdi-play-box-outline"
|
icon="mdi-play-box-outline"
|
||||||
color="207 96% 32%"
|
color="207 96% 32%"
|
||||||
|
id="btn-view-example"
|
||||||
@click="storeDataLocal"
|
@click="storeDataLocal"
|
||||||
>
|
>
|
||||||
{{ $t('general.view', { msg: $t('general.example') }) }}
|
{{ $t('general.view', { msg: $t('general.example') }) }}
|
||||||
|
|
@ -2258,6 +2265,7 @@ async function formDownload() {
|
||||||
solid
|
solid
|
||||||
icon="mdi-account-multiple-check-outline"
|
icon="mdi-account-multiple-check-outline"
|
||||||
color="207 96% 32%"
|
color="207 96% 32%"
|
||||||
|
id="btn-submit-accepted"
|
||||||
@click="
|
@click="
|
||||||
() => {
|
() => {
|
||||||
submitAccepted();
|
submitAccepted();
|
||||||
|
|
@ -2273,6 +2281,7 @@ async function formDownload() {
|
||||||
solid
|
solid
|
||||||
icon="mdi-account-multiple-check-outline"
|
icon="mdi-account-multiple-check-outline"
|
||||||
color="207 96% 32%"
|
color="207 96% 32%"
|
||||||
|
id="btn-select-invoice"
|
||||||
@click="
|
@click="
|
||||||
() => {
|
() => {
|
||||||
view = View.Invoice;
|
view = View.Invoice;
|
||||||
|
|
@ -2296,6 +2305,7 @@ async function formDownload() {
|
||||||
solid
|
solid
|
||||||
icon="mdi-account-multiple-check-outline"
|
icon="mdi-account-multiple-check-outline"
|
||||||
color="207 96% 32%"
|
color="207 96% 32%"
|
||||||
|
id="btn-approve-invoice"
|
||||||
@click="
|
@click="
|
||||||
() => {
|
() => {
|
||||||
convertInvoiceToSubmit();
|
convertInvoiceToSubmit();
|
||||||
|
|
@ -2319,15 +2329,18 @@ async function formDownload() {
|
||||||
<UndoButton
|
<UndoButton
|
||||||
outlined
|
outlined
|
||||||
@click="closeTab()"
|
@click="closeTab()"
|
||||||
|
id="btn-undo"
|
||||||
v-if="quotationFormState.mode === 'edit'"
|
v-if="quotationFormState.mode === 'edit'"
|
||||||
/>
|
/>
|
||||||
<CloseButton
|
<CloseButton
|
||||||
outlined
|
outlined
|
||||||
|
id="btn-close"
|
||||||
@click="closeTab()"
|
@click="closeTab()"
|
||||||
v-if="quotationFormState.mode === 'info' && closeAble()"
|
v-if="quotationFormState.mode === 'info' && closeAble()"
|
||||||
/>
|
/>
|
||||||
<SaveButton
|
<SaveButton
|
||||||
type="submit"
|
type="submit"
|
||||||
|
id="btn-save"
|
||||||
v-if="
|
v-if="
|
||||||
quotationFormState.mode === 'create' ||
|
quotationFormState.mode === 'create' ||
|
||||||
quotationFormState.mode === 'edit'
|
quotationFormState.mode === 'edit'
|
||||||
|
|
@ -2338,6 +2351,7 @@ async function formDownload() {
|
||||||
<EditButton
|
<EditButton
|
||||||
v-else
|
v-else
|
||||||
class="no-print"
|
class="no-print"
|
||||||
|
id="btn-edit"
|
||||||
@click="quotationFormState.mode = 'edit'"
|
@click="quotationFormState.mode = 'edit'"
|
||||||
solid
|
solid
|
||||||
/>
|
/>
|
||||||
|
|
|
||||||
|
|
@ -508,6 +508,7 @@ watch(
|
||||||
flat
|
flat
|
||||||
rounded
|
rounded
|
||||||
icon="mdi-store-plus-outline"
|
icon="mdi-store-plus-outline"
|
||||||
|
id="trigger-add-dialog"
|
||||||
@click="triggerAddDialog"
|
@click="triggerAddDialog"
|
||||||
/>
|
/>
|
||||||
<q-btn
|
<q-btn
|
||||||
|
|
@ -515,6 +516,7 @@ watch(
|
||||||
flat
|
flat
|
||||||
rounded
|
rounded
|
||||||
icon="mdi-information-outline"
|
icon="mdi-information-outline"
|
||||||
|
id="trigger-info"
|
||||||
@click="triggerInfo"
|
@click="triggerInfo"
|
||||||
:color="pageState.infoDrawer ? 'info' : ''"
|
:color="pageState.infoDrawer ? 'info' : ''"
|
||||||
style="color: hsl(var(--text-mute))"
|
style="color: hsl(var(--text-mute))"
|
||||||
|
|
|
||||||
|
|
@ -289,6 +289,7 @@ watch(() => state.search, getWorkerList);
|
||||||
<q-menu class="bordered" ref="refMenu">
|
<q-menu class="bordered" ref="refMenu">
|
||||||
<q-list>
|
<q-list>
|
||||||
<q-item
|
<q-item
|
||||||
|
id="trigger-create-employee"
|
||||||
v-close-popup
|
v-close-popup
|
||||||
dense
|
dense
|
||||||
clickable
|
clickable
|
||||||
|
|
@ -308,6 +309,7 @@ watch(() => state.search, getWorkerList);
|
||||||
</q-item>
|
</q-item>
|
||||||
|
|
||||||
<q-item
|
<q-item
|
||||||
|
id="import-worker"
|
||||||
v-close-popup
|
v-close-popup
|
||||||
dense
|
dense
|
||||||
clickable
|
clickable
|
||||||
|
|
@ -470,6 +472,7 @@ watch(() => state.search, getWorkerList);
|
||||||
<template #grid="{ item: emp, index }">
|
<template #grid="{ item: emp, index }">
|
||||||
<div :key="emp.id" class="col-md-2 col-sm-6 col-12">
|
<div :key="emp.id" class="col-md-2 col-sm-6 col-12">
|
||||||
<button
|
<button
|
||||||
|
:id="`select-worker-${emp.firstName}`"
|
||||||
class="selectable-item full-width"
|
class="selectable-item full-width"
|
||||||
:class="{
|
:class="{
|
||||||
['selectable-item__selected']:
|
['selectable-item__selected']:
|
||||||
|
|
@ -520,11 +523,12 @@ watch(() => state.search, getWorkerList);
|
||||||
</div>
|
</div>
|
||||||
<template #footer>
|
<template #footer>
|
||||||
<div class="q-gutter-x-xs q-ml-auto">
|
<div class="q-gutter-x-xs q-ml-auto">
|
||||||
<CancelButton outlined @click="clean" />
|
<CancelButton id="btn-cancel" outlined @click="clean" />
|
||||||
<MainButton
|
<MainButton
|
||||||
icon="mdi-check"
|
icon="mdi-check"
|
||||||
color="207 96% 32%"
|
color="207 96% 32%"
|
||||||
solid
|
solid
|
||||||
|
id="btn-success"
|
||||||
@click="
|
@click="
|
||||||
emits('success', {
|
emits('success', {
|
||||||
worker: workerSelected,
|
worker: workerSelected,
|
||||||
|
|
|
||||||
|
|
@ -102,6 +102,7 @@ function goToRequestList(id: string) {
|
||||||
<template v-if="col.name === '#codeRequest'">
|
<template v-if="col.name === '#codeRequest'">
|
||||||
<span
|
<span
|
||||||
class="cursor-pointer link"
|
class="cursor-pointer link"
|
||||||
|
:id="`go-to-request-list-${props.row.code}`"
|
||||||
@click="goToRequestList(props.row.id)"
|
@click="goToRequestList(props.row.id)"
|
||||||
>
|
>
|
||||||
{{ props.row.code }}
|
{{ props.row.code }}
|
||||||
|
|
|
||||||
|
|
@ -30,7 +30,7 @@ export const DEFAULT_DATA: QuotationPayload = {
|
||||||
paySplit: [],
|
paySplit: [],
|
||||||
paySplitCount: 0,
|
paySplitCount: 0,
|
||||||
payCondition: 'Full',
|
payCondition: 'Full',
|
||||||
dueDate: new Date(),
|
dueDate: new Date(Date.now() + 86400000),
|
||||||
discount: 0,
|
discount: 0,
|
||||||
contactTel: '',
|
contactTel: '',
|
||||||
contactName: '',
|
contactName: '',
|
||||||
|
|
|
||||||
|
|
@ -199,16 +199,23 @@ watch(
|
||||||
<ProfileBanner
|
<ProfileBanner
|
||||||
prefix="dialog"
|
prefix="dialog"
|
||||||
active
|
active
|
||||||
|
use-toggle
|
||||||
hide-fade
|
hide-fade
|
||||||
hide-active
|
:toggle-title="$t('status.title')"
|
||||||
:icon="'ph-building-office'"
|
:icon="'ph-building-office'"
|
||||||
:img="imageState.imageUrl || null"
|
:img="imageState.imageUrl || null"
|
||||||
:title="data.name"
|
:title="data.name"
|
||||||
:caption="data.code"
|
:caption="data.code"
|
||||||
:color="`hsla(var(--green-8-hsl)/1)`"
|
:color="`hsla(var(--green-8-hsl)/1)`"
|
||||||
:bg-color="`hsla(var(--green-8-hsl)/0.1)`"
|
:bg-color="`hsla(var(--green-8-hsl)/0.1)`"
|
||||||
|
v-model:toggle-status="data.status"
|
||||||
@view="viewImage"
|
@view="viewImage"
|
||||||
@edit="editImage"
|
@edit="editImage"
|
||||||
|
@update:toggle-status="
|
||||||
|
() => {
|
||||||
|
data.status = data.status === 'CREATED' ? 'INACTIVE' : 'CREATED';
|
||||||
|
}
|
||||||
|
"
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
|
@ -317,9 +324,10 @@ watch(
|
||||||
>
|
>
|
||||||
<ProfileBanner
|
<ProfileBanner
|
||||||
:prefix="data.name"
|
:prefix="data.name"
|
||||||
active
|
|
||||||
hide-fade
|
hide-fade
|
||||||
hide-active
|
use-toggle
|
||||||
|
:active="data.status !== 'INACTIVE'"
|
||||||
|
:toggle-title="$t('status.title')"
|
||||||
:icon="'ph-building-office'"
|
:icon="'ph-building-office'"
|
||||||
:title="data.name"
|
:title="data.name"
|
||||||
:caption="data.code"
|
:caption="data.code"
|
||||||
|
|
@ -330,8 +338,10 @@ watch(
|
||||||
imageState.refreshImageState ? `?ts=${Date.now()}` : '',
|
imageState.refreshImageState ? `?ts=${Date.now()}` : '',
|
||||||
) || null
|
) || null
|
||||||
"
|
"
|
||||||
|
v-model:toggle-status="data.status"
|
||||||
@view="viewImage"
|
@view="viewImage"
|
||||||
@edit="editImage"
|
@edit="editImage"
|
||||||
|
@update:toggle-status="$emit('changeStatus')"
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
|
@ -354,7 +364,10 @@ watch(
|
||||||
}"
|
}"
|
||||||
style="position: absolute; z-index: 999; top: 0; right: 0"
|
style="position: absolute; z-index: 999; top: 0; right: 0"
|
||||||
>
|
>
|
||||||
<div v-if="true" class="surface-1 row rounded">
|
<div
|
||||||
|
v-if="data.status !== 'INACTIVE'"
|
||||||
|
class="surface-1 row rounded"
|
||||||
|
>
|
||||||
<UndoButton
|
<UndoButton
|
||||||
v-if="isEdit"
|
v-if="isEdit"
|
||||||
id="btn-info-basic-undo"
|
id="btn-info-basic-undo"
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,5 @@
|
||||||
<script lang="ts" setup>
|
<script lang="ts" setup>
|
||||||
import { QTableProps } from 'quasar';
|
import { QSelect, QTableProps } from 'quasar';
|
||||||
import { dialog } from 'src/stores/utils';
|
import { dialog } from 'src/stores/utils';
|
||||||
import { onMounted, reactive, ref, watch } from 'vue';
|
import { onMounted, reactive, ref, watch } from 'vue';
|
||||||
import { storeToRefs } from 'pinia';
|
import { storeToRefs } from 'pinia';
|
||||||
|
|
@ -97,8 +97,11 @@ const blankFormData: InstitutionPayload = {
|
||||||
districtId: '',
|
districtId: '',
|
||||||
provinceId: '',
|
provinceId: '',
|
||||||
selectedImage: '',
|
selectedImage: '',
|
||||||
|
status: 'CREATED',
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const statusFilter = ref<'all' | 'statusACTIVE' | 'statusINACTIVE'>('all');
|
||||||
|
const refFilter = ref<InstanceType<typeof QSelect>>();
|
||||||
const refAgenciesDialog = ref();
|
const refAgenciesDialog = ref();
|
||||||
const formData = ref<InstitutionPayload>(structuredClone(blankFormData));
|
const formData = ref<InstitutionPayload>(structuredClone(blankFormData));
|
||||||
const currAgenciesData = ref<Institution>();
|
const currAgenciesData = ref<Institution>();
|
||||||
|
|
@ -109,6 +112,7 @@ const onCreateImageList = ref<{
|
||||||
|
|
||||||
function triggerDialog(type: 'add' | 'edit' | 'view') {
|
function triggerDialog(type: 'add' | 'edit' | 'view') {
|
||||||
if (type === 'add') {
|
if (type === 'add') {
|
||||||
|
formData.value = structuredClone(blankFormData);
|
||||||
pageState.addModal = true;
|
pageState.addModal = true;
|
||||||
pageState.isDrawerEdit = true;
|
pageState.isDrawerEdit = true;
|
||||||
}
|
}
|
||||||
|
|
@ -155,6 +159,7 @@ function assignFormData(data: Institution) {
|
||||||
districtId: data.districtId,
|
districtId: data.districtId,
|
||||||
provinceId: data.provinceId,
|
provinceId: data.provinceId,
|
||||||
selectedImage: data.selectedImage,
|
selectedImage: data.selectedImage,
|
||||||
|
status: data.status,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -175,6 +180,7 @@ async function submit(opt?: { selectedImage: string }) {
|
||||||
subDistrictId: formData.value.subDistrictId,
|
subDistrictId: formData.value.subDistrictId,
|
||||||
districtId: formData.value.districtId,
|
districtId: formData.value.districtId,
|
||||||
provinceId: formData.value.provinceId,
|
provinceId: formData.value.provinceId,
|
||||||
|
status: formData.value.status,
|
||||||
};
|
};
|
||||||
if (
|
if (
|
||||||
(pageState.isDrawerEdit && currAgenciesData.value?.id) ||
|
(pageState.isDrawerEdit && currAgenciesData.value?.id) ||
|
||||||
|
|
@ -182,6 +188,7 @@ async function submit(opt?: { selectedImage: string }) {
|
||||||
) {
|
) {
|
||||||
const ret = await institutionStore.editInstitution(
|
const ret = await institutionStore.editInstitution(
|
||||||
Object.assign(payload, {
|
Object.assign(payload, {
|
||||||
|
status: undefined,
|
||||||
id: currAgenciesData.value.id,
|
id: currAgenciesData.value.id,
|
||||||
selectedImage: opt?.selectedImage || undefined,
|
selectedImage: opt?.selectedImage || undefined,
|
||||||
}),
|
}),
|
||||||
|
|
@ -238,6 +245,12 @@ async function fetchData(mobileFetch?: boolean) {
|
||||||
? data.value.length + (pageState.total === data.value.length ? 1 : 0)
|
? data.value.length + (pageState.total === data.value.length ? 1 : 0)
|
||||||
: pageSize.value,
|
: pageSize.value,
|
||||||
query: pageState.inputSearch,
|
query: pageState.inputSearch,
|
||||||
|
status:
|
||||||
|
statusFilter.value === 'all'
|
||||||
|
? undefined
|
||||||
|
: statusFilter.value === 'statusACTIVE'
|
||||||
|
? 'ACTIVE'
|
||||||
|
: 'INACTIVE',
|
||||||
});
|
});
|
||||||
|
|
||||||
if (ret) {
|
if (ret) {
|
||||||
|
|
@ -250,6 +263,54 @@ async function fetchData(mobileFetch?: boolean) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async function triggerChangeStatus(data?: Institution) {
|
||||||
|
const targetId = (data && data.id) || currAgenciesData.value?.id;
|
||||||
|
const targetStatus = (data && data.status) || currAgenciesData.value?.status;
|
||||||
|
if (data) assignFormData(data);
|
||||||
|
if (targetId === undefined || targetStatus === undefined) return;
|
||||||
|
|
||||||
|
return await new Promise((resolve, reject) => {
|
||||||
|
dialog({
|
||||||
|
color: targetStatus !== 'INACTIVE' ? 'warning' : 'info',
|
||||||
|
icon:
|
||||||
|
targetStatus !== 'INACTIVE'
|
||||||
|
? 'mdi-alert'
|
||||||
|
: 'mdi-message-processing-outline',
|
||||||
|
title: t('dialog.title.confirmChangeStatus'),
|
||||||
|
actionText:
|
||||||
|
targetStatus !== 'INACTIVE' ? t('general.close') : t('general.open'),
|
||||||
|
message:
|
||||||
|
targetStatus !== 'INACTIVE'
|
||||||
|
? t('dialog.message.confirmChangeStatusOff')
|
||||||
|
: t('dialog.message.confirmChangeStatusOn'),
|
||||||
|
action: async () => {
|
||||||
|
await changeStatus(targetId).then(resolve).catch(reject);
|
||||||
|
},
|
||||||
|
cancel: () => {},
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
async function changeStatus(id?: string) {
|
||||||
|
const targetId = id || currAgenciesData.value?.id;
|
||||||
|
if (targetId === undefined) return;
|
||||||
|
|
||||||
|
formData.value.status =
|
||||||
|
formData.value.status !== 'INACTIVE' ? 'INACTIVE' : 'ACTIVE';
|
||||||
|
|
||||||
|
const res = await institutionStore.editInstitution({
|
||||||
|
id: targetId,
|
||||||
|
...formData.value,
|
||||||
|
});
|
||||||
|
if (res) {
|
||||||
|
formData.value.status = res.status;
|
||||||
|
if (currAgenciesData.value) {
|
||||||
|
currAgenciesData.value.status = res.status;
|
||||||
|
}
|
||||||
|
await fetchData();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
onMounted(async () => {
|
onMounted(async () => {
|
||||||
navigatorStore.current.title = 'agencies.title';
|
navigatorStore.current.title = 'agencies.title';
|
||||||
navigatorStore.current.path = [{ text: 'agencies.caption', i18n: true }];
|
navigatorStore.current.path = [{ text: 'agencies.caption', i18n: true }];
|
||||||
|
|
@ -259,7 +320,7 @@ onMounted(async () => {
|
||||||
});
|
});
|
||||||
|
|
||||||
watch(
|
watch(
|
||||||
() => pageState.inputSearch,
|
() => [pageState.inputSearch, statusFilter.value],
|
||||||
() => {
|
() => {
|
||||||
page.value = 1;
|
page.value = 1;
|
||||||
data.value = [];
|
data.value = [];
|
||||||
|
|
@ -342,10 +403,26 @@ watch(
|
||||||
<template #prepend>
|
<template #prepend>
|
||||||
<q-icon name="mdi-magnify" />
|
<q-icon name="mdi-magnify" />
|
||||||
</template>
|
</template>
|
||||||
|
<template v-if="$q.screen.lt.md" v-slot:append>
|
||||||
|
<span class="row">
|
||||||
|
<q-separator vertical />
|
||||||
|
<q-btn
|
||||||
|
icon="mdi-filter-variant"
|
||||||
|
unelevated
|
||||||
|
class="q-ml-sm"
|
||||||
|
padding="4px"
|
||||||
|
size="sm"
|
||||||
|
rounded
|
||||||
|
@click="refFilter?.showPopup"
|
||||||
|
/>
|
||||||
|
</span>
|
||||||
|
</template>
|
||||||
</q-input>
|
</q-input>
|
||||||
|
|
||||||
<div class="row col-md-5 justify-end" style="white-space: nowrap">
|
<div class="row col-md-5 justify-end" style="white-space: nowrap">
|
||||||
<!-- <q-select
|
<q-select
|
||||||
|
v-show="$q.screen.gt.sm"
|
||||||
|
ref="refFilter"
|
||||||
v-model="statusFilter"
|
v-model="statusFilter"
|
||||||
outlined
|
outlined
|
||||||
dense
|
dense
|
||||||
|
|
@ -362,7 +439,7 @@ watch(
|
||||||
{ label: $t('general.active'), value: 'statusACTIVE' },
|
{ label: $t('general.active'), value: 'statusACTIVE' },
|
||||||
{ label: $t('general.inactive'), value: 'statusINACTIVE' },
|
{ label: $t('general.inactive'), value: 'statusINACTIVE' },
|
||||||
]"
|
]"
|
||||||
/> -->
|
/>
|
||||||
<q-select
|
<q-select
|
||||||
v-if="!pageState.gridView"
|
v-if="!pageState.gridView"
|
||||||
id="select-field"
|
id="select-field"
|
||||||
|
|
@ -540,6 +617,18 @@ watch(
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
</q-img>
|
</q-img>
|
||||||
|
|
||||||
|
<q-badge
|
||||||
|
class="absolute-bottom-right no-padding"
|
||||||
|
style="
|
||||||
|
border-radius: 50%;
|
||||||
|
min-width: 8px;
|
||||||
|
min-height: 8px;
|
||||||
|
"
|
||||||
|
:style="{
|
||||||
|
background: `var(--${props.row.status === 'INACTIVE' ? 'stone-5' : 'green-6'})`,
|
||||||
|
}"
|
||||||
|
></q-badge>
|
||||||
</q-avatar>
|
</q-avatar>
|
||||||
<span class="col q-pl-md">
|
<span class="col q-pl-md">
|
||||||
<div>
|
<div>
|
||||||
|
|
@ -594,6 +683,7 @@ watch(
|
||||||
<q-td>
|
<q-td>
|
||||||
<q-btn
|
<q-btn
|
||||||
icon="mdi-eye-outline"
|
icon="mdi-eye-outline"
|
||||||
|
:id="`btn-eye-${props.row.name}`"
|
||||||
size="sm"
|
size="sm"
|
||||||
dense
|
dense
|
||||||
round
|
round
|
||||||
|
|
@ -606,8 +696,7 @@ watch(
|
||||||
"
|
"
|
||||||
/>
|
/>
|
||||||
<KebabAction
|
<KebabAction
|
||||||
hide-toggle
|
:id-name="props.row.name"
|
||||||
:id-name="props.row.id"
|
|
||||||
:status="props.row.status"
|
:status="props.row.status"
|
||||||
@view="
|
@view="
|
||||||
() => {
|
() => {
|
||||||
|
|
@ -622,6 +711,7 @@ watch(
|
||||||
}
|
}
|
||||||
"
|
"
|
||||||
@delete="() => triggerDelete(props.row.id)"
|
@delete="() => triggerDelete(props.row.id)"
|
||||||
|
@change-status="() => triggerChangeStatus(props.row)"
|
||||||
/>
|
/>
|
||||||
</q-td>
|
</q-td>
|
||||||
</q-tr>
|
</q-tr>
|
||||||
|
|
@ -649,6 +739,18 @@ watch(
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
</q-img>
|
</q-img>
|
||||||
|
|
||||||
|
<q-badge
|
||||||
|
class="absolute-bottom-right no-padding"
|
||||||
|
style="
|
||||||
|
border-radius: 50%;
|
||||||
|
min-width: 10px;
|
||||||
|
min-height: 10px;
|
||||||
|
"
|
||||||
|
:style="{
|
||||||
|
background: `var(--${props.row.status === 'INACTIVE' ? 'stone-5' : 'green-6'})`,
|
||||||
|
}"
|
||||||
|
></q-badge>
|
||||||
</q-avatar>
|
</q-avatar>
|
||||||
<span class="text-weight-bold column q-pl-md">
|
<span class="text-weight-bold column q-pl-md">
|
||||||
{{
|
{{
|
||||||
|
|
@ -677,7 +779,6 @@ watch(
|
||||||
"
|
"
|
||||||
/>
|
/>
|
||||||
<KebabAction
|
<KebabAction
|
||||||
hide-toggle
|
|
||||||
:id-name="props.row.id"
|
:id-name="props.row.id"
|
||||||
:status="props.row.status"
|
:status="props.row.status"
|
||||||
@view="
|
@view="
|
||||||
|
|
@ -693,6 +794,7 @@ watch(
|
||||||
}
|
}
|
||||||
"
|
"
|
||||||
@delete="() => triggerDelete(props.row.id)"
|
@delete="() => triggerDelete(props.row.id)"
|
||||||
|
@change-status="() => triggerChangeStatus(props.row)"
|
||||||
/>
|
/>
|
||||||
</nav>
|
</nav>
|
||||||
</header>
|
</header>
|
||||||
|
|
@ -814,6 +916,7 @@ watch(
|
||||||
if (v) await submit({ selectedImage: v });
|
if (v) await submit({ selectedImage: v });
|
||||||
}
|
}
|
||||||
"
|
"
|
||||||
|
@change-status="triggerChangeStatus"
|
||||||
:readonly="!pageState.isDrawerEdit"
|
:readonly="!pageState.isDrawerEdit"
|
||||||
:isEdit="pageState.isDrawerEdit"
|
:isEdit="pageState.isDrawerEdit"
|
||||||
v-model="pageState.addModal"
|
v-model="pageState.addModal"
|
||||||
|
|
|
||||||
|
|
@ -241,6 +241,10 @@ watch([() => pageState.inputSearch, () => pageState.statusFilter], () => {
|
||||||
label: $t('requestList.status.Pending'),
|
label: $t('requestList.status.Pending'),
|
||||||
value: RequestDataStatus.Pending,
|
value: RequestDataStatus.Pending,
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
label: $t('requestList.status.Ready'),
|
||||||
|
value: RequestDataStatus.Ready,
|
||||||
|
},
|
||||||
{
|
{
|
||||||
label: $t('requestList.status.InProgress'),
|
label: $t('requestList.status.InProgress'),
|
||||||
value: RequestDataStatus.InProgress,
|
value: RequestDataStatus.InProgress,
|
||||||
|
|
|
||||||
|
|
@ -320,6 +320,16 @@ function goToQuotation(
|
||||||
|
|
||||||
window.open(url.toString(), '_blank');
|
window.open(url.toString(), '_blank');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function goToDebitNote(opt?: { tab?: string; id?: string }) {
|
||||||
|
const { tab, id } = opt || {};
|
||||||
|
const url = new URL(
|
||||||
|
`/debit-note/${id}?mode=info&tab=${tab}`,
|
||||||
|
window.location.origin,
|
||||||
|
);
|
||||||
|
|
||||||
|
window.open(url.toString(), '_blank');
|
||||||
|
}
|
||||||
</script>
|
</script>
|
||||||
<template>
|
<template>
|
||||||
<div class="column surface-0 fullscreen" v-if="data">
|
<div class="column surface-0 fullscreen" v-if="data">
|
||||||
|
|
@ -503,7 +513,11 @@ function goToQuotation(
|
||||||
icon="mdi-file-document-outline"
|
icon="mdi-file-document-outline"
|
||||||
:label="$t('requestList.quotationCode')"
|
:label="$t('requestList.quotationCode')"
|
||||||
:value="data.quotation.code || '-'"
|
:value="data.quotation.code || '-'"
|
||||||
@label-click="goToQuotation(data.quotation)"
|
@label-click="
|
||||||
|
data.quotation.isDebitNote
|
||||||
|
? goToDebitNote({ id: data.quotation.id, tab: 'title' })
|
||||||
|
: goToQuotation(data.quotation)
|
||||||
|
"
|
||||||
/>
|
/>
|
||||||
<DataDisplay
|
<DataDisplay
|
||||||
clickable
|
clickable
|
||||||
|
|
@ -517,11 +531,17 @@ function goToQuotation(
|
||||||
@label-click="
|
@label-click="
|
||||||
(_: string, i: number) => {
|
(_: string, i: number) => {
|
||||||
if (!data) return;
|
if (!data) return;
|
||||||
goToQuotation(data.quotation, {
|
|
||||||
tab: 'invoice',
|
data.quotation.isDebitNote
|
||||||
id: data.quotation.invoice?.[i]?.id,
|
? goToDebitNote({
|
||||||
amount: data.quotation.invoice?.[i]?.amount,
|
id: data.quotation.id,
|
||||||
});
|
tab: 'payment',
|
||||||
|
})
|
||||||
|
: goToQuotation(data.quotation, {
|
||||||
|
tab: 'invoice',
|
||||||
|
id: data.quotation.invoice?.[i]?.id,
|
||||||
|
amount: data.quotation.invoice?.[i]?.amount,
|
||||||
|
});
|
||||||
}
|
}
|
||||||
"
|
"
|
||||||
/>
|
/>
|
||||||
|
|
@ -536,7 +556,14 @@ function goToQuotation(
|
||||||
(i: Invoice) => i.payment?.code || [],
|
(i: Invoice) => i.payment?.code || [],
|
||||||
)
|
)
|
||||||
"
|
"
|
||||||
@click="goToQuotation(data.quotation, { tab: 'receipt' })"
|
@click="
|
||||||
|
data.quotation.isDebitNote
|
||||||
|
? goToDebitNote({
|
||||||
|
id: data.quotation.id,
|
||||||
|
tab: 'receipt',
|
||||||
|
})
|
||||||
|
: goToQuotation(data.quotation, { tab: 'receipt' })
|
||||||
|
"
|
||||||
/>
|
/>
|
||||||
<div v-if="$q.screen.gt.sm" class="col"></div>
|
<div v-if="$q.screen.gt.sm" class="col"></div>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
||||||
|
|
@ -186,7 +186,7 @@ function getEmployeeName(
|
||||||
</q-td>
|
</q-td>
|
||||||
<q-td class="text-right">
|
<q-td class="text-right">
|
||||||
<q-btn
|
<q-btn
|
||||||
:id="`btn-eye-${props.row.quotation.workName}`"
|
:id="`btn-eye-${props.row.code}`"
|
||||||
icon="mdi-eye-outline"
|
icon="mdi-eye-outline"
|
||||||
size="sm"
|
size="sm"
|
||||||
dense
|
dense
|
||||||
|
|
@ -196,6 +196,7 @@ function getEmployeeName(
|
||||||
/>
|
/>
|
||||||
|
|
||||||
<KebabAction
|
<KebabAction
|
||||||
|
:id-name="`btn-kebab-${props.row.code}`"
|
||||||
hide-edit
|
hide-edit
|
||||||
hide-toggle
|
hide-toggle
|
||||||
hide-view
|
hide-view
|
||||||
|
|
@ -223,15 +224,13 @@ function getEmployeeName(
|
||||||
hide-kebab-delete
|
hide-kebab-delete
|
||||||
use-cancel
|
use-cancel
|
||||||
:badge-color="
|
:badge-color="
|
||||||
props.row.requestDataStatus === RequestDataStatus.Pending
|
{
|
||||||
? '--orange-5-hsl'
|
[RequestDataStatus.Pending]: '--orange-5-hsl',
|
||||||
: props.row.requestDataStatus === RequestDataStatus.Canceled
|
[RequestDataStatus.Ready]: '--yellow-6-hsl',
|
||||||
? '--red-5-hsl'
|
[RequestDataStatus.InProgress]: '--blue-6-hsl',
|
||||||
: props.row.requestDataStatus === RequestDataStatus.InProgress
|
[RequestDataStatus.Completed]: '--green-8-hsl',
|
||||||
? '--blue-6-hsl'
|
[RequestDataStatus.Canceled]: '--red-5-hsl',
|
||||||
: props.row.requestDataStatus === RequestDataStatus.Completed
|
}[props.row.requestDataStatus]
|
||||||
? '--green-8-hsl'
|
|
||||||
: '--orange-5-hsl'
|
|
||||||
"
|
"
|
||||||
:urgent="props.row.quotation.urgent"
|
:urgent="props.row.quotation.urgent"
|
||||||
:code="props.row.code"
|
:code="props.row.code"
|
||||||
|
|
|
||||||
|
|
@ -203,7 +203,7 @@ watch(
|
||||||
color: hsl(var(--info-bg));
|
color: hsl(var(--info-bg));
|
||||||
"
|
"
|
||||||
>
|
>
|
||||||
{{ pageState.total }}
|
{{ Object.values(stats).reduce((s, v) => s + v, 0) }}
|
||||||
</q-badge>
|
</q-badge>
|
||||||
<q-btn
|
<q-btn
|
||||||
class="q-ml-sm"
|
class="q-ml-sm"
|
||||||
|
|
|
||||||
|
|
@ -165,35 +165,49 @@ function submit() {
|
||||||
requestWorkId: string;
|
requestWorkId: string;
|
||||||
requestWorkStep?: Task;
|
requestWorkStep?: Task;
|
||||||
}[] = [];
|
}[] = [];
|
||||||
|
|
||||||
selectedEmployee.value.forEach((v, i) => {
|
selectedEmployee.value.forEach((v, i) => {
|
||||||
const curr = v.stepStatus.find(
|
if (v.stepStatus.length === 0) {
|
||||||
(s) =>
|
|
||||||
s.workStatus ===
|
|
||||||
(props.creditNote
|
|
||||||
? RequestWorkStatus.Canceled
|
|
||||||
: RequestWorkStatus.Ready) ||
|
|
||||||
s.workStatus ===
|
|
||||||
(props.creditNote
|
|
||||||
? RequestWorkStatus.Canceled
|
|
||||||
: RequestWorkStatus.InProgress),
|
|
||||||
);
|
|
||||||
if (curr) {
|
|
||||||
const task: Task = {
|
|
||||||
...curr,
|
|
||||||
attributes: curr.attributes,
|
|
||||||
workStatus:
|
|
||||||
curr.workStatus || props.creditNote
|
|
||||||
? RequestWorkStatus.Ready
|
|
||||||
: RequestWorkStatus.Canceled,
|
|
||||||
taskOrderId: '',
|
|
||||||
requestWork: selectedEmployee.value[i],
|
|
||||||
};
|
|
||||||
selected.push({
|
selected.push({
|
||||||
step: task.step,
|
step: 0,
|
||||||
requestWorkId: task.requestWorkId,
|
requestWorkId: v.id || '',
|
||||||
requestWorkStep: task,
|
requestWorkStep: {
|
||||||
|
taskOrderId: '',
|
||||||
|
requestWork: v,
|
||||||
|
step: 0,
|
||||||
|
workStatus: '',
|
||||||
|
requestWorkId: '',
|
||||||
|
attributes: undefined,
|
||||||
|
},
|
||||||
});
|
});
|
||||||
|
} else {
|
||||||
|
const curr = v.stepStatus.find(
|
||||||
|
(s) =>
|
||||||
|
s.workStatus ===
|
||||||
|
(props.creditNote
|
||||||
|
? RequestWorkStatus.Canceled
|
||||||
|
: RequestWorkStatus.Ready) ||
|
||||||
|
s.workStatus ===
|
||||||
|
(props.creditNote
|
||||||
|
? RequestWorkStatus.Canceled
|
||||||
|
: RequestWorkStatus.InProgress),
|
||||||
|
);
|
||||||
|
if (curr) {
|
||||||
|
const task: Task = {
|
||||||
|
...curr,
|
||||||
|
attributes: curr.attributes,
|
||||||
|
workStatus:
|
||||||
|
curr.workStatus || props.creditNote
|
||||||
|
? RequestWorkStatus.Ready
|
||||||
|
: RequestWorkStatus.Canceled,
|
||||||
|
taskOrderId: '',
|
||||||
|
requestWork: selectedEmployee.value[i],
|
||||||
|
};
|
||||||
|
selected.push({
|
||||||
|
step: task.step,
|
||||||
|
requestWorkId: task.requestWorkId,
|
||||||
|
requestWorkStep: task,
|
||||||
|
});
|
||||||
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
@ -217,11 +231,17 @@ function onDialogOpen() {
|
||||||
if (taskList.value.length === 0) return;
|
if (taskList.value.length === 0) return;
|
||||||
const matchingItems = tempGroupEdit.value
|
const matchingItems = tempGroupEdit.value
|
||||||
.flatMap((g) => g.list)
|
.flatMap((g) => g.list)
|
||||||
.filter((l) =>
|
.filter((l) => {
|
||||||
l.stepStatus.some((s) =>
|
if (l.stepStatus.length === 0) {
|
||||||
taskList.value.some((t) => s.requestWorkId === t.requestWorkId),
|
return taskList.value.some(
|
||||||
),
|
(t) => t.requestWorkStep?.requestWork.id === l.id,
|
||||||
);
|
);
|
||||||
|
} else {
|
||||||
|
return l.stepStatus.some((s) =>
|
||||||
|
taskList.value.some((t) => s.requestWorkId === t.requestWorkId),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
});
|
||||||
selectedEmployee.value = JSON.parse(JSON.stringify(matchingItems));
|
selectedEmployee.value = JSON.parse(JSON.stringify(matchingItems));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -630,6 +630,7 @@ onMounted(async () => {
|
||||||
:task-list="taskListGroup"
|
:task-list="taskListGroup"
|
||||||
@add-product="openProductDialog"
|
@add-product="openProductDialog"
|
||||||
/>
|
/>
|
||||||
|
|
||||||
<PaymentExpansion
|
<PaymentExpansion
|
||||||
v-if="view === null"
|
v-if="view === null"
|
||||||
:readonly="readonly"
|
:readonly="readonly"
|
||||||
|
|
@ -806,6 +807,7 @@ onMounted(async () => {
|
||||||
<!-- @click="submit" -->
|
<!-- @click="submit" -->
|
||||||
<SaveButton
|
<SaveButton
|
||||||
v-if="!readonly"
|
v-if="!readonly"
|
||||||
|
:disabled="taskListGroup.length === 0"
|
||||||
type="submit"
|
type="submit"
|
||||||
@click.stop="(e) => refForm?.submit(e)"
|
@click.stop="(e) => refForm?.submit(e)"
|
||||||
:label="$t('creditNote.label.submit')"
|
:label="$t('creditNote.label.submit')"
|
||||||
|
|
|
||||||
|
|
@ -88,6 +88,7 @@ async function triggerDelete(id: string) {
|
||||||
}
|
}
|
||||||
|
|
||||||
async function triggerCreateCreditNote() {
|
async function triggerCreateCreditNote() {
|
||||||
|
pageState.quotationId = '';
|
||||||
pageState.creditDialog = true;
|
pageState.creditDialog = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -110,6 +111,7 @@ function navigateTo(opts: {
|
||||||
|
|
||||||
async function submit() {
|
async function submit() {
|
||||||
navigateTo({ statusDialog: 'create', quotationId: pageState.quotationId });
|
navigateTo({ statusDialog: 'create', quotationId: pageState.quotationId });
|
||||||
|
close();
|
||||||
}
|
}
|
||||||
|
|
||||||
function close() {
|
function close() {
|
||||||
|
|
@ -156,7 +158,7 @@ watch(
|
||||||
color: hsl(var(--info-bg));
|
color: hsl(var(--info-bg));
|
||||||
"
|
"
|
||||||
>
|
>
|
||||||
{{ pageState.total }}
|
{{ stats.Pending + stats.Success || 0 }}
|
||||||
</q-badge>
|
</q-badge>
|
||||||
<q-btn
|
<q-btn
|
||||||
class="q-ml-sm"
|
class="q-ml-sm"
|
||||||
|
|
@ -180,13 +182,13 @@ watch(
|
||||||
:branch="[
|
:branch="[
|
||||||
{
|
{
|
||||||
icon: 'material-symbols-light:receipt-long',
|
icon: 'material-symbols-light:receipt-long',
|
||||||
count: stats[CreditNoteStatus.Pending],
|
count: stats[CreditNoteStatus.Pending] || 0,
|
||||||
label: `creditNote.stats.${CreditNoteStatus.Pending}`,
|
label: `creditNote.stats.${CreditNoteStatus.Pending}`,
|
||||||
color: 'orange',
|
color: 'orange',
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
icon: 'mdi-check-decagram-outline',
|
icon: 'mdi-check-decagram-outline',
|
||||||
count: stats[CreditNoteStatus.Success],
|
count: stats[CreditNoteStatus.Success] || 0,
|
||||||
label: `creditNote.stats.${CreditNoteStatus.Success}`,
|
label: `creditNote.stats.${CreditNoteStatus.Success}`,
|
||||||
color: 'blue',
|
color: 'blue',
|
||||||
},
|
},
|
||||||
|
|
@ -455,7 +457,6 @@ watch(
|
||||||
|
|
||||||
<section class="q-pa-md col full-width">
|
<section class="q-pa-md col full-width">
|
||||||
<div class="surface-1 rounded bordered q-pa-md full-height full-width">
|
<div class="surface-1 rounded bordered q-pa-md full-height full-width">
|
||||||
<!-- TODO: bind quotation id -->
|
|
||||||
<FormCredit v-model:quotation-id="pageState.quotationId" />
|
<FormCredit v-model:quotation-id="pageState.quotationId" />
|
||||||
</div>
|
</div>
|
||||||
</section>
|
</section>
|
||||||
|
|
|
||||||
|
|
@ -74,6 +74,7 @@ const visible = computed(() =>
|
||||||
|
|
||||||
<template v-if="col.name === '#action'">
|
<template v-if="col.name === '#action'">
|
||||||
<KebabAction
|
<KebabAction
|
||||||
|
:id-name="`btn-kebab-${props.row.quotation.workName}`"
|
||||||
hide-edit
|
hide-edit
|
||||||
hide-toggle
|
hide-toggle
|
||||||
:hide-delete
|
:hide-delete
|
||||||
|
|
|
||||||
|
|
@ -51,7 +51,7 @@ const bankList = ref<BankBook[]>([]);
|
||||||
const worker = ref<Employee[]>([]);
|
const worker = ref<Employee[]>([]);
|
||||||
const taskListGroup = ref<
|
const taskListGroup = ref<
|
||||||
{
|
{
|
||||||
product: RequestWork['productService']['product'];
|
product: RequestWork['productService'];
|
||||||
list: RequestWork[];
|
list: RequestWork[];
|
||||||
}[]
|
}[]
|
||||||
>([]);
|
>([]);
|
||||||
|
|
@ -59,7 +59,7 @@ const taskListGroup = ref<
|
||||||
const elements = ref<HTMLElement[]>([]);
|
const elements = ref<HTMLElement[]>([]);
|
||||||
const chunks = ref<
|
const chunks = ref<
|
||||||
{
|
{
|
||||||
product: RequestWork['productService']['product'];
|
product: RequestWork['productService'];
|
||||||
list: RequestWork[];
|
list: RequestWork[];
|
||||||
}[][]
|
}[][]
|
||||||
>([[]]);
|
>([[]]);
|
||||||
|
|
@ -112,6 +112,7 @@ async function getAttachment(quotationId: string) {
|
||||||
}
|
}
|
||||||
|
|
||||||
async function assignData() {
|
async function assignData() {
|
||||||
|
console.log(taskListGroup.value);
|
||||||
for (let i = 0; i < taskListGroup.value.length; i++) {
|
for (let i = 0; i < taskListGroup.value.length; i++) {
|
||||||
let el = elements.value.at(-1);
|
let el = elements.value.at(-1);
|
||||||
|
|
||||||
|
|
@ -269,7 +270,7 @@ function print() {
|
||||||
<PrintButton solid @click="print" />
|
<PrintButton solid @click="print" />
|
||||||
</div>
|
</div>
|
||||||
<div class="row justify-between container color-debit-note">
|
<div class="row justify-between container color-debit-note">
|
||||||
<section class="content" v-for="chunk in chunks">
|
<section class="content" v-for="(chunk, i) in chunks" :key="i">
|
||||||
<ViewHeader
|
<ViewHeader
|
||||||
v-if="!!branch && !!customer && !!details"
|
v-if="!!branch && !!customer && !!details"
|
||||||
:branch="branch"
|
:branch="branch"
|
||||||
|
|
@ -300,23 +301,31 @@ function print() {
|
||||||
<th>{{ $t('preview.pricePerUnit') }}</th>
|
<th>{{ $t('preview.pricePerUnit') }}</th>
|
||||||
<th>{{ $t('preview.value') }}</th>
|
<th>{{ $t('preview.value') }}</th>
|
||||||
</tr>
|
</tr>
|
||||||
<tr v-for="(v, i) in chunk">
|
{{ console.log(chunks) }}
|
||||||
|
{{ console.log(chunk) }}
|
||||||
|
<tr v-for="(v, i) in chunk" :key="i">
|
||||||
<td class="text-center">{{ i + 1 }}</td>
|
<td class="text-center">{{ i + 1 }}</td>
|
||||||
<td>{{ v.product.code }}</td>
|
<td>{{ v.product.product.code }}</td>
|
||||||
<td>{{ v.product.name }}</td>
|
<td>{{ v.product.product.name }}</td>
|
||||||
<td style="text-align: center">
|
<td style="text-align: center">
|
||||||
{{
|
{{
|
||||||
formatNumberDecimal(
|
formatNumberDecimal(
|
||||||
calcPricePerUnit(v.product) +
|
calcPricePerUnit(v.product.product) +
|
||||||
(v.product.calcVat
|
(v.product.product.calcVat
|
||||||
? calcPricePerUnit(v.product) * (config?.vat || 0.07)
|
? calcPricePerUnit(v.product.product) *
|
||||||
|
(config?.vat || 0.07)
|
||||||
: 0),
|
: 0),
|
||||||
2,
|
2,
|
||||||
)
|
)
|
||||||
}}
|
}}
|
||||||
</td>
|
</td>
|
||||||
<td style="text-align: center">
|
<td style="text-align: center">
|
||||||
{{ formatNumberDecimal(calcPrice(v.product, v.list.length), 2) }}
|
{{
|
||||||
|
formatNumberDecimal(
|
||||||
|
calcPrice(v.product.product, v.list.length),
|
||||||
|
2,
|
||||||
|
)
|
||||||
|
}}
|
||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
</tbody>
|
</tbody>
|
||||||
|
|
@ -513,14 +522,16 @@ function print() {
|
||||||
</section>
|
</section>
|
||||||
|
|
||||||
<section
|
<section
|
||||||
v-for="item in attachmentList.filter((v) => v.isImage)"
|
v-for="(item, i) in attachmentList.filter((v) => v.isImage)"
|
||||||
|
:key="i"
|
||||||
class="content"
|
class="content"
|
||||||
>
|
>
|
||||||
<q-img :src="item.url" />
|
<q-img :src="item.url" />
|
||||||
</section>
|
</section>
|
||||||
|
|
||||||
<ViewPDF
|
<ViewPDF
|
||||||
v-for="item in attachmentList.filter((v) => v.isPDF)"
|
v-for="(item, i) in attachmentList.filter((v) => v.isPDF)"
|
||||||
|
:key="i"
|
||||||
:url="item.url"
|
:url="item.url"
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
||||||
|
|
@ -44,8 +44,8 @@ const detail = defineModel<string>('detail');
|
||||||
outlined
|
outlined
|
||||||
dense
|
dense
|
||||||
class="col"
|
class="col"
|
||||||
v-model="detail"
|
:model-value="readonly ? detail || '-' : detail"
|
||||||
:rules="[(val: string) => !!val || $t('form.error.required')]"
|
@update:model-value="(v) => (detail = v?.toString())"
|
||||||
></q-input>
|
></q-input>
|
||||||
</main>
|
</main>
|
||||||
</q-expansion-item>
|
</q-expansion-item>
|
||||||
|
|
|
||||||
|
|
@ -119,7 +119,7 @@ const currentFormData = ref<DebitNotePayload>({
|
||||||
payBillDate: new Date(),
|
payBillDate: new Date(),
|
||||||
paySplitCount: 0,
|
paySplitCount: 0,
|
||||||
payCondition: PayCondition.Full,
|
payCondition: PayCondition.Full,
|
||||||
dueDate: new Date(),
|
dueDate: new Date(Date.now() + 86400000),
|
||||||
discount: 0,
|
discount: 0,
|
||||||
status: 'CREATED',
|
status: 'CREATED',
|
||||||
remark: '#[quotation-labor]<br/><br/>#[quotation-payment]',
|
remark: '#[quotation-labor]<br/><br/>#[quotation-payment]',
|
||||||
|
|
@ -879,6 +879,14 @@ onMounted(async () => {
|
||||||
pageState.mode = route.query['mode'] as 'create' | 'edit' | 'info';
|
pageState.mode = route.query['mode'] as 'create' | 'edit' | 'info';
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (typeof route.query['tab'] === 'string') {
|
||||||
|
view.value =
|
||||||
|
{
|
||||||
|
payment: QuotationStatus.PaymentPending,
|
||||||
|
receipt: QuotationStatus.PaymentSuccess,
|
||||||
|
}[route.query['tab']] || null;
|
||||||
|
}
|
||||||
|
|
||||||
await useConfigStore().getConfig();
|
await useConfigStore().getConfig();
|
||||||
});
|
});
|
||||||
</script>
|
</script>
|
||||||
|
|
@ -943,6 +951,7 @@ onMounted(async () => {
|
||||||
/>
|
/>
|
||||||
</nav>
|
</nav>
|
||||||
<!-- #TODO add goToQuotation as @goto-quotation-->
|
<!-- #TODO add goToQuotation as @goto-quotation-->
|
||||||
|
|
||||||
<DocumentExpansion
|
<DocumentExpansion
|
||||||
v-if="view === null"
|
v-if="view === null"
|
||||||
:readonly
|
:readonly
|
||||||
|
|
@ -957,7 +966,7 @@ onMounted(async () => {
|
||||||
/>
|
/>
|
||||||
|
|
||||||
<DebitNoteExpansion
|
<DebitNoteExpansion
|
||||||
v-if="view === null"
|
v-if="false"
|
||||||
:readonly
|
:readonly
|
||||||
v-model:reason="currentFormData.reason"
|
v-model:reason="currentFormData.reason"
|
||||||
v-model:detail="currentFormData.detail"
|
v-model:detail="currentFormData.detail"
|
||||||
|
|
@ -987,7 +996,6 @@ onMounted(async () => {
|
||||||
/>
|
/>
|
||||||
|
|
||||||
<!-- #TODO add openProductDialog at @add-product-->
|
<!-- #TODO add openProductDialog at @add-product-->
|
||||||
|
|
||||||
<ProductExpansion
|
<ProductExpansion
|
||||||
v-if="view === null"
|
v-if="view === null"
|
||||||
:readonly
|
:readonly
|
||||||
|
|
@ -1156,7 +1164,6 @@ onMounted(async () => {
|
||||||
<nav class="row justify-end">
|
<nav class="row justify-end">
|
||||||
<!-- TODO: view example -->
|
<!-- TODO: view example -->
|
||||||
<MainButton
|
<MainButton
|
||||||
v-if="view === null"
|
|
||||||
class="q-mr-auto"
|
class="q-mr-auto"
|
||||||
outlined
|
outlined
|
||||||
icon="mdi-play-box-outline"
|
icon="mdi-play-box-outline"
|
||||||
|
|
@ -1179,6 +1186,9 @@ onMounted(async () => {
|
||||||
|
|
||||||
<SaveButton
|
<SaveButton
|
||||||
v-if="!readonly && pageState.mode === 'create'"
|
v-if="!readonly && pageState.mode === 'create'"
|
||||||
|
:disabled="
|
||||||
|
selectedWorkerItem.length === 0 && productService.length === 0
|
||||||
|
"
|
||||||
@click="submit"
|
@click="submit"
|
||||||
:label="true ? $t('debitNote.label.submit') : $t('general.save')"
|
:label="true ? $t('debitNote.label.submit') : $t('general.save')"
|
||||||
:icon="
|
:icon="
|
||||||
|
|
|
||||||
|
|
@ -35,7 +35,7 @@ const { stats, pageMax, page, data, pageSize } = storeToRefs(debitNote);
|
||||||
// NOTE: Variable
|
// NOTE: Variable
|
||||||
const pageState = reactive({
|
const pageState = reactive({
|
||||||
quotationId: '',
|
quotationId: '',
|
||||||
currentTab: DebitNoteStatus.Pending,
|
currentTab: DebitNoteStatus.Issued,
|
||||||
hideStat: false,
|
hideStat: false,
|
||||||
statusFilter: 'None',
|
statusFilter: 'None',
|
||||||
inputSearch: '',
|
inputSearch: '',
|
||||||
|
|
@ -64,7 +64,9 @@ async function getList(opts?: { page?: number; pageSize?: number }) {
|
||||||
page: opts?.page || page.value,
|
page: opts?.page || page.value,
|
||||||
pageSize: opts?.pageSize || pageSize.value,
|
pageSize: opts?.pageSize || pageSize.value,
|
||||||
query: pageState.inputSearch === '' ? undefined : pageState.inputSearch,
|
query: pageState.inputSearch === '' ? undefined : pageState.inputSearch,
|
||||||
deebitNoteStatus: pageState.currentTab as DebitNoteStatus | undefined,
|
status: (pageState.currentTab === DebitNoteStatus.Issued
|
||||||
|
? undefined
|
||||||
|
: pageState.currentTab) as DebitNoteStatus,
|
||||||
includeRegisteredBranch: true,
|
includeRegisteredBranch: true,
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
@ -90,6 +92,7 @@ async function triggerDelete(id: string) {
|
||||||
}
|
}
|
||||||
|
|
||||||
async function triggerCreateDebitNote() {
|
async function triggerCreateDebitNote() {
|
||||||
|
pageState.quotationId = '';
|
||||||
pageState.debitDialog = true;
|
pageState.debitDialog = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -114,6 +117,7 @@ function navigateTo(opts: {
|
||||||
|
|
||||||
async function submit() {
|
async function submit() {
|
||||||
navigateTo({ statusDialog: 'create', quotationId: pageState.quotationId });
|
navigateTo({ statusDialog: 'create', quotationId: pageState.quotationId });
|
||||||
|
close();
|
||||||
}
|
}
|
||||||
|
|
||||||
function close() {
|
function close() {
|
||||||
|
|
@ -125,7 +129,17 @@ onMounted(async () => {
|
||||||
navigator.current.title = 'debitNote.title';
|
navigator.current.title = 'debitNote.title';
|
||||||
navigator.current.path = [{ text: 'debitNote.caption', i18n: true }];
|
navigator.current.path = [{ text: 'debitNote.caption', i18n: true }];
|
||||||
|
|
||||||
debitNote.getDebitNoteStats().then((res) => res && (stats.value = res));
|
await debitNote.getDebitNoteStats().then((res) => {
|
||||||
|
if (res) {
|
||||||
|
stats.value = res;
|
||||||
|
|
||||||
|
stats.value['issued'] = Object.values(res).reduce(
|
||||||
|
(sum, value) => sum + value,
|
||||||
|
0,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
getList();
|
getList();
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
@ -159,7 +173,12 @@ watch(
|
||||||
color: hsl(var(--info-bg));
|
color: hsl(var(--info-bg));
|
||||||
"
|
"
|
||||||
>
|
>
|
||||||
{{ pageState.total }}
|
{{
|
||||||
|
Object.entries(stats).reduce(
|
||||||
|
(sum, [key, value]) => (key === 'canceled' ? sum : sum + value),
|
||||||
|
0,
|
||||||
|
)
|
||||||
|
}}
|
||||||
</q-badge>
|
</q-badge>
|
||||||
<q-btn
|
<q-btn
|
||||||
class="q-ml-sm"
|
class="q-ml-sm"
|
||||||
|
|
@ -183,33 +202,28 @@ watch(
|
||||||
:branch="[
|
:branch="[
|
||||||
{
|
{
|
||||||
icon: 'material-symbols-light:receipt-long',
|
icon: 'material-symbols-light:receipt-long',
|
||||||
count: stats[DebitNoteStatus.Pending] || 0,
|
count: stats['issued'] || 0,
|
||||||
label: `debitNote.stats.${DebitNoteStatus.Pending}`,
|
label: `debitNote.stats.${DebitNoteStatus.Issued}`,
|
||||||
color: 'orange',
|
color: 'orange',
|
||||||
},
|
},
|
||||||
{
|
|
||||||
icon: 'mdi-clock-alert-outline',
|
|
||||||
count: stats[DebitNoteStatus.Expire] || 0,
|
|
||||||
label: `debitNote.stats.${DebitNoteStatus.Expire}`,
|
|
||||||
color: 'cyan',
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
icon: 'tabler:cash-register',
|
icon: 'tabler:cash-register',
|
||||||
count: stats[DebitNoteStatus.Payment] || 0,
|
count: stats['paymentPending'] || 0,
|
||||||
label: `debitNote.stats.${DebitNoteStatus.Payment}`,
|
label: `debitNote.stats.${DebitNoteStatus.PaymentPending}`,
|
||||||
color: 'dark-orange',
|
color: 'dark-orange',
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
icon: 'fluent:receipt-money-16-regular',
|
icon: 'fluent:receipt-money-16-regular',
|
||||||
count: stats[DebitNoteStatus.Receipt] || 0,
|
count: stats['paymentSuccess'] || 0,
|
||||||
label: `debitNote.stats.${DebitNoteStatus.Receipt}`,
|
label: `debitNote.stats.${DebitNoteStatus.PaymentSuccess}`,
|
||||||
color: 'green',
|
color: 'green',
|
||||||
},
|
},
|
||||||
|
|
||||||
{
|
{
|
||||||
icon: 'mdi-check-decagram-outline',
|
icon: 'mdi-check-decagram-outline',
|
||||||
count: stats[DebitNoteStatus.Succeed] || 0,
|
count: stats['processComplete'] || 0,
|
||||||
label: `debitNote.stats.${DebitNoteStatus.Succeed}`,
|
label: `debitNote.stats.${DebitNoteStatus.ProcessComplete}`,
|
||||||
color: 'blue',
|
color: 'blue',
|
||||||
},
|
},
|
||||||
]"
|
]"
|
||||||
|
|
@ -485,7 +499,6 @@ watch(
|
||||||
|
|
||||||
<section class="q-pa-md col full-width">
|
<section class="q-pa-md col full-width">
|
||||||
<div class="surface-1 rounded bordered q-pa-md full-height full-width">
|
<div class="surface-1 rounded bordered q-pa-md full-height full-width">
|
||||||
<!-- TODO: bind quotation id -->
|
|
||||||
<FormDebit v-model:quotation-id="pageState.quotationId" />
|
<FormDebit v-model:quotation-id="pageState.quotationId" />
|
||||||
</div>
|
</div>
|
||||||
</section>
|
</section>
|
||||||
|
|
|
||||||
|
|
@ -77,6 +77,7 @@ const visible = computed(() =>
|
||||||
|
|
||||||
<template v-if="col.name === '#action'">
|
<template v-if="col.name === '#action'">
|
||||||
<KebabAction
|
<KebabAction
|
||||||
|
:id-name="`btn-kebab-${props.row.workName}`"
|
||||||
hide-toggle
|
hide-toggle
|
||||||
hide-edit
|
hide-edit
|
||||||
@edit="$emit('edit', props.row)"
|
@edit="$emit('edit', props.row)"
|
||||||
|
|
|
||||||
|
|
@ -4,29 +4,24 @@ import { formatNumberDecimal } from 'src/stores/utils';
|
||||||
|
|
||||||
export const taskStatusOpts = [
|
export const taskStatusOpts = [
|
||||||
{
|
{
|
||||||
status: DebitNoteStatus.Expire,
|
status: DebitNoteStatus.PaymentPending,
|
||||||
name: `debitNote.status.${DebitNoteStatus.Expire}`,
|
name: `debitNote.status.${DebitNoteStatus.PaymentPending}`,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
status: DebitNoteStatus.Payment,
|
status: DebitNoteStatus.PaymentSuccess,
|
||||||
name: `debitNote.status.${DebitNoteStatus.Payment}`,
|
name: `debitNote.status.${DebitNoteStatus.PaymentSuccess}`,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
status: DebitNoteStatus.Receipt,
|
status: DebitNoteStatus.PaymentSuccess,
|
||||||
name: `debitNote.status.${DebitNoteStatus.Receipt}`,
|
name: `debitNote.status.${DebitNoteStatus.ProcessComplete}`,
|
||||||
},
|
|
||||||
{
|
|
||||||
status: DebitNoteStatus.Succeed,
|
|
||||||
name: `debitNote.status.${DebitNoteStatus.Succeed}`,
|
|
||||||
},
|
},
|
||||||
];
|
];
|
||||||
|
|
||||||
export const pageTabs = [
|
export const pageTabs = [
|
||||||
{ label: 'Pending', value: DebitNoteStatus.Pending },
|
{ label: 'Pending', value: DebitNoteStatus.Issued },
|
||||||
{ label: 'Expire', value: DebitNoteStatus.Expire },
|
{ label: 'Payment', value: DebitNoteStatus.PaymentPending },
|
||||||
{ label: 'Payment', value: DebitNoteStatus.Payment },
|
{ label: 'Receipt', value: DebitNoteStatus.PaymentSuccess },
|
||||||
{ label: 'Receipt', value: DebitNoteStatus.Receipt },
|
{ label: 'Succeed', value: DebitNoteStatus.ProcessComplete },
|
||||||
{ label: 'Succeed', value: DebitNoteStatus.Succeed },
|
|
||||||
];
|
];
|
||||||
|
|
||||||
export enum Status {
|
export enum Status {
|
||||||
|
|
@ -85,6 +80,9 @@ export const columns = [
|
||||||
] as const satisfies QTableProps['columns'];
|
] as const satisfies QTableProps['columns'];
|
||||||
|
|
||||||
export const hslaColors: Record<string, string> = {
|
export const hslaColors: Record<string, string> = {
|
||||||
Pending: '--blue-6-hsl',
|
Issued: '--orange-6-hsl',
|
||||||
Success: '--red-6-hsl',
|
PaymentPending: '--orange-10-hsl',
|
||||||
|
PaymentSuccess: '--green-8-hsl',
|
||||||
|
ProcessComplete: '--blue-6-hsl',
|
||||||
|
Canceled: '--red-6-hsl',
|
||||||
};
|
};
|
||||||
|
|
|
||||||
|
|
@ -61,7 +61,7 @@ const quotationCreatedBy = defineModel<string>('quotationCreatedBy');
|
||||||
:disabled="!readonly"
|
:disabled="!readonly"
|
||||||
/>
|
/>
|
||||||
<DatePicker
|
<DatePicker
|
||||||
:label="$t('general.createdAt')"
|
:label="$t('general.dueDate')"
|
||||||
class="col-md-2 col-6"
|
class="col-md-2 col-6"
|
||||||
:model-value="dueDate || new Date(Date.now())"
|
:model-value="dueDate || new Date(Date.now())"
|
||||||
@update:model-value="
|
@update:model-value="
|
||||||
|
|
@ -69,6 +69,22 @@ const quotationCreatedBy = defineModel<string>('quotationCreatedBy');
|
||||||
if (typeof v === 'string') dueDate = v;
|
if (typeof v === 'string') dueDate = v;
|
||||||
}
|
}
|
||||||
"
|
"
|
||||||
|
:rules="[
|
||||||
|
() => {
|
||||||
|
if (!dueDate) return $t('form.error.required');
|
||||||
|
|
||||||
|
const currentDate = new Date(dueDate);
|
||||||
|
const toDate = new Date();
|
||||||
|
if (
|
||||||
|
!readonly &&
|
||||||
|
(currentDate.getTime() === toDate.getTime() ||
|
||||||
|
currentDate.getTime() < toDate.getTime())
|
||||||
|
)
|
||||||
|
return $t('quotation.validateDueDate');
|
||||||
|
return true;
|
||||||
|
},
|
||||||
|
]"
|
||||||
|
:disabled-dates="(date: Date) => date.getTime() <= Date.now()"
|
||||||
:readonly
|
:readonly
|
||||||
/>
|
/>
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -26,7 +26,7 @@ export async function getDebitNoteList(params?: {
|
||||||
page?: number;
|
page?: number;
|
||||||
pageSize?: number;
|
pageSize?: number;
|
||||||
query?: string;
|
query?: string;
|
||||||
deebitNoteStatus?: Status;
|
status?: Status;
|
||||||
includeRegisteredBranch?: boolean;
|
includeRegisteredBranch?: boolean;
|
||||||
}) {
|
}) {
|
||||||
const res = await api.get<PaginationResult<Data>>(`/${ENDPOINT}`, {
|
const res = await api.get<PaginationResult<Data>>(`/${ENDPOINT}`, {
|
||||||
|
|
@ -66,12 +66,11 @@ export const useDebitNote = defineStore('debit-note-store', () => {
|
||||||
const page = ref<number>(1);
|
const page = ref<number>(1);
|
||||||
const pageMax = ref<number>(1);
|
const pageMax = ref<number>(1);
|
||||||
const pageSize = ref<number>(30);
|
const pageSize = ref<number>(30);
|
||||||
const stats = ref<Record<Status, number>>({
|
const stats = ref<Record<string, number>>({
|
||||||
[Status.Pending]: 0,
|
['issued']: 0,
|
||||||
[Status.Expire]: 0,
|
['paymentPending']: 0,
|
||||||
[Status.Payment]: 0,
|
['paymentSuccess']: 0,
|
||||||
[Status.Receipt]: 0,
|
['processComplete']: 0,
|
||||||
[Status.Succeed]: 0,
|
|
||||||
});
|
});
|
||||||
|
|
||||||
return {
|
return {
|
||||||
|
|
|
||||||
|
|
@ -86,9 +86,9 @@ export type DebitNote = {
|
||||||
};
|
};
|
||||||
|
|
||||||
export enum DebitNoteStatus {
|
export enum DebitNoteStatus {
|
||||||
Pending = 'Pending',
|
Issued = 'Issued',
|
||||||
Expire = 'Expire',
|
Expired = 'Expired',
|
||||||
Payment = 'Payment',
|
PaymentPending = 'PaymentPending',
|
||||||
Receipt = 'Receipt',
|
PaymentSuccess = 'PaymentSuccess',
|
||||||
Succeed = 'Succeed',
|
ProcessComplete = 'ProcessComplete',
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -4,6 +4,7 @@ import { Institution, InstitutionPayload } from './types';
|
||||||
import { api } from 'src/boot/axios';
|
import { api } from 'src/boot/axios';
|
||||||
import { PaginationResult } from 'src/types';
|
import { PaginationResult } from 'src/types';
|
||||||
import useFlowStore from '../flow';
|
import useFlowStore from '../flow';
|
||||||
|
import { Status } from '../types';
|
||||||
|
|
||||||
export const useInstitution = defineStore('institution-store', () => {
|
export const useInstitution = defineStore('institution-store', () => {
|
||||||
const flowStore = useFlowStore();
|
const flowStore = useFlowStore();
|
||||||
|
|
@ -26,6 +27,7 @@ export const useInstitution = defineStore('institution-store', () => {
|
||||||
pageSize?: number;
|
pageSize?: number;
|
||||||
query?: string;
|
query?: string;
|
||||||
group?: string;
|
group?: string;
|
||||||
|
status?: Status;
|
||||||
payload?: { group?: string[] };
|
payload?: { group?: string[] };
|
||||||
}) {
|
}) {
|
||||||
const { payload, ...params } = opts || {};
|
const { payload, ...params } = opts || {};
|
||||||
|
|
@ -40,7 +42,7 @@ export const useInstitution = defineStore('institution-store', () => {
|
||||||
params,
|
params,
|
||||||
},
|
},
|
||||||
)
|
)
|
||||||
: await api.get<PaginationResult<Institution>>(`/institution`, {
|
: await api.get<PaginationResult<Institution>>('/institution', {
|
||||||
params,
|
params,
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
@ -80,6 +82,7 @@ export const useInstitution = defineStore('institution-store', () => {
|
||||||
const res = await api.put(`/institution/${data.id}`, {
|
const res = await api.put(`/institution/${data.id}`, {
|
||||||
...data,
|
...data,
|
||||||
id: undefined,
|
id: undefined,
|
||||||
|
group: undefined,
|
||||||
});
|
});
|
||||||
if (res.status < 400) {
|
if (res.status < 400) {
|
||||||
return res.data;
|
return res.data;
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,5 @@
|
||||||
import { District, Province, SubDistrict } from '../address';
|
import { District, Province, SubDistrict } from '../address';
|
||||||
|
import { Status } from '../types';
|
||||||
|
|
||||||
export type Institution = {
|
export type Institution = {
|
||||||
id: string;
|
id: string;
|
||||||
|
|
@ -23,6 +24,7 @@ export type Institution = {
|
||||||
subDistrictId: string;
|
subDistrictId: string;
|
||||||
districtId: string;
|
districtId: string;
|
||||||
provinceId: string;
|
provinceId: string;
|
||||||
|
status: Status;
|
||||||
};
|
};
|
||||||
|
|
||||||
export type InstitutionPayload = {
|
export type InstitutionPayload = {
|
||||||
|
|
@ -44,4 +46,5 @@ export type InstitutionPayload = {
|
||||||
subDistrictId: string;
|
subDistrictId: string;
|
||||||
districtId: string;
|
districtId: string;
|
||||||
provinceId: string;
|
provinceId: string;
|
||||||
|
status?: Status;
|
||||||
};
|
};
|
||||||
|
|
|
||||||
|
|
@ -9,7 +9,7 @@ export type RequestData = {
|
||||||
createdAt: string;
|
createdAt: string;
|
||||||
updatedAt: string;
|
updatedAt: string;
|
||||||
|
|
||||||
quotation: QuotationFull;
|
quotation: QuotationFull & { isDebitNote: boolean };
|
||||||
quotationId: string;
|
quotationId: string;
|
||||||
|
|
||||||
flow: Record<string, any>;
|
flow: Record<string, any>;
|
||||||
|
|
|
||||||
|
|
@ -124,7 +124,7 @@ export function deleteItem(items: unknown[], index: number) {
|
||||||
}
|
}
|
||||||
|
|
||||||
export function formatNumberDecimal(num: number, point: number = 2): string {
|
export function formatNumberDecimal(num: number, point: number = 2): string {
|
||||||
return num.toLocaleString('eng', {
|
return (num || 0).toLocaleString('eng', {
|
||||||
minimumFractionDigits: point,
|
minimumFractionDigits: point,
|
||||||
maximumFractionDigits: point,
|
maximumFractionDigits: point,
|
||||||
});
|
});
|
||||||
|
|
@ -609,3 +609,9 @@ export function getEmployeeName(
|
||||||
['tha']: `${typeof employee.namePrefix === 'string' ? useOptionStore().mapOption(employee.namePrefix) : ''} ${employee.firstName} ${employee.lastName}`,
|
['tha']: `${typeof employee.namePrefix === 'string' ? useOptionStore().mapOption(employee.namePrefix) : ''} ${employee.firstName} ${employee.lastName}`,
|
||||||
}[opts?.locale || 'eng'];
|
}[opts?.locale || 'eng'];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export function toCamelCase(text: string): string {
|
||||||
|
return text
|
||||||
|
.replace(/[^a-zA-Z0-9]+(.)/g, (match, chr) => chr.toUpperCase())
|
||||||
|
.replace(/^[A-Z]/, (match) => match.toLowerCase());
|
||||||
|
}
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue