Merge branch 'develop' into working

# Conflicts:
#	src/interface/request/main/main.ts
#	src/modules/08_registryEmployee/router.ts
#	src/modules/08_registryEmployee/views/Main.vue
This commit is contained in:
Tanyalak 2023-08-16 17:06:58 +07:00
commit 06c3d36c7a
333 changed files with 64333 additions and 12866 deletions

4
package-lock.json generated
View file

@ -7722,7 +7722,7 @@
},
"node_modules/vue": {
"version": "3.2.47",
"resolved": "https://npm.joolsoft.com/vue/-/vue-3.2.47.tgz",
// "resolved": "https://npm.joolsoft.com/vue/-/vue-3.2.47.tgz",
"integrity": "sha512-60188y/9Dc9WVrAZeUVSDxRQOZ+z+y5nO2ts9jWXSTkMvayiWxCWOWtBQoYjLeccfXkiiPZWAHcV+WTPhkqJHQ==",
"dependencies": {
"@vue/compiler-dom": "3.2.47",
@ -13787,7 +13787,7 @@
},
"vue": {
"version": "3.2.47",
"resolved": "https://npm.joolsoft.com/vue/-/vue-3.2.47.tgz",
// "resolved": "https://npm.joolsoft.com/vue/-/vue-3.2.47.tgz",
"integrity": "sha512-60188y/9Dc9WVrAZeUVSDxRQOZ+z+y5nO2ts9jWXSTkMvayiWxCWOWtBQoYjLeccfXkiiPZWAHcV+WTPhkqJHQ==",
"requires": {
"@vue/compiler-dom": "3.2.47",

View file

@ -0,0 +1,11 @@
/**
* API Structure + Org Chart
*/
import env from "../index";
const message = `${env.API_DASHBOARD_URI}/message`;
export default {
msgNotificate: `${message}/my-notifications`,
msgInbox: `${message}/my-inboxes`,
};

View file

@ -1,6 +1,14 @@
import env from "../index";
const placement = `${env.API_PLACEMENT_URI}/placement`;
const orgTree = `${env.API_URI_ORG_TREE}`;
const order = `${env.API_PLACEMENT_URI}`;
const receive = `${env.API_PLACEMENT_URI}/placement/Receive`;
const transfer = `${placement}/transfer`;
const placemenHelpGov = `${placement}/officer`;
const placemenRepatriation = `${placement}/repatriation`;
const placemenRelocation = `${placement}/relocation`;
const placemenOther = `${env.API_URI}/retirement/other`;
const placemenAppointment = `${placement}/appointment`;
export default {
MainDetail: (year: number) => `${placement}/exam/${year}`,
@ -44,8 +52,96 @@ export default {
//education
placementEducationId: (id: string) => `${placement}/education/${id}`,
// position
// position
placementPosition: () => `${placement}/position/use`,
// putPositiom
putPosition: (id:any) => `${placement}/position/${id}`,
putPosition: (id: any) => `${placement}/position/${id}`,
// clear Position
clearPosition: (personalId: string) =>
`${placement}/position/clear/${personalId}`,
// order
yearOptionsOrder: () => `${order}/order/fiscal-year`,
listOrder: () => `${order}/order`,
detailOrder: (orderId: string) => `${order}/order/detail/${orderId}`,
deleteOrder: (orderId: string) => `${order}/order/${orderId}`,
typeOrder: () => `${order}/order/order-type`,
nextStep: (orderId: string) => `${order}/order/next/${orderId}`,
prevStep: (orderId: string) => `${order}/order/prev/${orderId}`,
executeOrder: (orderId: string) => `${order}/order/execute/${orderId}`,
createOrder: () => `${order}/order/detail`,
examroundOrder: () => `${order}/order/detail/exam-round`,
personsOrder: (orderId: string) => `${order}/order/persons/${orderId}`, //ข้อมูลเลือกรายชื่อออกคำสั่ง, ลบรายชื่อ
personsselectedOrder: (orderId: string) =>
`${order}/order/persons-selected/${orderId}`,
nextOrder: (orderId: string) => `${order}/order/next/${orderId}`, //เปลี่ยน status ของคำสั่งไปขั้นตอนถัดไป
preventOrder: (orderId: string) => `${order}/order/prev/${orderId}`, //เปลี่ยน status ของคำสั่งไปขั้นตอนถัดไป
swapUpOrder: (personalId: string) => `${order}/order/swap/up/${personalId}`, //สลับลำดับข้อมูลในบัญชีแนบท้ายขึ้น
swapDownOrder: (personalId: string) =>
`${order}/order/swap/down/${personalId}`, //สลับลำดับข้อมูลในบัญชีแนบท้ายลง
salaryOrder: (id: string) => `${order}/order/salary/${id}`, //บันทึกข้อมูลเงินเดือนสำหรับผู้บรรจุ
copyOrderPersonsId: (id: string) => `${order}/order/copy-order/persons/${id}`, // popup แสดงรายชื่อตามหน่วยงานที่เลือก , popup เลือกรายชื่อส่งสำเนา
copyOrder: `${order}/order/copy-order`,
copyOrderId: (id: string) => `${order}/order/copy-order/${id}`,
attachmentId: (id: string) => `${order}/order/attachment/${id}`,
attachmentOrderId: (orderId: string) =>
`${order}/order/attachment/order-file/${orderId}`,
attachmentFileId: (orderId: string) =>
`${order}/order/attachment/file/${orderId}`,
orderReady: (id: string) => `${order}/order/ready/${id}`,
attachmentOrder: (orderId: string) => `${order}/order/attachment/${orderId}`,
//receive ระบบรับโอน
receiveData: () => `${receive}`,
receiveReport: `${receive}/report`,
receiveDataId: (id: string) => `${receive}/${id}`,
receivePosition: (id: string) => `${receive}/position/${id}`,
//tranfer ระบบคำขอโอน
transfer,
transferId: (id: string) => `${transfer}/${id}`,
transferReport: `${transfer}/report`,
transferUser: `${transfer}/user`,
transferUserId: (id: string) => `${transfer}/user/${id}`,
transferConfirmId: (id: string) => `${transfer}/confirm/${id}`,
// แต่งตั้ง-เลื่อน
placemenAppointment,
appointmentMain: () => `${placement}/appointment`,
appointmentByid: (id: string) => `${placement}/appointment/${id}`,
appointmentDelete: (id: string) => `${placement}/appointment/${id}`,
appointmentPosition: (id: string) => `${placement}/appointment/position/${id}`,
apppointmentReport: (id: string) => `${placement}/appointment/report/${id}`,
// ช่วยราชการ
placemenHelpGov,
officerMain: () => `${placement}/officer`,
officerDetail: (id: string) => `${placement}/officer/${id}`,
officerMainDelete: (id: string) => `${placement}/officer/${id}`,
officerMainReport: () => `${placement}/officer/report`,
officerMainEdit: (id:string) => `${placemenHelpGov}/${id}`,
// ส่งตัวกลับ
placemenRepatriation,
repatriationMain: () => `${placement}/repatriation`,
repatriationDetail: (id: string) => `${placement}/repatriation/${id}`,
repatriationMainDelete: (id: string) => `${placement}/repatriation/${id}`,
repatriationMainReport: () => `${placement}/repatriation/report`,
repatriationMainEdit: (id:string) => `${placemenRepatriation}/${id}`,
// ขอย้าย
placemenRelocation,
relocationMain: () => `${placement}/relocation`,
relocationDetail: (id:string) => `${placement}/relocation/${id}`,
relocationMainDelete: (id:string) => `${placement}/relocation/${id}`,
relocationMainReport: () => `${placement}/relocation/report`,
relocationMainPut: (id:string) => `${placement}/relocation/position/${id}`,
relocationMainEdit: (id:string) => `${placemenRelocation}/${id}`,
// อื่นๆ
placemenOther,
otherMain: () => `${placemenOther}`,
otherPosition: (id: string) => `${placemenOther}/position/${id}`,
otherReport: (id: string) => `${placemenOther}/report/${id}`,
otherByid: (id: string) => `${placemenOther}/${id}`,
};

View file

@ -0,0 +1,62 @@
import env from "../index";
const dataOptions = `${env.API_PROBATION_URI}/data-options`;
const personal = `${env.API_PROBATION_URI}/personal`;
const calculate = `${env.API_PROBATION_URI}/calculate`;
const finish = `${env.API_PROBATION_URI}/assign`;
const evaluate = `${env.API_PROBATION_URI}`;
export default {
competencyOptions: (personalId: string) =>
`${dataOptions}/competency?personal_id=${personalId}`,
competencyGroupOptions: (personalId: string) =>
`${dataOptions}/competency-group?personal_id=${personalId}`,
knowledgeOptions: (personalId: string) =>
`${dataOptions}/knowledge?personal_id=${personalId}`,
skillOptions: (personalId: string) =>
`${dataOptions}/skill?personal_id=${personalId}`,
lawOptions: (personalId: string) =>
`${dataOptions}/law?personal_id=${personalId}`,
probationPersonalList: () => `${personal}/list`,
personal: (personalId: string) => `${personal}?personal_id=${personalId}`,
newAssign: (personalId: string) =>
`${dataOptions}/new-assign?personal_id=${personalId}`,
calculateDate: () => `${calculate}/assign-finish`,
saveFinish: (personalId: string) =>
`${finish}/probation-assign?personal_id=${personalId}`,
personalAdd: () => `${personal}/add`,
probationGetAssignList: (personalId:string) =>
`${finish}/probation-assign-list?personal_id=${personalId}`,
probationsGetAssign: (assignId:string) =>`${finish}/probation-assign?assign_id=${assignId}`,
// probationGetAssignList: (personalId: string) =>
// `${finish}/probation-assign-list?personal_id=${personalId}`,
// clearPosition: (personalId:string) => `${placement}/position/clear/${personalId}`
// บันทึกผล
formevaluate: (id: string) => `${evaluate}/evaluate-record?assign_id=${id}`,
formevaluateround: (id: string, no: string) => `${evaluate}/evaluate-record?assign_id=${id}&evaluate_no=${no}`,
formevaluateRecord: (id: string) => `${evaluate}/evaluate-record/create?assign_id=${id}`,
createformevaluate: (id: string) => `${evaluate}/evaluate-record?id=${id}`,
//แบบประเมินผล (ผู้บังคับบัญชา)
evaluateCreate: (id: string) => `${evaluate}/evaluate/create?assign_id=${id}`,
evaluatecommader: (id: string, no: string) => `${evaluate}/evaluate?assign_id=${id}&evaluate_no=${no}`,
createformCommader: (id: string) => `${evaluate}/evaluate?id=${id}`,
//แบบประเมินผล (คณะกรรมการ)
evaluateChairman: (id: string) => `${evaluate}/evaluate-chairman/create?assign_id=${id}`,
evaluateRoundChairman: (id: string, no: string) => `${evaluate}/evaluate-chairman?assign_id=${id}&evaluate_no=${no}`,
createformChairman: (id: string) => `${evaluate}/evaluate-chairman?id=${id}`,
//แบบรายงาน
evaluateReportcreate: (id: string) => `${evaluate}/evaluate-result/create?assign_id=${id}`,
evaluateReport: (id: string) => `${evaluate}/evaluate-result?assign_id=${id}`,
createformReport: (id: string) => `${evaluate}/evaluate-result?id=${id}`,
};

View file

@ -1,12 +1,46 @@
import env from "../index";
const retirement = `${env.API_URI}/retirement`
const retirement = `${env.API_URI}/retirement`;
const retirementDischarge = `${retirement}/discharge`;
const retirementExpulsion = `${retirement}/expulsion`;
const retirementOut = `${retirement}/out`;
export default {
profile: (type: string, year: string) => `${retirement}/profile/${type}/${year}`,
profileRetire: (retireProfileId: string) => `${retirement}/profile/${retireProfileId}`,
listRetire: (retireId: string) => `${retirement}/${retireId}`,
createnote: () => `${retirement}/reason`,
reasonId: (retireId:string) => `${retirement}/reason/${retireId}`,
retirement:(type:string,year:string) => `${retirement}/${type}/${year}`
profile: (type: string, year: string) =>
`${retirement}/profile/${type}/${year}`,
profileRetire: (retireProfileId: string) =>
`${retirement}/profile/${retireProfileId}`,
listRetire: (retireId: string) => `${retirement}/${retireId}`,
createnote: () => `${retirement}/edit`,
removeProfile: () => `${retirement}/remove`,
reasonId: (retireId: string) => `${retirement}/reason/${retireId}`,
retirement: (type: string, year: string) => `${retirement}/${type}/${year}`,
createProfile: () => `${retirement}/profile`,
//RetirementDeceased ถึงแก่กรรม
listDeceased: () => `${retirement}/deceased`,
detailDeceased: (id: string) => `${retirement}/deceased/${id}`,
// RetirementResign ระบบลาออก
listResign: () => `${retirement}/resign`,
resignReport: `${retirement}/resign/report`,
resingByid: (id: string) => `${retirement}/resign/${id}`,
resignConfirm: (id: string) => `${retirement}/resign/confirm/${id}`,
resignReject: (id: string) => `${retirement}/resign/reject/${id}`,
// ปลดออก
retirementDischarge,
listDischared: () => `${retirement}/dischared`,
discharedByid: (id: string) => `${retirement}/dischared/${id}`,
discharedReport: `${retirement}/dischared/report`,
// ไล่ออก
retirementExpulsion,
listExpulsion: () => `${retirement}/expulsion`,
expulsionByid: (id: string) => `${retirement}/expulsion/${id}`,
expulsionReport: `${retirement}/expulsion/report`,
// ให้ออก
retirementOut,
listOut: () => `${retirement}/out`,
outByid: (id: string) => `${retirement}/out/${id}`,
outReport: `${retirement}/out/report`,
};

View file

@ -2,5 +2,10 @@
* api
*/
import env from "../index";
export default {};
const insignia = `${env.API_URI}/insignia`;
export default {
getRoundInsignia: (id: string) => `${insignia}/period/${id}`,
listRoundInsignia: (type: string) => `${insignia}/period/${type}`,
editRoundInsignia: (id: string) => `${insignia}/period/${id}`,
RoundInsignia: (id: string) => `${insignia}/period/${id}`,
};

View file

@ -26,6 +26,10 @@ const config = ref<any>({
"https://s3cluster.frappet.com/bma-ehr-fpt/organization/strueture/tree_20230712_172702.json",
MEET_URI: "meet.frappet.com",
API_RETIREMENT_URI: "https://bma-ehr.frappet.synology.me/api/v1",
// API_PROBATION_URI: "https://ehr.joolsoft.com/v1",
API_PROBATION_URI: "https://bmaehr.joolsoft.com/nodeapi/v1",
// API_PROBATION_URI: "http://192.168.1.151:7776/v1",
API_DASHBOARD_URI: "http://192.168.1.9:6026/api/v1",
},
test: {
API_URI: "http://localhost:5010/api/v1",
@ -70,6 +74,13 @@ const API_RETIREMENT_URI = ref<string>(
config.value[env.value].API_RETIREMENT_URI
);
const API_URI_ORG_TREE = ref<string>(config.value[env.value].API_URI_ORG_TREE);
const API_PROBATION_URI = ref<string>(
config.value[env.value].API_PROBATION_URI
);
const API_DASHBOARD_URI = ref<string>(
config.value[env.value].API_DASHBOARD_URI
);
export default {
env: env.value,
@ -83,5 +94,7 @@ export default {
API_PLACEMENT_URI: API_PLACEMENT_URI.value,
API_URI_ORG_TREE: API_URI_ORG_TREE.value,
MEET_URI: MEET_URI.value,
API_RETIREMENT_URI:API_RETIREMENT_URI.value,
API_RETIREMENT_URI: API_RETIREMENT_URI.value,
API_PROBATION_URI: API_PROBATION_URI.value,
API_DASHBOARD_URI: API_DASHBOARD_URI.value,
};

View file

@ -156,6 +156,7 @@ export default {
`${profile}address/history/${profileId}`,
searchProfileByOcId: (OcId: string, type: string) =>
`${profile}search/new/oc/${OcId}/${type}`,
searchProfileTemp: (type: string) => `${profile}search/new/oc/${type}`,
profileAvatarId: (profileId: string) => `${profile}avatar/${profileId}`,
profileAvatarHistoryId: (profileId: string) =>
@ -181,4 +182,8 @@ export default {
profileCitizenId: (citizenId: string) => `${profile}citizenId/${citizenId}`,
profileEmployeeIn: `${profile}information/employee`,
};

View file

@ -29,6 +29,7 @@ import report2 from "./api/recruiting/api.report2";
/** API ระบบการบรรจุ แต่งตั้ง ย้าย โอน List */
import placement from "./api/05_placement/api.placement";
import probation from "./api/05_placement/api.probation";
/** API ระบบการพ้นจากราชการ List */
import retirement from "./api/06_retirement/api.retirement";
@ -36,6 +37,9 @@ import retirement from "./api/06_retirement/api.retirement";
/** API ระบบงานเครื่องราชอิสริยาภรณ์ List */
import insignia from "./api/07_insignia/api.insignia";
/** API dashboard */
import message from "./api/00_dashboard/api.message";
// environment variables
export const compettitivePanel = import.meta.env.VITE_COMPETITIVE_EXAM_PANEL;
export const qualifyDisableExamPanel = import.meta.env
@ -70,8 +74,12 @@ const API = {
...report2,
...placement,
...probation,
...retirement,
...insignia,
//dashboard
...message,
};
export default {

View file

@ -0,0 +1,873 @@
<template>
<q-card flat bordered class="col-12 q-px-lg q-py-md q-mt-md">
<HeaderTop
v-model:edit="edit"
header="ข้อมูลที่อยู่"
icon="mdi-map-marker"
:save="saveData"
:history="!statusAdd()"
:changeBtn="changeBtn"
:disable="statusEdit"
:cancel="refreshData"
:historyClick="clickHistory"
:addEmployee="statusAdd()"
/>
<q-form ref="myform">
<div class="row col-12 items-center q-col-gutter-x-xs q-col-gutter-y-xs">
<div class="col-xs-12">
<q-input
:class="getClass(edit)"
hide-bottom-space
:outlined="edit"
dense
lazy-rules
type="textarea"
autogrow
:readonly="!edit"
:borderless="!edit"
v-model="addressData.address"
:rules="[(val:string) => !!val || `${'กรุณากรอก ที่อยู่ตามทะเบียนบ้าน'}`]"
:label="`${'ที่อยู่ตามทะเบียนบ้าน'}`"
/>
</div>
<div class="col-xs-6 col-sm-3 col-md-3">
<selector
:hide-dropdown-icon="!edit"
hide-bottom-space
:class="getClass(edit)"
:readonly="!edit"
:borderless="!edit"
:rules="[(val:string) => !!val || `${'กรุณาเลือก จังหวัด'}`]"
:outlined="edit"
dense
lazy-rules
v-model="addressData.provinceId"
emit-value
map-options
option-label="name"
:options="Ops.provinceOps"
option-value="id"
:label="`${'จังหวัด'}`"
@update:model-value="(value:string) => selectProvince(value, '1')"
use-input
input-debounce="0"
@filter="(inputValue:string,
doneFn:Function) => filterSelector(inputValue, doneFn,'provinceOps'
) "
/>
</div>
<div class="col-xs-6 col-sm-3 col-md-3">
<selector
:hide-dropdown-icon="!edit"
hide-bottom-space
:class="getClass(edit)"
:readonly="!edit"
:borderless="!edit"
:rules="[(val:string) => !!val || `${'กรุณาเลือก เขต / อำเภอ'}`]"
:outlined="edit"
dense
lazy-rules
v-model="addressData.districtId"
emit-value
map-options
option-label="name"
:options="Ops.districtOps"
option-value="id"
:label="`${'เขต / อำเภอ'}`"
@update:model-value="(value:string) => selectDistrict(value, '1')"
use-input
input-debounce="0"
@filter="(inputValue:string,
doneFn:Function) => filterSelector(inputValue, doneFn,'districtOps'
) "
/>
</div>
<div class="col-xs-6 col-sm-3 col-md-3">
<selector
:hide-dropdown-icon="!edit"
hide-bottom-space
:class="getClass(edit)"
:readonly="!edit"
:borderless="!edit"
:rules="[(val:string) => !!val || `${'กรุณาเลือก ตำบล / แขวง'}`]"
:outlined="edit"
dense
lazy-rules
v-model="addressData.subdistrictId"
emit-value
map-options
option-label="name"
:options="Ops.subdistrictOps"
option-value="id"
:label="`${'ตำบล / แขวง'}`"
@update:model-value="(value:string) => selectSubDistrict(value, '1')"
use-input
input-debounce="0"
@filter="(inputValue:string,
doneFn:Function) => filterSelector(inputValue, doneFn,'subdistrictOps'
) "
/>
</div>
<div class="col-xs-6 col-sm-3 col-md-3">
<q-input
:class="getClass(edit)"
hide-bottom-space
dense
lazy-rules
readonly
borderless
v-model="codep"
:style="!edit ? '' : 'padding:0 12px;'"
:label="`${'รหัสไปรษณีย์'}`"
/>
</div>
<div class="col-12 q-pt-lg"><q-separator /></div>
<div class="col-xs-12 q-gutter-sm items-center flex q-my-sm">
<label class="text-bold"
>อยจจนตรงกบทอยตามทะเบยนบาน</label
>
<q-radio
v-model="addressData.same"
checked-icon="task_alt"
unchecked-icon="panorama_fish_eye"
val="1"
label="ใช่"
dense
:disable="!edit"
/>
<q-radio
v-model="addressData.same"
checked-icon="task_alt"
unchecked-icon="panorama_fish_eye"
val="0"
label="ไม่"
dense
:disable="!edit"
/>
</div>
<div class="col-xs-12" v-if="addressData.same == '0'">
<q-input
:class="getClass(edit)"
hide-bottom-space
:outlined="edit"
dense
lazy-rules
type="textarea"
autogrow
:readonly="!edit"
:borderless="!edit"
v-model="addressData.addressC"
:rules="[(val:string) => !!val || `${'กรุณากรอก ที่อยู่ปัจจุบัน'}`]"
:label="`${'ที่อยู่ปัจจุบัน'}`"
/>
</div>
<div class="col-xs-6 col-sm-3 col-md-3" v-if="addressData.same == '0'">
<selector
:hide-dropdown-icon="!edit"
hide-bottom-space
:class="getClass(edit)"
:readonly="!edit"
:borderless="!edit"
:rules="[(val:string) => !!val || `${'กรุณาเลือก จังหวัด'}`]"
:outlined="edit"
dense
lazy-rules
v-model="addressData.provinceIdC"
emit-value
map-options
option-label="name"
:options="Ops.provinceOps"
option-value="id"
:label="`${'จังหวัด'}`"
@update:model-value="(value:string) => selectProvince(value, '2')"
use-input
input-debounce="0"
@filter="(inputValue:string,
doneFn:Function) => filterSelector(inputValue, doneFn,'provinceOps'
) "
/>
</div>
<div class="col-xs-6 col-sm-3 col-md-3" v-if="addressData.same == '0'">
<selector
:hide-dropdown-icon="!edit"
hide-bottom-space
:class="getClass(edit)"
:readonly="!edit"
:borderless="!edit"
:rules="[(val:string) => !!val || `${'กรุณาเลือก เขต / อำเภอ'}`]"
:outlined="edit"
dense
lazy-rules
v-model="addressData.districtIdC"
emit-value
map-options
option-label="name"
:options="Ops.districtCOps"
option-value="id"
:label="`${'เขต / อำเภอ'}`"
@update:model-value="(value:string) => selectDistrict(value, '2')"
use-input
input-debounce="0"
@filter="(inputValue:string,
doneFn:Function) => filterSelector(inputValue, doneFn,'districtCOps'
) "
/>
</div>
<div class="col-xs-6 col-sm-3 col-md-3" v-if="addressData.same == '0'">
<selector
:hide-dropdown-icon="!edit"
hide-bottom-space
:class="getClass(edit)"
:readonly="!edit"
:borderless="!edit"
:rules="[(val:string) => !!val || `${'กรุณาเลือก ตำบล / แขวง'}`]"
:outlined="edit"
dense
lazy-rules
v-model="addressData.subdistrictIdC"
emit-value
map-options
option-label="name"
:options="Ops.subdistrictCOps"
option-value="id"
:label="`${'ตำบล / แขวง'}`"
@update:model-value="(value:string) => selectSubDistrict(value, '2')"
use-input
input-debounce="0"
@filter="(inputValue:string,
doneFn:Function) => filterSelector(inputValue, doneFn,'subdistrictCOps'
) "
/>
</div>
<div class="col-xs-6 col-sm-3 col-md-3" v-if="addressData.same == '0'">
<q-input
:class="getClass(edit)"
hide-bottom-space
dense
lazy-rules
readonly
borderless
v-model="codec"
:style="!edit ? '' : 'padding:0 12px;'"
:label="`${'รหัสไปรษณีย์'}`"
/>
</div>
</div>
</q-form>
</q-card>
<HistoryTable
:rows="rowsHistory"
:columns="columnsHistory"
:filter="filterHistory"
:visible-columns="visibleColumnsHistory"
v-model:modal="modalHistory"
v-model:inputfilter="filterHistory"
v-model:inputvisible="visibleColumnsHistory"
v-model:tittle="tittleHistory"
>
<template #columns="props">
<q-tr :props="props">
<q-td v-for="col in props.cols" :key="col.name" :props="props">
<div v-if="col.name == 'createdAt'" class="table_ellipsis">
{{ date2Thai(col.value) }}
</div>
<div
v-else-if="col.name == 'registrationSame'"
class="table_ellipsis"
>
{{ col.value ? "ใช่" : "ไม่" }}
</div>
<div v-else class="table_ellipsis">
{{ col.value }}
</div>
</q-td>
</q-tr>
</template>
</HistoryTable>
</template>
<script setup lang="ts">
import { ref, onMounted } from "vue";
import { useCounterMixin } from "@/stores/mixin";
import { useQuasar } from "quasar";
import http from "@/plugins/http";
import config from "@/app.config";
import type {
Address,
DataOption,
zipCodeOption,
} from "@/components/information/interface/profileType";
import { defaultAddress } from "@/components/information/interface/profileType";
import HeaderTop from "@/components/information/top.vue";
import type { RequestItemsHistoryObject } from "@/components/information/interface/request/Address";
import type { ResponseObject } from "@/components/information/interface/response/Address";
import HistoryTable from "@/components/TableHistory.vue";
import { useRoute } from "vue-router";
import type { AddressOps } from "@/components/information/interface/index/Main";
import type { QTableProps } from "quasar";
const props = defineProps({
statusEdit: {
type: Boolean,
required: true,
},
statusAdd: {
type: Boolean,
default: false,
},
});
const emit = defineEmits(["update:statusEdit"]);
const route = useRoute();
const $q = useQuasar();
const mixin = useCounterMixin();
const { date2Thai, success, messageError, showLoader, hideLoader } = mixin;
const edit = ref<boolean>(false);
const addressData = ref<Address>(defaultAddress);
const myform = ref<any>();
const codep = ref<string>("");
const codec = ref<string>("");
const rowsHistory = ref<RequestItemsHistoryObject[]>([]); //select data history
const tittleHistory = ref<string>("ประวัติแก้ไขข้อมูลที่อยู่"); //
const filterHistory = ref<string>(""); //search data table history
const modalHistory = ref<boolean>(false); //modal
const Ops = ref<AddressOps>({
provinceOps: [],
districtOps: [],
districtCOps: [],
subdistrictOps: [],
subdistrictCOps: [],
});
const OpsFilter = ref<AddressOps>({
provinceOps: [],
districtOps: [],
districtCOps: [],
subdistrictOps: [],
subdistrictCOps: [],
});
const columnsHistory = ref<QTableProps["columns"]>([
{
name: "registrationAddress",
align: "left",
label: "ที่อยู่ตามทะเบียนบ้าน",
sortable: true,
field: "registrationAddress",
headerStyle: "font-size: 14px",
style: "font-size: 14px",
sort: (a: string, b: string) =>
a.localeCompare(b, undefined, { numeric: true, sensitivity: "base" }),
},
{
name: "registrationProvince",
align: "left",
label: "จังหวัดตามทะเบียนบ้าน",
sortable: true,
field: "registrationProvince",
headerStyle: "font-size: 14px",
style: "font-size: 14px",
sort: (a: string, b: string) =>
a.localeCompare(b, undefined, { numeric: true, sensitivity: "base" }),
},
{
name: "registrationDistrict",
align: "left",
label: "เขต/อำเภอตามทะเบียนบ้าน",
sortable: true,
field: "registrationDistrict",
headerStyle: "font-size: 14px",
style: "font-size: 14px",
sort: (a: string, b: string) =>
a.localeCompare(b, undefined, { numeric: true, sensitivity: "base" }),
},
{
name: "registrationSubDistrict",
align: "left",
label: "ตำบล/แขวงตามทะเบียนบ้าน",
sortable: true,
field: "registrationSubDistrict",
headerStyle: "font-size: 14px",
style: "font-size: 14px",
sort: (a: string, b: string) =>
a.localeCompare(b, undefined, { numeric: true, sensitivity: "base" }),
},
{
name: "registrationZipCode",
align: "left",
label: "รหัสไปรษณีย์ตามทะเบียนบ้าน",
sortable: true,
field: "registrationZipCode",
headerStyle: "font-size: 14px",
style: "font-size: 14px",
sort: (a: string, b: string) =>
a.localeCompare(b, undefined, { numeric: true, sensitivity: "base" }),
},
{
name: "registrationSame",
align: "left",
label: "ที่อยู่ปัจจุบันตรงกับที่อยู่ตามทะเบียนบ้าน",
sortable: true,
field: "registrationSame",
headerStyle: "font-size: 14px",
style: "font-size: 14px",
sort: (a: string, b: string) =>
a.localeCompare(b, undefined, { numeric: true, sensitivity: "base" }),
},
{
name: "currentAddress",
align: "left",
label: "ที่อยู่ปัจจุบัน",
sortable: true,
field: "currentAddress",
headerStyle: "font-size: 14px",
style: "font-size: 14px",
sort: (a: string, b: string) =>
a.localeCompare(b, undefined, { numeric: true, sensitivity: "base" }),
},
{
name: "currentProvince",
align: "left",
label: "จังหวัดปัจจุบัน",
sortable: true,
field: "currentProvince",
headerStyle: "font-size: 14px",
style: "font-size: 14px",
sort: (a: string, b: string) =>
a.localeCompare(b, undefined, { numeric: true, sensitivity: "base" }),
},
{
name: "currentDistrict",
align: "left",
label: "เขต/อำเภอปัจจุบัน",
sortable: true,
field: "currentDistrict",
headerStyle: "font-size: 14px",
style: "font-size: 14px",
sort: (a: string, b: string) =>
a.localeCompare(b, undefined, { numeric: true, sensitivity: "base" }),
},
{
name: "currentSubDistrict",
align: "left",
label: "ตำบล/แขวงปัจจุบัน",
sortable: true,
field: "currentSubDistrict",
headerStyle: "font-size: 14px",
style: "font-size: 14px",
sort: (a: string, b: string) =>
a.localeCompare(b, undefined, { numeric: true, sensitivity: "base" }),
},
{
name: "currentZipCode",
align: "left",
label: "รหัสไปรษณีย์ปัจจุบัน",
sortable: true,
field: "currentZipCode",
headerStyle: "font-size: 14px",
style: "font-size: 14px",
sort: (a: string, b: string) =>
a.localeCompare(b, undefined, { numeric: true, sensitivity: "base" }),
},
{
name: "createdFullName",
align: "left",
label: "ผู้ดำเนินการ",
sortable: true,
field: "createdFullName",
headerStyle: "font-size: 14px",
style: "font-size: 14px",
sort: (a: string, b: string) =>
a.localeCompare(b, undefined, { numeric: true, sensitivity: "base" }),
},
{
name: "createdAt",
align: "left",
label: "วันที่แก้ไข",
sortable: true,
field: "createdAt",
headerStyle: "font-size: 14px",
style: "font-size: 14px",
sort: (a: string, b: string) =>
a.localeCompare(b, undefined, { numeric: true, sensitivity: "base" }),
},
]);
const visibleColumnsHistory = ref<String[]>([
"currentAddress",
"currentDistrict",
"currentProvince",
"currentSubDistrict",
"currentZipCode",
"registrationAddress",
"registrationDistrict",
"registrationProvince",
"registrationSame",
"registrationSubDistrict",
"registrationZipCode",
"createdFullName",
"createdAt",
]);
onMounted(async () => {
await getNewData();
emit("update:statusEdit", false);
defaultAdd();
});
const statusAdd = () => props.statusAdd;
const defaultAdd = () => {
if (props.statusAdd) {
edit.value = props.statusAdd;
addressData.value = {
address: null,
provinceId: null,
districtId: null,
subdistrictId: null,
addressC: null,
provinceIdC: null,
districtIdC: null,
subdistrictIdC: null,
same: "0",
};
}
};
const filterSelector = (val: any, update: Function, refData: string) => {
switch (refData) {
case "provinceOps":
update(() => {
Ops.value.provinceOps = OpsFilter.value.provinceOps.filter(
(v: DataOption) => v.name.indexOf(val) > -1
);
});
break;
case "districtOps":
update(() => {
Ops.value.districtOps = OpsFilter.value.districtOps.filter(
(v: DataOption) => v.name.indexOf(val) > -1
);
});
break;
case "districtCOps":
update(() => {
Ops.value.districtCOps = OpsFilter.value.districtCOps.filter(
(v: DataOption) => v.name.indexOf(val) > -1
);
});
break;
case "subdistrictOps":
update(() => {
Ops.value.subdistrictOps = OpsFilter.value.subdistrictOps.filter(
(v: DataOption) => v.name.indexOf(val) > -1
);
});
break;
case "subdistrictCOps":
update(() => {
Ops.value.subdistrictCOps = OpsFilter.value.subdistrictCOps.filter(
(v: DataOption) => v.name.indexOf(val) > -1
);
});
break;
default:
break;
}
};
/**
* งชนดอมลประวแกไขขอมลทเลอก
*/
const clickHistory = async () => {
modalHistory.value = true;
showLoader();
await http
.get(config.API.profileAdrsHisId(route.params.id.toString()))
.then((res) => {
let data = res.data.result;
rowsHistory.value = [];
data.map((e: RequestItemsHistoryObject) => {
rowsHistory.value.push({
currentAddress: e.currentAddress,
currentDistrict: e.currentDistrict,
currentProvince: e.currentProvince,
currentSubDistrict: e.currentSubDistrict,
currentZipCode: e.currentZipCode,
registrationSame: e.registrationSame,
registrationAddress: e.registrationAddress,
registrationDistrict: e.registrationDistrict,
registrationProvince: e.registrationProvince,
registrationSubDistrict: e.registrationSubDistrict,
registrationZipCode: e.registrationZipCode,
createdFullName: e.createdFullName,
createdAt: new Date(e.createdAt),
});
});
})
.catch((e) => {
messageError($q, e);
})
.finally(() => {
hideLoader();
});
};
const refreshData = async () => {
myform.value.reset();
await getNewData();
};
const getNewData = async () => {
await fetchData();
await fetchProvince();
await fetchDistrict(addressData.value.provinceId, "1");
await fetchDistrict(addressData.value.provinceIdC, "2");
await fetchSubDistrict(addressData.value.districtId, "1");
await fetchSubDistrict(addressData.value.districtIdC, "2");
};
const fetchData = async () => {
if (route.params.id) {
showLoader();
await http
.get(config.API.profileAdrsId(route.params.id.toString()))
.then((res) => {
const data: ResponseObject = res.data.result;
addressData.value.address = data.registrationAddress;
addressData.value.addressC = data.currentAddress;
addressData.value.districtId = data.registrationDistrictId;
addressData.value.districtIdC = data.currentDistrictId;
addressData.value.provinceId = data.registrationProvinceId;
addressData.value.provinceIdC = data.currentProvinceId;
addressData.value.subdistrictId = data.registrationSubDistrictId;
addressData.value.subdistrictIdC = data.currentSubDistrictId;
addressData.value.same = data.registrationSame ? "1" : "0";
})
.catch((e) => {
messageError($q, e);
})
.finally(() => {
hideLoader();
});
}
};
const editData = async () => {
const body: ResponseObject = {
registrationSame: addressData.value.same == "1",
registrationAddress: addressData.value.address,
registrationSubDistrictId: addressData.value.subdistrictId,
registrationDistrictId: addressData.value.districtId,
registrationProvinceId: addressData.value.provinceId,
registrationZipCode: codep.value,
currentAddress:
addressData.value.same == "1"
? addressData.value.address
: addressData.value.addressC,
currentSubDistrictId:
addressData.value.same == "1"
? addressData.value.subdistrictId
: addressData.value.subdistrictIdC,
currentDistrictId:
addressData.value.same == "1"
? addressData.value.districtId
: addressData.value.districtIdC,
currentProvinceId:
addressData.value.same == "1"
? addressData.value.provinceId
: addressData.value.provinceIdC,
currentZipCode: addressData.value.same == "1" ? codep.value : codec.value,
createdAt: new Date(),
createdFullName: "-",
};
showLoader();
await http
.put(config.API.profileAdrsId(route.params.id.toString()), body)
.then((res) => {
success($q, "บันทึกข้อมูลสำเร็จ");
})
.catch((e) => {
messageError($q, e);
})
.finally(async () => {
edit.value = false;
emit("update:statusEdit", false);
await getNewData();
});
};
const addData = async () => {
// showLoader();
// await http
// .put(config.API.profileInforId(route.params.id.toString()), body)
// .then((res) => {
// success($q, "");
// })
// .catch((e) => {
// messageError($q, e);
// })
// .finally(async () => {
// edit.value = false;
// emit("update:statusEdit", false);
// await fetchData();
// await changeBirth(informaData.value.birthDate ?? new Date());
// });
};
const saveData = async () => {
await myform.value.validate().then(async (success: boolean) => {
if (success) {
if (props.statusAdd) {
await addData();
} else {
await editData();
}
} else {
}
});
};
const selectProvince = async (e: string | null, name: string) => {
if (e != null) {
if (name == "1") {
addressData.value.districtId = "";
addressData.value.subdistrictId = "";
codep.value = "";
} else {
addressData.value.districtIdC = "";
addressData.value.subdistrictIdC = "";
codec.value = "";
}
myform.value.resetValidation();
await fetchDistrict(e, name);
}
};
const selectDistrict = async (e: string | null, name: string) => {
if (e != null) {
if (name == "1") {
addressData.value.subdistrictId = "";
codep.value = "";
} else {
addressData.value.subdistrictIdC = "";
codec.value = "";
}
myform.value.resetValidation();
await fetchSubDistrict(e, name);
}
};
const selectSubDistrict = (e: string | null, name: string) => {
if (e != null) {
if (name == "1") {
const findcode = Ops.value.subdistrictOps.filter((r) => r.id == e);
const namecode = findcode.length > 0 ? findcode[0].zipCode : "";
codep.value = namecode;
} else {
const findcode = Ops.value.subdistrictCOps.filter((r) => r.id == e);
const namecode = findcode.length > 0 ? findcode[0].zipCode : "";
codec.value = namecode;
}
}
};
const fetchProvince = async () => {
showLoader();
await http
.get(config.API.province)
.then((res) => {
const data = res.data.result;
let option: DataOption[] = [];
data.map((r: any) => {
option.push({ id: r.id.toString(), name: r.name.toString() });
});
Ops.value.provinceOps = option;
OpsFilter.value.provinceOps = option;
})
.catch((e) => {
messageError($q, e);
})
.finally(() => {
hideLoader();
});
};
const fetchDistrict = async (id: string | null, position: string) => {
if (id != null && id != "") {
showLoader();
await http
.get(config.API.listDistrict(id))
.then((res) => {
const data = res.data.result;
let option: DataOption[] = [];
data.map((r: any) => {
option.push({ id: r.id.toString(), name: r.name.toString() });
});
if (position == "1") {
Ops.value.districtOps = option;
OpsFilter.value.districtOps = option;
} else {
Ops.value.districtCOps = option;
OpsFilter.value.districtCOps = option;
}
})
.catch((e) => {
messageError($q, e);
})
.finally(() => {
hideLoader();
});
}
};
const fetchSubDistrict = async (id: string | null, position: string) => {
if (id != null && id != "") {
showLoader();
await http
.get(config.API.listSubDistrict(id))
.then((res) => {
const data = res.data.result;
let option: zipCodeOption[] = [];
data.map((r: any) => {
option.push({
id: r.id.toString(),
name: r.name.toString(),
zipCode: r.zipCode.toString(),
});
});
if (position == "1") {
Ops.value.subdistrictOps = option;
OpsFilter.value.subdistrictOps = option;
} else {
Ops.value.subdistrictCOps = option;
OpsFilter.value.subdistrictCOps = option;
}
})
.catch((e) => {
messageError($q, e);
})
.finally(() => {
hideLoader();
});
}
};
const changeBtn = async () => {
if (edit.value == true) {
if (props.statusEdit === true) {
edit.value = false;
} else {
emit("update:statusEdit", true);
}
} else {
emit("update:statusEdit", false);
}
};
const getClass = (val: boolean) => {
return {
"full-width inputgreen cursor-pointer": val,
"full-width cursor-pointer": !val,
};
};
</script>

View file

@ -0,0 +1,981 @@
<!-- card ผลการประเมนการปฏราชการ -->
<template>
<q-card flat bordered class="col-12 q-px-lg q-pa-md">
<q-form ref="myForm">
<ProfileTable
:rows="rows"
:columns="columns"
:filter="filter"
:visible-columns="visibleColumns"
v-model:inputfilter="filter"
v-model:inputvisible="visibleColumns"
:add="clickAdd"
name="ผลการประเมินการปฏิบัติราชการ"
icon="mdi-clipboard-text"
:statusEdit="statusEdit"
>
<template #columns="props">
<q-tr :props="props">
<q-td
v-for="col in props.cols"
:key="col.name"
:props="props"
@click="selectData(props)"
class="cursor-pointer"
>
<div v-if="col.name == 'date'" class="table_ellipsis">
{{ date2Thai(col.value) }}
</div>
<div v-else-if="col.name == 'name'" class="table_ellipsis">
{{ textPoint(props.row.pointSum) }}
{{ textRangePoint(props.row.pointSum) }}
</div>
<div v-else class="table_ellipsis">
{{ col.value }}
</div>
</q-td>
<q-td auto-width>
<q-btn
color="info"
flat
dense
round
size="14px"
icon="mdi-history"
@click="clickHistory(props.row)"
/>
</q-td>
</q-tr>
</template>
</ProfileTable>
</q-form>
</q-card>
<!-- popup Edit window-->
<q-dialog v-model="modal" persistent>
<q-card style="width: 600px">
<q-form ref="myForm">
<DialogHeader
tittle="ผลการประเมินการปฏิบัติราชการ"
:close="clickClose"
/>
<q-separator />
<q-card-section class="q-p-sm">
<div
class="row col-12 items-center q-col-gutter-x-xs q-col-gutter-y-xs"
>
<div class="col-xs-12 col-sm-12 col-md-12">
<datepicker
menu-class-name="modalfix"
:readonly="!edit"
v-model="date"
:locale="'th'"
autoApply
:enableTimePicker="false"
@update:modelValue="clickEditRow"
week-start="0"
>
<template #year="{ year }">{{ year + 543 }}</template>
<template #year-overlay-value="{ value }">{{
parseInt(value + 543)
}}</template>
<template #trigger>
<q-input
:class="getClass(edit)"
:outlined="edit"
dense
lazy-rules
:borderless="!edit"
:model-value="date2Thai(date)"
:rules="[(val) => !!val || `${'กรุณาเลือกวันที่ได้รับ'}`]"
hide-bottom-space
:label="`${'วันที่ได้รับ'}`"
>
<template v-slot:prepend>
<q-icon
name="event"
class="cursor-pointer"
:style="
edit
? 'color: var(--q-primary)'
: 'color: var(--q-grey)'
"
>
</q-icon>
</template>
</q-input>
</template>
</datepicker>
</div>
<!-- <div class="col-6">
<q-input
:class="getClass(edit)"
:outlined="edit"
dense
lazy-rules
:readonly="!edit"
:borderless="!edit"
v-model="point"
:rules="[(val) => !!val || `${'กรุณากรอกคะแนน'}`]"
hide-bottom-space
:label="`${'คะแนน'}`"
@update:modelValue="clickEditRow"
type="number"
/>
</div> -->
<div class="col-6">
<q-input
input-class="text-right"
:class="getClass(edit)"
:outlined="edit"
dense
lazy-rules
:readonly="!edit"
:borderless="!edit"
v-model="point1Total"
:rules="[(val) => !!val || `${'กรุณากรอกส่วนที่1 (คะแนน)'}`]"
hide-bottom-space
:label="`${'ส่วนที่1 (คะแนน)'}`"
@update:modelValue="clickEditRow"
type="number"
/>
</div>
<div class="col-6">
<q-input
input-class="text-right"
:class="getClass(edit)"
:outlined="edit"
dense
lazy-rules
:readonly="!edit"
:borderless="!edit"
v-model="point1"
:rules="[
(val) => !!val || `${'กรุณากรอกผลประเมินส่วนที่1 (คะแนน)'}`,
]"
hide-bottom-space
:label="`${'ผลประเมินส่วนที่1 (คะแนน)'}`"
@update:modelValue="clickEditRow"
type="number"
/>
</div>
<div class="col-6">
<q-input
input-class="text-right"
:class="getClass(edit)"
:outlined="edit"
dense
lazy-rules
:readonly="!edit"
:borderless="!edit"
v-model="point2Total"
:rules="[(val) => !!val || `${'กรุณากรอกส่วนที่2 (คะแนน)'}`]"
hide-bottom-space
:label="`${'ส่วนที่2 (คะแนน)'}`"
@update:modelValue="clickEditRow"
type="number"
/>
</div>
<div class="col-6">
<q-input
input-class="text-right"
:class="getClass(edit)"
:outlined="edit"
dense
lazy-rules
:readonly="!edit"
:borderless="!edit"
v-model="point2"
:rules="[
(val) => !!val || `${'กรุณากรอกผลประเมินส่วนที่2 (คะแนน)'}`,
]"
hide-bottom-space
:label="`${'ผลประเมินส่วนที่2 (คะแนน)'}`"
@update:modelValue="clickEditRow"
type="number"
/>
</div>
<div class="col-6">
<q-input
input-class="text-right"
:class="getClass(edit)"
:outlined="edit"
dense
lazy-rules
:readonly="!edit"
:borderless="!edit"
v-model="pointSumTotal"
:rules="[(val) => !!val || `${'กรุณากรอกผลรวม (คะแนน)'}`]"
hide-bottom-space
:label="`${'ผลรวม (คะแนน)'}`"
@update:modelValue="clickEditRow"
type="number"
/>
</div>
<div class="col-6">
<q-input
input-class="text-right"
:class="getClass(edit)"
:outlined="edit"
dense
lazy-rules
:readonly="!edit"
:borderless="!edit"
v-model="pointSum"
:rules="[
(val) => !!val || `${'กรุณากรอกผลประเมินรวม (คะแนน)'}`,
]"
hide-bottom-space
:label="`${'ผลประเมินรวม (คะแนน)'}`"
@update:modelValue="clickEditRow"
type="number"
/>
</div>
<div class="text-subtitle2 col-12 row items-center">
<q-space></q-space>
ผลการประเม:
<div class="text-bold items-center q-px-sm">
{{ textPoint(pointSum) }}
</div>
{{ textRangePoint(pointSum) }}
</div>
<!-- <div class="col-12">
<q-input
:class="getClass(edit)"
:outlined="edit"
dense
lazy-rules
:readonly="!edit"
:borderless="!edit"
v-model="name"
:rules="[(val) => !!val || `${'กรุณากรอกชื่อแบบประเมิน'}`]"
hide-bottom-space
:label="`${'ชื่อแบบประเมิน'}`"
@update:modelValue="clickEditRow"
/>
</div> -->
</div>
</q-card-section>
<q-separator />
<DialogFooter
:cancel="clickCancel"
:edit="clickEdit"
:save="clickSave"
:validate="validateData"
:clickNext="clickNext"
:clickPrevious="clickPrevious"
:clickDelete="clickDelete"
v-model:editvisible="edit"
v-model:next="next"
v-model:previous="previous"
v-model:modalEdit="modalEdit"
/>
</q-form>
</q-card>
</q-dialog>
<HistoryTable
:rows="rowsHistory"
:columns="columnsHistory"
:filter="filterHistory"
:visible-columns="visibleColumnsHistory"
v-model:modal="modalHistory"
v-model:inputfilter="filterHistory"
v-model:inputvisible="visibleColumnsHistory"
v-model:tittle="tittleHistory"
>
<template #columns="props">
<q-tr :props="props">
<q-td v-for="col in props.cols" :key="col.name" :props="props">
<div
v-if="col.name == 'date' || col.name == 'createdAt'"
class="table_ellipsis"
>
{{ date2Thai(col.value) }}
</div>
<div v-else-if="col.name == 'name'" class="table_ellipsis">
{{ textPoint(props.row.pointSum) }}
{{ textRangePoint(props.row.pointSum) }}
</div>
<div v-else class="table_ellipsis">
{{ col.value }}
</div>
</q-td>
</q-tr>
</template>
</HistoryTable>
</template>
<script setup lang="ts">
import { onMounted, ref, watch } from "vue";
import { useRoute } from "vue-router";
import { useCounterMixin } from "@/stores/mixin";
import { useProfileDataStore } from "@/modules/04_registry/store";
import ProfileTable from "@/modules/04_registry/components/Table.vue";
import DialogHeader from "@/modules/04_registry/components/DialogHeader.vue";
import DialogFooter from "@/modules/04_registry/components/DialogFooter.vue";
import { useQuasar } from "quasar";
import type {
RequestItemsObject,
DataProps,
} from "@/modules/04_registry/interface/request/Assessment";
import type { ResponseObject } from "@/modules/04_registry/interface/response/Assessment";
import type { DataOption } from "@/modules/04_registry/interface/index/Main";
import HistoryTable from "@/components/TableHistory.vue";
import http from "@/plugins/http";
import config from "@/app.config";
import type { QTableProps } from "quasar";
const props = defineProps({
statusEdit: {
type: Boolean,
required: true,
},
profileType: {
type: String,
required: true,
},
});
const $q = useQuasar();
const store = useProfileDataStore();
const { profileData, changeProfileColumns } = store;
const mixin = useCounterMixin();
const { date2Thai, success, dateToISO, messageError, showLoader, hideLoader } =
mixin;
const route = useRoute();
const id = ref<string>("");
const name = ref<string>();
const point1Total = ref<number>();
const point1 = ref<number>();
const point2Total = ref<number>();
const point2 = ref<number>();
const pointSumTotal = ref<number>();
const pointSum = ref<number>();
const date = ref<Date>(new Date());
const myForm = ref<any>(); //form data input
const edit = ref<boolean>(false); // dialog
const modal = ref<boolean>(false); //modal add detail
const modalEdit = ref<boolean>(false); //modal
const rawItem = ref<RequestItemsObject>(); // row
const rowIndex = ref<number>(0); //index row
const previous = ref<boolean>(); //
const next = ref<boolean>(); //
const editRow = ref<boolean>(false); //
const rowsHistory = ref<RequestItemsObject[]>([]); //select data history
const tittleHistory = ref<string>("ประวัติแก้ไขผลการประเมินการปฏิบัติราชการ"); //
const filterHistory = ref<string>(""); //search data table history
const modalHistory = ref<boolean>(false); //modal
const checkValidate = ref<boolean>(false); //validate data
const profileId = ref<string>(
route.params.id ? route.params.id.toString() : ""
);
const rows = ref<RequestItemsObject[]>([]);
const filter = ref<string>(""); //search data table
const visibleColumns = ref<String[]>([]);
profileData.assessment.columns.length == 0
? (visibleColumns.value = [
"point1Total",
"point1",
"point2Total",
"point2",
"pointSumTotal",
"pointSum",
"name",
"date",
])
: (visibleColumns.value = profileData.assessment.columns);
const columns = ref<QTableProps["columns"]>([
{
name: "date",
align: "left",
label: "วันที่ได้รับ",
sortable: true,
field: "date",
headerStyle: "font-size: 14px",
style: "font-size: 14px",
sort: (a: string, b: string) =>
a.localeCompare(b, undefined, { numeric: true, sensitivity: "base" }),
},
{
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: "name",
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: "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: "name",
headerStyle: "font-size: 14px",
style: "font-size: 14px",
sort: (a: string, b: string) =>
a.localeCompare(b, undefined, { numeric: true, sensitivity: "base" }),
},
{
name: "createdFullName",
align: "left",
label: "ผู้ดำเนินการ",
sortable: true,
field: "createdFullName",
headerStyle: "font-size: 14px",
style: "font-size: 14px",
sort: (a: string, b: string) =>
a.localeCompare(b, undefined, { numeric: true, sensitivity: "base" }),
},
{
name: "createdAt",
align: "left",
label: "วันที่แก้ไข",
sortable: true,
field: "createdAt",
headerStyle: "font-size: 14px",
style: "font-size: 14px",
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",
"createdFullName",
"createdAt",
]);
watch(visibleColumns, async (count: String[], prevCount: String[]) => {
await changeProfileColumns("assessment", count);
});
onMounted(async () => {
await fetchData();
});
const fetchData = async () => {
if (profileId.value) {
showLoader();
await http
.get(config.API.profileAssessmentId(profileId.value))
.then((res) => {
let data = res.data.result;
rows.value = [];
data.map((e: ResponseObject) => {
rows.value.push({
id: e.id,
name: e.name,
point1Total: e.point1Total,
point1: e.point1,
point2Total: e.point2Total,
point2: e.point2,
pointSumTotal: e.pointSumTotal,
pointSum: e.pointSum,
date: new Date(e.date),
createdAt: new Date(e.createdAt),
createdFullName: e.createdFullName,
});
});
})
.catch((e) => {
messageError($q, e);
})
.finally(() => {
hideLoader();
});
}
};
/**
* กดดอมลกอนหน
*/
const clickPrevious = async () => {
edit.value = false;
rowIndex.value -= 1;
await getData();
await checkRowPage();
};
/**
* กดดอมลตอไป
*/
const clickNext = async () => {
edit.value = false;
rowIndex.value += 1;
await getData();
await checkRowPage();
};
/**
* กดดอมลตอไป
*/
const getData = () => {
const row = rows.value[rowIndex.value];
name.value = row.name;
point1Total.value = row.point1Total;
point1.value = row.point1;
point2Total.value = row.point2Total;
point2.value = row.point2;
pointSumTotal.value = row.pointSumTotal;
pointSum.value = row.pointSum;
date.value = row.date;
id.value = row.id;
};
/**
* เชคปมดอม อน อไป าตองแสดงไหม
*/
const checkRowPage = () => {
editRow.value = false;
next.value = true;
previous.value = true;
if (rowIndex.value + 1 >= rows.value.length) {
next.value = false;
}
if (rowIndex.value - 1 < 0) {
previous.value = false;
}
};
/**
* กดปมแกไขใน dialog
*/
const clickEdit = () => {
editRow.value = false;
next.value = false;
previous.value = false;
};
/**
* กดปมเพมดานบน table
*/
const clickAdd = async () => {
editRow.value = false;
await addData();
};
/**
* กดบนทกใน dialog
*/
const clickSave = async () => {
myForm.value.validate().then(async (result: boolean) => {
if (result) {
if (modalEdit.value) {
await editData();
} else {
await saveData();
}
}
});
};
/**
* นทกเพมขอม
*/
const saveData = async () => {
if (profileId.value) {
showLoader();
await http
.post(config.API.profileAssessmentId(profileId.value), {
id: id.value,
name: name.value,
point1Total: point1Total.value,
point1: point1.value,
point2Total: point2Total.value,
point2: point2.value,
pointSumTotal: pointSumTotal.value,
pointSum: pointSum.value,
date: dateToISO(date.value),
})
.then((res) => {
success($q, "บันทึกข้อมูลสำเร็จ");
modal.value = false;
})
.catch((e) => {
messageError($q, e);
})
.finally(async () => {
await fetchData();
});
}
};
/**
* นทกแกไขขอม
*/
const editData = async () => {
showLoader();
await http
.put(config.API.profileAssessmentId(id.value), {
id: id.value,
name: name.value,
point1Total: point1Total.value,
point1: point1.value,
point2Total: point2Total.value,
point2: point2.value,
pointSumTotal: pointSumTotal.value,
pointSum: pointSum.value,
date: dateToISO(date.value),
})
.then((res) => {
success($q, "บันทึกข้อมูลสำเร็จ");
modal.value = false;
})
.catch((e) => {
messageError($q, e);
})
.finally(async () => {
await fetchData();
});
};
/**
* ลบลบขอม
*/
const clickDelete = async () => {
$q.dialog({
title: `ลบข้อมูล`,
message: `ต้องการทำการลบข้อมูลนี้ใช่หรือไม่?`,
cancel: "ยกเลิก",
ok: "ยืนยัน",
persistent: true,
})
.onOk(async () => {
showLoader();
await http
.delete(config.API.profileAssessmentId(id.value))
.then((res) => {
success($q, "ลบข้อมูลสำเร็จ");
modal.value = false;
})
.catch((e) => {
messageError($q, e);
})
.finally(async () => {
await fetchData();
});
})
.onCancel(async () => {
await fetchData();
});
};
/**
* กดป dialog
*/
const clickClose = async () => {
if (editRow.value == true) {
$q.dialog({
title: `ข้อมูลมีการแก้ไข`,
message: `ยืนยันที่จะปิดโดยไม่บันทึกใช่หรือไม่?`,
cancel: "ยกเลิก",
ok: "ยืนยัน",
persistent: true,
}).onOk(async () => {
modal.value = false;
next.value = false;
previous.value = false;
});
} else {
modal.value = false;
next.value = false;
previous.value = false;
}
};
/**
* กดเลอกขอมลทจะแกไข
* @param props props ใน row เลอก
*/
const selectData = async (props: DataProps) => {
modalEdit.value = true;
modal.value = true;
edit.value = false;
rawItem.value = props.row;
rowIndex.value = props.rowIndex;
name.value = props.row.name;
point1Total.value = props.row.point1Total;
point1.value = props.row.point1;
point2Total.value = props.row.point2Total;
point2.value = props.row.point2;
pointSumTotal.value = props.row.pointSumTotal;
pointSum.value = props.row.pointSum;
date.value = props.row.date;
id.value = props.row.id;
await checkRowPage();
};
/**
* กดปมเพมบน table
*/
const addData = () => {
modalEdit.value = false;
modal.value = true;
edit.value = true;
name.value = "";
point1Total.value = 0;
point1.value = 0;
point2Total.value = 0;
point2.value = 0;
pointSumTotal.value = 0;
pointSum.value = 0;
date.value = new Date();
};
/**
* งกนปมยกเลกการแกไขขอม
*/
const clickCancel = async () => {
if (editRow.value == true) {
$q.dialog({
title: `ข้อมูลมีการแก้ไข`,
message: `ยืนยันยกเลิกการแก้ไขใช่หรือไม่?`,
cancel: "ยกเลิก",
ok: "ยืนยัน",
persistent: true,
}).onOk(async () => {
edit.value = false;
await checkRowPage();
await getData();
});
} else {
edit.value = false;
await checkRowPage();
}
};
/**
* เชความการแกไขขอม
*/
const clickEditRow = () => {
editRow.value = true;
};
/**
* งชนดอมลประวแกไขขอมลทเลอก
* @param row อม row ประวการแกไข
*/
const clickHistory = async (row: RequestItemsObject) => {
tittleHistory.value = "ประวัติแก้ไขผลการประเมินการปฏิบัติราชการ";
modalHistory.value = true;
showLoader();
await http
.get(config.API.profileAssessmentHisId(row.id))
.then((res) => {
let data = res.data.result;
rowsHistory.value = [];
data.map((e: ResponseObject) => {
rowsHistory.value.push({
id: e.id,
name: e.name,
point1Total: e.point1Total,
point1: e.point1,
point2Total: e.point2Total,
point2: e.point2,
pointSumTotal: e.pointSumTotal,
pointSum: e.pointSum,
date: new Date(e.date),
createdAt: new Date(e.createdAt),
createdFullName: e.createdFullName,
});
});
})
.catch((e) => {
messageError($q, e);
})
.finally(() => {
hideLoader();
});
};
/**
* validate input ใน dialog
*/
const validateData = async () => {
checkValidate.value = true;
await myForm.value.validate().then((result: boolean) => {
if (result == false) {
checkValidate.value = false;
}
});
};
/**
* class ดรปแบบแสดงระหวางขอมลทแกไขหรอแสดงเฉยๆ
* @param val อม input สำหรบแกไขหรอไม
*/
const getClass = (val: boolean) => {
return {
"full-width inputgreen cursor-pointer": val,
"full-width cursor-pointer": !val,
};
};
const textRangePoint = (val: number | undefined) => {
if (val == undefined) val = -1;
if (val >= 0 && val <= 60) return "(ต่ำกว่าร้อยละ 60)";
if (val >= 60 && val <= 69) return "(ร้อยละ 60 69)";
if (val >= 70 && val <= 79) return "(ร้อยละ 70 79)";
if (val >= 80 && val <= 89) return "(ร้อยละ 80 89)";
if (val >= 90 && val <= 100) return "(ร้อยละ 90 - 100)";
else return "";
};
const textPoint = (val: number | undefined) => {
if (val == undefined) val = -1;
if (val >= 0 && val <= 60) return "ต้องปรับปรุง";
if (val >= 60 && val <= 69) return "พอใช้";
if (val >= 70 && val <= 79) return "ดี";
if (val >= 80 && val <= 89) return "ดีมาก";
if (val >= 90 && val <= 100) return "ดีเด่น";
else return "-";
};
</script>
<style lang="scss">
.modalfix {
position: fixed !important;
}
</style>

View file

@ -0,0 +1,829 @@
<!-- card ใบอนญาตประกอบอาช -->
<template>
<q-card flat bordered class="col-12 q-px-lg q-py-md q-mt-md">
<q-form ref="myForm">
<ProfileTable
:rows="rows"
:columns="columns"
:filter="filter"
:visible-columns="visibleColumns"
v-model:inputfilter="filter"
v-model:inputvisible="visibleColumns"
:add="clickAdd"
:name="
profileType == 'employee'
? 'ใบอนุญาตของลูกจ้าง'
: 'ใบอนุญาตประกอบอาชีพ'
"
icon="mdi-book"
:statusEdit="statusEdit"
>
<template #columns="props">
<q-tr :props="props">
<q-td
v-for="col in props.cols"
:key="col.name"
:props="props"
@click="selectData(props)"
class="cursor-pointer"
>
<div
v-if="col.name == 'issueDate' || col.name == 'expireDate'"
class="table_ellipsis"
>
{{ date2Thai(col.value) }}
</div>
<div v-else class="table_ellipsis">
{{ col.value }}
</div>
</q-td>
<q-td auto-width>
<q-btn
color="info"
flat
dense
round
size="14px"
icon="mdi-history"
@click="clickHistory(props.row)"
/>
</q-td>
</q-tr>
</template>
</ProfileTable>
</q-form>
</q-card>
<!-- popup Edit window-->
<q-dialog v-model="modal" persistent>
<q-card style="width: 600px">
<q-form ref="myForm">
<DialogHeader
:tittle="
profileType == 'employee'
? 'ใบอนุญาตของลูกจ้าง'
: 'ใบอนุญาตประกอบอาชีพ'
"
:close="clickClose"
/>
<q-separator />
<q-card-section class="q-p-sm">
<div
class="row col-12 items-center q-col-gutter-x-xs q-col-gutter-y-xs"
>
<div class="col-xs-6 col-sm-6 col-md-6">
<q-input
:class="getClass(edit)"
:outlined="edit"
dense
lazy-rules
:readonly="!edit"
:borderless="!edit"
v-model="certificateType"
:rules="[(val) => !!val || `${'กรุณากรอกชื่อใบอนุญาต'}`]"
hide-bottom-space
:label="`${'ชื่อใบอนุญาต'}`"
@update:modelValue="clickEditRow"
/>
</div>
<div class="col-xs-6 col-sm-6 col-md-6">
<q-input
:class="getClass(edit)"
:outlined="edit"
dense
lazy-rules
:readonly="!edit"
:borderless="!edit"
v-model="issuer"
:rules="[
(val) => !!val || `${'กรุณากรอกหน่วยงานผู้ออกใบอนุญาต'}`,
]"
hide-bottom-space
:label="`${'หน่วยงานผู้ออกใบอนุญาต'}`"
@update:modelValue="clickEditRow"
/>
</div>
<div class="col-xs-6 col-sm-6 col-md-6">
<q-input
:class="getClass(edit)"
:outlined="edit"
dense
lazy-rules
:readonly="!edit"
:borderless="!edit"
v-model="certificateNo"
:rules="[(val) => !!val || `${'กรุณากรอกเลขที่ใบอนุญาต'}`]"
hide-bottom-space
:label="`${'เลขที่ใบอนุญาต'}`"
@update:modelValue="clickEditRow"
/>
</div>
<div class="col-xs-6 col-sm-6 col-md-6">
<datepicker
menu-class-name="modalfix"
:readonly="!edit"
v-model="issueDate"
:locale="'th'"
autoApply
:enableTimePicker="false"
@update:modelValue="clickEditRow"
week-start="0"
>
<template #year="{ year }">{{ year + 543 }}</template>
<template #year-overlay-value="{ value }">{{
parseInt(value + 543)
}}</template>
<template #trigger>
<q-input
:class="getClass(edit)"
:outlined="edit"
dense
lazy-rules
:borderless="!edit"
:model-value="date2Thai(issueDate)"
:rules="[
(val) => !!val || `${'กรุณาเลือกวันที่ออกใบอนุญาต'}`,
]"
hide-bottom-space
:label="`${'วันที่ออกใบอนุญาต'}`"
>
<template v-slot:prepend>
<q-icon
name="event"
class="cursor-pointer"
:style="
edit
? 'color: var(--q-primary)'
: 'color: var(--q-grey)'
"
>
</q-icon>
</template>
</q-input>
</template>
</datepicker>
</div>
<div class="col-xs-6 col-sm-6 col-md-6">
<datepicker
menu-class-name="modalfix"
v-model="expireDate"
:locale="'th'"
autoApply
:enableTimePicker="false"
:min-date="minDate"
:readonly="!edit"
@update:modelValue="clickEditRow"
week-start="0"
>
<template #year="{ year }">{{ year + 543 }}</template>
<template #year-overlay-value="{ value }">{{
parseInt(value + 543)
}}</template>
<template #trigger>
<q-input
:class="getClass(edit)"
:outlined="edit"
dense
lazy-rules
:borderless="!edit"
:model-value="date2Thai(expireDate)"
:rules="[(val) => !!val || `${'กรุณาเลือกวันที่หมดอายุ'}`]"
hide-bottom-space
:label="`${'วันที่หมดอายุ'}`"
>
<template v-slot:prepend>
<q-icon
name="event"
class="cursor-pointer"
:style="
edit
? 'color: var(--q-primary)'
: 'color: var(--q-grey)'
"
>
</q-icon>
</template>
</q-input>
</template>
</datepicker>
</div>
</div>
</q-card-section>
<q-separator />
<DialogFooter
:cancel="clickCancel"
:edit="clickEdit"
:save="clickSave"
:validate="validateData"
:clickNext="clickNext"
:clickPrevious="clickPrevious"
:clickDelete="clickDelete"
v-model:editvisible="edit"
v-model:next="next"
v-model:previous="previous"
v-model:modalEdit="modalEdit"
/>
</q-form>
</q-card>
</q-dialog>
<HistoryTable
:rows="rowsHistory"
:columns="columnsHistory"
:filter="filterHistory"
:visible-columns="visibleColumnsHistory"
v-model:modal="modalHistory"
v-model:inputfilter="filterHistory"
v-model:inputvisible="visibleColumnsHistory"
v-model:tittle="tittleHistory"
>
<template #columns="props">
<q-tr :props="props">
<q-td v-for="col in props.cols" :key="col.name" :props="props">
<div
v-if="
col.name == 'expireDate' ||
col.name == 'issueDate' ||
col.name == 'createdAt'
"
class="table_ellipsis"
>
{{ date2Thai(col.value) }}
</div>
<div v-else class="table_ellipsis">
{{ col.value }}
</div>
</q-td>
</q-tr>
</template>
</HistoryTable>
</template>
<script setup lang="ts">
import { onMounted, ref, watch } from "vue";
import { useRoute } from "vue-router";
import { useComponentProfileDataStore } from "@/components/information/store/store";
import { useCounterMixin } from "@/stores/mixin";
import ProfileTable from "@/components/information/Table.vue";
import DialogHeader from "@/components/information/DialogHeader.vue";
import DialogFooter from "@/components/information/DialogFooter.vue";
import { useQuasar } from "quasar";
import type {
RequestItemsObject,
DataProps,
} from "@/components/information/interface/request/Certificate";
import type { ResponseObject } from "@/components/information/interface/response/Certificate";
import HistoryTable from "@/components/TableHistory.vue";
import http from "@/plugins/http";
import config from "@/app.config";
import type { QTableProps } from "quasar";
const props = defineProps({
statusEdit: {
type: Boolean,
required: true,
},
profileType: {
type: String,
required: true,
},
});
const $q = useQuasar();
const store = useComponentProfileDataStore();
const { profileData, changeProfileColumns } = store;
const mixin = useCounterMixin();
const { date2Thai, success, dateToISO, messageError, showLoader, hideLoader } =
mixin;
const route = useRoute();
const id = ref<string>("");
const certificateNo = ref<string>();
const issuer = ref<string>();
const issueDate = ref<Date>(new Date());
const expireDate = ref<Date>(new Date());
const certificateType = ref<string>();
const minDate = ref<Date>();
const myForm = ref<any>(); //form data input
const edit = ref<boolean>(false); // dialog
const modal = ref<boolean>(false); //modal add detail
const modalEdit = ref<boolean>(false); //modal
const rawItem = ref<RequestItemsObject>(); // row
const rowIndex = ref<number>(0); //index row
const previous = ref<boolean>(); //
const next = ref<boolean>(); //
const editRow = ref<boolean>(false); //
const rowsHistory = ref<RequestItemsObject[]>([]); //select data history
const tittleHistory = ref<string>("ประวัติแก้ไขใบอนุญาตประกอบอาชีพ"); //
const filterHistory = ref<string>(""); //search data table history
const modalHistory = ref<boolean>(false); //modal
const checkValidate = ref<boolean>(false); //validate data
const profileId = ref<string>(
route.params.id ? route.params.id.toString() : ""
);
const rows = ref<RequestItemsObject[]>([]);
const filter = ref<string>(""); //search data table
const visibleColumns = ref<String[]>([]);
profileData.certicate.columns.length == 0
? (visibleColumns.value = [
"certificateType",
"certificateNo",
"issuer",
"issueDate",
"expireDate",
])
: (visibleColumns.value = profileData.certicate.columns);
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",
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,
field: "expireDate",
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: "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",
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,
field: "expireDate",
headerStyle: "font-size: 14px",
style: "font-size: 14px",
sort: (a: string, b: string) =>
a.localeCompare(b, undefined, { numeric: true, sensitivity: "base" }),
},
{
name: "createdFullName",
align: "left",
label: "ผู้ดำเนินการ",
sortable: true,
field: "createdFullName",
headerStyle: "font-size: 14px",
style: "font-size: 14px",
sort: (a: string, b: string) =>
a.localeCompare(b, undefined, { numeric: true, sensitivity: "base" }),
},
{
name: "createdAt",
align: "left",
label: "วันที่แก้ไข",
sortable: true,
field: "createdAt",
headerStyle: "font-size: 14px",
style: "font-size: 14px",
sort: (a: string, b: string) =>
a.localeCompare(b, undefined, { numeric: true, sensitivity: "base" }),
},
]);
const visibleColumnsHistory = ref<String[]>([
"certificateType",
"certificateNo",
"issuer",
"issueDate",
"expireDate",
"createdFullName",
"createdAt",
]);
watch(visibleColumns, async (count: String[], prevCount: String[]) => {
await changeProfileColumns("certicate", count);
});
onMounted(async () => {
await fetchData();
});
const fetchData = async () => {
if (profileId.value) {
showLoader();
await http
.get(config.API.profileCertId(profileId.value))
.then((res) => {
let data = res.data.result;
rows.value = [];
data.map((e: ResponseObject) => {
rows.value.push({
id: e.id,
certificateNo: e.certificateNo,
issuer: e.issuer,
issueDate: new Date(e.issueDate),
expireDate: new Date(e.expireDate),
certificateType: e.certificateType,
createdFullName: e.createdFullName,
createdAt: new Date(e.createdAt),
});
});
})
.catch((e) => {
messageError($q, e);
})
.finally(() => {
hideLoader();
});
}
};
/**
* กดดอมลกอนหน
*/
const clickPrevious = async () => {
edit.value = false;
rowIndex.value -= 1;
await getData();
await checkRowPage();
};
/**
* กดดอมลตอไป
*/
const clickNext = async () => {
edit.value = false;
rowIndex.value += 1;
await getData();
await checkRowPage();
};
/**
* กดดอมลตอไป
*/
const getData = () => {
const row = rows.value[rowIndex.value];
certificateNo.value = row.certificateNo;
issuer.value = row.issuer;
issueDate.value = row.issueDate;
expireDate.value = row.expireDate;
certificateType.value = row.certificateType;
id.value = row.id;
};
/**
* เชคปมดอม อน อไป าตองแสดงไหม
*/
const checkRowPage = () => {
editRow.value = false;
next.value = true;
previous.value = true;
if (rowIndex.value + 1 >= rows.value.length) {
next.value = false;
}
if (rowIndex.value - 1 < 0) {
previous.value = false;
}
};
/**
* กดปมแกไขใน dialog
*/
const clickEdit = () => {
editRow.value = false;
next.value = false;
previous.value = false;
};
/**
* กดปมเพมดานบน table
*/
const clickAdd = async () => {
editRow.value = false;
await addData();
};
/**
* กดบนทกใน dialog
*/
const clickSave = async () => {
myForm.value.validate().then(async (result: boolean) => {
if (result) {
if (modalEdit.value) {
await editData();
} else {
await saveData();
}
}
});
};
/**
* นทกเพมขอม
*/
const saveData = async () => {
showLoader();
await http
.post(config.API.profileCertId(profileId.value), {
id: id.value,
certificateNo: certificateNo.value,
issuer: issuer.value,
issueDate: dateToISO(issueDate.value),
expireDate: dateToISO(expireDate.value),
certificateType: certificateType.value,
})
.then((res) => {
success($q, "บันทึกข้อมูลสำเร็จ");
modal.value = false;
})
.catch((e) => {
messageError($q, e);
})
.finally(async () => {
await fetchData();
});
};
/**
* นทกแกไขขอม
*/
const editData = async () => {
showLoader();
await http
.put(config.API.profileCertId(id.value), {
id: id.value,
certificateNo: certificateNo.value,
issuer: issuer.value,
issueDate: dateToISO(issueDate.value),
expireDate: dateToISO(expireDate.value),
certificateType: certificateType.value,
})
.then((res) => {
success($q, "บันทึกข้อมูลสำเร็จ");
modal.value = false;
})
.catch((e) => {
messageError($q, e);
})
.finally(async () => {
await fetchData();
});
};
/**
* ลบลบขอม
*/
const clickDelete = async () => {
$q.dialog({
title: `ลบข้อมูล`,
message: `ต้องการทำการลบข้อมูลนี้ใช่หรือไม่?`,
cancel: "ยกเลิก",
ok: "ยืนยัน",
persistent: true,
})
.onOk(async () => {
showLoader();
await http
.delete(config.API.profileCertId(id.value))
.then((res) => {
success($q, "ลบข้อมูลสำเร็จ");
modal.value = false;
})
.catch((e) => {
messageError($q, e);
})
.finally(async () => {
await fetchData();
});
})
.onCancel(async () => {
await fetchData();
});
};
/**
* กดป dialog
*/
const clickClose = async () => {
if (editRow.value == true) {
$q.dialog({
title: `ข้อมูลมีการแก้ไข`,
message: `ยืนยันที่จะปิดโดยไม่บันทึกใช่หรือไม่?`,
cancel: "ยกเลิก",
ok: "ยืนยัน",
persistent: true,
}).onOk(async () => {
modal.value = false;
next.value = false;
previous.value = false;
});
} else {
modal.value = false;
next.value = false;
previous.value = false;
}
};
/**
* กดเลอกขอมลทจะแกไข
* @param props props ใน row เลอก
*/
const selectData = async (props: DataProps) => {
modalEdit.value = true; //
modal.value = true; //modal
edit.value = false; // edit modal
rawItem.value = props.row;
rowIndex.value = props.rowIndex;
certificateNo.value = props.row.certificateNo;
issuer.value = props.row.issuer;
issueDate.value = props.row.issueDate;
expireDate.value = props.row.expireDate;
certificateType.value = props.row.certificateType;
id.value = props.row.id;
await checkRowPage();
};
/**
* กดปมเพมบน table
*/
const addData = () => {
modalEdit.value = false;
modal.value = true;
edit.value = true;
certificateNo.value = "";
issuer.value = "";
issueDate.value = new Date();
expireDate.value = new Date();
certificateType.value = "";
};
/**
* งกนปมยกเลกการแกไขขอม
*/
const clickCancel = async () => {
if (editRow.value == true) {
$q.dialog({
title: `ข้อมูลมีการแก้ไข`,
message: `ยืนยันยกเลิกการแก้ไขใช่หรือไม่?`,
cancel: "ยกเลิก",
ok: "ยืนยัน",
persistent: true,
}).onOk(async () => {
edit.value = false;
await checkRowPage();
await getData();
});
} else {
edit.value = false;
await checkRowPage();
}
};
/**
* เชความการแกไขขอม
*/
const clickEditRow = () => {
editRow.value = true;
};
/**
* งชนดอมลประวแกไขขอมลทเลอก
* @param row อม row ประวการแกไข
*/
const clickHistory = async (row: RequestItemsObject) => {
tittleHistory.value =
props.profileType == "employee"
? "ประวัติแก้ไขใบอนุญาตของลูกจ้าง"
: "ประวัติแก้ไขใบอนุญาตประกอบอาชีพ";
modalHistory.value = true;
showLoader();
await http
.get(config.API.profileCertHisId(row.id))
.then((res) => {
let data = res.data.result;
rowsHistory.value = [];
data.map((e: ResponseObject) => {
rowsHistory.value.push({
id: e.id,
certificateNo: e.certificateNo,
issuer: e.issuer,
issueDate: new Date(e.issueDate),
expireDate: new Date(e.expireDate),
certificateType: e.certificateType,
createdFullName: e.createdFullName,
createdAt: new Date(e.createdAt),
});
});
})
.catch((e) => {
messageError($q, e);
})
.finally(() => {
hideLoader();
});
};
/**
* validate input ใน dialog
*/
const validateData = async () => {
checkValidate.value = true;
await myForm.value.validate().then((result: boolean) => {
if (result == false) {
checkValidate.value = false;
}
});
};
/**
* class ดรปแบบแสดงระหวางขอมลทแกไขหรอแสดงเฉยๆ
* @param val อม input สำหรบแกไขหรอไม
*/
const getClass = (val: boolean) => {
return {
"full-width inputgreen cursor-pointer": val,
"full-width cursor-pointer": !val,
};
};
</script>
<style lang="scss">
.modalfix {
position: fixed !important;
}
</style>

View file

@ -0,0 +1,840 @@
<!-- card ประกาศเกยรต -->
<template>
<q-card flat bordered class="col-12 q-px-lg q-pa-md">
<q-form ref="myForm">
<ProfileTable
:rows="rows"
:columns="columns"
:filter="filter"
:visible-columns="visibleColumns"
v-model:inputfilter="filter"
v-model:inputvisible="visibleColumns"
:add="clickAdd"
:name="
profileType == 'employee' ? 'ประกาศลูกจ้างดีเด่น' : 'ประกาศเกียรติคุณ'
"
icon="mdi-script-text"
:statusEdit="statusEdit"
>
<template #columns="props">
<q-tr :props="props">
<q-td
v-for="col in props.cols"
:key="col.name"
:props="props"
@click="selectData(props)"
class="cursor-pointer"
>
<div
v-if="col.name == 'issueDate' || col.name == 'refCommandDate'"
class="table_ellipsis"
>
{{ col.value == null ? null : date2Thai(col.value) }}
</div>
<div v-else class="table_ellipsis">
{{ col.value }}
</div>
</q-td>
<q-td auto-width>
<q-btn
color="info"
flat
dense
round
size="14px"
icon="mdi-history"
@click="clickHistory(props.row)"
/>
</q-td>
</q-tr>
</template>
</ProfileTable>
</q-form>
</q-card>
<!-- popup Edit window-->
<q-dialog v-model="modal" persistent>
<q-card style="width: 600px">
<q-form ref="myForm">
<DialogHeader
:tittle="
profileType == 'employee'
? 'ประกาศลูกจ้างดีเด่น'
: 'ประกาศเกียรติคุณ'
"
:close="clickClose"
/>
<q-separator />
<q-card-section class="q-p-sm">
<div
class="row col-12 items-center q-col-gutter-x-xs q-col-gutter-y-xs"
>
<div class="col-xs-6 col-sm-6 col-md-6">
<datepicker
menu-class-name="modalfix"
:readonly="!edit"
v-model="issueDate"
:locale="'th'"
autoApply
:enableTimePicker="false"
@update:modelValue="clickEditRow"
week-start="0"
>
<template #year="{ year }">{{ year + 543 }}</template>
<template #year-overlay-value="{ value }">{{
parseInt(value + 543)
}}</template>
<template #trigger>
<q-input
:class="getClass(edit)"
:outlined="edit"
dense
lazy-rules
:borderless="!edit"
:model-value="date2Thai(issueDate)"
:rules="[(val) => !!val || `${'กรุณาเลือกวันที่ได้รับ'}`]"
hide-bottom-space
:label="`${'วันที่ได้รับ'}`"
>
<template v-slot:prepend>
<q-icon
name="event"
class="cursor-pointer"
:style="
edit
? 'color: var(--q-primary)'
: 'color: var(--q-grey)'
"
>
</q-icon>
</template>
</q-input>
</template>
</datepicker>
</div>
<div class="col-6">
<q-input
:class="getClass(edit)"
:outlined="edit"
dense
autogrow
lazy-rules
:readonly="!edit"
:borderless="!edit"
v-model="issuer"
:rules="[(val) => !!val || `${'กรุณากรอกผู้มีอำนาจลงนาม'}`]"
hide-bottom-space
:label="`${'ผู้มีอำนาจลงนาม'}`"
@update:modelValue="clickEditRow"
/>
</div>
<div class="col-12">
<q-input
:class="getClass(edit)"
:outlined="edit"
dense
autogrow
lazy-rules
:readonly="!edit"
:borderless="!edit"
v-model="detail"
:rules="[(val) => !!val || `${'กรุณากรอกรายละเอียด'}`]"
hide-bottom-space
:label="`${'รายละเอียด'}`"
@update:modelValue="clickEditRow"
/>
</div>
<div class="col-xs-6 col-sm-6 col-md-6">
<q-input
:class="getClass(edit)"
:outlined="edit"
dense
lazy-rules
:readonly="!edit"
:borderless="!edit"
v-model="refCommandNo"
hide-bottom-space
:label="`${'เลขที่คำสั่ง'}`"
@update:modelValue="clickEditRow"
>
<template v-slot:append>
<q-icon
name="mdi-file"
class="cursor-pointer"
@click="resetFilter"
/>
</template>
</q-input>
</div>
<div class="col-xs-6 col-sm-6 col-md-6">
<datepicker
menu-class-name="modalfix"
:readonly="!edit"
v-model="refCommandDate"
:locale="'th'"
autoApply
:enableTimePicker="false"
@update:modelValue="clickEditRow"
week-start="0"
>
<template #year="{ year }">{{ year + 543 }}</template>
<template #year-overlay-value="{ value }">{{
parseInt(value + 543)
}}</template>
<template #trigger>
<q-input
:class="getClass(edit)"
:outlined="edit"
dense
lazy-rules
:borderless="!edit"
:model-value="
refCommandDate == null ? null : date2Thai(refCommandDate)
"
hide-bottom-space
:label="`${'เอกสารอ้างอิง (ลงวันที่)'}`"
>
<template v-slot:prepend>
<q-icon
name="event"
class="cursor-pointer"
:style="
edit
? 'color: var(--q-primary)'
: 'color: var(--q-grey)'
"
>
</q-icon>
</template>
</q-input>
</template>
</datepicker>
</div>
</div>
</q-card-section>
<q-separator />
<DialogFooter
:cancel="clickCancel"
:edit="clickEdit"
:save="clickSave"
:validate="validateData"
:clickNext="clickNext"
:clickPrevious="clickPrevious"
:clickDelete="clickDelete"
v-model:editvisible="edit"
v-model:next="next"
v-model:previous="previous"
v-model:modalEdit="modalEdit"
/>
</q-form>
</q-card>
</q-dialog>
<HistoryTable
:rows="rowsHistory"
:columns="columnsHistory"
:filter="filterHistory"
:visible-columns="visibleColumnsHistory"
v-model:modal="modalHistory"
v-model:inputfilter="filterHistory"
v-model:inputvisible="visibleColumnsHistory"
v-model:tittle="tittleHistory"
>
<template #columns="props">
<q-tr :props="props">
<q-td v-for="col in props.cols" :key="col.name" :props="props">
<div
v-if="
col.name == 'issueDate' ||
col.name == 'createdAt' ||
col.name == 'refCommandDate'
"
class="table_ellipsis"
>
{{ col.value == null ? null : date2Thai(col.value) }}
</div>
<div v-else class="table_ellipsis">
{{ col.value }}
</div>
</q-td>
</q-tr>
</template>
</HistoryTable>
</template>
<script setup lang="ts">
import { onMounted, ref, watch } from "vue";
import { useRoute } from "vue-router";
import { useCounterMixin } from "@/stores/mixin";
import { useComponentProfileDataStore } from "@/components/information/store/store";
import ProfileTable from "@/components/information/Table.vue";
import DialogHeader from "@/components/information/DialogHeader.vue";
import DialogFooter from "@/components/information/DialogFooter.vue";
import { useQuasar } from "quasar";
import type {
RequestItemsObject,
Columns,
DataProps,
} from "@/components/information/interface/request/Coin";
import type { ResponseObject } from "@/components/information/interface/response/Coin";
import HistoryTable from "@/components/TableHistory.vue";
import http from "@/plugins/http";
import config from "@/app.config";
import type { QTableProps } from "quasar";
const props = defineProps({
statusEdit: {
type: Boolean,
required: true,
},
profileType: {
type: String,
required: true,
},
});
const $q = useQuasar();
const store = useComponentProfileDataStore();
const { profileData, changeProfileColumns } = store;
const mixin = useCounterMixin();
const { date2Thai, success, dateToISO, messageError, showLoader, hideLoader } =
mixin;
const route = useRoute();
const id = ref<string>("");
const issuer = ref<string>();
const detail = ref<string>();
const issueDate = ref<Date>(new Date());
const refCommandNo = ref<string>();
const refCommandDate = ref<Date | null>(new Date());
const myForm = ref<any>(); //form data input
const edit = ref<boolean>(false); // dialog
const modal = ref<boolean>(false); //modal add detail
const modalEdit = ref<boolean>(false); //modal
const rawItem = ref<RequestItemsObject>(); // row
const rowIndex = ref<number>(0); //index row
const previous = ref<boolean>(); //
const next = ref<boolean>(); //
const editRow = ref<boolean>(false); //
const rowsHistory = ref<RequestItemsObject[]>([]); //select data history
const tittleHistory = ref<string>("ประวัติแก้ไขประกาศเกียรติคุณ"); //
const filterHistory = ref<string>(""); //search data table history
const modalHistory = ref<boolean>(false); //modal
const checkValidate = ref<boolean>(false); //validate data
const profileId = ref<string>(
route.params.id ? route.params.id.toString() : ""
);
const rows = ref<RequestItemsObject[]>([]);
const filter = ref<string>(""); //search data table
const visibleColumns = ref<String[]>([]);
profileData.coined.columns.length == 0
? (visibleColumns.value = [
"issuer",
"detail",
"issueDate",
"refCommandNo",
"refCommandDate",
])
: (visibleColumns.value = profileData.coined.columns);
const columns = ref<QTableProps["columns"]>([
{
name: "issueDate",
align: "left",
label: "วันที่ได้รับ",
sortable: true,
field: "issueDate",
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: "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",
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: "issueDate",
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: "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",
sort: (a: string, b: string) =>
a.localeCompare(b, undefined, { numeric: true, sensitivity: "base" }),
},
{
name: "createdFullName",
align: "left",
label: "ผู้ดำเนินการ",
sortable: true,
field: "createdFullName",
headerStyle: "font-size: 14px",
style: "font-size: 14px",
sort: (a: string, b: string) =>
a.localeCompare(b, undefined, { numeric: true, sensitivity: "base" }),
},
{
name: "createdAt",
align: "left",
label: "วันที่แก้ไข",
sortable: true,
field: "createdAt",
headerStyle: "font-size: 14px",
style: "font-size: 14px",
sort: (a: string, b: string) =>
a.localeCompare(b, undefined, { numeric: true, sensitivity: "base" }),
},
]);
const visibleColumnsHistory = ref<String[]>([
"issuer",
"detail",
"issueDate",
"refCommandNo",
"refCommandDate",
"createdFullName",
"createdAt",
]);
watch(visibleColumns, async (count: String[], prevCount: String[]) => {
await changeProfileColumns("coined", count);
});
onMounted(async () => {
await fetchData();
});
const fetchData = async () => {
if (profileId.value) {
showLoader();
await http
.get(config.API.profileHonorId(profileId.value))
.then((res) => {
let data = res.data.result;
rows.value = [];
data.map((e: ResponseObject) => {
rows.value.push({
id: e.id,
issuer: e.issuer,
detail: e.detail,
issueDate: new Date(e.issueDate),
refCommandNo: e.refCommandNo,
refCommandDate:
e.refCommandDate == null ? null : new Date(e.refCommandDate),
createdAt: new Date(e.createdAt),
createdFullName: e.createdFullName,
});
});
})
.catch((e) => {
messageError($q, e);
})
.finally(() => {
hideLoader();
});
}
};
/**
* กดดอมลกอนหน
*/
const clickPrevious = async () => {
edit.value = false;
rowIndex.value -= 1;
await getData();
await checkRowPage();
};
/**
* กดดอมลตอไป
*/
const clickNext = async () => {
edit.value = false;
rowIndex.value += 1;
await getData();
await checkRowPage();
};
/**
* กดดอมลตอไป
*/
const getData = () => {
const row = rows.value[rowIndex.value];
issuer.value = row.issuer;
detail.value = row.detail;
issueDate.value = row.issueDate;
refCommandNo.value = row.refCommandNo;
refCommandDate.value = row.refCommandDate;
id.value = row.id;
};
/**
* เชคปมดอม อน อไป าตองแสดงไหม
*/
const checkRowPage = () => {
editRow.value = false;
next.value = true;
previous.value = true;
if (rowIndex.value + 1 >= rows.value.length) {
next.value = false;
}
if (rowIndex.value - 1 < 0) {
previous.value = false;
}
};
/**
* กดปมแกไขใน dialog
*/
const clickEdit = () => {
editRow.value = false;
next.value = false;
previous.value = false;
};
/**
* กดปมเพมดานบน table
*/
const clickAdd = async () => {
editRow.value = false;
await addData();
};
/**
* กดบนทกใน dialog
*/
const clickSave = async () => {
myForm.value.validate().then(async (result: boolean) => {
if (result) {
if (modalEdit.value) {
await editData();
} else {
await saveData();
}
}
});
};
/**
* นทกเพมขอม
*/
const saveData = async () => {
if (profileId.value) {
showLoader();
await http
.post(config.API.profileHonorId(profileId.value), {
id: id.value,
issuer: issuer.value,
detail: detail.value,
issueDate: dateToISO(issueDate.value),
refCommandNo: refCommandNo.value,
refCommandDate:
refCommandDate.value == null ? null : dateToISO(refCommandDate.value),
})
.then((res) => {
success($q, "บันทึกข้อมูลสำเร็จ");
modal.value = false;
})
.catch((e) => {
messageError($q, e);
})
.finally(async () => {
await fetchData();
});
}
};
/**
* นทกแกไขขอม
*/
const editData = async () => {
showLoader();
await http
.put(config.API.profileHonorId(id.value), {
id: id.value,
issuer: issuer.value,
detail: detail.value,
issueDate: dateToISO(issueDate.value),
refCommandNo: refCommandNo.value,
refCommandDate:
refCommandDate.value == null ? null : dateToISO(refCommandDate.value),
})
.then((res) => {
success($q, "บันทึกข้อมูลสำเร็จ");
modal.value = false;
})
.catch((e) => {
messageError($q, e);
})
.finally(async () => {
await fetchData();
});
};
/**
* ลบลบขอม
*/
const clickDelete = async () => {
$q.dialog({
title: `ลบข้อมูล`,
message: `ต้องการทำการลบข้อมูลนี้ใช่หรือไม่?`,
cancel: "ยกเลิก",
ok: "ยืนยัน",
persistent: true,
})
.onOk(async () => {
showLoader();
await http
.delete(config.API.profileHonorId(id.value))
.then((res) => {
success($q, "ลบข้อมูลสำเร็จ");
modal.value = false;
})
.catch((e) => {
messageError($q, e);
})
.finally(async () => {
await fetchData();
});
})
.onCancel(async () => {
await fetchData();
});
};
/**
* กดป dialog
*/
const clickClose = async () => {
if (editRow.value == true) {
$q.dialog({
title: `ข้อมูลมีการแก้ไข`,
message: `ยืนยันที่จะปิดโดยไม่บันทึกใช่หรือไม่?`,
cancel: "ยกเลิก",
ok: "ยืนยัน",
persistent: true,
}).onOk(async () => {
modal.value = false;
next.value = false;
previous.value = false;
});
} else {
modal.value = false;
next.value = false;
previous.value = false;
}
};
/**
* กดเลอกขอมลทจะแกไข
* @param props props ใน row เลอก
*/
const selectData = async (props: DataProps) => {
modalEdit.value = true;
modal.value = true;
edit.value = false;
rawItem.value = props.row;
rowIndex.value = props.rowIndex;
issuer.value = props.row.issuer;
detail.value = props.row.detail;
issueDate.value = props.row.issueDate;
refCommandNo.value = props.row.refCommandNo;
refCommandDate.value = props.row.refCommandDate;
id.value = props.row.id;
await checkRowPage();
};
/**
* กดปมเพมบน table
*/
const addData = () => {
modalEdit.value = false;
modal.value = true;
edit.value = true;
issuer.value = "";
detail.value = "";
issueDate.value = new Date();
refCommandNo.value = "";
refCommandDate.value = null;
};
/**
* งกนปมยกเลกการแกไขขอม
*/
const clickCancel = async () => {
if (editRow.value == true) {
$q.dialog({
title: `ข้อมูลมีการแก้ไข`,
message: `ยืนยันยกเลิกการแก้ไขใช่หรือไม่?`,
cancel: "ยกเลิก",
ok: "ยืนยัน",
persistent: true,
}).onOk(async () => {
edit.value = false;
await checkRowPage();
await getData();
});
} else {
edit.value = false;
await checkRowPage();
}
};
/**
* เชความการแกไขขอม
*/
const clickEditRow = () => {
editRow.value = true;
};
/**
* งชนดอมลประวแกไขขอมลทเลอก
* @param row อม row ประวการแกไข
*/
const clickHistory = async (row: RequestItemsObject) => {
tittleHistory.value =
props.profileType == "employee"
? "ประวัติแก้ไขประกาศลูกจ้างดีเด่น"
: "ประวัติแก้ไขประกาศเกียรติคุณ";
modalHistory.value = true;
showLoader();
await http
.get(config.API.profileHonorHisId(row.id))
.then((res) => {
let data = res.data.result;
rowsHistory.value = [];
data.map((e: ResponseObject) => {
rowsHistory.value.push({
id: e.id,
issuer: e.issuer,
detail: e.detail,
issueDate: new Date(e.issueDate),
refCommandNo: e.refCommandNo,
refCommandDate:
e.refCommandDate == null ? null : new Date(e.refCommandDate),
createdAt: new Date(e.createdAt),
createdFullName: e.createdFullName,
});
});
})
.catch((e) => {
messageError($q, e);
})
.finally(() => {
hideLoader();
});
};
/**
* validate input ใน dialog
*/
const validateData = async () => {
checkValidate.value = true;
await myForm.value.validate().then((result: boolean) => {
if (result == false) {
checkValidate.value = false;
}
});
};
/**
* class ดรปแบบแสดงระหวางขอมลทแกไขหรอแสดงเฉยๆ
* @param val อม input สำหรบแกไขหรอไม
*/
const getClass = (val: boolean) => {
return {
"full-width inputgreen cursor-pointer": val,
"full-width cursor-pointer": !val,
};
};
const resetFilter = () => {};
</script>
<style lang="scss">
.modalfix {
position: fixed !important;
}
</style>

View file

@ -0,0 +1,135 @@
<template>
<q-card-actions class="text-primary q-py-sm">
<q-btn
flat
round
icon="mdi-menu-left"
@click="clickPrevious"
v-if="modalEdit == true"
:disable="previous == false"
:color="!previous ? 'grey-7' : 'public'"
/>
<q-btn
flat
round
icon="mdi-menu-right"
@click="clickNext"
v-if="modalEdit == true"
:disable="next == false"
:color="!next ? 'grey-7' : 'public'"
/>
<q-space />
<q-btn
v-if="modalEdit == true"
flat
round
color="red"
@click="clickDelete"
icon="mdi-delete"
>
<q-tooltip>ลบขอม</q-tooltip>
</q-btn>
<q-btn
v-if="!editvisible"
flat
round
:disabled="editvisible"
:color="editvisible ? 'grey-7' : 'primary'"
@click="edit"
icon="mdi-pencil-outline"
>
<q-tooltip>แกไขขอม</q-tooltip>
</q-btn>
<div v-else>
<q-btn
flat
round
:disabled="!editvisible"
:outline="!editvisible"
:color="!editvisible ? 'grey-7' : 'red'"
@click="cancel()"
icon="mdi-undo"
v-if="modalEdit == true"
>
<q-tooltip>ยกเล</q-tooltip>
</q-btn>
<q-btn
flat
round
:disabled="!editvisible"
:color="!editvisible ? 'grey-7' : 'public'"
@click="checkSave"
icon="mdi-content-save-outline"
>
<q-tooltip>นท</q-tooltip>
</q-btn>
</div>
</q-card-actions>
</template>
<script setup lang="ts">
const props = defineProps({
editvisible: Boolean,
next: Boolean,
previous: Boolean,
modalEdit: Boolean,
clickNext: {
type: Function,
default: () => console.log("not function"),
},
clickPrevious: {
type: Function,
default: () => console.log("not function"),
},
cancel: {
type: Function,
default: () => console.log("not function"),
},
edit: {
type: Function,
default: () => console.log("not function"),
},
save: {
type: Function,
default: () => console.log("not function"),
},
validate: {
type: Function,
default: () => console.log("not function"),
},
clickDelete: {
type: Function,
default: () => console.log("not function"),
},
});
const emit = defineEmits([
"update:editvisible",
"update:next",
"update:previous",
]);
const updateEdit = (value: Boolean) => {
emit("update:editvisible", value);
};
const cancel = async () => {
props.cancel();
};
const clickDelete = async () => {
props.clickDelete();
};
const edit = async () => {
updateEdit(!props.editvisible);
props.edit();
};
const checkSave = () => {
props.validate();
props.save();
};
const clickNext = async () => {
await props.clickNext();
};
const clickPrevious = async () => {
await props.clickPrevious();
};
</script>

View file

@ -0,0 +1,27 @@
<template>
<q-toolbar>
<q-toolbar-title class="text-subtitle2 text-bold">{{
tittle
}}</q-toolbar-title>
<q-btn
icon="close"
unelevated
round
dense
@click="close"
style="color: #ff8080; background-color: #ffdede"
/>
</q-toolbar>
</template>
<script setup lang="ts">
const props = defineProps({
tittle: String,
close: {
type: Function,
default: () => console.log("not function"),
},
});
const close = async () => {
props.close();
};
</script>

View file

@ -0,0 +1,45 @@
<template>
<q-dialog :model-value="modal" persistent>
<q-card style="width: 600px">
<DialogHeader :tittle="props.title" :close="close" />
<q-separator />
<q-card-section
:class="props.fix ? 'q-pa-md scroll' : 'q-pa-md'"
:style="props.fix ? 'height: 50vh' : ''"
>
<slot name="body" />
</q-card-section>
<q-separator />
<q-card-actions class="text-primary">
<slot name="footer" />
</q-card-actions>
</q-card>
</q-dialog>
</template>
<script setup lang="ts">
import DialogHeader from "@/components/information/DialogHeader.vue";
const props = defineProps({
title: {
required: true,
type: String,
default: "",
},
modal: {
required: true,
type: Boolean,
default: false,
},
fix: {
required: true,
type: Boolean,
default: true,
},
});
const emit = defineEmits(["update:modal"]);
const close = async () => {
emit("update:modal", false);
};
</script>

View file

@ -0,0 +1,943 @@
<!-- card -->
<template>
<q-card flat bordered class="col-12 q-px-lg q-py-md">
<q-form ref="myForm">
<ProfileTable
:rows="rows"
:columns="columns"
:filter="filter"
:visible-columns="visibleColumns"
v-model:inputfilter="filter"
v-model:inputvisible="visibleColumns"
:add="clickAdd"
name="วินัย"
icon="mdi-scale-balance"
:statusEdit="statusEdit"
>
<template #columns="props">
<q-tr :props="props">
<q-td
v-for="col in props.cols"
:key="col.name"
:props="props"
@click="selectData(props)"
class="cursor-pointer"
>
<div
v-if="col.name == 'refCommandDate' || col.name == 'date'"
class="table_ellipsis"
>
{{ col.value == null ? null : date2Thai(col.value) }}
</div>
<div v-else class="table_ellipsis">
{{ col.value }}
</div>
</q-td>
<q-td auto-width>
<q-btn
color="info"
flat
dense
round
size="14px"
icon="mdi-history"
@click="clickHistory(props.row)"
/>
</q-td>
</q-tr>
</template>
</ProfileTable>
</q-form>
</q-card>
<!-- popup Edit window-->
<q-dialog v-model="modal" persistent>
<q-card style="width: 600px">
<q-form ref="myForm">
<DialogHeader tittle="วินัย" :close="clickClose" />
<q-separator />
<q-card-section class="q-p-sm">
<div
class="row col-12 items-center q-col-gutter-x-xs q-col-gutter-y-xs"
>
<div class="col-xs-6 col-sm-6 col-md-6">
<datepicker
menu-class-name="modalfix"
:readonly="!edit"
v-model="date"
:locale="'th'"
autoApply
:enableTimePicker="false"
@update:modelValue="clickEditRow"
week-start="0"
>
<template #year="{ year }">{{ year + 543 }}</template>
<template #year-overlay-value="{ value }">{{
parseInt(value + 543)
}}</template>
<template #trigger>
<q-input
:class="getClass(edit)"
:outlined="edit"
dense
lazy-rules
:borderless="!edit"
:model-value="date2Thai(date)"
:rules="[(val:string) => !!val || `${'กรุณาเลือกวัน เดือน ปี'}`]"
hide-bottom-space
:label="`${'วัน เดือน ปี'}`"
>
<template v-slot:prepend>
<q-icon
name="event"
class="cursor-pointer"
:style="
edit
? 'color: var(--q-primary)'
: 'color: var(--q-grey)'
"
>
</q-icon>
</template>
</q-input>
</template>
</datepicker>
</div>
<div class="col-xs-6 col-sm-6 col-md-6">
<q-input
:class="getClass(edit)"
:outlined="edit"
dense
lazy-rules
:readonly="!edit"
:borderless="!edit"
v-model="detail"
:rules="[(val:string) => !!val || `${'กรุณากรอกรายละเอียด'}`]"
hide-bottom-space
:label="`${'รายละเอียด'}`"
@update:modelValue="clickEditRow"
/>
</div>
<div class="col-xs-6 col-sm-6 col-md-6">
<selector
:class="getClass(edit)"
:outlined="edit"
dense
lazy-rules
:readonly="!edit"
:borderless="!edit"
v-model="level"
:rules="[(val:string) => !!val || `${'กรุณาเลือกระดับการลงโทษทางวินัย'}`]"
hide-bottom-space
:label="`${'ระดับการลงโทษทางวินัย'}`"
@update:modelValue="clickEditRow"
emit-value
map-options
option-label="name"
:options="Ops.levelOptions"
option-value="id"
use-input
input-debounce="0"
@filter="(inputValue:string,
doneFn:Function) => filterSelector(inputValue, doneFn,'levelOptions'
) "
/>
</div>
<div class="col-xs-6 col-sm-6 col-md-6">
<q-input
:class="getClass(edit)"
:outlined="edit"
dense
lazy-rules
:readonly="!edit"
:borderless="!edit"
v-model="unStigma"
hide-bottom-space
:label="`${'ล้างมลทิน'}`"
@update:modelValue="clickEditRow"
/>
</div>
<div class="col-xs-6 col-sm-6 col-md-6">
<q-input
:class="getClass(edit)"
:outlined="edit"
dense
lazy-rules
:readonly="!edit"
:borderless="!edit"
v-model="refCommandNo"
hide-bottom-space
:label="`${'เลขที่คำสั่ง'}`"
:rules="[(val:string) => !!val || `${'กรุณากรอกเลขที่คำสั่ง'}`]"
@update:modelValue="clickEditRow"
>
<template v-slot:append>
<q-icon
name="mdi-file"
class="cursor-pointer"
@click="resetFilter"
/>
</template>
</q-input>
</div>
<div class="col-xs-6 col-sm-6 col-md-6">
<datepicker
menu-class-name="modalfix"
:readonly="!edit"
v-model="refCommandDate"
:locale="'th'"
autoApply
:enableTimePicker="false"
@update:modelValue="clickEditRow"
week-start="0"
>
<template #year="{ year }">{{ year + 543 }}</template>
<template #year-overlay-value="{ value }">{{
parseInt(value + 543)
}}</template>
<template #trigger>
<q-input
:class="getClass(edit)"
:outlined="edit"
dense
lazy-rules
:borderless="!edit"
:model-value="
refCommandDate == null ? null : date2Thai(refCommandDate)
"
hide-bottom-space
:label="`${'เอกสารอ้างอิง (ลงวันที่)'}`"
>
<template v-slot:prepend>
<q-icon
name="event"
class="cursor-pointer"
:style="
edit
? 'color: var(--q-primary)'
: 'color: var(--q-grey)'
"
>
</q-icon>
</template>
</q-input>
</template>
</datepicker>
</div>
</div>
</q-card-section>
<q-separator />
<DialogFooter
:cancel="clickCancel"
:edit="clickEdit"
:save="clickSave"
:validate="validateData"
:clickNext="clickNext"
:clickPrevious="clickPrevious"
:clickDelete="clickDelete"
v-model:editvisible="edit"
v-model:next="next"
v-model:previous="previous"
v-model:modalEdit="modalEdit"
/>
</q-form>
</q-card>
</q-dialog>
<HistoryTable
:rows="rowsHistory"
:columns="columnsHistory"
:filter="filterHistory"
:visible-columns="visibleColumnsHistory"
v-model:modal="modalHistory"
v-model:inputfilter="filterHistory"
v-model:inputvisible="visibleColumnsHistory"
v-model:tittle="tittleHistory"
>
<template #columns="props">
<q-tr :props="props">
<q-td v-for="col in props.cols" :key="col.name" :props="props">
<div
v-if="
col.name == 'date' ||
col.name == 'refCommandDate' ||
col.name == 'createdAt'
"
class="table_ellipsis"
>
{{ col.value == null ? null : date2Thai(col.value) }}
</div>
<div v-else class="table_ellipsis">
{{ col.value }}
</div>
</q-td>
</q-tr>
</template>
</HistoryTable>
</template>
<script setup lang="ts">
import { onMounted, ref, watch } from "vue";
import { useRoute } from "vue-router";
import { useCounterMixin } from "@/stores/mixin";
import { useComponentProfileDataStore } from "@/components/information/store/store";
import ProfileTable from "@/components/information/Table.vue";
import DialogHeader from "@/components/information/DialogHeader.vue";
import DialogFooter from "@/components/information/DialogFooter.vue";
import { useQuasar } from "quasar";
import type {
RequestItemsObject,
DataProps,
} from "@/components/information/interface/request/Discipline";
import type { ResponseObject } from "@/components/information/interface/response/Discipline";
import type {
DisciplineOps,
DataOption,
} from "@/components/information/interface/index/Main";
import HistoryTable from "@/components/TableHistory.vue";
import http from "@/plugins/http";
import config from "@/app.config";
import type { QTableProps } from "quasar";
const props = defineProps({
statusEdit: {
type: Boolean,
required: true,
},
});
const $q = useQuasar();
const store = useComponentProfileDataStore();
const { profileData, changeProfileColumns } = store;
const mixin = useCounterMixin();
const { date2Thai, success, dateToISO, messageError, showLoader, hideLoader } =
mixin;
const route = useRoute();
const id = ref<string>("");
const level = ref<string>();
const Ops = ref<DisciplineOps>({
levelOptions: [
{
name: "ภาคทัณฑ์",
id: "ภาคทัณฑ์",
},
{
name: "ตัดเงินเดือน",
id: "ตัดเงินเดือน",
},
{
name: "ลดขั้นเงินเดือน",
id: "ลดขั้นเงินเดือน",
},
{
name: "ปลดออก",
id: "ปลดออก",
},
{
name: "ไล่ออก",
id: "ไล่ออก",
},
],
});
const OpsFilter = ref<DisciplineOps>({
levelOptions: [
{
name: "ภาคทัณฑ์",
id: "ภาคทัณฑ์",
},
{
name: "ตัดเงินเดือน",
id: "ตัดเงินเดือน",
},
{
name: "ลดขั้นเงินเดือน",
id: "ลดขั้นเงินเดือน",
},
{
name: "ปลดออก",
id: "ปลดออก",
},
{
name: "ไล่ออก",
id: "ไล่ออก",
},
],
});
const detail = ref<string>();
const unStigma = ref<string>();
const refCommandNo = ref<string>();
const refCommandDate = ref<Date | null>(new Date());
const date = ref<Date>(new Date());
const myForm = ref<any>(); //form data input
const edit = ref<boolean>(false); // dialog
const modal = ref<boolean>(false); //modal add detail
const modalEdit = ref<boolean>(false); //modal
const rawItem = ref<RequestItemsObject>(); // row
const rowIndex = ref<number>(0); //index row
const previous = ref<boolean>(); //
const next = ref<boolean>(); //
const editRow = ref<boolean>(false); //
const rowsHistory = ref<RequestItemsObject[]>([]); //select data history
const tittleHistory = ref<string>("ประวัติแก้ไขวินัย"); //
const filterHistory = ref<string>(""); //search data table history
const modalHistory = ref<boolean>(false); //modal
const checkValidate = ref<boolean>(false); //validate data
const profileId = ref<string>(
route.params.id ? route.params.id.toString() : ""
);
const rows = ref<RequestItemsObject[]>([]);
const filter = ref<string>(""); //search data table
const visibleColumns = ref<String[]>([]);
profileData.discipline.columns.length == 0
? (visibleColumns.value = [
"level",
"detail",
"unStigma",
"refCommandNo",
"refCommandDate",
"date",
])
: (visibleColumns.value = profileData.discipline.columns);
const columns = ref<QTableProps["columns"]>([
{
name: "date",
align: "left",
label: "วัน เดือน ปี",
sortable: true,
field: "date",
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: "level",
align: "left",
label: "ระดับการลงโทษทางวินัย",
sortable: true,
field: "level",
headerStyle: "font-size: 14px",
style: "font-size: 14px",
sort: (a: string, b: string) =>
a.localeCompare(b, undefined, { numeric: true, sensitivity: "base" }),
},
{
name: "unStigma",
align: "left",
label: "ล้างมลทิน",
sortable: true,
field: "unStigma",
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",
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",
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: "level",
align: "left",
label: "ระดับการลงโทษทางวินัย",
sortable: true,
field: "level",
headerStyle: "font-size: 14px",
style: "font-size: 14px",
sort: (a: string, b: string) =>
a.localeCompare(b, undefined, { numeric: true, sensitivity: "base" }),
},
{
name: "unStigma",
align: "left",
label: "ล้างมลทิน",
sortable: true,
field: "unStigma",
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",
sort: (a: string, b: string) =>
a.localeCompare(b, undefined, { numeric: true, sensitivity: "base" }),
},
{
name: "createdFullName",
align: "left",
label: "ผู้ดำเนินการ",
sortable: true,
field: "createdFullName",
headerStyle: "font-size: 14px",
style: "font-size: 14px",
sort: (a: string, b: string) =>
a.localeCompare(b, undefined, { numeric: true, sensitivity: "base" }),
},
{
name: "createdAt",
align: "left",
label: "วันที่แก้ไข",
sortable: true,
field: "createdAt",
headerStyle: "font-size: 14px",
style: "font-size: 14px",
sort: (a: string, b: string) =>
a.localeCompare(b, undefined, { numeric: true, sensitivity: "base" }),
},
]);
const visibleColumnsHistory = ref<String[]>([
"level",
"detail",
"unStigma",
"refCommandNo",
"refCommandDate",
"date",
"createdFullName",
"createdAt",
]);
watch(visibleColumns, async (count: String[], prevCount: String[]) => {
await changeProfileColumns("discipline", count);
});
onMounted(async () => {
await fetchData();
});
const filterSelector = (val: string, update: Function, refData: string) => {
switch (refData) {
case "levelOptions":
update(() => {
Ops.value.levelOptions = OpsFilter.value.levelOptions.filter(
(v: DataOption) => v.name.indexOf(val) > -1
);
});
break;
default:
break;
}
};
const fetchData = async () => {
if (profileId.value) {
showLoader();
await http
.get(config.API.profileDisId(profileId.value))
.then((res) => {
let data = res.data.result;
rows.value = [];
data.map((e: ResponseObject) => {
rows.value.push({
id: e.id,
level: e.level,
detail: e.detail,
unStigma: e.unStigma,
refCommandNo: e.refCommandNo,
refCommandDate:
e.refCommandDate == null ? null : new Date(e.refCommandDate),
date: new Date(e.date),
createdFullName: e.createdFullName,
createdAt: new Date(e.createdAt),
});
});
})
.catch((e) => {
messageError($q, e);
})
.finally(() => {
hideLoader();
});
}
};
/**
* กดดอมลกอนหน
*/
const clickPrevious = async () => {
edit.value = false;
rowIndex.value -= 1;
await getData();
await checkRowPage();
};
/**
* กดดอมลตอไป
*/
const clickNext = async () => {
edit.value = false;
rowIndex.value += 1;
await getData();
await checkRowPage();
};
/**
* กดดอมลตอไป
*/
const getData = () => {
const row = rows.value[rowIndex.value];
level.value = row.level;
detail.value = row.detail;
unStigma.value = row.unStigma;
refCommandNo.value = row.refCommandNo;
refCommandDate.value = row.refCommandDate;
date.value = row.date;
id.value = row.id;
};
/**
* เชคปมดอม อน อไป าตองแสดงไหม
*/
const checkRowPage = () => {
editRow.value = false;
next.value = true;
previous.value = true;
if (rowIndex.value + 1 >= rows.value.length) {
next.value = false;
}
if (rowIndex.value - 1 < 0) {
previous.value = false;
}
};
/**
* กดปมแกไขใน dialog
*/
const clickEdit = () => {
editRow.value = false;
next.value = false;
previous.value = false;
};
/**
* กดปมเพมดานบน table
*/
const clickAdd = async () => {
editRow.value = false;
await addData();
};
/**
* กดบนทกใน dialog
*/
const clickSave = async () => {
myForm.value.validate().then(async (result: boolean) => {
if (result) {
if (modalEdit.value) {
await editData();
} else {
await saveData();
}
}
});
};
/**
* นทกเพมขอม
*/
const saveData = async () => {
if (profileId.value) {
showLoader();
await http
.post(config.API.profileDisId(profileId.value), {
id: id.value,
level: level.value,
detail: detail.value,
unStigma: unStigma.value,
refCommandNo: refCommandNo.value,
refCommandDate:
refCommandDate.value == null ? null : dateToISO(refCommandDate.value),
date: dateToISO(date.value),
})
.then((res) => {
success($q, "บันทึกข้อมูลสำเร็จ");
modal.value = false;
})
.catch((e) => {
messageError($q, e);
})
.finally(async () => {
await fetchData();
});
}
};
/**
* นทกแกไขขอม
*/
const editData = async () => {
showLoader();
await http
.put(config.API.profileDisId(id.value), {
id: id.value,
level: level.value,
detail: detail.value,
unStigma: unStigma.value,
refCommandNo: refCommandNo.value,
refCommandDate:
refCommandDate.value == null ? null : dateToISO(refCommandDate.value),
date: dateToISO(date.value),
})
.then((res) => {
success($q, "บันทึกข้อมูลสำเร็จ");
modal.value = false;
})
.catch((e) => {
messageError($q, e);
})
.finally(async () => {
await fetchData();
});
};
/**
* ลบลบขอม
*/
const clickDelete = async () => {
$q.dialog({
title: `ลบข้อมูล`,
message: `ต้องการทำการลบข้อมูลนี้ใช่หรือไม่?`,
cancel: "ยกเลิก",
ok: "ยืนยัน",
persistent: true,
})
.onOk(async () => {
showLoader();
await http
.delete(config.API.profileDisId(id.value))
.then((res) => {
success($q, "ลบข้อมูลสำเร็จ");
modal.value = false;
})
.catch((e) => {
messageError($q, e);
})
.finally(async () => {
await fetchData();
});
})
.onCancel(async () => {
await fetchData();
});
};
/**
* กดป dialog
*/
const clickClose = async () => {
if (editRow.value == true) {
$q.dialog({
title: `ข้อมูลมีการแก้ไข`,
message: `ยืนยันที่จะปิดโดยไม่บันทึกใช่หรือไม่?`,
cancel: "ยกเลิก",
ok: "ยืนยัน",
persistent: true,
}).onOk(async () => {
modal.value = false;
next.value = false;
previous.value = false;
});
} else {
modal.value = false;
next.value = false;
previous.value = false;
}
};
/**
* กดเลอกขอมลทจะแกไข
* @param props props ใน row เลอก
*/
const selectData = async (props: DataProps) => {
modalEdit.value = true;
modal.value = true;
edit.value = false;
rawItem.value = props.row;
rowIndex.value = props.rowIndex;
level.value = props.row.level;
detail.value = props.row.detail;
unStigma.value = props.row.unStigma;
refCommandNo.value = props.row.refCommandNo;
refCommandDate.value = props.row.refCommandDate;
date.value = props.row.date;
id.value = props.row.id;
await checkRowPage();
};
/**
* กดปมเพมบน table
*/
const addData = () => {
modalEdit.value = false;
modal.value = true;
edit.value = true;
level.value = "";
detail.value = "";
unStigma.value = "";
refCommandNo.value = "";
refCommandDate.value = null;
date.value = new Date();
};
/**
* งกนปมยกเลกการแกไขขอม
*/
const clickCancel = async () => {
if (editRow.value == true) {
$q.dialog({
title: `ข้อมูลมีการแก้ไข`,
message: `ยืนยันยกเลิกการแก้ไขใช่หรือไม่?`,
cancel: "ยกเลิก",
ok: "ยืนยัน",
persistent: true,
}).onOk(async () => {
edit.value = false;
await checkRowPage();
await getData();
});
} else {
edit.value = false;
await checkRowPage();
}
};
/**
* เชความการแกไขขอม
*/
const clickEditRow = () => {
editRow.value = true;
};
/**
* งชนดอมลประวแกไขขอมลทเลอก
* @param row อม row ประวการแกไข
*/
const clickHistory = async (row: RequestItemsObject) => {
modalHistory.value = true;
showLoader();
await http
.get(config.API.profileDisHisId(row.id))
.then((res) => {
let data = res.data.result;
rowsHistory.value = [];
data.map((e: ResponseObject) => {
rowsHistory.value.push({
id: e.id,
level: e.level,
detail: e.detail,
unStigma: e.unStigma,
refCommandNo: e.refCommandNo,
refCommandDate:
e.refCommandDate == null ? null : new Date(e.refCommandDate),
date: new Date(e.date),
createdFullName: e.createdFullName,
createdAt: new Date(e.createdAt),
});
});
})
.catch((e) => {
messageError($q, e);
})
.finally(() => {
hideLoader();
});
};
/**
* validate input ใน dialog
*/
const validateData = async () => {
checkValidate.value = true;
await myForm.value.validate().then((result: boolean) => {
if (result == false) {
checkValidate.value = false;
}
});
};
/**
* class ดรปแบบแสดงระหวางขอมลทแกไขหรอแสดงเฉยๆ
* @param val อม input สำหรบแกไขหรอไม
*/
const getClass = (val: boolean) => {
return {
"full-width inputgreen cursor-pointer": val,
"full-width cursor-pointer": !val,
};
};
const resetFilter = () => {};
</script>
<style lang="scss">
.modalfix {
position: fixed !important;
}
</style>

View file

@ -0,0 +1,270 @@
<template>
<q-card flat bordered class="col-12 row q-px-lg q-py-md">
<HeaderTop
v-model:edit="edit"
header="เอกสารหลักฐาน"
icon="mdi-file-document"
:history="false"
:changeBtn="changeBtn"
:disable="statusEdit"
:save="uploadData"
/>
<div class="row col-12 q-pt-sm">
<q-card bordered flat class="full-width">
<q-list separator>
<q-item v-for="file in files" :key="file.key" class="q-my-xs">
<q-item-section>
<q-item-label class="full-width ellipsis">
{{ file.fileName }}
</q-item-label>
<q-item-label caption> </q-item-label>
</q-item-section>
<q-item-section top side>
<div class="row col-12">
<q-btn
class="gt-xs"
size="12px"
flat
dense
round
color="blue"
icon="mdi-download-outline"
@click="downloadData(file.file)"
/>
<q-btn
class="gt-xs"
size="12px"
flat
dense
round
color="red"
icon="mdi-delete-outline"
v-show="edit"
@click="deleteData(file.id)"
/>
</div>
</q-item-section>
</q-item>
</q-list>
</q-card>
<q-input
v-if="edit"
class="q-mt-sm col-12 q-pb-xs"
outlined
dense
lazy-rules
v-model="name"
hide-bottom-space
:rules="[(val) => !!val || `${'กรุณากรอกชื่อเอกสาร'}`]"
:label="`${'ชื่อเอกสาร'}`"
/>
<q-uploader
v-if="edit"
color="gray"
type="file"
flat
@factory="uploadData"
ref="uploader"
class="full-width"
text-color="white"
:max-size="10000000"
accept=".jpg,.png,.pdf,.csv,.doc"
bordered
label="[ไฟล์ jpg,png,pdf,csv,doc ขนาดไม่เกิน 10MB]"
@added="fileAdd"
>
<template v-slot:header="scope">
<div class="row no-wrap items-center q-pa-sm q-gutter-xs">
<q-btn
v-if="scope.queuedFiles.length > 0"
icon="clear_all"
@click="scope.removeQueuedFiles"
round
dense
flat
>
<q-tooltip>ลบทงหมด</q-tooltip>
</q-btn>
<q-btn
v-if="scope.uploadedFiles.length > 0"
icon="done_all"
@click="scope.removeUploadedFiles"
round
dense
flat
>
<q-tooltip>ลบไฟลปโหลด</q-tooltip>
</q-btn>
<q-spinner v-if="scope.isUploading" class="q-uploader__spinner" />
<div class="col">
<div class="q-uploader__title">
{{ "[ไฟล์ jpg,png,pdf,csv,doc ขนาดไม่เกิน 10MB]" }}
</div>
<div class="q-uploader__subtitle">
{{ scope.uploadSizeLabel }} / {{ scope.uploadProgressLabel }}
</div>
</div>
<q-btn
v-if="scope.canAddFiles"
type="a"
icon="add_box"
@click="scope.pickFiles"
round
dense
flat
>
<q-uploader-add-trigger />
<q-tooltip>เลอกไฟล</q-tooltip>
</q-btn>
<q-btn
v-if="scope.isUploading"
icon="clear"
@click="scope.abort"
round
dense
flat
>
<q-tooltip>ยกเลกการอปโหลด</q-tooltip>
</q-btn>
</div>
</template>
</q-uploader>
</div>
</q-card>
</template>
<script setup lang="ts">
import { onMounted, computed, ref, watch } from "vue";
import { useQuasar, QForm } from "quasar";
import { useCounterMixin } from "@/stores/mixin";
import { useRoute } from "vue-router";
import HeaderTop from "@/components/information/top.vue";
import http from "@/plugins/http";
import config from "@/app.config";
const props = defineProps({
statusEdit: {
type: Boolean,
required: true,
},
notiNoEdit: {
type: Function,
default: () => console.log("not function"),
},
});
const emit = defineEmits(["update:statusEdit"]);
const $q = useQuasar(); // show dialog
const mixin = useCounterMixin();
const route = useRoute();
const { success, messageError, showLoader, hideLoader } = mixin;
const profileId = ref<string>(
route.params.id ? route.params.id.toString() : ""
);
const edit = ref<boolean>(false);
const uploader = ref<any>();
const files = ref<any>([]);
const file = ref<any>([]);
const name = ref<string>("");
onMounted(async () => {
await getData();
});
const getData = async () => {
if (profileId.value) {
showLoader();
await http
.get(config.API.profilePaperId(profileId.value))
.then((res) => {
const data = res.data.result;
files.value = data;
})
.catch((e) => {
messageError($q, e);
})
.finally(() => {
hideLoader();
});
}
};
const deleteData = async (id: string) => {
showLoader();
await http
.delete(config.API.profilePaperId(id))
.then((res) => {
const data = res.data.result;
})
.catch((e) => {
messageError($q, e);
})
.finally(async () => {
await getData();
});
};
const uploadData = async () => {
if (profileId.value) {
if (file.value.length > 0) {
const blob = file.value.slice(0, file.value[0].size);
const newFile = new File(blob, name.value, {
type: file.value[0].type,
});
const formData = new FormData();
formData.append("avatar", newFile);
formData.append("moss", "newFile");
console.log(formData);
showLoader();
await http
.post(config.API.profilePaperId(profileId.value), formData)
.then((res) => {
const data = res.data.result;
success($q, "บันทึกข้อมูลสำเร็จ");
})
.catch((e) => {
messageError($q, e);
})
.finally(async () => {
uploader.value.reset();
name.value = "";
edit.value = false;
emit("update:statusEdit", false);
await getData();
});
} else {
// modalError(
// $q,
// "",
// ""
// );
getData();
}
}
};
const fileAdd = async (val: any) => {
name.value = val[0].name;
file.value = val;
};
const downloadData = async (path: string) => {
window.open(path);
};
const changeBtn = async () => {
name.value = "";
if (edit.value == true) {
if (props.statusEdit === true) {
edit.value = false;
props.notiNoEdit();
} else {
emit("update:statusEdit", true);
}
} else {
emit("update:statusEdit", false);
}
};
</script>

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,763 @@
<template>
<q-card flat bordered class="col-12 q-px-lg q-py-md q-mt-md">
<HeaderTop
v-model:edit="edit"
header="ข้อมูลราชการ"
icon="mdi-account-tie"
:save="saveData"
:history="true"
:changeBtn="changeBtn"
:disable="statusEdit"
:cancel="refreshData"
:historyClick="clickHistory"
/>
<q-form ref="myform" class="col-12">
<div class="row col-12 items-center q-col-gutter-x-xs q-col-gutter-y-xs">
<div class="col-xs-12">
<q-input
:class="getClass(false)"
hide-bottom-space
dense
lazy-rules
readonly
borderless
:model-value="govermentData.ocId"
:label="`${'สังกัด'}`"
/>
</div>
<div class="col-xs-6 col-sm-3 col-md-3" v-if="employeeClass != 'temp'">
<q-input
:class="getClass(false)"
hide-bottom-space
dense
lazy-rules
readonly
borderless
:model-value="govermentData.numberId"
:label="`${'ตำแหน่งเลขที่'}`"
/>
</div>
<div class="col-xs-6 col-sm-3 col-md-3">
<q-input
:class="getClass(false)"
hide-bottom-space
dense
lazy-rules
readonly
borderless
:model-value="govermentData.positionId"
:label="`${'ตำแหน่ง'}`"
/>
</div>
<div class="col-xs-6 col-sm-3 col-md-3">
<q-input
:class="getClass(false)"
hide-bottom-space
dense
lazy-rules
readonly
borderless
:model-value="govermentData.positionPathSide"
:label="`${'ด้าน/สาขา'}`"
/>
</div>
<div class="col-xs-6 col-sm-3 col-md-3">
<q-input
:class="getClass(false)"
hide-bottom-space
dense
lazy-rules
readonly
borderless
:model-value="govermentData.positionLine"
:label="`${'สายงาน'}`"
/>
</div>
<div class="col-xs-6 col-sm-3 col-md-3">
<q-input
:class="getClass(false)"
hide-bottom-space
dense
lazy-rules
readonly
borderless
:model-value="govermentData.positionType"
:label="`${'ประเภท'}`"
/>
</div>
<div class="col-xs-6 col-sm-3 col-md-3" v-if="employeeClass != 'temp'">
<q-input
:class="getClass(false)"
hide-bottom-space
dense
lazy-rules
readonly
borderless
:model-value="govermentData.positionLevel"
:label="`${'ระดับ'}`"
/>
</div>
<div class="col-xs-6 col-sm-3 col-md-3">
<q-input
:class="getClass(false)"
hide-bottom-space
dense
lazy-rules
readonly
borderless
:model-value="govermentData.positionExecutive"
:label="`${'ตำแหน่งทางการบริหาร'}`"
/>
</div>
<div class="col-xs-6 col-sm-3 col-md-3">
<q-input
:class="getClass(false)"
hide-bottom-space
dense
lazy-rules
readonly
borderless
:model-value="govermentData.positionExecutiveSide"
:label="`${'ด้านตำแหน่งทางการบริหาร'}`"
/>
</div>
<div class="col-12 q-py-md"><q-separator /></div>
<div class="col-xs-6 col-sm-3 col-md-3">
<datepicker
v-model="govermentData.containDate"
:locale="'th'"
autoApply
:enableTimePicker="false"
week-start="0"
:max-date="new Date()"
:disabled="!edit"
@update:model-value="handleDate"
>
<template #year="{ year }">
{{ year + 543 }}
</template>
<template #year-overlay-value="{ value }">
{{ parseInt(value + 543) }}
</template>
<template #trigger>
<q-input
:class="getClass(edit)"
hide-bottom-space
:outlined="edit"
dense
lazy-rules
:readonly="!edit"
:borderless="!edit"
:model-value="date2Thai(new Date(govermentData.containDate))"
:rules="[
(val) =>
!!val ||
`${
profileType == 'officer'
? 'กรุณาเลือกวันที่บรรจุ'
: 'กรุณาเลือกวันที่แต่งตั้ง'
}`,
]"
:label="`${
profileType == 'officer' ? 'วันที่บรรจุ' : 'วันที่แต่งตั้ง'
}`"
>
<template v-slot:prepend>
<q-icon
name="event"
class="cursor-pointer"
:style="
edit ? 'color: var(--q-primary)' : 'color: var(--q-grey)'
"
>
</q-icon>
</template>
</q-input>
</template>
</datepicker>
</div>
<div class="col-xs-6 col-sm-3 col-md-3">
<datepicker
v-model="govermentData.workDate"
:locale="'th'"
autoApply
:enableTimePicker="false"
week-start="0"
:max-date="new Date()"
:disabled="!edit"
>
<template #year="{ year }">
{{ year + 543 }}
</template>
<template #year-overlay-value="{ value }">
{{ parseInt(value + 543) }}
</template>
<template #trigger>
<q-input
:class="getClass(edit)"
hide-bottom-space
:outlined="edit"
dense
lazy-rules
:readonly="!edit"
:borderless="!edit"
:model-value="date2Thai(new Date(govermentData.workDate))"
:rules="[
(val) =>
!!val ||
`${
profileType == 'officer'
? 'กรุณาเลือกเริ่มปฎิบัติราชการ'
: 'กรุณาเลือกวันที่จ้างและแต่งตั้งมีผล'
}`,
]"
:label="`${
profileType == 'officer'
? 'เริ่มปฎิบัติราชการ'
: 'วันที่จ้างและแต่งตั้งมีผล'
}`"
>
<template v-slot:prepend>
<q-icon
name="event"
class="cursor-pointer"
:style="
edit ? 'color: var(--q-primary)' : 'color: var(--q-grey)'
"
>
</q-icon>
</template>
</q-input>
</template>
</datepicker>
</div>
<div class="col-xs-6 col-sm-6 col-md-6" v-if="profileType == 'officer'">
<q-input
:class="getClass(edit)"
hide-bottom-space
:outlined="edit"
dense
lazy-rules
stack-label
:readonly="!edit"
:borderless="!edit"
v-model="govermentData.reasonSameDate"
:label="`${'เหตุผลกรณีไม่ตรงวัน'}`"
/>
</div>
<div class="col-xs-6 col-sm-3 col-md-3">
<q-input
:class="getClass(false)"
hide-bottom-space
dense
lazy-rules
readonly
borderless
:model-value="govermentData.retireDate"
:label="`${'วันเกษียณอายุ'}`"
/>
</div>
<div class="col-xs-6 col-sm-3 col-md-3">
<q-input
:class="getClass(false)"
hide-bottom-space
dense
lazy-rules
readonly
borderless
:model-value="govermentData.ageAll"
:label="`${'อายุราชการ'}`"
/>
</div>
<div class="col-xs-6 col-sm-3 col-md-3">
<q-input
:class="getClass(false)"
hide-bottom-space
dense
lazy-rules
readonly
borderless
:model-value="govermentData.absent"
:label="`${'ขาดราชการ'}`"
/>
</div>
<div class="col-xs-6 col-sm-3 col-md-3">
<q-input
:class="getClass(false)"
hide-bottom-space
dense
lazy-rules
readonly
borderless
:model-value="govermentData.age"
:label="`${'อายุราชการเกื้อกูล'}`"
/>
</div>
</div>
</q-form>
</q-card>
<HistoryTable
:rows="rowsHistory"
:columns="columnsHistory"
:filter="filterHistory"
:visible-columns="visibleColumnsHistory"
v-model:modal="modalHistory"
v-model:inputfilter="filterHistory"
v-model:inputvisible="visibleColumnsHistory"
v-model:tittle="tittleHistory"
>
<template #columns="props">
<q-tr :props="props">
<q-td v-for="col in props.cols" :key="col.name" :props="props">
<div
v-if="
col.name == 'dateStart' ||
col.name == 'dateAppoint' ||
col.name == 'createdAt'
"
class="table_ellipsis"
>
{{ date2Thai(col.value) }}
</div>
<div v-else class="table_ellipsis">
{{ col.value }}
</div>
</q-td>
</q-tr>
</template>
</HistoryTable>
</template>
<script setup lang="ts">
import { onMounted, ref, watch } from "vue";
import { useCounterMixin } from "@/stores/mixin";
import { useQuasar } from "quasar";
import type { Goverment } from "@/components/information/interface/profileType";
import { defaultGoverment } from "@/components/information/interface/profileType";
import HeaderTop from "@/components/information/top.vue";
import http from "@/plugins/http";
import config from "@/app.config";
import HistoryTable from "@/components/TableHistory.vue";
import type { RequestItemsHistoryObject } from "@/components/information/interface/request/Government";
import type { ResponseObject } from "@/components/information/interface/response/Government";
import { useRoute } from "vue-router";
import { useComponentProfileDataStore } from "@/components/information/store/store";
import { storeToRefs } from "pinia";
import type { QTableProps } from "quasar";
const props = defineProps({
statusEdit: {
type: Boolean,
required: true,
},
profileType: {
type: String,
required: true,
},
employeeClass: {
type: String,
required: true,
},
});
const emit = defineEmits(["update:statusEdit"]);
const route = useRoute();
const $q = useQuasar();
const mixin = useCounterMixin();
const { date2Thai, success, dateToISO, messageError, showLoader, hideLoader } =
mixin;
const profileStore = useComponentProfileDataStore();
const { birthDate, retireText } = storeToRefs(profileStore);
const edit = ref<boolean>(false);
const govermentData = ref<Goverment>(defaultGoverment);
const myform = ref<any>();
const rowsHistory = ref<RequestItemsHistoryObject[]>([]); //select data history
const tittleHistory = ref<string>("ประวัติแก้ไขข้อมูลราชการ"); //
const filterHistory = ref<string>(""); //search data table history
const modalHistory = ref<boolean>(false); //modal
const columnsHistory = ref<QTableProps["columns"]>([
{
name: "oc",
align: "left",
label: "สังกัด",
sortable: true,
field: "oc",
headerStyle: "font-size: 14px",
style: "font-size: 14px",
sort: (a: string, b: string) =>
a.localeCompare(b, undefined, { numeric: true, sensitivity: "base" }),
},
{
name: "positionPathSide",
align: "left",
label: "ตำแหน่ง",
sortable: true,
field: "positionPathSide",
headerStyle: "font-size: 14px",
style: "font-size: 14px",
sort: (a: string, b: string) =>
a.localeCompare(b, undefined, { numeric: true, sensitivity: "base" }),
},
{
name: "position",
align: "left",
label: "ด้าน/สาขา",
sortable: true,
field: "position",
headerStyle: "font-size: 14px",
style: "font-size: 14px",
sort: (a: string, b: string) =>
a.localeCompare(b, undefined, { numeric: true, sensitivity: "base" }),
},
{
name: "posNo",
align: "left",
label: "ตำแหน่งเลขที่",
sortable: true,
field: "posNo",
headerStyle: "font-size: 14px",
style: "font-size: 14px",
sort: (a: string, b: string) =>
a.localeCompare(b, undefined, { numeric: true, sensitivity: "base" }),
},
{
name: "positionLine",
align: "left",
label: "สายงาน",
sortable: true,
field: "positionLine",
headerStyle: "font-size: 14px",
style: "font-size: 14px",
sort: (a: string, b: string) =>
a.localeCompare(b, undefined, { numeric: true, sensitivity: "base" }),
},
{
name: "positionType",
align: "left",
label: "ประเภท",
sortable: true,
field: "positionType",
headerStyle: "font-size: 14px",
style: "font-size: 14px",
sort: (a: string, b: string) =>
a.localeCompare(b, undefined, { numeric: true, sensitivity: "base" }),
},
{
name: "positionLevel",
align: "left",
label: "ระดับ",
sortable: true,
field: "positionLevel",
headerStyle: "font-size: 14px",
style: "font-size: 14px",
sort: (a: string, b: string) =>
a.localeCompare(b, undefined, { numeric: true, sensitivity: "base" }),
},
{
name: "positionExecutive",
align: "left",
label: "ตำแหน่งทางการบริหาร",
sortable: true,
field: "positionExecutive",
headerStyle: "font-size: 14px",
style: "font-size: 14px",
sort: (a: string, b: string) =>
a.localeCompare(b, undefined, { numeric: true, sensitivity: "base" }),
},
{
name: "positionExecutiveSide",
align: "left",
label: "ด้านทางการบริหาร",
sortable: true,
field: "positionExecutiveSide",
headerStyle: "font-size: 14px",
style: "font-size: 14px",
sort: (a: string, b: string) =>
a.localeCompare(b, undefined, { numeric: true, sensitivity: "base" }),
},
{
name: "dateAppoint",
align: "left",
label: "วันที่บรรจุ",
sortable: true,
field: "dateAppoint",
headerStyle: "font-size: 14px",
style: "font-size: 14px",
sort: (a: string, b: string) =>
a.localeCompare(b, undefined, { numeric: true, sensitivity: "base" }),
},
{
name: "dateStart",
align: "left",
label: "เริ่มปฎิบัติราชการ",
sortable: true,
field: "dateStart",
headerStyle: "font-size: 14px",
style: "font-size: 14px",
sort: (a: string, b: string) =>
a.localeCompare(b, undefined, { numeric: true, sensitivity: "base" }),
},
{
name: "retireDate",
align: "left",
label: "วันเกษียณอายุ",
sortable: true,
field: "retireDate",
headerStyle: "font-size: 14px",
style: "font-size: 14px",
sort: (a: string, b: string) =>
a.localeCompare(b, undefined, { numeric: true, sensitivity: "base" }),
},
{
name: "govAge",
align: "left",
label: "อายุราชการ",
sortable: true,
field: "govAge",
headerStyle: "font-size: 14px",
style: "font-size: 14px",
sort: (a: string, b: string) =>
a.localeCompare(b, undefined, { numeric: true, sensitivity: "base" }),
},
{
name: "govAgeAbsent",
align: "left",
label: "ขาดราชการ",
sortable: true,
field: "govAgeAbsent",
headerStyle: "font-size: 14px",
style: "font-size: 14px",
sort: (a: string, b: string) =>
a.localeCompare(b, undefined, { numeric: true, sensitivity: "base" }),
},
{
name: "govAgePlus",
align: "left",
label: "อายุราชการเกื้อกูล",
sortable: true,
field: "govAgePlus",
headerStyle: "font-size: 14px",
style: "font-size: 14px",
sort: (a: string, b: string) =>
a.localeCompare(b, undefined, { numeric: true, sensitivity: "base" }),
},
{
name: "reasonSameDate",
align: "left",
label: "เหตุผลกรณีไม่ตรงวัน",
sortable: true,
field: "reasonSameDate",
headerStyle: "font-size: 14px",
style: "font-size: 14px",
sort: (a: string, b: string) =>
a.localeCompare(b, undefined, { numeric: true, sensitivity: "base" }),
},
{
name: "createdFullName",
align: "left",
label: "ผู้ดำเนินการ",
sortable: true,
field: "createdFullName",
headerStyle: "font-size: 14px",
style: "font-size: 14px",
sort: (a: string, b: string) =>
a.localeCompare(b, undefined, { numeric: true, sensitivity: "base" }),
},
{
name: "createdAt",
align: "left",
label: "วันที่แก้ไข",
sortable: true,
field: "createdAt",
headerStyle: "font-size: 14px",
style: "font-size: 14px",
sort: (a: string, b: string) =>
a.localeCompare(b, undefined, { numeric: true, sensitivity: "base" }),
},
]);
const visibleColumnsHistory = ref<String[]>([
"oc",
"position",
"positionPathSide",
"posNo",
"positionLine",
"positionType",
"positionLevel",
"positionexecutive",
"positionExecutiveSide",
"dateAppoint",
"dateStart",
"retireDate",
"govAge",
"govAgeAbsent",
"govAgePlus",
"reasonSameDate",
"createdFullName",
"createdAt",
]);
onMounted(async () => {
await fetchData();
emit("update:statusEdit", false);
});
watch(birthDate, async () => {
await fetchData();
});
watch(retireText, async () => {
govermentData.value.retireDate = retireText.value;
});
const fetchData = async () => {
showLoader();
await http
.get(config.API.profileGovId(route.params.id.toString()))
.then((res) => {
const data: ResponseObject = res.data.result;
govermentData.value.ocId = data.oc;
govermentData.value.positionId = data.position;
govermentData.value.positionPathSide = data.positionPathSide;
govermentData.value.positionLine = data.positionLine;
govermentData.value.positionType = data.positionType;
govermentData.value.positionLevel = data.positionLevel;
govermentData.value.numberId = data.posNo;
govermentData.value.positionExecutive = data.positionExecutive;
govermentData.value.positionExecutiveSide = data.positionExecutiveSide;
govermentData.value.containDate = new Date(data.dateAppoint);
govermentData.value.workDate = new Date(data.dateStart);
govermentData.value.retireDate = data.retireDate;
govermentData.value.absent = data.govAgeAbsent;
govermentData.value.age = data.govAgePlus;
govermentData.value.ageAll = data.govAge;
govermentData.value.reasonSameDate = data.reasonSameDate;
})
.catch((e) => {
messageError($q, e);
})
.finally(async () => {
hideLoader();
});
};
const refreshData = async () => {
myform.value.reset();
await fetchData();
};
const editData = async () => {
showLoader();
await http
.put(config.API.profileGovId(route.params.id.toString()), {
dateAppoint: dateToISO(govermentData.value.containDate),
dateStart: dateToISO(govermentData.value.workDate),
reasonSameDate: govermentData.value.reasonSameDate,
})
.then((res) => {
success($q, "บันทึกข้อมูลสำเร็จ");
})
.catch((e) => {
messageError($q, e);
})
.finally(async () => {
emit("update:statusEdit", false);
edit.value = false;
await refreshData();
});
};
const saveData = async () => {
await myform.value.validate().then(async (success: boolean) => {
if (success) {
await editData();
} else {
}
});
};
const handleDate = async (modelData: Date) => {
govermentData.value.containDate = modelData;
await fetchCalAgeGov(modelData);
};
const fetchCalAgeGov = async (date: Date) => {
showLoader();
const body = {
dateAppoint: date,
};
await http
.post(config.API.profileCalGovId(route.params.id.toString()), body)
.then((res) => {
const result = res.data.result;
govermentData.value.ageAll = result;
})
.catch((e) => {
messageError($q, e);
})
.finally(async () => {
hideLoader();
});
};
/**
* งชนดอมลประวแกไขขอมลทเลอก
*/
const clickHistory = async () => {
modalHistory.value = true;
showLoader();
await http
.get(config.API.profileGovHisId(route.params.id.toString()))
.then((res) => {
let data = res.data.result;
rowsHistory.value = [];
data.map((e: RequestItemsHistoryObject) => {
rowsHistory.value.push({
oc: e.oc,
position: e.position,
positionPathSide: e.positionPathSide,
posNo: e.posNo,
positionLine: e.positionLine,
positionType: e.positionType,
positionLevel: e.positionLevel,
positionExecutive: e.positionExecutive,
positionExecutiveSide: e.positionExecutiveSide,
dateAppoint: new Date(e.dateAppoint),
dateStart: new Date(e.dateStart),
retireDate: e.retireDate,
govAge: e.govAge,
govAgeAbsent: e.govAgeAbsent,
govAgePlus: e.govAgePlus,
reasonSameDate: e.reasonSameDate,
createdFullName: e.createdFullName,
createdAt: new Date(e.createdAt),
});
});
})
.catch((e) => {
messageError($q, e);
})
.finally(() => {
hideLoader();
});
};
const changeBtn = async () => {
if (edit.value == true) {
if (props.statusEdit === true) {
edit.value = false;
} else {
emit("update:statusEdit", true);
}
} else {
emit("update:statusEdit", false);
}
};
const getClass = (val: boolean) => {
return {
"full-width inputgreen cursor-pointer": val,
"full-width cursor-pointer": !val,
};
};
</script>

View file

@ -0,0 +1,455 @@
<template>
<q-page-sticky
position="top"
expand
class="bg-grey-2 text-white"
style="z-index: 99; padding: 0% 1% 0% 1%"
>
<div class="row col-12 q-gutter-sm q-pb-sm text-dark no-wrap items-center">
<q-btn
flat
round
class="bg-teal-1 full-height"
color="primary"
icon="mdi-chevron-left"
dense
@click="router.go(-1)"
>
</q-btn>
<q-avatar
v-if="imageUrl == null"
size="65px"
rounded
class="containerimage"
>
<img
src="@/assets/avatar_user.jpg"
class="bg-grey-3"
style="object-fit: cover"
/>
<div
class="overlay absolute-bottom text-subtitle2 text-center cursor-pointer"
@click="clickImage()"
>
<q-icon name="mdi-camera" size="18px" color="blue">
<q-tooltip>ปเดตรปภาพ</q-tooltip>
</q-icon>
<input
type="file"
style="display: none"
ref="inputImage"
accept="image/*"
@change="uploadImage"
/>
</div>
</q-avatar>
<q-avatar v-else size="65px" rounded class="containerimage">
<img :src="imageUrl" class="bg-grey-3" style="object-fit: cover" />
<div
class="overlay absolute-bottom text-subtitle2 text-center cursor-pointer"
@click="clickImage()"
>
<q-icon name="mdi-camera" size="18px" color="blue">
<q-tooltip>ปเดตรปภาพ</q-tooltip>
</q-icon>
<input
type="file"
style="display: none"
ref="inputImage"
accept="image/*"
@change="uploadImage"
/>
</div>
</q-avatar>
<div class="row items-center text-dark q-ml-md">
<div class="column">
<div class="text-bold q-pb-xs text-name">
{{ fullname }}
</div>
<div>{{ position }}</div>
</div>
</div>
<q-space />
<slot name="button-right" />
</div>
</q-page-sticky>
<!---------------------------------------- Dialog เลอก Image ---------------------------------------->
<q-dialog v-model="dialogImage" persistent>
<q-card style="width: 100vw; max-width: 60vw">
<q-card-section class="q-py-sm row">
<div class="text-h6">เลอกรปภาพ</div>
<q-space />
<q-btn
icon="close"
unelevated
round
dense
@click="closeImage"
style="color: #ff8080; background-color: #ffdede"
>
<q-tooltip>ดหนาน</q-tooltip>
</q-btn>
</q-card-section>
<q-separator />
<q-card-section class="col-12 row">
<div
class="row wrap items-start col-12 q-col-gutter-sm"
style="height: 320px; overflow: auto"
>
<div class="col-3" @click="addNewImage">
<div
style="
height: 160px;
max-width: 15vw;
display: flex !important;
justify-content: center;
align-items: center;
"
class="column rounded-borders cursor-pointer bg-active-image text-white"
>
<q-icon name="add" size="60px" color="white" />
<strong>ปโหลดรปภาพ</strong>
</div>
</div>
<div
v-for="n in images"
:key="n"
class="col-3"
@click="imageActive(n)"
>
<div :class="getClass(n)">
<q-img
v-if="n.avatar != null"
:src="n.avatar"
:class="imageClass(n)"
>
<div
class="absolute-bottom col-12 cursor-pointer flex justify-between items-center"
style="padding: 5px"
>
{{ date2Thai(n.createdDate) }}
<q-btn
v-if="!n.isActive"
icon="delete"
unelevated
dense
@click="deletePhoto(n.id)"
class="bg-white"
style="color: #ff8080"
/>
</div>
</q-img>
</div>
</div>
</div>
</q-card-section>
<q-separator />
<q-card-actions align="right">
<q-btn
icon="check"
dense
flat
round
@click="selectAvatarHistory"
color="positive"
>
<q-tooltip>เลอกรปภาพ</q-tooltip>
</q-btn>
</q-card-actions>
</q-card>
</q-dialog>
</template>
<script setup lang="ts">
import { ref, onMounted } from "vue";
import { useRoute, useRouter } from "vue-router";
import { useCounterMixin } from "@/stores/mixin";
import { useQuasar } from "quasar";
import http from "@/plugins/http";
import config from "@/app.config";
const props = defineProps({
fetchData: {
type: Function,
default: () => console.log("not function"),
},
fetchSave: {
type: Function,
default: () => console.log("not function"),
},
fetchDelete: {
type: Function,
default: () => console.log("not function"),
},
fetchUpload: {
type: Function,
default: () => console.log("not function"),
},
});
const $q = useQuasar();
const mixin = useCounterMixin();
const {
date2Thai,
dateToISO,
messageError,
dialogMessage,
success,
showLoader,
hideLoader,
} = mixin;
const route = useRoute();
const router = useRouter();
const fullname = ref<string>("");
const position = ref<string>("");
const imageUrl = ref<any>(null);
const inputImage = ref<any>(null);
const activeImage = ref<any | null>(null);
const dialogImage = ref<boolean>(false);
const images = ref<any>([]);
onMounted(async () => {
await fetchData();
});
const closeImage = () => {
dialogImage.value = false;
};
const clickImage = async () => {
// ***************************************************************************************************
// ****************** fetch data ******************
// ***************************************************************************************************
await fetchAvatarHistory();
dialogImage.value = true;
};
const uploadImage = async (e: any) => {
let input = e.target.files;
if (input.length > 0) {
const formData = new FormData();
formData.append("FileData", input[0]);
showLoader();
await http
.post(config.API.profileAvatarId(route.params.id.toString()), formData)
.then((res) => {})
.catch((e) => {
messageError($q, e);
})
.finally(async () => {
await fetchData();
dialogImage.value = false;
});
return;
}
};
const selectAvatarHistory = async () => {
if (activeImage.value == null) {
dialogMessage(
$q,
"ไม่สามารถเปลี่ยนรูปได้",
"กรุณาเลือกรูปที่ต้องการเปลี่ยน",
"warning",
undefined,
"orange",
undefined,
undefined,
true
);
return;
}
showLoader();
await http
.put(config.API.profileAvatarId(route.params.id.toString()), {
avatar: activeImage.value.avatarId,
})
.then((res) => {
dialogImage.value = false;
})
.catch((e) => {
messageError($q, e);
})
.finally(async () => {
await fetchData();
});
// ***************************************************************************************************
// ****************** fetch data ID ******************
// ***************************************************************************************************
};
const imageActive = (n: any) => {
activeImage.value = n;
};
const addNewImage = () => {
inputImage.value.click();
imageActive(null);
};
const deletePhoto = async (id: string) => {
dialogMessage(
$q,
"ลบข้อมูล",
"ต้องการทำการลบข้อมูลนี้ใช่หรือไม่",
"delete",
undefined,
"red",
async () => await fetchDataDelete(id),
undefined,
false
);
};
const fetchDataDelete = async (id: string) => {
showLoader();
await http
.delete(config.API.profileAvatarHistoryId(id))
.then((res) => {
success($q, "ลบรูปภาพสำเร็จ");
})
.catch((e) => {
messageError($q, e);
})
.finally(async () => {
await fetchData();
await clickImage();
// dialogImage.value = false;
});
};
const fetchData = async () => {
showLoader();
await http
.get(config.API.profileAvatarId(route.params.id.toString()))
.then((res) => {
const data = res.data.result;
// console.log(data);
fullname.value = data.fullname;
imageUrl.value = data.avatar;
position.value = data.position;
// profileType.value = data.profileType;
// employeeClass.value =
// data.employeeClass == null ? "" : data.employeeClass;
// const reason = reasonOptions.value.filter(
// (r: DataOption) => r.id == data.leaveReason
// );
// if (reason.length > 0) {
// leaveReason.value = ` (: ${reason[0].name})`;
// } else {
// leaveReason.value = "";
// }
// reasonStatus.value = reason.length > 0 ? true : false;
})
.catch((e) => {
messageError($q, e);
})
.finally(() => {
hideLoader();
});
};
const fetchAvatarHistory = async () => {
showLoader();
await http
.get(config.API.profileAvatarHistoryId(route.params.id.toString()))
.then((res) => {
const data = res.data.result;
console.log(data);
images.value = [];
data.map((e: any) => {
images.value.push({
id: e.id,
avatar: e.avatar,
avatarId: e.avatarId,
createdDate: new Date(e.createdDate),
isActive: e.isActive,
});
});
})
.catch((e) => {
messageError($q, e);
})
.finally(() => {
hideLoader();
});
};
const imageClass = (n: any) => {
const val = n == activeImage.value;
return {
"rounded-borders bg-grey-2 image-size-default": val,
"rounded-borders bg-grey-2 image-size-full": !val,
};
};
const getClass = (n: any) => {
const val = n == activeImage.value;
return {
"rounded-borders border-green shadow-1": val,
"rounded-borders shadow-1": !val,
};
};
</script>
<style lang="scss" scoped>
.image-size-default {
height: 150px;
max-width: 15vw;
}
.image-size-full {
height: 160px;
max-width: 15vw;
}
.border-green {
border: 5px solid #52c688;
}
.area-div {
background-color: transparent;
}
.text-header {
font-size: 1.2em;
}
.containerimage {
position: relative;
}
.containerimage:hover .overlay {
opacity: 1;
}
.overlay {
background-color: #e4f2ffd2 !important;
opacity: 0;
padding: 2px !important;
}
.information:target {
padding-top: 84px;
}
.border-custom {
border: 0.5px solid #c3c3c3;
}
.bg-active-image {
background-color: #52c688;
}
.text-name {
font-size: 1.25em;
overflow: hidden;
}
</style>

File diff suppressed because it is too large Load diff

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,973 @@
<!-- card ประวการเปลยนช-นามสก -->
<template>
<div class="col-12">
<q-form ref="myForm">
<div class="col-12 q-pt-md q-pb-sm"><q-separator /></div>
<ProfileTable
:rows="rows"
:columns="columns"
:filter="filter"
:visible-columns="visibleColumns"
v-model:inputfilter="filter"
v-model:inputvisible="visibleColumns"
:add="clickAdd"
name="ประวัติการเปลี่ยนชื่อ-นามสกุล"
icon="mdi-book"
:statusEdit="!statusEdit"
>
<template #columns="props">
<q-tr :props="props">
<q-td
v-for="col in props.cols"
:key="col.name"
:props="props"
@click="statusEdit ? selectData(props) : ''"
class="cursor-pointer"
>
<div v-if="col.name == 'status'" class="table_ellipsis">
{{ typeChangeName(col.value) }}
</div>
<div v-else class="table_ellipsis">
{{ col.value }}
</div>
</q-td>
<q-td auto-width>
<q-btn
v-if="props.row.file != null"
color="green"
flat
dense
round
size="14px"
icon="mdi-file-document-outline"
@click="openFile(props.row.file)"
/>
<q-btn
color="info"
flat
dense
round
size="14px"
icon="mdi-history"
@click="clickHistory(props.row)"
/>
</q-td>
</q-tr>
</template>
</ProfileTable>
</q-form>
</div>
<!-- popup Edit window-->
<q-dialog v-model="modal" persistent>
<q-card style="width: 600px">
<q-form ref="myForm">
<DialogHeader tittle="เปลี่ยนชื่อ-นามสกุล" :close="clickClose" />
<q-separator />
<q-card-section class="q-p-sm">
<div
class="row col-12 items-center q-col-gutter-x-xs q-col-gutter-y-xs"
>
<div class="col-xs-6 col-sm-6 col-md-6">
<selector
:hide-dropdown-icon="!edit"
hide-bottom-space
:class="getClass(edit)"
:readonly="!edit"
:borderless="!edit"
:rules="[(val:string) => !!val || `${'กรุณาเลือก สถานะการเปลี่ยนชื่อ'}`]"
:outlined="edit"
dense
lazy-rules
v-model="status"
emit-value
map-options
option-label="name"
:options="Ops.statusOps"
option-value="id"
:label="`${'สถานะการเปลี่ยนชื่อ'}`"
use-input
input-debounce="0"
@filter="(inputValue:any,
doneFn:Function) => filterSelector(inputValue, doneFn,'statusOps'
) "
/>
</div>
<q-space class="col-6" />
<div class="col-xs-4 col-sm-4 col-md-4">
<selector
:hide-dropdown-icon="!edit"
hide-bottom-space
:class="getClass(edit)"
:readonly="!edit"
:borderless="!edit"
:rules="[(val:string) => !!val || `${'กรุณาเลือก คำนำหน้าชื่อ'}`]"
:outlined="edit"
dense
lazy-rules
v-model="prefixId"
emit-value
map-options
option-label="name"
:options="Ops.prefixOps"
option-value="id"
:label="`${'คำนำหน้าชื่อ'}`"
use-input
input-debounce="0"
@filter="(inputValue:any,
doneFn:Function) => filterSelector(inputValue, doneFn,'prefixOps'
) "
/>
</div>
<div class="col-xs-4 col-sm-4 col-md-4">
<q-input
:class="getClass(edit)"
:outlined="edit"
dense
lazy-rules
:readonly="!edit || status == 'lastName'"
:borderless="!edit"
v-model="firstName"
:rules="[(val) => !!val || `${'กรุณากรอกชื่อ'}`]"
hide-bottom-space
:label="`${'ชื่อ'}`"
@update:modelValue="clickEditRow"
/>
</div>
<div class="col-xs-4 col-sm-4 col-md-4">
<q-input
:class="getClass(edit)"
:outlined="edit"
dense
lazy-rules
:readonly="!edit || status == 'firstName'"
:borderless="!edit"
v-model="lastName"
:rules="[(val) => !!val || `${'กรุณากรอกนามสกุล'}`]"
hide-bottom-space
:label="`${'นามสกุล'}`"
@update:modelValue="clickEditRow"
/>
</div>
<q-btn
v-if="file != null && !edit"
color="green"
flat
dense
round
size="14px"
icon="mdi-file-document-outline"
@click="openFile(file)"
/>
<q-uploader
v-if="edit"
color="gray"
type="file"
flat
ref="uploader"
class="full-width"
text-color="white"
:max-size="10000000"
accept=".jpg,.png,.pdf,.csv,.doc"
bordered
label="[ไฟล์ jpg,png,pdf,csv,doc ขนาดไม่เกิน 10MB]"
@added="fileAdd"
>
<template v-slot:header="scope">
<div class="row no-wrap items-center q-pa-sm q-gutter-xs">
<q-btn
v-if="scope.queuedFiles.length > 0"
icon="clear_all"
@click="scope.removeQueuedFiles"
round
dense
flat
>
<q-tooltip>ลบทงหมด</q-tooltip>
</q-btn>
<q-btn
v-if="scope.uploadedFiles.length > 0"
icon="done_all"
@click="scope.removeUploadedFiles"
round
dense
flat
>
<q-tooltip>ลบไฟลปโหลด</q-tooltip>
</q-btn>
<q-spinner
v-if="scope.isUploading"
class="q-uploader__spinner"
/>
<div class="col">
<div class="q-uploader__title">
{{ "[ไฟล์ jpg,png,pdf,csv,doc ขนาดไม่เกิน 10MB]" }}
</div>
<div class="q-uploader__subtitle">
{{ scope.uploadSizeLabel }} /
{{ scope.uploadProgressLabel }}
</div>
</div>
<q-btn
v-if="scope.canAddFiles"
type="a"
icon="add_box"
@click="scope.pickFiles"
round
dense
flat
>
<q-uploader-add-trigger />
<q-tooltip>เลอกไฟล</q-tooltip>
</q-btn>
<q-btn
v-if="scope.isUploading"
icon="clear"
@click="scope.abort"
round
dense
flat
>
<q-tooltip>ยกเลกการอปโหลด</q-tooltip>
</q-btn>
</div>
</template>
</q-uploader>
</div>
</q-card-section>
<q-separator />
<DialogFooter
:cancel="clickCancel"
:edit="clickEdit"
:save="clickSave"
:validate="validateData"
:clickNext="clickNext"
:clickPrevious="clickPrevious"
:clickDelete="clickDelete"
v-model:editvisible="edit"
v-model:next="next"
v-model:previous="previous"
v-model:modalEdit="modalEdit"
/>
</q-form>
</q-card>
</q-dialog>
<HistoryTable
:rows="rowsHistory"
:columns="columnsHistory"
:filter="filterHistory"
:visible-columns="visibleColumnsHistory"
v-model:modal="modalHistory"
v-model:inputfilter="filterHistory"
v-model:inputvisible="visibleColumnsHistory"
v-model:tittle="tittleHistory"
:history="true"
>
<template #columns="props">
<q-tr :props="props">
<q-td v-for="col in props.cols" :key="col.name" :props="props">
<div v-if="col.name == 'createdAt'" class="table_ellipsis">
{{ date2Thai(col.value) }}
</div>
<div v-else-if="col.name == 'status'" class="table_ellipsis">
{{ typeChangeName(col.value) }}
</div>
<div v-else class="table_ellipsis">
{{ col.value }}
</div>
</q-td>
<q-td auto-width>
<q-btn
v-if="props.row.file != null"
color="green"
flat
dense
round
size="14px"
icon="mdi-file-document-outline"
@click="openFile(props.row.file)"
/>
</q-td>
</q-tr>
</template>
</HistoryTable>
</template>
<script setup lang="ts">
import { onMounted, ref, watch } from "vue";
import { useRoute } from "vue-router";
import { useComponentProfileDataStore } from "@/components/information/store/store";
import { useCounterMixin } from "@/stores/mixin";
import ProfileTable from "@/components/information/Table.vue";
import DialogHeader from "@/components/information/DialogHeader.vue";
import DialogFooter from "@/components/information/DialogFooter.vue";
import { useQuasar } from "quasar";
import type {
RequestItemsObject,
DataProps,
} from "@/components/information/interface/request/OldName";
import type { ResponseObject } from "@/components/information/interface/response/OldName";
import type {
OldNameOps,
DataOption,
} from "@/components/information/interface/index/Main";
import HistoryTable from "@/components/TableHistory.vue";
import http from "@/plugins/http";
import config from "@/app.config";
import type { QTableProps } from "quasar";
const props = defineProps({
statusEdit: {
type: Boolean,
required: true,
},
fetchDataInformation: {
type: Function,
default: () => console.log("not function"),
},
perfixId: {
type: String,
required: true,
},
firstname: {
type: String,
required: true,
},
lastname: {
type: String,
required: true,
},
});
const $q = useQuasar();
const store = useComponentProfileDataStore();
const { profileData, changeProfileColumns } = store;
const mixin = useCounterMixin();
const {
date2Thai,
success,
dateToISO,
messageError,
typeChangeName,
dialogMessage,
showLoader,
hideLoader,
} = mixin;
const route = useRoute();
const id = ref<string>("");
const prefixId = ref<string>();
const firstName = ref<string>();
const lastName = ref<string>();
const status = ref<string>();
const nameFile = ref<string>("");
const minDate = ref<Date>();
const myForm = ref<any>(); //form data input
const edit = ref<boolean>(false); // dialog
const modal = ref<boolean>(false); //modal add detail
const modalEdit = ref<boolean>(false); //modal
const rawItem = ref<RequestItemsObject>(); // row
const rowIndex = ref<number>(0); //index row
const previous = ref<boolean>(); //
const next = ref<boolean>(); //
const editRow = ref<boolean>(false); //
const rowsHistory = ref<RequestItemsObject[]>([]); //select data history
const tittleHistory = ref<string>("ประวัติแก้ไขประวัติการเปลี่ยนชื่อ-นามสกุล"); //
const filterHistory = ref<string>(""); //search data table history
const modalHistory = ref<boolean>(false); //modal
const checkValidate = ref<boolean>(false); //validate data
const profileId = ref<string>(route.params.id.toString());
const file = ref<string | null>(null);
const fileUpload = ref<any>([]);
const rows = ref<RequestItemsObject[]>([]);
const filter = ref<string>(""); //search data table
const visibleColumns = ref<String[]>([]);
const Ops = ref<OldNameOps>({
prefixOps: [],
statusOps: [
{
id: "firstName",
name: "เปลี่ยนชื่อ",
},
{
id: "lastName",
name: "เปลี่ยนนามสกุล",
},
{
id: "all",
name: "เปลี่ยนชื่อ-นามสกุล",
},
],
});
const OpsFilter = ref<OldNameOps>({
prefixOps: [],
statusOps: [
{
id: "firstName",
name: "เปลี่ยนชื่อ",
},
{
id: "lastName",
name: "เปลี่ยนนามสกุล",
},
{
id: "all",
name: "เปลี่ยนชื่อ-นามสกุล",
},
],
});
profileData.oldName.columns.length == 0
? (visibleColumns.value = ["prefix", "firstName", "lastName", "status"])
: (visibleColumns.value = profileData.oldName.columns);
const columns = ref<QTableProps["columns"]>([
{
name: "prefix",
align: "left",
label: "คำนำหน้าชื่อ",
sortable: true,
field: "prefix",
headerStyle: "font-size: 14px",
style: "font-size: 14px",
sort: (a: string, b: string) =>
a.localeCompare(b, undefined, { numeric: true, sensitivity: "base" }),
},
{
name: "firstName",
align: "left",
label: "ชื่อ",
sortable: true,
field: "firstName",
headerStyle: "font-size: 14px",
style: "font-size: 14px",
sort: (a: string, b: string) =>
a.localeCompare(b, undefined, { numeric: true, sensitivity: "base" }),
},
{
name: "lastName",
align: "left",
label: "นามสกุล",
sortable: true,
field: "lastName",
headerStyle: "font-size: 14px",
style: "font-size: 14px",
sort: (a: string, b: string) =>
a.localeCompare(b, undefined, { numeric: true, sensitivity: "base" }),
},
{
name: "status",
align: "left",
label: "สถานะการเปลี่ยนชื่อ",
sortable: true,
field: "status",
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: "prefix",
align: "left",
label: "คำนำหน้าชื่อ",
sortable: true,
field: "prefix",
headerStyle: "font-size: 14px",
style: "font-size: 14px",
sort: (a: string, b: string) =>
a.localeCompare(b, undefined, { numeric: true, sensitivity: "base" }),
},
{
name: "firstName",
align: "left",
label: "ชื่อ",
sortable: true,
field: "firstName",
headerStyle: "font-size: 14px",
style: "font-size: 14px",
sort: (a: string, b: string) =>
a.localeCompare(b, undefined, { numeric: true, sensitivity: "base" }),
},
{
name: "lastName",
align: "left",
label: "นามสกุล",
sortable: true,
field: "lastName",
headerStyle: "font-size: 14px",
style: "font-size: 14px",
sort: (a: string, b: string) =>
a.localeCompare(b, undefined, { numeric: true, sensitivity: "base" }),
},
{
name: "status",
align: "left",
label: "สถานะการเปลี่ยนชื่อ",
sortable: true,
field: "status",
headerStyle: "font-size: 14px",
style: "font-size: 14px",
sort: (a: string, b: string) =>
a.localeCompare(b, undefined, { numeric: true, sensitivity: "base" }),
},
{
name: "createdFullName",
align: "left",
label: "ผู้ดำเนินการ",
sortable: true,
field: "createdFullName",
headerStyle: "font-size: 14px",
style: "font-size: 14px",
sort: (a: string, b: string) =>
a.localeCompare(b, undefined, { numeric: true, sensitivity: "base" }),
},
{
name: "createdAt",
align: "left",
label: "วันที่แก้ไข",
sortable: true,
field: "createdAt",
headerStyle: "font-size: 14px",
style: "font-size: 14px",
sort: (a: string, b: string) =>
a.localeCompare(b, undefined, { numeric: true, sensitivity: "base" }),
},
]);
const visibleColumnsHistory = ref<String[]>([
"prefix",
"firstName",
"lastName",
"status",
"createdFullName",
"createdAt",
]);
watch(visibleColumns, async (count: String[], prevCount: String[]) => {
await changeProfileColumns("oldName", count);
});
onMounted(async () => {
await fetchPerson();
await fetchData();
});
const fetchData = async () => {
showLoader();
await http
.get(config.API.profileChangeNameId(profileId.value))
.then((res) => {
let data = res.data.result;
rows.value = [];
data.map((e: ResponseObject) => {
rows.value.push({
id: e.id,
prefix: e.prefix,
prefixId: e.prefixId,
firstName: e.firstName,
lastName: e.lastName,
status: e.status,
file: e.file,
createdFullName: e.createdFullName,
createdAt: new Date(e.createdAt),
});
});
})
.catch((e) => {
messageError($q, e);
})
.finally(() => {
hideLoader();
});
};
/**
* get รายการ อมลเกยวกบบคคล
*/
const fetchPerson = async () => {
showLoader();
await http
.get(config.API.person)
.then((res) => {
const data = res.data.result;
let optionprefixs: DataOption[] = [];
data.prefixs.map((r: any) => {
optionprefixs.push({
id: r.id.toString(),
name: r.name.toString(),
});
});
Ops.value.prefixOps = optionprefixs;
OpsFilter.value.prefixOps = optionprefixs;
})
.catch((e: any) => {})
.finally(() => {
hideLoader();
});
};
/**
* กดดอมลกอนหน
*/
const clickPrevious = async () => {
edit.value = false;
rowIndex.value -= 1;
await getData();
await checkRowPage();
};
/**
* กดดอมลตอไป
*/
const clickNext = async () => {
edit.value = false;
rowIndex.value += 1;
await getData();
await checkRowPage();
};
/**
* กดดอมลตอไป
*/
const getData = () => {
const row = rows.value[rowIndex.value];
prefixId.value = row.prefixId;
firstName.value = row.firstName;
lastName.value = row.lastName;
status.value = row.status;
file.value = row.file;
id.value = row.id;
};
/**
* เชคปมดอม อน อไป าตองแสดงไหม
*/
const checkRowPage = () => {
editRow.value = false;
next.value = true;
previous.value = true;
if (rowIndex.value + 1 >= rows.value.length) {
next.value = false;
}
if (rowIndex.value - 1 < 0) {
previous.value = false;
}
};
/**
* กดปมแกไขใน dialog
*/
const clickEdit = () => {
editRow.value = false;
next.value = false;
previous.value = false;
};
/**
* กดปมเพมดานบน table
*/
const clickAdd = async () => {
editRow.value = false;
await addData();
};
/**
* กดบนทกใน dialog
*/
const clickSave = async () => {
myForm.value.validate().then(async (result: boolean) => {
if (result) {
if (modalEdit.value) {
await editData();
} else {
await saveData();
}
}
});
};
/**
* นทกเพมขอม
*/
const saveData = async () => {
if (fileUpload.value.length > 0) {
const blob = fileUpload.value.slice(0, fileUpload.value[0].size);
const newFile = new File(blob, nameFile.value, {
type: fileUpload.value[0].type,
});
const formData = new FormData();
formData.append("", newFile);
if (prefixId.value != undefined)
formData.append("prefixId", prefixId.value);
if (firstName.value != undefined)
formData.append("firstName", firstName.value);
if (lastName.value != undefined)
formData.append("lastName", lastName.value);
if (status.value != undefined) formData.append("status", status.value);
showLoader();
await http
.post(config.API.profileChangeNameId(profileId.value), formData)
.then((res) => {
success($q, "บันทึกข้อมูลสำเร็จ");
modal.value = false;
})
.catch((e) => {
messageError($q, e);
})
.finally(async () => {
await fetchData();
await props.fetchDataInformation();
});
} else {
dialogMessage(
$q,
"ไม่สามารถบันทึกข้อมูลได้",
"กรุณาอัปโหลดเอกสารหลักฐาน",
"warning",
undefined,
"orange",
undefined,
undefined,
true
);
}
};
/**
* นทกแกไขขอม
*/
const editData = async () => {
const formData = new FormData();
if (fileUpload.value.length > 0) {
const blob = fileUpload.value.slice(0, fileUpload.value[0].size);
const newFile = new File(blob, nameFile.value, {
type: fileUpload.value[0].type,
});
formData.append("", newFile);
}
if (prefixId.value != undefined) formData.append("prefixId", prefixId.value);
if (firstName.value != undefined)
formData.append("firstName", firstName.value);
if (lastName.value != undefined) formData.append("lastName", lastName.value);
if (status.value != undefined) formData.append("status", status.value);
showLoader();
await http
.put(config.API.profileChangeNameId(id.value), formData)
.then((res) => {
success($q, "บันทึกข้อมูลสำเร็จ");
modal.value = false;
})
.catch((e) => {
messageError($q, e);
})
.finally(async () => {
await fetchData();
await props.fetchDataInformation();
});
};
/**
* ลบลบขอม
*/
const clickDelete = async () => {
$q.dialog({
title: `ลบข้อมูล`,
message: `ต้องการทำการลบข้อมูลนี้ใช่หรือไม่?`,
cancel: "ยกเลิก",
ok: "ยืนยัน",
persistent: true,
})
.onOk(async () => {
showLoader();
await http
.delete(config.API.profileChangeNameId(id.value))
.then((res) => {
success($q, "ลบข้อมูลสำเร็จ");
modal.value = false;
})
.catch((e) => {
messageError($q, e);
})
.finally(async () => {
await fetchData();
});
})
.onCancel(async () => {
await fetchData();
});
};
/**
* กดป dialog
*/
const clickClose = async () => {
if (editRow.value == true) {
$q.dialog({
title: `ข้อมูลมีการแก้ไข`,
message: `ยืนยันที่จะปิดโดยไม่บันทึกใช่หรือไม่?`,
cancel: "ยกเลิก",
ok: "ยืนยัน",
persistent: true,
}).onOk(async () => {
modal.value = false;
next.value = false;
previous.value = false;
});
} else {
modal.value = false;
next.value = false;
previous.value = false;
}
};
/**
* กดเลอกขอมลทจะแกไข
* @param props props ใน row เลอก
*/
const selectData = async (props: DataProps) => {
modalEdit.value = true; //
modal.value = true; //modal
edit.value = false; // edit modal
rawItem.value = props.row;
rowIndex.value = props.rowIndex;
prefixId.value = props.row.prefixId;
firstName.value = props.row.firstName;
lastName.value = props.row.lastName;
status.value = props.row.status;
file.value = props.row.file;
id.value = props.row.id;
await checkRowPage();
};
/**
* กดปมเพมบน table
*/
const addData = () => {
modalEdit.value = false;
modal.value = true;
edit.value = true;
prefixId.value = props.perfixId;
firstName.value = props.firstname;
lastName.value = props.lastname;
status.value = "";
file.value = "";
};
/**
* งกนปมยกเลกการแกไขขอม
*/
const clickCancel = async () => {
if (editRow.value == true) {
$q.dialog({
title: `ข้อมูลมีการแก้ไข`,
message: `ยืนยันยกเลิกการแก้ไขใช่หรือไม่?`,
cancel: "ยกเลิก",
ok: "ยืนยัน",
persistent: true,
}).onOk(async () => {
edit.value = false;
await checkRowPage();
await getData();
});
} else {
edit.value = false;
await checkRowPage();
}
};
/**
* เชความการแกไขขอม
*/
const clickEditRow = () => {
editRow.value = true;
};
/**
* งชนดอมลประวแกไขขอมลทเลอก
* @param row อม row ประวการแกไข
*/
const clickHistory = async (row: RequestItemsObject) => {
modalHistory.value = true;
showLoader();
await http
.get(config.API.profileChangeNameHisId(row.id))
.then((res) => {
let data = res.data.result;
rowsHistory.value = [];
data.map((e: ResponseObject) => {
rowsHistory.value.push({
id: e.id,
prefix: e.prefix,
prefixId: e.prefixId,
firstName: e.firstName,
lastName: e.lastName,
status: e.status,
file: e.file,
createdFullName: e.createdFullName,
createdAt: new Date(e.createdAt),
});
});
})
.catch((e) => {
messageError($q, e);
})
.finally(() => {
hideLoader();
});
};
const filterSelector = (val: any, update: Function, refData: string) => {
switch (refData) {
case "prefixOps":
update(() => {
Ops.value.prefixOps = OpsFilter.value.prefixOps.filter(
(v: DataOption) => v.name.indexOf(val) > -1
);
});
break;
case "statusOps":
update(() => {
Ops.value.statusOps = OpsFilter.value.statusOps.filter(
(v: DataOption) => v.name.indexOf(val) > -1
);
});
break;
default:
break;
}
};
const fileAdd = async (val: any) => {
nameFile.value = val[0].name;
fileUpload.value = val;
};
const openFile = async (val: string | null) => {
if (val != null) window.open(val);
};
/**
* validate input ใน dialog
*/
const validateData = async () => {
checkValidate.value = true;
await myForm.value.validate().then((result: boolean) => {
if (result == false) {
checkValidate.value = false;
}
});
};
/**
* class ดรปแบบแสดงระหวางขอมลทแกไขหรอแสดงเฉยๆ
* @param val อม input สำหรบแกไขหรอไม
*/
const getClass = (val: boolean) => {
return {
"full-width inputgreen cursor-pointer": val,
"full-width cursor-pointer": !val,
};
};
</script>
<style lang="scss">
.modalfix {
position: fixed !important;
}
</style>

View file

@ -0,0 +1,619 @@
<!-- card นๆ -->
<template>
<q-card flat bordered class="col-12 q-px-lg q-py-md">
<q-form ref="myForm">
<ProfileTable
:rows="rows"
:columns="columns"
:filter="filter"
:visible-columns="visibleColumns"
v-model:inputfilter="filter"
v-model:inputvisible="visibleColumns"
:add="clickAdd"
name="อื่นๆ"
icon="mdi-bookmark"
:statusEdit="statusEdit"
>
<template #columns="props">
<q-tr :props="props">
<q-td
v-for="col in props.cols"
:key="col.name"
:props="props"
@click="selectData(props)"
class="cursor-pointer"
>
<div v-if="col.name == 'date'" class="table_ellipsis">
{{ date2Thai(col.value) }}
</div>
<div v-else class="table_ellipsis">
{{ col.value }}
</div>
</q-td>
<q-td auto-width>
<q-btn
color="info"
flat
dense
round
size="14px"
icon="mdi-history"
@click="clickHistory(props.row)"
/>
</q-td>
</q-tr>
</template>
</ProfileTable>
</q-form>
</q-card>
<!-- popup Edit window-->
<q-dialog v-model="modal" persistent>
<q-card style="width: 600px">
<q-form ref="myForm">
<DialogHeader tittle="อื่นๆ" :close="clickClose" />
<q-separator />
<q-card-section class="q-p-sm">
<div
class="row col-12 items-center q-col-gutter-x-xs q-col-gutter-y-xs"
>
<div class="col-xs-6 col-sm-6 col-md-6">
<datepicker
menu-class-name="modalfix"
:readonly="!edit"
v-model="date"
:locale="'th'"
autoApply
:enableTimePicker="false"
@update:modelValue="clickEditRow"
week-start="0"
>
<template #year="{ year }">{{ year + 543 }}</template>
<template #year-overlay-value="{ value }">{{
parseInt(value + 543)
}}</template>
<template #trigger>
<q-input
:class="getClass(edit)"
:outlined="edit"
dense
lazy-rules
:borderless="!edit"
:model-value="date2Thai(date)"
:rules="[(val) => !!val || `${'กรุณาเลือกวันที่'}`]"
hide-bottom-space
:label="`${'วันที่'}`"
>
<template v-slot:prepend>
<q-icon
name="event"
class="cursor-pointer"
:style="
edit
? 'color: var(--q-primary)'
: 'color: var(--q-grey)'
"
>
</q-icon>
</template>
</q-input>
</template>
</datepicker>
</div>
<div class="col-xs-6 col-sm-6 col-md-6">
<q-input
:class="getClass(edit)"
:outlined="edit"
dense
lazy-rules
autogrow
:readonly="!edit"
:borderless="!edit"
v-model="detail"
:rules="[(val) => !!val || `${'กรุณากรอกรายละเอียด'}`]"
hide-bottom-space
:label="`${'รายละเอียด'}`"
@update:modelValue="clickEditRow"
/>
</div>
</div>
</q-card-section>
<q-separator />
<DialogFooter
:cancel="clickCancel"
:edit="clickEdit"
:save="clickSave"
:validate="validateData"
:clickNext="clickNext"
:clickPrevious="clickPrevious"
:clickDelete="clickDelete"
v-model:editvisible="edit"
v-model:next="next"
v-model:previous="previous"
v-model:modalEdit="modalEdit"
/>
</q-form>
</q-card>
</q-dialog>
<HistoryTable
:rows="rowsHistory"
:columns="columnsHistory"
:filter="filterHistory"
:visible-columns="visibleColumnsHistory"
v-model:modal="modalHistory"
v-model:inputfilter="filterHistory"
v-model:inputvisible="visibleColumnsHistory"
v-model:tittle="tittleHistory"
>
<template #columns="props">
<q-tr :props="props">
<q-td v-for="col in props.cols" :key="col.name" :props="props">
<div
v-if="col.name == 'date' || col.name == 'createdAt'"
class="table_ellipsis"
>
{{ date2Thai(col.value) }}
</div>
<div v-else class="table_ellipsis">
{{ col.value }}
</div>
</q-td>
</q-tr>
</template>
</HistoryTable>
</template>
<script setup lang="ts">
import { onMounted, ref, watch } from "vue";
import { useRoute } from "vue-router";
import { useComponentProfileDataStore } from "@/components/information/store/store";
import { useCounterMixin } from "@/stores/mixin";
import ProfileTable from "@/components/information/Table.vue";
import DialogHeader from "@/components/information/DialogHeader.vue";
import DialogFooter from "@/components/information/DialogFooter.vue";
import { useQuasar } from "quasar";
import type {
RequestItemsObject,
DataProps,
} from "@/components/information/interface/request/Other";
import type { ResponseObject } from "@/components/information/interface/response/Other";
import HistoryTable from "@/components/TableHistory.vue";
import http from "@/plugins/http";
import config from "@/app.config";
import type { QTableProps } from "quasar";
const props = defineProps({
statusEdit: {
type: Boolean,
required: true,
},
});
const $q = useQuasar();
const store = useComponentProfileDataStore();
const { profileData, changeProfileColumns } = store;
const mixin = useCounterMixin();
const { date2Thai, success, messageError, showLoader, hideLoader } = mixin;
const route = useRoute();
const id = ref<string>("");
const date = ref<Date>(new Date());
const detail = ref<string>();
const myForm = ref<any>(); //form data input
const edit = ref<boolean>(false); // dialog
const modal = ref<boolean>(false); //modal add detail
const modalEdit = ref<boolean>(false); //modal
const rawItem = ref<RequestItemsObject>(); // row
const rowIndex = ref<number>(0); //index row
const previous = ref<boolean>(); //
const next = ref<boolean>(); //
const editRow = ref<boolean>(false); //
const rowsHistory = ref<RequestItemsObject[]>([]); //select data history
const tittleHistory = ref<string>("ประวัติแก้ไขอื่นๆ"); //
const filterHistory = ref<string>(""); //search data table history
const modalHistory = ref<boolean>(false); //modal
const checkValidate = ref<boolean>(false); //validate data
const profileId = ref<string>(
route.params.id ? route.params.id.toString() : ""
);
const rows = ref<RequestItemsObject[]>([]);
const filter = ref<string>(""); //search data table
const visibleColumns = ref<String[]>([]);
profileData.other.columns.length == 0
? (visibleColumns.value = ["date", "detail"])
: (visibleColumns.value = profileData.other.columns);
const columns = ref<QTableProps["columns"]>([
{
name: "date",
align: "left",
label: "วันที่",
sortable: true,
field: "date",
headerStyle: "font-size: 14px",
style: "font-size: 14px; width: 50px;",
},
{
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" }),
},
]);
const columnsHistory = ref<QTableProps["columns"]>([
{
name: "date",
align: "left",
label: "วันที่",
sortable: true,
field: "date",
headerStyle: "font-size: 14px",
style: "font-size: 14px; width: 50px;",
},
{
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: "createdFullName",
align: "left",
label: "ผู้ดำเนินการ",
sortable: true,
field: "createdFullName",
headerStyle: "font-size: 14px",
style: "font-size: 14px",
sort: (a: string, b: string) =>
a.localeCompare(b, undefined, { numeric: true, sensitivity: "base" }),
},
{
name: "createdAt",
align: "left",
label: "วันที่แก้ไข",
sortable: true,
field: "createdAt",
headerStyle: "font-size: 14px",
style: "font-size: 14px",
sort: (a: string, b: string) =>
a.localeCompare(b, undefined, { numeric: true, sensitivity: "base" }),
},
]);
const visibleColumnsHistory = ref<String[]>([
"date",
"detail",
"createdFullName",
"createdAt",
]);
watch(visibleColumns, async (count: String[], prevCount: String[]) => {
await changeProfileColumns("other", count);
});
onMounted(async () => {
await fetchData();
});
const fetchData = async () => {
if (profileId.value) {
showLoader();
await http
.get(config.API.profileOtherId(profileId.value))
.then((res) => {
let data = res.data.result;
rows.value = [];
data.map((e: ResponseObject) => {
rows.value.push({
id: e.id,
date: new Date(e.date),
detail: e.detail,
createdFullName: e.createdFullName,
createdAt: new Date(e.createdAt),
});
});
})
.catch((e) => {
messageError($q, e);
})
.finally(() => {
hideLoader();
});
}
};
/**
* กดดอมลกอนหน
*/
const clickPrevious = async () => {
edit.value = false;
rowIndex.value -= 1;
await getData();
await checkRowPage();
};
/**
* กดดอมลตอไป
*/
const clickNext = async () => {
edit.value = false;
rowIndex.value += 1;
await getData();
await checkRowPage();
};
/**
* กดดอมลตอไป
*/
const getData = () => {
const row = rows.value[rowIndex.value];
date.value = row.date;
detail.value = row.detail;
id.value = row.id;
};
/**
* เชคปมดอม อน อไป าตองแสดงไหม
*/
const checkRowPage = () => {
editRow.value = false;
next.value = true;
previous.value = true;
if (rowIndex.value + 1 >= rows.value.length) {
next.value = false;
}
if (rowIndex.value - 1 < 0) {
previous.value = false;
}
};
/**
* กดปมแกไขใน dialog
*/
const clickEdit = () => {
editRow.value = false;
next.value = false;
previous.value = false;
};
/**
* กดปมเพมดานบน table
*/
const clickAdd = async () => {
editRow.value = false;
await addData();
};
/**
* กดบนทกใน dialog
*/
const clickSave = async () => {
myForm.value.validate().then(async (result: boolean) => {
if (result) {
if (modalEdit.value) {
await editData();
} else {
await saveData();
}
}
});
};
/**
* นทกเพมขอม
*/
const saveData = async () => {
if (profileId.value) {
showLoader();
await http
.post(config.API.profileOtherId(profileId.value), {
id: id.value,
date: date.value,
detail: detail.value,
})
.then((res) => {
success($q, "บันทึกข้อมูลสำเร็จ");
modal.value = false;
})
.catch((e) => {
messageError($q, e);
})
.finally(async () => {
await fetchData();
});
}
};
/**
* นทกแกไขขอม
*/
const editData = async () => {
showLoader();
await http
.put(config.API.profileOtherId(id.value), {
id: id.value,
date: date.value,
detail: detail.value,
})
.then((res) => {
success($q, "บันทึกข้อมูลสำเร็จ");
modal.value = false;
})
.catch((e) => {
messageError($q, e);
})
.finally(async () => {
await fetchData();
});
};
/**
* ลบลบขอม
*/
const clickDelete = async () => {
$q.dialog({
title: `ลบข้อมูล`,
message: `ต้องการทำการลบข้อมูลนี้ใช่หรือไม่?`,
cancel: "ยกเลิก",
ok: "ยืนยัน",
persistent: true,
})
.onOk(async () => {
showLoader();
await http
.delete(config.API.profileOtherId(id.value))
.then((res) => {
success($q, "ลบข้อมูลสำเร็จ");
modal.value = false;
})
.catch((e) => {
messageError($q, e);
})
.finally(async () => {
await fetchData();
});
})
.onCancel(async () => {
await fetchData();
});
};
/**
* กดป dialog
*/
const clickClose = async () => {
if (editRow.value == true) {
$q.dialog({
title: `ข้อมูลมีการแก้ไข`,
message: `ยืนยันที่จะปิดโดยไม่บันทึกใช่หรือไม่?`,
cancel: "ยกเลิก",
ok: "ยืนยัน",
persistent: true,
}).onOk(async () => {
modal.value = false;
next.value = false;
previous.value = false;
});
} else {
modal.value = false;
next.value = false;
previous.value = false;
}
};
/**
* กดเลอกขอมลทจะแกไข
* @param props props ใน row เลอก
*/
const selectData = async (props: DataProps) => {
modalEdit.value = true;
modal.value = true;
edit.value = false;
rawItem.value = props.row;
rowIndex.value = props.rowIndex;
date.value = props.row.date;
detail.value = props.row.detail;
id.value = props.row.id;
await checkRowPage();
};
/**
* กดปมเพมบน table
*/
const addData = () => {
modalEdit.value = false;
modal.value = true;
edit.value = true;
date.value = new Date();
detail.value = "";
};
/**
* งกนปมยกเลกการแกไขขอม
*/
const clickCancel = async () => {
if (editRow.value == true) {
$q.dialog({
title: `ข้อมูลมีการแก้ไข`,
message: `ยืนยันยกเลิกการแก้ไขใช่หรือไม่?`,
cancel: "ยกเลิก",
ok: "ยืนยัน",
persistent: true,
}).onOk(async () => {
edit.value = false;
await checkRowPage();
await getData();
});
} else {
edit.value = false;
await checkRowPage();
}
};
/**
* เชความการแกไขขอม
*/
const clickEditRow = () => {
editRow.value = true;
};
/**
* งชนดอมลประวแกไขขอมลทเลอก
* @param row อม row ประวการแกไข
*/
const clickHistory = async (row: RequestItemsObject) => {
modalHistory.value = true;
showLoader();
await http
.get(config.API.profileOtherHisId(row.id))
.then((res) => {
let data = res.data.result;
rowsHistory.value = [];
data.map((e: ResponseObject) => {
rowsHistory.value.push({
id: e.id,
date: e.date,
detail: e.detail,
createdFullName: e.createdFullName,
createdAt: new Date(e.createdAt),
});
});
})
.catch((e) => {
messageError($q, e);
})
.finally(() => {
hideLoader();
});
};
/**
* validate input ใน dialog
*/
const validateData = async () => {
checkValidate.value = true;
await myForm.value.validate().then((result: boolean) => {
if (result == false) {
checkValidate.value = false;
}
});
};
/**
* class ดรปแบบแสดงระหวางขอมลทแกไขหรอแสดงเฉยๆ
* @param val อม input สำหรบแกไขหรอไม
*/
const getClass = (val: boolean) => {
return {
"full-width inputgreen cursor-pointer": val,
"full-width cursor-pointer": !val,
};
};
</script>

View file

@ -0,0 +1,826 @@
<!-- card นทกวนทไมไดบเงนเดอนหรอไดบเงนเดอนไมเตมหรอวนทไดปฏหนาทอยในเขตทไดประดาศใชกฏอยการศ -->
<template>
<q-card flat bordered class="col-12 q-px-lg q-py-md">
<q-form ref="myForm">
<ProfileTable
:rows="rows"
:columns="columns"
:filter="filter"
:visible-columns="visibleColumns"
v-model:inputfilter="filter"
v-model:inputvisible="visibleColumns"
:add="clickAdd"
name="วันที่มิได้ปฏิบัติหน้าที่อยู่ในเขตที่ได้มีประกาศใช้กฎอัยการศึก"
icon="mdi-calendar-remove"
:statusEdit="statusEdit"
>
<template #columns="props">
<q-tr :props="props">
<q-td
v-for="col in props.cols"
:key="col.name"
:props="props"
@click="selectData(props)"
class="cursor-pointer"
>
<div
v-if="col.name == 'date' || col.name == 'refCommandDate'"
class="table_ellipsis"
>
{{ col.value == null ? null : date2Thai(col.value) }}
</div>
<div v-else class="table_ellipsis">
{{ col.value }}
</div>
</q-td>
<q-td auto-width>
<q-btn
color="info"
flat
dense
round
size="14px"
icon="mdi-history"
@click="clickHistory(props.row)"
/>
</q-td>
</q-tr>
</template>
</ProfileTable>
</q-form>
</q-card>
<!-- popup Edit window-->
<q-dialog v-model="modal" persistent>
<q-card style="width: 600px">
<q-form ref="myForm">
<DialogHeader
tittle="วันที่มิได้ปฏิบัติหน้าที่อยู่ในเขตที่ได้มีประกาศใช้กฎอัยการศึก"
:close="clickClose"
/>
<q-separator />
<q-card-section class="q-p-sm">
<div
class="row col-12 items-center q-col-gutter-x-xs q-col-gutter-y-xs"
>
<div class="col-xs-6 col-sm-6 col-md-6">
<datepicker
menu-class-name="modalfix"
:readonly="!edit"
v-model="date"
:locale="'th'"
autoApply
:enableTimePicker="false"
@update:modelValue="clickEditRow"
week-start="0"
>
<template #year="{ year }">{{ year + 543 }}</template>
<template #year-overlay-value="{ value }">{{
parseInt(value + 543)
}}</template>
<template #trigger>
<q-input
:class="getClass(edit)"
:outlined="edit"
dense
lazy-rules
:borderless="!edit"
:model-value="date2Thai(date)"
:rules="[(val) => !!val || `${'กรุณาเลือกวัน เดือน ปี'}`]"
hide-bottom-space
:label="`${'วัน เดือน ปี'}`"
>
<template v-slot:prepend>
<q-icon
name="event"
class="cursor-pointer"
:style="
edit
? 'color: var(--q-primary)'
: 'color: var(--q-grey)'
"
>
</q-icon>
</template>
</q-input>
</template>
</datepicker>
</div>
<div class="col-6">
<q-input
:class="getClass(edit)"
:outlined="edit"
dense
autogrow
lazy-rules
:readonly="!edit"
:borderless="!edit"
v-model="reference"
:rules="[(val) => !!val || `${'กรุณากรอกเอกสารอ้างอิง'}`]"
hide-bottom-space
:label="`${'เอกสารอ้างอิง'}`"
@update:modelValue="clickEditRow"
/>
</div>
<div class="col-12">
<q-input
:class="getClass(edit)"
:outlined="edit"
dense
autogrow
lazy-rules
:readonly="!edit"
:borderless="!edit"
v-model="detail"
:rules="[(val) => !!val || `${'กรุณากรอกรายละเอียด'}`]"
hide-bottom-space
:label="`${'รายละเอียด'}`"
@update:modelValue="clickEditRow"
/>
</div>
<div class="col-xs-6 col-sm-6 col-md-6">
<q-input
:class="getClass(edit)"
:outlined="edit"
dense
lazy-rules
:readonly="!edit"
:borderless="!edit"
v-model="refCommandNo"
hide-bottom-space
:label="`${'เลขที่คำสั่ง'}`"
@update:modelValue="clickEditRow"
>
<template v-slot:append>
<q-icon
name="mdi-file"
class="cursor-pointer"
@click="resetFilter"
/>
</template>
</q-input>
</div>
<div class="col-xs-6 col-sm-6 col-md-6">
<datepicker
menu-class-name="modalfix"
:readonly="!edit"
v-model="refCommandDate"
:locale="'th'"
autoApply
:enableTimePicker="false"
@update:modelValue="clickEditRow"
week-start="0"
>
<template #year="{ year }">{{ year + 543 }}</template>
<template #year-overlay-value="{ value }">{{
parseInt(value + 543)
}}</template>
<template #trigger>
<q-input
:class="getClass(edit)"
:outlined="edit"
dense
lazy-rules
:borderless="!edit"
:model-value="
refCommandDate == null ? null : date2Thai(refCommandDate)
"
hide-bottom-space
:label="`${'เอกสารอ้างอิง (ลงวันที่)'}`"
>
<template v-slot:prepend>
<q-icon
name="event"
class="cursor-pointer"
:style="
edit
? 'color: var(--q-primary)'
: 'color: var(--q-grey)'
"
>
</q-icon>
</template>
</q-input>
</template>
</datepicker>
</div>
</div>
</q-card-section>
<q-separator />
<DialogFooter
:cancel="clickCancel"
:edit="clickEdit"
:save="clickSave"
:validate="validateData"
:clickNext="clickNext"
:clickPrevious="clickPrevious"
:clickDelete="clickDelete"
v-model:editvisible="edit"
v-model:next="next"
v-model:previous="previous"
v-model:modalEdit="modalEdit"
/>
</q-form>
</q-card>
</q-dialog>
<HistoryTable
:rows="rowsHistory"
:columns="columnsHistory"
:filter="filterHistory"
:visible-columns="visibleColumnsHistory"
v-model:modal="modalHistory"
v-model:inputfilter="filterHistory"
v-model:inputvisible="visibleColumnsHistory"
v-model:tittle="tittleHistory"
>
<template #columns="props">
<q-tr :props="props">
<q-td v-for="col in props.cols" :key="col.name" :props="props">
<div
v-if="
col.name == 'date' ||
col.name == 'createdAt' ||
col.name == 'refCommandDate'
"
class="table_ellipsis"
>
{{ col.value == null ? null : date2Thai(col.value) }}
</div>
<div v-else class="table_ellipsis">
{{ col.value }}
</div>
</q-td>
</q-tr>
</template>
</HistoryTable>
</template>
<script setup lang="ts">
import { onMounted, ref, watch } from "vue";
import { useRoute } from "vue-router";
import { useComponentProfileDataStore } from "@/components/information/store/store";
import { useCounterMixin } from "@/stores/mixin";
import ProfileTable from "@/components/information/Table.vue";
import DialogHeader from "@/components/information/DialogHeader.vue";
import DialogFooter from "@/components/information/DialogFooter.vue";
import { useQuasar } from "quasar";
import type {
RequestItemsObject,
DataProps,
} from "@/components/information/interface/request/Record";
import type { ResponseObject } from "@/components/information/interface/response/Record";
import HistoryTable from "@/components/TableHistory.vue";
import http from "@/plugins/http";
import config from "@/app.config";
import type { QTableProps } from "quasar";
const props = defineProps({
statusEdit: {
type: Boolean,
required: true,
},
});
const $q = useQuasar();
const store = useComponentProfileDataStore();
const { profileData, changeProfileColumns } = store;
const mixin = useCounterMixin();
const { date2Thai, success, dateToISO, messageError, showLoader, hideLoader } =
mixin;
const route = useRoute();
const id = ref<string>("");
const date = ref<Date>(new Date());
const detail = ref<string>();
const reference = ref<string>();
const refCommandNo = ref<string>();
const refCommandDate = ref<Date | null>(new Date());
const myForm = ref<any>(); //form data input
const edit = ref<boolean>(false); // dialog
const modal = ref<boolean>(false); //modal add detail
const modalEdit = ref<boolean>(false); //modal
const rawItem = ref<RequestItemsObject>(); // row
const rowIndex = ref<number>(0); //index row
const previous = ref<boolean>(); //
const next = ref<boolean>(); //
const editRow = ref<boolean>(false); //
const rowsHistory = ref<RequestItemsObject[]>([]); //select data history
const tittleHistory = ref<string>(
"ประวัติแก้ไขวันที่มิได้ปฏิบัติหน้าที่อยู่ในเขตที่ได้มีประกาศใช้กฎอัยการศึก"
);
const filterHistory = ref<string>(""); //search data table history
const modalHistory = ref<boolean>(false); //modal
const profileId = ref<string>(
route.params.id ? route.params.id.toString() : ""
);
const checkValidate = ref<boolean>(false); //validate data
const rows = ref<RequestItemsObject[]>([]);
const filter = ref<string>(""); //search data table
const visibleColumns = ref<String[]>([]);
profileData.record.columns.length == 0
? (visibleColumns.value = [
"date",
"detail",
"reference",
"refCommandNo",
"refCommandDate",
])
: (visibleColumns.value = profileData.record.columns);
const columns = ref<QTableProps["columns"]>([
{
name: "date",
align: "left",
label: "วัน เดือน ปี",
sortable: true,
field: "date",
headerStyle: "font-size: 14px",
style: "font-size: 14px",
sort: (a: string, b: string) =>
a.localeCompare(b, undefined, { numeric: true, sensitivity: "base" }),
},
{
name: "reference",
align: "left",
label: "เอกสารอ้างอิง",
sortable: true,
field: "reference",
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",
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",
sort: (a: string, b: string) =>
a.localeCompare(b, undefined, { numeric: true, sensitivity: "base" }),
},
{
name: "reference",
align: "left",
label: "เอกสารอ้างอิง",
sortable: true,
field: "reference",
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",
sort: (a: string, b: string) =>
a.localeCompare(b, undefined, { numeric: true, sensitivity: "base" }),
},
{
name: "createdFullName",
align: "left",
label: "ผู้ดำเนินการ",
sortable: true,
field: "createdFullName",
headerStyle: "font-size: 14px",
style: "font-size: 14px",
sort: (a: string, b: string) =>
a.localeCompare(b, undefined, { numeric: true, sensitivity: "base" }),
},
{
name: "createdAt",
align: "left",
label: "วันที่แก้ไข",
sortable: true,
field: "createdAt",
headerStyle: "font-size: 14px",
style: "font-size: 14px",
sort: (a: string, b: string) =>
a.localeCompare(b, undefined, { numeric: true, sensitivity: "base" }),
},
]);
const visibleColumnsHistory = ref<String[]>([
"date",
"detail",
"reference",
"refCommandNo",
"refCommandDate",
"createdFullName",
"createdAt",
]);
watch(visibleColumns, async (count: String[], prevCount: String[]) => {
await changeProfileColumns("record", count);
});
onMounted(async () => {
await fetchData();
});
const fetchData = async () => {
if (profileId.value != "") {
showLoader();
await http
.get(config.API.profileNopaidId(profileId.value))
.then((res) => {
let data = res.data.result;
rows.value = [];
data.map((e: ResponseObject) => {
rows.value.push({
id: e.id,
date: new Date(e.date),
detail: e.detail,
reference: e.reference,
refCommandNo: e.refCommandNo,
refCommandDate:
e.refCommandDate == null ? null : new Date(e.refCommandDate),
createdFullName: e.createdFullName,
createdAt: new Date(e.createdAt),
});
});
})
.catch((e) => {
messageError($q, e);
})
.finally(() => {
hideLoader();
});
}
};
/**
* กดดอมลกอนหน
*/
const clickPrevious = async () => {
edit.value = false;
rowIndex.value -= 1;
await getData();
await checkRowPage();
};
/**
* กดดอมลตอไป
*/
const clickNext = async () => {
edit.value = false;
rowIndex.value += 1;
await getData();
await checkRowPage();
};
/**
* กดดอมลตอไป
*/
const getData = () => {
const row = rows.value[rowIndex.value];
date.value = row.date;
detail.value = row.detail;
reference.value = row.reference;
refCommandNo.value = row.refCommandNo;
refCommandDate.value = row.refCommandDate;
id.value = row.id;
};
/**
* เชคปมดอม อน อไป าตองแสดงไหม
*/
const checkRowPage = () => {
editRow.value = false;
next.value = true;
previous.value = true;
if (rowIndex.value + 1 >= rows.value.length) {
next.value = false;
}
if (rowIndex.value - 1 < 0) {
previous.value = false;
}
};
/**
* กดปมแกไขใน dialog
*/
const clickEdit = () => {
editRow.value = false;
next.value = false;
previous.value = false;
};
/**
* กดปมเพมดานบน table
*/
const clickAdd = async () => {
editRow.value = false;
await addData();
};
/**
* กดบนทกใน dialog
*/
const clickSave = async () => {
myForm.value.validate().then(async (result: boolean) => {
if (result) {
if (modalEdit.value) {
await editData();
} else {
await saveData();
}
}
});
};
/**
* นทกเพมขอม
*/
const saveData = async () => {
if (profileId.value) {
showLoader();
await http
.post(config.API.profileNopaidId(profileId.value), {
id: id.value,
date: dateToISO(date.value),
detail: detail.value,
reference: reference.value,
refCommandNo: refCommandNo.value,
refCommandDate:
refCommandDate.value == null ? null : dateToISO(refCommandDate.value),
})
.then((res) => {
success($q, "บันทึกข้อมูลสำเร็จ");
modal.value = false;
})
.catch((e) => {
messageError($q, e);
})
.finally(async () => {
await fetchData();
});
}
};
/**
* นทกแกไขขอม
*/
const editData = async () => {
showLoader();
await http
.put(config.API.profileNopaidId(id.value), {
id: id.value,
date: dateToISO(date.value),
detail: detail.value,
reference: reference.value,
refCommandNo: refCommandNo.value,
refCommandDate:
refCommandDate.value == null ? null : dateToISO(refCommandDate.value),
})
.then((res) => {
success($q, "บันทึกข้อมูลสำเร็จ");
modal.value = false;
})
.catch((e) => {
messageError($q, e);
})
.finally(async () => {
await fetchData();
});
};
/**
* ลบลบขอม
*/
const clickDelete = async () => {
$q.dialog({
title: `ลบข้อมูล`,
message: `ต้องการทำการลบข้อมูลนี้ใช่หรือไม่?`,
cancel: "ยกเลิก",
ok: "ยืนยัน",
persistent: true,
})
.onOk(async () => {
showLoader();
await http
.delete(config.API.profileNopaidId(id.value))
.then((res) => {
success($q, "ลบข้อมูลสำเร็จ");
modal.value = false;
})
.catch((e) => {
messageError($q, e);
})
.finally(async () => {
await fetchData();
});
})
.onCancel(async () => {
await fetchData();
});
};
/**
* กดป dialog
*/
const clickClose = async () => {
if (editRow.value == true) {
$q.dialog({
title: `ข้อมูลมีการแก้ไข`,
message: `ยืนยันที่จะปิดโดยไม่บันทึกใช่หรือไม่?`,
cancel: "ยกเลิก",
ok: "ยืนยัน",
persistent: true,
}).onOk(async () => {
modal.value = false;
next.value = false;
previous.value = false;
});
} else {
modal.value = false;
next.value = false;
previous.value = false;
}
};
/**
* กดเลอกขอมลทจะแกไข
* @param props props ใน row เลอก
*/
const selectData = async (props: DataProps) => {
modalEdit.value = true;
modal.value = true;
edit.value = false;
rawItem.value = props.row;
rowIndex.value = props.rowIndex;
date.value = props.row.date;
detail.value = props.row.detail;
reference.value = props.row.reference;
refCommandNo.value = props.row.refCommandNo;
refCommandDate.value = props.row.refCommandDate;
id.value = props.row.id;
await checkRowPage();
};
/**
* กดปมเพมบน table
*/
const addData = () => {
modalEdit.value = false;
modal.value = true;
edit.value = true;
date.value = new Date();
detail.value = "";
reference.value = "";
refCommandNo.value = "";
refCommandDate.value = null;
};
/**
* งกนปมยกเลกการแกไขขอม
*/
const clickCancel = async () => {
if (editRow.value == true) {
$q.dialog({
title: `ข้อมูลมีการแก้ไข`,
message: `ยืนยันยกเลิกการแก้ไขใช่หรือไม่?`,
cancel: "ยกเลิก",
ok: "ยืนยัน",
persistent: true,
}).onOk(async () => {
edit.value = false;
await checkRowPage();
await getData();
});
} else {
edit.value = false;
await checkRowPage();
}
};
/**
* เชความการแกไขขอม
*/
const clickEditRow = () => {
editRow.value = true;
};
/**
* งชนดอมลประวแกไขขอมลทเลอก
* @param row อม row ประวการแกไข
*/
const clickHistory = async (row: RequestItemsObject) => {
modalHistory.value = true;
showLoader();
await http
.get(config.API.profileNopaidHisId(row.id))
.then((res) => {
let data = res.data.result;
rowsHistory.value = [];
data.map((e: ResponseObject) => {
rowsHistory.value.push({
id: e.id,
date: new Date(e.date),
detail: e.detail,
reference: e.reference,
refCommandNo: e.refCommandNo,
refCommandDate:
e.refCommandDate == null ? null : new Date(e.refCommandDate),
createdFullName: e.createdFullName,
createdAt: new Date(e.createdAt),
});
});
})
.catch((e) => {
messageError($q, e);
})
.finally(() => {
hideLoader();
});
};
/**
* validate input ใน dialog
*/
const validateData = async () => {
checkValidate.value = true;
await myForm.value.validate().then((result: boolean) => {
if (result == false) {
checkValidate.value = false;
}
});
};
/**
* class ดรปแบบแสดงระหวางขอมลทแกไขหรอแสดงเฉยๆ
* @param val อม input สำหรบแกไขหรอไม
*/
const getClass = (val: boolean) => {
return {
"full-width inputgreen cursor-pointer": val,
"full-width cursor-pointer": !val,
};
};
const resetFilter = () => {};
</script>
<style lang="scss">
.modalfix {
position: fixed !important;
}
</style>

File diff suppressed because it is too large Load diff

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,215 @@
<template>
<div class="q-pb-sm row">
<HeaderTop
v-model:edit="editBtn"
:header="name"
:icon="icon"
:add="checkAdd"
:addleave="checkAddLeave"
:addData="true"
:history="false"
:disable="statusEdit"
:iconAdd="iconAdd"
/>
<q-space />
<div class="items-center" style="display: flex" v-if="headerShow">
<!-- นหาขอความใน table -->
<q-input
standout
dense
:model-value="inputfilter"
ref="filterRef"
@update:model-value="updateInput"
outlined
debounce="300"
placeholder="ค้นหา"
style="max-width: 200px"
class="q-ml-sm"
>
<template v-slot:append>
<q-icon v-if="inputfilter == ''" name="search" />
<q-icon
v-if="inputfilter !== ''"
name="clear"
class="cursor-pointer"
@click="resetFilter"
/>
</template>
</q-input>
<!-- แสดงคอลมนใน table -->
<q-select
:model-value="inputvisible"
@update:model-value="updateVisible"
:display-value="$q.lang.table.columns"
multiple
outlined
dense
:options="attrs.columns"
options-dense
option-value="name"
map-options
emit-value
style="min-width: 150px"
class="gt-xs q-ml-sm"
/>
</div>
</div>
<q-table
ref="table"
flat
bordered
class="custom-header-table"
v-bind="attrs"
virtual-scroll
:virtual-scroll-sticky-size-start="48"
dense
:pagination-label="paginationLabel"
:pagination="initialPagination"
:rows-per-page-options="[0]"
>
<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 #body="props">
<slot v-bind="props" name="columns"></slot>
</template>
</q-table>
</template>
<script setup lang="ts">
import { ref, useAttrs } from "vue";
import HeaderTop from "@/components/information/top.vue";
import type { Pagination } from "@/components/information/interface/store/main";
const attrs = ref<any>(useAttrs());
const table = ref<any>(null);
const filterRef = ref<any>(null);
const editBtn = ref<boolean>(false);
const initialPagination = ref<Pagination>({
rowsPerPage: 0,
});
const props = defineProps({
inputfilter: String,
name: String,
icon: String,
iconAdd: {
type: String,
default: null,
},
inputvisible: Array,
editvisible: Boolean,
headerShow: {
type: Boolean,
default: true,
},
statusEdit: {
type: Boolean,
required: true,
},
edit: {
type: Function,
default: () => console.log("not function"),
},
add: {
type: Function,
default: () => console.log("not function"),
},
addleave: {
type: Function,
default: () => console.log("not function"),
},
cancel: {
type: Function,
default: () => console.log("not function"),
},
validate: {
type: Function,
default: () => console.log("not function"),
},
});
const emit = defineEmits([
"update:inputfilter",
"update:inputvisible",
"update:editvisible",
]);
const updateEdit = (value: Boolean) => {
emit("update:editvisible", value);
};
const updateInput = (value: string | number | null) => {
emit("update:inputfilter", value);
};
const updateVisible = (value: []) => {
emit("update:inputvisible", value);
};
const paginationLabel = (start: string, end: string, total: string) => {
return start + "-" + end + " ใน " + total;
};
const checkAddLeave = () => {
props.addleave();
};
const checkAdd = () => {
props.add();
};
const edit = async () => {
updateEdit(!props.editvisible);
props.edit();
};
const cancel = async () => {
updateEdit(!props.editvisible);
props.cancel();
};
const resetFilter = () => {
// reset X
emit("update:inputfilter", "");
filterRef.value.focus();
};
</script>
<style lang="scss">
.icon-color {
color: #4154b3;
}
.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;
}
}
</style>

View file

@ -0,0 +1,694 @@
<template>
<q-table
ref="table"
flat
:class="
$q.screen.gt.xs
? 'q-px-md custom-header-table2'
: 'q-px-sm custom-header-table2 custom-table-height'
"
v-bind="attrs"
dense
virtual-scroll
:virtual-scroll-sticky-size-start="48"
:pagination-label="paginationLabel"
:pagination="initialPagination"
:rows-per-page-options="[0]"
>
<template v-slot:top="props">
<div class="q-py-sm col-12 row">
<q-space />
<div class="items-center row col-12 q-gutter-x-sm">
<q-btn
size="13px"
color="grey-7"
dense
flat
round
@click="onTab"
class="shadow-1"
icon="chevron_right"
v-if="!isTab"
>
<q-tooltip>เป</q-tooltip>
</q-btn>
<q-btn
size="12px"
flat
round
color="blue"
@click="clickSearchPanel"
icon="mdi-filter-variant"
v-show="searchPanel == false"
>
<q-tooltip>นหาขนส</q-tooltip>
</q-btn>
<q-space />
<q-input
v-show="searchPanel == false"
standout
dense
:model-value="inputfilter"
ref="filterRef"
@update:model-value="updateInput"
outlined
debounce="300"
placeholder="ค้นหา"
style="max-width: 200px"
>
<template v-slot:append>
<q-icon v-if="inputfilter == ''" name="search" />
<q-icon
v-if="inputfilter !== ''"
name="clear"
class="cursor-pointer"
@click="resetFilter"
/>
</template>
</q-input>
<!-- แสดงคอลมนใน table -->
<q-select
:model-value="inputvisible"
@update:model-value="updateVisible"
:display-value="$q.lang.table.columns"
multiple
outlined
dense
:options="attrs.columns"
options-dense
option-value="name"
map-options
emit-value
style="min-width: 150px"
class="gt-xs q-ml-sm"
/>
</div>
</div>
<div class="items-center">
<q-slide-transition
v-show="searchPanel"
class="q-mb-sm"
:duration="150"
>
<div class="my-content">
<div
class="row q-pa-xs items-center bg-blue-1"
style="border-radius: 4px 4px 0px 0px"
>
<q-icon
size="20px"
color="blue-9"
name="mdi-filter-variant"
class="q-mx-sm"
/>
<div class="text-blue-9 text-subtitle2 text-weight-medium">
<span>นหาขอมลทะเบยนประว</span>
</div>
<q-space />
<q-btn
color="blue-9"
icon="mdi-close"
size="12px"
flat
round
dense
@click="clickSearchPanel"
/>
</div>
<q-separator color="blue-1" />
<div class="dialog-card-contain">
<q-card-section class="q-pa-md">
<div class="row col-12 q-col-gutter-sm">
<div
:class="
$q.screen.lt.md
? ' row col-12 q-col-gutter-xs'
: 'no-wrap row col-12 q-col-gutter-xs'
"
>
<selector
class="col-3"
hide-bottom-space
:rules="[(val:string) => !!val || `${'กรุณาเลือก ประเภท'}`]"
outlined
dense
lazy-rules
:model-value="employeeClass"
emit-value
map-options
:options="employeeClassOps"
option-label="name"
option-value="id"
:label="`${'ประเภท'}`"
use-input
input-debounce="0"
@update:model-value="updateEmployeeClass"
/>
<!-- @filter="(inputValue:any,
doneFn:Function) => filterSelector(inputValue, doneFn,'employeeTypeOps'
) " -->
<q-input
class="col-3"
clearable
dense
outlined
lazy-rules
:model-value="profileId"
hide-bottom-space
label="เลขประจำตัวประชาชน"
@update:model-value="updateProfileId"
type="number"
/>
<q-input
class="col-2"
clearable
dense
outlined
lazy-rules
:model-value="fullName"
hide-bottom-space
label="ชื่อ-นามสกุล"
@update:model-value="updateFullname"
/>
<datepicker
class="col-2"
menu-class-name="modalfix"
:model-value="retireYear"
:locale="'th'"
autoApply
year-picker
:enableTimePicker="false"
@update:model-value="updateRetireYear"
clearable
>
<template #year="{ year }">{{ year + 543 }}</template>
<template #year-overlay-value="{ value }">{{
parseInt(value + 543)
}}</template>
<template #trigger>
<q-input
class="inputgreen cursor-pointer q-mb-sm"
hide-bottom-space
outlined
dense
lazy-rules
borderless
:model-value="
retireYear == null ? null : retireYear + 543
"
:label="`${'ปีเกษียณ'}`"
clearable
@clear="clearDate"
>
<!-- <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
class="col-2"
clearable
dense
outlined
lazy-rules
:model-value="govAge"
hide-bottom-space
label="อายุราชการ(ปี)"
type="number"
@update:model-value="updateGovAge"
/>
</div>
<div
:class="
$q.screen.lt.md
? ' row col-12 q-col-gutter-xs'
: 'no-wrap row col-12 q-col-gutter-xs'
"
>
<q-input
v-if="employeeClass == 'officer'"
clearable
dense
outlined
lazy-rules
:model-value="positionPath"
hide-bottom-space
label="ตำแหน่งในสายงาน"
@update:model-value="updatePositionPath"
class="col-3"
/>
<q-input
v-if="employeeClass == 'officer'"
clearable
dense
outlined
lazy-rules
:model-value="positionLevel"
hide-bottom-space
label="ระดับ"
@update:model-value="updatePositionLevel"
class="col-3"
/>
<q-input
v-if="employeeClass == 'officer'"
clearable
dense
outlined
lazy-rules
:model-value="positionExecutive"
hide-bottom-space
label="ตำแหน่งทางการบริหาร"
@update:model-value="updatePositionExecutive"
class="col-3"
/>
<q-input
v-if="employeeClass != 'officer'"
clearable
dense
outlined
lazy-rules
:model-value="employeePosition"
hide-bottom-space
label="ตำแหน่ง"
@update:model-value="updateEmployeePosition"
class="col-3"
/>
<q-input
v-if="employeeClass != 'officer'"
clearable
dense
outlined
lazy-rules
:model-value="employeeLevel"
hide-bottom-space
label="ระดับชั้นงาน"
@update:model-value="updateEmployeeLevel"
class="col-3"
/>
<q-input
clearable
dense
outlined
lazy-rules
:model-value="posNo"
hide-bottom-space
label="ตำแหน่งเลขที่"
@update:model-value="updatePosNo"
class="col-3"
/>
</div>
<div
:class="
$q.screen.lt.md
? ' row col-12 q-col-gutter-xs'
: 'no-wrap row col-12 q-col-gutter-xs'
"
>
<datepicker
class="col-2"
menu-class-name="modalfix"
:model-value="reportYear"
:locale="'th'"
autoApply
year-picker
:enableTimePicker="false"
@update:model-value="updateReportYear"
clearable
>
<template #year="{ year }">{{ year + 543 }}</template>
<template #year-overlay-value="{ value }">{{
parseInt(value + 543)
}}</template>
<template #trigger>
<q-input
class="inputgreen cursor-pointer q-mb-sm"
hide-bottom-space
outlined
dense
lazy-rules
borderless
:model-value="
reportYear == null ? null : reportYear + 543
"
:label="`${'ปีงบประมาณ'}`"
clearable
@clear="clearReportDate"
>
<!-- <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
clearable
dense
outlined
lazy-rules
:model-value="reportNo"
hide-bottom-space
label="เลขที่คำสั่ง"
@update:model-value="updateReportNo"
class="col-3"
/>
<q-input
clearable
dense
outlined
lazy-rules
:model-value="reportType"
hide-bottom-space
label="ประเภทคำสั่ง"
@update:model-value="updateReportType"
class="col-3"
/>
</div>
<div class="col-12 row items-center">
<q-toggle
dense
:model-value="isShowRetire"
color="primary"
@update:model-value="updateIsShowRetire"
class="q-pr-md"
>
แสดงขอมลผนจากราชการ
</q-toggle>
<q-toggle
dense
:model-value="isProbation"
color="primary"
@update:model-value="updateIsProbation"
>
ทดลองปฏหนาทราชการ
</q-toggle>
<q-space />
<div>
<q-btn
dense
color="primary"
icon="mdi-magnify"
label="ค้นหา"
class="q-px-md"
@click="doSearch"
/>
</div>
</div>
<!-- <div class="col-12 row q-col-gutter-y-md">
<div class="row q-gutter-md">
<q-radio
dense
:model-value="profileType"
val="officer"
label="ข้าราชการสามัญ"
class="q-pt-sm"
@update:model-value="updateProfileType"
/>
<q-radio
dense
:model-value="profileType"
val="employee"
class="q-pt-sm"
@update:model-value="updateProfileType"
>
กจาง
</q-radio>
</div>
<q-space />
<div>
<q-btn
dense
color="primary"
icon="mdi-magnify"
label="ค้นหา"
class="q-px-md"
@click="doSearch"
/>
</div>
</div> -->
</div>
</q-card-section>
</div>
</div>
</q-slide-transition>
</div>
</template>
<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 #body="props">
<slot v-bind="props" name="columns"></slot>
</template>
</q-table>
</template>
<script setup lang="ts">
import { ref, useAttrs } from "vue";
import type {
Pagination,
DataOption,
} from "@/components/information/interface/store/main";
const attrs = ref<any>(useAttrs());
const table = ref<any>(null);
const filterRef = ref<any>(null);
const searchPanel = ref<boolean>(true);
const initialPagination = ref<Pagination>({
rowsPerPage: 0,
});
const employeeClassOps = ref<DataOption[]>([
{ id: "officer", name: "ข้าราชการ กทม.สามัญ" },
// { id: "employee", name: "()" },
{ id: "perm", name: "ลูกจ้างประจำ" },
{ id: "temp", name: "ลูกจ้างชั่วคราว" },
]);
const props = defineProps({
inputfilter: String,
inputvisible: Array,
profileId: String,
employeeClass: String,
fullName: String,
oldFullName: String,
isShowRetire: Boolean,
isProbation: Boolean,
// profileType: String,
retireYear: Number || null,
govAge: Number || null,
positionPath: String,
positionLevel: String,
positionExecutive: String,
employeePosition: String,
employeeLevel: String,
posNo: String,
reportYear: Number || null,
reportNo: String,
reportType: String,
isTab: {
type: Boolean,
default: true,
},
doSearch: {
type: Function,
default: () => console.log("not function"),
},
onExport: {
type: Function,
default: () => console.log("not function"),
},
onTab: {
type: Function,
default: () => console.log("not function"),
},
});
const emit = defineEmits([
"update:inputfilter",
"update:inputvisible",
"update:profileId",
"update:employeeClass",
"update:fullName",
"update:oldFullName",
"update:oldName",
"update:retireYear",
"update:govAge",
"update:isShowRetire",
// "update:profileType",
"update:isProbation",
"update:positionPath",
"update:positionLevel",
"update:positionExecutive",
"update:employeePosition",
"update:employeeLevel",
"update:posNo",
"update:reportYear",
"update:reportNo",
"update:reportType",
]);
const updateInput = (value: string | number | null) => {
emit("update:inputfilter", value);
};
const updateVisible = (value: []) => {
emit("update:inputvisible", value);
};
const updateProfileId = (value: string | number | null) => {
emit("update:profileId", value);
};
const updateEmployeeClass = (value: string | number | null) => {
emit("update:employeeClass", value);
};
const updateFullname = (value: string | number | null) => {
emit("update:fullName", value);
};
const updateRetireYear = (value: string | number | null) => {
emit("update:retireYear", value);
};
const updateGovAge = (value: string | number | null) => {
emit("update:govAge", value);
};
const updateIsShowRetire = (value: string | number | null) => {
emit("update:isShowRetire", value);
};
const updateIsProbation = (value: string | number | null) => {
emit("update:isProbation", value);
};
const updatePositionPath = (value: string | number | null) => {
emit("update:positionPath", value);
};
const updatePositionLevel = (value: string | number | null) => {
emit("update:positionLevel", value);
};
const updatePositionExecutive = (value: string | number | null) => {
emit("update:positionExecutive", value);
};
const updateEmployeePosition = (value: string | number | null) => {
emit("update:employeePosition", value);
};
const updateEmployeeLevel = (value: string | number | null) => {
emit("update:employeeLevel", value);
};
const updatePosNo = (value: string | number | null) => {
emit("update:posNo", value);
};
const updateReportYear = (value: string | number | null) => {
emit("update:reportYear", value);
};
const updateReportNo = (value: string | number | null) => {
emit("update:reportNo", value);
};
const updateReportType = (value: string | number | null) => {
emit("update:reportType", value);
};
// const updateProfileType = (value: string | number | null) => {
// emit("update:profileType", value);
// };
const clearDate = () => {
emit("update:retireYear", null);
};
const clearReportDate = () => {
emit("update:reportYear", null);
};
const clickSearchPanel = () => {
emit("update:retireYear", null);
emit("update:govAge", null);
emit("update:oldName", null);
emit("update:oldFullName", null);
emit("update:fullName", null);
emit("update:profileId", null);
emit("update:employeeClass", null);
searchPanel.value = !searchPanel.value;
};
const paginationLabel = (start: string, end: string, total: string) => {
return start + "-" + end + " ใน " + total;
};
const doSearch = () => {
props.doSearch();
};
const onExport = () => {
props.onExport();
};
const onTab = () => {
props.onTab();
};
const resetFilter = () => {
// reset X
emit("update:inputfilter", "");
filterRef.value.focus();
};
</script>
<style lang="scss">
.icon-color {
color: #4154b3;
}
.my-content {
background: #fff;
border: 1px solid rgba(133, 133, 133, 0.2);
border-radius: 5px;
}
.custom-table-height {
height: auto !important;
}
.custom-header-table2 {
.q-table__top {
padding: 0px !important;
}
.q-table__bottom {
border-top: none !important;
}
.q-table__middle {
border-radius: 5px;
border: 1px solid rgba(133, 133, 133, 0.2) !important;
}
.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;
}
}
</style>

View file

@ -0,0 +1,683 @@
<!-- card ความสามารถพเศษ -->
<template>
<q-card flat bordered class="col-12 q-px-lg q-py-md">
<q-form ref="myForm">
<ProfileTable
:rows="rows"
:columns="columns"
:filter="filter"
:visible-columns="visibleColumns"
v-model:inputfilter="filter"
v-model:inputvisible="visibleColumns"
:add="clickAdd"
name="ความสามารถพิเศษ"
icon="mdi-folder-star"
:statusEdit="statusEdit"
>
<template #columns="props">
<q-tr :props="props">
<q-td
v-for="col in props.cols"
:key="col.name"
:props="props"
@click="selectData(props)"
class="cursor-pointer"
>
<div class="table_ellipsis">
{{ col.value }}
</div>
</q-td>
<q-td auto-width>
<q-btn
color="info"
flat
dense
round
size="14px"
icon="mdi-history"
@click="clickHistory(props.row)"
/>
</q-td>
</q-tr>
</template>
</ProfileTable>
</q-form>
</q-card>
<!-- popup Edit window-->
<q-dialog v-model="modal" persistent>
<q-card style="width: 600px">
<q-form ref="myForm">
<DialogHeader tittle="ความสามารถพิเศษ" :close="clickClose" />
<q-separator />
<q-card-section class="q-p-sm">
<div
class="row col-12 items-center q-col-gutter-x-xs q-col-gutter-y-xs"
>
<div class="col-6">
<q-input
:class="getClass(edit)"
:outlined="edit"
dense
lazy-rules
:readonly="!edit"
autogrow
:borderless="!edit"
v-model="field"
:rules="[(val) => !!val || `${'กรุณากรอกด้าน'}`]"
hide-bottom-space
:label="`${'ด้าน'}`"
@update:modelValue="clickEditRow"
/>
</div>
<div class="col-6">
<q-input
:class="getClass(edit)"
:outlined="edit"
dense
lazy-rules
:readonly="!edit"
autogrow
:borderless="!edit"
v-model="detail"
:rules="[(val) => !!val || `${'กรุณากรอกรายละเอียด'}`]"
hide-bottom-space
:label="`${'รายละเอียด'}`"
@update:modelValue="clickEditRow"
/>
</div>
<div class="col-12">
<q-input
:class="getClass(edit)"
:outlined="edit"
dense
lazy-rules
:readonly="!edit"
autogrow
:borderless="!edit"
v-model="remark"
hide-bottom-space
:label="`${'หมายเหตุ'}`"
@update:modelValue="clickEditRow"
/>
</div>
<div class="col-12">
<q-input
:class="getClass(edit)"
:outlined="edit"
dense
lazy-rules
:readonly="!edit"
autogrow
:borderless="!edit"
v-model="reference"
:rules="[(val) => !!val || `${'กรุณากรอกเอกสารอ้างอิง'}`]"
hide-bottom-space
:label="`${'เอกสารอ้างอิง'}`"
@update:modelValue="clickEditRow"
/>
</div>
</div>
</q-card-section>
<q-separator />
<DialogFooter
:cancel="clickCancel"
:edit="clickEdit"
:save="clickSave"
:validate="validateData"
:clickNext="clickNext"
:clickPrevious="clickPrevious"
:clickDelete="clickDelete"
v-model:editvisible="edit"
v-model:next="next"
v-model:previous="previous"
v-model:modalEdit="modalEdit"
/>
</q-form>
</q-card>
</q-dialog>
<HistoryTable
:rows="rowsHistory"
:columns="columnsHistory"
:filter="filterHistory"
:visible-columns="visibleColumnsHistory"
v-model:modal="modalHistory"
v-model:inputfilter="filterHistory"
v-model:inputvisible="visibleColumnsHistory"
v-model:tittle="tittleHistory"
>
<template #columns="props">
<q-tr :props="props">
<q-td v-for="col in props.cols" :key="col.name" :props="props">
<div v-if="col.name == 'createdAt'" class="table_ellipsis">
{{ date2Thai(col.value) }}
</div>
<div v-else class="table_ellipsis">
{{ col.value }}
</div>
</q-td>
</q-tr>
</template>
</HistoryTable>
</template>
<script setup lang="ts">
import { onMounted, ref, watch } from "vue";
import { useRoute } from "vue-router";
import { useComponentProfileDataStore } from "@/components/information/store/store";
import { useCounterMixin } from "@/stores/mixin";
import ProfileTable from "@/components/information/Table.vue";
import DialogHeader from "@/components/information/DialogHeader.vue";
import DialogFooter from "@/components/information/DialogFooter.vue";
import { useQuasar } from "quasar";
import type {
RequestItemsObject,
DataProps,
} from "@/components/information/interface/request/Talent";
import type { ResponseObject } from "@/components/information/interface/response/Talent";
import HistoryTable from "@/components/TableHistory.vue";
import http from "@/plugins/http";
import config from "@/app.config";
import type { QTableProps } from "quasar";
const props = defineProps({
statusEdit: {
type: Boolean,
required: true,
},
});
const $q = useQuasar();
const store = useComponentProfileDataStore();
const { profileData, changeProfileColumns } = store;
const mixin = useCounterMixin();
const { date2Thai, success, dateToISO, messageError, showLoader, hideLoader } =
mixin;
const route = useRoute();
const id = ref<string>("");
const field = ref<string>();
const detail = ref<string>();
const remark = ref<string>();
const reference = ref<string>();
const myForm = ref<any>(); //form data input
const edit = ref<boolean>(false); // dialog
const modal = ref<boolean>(false); //modal add detail
const modalEdit = ref<boolean>(false); //modal
const rawItem = ref<RequestItemsObject>(); // row
const rowIndex = ref<number>(0); //index row
const previous = ref<boolean>(); //
const next = ref<boolean>(); //
const editRow = ref<boolean>(false); //
const rowsHistory = ref<RequestItemsObject[]>([]); //select data history
const tittleHistory = ref<string>("ประวัติแก้ไขความสามารถพิเศษ"); //
const filterHistory = ref<string>(""); //search data table history
const modalHistory = ref<boolean>(false); //modal
const checkValidate = ref<boolean>(false); //validate data
const profileId = ref<string>(
route.params.id ? route.params.id.toString() : ""
);
const rows = ref<RequestItemsObject[]>([]);
const filter = ref<string>(""); //search data table
const visibleColumns = ref<String[]>([]);
profileData.talent.columns.length == 0
? (visibleColumns.value = ["field", "detail", "remark", "reference"])
: (visibleColumns.value = profileData.talent.columns);
const columns = ref<QTableProps["columns"]>([
{
name: "field",
align: "left",
label: "ด้าน",
sortable: true,
field: "field",
headerStyle: "font-size: 14px; width: 50px;",
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: "remark",
align: "left",
label: "หมายเหตุ",
sortable: true,
field: "remark",
headerStyle: "font-size: 14px",
style: "font-size: 14px",
sort: (a: string, b: string) =>
a.localeCompare(b, undefined, { numeric: true, sensitivity: "base" }),
},
{
name: "reference",
align: "left",
label: "เอกสารอ้างอิง",
sortable: true,
field: "reference",
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: "field",
align: "left",
label: "ด้าน",
sortable: true,
field: "field",
headerStyle: "font-size: 14px; width: 50px;",
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: "remark",
align: "left",
label: "หมายเหตุ",
sortable: true,
field: "remark",
headerStyle: "font-size: 14px",
style: "font-size: 14px",
sort: (a: string, b: string) =>
a.localeCompare(b, undefined, { numeric: true, sensitivity: "base" }),
},
{
name: "reference",
align: "left",
label: "เอกสารอ้างอิง",
sortable: true,
field: "reference",
headerStyle: "font-size: 14px",
style: "font-size: 14px",
sort: (a: string, b: string) =>
a.localeCompare(b, undefined, { numeric: true, sensitivity: "base" }),
},
{
name: "createdFullName",
align: "left",
label: "ผู้ดำเนินการ",
sortable: true,
field: "createdFullName",
headerStyle: "font-size: 14px",
style: "font-size: 14px",
sort: (a: string, b: string) =>
a.localeCompare(b, undefined, { numeric: true, sensitivity: "base" }),
},
{
name: "createdAt",
align: "left",
label: "วันที่แก้ไข",
sortable: true,
field: "createdAt",
headerStyle: "font-size: 14px",
style: "font-size: 14px",
sort: (a: string, b: string) =>
a.localeCompare(b, undefined, { numeric: true, sensitivity: "base" }),
},
]);
const visibleColumnsHistory = ref<String[]>([
"field",
"detail",
"remark",
"reference",
"createdFullName",
"createdAt",
]);
watch(visibleColumns, async (count: String[], prevCount: String[]) => {
await changeProfileColumns("talent", count);
});
onMounted(async () => {
await fetchData();
});
const fetchData = async () => {
if (profileId.value) {
showLoader();
await http
.get(config.API.profileAbiliId(profileId.value))
.then((res) => {
let data = res.data.result;
rows.value = [];
data.map((e: ResponseObject) => {
rows.value.push({
id: e.id,
field: e.field,
detail: e.detail,
remark: e.remark,
reference: e.reference,
createdFullName: e.createdFullName,
createdAt: new Date(e.createdAt),
});
});
})
.catch((e) => {
messageError($q, e);
})
.finally(() => {
hideLoader();
});
}
};
/**
* กดดอมลกอนหน
*/
const clickPrevious = async () => {
edit.value = false;
rowIndex.value -= 1;
await getData();
await checkRowPage();
};
/**
* กดดอมลตอไป
*/
const clickNext = async () => {
edit.value = false;
rowIndex.value += 1;
await getData();
await checkRowPage();
};
/**
* กดดอมลตอไป
*/
const getData = () => {
const row = rows.value[rowIndex.value];
field.value = row.field;
detail.value = row.detail;
remark.value = row.remark;
reference.value = row.reference;
id.value = row.id;
};
/**
* เชคปมดอม อน อไป าตองแสดงไหม
*/
const checkRowPage = () => {
editRow.value = false;
next.value = true;
previous.value = true;
if (rowIndex.value + 1 >= rows.value.length) {
next.value = false;
}
if (rowIndex.value - 1 < 0) {
previous.value = false;
}
};
/**
* กดปมแกไขใน dialog
*/
const clickEdit = () => {
editRow.value = false;
next.value = false;
previous.value = false;
};
/**
* กดปมเพมดานบน table
*/
const clickAdd = async () => {
editRow.value = false;
await addData();
};
/**
* กดบนทกใน dialog
*/
const clickSave = async () => {
myForm.value.validate().then(async (result: boolean) => {
if (result) {
if (modalEdit.value) {
await editData();
} else {
await saveData();
}
}
});
};
/**
* นทกเพมขอม
*/
const saveData = async () => {
if (profileId.value) {
showLoader();
await http
.post(config.API.profileAbiliId(profileId.value), {
id: id.value,
field: field.value,
detail: detail.value,
remark: remark.value,
reference: reference.value,
})
.then((res) => {
success($q, "บันทึกข้อมูลสำเร็จ");
modal.value = false;
})
.catch((e) => {
messageError($q, e);
})
.finally(async () => {
await fetchData();
});
}
};
/**
* นทกแกไขขอม
*/
const editData = async () => {
showLoader();
await http
.put(config.API.profileAbiliId(id.value), {
id: id.value,
field: field.value,
detail: detail.value,
remark: remark.value,
reference: reference.value,
})
.then((res) => {
success($q, "บันทึกข้อมูลสำเร็จ");
modal.value = false;
})
.catch((e) => {
messageError($q, e);
})
.finally(async () => {
await fetchData();
});
};
/**
* ลบลบขอม
*/
const clickDelete = async () => {
$q.dialog({
title: `ลบข้อมูล`,
message: `ต้องการทำการลบข้อมูลนี้ใช่หรือไม่?`,
cancel: "ยกเลิก",
ok: "ยืนยัน",
persistent: true,
})
.onOk(async () => {
showLoader();
await http
.delete(config.API.profileAbiliId(id.value))
.then((res) => {
success($q, "ลบข้อมูลสำเร็จ");
modal.value = false;
})
.catch((e) => {
messageError($q, e);
})
.finally(async () => {
await fetchData();
});
})
.onCancel(async () => {
await fetchData();
});
};
/**
* กดป dialog
*/
const clickClose = async () => {
if (editRow.value == true) {
$q.dialog({
title: `ข้อมูลมีการแก้ไข`,
message: `ยืนยันที่จะปิดโดยไม่บันทึกใช่หรือไม่?`,
cancel: "ยกเลิก",
ok: "ยืนยัน",
persistent: true,
}).onOk(async () => {
modal.value = false;
next.value = false;
previous.value = false;
});
} else {
modal.value = false;
next.value = false;
previous.value = false;
}
};
/**
* กดเลอกขอมลทจะแกไข
* @param props props ใน row เลอก
*/
const selectData = async (props: DataProps) => {
modalEdit.value = true;
modal.value = true;
edit.value = false;
rawItem.value = props.row;
rowIndex.value = props.rowIndex;
field.value = props.row.field;
detail.value = props.row.detail;
remark.value = props.row.remark;
reference.value = props.row.reference;
id.value = props.row.id;
await checkRowPage();
};
/**
* กดปมเพมบน table
*/
const addData = () => {
modalEdit.value = false;
modal.value = true;
edit.value = true;
field.value = "";
detail.value = "";
remark.value = "";
reference.value = "";
};
/**
* งกนปมยกเลกการแกไขขอม
*/
const clickCancel = async () => {
if (editRow.value == true) {
$q.dialog({
title: `ข้อมูลมีการแก้ไข`,
message: `ยืนยันยกเลิกการแก้ไขใช่หรือไม่?`,
cancel: "ยกเลิก",
ok: "ยืนยัน",
persistent: true,
}).onOk(async () => {
edit.value = false;
await checkRowPage();
await getData();
});
} else {
edit.value = false;
await checkRowPage();
}
};
/**
* เชความการแกไขขอม
*/
const clickEditRow = () => {
editRow.value = true;
};
/**
* งชนดอมลประวแกไขขอมลทเลอก
* @param row อม row ประวการแกไข
*/
const clickHistory = async (row: RequestItemsObject) => {
modalHistory.value = true;
showLoader();
await http
.get(config.API.profileAbiliHisId(row.id))
.then((res) => {
let data = res.data.result;
rowsHistory.value = [];
data.map((e: ResponseObject) => {
rowsHistory.value.push({
id: e.id,
field: e.field,
detail: e.detail,
remark: e.remark,
reference: e.reference,
createdFullName: e.createdFullName,
createdAt: new Date(e.createdAt),
});
});
})
.catch((e) => {
messageError($q, e);
})
.finally(() => {
hideLoader();
});
};
/**
* validate input ใน dialog
*/
const validateData = async () => {
checkValidate.value = true;
await myForm.value.validate().then((result: boolean) => {
if (result == false) {
checkValidate.value = false;
}
});
};
/**
* class ดรปแบบแสดงระหวางขอมลทแกไขหรอแสดงเฉยๆ
* @param val อม input สำหรบแกไขหรอไม
*/
const getClass = (val: boolean) => {
return {
"full-width inputgreen cursor-pointer": val,
"full-width cursor-pointer": !val,
};
};
</script>

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,907 @@
<!-- card ปฏราชการพเศษ -->
<template>
<q-card flat bordered class="col-12 q-px-lg q-py-md">
<q-form ref="myForm">
<ProfileTable
:rows="rows"
:columns="columns"
:filter="filter"
:visible-columns="visibleColumns"
v-model:inputfilter="filter"
v-model:inputvisible="visibleColumns"
:add="clickAdd"
name="ปฏิบัติราชการพิเศษ"
icon="mdi-bookmark"
:statusEdit="statusEdit"
>
<template #columns="props">
<q-tr :props="props">
<q-td
v-for="col in props.cols"
:key="col.name"
:props="props"
@click="selectData(props)"
class="cursor-pointer"
>
<div
v-if="
col.name == 'dateStart' ||
col.name == 'dateEnd' ||
col.name == 'refCommandDate'
"
class="table_ellipsis"
>
{{ col.value == null ? null : date2Thai(col.value) }}
</div>
<div v-else class="table_ellipsis">
{{ col.value }}
</div>
</q-td>
<q-td auto-width>
<q-btn
color="info"
flat
dense
round
size="14px"
icon="mdi-history"
@click="clickHistory(props.row)"
/>
</q-td>
</q-tr>
</template>
</ProfileTable>
</q-form>
</q-card>
<!-- popup Edit window-->
<q-dialog v-model="modal" persistent>
<q-card style="width: 600px">
<q-form ref="myForm">
<DialogHeader tittle="ปฏิบัติราชการพิเศษ" :close="clickClose" />
<q-separator />
<q-card-section class="q-p-sm">
<div
class="row col-12 items-center q-col-gutter-x-xs q-col-gutter-y-xs"
>
<div class="col-xs-6 col-sm-6 col-md-6">
<datepicker
menu-class-name="modalfix"
:readonly="!edit"
v-model="dateStart"
:locale="'th'"
autoApply
:enableTimePicker="false"
@update:modelValue="clickEditRow"
week-start="0"
>
<template #year="{ year }">{{ year + 543 }}</template>
<template #year-overlay-value="{ value }">{{
parseInt(value + 543)
}}</template>
<template #trigger>
<q-input
:class="getClass(edit)"
:outlined="edit"
dense
lazy-rules
:borderless="!edit"
:model-value="date2Thai(dateStart)"
:rules="[(val) => !!val || `${'กรุณาเลือกวันที่เริ่มต้น'}`]"
hide-bottom-space
:label="`${'วันที่เริ่มต้น'}`"
>
<template v-slot:prepend>
<q-icon
name="event"
class="cursor-pointer"
:style="
edit
? 'color: var(--q-primary)'
: 'color: var(--q-grey)'
"
>
</q-icon>
</template>
</q-input>
</template>
</datepicker>
</div>
<div class="col-xs-6 col-sm-6 col-md-6">
<datepicker
menu-class-name="modalfix"
v-model="dateEnd"
:locale="'th'"
autoApply
:enableTimePicker="false"
:min-date="minDate"
:readonly="!edit"
@update:modelValue="clickEditRow"
week-start="0"
>
<template #year="{ year }">{{ year + 543 }}</template>
<template #year-overlay-value="{ value }">{{
parseInt(value + 543)
}}</template>
<template #trigger>
<q-input
:class="getClass(edit)"
:outlined="edit"
dense
lazy-rules
:borderless="!edit"
:model-value="date2Thai(dateEnd)"
:rules="[(val) => !!val || `${'กรุณาเลือกวันที่สิ้นสุด'}`]"
hide-bottom-space
:label="`${'วันที่สิ้นสุด'}`"
>
<template v-slot:prepend>
<q-icon
name="event"
class="cursor-pointer"
:style="
edit
? 'color: var(--q-primary)'
: 'color: var(--q-grey)'
"
>
</q-icon>
</template>
</q-input>
</template>
</datepicker>
</div>
<div class="col-12">
<q-input
:class="getClass(edit)"
:outlined="edit"
dense
lazy-rules
autogrow
:readonly="!edit"
:borderless="!edit"
v-model="reference"
:rules="[(val) => !!val || `${'กรุณากรอกเอกสารอ้างอิง'}`]"
hide-bottom-space
:label="`${'เอกสารอ้างอิง'}`"
@update:modelValue="clickEditRow"
/>
</div>
<div class="col-12">
<q-input
:class="getClass(edit)"
:outlined="edit"
dense
lazy-rules
autogrow
:readonly="!edit"
:borderless="!edit"
v-model="detail"
:rules="[(val) => !!val || `${'กรุณากรอกรายละเอียด'}`]"
hide-bottom-space
:label="`${'รายละเอียด'}`"
@update:modelValue="clickEditRow"
/>
</div>
<div class="col-xs-6 col-sm-6 col-md-6">
<q-input
:class="getClass(edit)"
:outlined="edit"
dense
lazy-rules
:readonly="!edit"
:borderless="!edit"
v-model="refCommandNo"
hide-bottom-space
:label="`${'เลขที่คำสั่ง'}`"
@update:modelValue="clickEditRow"
>
<template v-slot:append>
<q-icon
name="mdi-file"
class="cursor-pointer"
@click="resetFilter"
/>
</template>
</q-input>
</div>
<div class="col-xs-6 col-sm-6 col-md-6">
<datepicker
menu-class-name="modalfix"
:readonly="!edit"
v-model="refCommandDate"
:locale="'th'"
autoApply
:enableTimePicker="false"
@update:modelValue="clickEditRow"
week-start="0"
>
<template #year="{ year }">{{ year + 543 }}</template>
<template #year-overlay-value="{ value }">{{
parseInt(value + 543)
}}</template>
<template #trigger>
<q-input
:class="getClass(edit)"
:outlined="edit"
dense
lazy-rules
:borderless="!edit"
:model-value="
refCommandDate == null ? null : date2Thai(refCommandDate)
"
hide-bottom-space
:label="`${'เอกสารอ้างอิง (ลงวันที่)'}`"
>
<template v-slot:prepend>
<q-icon
name="event"
class="cursor-pointer"
:style="
edit
? 'color: var(--q-primary)'
: 'color: var(--q-grey)'
"
>
</q-icon>
</template>
</q-input>
</template>
</datepicker>
</div>
</div>
</q-card-section>
<q-separator />
<DialogFooter
:cancel="clickCancel"
:edit="clickEdit"
:save="clickSave"
:validate="validateData"
:clickNext="clickNext"
:clickPrevious="clickPrevious"
:clickDelete="clickDelete"
v-model:editvisible="edit"
v-model:next="next"
v-model:previous="previous"
v-model:modalEdit="modalEdit"
/>
</q-form>
</q-card>
</q-dialog>
<HistoryTable
:rows="rowsHistory"
:columns="columnsHistory"
:filter="filterHistory"
:visible-columns="visibleColumnsHistory"
v-model:modal="modalHistory"
v-model:inputfilter="filterHistory"
v-model:inputvisible="visibleColumnsHistory"
v-model:tittle="tittleHistory"
>
<template #columns="props">
<q-tr :props="props">
<q-td v-for="col in props.cols" :key="col.name" :props="props">
<div
v-if="
col.name == 'dateStart' ||
col.name == 'dateEnd' ||
col.name == 'createdAt' ||
col.name == 'refCommandDate'
"
class="table_ellipsis"
>
{{ col.value == null ? null : date2Thai(col.value) }}
</div>
<div v-else class="table_ellipsis">
{{ col.value }}
</div>
</q-td>
</q-tr>
</template>
</HistoryTable>
</template>
<script setup lang="ts">
import { onMounted, ref, watch } from "vue";
import { useRoute } from "vue-router";
import { useComponentProfileDataStore } from "@/components/information/store/store";
import { useCounterMixin } from "@/stores/mixin";
import ProfileTable from "@/components/information/Table.vue";
import DialogHeader from "@/components/information/DialogHeader.vue";
import DialogFooter from "@/components/information/DialogFooter.vue";
import { useQuasar } from "quasar";
import type {
RequestItemsObject,
DataProps,
} from "@/components/information/interface/request/Work";
import type { ResponseObject } from "@/components/information/interface/response/Work";
import HistoryTable from "@/components/TableHistory.vue";
import http from "@/plugins/http";
import config from "@/app.config";
import type { QTableProps } from "quasar";
const props = defineProps({
statusEdit: {
type: Boolean,
required: true,
},
});
const $q = useQuasar();
const store = useComponentProfileDataStore();
const { profileData, changeProfileColumns } = store;
const mixin = useCounterMixin();
const { date2Thai, success, dateToISO, messageError, showLoader, hideLoader } =
mixin;
const route = useRoute();
const id = ref<string>("");
const dateStart = ref<Date>(new Date());
const dateEnd = ref<Date>(new Date());
const detail = ref<string>();
const reference = ref<string>();
const minDate = ref<Date>();
const refCommandNo = ref<string>();
const refCommandDate = ref<Date | null>(new Date());
const myForm = ref<any>(); //form data input
const edit = ref<boolean>(false); // dialog
const modal = ref<boolean>(false); //modal add detail
const modalEdit = ref<boolean>(false); //modal
const rawItem = ref<RequestItemsObject>(); // row
const rowIndex = ref<number>(0); //index row
const previous = ref<boolean>(); //
const next = ref<boolean>(); //
const editRow = ref<boolean>(false); //
const rowsHistory = ref<RequestItemsObject[]>([]); //select data history
const tittleHistory = ref<string>("ประวัติแก้ไขปฏิบัติราชการพิเศษ"); //
const filterHistory = ref<string>(""); //search data table history
const modalHistory = ref<boolean>(false); //modal
const checkValidate = ref<boolean>(false); //validate data
const profileId = ref<string>(
route.params.id ? route.params.id.toString() : ""
);
const rows = ref<RequestItemsObject[]>([]);
const filter = ref<string>(""); //search data table
const visibleColumns = ref<String[]>([]);
profileData.work.columns.length == 0
? (visibleColumns.value = [
"dateStart",
"dateEnd",
"detail",
"reference",
"refCommandNo",
"refCommandDate",
])
: (visibleColumns.value = profileData.work.columns);
const columns = ref<QTableProps["columns"]>([
{
name: "dateStart",
align: "left",
label: "เริ่มต้น",
sortable: true,
field: "dateStart",
headerStyle: "font-size: 14px",
style: "font-size: 14px",
sort: (a: string, b: string) =>
a.localeCompare(b, undefined, { numeric: true, sensitivity: "base" }),
},
{
name: "dateEnd",
align: "left",
label: "สิ้นสุด",
sortable: true,
field: "dateEnd",
headerStyle: "font-size: 14px",
style: "font-size: 14px",
sort: (a: string, b: string) =>
a.localeCompare(b, undefined, { numeric: true, sensitivity: "base" }),
},
{
name: "reference",
align: "left",
label: "เอกสารอ้างอิง",
sortable: true,
field: "reference",
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",
sort: (a: string, b: string) =>
a.localeCompare(b, undefined, { numeric: true, sensitivity: "base" }),
},
]);
const columnsHistory = ref<QTableProps["columns"]>([
{
name: "dateStart",
align: "left",
label: "เริ่มต้น",
sortable: true,
field: "dateStart",
headerStyle: "font-size: 14px",
style: "font-size: 14px",
sort: (a: string, b: string) =>
a.localeCompare(b, undefined, { numeric: true, sensitivity: "base" }),
},
{
name: "dateEnd",
align: "left",
label: "สิ้นสุด",
sortable: true,
field: "dateEnd",
headerStyle: "font-size: 14px",
style: "font-size: 14px",
sort: (a: string, b: string) =>
a.localeCompare(b, undefined, { numeric: true, sensitivity: "base" }),
},
{
name: "reference",
align: "left",
label: "เอกสารอ้างอิง",
sortable: true,
field: "reference",
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",
sort: (a: string, b: string) =>
a.localeCompare(b, undefined, { numeric: true, sensitivity: "base" }),
},
{
name: "createdFullName",
align: "left",
label: "ผู้ดำเนินการ",
sortable: true,
field: "createdFullName",
headerStyle: "font-size: 14px",
style: "font-size: 14px",
sort: (a: string, b: string) =>
a.localeCompare(b, undefined, { numeric: true, sensitivity: "base" }),
},
{
name: "createdAt",
align: "left",
label: "วันที่แก้ไข",
sortable: true,
field: "createdAt",
headerStyle: "font-size: 14px",
style: "font-size: 14px",
sort: (a: string, b: string) =>
a.localeCompare(b, undefined, { numeric: true, sensitivity: "base" }),
},
]);
const visibleColumnsHistory = ref<String[]>([
"dateStart",
"dateEnd",
"detail",
"reference",
"refCommandNo",
"refCommandDate",
"createdFullName",
"createdAt",
]);
watch(dateStart, (count, prevCount) => {
minDate.value = new Date(dateStart.value);
});
watch(visibleColumns, async (count: String[], prevCount: String[]) => {
await changeProfileColumns("work", count);
});
onMounted(async () => {
await fetchData();
});
const fetchData = async () => {
if (profileId.value) {
showLoader();
await http
.get(config.API.profileDutyId(profileId.value))
.then((res) => {
let data = res.data.result;
rows.value = [];
data.map((e: ResponseObject) => {
rows.value.push({
id: e.id,
dateStart: new Date(e.dateStart),
dateEnd: new Date(e.dateEnd),
detail: e.detail,
reference: e.reference,
refCommandNo: e.refCommandNo,
refCommandDate:
e.refCommandDate == null ? null : new Date(e.refCommandDate),
createdFullName: e.createdFullName,
createdAt: new Date(e.createdAt),
});
});
})
.catch((e) => {
messageError($q, e);
})
.finally(() => {
hideLoader();
});
}
};
/**
* กดดอมลกอนหน
*/
const clickPrevious = async () => {
edit.value = false;
rowIndex.value -= 1;
await getData();
await checkRowPage();
};
/**
* กดดอมลตอไป
*/
const clickNext = async () => {
edit.value = false;
rowIndex.value += 1;
await getData();
await checkRowPage();
};
/**
* กดดอมลตอไป
*/
const getData = () => {
const row = rows.value[rowIndex.value];
dateStart.value = row.dateStart;
dateEnd.value = row.dateEnd;
detail.value = row.detail;
reference.value = row.reference;
refCommandNo.value = row.refCommandNo;
refCommandDate.value = row.refCommandDate;
id.value = row.id;
};
/**
* เชคปมดอม อน อไป าตองแสดงไหม
*/
const checkRowPage = () => {
editRow.value = false;
next.value = true;
previous.value = true;
if (rowIndex.value + 1 >= rows.value.length) {
next.value = false;
}
if (rowIndex.value - 1 < 0) {
previous.value = false;
}
};
/**
* กดปมแกไขใน dialog
*/
const clickEdit = () => {
editRow.value = false;
next.value = false;
previous.value = false;
};
/**
* กดปมเพมดานบน table
*/
const clickAdd = async () => {
editRow.value = false;
await addData();
};
/**
* กดบนทกใน dialog
*/
const clickSave = async () => {
myForm.value.validate().then(async (result: boolean) => {
if (result) {
if (modalEdit.value) {
await editData();
} else {
await saveData();
}
}
});
};
/**
* นทกเพมขอม
*/
const saveData = async () => {
if (profileId.value) {
showLoader();
await http
.post(config.API.profileDutyId(profileId.value), {
id: id.value,
dateStart: dateToISO(dateStart.value),
dateEnd: dateToISO(dateEnd.value),
detail: detail.value,
reference: reference.value,
refCommandNo: refCommandNo.value,
refCommandDate:
refCommandDate.value == null ? null : dateToISO(refCommandDate.value),
})
.then((res) => {
success($q, "บันทึกข้อมูลสำเร็จ");
modal.value = false;
})
.catch((e) => {
messageError($q, e);
})
.finally(async () => {
await fetchData();
});
}
};
/**
* นทกแกไขขอม
*/
const editData = async () => {
showLoader();
await http
.put(config.API.profileDutyId(id.value), {
id: id.value,
dateStart: dateToISO(dateStart.value),
dateEnd: dateToISO(dateEnd.value),
detail: detail.value,
reference: reference.value,
refCommandNo: refCommandNo.value,
refCommandDate:
refCommandDate.value == null ? null : dateToISO(refCommandDate.value),
})
.then((res) => {
success($q, "บันทึกข้อมูลสำเร็จ");
modal.value = false;
})
.catch((e) => {
messageError($q, e);
})
.finally(async () => {
await fetchData();
});
};
/**
* ลบลบขอม
*/
const clickDelete = async () => {
$q.dialog({
title: `ลบข้อมูล`,
message: `ต้องการทำการลบข้อมูลนี้ใช่หรือไม่?`,
cancel: "ยกเลิก",
ok: "ยืนยัน",
persistent: true,
})
.onOk(async () => {
showLoader();
await http
.delete(config.API.profileDutyId(id.value))
.then((res) => {
success($q, "ลบข้อมูลสำเร็จ");
modal.value = false;
})
.catch((e) => {
messageError($q, e);
})
.finally(async () => {
await fetchData();
});
})
.onCancel(async () => {
await fetchData();
});
};
/**
* กดป dialog
*/
const clickClose = async () => {
if (editRow.value == true) {
$q.dialog({
title: `ข้อมูลมีการแก้ไข`,
message: `ยืนยันที่จะปิดโดยไม่บันทึกใช่หรือไม่?`,
cancel: "ยกเลิก",
ok: "ยืนยัน",
persistent: true,
}).onOk(async () => {
modal.value = false;
next.value = false;
previous.value = false;
});
} else {
modal.value = false;
next.value = false;
previous.value = false;
}
};
/**
* กดเลอกขอมลทจะแกไข
* @param props props ใน row เลอก
*/
const selectData = async (props: DataProps) => {
modalEdit.value = true;
modal.value = true;
edit.value = false;
rawItem.value = props.row;
rowIndex.value = props.rowIndex;
dateStart.value = props.row.dateStart;
dateEnd.value = props.row.dateEnd;
detail.value = props.row.detail;
reference.value = props.row.reference;
refCommandNo.value = props.row.refCommandNo;
refCommandDate.value = props.row.refCommandDate;
id.value = props.row.id;
await checkRowPage();
};
/**
* กดปมเพมบน table
*/
const addData = () => {
modalEdit.value = false;
modal.value = true;
edit.value = true;
dateStart.value = new Date();
dateEnd.value = new Date();
detail.value = "";
reference.value = "";
refCommandNo.value = "";
refCommandDate.value = null;
};
/**
* งกนปมยกเลกการแกไขขอม
*/
const clickCancel = async () => {
if (editRow.value == true) {
$q.dialog({
title: `ข้อมูลมีการแก้ไข`,
message: `ยืนยันยกเลิกการแก้ไขใช่หรือไม่?`,
cancel: "ยกเลิก",
ok: "ยืนยัน",
persistent: true,
}).onOk(async () => {
edit.value = false;
await checkRowPage();
await getData();
});
} else {
edit.value = false;
await checkRowPage();
}
};
/**
* เชความการแกไขขอม
*/
const clickEditRow = () => {
editRow.value = true;
};
/**
* งชนดอมลประวแกไขขอมลทเลอก
* @param row อม row ประวการแกไข
*/
const clickHistory = async (row: RequestItemsObject) => {
modalHistory.value = true;
showLoader();
await http
.get(config.API.profileDutyHisId(row.id))
.then((res) => {
let data = res.data.result;
rowsHistory.value = [];
data.map((e: ResponseObject) => {
rowsHistory.value.push({
id: e.id,
dateStart: new Date(e.dateStart),
dateEnd: new Date(e.dateEnd),
detail: e.detail,
reference: e.reference,
refCommandNo: e.refCommandNo,
refCommandDate:
e.refCommandDate == null ? null : new Date(e.refCommandDate),
createdFullName: e.createdFullName,
createdAt: new Date(e.createdAt),
});
});
})
.catch((e) => {
messageError($q, e);
})
.finally(() => {
hideLoader();
});
};
/**
* validate input ใน dialog
*/
const validateData = async () => {
checkValidate.value = true;
await myForm.value.validate().then((result: boolean) => {
if (result == false) {
checkValidate.value = false;
}
});
};
/**
* class ดรปแบบแสดงระหวางขอมลทแกไขหรอแสดงเฉยๆ
* @param val อม input สำหรบแกไขหรอไม
*/
const getClass = (val: boolean) => {
return {
"full-width inputgreen cursor-pointer": val,
"full-width cursor-pointer": !val,
};
};
const resetFilter = () => {};
</script>
<style lang="scss">
.modalfix {
position: fixed !important;
}
</style>

View file

@ -0,0 +1,84 @@
import type { zipCodeOption } from "../../components/profileType";
interface Pagination {
rowsPerPage: number;
}
interface DataOption {
id: string;
name: string;
disable?: boolean;
}
interface DataOptionLeave {
id: string;
name: string;
totalLeave: number;
}
interface DataOptionInsignia {
id: string;
name: string;
typeName: string;
}
interface treeTab {
id: string;
label: string;
children: treeTab[];
}
interface InformationOps {
prefixOps: DataOption[];
prefixOldOps: DataOption[];
genderOps: DataOption[];
bloodOps: DataOption[];
statusOps: DataOption[];
religionOps: DataOption[];
employeeClassOps: DataOption[];
employeeTypeOps: DataOption[];
}
interface OldNameOps {
prefixOps: DataOption[];
statusOps: DataOption[];
}
interface AddressOps {
provinceOps: DataOption[];
districtOps: DataOption[];
districtCOps: DataOption[];
subdistrictOps: zipCodeOption[];
subdistrictCOps: zipCodeOption[];
}
interface FamilyOps {
prefixOps: DataOption[];
}
interface EduOps {
levelOptions: DataOption[];
positionPathOptions: DataOption[];
}
interface InsigniaOps {
insigniaOptions: DataOptionInsignia[];
}
interface DisciplineOps {
levelOptions: DataOption[];
}
export type {
Pagination,
DataOption,
DataOptionInsignia,
treeTab,
InformationOps,
OldNameOps,
AddressOps,
FamilyOps,
EduOps,
InsigniaOps,
DisciplineOps,
DataOptionLeave,
};

View file

@ -0,0 +1,187 @@
//interface class array object {name string ,id number}
import type { childrenFamily } from "@/modules/04_registry/interface/response/Family";
interface ChangeActive {
name: string;
id: number;
}
//ข้อมูลส่วนตัว
interface Information {
cardid: string | null;
prefix: string | null;
age: string | null;
prefixId: string | null;
firstname: string | null;
lastname: string | null;
birthDate: Date | null;
genderId: string | null;
bloodId: string | null;
nationality: string | null;
ethnicity: string | null;
statusId: string | null;
religionId: string | null;
tel: string | null;
employeeType: string | null;
employeeClass: string | null;
profileType: string | null;
}
interface Family {
prefixC: string | null; // couple
prefixIdC: string | null;
firstnameC: string | null;
lastnameC: string | null;
lastnameCOld: string | null;
occupationC: string | null;
citizenIdC: string | null;
liveC: string | null;
prefixM: string | null; // male
prefixIdM: string | null;
firstnameM: string | null;
lastnameM: string | null;
occupationM: string | null;
citizenIdM: string | null;
liveM: string | null;
prefixF: string | null; // female
prefixIdF: string | null;
firstnameF: string | null;
lastnameF: string | null;
occupationF: string | null;
citizenIdF: string | null;
liveF: string | null;
same: string | null;
childrens: childrenFamily[];
}
interface Address {
address: string | null;
provinceId: string | null;
districtId: string | null;
subdistrictId: string | null;
addressC: string | null;
provinceIdC: string | null;
districtIdC: string | null;
subdistrictIdC: string | null;
same: string | null;
}
interface Goverment {
ocId: string | null;
positionId: string | null;
positionPathSide: string | null;
positionLine: string | null;
positionType: string | null;
positionLevel: string | null;
numberId: string | null;
positionExecutive: string | null;
positionExecutiveSide: string | null;
containDate: Date;
workDate: Date;
retireDate: string | null;
absent: number | null;
age: number | null;
ageAll: string | null;
reasonSameDate: string | null;
}
interface DataOption {
id: string;
name: string;
zipCode?: string;
}
interface zipCodeOption {
id: string;
name: string;
zipCode: string;
}
const defaultGoverment: Goverment = {
ocId: null,
positionId: null,
positionPathSide: null,
positionLine: null,
positionType: null,
positionLevel: null,
numberId: null,
positionExecutive: null,
positionExecutiveSide: null,
containDate: new Date(),
workDate: new Date(),
retireDate: null,
absent: 0,
age: 0,
ageAll: null,
reasonSameDate: null,
};
const defaultAddress: Address = {
address: null,
provinceId: null,
districtId: null,
subdistrictId: null,
addressC: null,
provinceIdC: null,
districtIdC: null,
subdistrictIdC: null,
same: "0",
};
const defaultInformation: Information = {
cardid: null,
age: null,
prefix: null,
prefixId: null,
firstname: null,
lastname: null,
birthDate: null,
genderId: null,
bloodId: null,
nationality: null,
ethnicity: null,
statusId: null,
religionId: null,
tel: null,
employeeType: null,
employeeClass: null,
profileType: null,
};
const defaultFamily: Family = {
prefixC: null,
prefixIdC: null,
firstnameC: null,
lastnameC: null,
lastnameCOld: null,
occupationC: null,
citizenIdC: null,
liveC: "1",
prefixM: null,
prefixIdM: null,
firstnameM: null,
lastnameM: null,
occupationM: null,
citizenIdM: null,
liveM: "1",
prefixF: null,
prefixIdF: null,
firstnameF: null,
lastnameF: null,
occupationF: null,
citizenIdF: null,
liveF: "1",
same: "0",
childrens: [],
};
export { defaultInformation, defaultFamily, defaultAddress, defaultGoverment };
export type {
ChangeActive,
Information,
Family,
Address,
Goverment,
DataOption,
zipCodeOption,
};

View file

@ -0,0 +1,55 @@
interface DataProps {
row: RequestItemsObject;
rowIndex: number;
}
//ข้อมูล
interface RequestItemsObject {
currentAddress: String | null;
currentDistrictId: String | null;
currentProvinceId: String | null;
currentSubDistrictId: String | null;
currentZipCode: String | null;
registrationAddress: String | null;
registrationDistrictId: String | null;
registrationProvinceId: String | null;
registrationSame: Boolean | null;
registrationSubDistrictId: String | null;
registrationZipCode: String | null;
}
interface RequestItemsHistoryObject {
currentAddress: String | null;
currentDistrict: String | null;
currentProvince: String | null;
currentSubDistrict: String | null;
currentZipCode: String | null;
registrationAddress: String | null;
registrationDistrict: String | null;
registrationProvince: String | null;
registrationSame: Boolean | null;
registrationSubDistrict: String | null;
registrationZipCode: String | null;
createdFullName: String | null;
createdAt: Date;
}
//columns
interface Columns {
[index: number]: {
name: String;
align: String;
label: String;
sortable: Boolean;
field: String;
headerStyle: String;
style: String;
};
}
export type {
RequestItemsObject,
Columns,
DataProps,
RequestItemsHistoryObject,
};

View file

@ -0,0 +1,34 @@
interface DataProps {
row: RequestItemsObject;
rowIndex: number;
}
//ข้อมูล
interface RequestItemsObject {
id: string;
point1Total: number;
point1: number;
point2Total: number;
point2: number;
pointSumTotal: number;
pointSum: number;
name: string;
date: Date;
createdFullName: string;
createdAt: Date;
}
//columns
interface Columns {
[index: number]: {
name: String;
align: String;
label: String;
sortable: Boolean;
field: String;
headerStyle: String;
style: String;
};
}
export type { RequestItemsObject, Columns, DataProps };

View file

@ -0,0 +1,31 @@
interface DataProps {
row: RequestItemsObject;
rowIndex: number;
}
//ข้อมูล
interface RequestItemsObject {
id: string;
certificateNo: string;
issuer: string;
issueDate: Date;
expireDate: Date;
certificateType: string;
createdFullName: string;
createdAt: Date;
}
//columns
interface Columns {
[index: number]: {
name: String;
align: String;
label: String;
sortable: Boolean;
field: String;
headerStyle: String;
style: String;
};
}
export type { RequestItemsObject, Columns, DataProps };

View file

@ -0,0 +1,31 @@
interface DataProps {
row: RequestItemsObject;
rowIndex: number;
}
//ข้อมูล
interface RequestItemsObject {
id: string;
issuer: string;
detail: string;
issueDate: Date;
refCommandNo: string;
refCommandDate: Date | null;
createdFullName: string;
createdAt: Date;
}
//columns
interface Columns {
[index: number]: {
name: String;
align: String;
label: String;
sortable: Boolean;
field: String;
headerStyle: String;
style: String;
};
}
export type { RequestItemsObject, Columns, DataProps };

View file

@ -0,0 +1,32 @@
interface DataProps {
row: RequestItemsObject;
rowIndex: number;
}
//ข้อมูล
interface RequestItemsObject {
id: string;
level: string;
detail: string;
unStigma: string;
refCommandNo: string;
refCommandDate: Date | null;
date: Date;
createdFullName: string;
createdAt: Date;
}
//columns
interface Columns {
[index: number]: {
name: String;
align: String;
label: String;
sortable: Boolean;
field: String;
headerStyle: String;
style: String;
};
}
export type { RequestItemsObject, Columns, DataProps };

View file

@ -0,0 +1,19 @@
//ข้อมูล
interface RequestItemsObject {
name: String;
}
//columns
interface Columns {
[index: number]: {
name: String;
align: String;
label: String;
sortable: Boolean;
field: String;
headerStyle: String;
style: String;
};
}
export type { RequestItemsObject, Columns };

View file

@ -0,0 +1,45 @@
interface DataProps {
row: RequestItemsObject;
rowIndex: number;
}
//ข้อมูล
interface RequestItemsObject {
id: string;
level: string;
levelId: string;
positionPath: string;
isEducation: boolean;
institute: string;
degree: string;
field: string;
gpa: string;
country: string;
duration: string;
durationYear: number;
other: string;
fundName: string;
isDate: string | null;
finishDate: Date;
startDate: number;
endDate: number;
startDate2: Date;
endDate2: Date;
createdFullName: string;
createdAt: Date;
}
//columns
interface Columns {
[index: number]: {
name: String;
align: String;
label: String;
sortable: Boolean;
field: String;
headerStyle: String;
style: String;
};
}
export type { RequestItemsObject, Columns, DataProps };

View file

@ -0,0 +1,29 @@
interface DataProps {
row: RequestItemsObject;
rowIndex: number;
}
//ข้อมูล
interface RequestItemsObject {
id: string;
date: Date;
status: string;
level: string;
refNo: string;
refDate: Date;
}
//columns
interface Columns {
[index: number]: {
name: String;
align: String;
label: String;
sortable: Boolean;
field: String;
headerStyle: String;
style: String;
};
}
export type { RequestItemsObject, Columns, DataProps };

View file

@ -0,0 +1,55 @@
interface DataProps {
row: RequestItemsObject;
rowIndex: number;
}
//ข้อมูล
interface RequestItemsObject {
id: string;
date: Date;
status: string;
level: string;
refNo: string;
refDate: Date;
}
interface RequestItemsHistoryObject {
oc: string | null;
position: string | null;
positionPathSide: string | null;
posNo: string | null;
positionLine: string | null;
positionType: string | null;
positionLevel: string | null;
positionExecutive: string | null;
positionExecutiveSide: string | null;
dateAppoint: Date;
dateStart: Date;
retireDate: string | null;
govAge: string | null;
govAgeAbsent: string | null;
govAgePlus: string | null;
reasonSameDate: string | null;
createdFullName: string | null;
createdAt: Date;
}
//columns
interface Columns {
[index: number]: {
name: String;
align: String;
label: String;
sortable: Boolean;
field: String;
headerStyle: String;
style: String;
};
}
export type {
RequestItemsObject,
Columns,
DataProps,
RequestItemsHistoryObject,
};

View file

@ -0,0 +1,59 @@
interface DataProps {
row: RequestItemsObject;
rowIndex: number;
}
//ข้อมูล
interface RequestItemsObject {
birthDate: Date | null;
bloodGroupId: string | null;
citizenId: string | null;
firstName: string | null;
genderId: string | null;
lastName: string | null;
nationality: string | null;
prefixId: string | null;
race: string | null;
relationshipId: string | null;
religionId: string | null;
telephoneNumber: string | null;
employeeType: string | null;
employeeClass: string | null;
}
interface RequestItemsHistoryObject {
citizenId: string | null;
prefix: string | null;
firstName: string | null;
lastName: string | null;
birthDate: Date;
gender: string | null;
relationship: string | null;
bloodGroup: string | null;
nationality: string | null;
race: string | null;
religion: string | null;
telephoneNumber: string | null;
createdFullName: string | null;
createdAt: Date;
employeeType: string | null;
employeeClass: string | null;
}
//columns
interface Columns {
name: String;
align: String;
label: String;
sortable: Boolean;
field: String;
headerStyle: String;
style: String;
}
export type {
RequestItemsObject,
Columns,
DataProps,
RequestItemsHistoryObject,
};

View file

@ -0,0 +1,40 @@
interface DataProps {
row: RequestItemsObject;
rowIndex: number;
}
//ข้อมูล
interface RequestItemsObject {
id: string;
insigniaType: string;
insignia: string;
insigniaId: string;
year: number;
no: string;
issue: string;
volumeNo: string;
volume: string;
section: string;
page: string;
receiveDate: Date;
dateAnnounce: Date;
refCommandNo: string;
refCommandDate: Date | null;
createdFullName: string;
createdAt: Date;
}
//columns
interface Columns {
[index: number]: {
name: String;
align: String;
label: String;
sortable: Boolean;
field: String;
headerStyle: String;
style: String;
};
}
export type { RequestItemsObject, Columns, DataProps };

View file

@ -0,0 +1,42 @@
interface DataProps {
row: RequestItemsObject;
rowIndex: number;
}
//ข้อมูล
interface RequestItemsObject {
id: string;
typeLeave: string;
dateStartLeave: Date;
dateEndLeave: Date;
numLeave: number;
sumLeave: number;
totalLeave: number;
status: string;
reason: string;
typeLeaveId: string;
}
//ข้อมูล
interface RequestItemsTotalObject {
typeLeaveId: string;
typeLeave: string;
totalLeave: number;
limitLeave: string;
remainLeave: string;
}
//columns
interface Columns {
[index: number]: {
name: String;
align: String;
label: String;
sortable: Boolean;
field: String;
headerStyle: String;
style: String;
};
}
export type { RequestItemsObject, Columns, DataProps, RequestItemsTotalObject };

View file

@ -0,0 +1,49 @@
//ข้อมูล
interface RequestItemsObject {
id: number;
fullname: String;
fullnameOld: String;
avatar: String;
citizenId: String;
oc: String;
position: String;
positionPathSide: String;
numberPosition: String | null;
positionLine: String;
positionType: String;
govAge: number;
positionLevel: String;
positionExecutive: String | null;
positionExecutiveSide: String | null;
refSalary: String;
positionEmployeePosition: String | null;
positionEmployeePositionSide: String | null;
positionEmployeeLevel: String | null;
positionEmployeeGroup: String | null;
dateAppoint: Date | string | null;
dateStart: Date | string | null;
createdAt: Date | string | null;
salaryDate: Date | string | null;
leaveReason: String;
age: String;
amount: String;
insignia: String;
insigniaLast: String;
isLeave: String;
leaveDateOrder: Date | string | null;
}
//columns
interface Columns {
[index: number]: {
name: String;
align: String;
label: String;
sortable: Boolean;
field: String;
headerStyle: String;
style: String;
};
}
export type { RequestItemsObject, Columns };

View file

@ -0,0 +1,32 @@
interface DataProps {
row: RequestItemsObject;
rowIndex: number;
}
//ข้อมูล
interface RequestItemsObject {
id: string;
prefix: string;
prefixId: string;
firstName: string;
lastName: string;
status: string;
file: string | null;
createdFullName: string;
createdAt: Date;
}
//columns
interface Columns {
[index: number]: {
name: String;
align: String;
label: String;
sortable: Boolean;
field: String;
headerStyle: String;
style: String;
};
}
export type { RequestItemsObject, Columns, DataProps };

View file

@ -0,0 +1,28 @@
interface DataProps {
row: RequestItemsObject;
rowIndex: number;
}
//ข้อมูล
interface RequestItemsObject {
id: string;
date: Date;
detail: string;
createdFullName: string;
createdAt: Date;
}
//columns
interface Columns {
[index: number]: {
name: String;
align: String;
label: String;
sortable: Boolean;
field: String;
headerStyle: String;
style: String;
};
}
export type { RequestItemsObject, Columns, DataProps };

View file

@ -0,0 +1,31 @@
interface DataProps {
row: RequestItemsObject;
rowIndex: number;
}
//ข้อมูล
interface RequestItemsObject {
id: string;
date: Date;
detail: string;
reference: string;
refCommandNo: string;
refCommandDate: Date | null;
createdFullName: string;
createdAt: Date;
}
//columns
interface Columns {
[index: number]: {
name: String;
align: String;
label: String;
sortable: Boolean;
field: String;
headerStyle: String;
style: String;
};
}
export type { RequestItemsObject, Columns, DataProps };

View file

@ -0,0 +1,90 @@
interface DataProps {
row: RequestItemsObject;
rowIndex: number;
}
interface DataPropsEmployee {
row: RequestItemsEmployee;
rowIndex: number;
}
//ข้อมูล
interface RequestItemsObject {
id: string;
date: Date;
amount: number;
positionSalaryAmount: number;
mouthSalaryAmount: number;
oc: string;
ocId: string;
position: string;
positionId: string;
posNo: string;
posNoId: string;
positionLine: string;
positionLineId: string;
positionPathSide: string;
positionPathSideId: string;
positionType: string;
positionTypeId: string;
positionLevel: string;
positionLevelId: string;
positionExecutive: string;
positionExecutiveId: string;
positionExecutiveSide: string;
positionExecutiveSideId: string;
salaryClass: string;
salaryRef: string;
refCommandNo: string;
// refCommandDate: Date | null;
createdFullName: string;
createdAt: Date;
}
interface RequestItemsEmployee {
amount: number;
createdAt: Date;
createdFullName: string;
date: Date;
id: string;
mouthSalaryAmount: number;
oc: string | null;
ocId: string;
posNo: string | null;
posNoId: string | null;
posNoEmployee: string | null;
positionEmployeeGroup: string | null;
positionEmployeeGroupId: string | null;
positionEmployeeLevel: string | null;
positionEmployeeLevelId: string | null;
positionEmployeePosition: string | null;
positionEmployeePositionId: string | null;
positionEmployeePositionSide: string | null;
positionEmployeePositionSideId: string | null;
positionSalaryAmount: number;
salaryClass: string | null;
salaryRef: string | null;
refCommandNo: string;
// refCommandDate: Date | null;
}
//columns
interface Columns {
[index: number]: {
name: String;
align: String;
label: String;
sortable: Boolean;
field: String;
headerStyle: String;
style: String;
};
}
export type {
RequestItemsObject,
Columns,
DataProps,
RequestItemsEmployee,
DataPropsEmployee,
};

View file

@ -0,0 +1,30 @@
interface DataProps {
row: RequestItemsObject;
rowIndex: number;
}
//ข้อมูล
interface RequestItemsObject {
id: string;
field: string;
detail: string;
remark: string;
reference: string;
createdFullName: string;
createdAt: Date;
}
//columns
interface Columns {
[index: number]: {
name: String;
align: String;
label: String;
sortable: Boolean;
field: String;
headerStyle: String;
style: String;
};
}
export type { RequestItemsObject, Columns, DataProps };

View file

@ -0,0 +1,36 @@
interface DataProps {
row: RequestItemsObject;
rowIndex: number;
}
//ข้อมูล
interface RequestItemsObject {
id: string;
name: string;
topic: string;
yearly: number;
place: string;
duration: string;
department: string;
numberOrder: string;
dateOrder: Date;
startDate: Date;
endDate: Date;
createdFullName: string;
createdAt: Date;
}
//columns
interface Columns {
[index: number]: {
name: String;
align: String;
label: String;
sortable: Boolean;
field: String;
headerStyle: String;
style: String;
};
}
export type { RequestItemsObject, Columns, DataProps };

View file

@ -0,0 +1,32 @@
interface DataProps {
row: RequestItemsObject;
rowIndex: number;
}
//ข้อมูล
interface RequestItemsObject {
id: string;
dateStart: Date;
dateEnd: Date;
detail: string;
reference: string;
refCommandNo: string;
refCommandDate: Date | null;
createdFullName: string;
createdAt: Date;
}
//columns
interface Columns {
[index: number]: {
name: String;
align: String;
label: String;
sortable: Boolean;
field: String;
headerStyle: String;
style: String;
};
}
export type { RequestItemsObject, Columns, DataProps };

View file

@ -0,0 +1,34 @@
//ข้อมูล
interface ResponseObject {
currentAddress: string | null;
currentDistrictId: string | null;
currentProvinceId: string | null;
currentSubDistrictId: string | null;
currentZipCode: string | null;
registrationAddress: string | null;
registrationDistrictId: string | null;
registrationProvinceId: string | null;
registrationSame: Boolean | null;
registrationSubDistrictId: string | null;
registrationZipCode: string | null;
createdFullName: string | null;
createdAt: Date;
}
interface ResponseHistory {
currentAddress: string | null;
currentDistrictId: string | null;
currentProvinceId: string | null;
currentSubDistrictId: string | null;
currentZipCode: string | null;
registrationAddress: string | null;
registrationDistrictId: string | null;
registrationProvinceId: string | null;
registrationSame: string | null;
registrationSubDistrictId: string | null;
registrationZipCode: string | null;
createdFullName: string | null;
createdAt: Date;
}
export type { ResponseObject, ResponseHistory };

View file

@ -0,0 +1,16 @@
//ข้อมูล
interface ResponseObject {
id: string;
point1Total: number;
point1: number;
point2Total: number;
point2: number;
pointSumTotal: number;
pointSum: number;
name: string;
date: Date;
createdFullName: string;
createdAt: Date;
}
export type { ResponseObject };

View file

@ -0,0 +1,13 @@
//ข้อมูล
interface ResponseObject {
id: string;
certificateNo: string;
issuer: string;
issueDate: Date;
expireDate: Date;
certificateType: string;
createdFullName: string;
createdAt: Date;
}
export type { ResponseObject };

View file

@ -0,0 +1,13 @@
//ข้อมูล
interface ResponseObject {
id: string;
issuer: string;
detail: string;
issueDate: Date;
refCommandNo: string;
refCommandDate: Date | null;
createdFullName: string;
createdAt: Date;
}
export type { ResponseObject };

View file

@ -0,0 +1,14 @@
//ข้อมูล
interface ResponseObject {
id: string;
level: string;
detail: string;
unStigma: string;
refCommandNo: string;
refCommandDate: Date;
date: Date;
createdFullName: string;
createdAt: Date;
}
export type { ResponseObject };

View file

@ -0,0 +1,6 @@
//ข้อมูล
interface ResponseObject {
name: String;
}
export type { ResponseObject };

View file

@ -0,0 +1,27 @@
//ข้อมูล
interface ResponseObject {
id: string;
educationLevel: string;
educationLevelId: string;
positionPath: string;
isEducation: boolean;
institute: string;
degree: string;
field: string;
gpa: string;
country: string;
duration: string;
durationYear: number;
other: string;
fundName: string;
isDate: string | null;
finishDate: Date;
startDate: number;
endDate: number;
startDate2: Date;
endDate2: Date;
createdFullName: string;
createdAt: Date;
}
export type { ResponseObject };

View file

@ -0,0 +1,64 @@
//ข้อมูล
interface ResponseObject {
couple: Boolean | null;
couplePrefixId: string | null;
coupleFirstName: string | null;
coupleLastName: string | null;
coupleLastNameOld: string | null;
coupleCareer: string | null;
coupleLive: Boolean | null;
coupleCitizenId: string | null;
fatherPrefixId: string | null;
fatherFirstName: string | null;
fatherLastName: string | null;
fatherCareer: string | null;
fatherLive: Boolean | null;
fatherCitizenId: string | null;
motherPrefixId: string | null;
motherFirstName: string | null;
motherLastName: string | null;
motherCareer: string | null;
motherLive: Boolean | null;
motherCitizenId: string | null;
createdFullName: string | null;
createdAt: Date;
childrens: childrenFamily[];
}
interface ResponseHistory {
couple: string | null;
couplePrefixId: string | null;
coupleFirstName: string | null;
coupleLastName: string | null;
coupleLastNameOld: string | null;
coupleCareer: string | null;
coupleLive: string | null;
coupleCitizenId: string | null;
fatherPrefixId: string | null;
fatherFirstName: string | null;
fatherLastName: string | null;
fatherCareer: string | null;
fatherLive: string | null;
fatherCitizenId: string | null;
motherPrefixId: string | null;
motherFirstName: string | null;
motherLastName: string | null;
motherCareer: string | null;
motherLive: string | null;
motherCitizenId: string | null;
createdFullName: string | null;
createdAt: Date;
childrens: childrenFamily[];
}
interface childrenFamily {
id: string;
childrenPrefixId: string | null;
childrenFirstName: string | null;
childrenLastName: string | null;
childrenCareer: string | null;
childrenLive: string | null;
childrenCitizenId: string | null;
}
export type { ResponseObject, childrenFamily, ResponseHistory };

View file

@ -0,0 +1,23 @@
//ข้อมูล
interface ResponseObject {
oc: string | null;
positionExecutive: string | null;
positionExecutiveSide: string | null;
dateAppoint: Date | string;
dateStart: Date | string;
govAge: string | null;
govAgeAbsent: number | null;
govAgePlus: number | null;
positionLevel: string | null;
posNo: string | null;
position: string | null;
positionPathSide: string | null;
retireDate: string | null;
positionType: string | null;
positionLine: string | null;
createdFullName: string | null;
createdAt: Date;
reasonSameDate: string | null;
}
export type { ResponseObject };

View file

@ -0,0 +1,24 @@
//ข้อมูล
interface ResponseObject {
changeName: boolean | null;
birthDate: Date;
bloodGroupId: string | null;
citizenId: string | null;
firstName: string | null;
genderId: string | null;
lastName: string | null;
nationality: string | null;
prefixId: string | null;
race: string | null;
relationshipId: string | null;
religionId: string | null;
telephoneNumber: string | null;
createdFullName: string | null;
createdAt: Date;
age: string | null;
employeeType: string | null;
employeeClass: string | null;
profileType: string | null;
}
export type { ResponseObject };

View file

@ -0,0 +1,22 @@
//ข้อมูล
interface ResponseObject {
id: string;
insigniaType: string;
insignia: string;
insigniaId: string;
year: number;
no: string;
issue: string;
volumeNo: string;
volume: string;
section: string;
page: string;
receiveDate: Date;
dateAnnounce: Date;
refCommandNo: string;
refCommandDate: Date | null;
createdFullName: string;
createdAt: Date;
}
export type { ResponseObject };

View file

@ -0,0 +1,22 @@
//ข้อมูล
interface ResponseObject {
id: string;
typeLeave: string;
dateStartLeave: Date;
dateEndLeave: Date;
numLeave: number;
sumLeave: number;
totalLeave: number;
status: string;
reason: string;
typeLeaveId: string;
}
interface ResponseTotalObject {
typeLeaveId: string;
typeLeave: string;
totalLeave: number;
limitLeave: string;
remainLeave: string;
}
export type { ResponseObject, ResponseTotalObject };

View file

@ -0,0 +1,37 @@
//ข้อมูล
interface ResponseObject {
id: number;
fullname: String;
fullnameOld: String;
avatar: String;
citizenId: String;
oc: String;
position: String;
positionPathSide: String;
posNo: String | null;
posNoEmployee: String | null;
positionLine: String;
positionType: String;
govAge: number;
positionLevel: String;
positionExecutive: String | null;
positionExecutiveSide: String | null;
refSalary: String;
positionEmployeePosition: String | null;
positionEmployeePositionSide: String | null;
positionEmployeeLevel: String | null;
positionEmployeeGroup: String | null;
dateAppoint: Date | null;
dateStart: Date | null;
createdAt: Date | null;
salaryDate: Date | null;
leaveReason: string;
age: String;
amount: String;
insignia: String;
insigniaLast: String;
isLeave: boolean;
leaveDateOrder: Date | null;
}
export type { ResponseObject };

View file

@ -0,0 +1,14 @@
//ข้อมูล
interface ResponseObject {
id: string;
prefix: string;
prefixId: string;
firstName: string;
lastName: string;
status: string;
file: string | null;
createdFullName: string;
createdAt: Date;
}
export type { ResponseObject };

View file

@ -0,0 +1,10 @@
//ข้อมูล
interface ResponseObject {
id: string;
date: Date;
detail: string;
createdFullName: string;
createdAt: Date;
}
export type { ResponseObject };

View file

@ -0,0 +1,13 @@
//ข้อมูล
interface ResponseObject {
id: string;
date: Date;
detail: string;
reference: string;
refCommandNo: string;
refCommandDate: Date | null;
createdFullName: string;
createdAt: Date;
}
export type { ResponseObject };

View file

@ -0,0 +1,61 @@
//ข้อมูล
interface ResponseObject {
id: string;
date: Date;
amount: number;
positionSalaryAmount: number;
mouthSalaryAmount: number;
oc: string;
ocId: string;
position: string;
positionId: string;
posNo: string;
posNoId: string;
positionLine: string;
positionLineId: string;
positionPathSide: string;
positionPathSideId: string;
positionType: string;
positionTypeId: string;
positionLevel: string;
positionLevelId: string;
positionExecutive: string;
positionExecutiveId: string;
positionExecutiveSide: string;
positionExecutiveSideId: string;
salaryClass: string;
salaryRef: string;
refCommandNo: string;
// refCommandDate: Date | null;
createdFullName: string;
createdAt: Date;
}
interface ResponseObjectEmployee {
amount: number;
createdAt: Date;
createdFullName: string;
date: Date;
id: string;
mouthSalaryAmount: number;
oc: string | null;
ocId: string;
posNo: string | null;
posNoId: string | null;
posNoEmployee: string | null;
positionEmployeeGroup: string | null;
positionEmployeeGroupId: string | null;
positionEmployeeLevel: string | null;
positionEmployeeLevelId: string | null;
positionEmployeePosition: string | null;
positionEmployeePositionId: string | null;
positionEmployeePositionSide: string | null;
positionEmployeePositionSideId: string | null;
positionSalaryAmount: number;
salaryClass: string | null;
salaryRef: string | null;
refCommandNo: string;
// refCommandDate: Date | null;
}
export type { ResponseObject, ResponseObjectEmployee };

View file

@ -0,0 +1,12 @@
//ข้อมูล
interface ResponseObject {
id: string;
field: string;
detail: string;
remark: string;
reference: string;
createdFullName: string;
createdAt: Date;
}
export type { ResponseObject };

View file

@ -0,0 +1,18 @@
//ข้อมูล
interface ResponseObject {
id: string;
name: string;
topic: string;
yearly: number;
place: string;
duration: string;
department: string;
numberOrder: string;
dateOrder: Date;
startDate: Date;
endDate: Date;
createdFullName: string;
createdAt: Date;
}
export type { ResponseObject };

View file

@ -0,0 +1,14 @@
//ข้อมูล
interface ResponseObject {
id: string;
dateStart: Date;
dateEnd: Date;
detail: string;
reference: string;
refCommandNo: string;
refCommandDate: Date | null;
createdFullName: string;
createdAt: Date;
}
export type { ResponseObject };

View file

@ -0,0 +1,30 @@
interface Profile {
main: { columns: String[] };
education: { columns: String[] };
oldName: { columns: String[] };
certicate: { columns: String[] };
train: { columns: String[] };
insignia: { columns: String[] };
coined: { columns: String[] };
assessment: { columns: String[] };
salary: { columns: String[] };
discipline: { columns: String[] };
leave: { columns: String[] };
talent: { columns: String[] };
work: { columns: String[] };
record: { columns: String[] };
other: { columns: String[] };
document: { columns: String[] };
}
interface DataOption {
id: string;
name: string;
zipCode?: string;
}
interface Pagination {
rowsPerPage: number;
}
export type { Profile, DataOption, Pagination };

View file

@ -0,0 +1,70 @@
import { ref } from "vue";
import { defineStore } from "pinia";
import type { Profile } from "@/components/information/interface/store/main";
export const useComponentProfileDataStore = defineStore(
"componentProfile",
() => {
const profile = "profile";
const birthDate = ref<Date>(new Date());
const retireText = ref<string | null>(null);
const profileData = ref<Profile>({
main: { columns: [] },
education: { columns: [] },
oldName: { columns: [] },
certicate: { columns: [] },
train: { columns: [] },
insignia: { columns: [] },
coined: { columns: [] },
assessment: { columns: [] },
salary: { columns: [] },
discipline: { columns: [] },
leave: { columns: [] },
talent: { columns: [] },
work: { columns: [] },
record: { columns: [] },
other: { columns: [] },
document: { columns: [] },
});
const changeRetireText = (val: string | null) => {
retireText.value = val;
};
const changeBirth = (val: Date) => {
birthDate.value = val;
};
const changeProfileColumns = (system: String, val: String[]) => {
if (system == "main") profileData.value.main.columns = val;
if (system == "education") profileData.value.education.columns = val;
if (system == "oldName") profileData.value.oldName.columns = val;
if (system == "certicate") profileData.value.certicate.columns = val;
if (system == "train") profileData.value.train.columns = val;
if (system == "insignia") profileData.value.insignia.columns = val;
if (system == "coined") profileData.value.coined.columns = val;
if (system == "assessment") profileData.value.assessment.columns = val;
if (system == "salary") profileData.value.salary.columns = val;
if (system == "discipline") profileData.value.discipline.columns = val;
if (system == "leave") profileData.value.leave.columns = val;
if (system == "talent") profileData.value.talent.columns = val;
if (system == "work") profileData.value.work.columns = val;
if (system == "record") profileData.value.record.columns = val;
if (system == "other") profileData.value.other.columns = val;
if (system == "document") profileData.value.document.columns = val;
localStorage.setItem(profile, JSON.stringify(profileData.value));
};
if (localStorage.getItem(profile) !== null) {
profileData.value = JSON.parse(localStorage.getItem(profile) || "{}");
}
return {
profileData,
changeProfileColumns,
birthDate,
changeBirth,
retireText,
changeRetireText,
};
}
);

View file

@ -0,0 +1,199 @@
<template>
<div class="flex items-center">
<div class="flex items-center">
<q-icon
:name="icon"
size="1.5em"
color="grey-5"
class="q-mr-md"
v-if="icon != ''"
/>
<div
class="text-bold text-subtitle2 col-12 row items-center"
v-if="header != ''"
>
{{ header }}
</div>
</div>
<div class="q-gutter-sm q-mx-sm" v-if="addData == false">
<q-btn
size="12px"
v-if="!edit"
flat
round
:disabled="disable"
:color="edit ? 'grey-7' : 'primary'"
@click="ClickEdit"
icon="mdi-pencil-outline"
>
<q-tooltip>แกไขขอม</q-tooltip>
</q-btn>
<q-btn
size="12px"
flat
round
v-if="edit"
:color="!edit ? 'grey-7' : 'public'"
@click="save"
icon="mdi-content-save-outline"
>
<q-tooltip>นทกขอม</q-tooltip>
</q-btn>
<q-btn
size="12px"
flat
round
v-if="edit && !addEmployee"
:color="!edit ? 'grey-7' : 'red'"
@click="ClickCancel"
icon="mdi-undo"
>
<q-tooltip>ยกเล</q-tooltip>
</q-btn>
</div>
<div class="q-pl-sm" v-else-if="iconAdd != '' && iconAdd != null">
<q-btn
size="12px"
flat
round
color="add"
@click="addleave"
icon="mdi-plus"
>
<q-tooltip>เพมขอม</q-tooltip>
</q-btn>
<q-btn size="12px" flat round color="add" @click="add" :icon="iconAdd">
<q-tooltip>สรปวนลา</q-tooltip>
</q-btn>
</div>
<div class="q-pl-sm" v-else>
<q-btn
size="12px"
flat
round
:disabled="disable"
color="add"
@click="add"
icon="mdi-plus"
>
<q-tooltip>เพมขอม</q-tooltip>
</q-btn>
</div>
<q-space />
<q-btn
color="info"
flat
dense
round
size="14px"
icon="mdi-history"
v-if="history"
@click="historyClick"
>
<q-tooltip>ประว{{ header }}</q-tooltip>
</q-btn>
</div>
</template>
<script setup lang="ts">
const props = defineProps({
header: {
type: String,
default: "ข้อความ",
required: true,
},
iconAdd: {
type: String,
default: null,
},
icon: {
type: String,
default: "mdi-help",
required: true,
},
edit: {
type: Boolean,
default: true,
required: true,
},
history: {
type: Boolean,
default: true,
required: true,
},
addData: {
type: Boolean,
defualt: false,
},
disable: {
type: Boolean,
defualt: false,
},
historyClick: {
type: Function,
default: () => console.log("not function"),
},
add: {
type: Function,
default: () => console.log("not function"),
},
addleave: {
type: Function,
default: () => console.log("not function"),
},
save: {
type: Function,
default: () => console.log("not function"),
},
deleted: {
type: Function,
default: () => console.log("not function"),
},
cancel: {
type: Function,
default: () => console.log("not function"),
},
changeBtn: {
type: Function,
default: () => console.log("not function"),
},
addEmployee: {
type: Boolean,
defualt: false,
},
});
const emit = defineEmits(["update:edit"]);
const updateEdit = (value: any) => {
emit("update:edit", value);
};
const ClickEdit = () => {
updateEdit(!props.edit);
props.changeBtn();
};
const historyClick = async () => {
await props.historyClick();
};
const ClickCancel = () => {
updateEdit(!props.edit);
props.cancel();
props.changeBtn();
};
const save = () => {
props.save();
};
const add = () => {
props.add();
};
const addleave = () => {
props.addleave();
};
</script>
<style scoped></style>

View file

@ -28,10 +28,10 @@ interface menuType {
}
interface notiType {
id: number;
id: string;
sender: string;
body: string;
timereceive: string;
timereceive: Date;
}
interface optionType {
@ -111,6 +111,22 @@ const menuList = readonly<any[]>([
path: "registry",
role: "registry",
},
{
key: 10,
icon: "o_contact_page",
activeIcon: "registry_employee_page",
label: "ทะเบียนประวัติลูกจ้าง",
path: "registry-employee",
role: "registryEmployee",
},
{
key: 10,
icon: "o_list",
activeIcon: "order",
label: "ออกคำสั่ง",
path: "order",
role: "order",
},
{
key: 5,
icon: "o_search",
@ -192,12 +208,12 @@ const menuList = readonly<any[]>([
path: "placement",
role: "placement",
},
{
key: 6.2,
label: "ออกคำสั่ง" /* ออกคำสั่งบรรจุ */,
path: "Orderplacement",
role: "placement",
},
// {
// key: 6.2,
// label: "ออกคำสั่ง" /* ออกคำสั่งบรรจุ */,
// path: "Orderplacement",
// role: "placement",
// },
{
key: 6.3,
label: "การทดลองงาน" /* การทดลองงาน */,
@ -206,7 +222,7 @@ const menuList = readonly<any[]>([
},
{
key: 6.4,
label: "รายการคำขอโอน" /* */,
label: "รายการขอโอน" /* */,
path: "transfer",
role: "placement",
},
@ -218,13 +234,36 @@ const menuList = readonly<any[]>([
},
{
key: 6.6,
label: "คำสั่งช่วยราชการ/ส่งตัวกลับ" /* */,
path: "repatriation-order",
label: "รายการช่วยราชการ" /* */,
path: "help-government",
role: "placement",
},
{
key: 6.7,
label: "รายการส่งตัวกลับ" /* */,
path: "repatriate",
role: "placement",
},
{
key: 6.8,
label: "รายการแต่งตั้ง-เลื่อน" /* */,
path: "appoint-promote",
role: "placement",
},
{
key: 6.9,
label: "รายการย้าย" /* */,
path: "relocation",
role: "placement",
},
{
key: 6.1,
label: "รายการอื่นๆ" /* */,
path: "other",
role: "placement",
},
],
},
{
key: 7,
icon: "mdi-account-cancel-outline",
@ -241,34 +280,46 @@ const menuList = readonly<any[]>([
},
{
key: 7.2,
label: "ลาออก",
label: "รายการลาออก",
path: "resign",
role: "retirement",
},
// {
// key: 7.3,
// label: "คำสั่งลาออก",
// path: "resign-order",
// role: "retirement",
// },
{
key: 7.3,
label: "คำสั่งลาออก",
path: "resign-order",
role: "retirement",
},
{
key: 7.4,
label: "Exit interview",
// path: "",
role: "retirement",
},
{
key: 7.5,
label: "ถึงแก่กรรม",
key: 7.4,
label: "รายการบันทึกการถึงแก่กรรม",
path: "deceased",
role: "retirement",
},
{
key: 7.6,
label: "คำสั่งให้ออก ปลดออก ไล่ออก",
key: 7.5,
label: "รายการให้ออก",
path: "dismiss-order",
role: "retirement",
},
{
key: 7.6,
label: "รายการปลดออก",
path: "discharged",
role: "retirement",
},
{
key: 7.7,
label: "รายการไล่ออก",
path: "expulsion",
role: "retirement",
},
],
},
{
@ -286,25 +337,25 @@ const menuList = readonly<any[]>([
role: "insignia",
children: [
{
label: "รายการเสนอขอ",
label: "รอบการเสนอขอ",
path: "insigniaProposals",
role: "insignia",
},
{
label: "จัดทำรายชื่อข้าราชการสามัญ",
path: "insigniaNameList",
label: "จัดการคำขอ",
path: "insigniaManage",
role: "insignia",
},
{
label: "อนุมัติรายชื่อข้าราชการสามัญ",
path: "insigniaNameApprove",
role: "insignia",
},
{
label: "บันทึกผลการได้รับพระราชทานเครื่องราชย์อิสริยสภรณ์",
label: "บันทึกผลการได้รับพระราช...",
path: "insigniaRecord",
role: "insignia",
},
{
label: "จัดสรรเครื่องราชฯ",
path: "insigniaAllocate",
role: "insignia",
},
{
label: "รายงาน",
path: "insigniaReport",
@ -319,7 +370,7 @@ const menuList = readonly<any[]>([
role: "coin",
children: [
{
label: "รายการเสนอขอ",
label: "รอบการเสนอขอ",
path: "coinProposals",
role: "coin",
},
@ -363,14 +414,6 @@ const menuList = readonly<any[]>([
},
],
},
{
key: 11,
icon: "o_contact_page",
activeIcon: "contact_page",
label: "ทะเบียนประวัติลูกจ้าง",
path: "employee",
role: "registryEmployee",
},
]);
const tabList = readonly<tabType[]>([

View file

@ -0,0 +1,27 @@
interface ResponseInbox {
body: string;
createdAt: Date;
createdFullName: string;
createdUserId: string;
id: string;
isOpen: boolean;
lastUpdateFullName: string;
lastUpdateUserId: string;
lastUpdatedAt: Date;
openDate: Date | null;
payload: string;
receiveDate: Date;
receiverUserId: string;
subject: string;
}
interface DataInbox {
no: string;
sender: string;
subject: string;
timereceive: Date;
body: string;
ratingModel: number;
}
export type { ResponseInbox, DataInbox };

View file

@ -121,7 +121,8 @@
color="red"
@click="cancelClick()"
label="ยกเลิกแก้ไข"
> <!-- icon="mdi-undo"
>
<!-- icon="mdi-undo"
<q-tooltip>ยกเล</q-tooltip> -->
</q-btn>
<q-btn
@ -130,7 +131,8 @@
color="red"
@click="deleteClick()"
label="ลบวันหยุด"
> <!-- icon="mdi-delete"
>
<!-- icon="mdi-delete"
<q-tooltip>ลบ</q-tooltip> -->
</q-btn>
<q-btn
@ -215,7 +217,6 @@ import type {
DataDateRowObject,
DataDateAddObject,
} from "@/modules/01_metadata/interface/request/Calendar";
import { useDataStore } from "@/stores/data";
const props = defineProps({
dateYear: {
@ -240,8 +241,6 @@ const props = defineProps({
},
});
const store = useDataStore();
const { loaderPage } = store;
const mixin = useCounterMixin(); //
const { success, dateToISO, date2Thai, messageError, showLoader, hideLoader } =
mixin;

View file

@ -156,13 +156,8 @@
</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-btn unelevated label="บันทึก" color="public" type="submit">
<!-- icon="mdi-content-save-outline"
<q-tooltip>นท</q-tooltip> -->
</q-btn>
</q-card-actions>
@ -221,7 +216,6 @@ import type {
DataDateListsObject,
TabsObject,
} from "@/modules/01_metadata/interface/request/Calendar";
import { useDataStore } from "@/stores/data";
const props = defineProps({
dateYear: {
@ -241,8 +235,6 @@ const props = defineProps({
},
});
const store = useDataStore();
const { loaderPage } = store;
const mixin = useCounterMixin(); //
const {
success,

View file

@ -289,7 +289,6 @@ import type {
import type { ResponseHistoryObject } from "@/modules/01_metadata/interface/response/insignia/Insignia";
import type { DataOption } from "@/modules/01_metadata/interface/index/Main";
import HistoryTable from "@/components/TableHistory.vue";
import { useDataStore } from "@/stores/data";
const props = defineProps({
fetchDataComponent: {
@ -298,8 +297,6 @@ const props = defineProps({
},
});
const dataStore = useDataStore();
const { loaderPage } = dataStore;
const mixin = useCounterMixin();
const { success, dateText, messageError, showLoader, hideLoader } = mixin;
const store = useManageDataStore();

View file

@ -190,7 +190,6 @@ import type {
} from "@/modules/01_metadata/interface/request/insignia/InsigniaType";
import type { ResponseHistoryObject } from "@/modules/01_metadata/interface/response/insignia/InsigniaType";
import HistoryTable from "@/components/TableHistory.vue";
import { useDataStore } from "@/stores/data";
const props = defineProps({
fetchDataComponent: {
@ -199,8 +198,6 @@ const props = defineProps({
},
});
const dataStore = useDataStore();
const { loaderPage } = dataStore;
const mixin = useCounterMixin();
const { success, dateText, messageError, showLoader, hideLoader } = mixin;
const store = useManageDataStore();

View file

@ -190,7 +190,6 @@ import type {
} from "@/modules/01_metadata/interface/request/organization/Agency";
import type { ResponseHistoryObject } from "@/modules/01_metadata/interface/response/organization/Agency";
import HistoryTable from "@/components/TableHistory.vue";
import { useDataStore } from "@/stores/data";
const props = defineProps({
fetchDataComponent: {
@ -199,8 +198,6 @@ const props = defineProps({
},
});
const dataStore = useDataStore();
const { loaderPage } = dataStore;
const mixin = useCounterMixin();
const { success, dateText, messageError, showLoader, hideLoader } = mixin;
const store = useManageDataStore();

View file

@ -190,7 +190,6 @@ import type {
} from "@/modules/01_metadata/interface/request/organization/Fax";
import type { ResponseHistoryObject } from "@/modules/01_metadata/interface/response/organization/Fax";
import HistoryTable from "@/components/TableHistory.vue";
import { useDataStore } from "@/stores/data";
const props = defineProps({
fetchDataComponent: {
@ -199,8 +198,6 @@ const props = defineProps({
},
});
const dataStore = useDataStore();
const { loaderPage } = dataStore;
const mixin = useCounterMixin();
const { success, dateText, messageError, showLoader, hideLoader } = mixin;
const store = useManageDataStore();

View file

@ -190,7 +190,6 @@ import type {
} from "@/modules/01_metadata/interface/request/organization/GovernmentAgency";
import type { ResponseHistoryObject } from "@/modules/01_metadata/interface/response/organization/GovernmentAgency";
import HistoryTable from "@/components/TableHistory.vue";
import { useDataStore } from "@/stores/data";
const props = defineProps({
fetchDataComponent: {
@ -199,8 +198,6 @@ const props = defineProps({
},
});
const dataStore = useDataStore();
const { loaderPage } = dataStore;
const mixin = useCounterMixin();
const { success, dateText, messageError, showLoader, hideLoader } = mixin;
const store = useManageDataStore();

View file

@ -190,7 +190,6 @@ import type {
} from "@/modules/01_metadata/interface/request/organization/Level";
import type { ResponseHistoryObject } from "@/modules/01_metadata/interface/response/organization/Level";
import HistoryTable from "@/components/TableHistory.vue";
import { useDataStore } from "@/stores/data";
const props = defineProps({
fetchDataComponent: {
@ -199,8 +198,6 @@ const props = defineProps({
},
});
const dataStore = useDataStore();
const { loaderPage } = dataStore;
const mixin = useCounterMixin();
const { success, dateText, messageError, showLoader, hideLoader } = mixin;
const store = useManageDataStore();

View file

@ -202,7 +202,6 @@ import type {
} from "@/modules/01_metadata/interface/request/organization/Organization";
import type { ResponseHistoryObject } from "@/modules/01_metadata/interface/response/organization/Organization";
import HistoryTable from "@/components/TableHistory.vue";
import { useDataStore } from "@/stores/data";
const props = defineProps({
fetchDataComponent: {
@ -211,8 +210,6 @@ const props = defineProps({
},
});
const dataStore = useDataStore();
const { loaderPage } = dataStore;
const mixin = useCounterMixin();
const { success, dateText, messageError, showLoader, hideLoader } = mixin;
const store = useManageDataStore();

View file

@ -243,7 +243,6 @@ import type {
} from "@/modules/01_metadata/interface/request/organization/ShortName";
import type { ResponseHistoryObject } from "@/modules/01_metadata/interface/response/organization/ShortName";
import HistoryTable from "@/components/TableHistory.vue";
import { useDataStore } from "@/stores/data";
const props = defineProps({
fetchDataComponent: {
@ -252,8 +251,6 @@ const props = defineProps({
},
});
const dataStore = useDataStore();
const { loaderPage } = dataStore;
const mixin = useCounterMixin();
const { success, dateText, messageError, showLoader, hideLoader } = mixin;
const store = useManageDataStore();

View file

@ -190,7 +190,6 @@ import type {
} from "@/modules/01_metadata/interface/request/organization/Status";
import type { ResponseHistoryObject } from "@/modules/01_metadata/interface/response/organization/Status";
import HistoryTable from "@/components/TableHistory.vue";
import { useDataStore } from "@/stores/data";
const props = defineProps({
fetchDataComponent: {
@ -199,8 +198,6 @@ const props = defineProps({
},
});
const dataStore = useDataStore();
const { loaderPage } = dataStore;
const mixin = useCounterMixin();
const { success, dateText, messageError, showLoader, hideLoader } = mixin;
const store = useManageDataStore();

View file

@ -190,7 +190,6 @@ import type {
} from "@/modules/01_metadata/interface/request/organization/TelExternal";
import type { ResponseHistoryObject } from "@/modules/01_metadata/interface/response/organization/TelExternal";
import HistoryTable from "@/components/TableHistory.vue";
import { useDataStore } from "@/stores/data";
const props = defineProps({
fetchDataComponent: {
@ -199,8 +198,6 @@ const props = defineProps({
},
});
const dataStore = useDataStore();
const { loaderPage } = dataStore;
const mixin = useCounterMixin();
const { success, dateText, messageError, showLoader, hideLoader } = mixin;
const store = useManageDataStore();

View file

@ -190,7 +190,6 @@ import type {
} from "@/modules/01_metadata/interface/request/organization/TelInternal";
import type { ResponseHistoryObject } from "@/modules/01_metadata/interface/response/organization/TelInternal";
import HistoryTable from "@/components/TableHistory.vue";
import { useDataStore } from "@/stores/data";
const props = defineProps({
fetchDataComponent: {
@ -199,8 +198,6 @@ const props = defineProps({
},
});
const dataStore = useDataStore();
const { loaderPage } = dataStore;
const mixin = useCounterMixin();
const { success, dateText, messageError, showLoader, hideLoader } = mixin;
const store = useManageDataStore();

View file

@ -190,7 +190,6 @@ import type {
} from "@/modules/01_metadata/interface/request/organization/Type";
import type { ResponseHistoryObject } from "@/modules/01_metadata/interface/response/organization/Type";
import HistoryTable from "@/components/TableHistory.vue";
import { useDataStore } from "@/stores/data";
const props = defineProps({
fetchDataComponent: {
@ -199,8 +198,6 @@ const props = defineProps({
},
});
const dataStore = useDataStore();
const { loaderPage } = dataStore;
const mixin = useCounterMixin();
const { success, dateText, messageError, showLoader, hideLoader } = mixin;
const store = useManageDataStore();

View file

@ -194,7 +194,6 @@ import type {
} from "@/modules/01_metadata/interface/request/person/Blood";
import type { ResponseHistoryObject } from "@/modules/01_metadata/interface/response/person/Blood";
import HistoryTable from "@/components/TableHistory.vue";
import { useDataStore } from "@/stores/data";
const props = defineProps({
fetchDataComponent: {
@ -203,8 +202,6 @@ const props = defineProps({
},
});
const dataStore = useDataStore();
const { loaderPage } = dataStore;
const mixin = useCounterMixin();
const { success, dateText, messageError, showLoader, hideLoader } = mixin;
const store = useManageDataStore();

View file

@ -13,25 +13,20 @@
>
<q-tooltip>กล</q-tooltip>
</q-btn>
<div class="text-h6 text-dark text-weight-bold">การจดการขอมลเขต</div>
<q-space />
<q-breadcrumbs class="text-grey" active-color="blue">
<template v-slot:separator>
<q-icon
size="1.2em"
name="chevron_right"
color="blue"
/>
<q-icon size="1.2em" name="chevron_right" color="blue" />
</template>
<q-breadcrumbs-el to="/metadata" label="การจัดการข้อมูลจังหวัด" />
<q-breadcrumbs-el to="/metadata" label="การจัดการข้อมูลจังหวัด" />
<q-breadcrumbs-el label="การจัดการข้อมูลเขต" />
</q-breadcrumbs>
</div>
<q-form ref="myForm">
<q-card flat bordered class=" row col-12">
<q-card flat bordered class="row col-12">
<div class="col-xs-12">
<div class="q-mt-sm">
<data-table
@ -247,14 +242,13 @@ import type {
import type { ResponseHistoryObject } from "@/modules/01_metadata/interface/response/person/District";
import HistoryTable from "@/components/TableHistory.vue";
import { useRoute, useRouter } from "vue-router";
import { useDataStore } from "@/stores/data";
const mixin = useCounterMixin();
const { success, dateText, messageError, showLoader, hideLoader } = mixin;
const store = useManageDataStore();
const dataStore = useDataStore();
const { manageData, changeManageColumns, changeManageCurrentTab } = store;
const { loaderPage } = dataStore; // load api
const rows = ref<RequestItemsHistoryObject[]>([]); //list data table
const rowsHistory = ref<RequestItemsHistoryObject[]>([]); //select data history
const rawHistory = ref<RequestItemsHistoryObject[]>([]); //raw data history

View file

@ -191,7 +191,6 @@ import type {
} from "@/modules/01_metadata/interface/request/person/Education";
import type { ResponseHistoryObject } from "@/modules/01_metadata/interface/response/person/Education";
import HistoryTable from "@/components/TableHistory.vue";
import { useDataStore } from "@/stores/data";
const props = defineProps({
fetchDataComponent: {
@ -200,8 +199,6 @@ const props = defineProps({
},
});
const dataStore = useDataStore();
const { loaderPage } = dataStore;
const mixin = useCounterMixin();
const { success, dateText, messageError, showLoader, hideLoader } = mixin;
const store = useManageDataStore();

Some files were not shown because too many files have changed in this diff Show more