fix(04): product service (unfinish)

This commit is contained in:
puriphatt 2024-08-14 14:38:26 +07:00
parent 485e0b82b2
commit 7cfc1ddee5
4 changed files with 342 additions and 165 deletions

View file

@ -107,7 +107,7 @@ const branchFilter = selectFilterOptionRefMod(
/> />
</div> </div>
<div v-if="service" class="col-9 row q-col-gutter-md"> <div v-if="service" class="col-12 row q-col-gutter-sm">
<q-input <q-input
lazy-rules="ondemand" lazy-rules="ondemand"
id="input-service-code" id="input-service-code"

View file

@ -18,46 +18,50 @@ defineEmits<{
}>(); }>();
</script> </script>
<template> <template>
<div class="col-3 app-text-muted"> <div class="full-width full-height">
{{ $t(`properties`) }} <div
<div> class="text-weight-bold text-body1 flex items-center justify-between q-px-md q-py-sm"
style="background: hsla(var(--info-bg) / 0.1)"
>
{{ $t(`serviceProperties`) }}
<q-btn <q-btn
:disable="readonly" :disable="readonly"
dense dense
flat
unelevated unelevated
outline class="q-px-sm"
class="q-mt-sm q-px-sm" color="info"
color="primary"
@click="$emit('serviceProperties')" @click="$emit('serviceProperties')"
> >
<Icon <Icon
icon="basil:settings-adjust-solid" icon="basil:settings-adjust-solid"
width="24px" width="24px"
class="q-mr-sm" class="q-mr-sm"
style="color: var(--brand-1)" style="color: hsl(var(--info-bg))"
/> />
{{ $t('properties') }} {{ $t('serviceProperties') }}
</q-btn> </q-btn>
</div> </div>
</div>
<div class="col-9 row"> <div class="col-12 row q-px-md q-py-xs items-center surface-1 scroll">
<div
v-if="serviceAttributes.additional.length > 0"
class="col q-gutter-sm row items-center"
>
<div <div
v-for="(p, index) in serviceAttributes.additional" v-if="serviceAttributes.additional.length > 0"
:key="index" class="row items-center q-gutter-sm items-center"
class="bordered q-px-sm surface-3"
style="border-radius: 6px"
> >
{{ optionStore.mapOption(p.fieldName ?? '') }} <div
v-for="(p, index) in serviceAttributes.additional"
:key="index"
class="bordered q-px-sm surface-3"
style="border-radius: 6px"
>
{{ optionStore.mapOption(p.fieldName ?? '') }}
</div>
</div> </div>
</div>
<div v-else class="col flex items-center app-text-muted"> <div v-else class="col flex items-center app-text-muted">
{{ $t('noProperties') }} {{ $t('noProperties') }}
</div>
</div> </div>
</div> </div>
</template> </template>

View file

@ -3,14 +3,15 @@ import { ref } from 'vue';
import ToggleButton from './button/ToggleButton.vue'; import ToggleButton from './button/ToggleButton.vue';
defineProps<{ defineProps<{
icon?: string;
fallbackCover?: string;
color?: string;
img?: string | null; img?: string | null;
bgColor?: string; icon?: string;
title?: string; title?: string;
caption?: string; caption?: string;
color?: string;
bgColor?: string;
toggleTitle?: string; toggleTitle?: string;
fallbackImg?: string;
fallbackCover?: string;
hideFade?: boolean; hideFade?: boolean;
hideActive?: boolean; hideActive?: boolean;
@ -67,12 +68,6 @@ const showOverlay = ref(false);
class="surface-1" class="surface-1"
style="border-radius: 50%; border: 4px solid var(--surface-1)" style="border-radius: 50%; border: 4px solid var(--surface-1)"
> >
<!-- <div
class="avatar__status"
style="z-index: 2"
:style="`${active ? 'background-color: hsla(var(--positive-bg) / 1)' : 'background-color: hsla(var(--text-mute) / 1)'}`"
></div> -->
<q-avatar <q-avatar
size="6rem" size="6rem"
font-size="3rem" font-size="3rem"
@ -89,7 +84,26 @@ const showOverlay = ref(false);
> >
<q-img id="profile-view" v-if="img" :src="img" :ratio="1"> <q-img id="profile-view" v-if="img" :src="img" :ratio="1">
<template #error> <template #error>
<q-img
v-if="fallbackImg"
:src="fallbackImg"
:ratio="1"
style="background-color: transparent"
>
<template #error>
<div
class="full-width full-height flex items-center justify-center"
style="background-color: transparent"
:style="{
color: `${color || 'white'}`,
}"
>
<q-icon :name="icon || 'mdi-account'" />
</div>
</template>
</q-img>
<div <div
v-else
class="full-width full-height flex items-center justify-center" class="full-width full-height flex items-center justify-center"
style="background-color: transparent" style="background-color: transparent"
:style="{ :style="{

View file

@ -12,7 +12,6 @@ import ProductCardComponent from 'components/04_product-service/ProductCardCompo
import StatCard from 'components/StatCardComponent.vue'; import StatCard from 'components/StatCardComponent.vue';
import DrawerInfo from 'components/DrawerInfo.vue'; import DrawerInfo from 'components/DrawerInfo.vue';
import BasicInformation from 'components/04_product-service/BasicInformation.vue'; import BasicInformation from 'components/04_product-service/BasicInformation.vue';
import FormDialog from 'components/FormDialog.vue';
import TooltipComponent from 'components/TooltipComponent.vue'; import TooltipComponent from 'components/TooltipComponent.vue';
import ButtonAddComponent from 'components/ButtonAddCompoent.vue'; import ButtonAddComponent from 'components/ButtonAddCompoent.vue';
import BasicInfoProduct from 'components/04_product-service/BasicInfoProduct.vue'; import BasicInfoProduct from 'components/04_product-service/BasicInfoProduct.vue';
@ -32,6 +31,7 @@ import DialogForm from 'components/DialogForm.vue';
import ProfileBanner from 'components/ProfileBanner.vue'; import ProfileBanner from 'components/ProfileBanner.vue';
import SideMenu from 'components/SideMenu.vue'; import SideMenu from 'components/SideMenu.vue';
import ImageUploadDialog from 'components/ImageUploadDialog.vue'; import ImageUploadDialog from 'components/ImageUploadDialog.vue';
import ToggleButton from 'src/components/button/ToggleButton.vue';
import useFlowStore from 'stores/flow'; import useFlowStore from 'stores/flow';
import useMyBranchStore from 'stores/my-branch'; import useMyBranchStore from 'stores/my-branch';
@ -134,7 +134,7 @@ const stat = ref<
color: 'orange', color: 'orange',
}, },
{ {
icon: 'mdi-folder', icon: 'mdi-shopping',
count: 0, count: 0,
label: 'product', label: 'product',
mode: 'product', mode: 'product',
@ -185,6 +185,7 @@ const treeProductTypeAndGroup = computed(() => {
return tempValue; return tempValue;
}); });
const profileFileImg = ref<File | null>(null); const profileFileImg = ref<File | null>(null);
const refImageUpload = ref<InstanceType<typeof ImageUploadDialog>>();
const inputSearch = ref(''); const inputSearch = ref('');
const inputSearchProductAndService = ref(''); const inputSearchProductAndService = ref('');
@ -394,7 +395,7 @@ const workNameRef = ref();
const selectProduct = ref<ProductList[]>([]); const selectProduct = ref<ProductList[]>([]);
const currentWorkIndex = ref<number>(0); const currentWorkIndex = ref<number>(0);
const currentServiceTab = ref('serviceInformation'); const currentServiceTab = ref(1);
const propertiesDialog = ref<boolean>(false); const propertiesDialog = ref<boolean>(false);
const totalProduct = ref<number>(0); const totalProduct = ref<number>(0);
@ -964,6 +965,7 @@ const prevProduct = ref<ProductCreate>({
function assignFormDataProduct(data: ProductList) { function assignFormDataProduct(data: ProductList) {
statusToggle.value = data.status === 'INACTIVE' ? false : true; statusToggle.value = data.status === 'INACTIVE' ? false : true;
profileUrl.value = `${baseUrl.value}/product/${data?.id}/image`; profileUrl.value = `${baseUrl.value}/product/${data?.id}/image`;
profileSubmit.value = true; profileSubmit.value = true;
prevProduct.value = { prevProduct.value = {
@ -1089,8 +1091,9 @@ async function submitService() {
async function submitProduct() { async function submitProduct() {
formDataProduct.value.productTypeId = currentIdType.value; formDataProduct.value.productTypeId = currentIdType.value;
if (profileSubmit.value) { if (profileFileImg.value) {
formDataProduct.value.image = imageProduct.value; formDataProduct.value.image = profileFileImg.value;
// formDataProduct.value.image = imageProduct.value;
} }
if (dialogProduct.value) { if (dialogProduct.value) {
@ -1282,6 +1285,18 @@ function handleHold(node: ProductGroup) {
}; };
} }
async function handleImageUpload(file: File | null, url: string | null) {
// if (!infoProductEdit.value && !dialogProductEdit.value) {
// infoProductEdit.value = true;
// await submitProduct();
// infoProductEdit.value = false;
// }
// if (infoProductEdit.value && !dialogProductEdit.value) {
// await submitProduct();
// }
// imageDialog.value = false;
}
onMounted(async () => { onMounted(async () => {
utilsStore.currentTitle.title = 'mainProductTitle'; utilsStore.currentTitle.title = 'mainProductTitle';
utilsStore.currentTitle.path = [ utilsStore.currentTitle.path = [
@ -1310,6 +1325,7 @@ watch(productMode, () => {
const tmp: typeof utilsStore.currentTitle.path = [ const tmp: typeof utilsStore.currentTitle.path = [
{ {
text: 'manage', text: 'manage',
i18n: true,
handler: () => { handler: () => {
productMode.value = 'group'; productMode.value = 'group';
expandedTree.value = []; expandedTree.value = [];
@ -1322,6 +1338,7 @@ watch(productMode, () => {
if (productMode.value === 'type' || productMode.value === 'service') { if (productMode.value === 'type' || productMode.value === 'service') {
tmp.push({ tmp.push({
text: 'productGroup', text: 'productGroup',
i18n: true,
argsi18n: { name: pathGroupName.value }, argsi18n: { name: pathGroupName.value },
handler: () => { handler: () => {
productMode.value = 'type'; productMode.value = 'type';
@ -1332,7 +1349,11 @@ watch(productMode, () => {
}); });
} }
if (productMode.value === 'service') { if (productMode.value === 'service') {
tmp.push({ text: 'productType', argsi18n: { name: pathTypeName.value } }); tmp.push({
text: 'productType',
i18n: true,
argsi18n: { name: pathTypeName.value },
});
} }
utilsStore.currentTitle.path = tmp; utilsStore.currentTitle.path = tmp;
@ -1435,7 +1456,7 @@ watch(
clearFormGroup(); clearFormGroup();
clearFormService(); clearFormService();
await fetchListOfOptionBranch(); await fetchListOfOptionBranch();
currentServiceTab = 'serviceInformation'; currentServiceTab = 1;
dialogService = true; dialogService = true;
} }
" "
@ -1447,7 +1468,7 @@ watch(
{{ $t('dataSum') }} {{ $t('dataSum') }}
<q-btn <q-btn
class="q-ml-xs" class="q-ml-xs"
icon="mdi-pin" icon="mdi-pin-outline"
color="primary" color="primary"
size="sm" size="sm"
flat flat
@ -2349,16 +2370,14 @@ watch(
<q-item dense> <q-item dense>
<q-item-section class="q-py-sm"> <q-item-section class="q-py-sm">
<div class="q-pa-sm surface-2 rounded"> <div
<q-toggle class="q-pa-sm surface-2 rounded flex items-center"
color="positive" >
<ToggleButton
two-way
:id="`view-detail-btn-${props.row.name}-status`" :id="`view-detail-btn-${props.row.name}-status`"
dense :model-value="
size="sm"
:label="
props.row.status !== 'INACTIVE' props.row.status !== 'INACTIVE'
? $t('switchOnLabel')
: $t('switchOffLabel')
" "
@click=" @click="
async () => { async () => {
@ -2368,10 +2387,14 @@ watch(
); );
} }
" "
:model-value="
props.row.status !== 'INACTIVE'
"
/> />
<span class="q-pl-md">
{{
props.row.status !== 'INACTIVE'
? $t('switchOnLabel')
: $t('switchOffLabel')
}}
</span>
</div> </div>
</q-item-section> </q-item-section>
</q-item> </q-item>
@ -2896,15 +2919,27 @@ watch(
class="table__icon" class="table__icon"
:class="`icon-color-${productAndServiceTab === 'product' ? 'green' : 'orange'}`" :class="`icon-color-${productAndServiceTab === 'product' ? 'green' : 'orange'}`"
> >
<q-icon <q-avatar size="md">
size="md" <q-img
style="scale: 0.8" class="text-center"
:name=" :ratio="1"
productAndServiceTab === 'product' :src="`
? 'mdi-folder' ${props.row.imageUrl ?? null}
: 'mdi-server-network' `"
" >
/> <template #error>
<q-icon
size="sm"
:name="
productAndServiceTab === 'product'
? 'mdi-shopping'
: 'mdi-server-network'
"
style="color: var(--teal-10); top: 10%"
/>
</template>
</q-img>
</q-avatar>
</div> </div>
</div> </div>
<div class="col"> <div class="col">
@ -3170,16 +3205,15 @@ watch(
<q-item dense> <q-item dense>
<q-item-section class="q-py-sm"> <q-item-section class="q-py-sm">
<div class="q-pa-sm surface-2 rounded"> <div
<q-toggle class="q-pa-sm surface-2 rounded flex items-center"
color="positive" >
<ToggleButton
two-way
:id="`view-detail-btn-${props.row.name}-status`" :id="`view-detail-btn-${props.row.name}-status`"
dense :model-value="
size="sm" props.row.status === 'CREATED' ||
:label=" props.row.status === 'ACTIVE'
props.row.status !== 'INACTIVE'
? $t('switchOnLabel')
: $t('switchOffLabel')
" "
@click=" @click="
() => { () => {
@ -3190,11 +3224,14 @@ watch(
); );
} }
" "
:model-value="
props.row.status === 'CREATED' ||
props.row.status === 'ACTIVE'
"
/> />
<span class="q-pl-md">
{{
props.row.status !== 'INACTIVE'
? $t('switchOnLabel')
: $t('switchOffLabel')
}}
</span>
</div> </div>
</q-item-section> </q-item-section>
</q-item> </q-item>
@ -3351,8 +3388,9 @@ watch(
hideFade hideFade
hideActive hideActive
useToggle useToggle
:img="`/images/product-service-${productMode}-avatar-add${productMode === 'type' ? ($q.dark.isActive ? '-d' : '-l') : ''}.png`"
:toggleTitle="$t('formDialogTitleUseStatus')" :toggleTitle="$t('formDialogTitleUseStatus')"
:icon="productMode === 'group' ? 'mdi-folder' : 'mdi-folder-table'" :icon="productMode === 'group' ? 'mdi-folder-plus' : 'mdi-folder-table'"
:title="formDataGroup.name" :title="formDataGroup.name"
:caption="formDataGroup.code" :caption="formDataGroup.code"
:menu="[ :menu="[
@ -3428,9 +3466,7 @@ watch(
</div> </div>
</div> </div>
</DialogForm> </DialogForm>
<DrawerInfo <DrawerInfo
:hideAction="!currentStatusProduct"
ref="formDialogRef" ref="formDialogRef"
v-model:drawerOpen="drawerInfo" v-model:drawerOpen="drawerInfo"
:title=" :title="
@ -3559,7 +3595,7 @@ watch(
</InfoForm> </InfoForm>
</DrawerInfo> </DrawerInfo>
<FormDialog <DialogForm
v-model:modal="dialogProductServiceType" v-model:modal="dialogProductServiceType"
:title="'สร้างสินค้าและบริการ'" :title="'สร้างสินค้าและบริการ'"
no-footer no-footer
@ -3585,9 +3621,9 @@ watch(
/> />
</div> </div>
</template> </template>
</FormDialog> </DialogForm>
<FormDialog <DialogForm
v-model:modal="dialogTotalProduct" v-model:modal="dialogTotalProduct"
noAddress noAddress
noAppBox noAppBox
@ -3704,7 +3740,7 @@ watch(
</AppBox> </AppBox>
</div> </div>
</div> </div>
</FormDialog> </DialogForm>
<!-- Add Product --> <!-- Add Product -->
<DialogForm <DialogForm
@ -3737,7 +3773,7 @@ watch(
useToggle useToggle
hideActive hideActive
:toggleTitle="$t('formDialogTitleUseStatus')" :toggleTitle="$t('formDialogTitleUseStatus')"
img="/images/product-avatar.png" :img="profileUrl || '/images/product-avatar-add.png'"
fallbackCover="/images/product-banner.png" fallbackCover="/images/product-banner.png"
bgColor="#ebf1ee" bgColor="#ebf1ee"
:menu="[ :menu="[
@ -3747,6 +3783,8 @@ watch(
bgColor: 'var(--surface-1)', bgColor: 'var(--surface-1)',
}, },
]" ]"
@view="imageDialog = true"
@edit="refImageUpload && refImageUpload.browse()"
/> />
</div> </div>
@ -3773,7 +3811,7 @@ watch(
> >
<span class="full-width q-py-sm" style="padding-inline: 20px"> <span class="full-width q-py-sm" style="padding-inline: 20px">
{{ {{
v === 0 v === 1
? $t('formDialogTitleInformation') ? $t('formDialogTitleInformation')
: $t('priceInformation') : $t('priceInformation')
}} }}
@ -3810,7 +3848,7 @@ watch(
</DialogForm> </DialogForm>
<!-- edit product --> <!-- edit product -->
<FormDialog <DialogForm
:edit="!(formDataProduct.status === 'INACTIVE')" :edit="!(formDataProduct.status === 'INACTIVE')"
:isEdit="infoProductEdit" :isEdit="infoProductEdit"
v-model:modal="dialogProductEdit" v-model:modal="dialogProductEdit"
@ -3836,12 +3874,98 @@ watch(
" "
:close=" :close="
() => { () => {
infoProductEdit = false;
dialogProductEdit = false; dialogProductEdit = false;
flowStore.rotate(); flowStore.rotate();
} }
" "
> >
<template #prepend> <div class="q-mx-lg q-mt-lg">
<ProfileBanner
active
hideFade
useToggle
hideActive
icon="mdi-shopping"
fallbackImg="/images/product-avatar.png"
color="var(--teal-10)"
:readonly="!infoProductEdit"
:toggleTitle="$t('formDialogTitleUseStatus')"
:img="profileUrl || '/images/product-avatar.png'"
fallbackCover="/images/product-banner.png"
bgColor="#ebf1ee"
:menu="[
{
icon: 'mdi-office-building-outline',
color: 'hsl(var(--info-bg))',
bgColor: 'var(--surface-1)',
},
]"
@view="imageDialog = true"
@edit="refImageUpload && refImageUpload.browse()"
/>
</div>
<div
class="col surface-1 q-ma-lg rounded bordered scroll row relative-position"
id="group-form"
>
<div
class="col"
style="height: 100%; max-height: 100; overflow-y: auto"
v-if="$q.screen.gt.sm"
>
<div class="q-py-md q-pl-md q-pr-sm">
<q-item
v-for="v in 2"
:key="v"
dense
clickable
class="no-padding items-center rounded full-width"
:class="{ 'q-mt-xs': v > 1 }"
active-class="product-form-active"
:active="productTab === v"
@click="productTab = v"
>
<span class="full-width q-py-sm" style="padding-inline: 20px">
{{
v === 1
? $t('formDialogTitleInformation')
: $t('priceInformation')
}}
</span>
</q-item>
</div>
</div>
<div
class="col-12 col-md-10 q-py-md q-pr-md q-pl-sm"
id="customer-form-content"
style="height: 100%; max-height: 100%; overflow-y: auto"
>
<BasicInfoProduct
v-if="productTab === 1"
:readonly="!infoProductEdit"
v-model:options-branch="branchOption"
v-model:registered-branch-id="formDataProduct.registeredBranchId"
v-model:detail="formDataProduct.detail"
v-model:remark="formDataProduct.remark"
v-model:name="formDataProduct.name"
v-model:code="formDataProduct.code"
v-model:process="formDataProduct.process"
dense
separator
/>
<PriceDataComponent
v-if="productTab === 2"
:readonly="!infoProductEdit"
v-model:price="formDataProduct.price"
v-model:agent-price="formDataProduct.agentPrice"
v-model:service-charge="formDataProduct.serviceCharge"
dense
/>
</div>
</div>
<!-- <template #prepend>
<ProfileUpload <ProfileUpload
prefix-id="form-dialog-product" prefix-id="form-dialog-product"
isProduct isProduct
@ -3876,18 +4000,16 @@ watch(
v-model:service-charge="formDataProduct.serviceCharge" v-model:service-charge="formDataProduct.serviceCharge"
dense dense
/> />
</template> </template> -->
</FormDialog> </DialogForm>
<!-- add service --> <!-- add service -->
<FormDialog <DialogForm
no-address no-address
no-app-box no-app-box
height="95vh" height="95vh"
:title="$t('addService')" :title="$t('addService')"
v-model:modal="dialogService" v-model:modal="dialogService"
:tabs-list="serviceTab"
v-model:current-tab="currentServiceTab"
:submit=" :submit="
() => { () => {
submitService(); submitService();
@ -3901,8 +4023,8 @@ watch(
} }
" "
> >
<template #prepend> <!-- :tabs-list="serviceTab" -->
<ProfileUpload <!-- <ProfileUpload
prefix-id="form-dialog-service" prefix-id="form-dialog-service"
isService isService
v-model:url-profile="profileUrl" v-model:url-profile="profileUrl"
@ -3910,15 +4032,62 @@ watch(
v-model:profile-submit="profileSubmit" v-model:profile-submit="profileSubmit"
@cancel-file="inputFile.value = ''" @cancel-file="inputFile.value = ''"
@input-file="inputFile.click()" @input-file="inputFile.click()"
/> -->
<div class="q-mx-lg q-mt-lg">
<ProfileBanner
hideFade
useToggle
hideActive
:toggleTitle="$t('formDialogTitleUseStatus')"
:img="profileUrl || '/images/product-avatar-add.png'"
fallbackCover="/images/product-banner.png"
bgColor="#ebf1ee"
:menu="[
{
icon: 'mdi-office-building-outline',
color: 'hsl(var(--info-bg))',
bgColor: 'var(--surface-1)',
},
]"
@view="imageDialog = true"
@edit="refImageUpload && refImageUpload.browse()"
/> />
</template> </div>
<div <div
v-if="currentServiceTab === 'serviceInformation'" class="col surface-1 q-mx-lg q-mt-lg q-mb-md rounded bordered scroll row relative-position"
class="col-md-10 col-sm-12" id="group-form"
> >
<div class="surface-1 rounded bordered q-pa-lg full-width row"> <div
class="col"
style="height: 100%; max-height: 100; overflow-y: auto"
v-if="$q.screen.gt.sm"
>
<div class="q-py-md q-pl-md q-pr-sm">
<q-item
v-for="v in 2"
:key="v"
dense
clickable
class="no-padding items-center rounded full-width"
:class="{ 'q-mt-xs': v > 1 }"
active-class="product-form-active"
:active="currentServiceTab === v"
@click="currentServiceTab = v"
>
<span class="full-width q-py-sm" style="padding-inline: 20px">
{{ v === 1 ? $t('serviceInformation') : $t('workInformation') }}
</span>
</q-item>
</div>
</div>
<div
class="col-12 col-md-10 q-py-md q-pr-md q-pl-sm"
id="customer-form-content"
style="height: 100%; max-height: 100%; overflow-y: auto"
>
<BasicInformation <BasicInformation
v-if="currentServiceTab === 1"
dense dense
service service
v-model:options-branch="branchOption" v-model:options-branch="branchOption"
@ -3929,52 +4098,51 @@ watch(
v-model:service-description="formDataProductService.detail" v-model:service-description="formDataProductService.detail"
v-model:service-name-th="formDataProductService.name" v-model:service-name-th="formDataProductService.name"
/> />
</div>
<div class="surface-1 rounded bordered q-mt-md q-pa-lg row"> <FormServiceWork
<FormServiceProperties v-if="currentServiceTab === 2"
v-model:service-attributes="formDataProductService.attributes" v-model:work-items="workItems"
@service-properties=" dense
@addProduct="
async (index) => {
await fetchListOfProductIsAdd(currentIdType);
currentWorkIndex = index;
dialogTotalProduct = true;
}
"
@manage-work-name="
() => { () => {
tempValueProperties = formDataProductService.attributes; manageWorkNameDialog = true;
openPropertiesDialog('service'); }
"
@work-properties="
(index) => {
currentWorkIndex = index;
tempValueProperties = workItems[index].attributes;
openPropertiesDialog('work');
} }
" "
/> />
</div> </div>
</div> </div>
<div <div
v-if="currentServiceTab === 'workInformation'" class="col-2 surface-1 q-mx-lg q-mb-lg rounded bordered row"
class="surface-1 rounded bordered col-md-10 col-sm-12 q-pa-lg" v-if="currentServiceTab === 1"
> >
<FormServiceWork <FormServiceProperties
v-model:work-items="workItems" v-model:service-attributes="formDataProductService.attributes"
dense @service-properties="
@addProduct="
async (index) => {
await fetchListOfProductIsAdd(currentIdType);
currentWorkIndex = index;
dialogTotalProduct = true;
}
"
@manage-work-name="
() => { () => {
manageWorkNameDialog = true; tempValueProperties = formDataProductService.attributes;
} openPropertiesDialog('service');
"
@work-properties="
(index) => {
currentWorkIndex = index;
tempValueProperties = workItems[index].attributes;
openPropertiesDialog('work');
} }
" "
/> />
</div> </div>
</FormDialog> </DialogForm>
<!-- service properties --> <!-- service properties -->
<FormDialog <DialogForm
no-address no-address
no-app-box no-app-box
height="75vh" height="75vh"
@ -4003,10 +4171,10 @@ watch(
v-model:properties-option="propertiesOption" v-model:properties-option="propertiesOption"
v-model:form-service-properties="tempValueProperties" v-model:form-service-properties="tempValueProperties"
/> />
</FormDialog> </DialogForm>
<!-- manage work name --> <!-- manage work name -->
<FormDialog <DialogForm
no-address no-address
no-app-box no-app-box
no-footer no-footer
@ -4023,19 +4191,17 @@ watch(
@edit="editWork" @edit="editWork"
@add="createWork" @add="createWork"
/> />
</FormDialog> </DialogForm>
<!-- edit service --> <!-- edit service -->
<FormDialog <DialogForm
no-address no-address
:no-app-box="currentServiceTab !== 'workInformation'"
:edit="!(formDataProductService.status === 'INACTIVE')" :edit="!(formDataProductService.status === 'INACTIVE')"
height="95vh" height="95vh"
:isEdit="infoServiceEdit" :isEdit="infoServiceEdit"
:title="$t('service')" :title="$t('service')"
:tabs-list="serviceTab" :tabs-list="serviceTab"
v-model:modal="dialogServiceEdit" v-model:modal="dialogServiceEdit"
v-model:current-tab="currentServiceTab"
:submit=" :submit="
() => { () => {
submitService(); submitService();
@ -4076,14 +4242,11 @@ watch(
/> />
</template> </template>
<div <div v-if="currentServiceTab === 1" class="col-md-10 col-sm-12">
v-if="currentServiceTab === 'serviceInformation'"
class="col-md-10 col-sm-12"
>
<div class="surface-1 rounded bordered q-pa-lg full-width row"> <div class="surface-1 rounded bordered q-pa-lg full-width row">
<BasicInformation <BasicInformation
:readonly="!infoServiceEdit" :readonly="!infoServiceEdit"
v-if="currentServiceTab === 'serviceInformation'" v-if="currentServiceTab === 1"
dense dense
service service
v-model:options-branch="branchOption" v-model:options-branch="branchOption"
@ -4113,7 +4276,7 @@ watch(
<FormServiceWork <FormServiceWork
:readonly="!infoServiceEdit" :readonly="!infoServiceEdit"
v-model:work-items="workItems" v-model:work-items="workItems"
v-if="currentServiceTab === 'workInformation'" v-if="currentServiceTab === 2"
dense dense
@addProduct=" @addProduct="
async (index) => { async (index) => {
@ -4132,7 +4295,7 @@ watch(
" "
/> />
</template> </template>
</FormDialog> </DialogForm>
<q-dialog v-model="holdDialog" position="bottom"> <q-dialog v-model="holdDialog" position="bottom">
<div class="surface-1 full-width rounded column q-pb-md"> <div class="surface-1 full-width rounded column q-pb-md">
@ -4248,12 +4411,11 @@ watch(
<q-item clickable v-ripple> <q-item clickable v-ripple>
<q-item-section avatar> <q-item-section avatar>
<q-toggle <ToggleButton
color="positive" two-way
dense
:id="`view-detail-btn-${currentNode.name}-status`" :id="`view-detail-btn-${currentNode.name}-status`"
size="sm" :model-value="currentNode.status !== 'INACTIVE'"
@click.stop=" @click="
async () => { async () => {
if (!currentNode) return; if (!currentNode) return;
if (currentNode.type === 'type') { if (currentNode.type === 'type') {
@ -4278,7 +4440,6 @@ watch(
} }
} }
" "
:model-value="currentNode.status !== 'INACTIVE'"
/> />
</q-item-section> </q-item-section>
<q-item-section> <q-item-section>
@ -4297,31 +4458,22 @@ watch(
ref="refImageUpload" ref="refImageUpload"
v-model:dialogState="imageDialog" v-model:dialogState="imageDialog"
v-model:file="profileFileImg" v-model:file="profileFileImg"
v-model:image-url="profileUrl"
:hidden-footer="!infoProductEdit"
clearButton clearButton
@save="handleImageUpload"
> >
<template #error> <template #error>
<div class="full-height full-width" style="background: white"> <div class="full-height full-width" style="background: white">
<div <div
class="full-height full-width flex justify-center items-center" class="full-height full-width flex justify-center items-center"
:style="`background: hsla(var(${ style="background: #ebf1ee"
productMode === 'group'
? '--pink-6'
: $q.dark.isActive
? '--violet-10'
: '--violet-11'
}-hsl)/0.1)`"
> >
<q-icon <q-img
size="15rem" src="/images/product-avatar.png"
:name="productMode === 'group' ? 'mdi-folder' : 'mdi-folder-table'" fit="contain"
:style="`color: hsla(var(${ style="height: 100%"
productMode === 'group' />
? '--pink-6'
: $q.dark.isActive
? '--violet-10'
: '--violet-11'
}-hsl)/1)`"
></q-icon>
</div> </div>
</div> </div>
</template> </template>
@ -4386,7 +4538,6 @@ watch(
color: hsla(var(--_color) / 1); color: hsla(var(--_color) / 1);
border-radius: 50%; border-radius: 50%;
padding: var(--size-1);
position: relative; position: relative;
transform: rotate(45deg); transform: rotate(45deg);
@ -4407,6 +4558,14 @@ watch(
transform: rotate(-45deg); transform: rotate(-45deg);
color: hsla(var(--_branch-card-bg) / 1); color: hsla(var(--_branch-card-bg) / 1);
} }
&:deep(.q-img) {
transform: rotate(-45deg);
&:deep(.q-icon) {
transform: rotate(0deg);
}
}
} }
.tags { .tags {