607 lines
19 KiB
Vue
607 lines
19 KiB
Vue
<!-- page:จัดการข้อมูลหลัก tab วันหยุด -->
|
|
<template>
|
|
<div>
|
|
<div class="row col-12 q-col-gutter-sm">
|
|
<div class="row items-center">
|
|
<!-- filter เลือกเดือนปี -->
|
|
<datepicker
|
|
v-model="dateMonth"
|
|
:locale="'th'"
|
|
autoApply
|
|
month-picker
|
|
:enableTimePicker="false"
|
|
v-if="currentTab === 'calendar'"
|
|
@update:modelValue="updateMonth"
|
|
>
|
|
<template #year="{ year }">{{ year + 543 }}</template>
|
|
<template #year-overlay-value="{ value }">{{
|
|
parseInt(value + 543)
|
|
}}</template>
|
|
<template #trigger>
|
|
<q-input
|
|
:model-value="monthYearThai(dateMonth)"
|
|
dense
|
|
outlined
|
|
style="width: 130px"
|
|
>
|
|
<template v-slot:prepend>
|
|
<q-icon
|
|
name="event"
|
|
class="cursor-pointer"
|
|
style="color: var(--q-primary)"
|
|
>
|
|
</q-icon>
|
|
</template>
|
|
</q-input>
|
|
</template>
|
|
</datepicker>
|
|
|
|
<!-- filter เลือกปี -->
|
|
<datepicker
|
|
v-model="dateYear"
|
|
:locale="'th'"
|
|
autoApply
|
|
year-picker
|
|
:enableTimePicker="false"
|
|
v-if="currentTab === 'list'"
|
|
@update:modelValue="updateYear"
|
|
>
|
|
<template #year="{ year }">{{ year + 543 }}</template>
|
|
<template #year-overlay-value="{ value }">{{
|
|
parseInt(value + 543)
|
|
}}</template>
|
|
<template #trigger>
|
|
<q-input
|
|
:model-value="dateYear + 543"
|
|
dense
|
|
outlined
|
|
style="width: 100px"
|
|
>
|
|
<template v-slot:prepend>
|
|
<q-icon
|
|
name="event"
|
|
class="cursor-pointer"
|
|
style="color: var(--q-primary)"
|
|
>
|
|
</q-icon>
|
|
</template>
|
|
</q-input>
|
|
</template>
|
|
</datepicker>
|
|
<div class="q-ml-sm">
|
|
<!-- icon เพิ่มวันหยุด -->
|
|
<q-btn round dense flat size="13px" class="q-px-sm">
|
|
<q-icon
|
|
name="mdi-plus"
|
|
size="25px"
|
|
color="grey-7"
|
|
@click="addCalendar()"
|
|
/>
|
|
<q-tooltip>เพิ่มวันหยุด</q-tooltip>
|
|
</q-btn>
|
|
<!-- icon คัดลอกวันหยุด -->
|
|
<q-btn round dense flat size="13px" class="q-px-sm">
|
|
<q-icon
|
|
name="mdi-content-copy"
|
|
size="22px"
|
|
color="grey-7"
|
|
@click="copyCalendar()"
|
|
/>
|
|
<q-tooltip>คัดลอกวันหยุด</q-tooltip>
|
|
</q-btn>
|
|
</div>
|
|
</div>
|
|
<q-space />
|
|
<div class="justify-center row q-gutter-md items-center">
|
|
<!-- tab รูปแบบแสดงวันหยุด ปฏิทินกับรายการ -->
|
|
<q-tabs
|
|
v-model="currentTab"
|
|
indicator-color="transparent"
|
|
align="left"
|
|
active-color="activetab"
|
|
class="text-nativetab"
|
|
inline-label
|
|
dense
|
|
>
|
|
<q-btn
|
|
name="calendar"
|
|
round
|
|
flat
|
|
icon="mdi-calendar-month"
|
|
@click="currentTab = 'calendar'"
|
|
:color="currentTab == 'calendar' ? 'primary' : ''"
|
|
class="q-mr-sm"
|
|
>
|
|
<q-tooltip>ปฏิทิน</q-tooltip>
|
|
</q-btn>
|
|
<q-separator vertical inset />
|
|
<q-btn
|
|
name="list"
|
|
round
|
|
flat
|
|
icon="mdi-format-list-bulleted"
|
|
@click="currentTab = 'list'"
|
|
:color="currentTab == 'list' ? 'primary' : ''"
|
|
class="q-ml-sm"
|
|
>
|
|
<q-tooltip>รายการ</q-tooltip>
|
|
</q-btn>
|
|
</q-tabs>
|
|
</div>
|
|
</div>
|
|
<div>
|
|
<!-- component ปฏิทินวันหยุด -->
|
|
<subCalendarComponent
|
|
v-if="currentTab === 'calendar'"
|
|
:dateYear="dateMonth.year"
|
|
:dateMonth="dateMonth.month"
|
|
:refreshData="refreshData"
|
|
:fetchDataSummaryCalendar="fetchDataSummaryCalendar"
|
|
/>
|
|
<!-- component รายการวันหยุด -->
|
|
<subCalendarListComponent
|
|
v-if="currentTab === 'list'"
|
|
:dateYear="dateYear"
|
|
:refreshData="refreshData"
|
|
:fetchDataSummaryCalendar="fetchDataSummaryCalendar"
|
|
/>
|
|
</div>
|
|
</div>
|
|
<!-- modal เพิ่มวันหยุด -->
|
|
<q-dialog v-model="modalAdd" persistent>
|
|
<q-card style="min-width: 550px">
|
|
<q-form ref="formDate" @submit.prevent.stop="onSubmit">
|
|
<q-card-section class="row items-center q-py-sm">
|
|
<div class="text-bold">เพิ่มวันหยุด</div>
|
|
<q-space />
|
|
<q-btn
|
|
icon="close"
|
|
unelevated
|
|
round
|
|
dense
|
|
v-close-popup
|
|
style="color: #ff8080; background-color: #ffdede"
|
|
/>
|
|
</q-card-section>
|
|
<q-separator />
|
|
<q-card-section class="q-p-md row q-gutter-y-sm">
|
|
<datepicker
|
|
v-model="dateAdd"
|
|
:locale="'th'"
|
|
autoApply
|
|
range
|
|
:enableTimePicker="false"
|
|
week-start="0"
|
|
>
|
|
<template #year="{ year }">
|
|
{{ year + 543 }}
|
|
</template>
|
|
<template #year-overlay-value="{ value }">
|
|
{{ parseInt(value + 543) }}
|
|
</template>
|
|
<template #trigger>
|
|
<q-input
|
|
:model-value="dateThaiRange(dateAdd)"
|
|
outlined
|
|
label="เลือกวันที่"
|
|
dense
|
|
class="full-width datepicker"
|
|
>
|
|
<template v-slot:prepend>
|
|
<q-icon
|
|
name="event"
|
|
class="cursor-pointer"
|
|
style="color: var(--q-primary)"
|
|
>
|
|
</q-icon>
|
|
</template>
|
|
</q-input>
|
|
</template>
|
|
</datepicker>
|
|
<q-input
|
|
dense
|
|
label="คำอธิบาย"
|
|
outlined
|
|
class="full-width datepicker q-pb-none"
|
|
v-model="name"
|
|
type="textarea"
|
|
:rules="[(val) => (val && val.length > 0) || '']"
|
|
/>
|
|
<q-option-group
|
|
dense
|
|
v-model="category"
|
|
:options="categoryOptions"
|
|
color="primary"
|
|
inline
|
|
/>
|
|
</q-card-section>
|
|
<q-separator />
|
|
<q-card-actions align="right" class="text-primary">
|
|
<q-btn
|
|
unelevated
|
|
label="บันทึก"
|
|
color="public"
|
|
type="submit"
|
|
> <!-- icon="mdi-content-save-outline"
|
|
<q-tooltip>บันทึก</q-tooltip> -->
|
|
</q-btn>
|
|
</q-card-actions>
|
|
</q-form>
|
|
</q-card>
|
|
</q-dialog>
|
|
|
|
<!-- modal คัดลอกวันหยุด -->
|
|
<q-dialog v-model="modalCopy" persistent>
|
|
<q-card style="min-width: 500px">
|
|
<q-form @submit.prevent.stop="onSubmitCopy">
|
|
<q-card-section class="row items-center q-py-sm">
|
|
<div class="text-bold">คัดลอกวันหยุดปีก่อนหน้า</div>
|
|
<q-space />
|
|
<q-btn
|
|
icon="close"
|
|
unelevated
|
|
round
|
|
dense
|
|
v-close-popup
|
|
style="color: #ff8080; background-color: #ffdede"
|
|
/>
|
|
</q-card-section>
|
|
<q-separator />
|
|
<q-card-section class="q-p-sm">
|
|
<div class="row col-12 q-col-gutter-sm">
|
|
<datepicker
|
|
v-model="dateYearStart"
|
|
:locale="'th'"
|
|
autoApply
|
|
year-picker
|
|
:enableTimePicker="false"
|
|
>
|
|
<template #year="{ year }">{{ year + 543 }}</template>
|
|
<template #year-overlay-value="{ value }">{{
|
|
parseInt(value + 543)
|
|
}}</template>
|
|
<template #trigger>
|
|
<q-input
|
|
:model-value="dateYearStart + 543"
|
|
dense
|
|
outlined
|
|
class="q-pb-sm"
|
|
label="ปีที่คัดลอกวันหยุด"
|
|
>
|
|
<template v-slot:prepend>
|
|
<q-icon
|
|
name="event"
|
|
class="cursor-pointer"
|
|
style="color: var(--q-primary)"
|
|
>
|
|
</q-icon>
|
|
</template>
|
|
</q-input>
|
|
</template>
|
|
</datepicker>
|
|
<datepicker
|
|
v-model="dateYearEnd"
|
|
:locale="'th'"
|
|
autoApply
|
|
year-picker
|
|
:enableTimePicker="false"
|
|
:min-date="minDate"
|
|
>
|
|
<template #year="{ year }">{{ year + 543 }}</template>
|
|
<template #year-overlay-value="{ value }">{{
|
|
parseInt(value + 543)
|
|
}}</template>
|
|
<template #trigger>
|
|
<q-input
|
|
:model-value="dateYearEnd + 543"
|
|
dense
|
|
outlined
|
|
label="ปีที่ลงวันหยุดคัดลอก"
|
|
class="q-pb-sm"
|
|
>
|
|
<template v-slot:prepend>
|
|
<q-icon
|
|
name="event"
|
|
class="cursor-pointer"
|
|
style="color: var(--q-primary)"
|
|
>
|
|
</q-icon>
|
|
</template>
|
|
</q-input>
|
|
</template>
|
|
</datepicker>
|
|
</div>
|
|
</q-card-section>
|
|
<q-separator />
|
|
<q-card-actions align="right" class="text-primary">
|
|
<q-btn
|
|
unelevated
|
|
label="บันทึก"
|
|
color="public"
|
|
type="submit"
|
|
> <!-- icon="mdi-content-save-outline"
|
|
<q-tooltip>บันทึก</q-tooltip> -->
|
|
</q-btn>
|
|
</q-card-actions>
|
|
</q-form>
|
|
</q-card>
|
|
</q-dialog>
|
|
</template>
|
|
|
|
<script setup lang="ts">
|
|
import type { QTableProps } from "quasar";
|
|
import { defineComponent, onMounted } from "@vue/runtime-core";
|
|
import { reactive, ref, watch } from "vue";
|
|
import http from "@/plugins/http";
|
|
import config from "@/app.config";
|
|
import { useQuasar } from "quasar";
|
|
import { useDataStore } from "@/stores/data";
|
|
import { useCounterMixin } from "@/stores/mixin";
|
|
import { useManageDataStore } from "@/modules/01_metadata/store";
|
|
import type {
|
|
DataDateMonthObject,
|
|
DataDateAddObject,
|
|
} from "@/modules/01_metadata/interface/request/Calendar";
|
|
import subCalendarComponent from "@/modules/01_metadata/components/Calendar.vue";
|
|
import subCalendarListComponent from "@/modules/01_metadata/components/CalendarList.vue";
|
|
|
|
const props = defineProps({
|
|
dateYear: Number, //ปีที่ส่งไป parent สรุปวันหยุด
|
|
fetchDataSummaryCalendar: {
|
|
//ฟังก์ชันอัพเดทสรุปวันหยุด
|
|
type: Function,
|
|
default: () => console.log("not function"),
|
|
},
|
|
});
|
|
|
|
const dataStore = useDataStore();
|
|
const mixin = useCounterMixin(); //เรียกฟังก์ชันกลาง
|
|
const {
|
|
success,
|
|
dateToISO,
|
|
monthYear2Thai,
|
|
date2Thai,
|
|
messageError,
|
|
dialogMessage,
|
|
showLoader,
|
|
hideLoader,
|
|
} = mixin;
|
|
const { loaderPage } = dataStore; //รอโหลด
|
|
const store = useManageDataStore();
|
|
const $q = useQuasar(); //ใช้ noti quasar
|
|
const currentTab = ref<string>(
|
|
store.manageData.calendar.name === ""
|
|
? "calendar"
|
|
: store.manageData.calendar.name
|
|
); //ระบุ tab ใช้งานอยู่ calendar=รายการ list=รายการ
|
|
const modalAdd = ref<boolean>(false); //แสดง modal add calendar
|
|
const modalCopy = ref<boolean>(false); //แสดง modal copy calendar
|
|
const dateMonth = ref<DataDateMonthObject>({
|
|
month: new Date().getMonth(),
|
|
year: new Date().getFullYear(),
|
|
}); //ค่าเดือนที่เลือก tab ปฏิทิน
|
|
const dateYear = ref<number>(new Date().getFullYear()); //ค่าปีที่เลือก tab รายการ
|
|
const dateYearStart = ref<number>(new Date().getFullYear()); //ค่าปีที่ copy วันหยุด
|
|
const dateYearEnd = ref<number>(new Date().getFullYear()); //ค่าปีที่จะลงวันหยุด copy
|
|
const dateAdd = ref<[Date, Date]>([new Date(), new Date()]); //วันที่ ที่เพิ่มเป็นวันหยุด
|
|
const formDate = ref<any>(); //ref เช็ค validate เพิ่มวันหยุด
|
|
const name = ref<string>(""); //ชื่อวันหยุด
|
|
const isSpecial = ref<boolean>(true); //เช็ควันหยุดพิเศษ
|
|
|
|
const category = ref<string>("all");
|
|
const categoryOptions = ref<any>([
|
|
{
|
|
label: "ทั้งหมด",
|
|
value: "all",
|
|
},
|
|
{
|
|
label: "ทำงาน 5 วัน",
|
|
value: "normal",
|
|
},
|
|
{
|
|
label: "ทำงาน 6 วัน",
|
|
value: "6days",
|
|
},
|
|
]);
|
|
const minDate = ref<Date>();
|
|
const refreshData = ref<boolean>(false); //ส่งค่าให้ component refresh data วันหยุด
|
|
const emit = defineEmits(["update:dateYear"]);
|
|
|
|
/**
|
|
* มีการเลือก datepicker ให้แปลงค่าเป็น text ที่แสดง
|
|
*/
|
|
watch(dateYearStart, (count, prevCount) => {
|
|
dateYearEnd.value = dateYearStart.value + 1;
|
|
minDate.value = new Date(`${dateYearStart.value + 1}-01-01`);
|
|
});
|
|
watch(currentTab, async (count, prevCount) => {
|
|
await store.changeManageCurrentTab(5, count);
|
|
});
|
|
|
|
/**
|
|
* เรียกฟังก์ชันทั้งหมดตอนเรียกใช้ไฟล์นี้
|
|
*/
|
|
onMounted(async () => {
|
|
dateYearEnd.value = dateYearStart.value + 1;
|
|
minDate.value = new Date(`${dateYearStart.value + 1}-01-01`);
|
|
});
|
|
|
|
/**
|
|
* ค่าเดือนปีที่ถูกเลือกใน component ปฏิทินจะให้อัพเดทค่าสรุปวันหยุดรวม
|
|
* @param e เลือกเดือนปี tab ปฏิทิน
|
|
*/
|
|
const updateMonth = async (e: DataDateMonthObject) => {
|
|
if (e != null) {
|
|
dateYear.value = e.year;
|
|
emit("update:dateYear", e.year);
|
|
await props.fetchDataSummaryCalendar();
|
|
}
|
|
};
|
|
|
|
/**
|
|
* ค่าปีที่ถูกเลือกใน component รายการจะให้อัพเดทค่าสรุปวันหยุดรวม
|
|
* @param e เลือกปี tab รายการ
|
|
*/
|
|
const updateYear = async (e: number) => {
|
|
dateMonth.value = { month: 0, year: e };
|
|
emit("update:dateYear", dateYear.value);
|
|
await props.fetchDataSummaryCalendar();
|
|
};
|
|
|
|
/**
|
|
* ฟังก์ชันปุ่มเพิ่มวันหยุดแบบเลือกวันได้
|
|
*/
|
|
const addCalendar = () => {
|
|
dateAdd.value = [new Date(), new Date()];
|
|
name.value = "";
|
|
category.value = "all";
|
|
isSpecial.value = true;
|
|
modalAdd.value = true;
|
|
};
|
|
|
|
/**
|
|
* ฟังก์ชัน copy วันหยุดจากปีนิงไปอีกปี
|
|
*/
|
|
const copyCalendar = () => {
|
|
modalCopy.value = true;
|
|
dateYearStart.value = new Date().getFullYear();
|
|
dateYearEnd.value = new Date().getFullYear() + 1;
|
|
};
|
|
|
|
/**
|
|
* ฟังก์ชันปุ่มบันทึกเพิ่มวันหยุด
|
|
*/
|
|
const onSubmit = async () => {
|
|
await formDate.value.validate().then(async (result: boolean) => {
|
|
if (result) {
|
|
const dataAdd = ref<DataDateAddObject[]>([]);
|
|
let i = 0;
|
|
const dateStart = ref<Date>(dateAdd.value[0]);
|
|
do {
|
|
i = i + 1;
|
|
dataAdd.value.push({
|
|
year: new Date(dateStart.value).getFullYear(),
|
|
holidayDate: dateToISO(new Date(dateStart.value)),
|
|
name: name.value,
|
|
isSpecial: true,
|
|
});
|
|
dateStart.value = new Date(
|
|
new Date(dateStart.value).setDate(
|
|
new Date(dateStart.value).getDate() + 1
|
|
)
|
|
);
|
|
} while (new Date(dateStart.value) <= new Date(dateAdd.value[1]));
|
|
showLoader();
|
|
await http
|
|
.post(config.API.listHolidayHistoryAdd(category.value), dataAdd.value)
|
|
.then((res) => {
|
|
modalAdd.value = false;
|
|
success($q, "เพิ่มวันหยุดสำเร็จ");
|
|
})
|
|
.catch((e) => {
|
|
messageError($q, e);
|
|
})
|
|
.finally(() => {
|
|
refreshData.value = !refreshData.value;
|
|
hideLoader();
|
|
});
|
|
}
|
|
});
|
|
await props.fetchDataSummaryCalendar();
|
|
};
|
|
|
|
/**
|
|
* ฟังก์ชันคัดลอกวันหยุด
|
|
*/
|
|
const onSubmitCopy = async () => {
|
|
if (dateYearStart.value >= dateYearEnd.value) {
|
|
dialogMessage(
|
|
$q,
|
|
"ไม่สามารถคัดลอกวันหยุดได้",
|
|
"ปีที่เริ่มต้นคัดลอกต้องมากกว่าปีที่จะลงวันคัดลอก",
|
|
"warning",
|
|
undefined,
|
|
"orange",
|
|
undefined,
|
|
undefined,
|
|
true
|
|
);
|
|
return;
|
|
}
|
|
showLoader();
|
|
await http
|
|
.post(config.API.listHolidayCopy, {
|
|
fromYear: dateYearStart.value,
|
|
toYear: dateYearEnd.value,
|
|
})
|
|
.then((res) => {
|
|
modalCopy.value = false;
|
|
success($q, "คัดลอกวันหยุดสำเร็จ");
|
|
})
|
|
.catch((e) => {
|
|
messageError($q, e);
|
|
})
|
|
.finally(async () => {
|
|
refreshData.value = !refreshData.value;
|
|
await props.fetchDataSummaryCalendar();
|
|
});
|
|
};
|
|
|
|
/**
|
|
* แปลง ปีและเดือนเป็นภาษาไทย
|
|
* @param val datepicker แบบเลือกปีและเดือน
|
|
*/
|
|
const monthYearThai = (val: DataDateMonthObject) => {
|
|
if (val == null) return "";
|
|
else return monthYear2Thai(val.month, val.year);
|
|
};
|
|
|
|
/**
|
|
* แปลงช่วงวันที่ถ้า2ค่าเป็นวันเดียวกันจะโชววันเดียวแต่ถ้าไม่เท่ากันจะแสดงเป็นช่วง
|
|
* @param val ช่วงวันที่
|
|
*/
|
|
const dateThaiRange = (val: [Date, Date] | []) => {
|
|
if (val.length === 0) {
|
|
} else if (date2Thai(val[0]) === date2Thai(val[1])) {
|
|
return `${date2Thai(val[0])}`;
|
|
} else {
|
|
return `${date2Thai(val[0])} - ${date2Thai(val[1])} `;
|
|
}
|
|
};
|
|
</script>
|
|
|
|
<style>
|
|
.my-menu-link {
|
|
color: black;
|
|
background: #d0d0d0;
|
|
}
|
|
|
|
.my-list-link {
|
|
color: black;
|
|
border-radius: 5px;
|
|
background: #f4f4f4;
|
|
}
|
|
|
|
.my-list {
|
|
padding: 10px 10px;
|
|
}
|
|
|
|
.my-card {
|
|
width: 100%;
|
|
max-width: 160px;
|
|
}
|
|
|
|
.sub-card {
|
|
height: 100%;
|
|
max-height: 265px;
|
|
}
|
|
|
|
.cardNum {
|
|
border-radius: 5px;
|
|
}
|
|
|
|
.fc-direction-ltr .fc-daygrid-event.fc-event-end,
|
|
.fc-direction-rtl .fc-daygrid-event.fc-event-start {
|
|
padding-left: 5px;
|
|
}
|
|
</style>
|