refactor: แสดง tree
This commit is contained in:
parent
382ebe6e06
commit
7dc01a301d
1 changed files with 328 additions and 150 deletions
|
|
@ -55,6 +55,7 @@ import {
|
||||||
Attributes,
|
Attributes,
|
||||||
ServiceAndProduct,
|
ServiceAndProduct,
|
||||||
} from 'src/stores/product-service/types';
|
} from 'src/stores/product-service/types';
|
||||||
|
import { computed } from 'vue';
|
||||||
|
|
||||||
const flowStore = useFlowStore();
|
const flowStore = useFlowStore();
|
||||||
const utilsStore = useUtilsStore();
|
const utilsStore = useUtilsStore();
|
||||||
|
|
@ -94,7 +95,8 @@ const {
|
||||||
fetchListProductAndService,
|
fetchListProductAndService,
|
||||||
} = productServiceStore;
|
} = productServiceStore;
|
||||||
|
|
||||||
const { workNameItems } = storeToRefs(productServiceStore);
|
const { workNameItems, recordTreeProductType } =
|
||||||
|
storeToRefs(productServiceStore);
|
||||||
|
|
||||||
const stat = ref<
|
const stat = ref<
|
||||||
{
|
{
|
||||||
|
|
@ -138,6 +140,30 @@ const stat = ref<
|
||||||
const { t } = useI18n();
|
const { t } = useI18n();
|
||||||
const baseUrl = ref<string>(import.meta.env.VITE_API_BASE_URL);
|
const baseUrl = ref<string>(import.meta.env.VITE_API_BASE_URL);
|
||||||
|
|
||||||
|
const expandedTree = ref<string[]>([]);
|
||||||
|
const editByTree = ref<'group' | 'type' | undefined>();
|
||||||
|
const treeProductTypeAndGroup = computed(() => {
|
||||||
|
const tempValue =
|
||||||
|
productGroup.value?.map((item) => {
|
||||||
|
return {
|
||||||
|
...item,
|
||||||
|
type: 'group',
|
||||||
|
children:
|
||||||
|
item.id === currentId.value
|
||||||
|
? recordTreeProductType.value[currentId.value]?.map((item) => ({
|
||||||
|
...item,
|
||||||
|
type: 'type',
|
||||||
|
})) ?? []
|
||||||
|
: recordTreeProductType.value[item.id]?.map((item) => ({
|
||||||
|
...item,
|
||||||
|
type: 'type',
|
||||||
|
})) ?? [],
|
||||||
|
};
|
||||||
|
}) ?? [];
|
||||||
|
|
||||||
|
return tempValue;
|
||||||
|
});
|
||||||
|
|
||||||
const inputSearch = ref('');
|
const inputSearch = ref('');
|
||||||
const inputSearchProductAndService = ref('');
|
const inputSearchProductAndService = ref('');
|
||||||
|
|
||||||
|
|
@ -747,21 +773,42 @@ async function deleteProductById(productId?: string) {
|
||||||
persistent: true,
|
persistent: true,
|
||||||
message: t('deleteConfirmMessage'),
|
message: t('deleteConfirmMessage'),
|
||||||
action: async () => {
|
action: async () => {
|
||||||
if (productMode.value === 'type') {
|
if (editByTree !== undefined) {
|
||||||
// Product Type
|
if (editByTree.value === 'type') {
|
||||||
await deleteProductServiceType(productId ?? currentIdType.value);
|
// Product Type
|
||||||
await fetchListType();
|
await deleteProductServiceType(productId ?? currentIdType.value);
|
||||||
}
|
await fetchListType();
|
||||||
if (productMode.value === 'group') {
|
|
||||||
// Product Group
|
|
||||||
const res = await deleteProductService(productId ?? currentId.value);
|
|
||||||
if (res) {
|
|
||||||
}
|
}
|
||||||
await fetchListGroups();
|
if (editByTree.value === 'group') {
|
||||||
|
// Product Group
|
||||||
|
const res = await deleteProductService(productId ?? currentId.value);
|
||||||
|
if (res) {
|
||||||
|
}
|
||||||
|
await fetchListGroups();
|
||||||
|
}
|
||||||
|
|
||||||
|
flowStore.rotate();
|
||||||
|
calculateStats();
|
||||||
|
editByTree.value = undefined;
|
||||||
|
drawerInfo.value = false;
|
||||||
|
} else {
|
||||||
|
if (productMode.value === 'type') {
|
||||||
|
// Product Type
|
||||||
|
await deleteProductServiceType(productId ?? currentIdType.value);
|
||||||
|
await fetchListType();
|
||||||
|
}
|
||||||
|
if (productMode.value === 'group') {
|
||||||
|
// Product Group
|
||||||
|
const res = await deleteProductService(productId ?? currentId.value);
|
||||||
|
if (res) {
|
||||||
|
}
|
||||||
|
await fetchListGroups();
|
||||||
|
}
|
||||||
|
|
||||||
|
flowStore.rotate();
|
||||||
|
calculateStats();
|
||||||
|
drawerInfo.value = false;
|
||||||
}
|
}
|
||||||
flowStore.rotate();
|
|
||||||
calculateStats();
|
|
||||||
drawerInfo.value = false;
|
|
||||||
},
|
},
|
||||||
cancel: () => {},
|
cancel: () => {},
|
||||||
});
|
});
|
||||||
|
|
@ -1163,6 +1210,10 @@ onMounted(async () => {
|
||||||
|
|
||||||
calculateStats();
|
calculateStats();
|
||||||
await fetchListGroups();
|
await fetchListGroups();
|
||||||
|
|
||||||
|
console.log(treeProductTypeAndGroup.value);
|
||||||
|
|
||||||
|
console.log('ddd');
|
||||||
flowStore.rotate();
|
flowStore.rotate();
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
@ -1341,153 +1392,248 @@ watch(inputSearchProductAndService, async () => {
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="col" style="position: relative">
|
<div class="col" style="position: relative">
|
||||||
<div class="scroll" style="position: absolute; inset: 0">
|
<div
|
||||||
<!-- <q-tree
|
class="q-pa-md scroll surface-1"
|
||||||
:nodes="treeData"
|
style="position: absolute; inset: 0"
|
||||||
node-key="id"
|
>
|
||||||
label-key="name"
|
<q-tree
|
||||||
children-key="branch"
|
:nodes="treeProductTypeAndGroup"
|
||||||
style="color: var(--foreground)"
|
node-key="id"
|
||||||
>
|
label-key="name"
|
||||||
<template #default-header="{ node }">
|
children-key="children"
|
||||||
<div
|
v-model:expanded="expandedTree"
|
||||||
class="row items-center justify-between full-width no-wrap"
|
>
|
||||||
>
|
<template #default-header="{ node }">
|
||||||
<span>{{ node.name }}</span>
|
<div
|
||||||
<div
|
@click.stop="
|
||||||
class="row q-gutter-xs items-center no-wrap"
|
async () => {
|
||||||
@click.stop
|
if (node.type === 'group' && node._count.type > 0) {
|
||||||
>
|
pathGroupName = node.name;
|
||||||
|
currentId = node.id;
|
||||||
|
productMode = 'type';
|
||||||
|
await fetchListType();
|
||||||
|
expandedTree.push(node.id);
|
||||||
|
flowStore.rotate();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
"
|
||||||
|
class="column full-width items-center no-wrap"
|
||||||
|
:class="{
|
||||||
|
'cursor-pointer':
|
||||||
|
node.type === 'group' && node._count.type > 0,
|
||||||
|
}"
|
||||||
|
>
|
||||||
|
<div class="col row full-width">
|
||||||
|
<div class="col-9">{{ node.name }}</div>
|
||||||
|
<div class="col no-wrap">
|
||||||
<q-btn
|
<q-btn
|
||||||
v-if="node.isHeadOffice"
|
icon="mdi-eye-outline"
|
||||||
:id="`create-sub-branch-btn-${node.name}`"
|
:id="`btn-tree-eye-${node.name}`"
|
||||||
@click.stop=""
|
size="sm"
|
||||||
icon="mdi-file-plus-outline"
|
dense
|
||||||
size="sm"
|
round
|
||||||
dense
|
flat
|
||||||
round
|
@click.stop="
|
||||||
flat
|
() => {
|
||||||
|
if (node.type === 'type') {
|
||||||
|
editByTree = 'type';
|
||||||
|
currentStatusProduct =
|
||||||
|
node.status === 'INACTIVE';
|
||||||
|
clearFormGroup();
|
||||||
|
currentIdType = node.id;
|
||||||
|
assignFormDataGroup(node);
|
||||||
|
isEdit = false;
|
||||||
|
drawerInfo = true;
|
||||||
|
}
|
||||||
|
if (node.type === 'group') {
|
||||||
|
editByTree = 'group';
|
||||||
|
currentStatusProduct =
|
||||||
|
node.status === 'INACTIVE';
|
||||||
|
clearFormGroup();
|
||||||
|
assignFormDataGroup(node);
|
||||||
|
isEdit = false;
|
||||||
|
currentId = node.id;
|
||||||
|
drawerInfo = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
"
|
||||||
/>
|
/>
|
||||||
|
|
||||||
<q-btn
|
<q-btn
|
||||||
:id="`view-detail-btn-${node.name}`"
|
icon="mdi-dots-vertical"
|
||||||
icon="mdi-dots-vertical"
|
:id="`btn-tree-dots-${node.name}`"
|
||||||
size="sm"
|
size="sm"
|
||||||
dense
|
dense
|
||||||
round
|
round
|
||||||
flat
|
flat
|
||||||
|
@click.stop
|
||||||
|
:key="node.id"
|
||||||
|
>
|
||||||
|
<q-menu class="bordered">
|
||||||
|
<q-list v-close-popup>
|
||||||
|
<q-item
|
||||||
|
v-close-popup
|
||||||
|
clickable
|
||||||
|
:id="`view-detail-btn-${node.name}-view`"
|
||||||
|
@click.stop="
|
||||||
|
() => {
|
||||||
|
editByTree = node.type;
|
||||||
|
if (node.type === 'type') {
|
||||||
|
currentStatusProduct =
|
||||||
|
node.status === 'INACTIVE';
|
||||||
|
clearFormGroup();
|
||||||
|
currentIdType = node.id;
|
||||||
|
assignFormDataGroup(node);
|
||||||
|
isEdit = false;
|
||||||
|
drawerInfo = true;
|
||||||
|
}
|
||||||
|
if (node.type === 'group') {
|
||||||
|
currentStatusProduct =
|
||||||
|
node.status === 'INACTIVE';
|
||||||
|
clearFormGroup();
|
||||||
|
assignFormDataGroup(node);
|
||||||
|
isEdit = false;
|
||||||
|
currentId = node.id;
|
||||||
|
drawerInfo = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
"
|
||||||
|
dense
|
||||||
|
class="row q-py-sm"
|
||||||
|
style="white-space: nowrap"
|
||||||
>
|
>
|
||||||
<q-menu class="bordered">
|
<q-icon
|
||||||
<q-list v-close-popup>
|
|
||||||
<q-item
|
|
||||||
:id="`view-detail-btn-${node.name}-view`"
|
|
||||||
@click.stop="
|
|
||||||
|
|
||||||
"
|
|
||||||
clickable
|
|
||||||
dense
|
|
||||||
class="row q-py-sm"
|
|
||||||
style="white-space: nowrap"
|
|
||||||
>
|
|
||||||
<q-icon
|
|
||||||
name="mdi-eye-outline"
|
name="mdi-eye-outline"
|
||||||
class="col-3"
|
class="col-3"
|
||||||
size="xs"
|
size="xs"
|
||||||
style="color: hsl(var(--green-6-hsl))"
|
style="color: hsl(var(--green-6-hsl))"
|
||||||
/>
|
/>
|
||||||
<span
|
<span class="col-9 q-px-md flex items-center">
|
||||||
class="col-9 q-px-md flex items-center"
|
|
||||||
>
|
|
||||||
{{ $t('viewDetail') }}
|
{{ $t('viewDetail') }}
|
||||||
</span>
|
</span>
|
||||||
</q-item>
|
</q-item>
|
||||||
|
|
||||||
<q-item
|
<q-item
|
||||||
:id="`view-detail-btn-${node.name}-edit`"
|
:id="`view-detail-btn-${node.name}-edit`"
|
||||||
clickable
|
v-close-popup
|
||||||
dense
|
clickable
|
||||||
class="row q-py-sm"
|
dense
|
||||||
style="white-space: nowrap"
|
class="row q-py-sm"
|
||||||
@click="
|
style="white-space: nowrap"
|
||||||
() => {
|
@click.stop="
|
||||||
|
() => {
|
||||||
}
|
editByTree = node.type;
|
||||||
"
|
if (node.type === 'type') {
|
||||||
>
|
clearFormGroup();
|
||||||
<q-icon
|
currentIdType = node.id;
|
||||||
name="mdi-pencil-outline"
|
assignFormDataGroup(node);
|
||||||
class="col-3"
|
isEdit = true;
|
||||||
size="xs"
|
drawerInfo = true;
|
||||||
style="color: hsl(var(--cyan-6-hsl))"
|
}
|
||||||
/>
|
if (node.type === 'group') {
|
||||||
<span
|
clearFormGroup();
|
||||||
class="col-9 q-px-md flex items-center"
|
assignFormDataGroup(node);
|
||||||
>
|
isEdit = true;
|
||||||
{{ $t('edit') }}
|
currentId = node.id;
|
||||||
</span>
|
|
||||||
</q-item>
|
|
||||||
<q-item
|
|
||||||
:id="`view-detail-btn-${node.name}-delete`"
|
|
||||||
dense
|
|
||||||
:clickable="node.status === 'CREATED'"
|
|
||||||
class="row"
|
|
||||||
:class="{
|
|
||||||
'surface-3': node.status !== 'CREATED',
|
|
||||||
'app-text-muted':
|
|
||||||
node.status !== 'CREATED',
|
|
||||||
}"
|
|
||||||
style="white-space: nowrap"
|
|
||||||
@click=""
|
|
||||||
>
|
|
||||||
<q-icon
|
|
||||||
name="mdi-trash-can-outline"
|
|
||||||
size="xs"
|
|
||||||
class="col-3"
|
|
||||||
:class="{
|
|
||||||
'app-text-negative':
|
|
||||||
node.status === 'CREATED',
|
|
||||||
}"
|
|
||||||
/>
|
|
||||||
<span
|
|
||||||
class="col-9 q-px-md flex items-center"
|
|
||||||
>
|
|
||||||
{{ $t('delete') }}
|
|
||||||
</span>
|
|
||||||
</q-item>
|
|
||||||
|
|
||||||
<q-item dense>
|
drawerInfo = true;
|
||||||
<q-item-section class="q-py-sm">
|
}
|
||||||
<div class="q-pa-sm surface-2 rounded">
|
}
|
||||||
<q-toggle
|
"
|
||||||
:id="`view-detail-btn-${node.name}-status`"
|
>
|
||||||
dense
|
<q-icon
|
||||||
size="sm"
|
name="mdi-pencil-outline"
|
||||||
:label="
|
class="col-3"
|
||||||
node.status !== 'INACTIVE'
|
size="xs"
|
||||||
|
style="color: hsl(var(--cyan-6-hsl))"
|
||||||
|
/>
|
||||||
|
<span class="col-9 q-px-md flex items-center">
|
||||||
|
{{ $t('edit') }}
|
||||||
|
</span>
|
||||||
|
</q-item>
|
||||||
|
<q-item
|
||||||
|
v-close-popup
|
||||||
|
:id="`view-detail-btn-${node.name}-delete`"
|
||||||
|
dense
|
||||||
|
:clickable="node.status === 'CREATED'"
|
||||||
|
class="row"
|
||||||
|
:class="{
|
||||||
|
'surface-3': node.status !== 'CREATED',
|
||||||
|
'app-text-muted': node.status !== 'CREATED',
|
||||||
|
}"
|
||||||
|
style="white-space: nowrap"
|
||||||
|
@click.stop="
|
||||||
|
() => {
|
||||||
|
editByTree = node.type;
|
||||||
|
|
||||||
|
if (node.type === 'type') {
|
||||||
|
deleteProductById(node.id);
|
||||||
|
}
|
||||||
|
if (node.type === 'group') {
|
||||||
|
deleteProductById(node.id);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
"
|
||||||
|
>
|
||||||
|
<q-icon
|
||||||
|
name="mdi-trash-can-outline"
|
||||||
|
size="xs"
|
||||||
|
class="col-3"
|
||||||
|
:class="{
|
||||||
|
'app-text-negative':
|
||||||
|
node.status === 'CREATED',
|
||||||
|
}"
|
||||||
|
/>
|
||||||
|
<span class="col-9 q-px-md flex items-center">
|
||||||
|
{{ $t('delete') }}
|
||||||
|
</span>
|
||||||
|
</q-item>
|
||||||
|
|
||||||
|
<q-item dense>
|
||||||
|
<q-item-section class="q-py-sm">
|
||||||
|
<div class="q-pa-sm surface-2 rounded">
|
||||||
|
<q-toggle
|
||||||
|
:id="`view-detail-btn-${node.name}-status`"
|
||||||
|
dense
|
||||||
|
size="sm"
|
||||||
|
:label="
|
||||||
|
node.status !== 'INACTIVE'
|
||||||
? $t('switchOnLabel')
|
? $t('switchOnLabel')
|
||||||
: $t('switchOffLabel')
|
: $t('switchOffLabel')
|
||||||
"
|
"
|
||||||
@click="
|
@click.stop="
|
||||||
async () => {
|
async () => {
|
||||||
|
if (node.type === 'type') {
|
||||||
|
toggleStatusType(
|
||||||
|
node.id,
|
||||||
|
node.status,
|
||||||
|
);
|
||||||
}
|
}
|
||||||
"
|
if (node.type === 'group') {
|
||||||
:model-value="
|
toggleStatusGroup(
|
||||||
node.status === 'CREATED' ||
|
node.id,
|
||||||
node.status === 'ACTIVE'
|
node.status,
|
||||||
"
|
);
|
||||||
/>
|
}
|
||||||
</div>
|
}
|
||||||
</q-item-section>
|
"
|
||||||
</q-item>
|
:model-value="node.status !== 'INACTIVE'"
|
||||||
</q-list>
|
/>
|
||||||
</q-menu>
|
</div>
|
||||||
</q-btn>
|
</q-item-section>
|
||||||
</div>
|
</q-item>
|
||||||
</div>
|
</q-list>
|
||||||
</template>
|
</q-menu>
|
||||||
</q-tree> -->
|
</q-btn>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="col row full-width">
|
||||||
|
<div class="col- app-text-muted">{{ node.code }}</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
</q-tree>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
@ -2978,14 +3124,46 @@ watch(inputSearchProductAndService, async () => {
|
||||||
ref="formDialogRef"
|
ref="formDialogRef"
|
||||||
v-model:drawerOpen="drawerInfo"
|
v-model:drawerOpen="drawerInfo"
|
||||||
:title="
|
:title="
|
||||||
$t(productMode === 'group' ? 'productGroup' : 'productType', {
|
$t(
|
||||||
name: formDataGroup.code,
|
editByTree !== undefined
|
||||||
})
|
? editByTree === 'group'
|
||||||
|
? 'productGroup'
|
||||||
|
: editByTree === 'type'
|
||||||
|
? 'productType'
|
||||||
|
: undefined
|
||||||
|
: productMode === 'group'
|
||||||
|
? 'productGroup'
|
||||||
|
: productMode === 'type'
|
||||||
|
? 'productType'
|
||||||
|
: undefined,
|
||||||
|
{
|
||||||
|
name: formDataGroup.code,
|
||||||
|
},
|
||||||
|
)
|
||||||
"
|
"
|
||||||
:undo="() => undoProductGroup()"
|
:undo="() => undoProductGroup()"
|
||||||
:isEdit="isEdit"
|
:isEdit="isEdit"
|
||||||
:editData="() => (isEdit = true)"
|
:editData="() => (isEdit = true)"
|
||||||
:submit="() => (productMode === 'type' ? submitType() : submitGroup())"
|
:submit="
|
||||||
|
() => {
|
||||||
|
if (editByTree !== undefined) {
|
||||||
|
if (editByTree === 'group') {
|
||||||
|
submitGroup();
|
||||||
|
}
|
||||||
|
if (editByTree === 'type') {
|
||||||
|
submitType();
|
||||||
|
}
|
||||||
|
editByTree = undefined;
|
||||||
|
} else {
|
||||||
|
if (productMode === 'group') {
|
||||||
|
submitGroup();
|
||||||
|
}
|
||||||
|
if (productMode === 'type') {
|
||||||
|
submitType();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
"
|
||||||
:delete-data="() => deleteProductById()"
|
:delete-data="() => deleteProductById()"
|
||||||
:close="() => (drawerInfo = false)"
|
:close="() => (drawerInfo = false)"
|
||||||
>
|
>
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue