fix Load การลา

This commit is contained in:
DESKTOP-1R2VSQH\Lenovo ThinkPad E490 2025-06-16 11:15:31 +07:00
parent 3817416ba9
commit ce94ea009a
5 changed files with 184 additions and 80 deletions

View file

@ -6,6 +6,7 @@ import http from "@/plugins/http";
import config from "@/app.config"; import config from "@/app.config";
import { tokenParsed } from "@/plugins/auth"; import { tokenParsed } from "@/plugins/auth";
import { useCounterMixin } from "@/stores/mixin"; import { useCounterMixin } from "@/stores/mixin";
import { useLeaveStore } from "@/modules/05_leave/store";
import FullCalendar from "@fullcalendar/vue3"; import FullCalendar from "@fullcalendar/vue3";
import dayGridPlugin from "@fullcalendar/daygrid"; import dayGridPlugin from "@fullcalendar/daygrid";
@ -23,6 +24,7 @@ import type {
import DialogDetail from "@/modules/05_leave/components/DialogDetail.vue"; import DialogDetail from "@/modules/05_leave/components/DialogDetail.vue";
const $q = useQuasar(); const $q = useQuasar();
const store = useLeaveStore();
const mixin = useCounterMixin(); const mixin = useCounterMixin();
const { showLoader, hideLoader, messageError, monthYear2Thai } = mixin; const { showLoader, hideLoader, messageError, monthYear2Thai } = mixin;
const emit = defineEmits(["update:dateYear"]); const emit = defineEmits(["update:dateYear"]);
@ -74,7 +76,6 @@ const dateMonth = ref<DataDateMonthObject>({
/** function เรียกข้อมูล calendar*/ /** function เรียกข้อมูล calendar*/
async function fetchDataCalendar() { async function fetchDataCalendar() {
showLoader();
await http await http
.post(config.API.leaveCalendar(), { .post(config.API.leaveCalendar(), {
year: dateMonth.value.year, year: dateMonth.value.year,
@ -118,9 +119,6 @@ async function fetchDataCalendar() {
}) })
.catch((err) => { .catch((err) => {
messageError($q, err); messageError($q, err);
})
.finally(() => {
hideLoader();
}); });
} }
@ -128,7 +126,6 @@ async function fetchDataCalendar() {
* fetch นหยดในปฏ * fetch นหยดในปฏ
*/ */
async function fetchData() { async function fetchData() {
showLoader();
await http await http
.get( .get(
config.API.listHolidayHistoryYearMonth( config.API.listHolidayHistoryYearMonth(
@ -138,7 +135,6 @@ async function fetchData() {
) )
.then((res) => { .then((res) => {
const dataNormal = res.data.result.normal; const dataNormal = res.data.result.normal;
const dataSixDays = res.data.result.sixDays;
const data = dataNormal; const data = dataNormal;
const event = data.map((e: any) => ({ const event = data.map((e: any) => ({
id: e.id, id: e.id,
@ -155,23 +151,9 @@ async function fetchData() {
...calendarOptions.value.events, ...calendarOptions.value.events,
...event, ...event,
]; ];
// const dataSix = dataSixDays
// const eventSix = dataSix.map((e: any) => ({
// id: e.id,
// title: `${e.name} `,
// start: e.holidayDate,
// end: new Date(new Date(e.holidayDate).setHours(23, 59, 59)).toISOString(),
// allDay: e.holidayDate === e.holidayDate ? true : false,
// color: "#FFE5CC",
// textColor: "#FF8000",
// }))
// calendarOptions.value.events = [...calendarOptions.value.events, ...eventSix]
}) })
.catch((e) => { .catch((e) => {
messageError($q, e); messageError($q, e);
})
.finally(async () => {
hideLoader();
}); });
} }
@ -184,14 +166,11 @@ function convertKeycloakId(id: any) {
/** function เรียกประเภทการลา */ /** function เรียกประเภทการลา */
const leaveType = ref<LeaveType[]>([]); const leaveType = ref<LeaveType[]>([]);
async function fectOptionType() { async function fectOptionType() {
await http const data = await store.fetchLeaveTypeData();
.get(config.API.leaveType()) if (!data) {
.then(async (res) => { return;
leaveType.value = res.data.result; }
}) leaveType.value = data;
.catch((err) => {
messageError($q, err);
});
} }
/** /**
@ -205,11 +184,17 @@ function monthYearThai(val: DataDateMonthObject) {
/** function อัปเดท Calendar */ /** function อัปเดท Calendar */
async function updateMonth() { async function updateMonth() {
await fetchDataCalendar(); try {
await fetchData(); await fetchDataCalendar();
const calen = fullCalendar.value.getApi(); await fetchData();
const date = new Date(dateMonth.value.year, dateMonth.value.month); const calen = fullCalendar.value.getApi();
calen.gotoDate(date); const date = new Date(dateMonth.value.year, dateMonth.value.month);
calen.gotoDate(date);
} catch (error) {
messageError($q, error);
} finally {
hideLoader();
}
} }
/** /**
@ -226,10 +211,11 @@ async function onClickClose() {
modal.value = false; modal.value = false;
} }
/**** ตรวจสอบว่ามีการส่งข้อมูลเข้ามาที่Calendar */ /** ตรวจสอบว่ามีการส่งข้อมูลเข้ามาที่Calendar */
watch( watch(
() => filterVal.value, () => filterVal.value,
async () => { async () => {
showLoader();
const eventData = filterVal.value.map((item: any) => { const eventData = filterVal.value.map((item: any) => {
return mainData.value return mainData.value
.filter( .filter(
@ -250,24 +236,32 @@ watch(
const allEventData = [].concat(...eventData); const allEventData = [].concat(...eventData);
calendarOptions.value.events = allEventData; calendarOptions.value.events = allEventData;
await fetchData(); await fetchData();
hideLoader();
} }
); );
/**Hook */ /**Hook */
onMounted(async () => { onMounted(async () => {
const user = await tokenParsed(); try {
keycloakId.value = await (user ? user.sub : ""); showLoader();
filterVal.value.push(keycloakId.value); // keycloakId
await fetchDataCalendar(); const user = await tokenParsed();
await fetchData(); keycloakId.value = await (user ? user.sub : "");
await fectOptionType(); filterVal.value.push(keycloakId.value);
await Promise.all([fetchDataCalendar(), fectOptionType()]);
await fetchData();
} catch (error) {
messageError($q, error);
} finally {
hideLoader();
}
}); });
</script> </script>
<template> <template>
<div class="row"> <div class="row">
<div class="col-xs-12 col-md-3 q-mt-sm q-pr-sm row"> <div class="col-xs-12 col-md-3 q-mt-sm q-pr-sm row">
<q-card class="col-12" flat bordered > <q-card class="col-12" flat bordered>
<q-scroll-area style="height: 38vw"> <q-scroll-area style="height: 38vw">
<div class="q-gutter-sm col-12"> <div class="q-gutter-sm col-12">
<q-list class="rounded-borders q-pt-sm" dense> <q-list class="rounded-borders q-pt-sm" dense>

View file

@ -65,15 +65,12 @@ async function fetchDataTable() {
/** function เรียกประเภทการลา */ /** function เรียกประเภทการลา */
async function fectOptionType() { async function fectOptionType() {
await http const data = await LeaveData.fetchLeaveTypeData();
.get(config.API.leaveType()) if (!data) {
.then(async (res) => { return;
leaveType.value = res.data.result; }
LeaveData.fetchLeaveType(res.data.result); leaveType.value = data;
}) LeaveData.fetchLeaveType(data);
.catch((err) => {
messageError($q, err);
});
} }
/** /**
@ -95,25 +92,26 @@ async function onClickEdit(id: string) {
router.push(`/leave/edit/${id}`); router.push(`/leave/edit/${id}`);
} }
//
function clickDelete(id: string) {
dialogRemove($q, () => onClickDelete(id));
}
/** /**
* function ลบรายการ * งกนลบขอมลการลา
* @param id * @param id รายการลาทองการลบ
*/ */
async function onClickDelete(id: string) { function clickDelete(id: string) {
await http dialogRemove($q, async () => {
.delete(config.API.leaveUserId(id)) showLoader();
.then(async (res) => { await http
success($q, "ลบข้อมูลสำเร็จ"); .delete(config.API.leaveUserId(id))
fetchDataTable(); .then(async () => {
}) await fetchDataTable();
.catch((err) => { success($q, "ลบข้อมูลสำเร็จ");
messageError($q, err); })
}); .catch((err) => {
messageError($q, err);
})
.finally(() => {
hideLoader();
});
});
} }
/** function closePopup*/ /** function closePopup*/
@ -170,8 +168,15 @@ function convert(val: any) {
* เรยกฟงกนทงหมดตอนเรยกใชไฟล * เรยกฟงกนทงหมดตอนเรยกใชไฟล
*/ */
onMounted(async () => { onMounted(async () => {
await fectOptionType(); try {
await fetchDataTable(); showLoader();
await fectOptionType();
await fetchDataTable();
} catch (error) {
messageError($q, error);
} finally {
hideLoader();
}
}); });
</script> </script>
<template> <template>

View file

@ -134,6 +134,8 @@ watch([() => currentPage.value, () => pagination.value.rowsPerPage], () => {
</datepicker> </datepicker>
<!-- นหาขอความใน table --> <!-- นหาขอความใน table -->
<q-select <q-select
fill-input
hide-selected
outlined outlined
dense dense
v-model="leaveStore.type" v-model="leaveStore.type"
@ -173,6 +175,8 @@ watch([() => currentPage.value, () => pagination.value.rowsPerPage], () => {
/> </template /> </template
></q-select> ></q-select>
<q-select <q-select
fill-input
hide-selected
outlined outlined
dense dense
v-model="leaveStore.status" v-model="leaveStore.status"

View file

@ -17,7 +17,7 @@ import type {
import type { DataOption } from "../14_IDP/interface/Main"; import type { DataOption } from "../14_IDP/interface/Main";
const mixin = useCounterMixin(); const mixin = useCounterMixin();
const { date2Thai, messageError, showLoader, hideLoader } = mixin; const { date2Thai, showLoader, hideLoader } = mixin;
const type = ref<string>("00000000-0000-0000-0000-000000000000"); const type = ref<string>("00000000-0000-0000-0000-000000000000");
const status = ref<string>("ALL"); const status = ref<string>("ALL");
export const useLeaveStore = defineStore("Leave", () => { export const useLeaveStore = defineStore("Leave", () => {
@ -27,6 +27,7 @@ export const useLeaveStore = defineStore("Leave", () => {
const LeaveStatus = ref<string | null>("0"); const LeaveStatus = ref<string | null>("0");
const fiscalYearyear = ref<Number | null>(new Date().getFullYear()); const fiscalYearyear = ref<Number | null>(new Date().getFullYear());
const rows = ref<ListLeaveTable[]>([]); const rows = ref<ListLeaveTable[]>([]);
const leaveTypeData = ref<TypeLeave[]>([]);
/** /**
* function Table * function Table
@ -134,10 +135,9 @@ export const useLeaveStore = defineStore("Leave", () => {
* @param update * @param update
* @param refData * @param refData
*/ */
function filterOption(val: any, update: Function, refData: string) { function filterOption(val: string, update: Function, refData: string) {
switch (refData) { switch (refData) {
case "LeaveTypeOption": case "LeaveTypeOption":
type.value = "";
update(() => { update(() => {
typeOptions.value = typeOptionsMain.value.filter( typeOptions.value = typeOptionsMain.value.filter(
(v: any) => v.name.indexOf(val) > -1 (v: any) => v.name.indexOf(val) > -1
@ -145,7 +145,6 @@ export const useLeaveStore = defineStore("Leave", () => {
}); });
break; break;
case "LeaveStatusOption": case "LeaveStatusOption":
status.value = "";
update(() => { update(() => {
statusOptions.value = statusOptionsMain.value.filter( statusOptions.value = statusOptionsMain.value.filter(
(v: any) => v.name.indexOf(val) > -1 (v: any) => v.name.indexOf(val) > -1
@ -403,6 +402,21 @@ export const useLeaveStore = defineStore("Leave", () => {
restDayCurrentTotal.value = 0; restDayCurrentTotal.value = 0;
} }
/** ฟังก์ชันเรียกข้อมูลประเภทการลา */
async function fetchLeaveTypeData() {
if (leaveTypeData.value.length > 0) {
return leaveTypeData.value;
} else {
try {
const res = await http.get(config.API.leaveType());
leaveTypeData.value = res.data.result;
return leaveTypeData.value;
} catch (error) {
console.error("Fetch leave type error:", error);
}
}
}
return { return {
tabValue, tabValue,
typeOptions, typeOptions,
@ -457,5 +471,7 @@ export const useLeaveStore = defineStore("Leave", () => {
currentAddress, currentAddress,
rangeOptions, rangeOptions,
converstType, converstType,
fetchLeaveTypeData,
}; };
}); });

View file

@ -118,8 +118,11 @@ const columns = ref<QTableProps["columns"]>([
}, },
]); ]);
const isloading = ref<boolean>(false);
/** function เรียกข้อมูลตารางสถิติการลา*/ /** function เรียกข้อมูลตารางสถิติการลา*/
async function fetchStatsTable() { async function fetchStatsTable() {
isloading.value = true;
await http await http
.get(config.API.leaveStats()) .get(config.API.leaveStats())
.then((res) => { .then((res) => {
@ -168,9 +171,11 @@ async function fetchStatsTable() {
leaveCountReject: e.leaveCountReject, leaveCountReject: e.leaveCountReject,
leaveCountDelete: e.leaveCountDelete, leaveCountDelete: e.leaveCountDelete,
})); }));
isloading.value = false;
}) })
.catch((err) => { .catch((err) => {
messageError($q, err); messageError($q, err);
isloading.value = true;
}); });
} }
@ -210,7 +215,7 @@ onMounted(async () => {
<div class="col-xs-12 col-sm-12 col-md-11 row"> <div class="col-xs-12 col-sm-12 col-md-11 row">
<!-- สถการลา --> <!-- สถการลา -->
<div class="col-12 row q-pb-sm"> <div class="col-12 row q-pb-sm">
<q-card bordered class="col-12 row"> <q-card bordered class="col-12 row" v-if="!isloading">
<div class="row col-12 items-center q-px-md q-py-sm"> <div class="row col-12 items-center q-px-md q-py-sm">
<div class="text-weight-bold">สถการลา</div> <div class="text-weight-bold">สถการลา</div>
<q-space /> <q-space />
@ -230,12 +235,7 @@ onMounted(async () => {
:key="item.text" :key="item.text"
> >
<div class="col-xs-12 col-sm-12"> <div class="col-xs-12 col-sm-12">
<q-card <q-card bordered flat class="col-12 row shadow-0 no-wrap">
bordered
flat
class="col-12 row shadow-0 no-wrap"
v-if="item.text === 'ลาพักผ่อน'"
>
<div class="col-xs-12 col-sm-8 row justify-center q-py-md"> <div class="col-xs-12 col-sm-8 row justify-center q-py-md">
<div class="col-12 row items-center justify-center q-pb-sm"> <div class="col-12 row items-center justify-center q-pb-sm">
<q-knob <q-knob
@ -327,6 +327,91 @@ onMounted(async () => {
</div> </div>
</div> </div>
</q-card> </q-card>
<q-card bordered class="col-12 row q-px-md q-py-sm" v-else>
<div class="row col-12 items-center q-px-md q-py-sm">
<div class="text-weight-bold">สถการลา</div>
<q-space />
<q-skeleton type="QBtn" size="20px" style="width: 100px" />
</div>
<div
bordered
class="col-6 row justify-center q-px-md q-pb-md q-col-gutter-sm"
>
<div class="col-xs-12 col-sm-12">
<q-card bordered flat class="col-12 row shadow-0 no-wrap">
<div class="col-xs-12 col-sm-8 row justify-center q-py-md">
<div class="col-12 row items-center justify-center q-pb-sm">
<q-skeleton type="circle" size="60px" />
<div class="col-12 row items-center justify-center">
<q-skeleton type="text" size="20px" style="width: 50px" />
</div>
</div>
</div>
<div class="row gt-xs"><q-separator vertical /></div>
<div class="col-xs-12 col-sm-4 gt-xs row">
<div class="col-12 row text-dark text-body2 items-center">
<div class="col-12 row q-pa-xs q-px-md row">
<span class="text-grey-7 col-6">ได</span>
<q-skeleton type="text" style="width: 50px" />
</div>
<div class="col-12"><q-separator /></div>
<div class="col-12 row q-pa-xs q-px-md">
<span class="text-grey-7 col-6">ใชไป</span>
<q-skeleton type="text" style="width: 50px" />
</div>
<div class="col-12"><q-separator /></div>
<div class="col-12 row q-pa-xs q-px-md">
<span class="text-grey-7 col-6">คงเหล</span>
<q-skeleton type="text" style="width: 50px" />
</div>
</div>
</div>
</q-card>
</div>
</div>
<div class="col-6 row">
<div bordered class="col-12 row justify-center q-px-md q-pb-md">
<div class="col-xs-12 col-sm-12 row">
<div class="col-12 row">
<q-card
bordered
flat
class="shadow-0 col-12 fit row items-center q-px-lg"
>
<div class="text-subtitle2 col-4">
<q-skeleton type="text" style="width: 50px" />
</div>
<div class="text-subtitle2 col-8 row">
<span class="text-grey-7 q-pr-md">ใชไป</span>
<q-skeleton type="text" style="width: 50px" />
</div>
</q-card>
</div>
</div>
</div>
<div bordered class="col-12 row justify-center q-px-md q-pb-md">
<div class="col-xs-12 col-sm-12 row">
<div class="col-12 row">
<q-card
bordered
flat
class="shadow-0 col-12 fit row items-center q-px-lg"
>
<div class="text-subtitle2 col-4">
<q-skeleton type="text" style="width: 50px" />
</div>
<div class="text-subtitle2 col-8 row">
<span class="text-grey-7 q-pr-md">ใชไป</span>
<q-skeleton type="text" style="width: 50px" />
</div>
</q-card>
</div>
</div>
</div>
</div>
</q-card>
</div> </div>
<div class="row col-12"> <div class="row col-12">