2024-06-10 16:42:59 +07:00
|
|
|
<script setup lang="ts">
|
2024-07-09 11:19:10 +07:00
|
|
|
import { ref, watch, reactive } from 'vue';
|
2024-06-28 14:38:16 +07:00
|
|
|
import { useI18n } from 'vue-i18n';
|
|
|
|
|
import { onMounted } from 'vue';
|
2024-07-10 13:21:32 +07:00
|
|
|
import { getUserId, getRole } from 'src/services/keycloak';
|
2024-06-28 14:38:16 +07:00
|
|
|
import { storeToRefs } from 'pinia';
|
2024-07-18 09:10:51 +00:00
|
|
|
import { useQuasar, type QTableProps } from 'quasar';
|
2024-06-28 14:38:16 +07:00
|
|
|
import ItemCard from 'components/ItemCard.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-28 14:14:23 +07:00
|
|
|
import ProductCardComponent from 'components/04_product-service/ProductCardComponent.vue';
|
2024-06-10 16:42:59 +07:00
|
|
|
import StatCard from 'components/StatCardComponent.vue';
|
2024-06-28 14:14:23 +07:00
|
|
|
import DrawerInfo from 'components/DrawerInfo.vue';
|
|
|
|
|
import BasicInformation from 'components/04_product-service/BasicInformation.vue';
|
|
|
|
|
import FormDialog from 'components/FormDialog.vue';
|
2024-06-12 15:37:17 +07:00
|
|
|
import TooltipComponent from 'components/TooltipComponent.vue';
|
2024-06-28 14:14:23 +07:00
|
|
|
import ButtonAddComponent from 'components/ButtonAddCompoent.vue';
|
|
|
|
|
import BasicInfoProduct from 'components/04_product-service/BasicInfoProduct.vue';
|
|
|
|
|
import PriceDataComponent from 'components/04_product-service/PriceDataComponent.vue';
|
|
|
|
|
import ProfileUpload from 'components/ProfileUpload.vue';
|
2024-06-17 17:59:09 +07:00
|
|
|
import TotalProductCardComponent from 'components/04_product-service/TotalProductCardComponent.vue';
|
2024-06-28 14:14:23 +07:00
|
|
|
import FormServiceWork from 'components/04_product-service/FormServiceWork.vue';
|
|
|
|
|
import ServiceProperties from 'components/04_product-service/ServiceProperties.vue';
|
|
|
|
|
import WorkNameManagement from 'components/04_product-service/WorkNameManagement.vue';
|
2024-06-18 11:47:53 +00:00
|
|
|
import useOptionStore from 'src/stores/options';
|
2024-06-28 14:14:23 +07:00
|
|
|
import FormServiceProperties from 'components/04_product-service/FormServiceProperties.vue';
|
|
|
|
|
import InfoForm from 'components/02_personnel-management/InfoForm.vue';
|
2024-06-28 14:38:16 +07:00
|
|
|
import NoData from 'components/NoData.vue';
|
2024-07-01 13:48:48 +07:00
|
|
|
import PaginationComponent from 'src/components/PaginationComponent.vue';
|
2024-07-30 16:24:11 +07:00
|
|
|
import TreeCompoent from 'src/components/TreeCompoent.vue';
|
2024-08-07 10:11:53 +00:00
|
|
|
import DialogForm from 'src/components/DialogForm.vue';
|
|
|
|
|
import ProfileBanner from 'src/components/ProfileBanner.vue';
|
|
|
|
|
import SideMenu from 'src/components/SideMenu.vue';
|
2024-08-08 02:25:12 +00:00
|
|
|
import ImageUploadDialog from 'src/components/ImageUploadDialog.vue';
|
2024-06-14 09:31:45 +07:00
|
|
|
|
2024-06-26 17:21:26 +07:00
|
|
|
import useFlowStore from 'src/stores/flow';
|
2024-07-04 11:38:10 +07:00
|
|
|
import useMyBranchStore from 'src/stores/my-branch';
|
|
|
|
|
|
2024-07-09 16:18:48 +07:00
|
|
|
import { dateFormat } from 'src/utils/datetime';
|
2024-07-09 17:17:08 +07:00
|
|
|
import { formatNumberDecimal } from 'src/stores/utils';
|
2024-07-09 16:18:48 +07:00
|
|
|
|
2024-07-10 13:21:32 +07:00
|
|
|
const userBranchStore = useMyBranchStore();
|
2024-07-04 11:38:10 +07:00
|
|
|
|
2024-07-10 13:21:32 +07:00
|
|
|
const { currentMyBranch } = storeToRefs(userBranchStore);
|
2024-07-04 11:38:10 +07:00
|
|
|
|
2024-06-14 09:31:45 +07:00
|
|
|
import { Status } from 'src/stores/types';
|
2024-06-26 17:21:26 +07:00
|
|
|
|
2024-07-02 09:58:59 +00:00
|
|
|
import useUtilsStore, { dialog, dialogWarningClose } 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,
|
2024-06-17 17:59:09 +07:00
|
|
|
ProductCreate,
|
|
|
|
|
ProductList,
|
2024-06-18 14:20:37 +07:00
|
|
|
ServiceCreate,
|
2024-06-18 15:41:30 +07:00
|
|
|
Service,
|
|
|
|
|
ServiceById,
|
2024-06-20 18:02:02 +07:00
|
|
|
WorkItems,
|
|
|
|
|
Attributes,
|
2024-06-25 14:31:08 +07:00
|
|
|
ServiceAndProduct,
|
2024-06-14 15:18:59 +07:00
|
|
|
} from 'src/stores/product-service/types';
|
2024-07-15 14:12:53 +07:00
|
|
|
import { computed } from 'vue';
|
2024-06-11 15:04:01 +07:00
|
|
|
|
2024-06-28 14:38:16 +07:00
|
|
|
const flowStore = useFlowStore();
|
2024-07-02 09:58:59 +00:00
|
|
|
const utilsStore = useUtilsStore();
|
2024-06-11 15:04:01 +07:00
|
|
|
const productServiceStore = useProductServiceStore();
|
2024-06-18 11:47:53 +00:00
|
|
|
const optionStore = useOptionStore();
|
2024-06-11 15:04:01 +07:00
|
|
|
|
|
|
|
|
const {
|
2024-06-17 17:59:09 +07:00
|
|
|
fetchStatsProductType,
|
2024-06-12 15:37:17 +07:00
|
|
|
createProductServiceType,
|
|
|
|
|
editProductServiceType,
|
|
|
|
|
deleteProductServiceType,
|
|
|
|
|
fetchListProductServiceType,
|
|
|
|
|
|
2024-06-11 15:04:01 +07:00
|
|
|
fetchStatsProductGroup,
|
|
|
|
|
fetchListProductService,
|
|
|
|
|
createProductService,
|
2024-06-11 16:29:00 +07:00
|
|
|
editProductService,
|
2024-06-11 15:46:51 +07:00
|
|
|
deleteProductService,
|
2024-06-17 17:59:09 +07:00
|
|
|
|
2024-06-18 16:26:49 +07:00
|
|
|
fetchStatsProduct,
|
2024-06-17 17:59:09 +07:00
|
|
|
fetchListProduct,
|
|
|
|
|
createProduct,
|
2024-06-19 13:51:45 +07:00
|
|
|
editProduct,
|
|
|
|
|
deleteProduct,
|
2024-06-18 15:41:30 +07:00
|
|
|
|
2024-06-24 09:44:38 +07:00
|
|
|
fetchStatsService,
|
2024-06-18 16:08:50 +07:00
|
|
|
fetchListService,
|
2024-06-18 15:41:30 +07:00
|
|
|
fetchListServiceById,
|
2024-06-18 16:08:50 +07:00
|
|
|
createService,
|
2024-06-18 16:14:50 +07:00
|
|
|
deleteService,
|
2024-06-21 14:50:43 +07:00
|
|
|
editService,
|
2024-06-21 15:59:18 +07:00
|
|
|
|
|
|
|
|
createWork,
|
|
|
|
|
editWork,
|
|
|
|
|
deleteWork,
|
2024-06-25 14:31:08 +07:00
|
|
|
|
|
|
|
|
fetchListProductAndService,
|
2024-06-11 15:04:01 +07:00
|
|
|
} = productServiceStore;
|
|
|
|
|
|
2024-07-15 14:12:53 +07:00
|
|
|
const { workNameItems, recordTreeProductType } =
|
|
|
|
|
storeToRefs(productServiceStore);
|
2024-06-21 15:59:18 +07:00
|
|
|
|
2024-06-10 16:42:59 +07:00
|
|
|
const stat = ref<
|
|
|
|
|
{
|
2024-07-03 14:13:22 +07:00
|
|
|
icon: string;
|
2024-06-10 16:42:59 +07:00
|
|
|
count: number;
|
|
|
|
|
label: string;
|
2024-07-11 11:44:17 +07:00
|
|
|
mode: 'group' | 'type' | 'service' | 'product';
|
2024-06-12 15:37:17 +07:00
|
|
|
color: 'pink' | 'purple' | 'green' | 'orange';
|
2024-06-10 16:42:59 +07:00
|
|
|
}[]
|
|
|
|
|
>([
|
2024-07-12 13:35:15 +07:00
|
|
|
{
|
2024-07-11 11:44:17 +07:00
|
|
|
icon: 'mdi-folder',
|
2024-07-12 13:35:15 +07:00
|
|
|
count: 0,
|
|
|
|
|
label: 'productAndService',
|
2024-07-11 11:44:17 +07:00
|
|
|
mode: 'group',
|
2024-07-12 13:35:15 +07:00
|
|
|
color: 'pink',
|
2024-07-11 11:44:17 +07:00
|
|
|
},
|
2024-07-03 14:13:22 +07:00
|
|
|
{
|
2024-07-09 15:23:42 +07:00
|
|
|
icon: 'mdi-folder-table',
|
2024-07-03 14:13:22 +07:00
|
|
|
count: 0,
|
|
|
|
|
label: 'productAndServiceType',
|
2024-07-11 11:44:17 +07:00
|
|
|
mode: 'type',
|
2024-07-03 14:13:22 +07:00
|
|
|
color: 'purple',
|
|
|
|
|
},
|
2024-07-12 13:35:15 +07:00
|
|
|
{
|
|
|
|
|
icon: 'mdi-server-network',
|
|
|
|
|
count: 0,
|
|
|
|
|
label: 'service',
|
|
|
|
|
mode: 'service',
|
|
|
|
|
color: 'orange',
|
2024-07-11 11:44:17 +07:00
|
|
|
},
|
2024-07-12 13:35:15 +07:00
|
|
|
{
|
|
|
|
|
icon: 'mdi-folder',
|
|
|
|
|
count: 0,
|
|
|
|
|
label: 'product',
|
|
|
|
|
mode: 'product',
|
|
|
|
|
color: 'green',
|
2024-07-11 11:44:17 +07:00
|
|
|
},
|
2024-06-10 16:42:59 +07:00
|
|
|
]);
|
|
|
|
|
|
2024-06-11 12:01:35 +07:00
|
|
|
const { t } = useI18n();
|
2024-07-03 10:08:51 +00:00
|
|
|
const baseUrl = ref<string>(import.meta.env.VITE_API_BASE_URL);
|
2024-06-11 12:01:35 +07:00
|
|
|
|
2024-07-19 10:35:18 +00:00
|
|
|
const holdDialog = ref(false);
|
2024-08-08 02:25:12 +00:00
|
|
|
const imageDialog = ref(false);
|
2024-07-19 10:35:18 +00:00
|
|
|
const currentNode = ref<ProductGroup>();
|
2024-07-15 14:12:53 +07:00
|
|
|
const expandedTree = ref<string[]>([]);
|
|
|
|
|
const editByTree = ref<'group' | 'type' | undefined>();
|
|
|
|
|
const treeProductTypeAndGroup = computed(() => {
|
|
|
|
|
const tempValue =
|
|
|
|
|
productGroup.value?.map((item) => {
|
|
|
|
|
return {
|
|
|
|
|
...item,
|
2024-07-24 15:52:44 +07:00
|
|
|
_count: {
|
2024-07-25 10:41:58 +07:00
|
|
|
type:
|
|
|
|
|
recordTreeProductType.value[item.id]?.length ?? item._count.type,
|
2024-07-24 15:52:44 +07:00
|
|
|
service: item._count.service,
|
|
|
|
|
product: item._count.product,
|
|
|
|
|
},
|
2024-07-15 14:12:53 +07:00
|
|
|
type: 'group',
|
|
|
|
|
children:
|
2024-07-23 10:24:22 +07:00
|
|
|
item.id === currentIdGrop.value
|
2024-08-07 10:11:53 +00:00
|
|
|
? (recordTreeProductType.value[currentIdGrop.value]?.map((x) => ({
|
2024-07-19 14:04:02 +07:00
|
|
|
...x,
|
2024-07-15 14:12:53 +07:00
|
|
|
type: 'type',
|
2024-08-07 10:11:53 +00:00
|
|
|
})) ?? [])
|
|
|
|
|
: (recordTreeProductType.value[item.id]?.map((x) => ({
|
2024-07-19 18:05:58 +07:00
|
|
|
...x,
|
|
|
|
|
type: 'type',
|
2024-08-07 10:11:53 +00:00
|
|
|
})) ?? item._count.type > 0)
|
2024-07-19 18:05:58 +07:00
|
|
|
? [
|
|
|
|
|
{
|
|
|
|
|
id: '',
|
|
|
|
|
name: '',
|
|
|
|
|
},
|
|
|
|
|
]
|
|
|
|
|
: [],
|
2024-07-15 14:12:53 +07:00
|
|
|
};
|
|
|
|
|
}) ?? [];
|
|
|
|
|
|
|
|
|
|
return tempValue;
|
|
|
|
|
});
|
2024-08-08 02:25:12 +00:00
|
|
|
const profileFileImg = ref<File | null>(null);
|
2024-07-15 14:12:53 +07:00
|
|
|
|
2024-06-28 14:38:16 +07:00
|
|
|
const inputSearch = ref('');
|
|
|
|
|
const inputSearchProductAndService = ref('');
|
2024-06-19 18:00:38 +07:00
|
|
|
|
2024-06-28 14:38:16 +07:00
|
|
|
const currentStatusProduct = ref(false);
|
|
|
|
|
const drawerInfo = ref(false);
|
|
|
|
|
const isEdit = ref(false);
|
2024-06-21 14:50:43 +07:00
|
|
|
|
2024-07-09 11:19:10 +07:00
|
|
|
const modeView = ref(false);
|
2024-07-12 13:35:15 +07:00
|
|
|
const splitterModel = ref(25);
|
2024-07-09 11:19:10 +07:00
|
|
|
|
2024-06-28 14:38:16 +07:00
|
|
|
const dialogInputForm = ref(false);
|
|
|
|
|
const dialogProduct = ref(false);
|
|
|
|
|
const dialogService = ref(false);
|
|
|
|
|
const dialogProductEdit = ref(false);
|
|
|
|
|
const dialogServiceEdit = ref(false);
|
2024-06-21 14:50:43 +07:00
|
|
|
|
2024-06-28 14:38:16 +07:00
|
|
|
const statusToggle = ref(false);
|
|
|
|
|
const profileSubmit = ref(false);
|
|
|
|
|
const infoProductEdit = ref(false);
|
|
|
|
|
const infoServiceEdit = ref(false);
|
2024-06-19 13:51:45 +07:00
|
|
|
|
2024-06-18 14:00:20 +07:00
|
|
|
const imageProduct = ref<File | undefined>(undefined);
|
2024-06-14 14:45:17 +07:00
|
|
|
const profileUrl = ref<string | null>('');
|
2024-06-11 16:52:35 +07:00
|
|
|
|
2024-06-28 14:38:16 +07:00
|
|
|
const pathGroupName = ref('');
|
|
|
|
|
const pathTypeName = ref('');
|
2024-06-20 18:02:02 +07:00
|
|
|
|
2024-06-28 14:38:16 +07:00
|
|
|
const dialogProductServiceType = ref(false);
|
|
|
|
|
const dialogTotalProduct = ref(false);
|
2024-06-11 15:11:55 +07:00
|
|
|
const productMode = ref<'group' | 'type' | 'service' | 'product'>('group');
|
2024-06-17 17:59:09 +07:00
|
|
|
|
2024-06-14 15:18:59 +07:00
|
|
|
const productGroup = ref<ProductGroup[]>();
|
|
|
|
|
const productType = ref<ProductGroup[]>();
|
2024-06-25 14:31:08 +07:00
|
|
|
const product = ref<(ProductList & { type: 'product' })[]>();
|
2024-06-27 09:41:39 +07:00
|
|
|
const productIsAdd = ref<(ProductList & { type: 'product' })[]>();
|
2024-06-25 14:31:08 +07:00
|
|
|
const service = ref<(Service & { type: 'service' })[]>();
|
2024-06-24 13:07:00 +07:00
|
|
|
const resultSearchProduct = ref<ProductList[]>();
|
2024-06-25 14:31:08 +07:00
|
|
|
const productAndService = ref<ServiceAndProduct[]>([]);
|
2024-06-17 17:59:09 +07:00
|
|
|
|
2024-07-09 11:19:10 +07:00
|
|
|
const productAndServiceTab = ref<'product' | 'service'>('service');
|
2024-06-28 14:38:16 +07:00
|
|
|
const manageWorkNameDialog = ref(false);
|
2024-06-11 16:29:00 +07:00
|
|
|
const previousValue = ref();
|
|
|
|
|
|
2024-06-20 09:10:34 +00:00
|
|
|
const propertiesOption = ref();
|
|
|
|
|
|
2024-06-17 17:59:09 +07:00
|
|
|
const formDataGroup = ref<ProductGroupCreate>({
|
2024-06-11 12:01:35 +07:00
|
|
|
remark: '',
|
|
|
|
|
detail: '',
|
|
|
|
|
name: '',
|
|
|
|
|
code: '',
|
|
|
|
|
});
|
|
|
|
|
|
2024-06-17 17:59:09 +07:00
|
|
|
const formDataProduct = ref<ProductCreate>({
|
2024-07-04 11:38:10 +07:00
|
|
|
registeredBranchId: '',
|
2024-06-17 17:59:09 +07:00
|
|
|
productTypeId: '',
|
|
|
|
|
remark: '',
|
|
|
|
|
serviceCharge: 0,
|
|
|
|
|
agentPrice: 0,
|
|
|
|
|
price: 0,
|
|
|
|
|
process: 0,
|
|
|
|
|
detail: '',
|
|
|
|
|
name: '',
|
|
|
|
|
code: '',
|
2024-06-18 14:00:20 +07:00
|
|
|
image: undefined,
|
2024-06-17 17:59:09 +07:00
|
|
|
});
|
|
|
|
|
|
2024-06-18 14:20:37 +07:00
|
|
|
const formDataProductService = ref<ServiceCreate>({
|
|
|
|
|
work: [],
|
|
|
|
|
attributes: {
|
|
|
|
|
additional: [],
|
|
|
|
|
},
|
|
|
|
|
detail: '',
|
|
|
|
|
name: '',
|
|
|
|
|
code: '',
|
2024-06-25 14:31:08 +07:00
|
|
|
productTypeId: '',
|
2024-07-04 11:38:10 +07:00
|
|
|
registeredBranchId: '',
|
2024-06-18 14:20:37 +07:00
|
|
|
});
|
|
|
|
|
|
2024-06-18 02:01:02 +00:00
|
|
|
const serviceTab = [
|
|
|
|
|
{
|
|
|
|
|
name: 'serviceInformation',
|
|
|
|
|
label: 'serviceInformation',
|
|
|
|
|
},
|
|
|
|
|
{
|
|
|
|
|
name: 'workInformation',
|
|
|
|
|
label: 'workInformation',
|
|
|
|
|
},
|
|
|
|
|
];
|
2024-07-05 03:57:43 +00:00
|
|
|
const hideStat = ref(false);
|
2024-06-20 18:02:02 +07:00
|
|
|
|
2024-07-09 11:19:10 +07:00
|
|
|
const tbColumn = {
|
2024-07-09 14:38:22 +07:00
|
|
|
groupAndType: [
|
2024-07-09 17:17:08 +07:00
|
|
|
{
|
|
|
|
|
name: 'name',
|
|
|
|
|
align: 'left',
|
|
|
|
|
label: 'name',
|
|
|
|
|
field: 'name',
|
|
|
|
|
},
|
|
|
|
|
{
|
|
|
|
|
name: 'detail',
|
|
|
|
|
align: 'left',
|
|
|
|
|
label: 'detail',
|
|
|
|
|
field: 'detail',
|
|
|
|
|
},
|
|
|
|
|
{
|
|
|
|
|
name: 'formDialogInputRemark',
|
|
|
|
|
align: 'left',
|
|
|
|
|
label: 'formDialogInputRemark',
|
|
|
|
|
field: 'remark',
|
|
|
|
|
},
|
|
|
|
|
{
|
|
|
|
|
name: 'createdAt',
|
|
|
|
|
align: 'left',
|
|
|
|
|
label: 'createdAt',
|
|
|
|
|
field: 'createdAt',
|
|
|
|
|
},
|
2024-07-09 14:38:22 +07:00
|
|
|
],
|
|
|
|
|
|
2024-07-09 11:19:10 +07:00
|
|
|
product: [
|
|
|
|
|
{ name: 'productName', align: 'left', label: 'productName', field: 'name' },
|
|
|
|
|
{
|
|
|
|
|
name: 'productDetail',
|
|
|
|
|
align: 'left',
|
|
|
|
|
label: 'productDetail',
|
|
|
|
|
field: 'detail',
|
|
|
|
|
},
|
|
|
|
|
{
|
|
|
|
|
name: 'productProcessingTime',
|
|
|
|
|
align: 'left',
|
|
|
|
|
label: 'productProcessingTime',
|
|
|
|
|
field: 'process',
|
|
|
|
|
},
|
|
|
|
|
{
|
|
|
|
|
name: 'priceInformation',
|
2024-07-09 16:18:48 +07:00
|
|
|
align: 'center',
|
2024-07-09 11:19:10 +07:00
|
|
|
label: 'priceInformation',
|
|
|
|
|
field: 'name',
|
|
|
|
|
},
|
|
|
|
|
],
|
|
|
|
|
service: [
|
|
|
|
|
{ name: 'serviceName', align: 'left', label: 'serviceName', field: 'name' },
|
|
|
|
|
{
|
|
|
|
|
name: 'serviceDetail',
|
|
|
|
|
align: 'left',
|
|
|
|
|
label: 'serviceDetail',
|
|
|
|
|
field: 'detail',
|
|
|
|
|
},
|
|
|
|
|
{
|
|
|
|
|
name: 'serviceWorkTotal',
|
|
|
|
|
align: 'left',
|
|
|
|
|
label: 'serviceWorkTotal',
|
|
|
|
|
field: (v) => v.work.length,
|
|
|
|
|
},
|
2024-07-09 16:18:48 +07:00
|
|
|
{
|
|
|
|
|
name: 'createdAt',
|
|
|
|
|
align: 'left',
|
|
|
|
|
label: 'createdAt',
|
|
|
|
|
field: 'createdAt',
|
2024-07-09 17:17:08 +07:00
|
|
|
},
|
2024-07-09 11:19:10 +07:00
|
|
|
],
|
|
|
|
|
} satisfies {
|
2024-07-09 14:38:22 +07:00
|
|
|
groupAndType: QTableProps['columns'];
|
2024-07-09 11:19:10 +07:00
|
|
|
product: QTableProps['columns'];
|
|
|
|
|
service: QTableProps['columns'];
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
const tbControl = reactive({
|
2024-07-09 14:38:22 +07:00
|
|
|
groupAndType: {
|
|
|
|
|
fieldDisplay: ['name', 'detail', 'formDialogInputRemark', 'createdAt'],
|
|
|
|
|
fieldSelected: ['name', 'detail', 'formDialogInputRemark', 'createdAt'],
|
|
|
|
|
},
|
2024-07-09 11:19:10 +07:00
|
|
|
product: {
|
|
|
|
|
fieldDisplay: [
|
|
|
|
|
'productName',
|
|
|
|
|
'productDetail',
|
|
|
|
|
'productProcessingTime',
|
|
|
|
|
'priceInformation',
|
|
|
|
|
],
|
|
|
|
|
fieldSelected: [
|
|
|
|
|
'productName',
|
|
|
|
|
'productDetail',
|
|
|
|
|
'productProcessingTime',
|
|
|
|
|
'priceInformation',
|
|
|
|
|
],
|
|
|
|
|
},
|
|
|
|
|
service: {
|
2024-07-09 17:17:08 +07:00
|
|
|
fieldDisplay: [
|
|
|
|
|
'serviceName',
|
|
|
|
|
'serviceDetail',
|
|
|
|
|
'serviceWorkTotal',
|
|
|
|
|
'createdAt',
|
|
|
|
|
],
|
|
|
|
|
fieldSelected: [
|
|
|
|
|
'serviceName',
|
|
|
|
|
'serviceDetail',
|
|
|
|
|
'serviceWorkTotal',
|
|
|
|
|
'createdAt',
|
|
|
|
|
],
|
2024-07-09 11:19:10 +07:00
|
|
|
},
|
|
|
|
|
});
|
2024-07-18 09:10:51 +00:00
|
|
|
const $q = useQuasar();
|
2024-07-09 11:19:10 +07:00
|
|
|
|
2024-06-20 18:02:02 +07:00
|
|
|
const workItems = ref<WorkItems[]>([]);
|
2024-06-21 11:06:35 +00:00
|
|
|
const workNameRef = ref();
|
2024-06-26 13:11:03 +07:00
|
|
|
const selectProduct = ref<ProductList[]>([]);
|
|
|
|
|
const currentWorkIndex = ref<number>(0);
|
2024-06-20 18:02:02 +07:00
|
|
|
|
2024-06-18 02:01:02 +00:00
|
|
|
const currentServiceTab = ref('serviceInformation');
|
2024-06-18 11:47:53 +00:00
|
|
|
const propertiesDialog = ref<boolean>(false);
|
2024-06-18 02:01:02 +00:00
|
|
|
|
2024-06-25 14:31:08 +07:00
|
|
|
const totalProduct = ref<number>(0);
|
|
|
|
|
const totalService = ref<number>(0);
|
|
|
|
|
const totalProductAndService = ref<number>(0);
|
|
|
|
|
|
2024-07-11 11:44:17 +07:00
|
|
|
const filterStat = ref<('group' | 'type' | 'service' | 'product')[]>([]);
|
|
|
|
|
|
2024-06-26 13:11:03 +07:00
|
|
|
// แบ่งหน้า
|
|
|
|
|
const currentPageGroup = ref<number>(1);
|
|
|
|
|
const maxPageGroup = ref<number>(1);
|
2024-06-26 13:12:41 +07:00
|
|
|
const pageSizeGroup = ref<number>(30);
|
2024-06-26 13:11:03 +07:00
|
|
|
const currentPageType = ref<number>(1);
|
|
|
|
|
const maxPageType = ref<number>(1);
|
2024-07-01 10:33:39 +07:00
|
|
|
const pageSizeType = ref<number>(30);
|
2024-06-26 13:39:38 +07:00
|
|
|
const maxPageServiceAndProduct = ref<number>(1);
|
2024-07-02 04:35:04 +00:00
|
|
|
const pageSizeServiceAndProduct = ref<number>(10);
|
2024-07-01 14:20:24 +07:00
|
|
|
const currentPageServiceAndProduct = ref<number>(1);
|
2024-07-01 13:48:48 +07:00
|
|
|
const totalType = ref<number>(0);
|
|
|
|
|
const totalGroup = ref<number>(0);
|
2024-07-01 14:20:24 +07:00
|
|
|
const total = ref<number>(0);
|
2024-06-26 11:26:29 +07:00
|
|
|
|
2024-06-26 13:11:03 +07:00
|
|
|
// เก็บ id ที่เข้ามา
|
2024-07-23 10:24:22 +07:00
|
|
|
const currentIdGrop = ref<string>('');
|
2024-06-12 15:37:17 +07:00
|
|
|
const currentIdType = ref<string>('');
|
2024-06-18 16:10:42 +07:00
|
|
|
const currentIdService = ref<string>('');
|
2024-06-19 13:51:45 +07:00
|
|
|
const currentIdProduct = ref<string>('');
|
2024-06-18 16:10:42 +07:00
|
|
|
|
2024-08-07 11:13:42 +00:00
|
|
|
const currentStatusGroupType = ref<Status>('CREATED');
|
|
|
|
|
const currentIdGroupType = ref('');
|
2024-08-07 10:11:53 +00:00
|
|
|
|
2024-07-04 11:38:10 +07:00
|
|
|
const branchOption = ref<{ id: string; name: string }[]>([]);
|
|
|
|
|
|
2024-06-26 13:11:03 +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', () => {
|
2024-06-18 14:00:20 +07:00
|
|
|
imageProduct.value = element.files?.[0];
|
|
|
|
|
if (imageProduct.value) {
|
|
|
|
|
reader.readAsDataURL(imageProduct.value);
|
2024-06-14 14:45:17 +07:00
|
|
|
}
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
return element;
|
|
|
|
|
})();
|
|
|
|
|
|
2024-06-25 14:51:58 +07:00
|
|
|
async function searchProduct(isAdd: boolean = true) {
|
|
|
|
|
const res = await fetchListProduct({
|
|
|
|
|
query: inputSearchProductAndService.value,
|
|
|
|
|
});
|
2024-06-24 13:07:00 +07:00
|
|
|
|
2024-06-25 14:51:58 +07:00
|
|
|
if (res) {
|
|
|
|
|
if (isAdd) {
|
|
|
|
|
resultSearchProduct.value = res.result;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (!isAdd) {
|
|
|
|
|
product.value = res.result.map((v) => {
|
|
|
|
|
return {
|
|
|
|
|
...v,
|
|
|
|
|
type: 'product',
|
|
|
|
|
};
|
|
|
|
|
});
|
|
|
|
|
}
|
|
|
|
|
}
|
2024-06-26 17:21:26 +07:00
|
|
|
flowStore.rotate();
|
2024-06-25 14:51:58 +07:00
|
|
|
}
|
|
|
|
|
|
2024-06-25 14:31:08 +07:00
|
|
|
async function featchStatsService() {
|
|
|
|
|
const resStatsService = await fetchStatsService();
|
|
|
|
|
|
|
|
|
|
totalService.value = resStatsService;
|
2024-06-26 17:21:26 +07:00
|
|
|
flowStore.rotate();
|
2024-06-25 14:31:08 +07:00
|
|
|
}
|
|
|
|
|
|
2024-07-04 11:38:10 +07:00
|
|
|
async function fetchListOfOptionBranch() {
|
2024-07-10 13:21:32 +07:00
|
|
|
const uid = getUserId();
|
|
|
|
|
const role = getRole();
|
2024-07-04 11:38:10 +07:00
|
|
|
|
2024-07-10 13:21:32 +07:00
|
|
|
if (!uid) return;
|
|
|
|
|
|
|
|
|
|
if (role?.includes('system')) {
|
|
|
|
|
const result = await userBranchStore.fetchListOptionBranch();
|
|
|
|
|
if (result && result.total > 0) branchOption.value = result.result;
|
|
|
|
|
} else {
|
|
|
|
|
const result = await userBranchStore.fetchListMyBranch(uid);
|
|
|
|
|
if (result && result.total > 0) branchOption.value = result.result;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
formDataProduct.value.registeredBranchId = currentMyBranch.value?.id || '';
|
|
|
|
|
formDataProductService.value.registeredBranchId =
|
|
|
|
|
currentMyBranch.value?.id || '';
|
2024-07-04 11:38:10 +07:00
|
|
|
}
|
|
|
|
|
|
2024-06-25 14:31:08 +07:00
|
|
|
async function featchStatsProduct() {
|
|
|
|
|
const resStatsProduct = await fetchStatsProduct({
|
|
|
|
|
productTypeId: currentIdType.value,
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
totalProduct.value = resStatsProduct;
|
2024-06-26 17:21:26 +07:00
|
|
|
flowStore.rotate();
|
2024-06-25 14:31:08 +07:00
|
|
|
}
|
|
|
|
|
|
2024-06-12 15:37:17 +07:00
|
|
|
async function fetchListType() {
|
|
|
|
|
const res = await fetchListProductServiceType({
|
2024-06-26 13:11:03 +07:00
|
|
|
page: currentPageType.value,
|
|
|
|
|
pageSize: pageSizeType.value,
|
2024-07-01 09:53:51 +07:00
|
|
|
query: !!inputSearch.value ? inputSearch.value : undefined,
|
2024-07-23 10:24:22 +07:00
|
|
|
productGroupId: currentIdGrop.value,
|
2024-06-17 17:59:09 +07:00
|
|
|
status:
|
|
|
|
|
currentStatus.value === 'All'
|
|
|
|
|
? undefined
|
|
|
|
|
: currentStatus.value === 'ACTIVE'
|
|
|
|
|
? 'ACTIVE'
|
|
|
|
|
: 'INACTIVE',
|
2024-06-12 15:37:17 +07:00
|
|
|
});
|
|
|
|
|
|
|
|
|
|
if (res) {
|
2024-06-26 13:11:03 +07:00
|
|
|
currentPageType.value = res.page;
|
2024-07-01 13:48:48 +07:00
|
|
|
totalType.value = res.total;
|
2024-06-26 13:11:03 +07:00
|
|
|
maxPageType.value = Math.ceil(res.total / pageSizeType.value);
|
2024-06-26 11:26:29 +07:00
|
|
|
productType.value = res.result;
|
2024-06-12 15:37:17 +07:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
async function fetchListGroups() {
|
2024-06-17 17:59:09 +07:00
|
|
|
const res = await fetchListProductService({
|
2024-06-26 13:11:03 +07:00
|
|
|
page: currentPageGroup.value,
|
|
|
|
|
pageSize: pageSizeGroup.value,
|
2024-07-01 09:53:51 +07:00
|
|
|
query: !!inputSearch.value ? inputSearch.value : undefined,
|
2024-06-17 17:59:09 +07:00
|
|
|
status:
|
|
|
|
|
currentStatus.value === 'All'
|
|
|
|
|
? undefined
|
|
|
|
|
: currentStatus.value === 'ACTIVE'
|
|
|
|
|
? 'ACTIVE'
|
|
|
|
|
: 'INACTIVE',
|
|
|
|
|
});
|
2024-06-12 15:37:17 +07:00
|
|
|
|
|
|
|
|
if (res) {
|
2024-06-26 13:11:03 +07:00
|
|
|
currentPageGroup.value = res.page;
|
2024-07-01 13:48:48 +07:00
|
|
|
totalGroup.value = res.total;
|
2024-06-26 13:11:03 +07:00
|
|
|
maxPageGroup.value = Math.ceil(res.total / pageSizeGroup.value);
|
2024-06-26 11:26:29 +07:00
|
|
|
productGroup.value = res.result;
|
2024-06-12 15:37:17 +07:00
|
|
|
}
|
|
|
|
|
}
|
2024-06-11 15:46:51 +07:00
|
|
|
|
2024-06-27 09:41:39 +07:00
|
|
|
async function fetchListOfProductIsAdd(productTypeId: string) {
|
|
|
|
|
const res = await fetchListProduct({
|
|
|
|
|
status:
|
|
|
|
|
currentStatus.value === 'INACTIVE'
|
|
|
|
|
? 'INACTIVE'
|
|
|
|
|
: currentStatus.value === 'ACTIVE'
|
|
|
|
|
? 'ACTIVE'
|
|
|
|
|
: undefined,
|
|
|
|
|
productTypeId,
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
if (res) {
|
|
|
|
|
productIsAdd.value = res.result.map((v) => {
|
|
|
|
|
return {
|
|
|
|
|
...v,
|
|
|
|
|
type: 'product',
|
|
|
|
|
};
|
|
|
|
|
});
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2024-07-01 10:33:39 +07:00
|
|
|
async function fetchListOfProduct() {
|
2024-06-25 14:31:08 +07:00
|
|
|
const res = await fetchListProduct({
|
2024-07-01 14:20:24 +07:00
|
|
|
page: currentPageServiceAndProduct.value,
|
|
|
|
|
pageSize: pageSizeServiceAndProduct.value,
|
2024-07-01 09:53:51 +07:00
|
|
|
query: !!inputSearchProductAndService.value
|
|
|
|
|
? inputSearchProductAndService.value
|
|
|
|
|
: undefined,
|
2024-06-25 14:31:08 +07:00
|
|
|
status:
|
|
|
|
|
currentStatus.value === 'INACTIVE'
|
|
|
|
|
? 'INACTIVE'
|
|
|
|
|
: currentStatus.value === 'ACTIVE'
|
|
|
|
|
? 'ACTIVE'
|
|
|
|
|
: undefined,
|
2024-07-01 10:33:39 +07:00
|
|
|
productTypeId: currentIdType.value,
|
2024-06-25 14:31:08 +07:00
|
|
|
});
|
2024-06-17 17:59:09 +07:00
|
|
|
|
|
|
|
|
if (res) {
|
2024-07-01 14:20:24 +07:00
|
|
|
total.value = res.total;
|
2024-07-01 10:33:39 +07:00
|
|
|
totalProduct.value = res.total;
|
2024-07-01 14:20:24 +07:00
|
|
|
currentPageServiceAndProduct.value = res.page;
|
|
|
|
|
maxPageServiceAndProduct.value = Math.ceil(
|
|
|
|
|
res.total / pageSizeServiceAndProduct.value,
|
|
|
|
|
);
|
2024-06-26 13:39:38 +07:00
|
|
|
|
2024-06-25 14:31:08 +07:00
|
|
|
product.value = res.result.map((v) => {
|
|
|
|
|
return {
|
|
|
|
|
...v,
|
|
|
|
|
type: 'product',
|
|
|
|
|
};
|
|
|
|
|
});
|
2024-06-17 17:59:09 +07:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2024-06-18 16:08:50 +07:00
|
|
|
async function fetchListOfService() {
|
2024-06-25 14:31:08 +07:00
|
|
|
const res = await fetchListService({
|
2024-07-01 14:20:24 +07:00
|
|
|
page: currentPageServiceAndProduct.value,
|
2024-07-01 09:53:51 +07:00
|
|
|
query: !!inputSearchProductAndService.value
|
|
|
|
|
? inputSearchProductAndService.value
|
|
|
|
|
: undefined,
|
2024-07-01 14:20:24 +07:00
|
|
|
pageSize: pageSizeServiceAndProduct.value,
|
2024-06-25 14:31:08 +07:00
|
|
|
status:
|
|
|
|
|
currentStatus.value === 'INACTIVE'
|
|
|
|
|
? 'INACTIVE'
|
|
|
|
|
: currentStatus.value === 'ACTIVE'
|
|
|
|
|
? 'ACTIVE'
|
|
|
|
|
: undefined,
|
|
|
|
|
productTypeId: currentIdType.value,
|
|
|
|
|
});
|
2024-06-18 16:08:50 +07:00
|
|
|
|
|
|
|
|
if (res) {
|
2024-07-01 10:33:39 +07:00
|
|
|
totalService.value = res.total;
|
2024-07-01 14:20:24 +07:00
|
|
|
total.value = res.total;
|
|
|
|
|
currentPageServiceAndProduct.value = res.page;
|
|
|
|
|
maxPageServiceAndProduct.value = Math.ceil(
|
|
|
|
|
res.total / pageSizeServiceAndProduct.value,
|
|
|
|
|
);
|
2024-06-25 14:31:08 +07:00
|
|
|
service.value = res.result.map((v) => {
|
|
|
|
|
return {
|
|
|
|
|
...v,
|
|
|
|
|
type: 'service',
|
|
|
|
|
};
|
|
|
|
|
});
|
2024-06-18 16:08:50 +07:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2024-06-11 12:01:35 +07:00
|
|
|
async function submitType() {
|
2024-06-12 15:37:17 +07:00
|
|
|
if (drawerInfo.value) {
|
|
|
|
|
await editProductServiceType(currentIdType.value, {
|
2024-06-17 17:59:09 +07:00
|
|
|
...formDataGroup.value,
|
2024-07-23 10:24:22 +07:00
|
|
|
productGroupId: currentIdGrop.value,
|
2024-06-12 15:37:17 +07:00
|
|
|
});
|
|
|
|
|
drawerInfo.value = false;
|
|
|
|
|
} else {
|
|
|
|
|
dialogInputForm.value = false;
|
2024-06-17 17:59:09 +07:00
|
|
|
const res = await createProductServiceType(
|
2024-07-23 10:24:22 +07:00
|
|
|
currentIdGrop.value,
|
2024-06-17 17:59:09 +07:00
|
|
|
formDataGroup.value,
|
|
|
|
|
);
|
|
|
|
|
|
|
|
|
|
if (res) {
|
|
|
|
|
stat.value[1].count = stat.value[1].count + 1;
|
|
|
|
|
}
|
2024-06-12 15:37:17 +07:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
await fetchListType();
|
2024-06-11 12:01:35 +07:00
|
|
|
}
|
|
|
|
|
|
2024-06-11 15:11:55 +07:00
|
|
|
const itemCard = [
|
|
|
|
|
{
|
|
|
|
|
icon: 'mdi:server-network',
|
|
|
|
|
text: 'บริการ',
|
|
|
|
|
color: 'var(--orange-5)',
|
|
|
|
|
},
|
|
|
|
|
{
|
|
|
|
|
icon: 'mdi:shopping',
|
|
|
|
|
text: 'สินค้า',
|
|
|
|
|
color: 'var(--green-9)',
|
|
|
|
|
},
|
|
|
|
|
];
|
|
|
|
|
|
2024-06-24 14:29:31 +07:00
|
|
|
async function toggleStatusProduct(id: string, status: Status) {
|
|
|
|
|
await editProduct(id, {
|
|
|
|
|
status: status === 'INACTIVE' ? 'ACTIVE' : 'INACTIVE',
|
|
|
|
|
});
|
|
|
|
|
|
2024-07-08 16:52:00 +07:00
|
|
|
await alternativeFetch();
|
2024-06-26 17:21:26 +07:00
|
|
|
flowStore.rotate();
|
2024-06-24 14:29:31 +07:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
async function toggleStatusService(id: string, status: Status) {
|
|
|
|
|
await editService(id, {
|
|
|
|
|
status: status === 'INACTIVE' ? 'ACTIVE' : 'INACTIVE',
|
|
|
|
|
});
|
|
|
|
|
|
2024-07-08 16:52:00 +07:00
|
|
|
await alternativeFetch();
|
2024-06-26 17:21:26 +07:00
|
|
|
flowStore.rotate();
|
2024-06-24 14:29:31 +07:00
|
|
|
}
|
2024-06-19 18:00:38 +07:00
|
|
|
async function toggleStatusType(id: string, status: Status) {
|
2024-08-07 11:13:42 +00:00
|
|
|
const res = await editProductServiceType(id, {
|
2024-06-19 18:00:38 +07:00
|
|
|
status: status === 'INACTIVE' ? 'ACTIVE' : 'INACTIVE',
|
|
|
|
|
});
|
2024-08-07 11:13:42 +00:00
|
|
|
if (res) currentStatusGroupType.value = res.status;
|
2024-06-19 18:00:38 +07:00
|
|
|
|
|
|
|
|
await fetchListType();
|
2024-06-26 17:21:26 +07:00
|
|
|
flowStore.rotate();
|
2024-06-19 18:00:38 +07:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
async function toggleStatusGroup(id: string, status: Status) {
|
2024-08-07 10:11:53 +00:00
|
|
|
const res = await editProductService(id, {
|
2024-06-19 18:00:38 +07:00
|
|
|
status: status === 'INACTIVE' ? 'ACTIVE' : 'INACTIVE',
|
|
|
|
|
});
|
2024-08-07 11:13:42 +00:00
|
|
|
if (res) currentStatusGroupType.value = res.status;
|
2024-06-19 18:00:38 +07:00
|
|
|
|
|
|
|
|
await fetchListGroups();
|
2024-06-26 17:21:26 +07:00
|
|
|
flowStore.rotate();
|
2024-06-19 18:00:38 +07:00
|
|
|
}
|
|
|
|
|
|
2024-07-25 10:49:43 +00:00
|
|
|
async function triggerChangeStatus(
|
|
|
|
|
id: string,
|
|
|
|
|
status: string,
|
|
|
|
|
type?: 'type' | 'group' | 'service' | 'product',
|
|
|
|
|
) {
|
|
|
|
|
return await new Promise((resolve, reject) => {
|
|
|
|
|
dialog({
|
|
|
|
|
color: status !== 'INACTIVE' ? 'warning' : 'info',
|
|
|
|
|
icon: status !== 'INACTIVE' ? 'mdi-alert' : 'mdi-comment-alert',
|
|
|
|
|
title: t('confirmChangeStatusTitle'),
|
|
|
|
|
actionText:
|
|
|
|
|
status !== 'INACTIVE' ? t('switchOffLabel') : t('switchOnLabel'),
|
|
|
|
|
message:
|
|
|
|
|
status !== 'INACTIVE'
|
|
|
|
|
? t('confirmChangeStatusOffMessage')
|
|
|
|
|
: t('confirmChangeStatusOnMessage'),
|
|
|
|
|
action: async () => {
|
|
|
|
|
if (type === 'group' || productMode.value === 'group') {
|
|
|
|
|
await toggleStatusGroup(id, status as Status)
|
|
|
|
|
.then(resolve)
|
|
|
|
|
.catch(reject);
|
|
|
|
|
} else if (type === 'type' || productMode.value === 'type') {
|
|
|
|
|
await toggleStatusType(id, status as Status)
|
|
|
|
|
.then(resolve)
|
|
|
|
|
.catch(reject);
|
|
|
|
|
} else if (type === 'service' || productMode.value === 'service') {
|
|
|
|
|
await toggleStatusService(id, status as Status)
|
|
|
|
|
.then(resolve)
|
|
|
|
|
.catch(reject);
|
|
|
|
|
} else if (type === 'product' || productMode.value === 'product') {
|
|
|
|
|
await toggleStatusProduct(id, status as Status)
|
|
|
|
|
.then(resolve)
|
|
|
|
|
.catch(reject);
|
|
|
|
|
}
|
|
|
|
|
},
|
|
|
|
|
cancel: () => {},
|
|
|
|
|
});
|
|
|
|
|
});
|
|
|
|
|
}
|
|
|
|
|
|
2024-06-18 16:14:50 +07:00
|
|
|
async function deleteServiceById(serviceId?: string) {
|
|
|
|
|
dialog({
|
|
|
|
|
color: 'negative',
|
|
|
|
|
icon: 'mdi-alert',
|
|
|
|
|
title: t('deleteConfirmTitle'),
|
|
|
|
|
actionText: t('ok'),
|
|
|
|
|
persistent: true,
|
|
|
|
|
message: t('deleteConfirmMessage'),
|
|
|
|
|
action: async () => {
|
2024-06-25 14:31:08 +07:00
|
|
|
const res = await deleteService(serviceId ?? currentIdService.value);
|
2024-06-18 16:14:50 +07:00
|
|
|
|
2024-06-28 15:51:13 +07:00
|
|
|
if (productAndServiceTab.value === 'service') {
|
2024-07-09 11:19:10 +07:00
|
|
|
await fetchListOfService();
|
2024-06-28 15:51:13 +07:00
|
|
|
}
|
2024-06-21 14:50:43 +07:00
|
|
|
|
|
|
|
|
dialogServiceEdit.value = false;
|
2024-06-25 14:31:08 +07:00
|
|
|
|
|
|
|
|
if (res) {
|
|
|
|
|
totalService.value = totalService.value - 1;
|
|
|
|
|
}
|
2024-06-26 17:21:26 +07:00
|
|
|
flowStore.rotate();
|
2024-06-24 09:44:38 +07:00
|
|
|
calculateStats();
|
2024-06-18 16:14:50 +07:00
|
|
|
},
|
|
|
|
|
cancel: () => {},
|
|
|
|
|
});
|
|
|
|
|
}
|
|
|
|
|
|
2024-06-19 13:51:45 +07:00
|
|
|
async function deleteTypeOfProduct(id?: string) {
|
|
|
|
|
dialog({
|
|
|
|
|
color: 'negative',
|
|
|
|
|
icon: 'mdi-alert',
|
|
|
|
|
title: t('deleteConfirmTitle'),
|
|
|
|
|
actionText: t('ok'),
|
|
|
|
|
persistent: true,
|
|
|
|
|
message: t('deleteConfirmMessage'),
|
|
|
|
|
action: async () => {
|
2024-06-25 14:31:08 +07:00
|
|
|
const res = await deleteProduct(id ?? currentIdProduct.value);
|
2024-06-28 15:51:13 +07:00
|
|
|
|
|
|
|
|
if (productAndServiceTab.value === 'product') {
|
2024-07-01 10:33:39 +07:00
|
|
|
await fetchListOfProduct();
|
2024-06-28 15:51:13 +07:00
|
|
|
}
|
2024-06-19 13:51:45 +07:00
|
|
|
|
|
|
|
|
dialogProductEdit.value = false;
|
|
|
|
|
|
2024-06-25 14:31:08 +07:00
|
|
|
if (res) {
|
|
|
|
|
totalProduct.value = totalProduct.value - 1;
|
|
|
|
|
}
|
2024-06-26 17:21:26 +07:00
|
|
|
flowStore.rotate();
|
2024-06-24 09:44:38 +07:00
|
|
|
calculateStats();
|
2024-06-19 13:51:45 +07:00
|
|
|
},
|
|
|
|
|
cancel: () => {},
|
|
|
|
|
});
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// type or group
|
2024-06-17 17:59:09 +07:00
|
|
|
async function deleteProductById(productId?: string) {
|
2024-06-11 12:01:35 +07:00
|
|
|
dialog({
|
|
|
|
|
color: 'negative',
|
|
|
|
|
icon: 'mdi-alert',
|
|
|
|
|
title: t('deleteConfirmTitle'),
|
|
|
|
|
actionText: t('ok'),
|
|
|
|
|
persistent: true,
|
|
|
|
|
message: t('deleteConfirmMessage'),
|
|
|
|
|
action: async () => {
|
2024-07-17 07:32:56 +00:00
|
|
|
if (editByTree.value !== undefined) {
|
2024-07-15 14:12:53 +07:00
|
|
|
if (editByTree.value === 'type') {
|
|
|
|
|
// Product Type
|
|
|
|
|
await deleteProductServiceType(productId ?? currentIdType.value);
|
|
|
|
|
await fetchListType();
|
2024-06-12 15:37:17 +07:00
|
|
|
}
|
2024-07-15 14:12:53 +07:00
|
|
|
if (editByTree.value === 'group') {
|
|
|
|
|
// Product Group
|
2024-07-23 10:24:22 +07:00
|
|
|
const res = await deleteProductService(
|
|
|
|
|
productId ?? currentIdGrop.value,
|
|
|
|
|
);
|
2024-07-15 14:12:53 +07:00
|
|
|
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
|
2024-07-23 10:24:22 +07:00
|
|
|
const res = await deleteProductService(
|
|
|
|
|
productId ?? currentIdGrop.value,
|
|
|
|
|
);
|
2024-07-15 14:12:53 +07:00
|
|
|
if (res) {
|
|
|
|
|
}
|
|
|
|
|
await fetchListGroups();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
flowStore.rotate();
|
|
|
|
|
calculateStats();
|
|
|
|
|
drawerInfo.value = false;
|
2024-06-11 15:46:51 +07:00
|
|
|
}
|
2024-06-11 12:01:35 +07:00
|
|
|
},
|
|
|
|
|
cancel: () => {},
|
|
|
|
|
});
|
|
|
|
|
}
|
2024-06-11 15:04:01 +07:00
|
|
|
|
2024-06-11 16:29:00 +07:00
|
|
|
function undoProductGroup() {
|
2024-06-17 17:59:09 +07:00
|
|
|
formDataGroup.value = {
|
2024-06-11 16:29:00 +07:00
|
|
|
remark: previousValue.value.remark,
|
|
|
|
|
detail: previousValue.value.detail,
|
|
|
|
|
name: previousValue.value.name,
|
|
|
|
|
code: previousValue.value.code,
|
|
|
|
|
};
|
|
|
|
|
isEdit.value = false;
|
2024-06-26 17:21:26 +07:00
|
|
|
flowStore.rotate();
|
2024-06-11 16:29:00 +07:00
|
|
|
}
|
|
|
|
|
|
2024-06-17 17:59:09 +07:00
|
|
|
function assignFormDataGroup(data: ProductGroup) {
|
2024-06-11 16:29:00 +07:00
|
|
|
previousValue.value = data;
|
2024-08-07 11:13:42 +00:00
|
|
|
currentStatusGroupType.value = data.status;
|
|
|
|
|
currentIdGroupType.value = data.id;
|
2024-06-11 16:29:00 +07:00
|
|
|
|
2024-06-17 17:59:09 +07:00
|
|
|
formDataGroup.value = {
|
|
|
|
|
remark: data.remark,
|
|
|
|
|
detail: data.detail,
|
|
|
|
|
name: data.name,
|
|
|
|
|
code: data.code,
|
|
|
|
|
};
|
|
|
|
|
}
|
|
|
|
|
|
2024-06-24 16:53:33 +07:00
|
|
|
const prevService = ref<ServiceCreate>({
|
|
|
|
|
work: [],
|
|
|
|
|
attributes: {
|
|
|
|
|
additional: [],
|
|
|
|
|
},
|
|
|
|
|
detail: '',
|
|
|
|
|
name: '',
|
|
|
|
|
code: '',
|
2024-06-25 14:31:08 +07:00
|
|
|
productTypeId: '',
|
2024-07-04 11:38:10 +07:00
|
|
|
registeredBranchId: '',
|
2024-06-24 16:53:33 +07:00
|
|
|
});
|
|
|
|
|
|
2024-06-26 17:44:13 +07:00
|
|
|
const currentService = ref<ServiceById>();
|
|
|
|
|
|
2024-06-18 15:41:30 +07:00
|
|
|
async function assignFormDataProductService(id: string) {
|
|
|
|
|
const res = await fetchListServiceById(id);
|
|
|
|
|
|
|
|
|
|
if (res) {
|
2024-06-24 16:53:33 +07:00
|
|
|
statusToggle.value = res.status === 'INACTIVE' ? false : true;
|
2024-07-01 11:04:24 +00:00
|
|
|
profileUrl.value = res.imageUrl;
|
|
|
|
|
profileSubmit.value = true;
|
|
|
|
|
|
2024-06-26 17:44:13 +07:00
|
|
|
currentService.value = JSON.parse(JSON.stringify(res));
|
2024-06-24 16:53:33 +07:00
|
|
|
|
|
|
|
|
prevService.value = {
|
2024-06-18 15:41:30 +07:00
|
|
|
code: res.code,
|
|
|
|
|
name: res.name,
|
|
|
|
|
detail: res.detail,
|
|
|
|
|
attributes: res.attributes,
|
|
|
|
|
work: [],
|
2024-06-24 16:25:33 +07:00
|
|
|
status: res.status,
|
2024-06-25 14:31:08 +07:00
|
|
|
productTypeId: res.productTypeId,
|
2024-07-04 11:38:10 +07:00
|
|
|
registeredBranchId: res.registeredBranchId,
|
2024-06-18 15:41:30 +07:00
|
|
|
};
|
|
|
|
|
|
2024-06-24 16:53:33 +07:00
|
|
|
formDataProductService.value = { ...prevService.value };
|
|
|
|
|
|
2024-06-18 15:41:30 +07:00
|
|
|
res.work.forEach((item) => {
|
2024-06-24 16:53:33 +07:00
|
|
|
prevService.value.work.push({
|
2024-06-18 15:41:30 +07:00
|
|
|
name: item.name,
|
|
|
|
|
attributes: item.attributes,
|
|
|
|
|
productId: item.productOnWork.map(
|
|
|
|
|
(productOnWorkItem) => productOnWorkItem.product.id,
|
|
|
|
|
),
|
|
|
|
|
});
|
|
|
|
|
});
|
2024-06-21 14:50:43 +07:00
|
|
|
|
2024-06-24 16:53:33 +07:00
|
|
|
formDataProductService.value.work = prevService.value.work;
|
|
|
|
|
|
2024-06-21 14:50:43 +07:00
|
|
|
workItems.value = res.work.map((item) => {
|
|
|
|
|
return {
|
|
|
|
|
id: item.id,
|
|
|
|
|
name: item.name,
|
|
|
|
|
attributes: item.attributes,
|
|
|
|
|
product: item.productOnWork.map((productOnWorkItem) => {
|
|
|
|
|
return {
|
|
|
|
|
...productOnWorkItem.product,
|
2024-06-26 17:44:13 +07:00
|
|
|
nameEn: productOnWorkItem.product.name,
|
2024-06-21 14:50:43 +07:00
|
|
|
};
|
|
|
|
|
}),
|
|
|
|
|
};
|
|
|
|
|
});
|
2024-06-18 15:41:30 +07:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2024-06-25 14:58:56 +07:00
|
|
|
const prevProduct = ref<ProductCreate>({
|
|
|
|
|
productTypeId: '',
|
|
|
|
|
remark: '',
|
|
|
|
|
serviceCharge: 0,
|
|
|
|
|
agentPrice: 0,
|
|
|
|
|
price: 0,
|
|
|
|
|
process: 0,
|
|
|
|
|
detail: '',
|
|
|
|
|
name: '',
|
|
|
|
|
code: '',
|
|
|
|
|
image: undefined,
|
2024-07-04 11:38:10 +07:00
|
|
|
registeredBranchId: '',
|
2024-06-25 14:58:56 +07:00
|
|
|
});
|
|
|
|
|
|
2024-06-17 17:59:09 +07:00
|
|
|
function assignFormDataProduct(data: ProductList) {
|
2024-06-20 13:59:25 +07:00
|
|
|
statusToggle.value = data.status === 'INACTIVE' ? false : true;
|
2024-07-03 10:08:51 +00:00
|
|
|
profileUrl.value = `${baseUrl.value}/product/${data?.id}/image`;
|
|
|
|
|
profileSubmit.value = true;
|
2024-06-20 13:59:25 +07:00
|
|
|
|
2024-06-25 14:58:56 +07:00
|
|
|
prevProduct.value = {
|
2024-06-17 17:59:09 +07:00
|
|
|
productTypeId: data.productTypeId,
|
2024-06-11 16:29:00 +07:00
|
|
|
remark: data.remark,
|
2024-06-17 17:59:09 +07:00
|
|
|
serviceCharge: data.serviceCharge,
|
|
|
|
|
agentPrice: data.agentPrice,
|
|
|
|
|
price: data.price,
|
|
|
|
|
process: data.process,
|
2024-06-20 13:21:50 +07:00
|
|
|
detail: data.detail === '' ? '-' : data.detail,
|
2024-06-11 16:29:00 +07:00
|
|
|
name: data.name,
|
|
|
|
|
code: data.code,
|
2024-06-18 14:00:20 +07:00
|
|
|
image: undefined,
|
2024-07-04 11:38:10 +07:00
|
|
|
registeredBranchId: data.registeredBranchId,
|
2024-06-11 16:29:00 +07:00
|
|
|
};
|
2024-06-25 14:58:56 +07:00
|
|
|
|
|
|
|
|
formDataProduct.value = { ...prevProduct.value };
|
2024-06-11 16:29:00 +07:00
|
|
|
}
|
|
|
|
|
|
2024-06-17 17:59:09 +07:00
|
|
|
function clearFormGroup() {
|
|
|
|
|
formDataGroup.value = {
|
2024-06-11 15:04:01 +07:00
|
|
|
remark: '',
|
|
|
|
|
detail: '',
|
|
|
|
|
name: '',
|
|
|
|
|
code: '',
|
|
|
|
|
};
|
2024-08-07 11:13:42 +00:00
|
|
|
currentStatusGroupType.value = 'CREATED';
|
2024-06-11 15:04:01 +07:00
|
|
|
dialogInputForm.value = false;
|
|
|
|
|
}
|
|
|
|
|
|
2024-06-17 17:59:09 +07:00
|
|
|
function clearFormProduct() {
|
|
|
|
|
formDataProduct.value = {
|
|
|
|
|
productTypeId: '',
|
|
|
|
|
remark: '',
|
|
|
|
|
serviceCharge: 0,
|
|
|
|
|
agentPrice: 0,
|
|
|
|
|
price: 0,
|
|
|
|
|
process: 0,
|
|
|
|
|
detail: '',
|
|
|
|
|
name: '',
|
|
|
|
|
code: '',
|
2024-06-18 14:00:20 +07:00
|
|
|
image: undefined,
|
2024-07-04 11:38:10 +07:00
|
|
|
registeredBranchId: '',
|
2024-06-17 17:59:09 +07:00
|
|
|
};
|
2024-07-01 11:04:24 +00:00
|
|
|
imageProduct.value = undefined;
|
2024-06-17 17:59:09 +07:00
|
|
|
dialogProduct.value = false;
|
2024-06-19 13:51:45 +07:00
|
|
|
dialogProductEdit.value = false;
|
2024-07-01 08:52:56 +00:00
|
|
|
profileUrl.value = '';
|
|
|
|
|
profileSubmit.value = false;
|
2024-06-17 17:59:09 +07:00
|
|
|
}
|
|
|
|
|
|
2024-06-18 16:08:50 +07:00
|
|
|
function clearFormService() {
|
|
|
|
|
formDataProductService.value = {
|
|
|
|
|
code: '',
|
|
|
|
|
name: '',
|
|
|
|
|
detail: '',
|
|
|
|
|
attributes: {
|
|
|
|
|
additional: [],
|
|
|
|
|
},
|
|
|
|
|
work: [],
|
2024-06-24 16:25:33 +07:00
|
|
|
status: undefined,
|
2024-06-25 14:31:08 +07:00
|
|
|
productTypeId: '',
|
2024-07-04 11:38:10 +07:00
|
|
|
registeredBranchId: '',
|
2024-06-18 16:08:50 +07:00
|
|
|
};
|
2024-06-21 11:40:18 +07:00
|
|
|
|
2024-06-21 14:50:43 +07:00
|
|
|
workItems.value = [];
|
2024-06-21 11:40:18 +07:00
|
|
|
selectProduct.value = [];
|
2024-06-18 16:08:50 +07:00
|
|
|
dialogService.value = false;
|
2024-06-21 14:50:43 +07:00
|
|
|
dialogServiceEdit.value = false;
|
2024-07-01 08:52:56 +00:00
|
|
|
profileUrl.value = '';
|
|
|
|
|
profileSubmit.value = false;
|
2024-07-01 11:04:24 +00:00
|
|
|
imageProduct.value = undefined;
|
2024-06-18 16:08:50 +07:00
|
|
|
}
|
|
|
|
|
|
2024-06-21 11:40:18 +07:00
|
|
|
function assignFormDataProductServiceCreate() {
|
2024-06-21 14:50:43 +07:00
|
|
|
formDataProductService.value.work = [];
|
|
|
|
|
|
2024-06-21 11:40:18 +07:00
|
|
|
workItems.value.forEach((item) => {
|
|
|
|
|
formDataProductService.value.work.push({
|
|
|
|
|
name: item.name,
|
|
|
|
|
attributes: item.attributes,
|
|
|
|
|
productId: item.product.map((productItem) => productItem.id),
|
|
|
|
|
});
|
|
|
|
|
});
|
|
|
|
|
}
|
|
|
|
|
|
2024-06-18 16:08:50 +07:00
|
|
|
async function submitService() {
|
2024-06-21 11:40:18 +07:00
|
|
|
assignFormDataProductServiceCreate();
|
2024-06-21 14:50:43 +07:00
|
|
|
formDataProductService.value.image = imageProduct.value;
|
2024-06-25 14:31:08 +07:00
|
|
|
formDataProductService.value.productTypeId = currentIdType.value;
|
2024-06-21 14:50:43 +07:00
|
|
|
|
|
|
|
|
if (dialogService.value) {
|
2024-07-03 10:08:51 +00:00
|
|
|
formDataProductService.value.productTypeId = currentIdType.value;
|
2024-07-04 13:28:28 +07:00
|
|
|
|
|
|
|
|
if (formDataProductService.value.registeredBranchId === '') {
|
|
|
|
|
formDataProductService.value.registeredBranchId = null;
|
|
|
|
|
}
|
|
|
|
|
|
2024-07-10 11:54:22 +07:00
|
|
|
const res = await createService(formDataProductService.value);
|
|
|
|
|
if (res) {
|
|
|
|
|
stat.value[2].count = stat.value[2].count + 1;
|
|
|
|
|
}
|
2024-06-26 14:21:14 +07:00
|
|
|
totalService.value = totalService.value + 1;
|
2024-07-10 11:36:15 +07:00
|
|
|
productAndServiceTab.value = 'service';
|
2024-06-21 14:50:43 +07:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (dialogServiceEdit.value) {
|
2024-06-26 14:21:14 +07:00
|
|
|
await editService(currentIdService.value, {
|
2024-06-21 14:50:43 +07:00
|
|
|
...formDataProductService.value,
|
2024-06-24 16:53:33 +07:00
|
|
|
status: statusToggle.value
|
|
|
|
|
? formDataProductService.value.status
|
|
|
|
|
: 'INACTIVE',
|
2024-06-21 14:50:43 +07:00
|
|
|
});
|
2024-06-18 16:08:50 +07:00
|
|
|
}
|
2024-06-26 14:21:14 +07:00
|
|
|
|
|
|
|
|
if (productAndServiceTab.value === 'service') {
|
|
|
|
|
await fetchListOfService();
|
|
|
|
|
}
|
2024-07-10 11:54:22 +07:00
|
|
|
|
2024-06-26 17:21:26 +07:00
|
|
|
flowStore.rotate();
|
2024-06-18 16:08:50 +07:00
|
|
|
clearFormService();
|
|
|
|
|
}
|
|
|
|
|
|
2024-06-17 17:59:09 +07:00
|
|
|
async function submitProduct() {
|
|
|
|
|
formDataProduct.value.productTypeId = currentIdType.value;
|
2024-06-18 14:00:20 +07:00
|
|
|
if (profileSubmit.value) {
|
|
|
|
|
formDataProduct.value.image = imageProduct.value;
|
|
|
|
|
}
|
|
|
|
|
|
2024-06-19 13:51:45 +07:00
|
|
|
if (dialogProduct.value) {
|
|
|
|
|
const res = await createProduct(formDataProduct.value);
|
2024-06-18 16:26:49 +07:00
|
|
|
|
2024-06-19 13:51:45 +07:00
|
|
|
if (res) {
|
|
|
|
|
stat.value[3].count = stat.value[3].count + 1;
|
|
|
|
|
}
|
2024-07-10 11:36:15 +07:00
|
|
|
|
|
|
|
|
productAndServiceTab.value = 'product';
|
2024-06-19 13:51:45 +07:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (dialogProductEdit.value) {
|
2024-06-20 13:59:25 +07:00
|
|
|
await editProduct(currentIdProduct.value, {
|
|
|
|
|
...formDataProduct.value,
|
|
|
|
|
status: statusToggle.value ? 'ACTIVE' : 'INACTIVE',
|
|
|
|
|
});
|
2024-06-18 16:26:49 +07:00
|
|
|
}
|
2024-06-25 14:31:08 +07:00
|
|
|
totalProduct.value = totalProduct.value + 1;
|
2024-06-18 16:32:17 +07:00
|
|
|
clearFormProduct();
|
2024-06-26 14:21:14 +07:00
|
|
|
|
|
|
|
|
if (productAndServiceTab.value === 'product') {
|
2024-07-01 10:33:39 +07:00
|
|
|
await fetchListOfProduct();
|
2024-06-26 14:21:14 +07:00
|
|
|
}
|
2024-06-26 17:21:26 +07:00
|
|
|
|
|
|
|
|
flowStore.rotate();
|
2024-06-17 17:59:09 +07:00
|
|
|
}
|
|
|
|
|
|
2024-06-11 15:04:01 +07:00
|
|
|
async function submitGroup() {
|
2024-06-11 16:29:00 +07:00
|
|
|
if (drawerInfo.value) {
|
2024-07-23 10:24:22 +07:00
|
|
|
await editProductService(currentIdGrop.value, formDataGroup.value);
|
2024-06-11 16:29:00 +07:00
|
|
|
} else {
|
2024-06-17 17:59:09 +07:00
|
|
|
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 16:29:00 +07:00
|
|
|
}
|
2024-06-11 15:04:01 +07:00
|
|
|
|
2024-06-14 09:31:45 +07:00
|
|
|
drawerInfo.value = false;
|
2024-06-11 15:46:51 +07:00
|
|
|
await fetchListGroups();
|
2024-06-17 17:59:09 +07:00
|
|
|
clearFormGroup();
|
2024-06-26 17:21:26 +07:00
|
|
|
flowStore.rotate();
|
2024-06-11 15:04:01 +07:00
|
|
|
}
|
|
|
|
|
|
2024-06-21 11:06:35 +00:00
|
|
|
function confirmDeleteWork(id: string) {
|
|
|
|
|
dialog({
|
|
|
|
|
color: 'negative',
|
|
|
|
|
icon: 'mdi-alert',
|
|
|
|
|
title: t('deleteConfirmTitle'),
|
|
|
|
|
actionText: t('delete'),
|
|
|
|
|
message: t('deleteConfirmMessage'),
|
|
|
|
|
action: async () => {
|
|
|
|
|
deleteWork(id);
|
2024-06-26 17:21:26 +07:00
|
|
|
flowStore.rotate();
|
2024-06-21 11:06:35 +00:00
|
|
|
},
|
|
|
|
|
cancel: () => {},
|
|
|
|
|
});
|
|
|
|
|
}
|
|
|
|
|
|
2024-06-24 09:01:44 +00:00
|
|
|
function triggerConfirmCloseWork() {
|
|
|
|
|
const isWorkNameEdit =
|
|
|
|
|
workNameRef.value && workNameRef.value.isWorkNameEdit
|
|
|
|
|
? workNameRef.value.isWorkNameEdit()
|
|
|
|
|
: false;
|
|
|
|
|
if (isWorkNameEdit) {
|
|
|
|
|
dialogWarningClose(t, {
|
|
|
|
|
action: () => {
|
|
|
|
|
manageWorkNameDialog.value = false;
|
|
|
|
|
},
|
|
|
|
|
});
|
|
|
|
|
} else {
|
|
|
|
|
manageWorkNameDialog.value = false;
|
|
|
|
|
}
|
2024-06-21 11:06:35 +00:00
|
|
|
}
|
|
|
|
|
|
2024-06-20 18:02:02 +07:00
|
|
|
const tempValueProperties = ref<Attributes>({
|
|
|
|
|
additional: [],
|
|
|
|
|
});
|
|
|
|
|
const currentPropertiesMode = ref<'service' | 'work'>('service');
|
|
|
|
|
|
2024-06-20 09:10:34 +00:00
|
|
|
function openPropertiesDialog(type: 'service' | 'work') {
|
|
|
|
|
if (type === 'service') {
|
2024-06-24 07:21:36 +00:00
|
|
|
propertiesOption.value = optionStore.globalOption.servicePropertiesField;
|
2024-06-20 09:10:34 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (type === 'work') {
|
2024-06-24 07:21:36 +00:00
|
|
|
propertiesOption.value = optionStore.globalOption.workPropertiesField;
|
2024-06-20 09:10:34 +00:00
|
|
|
}
|
2024-06-20 18:02:02 +07:00
|
|
|
|
|
|
|
|
currentPropertiesMode.value = type;
|
2024-06-20 09:10:34 +00:00
|
|
|
propertiesDialog.value = true;
|
|
|
|
|
}
|
|
|
|
|
|
2024-06-24 09:44:38 +07:00
|
|
|
async function calculateStats() {
|
2024-06-12 15:37:17 +07:00
|
|
|
const resStatsGroup = await fetchStatsProductGroup();
|
2024-06-17 17:59:09 +07:00
|
|
|
const resStatsType = await fetchStatsProductType();
|
2024-06-24 09:44:38 +07:00
|
|
|
const resStatsService = await fetchStatsService();
|
2024-06-18 16:26:49 +07:00
|
|
|
const resStatsProduct = await fetchStatsProduct();
|
|
|
|
|
|
2024-06-12 15:37:17 +07:00
|
|
|
stat.value[0].count = resStatsGroup ?? 0;
|
2024-06-17 17:59:09 +07:00
|
|
|
stat.value[1].count = resStatsType ?? 0;
|
2024-06-24 09:44:38 +07:00
|
|
|
stat.value[2].count = resStatsService ?? 0;
|
2024-06-18 16:26:49 +07:00
|
|
|
stat.value[3].count = resStatsProduct ?? 0;
|
2024-06-24 09:44:38 +07:00
|
|
|
}
|
2024-06-12 15:37:17 +07:00
|
|
|
|
2024-06-25 14:31:08 +07:00
|
|
|
async function fetchStatus() {
|
|
|
|
|
if (productAndServiceTab.value === 'product') {
|
2024-07-01 10:33:39 +07:00
|
|
|
await fetchListOfProduct();
|
2024-06-26 17:21:26 +07:00
|
|
|
flowStore.rotate();
|
2024-06-25 14:31:08 +07:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (productAndServiceTab.value === 'service') {
|
|
|
|
|
await fetchListOfService();
|
2024-06-26 17:21:26 +07:00
|
|
|
flowStore.rotate();
|
2024-06-25 14:31:08 +07:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2024-07-01 14:20:24 +07:00
|
|
|
async function alternativeFetch() {
|
|
|
|
|
if (productAndServiceTab.value === 'product') {
|
|
|
|
|
await fetchListOfProduct();
|
|
|
|
|
|
|
|
|
|
flowStore.rotate();
|
|
|
|
|
}
|
|
|
|
|
if (productAndServiceTab.value === 'service') {
|
|
|
|
|
await fetchListOfService();
|
|
|
|
|
flowStore.rotate();
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2024-06-26 17:44:13 +07:00
|
|
|
function cloneData() {
|
|
|
|
|
if (!currentService.value) return;
|
|
|
|
|
formDataProductService.value = {
|
|
|
|
|
...prevService.value,
|
|
|
|
|
attributes: JSON.parse(JSON.stringify(currentService.value.attributes)),
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
workItems.value = currentService.value.work.map((item) => {
|
|
|
|
|
return {
|
|
|
|
|
id: item.id,
|
|
|
|
|
name: item.name,
|
|
|
|
|
attributes: JSON.parse(JSON.stringify(item.attributes)),
|
|
|
|
|
product: item.productOnWork.map((productOnWorkItem) => {
|
|
|
|
|
return {
|
|
|
|
|
...productOnWorkItem.product,
|
|
|
|
|
nameEn: productOnWorkItem.product.name,
|
|
|
|
|
};
|
|
|
|
|
}),
|
|
|
|
|
};
|
|
|
|
|
});
|
|
|
|
|
}
|
|
|
|
|
|
2024-07-23 10:24:22 +07:00
|
|
|
async function enterGroup(id: string, name: string) {
|
|
|
|
|
expandedTree.value = [];
|
|
|
|
|
expandedTree.value.push(id);
|
|
|
|
|
pathGroupName.value = name;
|
|
|
|
|
currentIdGrop.value = id;
|
|
|
|
|
await fetchListType();
|
|
|
|
|
productMode.value = 'type';
|
|
|
|
|
flowStore.rotate();
|
|
|
|
|
}
|
|
|
|
|
|
2024-07-23 13:47:42 +07:00
|
|
|
async function enterType(id: string, name: string) {
|
2024-07-23 07:25:11 +00:00
|
|
|
if (
|
|
|
|
|
expandedTree.value.length > 1 &&
|
|
|
|
|
expandedTree.value[expandedTree.value.length - 1] !== id
|
|
|
|
|
) {
|
|
|
|
|
expandedTree.value.pop();
|
|
|
|
|
expandedTree.value.push(id);
|
|
|
|
|
} else {
|
|
|
|
|
expandedTree.value.push(id);
|
|
|
|
|
}
|
2024-07-23 13:47:42 +07:00
|
|
|
pathTypeName.value = name;
|
|
|
|
|
currentIdType.value = id;
|
|
|
|
|
productMode.value = 'service';
|
|
|
|
|
productAndServiceTab.value = 'service';
|
|
|
|
|
|
|
|
|
|
await fetchListOfProduct();
|
|
|
|
|
await fetchListOfService();
|
|
|
|
|
|
|
|
|
|
flowStore.rotate();
|
|
|
|
|
}
|
|
|
|
|
|
2024-07-19 10:35:18 +00:00
|
|
|
function handleHold(node: ProductGroup) {
|
|
|
|
|
if ($q.screen.gt.xs) return;
|
|
|
|
|
return function (props: unknown) {
|
|
|
|
|
holdDialog.value = true;
|
|
|
|
|
currentNode.value = node;
|
|
|
|
|
};
|
|
|
|
|
}
|
|
|
|
|
|
2024-06-24 09:44:38 +07:00
|
|
|
onMounted(async () => {
|
2024-07-02 09:58:59 +00:00
|
|
|
utilsStore.currentTitle.title = 'mainProductTitle';
|
2024-07-09 17:17:08 +07:00
|
|
|
utilsStore.currentTitle.path = [
|
|
|
|
|
{
|
|
|
|
|
text: 'manage',
|
2024-08-06 13:26:38 +07:00
|
|
|
i18n: true,
|
2024-07-09 17:17:08 +07:00
|
|
|
handler: () => {
|
2024-07-23 10:24:22 +07:00
|
|
|
expandedTree.value = [];
|
|
|
|
|
currentIdGrop.value = '';
|
2024-07-09 17:17:08 +07:00
|
|
|
productMode.value = 'group';
|
|
|
|
|
},
|
|
|
|
|
},
|
|
|
|
|
];
|
2024-07-18 09:10:51 +00:00
|
|
|
modeView.value = $q.screen.lt.md ? true : false;
|
2024-07-02 09:58:59 +00:00
|
|
|
|
2024-06-24 09:44:38 +07:00
|
|
|
calculateStats();
|
2024-06-11 15:46:51 +07:00
|
|
|
await fetchListGroups();
|
2024-07-15 14:12:53 +07:00
|
|
|
|
2024-06-26 17:21:26 +07:00
|
|
|
flowStore.rotate();
|
2024-06-11 15:04:01 +07:00
|
|
|
});
|
2024-06-13 11:31:21 +07:00
|
|
|
|
2024-06-24 13:07:00 +07:00
|
|
|
watch(productMode, () => {
|
|
|
|
|
inputSearch.value = '';
|
|
|
|
|
currentStatus.value = 'All';
|
2024-07-09 17:17:08 +07:00
|
|
|
|
|
|
|
|
const tmp: typeof utilsStore.currentTitle.path = [
|
|
|
|
|
{
|
|
|
|
|
text: 'manage',
|
|
|
|
|
handler: () => {
|
|
|
|
|
productMode.value = 'group';
|
2024-07-23 10:24:22 +07:00
|
|
|
expandedTree.value = [];
|
|
|
|
|
currentIdGrop.value = '';
|
2024-07-12 13:35:15 +07:00
|
|
|
filterStat.value = [];
|
2024-07-09 17:17:08 +07:00
|
|
|
},
|
|
|
|
|
},
|
|
|
|
|
];
|
2024-07-08 16:29:37 +07:00
|
|
|
|
|
|
|
|
if (productMode.value === 'type' || productMode.value === 'service') {
|
|
|
|
|
tmp.push({
|
|
|
|
|
text: 'productGroup',
|
|
|
|
|
argsi18n: { name: pathGroupName.value },
|
|
|
|
|
handler: () => {
|
|
|
|
|
productMode.value = 'type';
|
2024-07-11 11:44:17 +07:00
|
|
|
filterStat.value = filterStat.value.filter((item) => {
|
|
|
|
|
return item !== 'type';
|
2024-07-12 13:35:15 +07:00
|
|
|
});
|
2024-07-08 16:29:37 +07:00
|
|
|
},
|
|
|
|
|
});
|
|
|
|
|
}
|
|
|
|
|
if (productMode.value === 'service') {
|
|
|
|
|
tmp.push({ text: 'productType', argsi18n: { name: pathTypeName.value } });
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
utilsStore.currentTitle.path = tmp;
|
2024-06-24 13:07:00 +07:00
|
|
|
});
|
2024-06-14 09:31:45 +07:00
|
|
|
|
2024-06-14 13:37:11 +07:00
|
|
|
watch(currentStatus, async () => {
|
2024-06-17 17:59:09 +07:00
|
|
|
if (productMode.value === 'group') {
|
|
|
|
|
await fetchListGroups();
|
|
|
|
|
} else {
|
|
|
|
|
await fetchListType();
|
|
|
|
|
}
|
2024-06-26 17:21:26 +07:00
|
|
|
flowStore.rotate();
|
2024-06-14 13:37:11 +07:00
|
|
|
});
|
2024-06-26 13:11:03 +07:00
|
|
|
|
2024-07-01 09:53:51 +07:00
|
|
|
watch(inputSearch, async () => {
|
|
|
|
|
if (productMode.value === 'group') {
|
|
|
|
|
await fetchListGroups();
|
2024-07-01 10:33:39 +07:00
|
|
|
flowStore.rotate();
|
2024-07-01 09:53:51 +07:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (productMode.value === 'type') {
|
|
|
|
|
await fetchListType();
|
2024-07-01 10:33:39 +07:00
|
|
|
flowStore.rotate();
|
|
|
|
|
}
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
watch(inputSearchProductAndService, async () => {
|
2024-07-01 14:20:24 +07:00
|
|
|
await alternativeFetch();
|
2024-07-01 09:53:51 +07:00
|
|
|
});
|
2024-07-18 09:10:51 +00:00
|
|
|
|
|
|
|
|
watch(
|
|
|
|
|
() => $q.screen.lt.md,
|
|
|
|
|
(v) => {
|
|
|
|
|
if (v) modeView.value = true;
|
|
|
|
|
},
|
|
|
|
|
);
|
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="
|
|
|
|
|
() => {
|
2024-06-17 17:59:09 +07:00
|
|
|
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="
|
|
|
|
|
() => {
|
2024-06-17 17:59:09 +07:00
|
|
|
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'"
|
2024-06-19 13:51:45 +07:00
|
|
|
:label="$t('buttonAddProduct')"
|
2024-06-14 14:45:17 +07:00
|
|
|
external-label
|
|
|
|
|
label-position="left"
|
|
|
|
|
style="color: white; background-color: hsla(var(--green-11-hsl))"
|
|
|
|
|
padding="xs"
|
|
|
|
|
icon="mdi-folder-multiple-plus"
|
|
|
|
|
@click="
|
2024-07-30 05:29:36 +00:00
|
|
|
async () => {
|
2024-06-20 13:21:50 +07:00
|
|
|
clearFormProduct();
|
2024-07-30 05:29:36 +00:00
|
|
|
await fetchListOfOptionBranch();
|
2024-06-14 14:45:17 +07:00
|
|
|
dialogProduct = true;
|
|
|
|
|
}
|
|
|
|
|
"
|
|
|
|
|
></q-fab-action>
|
|
|
|
|
<q-fab-action
|
|
|
|
|
v-if="productMode === 'service'"
|
2024-06-18 02:01:02 +00:00
|
|
|
:label="$t('addService')"
|
2024-06-14 14:45:17 +07:00
|
|
|
external-label
|
|
|
|
|
label-position="left"
|
2024-06-26 14:21:14 +07:00
|
|
|
style="color: white; background-color: hsla(var(--orange-6-hsl))"
|
2024-06-14 14:45:17 +07:00
|
|
|
padding="xs"
|
|
|
|
|
icon="mdi-folder-multiple-plus"
|
|
|
|
|
@click="
|
2024-07-30 05:29:36 +00:00
|
|
|
async () => {
|
2024-06-17 17:59:09 +07:00
|
|
|
clearFormGroup();
|
2024-07-01 08:52:56 +00:00
|
|
|
clearFormService();
|
2024-07-30 05:29:36 +00:00
|
|
|
await fetchListOfOptionBranch();
|
2024-06-18 02:01:02 +00:00
|
|
|
currentServiceTab = 'serviceInformation';
|
|
|
|
|
dialogService = true;
|
2024-06-14 14:45:17 +07:00
|
|
|
}
|
|
|
|
|
"
|
|
|
|
|
></q-fab-action>
|
2024-06-14 09:31:45 +07:00
|
|
|
</ButtonAddComponent>
|
|
|
|
|
|
2024-07-17 07:32:56 +00:00
|
|
|
<div class="full-height column no-wrap">
|
2024-07-12 15:26:13 +07:00
|
|
|
<div class="text-body-2 q-mb-xs flex items-center">
|
|
|
|
|
{{ $t('dataSum') }}
|
|
|
|
|
<q-btn
|
|
|
|
|
class="q-ml-xs"
|
|
|
|
|
icon="mdi-pin"
|
|
|
|
|
color="primary"
|
|
|
|
|
size="sm"
|
|
|
|
|
flat
|
|
|
|
|
dense
|
|
|
|
|
rounded
|
|
|
|
|
@click="hideStat = !hideStat"
|
|
|
|
|
:style="hideStat ? 'rotate: 90deg' : ''"
|
|
|
|
|
style="transition: 0.1s ease-in-out"
|
|
|
|
|
/>
|
2024-07-04 04:12:10 +00:00
|
|
|
</div>
|
2024-06-12 15:37:17 +07:00
|
|
|
|
2024-07-12 15:26:13 +07:00
|
|
|
<transition name="slide">
|
|
|
|
|
<div v-if="!hideStat" class="scroll q-mb-md">
|
|
|
|
|
<div style="display: inline-block">
|
|
|
|
|
<StatCard
|
|
|
|
|
label-i18n
|
|
|
|
|
:branch="stat.filter((v) => !filterStat.includes(v.mode))"
|
|
|
|
|
:dark="$q.dark.isActive"
|
|
|
|
|
nowrap
|
|
|
|
|
/>
|
2024-07-12 13:35:15 +07:00
|
|
|
</div>
|
2024-07-12 15:26:13 +07:00
|
|
|
</div>
|
|
|
|
|
</transition>
|
|
|
|
|
|
2024-07-17 07:32:56 +00:00
|
|
|
<div
|
|
|
|
|
class="column col rounded bordered"
|
|
|
|
|
style="flex-wrap: nowrap; overflow: hidden"
|
2024-07-12 15:26:13 +07:00
|
|
|
>
|
2024-07-17 07:32:56 +00:00
|
|
|
<q-splitter
|
|
|
|
|
v-model="splitterModel"
|
2024-07-18 11:01:39 +00:00
|
|
|
:limits="[0, 100]"
|
2024-07-17 07:32:56 +00:00
|
|
|
style="width: 100%"
|
|
|
|
|
class="col"
|
|
|
|
|
after-class="overflow-hidden"
|
|
|
|
|
>
|
|
|
|
|
<template v-slot:before>
|
|
|
|
|
<div class="surface-1 column full-height">
|
2024-07-15 14:12:53 +07:00
|
|
|
<div
|
2024-07-19 10:35:18 +00:00
|
|
|
class="row no-wrap full-width bordered-b text-weight-bold surface-3 items-center q-px-md q-py-sm"
|
2024-07-17 07:32:56 +00:00
|
|
|
:style="`min-height: ${$q.screen.gt.sm ? '57px' : '100.8px'}`"
|
2024-07-15 14:12:53 +07:00
|
|
|
>
|
2024-07-19 10:35:18 +00:00
|
|
|
<div class="col ellipsis-2-lines">จัดการสาขาทั้งหมด</div>
|
2024-07-17 07:32:56 +00:00
|
|
|
</div>
|
|
|
|
|
|
2024-07-24 02:06:33 +00:00
|
|
|
<div class="col full-width scroll">
|
2024-07-19 10:35:18 +00:00
|
|
|
<div class="q-pa-md">
|
2024-07-30 16:24:11 +07:00
|
|
|
<TreeCompoent
|
|
|
|
|
:nodes="treeProductTypeAndGroup"
|
|
|
|
|
v-model:expanded-tree="expandedTree"
|
|
|
|
|
node-key="id"
|
|
|
|
|
label-key="name"
|
|
|
|
|
children-key="children"
|
|
|
|
|
type-tree="product"
|
|
|
|
|
@select="
|
|
|
|
|
async (v) => {
|
|
|
|
|
if (v.type === 'group') {
|
|
|
|
|
if (currentIdGrop !== v.id) {
|
|
|
|
|
filterStat.push('group');
|
|
|
|
|
await enterGroup(v.id, v.name);
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (currentIdGrop === v.id) {
|
|
|
|
|
expandedTree = [];
|
|
|
|
|
filterStat = [];
|
|
|
|
|
expandedTree = expandedTree.filter((i) => v.id !== i);
|
|
|
|
|
currentIdGrop = '';
|
|
|
|
|
currentIdType = '';
|
|
|
|
|
productMode = 'group';
|
|
|
|
|
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
if (v.type === 'type') {
|
|
|
|
|
if (currentIdType !== v.id) {
|
|
|
|
|
filterStat.push('group', 'type');
|
|
|
|
|
await enterType(v.id, v.name);
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
if (currentIdType === v.id) {
|
|
|
|
|
filterStat = filterStat.filter((item) => {
|
|
|
|
|
return item !== 'type';
|
|
|
|
|
});
|
|
|
|
|
currentIdType = '';
|
|
|
|
|
productMode = 'type';
|
|
|
|
|
expandedTree.pop();
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
"
|
|
|
|
|
@view="
|
|
|
|
|
(v) => {
|
|
|
|
|
if (v.type === 'type') {
|
|
|
|
|
editByTree = 'type';
|
|
|
|
|
currentStatusProduct = v.status === 'INACTIVE';
|
|
|
|
|
clearFormGroup();
|
|
|
|
|
currentIdType = v.id;
|
|
|
|
|
assignFormDataGroup(v);
|
|
|
|
|
isEdit = false;
|
|
|
|
|
drawerInfo = true;
|
|
|
|
|
}
|
|
|
|
|
if (v.type === 'group') {
|
|
|
|
|
editByTree = 'group';
|
|
|
|
|
currentStatusProduct = v.status === 'INACTIVE';
|
|
|
|
|
clearFormGroup();
|
|
|
|
|
assignFormDataGroup(v);
|
|
|
|
|
isEdit = false;
|
|
|
|
|
currentIdGrop = v.id;
|
|
|
|
|
drawerInfo = true;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
"
|
|
|
|
|
@edit="
|
|
|
|
|
(v) => {
|
|
|
|
|
editByTree = v.type;
|
|
|
|
|
if (v.type === 'type') {
|
|
|
|
|
clearFormGroup();
|
|
|
|
|
currentIdType = v.id;
|
|
|
|
|
assignFormDataGroup(v);
|
|
|
|
|
isEdit = true;
|
|
|
|
|
drawerInfo = true;
|
|
|
|
|
}
|
|
|
|
|
if (v.type === 'group') {
|
|
|
|
|
clearFormGroup();
|
|
|
|
|
assignFormDataGroup(v);
|
|
|
|
|
isEdit = true;
|
|
|
|
|
currentIdGrop = v.id;
|
|
|
|
|
|
|
|
|
|
drawerInfo = true;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
"
|
|
|
|
|
@delete="
|
|
|
|
|
(v) => {
|
|
|
|
|
editByTree = v.type;
|
|
|
|
|
|
|
|
|
|
if (v.type === 'type') {
|
|
|
|
|
deleteProductById(v.id);
|
|
|
|
|
}
|
|
|
|
|
if (v.type === 'group') {
|
|
|
|
|
deleteProductById(v.id);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
"
|
|
|
|
|
@change-status="
|
|
|
|
|
async (v) => {
|
|
|
|
|
if (v.type === 'type') {
|
|
|
|
|
triggerChangeStatus(v.id, v.status, v.type);
|
|
|
|
|
}
|
|
|
|
|
if (v.type === 'group') {
|
|
|
|
|
triggerChangeStatus(v.id, v.status, v.type);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
"
|
|
|
|
|
/>
|
|
|
|
|
|
|
|
|
|
<!-- <q-tree
|
2024-07-17 07:32:56 +00:00
|
|
|
:nodes="treeProductTypeAndGroup"
|
2024-07-19 10:35:18 +00:00
|
|
|
color="transparent"
|
2024-07-17 07:32:56 +00:00
|
|
|
node-key="id"
|
|
|
|
|
label-key="name"
|
|
|
|
|
children-key="children"
|
|
|
|
|
v-model:expanded="expandedTree"
|
2024-07-19 10:35:18 +00:00
|
|
|
style="color: var(--foreground)"
|
2024-07-17 07:32:56 +00:00
|
|
|
>
|
|
|
|
|
<template #default-header="{ node }">
|
|
|
|
|
<div
|
2024-07-23 02:48:17 +00:00
|
|
|
class="full-width q-py-xs clickable-node"
|
2024-07-23 07:25:11 +00:00
|
|
|
:class="{
|
|
|
|
|
'cursor-pointer':
|
|
|
|
|
node.type === 'group' || node.type === 'type',
|
|
|
|
|
'active-node':
|
|
|
|
|
expandedTree[expandedTree.length - 1] === node.id,
|
|
|
|
|
}"
|
2024-07-19 10:35:18 +00:00
|
|
|
v-touch-hold.mouse="handleHold(node)"
|
2024-07-17 07:32:56 +00:00
|
|
|
@click.stop="
|
|
|
|
|
async () => {
|
2024-07-23 10:24:22 +07:00
|
|
|
if (node.type === 'group') {
|
|
|
|
|
if (currentIdGrop !== node.id) {
|
2024-07-25 11:01:00 +07:00
|
|
|
filterStat.push('group');
|
2024-07-23 10:24:22 +07:00
|
|
|
await enterGroup(node.id, node.name);
|
|
|
|
|
return;
|
|
|
|
|
}
|
2024-07-15 16:05:40 +07:00
|
|
|
|
2024-07-23 10:24:22 +07:00
|
|
|
if (currentIdGrop === node.id) {
|
2024-07-23 07:36:28 +00:00
|
|
|
expandedTree = [];
|
2024-07-25 11:01:00 +07:00
|
|
|
filterStat = [];
|
2024-07-23 10:24:22 +07:00
|
|
|
expandedTree = expandedTree.filter(
|
|
|
|
|
(i) => node.id !== i,
|
|
|
|
|
);
|
|
|
|
|
currentIdGrop = '';
|
2024-07-23 07:36:28 +00:00
|
|
|
currentIdType = '';
|
2024-07-23 10:24:22 +07:00
|
|
|
productMode = 'group';
|
|
|
|
|
|
|
|
|
|
return;
|
|
|
|
|
}
|
2024-07-17 07:32:56 +00:00
|
|
|
}
|
2024-07-23 13:47:42 +07:00
|
|
|
if (node.type === 'type') {
|
|
|
|
|
if (currentIdType !== node.id) {
|
2024-07-25 11:01:00 +07:00
|
|
|
filterStat.push('group', 'type');
|
2024-07-23 13:47:42 +07:00
|
|
|
await enterType(node.id, node.name);
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
if (currentIdType === node.id) {
|
2024-07-25 11:01:00 +07:00
|
|
|
filterStat = filterStat.filter((item) => {
|
|
|
|
|
return item !== 'type';
|
|
|
|
|
});
|
2024-07-23 13:47:42 +07:00
|
|
|
currentIdType = '';
|
|
|
|
|
productMode = 'type';
|
2024-07-23 07:25:11 +00:00
|
|
|
expandedTree.pop();
|
2024-07-23 13:47:42 +07:00
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
}
|
2024-07-15 14:12:53 +07:00
|
|
|
}
|
2024-07-17 07:32:56 +00:00
|
|
|
"
|
|
|
|
|
>
|
2024-07-19 10:35:18 +00:00
|
|
|
<div
|
|
|
|
|
class="row col items-center justify-between full-width no-wrap"
|
|
|
|
|
>
|
2024-07-23 02:26:15 +00:00
|
|
|
<q-icon
|
|
|
|
|
v-if="node.type === 'group' && node._count.type > 0"
|
|
|
|
|
name="mdi-triangle-down"
|
|
|
|
|
size="12px"
|
2024-07-23 07:25:11 +00:00
|
|
|
class="app-text-muted q-mr-md q-ml-sm"
|
2024-07-23 02:26:15 +00:00
|
|
|
:style="`rotate: ${expandedTree[0] === node.id ? '0deg' : '30deg'}`"
|
|
|
|
|
/>
|
2024-07-23 07:25:11 +00:00
|
|
|
<div
|
|
|
|
|
class="col row"
|
|
|
|
|
:class="{ 'q-pl-sm': node.type === 'type' }"
|
|
|
|
|
:style="`padding-left:${node.type === 'group' && node._count.type === 0 ? '36px' : ''}`"
|
|
|
|
|
>
|
2024-07-19 10:35:18 +00:00
|
|
|
<span
|
|
|
|
|
class="ellipsis col-12"
|
|
|
|
|
style="white-space: nowrap"
|
|
|
|
|
:class="{
|
2024-07-23 13:47:42 +07:00
|
|
|
'text-weight-bold':
|
|
|
|
|
expandedTree[expandedTree.length - 1] ===
|
|
|
|
|
node.id,
|
|
|
|
|
'app-text-info':
|
|
|
|
|
expandedTree[expandedTree.length - 1] ===
|
|
|
|
|
node.id,
|
2024-07-19 10:35:18 +00:00
|
|
|
}"
|
|
|
|
|
>
|
|
|
|
|
{{ node.name }}
|
|
|
|
|
</span>
|
|
|
|
|
<span class="app-text-muted text-caption ellipsis">
|
|
|
|
|
{{ node.code }}
|
|
|
|
|
</span>
|
|
|
|
|
</div>
|
|
|
|
|
|
|
|
|
|
<div
|
2024-07-23 02:49:21 +00:00
|
|
|
class="row q-gutter-xs items-center no-wrap app-text-muted-2"
|
2024-07-19 10:35:18 +00:00
|
|
|
v-if="$q.screen.gt.xs"
|
|
|
|
|
>
|
2024-07-17 07:32:56 +00:00
|
|
|
<q-btn
|
|
|
|
|
icon="mdi-eye-outline"
|
|
|
|
|
:id="`btn-tree-eye-${node.name}`"
|
|
|
|
|
size="sm"
|
|
|
|
|
dense
|
|
|
|
|
round
|
|
|
|
|
flat
|
|
|
|
|
@click.stop="
|
|
|
|
|
() => {
|
|
|
|
|
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;
|
2024-07-23 10:24:22 +07:00
|
|
|
currentIdGrop = node.id;
|
2024-07-17 07:32:56 +00:00
|
|
|
drawerInfo = true;
|
|
|
|
|
}
|
2024-07-15 14:12:53 +07:00
|
|
|
}
|
2024-07-17 07:32:56 +00:00
|
|
|
"
|
|
|
|
|
/>
|
|
|
|
|
|
|
|
|
|
<q-btn
|
|
|
|
|
icon="mdi-dots-vertical"
|
|
|
|
|
:id="`btn-tree-dots-${node.name}`"
|
|
|
|
|
size="sm"
|
|
|
|
|
dense
|
|
|
|
|
round
|
|
|
|
|
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;
|
2024-07-23 10:24:22 +07:00
|
|
|
currentIdGrop = node.id;
|
2024-07-17 07:32:56 +00:00
|
|
|
drawerInfo = true;
|
|
|
|
|
}
|
2024-07-15 14:12:53 +07:00
|
|
|
}
|
2024-07-17 07:32:56 +00:00
|
|
|
"
|
|
|
|
|
dense
|
|
|
|
|
class="row q-py-sm"
|
|
|
|
|
style="white-space: nowrap"
|
|
|
|
|
>
|
|
|
|
|
<q-icon
|
|
|
|
|
name="mdi-eye-outline"
|
|
|
|
|
class="col-3"
|
|
|
|
|
size="xs"
|
|
|
|
|
style="color: hsl(var(--green-6-hsl))"
|
|
|
|
|
/>
|
|
|
|
|
<span class="col-9 q-px-md flex items-center">
|
|
|
|
|
{{ $t('viewDetail') }}
|
|
|
|
|
</span>
|
|
|
|
|
</q-item>
|
|
|
|
|
|
|
|
|
|
<q-item
|
|
|
|
|
:id="`view-detail-btn-${node.name}-edit`"
|
|
|
|
|
v-close-popup
|
|
|
|
|
clickable
|
|
|
|
|
dense
|
|
|
|
|
class="row q-py-sm"
|
|
|
|
|
style="white-space: nowrap"
|
|
|
|
|
@click.stop="
|
|
|
|
|
() => {
|
|
|
|
|
editByTree = node.type;
|
|
|
|
|
if (node.type === 'type') {
|
|
|
|
|
clearFormGroup();
|
|
|
|
|
currentIdType = node.id;
|
|
|
|
|
assignFormDataGroup(node);
|
|
|
|
|
isEdit = true;
|
|
|
|
|
drawerInfo = true;
|
|
|
|
|
}
|
|
|
|
|
if (node.type === 'group') {
|
|
|
|
|
clearFormGroup();
|
|
|
|
|
assignFormDataGroup(node);
|
|
|
|
|
isEdit = true;
|
2024-07-23 10:24:22 +07:00
|
|
|
currentIdGrop = node.id;
|
2024-07-17 07:32:56 +00:00
|
|
|
|
|
|
|
|
drawerInfo = true;
|
|
|
|
|
}
|
2024-07-15 14:12:53 +07:00
|
|
|
}
|
2024-07-17 07:32:56 +00:00
|
|
|
"
|
|
|
|
|
>
|
|
|
|
|
<q-icon
|
|
|
|
|
name="mdi-pencil-outline"
|
|
|
|
|
class="col-3"
|
|
|
|
|
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"
|
2024-07-15 14:12:53 +07:00
|
|
|
:class="{
|
2024-07-17 07:32:56 +00:00
|
|
|
'surface-3': node.status !== 'CREATED',
|
|
|
|
|
'app-text-muted': node.status !== 'CREATED',
|
2024-07-15 14:12:53 +07:00
|
|
|
}"
|
2024-07-17 07:32:56 +00:00
|
|
|
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('switchOffLabel')
|
|
|
|
|
"
|
|
|
|
|
@click.stop="
|
|
|
|
|
async () => {
|
|
|
|
|
if (node.type === 'type') {
|
2024-07-25 10:49:43 +00:00
|
|
|
triggerChangeStatus(
|
2024-07-17 07:32:56 +00:00
|
|
|
node.id,
|
|
|
|
|
node.status,
|
2024-07-25 10:49:43 +00:00
|
|
|
node.type,
|
2024-07-17 07:32:56 +00:00
|
|
|
);
|
|
|
|
|
}
|
|
|
|
|
if (node.type === 'group') {
|
2024-07-25 10:49:43 +00:00
|
|
|
triggerChangeStatus(
|
2024-07-17 07:32:56 +00:00
|
|
|
node.id,
|
|
|
|
|
node.status,
|
2024-07-25 10:49:43 +00:00
|
|
|
node.type,
|
2024-07-17 07:32:56 +00:00
|
|
|
);
|
|
|
|
|
}
|
2024-07-15 14:12:53 +07:00
|
|
|
}
|
2024-07-17 07:32:56 +00:00
|
|
|
"
|
|
|
|
|
:model-value="
|
|
|
|
|
node.status !== 'INACTIVE'
|
|
|
|
|
"
|
|
|
|
|
/>
|
|
|
|
|
</div>
|
|
|
|
|
</q-item-section>
|
|
|
|
|
</q-item>
|
|
|
|
|
</q-list>
|
|
|
|
|
</q-menu>
|
|
|
|
|
</q-btn>
|
|
|
|
|
</div>
|
2024-07-15 14:12:53 +07:00
|
|
|
</div>
|
|
|
|
|
</div>
|
2024-07-17 07:32:56 +00:00
|
|
|
</template>
|
2024-07-30 16:24:11 +07:00
|
|
|
</q-tree> -->
|
2024-07-17 07:32:56 +00:00
|
|
|
</div>
|
2024-07-12 15:26:13 +07:00
|
|
|
</div>
|
2024-07-05 06:13:55 +00:00
|
|
|
</div>
|
2024-07-17 07:32:56 +00:00
|
|
|
</template>
|
|
|
|
|
|
|
|
|
|
<template v-slot:after>
|
|
|
|
|
<div class="column no-wrap full-height">
|
|
|
|
|
<!-- group/type -->
|
2024-07-12 15:26:13 +07:00
|
|
|
<div
|
2024-07-17 07:32:56 +00:00
|
|
|
v-if="productMode === 'group' || productMode === 'type'"
|
|
|
|
|
class="surface-2 items-center full-width full-height column col"
|
2024-06-12 15:37:17 +07:00
|
|
|
>
|
2024-07-17 07:32:56 +00:00
|
|
|
<!-- tool bar -->
|
|
|
|
|
<div
|
|
|
|
|
class="row q-py-sm q-px-md justify-between full-width surface-3 bordered-b"
|
2024-07-09 14:38:22 +07:00
|
|
|
>
|
2024-07-17 07:32:56 +00:00
|
|
|
<q-input
|
2024-07-26 11:05:07 +07:00
|
|
|
lazy-rules="ondemand"
|
2024-07-17 07:32:56 +00:00
|
|
|
for="input-search"
|
2024-07-12 15:26:13 +07:00
|
|
|
outlined
|
2024-07-17 07:32:56 +00:00
|
|
|
:class="{ 'col-12': $q.screen.lt.md }"
|
2024-07-12 15:26:13 +07:00
|
|
|
dense
|
2024-07-17 07:32:56 +00:00
|
|
|
:label="$t('search')"
|
|
|
|
|
class=""
|
|
|
|
|
:bg-color="$q.dark.isActive ? 'dark' : 'white'"
|
|
|
|
|
v-model="inputSearch"
|
|
|
|
|
debounce="200"
|
2024-07-12 15:26:13 +07:00
|
|
|
>
|
2024-07-17 07:32:56 +00:00
|
|
|
<template v-slot:prepend>
|
|
|
|
|
<q-icon name="mdi-magnify" />
|
2024-07-12 15:26:13 +07:00
|
|
|
</template>
|
2024-07-17 07:32:56 +00:00
|
|
|
</q-input>
|
|
|
|
|
|
|
|
|
|
<div
|
|
|
|
|
class="row col-12 col-md-6"
|
|
|
|
|
:class="{ 'q-pt-xs': $q.screen.lt.md }"
|
|
|
|
|
style="white-space: nowrap"
|
|
|
|
|
>
|
|
|
|
|
<q-select
|
2024-07-26 11:05:07 +07:00
|
|
|
lazy-rules="ondemand"
|
2024-07-17 07:32:56 +00:00
|
|
|
v-model="currentStatus"
|
2024-07-19 14:04:02 +07:00
|
|
|
for="select-status"
|
2024-07-17 07:32:56 +00:00
|
|
|
outlined
|
|
|
|
|
dense
|
|
|
|
|
option-value="value"
|
|
|
|
|
option-label="label"
|
|
|
|
|
class="col"
|
2024-07-30 04:17:51 +00:00
|
|
|
:class="{ 'offset-md-5': modeView }"
|
2024-07-17 07:32:56 +00:00
|
|
|
map-options
|
|
|
|
|
emit-value
|
2024-07-18 04:51:09 +00:00
|
|
|
:hide-dropdown-icon="$q.screen.lt.sm"
|
2024-07-17 07:32:56 +00:00
|
|
|
:options="[
|
|
|
|
|
{ label: $t('all'), value: 'All' },
|
|
|
|
|
{ label: $t('statusACTIVE'), value: 'ACTIVE' },
|
|
|
|
|
{
|
|
|
|
|
label: $t('statusINACTIVE'),
|
|
|
|
|
value: 'INACTIVE',
|
|
|
|
|
},
|
|
|
|
|
]"
|
|
|
|
|
></q-select>
|
|
|
|
|
|
|
|
|
|
<q-select
|
2024-07-26 11:05:07 +07:00
|
|
|
lazy-rules="ondemand"
|
2024-07-17 07:32:56 +00:00
|
|
|
v-if="modeView === false"
|
|
|
|
|
id="select-field"
|
|
|
|
|
for="select-field"
|
|
|
|
|
:options="
|
|
|
|
|
tbControl.groupAndType.fieldDisplay.map((x) => ({
|
|
|
|
|
label: $t(x),
|
|
|
|
|
value: x,
|
|
|
|
|
}))
|
|
|
|
|
"
|
2024-07-18 04:51:09 +00:00
|
|
|
:hide-dropdown-icon="$q.screen.lt.sm"
|
2024-07-17 07:32:56 +00:00
|
|
|
:display-value="$t('displayField')"
|
|
|
|
|
v-model="tbControl.groupAndType.fieldSelected"
|
2024-07-18 09:10:51 +00:00
|
|
|
class="col q-ml-sm"
|
2024-07-17 07:32:56 +00:00
|
|
|
option-label="label"
|
|
|
|
|
option-value="value"
|
|
|
|
|
map-options
|
|
|
|
|
emit-value
|
|
|
|
|
outlined
|
|
|
|
|
multiple
|
|
|
|
|
dense
|
|
|
|
|
/>
|
|
|
|
|
|
|
|
|
|
<q-btn-toggle
|
|
|
|
|
v-model="modeView"
|
|
|
|
|
id="btn-mode"
|
|
|
|
|
dense
|
2024-07-18 09:10:51 +00:00
|
|
|
class="no-shadow bordered rounded surface-1 q-ml-sm"
|
2024-07-17 07:32:56 +00:00
|
|
|
:toggle-color="$q.dark.isActive ? 'grey-9' : 'grey-2'"
|
|
|
|
|
size="xs"
|
|
|
|
|
:options="[
|
|
|
|
|
{ value: true, slot: 'folder' },
|
|
|
|
|
{ value: false, slot: 'list' },
|
|
|
|
|
]"
|
|
|
|
|
>
|
|
|
|
|
<template v-slot:folder>
|
|
|
|
|
<q-icon
|
|
|
|
|
name="mdi-view-grid-outline"
|
|
|
|
|
size="16px"
|
|
|
|
|
class="q-px-sm q-py-xs rounded"
|
|
|
|
|
:style="{
|
|
|
|
|
color: $q.dark.isActive
|
|
|
|
|
? modeView
|
|
|
|
|
? '#C9D3DB '
|
|
|
|
|
: '#787B7C'
|
|
|
|
|
: modeView
|
|
|
|
|
? '#787B7C'
|
|
|
|
|
: '#C9D3DB',
|
|
|
|
|
}"
|
|
|
|
|
/>
|
|
|
|
|
</template>
|
|
|
|
|
<template v-slot:list>
|
|
|
|
|
<q-icon
|
|
|
|
|
name="mdi-format-list-bulleted"
|
|
|
|
|
class="q-px-sm q-py-xs rounded"
|
|
|
|
|
size="16px"
|
|
|
|
|
:style="{
|
|
|
|
|
color: $q.dark.isActive
|
|
|
|
|
? modeView === false
|
|
|
|
|
? '#C9D3DB'
|
|
|
|
|
: '#787B7C'
|
|
|
|
|
: modeView === false
|
|
|
|
|
? '#787B7C'
|
|
|
|
|
: '#C9D3DB',
|
|
|
|
|
}"
|
|
|
|
|
/>
|
|
|
|
|
</template>
|
|
|
|
|
</q-btn-toggle>
|
|
|
|
|
</div>
|
2024-07-12 15:26:13 +07:00
|
|
|
</div>
|
2024-07-09 14:38:22 +07:00
|
|
|
|
2024-07-17 07:32:56 +00:00
|
|
|
<div
|
|
|
|
|
v-if="
|
|
|
|
|
((productMode === 'type' && productType?.length === 0) ||
|
|
|
|
|
(productGroup?.length === 0 && productMode === 'group')) &&
|
|
|
|
|
stat[0].count !== undefined
|
|
|
|
|
"
|
|
|
|
|
class="items-center justify-center full-width flex col"
|
|
|
|
|
>
|
|
|
|
|
<NoData :not-found="!!inputSearch" />
|
|
|
|
|
</div>
|
2024-07-12 13:35:15 +07:00
|
|
|
|
2024-07-17 07:32:56 +00:00
|
|
|
<template v-else>
|
|
|
|
|
<div class="surface-2 q-pa-md scroll col full-width">
|
|
|
|
|
<q-table
|
|
|
|
|
flat
|
|
|
|
|
bordered
|
|
|
|
|
:grid="modeView"
|
|
|
|
|
:rows="
|
|
|
|
|
(productMode === 'type' ? productType : productGroup) ||
|
|
|
|
|
[]
|
|
|
|
|
"
|
|
|
|
|
:columns="tbColumn.groupAndType"
|
|
|
|
|
class="full-width"
|
|
|
|
|
card-container-class="q-col-gutter-md"
|
|
|
|
|
row-key="name"
|
|
|
|
|
:rows-per-page-options="[0]"
|
|
|
|
|
hide-pagination
|
|
|
|
|
:visible-columns="tbControl.groupAndType.fieldSelected"
|
|
|
|
|
>
|
|
|
|
|
<template v-slot:header="props">
|
2024-07-31 06:18:52 +00:00
|
|
|
<q-tr
|
|
|
|
|
style="background-color: hsla(var(--info-bg) / 0.07)"
|
|
|
|
|
:props="props"
|
|
|
|
|
>
|
2024-07-17 07:32:56 +00:00
|
|
|
<q-th
|
|
|
|
|
v-for="col in props.cols"
|
|
|
|
|
:key="col.name"
|
|
|
|
|
:props="props"
|
|
|
|
|
>
|
|
|
|
|
{{ $t(col.label) }}
|
|
|
|
|
</q-th>
|
|
|
|
|
<q-th auto-width />
|
|
|
|
|
</q-tr>
|
|
|
|
|
</template>
|
|
|
|
|
|
|
|
|
|
<template v-slot:body="props">
|
|
|
|
|
<q-tr
|
2024-07-31 14:34:51 +07:00
|
|
|
:id="`enter-${props.row.name}`"
|
2024-07-19 10:35:18 +00:00
|
|
|
class="cursor-pointer"
|
2024-07-17 07:32:56 +00:00
|
|
|
:class="{
|
|
|
|
|
'app-text-muted': props.row.status === 'INACTIVE',
|
|
|
|
|
'status-active': props.row.status !== 'INACTIVE',
|
|
|
|
|
'status-inactive': props.row.status === 'INACTIVE',
|
|
|
|
|
}"
|
2024-07-12 13:35:15 +07:00
|
|
|
:props="props"
|
2024-07-17 07:32:56 +00:00
|
|
|
@click="
|
|
|
|
|
async () => {
|
|
|
|
|
filterStat.push(productMode);
|
|
|
|
|
if (productMode === 'type') {
|
2024-07-23 13:47:42 +07:00
|
|
|
await enterType(props.row.id, props.row.name);
|
2024-07-17 07:32:56 +00:00
|
|
|
}
|
|
|
|
|
if (productMode === 'group') {
|
2024-07-23 10:24:22 +07:00
|
|
|
await enterGroup(props.row.id, props.row.name);
|
2024-07-17 07:32:56 +00:00
|
|
|
}
|
2024-07-12 13:35:15 +07:00
|
|
|
}
|
|
|
|
|
"
|
|
|
|
|
>
|
2024-07-17 07:32:56 +00:00
|
|
|
<q-td
|
|
|
|
|
v-if="
|
|
|
|
|
tbControl.groupAndType.fieldSelected.includes(
|
|
|
|
|
'name',
|
|
|
|
|
)
|
|
|
|
|
"
|
|
|
|
|
>
|
|
|
|
|
<div class="row items-center">
|
2024-07-12 13:35:15 +07:00
|
|
|
<div
|
2024-07-17 07:32:56 +00:00
|
|
|
style="
|
|
|
|
|
width: 50px;
|
|
|
|
|
display: flex;
|
|
|
|
|
margin-bottom: var(--size-2);
|
|
|
|
|
"
|
2024-07-12 13:35:15 +07:00
|
|
|
>
|
2024-07-17 07:32:56 +00:00
|
|
|
<div
|
|
|
|
|
:class="`icon-color-${productMode === 'group' ? 'pink' : 'purple'}`"
|
|
|
|
|
class="table__icon"
|
|
|
|
|
>
|
|
|
|
|
<q-icon
|
|
|
|
|
size="md"
|
|
|
|
|
style="scale: 0.8"
|
|
|
|
|
:name="
|
|
|
|
|
productMode === 'group'
|
|
|
|
|
? 'mdi-folder'
|
|
|
|
|
: 'mdi-folder-table'
|
|
|
|
|
"
|
|
|
|
|
/>
|
|
|
|
|
</div>
|
2024-07-12 13:35:15 +07:00
|
|
|
</div>
|
|
|
|
|
<div class="col">
|
2024-07-17 07:32:56 +00:00
|
|
|
<div class="col">
|
|
|
|
|
{{ props.row.name }}
|
|
|
|
|
</div>
|
|
|
|
|
<div class="col app-text-muted">
|
|
|
|
|
{{ props.row.code || '-' }}
|
|
|
|
|
</div>
|
2024-07-12 13:35:15 +07:00
|
|
|
</div>
|
2024-07-10 11:54:22 +07:00
|
|
|
</div>
|
2024-07-17 07:32:56 +00:00
|
|
|
</q-td>
|
|
|
|
|
<q-td
|
|
|
|
|
v-if="
|
|
|
|
|
tbControl.groupAndType.fieldSelected.includes(
|
|
|
|
|
'detail',
|
|
|
|
|
)
|
|
|
|
|
"
|
|
|
|
|
>
|
|
|
|
|
{{ props.row.detail || '-' }}
|
|
|
|
|
</q-td>
|
|
|
|
|
|
|
|
|
|
<q-td
|
|
|
|
|
v-if="
|
|
|
|
|
tbControl.groupAndType.fieldSelected.includes(
|
|
|
|
|
'formDialogInputRemark',
|
|
|
|
|
)
|
|
|
|
|
"
|
|
|
|
|
>
|
|
|
|
|
{{ props.row.remark || '-' }}
|
|
|
|
|
</q-td>
|
|
|
|
|
|
|
|
|
|
<q-td
|
|
|
|
|
v-if="
|
|
|
|
|
tbControl.groupAndType.fieldSelected.includes(
|
|
|
|
|
'createdAt',
|
|
|
|
|
)
|
|
|
|
|
"
|
|
|
|
|
>
|
|
|
|
|
{{ dateFormat(props.row.createdAt) }}
|
|
|
|
|
</q-td>
|
|
|
|
|
|
|
|
|
|
<q-td>
|
|
|
|
|
<q-btn
|
|
|
|
|
icon="mdi-eye-outline"
|
|
|
|
|
:id="`btn-eye-${props.row.name}`"
|
|
|
|
|
size="sm"
|
|
|
|
|
dense
|
|
|
|
|
round
|
|
|
|
|
flat
|
|
|
|
|
@click.stop="
|
|
|
|
|
() => {
|
|
|
|
|
if (productMode === 'type') {
|
|
|
|
|
currentStatusProduct =
|
|
|
|
|
props.row.status === 'INACTIVE';
|
|
|
|
|
clearFormGroup();
|
|
|
|
|
currentIdType = props.row.id;
|
|
|
|
|
assignFormDataGroup(props.row);
|
|
|
|
|
isEdit = false;
|
|
|
|
|
drawerInfo = true;
|
|
|
|
|
}
|
|
|
|
|
if (productMode === 'group') {
|
|
|
|
|
currentStatusProduct =
|
|
|
|
|
props.row.status === 'INACTIVE';
|
|
|
|
|
clearFormGroup();
|
|
|
|
|
assignFormDataGroup(props.row);
|
|
|
|
|
isEdit = false;
|
2024-07-23 10:24:22 +07:00
|
|
|
currentIdGrop = props.row.id;
|
2024-07-17 07:32:56 +00:00
|
|
|
drawerInfo = true;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
"
|
|
|
|
|
/>
|
|
|
|
|
|
|
|
|
|
<q-btn
|
|
|
|
|
icon="mdi-dots-vertical"
|
|
|
|
|
:id="`btn-dots-${props.row.name}`"
|
|
|
|
|
size="sm"
|
|
|
|
|
dense
|
|
|
|
|
round
|
|
|
|
|
flat
|
|
|
|
|
@click.stop
|
|
|
|
|
:key="props.row.id"
|
|
|
|
|
>
|
|
|
|
|
<q-menu class="bordered">
|
|
|
|
|
<q-list v-close-popup>
|
|
|
|
|
<q-item
|
|
|
|
|
v-close-popup
|
|
|
|
|
clickable
|
|
|
|
|
:id="`view-detail-btn-${props.row.name}-view`"
|
|
|
|
|
@click.stop="
|
|
|
|
|
() => {
|
|
|
|
|
if (productMode === 'type') {
|
|
|
|
|
currentStatusProduct =
|
|
|
|
|
props.row.status === 'INACTIVE';
|
|
|
|
|
clearFormGroup();
|
|
|
|
|
currentIdType = props.row.id;
|
|
|
|
|
assignFormDataGroup(props.row);
|
|
|
|
|
isEdit = false;
|
|
|
|
|
drawerInfo = true;
|
|
|
|
|
}
|
|
|
|
|
if (productMode === 'group') {
|
|
|
|
|
currentStatusProduct =
|
|
|
|
|
props.row.status === 'INACTIVE';
|
|
|
|
|
clearFormGroup();
|
|
|
|
|
assignFormDataGroup(props.row);
|
|
|
|
|
isEdit = false;
|
2024-07-23 10:24:22 +07:00
|
|
|
currentIdGrop = props.row.id;
|
2024-07-17 07:32:56 +00:00
|
|
|
drawerInfo = true;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
"
|
|
|
|
|
dense
|
|
|
|
|
class="row q-py-sm"
|
|
|
|
|
style="white-space: nowrap"
|
|
|
|
|
>
|
|
|
|
|
<q-icon
|
|
|
|
|
name="mdi-eye-outline"
|
|
|
|
|
class="col-3"
|
|
|
|
|
size="xs"
|
|
|
|
|
style="color: hsl(var(--green-6-hsl))"
|
|
|
|
|
/>
|
|
|
|
|
<span class="col-9 q-px-md flex items-center">
|
|
|
|
|
{{ $t('viewDetail') }}
|
|
|
|
|
</span>
|
|
|
|
|
</q-item>
|
|
|
|
|
|
|
|
|
|
<q-item
|
|
|
|
|
:id="`view-detail-btn-${props.row.name}-edit`"
|
|
|
|
|
v-close-popup
|
|
|
|
|
clickable
|
|
|
|
|
dense
|
|
|
|
|
class="row q-py-sm"
|
|
|
|
|
style="white-space: nowrap"
|
|
|
|
|
@click="
|
|
|
|
|
() => {
|
|
|
|
|
if (productMode === 'type') {
|
|
|
|
|
clearFormGroup();
|
|
|
|
|
currentIdType = props.row.id;
|
|
|
|
|
assignFormDataGroup(props.row);
|
|
|
|
|
isEdit = true;
|
|
|
|
|
drawerInfo = true;
|
|
|
|
|
}
|
|
|
|
|
if (productMode === 'group') {
|
|
|
|
|
clearFormGroup();
|
|
|
|
|
assignFormDataGroup(props.row);
|
|
|
|
|
isEdit = true;
|
2024-07-23 10:24:22 +07:00
|
|
|
currentIdGrop = props.row.id;
|
2024-07-17 07:32:56 +00:00
|
|
|
|
|
|
|
|
drawerInfo = true;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
"
|
|
|
|
|
>
|
|
|
|
|
<q-icon
|
|
|
|
|
name="mdi-pencil-outline"
|
|
|
|
|
class="col-3"
|
|
|
|
|
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-${props.row.name}-delete`"
|
|
|
|
|
dense
|
|
|
|
|
:clickable="props.row.status === 'CREATED'"
|
|
|
|
|
class="row"
|
|
|
|
|
:class="{
|
|
|
|
|
'surface-3': props.row.status !== 'CREATED',
|
|
|
|
|
'app-text-muted':
|
|
|
|
|
props.row.status !== 'CREATED',
|
|
|
|
|
}"
|
|
|
|
|
style="white-space: nowrap"
|
|
|
|
|
@click="
|
|
|
|
|
() => {
|
|
|
|
|
if (productMode === 'type') {
|
|
|
|
|
deleteProductById(props.row.id);
|
|
|
|
|
}
|
|
|
|
|
if (productMode === 'group') {
|
|
|
|
|
deleteProductById(props.row.id);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
"
|
|
|
|
|
>
|
|
|
|
|
<q-icon
|
|
|
|
|
name="mdi-trash-can-outline"
|
|
|
|
|
size="xs"
|
|
|
|
|
class="col-3"
|
|
|
|
|
:class="{
|
|
|
|
|
'app-text-negative':
|
|
|
|
|
props.row.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-${props.row.name}-status`"
|
|
|
|
|
dense
|
|
|
|
|
size="sm"
|
|
|
|
|
:label="
|
|
|
|
|
props.row.status !== 'INACTIVE'
|
|
|
|
|
? $t('switchOnLabel')
|
|
|
|
|
: $t('switchOffLabel')
|
|
|
|
|
"
|
|
|
|
|
@click="
|
|
|
|
|
async () => {
|
2024-07-25 10:49:43 +00:00
|
|
|
triggerChangeStatus(
|
|
|
|
|
props.row.id,
|
|
|
|
|
props.row.status,
|
|
|
|
|
);
|
2024-07-17 07:32:56 +00:00
|
|
|
}
|
|
|
|
|
"
|
|
|
|
|
:model-value="
|
|
|
|
|
props.row.status !== 'INACTIVE'
|
|
|
|
|
"
|
|
|
|
|
/>
|
|
|
|
|
</div>
|
|
|
|
|
</q-item-section>
|
|
|
|
|
</q-item>
|
|
|
|
|
</q-list>
|
|
|
|
|
</q-menu>
|
|
|
|
|
</q-btn>
|
|
|
|
|
</q-td>
|
|
|
|
|
</q-tr>
|
|
|
|
|
</template>
|
|
|
|
|
|
|
|
|
|
<template v-slot:item="props">
|
2024-07-25 13:17:40 +07:00
|
|
|
<div class="col-12 col-md-6 col-lg-4">
|
2024-07-17 07:32:56 +00:00
|
|
|
<ProductCardComponent
|
|
|
|
|
:isType="productMode === 'type'"
|
|
|
|
|
:count-product="props.row._count.product"
|
|
|
|
|
:count-type="props.row._count.type"
|
|
|
|
|
:count-service="props.row._count.service"
|
|
|
|
|
:title="props.row.name"
|
|
|
|
|
:subtitle="props.row.code"
|
|
|
|
|
:date="new Date(props.row.updatedAt)"
|
|
|
|
|
:status="props.row.status"
|
2024-07-31 14:34:51 +07:00
|
|
|
:id="`enter-${props.row.name}`"
|
|
|
|
|
:for="`enter-${props.row.name}`"
|
2024-07-17 07:32:56 +00:00
|
|
|
:isDisabled="props.row.status === 'INACTIVE'"
|
|
|
|
|
:color="
|
|
|
|
|
{
|
|
|
|
|
type: $q.dark.isActive
|
|
|
|
|
? 'var(--purple-7-hsl)'
|
|
|
|
|
: 'var(--violet-11-hsl)',
|
|
|
|
|
group: 'var(--pink-6-hsl)',
|
|
|
|
|
}[productMode] || 'var(--pink-6-hsl)'
|
|
|
|
|
"
|
|
|
|
|
@toggleStatus="
|
2024-07-25 10:49:43 +00:00
|
|
|
triggerChangeStatus(props.row.id, props.row.status)
|
2024-07-17 07:32:56 +00:00
|
|
|
"
|
|
|
|
|
@viewCard="
|
2024-07-12 13:35:15 +07:00
|
|
|
() => {
|
|
|
|
|
if (productMode === 'type') {
|
|
|
|
|
currentStatusProduct =
|
|
|
|
|
props.row.status === 'INACTIVE';
|
|
|
|
|
clearFormGroup();
|
|
|
|
|
currentIdType = props.row.id;
|
|
|
|
|
assignFormDataGroup(props.row);
|
|
|
|
|
isEdit = false;
|
|
|
|
|
drawerInfo = true;
|
|
|
|
|
}
|
|
|
|
|
if (productMode === 'group') {
|
|
|
|
|
currentStatusProduct =
|
|
|
|
|
props.row.status === 'INACTIVE';
|
|
|
|
|
clearFormGroup();
|
|
|
|
|
assignFormDataGroup(props.row);
|
|
|
|
|
isEdit = false;
|
2024-07-23 10:24:22 +07:00
|
|
|
currentIdGrop = props.row.id;
|
2024-07-12 13:35:15 +07:00
|
|
|
drawerInfo = true;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
"
|
2024-07-17 07:32:56 +00:00
|
|
|
@updateCard="
|
|
|
|
|
() => {
|
|
|
|
|
if (productMode === 'type') {
|
|
|
|
|
clearFormGroup();
|
|
|
|
|
currentIdType = props.row.id;
|
|
|
|
|
assignFormDataGroup(props.row);
|
|
|
|
|
isEdit = true;
|
|
|
|
|
drawerInfo = true;
|
|
|
|
|
}
|
|
|
|
|
if (productMode === 'group') {
|
|
|
|
|
clearFormGroup();
|
|
|
|
|
assignFormDataGroup(props.row);
|
|
|
|
|
isEdit = true;
|
2024-07-23 10:24:22 +07:00
|
|
|
currentIdGrop = props.row.id;
|
2024-07-17 07:32:56 +00:00
|
|
|
|
|
|
|
|
drawerInfo = true;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
"
|
|
|
|
|
@deleteCard="
|
|
|
|
|
() => {
|
|
|
|
|
if (productMode === 'type') {
|
|
|
|
|
deleteProductById(props.row.id);
|
|
|
|
|
}
|
|
|
|
|
if (productMode === 'group') {
|
|
|
|
|
deleteProductById(props.row.id);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
"
|
|
|
|
|
@on-click="
|
|
|
|
|
async () => {
|
|
|
|
|
filterStat.push(productMode);
|
|
|
|
|
if (productMode === 'type') {
|
2024-07-23 13:47:42 +07:00
|
|
|
await enterType(props.row.id, props.row.name);
|
2024-07-17 07:32:56 +00:00
|
|
|
}
|
|
|
|
|
if (productMode === 'group') {
|
2024-07-23 10:24:22 +07:00
|
|
|
await enterGroup(props.row.id, props.row.name);
|
2024-07-17 07:32:56 +00:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
"
|
2024-07-12 13:35:15 +07:00
|
|
|
/>
|
2024-07-17 07:32:56 +00:00
|
|
|
</div>
|
|
|
|
|
</template>
|
|
|
|
|
</q-table>
|
|
|
|
|
</div>
|
2024-07-12 13:35:15 +07:00
|
|
|
|
2024-07-17 07:32:56 +00:00
|
|
|
<div
|
|
|
|
|
v-if="productMode === 'group'"
|
|
|
|
|
class="row items-center justify-between q-px-md q-py-sm full-width"
|
|
|
|
|
>
|
|
|
|
|
<div class="col-4">
|
|
|
|
|
<div class="row items-center">
|
2024-07-18 09:10:51 +00:00
|
|
|
<div
|
|
|
|
|
class="app-text-muted"
|
|
|
|
|
style="width: 80px"
|
|
|
|
|
v-if="$q.screen.gt.sm"
|
|
|
|
|
>
|
2024-07-17 07:32:56 +00:00
|
|
|
{{ $t('showing') }}
|
|
|
|
|
</div>
|
|
|
|
|
<div>
|
|
|
|
|
<q-btn-dropdown
|
2024-07-12 13:35:15 +07:00
|
|
|
dense
|
2024-07-17 07:32:56 +00:00
|
|
|
unelevated
|
|
|
|
|
:label="pageSizeGroup"
|
|
|
|
|
class="bordered q-pl-md"
|
2024-07-12 13:35:15 +07:00
|
|
|
>
|
2024-07-17 07:32:56 +00:00
|
|
|
<q-list>
|
|
|
|
|
<q-item
|
|
|
|
|
v-for="v in [10, 30, 50, 100, 500, 1000]"
|
|
|
|
|
:key="v"
|
|
|
|
|
clickable
|
|
|
|
|
v-close-popup
|
|
|
|
|
@click="
|
|
|
|
|
async () => {
|
|
|
|
|
pageSizeGroup = v;
|
|
|
|
|
await fetchListGroups();
|
|
|
|
|
}
|
|
|
|
|
"
|
|
|
|
|
>
|
|
|
|
|
<q-item-section>
|
|
|
|
|
<q-item-label>{{ v }}</q-item-label>
|
|
|
|
|
</q-item-section>
|
|
|
|
|
</q-item>
|
|
|
|
|
</q-list>
|
|
|
|
|
</q-btn-dropdown>
|
|
|
|
|
</div>
|
|
|
|
|
</div>
|
|
|
|
|
</div>
|
2024-07-12 13:35:15 +07:00
|
|
|
|
2024-07-17 07:32:56 +00:00
|
|
|
<div class="col-4 row justify-center app-text-muted">
|
|
|
|
|
{{
|
|
|
|
|
$t('recordsPage', {
|
|
|
|
|
resultcurrentPage: productGroup?.length,
|
|
|
|
|
total: totalGroup,
|
|
|
|
|
})
|
|
|
|
|
}}
|
|
|
|
|
</div>
|
2024-07-12 13:35:15 +07:00
|
|
|
|
2024-07-17 07:32:56 +00:00
|
|
|
<div class="col-4 row justify-end">
|
|
|
|
|
<PaginationComponent
|
|
|
|
|
v-model:current-page="currentPageGroup"
|
|
|
|
|
v-model:max-page="maxPageGroup"
|
|
|
|
|
:fetch-data="
|
|
|
|
|
async () => {
|
|
|
|
|
await fetchListGroups();
|
|
|
|
|
flowStore.rotate();
|
|
|
|
|
}
|
|
|
|
|
"
|
|
|
|
|
/>
|
|
|
|
|
</div>
|
|
|
|
|
</div>
|
|
|
|
|
|
|
|
|
|
<div
|
|
|
|
|
v-if="productMode === 'type'"
|
|
|
|
|
class="row justify-between items-center q-px-md q-py-sm full-width"
|
|
|
|
|
>
|
|
|
|
|
<div class="col-4">
|
|
|
|
|
<div class="row items-center">
|
2024-07-18 09:10:51 +00:00
|
|
|
<div
|
|
|
|
|
class="app-text-muted"
|
|
|
|
|
style="width: 80px"
|
|
|
|
|
v-if="$q.screen.gt.sm"
|
|
|
|
|
>
|
2024-07-17 07:32:56 +00:00
|
|
|
{{ $t('showing') }}
|
|
|
|
|
</div>
|
|
|
|
|
<div>
|
|
|
|
|
<q-btn-dropdown
|
|
|
|
|
dense
|
|
|
|
|
unelevated
|
|
|
|
|
:label="pageSizeType"
|
|
|
|
|
class="bordered q-pl-md"
|
|
|
|
|
>
|
|
|
|
|
<q-list>
|
|
|
|
|
<q-item
|
|
|
|
|
v-for="v in [10, 30, 50, 100, 500, 1000]"
|
|
|
|
|
:key="v"
|
|
|
|
|
clickable
|
|
|
|
|
v-close-popup
|
|
|
|
|
@click="
|
|
|
|
|
async () => {
|
|
|
|
|
pageSizeType = v;
|
|
|
|
|
await fetchListType();
|
|
|
|
|
}
|
|
|
|
|
"
|
|
|
|
|
>
|
|
|
|
|
<q-item-section>
|
|
|
|
|
<q-item-label>{{ v }}</q-item-label>
|
|
|
|
|
</q-item-section>
|
|
|
|
|
</q-item>
|
|
|
|
|
</q-list>
|
|
|
|
|
</q-btn-dropdown>
|
|
|
|
|
</div>
|
|
|
|
|
</div>
|
|
|
|
|
</div>
|
|
|
|
|
|
|
|
|
|
<div class="col-4 row justify-center app-text-muted">
|
|
|
|
|
{{
|
|
|
|
|
$t('recordsPage', {
|
|
|
|
|
resultcurrentPage: productType?.length,
|
|
|
|
|
total: totalType,
|
|
|
|
|
})
|
|
|
|
|
}}
|
|
|
|
|
</div>
|
|
|
|
|
<div class="col-4 row justify-end">
|
|
|
|
|
<PaginationComponent
|
|
|
|
|
v-model:current-page="currentPageType"
|
|
|
|
|
v-model:max-page="maxPageType"
|
|
|
|
|
:fetch-data="
|
|
|
|
|
async () => {
|
|
|
|
|
await fetchListType();
|
|
|
|
|
flowStore.rotate();
|
|
|
|
|
}
|
|
|
|
|
"
|
|
|
|
|
/>
|
|
|
|
|
</div>
|
|
|
|
|
</div>
|
|
|
|
|
</template>
|
|
|
|
|
</div>
|
|
|
|
|
|
|
|
|
|
<!-- product/service -->
|
|
|
|
|
<div
|
|
|
|
|
v-else-if="productMode === 'service'"
|
|
|
|
|
class="surface-1 col column no-wrap"
|
|
|
|
|
style="overflow: hidden"
|
|
|
|
|
>
|
|
|
|
|
<div
|
|
|
|
|
class="row justify-between items-center q-px-md q-py-sm surface-3 bordered-b"
|
|
|
|
|
>
|
|
|
|
|
<q-input
|
2024-07-26 11:05:07 +07:00
|
|
|
lazy-rules="ondemand"
|
2024-07-17 07:32:56 +00:00
|
|
|
:class="{ 'col-12': $q.screen.lt.md }"
|
|
|
|
|
outlined
|
|
|
|
|
dense
|
|
|
|
|
unelavated
|
|
|
|
|
:label="$t('search')"
|
|
|
|
|
:bg-color="$q.dark.isActive ? 'dark' : 'white'"
|
|
|
|
|
v-model="inputSearchProductAndService"
|
|
|
|
|
debounce="250"
|
|
|
|
|
>
|
|
|
|
|
<template v-slot:prepend>
|
|
|
|
|
<q-icon name="mdi-magnify" />
|
|
|
|
|
</template>
|
|
|
|
|
</q-input>
|
2024-07-10 11:54:22 +07:00
|
|
|
|
2024-07-17 07:32:56 +00:00
|
|
|
<div
|
|
|
|
|
class="row col-12 col-md-6"
|
|
|
|
|
:class="{ 'q-pt-xs': $q.screen.lt.md }"
|
|
|
|
|
style="white-space: nowrap"
|
|
|
|
|
>
|
2024-07-24 06:40:03 +00:00
|
|
|
<q-select
|
2024-07-30 16:18:37 +07:00
|
|
|
:for="'field-select-status'"
|
2024-07-26 11:05:07 +07:00
|
|
|
lazy-rules="ondemand"
|
2024-07-24 06:40:03 +00:00
|
|
|
v-model="currentStatus"
|
|
|
|
|
outlined
|
|
|
|
|
dense
|
|
|
|
|
option-value="value"
|
|
|
|
|
:hide-dropdown-icon="$q.screen.lt.sm"
|
|
|
|
|
option-label="label"
|
2024-07-30 04:17:51 +00:00
|
|
|
:class="{ 'offset-md-5': modeView }"
|
2024-07-24 06:40:03 +00:00
|
|
|
class="col"
|
|
|
|
|
map-options
|
|
|
|
|
emit-value
|
|
|
|
|
:options="[
|
|
|
|
|
{ label: $t('all'), value: 'All' },
|
|
|
|
|
{ label: $t('statusACTIVE'), value: 'ACTIVE' },
|
|
|
|
|
{
|
|
|
|
|
label: $t('statusINACTIVE'),
|
|
|
|
|
value: 'INACTIVE',
|
|
|
|
|
},
|
|
|
|
|
]"
|
|
|
|
|
@update:model-value="fetchStatus()"
|
|
|
|
|
></q-select>
|
2024-07-17 07:32:56 +00:00
|
|
|
|
|
|
|
|
<q-select
|
2024-07-26 11:05:07 +07:00
|
|
|
lazy-rules="ondemand"
|
2024-07-17 07:32:56 +00:00
|
|
|
v-if="modeView === false"
|
2024-07-18 09:10:51 +00:00
|
|
|
:hide-dropdown-icon="$q.screen.lt.sm"
|
2024-07-17 07:32:56 +00:00
|
|
|
id="select-field"
|
|
|
|
|
for="select-field"
|
2024-07-18 09:10:51 +00:00
|
|
|
class="col q-ml-sm"
|
2024-07-17 07:32:56 +00:00
|
|
|
:options="
|
|
|
|
|
{
|
|
|
|
|
product: tbControl.product.fieldDisplay,
|
|
|
|
|
service: tbControl.service.fieldDisplay,
|
|
|
|
|
}[productAndServiceTab].map((x) => ({
|
|
|
|
|
label: $t(x),
|
|
|
|
|
value: x,
|
|
|
|
|
}))
|
|
|
|
|
"
|
|
|
|
|
:display-value="$t('displayField')"
|
|
|
|
|
:model-value="
|
|
|
|
|
{
|
|
|
|
|
product: tbControl.product.fieldSelected,
|
|
|
|
|
service: tbControl.service.fieldSelected,
|
|
|
|
|
}[productAndServiceTab]
|
|
|
|
|
"
|
|
|
|
|
@update:model-value="
|
|
|
|
|
(v) => (tbControl[productAndServiceTab].fieldSelected = v)
|
|
|
|
|
"
|
|
|
|
|
option-label="label"
|
|
|
|
|
option-value="value"
|
|
|
|
|
map-options
|
|
|
|
|
emit-value
|
|
|
|
|
outlined
|
|
|
|
|
multiple
|
|
|
|
|
dense
|
|
|
|
|
/>
|
2024-07-09 14:38:22 +07:00
|
|
|
|
2024-07-17 07:32:56 +00:00
|
|
|
<q-btn-toggle
|
|
|
|
|
v-model="modeView"
|
|
|
|
|
id="btn-mode"
|
|
|
|
|
dense
|
2024-07-18 09:10:51 +00:00
|
|
|
class="no-shadow bordered rounded surface-1 q-ml-sm"
|
2024-07-17 07:32:56 +00:00
|
|
|
:toggle-color="$q.dark.isActive ? 'grey-9' : 'grey-2'"
|
|
|
|
|
size="xs"
|
|
|
|
|
:options="[
|
|
|
|
|
{ value: true, slot: 'folder' },
|
|
|
|
|
{ value: false, slot: 'list' },
|
|
|
|
|
]"
|
|
|
|
|
>
|
|
|
|
|
<template v-slot:folder>
|
|
|
|
|
<q-icon
|
|
|
|
|
name="mdi-view-grid-outline"
|
|
|
|
|
size="16px"
|
|
|
|
|
class="q-px-sm q-py-xs rounded"
|
|
|
|
|
:style="{
|
|
|
|
|
color: $q.dark.isActive
|
|
|
|
|
? modeView
|
|
|
|
|
? '#C9D3DB '
|
|
|
|
|
: '#787B7C'
|
|
|
|
|
: modeView
|
|
|
|
|
? '#787B7C'
|
|
|
|
|
: '#C9D3DB',
|
|
|
|
|
}"
|
|
|
|
|
/>
|
|
|
|
|
</template>
|
|
|
|
|
<template v-slot:list>
|
|
|
|
|
<q-icon
|
|
|
|
|
name="mdi-format-list-bulleted"
|
|
|
|
|
class="q-px-sm q-py-xs rounded"
|
|
|
|
|
size="16px"
|
|
|
|
|
:style="{
|
|
|
|
|
color: $q.dark.isActive
|
|
|
|
|
? modeView === false
|
|
|
|
|
? '#C9D3DB'
|
|
|
|
|
: '#787B7C'
|
|
|
|
|
: modeView === false
|
|
|
|
|
? '#787B7C'
|
|
|
|
|
: '#C9D3DB',
|
|
|
|
|
}"
|
2024-07-12 13:35:15 +07:00
|
|
|
/>
|
2024-07-17 07:32:56 +00:00
|
|
|
</template>
|
|
|
|
|
</q-btn-toggle>
|
|
|
|
|
</div>
|
|
|
|
|
</div>
|
|
|
|
|
|
|
|
|
|
<div class="surface-2 bordered-b q-px-md">
|
|
|
|
|
<q-tabs
|
|
|
|
|
dense
|
|
|
|
|
v-model="productAndServiceTab"
|
|
|
|
|
active-color="info"
|
|
|
|
|
align="left"
|
|
|
|
|
>
|
|
|
|
|
<q-tab
|
2024-07-19 14:04:02 +07:00
|
|
|
id="tab-service"
|
2024-07-17 07:32:56 +00:00
|
|
|
name="service"
|
|
|
|
|
@click="
|
|
|
|
|
async () => {
|
|
|
|
|
currentPageServiceAndProduct = 1;
|
|
|
|
|
inputSearchProductAndService = '';
|
|
|
|
|
currentStatus = 'All';
|
|
|
|
|
// await fetchListOfService();
|
|
|
|
|
flowStore.rotate();
|
|
|
|
|
}
|
|
|
|
|
"
|
|
|
|
|
>
|
|
|
|
|
<div
|
|
|
|
|
class="row"
|
|
|
|
|
:class="
|
|
|
|
|
productAndServiceTab === 'service'
|
|
|
|
|
? 'text-bold'
|
|
|
|
|
: 'app-text-muted'
|
|
|
|
|
"
|
|
|
|
|
>
|
|
|
|
|
{{ $t('service') }}
|
2024-07-12 13:35:15 +07:00
|
|
|
</div>
|
2024-07-17 07:32:56 +00:00
|
|
|
</q-tab>
|
|
|
|
|
<q-tab
|
2024-07-19 14:04:02 +07:00
|
|
|
id="tab-product"
|
2024-07-17 07:32:56 +00:00
|
|
|
name="product"
|
|
|
|
|
@click="
|
|
|
|
|
async () => {
|
|
|
|
|
currentPageServiceAndProduct = 1;
|
|
|
|
|
inputSearchProductAndService = '';
|
|
|
|
|
currentStatus = 'All';
|
|
|
|
|
// await fetchListOfProduct();
|
|
|
|
|
flowStore.rotate();
|
|
|
|
|
}
|
|
|
|
|
"
|
|
|
|
|
>
|
|
|
|
|
<div
|
|
|
|
|
class="row"
|
|
|
|
|
:class="
|
|
|
|
|
productAndServiceTab === 'product'
|
|
|
|
|
? 'text-bold'
|
|
|
|
|
: 'app-text-muted'
|
|
|
|
|
"
|
|
|
|
|
>
|
|
|
|
|
{{ $t('product') }}
|
|
|
|
|
</div>
|
|
|
|
|
</q-tab>
|
|
|
|
|
</q-tabs>
|
2024-07-12 13:35:15 +07:00
|
|
|
</div>
|
2024-07-09 14:38:22 +07:00
|
|
|
|
2024-07-12 15:26:13 +07:00
|
|
|
<div
|
2024-07-17 07:32:56 +00:00
|
|
|
v-if="
|
|
|
|
|
(productAndServiceTab === 'product' &&
|
|
|
|
|
product?.length === 0) ||
|
|
|
|
|
(productAndServiceTab === 'service' && service?.length === 0)
|
|
|
|
|
"
|
|
|
|
|
class="flex justify-center items-center surface-2 col"
|
2024-07-12 15:26:13 +07:00
|
|
|
>
|
2024-07-17 07:32:56 +00:00
|
|
|
<NoData :not-found="!!inputSearchProductAndService" />
|
|
|
|
|
</div>
|
|
|
|
|
<!-- tab -->
|
|
|
|
|
<template v-else>
|
|
|
|
|
<div
|
|
|
|
|
class="flex scroll full-width q-pa-md surface-2 column col"
|
|
|
|
|
>
|
|
|
|
|
<q-table
|
|
|
|
|
class="full-width"
|
|
|
|
|
flat
|
|
|
|
|
bordered
|
|
|
|
|
:rows-per-page-options="[0]"
|
|
|
|
|
:rows="{ product, service }[productAndServiceTab] || []"
|
|
|
|
|
:columns="
|
|
|
|
|
{
|
|
|
|
|
product: tbColumn.product,
|
|
|
|
|
service: tbColumn.service,
|
|
|
|
|
}[productAndServiceTab]
|
|
|
|
|
"
|
|
|
|
|
:grid="modeView"
|
|
|
|
|
card-container-class="row q-col-gutter-md"
|
|
|
|
|
row-key="name"
|
|
|
|
|
hide-pagination
|
|
|
|
|
:visible-columns="
|
|
|
|
|
{
|
|
|
|
|
product: tbControl.product.fieldSelected,
|
|
|
|
|
service: tbControl.service.fieldSelected,
|
|
|
|
|
}[productAndServiceTab]
|
|
|
|
|
"
|
|
|
|
|
>
|
|
|
|
|
<template v-slot:header="props">
|
2024-07-31 06:18:52 +00:00
|
|
|
<q-tr
|
|
|
|
|
style="background-color: hsla(var(--info-bg) / 0.07)"
|
|
|
|
|
:props="props"
|
|
|
|
|
>
|
2024-07-17 07:32:56 +00:00
|
|
|
<q-th
|
|
|
|
|
v-for="col in props.cols"
|
|
|
|
|
:key="col.name"
|
|
|
|
|
:props="props"
|
|
|
|
|
>
|
|
|
|
|
{{ $t(col.label) }}
|
|
|
|
|
</q-th>
|
|
|
|
|
<q-th auto-width />
|
|
|
|
|
</q-tr>
|
|
|
|
|
</template>
|
|
|
|
|
|
|
|
|
|
<template v-slot:body="props">
|
|
|
|
|
<q-tr
|
|
|
|
|
:class="{
|
|
|
|
|
'app-text-muted': props.row.status === 'INACTIVE',
|
|
|
|
|
}"
|
|
|
|
|
:props="props"
|
2024-07-12 15:26:13 +07:00
|
|
|
>
|
2024-07-17 07:32:56 +00:00
|
|
|
<q-td
|
|
|
|
|
v-if="
|
|
|
|
|
{
|
|
|
|
|
product: tbControl.product.fieldSelected,
|
|
|
|
|
|
|
|
|
|
service: tbControl.service.fieldSelected,
|
|
|
|
|
}[productAndServiceTab].includes(
|
|
|
|
|
{
|
|
|
|
|
product: 'productName',
|
|
|
|
|
service: 'serviceName',
|
|
|
|
|
}[productAndServiceTab],
|
|
|
|
|
)
|
|
|
|
|
"
|
|
|
|
|
>
|
|
|
|
|
<div class="row items-center">
|
|
|
|
|
<div
|
|
|
|
|
:class="{
|
|
|
|
|
'status-active':
|
|
|
|
|
props.row.status !== 'INACTIVE',
|
|
|
|
|
'status-inactive':
|
|
|
|
|
props.row.status === 'INACTIVE',
|
|
|
|
|
}"
|
|
|
|
|
style="
|
|
|
|
|
width: 50px;
|
|
|
|
|
display: flex;
|
|
|
|
|
margin-bottom: var(--size-2);
|
|
|
|
|
"
|
|
|
|
|
>
|
|
|
|
|
<div
|
|
|
|
|
class="table__icon"
|
|
|
|
|
:class="`icon-color-${productAndServiceTab === 'product' ? 'green' : 'orange'}`"
|
|
|
|
|
>
|
|
|
|
|
<q-icon
|
|
|
|
|
size="md"
|
|
|
|
|
style="scale: 0.8"
|
|
|
|
|
:name="
|
|
|
|
|
productAndServiceTab === 'product'
|
|
|
|
|
? 'mdi-folder'
|
|
|
|
|
: 'mdi-server-network'
|
|
|
|
|
"
|
|
|
|
|
/>
|
|
|
|
|
</div>
|
|
|
|
|
</div>
|
|
|
|
|
<div class="col">
|
|
|
|
|
<div class="col">{{ props.row.name }}</div>
|
|
|
|
|
<div class="col app-text-muted">
|
|
|
|
|
{{ props.row.code }}
|
|
|
|
|
</div>
|
|
|
|
|
</div>
|
|
|
|
|
</div>
|
|
|
|
|
</q-td>
|
|
|
|
|
<q-td
|
|
|
|
|
v-if="
|
|
|
|
|
{
|
|
|
|
|
product: tbControl.product.fieldSelected,
|
|
|
|
|
service: tbControl.service.fieldSelected,
|
|
|
|
|
}[productAndServiceTab].includes(
|
|
|
|
|
{
|
|
|
|
|
product: 'productDetail',
|
|
|
|
|
service: 'serviceDetail',
|
|
|
|
|
}[productAndServiceTab],
|
|
|
|
|
)
|
|
|
|
|
"
|
|
|
|
|
>
|
|
|
|
|
{{ props.row.detail }}
|
|
|
|
|
</q-td>
|
|
|
|
|
<q-td
|
|
|
|
|
v-if="
|
|
|
|
|
{
|
|
|
|
|
product: tbControl.product.fieldSelected,
|
|
|
|
|
service: tbControl.service.fieldSelected,
|
|
|
|
|
}[productAndServiceTab].includes(
|
|
|
|
|
{
|
|
|
|
|
product: 'productProcessingTime',
|
|
|
|
|
service: 'serviceWorkTotal',
|
|
|
|
|
}[productAndServiceTab],
|
|
|
|
|
)
|
|
|
|
|
"
|
|
|
|
|
>
|
|
|
|
|
{{
|
|
|
|
|
{
|
|
|
|
|
product: props.row.process,
|
|
|
|
|
service: props.row.work?.length,
|
|
|
|
|
}[productAndServiceTab]
|
|
|
|
|
}}
|
|
|
|
|
</q-td>
|
|
|
|
|
<q-td
|
|
|
|
|
v-if="
|
|
|
|
|
{
|
|
|
|
|
product: tbControl.product.fieldSelected,
|
|
|
|
|
service: tbControl.service.fieldSelected,
|
|
|
|
|
}[productAndServiceTab].includes(
|
|
|
|
|
{
|
|
|
|
|
product: 'priceInformation',
|
|
|
|
|
service: 'empty',
|
|
|
|
|
}[productAndServiceTab],
|
|
|
|
|
)
|
|
|
|
|
"
|
|
|
|
|
>
|
|
|
|
|
<div
|
|
|
|
|
class="row tags-color-green q-gutter-x-md no-wrap items-center text-right"
|
|
|
|
|
>
|
|
|
|
|
<div
|
|
|
|
|
class="tags col-3 column ellipsis-2-lines"
|
|
|
|
|
style="min-width: 50px"
|
|
|
|
|
>
|
|
|
|
|
<div class="col-4">{{ $t('salePrice') }}</div>
|
|
|
|
|
<div class="col-4 text-weight-bold">
|
|
|
|
|
{{
|
|
|
|
|
formatNumberDecimal(props.row.price || 0, 2)
|
|
|
|
|
}}
|
|
|
|
|
</div>
|
|
|
|
|
</div>
|
|
|
|
|
<div
|
|
|
|
|
class="tags col-3 column ellipsis-2-lines"
|
|
|
|
|
style="min-width: 50px"
|
|
|
|
|
>
|
|
|
|
|
<div class="col-4">{{ $t('agentPrice') }}</div>
|
|
|
|
|
<div class="col-4 text-weight-bold">
|
|
|
|
|
{{
|
|
|
|
|
formatNumberDecimal(
|
|
|
|
|
props.row.agentPrice || 0,
|
|
|
|
|
2,
|
|
|
|
|
)
|
|
|
|
|
}}
|
|
|
|
|
</div>
|
|
|
|
|
</div>
|
|
|
|
|
<div
|
|
|
|
|
class="tags col-3 column ellipsis-2-lines"
|
|
|
|
|
style="min-width: 50px"
|
|
|
|
|
>
|
|
|
|
|
<div class="col-4">
|
|
|
|
|
{{ $t('processingPrice') }}
|
|
|
|
|
</div>
|
|
|
|
|
<div class="col-4 text-weight-bold">
|
|
|
|
|
{{
|
|
|
|
|
formatNumberDecimal(
|
|
|
|
|
props.row.serviceCharge || 0,
|
|
|
|
|
2,
|
|
|
|
|
)
|
|
|
|
|
}}
|
|
|
|
|
</div>
|
|
|
|
|
</div>
|
|
|
|
|
</div>
|
|
|
|
|
</q-td>
|
|
|
|
|
|
|
|
|
|
<q-td
|
|
|
|
|
v-if="
|
|
|
|
|
{
|
|
|
|
|
product: tbControl.product.fieldSelected,
|
|
|
|
|
service: tbControl.service.fieldSelected,
|
|
|
|
|
}[productAndServiceTab].includes('createdAt')
|
|
|
|
|
"
|
|
|
|
|
>
|
|
|
|
|
{{ dateFormat(props.row.createdAt) }}
|
|
|
|
|
</q-td>
|
|
|
|
|
<q-td>
|
|
|
|
|
<q-btn
|
|
|
|
|
icon="mdi-eye-outline"
|
|
|
|
|
:id="`btn-eye-${props.row.name}`"
|
|
|
|
|
size="sm"
|
|
|
|
|
dense
|
|
|
|
|
round
|
|
|
|
|
flat
|
|
|
|
|
@click.stop="
|
2024-07-12 15:26:13 +07:00
|
|
|
async () => {
|
2024-07-30 05:29:36 +00:00
|
|
|
await fetchListOfOptionBranch();
|
2024-07-17 07:32:56 +00:00
|
|
|
if (props.row.type === 'product') {
|
|
|
|
|
currentIdProduct = props.row.id;
|
|
|
|
|
assignFormDataProduct(props.row);
|
|
|
|
|
dialogProductEdit = true;
|
|
|
|
|
}
|
|
|
|
|
if (props.row.type === 'service') {
|
|
|
|
|
currentIdService = props.row.id;
|
|
|
|
|
infoServiceEdit = false;
|
|
|
|
|
assignFormDataProductService(props.row.id);
|
|
|
|
|
dialogServiceEdit = true;
|
|
|
|
|
}
|
2024-07-12 15:26:13 +07:00
|
|
|
}
|
|
|
|
|
"
|
2024-07-17 07:32:56 +00:00
|
|
|
/>
|
|
|
|
|
|
|
|
|
|
<q-btn
|
|
|
|
|
icon="mdi-dots-vertical"
|
|
|
|
|
:id="`btn-dots-${props.row.name}`"
|
|
|
|
|
size="sm"
|
|
|
|
|
dense
|
|
|
|
|
round
|
|
|
|
|
flat
|
|
|
|
|
@click.stop
|
2024-07-12 15:26:13 +07:00
|
|
|
>
|
2024-07-17 07:32:56 +00:00
|
|
|
<q-menu class="bordered">
|
|
|
|
|
<q-list v-close-popup>
|
|
|
|
|
<q-item
|
|
|
|
|
:id="`view-detail-btn-${props.row.name}-view`"
|
|
|
|
|
@click.stop="
|
|
|
|
|
async () => {
|
2024-07-30 05:29:36 +00:00
|
|
|
await fetchListOfOptionBranch();
|
2024-07-17 07:32:56 +00:00
|
|
|
if (props.row.type === 'product') {
|
|
|
|
|
currentIdProduct = props.row.id;
|
|
|
|
|
assignFormDataProduct(props.row);
|
|
|
|
|
dialogProductEdit = true;
|
|
|
|
|
}
|
|
|
|
|
if (props.row.type === 'service') {
|
|
|
|
|
currentIdService = props.row.id;
|
|
|
|
|
infoServiceEdit = false;
|
|
|
|
|
assignFormDataProductService(
|
|
|
|
|
props.row.id,
|
|
|
|
|
);
|
|
|
|
|
dialogServiceEdit = true;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
"
|
|
|
|
|
v-close-popup
|
|
|
|
|
clickable
|
|
|
|
|
dense
|
|
|
|
|
class="row q-py-sm"
|
|
|
|
|
style="white-space: nowrap"
|
|
|
|
|
>
|
|
|
|
|
<q-icon
|
|
|
|
|
name="mdi-eye-outline"
|
|
|
|
|
class="col-3"
|
|
|
|
|
size="xs"
|
|
|
|
|
style="color: hsl(var(--green-6-hsl))"
|
|
|
|
|
/>
|
|
|
|
|
<span class="col-9 q-px-md flex items-center">
|
|
|
|
|
{{ $t('viewDetail') }}
|
|
|
|
|
</span>
|
|
|
|
|
</q-item>
|
|
|
|
|
|
|
|
|
|
<q-item
|
|
|
|
|
:id="`view-detail-btn-${props.row.name}-edit`"
|
|
|
|
|
v-close-popup
|
|
|
|
|
clickable
|
|
|
|
|
dense
|
|
|
|
|
class="row q-py-sm"
|
|
|
|
|
style="white-space: nowrap"
|
|
|
|
|
@click="
|
|
|
|
|
async () => {
|
2024-07-30 05:29:36 +00:00
|
|
|
await fetchListOfOptionBranch();
|
2024-07-17 07:32:56 +00:00
|
|
|
if (props.row.type === 'product') {
|
|
|
|
|
currentIdProduct = props.row.id;
|
|
|
|
|
infoProductEdit = true;
|
|
|
|
|
assignFormDataProduct(props.row);
|
|
|
|
|
dialogProductEdit = true;
|
|
|
|
|
}
|
|
|
|
|
if (props.row.type === 'service') {
|
|
|
|
|
currentIdService = props.row.id;
|
|
|
|
|
infoServiceEdit = true;
|
|
|
|
|
assignFormDataProductService(
|
|
|
|
|
props.row.id,
|
|
|
|
|
);
|
|
|
|
|
dialogServiceEdit = true;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
"
|
|
|
|
|
>
|
|
|
|
|
<q-icon
|
|
|
|
|
name="mdi-pencil-outline"
|
|
|
|
|
class="col-3"
|
|
|
|
|
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
|
|
|
|
|
:id="`view-detail-btn-${props.row.name}-delete`"
|
|
|
|
|
dense
|
|
|
|
|
v-close-popup
|
|
|
|
|
:clickable="props.row.status === 'CREATED'"
|
|
|
|
|
class="row"
|
|
|
|
|
:class="{
|
|
|
|
|
'surface-3': props.row.status !== 'CREATED',
|
|
|
|
|
'app-text-muted':
|
|
|
|
|
props.row.status !== 'CREATED',
|
|
|
|
|
}"
|
|
|
|
|
style="white-space: nowrap"
|
|
|
|
|
@click="
|
|
|
|
|
() => {
|
|
|
|
|
if (props.row.type === 'product') {
|
|
|
|
|
deleteTypeOfProduct(props.row.id);
|
|
|
|
|
}
|
|
|
|
|
if (props.row.type === 'service') {
|
|
|
|
|
deleteServiceById(props.row.id);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
"
|
|
|
|
|
>
|
|
|
|
|
<q-icon
|
|
|
|
|
name="mdi-trash-can-outline"
|
|
|
|
|
size="xs"
|
|
|
|
|
class="col-3"
|
|
|
|
|
:class="{
|
|
|
|
|
'app-text-negative':
|
|
|
|
|
props.row.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-${props.row.name}-status`"
|
|
|
|
|
dense
|
|
|
|
|
size="sm"
|
|
|
|
|
:label="
|
|
|
|
|
props.row.status !== 'INACTIVE'
|
|
|
|
|
? $t('switchOnLabel')
|
|
|
|
|
: $t('switchOffLabel')
|
|
|
|
|
"
|
|
|
|
|
@click="
|
|
|
|
|
() => {
|
2024-07-25 10:49:43 +00:00
|
|
|
triggerChangeStatus(
|
|
|
|
|
props.row.id,
|
|
|
|
|
props.row.status,
|
|
|
|
|
props.row.type,
|
|
|
|
|
);
|
2024-07-17 07:32:56 +00:00
|
|
|
}
|
|
|
|
|
"
|
|
|
|
|
:model-value="
|
|
|
|
|
props.row.status === 'CREATED' ||
|
|
|
|
|
props.row.status === 'ACTIVE'
|
|
|
|
|
"
|
|
|
|
|
/>
|
|
|
|
|
</div>
|
|
|
|
|
</q-item-section>
|
|
|
|
|
</q-item>
|
|
|
|
|
</q-list>
|
|
|
|
|
</q-menu>
|
|
|
|
|
</q-btn>
|
|
|
|
|
</q-td>
|
|
|
|
|
</q-tr>
|
|
|
|
|
</template>
|
|
|
|
|
|
|
|
|
|
<template v-slot:item="{ row }">
|
|
|
|
|
<div class="col-12 col-md-6 col-lg-4">
|
|
|
|
|
<TotalProductCardComponent
|
|
|
|
|
:data="row"
|
|
|
|
|
:key="row.id"
|
|
|
|
|
:title="row.name"
|
|
|
|
|
:isDisabled="row.status === 'INACTIVE' ? true : false"
|
|
|
|
|
@toggleStatus="
|
|
|
|
|
() => {
|
2024-07-25 10:49:43 +00:00
|
|
|
triggerChangeStatus(row.id, row.status, row.type);
|
2024-07-17 07:32:56 +00:00
|
|
|
}
|
|
|
|
|
"
|
|
|
|
|
@menuViewDetail="
|
|
|
|
|
async () => {
|
2024-07-30 05:29:36 +00:00
|
|
|
await fetchListOfOptionBranch();
|
2024-07-17 07:32:56 +00:00
|
|
|
if (row.type === 'product') {
|
|
|
|
|
currentIdProduct = row.id;
|
|
|
|
|
assignFormDataProduct(row);
|
|
|
|
|
dialogProductEdit = true;
|
|
|
|
|
}
|
|
|
|
|
if (row.type === 'service') {
|
|
|
|
|
currentIdService = row.id;
|
|
|
|
|
infoServiceEdit = false;
|
|
|
|
|
assignFormDataProductService(row.id);
|
|
|
|
|
dialogServiceEdit = true;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
"
|
|
|
|
|
@menuEdit="
|
|
|
|
|
async () => {
|
2024-07-30 05:29:36 +00:00
|
|
|
await fetchListOfOptionBranch();
|
2024-07-17 07:32:56 +00:00
|
|
|
if (row.type === 'product') {
|
|
|
|
|
currentIdProduct = row.id;
|
|
|
|
|
infoProductEdit = true;
|
|
|
|
|
assignFormDataProduct(row);
|
|
|
|
|
dialogProductEdit = true;
|
|
|
|
|
}
|
|
|
|
|
if (row.type === 'service') {
|
|
|
|
|
currentIdService = row.id;
|
|
|
|
|
infoServiceEdit = true;
|
|
|
|
|
assignFormDataProductService(row.id);
|
|
|
|
|
dialogServiceEdit = true;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
"
|
|
|
|
|
/>
|
|
|
|
|
</div>
|
|
|
|
|
</template>
|
|
|
|
|
</q-table>
|
2024-07-12 15:26:13 +07:00
|
|
|
</div>
|
2024-07-17 07:32:56 +00:00
|
|
|
</template>
|
|
|
|
|
<!-- footer -->
|
2024-07-12 15:26:13 +07:00
|
|
|
<div
|
2024-07-17 07:32:56 +00:00
|
|
|
class="row items-center justify-between q-py-sm q-px-md surface-2"
|
2024-07-12 15:26:13 +07:00
|
|
|
>
|
|
|
|
|
<div class="col-4">
|
|
|
|
|
<div class="row items-center">
|
2024-07-18 09:10:51 +00:00
|
|
|
<div
|
|
|
|
|
class="app-text-muted"
|
|
|
|
|
style="width: 80px"
|
|
|
|
|
v-if="$q.screen.gt.sm"
|
|
|
|
|
>
|
2024-07-12 15:26:13 +07:00
|
|
|
{{ $t('showing') }}
|
|
|
|
|
</div>
|
|
|
|
|
<div>
|
|
|
|
|
<q-btn-dropdown
|
|
|
|
|
dense
|
|
|
|
|
unelevated
|
2024-07-17 07:32:56 +00:00
|
|
|
:label="pageSizeServiceAndProduct"
|
2024-07-12 15:26:13 +07:00
|
|
|
class="bordered q-pl-md"
|
|
|
|
|
>
|
|
|
|
|
<q-list>
|
|
|
|
|
<q-item
|
2024-07-23 14:01:30 +07:00
|
|
|
v-for="v in [10, 30, 50, 100, 500, 1000]"
|
2024-07-12 15:26:13 +07:00
|
|
|
:key="v"
|
|
|
|
|
clickable
|
|
|
|
|
v-close-popup
|
|
|
|
|
@click="
|
|
|
|
|
async () => {
|
2024-07-17 07:32:56 +00:00
|
|
|
pageSizeServiceAndProduct = v;
|
2024-07-23 13:47:42 +07:00
|
|
|
|
|
|
|
|
if (productAndServiceTab === 'product') {
|
|
|
|
|
await fetchListOfProduct();
|
|
|
|
|
}
|
|
|
|
|
if (productAndServiceTab === 'service') {
|
|
|
|
|
await fetchListOfService();
|
|
|
|
|
}
|
2024-07-12 15:26:13 +07:00
|
|
|
}
|
|
|
|
|
"
|
|
|
|
|
>
|
|
|
|
|
<q-item-section>
|
|
|
|
|
<q-item-label>{{ v }}</q-item-label>
|
|
|
|
|
</q-item-section>
|
|
|
|
|
</q-item>
|
|
|
|
|
</q-list>
|
|
|
|
|
</q-btn-dropdown>
|
|
|
|
|
</div>
|
2024-07-12 13:35:15 +07:00
|
|
|
</div>
|
2024-07-04 14:55:09 +07:00
|
|
|
</div>
|
2024-07-12 13:35:15 +07:00
|
|
|
|
2024-07-12 15:26:13 +07:00
|
|
|
<div class="col-4 row justify-center app-text-muted">
|
|
|
|
|
{{
|
|
|
|
|
$t('recordsPage', {
|
2024-07-17 07:32:56 +00:00
|
|
|
resultcurrentPage:
|
|
|
|
|
productAndServiceTab === 'product'
|
|
|
|
|
? product?.length
|
|
|
|
|
: service?.length,
|
|
|
|
|
total: total,
|
2024-07-12 15:26:13 +07:00
|
|
|
})
|
|
|
|
|
}}
|
|
|
|
|
</div>
|
|
|
|
|
<div class="col-4 row justify-end">
|
|
|
|
|
<PaginationComponent
|
2024-07-17 07:32:56 +00:00
|
|
|
v-model:current-page="currentPageServiceAndProduct"
|
|
|
|
|
v-model:max-page="maxPageServiceAndProduct"
|
2024-07-12 15:26:13 +07:00
|
|
|
:fetch-data="
|
|
|
|
|
async () => {
|
2024-07-17 07:32:56 +00:00
|
|
|
await alternativeFetch();
|
2024-07-12 15:26:13 +07:00
|
|
|
flowStore.rotate();
|
|
|
|
|
}
|
|
|
|
|
"
|
|
|
|
|
/>
|
|
|
|
|
</div>
|
2024-07-12 13:35:15 +07:00
|
|
|
</div>
|
2024-07-04 14:55:09 +07:00
|
|
|
</div>
|
2024-06-28 14:14:23 +07:00
|
|
|
</div>
|
2024-07-17 07:32:56 +00:00
|
|
|
</template>
|
|
|
|
|
</q-splitter>
|
|
|
|
|
</div>
|
2024-07-12 15:26:13 +07:00
|
|
|
</div>
|
2024-06-11 12:01:35 +07:00
|
|
|
|
2024-08-07 10:11:53 +00:00
|
|
|
<DialogForm
|
2024-06-11 12:01:35 +07:00
|
|
|
v-model:modal="dialogInputForm"
|
|
|
|
|
noAddress
|
2024-06-12 15:37:17 +07:00
|
|
|
:title="$t('addProduct')"
|
|
|
|
|
:submit="() => (productMode === 'type' ? submitType() : submitGroup())"
|
2024-06-24 09:07:06 +00:00
|
|
|
:close="clearFormGroup"
|
2024-06-11 12:01:35 +07:00
|
|
|
>
|
2024-08-07 10:11:53 +00:00
|
|
|
<div class="q-mx-lg q-mt-lg">
|
|
|
|
|
<ProfileBanner
|
|
|
|
|
active
|
|
|
|
|
hideFade
|
|
|
|
|
useToggle
|
2024-08-07 11:13:42 +00:00
|
|
|
:icon="productMode === 'group' ? 'mdi-folder' : 'mdi-folder-table'"
|
2024-08-07 10:11:53 +00:00
|
|
|
:title="formDataGroup.name"
|
|
|
|
|
:caption="formDataGroup.code"
|
|
|
|
|
:menu="[
|
|
|
|
|
{
|
|
|
|
|
icon: 'mdi-office-building-outline',
|
|
|
|
|
color: 'hsl(var(--info-bg))',
|
|
|
|
|
bgColor: 'var(--surface-1)',
|
|
|
|
|
},
|
|
|
|
|
]"
|
2024-08-07 11:13:42 +00:00
|
|
|
:fallbackCover="`/images/product-service-${productMode}-banner.png`"
|
|
|
|
|
:color="`hsla(var(${
|
|
|
|
|
productMode === 'group'
|
|
|
|
|
? '--pink-6'
|
|
|
|
|
: $q.dark.isActive
|
|
|
|
|
? '--violet-10'
|
|
|
|
|
: '--violet-11'
|
|
|
|
|
}-hsl)/1)`"
|
|
|
|
|
:bg-color="`hsla(var(${
|
|
|
|
|
productMode === 'group'
|
|
|
|
|
? '--pink-6'
|
|
|
|
|
: $q.dark.isActive
|
|
|
|
|
? '--violet-10'
|
|
|
|
|
: '--violet-11'
|
|
|
|
|
}-hsl)/0.1)`"
|
|
|
|
|
v-model:toggle-status="currentStatusGroupType"
|
2024-08-08 02:25:12 +00:00
|
|
|
@view="imageDialog = true"
|
2024-08-07 10:11:53 +00:00
|
|
|
@update:toggle-status="
|
|
|
|
|
() => {
|
2024-08-07 11:13:42 +00:00
|
|
|
currentStatusGroupType =
|
|
|
|
|
currentStatusGroupType === 'CREATED' ? 'INACTIVE' : 'CREATED';
|
2024-08-07 10:11:53 +00:00
|
|
|
}
|
|
|
|
|
"
|
2024-06-11 12:01:35 +07:00
|
|
|
/>
|
2024-08-07 10:11:53 +00:00
|
|
|
</div>
|
|
|
|
|
<div
|
|
|
|
|
class="col surface-1 q-ma-lg rounded bordered scroll row relative-position"
|
|
|
|
|
id="group-form"
|
|
|
|
|
>
|
|
|
|
|
<div
|
|
|
|
|
class="col"
|
|
|
|
|
style="height: 100%; max-height: 100; overflow-y: auto"
|
|
|
|
|
v-if="$q.screen.gt.sm"
|
|
|
|
|
>
|
|
|
|
|
<div class="q-py-md q-pl-md q-pr-sm">
|
|
|
|
|
<SideMenu
|
|
|
|
|
:menu="[
|
|
|
|
|
{
|
|
|
|
|
name: $t('formDialogTitleInformation'),
|
|
|
|
|
anchor: 'form-group',
|
|
|
|
|
},
|
|
|
|
|
]"
|
|
|
|
|
background="transparent"
|
|
|
|
|
:active="{
|
|
|
|
|
background: 'hsla(var(--blue-6-hsl) / .2)',
|
|
|
|
|
foreground: 'var(--blue-6)',
|
|
|
|
|
}"
|
|
|
|
|
scroll-element="#group-form"
|
|
|
|
|
/>
|
|
|
|
|
</div>
|
|
|
|
|
</div>
|
|
|
|
|
<div
|
|
|
|
|
class="col-12 col-md-10 q-py-md q-pr-md q-pl-sm"
|
|
|
|
|
id="customer-form-content"
|
|
|
|
|
style="height: 100%; max-height: 100%; overflow-y: auto"
|
|
|
|
|
>
|
|
|
|
|
<BasicInformation
|
|
|
|
|
ide="form-group"
|
|
|
|
|
dense
|
|
|
|
|
:isType="productMode === 'type'"
|
|
|
|
|
v-model:remark="formDataGroup.remark"
|
|
|
|
|
v-model:name="formDataGroup.name"
|
|
|
|
|
v-model:detail="formDataGroup.detail"
|
|
|
|
|
/>
|
|
|
|
|
</div>
|
|
|
|
|
</div>
|
|
|
|
|
</DialogForm>
|
2024-06-11 12:01:35 +07:00
|
|
|
|
|
|
|
|
<DrawerInfo
|
2024-08-09 02:10:06 +00:00
|
|
|
:hideAction="!currentStatusProduct"
|
2024-06-11 12:01:35 +07:00
|
|
|
ref="formDialogRef"
|
|
|
|
|
v-model:drawerOpen="drawerInfo"
|
2024-06-28 14:14:23 +07:00
|
|
|
:title="
|
2024-07-15 14:12:53 +07:00
|
|
|
$t(
|
2024-07-15 16:05:40 +07:00
|
|
|
editByTree === 'group'
|
|
|
|
|
? 'productGroup'
|
|
|
|
|
: editByTree === 'type'
|
|
|
|
|
? 'productType'
|
|
|
|
|
: productMode === 'group'
|
|
|
|
|
? 'productGroup'
|
2024-07-23 07:25:11 +00:00
|
|
|
: 'productType',
|
2024-07-15 14:12:53 +07:00
|
|
|
{
|
|
|
|
|
name: formDataGroup.code,
|
|
|
|
|
},
|
|
|
|
|
)
|
2024-06-28 14:14:23 +07:00
|
|
|
"
|
2024-06-11 16:29:00 +07:00
|
|
|
:undo="() => undoProductGroup()"
|
2024-06-11 12:01:35 +07:00
|
|
|
:isEdit="isEdit"
|
|
|
|
|
:editData="() => (isEdit = true)"
|
2024-07-15 14:12:53 +07:00
|
|
|
:submit="
|
|
|
|
|
() => {
|
|
|
|
|
if (editByTree !== undefined) {
|
|
|
|
|
if (editByTree === 'group') {
|
|
|
|
|
submitGroup();
|
|
|
|
|
}
|
|
|
|
|
if (editByTree === 'type') {
|
|
|
|
|
submitType();
|
|
|
|
|
}
|
|
|
|
|
editByTree = undefined;
|
|
|
|
|
} else {
|
|
|
|
|
if (productMode === 'group') {
|
|
|
|
|
submitGroup();
|
|
|
|
|
}
|
|
|
|
|
if (productMode === 'type') {
|
|
|
|
|
submitType();
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
"
|
2024-06-11 12:01:35 +07:00
|
|
|
:delete-data="() => deleteProductById()"
|
2024-08-07 11:13:42 +00:00
|
|
|
:close="
|
|
|
|
|
() => {
|
|
|
|
|
(drawerInfo = false), (currentIdGroupType = '');
|
|
|
|
|
}
|
|
|
|
|
"
|
2024-06-11 12:01:35 +07:00
|
|
|
>
|
2024-08-07 10:11:53 +00:00
|
|
|
<InfoForm>
|
|
|
|
|
<div class="q-mx-lg q-mt-lg">
|
|
|
|
|
<ProfileBanner
|
2024-08-07 11:13:42 +00:00
|
|
|
:active="currentStatusGroupType !== 'INACTIVE'"
|
2024-08-07 10:11:53 +00:00
|
|
|
hideFade
|
|
|
|
|
useToggle
|
2024-08-08 02:25:12 +00:00
|
|
|
:readonly="!isEdit"
|
2024-08-07 11:13:42 +00:00
|
|
|
:icon="productMode === 'group' ? 'mdi-folder' : 'mdi-folder-table'"
|
|
|
|
|
:fallbackCover="`/images/product-service-${productMode}-banner.png`"
|
|
|
|
|
v-model:toggle-status="currentStatusGroupType"
|
|
|
|
|
:color="`hsla(var(${
|
|
|
|
|
productMode === 'group'
|
|
|
|
|
? '--pink-6'
|
|
|
|
|
: $q.dark.isActive
|
|
|
|
|
? '--violet-10'
|
|
|
|
|
: '--violet-11'
|
|
|
|
|
}-hsl)/1)`"
|
|
|
|
|
:bg-color="`hsla(var(${
|
|
|
|
|
productMode === 'group'
|
|
|
|
|
? '--pink-6'
|
|
|
|
|
: $q.dark.isActive
|
|
|
|
|
? '--violet-10'
|
|
|
|
|
: '--violet-11'
|
|
|
|
|
}-hsl)/0.1)`"
|
2024-08-07 10:11:53 +00:00
|
|
|
:title="formDataGroup.name"
|
|
|
|
|
:caption="formDataGroup.code"
|
|
|
|
|
:toggleTitle="$t('formDialogTitleUserStatus')"
|
|
|
|
|
:menu="[
|
|
|
|
|
{
|
|
|
|
|
icon: 'mdi-office-building-outline',
|
|
|
|
|
color: 'hsl(var(--info-bg))',
|
|
|
|
|
bgColor: 'var(--surface-1)',
|
|
|
|
|
},
|
|
|
|
|
]"
|
2024-08-08 02:25:12 +00:00
|
|
|
@view="imageDialog = true"
|
2024-08-07 10:11:53 +00:00
|
|
|
@update:toggle-status="
|
|
|
|
|
async (v) => {
|
2024-08-07 11:13:42 +00:00
|
|
|
await triggerChangeStatus(currentIdGroupType, v, productMode);
|
2024-08-07 10:11:53 +00:00
|
|
|
}
|
|
|
|
|
"
|
|
|
|
|
/>
|
|
|
|
|
</div>
|
|
|
|
|
|
|
|
|
|
<div
|
|
|
|
|
class="col surface-1 q-ma-lg rounded bordered scroll row"
|
|
|
|
|
id="group-info"
|
|
|
|
|
>
|
|
|
|
|
<div class="col">
|
|
|
|
|
<div style="position: sticky; top: 0" class="q-pa-sm">
|
|
|
|
|
<SideMenu
|
|
|
|
|
:menu="[
|
|
|
|
|
{
|
|
|
|
|
name: $t('formDialogTitleInformation'),
|
|
|
|
|
anchor: 'info-group',
|
|
|
|
|
},
|
|
|
|
|
]"
|
|
|
|
|
background="transparent"
|
|
|
|
|
:active="{
|
|
|
|
|
background: 'hsla(var(--blue-6-hsl) / .2)',
|
|
|
|
|
foreground: 'var(--blue-6)',
|
|
|
|
|
}"
|
|
|
|
|
scroll-element="#group-info"
|
|
|
|
|
/>
|
|
|
|
|
</div>
|
|
|
|
|
</div>
|
|
|
|
|
|
|
|
|
|
<div class="col-10 q-pa-md q-gutter-y-xl">
|
2024-06-27 04:55:39 +00:00
|
|
|
<BasicInformation
|
2024-08-07 10:11:53 +00:00
|
|
|
id="info-group"
|
2024-06-27 04:55:39 +00:00
|
|
|
dense
|
|
|
|
|
: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"
|
|
|
|
|
/>
|
2024-08-07 10:11:53 +00:00
|
|
|
</div>
|
|
|
|
|
</div>
|
|
|
|
|
</InfoForm>
|
2024-06-11 12:01:35 +07:00
|
|
|
</DrawerInfo>
|
2024-06-11 15:11:55 +07:00
|
|
|
|
|
|
|
|
<FormDialog
|
|
|
|
|
v-model:modal="dialogProductServiceType"
|
|
|
|
|
:title="'สร้างสินค้าและบริการ'"
|
|
|
|
|
no-footer
|
|
|
|
|
no-app-box
|
2024-06-18 11:47:53 +00:00
|
|
|
max-width="80%"
|
2024-06-24 09:07:06 +00:00
|
|
|
:close="() => (dialogProductServiceType = false)"
|
2024-06-11 15:11:55 +07:00
|
|
|
>
|
|
|
|
|
<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;
|
|
|
|
|
}
|
|
|
|
|
"
|
|
|
|
|
/>
|
|
|
|
|
</div>
|
|
|
|
|
</template>
|
|
|
|
|
</FormDialog>
|
|
|
|
|
|
|
|
|
|
<FormDialog
|
|
|
|
|
v-model:modal="dialogTotalProduct"
|
|
|
|
|
noAddress
|
|
|
|
|
noAppBox
|
2024-06-19 18:00:38 +07:00
|
|
|
title="สินค้าทั้งหมด"
|
2024-06-11 15:11:55 +07:00
|
|
|
:submit="
|
|
|
|
|
() => {
|
2024-06-20 18:02:02 +07:00
|
|
|
selectProduct.forEach((i) => {
|
|
|
|
|
workItems[currentWorkIndex].product.push({
|
|
|
|
|
...i,
|
|
|
|
|
nameEn: '',
|
|
|
|
|
});
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
dialogTotalProduct = false;
|
|
|
|
|
selectProduct = [];
|
2024-06-11 15:11:55 +07:00
|
|
|
}
|
|
|
|
|
"
|
2024-06-24 13:07:00 +07:00
|
|
|
:close="
|
|
|
|
|
() => {
|
2024-06-25 09:45:55 +07:00
|
|
|
dialogTotalProduct = false;
|
2024-06-25 14:51:58 +07:00
|
|
|
inputSearchProductAndService = '';
|
2024-06-24 13:07:00 +07:00
|
|
|
}
|
|
|
|
|
"
|
2024-06-11 15:11:55 +07:00
|
|
|
>
|
2024-06-25 09:45:55 +07:00
|
|
|
<div class="full-width full-height">
|
2024-06-24 13:53:22 +07:00
|
|
|
<div class="row items-center">
|
2024-06-19 18:00:38 +07:00
|
|
|
<q-space />
|
|
|
|
|
<q-input
|
2024-07-26 11:05:07 +07:00
|
|
|
lazy-rules="ondemand"
|
2024-07-19 14:04:02 +07:00
|
|
|
id="input-search-add-product"
|
2024-06-19 18:00:38 +07:00
|
|
|
outlined
|
2024-07-09 11:54:03 +07:00
|
|
|
style="width: 250px"
|
2024-06-19 18:00:38 +07:00
|
|
|
dense
|
|
|
|
|
:label="$t('search')"
|
|
|
|
|
:bg-color="$q.dark.isActive ? 'dark' : 'white'"
|
2024-06-25 14:51:58 +07:00
|
|
|
v-model="inputSearchProductAndService"
|
2024-06-19 18:00:38 +07:00
|
|
|
debounce="500"
|
2024-06-24 13:07:00 +07:00
|
|
|
@update:model-value="searchProduct()"
|
2024-06-19 18:00:38 +07:00
|
|
|
>
|
|
|
|
|
<template v-slot:prepend>
|
|
|
|
|
<q-icon name="mdi-magnify" />
|
|
|
|
|
</template>
|
|
|
|
|
</q-input>
|
2024-06-13 15:59:09 +07:00
|
|
|
</div>
|
2024-06-24 13:53:22 +07:00
|
|
|
<div>
|
2024-07-09 11:54:03 +07:00
|
|
|
<AppBox
|
|
|
|
|
no-padding
|
|
|
|
|
class="row q-mt-sm q-col-gutter-sm"
|
|
|
|
|
style="background: none"
|
|
|
|
|
>
|
2024-06-25 09:45:55 +07:00
|
|
|
<div
|
|
|
|
|
class="col-12 text-center"
|
|
|
|
|
v-if="resultSearchProduct?.length === 0"
|
|
|
|
|
>
|
|
|
|
|
<NoData />
|
|
|
|
|
</div>
|
|
|
|
|
|
2024-06-24 13:53:22 +07:00
|
|
|
<div
|
|
|
|
|
:class="`${$q.screen.gt.sm ? 'col-3 ' : $q.screen.gt.xs ? 'col-6' : 'col-12'}`"
|
2024-06-25 14:51:58 +07:00
|
|
|
v-for="i in (!!inputSearchProductAndService
|
2024-06-24 13:53:22 +07:00
|
|
|
? resultSearchProduct
|
2024-06-27 09:41:39 +07:00
|
|
|
: productIsAdd
|
2024-06-24 13:53:22 +07:00
|
|
|
)?.filter((i) => {
|
|
|
|
|
if (i.status === 'INACTIVE') {
|
|
|
|
|
return false;
|
2024-06-20 15:05:44 +07:00
|
|
|
}
|
2024-06-24 13:53:22 +07:00
|
|
|
return true;
|
|
|
|
|
})"
|
|
|
|
|
:key="i.id"
|
|
|
|
|
>
|
|
|
|
|
<TotalProductCardComponent
|
|
|
|
|
:index="selectProduct.findIndex((v) => v.id === i.id)"
|
|
|
|
|
:isAddProduct="!!selectProduct.find((v) => v.id === i.id)"
|
|
|
|
|
:isSelected="true"
|
2024-06-25 14:31:08 +07:00
|
|
|
:data="{ ...i, type: 'product' }"
|
2024-06-24 13:53:22 +07:00
|
|
|
:title="i.name"
|
|
|
|
|
:status="i.status === 'INACTIVE' ? true : false"
|
|
|
|
|
@menuViewDetail="
|
|
|
|
|
() => {
|
|
|
|
|
currentIdProduct = i.id;
|
|
|
|
|
assignFormDataProduct(i);
|
|
|
|
|
dialogProductEdit = true;
|
2024-06-20 15:05:44 +07:00
|
|
|
}
|
2024-06-24 13:53:22 +07:00
|
|
|
"
|
|
|
|
|
@menuEdit="
|
|
|
|
|
() => {
|
|
|
|
|
currentIdProduct = i.id;
|
|
|
|
|
infoProductEdit = true;
|
|
|
|
|
assignFormDataProduct(i);
|
|
|
|
|
dialogProductEdit = true;
|
|
|
|
|
}
|
|
|
|
|
"
|
|
|
|
|
@viewDetail="
|
|
|
|
|
() => {
|
|
|
|
|
currentIdProduct = i.id;
|
|
|
|
|
infoProductEdit = false;
|
|
|
|
|
assignFormDataProduct(i);
|
|
|
|
|
dialogProductEdit = true;
|
|
|
|
|
}
|
|
|
|
|
"
|
|
|
|
|
@select="
|
|
|
|
|
(data) => {
|
|
|
|
|
const tempValue = selectProduct.find((v) => v.id === i.id);
|
|
|
|
|
|
|
|
|
|
if (tempValue) {
|
|
|
|
|
selectProduct = selectProduct.filter((v) => v.id !== i.id);
|
|
|
|
|
} else {
|
|
|
|
|
selectProduct.push(data);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
"
|
|
|
|
|
/>
|
|
|
|
|
</div>
|
|
|
|
|
</AppBox>
|
|
|
|
|
</div>
|
2024-06-19 18:00:38 +07:00
|
|
|
</div>
|
2024-06-11 15:11:55 +07:00
|
|
|
</FormDialog>
|
2024-06-14 14:45:17 +07:00
|
|
|
|
2024-06-17 17:59:09 +07:00
|
|
|
<!-- Add Product -->
|
2024-06-14 14:45:17 +07:00
|
|
|
<FormDialog
|
|
|
|
|
v-model:modal="dialogProduct"
|
|
|
|
|
noAddress
|
2024-06-19 13:51:45 +07:00
|
|
|
:title="$t('buttonAddProduct')"
|
2024-06-14 14:45:17 +07:00
|
|
|
:submit="
|
|
|
|
|
() => {
|
2024-06-17 17:59:09 +07:00
|
|
|
submitProduct();
|
|
|
|
|
}
|
|
|
|
|
"
|
|
|
|
|
:close="
|
|
|
|
|
() => {
|
|
|
|
|
dialogProduct = false;
|
2024-06-26 17:21:26 +07:00
|
|
|
flowStore.rotate();
|
2024-06-17 17:59:09 +07:00
|
|
|
}
|
|
|
|
|
"
|
|
|
|
|
>
|
|
|
|
|
<template #prepend>
|
|
|
|
|
<ProfileUpload
|
2024-07-25 14:44:32 +07:00
|
|
|
prefix-id="form-dialog-product"
|
2024-06-17 17:59:09 +07:00
|
|
|
isProduct
|
|
|
|
|
v-model:url-profile="profileUrl"
|
|
|
|
|
v-model:status-toggle="statusToggle"
|
|
|
|
|
v-model:profile-submit="profileSubmit"
|
|
|
|
|
@input-file="inputFile.click()"
|
2024-07-24 15:18:04 +07:00
|
|
|
@cancel-file="inputFile.value = ''"
|
2024-06-17 17:59:09 +07:00
|
|
|
/>
|
|
|
|
|
</template>
|
|
|
|
|
|
2024-06-21 08:49:20 +00:00
|
|
|
<template #information>
|
2024-06-17 17:59:09 +07:00
|
|
|
<BasicInfoProduct
|
2024-07-26 10:46:23 +00:00
|
|
|
v-model:options-branch="branchOption"
|
2024-07-04 11:38:10 +07:00
|
|
|
v-model:registered-branch-id="formDataProduct.registeredBranchId"
|
2024-06-17 17:59:09 +07:00
|
|
|
v-model:detail="formDataProduct.detail"
|
|
|
|
|
v-model:remark="formDataProduct.remark"
|
|
|
|
|
v-model:name="formDataProduct.name"
|
|
|
|
|
v-model:code="formDataProduct.code"
|
2024-06-18 16:35:40 +07:00
|
|
|
v-model:process="formDataProduct.process"
|
2024-06-17 17:59:09 +07:00
|
|
|
dense
|
|
|
|
|
separator
|
|
|
|
|
/>
|
2024-06-21 08:49:20 +00:00
|
|
|
</template>
|
|
|
|
|
<template #person>
|
2024-06-17 17:59:09 +07:00
|
|
|
<PriceDataComponent
|
|
|
|
|
v-model:price="formDataProduct.price"
|
|
|
|
|
v-model:agent-price="formDataProduct.agentPrice"
|
|
|
|
|
v-model:service-charge="formDataProduct.serviceCharge"
|
|
|
|
|
dense
|
|
|
|
|
/>
|
2024-06-21 08:49:20 +00:00
|
|
|
</template>
|
2024-06-17 17:59:09 +07:00
|
|
|
</FormDialog>
|
|
|
|
|
|
|
|
|
|
<!-- edit product -->
|
|
|
|
|
<FormDialog
|
2024-06-24 13:07:00 +07:00
|
|
|
:edit="!(formDataProduct.status === 'INACTIVE')"
|
2024-06-19 13:51:45 +07:00
|
|
|
:isEdit="infoProductEdit"
|
|
|
|
|
v-model:modal="dialogProductEdit"
|
2024-06-17 17:59:09 +07:00
|
|
|
noAddress
|
2024-06-19 13:51:45 +07:00
|
|
|
:title="$t('editProduct')"
|
|
|
|
|
:editData="() => (infoProductEdit = true)"
|
2024-06-25 14:58:56 +07:00
|
|
|
:undo="
|
|
|
|
|
() => {
|
|
|
|
|
formDataProduct = { ...prevProduct };
|
|
|
|
|
infoProductEdit = false;
|
2024-06-26 17:21:26 +07:00
|
|
|
flowStore.rotate();
|
2024-06-25 14:58:56 +07:00
|
|
|
}
|
|
|
|
|
"
|
2024-06-19 13:51:45 +07:00
|
|
|
:deleteData="
|
|
|
|
|
() => {
|
|
|
|
|
deleteTypeOfProduct();
|
|
|
|
|
}
|
|
|
|
|
"
|
2024-06-17 17:59:09 +07:00
|
|
|
:submit="
|
|
|
|
|
() => {
|
|
|
|
|
submitProduct();
|
2024-06-14 14:45:17 +07:00
|
|
|
}
|
|
|
|
|
"
|
|
|
|
|
:close="
|
|
|
|
|
() => {
|
2024-06-19 13:51:45 +07:00
|
|
|
dialogProductEdit = false;
|
2024-06-26 17:21:26 +07:00
|
|
|
flowStore.rotate();
|
2024-06-14 14:45:17 +07:00
|
|
|
}
|
|
|
|
|
"
|
|
|
|
|
>
|
|
|
|
|
<template #prepend>
|
|
|
|
|
<ProfileUpload
|
2024-07-25 14:44:32 +07:00
|
|
|
prefix-id="form-dialog-product"
|
2024-06-14 14:45:17 +07:00
|
|
|
isProduct
|
|
|
|
|
v-model:url-profile="profileUrl"
|
|
|
|
|
v-model:status-toggle="statusToggle"
|
|
|
|
|
v-model:profile-submit="profileSubmit"
|
|
|
|
|
@input-file="inputFile.click()"
|
2024-07-24 15:18:04 +07:00
|
|
|
@cancel-file="inputFile.value = ''"
|
2024-06-20 13:59:25 +07:00
|
|
|
:label-status-toggle="'formDialogTitleProductStatus'"
|
2024-06-14 14:45:17 +07:00
|
|
|
/>
|
|
|
|
|
</template>
|
|
|
|
|
|
2024-06-21 08:49:20 +00:00
|
|
|
<template #information>
|
2024-06-17 17:59:09 +07:00
|
|
|
<BasicInfoProduct
|
2024-06-19 13:51:45 +07:00
|
|
|
:readonly="!infoProductEdit"
|
2024-07-26 10:46:23 +00:00
|
|
|
v-model:options-branch="branchOption"
|
2024-07-04 11:38:10 +07:00
|
|
|
v-model:registered-branch-id="formDataProduct.registeredBranchId"
|
2024-06-17 17:59:09 +07:00
|
|
|
v-model:detail="formDataProduct.detail"
|
|
|
|
|
v-model:remark="formDataProduct.remark"
|
|
|
|
|
v-model:name="formDataProduct.name"
|
|
|
|
|
v-model:code="formDataProduct.code"
|
2024-06-18 16:39:34 +07:00
|
|
|
v-model:process="formDataProduct.process"
|
2024-06-17 17:59:09 +07:00
|
|
|
dense
|
|
|
|
|
separator
|
|
|
|
|
/>
|
2024-06-21 08:49:20 +00:00
|
|
|
</template>
|
|
|
|
|
<template #person>
|
2024-06-17 17:59:09 +07:00
|
|
|
<PriceDataComponent
|
2024-06-19 13:51:45 +07:00
|
|
|
:readonly="!infoProductEdit"
|
2024-06-17 17:59:09 +07:00
|
|
|
v-model:price="formDataProduct.price"
|
|
|
|
|
v-model:agent-price="formDataProduct.agentPrice"
|
|
|
|
|
v-model:service-charge="formDataProduct.serviceCharge"
|
|
|
|
|
dense
|
|
|
|
|
/>
|
2024-06-21 08:49:20 +00:00
|
|
|
</template>
|
2024-06-14 14:45:17 +07:00
|
|
|
</FormDialog>
|
2024-06-18 02:01:02 +00:00
|
|
|
|
2024-06-18 11:47:53 +00:00
|
|
|
<!-- add service -->
|
2024-06-18 02:01:02 +00:00
|
|
|
<FormDialog
|
|
|
|
|
no-address
|
2024-06-25 09:35:06 +00:00
|
|
|
no-app-box
|
2024-06-21 08:49:20 +00:00
|
|
|
height="95vh"
|
2024-06-18 02:01:02 +00:00
|
|
|
:title="$t('addService')"
|
|
|
|
|
v-model:modal="dialogService"
|
2024-06-28 02:21:21 +00:00
|
|
|
:tabs-list="serviceTab"
|
2024-06-18 02:01:02 +00:00
|
|
|
v-model:current-tab="currentServiceTab"
|
2024-06-21 11:40:18 +07:00
|
|
|
:submit="
|
|
|
|
|
() => {
|
|
|
|
|
submitService();
|
|
|
|
|
}
|
|
|
|
|
"
|
|
|
|
|
:close="
|
|
|
|
|
() => {
|
2024-06-24 09:07:06 +00:00
|
|
|
clearFormService();
|
2024-06-21 11:40:18 +07:00
|
|
|
dialogService = false;
|
2024-06-26 17:21:26 +07:00
|
|
|
flowStore.rotate();
|
2024-06-21 11:40:18 +07:00
|
|
|
}
|
|
|
|
|
"
|
2024-06-18 02:01:02 +00:00
|
|
|
>
|
|
|
|
|
<template #prepend>
|
|
|
|
|
<ProfileUpload
|
2024-07-25 14:44:32 +07:00
|
|
|
prefix-id="form-dialog-service"
|
2024-06-18 02:28:29 +00:00
|
|
|
isService
|
2024-06-18 02:01:02 +00:00
|
|
|
v-model:url-profile="profileUrl"
|
|
|
|
|
v-model:status-toggle="statusToggle"
|
|
|
|
|
v-model:profile-submit="profileSubmit"
|
2024-07-24 15:18:04 +07:00
|
|
|
@cancel-file="inputFile.value = ''"
|
2024-06-18 02:01:02 +00:00
|
|
|
@input-file="inputFile.click()"
|
|
|
|
|
/>
|
|
|
|
|
</template>
|
|
|
|
|
|
2024-07-01 08:40:37 +00:00
|
|
|
<div
|
|
|
|
|
v-if="currentServiceTab === 'serviceInformation'"
|
|
|
|
|
class="col-md-10 col-sm-12"
|
|
|
|
|
>
|
2024-06-25 09:35:06 +00:00
|
|
|
<div class="surface-1 rounded bordered q-pa-lg full-width row">
|
|
|
|
|
<BasicInformation
|
|
|
|
|
dense
|
|
|
|
|
service
|
2024-07-26 10:46:23 +00:00
|
|
|
v-model:options-branch="branchOption"
|
2024-07-04 13:28:28 +07:00
|
|
|
v-model:registered-branch-id="
|
|
|
|
|
formDataProductService.registeredBranchId
|
|
|
|
|
"
|
2024-06-25 09:35:06 +00:00
|
|
|
v-model:service-code="formDataProductService.code"
|
|
|
|
|
v-model:service-description="formDataProductService.detail"
|
|
|
|
|
v-model:service-name-th="formDataProductService.name"
|
|
|
|
|
/>
|
|
|
|
|
</div>
|
|
|
|
|
<div class="surface-1 rounded bordered q-mt-md q-pa-lg row">
|
|
|
|
|
<FormServiceProperties
|
|
|
|
|
v-model:service-attributes="formDataProductService.attributes"
|
|
|
|
|
@service-properties="
|
|
|
|
|
() => {
|
|
|
|
|
tempValueProperties = formDataProductService.attributes;
|
|
|
|
|
openPropertiesDialog('service');
|
|
|
|
|
}
|
|
|
|
|
"
|
|
|
|
|
/>
|
|
|
|
|
</div>
|
|
|
|
|
</div>
|
|
|
|
|
|
|
|
|
|
<div
|
|
|
|
|
v-if="currentServiceTab === 'workInformation'"
|
2024-07-01 08:40:37 +00:00
|
|
|
class="surface-1 rounded bordered col-md-10 col-sm-12 q-pa-lg"
|
2024-06-25 09:35:06 +00:00
|
|
|
>
|
2024-06-18 02:01:02 +00:00
|
|
|
<FormServiceWork
|
2024-06-20 18:02:02 +07:00
|
|
|
v-model:work-items="workItems"
|
2024-06-18 02:01:02 +00:00
|
|
|
dense
|
2024-06-20 18:02:02 +07:00
|
|
|
@addProduct="
|
2024-06-25 14:31:08 +07:00
|
|
|
async (index) => {
|
2024-06-27 09:41:39 +07:00
|
|
|
await fetchListOfProductIsAdd(currentIdType);
|
2024-06-20 18:02:02 +07:00
|
|
|
currentWorkIndex = index;
|
|
|
|
|
dialogTotalProduct = true;
|
|
|
|
|
}
|
|
|
|
|
"
|
2024-06-21 15:59:18 +07:00
|
|
|
@manage-work-name="
|
|
|
|
|
() => {
|
|
|
|
|
manageWorkNameDialog = true;
|
|
|
|
|
}
|
|
|
|
|
"
|
2024-06-20 18:02:02 +07:00
|
|
|
@work-properties="
|
|
|
|
|
(index) => {
|
|
|
|
|
currentWorkIndex = index;
|
|
|
|
|
tempValueProperties = workItems[index].attributes;
|
|
|
|
|
openPropertiesDialog('work');
|
|
|
|
|
}
|
|
|
|
|
"
|
2024-06-18 02:01:02 +00:00
|
|
|
/>
|
2024-06-25 09:35:06 +00:00
|
|
|
</div>
|
2024-06-18 02:01:02 +00:00
|
|
|
</FormDialog>
|
2024-06-18 11:47:53 +00:00
|
|
|
|
|
|
|
|
<!-- service properties -->
|
|
|
|
|
<FormDialog
|
|
|
|
|
no-address
|
|
|
|
|
no-app-box
|
2024-06-24 02:19:41 +00:00
|
|
|
height="75vh"
|
2024-06-18 11:47:53 +00:00
|
|
|
width="75%"
|
2024-06-24 04:45:58 +00:00
|
|
|
:title="$t('properties')"
|
2024-06-18 11:47:53 +00:00
|
|
|
v-model:modal="propertiesDialog"
|
2024-06-20 18:02:02 +07:00
|
|
|
:submit="
|
|
|
|
|
() => {
|
|
|
|
|
if (currentPropertiesMode === 'service') {
|
|
|
|
|
formDataProductService.attributes = tempValueProperties;
|
|
|
|
|
}
|
|
|
|
|
if (currentPropertiesMode === 'work') {
|
|
|
|
|
workItems[currentWorkIndex].attributes = tempValueProperties;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
propertiesDialog = false;
|
|
|
|
|
}
|
|
|
|
|
"
|
|
|
|
|
:close="
|
|
|
|
|
() => {
|
|
|
|
|
propertiesDialog = false;
|
|
|
|
|
}
|
|
|
|
|
"
|
2024-06-18 11:47:53 +00:00
|
|
|
>
|
|
|
|
|
<ServiceProperties
|
2024-06-20 09:10:34 +00:00
|
|
|
v-model:properties-option="propertiesOption"
|
2024-06-20 18:02:02 +07:00
|
|
|
v-model:form-service-properties="tempValueProperties"
|
2024-06-18 11:47:53 +00:00
|
|
|
/>
|
|
|
|
|
</FormDialog>
|
2024-06-20 09:10:34 +00:00
|
|
|
|
|
|
|
|
<!-- manage work name -->
|
|
|
|
|
<FormDialog
|
|
|
|
|
no-address
|
|
|
|
|
no-app-box
|
2024-06-21 11:06:35 +00:00
|
|
|
no-footer
|
2024-06-24 02:19:41 +00:00
|
|
|
height="65vh"
|
2024-06-20 09:10:34 +00:00
|
|
|
width="65%"
|
|
|
|
|
v-model:modal="manageWorkNameDialog"
|
2024-06-24 09:01:44 +00:00
|
|
|
:title="$t('manage')"
|
|
|
|
|
:close="triggerConfirmCloseWork"
|
2024-06-20 09:10:34 +00:00
|
|
|
>
|
2024-06-21 11:06:35 +00:00
|
|
|
<WorkNameManagement
|
|
|
|
|
ref="workNameRef"
|
|
|
|
|
v-model:nameList="workNameItems"
|
|
|
|
|
@delete="confirmDeleteWork"
|
|
|
|
|
@edit="editWork"
|
|
|
|
|
@add="createWork"
|
|
|
|
|
/>
|
2024-06-20 09:10:34 +00:00
|
|
|
</FormDialog>
|
2024-06-21 14:50:43 +07:00
|
|
|
|
|
|
|
|
<!-- edit service -->
|
|
|
|
|
<FormDialog
|
|
|
|
|
no-address
|
2024-06-25 11:04:34 +00:00
|
|
|
:no-app-box="currentServiceTab !== 'workInformation'"
|
2024-06-24 16:53:33 +07:00
|
|
|
:edit="!(formDataProductService.status === 'INACTIVE')"
|
2024-06-24 10:13:23 +00:00
|
|
|
height="95vh"
|
2024-06-21 14:50:43 +07:00
|
|
|
:isEdit="infoServiceEdit"
|
2024-07-10 11:54:22 +07:00
|
|
|
:title="$t('service')"
|
2024-06-28 02:21:21 +00:00
|
|
|
:tabs-list="serviceTab"
|
2024-06-21 14:50:43 +07:00
|
|
|
v-model:modal="dialogServiceEdit"
|
|
|
|
|
v-model:current-tab="currentServiceTab"
|
|
|
|
|
:submit="
|
|
|
|
|
() => {
|
|
|
|
|
submitService();
|
|
|
|
|
}
|
|
|
|
|
"
|
|
|
|
|
:close="
|
|
|
|
|
() => {
|
|
|
|
|
clearFormService();
|
2024-06-26 17:21:26 +07:00
|
|
|
flowStore.rotate();
|
2024-06-21 14:50:43 +07:00
|
|
|
dialogServiceEdit = false;
|
|
|
|
|
}
|
|
|
|
|
"
|
|
|
|
|
:edit-data="
|
|
|
|
|
() => {
|
|
|
|
|
infoServiceEdit = true;
|
|
|
|
|
}
|
|
|
|
|
"
|
2024-06-24 16:53:33 +07:00
|
|
|
:undo="
|
|
|
|
|
() => {
|
|
|
|
|
infoServiceEdit = false;
|
2024-06-26 17:44:13 +07:00
|
|
|
cloneData();
|
2024-06-24 16:53:33 +07:00
|
|
|
statusToggle = prevService.status === 'INACTIVE' ? false : true;
|
2024-06-26 17:21:26 +07:00
|
|
|
flowStore.rotate();
|
2024-06-24 16:53:33 +07:00
|
|
|
}
|
|
|
|
|
"
|
2024-06-21 14:50:43 +07:00
|
|
|
:delete-data="() => deleteServiceById()"
|
|
|
|
|
>
|
|
|
|
|
<template #prepend>
|
|
|
|
|
<ProfileUpload
|
2024-07-25 14:44:32 +07:00
|
|
|
prefix-id="form-dialog-service"
|
2024-06-21 14:50:43 +07:00
|
|
|
isService
|
2024-07-01 11:04:24 +00:00
|
|
|
:readonly="!infoServiceEdit"
|
2024-06-21 14:50:43 +07:00
|
|
|
v-model:url-profile="profileUrl"
|
|
|
|
|
v-model:status-toggle="statusToggle"
|
|
|
|
|
v-model:profile-submit="profileSubmit"
|
2024-07-24 15:18:04 +07:00
|
|
|
@cancel-file="inputFile.value = ''"
|
2024-06-21 14:50:43 +07:00
|
|
|
@input-file="inputFile.click()"
|
|
|
|
|
/>
|
|
|
|
|
</template>
|
|
|
|
|
|
2024-06-25 11:04:34 +00:00
|
|
|
<div
|
|
|
|
|
v-if="currentServiceTab === 'serviceInformation'"
|
|
|
|
|
class="col-md-10 col-sm-12"
|
|
|
|
|
>
|
2024-06-25 09:35:06 +00:00
|
|
|
<div class="surface-1 rounded bordered q-pa-lg full-width row">
|
|
|
|
|
<BasicInformation
|
|
|
|
|
:readonly="!infoServiceEdit"
|
|
|
|
|
v-if="currentServiceTab === 'serviceInformation'"
|
|
|
|
|
dense
|
|
|
|
|
service
|
2024-07-26 10:46:23 +00:00
|
|
|
v-model:options-branch="branchOption"
|
2024-07-04 13:28:28 +07:00
|
|
|
v-model:registered-branch-id="
|
|
|
|
|
formDataProductService.registeredBranchId
|
|
|
|
|
"
|
2024-06-25 09:35:06 +00:00
|
|
|
v-model:service-code="formDataProductService.code"
|
|
|
|
|
v-model:service-description="formDataProductService.detail"
|
|
|
|
|
v-model:service-name-th="formDataProductService.name"
|
|
|
|
|
/>
|
|
|
|
|
</div>
|
|
|
|
|
<div class="surface-1 rounded bordered q-mt-md q-pa-lg row">
|
|
|
|
|
<FormServiceProperties
|
|
|
|
|
:readonly="!infoServiceEdit"
|
|
|
|
|
v-model:service-attributes="formDataProductService.attributes"
|
|
|
|
|
@service-properties="
|
|
|
|
|
() => {
|
|
|
|
|
tempValueProperties = formDataProductService.attributes;
|
|
|
|
|
openPropertiesDialog('service');
|
|
|
|
|
}
|
|
|
|
|
"
|
|
|
|
|
/>
|
|
|
|
|
</div>
|
|
|
|
|
</div>
|
|
|
|
|
|
2024-06-25 11:04:34 +00:00
|
|
|
<template #information>
|
2024-06-21 14:50:43 +07:00
|
|
|
<FormServiceWork
|
|
|
|
|
:readonly="!infoServiceEdit"
|
|
|
|
|
v-model:work-items="workItems"
|
|
|
|
|
v-if="currentServiceTab === 'workInformation'"
|
|
|
|
|
dense
|
|
|
|
|
@addProduct="
|
2024-06-25 14:31:08 +07:00
|
|
|
async (index) => {
|
2024-07-09 11:54:03 +07:00
|
|
|
await fetchListOfProductIsAdd(currentIdType);
|
2024-06-21 14:50:43 +07:00
|
|
|
currentWorkIndex = index;
|
|
|
|
|
dialogTotalProduct = true;
|
|
|
|
|
}
|
|
|
|
|
"
|
|
|
|
|
@manage-work-name="manageWorkNameDialog = true"
|
|
|
|
|
@work-properties="
|
|
|
|
|
(index) => {
|
|
|
|
|
currentWorkIndex = index;
|
|
|
|
|
tempValueProperties = workItems[index].attributes;
|
|
|
|
|
openPropertiesDialog('work');
|
|
|
|
|
}
|
|
|
|
|
"
|
|
|
|
|
/>
|
2024-06-25 11:04:34 +00:00
|
|
|
</template>
|
2024-06-21 14:50:43 +07:00
|
|
|
</FormDialog>
|
2024-07-19 10:35:18 +00:00
|
|
|
|
|
|
|
|
<q-dialog v-model="holdDialog" position="bottom">
|
|
|
|
|
<div class="surface-1 full-width rounded column q-pb-md">
|
|
|
|
|
<div class="flex q-py-sm justify-center full-width">
|
|
|
|
|
<div
|
|
|
|
|
class="rounded"
|
|
|
|
|
style="
|
|
|
|
|
width: 8%;
|
|
|
|
|
height: 4px;
|
|
|
|
|
background-color: hsla(0, 0%, 50%, 0.75);
|
|
|
|
|
"
|
|
|
|
|
></div>
|
|
|
|
|
</div>
|
|
|
|
|
|
|
|
|
|
<q-list v-if="currentNode">
|
|
|
|
|
<q-item
|
|
|
|
|
clickable
|
|
|
|
|
v-ripple
|
|
|
|
|
v-close-popup
|
|
|
|
|
@click.stop="
|
2024-07-30 05:29:36 +00:00
|
|
|
async () => {
|
2024-07-19 10:35:18 +00:00
|
|
|
if (!currentNode) return;
|
2024-07-30 05:29:36 +00:00
|
|
|
|
|
|
|
|
await fetchListOfOptionBranch();
|
2024-07-19 10:35:18 +00:00
|
|
|
if (currentNode.type === 'type') {
|
|
|
|
|
editByTree = 'type';
|
|
|
|
|
currentStatusProduct = currentNode.status === 'INACTIVE';
|
|
|
|
|
clearFormGroup();
|
|
|
|
|
currentIdType = currentNode.id;
|
|
|
|
|
assignFormDataGroup(currentNode);
|
|
|
|
|
isEdit = false;
|
|
|
|
|
drawerInfo = true;
|
|
|
|
|
}
|
|
|
|
|
if (currentNode.type === 'group') {
|
|
|
|
|
editByTree = 'group';
|
|
|
|
|
currentStatusProduct = currentNode.status === 'INACTIVE';
|
|
|
|
|
clearFormGroup();
|
|
|
|
|
assignFormDataGroup(currentNode);
|
|
|
|
|
isEdit = false;
|
2024-07-23 10:24:22 +07:00
|
|
|
currentIdGrop = currentNode.id;
|
2024-07-19 10:35:18 +00:00
|
|
|
drawerInfo = true;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
"
|
|
|
|
|
>
|
|
|
|
|
<q-item-section avatar>
|
|
|
|
|
<q-icon
|
|
|
|
|
name="mdi-eye-outline"
|
|
|
|
|
style="color: hsl(var(--green-6-hsl))"
|
|
|
|
|
/>
|
|
|
|
|
</q-item-section>
|
|
|
|
|
<q-item-section>{{ $t('viewDetail') }}</q-item-section>
|
|
|
|
|
</q-item>
|
|
|
|
|
|
|
|
|
|
<q-item
|
|
|
|
|
clickable
|
|
|
|
|
v-ripple
|
|
|
|
|
v-close-popup
|
|
|
|
|
@click.stop="
|
|
|
|
|
() => {
|
|
|
|
|
if (!currentNode) return;
|
|
|
|
|
editByTree = currentNode.type as 'type' | 'group';
|
|
|
|
|
if (currentNode.type === 'type') {
|
|
|
|
|
clearFormGroup();
|
|
|
|
|
currentIdType = currentNode.id;
|
|
|
|
|
assignFormDataGroup(currentNode);
|
|
|
|
|
isEdit = true;
|
|
|
|
|
drawerInfo = true;
|
|
|
|
|
}
|
|
|
|
|
if (currentNode.type === 'group') {
|
|
|
|
|
clearFormGroup();
|
|
|
|
|
assignFormDataGroup(currentNode);
|
|
|
|
|
isEdit = true;
|
2024-07-23 10:24:22 +07:00
|
|
|
currentIdGrop = currentNode.id;
|
2024-07-19 10:35:18 +00:00
|
|
|
|
|
|
|
|
drawerInfo = true;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
"
|
|
|
|
|
>
|
|
|
|
|
<q-item-section avatar>
|
|
|
|
|
<q-icon
|
|
|
|
|
name="mdi-pencil-outline"
|
|
|
|
|
style="color: hsl(var(--cyan-6-hsl))"
|
|
|
|
|
/>
|
|
|
|
|
</q-item-section>
|
|
|
|
|
<q-item-section>{{ $t('edit') }}</q-item-section>
|
|
|
|
|
</q-item>
|
|
|
|
|
|
|
|
|
|
<q-item
|
|
|
|
|
clickable
|
|
|
|
|
v-ripple
|
|
|
|
|
v-close-popup
|
|
|
|
|
@click.stop="
|
|
|
|
|
() => {
|
|
|
|
|
if (!currentNode) return;
|
|
|
|
|
editByTree = currentNode.type as 'type' | 'group';
|
|
|
|
|
|
|
|
|
|
if (currentNode.type === 'type') {
|
|
|
|
|
deleteProductById(currentNode.id);
|
|
|
|
|
}
|
|
|
|
|
if (currentNode.type === 'group') {
|
|
|
|
|
deleteProductById(currentNode.id);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
"
|
|
|
|
|
>
|
|
|
|
|
<q-item-section avatar>
|
|
|
|
|
<q-icon name="mdi-trash-can-outline" class="app-text-negative" />
|
|
|
|
|
</q-item-section>
|
|
|
|
|
<q-item-section>{{ $t('delete') }}</q-item-section>
|
|
|
|
|
</q-item>
|
|
|
|
|
|
|
|
|
|
<q-item clickable v-ripple>
|
|
|
|
|
<q-item-section avatar>
|
|
|
|
|
<q-toggle
|
|
|
|
|
dense
|
|
|
|
|
:id="`view-detail-btn-${currentNode.name}-status`"
|
|
|
|
|
size="sm"
|
|
|
|
|
@click.stop="
|
|
|
|
|
async () => {
|
|
|
|
|
if (!currentNode) return;
|
|
|
|
|
if (currentNode.type === 'type') {
|
2024-07-25 10:49:43 +00:00
|
|
|
triggerChangeStatus(
|
|
|
|
|
currentNode.id,
|
|
|
|
|
currentNode.status,
|
|
|
|
|
currentNode.type,
|
|
|
|
|
);
|
2024-07-19 10:35:18 +00:00
|
|
|
currentNode.status === 'ACTIVE'
|
|
|
|
|
? (currentNode.status = 'INACTIVE')
|
|
|
|
|
: (currentNode.status = 'ACTIVE');
|
|
|
|
|
}
|
|
|
|
|
if (currentNode.type === 'group') {
|
2024-07-25 10:49:43 +00:00
|
|
|
triggerChangeStatus(
|
|
|
|
|
currentNode.id,
|
|
|
|
|
currentNode.status,
|
|
|
|
|
currentNode.type,
|
|
|
|
|
);
|
2024-07-19 10:35:18 +00:00
|
|
|
currentNode.status === 'ACTIVE'
|
|
|
|
|
? (currentNode.status = 'INACTIVE')
|
|
|
|
|
: (currentNode.status = 'ACTIVE');
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
"
|
|
|
|
|
:model-value="currentNode.status !== 'INACTIVE'"
|
|
|
|
|
/>
|
|
|
|
|
</q-item-section>
|
|
|
|
|
<q-item-section>
|
|
|
|
|
{{
|
|
|
|
|
currentNode.status !== 'INACTIVE'
|
|
|
|
|
? $t('switchOnLabel')
|
|
|
|
|
: $t('switchOffLabel')
|
|
|
|
|
}}
|
|
|
|
|
</q-item-section>
|
|
|
|
|
</q-item>
|
|
|
|
|
</q-list>
|
|
|
|
|
</div>
|
|
|
|
|
</q-dialog>
|
2024-08-08 02:25:12 +00:00
|
|
|
|
|
|
|
|
<ImageUploadDialog
|
|
|
|
|
ref="refImageUpload"
|
|
|
|
|
v-model:dialogState="imageDialog"
|
|
|
|
|
v-model:file="profileFileImg"
|
|
|
|
|
clearButton
|
|
|
|
|
>
|
|
|
|
|
<template #error>
|
|
|
|
|
<div class="full-height full-width" style="background: white">
|
|
|
|
|
<div
|
|
|
|
|
class="full-height full-width flex justify-center items-center"
|
|
|
|
|
:style="`background: hsla(var(${
|
|
|
|
|
productMode === 'group'
|
|
|
|
|
? '--pink-6'
|
|
|
|
|
: $q.dark.isActive
|
|
|
|
|
? '--violet-10'
|
|
|
|
|
: '--violet-11'
|
|
|
|
|
}-hsl)/0.1)`"
|
|
|
|
|
>
|
|
|
|
|
<q-icon
|
|
|
|
|
size="15rem"
|
|
|
|
|
:name="productMode === 'group' ? 'mdi-folder' : 'mdi-folder-table'"
|
|
|
|
|
:style="`color: hsla(var(${
|
|
|
|
|
productMode === 'group'
|
|
|
|
|
? '--pink-6'
|
|
|
|
|
: $q.dark.isActive
|
|
|
|
|
? '--violet-10'
|
|
|
|
|
: '--violet-11'
|
|
|
|
|
}-hsl)/1)`"
|
|
|
|
|
></q-icon>
|
|
|
|
|
</div>
|
|
|
|
|
</div>
|
|
|
|
|
</template>
|
|
|
|
|
</ImageUploadDialog>
|
2024-06-10 16:42:59 +07:00
|
|
|
</template>
|
|
|
|
|
|
2024-06-11 12:01:35 +07:00
|
|
|
<style scoped>
|
|
|
|
|
.hover-underline:hover {
|
|
|
|
|
cursor: pointer;
|
|
|
|
|
text-decoration: underline;
|
|
|
|
|
}
|
2024-07-09 14:38:22 +07:00
|
|
|
|
|
|
|
|
.status-active {
|
|
|
|
|
--_branch-status-color: var(--green-6-hsl);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
.status-inactive {
|
2024-08-07 10:11:53 +00:00
|
|
|
--_branch-status-color: var(--stone-5-hsl);
|
|
|
|
|
--_branch-badge-bg: var(--stone-5-hsl);
|
2024-07-09 14:38:22 +07:00
|
|
|
filter: grayscale(0.5);
|
|
|
|
|
opacity: 0.5;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
.icon-color-purple {
|
|
|
|
|
--_color: var(--violet-11-hsl);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
.icon-color-pink {
|
|
|
|
|
--_color: var(--pink-6-hsl);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
.icon-color-orange {
|
|
|
|
|
--_color: var(--orange-5-hsl);
|
|
|
|
|
}
|
|
|
|
|
|
2024-07-09 17:17:08 +07:00
|
|
|
.icon-color-green {
|
2024-07-09 14:38:22 +07:00
|
|
|
--_color: var(--teal-10-hsl);
|
|
|
|
|
}
|
|
|
|
|
|
2024-07-09 16:18:48 +07:00
|
|
|
.tags-color-green {
|
|
|
|
|
--_color-tag: var(--teal-10-hsl);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
.dark .tags-color-green {
|
|
|
|
|
--_color-tag: var(--teal-8-hsl);
|
|
|
|
|
}
|
|
|
|
|
|
2024-07-09 14:38:22 +07:00
|
|
|
.dark .icon-color-purple {
|
|
|
|
|
--_color: var(--violet-10-hsl);
|
|
|
|
|
}
|
|
|
|
|
|
2024-07-09 17:17:08 +07:00
|
|
|
.dark .icon-color-green {
|
2024-07-09 14:38:22 +07:00
|
|
|
--_color: var(--teal-8-hsl);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
.dark .icon-color-orange {
|
|
|
|
|
--_color: var(--orange-6-hsl);
|
|
|
|
|
}
|
|
|
|
|
|
2024-07-09 15:23:42 +07:00
|
|
|
.table__icon {
|
2024-07-09 14:38:22 +07:00
|
|
|
background-color: hsla(var(--_color) / 0.15);
|
|
|
|
|
color: hsla(var(--_color) / 1);
|
2024-07-09 17:17:08 +07:00
|
|
|
|
2024-07-09 14:38:22 +07:00
|
|
|
border-radius: 50%;
|
|
|
|
|
padding: var(--size-1);
|
|
|
|
|
position: relative;
|
|
|
|
|
transform: rotate(45deg);
|
|
|
|
|
|
|
|
|
|
&::after {
|
|
|
|
|
content: ' ';
|
|
|
|
|
display: block;
|
|
|
|
|
block-size: 0.5rem;
|
|
|
|
|
aspect-ratio: 1;
|
|
|
|
|
position: absolute;
|
|
|
|
|
border-radius: 50%;
|
|
|
|
|
right: -0.1rem;
|
|
|
|
|
top: calc(50% - 0.25rem);
|
|
|
|
|
bottom: calc(50% - 0.25rem);
|
|
|
|
|
background-color: hsla(var(--_branch-status-color) / 1);
|
|
|
|
|
}
|
|
|
|
|
|
2024-07-09 17:17:08 +07:00
|
|
|
&:deep(.q-icon) {
|
2024-07-09 14:38:22 +07:00
|
|
|
transform: rotate(-45deg);
|
|
|
|
|
color: hsla(var(--_branch-card-bg) / 1);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2024-07-09 16:18:48 +07:00
|
|
|
.tags {
|
|
|
|
|
display: inline-block;
|
|
|
|
|
color: hsla(var(--_color-tag) / 1);
|
|
|
|
|
background: hsla(var(--_color-tag) / 0.15);
|
|
|
|
|
border-radius: var(--radius-2);
|
|
|
|
|
padding-inline: var(--size-2);
|
|
|
|
|
}
|
2024-07-19 18:05:58 +07:00
|
|
|
|
|
|
|
|
* :deep(.q-icon.mdi-play) {
|
|
|
|
|
display: none;
|
|
|
|
|
}
|
2024-06-11 12:01:35 +07:00
|
|
|
</style>
|