This commit is contained in:
Warunee Tamkoo 2024-08-01 12:12:28 +07:00
parent 46533bbd62
commit 15d3ac574d
128 changed files with 347 additions and 322 deletions

View file

@ -0,0 +1,785 @@
<script setup lang="ts">
import { ref, reactive, watch, onMounted } from "vue";
import dialogHeader from "@/components/DialogHeader.vue";
import type { QTableProps } from "quasar";
import { useCounterMixin } from "@/stores/mixin";
import { QForm, useQuasar } from "quasar";
import { useRoute } from "vue-router";
import type { RequestItemsObject } from "@/modules/04_registryPerson/interface/request/ProfesLicense";
import type { ResponseObject } from "@/modules/04_registryPerson/interface/response/ProfesLicense";
import http from "@/plugins/http";
import config from "@/app.config";
const mixin = useCounterMixin();
const $q = useQuasar();
const {
dialogConfirm,
showLoader,
hideLoader,
messageError,
success,
date2Thai,
} = mixin;
const historyDialog = ref<boolean>(false);
const mode = ref<string>("table");
const dialog = ref<boolean>(false);
const route = useRoute();
const id = ref<string>(route.params.id.toString());
const empType = ref<string>(
route.name === "registryNewByid" ? "" : "-employee"
);
const dialogStatus = ref<string>("create");
const editId = ref<string>("");
const keyword = ref<string>("");
const historyKeyword = ref<string>("");
const columns = ref<QTableProps["columns"]>([
{
name: "certificateType",
align: "left",
label: "ชื่อใบอนุญาต",
sortable: true,
field: "certificateType",
headerStyle: "font-size: 14px",
style: "font-size: 14px",
sort: (a: string, b: string) =>
a.localeCompare(b, undefined, { numeric: true, sensitivity: "base" }),
},
{
name: "issuer",
align: "left",
label: "หน่วยงานผู้ออกใบอนุญาต",
sortable: true,
field: "issuer",
headerStyle: "font-size: 14px",
style: "font-size: 14px",
sort: (a: string, b: string) =>
a.localeCompare(b, undefined, { numeric: true, sensitivity: "base" }),
},
{
name: "certificateNo",
align: "left",
label: "เลขที่ใบอนุญาต",
sortable: true,
field: "certificateNo",
headerStyle: "font-size: 14px",
style: "font-size: 14px",
sort: (a: string, b: string) =>
a.localeCompare(b, undefined, { numeric: true, sensitivity: "base" }),
},
{
name: "issueDate",
align: "left",
label: "วันที่ออกใบอนุญาต",
sortable: true,
field: "issueDate",
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: "expireDate",
align: "left",
label: "วันที่หมดอายุ",
sortable: true,
format: (v) => date2Thai(v),
field: "expireDate",
headerStyle: "font-size: 14px",
style: "font-size: 14px",
sort: (a: string, b: string) =>
a.localeCompare(b, undefined, { numeric: true, sensitivity: "base" }),
},
]);
const historyColumns = ref<QTableProps["columns"]>([
{
name: "certificateType",
align: "left",
label: "ชื่อใบอนุญาต",
sortable: true,
field: "certificateType",
headerStyle: "font-size: 14px",
style: "font-size: 14px",
sort: (a: string, b: string) =>
a.localeCompare(b, undefined, { numeric: true, sensitivity: "base" }),
},
{
name: "issuer",
align: "left",
label: "หน่วยงานผู้ออกใบอนุญาต",
sortable: true,
field: "issuer",
headerStyle: "font-size: 14px",
style: "font-size: 14px",
sort: (a: string, b: string) =>
a.localeCompare(b, undefined, { numeric: true, sensitivity: "base" }),
},
{
name: "certificateNo",
align: "left",
label: "เลขที่ใบอนุญาต",
sortable: true,
field: "certificateNo",
headerStyle: "font-size: 14px",
style: "font-size: 14px",
sort: (a: string, b: string) =>
a.localeCompare(b, undefined, { numeric: true, sensitivity: "base" }),
},
{
name: "issueDate",
align: "left",
label: "วันที่ออกใบอนุญาต",
sortable: true,
field: "issueDate",
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: "expireDate",
align: "left",
label: "วันที่หมดอายุ",
sortable: true,
format: (v) => date2Thai(v),
field: "expireDate",
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),
headerStyle: "font-size: 14px",
style: "font-size: 14px",
sort: (a: string, b: string) =>
a.localeCompare(b, undefined, { numeric: true, sensitivity: "base" }),
},
]);
const profesLicenseData = reactive<RequestItemsObject>({
certificateType: "",
issuer: "",
certificateNo: "",
issueDate: new Date(),
expireDate: null,
profileId: id.value,
});
const rows = ref<ResponseObject[]>([]);
const historyRows = ref<ResponseObject[]>([]);
const pagination = ref({
page: 1,
rowsPerPage: 10,
});
const historyPagination = ref({
page: 1,
rowsPerPage: 10,
});
const visibleColumns = ref<string[]>([
"certificateType",
"issuer",
"certificateNo",
"issueDate",
"expireDate",
]);
const historyVisibleColumns = ref<string[]>([
"certificateType",
"issuer",
"certificateNo",
"issueDate",
"expireDate",
"lastUpdateFullName",
"lastUpdatedAt",
]);
async function onSubmit() {
dialogConfirm(
$q,
async () => {
dialogStatus.value === "create" ? addData() : editData(editId.value);
closeDialog();
},
"ยืนยันการบันทึกข้อมูล",
"ต้องการยืนยันการบันทึกข้อมูลนี้หรือไม่ ?"
);
}
function closeDialog() {
dialog.value = false;
}
function closeHistoryDialog() {
historyDialog.value = false;
}
async function fetchData(id: string) {
showLoader();
await http
.get(config.API.profileNewCertificateByProfileId(id, empType.value))
.then(async (res) => {
rows.value = res.data.result;
})
.catch((err) => {
messageError($q, err);
})
.finally(() => {
hideLoader();
});
}
function clearForm() {
profesLicenseData.expireDate = null;
profesLicenseData.issueDate = new Date();
profesLicenseData.certificateNo = "";
profesLicenseData.certificateType = "";
profesLicenseData.issuer = "";
}
function editForm(row: any) {
dialogStatus.value = "edit";
editId.value = row.id;
profesLicenseData.certificateType = row.certificateType;
profesLicenseData.certificateNo = row.certificateNo;
profesLicenseData.issuer = row.issuer;
profesLicenseData.issueDate = row.issueDate;
profesLicenseData.expireDate = row.expireDate;
dialog.value = true;
}
async function addData() {
await http
.post(config.API.profileNewCertificate(empType.value), {
...profesLicenseData,
profileId: empType.value === "" ? id.value : undefined,
profileEmployeeId: empType.value !== "" ? id.value : undefined,
})
.then(() => {
fetchData(id.value);
success($q, "บันทึกข้อมูลสำเร็จ");
})
.catch((err) => {
messageError($q, err);
})
.finally(() => {
hideLoader();
});
}
async function editData(idData: string) {
await http
.patch(
config.API.profileNewCertificateByCertificateId(idData, empType.value),
{
...profesLicenseData,
profileId: undefined,
}
)
.then(() => {
fetchData(id.value);
success($q, "บันทึกข้อมูลสำเร็จ");
})
.catch((err) => {
messageError($q, err);
})
.finally(() => {
hideLoader();
});
}
// function deleteData(idData: string) {
// dialogRemove($q, () =>
// http
// .delete(config.API.profileNewCertificateByCertificateId(idData))
// .then(() => {
// fetchData(id.value);
// })
// .catch((err) => {
// messageError($q, err);
// })
// .finally(() => {
// hideLoader();
// })
// );
// }
async function fetchHistoryData(id: string) {
showLoader();
await http
.get(config.API.profileNewCertificateHisByCertificateId(id, empType.value))
.then(async (res) => {
historyRows.value = res.data.result;
})
.catch((err) => {
messageError($q, err);
})
.finally(() => {
hideLoader();
});
}
onMounted(async () => {
await fetchData(id.value);
});
</script>
<template>
<div class="row items-center q-gutter-x-sm q-pb-sm">
<q-btn
round
flat
color="primary"
icon="add"
dense
@click="
dialogStatus = 'create';
clearForm();
dialog = true;
"
>
<q-tooltip>เพมขอม</q-tooltip></q-btn
>
<q-space />
<q-input dense outlined v-model="keyword" label="ค้นหา">
<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"
options-cover
style="min-width: 150px"
/>
<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
:paging="true"
dense
:filter="keyword"
v-model:pagination="pagination"
:rows-per-page-options="[20, 50, 100]"
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" class="cursor-pointer">
<q-td auto-width>
<q-btn
color="primary"
flat
dense
round
class="q-mr-xs"
size="14px"
icon="mdi-pencil-outline"
clickable
@click="
() => {
editForm(props.row);
}
"
>
<q-tooltip>แกไขขอม</q-tooltip>
</q-btn>
<q-btn
color="info"
flat
dense
round
size="14px"
icon="mdi-history"
@click="
() => (fetchHistoryData(props.row.id), (historyDialog = true))
"
>
<q-tooltip>ประวแกไขใบอนญาตประกอบวชาช</q-tooltip>
</q-btn>
<!-- <q-btn
color="red"
flat
dense
round
size="14px"
icon="mdi-delete"
clickable
@click.stop="deleteData(props.row.id)"
v-close-popup
>
<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="primary"
icon="edit"
@click="editForm(props.row)"
>
<q-tooltip>แกไขขอม</q-tooltip>
</q-btn>
<q-btn
flat
round
color="info"
icon="mdi-history"
size="14px"
@click="
() => (fetchHistoryData(props.row.id), (historyDialog = true))
"
>
<q-tooltip>ประวแกไขใบอนญาตประกอบวชาช</q-tooltip>
</q-btn>
</q-card-actions>
<q-separator />
<q-list>
<div
:class="`row q-pa-sm`"
:style="`background-color: ${index % 2 !== 0 ? '#FAFAFA' : ''}`"
v-for="(col, index) in props.cols"
:key="col.name"
>
<div></div>
<div class="col label-color">
<div>{{ col.label }}</div>
</div>
<div class="col">
<div>{{ col.value }}</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-col-gutter-sm q-pb-sm">
<div class="col-xs-12 col-md-6">
<q-input
outlined
v-model="profesLicenseData.certificateType"
label="ชื่อใบอนุญาต"
bg-color="white"
dense
class="inputgreen"
:rules="[(val) => !!val || `${'กรุณากรอกชื่อใบอนุญาต'}`]"
hide-bottom-space
/>
</div>
<div class="col-xs-12 col-md-6">
<q-input
outlined
v-model="profesLicenseData.issuer"
label="หน่วยงานผู้ออกใบอนุญาต"
bg-color="white"
dense
class="inputgreen"
:rules="[
(val) => !!val || `${'กรุณากรอกหน่วยงานผู้ออกใบอนุญาต'}`,
]"
hide-bottom-space
/>
</div>
</div>
<div class="row q-col-gutter-sm q-pb-sm">
<div class="col-xs-12 col-md-6">
<q-input
outlined
v-model="profesLicenseData.certificateNo"
label="เลขที่ใบอนุญาต"
bg-color="white"
class="inputgreen"
dense
:rules="[(val) => !!val || `${'กรุณากรอกเลขที่ใบอนุญาต'}`]"
hide-bottom-space
/>
</div>
<div class="col-xs-12 col-md-6">
<datepicker
menu-class-name="modalfix"
v-model="profesLicenseData.issueDate"
:locale="'th'"
autoApply
class="col"
:enableTimePicker="false"
@update:modelValue="profesLicenseData.issueDate"
>
<template #year="{ year }">{{ year + 543 }}</template>
<template #year-overlay-value="{ value }">{{
parseInt(value + 543)
}}</template>
<template #trigger>
<q-input
dense
class="inputgreen"
outlined
bg-color="white"
hide-bottom-space
:model-value="
profesLicenseData.issueDate
? date2Thai(profesLicenseData.issueDate)
: ''
"
:rules="[
(val) => !!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 class="row q-gutter-sm q-pb-sm">
<div class="col">
<datepicker
menu-class-name="modalfix"
v-model="profesLicenseData.expireDate"
:locale="'th'"
autoApply
:enableTimePicker="false"
@update:modelValue="profesLicenseData.expireDate"
>
<template #year="{ year }">{{ year + 543 }}</template>
<template #year-overlay-value="{ value }">{{
parseInt(value + 543)
}}</template>
<template #trigger>
<q-input
dense
outlined
bg-color="white"
class="inputgreen"
clearable
@clear="() => (profesLicenseData.expireDate = null)"
hide-bottom-space
:model-value="
profesLicenseData.expireDate
? date2Thai(profesLicenseData.expireDate)
: ''
"
:label="`${'วันที่หมดอายุ'}`"
@update:modelValue="profesLicenseData.expireDate = 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>
</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="ค้นหา"
>
<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"
options-cover
style="min-width: 150px"
/>
</div>
<d-table
ref="table"
:columns="historyColumns"
:rows="historyRows"
row-key="name"
flat
:filter="historyKeyword"
v-model:pagination="historyPagination"
bordered
:paging="true"
dense
:rows-per-page-options="[20, 50, 100]"
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-th auto-width />
</q-tr>
</template>
<template v-slot:body="props">
<q-tr :props="props" class="cursor-pointer">
<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>
.bg-color {
background-color: #fafafa;
}
.label-color {
color: #747474cc;
}
</style>

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,835 @@
<script setup lang="ts">
import { ref, onMounted, reactive, watch } from "vue";
import { useRoute } from "vue-router";
import { useQuasar } from "quasar";
import http from "@/plugins/http";
import config from "@/app.config";
import type { QTableProps, QForm } from "quasar";
import { useCounterMixin } from "@/stores/mixin";
import DialogHeader from "@/components/DialogHeader.vue";
import type { RequestItemsObject } from "@/modules/04_registryPerson/interface/request/DeclarationHonor";
import type { ResponseObject } from "@/modules/04_registryPerson/interface/response/DeclarationHonor";
const $q = useQuasar();
const route = useRoute();
const mixin = useCounterMixin();
const {
date2Thai,
success,
messageError,
showLoader,
hideLoader,
dialogConfirm,
} = mixin;
const profileId = ref<string>(
route.params.id ? route.params.id.toString() : ""
);
const empType = ref<string>(
route.name === "registryNewByid" ? "" : "-employee"
);
const id = ref<string>("");
const issueDateYear = ref<number>(0);
const declHonorForm = reactive<RequestItemsObject>({
isDate: "false",
issuer: "",
detail: "",
issueDate: null,
refCommandNo: "",
refCommandDate: null,
});
const isEdit = ref<boolean>(false);
const modal = ref<boolean>(false);
const modeView = ref<string>("table");
const filterSearch = ref("");
const filterHistory = ref<string>("");
const modalHistory = ref<boolean>(false);
const rowsHistory = ref<ResponseObject[]>([]);
const rows = ref<ResponseObject[]>([]);
const columns = ref<QTableProps["columns"]>([
{
name: "issueDate",
align: "left",
label: "วันที่ได้รับ",
sortable: true,
field: (v) =>
v.isDate
? date2Thai(v.issueDate)
: new Date(v.issueDate).getFullYear() + 543,
headerStyle: "font-size: 14px",
style: "font-size: 14px",
},
{
name: "issuer",
align: "left",
label: "ผู้มีอำนาจลงนาม",
sortable: true,
field: "issuer",
headerStyle: "font-size: 14px",
style: "font-size: 14px",
sort: (a: string, b: string) =>
a.localeCompare(b, undefined, { numeric: true, sensitivity: "base" }),
},
{
name: "detail",
align: "left",
label: "รายละเอียด",
sortable: true,
field: "detail",
headerStyle: "font-size: 14px",
style: "font-size: 14px",
sort: (a: string, b: string) =>
a.localeCompare(b, undefined, { numeric: true, sensitivity: "base" }),
},
{
name: "refCommandNo",
align: "left",
label: "เลขที่คำสั่ง",
sortable: true,
field: "refCommandNo",
headerStyle: "font-size: 14px",
style: "font-size: 14px",
sort: (a: string, b: string) =>
a.localeCompare(b, undefined, { numeric: true, sensitivity: "base" }),
},
{
name: "refCommandDate",
align: "left",
label: "เอกสารอ้างอิง (ลงวันที่)",
sortable: true,
field: "refCommandDate",
headerStyle: "font-size: 14px",
style: "font-size: 14px",
format: (v) => date2Thai(v),
sort: (a: string, b: string) =>
a.localeCompare(b, undefined, { numeric: true, sensitivity: "base" }),
},
]);
const columnsHistory = ref<QTableProps["columns"]>([
{
name: "issueDate",
align: "left",
label: "วันที่ได้รับ",
sortable: true,
field: (v) =>
v.isDate
? date2Thai(v.issueDate)
: new Date(v.issueDate).getFullYear() + 543,
headerStyle: "font-size: 14px",
style: "font-size: 14px",
},
{
name: "issuer",
align: "left",
label: "ผู้มีอำนาจลงนาม",
sortable: true,
field: "issuer",
headerStyle: "font-size: 14px",
style: "font-size: 14px",
sort: (a: string, b: string) =>
a.localeCompare(b, undefined, { numeric: true, sensitivity: "base" }),
},
{
name: "detail",
align: "left",
label: "รายละเอียด",
sortable: true,
field: "detail",
headerStyle: "font-size: 14px",
style: "font-size: 14px",
sort: (a: string, b: string) =>
a.localeCompare(b, undefined, { numeric: true, sensitivity: "base" }),
},
{
name: "refCommandNo",
align: "left",
label: "เลขที่คำสั่ง",
sortable: true,
field: "refCommandNo",
headerStyle: "font-size: 14px",
style: "font-size: 14px",
sort: (a: string, b: string) =>
a.localeCompare(b, undefined, { numeric: true, sensitivity: "base" }),
},
{
name: "refCommandDate",
align: "left",
label: "เอกสารอ้างอิง (ลงวันที่)",
sortable: true,
field: "refCommandDate",
headerStyle: "font-size: 14px",
style: "font-size: 14px",
format: (v) => date2Thai(v),
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",
headerStyle: "font-size: 14px",
style: "font-size: 14px",
format: (v) => date2Thai(v),
sort: (a: string, b: string) =>
a.localeCompare(b, undefined, { numeric: true, sensitivity: "base" }),
},
]);
const visibleColumns = ref<String[]>([
"issuer",
"detail",
"issueDate",
"refCommandNo",
"refCommandDate",
]);
const visibleColumnsHistory = ref<String[]>([
"issuer",
"detail",
"issueDate",
"refCommandNo",
"refCommandDate",
"lastUpdateFullName",
"lastUpdatedAt",
]);
const pagination = ref({
page: 1,
rowsPerPage: 10,
});
const historyPagination = ref({
page: 1,
rowsPerPage: 10,
});
async function fetchData() {
if (!profileId.value) return;
showLoader();
try {
const res = await http.get(
config.API.profileNewHonorByProfileId(profileId.value, empType.value)
);
rows.value = res.data.result;
} catch (error) {
messageError($q, error);
} finally {
hideLoader();
}
}
async function addEditData(editStatus: boolean = false) {
if (!profileId.value) return;
const url = editStatus
? config.API.profileNewHonorById(id.value, empType.value)
: config.API.profileNewHonor(empType.value);
const method = editStatus ? "patch" : "post";
const reqBody: RequestItemsObject = {
...declHonorForm,
profileEmployeeId:
!editStatus && empType.value !== "" ? profileId.value : undefined,
profileId:
!editStatus && empType.value === "" ? profileId.value : undefined,
isDate: declHonorForm.isDate === "true" ? true : false,
issueDate:
declHonorForm.isDate === "true"
? declHonorForm.issueDate
: new Date(`${issueDateYear.value}-01-01`),
};
try {
await http[method](url, reqBody);
success($q, "บันทึกข้อมูลสำเร็จ");
await fetchData();
} catch (e) {
messageError($q, e);
} finally {
hideLoader();
}
}
function onClickOpenDialog(editStatus: boolean = false, row?: ResponseObject) {
modal.value = true;
isEdit.value = editStatus;
if (editStatus && row) {
id.value = row.id;
issueDateYear.value = new Date(row.issueDate).getFullYear();
declHonorForm.issuer = row.issuer;
declHonorForm.detail = row.detail;
declHonorForm.issueDate = row.issueDate;
declHonorForm.refCommandNo = row.refCommandNo;
declHonorForm.refCommandDate = row.refCommandDate;
declHonorForm.isDate = row.isDate ? "true" : "false";
} else {
clearData();
}
}
async function clickClose() {
clearData();
modal.value = false;
}
async function clickHistory(row: ResponseObject) {
modalHistory.value = true;
filterSearch.value = "";
showLoader();
try {
const res = await http.get(
config.API.profileNewHonorHisById(row.id, empType.value)
);
rowsHistory.value = res.data.result;
} catch (e) {
messageError($q, e);
} finally {
hideLoader();
}
}
function onSubmit() {
dialogConfirm(
$q,
async () => {
addEditData(isEdit.value);
modal.value = false;
},
"ยืนยันการบันทึกข้อมูล",
"ต้องการยืนยันการบันทึกข้อมูลนี้หรือไม่ ?"
);
}
function clearData() {
id.value = "";
issueDateYear.value = new Date().getFullYear();
declHonorForm.issuer = "";
declHonorForm.detail = "";
declHonorForm.issueDate = new Date();
declHonorForm.refCommandNo = "";
declHonorForm.refCommandDate = null;
declHonorForm.isDate = "false";
}
onMounted(async () => {
await fetchData();
});
</script>
<template>
<div class="row items-center q-gutter-x-sm q-pb-sm">
<q-btn
dense
color="primary"
icon="add"
flat
round
@click="onClickOpenDialog()"
><q-tooltip>เพมขอม</q-tooltip></q-btn
>
<q-space />
<q-input
standout
dense
v-model="filterSearch"
ref="filterRef"
outlined
placeholder="ค้นหา"
debounce="300"
>
<template v-slot:append>
<q-icon
v-if="filterSearch == ''"
name="search"
@click.stop.prevent="filterSearch = ''"
class="cursor-pointer"
/>
<q-icon
v-if="filterSearch"
name="cancel"
@click.stop.prevent="filterSearch = ''"
class="cursor-pointer"
/>
</template>
</q-input>
<q-select
v-if="modeView == 'table'"
v-model="visibleColumns"
multiple
outlined
dense
options-dense
:display-value="$q.lang.table.columns"
emit-value
map-options
:options="columns"
option-value="name"
options-cover
style="min-width: 150px"
/>
<q-btn-toggle
v-model="modeView"
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: modeView === 'table' ? '#787B7C' : '#C9D3DB',
}"
/>
</template>
<template v-slot:card>
<q-icon
name="mdi-view-grid-outline"
size="24px"
:style="{
color: modeView === 'card' ? '#787B7C' : '#C9D3DB',
}"
/>
</template>
</q-btn-toggle>
</div>
<d-table
flat
dense
bordered
:rows="rows"
:paging="true"
:columns="columns"
:filter="filterSearch"
:grid="modeView === 'card'"
v-model:pagination="pagination"
:visible-columns="visibleColumns"
:rows-per-page-options="[20, 50, 100]"
:card-container-class="modeView === 'card' ? 'q-col-gutter-md' : ''"
>
<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="modeView === 'table'">
<q-tr :props="props">
<q-td auto-width>
<q-btn
flat
dense
round
class="q-mr-xs"
size="14px"
color="primary"
icon="mdi-pencil-outline"
@click="onClickOpenDialog(true, props.row)"
>
<q-tooltip>แกไขขอม</q-tooltip>
</q-btn>
<q-btn
color="info"
flat
dense
round
size="14px"
icon="mdi-history"
@click="clickHistory(props.row)"
>
<q-tooltip>ประวแกไขประกาศเกยรต</q-tooltip>
</q-btn>
</q-td>
<q-td
v-for="col in props.cols"
:key="col.name"
:props="props"
class="cursor-pointer"
>
<div class="table_ellipsis">
{{ col.value ? col.value : "-" }}
</div>
</q-td>
</q-tr>
</template>
<template v-slot:item="props" v-else>
<div class="col-xs-12 col-sm-6 col-md-6">
<q-card bordered>
<q-card-actions class="bg-grey-3" align="right">
<q-btn
flat
round
color="primary"
icon="mdi-pencil-outline"
@click="onClickOpenDialog(true, props.row)"
>
<q-tooltip>แกไขขอม</q-tooltip>
</q-btn>
<q-btn
flat
round
color="info"
icon="mdi-history"
@click.stop.prevent="clickHistory(props.row)"
>
<q-tooltip>ประวแกไขประกาศเกยรต</q-tooltip>
</q-btn>
</q-card-actions>
<q-separator />
<div>
<q-item
v-for="(col, index) in props.cols.filter(
(col) => col.name !== 'desc'
)"
:key="col.name"
:class="index % 2 !== 0 ? 'bg-grey-1' : ''"
>
<q-item-section class="col-7 text-grey-6">
<q-item-label>{{ col.label }}</q-item-label>
</q-item-section>
<q-item-section class="text-dark">
<q-item-label>
{{ col.value ? col.value : "-" }}
</q-item-label>
</q-item-section>
</q-item>
</div>
</q-card>
</div>
</template>
</d-table>
<q-dialog v-model="modal" persistent>
<q-card>
<q-form greedy @submit.prevent @validation-success="onSubmit">
<DialogHeader
:tittle="
isEdit
? 'แก้ไขข้อมูลประกาศเกียรติคุณ'
: 'เพิ่มข้อมูลประกาศเกียรติคุณ'
"
:close="clickClose"
/>
<q-separator />
<q-card-section>
<div class="row col-12 q-col-gutter-sm">
<div class="row col-12 q-gutter-md q-py-sm text-grey-7">
<q-radio
v-model="(declHonorForm.isDate as string)"
dense
checked-icon="task_alt"
unchecked-icon="panorama_fish_eye"
val="false"
label="ปี"
/>
<q-radio
v-model="(declHonorForm.isDate as string)"
checked-icon="task_alt"
unchecked-icon="panorama_fish_eye"
val="true"
label="วัน/เดือน/ปี"
dense
/>
</div>
<div class="col-xs-6 col-sm-6 col-md-6">
<datepicker
autoApply
year-picker
v-model="issueDateYear"
week-start="0"
menu-class-name="modalfix"
:locale="'th'"
:enableTimePicker="false"
@update:modelValue="
(v:number) =>
(declHonorForm.issueDate = new Date(
`${v}-01-01T00:00:02.010+07:00`
))
"
v-if="declHonorForm.isDate === 'false'"
>
<template #year="{ year }">{{ year + 543 }}</template>
<template #year-overlay-value="{ value }">{{
parseInt(value + 543)
}}</template>
<template #trigger>
<q-input
dense
outlined
hide-bottom-space
class="inputgreen"
:model-value="issueDateYear + 543"
:rules="[
(val:string) =>
!!val ||
`${'กรุณาเลือกปีที่ได้รับ'}`,
]"
:label="`${'ปีที่ได้รับ'}`"
>
<template v-slot:prepend>
<q-icon
name="event"
class="cursor-pointer"
color="primary"
/>
</template>
</q-input>
</template>
</datepicker>
<datepicker
autoApply
borderless
v-else
week-start="0"
menu-class-name="modalfix"
v-model="declHonorForm.issueDate"
:locale="'th'"
:enableTimePicker="false"
@update:modelValue="
(v: Date) =>
(issueDateYear = 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
dense
outlined
hide-bottom-space
for="inputDatereceive"
ref="dateReceivedRef"
class="inputgreen"
:model-value="date2Thai(declHonorForm.issueDate)"
:label="`${'วันที่ได้รับ'}`"
:rules="[(val) => !!val || `${'กรุณาเลือกวันที่ได้รับ'}`]"
>
<template v-slot:prepend>
<q-icon
name="event"
class="cursor-pointer"
color="primary"
/>
</template>
</q-input>
</template>
</datepicker>
</div>
<div class="col-xs-6 col-sm-6 col-md-6">
<q-input
dense
outlined
lazy-rules
hide-bottom-space
class="inputgreen"
v-model="declHonorForm.issuer"
:label="`${'ผู้มีอำนาจลงนาม'}`"
/>
</div>
<div class="col-12">
<q-input
dense
outlined
lazy-rules
hide-bottom-space
class="inputgreen"
v-model="declHonorForm.detail"
:label="`${'รายละเอียด'}`"
:rules="[(val) => !!val || `${'กรุณากรอกรายละเอียด'}`]"
/>
</div>
<div class="col-xs-6 col-sm-6 col-md-6">
<q-input
dense
outlined
lazy-rules
hide-bottom-space
class="inputgreen"
v-model="declHonorForm.refCommandNo"
:label="`${'เลขที่คำสั่ง'}`"
>
<template v-slot:append>
<q-icon name="mdi-file" class="cursor-pointer" />
</template>
</q-input>
</div>
<div class="col-xs-6 col-sm-6 col-md-6">
<datepicker
autoApply
borderless
week-start="0"
menu-class-name="modalfix"
v-model="declHonorForm.refCommandDate"
:locale="'th'"
:enableTimePicker="false"
>
<template #year="{ year }">
{{ year + 543 }}
</template>
<template #year-overlay-value="{ value }">
{{ parseInt(value + 543) }}
</template>
<template #trigger>
<q-input
dense
outlined
clearable
hide-bottom-space
class="inputgreen"
:model-value="
declHonorForm.refCommandDate == null
? null
: date2Thai(declHonorForm.refCommandDate)
"
:label="`${'เอกสารอ้างอิง (ลงวันที่)'}`"
@clear="declHonorForm.refCommandDate = null"
>
<template v-slot:prepend>
<q-icon
name="event"
class="cursor-pointer"
color="primary"
/>
</template>
</q-input>
</template>
</datepicker>
</div>
</div>
</q-card-section>
<q-separator color="grey-4" />
<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="modalHistory" persistent>
<q-card style="min-width: 80%">
<q-card-section class="flex justify-between" style="padding: 0">
<DialogHeader
tittle="ประวัติแก้ไขประกาศเกียรติคุณ"
:close="() => (modalHistory = false)"
/>
</q-card-section>
<q-separator />
<q-card-section class="q-p-sm">
<div class="row q-gutter-sm q-mb-sm">
<q-space />
<q-input
standout
dense
v-model="filterHistory"
ref="filterRef"
outlined
placeholder="ค้นหา"
debounce="300"
>
<template v-slot:append>
<q-icon
v-if="filterHistory == ''"
name="search"
@click.stop.prevent="filterHistory = ''"
class="cursor-pointer"
/>
<q-icon
v-if="filterHistory"
name="cancel"
@click.stop.prevent="filterHistory = ''"
class="cursor-pointer"
/>
</template>
</q-input>
<q-select
v-model="visibleColumnsHistory"
multiple
outlined
dense
options-dense
:display-value="$q.lang.table.columns"
emit-value
map-options
:options="columnsHistory"
option-value="name"
options-cover
style="min-width: 150px"
/>
</div>
<d-table
ref="table"
flat
bordered
dense
:columns="columnsHistory"
:rows="rowsHistory"
:paging="true"
v-model:pagination="historyPagination"
:rows-per-page-options="[10, 25, 50, 100]"
:visible-columns="visibleColumnsHistory"
:filter="filterHistory"
>
>
<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" class="cursor-pointer">
<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></style>

View file

@ -0,0 +1,847 @@
<script setup lang="ts">
import { onMounted, ref, watch, reactive } from "vue";
import { useRoute } from "vue-router";
import { useQuasar } from "quasar";
import http from "@/plugins/http";
import config from "@/app.config";
import type { QTableProps, QForm } from "quasar";
import { useCounterMixin } from "@/stores/mixin";
import { useResultsPerformDataStore } from "@/modules/04_registryPerson/stores/ResultsPerformance";
import DialogHeader from "@/components/DialogHeader.vue";
import type { RequestItemsObject } from "@/modules/04_registryPerson/interface/request/ResultsPerformance";
import type { ResponseObject } from "@/modules/04_registryPerson/interface/response/ResultsPerformance";
const $q = useQuasar();
const route = useRoute();
const store = useResultsPerformDataStore();
const { textRangePoint, textPoint } = store;
const mixin = useCounterMixin();
const {
date2Thai,
success,
messageError,
showLoader,
hideLoader,
dialogConfirm,
} = mixin;
const profileId = ref<string>(
route.params.id ? route.params.id.toString() : ""
);
const empType = ref<string>(
route.name === "registryNewByid" ? "" : "-employee"
);
const id = ref<string>("");
const resPerformForm = reactive<RequestItemsObject>({
name: "",
point1Total: 0,
point1: 0,
point2Total: 0,
point2: 0,
pointSumTotal: 0,
pointSum: 0,
date: null,
});
const currentPage = ref<number>(1);
const maxPage = ref<number>(1);
const currentPageHistory = ref<number>(1);
const maxPageHistory = ref<number>(1);
const isEdit = ref<boolean>(false);
const modal = ref<boolean>(false);
const modeView = ref<string>("table");
const filterSearch = ref("");
const filterHistory = ref<string>("");
const modalHistory = ref<boolean>(false);
const rowsHistory = ref<ResponseObject[]>([]);
const rows = ref<ResponseObject[]>([]);
const columns = ref<QTableProps["columns"]>([
{
name: "date",
align: "left",
label: "วันที่ได้รับ",
sortable: true,
field: "date",
headerStyle: "font-size: 14px",
style: "font-size: 14px",
format: (v) => date2Thai(v),
},
{
name: "point1Total",
align: "left",
label: "ส่วนที่1 (น้ำหนัก)",
sortable: true,
field: "point1Total",
headerStyle: "font-size: 14px",
style: "font-size: 14px",
sort: (a: string, b: string) =>
a.localeCompare(b, undefined, { numeric: true, sensitivity: "base" }),
},
{
name: "point1",
align: "left",
label: "ผลประเมินส่วนที่1 (คะแนน)",
sortable: true,
field: "point1",
headerStyle: "font-size: 14px",
style: "font-size: 14px",
sort: (a: string, b: string) =>
a.localeCompare(b, undefined, { numeric: true, sensitivity: "base" }),
},
{
name: "point2Total",
align: "left",
label: "ส่วนที่2 (น้ำหนัก)",
sortable: true,
field: "point2Total",
headerStyle: "font-size: 14px",
style: "font-size: 14px",
sort: (a: string, b: string) =>
a.localeCompare(b, undefined, { numeric: true, sensitivity: "base" }),
},
{
name: "point2",
align: "left",
label: "ผลประเมินส่วนที่2 (คะแนน)",
sortable: true,
field: "point2",
headerStyle: "font-size: 14px",
style: "font-size: 14px",
sort: (a: string, b: string) =>
a.localeCompare(b, undefined, { numeric: true, sensitivity: "base" }),
},
{
name: "pointSumTotal",
align: "left",
label: "ผลรวม (น้ำหนัก)",
sortable: true,
field: "pointSumTotal",
headerStyle: "font-size: 14px",
style: "font-size: 14px",
sort: (a: string, b: string) =>
a.localeCompare(b, undefined, { numeric: true, sensitivity: "base" }),
},
{
name: "pointSum",
align: "left",
label: "ผลประเมินรวม (คะแนน)",
sortable: true,
field: "pointSum",
headerStyle: "font-size: 14px",
style: "font-size: 14px",
sort: (a: string, b: string) =>
a.localeCompare(b, undefined, { numeric: true, sensitivity: "base" }),
},
{
name: "name",
align: "left",
label: "ผลประเมิน",
sortable: true,
field: (v) => `${textPoint(v.pointSum)} ${textRangePoint(v.pointSum)}`,
headerStyle: "font-size: 14px",
style: "font-size: 14px",
sort: (a: string, b: string) =>
a.localeCompare(b, undefined, { numeric: true, sensitivity: "base" }),
},
]);
const columnsHistory = ref<QTableProps["columns"]>([
{
name: "date",
align: "left",
label: "วันที่ได้รับ",
sortable: true,
field: "date",
headerStyle: "font-size: 14px",
style: "font-size: 14px",
format: (v) => date2Thai(v),
},
{
name: "point1Total",
align: "left",
label: "ส่วนที่1 (น้ำหนัก)",
sortable: true,
field: "point1Total",
headerStyle: "font-size: 14px",
style: "font-size: 14px",
},
{
name: "point1",
align: "left",
label: "ผลประเมินส่วนที่1 (คะแนน)",
sortable: true,
field: "point1",
headerStyle: "font-size: 14px",
style: "font-size: 14px",
sort: (a: string, b: string) =>
a.localeCompare(b, undefined, { numeric: true, sensitivity: "base" }),
},
{
name: "point2Total",
align: "left",
label: "ส่วนที่2 (น้ำหนัก)",
sortable: true,
field: "point2Total",
headerStyle: "font-size: 14px",
style: "font-size: 14px",
sort: (a: string, b: string) =>
a.localeCompare(b, undefined, { numeric: true, sensitivity: "base" }),
},
{
name: "point2",
align: "left",
label: "ผลประเมินส่วนที่2 (คะแนน)",
sortable: true,
field: "point2",
headerStyle: "font-size: 14px",
style: "font-size: 14px",
sort: (a: string, b: string) =>
a.localeCompare(b, undefined, { numeric: true, sensitivity: "base" }),
},
{
name: "pointSumTotal",
align: "left",
label: "ผลรวม (น้ำหนัก)",
sortable: true,
field: "pointSumTotal",
headerStyle: "font-size: 14px",
style: "font-size: 14px",
sort: (a: string, b: string) =>
a.localeCompare(b, undefined, { numeric: true, sensitivity: "base" }),
},
{
name: "pointSum",
align: "left",
label: "ผลประเมินรวม (คะแนน)",
sortable: true,
field: "pointSum",
headerStyle: "font-size: 14px",
style: "font-size: 14px",
sort: (a: string, b: string) =>
a.localeCompare(b, undefined, { numeric: true, sensitivity: "base" }),
},
{
name: "name",
align: "left",
label: "ผลประเมิน",
sortable: true,
field: (v) => `${textPoint(v.pointSum)} ${textRangePoint(v.pointSum)}`,
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",
headerStyle: "font-size: 14px",
style: "font-size: 14px",
format: (v) => date2Thai(v),
sort: (a: string, b: string) =>
a.localeCompare(b, undefined, { numeric: true, sensitivity: "base" }),
},
]);
const visibleColumnsHistory = ref<String[]>([
"point1Total",
"point1",
"point2Total",
"point2",
"pointSumTotal",
"pointSum",
"name",
"date",
"lastUpdateFullName",
"lastUpdatedAt",
]);
const visibleColumns = ref<String[]>([
"point1Total",
"point1",
"point2Total",
"point2",
"pointSumTotal",
"pointSum",
"name",
"date",
]);
const pagination = ref({
page: 1,
rowsPerPage: 10,
});
const historyPagination = ref({
page: 1,
rowsPerPage: 10,
});
async function fetchData() {
if (!profileId.value) return;
showLoader();
try {
const res = await http.get(
config.API.profileNewAssessmentsByProfileId(
profileId.value,
empType.value
)
);
rows.value = res.data.result;
} catch (error) {
messageError($q, error);
} finally {
hideLoader();
}
}
async function addEditData(editStatus: boolean = false) {
if (!profileId.value) return;
const url = editStatus
? config.API.profileNewAssessmentsById(id.value, empType.value)
: config.API.profileNewAssessments(empType.value);
const method = editStatus ? "patch" : "post";
const reqBody: RequestItemsObject = {
...resPerformForm,
profileEmployeeId:
!editStatus && empType.value !== "" ? profileId.value : undefined,
profileId:
!editStatus && empType.value === "" ? profileId.value : undefined,
};
try {
await http[method](url, reqBody);
success($q, "บันทึกข้อมูลสำเร็จ");
await fetchData();
} catch (e) {
messageError($q, e);
} finally {
hideLoader();
}
}
function onClickOpenDialog(editStatus: boolean = false, row?: ResponseObject) {
modal.value = true;
isEdit.value = editStatus;
if (editStatus && row) {
id.value = row.id;
resPerformForm.name = row.name;
resPerformForm.point1Total = row.point1Total;
resPerformForm.point1 = row.point1;
resPerformForm.point2Total = row.point2Total;
resPerformForm.point2 = row.point2;
resPerformForm.pointSumTotal = row.pointSumTotal;
resPerformForm.pointSum = row.pointSum;
resPerformForm.date = row.date;
} else {
clearData();
}
}
async function clickClose() {
clearData();
modal.value = false;
}
async function clickHistory(row: ResponseObject) {
modalHistory.value = true;
filterSearch.value = "";
showLoader();
try {
const res = await http.get(
config.API.profileNewAssessmentsHisById(row.id, empType.value)
);
rowsHistory.value = res.data.result;
} catch (e) {
messageError($q, e);
} finally {
hideLoader();
}
}
function onSubmit() {
dialogConfirm(
$q,
async () => {
addEditData(isEdit.value);
modal.value = false;
},
"ยืนยันการบันทึกข้อมูล",
"ต้องการยืนยันการบันทึกข้อมูลนี้หรือไม่ ?"
);
}
function clearData() {
(id.value = ""),
(resPerformForm.name = ""),
(resPerformForm.point1Total = 0),
(resPerformForm.point1 = 0),
(resPerformForm.point2Total = 0),
(resPerformForm.point2 = 0),
(resPerformForm.pointSumTotal = 0),
(resPerformForm.pointSum = 0),
(resPerformForm.date = null);
}
onMounted(async () => {
await fetchData();
});
</script>
<template>
<div class="row items-center q-gutter-x-sm q-pb-sm">
<q-btn
dense
color="primary"
icon="add"
flat
round
@click="onClickOpenDialog()"
><q-tooltip>เพมขอม</q-tooltip></q-btn
>
<q-space />
<q-input
standout
dense
v-model="filterSearch"
ref="filterRef"
outlined
placeholder="ค้นหา"
debounce="300"
>
<template v-slot:append>
<q-icon
v-if="filterSearch == ''"
name="search"
@click.stop.prevent="filterSearch = ''"
class="cursor-pointer"
/>
<q-icon
v-if="filterSearch"
name="cancel"
@click.stop.prevent="filterSearch = ''"
class="cursor-pointer"
/>
</template>
</q-input>
<q-select
v-if="modeView == 'table'"
v-model="visibleColumns"
multiple
outlined
dense
options-dense
:display-value="$q.lang.table.columns"
emit-value
map-options
:options="columns"
option-value="name"
options-cover
style="min-width: 150px"
/>
<q-btn-toggle
v-model="modeView"
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: modeView === 'table' ? '#787B7C' : '#C9D3DB',
}"
/>
</template>
<template v-slot:card>
<q-icon
name="mdi-view-grid-outline"
size="24px"
:style="{
color: modeView === 'card' ? '#787B7C' : '#C9D3DB',
}"
/>
</template>
</q-btn-toggle>
</div>
<d-table
flat
dense
bordered
:rows="rows"
:paging="true"
:columns="columns"
:filter="filterSearch"
v-model:pagination="pagination"
:grid="modeView === 'card'"
:visible-columns="visibleColumns"
:rows-per-page-options="[20, 50, 100]"
:card-container-class="modeView === 'card' ? 'q-col-gutter-md' : ''"
>
<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="modeView === 'table'">
<q-tr :props="props">
<q-td auto-width>
<q-btn
flat
dense
round
class="q-mr-xs"
size="14px"
color="primary"
icon="mdi-pencil-outline"
@click="onClickOpenDialog(true, props.row)"
>
<q-tooltip>แกไขขอม</q-tooltip>
</q-btn>
<q-btn
color="info"
flat
dense
round
size="14px"
icon="mdi-history"
@click="clickHistory(props.row)"
>
<q-tooltip>ประวแกไขผลการประเมนการปฏราชการ</q-tooltip>
</q-btn>
</q-td>
<q-td
v-for="col in props.cols"
:key="col.name"
:props="props"
class="cursor-pointer"
>
<div class="table_ellipsis">
{{ col.value ? col.value : "-" }}
</div>
</q-td>
</q-tr>
</template>
<template v-slot:item="props" v-else>
<div class="col-xs-12 col-sm-6 col-md-6">
<q-card bordered>
<q-card-actions class="bg-grey-3" align="right">
<q-btn
flat
round
color="primary"
icon="mdi-pencil-outline"
@click.stop.prevent="onClickOpenDialog(true, props.row)"
>
<q-tooltip>แกไขขอม</q-tooltip>
</q-btn>
<q-btn
flat
round
color="info"
icon="mdi-history"
@click="clickHistory(props.row)"
>
<q-tooltip>ประวแกไขเครองราชอสรยาภรณ</q-tooltip>
</q-btn>
</q-card-actions>
<q-separator />
<div>
<q-item
v-for="(col, index) in props.cols.filter(
(col) => col.name !== 'desc'
)"
:key="col.name"
:class="index % 2 !== 0 ? 'bg-grey-1' : ''"
>
<q-item-section class="text-grey-6">
<q-item-label>{{ col.label }}</q-item-label>
</q-item-section>
<q-item-section class="text-dark">
<q-item-label>
{{ col.value ? col.value : "-" }}
</q-item-label>
</q-item-section>
</q-item>
</div>
</q-card>
</div>
</template>
</d-table>
<q-dialog v-model="modal" persistent>
<q-card>
<q-form greedy @submit.prevent @validation-success="onSubmit">
<DialogHeader
:tittle="
isEdit
? 'แก้ไขผลการประเมินการปฏิบัติราชการ'
: 'เพิ่มผลการประเมินการปฏิบัติราชการ'
"
:close="clickClose"
/>
<q-separator />
<q-card-section>
<div class="row col-12 q-col-gutter-sm">
<div class="col-12">
<datepicker
autoApply
borderless
week-start="0"
menu-class-name="modalfix"
v-model="resPerformForm.date"
:locale="'th'"
:enableTimePicker="false"
>
<template #year="{ year }">
{{ year + 543 }}
</template>
<template #year-overlay-value="{ value }">
{{ parseInt(value + 543) }}
</template>
<template #trigger>
<q-input
dense
outlined
for="inputDatereceive"
ref="dateReceivedRef"
class="inputgreen"
hide-bottom-space
:model-value="date2Thai(resPerformForm.date as Date)"
:label="`${'วันที่ได้รับ'}`"
:rules="[(val) => !!val || `${'กรุณาเลือกวันที่ได้รับ'}`]"
>
<template v-slot:prepend>
<q-icon
name="event"
class="cursor-pointer"
color="primary"
/>
</template>
</q-input>
</template>
</datepicker>
</div>
<div class="col-xs-6 col-sm-6 col-md-6">
<q-input
dense
outlined
lazy-rules
hide-bottom-space
class="inputgreen"
v-model="resPerformForm.point1Total"
input-class="text-right "
:label="`${'ส่วนที่1 (น้ำหนัก)'}`"
:rules="[(val) => !!val || `${'กรุณากรอกส่วนที่1 (น้ำหนัก)'}`]"
/>
</div>
<div class="col-xs-6 col-sm-6 col-md-6">
<q-input
dense
outlined
lazy-rules
hide-bottom-space
class="inputgreen"
v-model="resPerformForm.point1"
input-class="text-right"
:label="`${'ผลประเมินส่วนที่1 (คะแนน)'}`"
:rules="[
(val) => !!val || `${'กรุณากรอกผลประเมินส่วนที่1 (คะแนน)'}`,
]"
/>
</div>
<div class="col-xs-6 col-sm-6 col-md-6">
<q-input
dense
outlined
lazy-rules
hide-bottom-space
class="inputgreen"
v-model="resPerformForm.point2Total"
input-class="text-right"
:label="`${'ส่วนที่2 (น้ำหนัก)'}`"
:rules="[(val) => !!val || `${'กรุณากรอกส่วนที่2 (น้ำหนัก)'}`]"
/>
</div>
<div class="col-xs-6 col-sm-6 col-md-6">
<q-input
dense
outlined
lazy-rules
hide-bottom-space
class="inputgreen"
v-model="resPerformForm.point2"
input-class="text-right"
:label="`${'ผลประเมินส่วนที่2 (คะแนน)'}`"
:rules="[
(val) => !!val || `${'กรุณากรอกผลประเมินส่วนที่2 (คะแนน)'}`,
]"
/>
</div>
<div class="col-xs-6 col-sm-6 col-md-6">
<q-input
dense
outlined
lazy-rules
hide-bottom-space
class="inputgreen"
v-model="resPerformForm.pointSumTotal"
input-class="text-right"
:label="`${'ผลรวม (น้ำหนัก)'}`"
:rules="[(val) => !!val || `${'กรุณากรอกผลรวม (น้ำหนัก)'}`]"
/>
</div>
<div class="col-xs-6 col-sm-6 col-md-6">
<q-input
dense
outlined
lazy-rules
hide-bottom-space
v-model="resPerformForm.pointSum"
class="inputgreen"
input-class="text-right"
:label="`${'ผลประเมินรวม (คะแนน)'}`"
:rules="[
(val) => !!val || `${'กรุณากรอกผลประเมินรวม (คะแนน)'}`,
]"
/>
</div>
<div class="col-12 row items-center q-pt-md justify-center">
ผลการประเม:
<div class="text-bold items-center q-px-sm">
{{ textPoint(resPerformForm.pointSum) }}
</div>
{{ textRangePoint(resPerformForm.pointSum) }}
</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="modalHistory" persistent>
<q-card style="min-width: 80%">
<DialogHeader
tittle="ประวัติแก้ไขผลการประเมินการปฏิบัติราชการ"
:close="() => (modalHistory = false)"
/>
<q-separator />
<q-card-section style="max-height: 60vh" class="scroll">
<div class="row q-gutter-sm q-mb-sm">
<q-space />
<q-input
standout
dense
v-model="filterHistory"
ref="filterRef"
outlined
placeholder="ค้นหา"
debounce="300"
>
<template v-slot:append>
<q-icon
v-if="filterHistory == ''"
name="search"
@click.stop.prevent="filterHistory = ''"
class="cursor-pointer"
/>
<q-icon
v-if="filterHistory"
name="cancel"
@click.stop.prevent="filterHistory = ''"
class="cursor-pointer"
/>
</template>
</q-input>
<q-select
v-model="visibleColumnsHistory"
multiple
outlined
dense
options-dense
:display-value="$q.lang.table.columns"
emit-value
map-options
:options="columnsHistory"
option-value="name"
options-cover
style="min-width: 150px"
/>
</div>
<d-table
ref="table"
flat
bordered
dense
:columns="columnsHistory"
v-model:pagination="historyPagination"
:rows="rowsHistory"
:paging="true"
:rows-per-page-options="[10, 25, 50, 100]"
:visible-columns="visibleColumnsHistory"
:filter="filterHistory"
>
>
<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" class="cursor-pointer">
<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></style>

View file

@ -0,0 +1,64 @@
<script setup lang="ts">
import { ref } from "vue";
/** importComponents*/
import ProfessionalLicense from "@/modules/04_registryPerson/components/detail/Achievement/01_ProfessionalLicense.vue";
import Train from "@/modules/04_registryPerson/components/detail/Achievement/02_Train.vue";
import Insignia from "@/modules/04_registryPerson/components/detail/Achievement/03_Insignia.vue";
import DeclarationHonor from "@/modules/04_registryPerson/components/detail/Achievement/04_DeclarationHonor.vue";
import ResultsPerformance from "@/modules/04_registryPerson/components/detail/Achievement/05_ResultsPerformance.vue";
const tab = ref<string>("1");
</script>
<template>
<div class="row items-center q-my-md">
<div class="text-dark row items-center q-px-md">
<q-icon name="mdi-account" class="q-mr-md" size="22px" />
<div class="text-subtitle1 text-weight-bold">
อมลผลงานและเครองราชฯ
</div>
</div>
</div>
<q-separator />
<q-tabs
v-model="tab"
active-color="blue-8"
align="left"
bordered
narrow-indicator
indicator-color="transparent"
dense
class="text-grey q-pl-sm"
>
<q-tab name="1" label="ใบอนุญาตประกอบวิชาชีพ" />
<q-tab name="2" label="การฝึกอบรม/ดูงาน" />
<q-tab name="3" label="เครื่องราชอิสริยาภรณ์" />
<q-tab name="4" label="ประกาศเกียรติคุณ" />
<q-tab name="5" label="ผลการประเมินการปฏิบัติราชการ" />
</q-tabs>
<q-separator />
<q-tab-panels v-model="tab" animated>
<q-tab-panel name="1">
<ProfessionalLicense />
</q-tab-panel>
<q-tab-panel name="2">
<Train />
</q-tab-panel>
<q-tab-panel name="3">
<Insignia />
</q-tab-panel>
<q-tab-panel name="4">
<DeclarationHonor />
</q-tab-panel>
<q-tab-panel name="4">
<PerformSpecialWork />
</q-tab-panel>
<q-tab-panel name="5">
<ResultsPerformance />
</q-tab-panel>
</q-tab-panels>
</template>
<style scoped></style>