hrms-mgt/src/modules/01_metadata/components/CalendarList.vue
Thanit Konmek fe6c712a18 new loader
2023-06-09 14:25:41 +07:00

588 lines
17 KiB
Vue

<!-- tab รายการ หนาปฏนวนหย -->
<template>
<q-card class="q-mt-md" flat bordered>
<!-- list รายการนหย -->
<q-tabs
dense
v-model="currentTab"
indicator-color="primary"
active-color="primary bg-teal-1"
class="text-body2 text-grey-7"
>
<q-tab
v-for="tab in tabs"
:key="tab.value"
v-on:click="changeTab(tab.value)"
:label="tab.label"
:name="tab.value"
class="q-py-xs col-6 row"
/>
</q-tabs>
<q-table
ref="table"
flat
bordered
class="custom-header-table"
virtual-scroll
:rows="calendarData"
:columns="columns"
dense
:rows-per-page-options="[0]"
hide-header
>
<template v-slot:body="props">
<q-tr :props="props">
<q-td v-for="col in props.cols" :key="col.name" :props="props">
<div v-if="col.name == 'week'" class="">
{{ dayThaiRange(props.row.dateRange) }}
</div>
<div v-else-if="col.name == 'holidayDate'" class="">
{{ dateThaiRange(props.row.dateRange) }}
</div>
<div v-else class="my-table-details">
{{ col.value }}
</div>
</q-td>
<q-td auto-width>
<q-btn
flat
round
color="grey"
@click.stop
size="10px"
icon="more_vert"
>
<q-menu>
<q-list>
<q-item
clickable
v-close-popup
@click="editCalendar(props.row)"
>
<q-item-section>
<q-item-label>แกไขวนหย</q-item-label>
</q-item-section>
</q-item>
<q-item
clickable
v-close-popup
@click="deleteClick(props.row)"
>
<q-item-section>
<q-item-label>ลบวนหย</q-item-label>
</q-item-section>
</q-item>
</q-list>
</q-menu>
</q-btn>
</q-td>
</q-tr>
</template>
</q-table>
</q-card>
<!-- modal เพมวนหย -->
<q-dialog v-model="modalAdd" persistent>
<q-card style="min-width: 550px">
<q-form ref="formDate" @submit.prevent.stop="editData">
<q-card-section class="row items-center q-pb-xs">
<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">
<div class="col-2 subName">
<label>เลอกวนท</label>
</div>
<div class="col-10">
<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
outlined
dense
class="full-width datepicker"
:model-value="dateThaiRange(dateAdd)"
>
<template v-slot:prepend>
<q-icon
name="event"
class="cursor-pointer"
style="color: var(--q-primary)"
>
</q-icon>
</template>
</q-input>
</template>
</datepicker>
</div>
</div>
<div class="row col-12 q-col-gutter-sm">
<div class="col-2 subName">
<label>คำอธบาย</label>
</div>
<div class="col-10">
<q-input
dense
borderless
class="full-width datepicker q-pb-none"
v-model="name"
type="textarea"
:rules="[(val) => (val && val.length > 0) || '']"
/>
</div>
</div>
</q-card-section>
<q-separator />
<q-card-actions align="right" class="text-primary">
<q-btn
flat
round
color="public"
icon="mdi-content-save-outline"
type="submit"
>
<q-tooltip>นท</q-tooltip>
</q-btn>
</q-card-actions>
</q-form>
</q-card>
</q-dialog>
<!-- modal ลบวนหย -->
<q-dialog v-model="modalDelete" persistent>
<q-card style="min-width: 550px">
<q-card-section class="row items-center q-pb-xs">
<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="row items-center">
<div class="q-pr-md">
<q-avatar
icon="mdi-trash-can-outline"
font-size="25px"
size="lg"
color="red-1"
text-color="red"
/>
</div>
<div class="col text-dark">
<span>อมลทกำลงถกลบนจะมผลใชงานทนท</span>
</div>
</q-card-section>
<q-separator />
<q-card-actions align="right" class="bg-white text-teal">
<q-btn label="ตกลง" color="primary" @click="deleteConfirm" />
</q-card-actions>
</q-card>
</q-dialog>
</template>
<script setup lang="ts">
import type { QTableProps } from "quasar";
import { onMounted, ref, watch } from "vue";
import http from "@/plugins/http";
import config from "@/app.config";
import { useQuasar } from "quasar";
import { useCounterMixin } from "@/stores/mixin";
import type {
RequestItemsObject,
DataDateRowObject,
DataDateAddObject,
DataDateListsObject,
TabsObject,
} from "@/modules/01_metadata/interface/request/Calendar";
import { useDataStore } from "@/stores/data";
const props = defineProps({
dateYear: {
//filter ปี วันหยุด
type: Number,
required: true,
},
refreshData: {
//หน้า main มีการอัพเดทค่าให้ refresh data
type: Boolean,
required: true,
},
fetchDataSummaryCalendar: {
//ฟังก์ชันอัพเดทสรุปวันหยุด
type: Function,
default: () => console.log("not function"),
},
});
const store = useDataStore();
const { loaderPage } = store;
const mixin = useCounterMixin(); //เรียกฟังก์ชันกลาง
const {
success,
dateToISO,
dateMonth2Thai,
weekThai,
messageError,
showLoader,
hideLoader,
} = mixin;
const $q = useQuasar(); //ใช้ noti quasar
const calendarData = ref<DataDateListsObject[]>([]); //data วันหยุด
const modalAdd = ref<boolean>(false); //modal เพิ่มวันหยุด
const modalDelete = ref<boolean>(false); //modal ลบวันหยุด
const name = ref<string>(""); //ชื่อวันหยุด
const isSpecial = ref<boolean>(true); //เช็ควันหยุด
const dateAdd = ref<[Date, Date]>([new Date(), new Date()]); //วันที่ ที่เพิ่มเป็นวันหยุด
const rowData = ref<DataDateListsObject>(); //data ที่ถูกเลือกใน row นั้น
const formDate = ref<any>(); //ref เพิ่ม แก้ไข วันหยุดสำหรับ validate
const currentTab = ref<string>("normal"); //เลือก tab ประเภทวันหยุด
const tabs = ref<TabsObject[]>([
{ label: "ทำงานจันทร์-ศุกร์ (5 วัน)", value: "normal" },
{ label: "ทำงานจันทร์-เสาร์ (6 วัน)", value: "6day" },
]); //tab ประเภทวันหยุดทั้งหมด
//columns รายการวันหยุด
const columns = ref<any>([
{
name: "week",
align: "left",
label: "-",
sortable: true,
field: "week",
style: "font-size: 15px",
},
{
name: "holidayDate",
align: "left",
label: "-",
sortable: true,
field: "holidayDate",
style: "font-size: 15px",
},
{
name: "detail",
align: "left",
label: "-",
sortable: true,
field: "detail",
style: "font-size: 15px",
},
]);
/**
* เรียกฟังก์ชันทั้งหมดตอนเรียกใช้ไฟล์นี้
*/
onMounted(async () => {
await fetchData();
});
/**
* ค่า props(วันปีที่เลือก และเพิ่มหรือแก้ไข) ตอนอัพเดท ค่าฏิทินให้อัพเดทใหม่
*/
watch(props, async (count, prevCount) => {
await fetchData();
});
/**
* กดปุ่มแก้ไขวันหยุด
* @param val data วันหยุดทั้ง row
*/
const editCalendar = async (val: DataDateListsObject) => {
rowData.value = val;
dateAdd.value = [val.dateRange[0], val.dateRange[1]];
name.value = val.detail;
isSpecial.value = true;
modalAdd.value = true;
};
/**
* กดปุ่มลบวันหยุด
* @param val data วันหยุดทั้ง row
*/
const deleteClick = async (val: DataDateListsObject) => {
rowData.value = val;
modalDelete.value = true;
};
/**
* fetch วันหยุดในรายการ
*/
const fetchData = async () => {
calendarData.value = [];
showLoader();
await http
.get(config.API.listHolidayHistoryYear(props.dateYear))
.then((res) => {
let data = res.data.result.normal;
if (currentTab.value == "6day") {
data = res.data.result.sixDays;
}
const dateStart = ref<Date | null>();
const firstEvent = ref<boolean>(true);
const dateRow = ref<DataDateRowObject[]>([]);
data.map((e: RequestItemsObject, index: number) => {
dateRow.value.push({
holidayDate: new Date(e.holidayDate),
name: e.name,
isSpecial: true,
id: e.id,
});
if (
index == data.length - 1 ||
data[index + 1].name != e.name ||
(data[index + 1].name == e.name &&
dateToISO(new Date(data[index + 1].holidayDate)) !=
dateToISO(
new Date(
new Date(e.holidayDate).setDate(
new Date(e.holidayDate).getDate() + 1
)
)
))
) {
firstEvent.value = true;
calendarData.value.push({
id: e.id,
dateRange: [
dateStart.value ? dateStart.value : new Date(e.holidayDate),
new Date(e.holidayDate),
],
dataRangeRow: dateRow.value,
detail:
dateToISO(new Date(e.holidayDate)) ==
dateToISO(new Date(e.originalDate))
? e.name
: `ชดเชย ${e.name}`,
isSpecial: true,
});
dateStart.value = null;
dateRow.value = [];
} else if (firstEvent.value == true) {
firstEvent.value = false;
dateStart.value = new Date(e.holidayDate);
}
});
})
.catch((e) => {
messageError($q, e);
})
.finally(async () => {
await props.fetchDataSummaryCalendar();
});
};
/**
* ลบข้อมูลวันหยุด
*/
const deleteConfirm = async () => {
modalDelete.value = false;
const dataDelete = ref<DataDateAddObject[]>([]);
if (rowData.value != null) {
await rowData.value.dataRangeRow.map((e: DataDateRowObject) => {
dataDelete.value.push({
year: new Date(e.holidayDate).getFullYear(),
holidayDate: dateToISO(e.holidayDate),
name: e.name,
isSpecial: true,
});
});
} else {
return;
}
showLoader();
await http
.post(
config.API.listHolidayHistoryDelete(currentTab.value),
dataDelete.value
)
.then((res) => {
success($q, "ลบข้อมูลสำเร็จ");
})
.catch((e) => {
messageError($q, e);
})
.finally(async () => {
await fetchData();
});
};
/**
* บันทึกแก้ไขวันหยุด
*/
const editData = async () => {
await formDate.value.validate().then(async (result: boolean) => {
if (result) {
const dataEdit = ref<DataDateAddObject[]>([]);
let i = 0;
const dateStart = ref<Date>(dateAdd.value[0]);
do {
i = i + 1;
dataEdit.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]));
const _dataHistory = ref<DataDateAddObject[]>([]);
if (rowData.value != null) {
rowData.value.dataRangeRow.map(
(e: DataDateRowObject, index: number) => {
_dataHistory.value.push({
year: new Date(e.holidayDate).getFullYear(),
holidayDate: dateToISO(e.holidayDate),
name: e.name,
isSpecial: true,
});
}
);
}
showLoader();
await http
.post(config.API.listHolidayHistoryEdit(currentTab.value), {
history: _dataHistory.value,
updated: dataEdit.value,
})
.then((res) => {
modalAdd.value = false;
success($q, "แก้ไขข้อมูลสำเร็จ");
})
.catch((e) => {
messageError($q, e);
})
.finally(async () => {
await fetchData();
});
} else {
}
});
};
/**
* เปลี่ยน tab ดูวันหยุดตามประเภท
* @param tab tab ประเภทวันหยุดที่เลือก
*/
const changeTab = async (tab: string) => {
currentTab.value = tab;
await fetchData();
};
/**
* แปลงช่วงวันที่ถ้า2ค่าเป็นวันเดียวกันจะโชววันเดียวแต่ถ้าไม่เท่ากันจะแสดงเป็นช่วง
* @param val ช่วงวันที่
*/
const dateThaiRange = (val: [Date, Date]) => {
if (val === null) {
return "";
} else if (dateMonth2Thai(val[0], true) === dateMonth2Thai(val[1], true)) {
return `${dateMonth2Thai(val[0], true)}`;
} else {
return `${dateMonth2Thai(val[0], true)} - ${dateMonth2Thai(val[1], true)}`;
}
};
/**
* แปลงช่วงวันที่ถ้า2ค่าเป็นวันเดียวกันจะโชววันเดียวแต่ถ้าไม่เท่ากันจะแสดงเป็นช่วง(เช่นวันจันทร์ -วันศุกร์)
* @param val ช่วงวันที่
*/
const dayThaiRange = (val: [Date, Date]) => {
if (val === null) {
} else if (dateToISO(val[0]) == dateToISO(val[1])) {
return `${weekThai(new Date(val[0]).getDay())}`;
} else {
return `${weekThai(new Date(val[0]).getDay())} - ${weekThai(
new Date(val[1]).getDay()
)}`;
}
};
</script>
<style lang="scss">
.custom-header-table {
max-height: 64vh;
.q-table tr:nth-child(odd) td {
background: white;
}
.q-table tr:nth-child(even) td {
background: #f8f8f8;
}
.q-table thead tr {
background: #ecebeb;
}
.q-table thead tr th {
position: sticky;
z-index: 1;
}
/* this will be the loading indicator */
.q-table thead tr:last-child th {
/* height of all previous header rows */
top: 48px;
}
.q-table thead tr:first-child th {
top: 0;
}
}
.my-table-details {
white-space: -moz-pre-wrap !important;
/* Mozilla, since 1999 */
white-space: -webkit-pre-wrap;
/* Chrome & Safari */
white-space: -pre-wrap;
/* Opera 4-6 */
white-space: -o-pre-wrap;
/* Opera 7 */
white-space: pre-wrap;
/* CSS3 */
word-wrap: break-word;
/* Internet Explorer 5.5+ */
word-break: break-all;
white-space: normal;
}
.table_ellipsis {
overflow: hidden;
text-overflow: ellipsis;
white-space: wrap;
max-width: 250px;
}
</style>