fix(04): tree view

This commit is contained in:
puriphatt 2024-09-26 11:51:59 +07:00
parent 3c64285ce4
commit 927841eda5
4 changed files with 120 additions and 15 deletions

View file

@ -7,7 +7,7 @@ import WorkManagementComponent from './WorkManagementComponent.vue';
import AddButton from '../button/AddButton.vue'; import AddButton from '../button/AddButton.vue';
import { ServiceCreate, WorkItems } from 'stores/product-service/types'; import { ServiceCreate, WorkItems } from 'stores/product-service/types';
import TreeView from '../shared/TreeView.vue'; import TreeView from '../shared/TreeView.vue';
import { ref } from 'vue'; import { ref, watch } from 'vue';
const { t } = useI18n(); const { t } = useI18n();
@ -37,16 +37,33 @@ defineEmits<{
const nodes = ref([ const nodes = ref([
{ {
title: props.service?.name, title: props.service?.name,
subtitle: props.service?.code, subtitle: props.service?.code || ' ',
selected: false, selected: false,
children: workItems.value.map((v) => ({ opened: true,
title: v.name, children: (function () {
subtitle: ' ', const noNameObjects = workItems.value
children: v.product.map((x) => ({ .filter((v) => !v.name)
title: x.name, .flatMap((v) =>
subtitle: x.code, v.product.map((x) => ({
})), title: x.name,
})), subtitle: x.code || ' ',
icon: 'mdi-shopping-outline',
bg: 'hsla(var(--teal-10-hsl)/0.1)',
fg: 'var(--teal-10)',
})),
);
const withNameObjects = workItems.value
.filter((v) => v.name)
.flatMap((v) => ({
title: v.name,
subtitle: ' ',
children: v.product.map((x) => ({
title: x.name,
subtitle: x.code || ' ',
})),
}));
return noNameObjects.concat(withNameObjects);
})(),
}, },
]); ]);
@ -72,6 +89,45 @@ function confirmDelete(items: unknown[], index: number) {
cancel: () => {}, cancel: () => {},
}); });
} }
watch(
() => workItems,
() => {
nodes.value = [
{
title: props.service?.name,
subtitle: props.service?.code || ' ',
selected: false,
opened: true,
children: (function () {
const noNameObjects = workItems.value
.filter((v) => !v.name)
.flatMap((v) =>
v.product.map((x) => ({
title: x.name,
subtitle: x.code || ' ',
icon: 'mdi-shopping-outline',
bg: 'hsla(var(--teal-10-hsl)/0.1)',
fg: 'var(--teal-10)',
})),
);
const withNameObjects = workItems.value
.filter((v) => v.name)
.flatMap((v) => ({
title: v.name,
subtitle: ' ',
children: v.product.map((x) => ({
title: x.name,
subtitle: x.code || ' ',
})),
}));
return noNameObjects.concat(withNameObjects);
})(),
},
];
},
{ deep: true },
);
</script> </script>
<template> <template>

View file

@ -6,6 +6,9 @@ type Node = {
[key: string]: any; [key: string]: any;
opened?: boolean; opened?: boolean;
selected?: boolean; selected?: boolean;
bg?: string;
fg?: string;
icon?: string;
children?: Node[]; children?: Node[];
}; };
@ -86,7 +89,7 @@ function toggleExpand(node: Node) {
<div <div
v-if="level !== maxLevel" v-if="level !== maxLevel"
class="q-mr-md" class="q-mr-md"
style="color: var(--stone-4)" :style="`color: ${node.children?.length === 0 || !node.children ? 'transparent' : 'var(--stone-4)'}`"
> >
<q-icon <q-icon
name="mdi-chevron-down-circle" name="mdi-chevron-down-circle"
@ -109,14 +112,14 @@ function toggleExpand(node: Node) {
<div <div
class="item__icon flex items-center justify-center" class="item__icon flex items-center justify-center"
:style="`background: ${dec?.bg}; color: ${dec?.fg}; height: ${iconSize}; width: ${iconSize}`" :style="`background: ${node.bg || dec?.bg}; color: ${node.fg || dec?.fg}; height: ${iconSize}; width: ${iconSize}`"
> >
<div <div
:style="`height: calc(${iconSize} - 40%); width: calc(${iconSize} - 40%)`" :style="`height: calc(${iconSize} - 40%); width: calc(${iconSize} - 40%)`"
> >
<Icon <Icon
v-if="dec && dec.icon" v-if="(node.icon && dec && dec.icon) || (dec && dec.icon)"
:icon="dec.icon" :icon="node.icon || dec.icon"
class="full-width full-height" class="full-width full-height"
/> />
</div> </div>

View file

@ -20,7 +20,7 @@ html {
--surface-tab: var(--gray-2); --surface-tab: var(--gray-2);
--text-mute: var(--stone-7-hsl); --text-mute: var(--stone-7-hsl);
--text-mute-2: var(--stone-8-hsl); --text-mute-2: var(--stone-9-hsl);
--info-fg: 0 0% 100%; --info-fg: 0 0% 100%;
--info-bg: var(--blue-6-hsl); --info-bg: var(--blue-6-hsl);

View file

@ -3802,6 +3802,50 @@ watch(
:class="$q.screen.xs ? 'q-pl-md' : 'q-pl-sm'" :class="$q.screen.xs ? 'q-pl-md' : 'q-pl-sm'"
style="height: 100%; max-height: 100%; overflow-y: auto" style="height: 100%; max-height: 100%; overflow-y: auto"
> >
<div
class="surface-1 rounded q-my-md q-mx-lg row items-center"
style="position: absolute; z-index: 999; top: 0; right: 0"
v-if="actionDisplay && !currentNoAction"
>
<div class="bordered rounded q-mr-md" v-if="serviceTab === 2">
<q-btn
icon="mdi-file-tree-outline"
flat
square
:class="{
' surface-3': serviceTreeView,
'app-text-muted-2': serviceTreeView,
'app-text-muted': !serviceTreeView,
}"
size="sm"
padding="6px 10px"
title="Tree"
style="
border-top-left-radius: var(--radius-2);
border-bottom-left-radius: var(--radius-2);
"
@click="serviceTreeView = true"
/>
<q-btn
icon="mdi-view-list-outline"
flat
square
:class="{
' surface-3': !serviceTreeView,
'app-text-muted-2': !serviceTreeView,
'app-text-muted': serviceTreeView,
}"
size="sm"
padding="6px 10px"
title="List"
style="
border-top-right-radius: var(--radius-2);
border-bottom-right-radius: var(--radius-2);
"
@click="serviceTreeView = false"
/>
</div>
</div>
<BasicInformation <BasicInformation
v-if="serviceTab === 1" v-if="serviceTab === 1"
dense dense
@ -3814,6 +3858,8 @@ watch(
<FormServiceWork <FormServiceWork
v-if="serviceTab === 2" v-if="serviceTab === 2"
v-model:work-items="workItems" v-model:work-items="workItems"
:tree-view="serviceTreeView"
:service="formDataProductService"
dense dense
@addProduct=" @addProduct="
async (index) => { async (index) => {