diff --git a/src/components/04_product-service/FormServiceWork.vue b/src/components/04_product-service/FormServiceWork.vue
index 7c186b81..e17e1a4e 100644
--- a/src/components/04_product-service/FormServiceWork.vue
+++ b/src/components/04_product-service/FormServiceWork.vue
@@ -38,7 +38,6 @@ const nodes = ref([
{
title: props.service?.name,
subtitle: props.service?.code || ' ',
- selected: false,
opened: true,
children: (function () {
const noNameObjects = workItems.value
@@ -99,7 +98,6 @@ watch(
{
title: props.service?.name,
subtitle: props.service?.code || ' ',
- selected: false,
opened: true,
children: (function () {
const noNameObjects = workItems.value
diff --git a/src/components/shared/TreeView.vue b/src/components/shared/TreeView.vue
index 60bbd5d6..7e599df7 100644
--- a/src/components/shared/TreeView.vue
+++ b/src/components/shared/TreeView.vue
@@ -1,6 +1,6 @@
@@ -98,13 +101,25 @@ function toggleExpand(node: Node) {
@@ -125,6 +140,7 @@ function toggleExpand(node: Node) {
:style="`background: ${node.bg || dec?.bg}; color: ${node.fg || dec?.fg}; height: ${iconSize}; width: ${iconSize}`"
>
{
+ $emit(
+ 'open',
+ n,
+ !props.ancestorNode || props.ancestorNode.length === 0
+ ? [node]
+ : [...props.ancestorNode, node],
+ );
+ }
+ "
@checked="
() => {
node.checked = true;
$emit('checked');
}
"
- @select="(v) => $emit('select', v, props.ancestorNode)"
+ @select="
+ (v) =>
+ $emit(
+ 'select',
+ v,
+ !props.ancestorNode || props.ancestorNode.length === 0
+ ? [node]
+ : [...props.ancestorNode, node],
+ )
+ "
:level="(level || 0) + 1"
:ancestorNode="
- !props.ancestorNode ? [node] : [...props.ancestorNode, node]
+ !props.ancestorNode || props.ancestorNode.length === 0
+ ? [node]
+ : [...props.ancestorNode, node]
"
:expandable
:decoration
diff --git a/src/pages/05_quotation/MainPage.vue b/src/pages/05_quotation/MainPage.vue
index dd37a96e..5843c80d 100644
--- a/src/pages/05_quotation/MainPage.vue
+++ b/src/pages/05_quotation/MainPage.vue
@@ -65,6 +65,17 @@ import { useQuotationStore } from 'src/stores/quotations';
import QuotationView from './QuotationView.vue';
import { watch } from 'vue';
+type Node = {
+ [key: string]: any;
+ opened?: boolean;
+ checked?: boolean;
+ bg?: string;
+ fg?: string;
+ icon?: string;
+ displayDropIcon?: boolean;
+ children?: Node[];
+};
+
const flowStore = useFlowStore();
const tabFieldRequired = ref<{ [key: string]: (keyof CustomerBranchCreate)[] }>(
{
@@ -91,49 +102,92 @@ const { state: customerFormState, currentFormData: customerFormData } =
const { state: employeeFormState, currentFromDataEmployee } =
storeToRefs(employeeFormStore);
-const test1 = ref(true);
-const test2 = ref(true);
+const test1 = ref(false);
+const test2 = ref(false);
const dialog = ref(true);
-const nodes = ref([
+const nodes = ref([
{
title: 'กลุ่มสินค้าและบริการที่ 1',
subtitle: 'TG01000000001',
selected: false,
+ type: 'group',
children: [
{
- title: 'งานที่ 1',
+ title:
+ 'บริการค่าบริการและค่าดำเนินงานยื่นแบบคำร้องขอนำเข้า MOU (Demand)',
subtitle: 'TG01000000001',
selected: false,
+ type: 'type',
children: [
{
- title: 'สินค้า 1',
+ title: 'งาน 1',
subtitle: 'TG01000000001',
selected: false,
+ type: 'work',
+ children: [
+ {
+ title: 'สินค้า 1',
+ subtitle: 'TG01000000001',
+ selected: false,
+ type: 'product',
+ },
+ {
+ title: 'สินค้า 2',
+ subtitle: 'TG01000000001',
+ selected: false,
+ type: 'product',
+ },
+ {
+ title: 'สินค้า 3',
+ subtitle: 'TG01000000001',
+ selected: false,
+ type: 'product',
+ },
+ ],
},
+ ],
+ },
+ ],
+ },
+
+ {
+ title: 'กลุ่มสินค้าและบริการที่ 2',
+ subtitle: 'TG01000000001',
+ selected: false,
+ type: 'group',
+ children: [
+ {
+ title:
+ 'บริการค่าบริการและค่าดำเนินงานยื่นแบบคำร้องขอนำเข้า MOU (Demand)',
+ subtitle: 'TG01000000001',
+ selected: false,
+ type: 'type',
+ children: [
{
- title: 'สินค้า 2',
- subtitle: 'TG01000000001',
- selected: false,
- },
- {
- title: 'สินค้า 3',
- subtitle: 'TG01000000001',
- selected: false,
- },
- {
- title: 'สินค้า 4',
- subtitle: 'TG01000000001',
- selected: false,
- },
- {
- title: 'สินค้า 5',
- subtitle: 'TG01000000001',
- selected: false,
- },
- {
- title: 'สินค้า 6',
+ title: 'งาน 1',
subtitle: 'TG01000000001',
selected: false,
+ type: 'work',
+ children: [
+ {
+ title: 'สินค้า 1',
+ subtitle: 'TG01000000001',
+ selected: false,
+ type: 'product',
+ },
+ {
+ title: 'สินค้า 2',
+ subtitle: 'TG01000000001',
+ selected: false,
+ type: 'product',
+ },
+ {
+ title: 'สินค้า 3',
+ subtitle: 'TG01000000001',
+ selected: false,
+ type: 'product',
+ },
+ ],
},
],
},
@@ -288,8 +342,75 @@ async function getService(id: string, force = false) {
}
function convertToTree() {
- // TODO: convert product or service into selectable tree
- // NOTE: this is meant to be used inside getService() and getProduct() before return and after return
+ const node = productGroup.value.map((g) => ({
+ id: g.id,
+ title: g.name,
+ subtitle: g.code,
+ detail: g.detail,
+ remark: g.remark,
+ type: 'group',
+ displayDropIcon: g._count.service + g._count.product !== 0,
+ }));
+ nodes.value = node;
+}
+
+async function openProductServiceTree(node: Node, anchestor?: Node[]) {
+ if (node.type === 'group') {
+ const curGroupNode = nodes.value.find((v) => v.id === node.id);
+ await getAllService(node.id);
+ if (!curGroupNode) return;
+
+ curGroupNode.children = serviceList.value[curGroupNode.id]?.map((t) => ({
+ id: t.id,
+ title: t.name,
+ subtitle: t.code,
+ detail: t.detail,
+ type: 'type',
+ displayDropIcon: t.work.length > 0,
+ }));
+ }
+
+ if (node.type === 'type' && anchestor && anchestor[0].children) {
+ const curTypeNode = anchestor[0].children.find((v) => v.id === node.id);
+ const curType = serviceList.value[anchestor[0].id]?.find(
+ (v) => v.id === node.id,
+ );
+ if (!curTypeNode) return;
+ const noNameWork = curType.work
+ .filter((v) => !v.name)
+ .flatMap((v) =>
+ v.productOnWork.map((p) => ({
+ id: p.product.id,
+ title: p.product.name,
+ subtitle: p.product.code,
+ detail: p.product.detail,
+ remark: p.product.remark,
+ type: 'product',
+ icon: 'mdi-shopping-outline',
+ bg: 'hsla(var(--teal-10-hsl)/0.1)',
+ fg: 'var(--teal-10)',
+ })),
+ );
+ const withNameWork = curType.work
+ .filter((v) => v.name)
+ .flatMap((w) => ({
+ id: w.id,
+ title: w.name,
+ subtitle: ' ',
+ attributes: w.attributes,
+ type: 'work',
+ displayDropIcon: w.productOnWork.length > 0,
+ children: w.productOnWork.map((p) => ({
+ id: p.product.id,
+ title: p.product.name,
+ subtitle: p.product.code,
+ detail: p.product.detail,
+ remark: p.product.remark,
+ type: 'product',
+ })),
+ }));
+ curTypeNode.children = noNameWork.concat(withNameWork);
+ }
}
const quotationStore = useQuotationStore();
@@ -354,6 +475,7 @@ watch(
+ {{ convertToTree() }}
@@ -618,8 +740,8 @@ watch(
:date="new Date(n.createdAt).toLocaleString()"
:amount="n.workerCount"
:customer-name="
- n.customerBranch.registerName ||
- `${n.customerBranch.firstName || '-'} ${n.customerBranch.lastName}`
+ n.customerBranch?.registerName ||
+ `${n.customerBranch?.firstName || '-'} ${n.customerBranch?.lastName || ''}`
"
:reporter="n.actorName"
:total-price="n.totalPrice"
@@ -1252,6 +1374,8 @@ watch(
diff --git a/src/pages/05_quotation/ProductServiceForm.vue b/src/pages/05_quotation/ProductServiceForm.vue
index 31394933..34d0b686 100644
--- a/src/pages/05_quotation/ProductServiceForm.vue
+++ b/src/pages/05_quotation/ProductServiceForm.vue
@@ -1,8 +1,14 @@