2024-06-19 15:43:58 +07:00
|
|
|
<script lang="ts" setup>
|
2024-09-18 16:04:07 +07:00
|
|
|
import { onMounted, ref } from 'vue';
|
|
|
|
|
|
|
|
|
|
import { productTreeDecoration } from './constants';
|
|
|
|
|
import useProductServiceStore from 'src/stores/product-service';
|
|
|
|
|
|
|
|
|
|
import {
|
|
|
|
|
ProductGroup,
|
|
|
|
|
ProductList,
|
|
|
|
|
Service,
|
|
|
|
|
} from 'src/stores/product-service/types';
|
|
|
|
|
|
2024-09-18 09:51:28 +07:00
|
|
|
import QuotationForm from './QuotationForm.vue';
|
2024-09-16 10:32:06 +07:00
|
|
|
import TreeView from 'src/components/shared/TreeView.vue';
|
2024-09-18 16:52:46 +07:00
|
|
|
import { AddButton } from 'src/components/button';
|
|
|
|
|
import MainButton from 'src/components/button/MainButton.vue';
|
2024-06-26 17:03:39 +07:00
|
|
|
|
2024-09-18 16:04:07 +07:00
|
|
|
const dialog = ref(true);
|
|
|
|
|
|
2024-09-16 10:32:06 +07:00
|
|
|
const nodes = ref([
|
|
|
|
|
{
|
|
|
|
|
title: 'กลุ่มสินค้าและบริการที่ 1',
|
|
|
|
|
subtitle: 'TG01000000001',
|
|
|
|
|
selected: false,
|
|
|
|
|
children: [
|
|
|
|
|
{
|
|
|
|
|
title: 'งานที่ 1',
|
|
|
|
|
subtitle: 'TG01000000001',
|
|
|
|
|
selected: false,
|
|
|
|
|
children: [
|
|
|
|
|
{
|
|
|
|
|
title: 'สินค้า 1',
|
|
|
|
|
subtitle: 'TG01000000001',
|
|
|
|
|
selected: false,
|
|
|
|
|
},
|
|
|
|
|
{
|
|
|
|
|
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',
|
|
|
|
|
subtitle: 'TG01000000001',
|
|
|
|
|
selected: false,
|
|
|
|
|
},
|
|
|
|
|
],
|
|
|
|
|
},
|
|
|
|
|
],
|
|
|
|
|
},
|
|
|
|
|
]);
|
2024-09-18 16:04:07 +07:00
|
|
|
const productServiceStore = useProductServiceStore();
|
|
|
|
|
|
|
|
|
|
type ProductGroupId = string;
|
|
|
|
|
|
|
|
|
|
const productGroup = ref<ProductGroup[]>([]);
|
|
|
|
|
const productList = ref<Partial<Record<ProductGroupId, ProductList[]>>>({});
|
|
|
|
|
const serviceList = ref<Partial<Record<ProductGroupId, Service[]>>>({});
|
|
|
|
|
|
2024-09-18 16:52:46 +07:00
|
|
|
type Id = string;
|
|
|
|
|
const product = ref<Record<Id, ProductList>>({});
|
|
|
|
|
const service = ref<Record<Id, Service>>({});
|
|
|
|
|
|
|
|
|
|
const selectedGroup = ref<ProductGroup | null>(null);
|
|
|
|
|
const selectedGroupSub = ref<'product' | 'service' | null>(null);
|
|
|
|
|
const selectedProductServiceId = ref('');
|
|
|
|
|
|
2024-09-18 16:04:07 +07:00
|
|
|
onMounted(async () => {
|
|
|
|
|
const ret = await productServiceStore.fetchListProductService({
|
|
|
|
|
page: 1,
|
|
|
|
|
pageSize: 9999,
|
|
|
|
|
});
|
|
|
|
|
if (ret) productGroup.value = ret.result;
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
async function getAllProduct(
|
|
|
|
|
groupId: string,
|
|
|
|
|
opts?: { force?: false; page?: number; pageSize?: number },
|
|
|
|
|
) {
|
2024-09-18 16:52:46 +07:00
|
|
|
selectedGroupSub.value = 'product';
|
2024-09-18 16:04:07 +07:00
|
|
|
if (!opts?.force && productList.value[groupId] !== undefined) return;
|
|
|
|
|
const ret = await productServiceStore.fetchListProduct({
|
|
|
|
|
page: opts?.page ?? 1,
|
|
|
|
|
pageSize: opts?.pageSize ?? 9999,
|
2024-09-18 16:52:46 +07:00
|
|
|
productGroupId: groupId,
|
2024-09-18 16:04:07 +07:00
|
|
|
});
|
|
|
|
|
if (ret) productList.value[groupId] = ret.result;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
async function getAllService(
|
|
|
|
|
groupId: string,
|
|
|
|
|
opts?: { force?: false; page?: number; pageSize?: number },
|
|
|
|
|
) {
|
2024-09-18 16:52:46 +07:00
|
|
|
selectedGroupSub.value = 'service';
|
2024-09-18 16:04:07 +07:00
|
|
|
if (!opts?.force && serviceList.value[groupId] !== undefined) return;
|
|
|
|
|
const ret = await productServiceStore.fetchListService({
|
|
|
|
|
page: opts?.page ?? 1,
|
|
|
|
|
pageSize: opts?.pageSize ?? 9999,
|
2024-09-18 16:52:46 +07:00
|
|
|
productGroupId: groupId,
|
2024-09-18 16:04:07 +07:00
|
|
|
});
|
|
|
|
|
if (ret) serviceList.value[groupId] = ret.result;
|
|
|
|
|
}
|
2024-09-18 16:52:46 +07:00
|
|
|
|
|
|
|
|
async function getProduct(id: string, force = false) {
|
|
|
|
|
selectedGroupSub.value = 'product';
|
|
|
|
|
selectedProductServiceId.value = id;
|
|
|
|
|
if (!force && product.value[id] !== undefined) return;
|
|
|
|
|
const ret = await productServiceStore.fetchListProductById(id);
|
|
|
|
|
if (ret) product.value[id] = ret;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
async function getService(id: string, force = false) {
|
|
|
|
|
selectedGroupSub.value = 'service';
|
|
|
|
|
selectedProductServiceId.value = id;
|
|
|
|
|
if (!force && service.value[id] !== undefined) return;
|
|
|
|
|
const ret = await productServiceStore.fetchListServiceById(id);
|
|
|
|
|
if (ret) service.value[id] = ret;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
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
|
|
|
|
|
}
|
2024-06-19 15:43:58 +07:00
|
|
|
</script>
|
|
|
|
|
|
|
|
|
|
<template>
|
2024-09-18 16:52:46 +07:00
|
|
|
<div v-for="item in productGroup" class="row items-center">
|
|
|
|
|
{{ item.name }}
|
|
|
|
|
{{ item.code }}
|
|
|
|
|
<AddButton icon-only @click="selectedGroup = item" />
|
|
|
|
|
</div>
|
|
|
|
|
|
|
|
|
|
<template v-if="selectedGroup">
|
|
|
|
|
<MainButton
|
|
|
|
|
icon="mdi-check"
|
|
|
|
|
color="var(--blue-6-hsl)"
|
|
|
|
|
@click="getAllProduct(selectedGroup.id)"
|
|
|
|
|
>
|
|
|
|
|
Product
|
|
|
|
|
</MainButton>
|
|
|
|
|
<MainButton
|
|
|
|
|
icon="mdi-check"
|
|
|
|
|
color="var(--blue-6-hsl)"
|
|
|
|
|
@click="getAllService(selectedGroup.id)"
|
|
|
|
|
>
|
|
|
|
|
Service
|
|
|
|
|
</MainButton>
|
|
|
|
|
|
|
|
|
|
<div
|
|
|
|
|
v-if="productList[selectedGroup.id]"
|
|
|
|
|
v-for="item in productList[selectedGroup.id]"
|
|
|
|
|
class="row items-center"
|
|
|
|
|
>
|
|
|
|
|
{{ item.name }}
|
|
|
|
|
{{ item.code }}
|
|
|
|
|
<AddButton icon-only @click="getProduct(item.id)" />
|
|
|
|
|
</div>
|
|
|
|
|
|
|
|
|
|
<div
|
|
|
|
|
v-if="serviceList[selectedGroup.id]"
|
|
|
|
|
v-for="item in serviceList[selectedGroup.id]"
|
|
|
|
|
class="row items-center"
|
|
|
|
|
>
|
|
|
|
|
{{ item.name }}
|
|
|
|
|
{{ item.code }}
|
|
|
|
|
<AddButton icon-only @click="getService(item.id)" />
|
|
|
|
|
</div>
|
|
|
|
|
|
|
|
|
|
<template
|
|
|
|
|
v-if="selectedGroupSub === 'service' && service[selectedProductServiceId]"
|
|
|
|
|
>
|
|
|
|
|
{{ service[selectedProductServiceId] }}
|
|
|
|
|
</template>
|
|
|
|
|
<template
|
|
|
|
|
v-if="selectedGroupSub === 'product' && product[selectedProductServiceId]"
|
|
|
|
|
>
|
|
|
|
|
{{ product[selectedProductServiceId] }}
|
|
|
|
|
</template>
|
|
|
|
|
</template>
|
|
|
|
|
|
2024-09-16 10:32:06 +07:00
|
|
|
<div class="surface-1 rounded full-height q-pa-md">
|
|
|
|
|
<TreeView
|
2024-09-18 16:04:07 +07:00
|
|
|
:decoration="productTreeDecoration"
|
2024-09-16 10:32:06 +07:00
|
|
|
v-model:nodes="nodes"
|
|
|
|
|
expandable
|
|
|
|
|
/>
|
|
|
|
|
</div>
|
|
|
|
|
<!-- <ImageUploadDialog
|
2024-08-02 16:13:07 +07:00
|
|
|
v-model:dialog-state="isOpen"
|
|
|
|
|
v-model:file="file"
|
|
|
|
|
ref="imageUploadDialog"
|
|
|
|
|
clear-button
|
|
|
|
|
>
|
|
|
|
|
<template #error>
|
|
|
|
|
<div style="display: flex; align-items: center; justify-content: center">
|
|
|
|
|
<h1>Fallback</h1>
|
|
|
|
|
</div>
|
|
|
|
|
</template>
|
|
|
|
|
</ImageUploadDialog>
|
|
|
|
|
|
|
|
|
|
<button @click="isOpen = !isOpen">Open</button>
|
|
|
|
|
<button @click="imageUploadDialog?.browse()">Click Me</button>
|
|
|
|
|
<div
|
|
|
|
|
style="
|
|
|
|
|
height: 100vh;
|
|
|
|
|
background: green;
|
|
|
|
|
width: 100%;
|
|
|
|
|
color: white;
|
|
|
|
|
font-weight: 600;
|
|
|
|
|
display: flex;
|
|
|
|
|
align-items: center;
|
|
|
|
|
justify-content: center;
|
|
|
|
|
"
|
|
|
|
|
id="aaa"
|
|
|
|
|
>
|
|
|
|
|
My AAA
|
|
|
|
|
</div>
|
|
|
|
|
<div
|
|
|
|
|
style="
|
|
|
|
|
height: 100vh;
|
|
|
|
|
background: red;
|
|
|
|
|
width: 100%;
|
|
|
|
|
color: white;
|
|
|
|
|
display: flex;
|
|
|
|
|
align-items: center;
|
|
|
|
|
justify-content: center;
|
|
|
|
|
font-weight: 600;
|
|
|
|
|
"
|
|
|
|
|
id="my-anchor"
|
|
|
|
|
>
|
|
|
|
|
My Menu
|
2024-09-18 15:38:50 +07:00
|
|
|
</div> -->
|
2024-09-18 16:04:07 +07:00
|
|
|
<QuotationForm v-model:dialog-state="dialog" readonly />
|
2024-06-19 15:43:58 +07:00
|
|
|
</template>
|
|
|
|
|
|
|
|
|
|
<style scoped></style>
|