hrms-mgt/src/modules/04_registryPerson/components/detail/Achievement/02_Train.vue
2025-02-25 15:27:01 +07:00

1225 lines
40 KiB
Vue

<script setup lang="ts">
import { ref, reactive, onMounted } from "vue";
import { QForm, useQuasar } from "quasar";
import { useRoute } from "vue-router";
import { checkPermission } from "@/utils/permissions";
import type { QTableProps } from "quasar";
import { useCounterMixin } from "@/stores/mixin";
import http from "@/plugins/http";
import config from "@/app.config";
import type { RequestItemsObject } from "@/modules/04_registryPerson/interface/request/Training";
import type { ResponseObject } from "@/modules/04_registryPerson/interface/response/Training";
import dialogHeader from "@/components/DialogHeader.vue";
/** props*/
const isLeave = defineModel<boolean>("isLeave", {
required: true,
});
const route = useRoute();
const $q = useQuasar();
const mixin = useCounterMixin();
const {
dialogConfirm,
showLoader,
hideLoader,
messageError,
success,
date2Thai,
pathRegistryEmp,
onSearchDataTable,
} = mixin;
const id = ref<string>(route.params.id.toString());
const empType = ref<string>(pathRegistryEmp(route.name?.toString() ?? ""));
const mode = ref<string>("table"); //การแสดงผล Table,Card
const dialog = ref<boolean>(false); //แสดง popup การฝึกอบรม/ดูงาน
const dialogStatus = ref<string>("create"); //สถานะการแก้ไขข้อมูล
const editId = ref<string>(""); //id ที่ต้องการแก้ไข
const historyDialog = ref<boolean>(false); //แสดง popup ประวัติแก้ไข
const isDate = ref<string>("false"); //ปี ,วัน/เดือน/ปี
const trainData = reactive<RequestItemsObject>({
profileId: id.value,
name: "", //ชื่อโครงการ/หลักสูตรการฝึกอบรม
topic: "", //หัวข้อการฝึกอบรม/ดูงาน
startYear: new Date().getFullYear(), //ปีที่เริ่มต้นการฝึกอบรม/ดูงาน
finishYear: new Date().getFullYear(), //ปีที่จบการฝึกอบรม/ดูงาน
startDate: new Date(), //วันที่เริ่มต้นการฝึกอบรม/ดูงาน
endDate: new Date(), //วันที่จบการฝึกอบรม/ดูงาน
yearly: null, //ปีงบประมาณ
place: "", //สถานที่ฝึกอบรม/ดูงาน
duration: "", //รวมระยะเวลาในการฝึกอบรม/ดูงาน
department: "", //หน่วยงานที่รับผิดชอบจัดการฝึกอบรม/ดูงาน
numberOrder: "", //เลขที่คำสั่ง/เลขที่หนังสืออนุมัติ
dateOrder: null, //คำสั่งลงวันที่/หนังสืออนุมัติลงวันที่
isDate: isDate.value === "false" ? false : true,
});
//Table Main
const rows = ref<ResponseObject[]>([]);
const rowsMain = ref<ResponseObject[]>([]);
const keyword = ref<string>("");
const columns = ref<QTableProps["columns"]>([
{
name: "name",
align: "left",
label: "ชื่อโครงการ/หลักสูตรการฝึกอบรม",
sortable: true,
field: "name",
headerStyle: "font-size: 14px",
style: "font-size: 14px",
sort: (a: string, b: string) =>
a.localeCompare(b, undefined, { numeric: true, sensitivity: "base" }),
},
{
name: "topic",
align: "left",
label: "หัวข้อการฝึกอบรม/ดูงาน",
sortable: true,
field: "topic",
headerStyle: "font-size: 14px",
style: "font-size: 14px",
sort: (a: string, b: string) =>
a.localeCompare(b, undefined, { numeric: true, sensitivity: "base" }),
},
{
name: "startDate",
align: "left",
label: "วันเริ่มต้นการฝึกอบรม/ดูงาน",
sortable: true,
field: "startDate",
format(val, row) {
return row.isDate
? date2Thai(row.startDate)
: new Date(row.startDate).getFullYear() + 543;
},
headerStyle: "font-size: 14px",
style: "font-size: 14px",
sort: (a: string, b: string) =>
a
.toString()
.localeCompare(b, undefined, { numeric: true, sensitivity: "base" }),
},
{
name: "endDate",
align: "left",
label: "วันสิ้นสุดการฝึกอบรม/ดูงาน",
sortable: true,
field: "endDate",
format(val, row) {
return row.isDate
? date2Thai(row.endDate)
: new Date(row.endDate).getFullYear() + 543;
},
headerStyle: "font-size: 14px",
style: "font-size: 14px",
sort: (a: string, b: string) =>
a
.toString()
.localeCompare(b, undefined, { numeric: true, sensitivity: "base" }),
},
{
name: "yearly",
align: "left",
label: "ปีที่อบรม (พ.ศ.)",
sortable: true,
field: "yearly",
format: (v) => (v !== null ? v + 543 : "-"),
headerStyle: "font-size: 14px",
style: "font-size: 14px",
sort: (a: string, b: string) =>
a
.toString()
.localeCompare(b, undefined, { numeric: true, sensitivity: "base" }),
},
{
name: "place",
align: "left",
label: "สถานที่ฝึกอบรม/ดูงาน",
sortable: true,
field: "place",
headerStyle: "font-size: 14px",
style: "font-size: 14px",
sort: (a: string, b: string) =>
a.localeCompare(b, undefined, { numeric: true, sensitivity: "base" }),
},
{
name: "duration",
align: "left",
label: "รวมระยะเวลาในการฝึกอบรม/ดูงาน",
sortable: true,
field: "duration",
headerStyle: "font-size: 14px",
style: "font-size: 14px",
sort: (a: string, b: string) =>
a.localeCompare(b, undefined, { numeric: true, sensitivity: "base" }),
},
{
name: "department",
align: "left",
label: "หน่วยงานที่รับผิดชอบจัดการฝึกอบรม/ดูงาน",
sortable: true,
field: "department",
headerStyle: "font-size: 14px",
style: "font-size: 14px",
sort: (a: string, b: string) =>
a.localeCompare(b, undefined, { numeric: true, sensitivity: "base" }),
},
{
name: "numberOrder",
align: "left",
label: "เลขที่คำสั่ง/เลขที่หนังสืออนุมัติ",
sortable: true,
field: "numberOrder",
headerStyle: "font-size: 14px",
style: "font-size: 14px",
sort: (a: string, b: string) =>
a.localeCompare(b, undefined, { numeric: true, sensitivity: "base" }),
},
{
name: "dateOrder",
align: "left",
label: "คำสั่งลงวันที่/หนังสืออนุมัติลงวันที่",
sortable: true,
field: "dateOrder",
format: (v) => date2Thai(v),
headerStyle: "font-size: 14px",
style: "font-size: 14px",
sort: (a: string, b: string) =>
a.localeCompare(b, undefined, { numeric: true, sensitivity: "base" }),
},
{
name: "lastUpdatedAt",
align: "left",
label: "วันที่แก้ไข",
sortable: true,
field: "lastUpdatedAt",
format: (v) => date2Thai(v, false, true),
headerStyle: "font-size: 14px",
style: "font-size: 14px",
sort: (a: string, b: string) =>
a.localeCompare(b, undefined, { numeric: true, sensitivity: "base" }),
},
]);
const visibleColumns = ref<string[]>([
"name", // ชื่อโครงงาน
"topic", // หัวข้อ
"yearly", // ปีที่อบรม
"place", // สถานที่
"duration", // รวมระยะเวลา
"department", // หน่วยงานที่รับผิดชอบ
"numberOrder", // เลขที่คำสั่ง
"dateOrder", // คำสั่งลงวันที่
"startDate", // วันเริ่มต้น
"endDate", // วันสิ้นสุด
"lastUpdatedAt",
]);
const pagination = ref({
sortBy: "lastUpdatedAt",
});
//Table ประวัติแก้ไข
const historyRows = ref<ResponseObject[]>([]);
const historyRowsMain = ref<ResponseObject[]>([]);
const historyKeyword = ref<string>("");
const historyColumns = ref<QTableProps["columns"]>([
{
name: "name",
align: "left",
label: "ชื่อโครงการ/หลักสูตรการฝึกอบรม",
sortable: true,
field: "name",
headerStyle: "font-size: 14px",
style: "font-size: 14px",
sort: (a: string, b: string) =>
a.localeCompare(b, undefined, { numeric: true, sensitivity: "base" }),
},
{
name: "topic",
align: "left",
label: "หัวข้อการฝึกอบรม/ดูงาน",
sortable: true,
field: "topic",
headerStyle: "font-size: 14px",
style: "font-size: 14px",
sort: (a: string, b: string) =>
a.localeCompare(b, undefined, { numeric: true, sensitivity: "base" }),
},
{
name: "startDate",
align: "left",
label: "วันเริ่มต้นการฝึกอบรม/ดูงาน",
sortable: true,
field: "startDate",
format(val, row) {
return row.isDate
? date2Thai(row.startDate)
: new Date(row.startDate).getFullYear() + 543;
},
headerStyle: "font-size: 14px",
style: "font-size: 14px",
sort: (a: string, b: string) =>
a
.toString()
.localeCompare(b, undefined, { numeric: true, sensitivity: "base" }),
},
{
name: "endDate",
align: "left",
label: "วันสิ้นสุดการฝึกอบรม/ดูงาน",
sortable: true,
field: "endDate",
format(val, row) {
return row.isDate
? date2Thai(row.endDate)
: new Date(row.endDate).getFullYear() + 543;
},
headerStyle: "font-size: 14px",
style: "font-size: 14px",
sort: (a: string, b: string) =>
a
.toString()
.localeCompare(b, undefined, { numeric: true, sensitivity: "base" }),
},
{
name: "yearly",
align: "left",
label: "ปีที่อบรม (พ.ศ.)",
sortable: true,
field: "yearly",
format: (v) => (v !== null ? v + 543 : "-"),
headerStyle: "font-size: 14px",
style: "font-size: 14px",
sort: (a: string, b: string) =>
a
.toString()
.localeCompare(b, undefined, { numeric: true, sensitivity: "base" }),
},
{
name: "place",
align: "left",
label: "สถานที่ฝึกอบรม/ดูงาน",
sortable: true,
field: "place",
headerStyle: "font-size: 14px",
style: "font-size: 14px",
sort: (a: string, b: string) =>
a.localeCompare(b, undefined, { numeric: true, sensitivity: "base" }),
},
{
name: "duration",
align: "left",
label: "รวมระยะเวลาในการฝึกอบรม/ดูงาน",
sortable: true,
field: "duration",
headerStyle: "font-size: 14px",
style: "font-size: 14px",
sort: (a: string, b: string) =>
a.localeCompare(b, undefined, { numeric: true, sensitivity: "base" }),
},
{
name: "department",
align: "left",
label: "หน่วยงานที่รับผิดชอบจัดการฝึกอบรม/ดูงาน",
sortable: true,
field: "department",
headerStyle: "font-size: 14px",
style: "font-size: 14px",
sort: (a: string, b: string) =>
a.localeCompare(b, undefined, { numeric: true, sensitivity: "base" }),
},
{
name: "numberOrder",
align: "left",
label: "เลขที่คำสั่ง/เลขที่หนังสืออนุมัติ",
sortable: true,
field: "numberOrder",
headerStyle: "font-size: 14px",
style: "font-size: 14px",
sort: (a: string, b: string) =>
a.localeCompare(b, undefined, { numeric: true, sensitivity: "base" }),
},
{
name: "dateOrder",
align: "left",
label: "คำสั่งลงวันที่/หนังสืออนุมัติลงวันที่",
sortable: true,
field: "dateOrder",
format: (v) => date2Thai(v),
headerStyle: "font-size: 14px",
style: "font-size: 14px",
sort: (a: string, b: string) =>
a.localeCompare(b, undefined, { numeric: true, sensitivity: "base" }),
},
{
name: "lastUpdateFullName",
align: "left",
label: "ผู้ดำเนินการ",
sortable: true,
field: "lastUpdateFullName",
headerStyle: "font-size: 14px",
style: "font-size: 14px",
sort: (a: string, b: string) =>
a.localeCompare(b, undefined, { numeric: true, sensitivity: "base" }),
},
{
name: "lastUpdatedAt",
align: "left",
label: "วันที่แก้ไข",
sortable: true,
field: "lastUpdatedAt",
format: (v) => date2Thai(v, false, true),
headerStyle: "font-size: 14px",
style: "font-size: 14px",
sort: (a: string, b: string) =>
a.localeCompare(b, undefined, { numeric: true, sensitivity: "base" }),
},
]);
const historyVisibleColumns = ref<string[]>([
"name", // ชื่อโครงงาน
"topic", // หัวข้อ
"yearly", // ปีที่อบรม
"place", // สถานที่
"duration", // รวมระยะเวลา
"department", // หน่วยงานที่รับผิดชอบ
"numberOrder", // เลขที่คำสั่ง
"dateOrder", // คำสั่งลงวันที่
"startDate", // วันเริ่มต้น
"endDate", // วันสิ้นสุด
"lastUpdateFullName", // แก้ไขโดย
"lastUpdatedAt", // แก้ไขเมื่อวันที่
]);
const historyPagination = ref({
sortBy: "lastUpdatedAt",
});
/** ยืนยันการบันทึกข้อมูล*/
function onSubmit() {
dialogConfirm(
$q,
() => {
dialogStatus.value === "create" ? addData() : editData(editId.value);
},
"ยืนยันการบันทึกข้อมูล",
"ต้องการยืนยันการบันทึกข้อมูลนี้หรือไม่ ?"
);
}
/** เคลียร์ form ฝึกอบรม/ดูงาน */
function clearForm() {
isDate.value = "false";
trainData.name = "";
trainData.topic = "";
trainData.yearly = null;
trainData.place = "";
trainData.duration = "";
trainData.department = "";
trainData.numberOrder = "";
trainData.dateOrder = new Date();
trainData.startDate = new Date();
trainData.endDate = new Date();
}
/** เปิด popoup แก้ไขข้อมูลฝึกอบรม/ดูงาน */
function editForm(row: any) {
dialogStatus.value = "edit";
editId.value = row.id;
isDate.value = row.isDate ? "true" : "false";
trainData.name = row.name;
trainData.topic = row.topic;
trainData.yearly = row.yearly;
trainData.place = row.place;
trainData.duration = row.duration;
trainData.department = row.department;
trainData.numberOrder = row.numberOrder;
trainData.dateOrder = row.dateOrder;
trainData.startDate = row.startDate;
trainData.endDate = row.endDate;
trainData.startYear = +row.startDate.slice(0, 4);
trainData.finishYear = +row.endDate.slice(0, 4);
dialog.value = true;
}
/** เพิ่มข้อมูลการฝึกอบรม/ดูงาน*/
function addData() {
showLoader();
http
.post(config.API.profileNewTraining(empType.value), {
...trainData,
startYear: undefined,
finishYear: undefined,
isDate: isDate.value === "false" ? false : true,
profileId: empType.value === "" ? id.value : undefined,
profileEmployeeId: empType.value !== "" ? id.value : undefined,
})
.then(async () => {
await fetchData(id.value);
await success($q, "บันทึกข้อมูลสำเร็จ");
closeDialog();
})
.catch((err) => {
messageError($q, err);
})
.finally(() => {
hideLoader();
});
}
/**
* แก้ไขข้อมูลการฝึกอบรม/ดูงาน
* @param idData รายการฝึกอบรม/ดูงาน
*/
function editData(idData: string) {
showLoader();
http
.patch(config.API.profileNewTrainingByTrainingId(idData, empType.value), {
...trainData,
profileId: undefined,
startYear: undefined,
finishYear: undefined,
isDate: isDate.value === "false" ? false : true,
})
.then(async () => {
await fetchData(id.value);
await success($q, "บันทึกข้อมูลสำเร็จ");
closeDialog();
})
.catch((err) => {
messageError($q, err);
})
.finally(() => {
hideLoader();
});
}
/** ปิด from การฝึกอบรม/ดูงาน*/
function closeDialog() {
dialog.value = false;
clearForm();
}
/** ปิด ประวัติการแก่ไขการฝึกอบรม/ดูงาน */
function closeHistoryDialog() {
historyDialog.value = false;
historyRows.value = [];
historyKeyword.value = "";
}
/** fetch รายการการฝึกอบรม/ดูงาน*/
async function fetchData(id: string) {
showLoader();
await http
.get(config.API.profileNewTrainingByProfileId(id, empType.value))
.then(async (res) => {
rows.value = await res.data.result;
rowsMain.value = await res.data.result;
})
.catch((err) => {
messageError($q, err);
})
.finally(() => {
hideLoader();
});
}
/** fetch ประวัติรายการแก้ไขการฝึกอบรม/ดูงาน*/
function fetchHistoryData(id: string) {
showLoader();
http
.get(config.API.profileNewTrainingHisByTrainingId(id, empType.value))
.then((res) => {
historyRows.value = res.data.result;
historyRowsMain.value = res.data.result;
})
.catch((err) => {
messageError($q, err);
})
.finally(() => {
hideLoader();
});
}
function serchDataTable() {
rows.value = onSearchDataTable(
keyword.value,
rowsMain.value,
columns.value ? columns.value : []
);
}
function serchDataTableHistory() {
historyRows.value = onSearchDataTable(
historyKeyword.value,
historyRowsMain.value,
historyColumns.value ? historyColumns.value : []
);
}
/** ทำงานเมื่อ Components ถูกเรียกใช้งาน*/
onMounted(() => {
fetchData(id.value);
});
</script>
<template>
<div class="row items-center q-gutter-x-sm q-pb-sm">
<q-btn
v-if="isLeave == false && checkPermission($route)?.attrIsUpdate"
round
dense
flat
color="primary"
icon="add"
@click="
() => {
dialogStatus = 'create';
clearForm;
dialog = true;
}
"
>
<q-tooltip>เพิ่มข้อมูล</q-tooltip></q-btn
>
<q-space />
<q-input
dense
outlined
v-model="keyword"
label="ค้นหา"
@keydown.enter.pervent="serchDataTable"
>
<template v-slot:append>
<q-icon name="search" />
</template>
</q-input>
<q-select
v-if="mode === 'table'"
v-model="visibleColumns"
multiple
outlined
dense
options-dense
:display-value="$q.lang.table.columns"
emit-value
map-options
:options="columns"
option-value="name"
style="min-width: 140px"
/>
<q-btn-toggle
v-model="mode"
dense
class="no-shadow toggle-borderd"
toggle-color="grey-4"
:options="[
{ value: 'table', slot: 'table' },
{ value: 'card', slot: 'card' },
]"
>
<template v-slot:table>
<q-icon
name="format_list_bulleted"
size="24px"
:style="{
color: mode === 'table' ? '#787B7C' : '#C9D3DB',
}"
/>
</template>
<template v-slot:card>
<q-icon
name="mdi-view-grid-outline"
size="24px"
:style="{
color: mode === 'card' ? '#787B7C' : '#C9D3DB',
}"
/>
</template>
</q-btn-toggle>
</div>
<d-table
:grid="mode === 'card'"
ref="table"
:columns="columns"
:rows="rows"
row-key="name"
flat
bordered
dense
v-model:pagination="pagination"
class="custom-header-table"
:visible-columns="visibleColumns"
>
<template v-slot:header="props">
<q-tr :props="props">
<q-th auto-width />
<q-th v-for="col in props.cols" :key="col.name" :props="props">
<span class="text-weight-medium">{{ col.label }}</span>
</q-th>
</q-tr>
</template>
<template v-slot:body="props" v-if="mode === 'table'">
<q-tr :props="props">
<q-td auto-width>
<q-btn
flat
dense
round
color="deep-purple"
icon="mdi-history"
@click="
() => (fetchHistoryData(props.row.id), (historyDialog = true))
"
>
<q-tooltip>ประวัติแก้ไขการฝึกอบรม/ดูงาน</q-tooltip>
</q-btn>
<q-btn
v-if="isLeave == false && checkPermission($route)?.attrIsUpdate"
flat
dense
round
color="edit"
icon="edit"
@click="
() => {
editForm(props.row);
}
"
>
<q-tooltip>แก้ไขข้อมูล</q-tooltip>
</q-btn>
</q-td>
<q-td v-for="col in props.cols" :key="col.id">
<div>
{{ col.value ? col.value : "-" }}
</div>
</q-td>
</q-tr>
</template>
<template v-slot:item="props" v-else>
<div
class="q-pa-xs col-xs-12 col-sm-6 col-md-6 col-lg-6 grid-style-transition"
>
<q-card bordered>
<q-card-actions align="right" class="bg-grey-3">
<q-btn
flat
round
color="deep-purple"
icon="mdi-history"
@click="
() => (fetchHistoryData(props.row.id), (historyDialog = true))
"
>
<q-tooltip>ประวัติแก้ไขการฝึกอบรม/ดูงาน</q-tooltip>
</q-btn>
<q-btn
v-if="isLeave == false && checkPermission($route)?.attrIsUpdate"
flat
round
color="edit"
icon="edit"
@click="editForm(props.row)"
>
<q-tooltip>แก้ไขข้อมูล</q-tooltip>
</q-btn>
</q-card-actions>
<q-separator />
<q-list>
<div
v-for="(col, index) in props.cols"
:key="col.name"
:style="`background-color: ${index % 2 !== 0 ? '#FAFAFA' : ''}`"
>
<div class="row q-pa-sm">
<div class="col-7 label-color">
<div>{{ col.label }}</div>
</div>
<div class="col">
<div>{{ col.value }}</div>
</div>
</div>
</div>
</q-list>
</q-card>
</div>
</template>
</d-table>
<q-dialog v-model="dialog" class="dialog" persistent>
<q-card>
<q-form @submit.prevent greedy @validation-success="onSubmit()">
<dialog-header
:tittle="
dialogStatus == 'edit'
? 'แก้ไขการฝึกอบรม/ดูงาน'
: 'เพิ่มการฝึกอบรม/ดูงาน'
"
:close="closeDialog"
/>
<q-separator />
<q-card-section>
<div class="row q-mb-sm q-gutter-sm">
<div class="col">
<q-input
outlined
v-model="trainData.name"
label="ชื่อโครงการ/หลักสูตรการฝึกอบรม"
bg-color="white"
dense
class="inputgreen"
:rules="[
(val:string) =>
!!val || `${'กรุณากรอกชื่อโครงการ/หลักสูตรการฝึกอบรม'}`,
]"
hide-bottom-space
/>
</div>
<div class="col">
<q-input
outlined
class="inputgreen"
v-model="trainData.topic"
label="หัวข้อการฝึกอบรม/ดูงาน"
bg-color="white"
dense
:rules="[
(val:string) => !!val || `${'กรุณากรอกหัวข้อการฝึกอบรม/ดูงาน'}`,
]"
hide-bottom-space
/>
</div>
</div>
<q-card flat bordered class="q-px-sm q-my-sm q-pb-sm borderCard">
<div class="row col-12 q-gutter-md q-py-sm text-grey-7">
<q-radio
v-model="isDate"
checked-icon="task_alt"
unchecked-icon="panorama_fish_eye"
val="false"
label="ปี"
dense
/>
<q-radio
v-model="isDate"
checked-icon="task_alt"
unchecked-icon="panorama_fish_eye"
val="true"
label="วัน/เดือน/ปี"
dense
/>
</div>
<div v-if="isDate === 'false'" class="row q-gutter-sm">
<div class="col">
<datepicker
menu-class-name="modalfix"
v-model="trainData.startYear"
:locale="'th'"
autoApply
year-picker
:enableTimePicker="false"
@update:modelValue="
(v:number) =>
(trainData.startDate = new Date(
`${v}-01-01T00:00:02.010+07:00`
))
"
>
<template #year="{ year }">{{ year + 543 }}</template>
<template #year-overlay-value="{ value }">{{
parseInt(value + 543)
}}</template>
<template #trigger>
<q-input
dense
outlined
class="inputgreen"
hide-bottom-space
:model-value="trainData.startYear + 543"
:rules="[
(val:string) =>
!!val ||
`${'กรุณาเลือกปีที่เริ่มต้นการฝึกอบรม/ดูงาน'}`,
]"
:label="`${'ปีที่เริ่มต้นการฝึกอบรม/ดูงาน'}`"
>
<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 class="col">
<datepicker
menu-class-name="modalfix"
v-model="trainData.finishYear"
:locale="'th'"
autoApply
year-picker
:enableTimePicker="false"
@update:modelValue="
(v:number) =>
(trainData.endDate = new Date(
`${v}-01-01T00:00:02.010+07:00`
))
"
>
<template #year="{ year }">{{ year + 543 }}</template>
<template #year-overlay-value="{ value }">{{
parseInt(value + 543)
}}</template>
<template #trigger>
<q-input
dense
class="inputgreen"
outlined
hide-bottom-space
:model-value="trainData.finishYear + 543"
:rules="[
(val:string) =>
!!val || `${'กรุณาเลือกปีที่จบการฝึกอบรม/ดูงาน'}`,
]"
:label="`${'ปีที่จบการฝึกอบรม/ดูงาน'}`"
>
<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 v-if="isDate === 'true'" class="row q-gutter-sm">
<div class="col">
<datepicker
menu-class-name="modalfix"
v-model="trainData.startDate"
:locale="'th'"
autoApply
:enableTimePicker="false"
week-start="0"
@update:modelValue="
(v: Date) =>
(trainData.startYear = parseInt(
v.toString().slice(11, 15)
))
"
>
<template #year="{ year }">{{ year + 543 }}</template>
<template #year-overlay-value="{ value }">{{
parseInt(value + 543)
}}</template>
<template #trigger>
<q-input
outlined
dense
class="inputgreen"
:model-value="date2Thai(trainData.startDate)"
:rules="[
(val:string) =>
!!val ||
`${'กรุณาเลือกวันที่เริ่มต้นการฝึกอบรม/ดูงาน'}`,
]"
hide-bottom-space
:label="`${'วันที่เริ่มต้นการฝึกอบรม/ดูงาน'}`"
>
<template v-slot:prepend>
<q-icon
name="event"
class="cursor-pointer"
color="primary"
>
</q-icon>
</template>
</q-input>
</template>
</datepicker>
</div>
<div class="col">
<datepicker
menu-class-name="modalfix"
v-model="trainData.endDate"
:locale="'th'"
autoApply
:enableTimePicker="false"
week-start="0"
@update:modelValue="
(v: Date) =>
(trainData.finishYear = parseInt(
v.toString().slice(11, 15)
))
"
>
<template #year="{ year }">{{ year + 543 }}</template>
<template #year-overlay-value="{ value }">{{
parseInt(value + 543)
}}</template>
<template #trigger>
<q-input
outlined
dense
class="inputgreen"
:model-value="date2Thai(trainData.endDate)"
:rules="[
(val:string) =>
!!val || `${'กรุณาเลือกวันที่จบการฝึกอบรม/ดูงาน'}`,
]"
hide-bottom-space
:label="`${'วันที่จบการฝึกอบรม/ดูงาน'}`"
>
<template v-slot:prepend>
<q-icon
name="event"
class="cursor-pointer"
color="primary"
>
</q-icon>
</template>
</q-input>
</template>
</datepicker>
</div>
</div>
</q-card>
<div class="row q-mb-sm q-gutter-sm">
<div class="col">
<datepicker
menu-class-name="modalfix"
v-model="trainData.yearly"
:locale="'th'"
autoApply
year-picker
:enableTimePicker="false"
@update:modelValue="trainData.yearly"
>
<template #year="{ year }">{{ year + 543 }}</template>
<template #year-overlay-value="{ value }">{{
parseInt(value + 543)
}}</template>
<template #trigger>
<q-input
dense
outlined
class="inputgreen"
clearable
@clear="() => (trainData.yearly = null)"
hide-bottom-space
:model-value="
!!trainData.yearly ? trainData.yearly + 543 : null
"
:label="`${'ปีงบประมาณ'}`"
@update:modelValue="trainData.yearly = null"
>
<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 class="col">
<q-input
outlined
v-model="trainData.place"
label="สถานที่ฝึกอบรม/ดูงาน"
bg-color="white"
class="inputgreen"
dense
:rules="[
(val:string) => !!val || `${'กรุณากรอกสถานที่ฝึกอบรม/ดูงาน'}`,
]"
hide-bottom-space
/>
</div>
</div>
<div class="row q-mb-sm q-gutter-sm">
<div class="col">
<q-input
outlined
class="inputgreen"
v-model="trainData.duration"
label="รวมระยะเวลาในการฝึกอบรม/ดูงาน"
bg-color="white"
dense
/>
</div>
<div class="col">
<q-input
outlined
class="inputgreen"
v-model="trainData.department"
label="หน่วยงานที่รับผิดชอบจัดการฝึกอบรม/ดูงาน"
bg-color="white"
dense
/>
</div>
</div>
<div class="row q-mb-sm q-gutter-sm">
<div class="col">
<q-input
class="inputgreen"
outlined
v-model="trainData.numberOrder"
label="เลขที่คำสั่ง/เลขที่หนังสืออนุมัติ"
bg-color="white"
dense
/>
</div>
<div class="col">
<datepicker
menu-class-name="modalfix"
v-model="trainData.dateOrder"
:locale="'th'"
autoApply
: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="inputgreen"
clearable
@clear="() => (trainData.dateOrder = null)"
@update:modelValue="trainData.dateOrder = null"
:model-value="date2Thai(trainData.dateOrder)"
hide-bottom-space
:label="`${'คำสั่งลงวันที่/หนังสืออนุมัติลงวันที่'}`"
>
<template v-slot:prepend>
<q-icon
name="event"
class="cursor-pointer"
color="primary"
>
</q-icon>
</template>
</q-input>
</template>
</datepicker>
</div>
</div>
</q-card-section>
<q-separator />
<q-card-actions align="right">
<q-btn label="บันทึก" id="onSubmit" type="submit" color="public">
<q-tooltip>บันทึกข้อมูล</q-tooltip>
</q-btn>
</q-card-actions>
</q-form>
</q-card>
</q-dialog>
<q-dialog v-model="historyDialog" class="dialog" persistent>
<q-card style="min-width: 80%">
<dialog-header
tittle="ประวัติแก้ไขการฝึกอบรม/ดูงาน"
:close="closeHistoryDialog"
/>
<q-separator />
<q-card-section style="max-height: 60vh" class="scroll">
<div class="row q-gutter-sm q-mb-sm">
<q-space />
<q-input
dense
outlined
bg-color="white"
v-model="historyKeyword"
label="ค้นหา"
@keydown.enter.pervent="serchDataTableHistory"
>
<template v-slot:append>
<q-icon name="search" />
</template>
</q-input>
<q-select
v-model="historyVisibleColumns"
multiple
outlined
dense
bg-color="white"
options-dense
:display-value="$q.lang.table.columns"
emit-value
map-options
:options="historyColumns"
option-value="name"
style="min-width: 140px"
/>
</div>
<d-table
ref="table"
:columns="historyColumns"
:rows="historyRows"
row-key="name"
flat
v-model:pagination="historyPagination"
bordered
dense
class="custom-header-table"
:visible-columns="historyVisibleColumns"
>
<template v-slot:header="props">
<q-tr :props="props">
<q-th v-for="col in props.cols" :key="col.name" :props="props">
<span class="text-weight-medium">{{ col.label }}</span>
</q-th>
</q-tr>
</template>
<template v-slot:body="props">
<q-tr :props="props">
<q-td v-for="col in props.cols" :key="col.id">
<div>
{{ col.value ? col.value : "-" }}
</div>
</q-td>
</q-tr>
</template>
</d-table>
</q-card-section>
</q-card>
</q-dialog>
</template>
<style scoped>
.borderCard {
border: 1px solid #d0d0d0;
}
.label-color {
color: #747474cc;
}
.bg-color {
background-color: #fafafa;
}
</style>