jws-frontend/src/pages/04_product-service/MainPage.vue

1058 lines
29 KiB
Vue
Raw Normal View History

2024-06-10 16:42:59 +07:00
<script setup lang="ts">
import { ref, watch } from 'vue';
2024-06-10 16:42:59 +07:00
import AppBox from 'components/app/AppBox.vue';
2024-06-12 15:37:17 +07:00
import AddButton from 'components/AddButton.vue';
2024-06-10 16:42:59 +07:00
import ProductCardComponent from 'src/components/04_product-service/ProductCardComponent.vue';
import StatCard from 'components/StatCardComponent.vue';
2024-06-10 17:42:37 +07:00
import NewProductCardCompoent from 'components/04_product-service/NewProductCardComponent.vue';
import DrawerInfo from 'src/components/DrawerInfo.vue';
import BasicInformation from 'src/components/04_product-service/BasicInformation.vue';
import FormDialog from 'src/components/FormDialog.vue';
2024-06-12 15:37:17 +07:00
import TooltipComponent from 'components/TooltipComponent.vue';
2024-06-14 09:31:45 +07:00
import ButtonAddComponent from 'src/components/ButtonAddCompoent.vue';
2024-06-14 14:45:17 +07:00
import BasicInfoProduct from 'src/components/04_product-service/ฺBasicInfoProduct.vue';
import PriceDataComponent from 'src/components/04_product-service/PriceDataComponent.vue';
import ProfileUpload from 'src/components/ProfileUpload.vue';
import TotalProductCardComponent from 'components/04_product-service/TotalProductCardComponent.vue';
2024-06-14 09:31:45 +07:00
import { Status } from 'src/stores/types';
import NoData from 'components/NoData.vue';
2024-06-12 15:37:17 +07:00
import { dialog } from 'src/stores/utils';
2024-06-11 15:04:01 +07:00
import useProductServiceStore from 'src/stores/product-service';
2024-06-14 15:18:59 +07:00
import {
ProductGroup,
ProductGroupCreate,
ProductCreate,
ProductList,
2024-06-14 15:18:59 +07:00
} from 'src/stores/product-service/types';
2024-06-11 15:04:01 +07:00
const productServiceStore = useProductServiceStore();
const {
fetchStatsProductType,
2024-06-12 15:37:17 +07:00
createProductServiceType,
editProductServiceType,
deleteProductServiceType,
fetchListProductServiceType,
2024-06-11 15:04:01 +07:00
fetchStatsProductGroup,
fetchListProductService,
createProductService,
editProductService,
deleteProductService,
fetchListProduct,
createProduct,
2024-06-11 15:04:01 +07:00
} = productServiceStore;
import ItemCard from 'src/components/ItemCard.vue';
import TotalProductComponent from 'src/components/04_product-service/TotalProductComponent.vue';
2024-06-10 16:42:59 +07:00
const stat = ref<
{
count: number;
label: string;
2024-06-12 15:37:17 +07:00
color: 'pink' | 'purple' | 'green' | 'orange';
2024-06-10 16:42:59 +07:00
}[]
>([
2024-06-12 15:37:17 +07:00
{ count: 0, label: 'productAndService', color: 'pink' },
{ count: 0, label: 'productAndServiceType', color: 'purple' },
{ count: 0, label: 'service', color: 'orange' },
{ count: 0, label: 'product', color: 'green' },
2024-06-10 16:42:59 +07:00
]);
import { useI18n } from 'vue-i18n';
2024-06-11 15:04:01 +07:00
import { onMounted } from 'vue';
const { t } = useI18n();
2024-06-10 16:42:59 +07:00
const inputSearch = ref<string>('');
const drawerInfo = ref<boolean>(false);
const isEdit = ref<boolean>(false);
const dialogInputForm = ref<boolean>(false);
2024-06-14 14:45:17 +07:00
const dialogProduct = ref<boolean>(false);
const statusToggle = ref<boolean>(false);
const profileSubmit = ref<boolean>(false);
const profileFile = ref<File | undefined>(undefined);
const profileUrl = ref<string | null>('');
2024-06-11 16:52:35 +07:00
const groupName = ref<string>('งาน MOU');
const dialogProductServiceType = ref<boolean>(false);
const dialogTotalProduct = ref<boolean>(true);
const productMode = ref<'group' | 'type' | 'service' | 'product'>('group');
2024-06-14 15:18:59 +07:00
const productGroup = ref<ProductGroup[]>();
const productType = ref<ProductGroup[]>();
const product = ref<ProductList[]>();
const productAndServiceTab = ref<string>('all');
const previousValue = ref();
const formDataGroup = ref<ProductGroupCreate>({
remark: '',
detail: '',
name: '',
code: '',
});
const formDataProduct = ref<ProductCreate>({
productTypeId: '',
remark: '',
serviceCharge: 0,
agentPrice: 0,
price: 0,
process: 0,
detail: '',
name: '',
code: '',
});
const currentId = ref<string>('');
2024-06-12 15:37:17 +07:00
const currentIdType = ref<string>('');
2024-06-14 15:18:59 +07:00
const resultSearchGroup = ref<ProductGroup[]>();
const resultSearchType = ref<(ProductGroup & { productGroupId: string })[]>();
2024-06-12 15:37:17 +07:00
2024-06-14 09:31:45 +07:00
const currentStatus = ref<Status | 'All'>('All');
2024-06-14 14:45:17 +07:00
const inputFile = (() => {
const element = document.createElement('input');
element.type = 'file';
element.accept = 'image/*';
const reader = new FileReader();
reader.addEventListener('load', () => {
if (typeof reader.result === 'string') profileUrl.value = reader.result;
});
element.addEventListener('change', () => {
profileFile.value = element.files?.[0];
if (profileFile.value) {
reader.readAsDataURL(profileFile.value);
}
});
return element;
})();
2024-06-13 11:20:35 +07:00
async function searchGroup() {
const resultList = await fetchListProductService({
query: inputSearch.value,
});
if (resultList) {
resultSearchGroup.value = resultList;
}
}
2024-06-12 15:37:17 +07:00
async function fetchListType() {
const res = await fetchListProductServiceType({
productGroupId: currentId.value,
status:
currentStatus.value === 'All'
? undefined
: currentStatus.value === 'ACTIVE'
? 'ACTIVE'
: 'INACTIVE',
2024-06-12 15:37:17 +07:00
});
if (res) {
productType.value = res;
}
}
async function fetchListGroups() {
const res = await fetchListProductService({
status:
currentStatus.value === 'All'
? undefined
: currentStatus.value === 'ACTIVE'
? 'ACTIVE'
: 'INACTIVE',
});
2024-06-12 15:37:17 +07:00
if (res) {
productGroup.value = res;
}
}
async function fetchListOfProduct(productTypeId: string) {
const res = await fetchListProduct({ productTypeId });
if (res) {
product.value = res.result;
}
}
async function searchType() {
const res = await await fetchListProductServiceType({
query: inputSearch.value,
productGroupId: currentId.value,
});
if (res) {
resultSearchType.value = res;
}
}
async function submitType() {
2024-06-12 15:37:17 +07:00
if (drawerInfo.value) {
await editProductServiceType(currentIdType.value, {
...formDataGroup.value,
2024-06-12 15:37:17 +07:00
productGroupId: currentId.value,
});
drawerInfo.value = false;
} else {
dialogInputForm.value = false;
const res = await createProductServiceType(
currentId.value,
formDataGroup.value,
);
if (res) {
stat.value[1].count = stat.value[1].count + 1;
}
2024-06-12 15:37:17 +07:00
}
await fetchListType();
}
const itemCard = [
{
icon: 'mdi:server-network',
text: 'บริการ',
color: 'var(--orange-5)',
},
{
icon: 'mdi:shopping',
text: 'สินค้า',
color: 'var(--green-9)',
},
];
async function deleteProductById(productId?: string) {
dialog({
color: 'negative',
icon: 'mdi-alert',
title: t('deleteConfirmTitle'),
actionText: t('ok'),
persistent: true,
message: t('deleteConfirmMessage'),
action: async () => {
2024-06-11 16:52:35 +07:00
if (productMode.value === 'type') {
// Product Type
await deleteProductServiceType(productId ?? currentIdType.value);
2024-06-12 15:37:17 +07:00
await fetchListType();
stat.value[1].count = stat.value[1].count - 1;
}
if (productMode.value === 'group') {
// Product Group
const res = await deleteProductService(productId ?? currentId.value);
2024-06-12 15:37:17 +07:00
if (res) {
stat.value[0].count = stat.value[0].count - 1;
}
await fetchListGroups();
}
drawerInfo.value = false;
},
cancel: () => {},
});
}
2024-06-11 15:04:01 +07:00
function undoProductGroup() {
formDataGroup.value = {
remark: previousValue.value.remark,
detail: previousValue.value.detail,
name: previousValue.value.name,
code: previousValue.value.code,
};
isEdit.value = false;
}
function assignFormDataGroup(data: ProductGroup) {
previousValue.value = data;
formDataGroup.value = {
remark: data.remark,
detail: data.detail,
name: data.name,
code: data.code,
};
}
function assignFormDataProduct(data: ProductList) {
formDataProduct.value = {
productTypeId: data.productTypeId,
remark: data.remark,
serviceCharge: data.serviceCharge,
agentPrice: data.agentPrice,
price: data.price,
process: data.process,
detail: data.detail,
name: data.name,
code: data.code,
};
}
function clearFormGroup() {
formDataGroup.value = {
2024-06-11 15:04:01 +07:00
remark: '',
detail: '',
name: '',
code: '',
};
dialogInputForm.value = false;
}
function clearFormProduct() {
formDataProduct.value = {
productTypeId: '',
remark: '',
serviceCharge: 0,
agentPrice: 0,
price: 0,
process: 0,
detail: '',
name: '',
code: '',
};
dialogProduct.value = false;
}
async function submitProduct() {
formDataProduct.value.productTypeId = currentIdType.value;
await createProduct(formDataProduct.value);
dialogProduct.value = false;
await fetchListOfProduct(currentIdType.value);
}
2024-06-11 15:04:01 +07:00
async function submitGroup() {
if (drawerInfo.value) {
await editProductService(currentId.value, formDataGroup.value);
} else {
const res = await createProductService(formDataGroup.value);
2024-06-12 15:37:17 +07:00
if (res) {
stat.value[0].count = stat.value[0].count + 1;
}
}
2024-06-11 15:04:01 +07:00
2024-06-14 09:31:45 +07:00
drawerInfo.value = false;
await fetchListGroups();
clearFormGroup();
2024-06-11 15:04:01 +07:00
}
onMounted(async () => {
2024-06-12 15:37:17 +07:00
const resStatsGroup = await fetchStatsProductGroup();
const resStatsType = await fetchStatsProductType();
2024-06-12 15:37:17 +07:00
stat.value[0].count = resStatsGroup ?? 0;
stat.value[1].count = resStatsType ?? 0;
2024-06-12 15:37:17 +07:00
await fetchListGroups();
2024-06-11 15:04:01 +07:00
});
watch(productMode, () => (inputSearch.value = ''));
2024-06-14 09:31:45 +07:00
2024-06-14 13:37:11 +07:00
watch(currentStatus, async () => {
if (productMode.value === 'group') {
await fetchListGroups();
} else {
await fetchListType();
}
2024-06-14 13:37:11 +07:00
});
2024-06-10 16:42:59 +07:00
</script>
<template>
2024-06-14 09:31:45 +07:00
<ButtonAddComponent style="z-index: 999">
<q-fab-action
v-if="productMode === 'group'"
2024-06-14 13:37:11 +07:00
id="btn-add-product-group"
2024-06-14 09:31:45 +07:00
style="color: white; background-color: hsla(var(--pink-6-hsl))"
padding="xs"
icon="mdi-folder-multiple-plus"
:label="$t('productAndService')"
external-label
label-position="left"
@click="
() => {
clearFormGroup();
2024-06-14 09:31:45 +07:00
dialogInputForm = true;
}
"
/>
<q-fab-action
v-if="productMode === 'type'"
2024-06-14 13:37:11 +07:00
id="btn-add-product-type"
2024-06-14 09:31:45 +07:00
:label="$t('productAndServiceType')"
external-label
label-position="left"
style="color: white; background-color: hsla(var(--purple-11-hsl))"
padding="xs"
icon="mdi-folder-multiple-plus"
@click="
() => {
clearFormGroup();
2024-06-14 09:31:45 +07:00
dialogInputForm = true;
}
"
></q-fab-action>
2024-06-14 14:45:17 +07:00
<q-fab-action
v-if="productMode === 'service'"
label="เพิ่มสินค้า"
external-label
label-position="left"
style="color: white; background-color: hsla(var(--green-11-hsl))"
padding="xs"
icon="mdi-folder-multiple-plus"
@click="
() => {
dialogProduct = true;
}
"
></q-fab-action>
<q-fab-action
v-if="productMode === 'service'"
label="เพิ่มบริการ"
external-label
label-position="left"
style="color: white; background-color: hsla(var(--blue-11-hsl))"
padding="xs"
icon="mdi-folder-multiple-plus"
@click="
() => {
clearFormGroup();
2024-06-14 14:45:17 +07:00
dialogInputForm = true;
}
"
></q-fab-action>
2024-06-14 09:31:45 +07:00
</ButtonAddComponent>
2024-06-12 15:37:17 +07:00
<div class="column q-pb-lg">
<div class="row text-h6 text-weight-bold q-mb-md">
{{ $t('productAndService') }}
</div>
2024-06-11 16:52:35 +07:00
<AppBox
v-if="stat[0].count === 0"
2024-06-12 15:37:17 +07:00
class="column"
:no-padding="productGroup?.length !== 0"
2024-06-11 16:52:35 +07:00
bordered
2024-06-12 15:37:17 +07:00
style="min-height: 70vh"
2024-06-11 16:52:35 +07:00
>
<TooltipComponent
class="self-end"
title="messageTooltipNoProduct"
caption="messageTooltipProductCreate"
imgSrc="personnel-table-"
/>
<div class="row items-center justify-center" style="flex-grow: 1">
<AddButton
label="productCreate"
@trigger="() => (dialogInputForm = true)"
2024-06-12 15:37:17 +07:00
/>
</div>
2024-06-10 16:42:59 +07:00
</AppBox>
2024-06-12 15:37:17 +07:00
<div v-if="stat[0].count !== 0">
2024-06-12 15:37:17 +07:00
<div
v-if="productMode === 'group'"
class="text-h6 text-weight-bold q-mb-md"
></div>
<div v-else-if="productMode === 'type'" class="row items-center q-mb-md">
<q-btn
round
icon="mdi-arrow-left"
flat
dense
@click="productMode = 'group'"
class="q-mr-md"
/>
<div class="text-h6 app-text-muted q-mr-sm hover-underline">
{{ groupName }}
</div>
2024-06-12 15:37:17 +07:00
<div class="text-h6 app-text-muted q-mx-sm">/</div>
<div class="text-h6 text-weight-bold">
{{ $t('productAndServiceType') }}
</div>
</div>
<div
v-else-if="productMode === 'service'"
class="row items-center q-mb-md"
>
<q-btn
round
icon="mdi-arrow-left"
flat
dense
@click="productMode = 'type'"
class="q-mr-md"
/>
<div class="text-h6 app-text-muted q-mr-sm hover-underline">
{{ groupName }}
</div>
<div class="text-h6 app-text-muted q-mx-sm">/</div>
<div class="text-h6 app-text-muted q-mr-sm hover-underline">
{{ 'บริการพิสูจน์สัญชาติ' }}
2024-06-10 16:42:59 +07:00
</div>
2024-06-12 15:37:17 +07:00
<div class="text-h6 app-text-muted q-mx-sm">/</div>
<div class="text-h6 text-weight-bold">
{{ $t('mainProductTitle') }}
</div>
</div>
<AppBox
v-if="productMode === 'group' || productMode === 'type'"
bordered
class="q-mb-md"
>
<StatCard label-i18n :branch="stat" :dark="$q.dark.isActive" />
</AppBox>
<AppBox
v-if="productMode === 'group' || productMode === 'type'"
bordered
style="min-height: 80vh"
>
<div class="row justify-between">
<div
v-if="productMode === 'type'"
class="text-h6 text-weight-bold q-mb-md"
>
{{ $t('productAndServiceType') }}
</div>
<div
v-else-if="productMode === 'group'"
class="text-h6 text-weight-bold q-mb-md"
>
{{ $t('productAndServiceAll') }}
</div>
<div
v-if="productMode === 'group' || productMode === 'type'"
class="row q-px-md q-pb-md"
>
<q-input
style="width: 300px"
outlined
dense
:label="$t('search')"
class="q-mr-lg"
:bg-color="$q.dark.isActive ? 'dark' : 'white'"
v-model="inputSearch"
debounce="500"
2024-06-13 11:20:35 +07:00
@update:model-value="
productMode === 'group'
? searchGroup()
: productMode === 'type'
? searchType()
2024-06-13 11:20:35 +07:00
: ''
"
2024-06-12 15:37:17 +07:00
>
<template v-slot:prepend>
<q-icon name="mdi-magnify" />
</template>
</q-input>
<q-btn
icon="mdi-tune-vertical-variant"
size="sm"
:color="$q.dark.isActive ? 'dark' : 'white'"
:text-color="$q.dark.isActive ? 'white' : 'dark'"
class="bordered rounded"
unelevated
>
<q-menu class="bordered">
<q-list v-close-popup dense>
<q-item
clickable
class="flex items-center"
2024-06-14 09:31:45 +07:00
@click="currentStatus = 'All'"
2024-06-12 15:37:17 +07:00
>
{{ $t('all') }}
</q-item>
<q-item
clickable
class="flex items-center"
2024-06-14 09:31:45 +07:00
@click="currentStatus = 'ACTIVE'"
2024-06-12 15:37:17 +07:00
>
{{ $t('statusACTIVE') }}
</q-item>
<q-item
clickable
class="flex items-center"
2024-06-14 09:31:45 +07:00
@click="currentStatus = 'INACTIVE'"
2024-06-12 15:37:17 +07:00
>
{{ $t('statusINACTIVE') }}
</q-item>
</q-list>
</q-menu>
</q-btn>
</div>
</div>
2024-06-12 15:37:17 +07:00
<div class="row q-col-gutter-lg">
<div
:class="`${$q.screen.gt.sm ? 'col-3' : $q.screen.gt.xs ? 'col-6' : 'col-12'}`"
2024-06-13 11:26:26 +07:00
v-for="(v, i) in !!inputSearch
? productMode === 'group'
2024-06-13 11:20:35 +07:00
? resultSearchGroup
2024-06-13 11:26:26 +07:00
: resultSearchType
: productMode === 'type'
? productType
2024-06-13 11:20:35 +07:00
: productGroup"
2024-06-12 15:37:17 +07:00
:key="i"
>
<ProductCardComponent
v-if="productMode === 'type'"
:title="v.name"
2024-06-14 16:36:28 +07:00
isType
2024-06-12 15:37:17 +07:00
:subtitle="v.code"
:date="new Date(v.updatedAt)"
:status="v.status"
2024-06-14 16:36:28 +07:00
color="var(--purple-11-hsl)"
@viewCard="
2024-06-12 15:37:17 +07:00
() => {
clearFormGroup();
2024-06-12 15:37:17 +07:00
currentIdType = v.id;
assignFormDataGroup(v);
2024-06-12 15:37:17 +07:00
isEdit = false;
drawerInfo = true;
}
"
@updateCard="
2024-06-12 15:37:17 +07:00
() => {
clearFormGroup();
currentIdType = v.id;
assignFormDataGroup(v);
isEdit = true;
drawerInfo = true;
}
"
@deleteCard="
() => {
deleteProductById(v.id);
}
"
@on-click="
async () => {
2024-06-12 15:37:17 +07:00
currentIdType = v.id;
productMode = 'service';
await fetchListOfProduct(currentIdType);
2024-06-12 15:37:17 +07:00
}
"
/>
<ProductCardComponent
v-else-if="productMode === 'group'"
:title="v.name"
:subtitle="v.code"
:date="new Date(v.updatedAt)"
:status="v.status"
2024-06-14 16:36:28 +07:00
color="var(--pink-6-hsl)"
@viewCard="
2024-06-12 15:37:17 +07:00
() => {
clearFormGroup();
assignFormDataGroup(v);
2024-06-12 15:37:17 +07:00
isEdit = false;
currentId = v.id;
drawerInfo = true;
}
"
@updateCard="
() => {
clearFormGroup();
assignFormDataGroup(v);
isEdit = true;
currentId = v.id;
2024-06-12 15:37:17 +07:00
drawerInfo = true;
}
"
@deleteCard="
() => {
deleteProductById(v.id);
}
"
2024-06-12 15:37:17 +07:00
@on-click="
async () => {
currentId = v.id;
console.log(v.id);
productMode = 'type';
await fetchListType();
}
"
/>
</div>
</div>
<div
v-if="
(productMode === 'type' && productType?.length === 0) ||
(productGroup?.length === 0 && productMode === 'group')
"
class="flex justify-center items-center"
style="min-height: 70vh; background-color: var(--surface-2)"
>
<NoData />
</div>
2024-06-12 15:37:17 +07:00
</AppBox>
<AppBox bordered v-else-if="productMode === 'service'" no-padding>
<div class="row justify-between q-px-md">
<q-tabs v-model="productAndServiceTab" dense>
<q-tab name="all">
<div
class="row"
:class="
productAndServiceTab === 'all'
? 'text-bold'
: 'app-text-muted'
"
>
ทั้งหมด
<q-badge
class="rounded q-ml-sm"
:class="
productAndServiceTab === 'all' ? '' : 'app-text-muted'
"
:color="productAndServiceTab === 'all' ? 'primary' : ''"
style="background-color: var(--surface-3)"
label="2"
/>
</div>
</q-tab>
<q-tab name="product">
<div
class="row"
:class="
productAndServiceTab === 'product'
? 'text-bold'
: 'app-text-muted'
"
>
ทั้งหมด
<q-badge
class="rounded q-ml-sm"
:class="
productAndServiceTab === 'product' ? '' : 'app-text-muted'
"
:color="productAndServiceTab === 'product' ? 'primary' : ''"
style="background-color: var(--surface-3)"
label="2"
/>
</div>
</q-tab>
<q-tab name="service">
<div
class="row"
:class="
productAndServiceTab === 'service'
? 'text-bold'
: 'app-text-muted'
"
>
ทั้งหมด
<q-badge
class="rounded q-ml-sm"
:class="
productAndServiceTab === 'service' ? '' : 'app-text-muted'
"
:color="productAndServiceTab === 'service' ? 'primary' : ''"
style="background-color: var(--surface-3)"
label="2"
/>
</div>
</q-tab>
</q-tabs>
<div class="row q-pt-sm q-mb-sm">
<q-input
style="width: 300px"
outlined
dense
unelavated
:label="$t('search')"
class="q-mr-md"
:bg-color="$q.dark.isActive ? 'dark' : 'white'"
v-model="inputSearch"
debounce="500"
>
<template v-slot:prepend>
<q-icon name="mdi-magnify" />
</template>
</q-input>
<q-btn
icon="mdi-tune-vertical-variant"
size="sm"
:color="$q.dark.isActive ? 'dark' : 'white'"
:text-color="$q.dark.isActive ? 'white' : 'dark'"
class="bordered rounded q-py-sm"
unelevated
>
<q-menu class="bordered">
<q-list v-close-popup dense>
<q-item
clickable
class="flex items-center"
@click="console.log('test')"
>
{{ $t('all') }}
</q-item>
<q-item
clickable
class="flex items-center"
@click="console.log('test')"
>
{{ $t('statusACTIVE') }}
</q-item>
<q-item
clickable
class="flex items-center"
@click="console.log('test')"
>
{{ $t('statusINACTIVE') }}
</q-item>
</q-list>
</q-menu>
</q-btn>
</div>
</div>
2024-06-11 16:52:35 +07:00
<div
v-if="product && product.length === 0"
class="flex justify-center items-center"
style="min-height: 70vh; background-color: var(--surface-2)"
2024-06-11 16:52:35 +07:00
>
<NoData />
2024-06-10 17:42:37 +07:00
</div>
<div
v-if="product && product.length > 0"
class="flex q-pa-md"
style="
min-height: 70vh;
background-color: var(--surface-2);
grid-template-columns: repeat(4, 1fr);
gap: var(--size-3);
"
>
<div v-for="i in product" :key="i.id">
<TotalProductCardComponent
typeProduct="product"
:title="i.name"
:code="i.code"
:price="i.price"
:process="i.process"
@viewDetail="() => {}"
/>
</div>
</div>
2024-06-12 15:37:17 +07:00
</AppBox>
</div>
2024-06-10 16:42:59 +07:00
</div>
<FormDialog
v-model:modal="dialogInputForm"
noAddress
2024-06-12 15:37:17 +07:00
:title="$t('addProduct')"
:submit="() => (productMode === 'type' ? submitType() : submitGroup())"
:close="() => {}"
>
<template #information>
<BasicInformation
dense
2024-06-11 16:52:35 +07:00
:isType="productMode === 'type'"
v-model:remark="formDataGroup.remark"
v-model:name="formDataGroup.name"
v-model:detail="formDataGroup.detail"
/>
</template>
</FormDialog>
<DrawerInfo
ref="formDialogRef"
v-model:drawerOpen="drawerInfo"
:title="'test'"
:undo="() => undoProductGroup()"
:isEdit="isEdit"
:editData="() => (isEdit = true)"
2024-06-11 16:52:35 +07:00
:submit="() => (productMode === 'type' ? submitType() : submitGroup())"
:delete-data="() => deleteProductById()"
:close="() => (drawerInfo = false)"
>
<template #info>
<AppBox class="q-ma-md" bordered>
<BasicInformation
dense
2024-06-11 16:52:35 +07:00
:isType="productMode === 'type'"
:readonly="!isEdit"
v-model:remark="formDataGroup.remark"
v-model:name="formDataGroup.name"
v-model:code="formDataGroup.code"
v-model:detail="formDataGroup.detail"
/>
</AppBox>
</template>
</DrawerInfo>
<FormDialog
v-model:modal="dialogProductServiceType"
:title="'สร้างสินค้าและบริการ'"
no-footer
no-app-box
:max-width="80"
>
<template #body>
<div class="row q-gutter-xl q-pa-sm">
<ItemCard
class="col"
v-for="i in itemCard"
changeColor
:key="i.text"
:icon="i.icon"
:text="i.text"
:color="i.color"
@trigger="
() => {
dialogProductServiceType = false;
console.log('test');
}
"
/>
</div>
</template>
</FormDialog>
<FormDialog
v-model:modal="dialogTotalProduct"
noAddress
noAppBox
title="รวมสินค้าทั้งหมด (2 ชิ้น)"
:submit="
() => {
console.log('submit');
}
"
:close="() => {}"
>
2024-06-13 15:59:09 +07:00
<template #footer>
<div class="row items-center q-gutter-md">
<q-icon name="mdi-cart" class="app-text-muted" size="sm" />
<div class="relative-position" style="bottom: 15px; right: 25px">
<div
class="absolute bg-red text-white flex justify-center text-center rounded items-center"
style="width: 16px; height: 16px; font-size: 11px"
>
2
</div>
</div>
<div>
รวมสินค้าทั้งหมด
<div class="text-bold" style="color: var(--green-10)">฿ 2,400</div>
</div>
</div>
</template>
<TotalProductComponent />
</FormDialog>
2024-06-14 14:45:17 +07:00
<!-- Add Product -->
2024-06-14 14:45:17 +07:00
<FormDialog
v-model:modal="dialogProduct"
noAddress
noAppBox
title="เพิ่มสินค้า"
:submit="
() => {
submitProduct();
}
"
:close="
() => {
dialogProduct = false;
}
"
>
<template #prepend>
<ProfileUpload
isProduct
v-model:url-profile="profileUrl"
v-model:status-toggle="statusToggle"
v-model:profile-submit="profileSubmit"
@input-file="inputFile.click()"
/>
</template>
<AppBox class="col-10" bordered>
<BasicInfoProduct
v-model:detail="formDataProduct.detail"
v-model:remark="formDataProduct.remark"
v-model:name="formDataProduct.name"
v-model:code="formDataProduct.code"
dense
separator
/>
<PriceDataComponent
v-model:price="formDataProduct.price"
v-model:agent-price="formDataProduct.agentPrice"
v-model:service-charge="formDataProduct.serviceCharge"
dense
/>
</AppBox>
</FormDialog>
<!-- edit product -->
<FormDialog
v-model:modal="dialogProduct"
noAddress
noAppBox
title="แก้ไข"
:submit="
() => {
submitProduct();
2024-06-14 14:45:17 +07:00
}
"
:close="
() => {
dialogProduct = false;
}
"
>
<template #prepend>
<ProfileUpload
isProduct
v-model:url-profile="profileUrl"
v-model:status-toggle="statusToggle"
v-model:profile-submit="profileSubmit"
@input-file="inputFile.click()"
/>
</template>
<AppBox class="col-10" bordered>
<BasicInfoProduct
v-model:detail="formDataProduct.detail"
v-model:remark="formDataProduct.remark"
v-model:name="formDataProduct.name"
v-model:code="formDataProduct.code"
dense
separator
/>
<PriceDataComponent
v-model:price="formDataProduct.price"
v-model:agent-price="formDataProduct.agentPrice"
v-model:service-charge="formDataProduct.serviceCharge"
dense
/>
2024-06-14 14:45:17 +07:00
</AppBox>
</FormDialog>
2024-06-10 16:42:59 +07:00
</template>
<style scoped>
.hover-underline:hover {
cursor: pointer;
text-decoration: underline;
}
</style>