ปรับข้อมูลการลา และปรับ layout หน้าหลักการลา
This commit is contained in:
Warunee Tamkoo 2023-11-21 15:59:14 +07:00
parent 0705eff57c
commit 1ea53b0fe5
7 changed files with 1465 additions and 1521 deletions

View file

@ -1,253 +1,419 @@
<script setup lang="ts"> <script setup lang="ts">
import { ref, watch, onMounted } from "vue" import { ref, watch, onMounted } from "vue";
import FullCalendar from "@fullcalendar/vue3" import FullCalendar from "@fullcalendar/vue3";
import dayGridPlugin from "@fullcalendar/daygrid" import dayGridPlugin from "@fullcalendar/daygrid";
import type { CalendarOptions } from "@fullcalendar/core" import type { CalendarOptions } from "@fullcalendar/core";
import timeGridPlugin from "@fullcalendar/timegrid" import timeGridPlugin from "@fullcalendar/timegrid";
import interactionPlugin from "@fullcalendar/interaction" import interactionPlugin from "@fullcalendar/interaction";
import allLocales from "@fullcalendar/core/locales-all" import allLocales from "@fullcalendar/core/locales-all";
import listPlugin from "@fullcalendar/list" import listPlugin from "@fullcalendar/list";
import { useCounterMixin } from "@/stores/mixin";
import type { DataDateMonthObject } from "@/modules/05_leave/interface/request/Calendar.ts";
/** /**
* Option ของปฏ * Option ของปฏ
*/ */
const fullCalendar = ref<any>() //ref calendar const fullCalendar = ref<any>(); //ref calendar
const calendarOptions = ref<CalendarOptions>({ const calendarOptions = ref<CalendarOptions>({
plugins: [ plugins: [
dayGridPlugin, dayGridPlugin,
timeGridPlugin, timeGridPlugin,
interactionPlugin, // needed for dateClick interactionPlugin, // needed for dateClick
listPlugin, listPlugin,
], ],
buttonText: { // buttonText: {
listYear: "รายการ", // listYear: "",
dayGridMonth: "ปฏิทิน", // dayGridMonth: "",
test: "เพิ่มวันหยุด", // test: "",
}, // },
headerToolbar: false, headerToolbar: false,
initialView: "dayGridMonth", initialView: "dayGridMonth",
initialEvents: [], // alternatively, use the `events` setting to fetch from a feed initialEvents: [], // alternatively, use the `events` setting to fetch from a feed
selectable: true, selectable: true,
dayMaxEvents: true, dayMaxEvents: true,
weekends: true, weekends: true,
locale: "th", locale: "th",
locales: allLocales, locales: allLocales,
expandRows: true, expandRows: true,
nowIndicator: true, nowIndicator: true,
height: "100%", height: "100%",
eventColor: "#fff", eventColor: "#fff",
eventTextColor: "#4A5568", eventTextColor: "#4A5568",
eventBorderColor: "#50a5fc", eventBorderColor: "#50a5fc",
displayEventTime: false, displayEventTime: false,
editable: true, editable: true,
events: [ events: [
{ groupId: "3", title: "ลากิจส่วนตัว", start: "2023-10-10", allDay: true, status: "done", color: "#E3FDDA" }, {
{ groupId: "3", title: "ลากิจส่วนตัว", start: "2023-11-10", allDay: true, status: "done", color: "#E3FDDA" }, groupId: "2",
{ groupId: "3", title: "ลากิจส่วนตัว", start: "2023-10-11", allDay: true, status: "done", color: "#E3FDDA" }, title: "ลาป่วย",
{ groupId: "3", title: "ลากิจส่วนตัว", start: "2023-10-12", allDay: true, status: "done", color: "#E3FDDA" }, start: "2023-11-24",
{ groupId: "3", title: "ลากิจส่วนตัว", start: "2023-10-13", allDay: true, status: "done", color: "#E3FDDA" }, end: "2023-11-25",
{ groupId: "2", title: "ลาป่วย", start: "2023-10-19", allDay: true, status: "proceed", color: "#e4f3ff" }, allDay: true,
{ groupId: "1", title: "ลาป่วย", start: "2023-10-20", allDay: true, status: "new", color: "#FFF1CC" }, color: "#4CAF4F",
], textColor: "white",
}) },
{
groupId: "4",
title: "ลากิจ",
start: "2023-11-15",
allDay: true,
color: "#4CAF4F",
textColor: "white",
},
{
groupId: "4",
title: "นางสาวสมศรี ใจดี (ลากิจ)",
start: "2023-11-21",
end: "2023-11-23",
allDay: true,
color: "#ddd",
},
{
groupId: "4",
title: "นายสมชาย สุขใจ",
start: "2023-11-21",
allDay: true,
color: "#ddd",
},
],
});
/** /**
* วแปรทงหมด * วแปรทงหมด
*/ */
const modalCancel = ref(false) const modalCancel = ref(false);
const title = ref("") const title = ref("");
const location = ref("บ้าน") const location = ref("บ้าน");
const subject = ref("ลาป่วย") const subject = ref("ลาป่วย");
const dateStart = ref("20 ส.ค. 2566") const dateStart = ref("20 ส.ค. 2566");
const dateEnd = ref("21 ส.ค. 2566") const dateEnd = ref("21 ส.ค. 2566");
const numDate = ref("20") const numDate = ref("20");
const place = ref("บ้าน") const place = ref("บ้าน");
const phone = ref("000-00000000") const phone = ref("000-00000000");
const reason = ref("ยกเลิกการลา") const reason = ref("ยกเลิกการลา");
const model = ref(null) const model = ref(null);
const modeCancel = ref(true) const modeCancel = ref(true);
/** รับ props มาจากหน้าหลัก */ const dateMonth = ref<DataDateMonthObject>({
const props = defineProps({ month: new Date().getMonth(),
dateYear: { year: new Date().getFullYear(),
//filter });
type: Number,
default: () => new Date().getFullYear(),
},
dateMonth: {
//filter
type: Number,
default: () => new Date().getMonth(),
},
// refreshData: {
// // main refresh data
// type: Boolean,
// required: true,
// },
fetchDataSummaryCalendar: {
//
type: Function,
default: () => console.log("not function"),
},
})
const dateYear = ref<number>(new Date().getFullYear());
const emit = defineEmits(["update:dateYear"]);
const mixin = useCounterMixin(); //
const { monthYear2Thai } = mixin;
/** /**
* เรยกฟงกนทงหมดตอนเรยกใชไฟล * แปลง และเดอนเปนภาษาไทย
* @param val datepicker แบบเลอกปและเดอน
*/ */
onMounted(async () => { const monthYearThai = (val: DataDateMonthObject) => {
if (fullCalendar !== undefined) { if (val == null) return "";
const calen = fullCalendar.value.getApi() else return monthYear2Thai(val.month, val.year);
const date = new Date(props.dateYear, props.dateMonth) };
calen.gotoDate(date)
}
})
/** const updateMonth = async (e: DataDateMonthObject) => {
* props(นเดอนปเลอก) ตอนอพเดท าฏนใหพเดทใหม // console.log(dateMonth.value);
*/ if (e != null) {
watch(props, async (count, prevCount) => { dateYear.value = e.year;
const calen = fullCalendar.value.getApi() emit("update:dateYear", e.year);
const date = new Date(props.dateYear, props.dateMonth) const calen = fullCalendar.value.getApi();
calen.gotoDate(date) const date = new Date(dateMonth.value.year, dateMonth.value.month);
}) calen.gotoDate(date);
}
};
/** /**
* งกนยกเล model * งกนยกเล model
* @param text * @param text
*/ */
const cancel = async (text: string) => { const cancel = async (text: string) => {
title.value = text title.value = text;
modalCancel.value = true modalCancel.value = true;
modeCancel.value = true modeCancel.value = true;
} };
/** /**
* งกนเป model * งกนเป model
* @param text * @param text
*/ */
const view = async (text: string) => { const view = async (text: string) => {
title.value = text title.value = text;
modalCancel.value = true modalCancel.value = true;
modeCancel.value = false modeCancel.value = false;
} };
// filter calendar left
const filterLists = ref<any[]>([
{
id: "x1",
name: "นางสาววารุณี แต้มคู",
color: "green",
},
{
id: "x2",
name: "นางสาวสมศรี ใจดี",
color: "grey",
},
{
id: "x3",
name: "นายสมชาย สุขใจ",
color: "grey",
},
]);
const filterVal = ref(["x1"]);
</script> </script>
<template> <template>
<div class="q-mt-sm"> <div class="row">
<div class="row q-gutter-sm q-pb-sm main-content"> <!-- Filter ตามคนและประเภทการลา -->
<div class="demo-app-main"> <div class="col-sm-12 col-md-3 q-mt-sm q-pr-sm">
<FullCalendar ref="fullCalendar" class="demo-app-calendar" :options="calendarOptions"> <q-card class="col-12">
<template v-slot:eventContent="arg"> <div class="q-gutter-sm">
<div class="row col-12 items-center no-wrap" :style="`background: + ${arg.event.color}`"> <q-list bordered class="rounded-borders">
<!-- <b>{{ arg.timeText }}</b> --> <!-- <q-item-label header>User</q-item-label> -->
<div class="textHover col-10" @click="view(arg.event.title)">{{ arg.event.title }}</div> <q-item
<q-btn dense v-if="arg.event.groupId == 1" icon="mdi-close" flat round size="8px" @click="cancel(arg.event.title)" /> v-for="(item, i) in filterLists"
</div> :key="i"
</template> tag="label"
</FullCalendar> v-ripple
</div> >
</div> <q-checkbox
<div class="row q-col-gutter-lg justify-end"> size="sm"
<div class="items-center row"> v-model="filterVal"
<q-icon size="10px" color="light-green" name="mdi-circle" class="q-mr-sm" /> :val="item.id"
<span class="text-caption text-grey-8">สถานะอน</span> :color="item.color"
</div> />
<div class="items-center row"> <q-item-section>
<q-icon size="10px" color="red-6" name="mdi-circle" class="q-mr-sm" /> <q-item-label>{{ item.name }}</q-item-label>
<span class="text-caption text-grey-8">สถานะไมอน</span> </q-item-section>
</div> </q-item>
<div class="items-center row"> </q-list>
</div>
<!-- show value filterVal -->
<!-- <div class="q-px-sm q-mt-sm">
Your selection is: <strong>{{ filterVal }}</strong>
</div> -->
</q-card>
</div>
<div class="col-sm-12 col-md-9">
<div class="q-mt-sm">
<div class="row col-12 q-gutter-sm">
<div class="demo-app-main">
<q-card bordered flat class="q-pa-sm col-12 row bg-grey-1 shadow-0">
<div class="items-center col-12 row q-col-gutter-sm">
<!-- filter เลอกเดอนป -->
<datepicker
v-model="dateMonth"
:locale="'th'"
autoApply
month-picker
:enableTimePicker="false"
@update:modelValue="updateMonth"
>
<template #year="{ year }">{{ year + 543 }}</template>
<template #year-overlay-value="{ value }">{{
parseInt(value + 543)
}}</template>
<template #trigger>
<q-input
:model-value="monthYearThai(dateMonth)"
dense
outlined
bg-color="white"
style="width: 130px"
>
<template v-slot:prepend>
<q-icon
name="event"
class="cursor-pointer"
style="color: var(--q-primary)"
>
</q-icon>
</template>
</q-input>
</template>
</datepicker>
</div>
</q-card>
<div class="main-content">
<FullCalendar
ref="fullCalendar"
class="demo-app-calendar"
:options="calendarOptions"
>
<template v-slot:eventContent="arg">
<div
class="row col-12 items-center no-wrap"
:style="`background: + ${arg.event.color}`"
>
<!-- <b>{{ arg.timeText }}</b> -->
<div
class="textHover col-10"
@click="view(arg.event.title)"
>
{{ arg.event.title }}
</div>
<q-btn
dense
v-if="arg.event.groupId == 1"
icon="mdi-close"
flat
round
size="8px"
@click="cancel(arg.event.title)"
/>
</div>
</template>
</FullCalendar>
</div>
</div>
</div>
<div class="row q-col-gutter-lg justify-end">
<div class="items-center row">
<q-icon
size="10px"
color="green-7"
name="mdi-circle"
class="q-mr-sm"
/>
<span class="text-caption text-grey-8">การลาของฉ</span>
</div>
<div class="items-center row">
<q-icon
size="10px"
color="grey-6"
name="mdi-circle"
class="q-mr-sm"
/>
<span class="text-caption text-grey-8">การลาของบคคลอ</span>
</div>
<!-- <div class="items-center row">
<q-icon size="10px" color="light-blue-14" name="mdi-circle" class="q-mr-sm" /> <q-icon size="10px" color="light-blue-14" name="mdi-circle" class="q-mr-sm" />
<span class="text-caption text-grey-8">สถานะอยระหวางดำเนนการ</span> <span class="text-caption text-grey-8">สถานะอยระหวางดำเนนการ</span>
</div> </div>
<div class="items-center row"> <div class="items-center row">
<q-icon size="10px" color="orange" name="mdi-circle" class="q-mr-sm" /> <q-icon size="10px" color="orange" name="mdi-circle" class="q-mr-sm" />
<span class="text-caption text-grey-8">สถานะใหม</span> <span class="text-caption text-grey-8">สถานะใหม</span>
</div> </div> -->
</div> </div>
</div> </div>
</div>
</div>
<!-- modal ขอยกเล/รายละเอยด --> <!-- modal รายละเอยด -->
<q-dialog v-model="modalCancel" persistent> <q-dialog v-model="modalCancel" persistent>
<q-card :style="modeCancel == true ? 'min-width: 50%;' : 'min-width:30%'"> <q-card :style="modeCancel == true ? 'min-width: 50%;' : 'min-width:30%'">
<q-card-section class="row items-center q-pa-sm"> <q-card-section class="row items-center q-pa-sm">
<div v-if="modeCancel == false" class="text-bold q-pl-sm">รายละเอียดของ{{ title }}</div> <div v-if="modeCancel == false" class="text-bold q-pl-sm">
<div v-else class="text-bold q-pl-sm">ขอยกเล{{ title }}</div> รายละเอยดของ{{ title }}
<q-space /> </div>
<q-btn icon="close" unelevated round dense v-close-popup style="color: #ff8080; background-color: #ffdede" /> <div v-else class="text-bold q-pl-sm">ขอยกเล{{ title }}</div>
</q-card-section> <q-space />
<q-separator /> <q-btn
<q-card-section class="q-p-md row q-gutter-y-md"> icon="close"
<div flat :class="modeCancel == true ? 'col-xs-6 col-sm-6' : 'col-12'"> unelevated
<div class="col-12 q-col-gutter-sm row items-center"> round
<div class="col-6 text-grey-7">เขยนท</div> dense
<div class="col-6 text-black">{{ location }}</div> v-close-popup
<div class="col-6 text-grey-7">เรองและเหตผลการลา</div> style="color: #ff8080; background-color: #ffdede"
<div class="col-6 text-black">{{ subject }}</div> />
<div class="col-6 text-grey-7"> เดอน เรมต</div> </q-card-section>
<div class="col-6 text-black">{{ dateStart }}</div> <q-separator />
<div class="col-6 text-grey-7"> เดอน นส</div> <q-card-section class="q-p-md row q-gutter-y-md">
<div class="col-6 text-black">{{ dateEnd }}</div> <div flat :class="modeCancel == true ? 'col-xs-6 col-sm-6' : 'col-12'">
<div class="col-6 text-grey-7">จำนวนวนทลา</div> <div class="col-12 q-col-gutter-sm row items-center">
<div class="col-6 text-black">{{ numDate }}</div> <div class="col-6 text-grey-7">เขยนท</div>
<div class="col-6 text-grey-7">สถานทดตอขณะลา</div> <div class="col-6 text-black">{{ location }}</div>
<div class="col-6 text-black">{{ place }}</div> <div class="col-6 text-grey-7">เรองและเหตผลการลา</div>
<div class="col-6 text-grey-7">หมายเลขโทรศพท</div> <div class="col-6 text-black">{{ subject }}</div>
<div class="col-6 text-black">{{ phone }}</div> <div class="col-6 text-grey-7"> เดอน เรมต</div>
</div> <div class="col-6 text-black">{{ dateStart }}</div>
</div> <div class="col-6 text-grey-7"> เดอน นส</div>
<div flat class="col-xs-6 col-sm-6" v-if="modeCancel == true"> <div class="col-6 text-black">{{ dateEnd }}</div>
<q-input v-model="reason" type="textarea" label="กรอกเหตุผล" outlined dense /> <div class="col-6 text-grey-7">จำนวนวนทลา</div>
<q-file outlined v-model="model" label="เลือกไฟล์เอกสารหลักฐาน" class="q-mt-md" use-chips dense> <div class="col-6 text-black">{{ numDate }}</div>
<template v-slot:prepend> <div class="col-6 text-grey-7">สถานทดตอขณะลา</div>
<q-icon name="attach_file" /> <div class="col-6 text-black">{{ place }}</div>
</template> <div class="col-6 text-grey-7">หมายเลขโทรศพท</div>
</q-file> <div class="col-6 text-black">{{ phone }}</div>
</div> </div>
</q-card-section> </div>
<q-separator /> <div flat class="col-xs-6 col-sm-6" v-if="modeCancel == true">
<q-card-section class="row items-center q-pa-sm" v-if="modeCancel == true"> <q-input
<q-space /> v-model="reason"
<q-btn label="ยืนยัน" unelevated color="secondary" dense class="q-px-md" v-close-popup /> type="textarea"
</q-card-section> label="กรอกเหตุผล"
</q-card> outlined
</q-dialog> dense
/>
<q-file
outlined
v-model="model"
label="เลือกไฟล์เอกสารหลักฐาน"
class="q-mt-md"
use-chips
dense
>
<template v-slot:prepend>
<q-icon name="attach_file" />
</template>
</q-file>
</div>
</q-card-section>
<q-separator />
<q-card-section
class="row items-center q-pa-sm"
v-if="modeCancel == true"
>
<q-space />
<q-btn
label="ยืนยัน"
unelevated
color="secondary"
dense
class="q-px-md"
v-close-popup
/>
</q-card-section>
</q-card>
</q-dialog>
</template> </template>
<style scope lang="scss"> <style scope lang="scss">
.main-content { .main-content {
height: 65vh; height: 70vh;
}
.color-main {
color: #18a259;
} }
.padding-content { .padding-content {
padding: 10px; padding: 10px;
} }
.demo-app-main { .demo-app-main {
flex-grow: 1; flex-grow: 1;
/* padding: 3em; */ /* padding: 3em; */
} }
.fc { .fc {
/* the calendar root */ /* the calendar root */
max-width: 1100px; max-width: 1100px;
margin: 0 auto; margin: 0 auto;
background-color: white; background-color: white;
border-radius: 10px; border-radius: 10px;
} }
.fc-day-today { .fc-day-today {
background-color: #f8f8f8 !important; background-color: #f8f8f8 !important;
} }
.fc-day-today .fc-daygrid-day-number { .fc-day-today .fc-daygrid-day-number {
display: flex; display: flex;
justify-content: center; justify-content: center;
align-items: center; align-items: center;
/* border: 2px solid #17a259; */ /* border: 2px solid #17a259; */
/* border-radius: 50%; /* border-radius: 50%;
height: 25px; height: 25px;
width: 25px; width: 25px;
font-weight: bold; font-weight: bold;
@ -256,123 +422,123 @@ const view = async (text: string) => {
} }
.fc-day-today .fc-daygrid-day-frame { .fc-day-today .fc-daygrid-day-frame {
padding: 5%; padding: 5%;
} }
.fc .fc-button-group > .fc-button { .fc .fc-button-group > .fc-button {
color: black; color: black;
background-color: #fafafa; background-color: #fafafa;
border: none; border: none;
} }
.fc .fc-button-group > .fc-button:active { .fc .fc-button-group > .fc-button:active {
color: white; color: white;
background-color: #22a15e; background-color: #22a15e;
border: none; border: none;
} }
.fc .fc-button-group > .fc-button.fc-button-active { .fc .fc-button-group > .fc-button.fc-button-active {
color: white; color: white;
background-color: #22a15e; background-color: #22a15e;
border: none; border: none;
} }
.fc-header-toolbar { .fc-header-toolbar {
background-color: white; background-color: white;
padding: 0px 10px 0px 10px; padding: 0px 10px 0px 10px;
border-radius: 10px 10px 0px 0px; border-radius: 10px 10px 0px 0px;
} }
.fc .fc-scrollgrid-liquid > thead { .fc .fc-scrollgrid-liquid > thead {
background-color: white; background-color: white;
} }
.dp-custom-cell { .dp-custom-cell {
border-radius: 50%; border-radius: 50%;
} }
.dp__today { .dp__today {
border: 1px solid var(--q-primary); border: 1px solid var(--q-primary);
} }
.dp__range_end, .dp__range_end,
.dp__range_start, .dp__range_start,
.dp__active_date { .dp__active_date {
background: var(--q-primary); background: var(--q-primary);
color: var(--dp-primary-text-color); color: var(--dp-primary-text-color);
} }
.datepicker .q-field__label { .datepicker .q-field__label {
padding-left: 5px; padding-left: 5px;
} }
.datepicker .q-field__messages { .datepicker .q-field__messages {
padding-left: 20px; padding-left: 20px;
} }
.datepicker .q-field__native { .datepicker .q-field__native {
padding-left: 5px; padding-left: 5px;
color: var(--q-primary) !important; color: var(--q-primary) !important;
} }
.datepicker .q-field__prepend { .datepicker .q-field__prepend {
padding-left: 6px; padding-left: 6px;
} }
.datepicker .q-field__append { .datepicker .q-field__append {
padding-right: 6px; padding-right: 6px;
} }
.datepicker .q-field__after { .datepicker .q-field__after {
display: flex; display: flex;
justify-content: flex-end; justify-content: flex-end;
align-items: center; align-items: center;
font-weight: 500; font-weight: 500;
} }
.fc .fc-popover { .fc .fc-popover {
z-index: 6000; z-index: 6000;
} }
.fc-direction-ltr .fc-daygrid-event.fc-event-end, .fc-direction-ltr .fc-daygrid-event.fc-event-end,
.fc-direction-rtl .fc-daygrid-event.fc-event-start { .fc-direction-rtl .fc-daygrid-event.fc-event-start {
cursor: pointer; cursor: pointer;
} }
.subName { .subName {
display: flex; display: flex;
justify-content: flex-end; justify-content: flex-end;
align-items: center; align-items: center;
font-weight: 500; font-weight: 500;
} }
.subInput { .subInput {
display: flex; display: flex;
align-items: center; align-items: center;
} }
.fc-event { .fc-event {
overflow: hidden; overflow: hidden;
border-color: transparent !important; border-color: transparent !important;
font-weight: 500; font-weight: 500;
} }
.fc-event-main { .fc-event-main {
text-align: left; text-align: left;
padding: 0px 5px; padding: 0px 5px;
} }
.fc-direction-ltr .fc-daygrid-event.fc-event-end, .fc-direction-ltr .fc-daygrid-event.fc-event-end,
.fc-direction-rtl .fc-daygrid-event.fc-event-start { .fc-direction-rtl .fc-daygrid-event.fc-event-start {
padding-left: 0px; padding-left: 0px;
} }
.fc-theme-standard td, .fc-theme-standard td,
.fc-theme-standard th { .fc-theme-standard th {
border: 1px solid #ebe9f1; border: 1px solid #ebe9f1;
} }
.textHover:hover { .textHover:hover {
color: #18a259; color: var(--q-primary);
} }
</style> </style>

View file

@ -1,153 +1,219 @@
<script setup lang="ts"> <script setup lang="ts">
import type { QTableProps } from "quasar" import type { QTableProps } from "quasar";
import { ref, onMounted } from "vue" import { ref, onMounted } from "vue";
import Table from "@/modules/05_leave/componenst/Table.vue" import Table from "@/modules/05_leave/componenst/Table.vue";
import { useLeaveStore } from "@/modules/05_leave/store" import { useLeaveStore } from "@/modules/05_leave/store";
const LeaveData = useLeaveStore() const LeaveData = useLeaveStore();
const { fecthList, searchFilterTable } = LeaveData const { fecthList, searchFilterTable } = LeaveData;
const filter = ref<string>("") const filter = ref<string>("");
/** /**
* งค pagination * งค pagination
*/ */
const initialPagination = ref({ const initialPagination = ref({
rowsPerPage: 0, rowsPerPage: 0,
}) });
/** /**
* mocking าในตวแปร * mocking าในตวแปร
*/ */
const modalCancel = ref(false) const modalCancel = ref(false);
const title = ref("") const title = ref("");
const location = ref("บ้าน") const location = ref("บ้าน");
const subject = ref("ลาป่วย") const subject = ref("ลาป่วย");
const dateStart = ref("20 ส.ค. 2566") const dateStart = ref("20 ส.ค. 2566");
const dateEnd = ref("21 ส.ค. 2566") const dateEnd = ref("21 ส.ค. 2566");
const numDate = ref("20") const numDate = ref("20");
const place = ref("บ้าน") const place = ref("บ้าน");
const phone = ref("000-00000000") const phone = ref("000-00000000");
const reason = ref("ยกเลิกการลา") const reason = ref("ยกเลิกการลา");
const model = ref(null) const writeAt = ref<string>("");
const modeCancel = ref(true) const model = ref(null);
const modeCancel = ref(true);
/** /**
* งกนยกเล model * งกนยกเล model
* @param text * @param text
*/ */
const cancel = async (text: string) => { const cancel = async (text: string) => {
title.value = text title.value = text;
modalCancel.value = true modalCancel.value = true;
modeCancel.value = true modeCancel.value = true;
} };
/** /**
* งกนเป model * งกนเป model
* @param text * @param text
*/ */
const view = async (text: string) => { const view = async (text: string) => {
title.value = text title.value = text;
modalCancel.value = true modalCancel.value = true;
modeCancel.value = false modeCancel.value = false;
} };
/** /**
* เรยกฟงกนทงหมดตอนเรยกใชไฟล * เรยกฟงกนทงหมดตอนเรยกใชไฟล
*/ */
onMounted(async () => { onMounted(async () => {
searchFilterTable() searchFilterTable();
fecthList([ fecthList([
{ no: "1", date: "2023-09-20", type: "1", status: "4", year: "1" }, { no: "1", date: "2023-09-20", type: "1", status: "4", year: "1" },
{ no: "2", date: "2023-09-19", type: "1", status: "2", year: "1" }, { no: "2", date: "2023-09-19", type: "1", status: "2", year: "1" },
{ no: "3", date: "2023-09-10", type: "2", status: "3", year: "1" }, { no: "3", date: "2023-09-10", type: "2", status: "3", year: "1" },
]) ]);
}) });
</script> </script>
<template> <template>
<Table <Table
:style="$q.screen.gt.xs ? 'height: 58.5vh' : ''" :style="$q.screen.gt.xs ? 'height: 58.5vh' : ''"
:rows="LeaveData.rows" :rows="LeaveData.rows"
:columns="LeaveData.columns" :columns="LeaveData.columns"
:filter="filter" :filter="filter"
:visible-columns="LeaveData.visibleColumns" :visible-columns="LeaveData.visibleColumns"
v-model:inputfilter="filter" v-model:inputfilter="filter"
v-model:inputvisible="LeaveData.visibleColumns" v-model:inputvisible="LeaveData.visibleColumns"
:pagination="initialPagination" :pagination="initialPagination"
:inputShow="true" :inputShow="true"
:grid="$q.screen.gt.xs ? false : true" :grid="$q.screen.gt.xs ? false : true"
> >
<template #columns="props"> <template #columns="props">
<q-tr :props="props" class="cursor-pointer"> <q-tr :props="props" class="cursor-pointer">
<q-td key="no" :props="props" @click="view(props.row.type)"> <q-td key="no" :props="props" @click="view(props.row.type)">
{{ props.rowIndex + 1 }} {{ props.rowIndex + 1 }}
</q-td> </q-td>
<q-td key="type" :props="props" @click="view(props.row.type)"> <q-td key="type" :props="props" @click="view(props.row.type)">
{{ props.row.type }} {{ props.row.type }}
</q-td> </q-td>
<q-td key="date" :props="props" @click="view(props.row.type)"> <q-td key="date" :props="props" @click="view(props.row.type)">
{{ props.row.date }} {{ props.row.date }}
</q-td> </q-td>
<q-td key="status" :props="props"> <q-td key="status" :props="props">
<div class="col-12 row items-center"> <div class="col-12 row items-center">
<div @click="view(props.row.type)"> <div @click="view(props.row.type)">
<q-icon v-if="props.row.status == 'อนุมัติ'" size="10px" color="light-green" name="mdi-circle" class="q-mr-sm" /> <q-icon
<q-icon v-else-if="props.row.status == 'ไม่อนุมัติ'" size="10px" color="red-6" name="mdi-circle" class="q-mr-sm" /> v-if="props.row.status == 'อนุมัติ'"
<q-icon v-else-if="props.row.status == 'อยู่ระหว่างดำเนินการ'" size="10px" color="light-blue-14" name="mdi-circle" class="q-mr-sm" /> size="10px"
<q-icon v-else-if="props.row.status == 'ใหม่'" size="10px" color="orange" name="mdi-circle" class="q-mr-sm" /> color="light-green"
<span class="q-pr-md">{{ props.row.status }}</span> name="mdi-circle"
</div> class="q-mr-sm"
<q-space /> />
<q-btn v-if="props.row.status == 'ใหม่'" label="ขอยกเลิก" @click="cancel(props.row.type)" size="13px" class="q-px-sm" outline dense color="orange" /> <q-icon
</div> v-else-if="props.row.status == 'ไม่อนุมัติ'"
</q-td> size="10px"
</q-tr> color="red-6"
</template> name="mdi-circle"
</Table> class="q-mr-sm"
/>
<q-icon
v-else-if="props.row.status == 'อยู่ระหว่างดำเนินการ'"
size="10px"
color="light-blue-14"
name="mdi-circle"
class="q-mr-sm"
/>
<q-icon
v-else-if="props.row.status == 'ใหม่'"
size="10px"
color="orange"
name="mdi-circle"
class="q-mr-sm"
/>
<span class="q-pr-md">{{ props.row.status }}</span>
</div>
<q-space />
<q-btn
v-if="props.row.status == 'ใหม่'"
label="ขอยกเลิก"
@click="cancel(props.row.type)"
size="13px"
class="q-px-sm"
outline
dense
color="orange"
/>
</div>
</q-td>
</q-tr>
</template>
</Table>
<!-- modal ขอยกเล/รายละเอยด --> <!-- modal ขอยกเล/รายละเอยด -->
<q-dialog v-model="modalCancel" persistent> <q-dialog v-model="modalCancel" persistent>
<q-card :style="modeCancel == true ? 'min-width: 50%;' : 'min-width:30%'"> <q-card :style="modeCancel == true ? 'min-width: 50%;' : 'min-width:30%'">
<q-card-section class="row items-center q-pa-sm"> <q-card-section class="row items-center q-pa-sm">
<div v-if="modeCancel == false" class="text-bold q-pl-sm">รายละเอียดของ{{ title }}</div> <div v-if="modeCancel == false" class="text-bold q-pl-sm">
<div v-else class="text-bold q-pl-sm">ขอยกเล{{ title }}</div> รายละเอยดของ{{ title }}
<q-space /> </div>
<q-btn icon="close" unelevated round dense v-close-popup style="color: #ff8080; background-color: #ffdede" /> <div v-else class="text-bold q-pl-sm">ขอยกเล{{ title }}</div>
</q-card-section> <q-space />
<q-separator /> <q-btn
<q-card-section class="q-p-md row q-gutter-y-md"> icon="close"
<div flat :class="modeCancel == true ? 'col-xs-6 col-sm-6' : 'col-12'"> unelevated
<div class="col-12 q-col-gutter-sm row items-center"> round
<div class="col-6 text-grey-7">เขยนท</div> dense
<div class="col-6 text-black">{{ location }}</div> v-close-popup
<div class="col-6 text-grey-7">เรองและเหตผลการลา</div> style="color: #ff8080; background-color: #ffdede"
<div class="col-6 text-black">{{ subject }}</div> />
<div class="col-6 text-grey-7"> เดอน เรมต</div> </q-card-section>
<div class="col-6 text-black">{{ dateStart }}</div> <q-separator />
<div class="col-6 text-grey-7"> เดอน นส</div> <q-card-section class="q-p-md row q-gutter-y-md">
<div class="col-6 text-black">{{ dateEnd }}</div> <div flat :class="modeCancel == true ? 'col-xs-6 col-sm-6' : 'col-12'">
<div class="col-6 text-grey-7">จำนวนวนทลา</div> <div class="col-12 q-col-gutter-sm row items-center">
<div class="col-6 text-black">{{ numDate }}</div> <div class="col-6 text-grey-7">เรองและเหตผลการลา</div>
<div class="col-6 text-grey-7">สถานทดตอขณะลา</div> <div class="col-6 text-black">{{ subject }}</div>
<div class="col-6 text-black">{{ place }}</div> <div class="col-6 text-grey-7"> เดอน เรมต</div>
<div class="col-6 text-grey-7">หมายเลขโทรศพท</div> <div class="col-6 text-black">{{ dateStart }}</div>
<div class="col-6 text-black">{{ phone }}</div> <div class="col-6 text-grey-7"> เดอน นส</div>
</div> <div class="col-6 text-black">{{ dateEnd }}</div>
</div> <div class="col-6 text-grey-7">จำนวนวนทลา</div>
<div flat class="col-xs-6 col-sm-6" v-if="modeCancel == true"> <div class="col-6 text-black">{{ numDate }}</div>
<q-input v-model="reason" type="textarea" label="กรอกเหตุผล" outlined dense /> <div class="col-6 text-grey-7">สถานทดตอขณะลา</div>
<q-file outlined v-model="model" label="เลือกไฟล์เอกสารหลักฐาน" class="q-mt-md" use-chips dense> <div class="col-6 text-black">{{ place }}</div>
<template v-slot:prepend> <div class="col-6 text-grey-7">หมายเลขโทรศพท</div>
<q-icon name="attach_file" /> <div class="col-6 text-black">{{ phone }}</div>
</template> </div>
</q-file> </div>
</div> <div flat class="col-xs-6 col-sm-6" v-if="modeCancel == true">
</q-card-section> <q-input v-model="writeAt" label="เขียนที่" outlined dense />
<q-separator /> <q-input
<q-card-section class="row items-center q-pa-sm" v-if="modeCancel == true"> v-model="reason"
<q-space /> type="textarea"
<q-btn label="ยืนยัน" unelevated color="secondary" dense class="q-px-md" v-close-popup /> label="กรอกเหตุผล"
</q-card-section> class="q-mt-md"
</q-card> outlined
</q-dialog> dense
/>
<q-file
outlined
v-model="model"
label="เลือกไฟล์เอกสารหลักฐาน"
class="q-mt-md"
use-chips
dense
>
<template v-slot:prepend>
<q-icon name="attach_file" />
</template>
</q-file>
</div>
</q-card-section>
<q-separator />
<q-card-section
class="row items-center q-pa-sm"
v-if="modeCancel == true"
>
<q-space />
<q-btn
label="ยืนยัน"
unelevated
color="secondary"
dense
class="q-px-md"
v-close-popup
/>
</q-card-section>
</q-card>
</q-dialog>
</template> </template>

View file

@ -2,8 +2,8 @@
import { ref, useAttrs, reactive, onMounted } from "vue" import { ref, useAttrs, reactive, onMounted } from "vue"
import { useLeaveStore } from "@/modules/05_leave/store" import { useLeaveStore } from "@/modules/05_leave/store"
const LeaveData = useLeaveStore() const leaveStore = useLeaveStore()
const { filterSelector, searchFilterTable } = LeaveData const { filterSelector, searchFilterTable } = leaveStore
const attrs = ref<any>(useAttrs()) const attrs = ref<any>(useAttrs())
const table = ref<any>(null) const table = ref<any>(null)
const filterRef = ref<any>(null) const filterRef = ref<any>(null)
@ -59,18 +59,38 @@ const resetFilter = () => {
<div class="q-py-sm row"> <div class="q-py-sm row">
<q-card bordered flat class="q-py-sm q-pl-sm col-12 row bg-grey-1 shadow-0"> <q-card bordered flat class="q-py-sm q-pl-sm col-12 row bg-grey-1 shadow-0">
<div class="items-center col-12 row q-col-gutter-sm"> <div class="items-center col-12 row q-col-gutter-sm">
<q-select
v-if="leaveStore.tabValue === 'list'"
outlined
dense
lazy-rules
v-model="leaveStore.fiscalYearyear"
:label="`${'ปี พ.ศ.'}`"
emit-value
map-options
option-label="name"
:options="leaveStore.fiscalyearOP"
option-value="id"
hide-bottom-space
style="min-width: 150px"
class="col-xs-12 col-sm-auto"
@update:model-value="searchFilterTable"
@filter="(inputValue:any,
doneFn:Function) => filterSelector(inputValue, doneFn,'fiscalyearOP'
) "
/>
<!-- นหาขอความใน table --> <!-- นหาขอความใน table -->
<q-select <q-select
outlined outlined
dense dense
lazy-rules lazy-rules
v-model="LeaveData.LeaveType" v-model="leaveStore.LeaveType"
:rules="[val => !!val || `${'กรุณาเลือกประเภทใบลา'}`]" :rules="[val => !!val || `${'กรุณาเลือกประเภทใบลา'}`]"
:label="`${'ประเภทใบลา'}`" :label="`${'ประเภทใบลา'}`"
emit-value emit-value
map-options map-options
option-label="name" option-label="name"
:options="LeaveData.typeOptions" :options="leaveStore.typeOptions"
option-value="id" option-value="id"
hide-bottom-space hide-bottom-space
style="min-width: 150px" style="min-width: 150px"
@ -84,13 +104,13 @@ const resetFilter = () => {
outlined outlined
dense dense
lazy-rules lazy-rules
v-model="LeaveData.LeaveStatus" v-model="leaveStore.LeaveStatus"
:rules="[val => !!val || `${'กรุณาเลือกสถานะ'}`]" :rules="[val => !!val || `${'กรุณาเลือกสถานะ'}`]"
:label="`${'สถานะ'}`" :label="`${'สถานะ'}`"
emit-value emit-value
map-options map-options
option-label="name" option-label="name"
:options="LeaveData.statusOptions" :options="leaveStore.statusOptions"
option-value="id" option-value="id"
hide-bottom-space hide-bottom-space
style="min-width: 150px" style="min-width: 150px"

View file

@ -1,374 +0,0 @@
<script setup lang="ts">
import { ref, onMounted } from "vue"
import { useQuasar } from "quasar"
import { useRouter, useRoute } from "vue-router"
import { useCounterMixin } from "@/stores/mixin"
import { useLeaveStore } from "@/modules/05_leave/store"
import http from "@/plugins/http"
import config from "@/app.config"
import type { QForm } from "quasar"
const mixin = useCounterMixin()
const dataStore = useLeaveStore()
const { date2Thai, dateToISO, success, messageError, showLoader, hideLoader } = mixin
const router = useRouter()
const route = useRoute()
const myform = ref<QForm | null>(null)
const $q = useQuasar()
const routeName = router.currentRoute.value.name
const id = ref<string>("")
const fileDocDataUpload = ref<File[]>([])
const files = ref<any>()
const locationAbsence = ref<string>("")
const levelStudy = ref<string>("")
const degree = ref<string>("")
const major = ref<string>("")
const educational = ref<string>("")
const studyPeriod = ref<string>("")
const country = ref<string>("")
const capital = ref<string>("")
const tel = ref<number>()
const detail = ref<string>()
const Writeat = ref<string>()
const dateLeaveStart = ref<Date>(new Date())
const dateLeaveEnd = ref<Date>(new Date())
const dateTotal = ref<number>()
const noteReason = ref("")
const nameFile = ref<string>("")
const model = ref(null)
const modelSpecific = ref(null)
const options = ref([
{ id: "0", name: "ลาป่วย" },
{ id: "1", name: "ลากิจส่วนตัว" },
{ id: "2", name: "ลาคลอดบุตร" },
{ id: "3", name: "ลาไปช่วยเหลือภริยาที่คลอดบุตร" },
{ id: "4", name: "ลาพักผ่อน" },
{ id: "5", name: "ลาอุปสมบทหรือลาประกอบพิธีฮัจย์ฯ" },
{ id: "6", name: "ลาเข้ารับการตรวจเลือกหรือเข้ารับการเตรียมพล" },
{ id: "7", name: "ลาไปศึกษา ฝึกอบรม ปฎิบัติการวิจัย หรือดูงาน" },
{ id: "8", name: "ลาไปปฎิบัติงานในองค์การระหว่างประเทศ" },
{ id: "9", name: "ลาติดตามคู่สมรส" },
{ id: "10", name: "ลาไปฟื้นฟูสมรรถภาพด้านอาชีพ" },
])
const optionsSpecific = ref([
{ id: "0", name: "ลาไปศึกษา" },
{ id: "1", name: "ฝึกอบรม" },
{ id: "2", name: "ปฎิบัติการวิจัย" },
{ id: "3", name: "ดูงาน" },
])
const dataDetail = ref<any>({
datetext: "",
activeDate: new Date(),
createdAt: new Date(),
firstName: "",
id: "",
isActive: true,
lastName: "",
location: "",
organizationPositionOld: "",
positionLevelOld: "",
positionNumberOld: "",
positionTypeOld: "",
prefix: "",
profileId: "",
reason: "",
salary: 0,
sendDate: new Date(),
status: "",
statustext: "",
fullname: "",
})
const clickBack = () => {
router.push(`/leave`)
}
onMounted(() => {})
const saveAbsence = () => {
$q.dialog({
title: "ยืนยันการยื่นใบลา",
message: "ต้องการยืนยันการยื่นใบลานี้ใช่หรือไม่?",
cancel: {
flat: true,
color: "negative",
},
persistent: true,
})
.onOk(() => {
// createFormresign()
if (model.value !== "ลาไปศึกษา ฝึกอบรม ปฎิบัติการวิจัย หรือดูงาน") {
console.log(1)
} else if (model.value === "ลาไปศึกษา ฝึกอบรม ปฎิบัติการวิจัย หรือดูงาน") {
console.log(2)
}
router.push(`/leave`)
})
.onCancel(() => {})
.onDismiss(() => {})
}
</script>
<template>
<div class="col-12 row justify-center">
<div class="col-xs-12 col-sm-12 col-md-11">
<div class="toptitle text-white col-12 row items-center">
<q-btn icon="mdi-arrow-left" unelevated round dense flat color="primary" class="q-mr-sm" @click="clickBack" />
<div>นใบลา</div>
</div>
<q-form ref="myform" class="col-12">
<q-card bordered>
<div class="col-12 row q-col-gutter-md q-pa-md">
<div class="col-xs-12 col-sm-12">
<q-icon name="mdi-numeric-1-circle" size="20px" color="primary" />
<div class="q-pl-sm text-weight-bold text-dark">เลอกประเภทการลา</div>
<div class="col-12 row q-pa-sm q-col-gutter-sm">
<q-select dense class="q-ml-lg col-6" outlined v-model="model" :options="dataStore.optionsSpecific" prefix="ประเภทใบลา :" />
<div class="col-6 row q-pa-sm" v-if="model == 'ลาไปศึกษา ฝึกอบรม ปฎิบัติการวิจัย หรือดูงาน'">
<q-select dense class="q-ml-lg col-6" outlined v-model="modelSpecific" :options="optionsSpecific" prefix="ประเภทใบลา :" />
</div>
</div>
<q-icon name="mdi-numeric-2-circle" size="20px" color="primary" v-if="model == 'ลาไปศึกษา ฝึกอบรม ปฎิบัติการวิจัย หรือดูงาน'" />
<div class="q-pl-sm text-weight-bold text-dark" v-if="model == 'ลาไปศึกษา ฝึกอบรม ปฎิบัติการวิจัย หรือดูงาน'">เลือกประเภทใบลาศึกษา ฝึกอบรม ปฎิบัติการวิจัย หรือดูงาน</div>
<div class="col-12 row q-pa-sm q-col-gutter-sm" v-if="model == 'ลาไปศึกษา ฝึกอบรม ปฎิบัติการวิจัย หรือดูงาน'">
<q-select dense class="q-ml-lg col-6" outlined v-model="modelSpecific" :options="optionsSpecific" prefix="ประเภทใบลา :" />
</div>
<q-icon name="mdi-numeric-2-circle" size="20px" color="primary" v-else />
<q-icon name="mdi-numeric-3-circle" size="20px" color="primary" v-if="model == 'ลาไปศึกษา ฝึกอบรม ปฎิบัติการวิจัย หรือดูงาน'" />
<div class="q-pl-sm text-weight-bold text-dark">กรอกขอม</div>
<q-card bordered class="q-pa-md bg-grey-1">
<div class="col-12 row q-pa-sm q-col-gutter-sm">
<datepicker
class="col-2"
menu-class-name="modalfix"
v-model="dateLeaveStart"
:locale="'th'"
autoApply
borderless
:enableTimePicker="false"
week-start="0"
:readonly="routeName != 'addAbsence'"
>
<template #year="{ year }">
{{ year + 543 }}
</template>
<template #year-overlay-value="{ value }">
{{ parseInt(value + 543) }}
</template>
<template #trigger>
<q-input
outlined
dense
hide-bottom-space
:readonly="routeName != 'addAbsence'"
class="full-width datepicker"
:model-value="dateLeaveStart != null ? date2Thai(dateLeaveStart) : null"
:label="`${'วันที่เริ่ม'}`"
:rules="[val => !!val || `${'กรุณาเลือกวันที่เริ่มลา'}`]"
>
<template v-slot:prepend>
<q-icon name="event" class="cursor-pointer" style="color: var(--q-primary)"> </q-icon>
</template>
</q-input>
</template>
</datepicker>
<datepicker
class="col-2"
menu-class-name="modalfix"
v-model="dateLeaveEnd"
:locale="'th'"
autoApply
borderless
:enableTimePicker="false"
week-start="0"
:readonly="routeName != 'addAbsence'"
>
<template #year="{ year }">
{{ year + 543 }}
</template>
<template #year-overlay-value="{ value }">
{{ parseInt(value + 543) }}
</template>
<template #trigger>
<q-input
outlined
dense
hide-bottom-space
:readonly="routeName != 'addAbsence'"
class="full-width datepicker"
:model-value="dateLeaveEnd != null ? date2Thai(dateLeaveEnd) : null"
:label="`${'จนถึงวันที่'}`"
:rules="[val => !!val || `${'กรุณาเลือกวันที่่สิ้นสุดการลา'}`]"
>
<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"
dense
outlined
type="number"
v-model="dateTotal"
label="จำนวนวัน(บันทึกลง ก.พ.7)"
:readonly="routeName != 'addAbsence'"
:rules="[val => !!val || `${'กรุณากรอกจำนวนวัน'}`]"
/>
<q-input class="col-3" dense outlined v-model="Writeat" label="เขียนที่" :readonly="routeName != 'addAbsence'" :rules="[val => !!val || `${'เขียนที่'}`]" />
<q-input
class="col-3"
dense
outlined
v-model="tel"
mask="(###)-###-####"
unmasked-value
label="หมายเลขโทรศัพท์ที่ติดต่อได้"
:readonly="routeName != 'addAbsence'"
:rules="[val => !!val || `${'กรุณากรอกหมายเลขโทรศัพท์ที่ติดต่อได้'}`]"
/>
<q-input
class="col-6"
dense
outlined
v-model="detail"
label="รายละเอียด"
:readonly="routeName != 'addAbsence'"
:rules="[val => !!val || `${'กรุณากรอกรายละเอียด'}`]"
/>
<q-input
class="col-6"
dense
outlined
v-model="locationAbsence"
label="สถาที่ติดต่อขณะลา"
:readonly="routeName != 'addAbsence'"
:rules="[val => !!val || `${'กรุณากรอกสถาที่ติดต่อขณะลา'}`]"
/>
<q-input
class="col-4"
v-if="model == 'ลาไปศึกษา ฝึกอบรม ปฎิบัติการวิจัย หรือดูงาน'"
dense
outlined
v-model="levelStudy"
label="ระดับที่ขอลาศึกษา"
:readonly="routeName != 'addAbsence'"
/>
<q-input
class="col-4"
v-if="model == 'ลาไปศึกษา ฝึกอบรม ปฎิบัติการวิจัย หรือดูงาน'"
dense
outlined
v-model="degree"
label="ชื่อปริญญา/ประกาศนียบัตร"
:readonly="routeName != 'addAbsence'"
/>
<q-input
class="col-4"
v-if="model == 'ลาไปศึกษา ฝึกอบรม ปฎิบัติการวิจัย หรือดูงาน'"
dense
outlined
v-model="major"
label="สาขาวิชาเอก/หลักสูตร/วิชา"
:readonly="routeName != 'addAbsence'"
/>
<q-input
class="col-4"
v-if="model == 'ลาไปศึกษา ฝึกอบรม ปฎิบัติการวิจัย หรือดูงาน'"
dense
outlined
v-model="educational"
label="ณ สถานศึกษา"
:readonly="routeName != 'addAbsence'"
/>
<q-input
class="col-4"
v-if="model == 'ลาไปศึกษา ฝึกอบรม ปฎิบัติการวิจัย หรือดูงาน'"
dense
outlined
v-model="studyPeriod"
label="ระยะเวลาในการศึกษาตลอดหลักสูตร"
:readonly="routeName != 'addAbsence'"
/>
<q-input
class="col-4"
v-if="model == 'ลาไปศึกษา ฝึกอบรม ปฎิบัติการวิจัย หรือดูงาน'"
dense
outlined
v-model="country"
label="ประเทศ"
:readonly="routeName != 'addAbsence'"
/>
<q-input
class="col-4"
v-if="model == 'ลาไปศึกษา ฝึกอบรม ปฎิบัติการวิจัย หรือดูงาน'"
dense
outlined
v-model="capital"
label="ด้วยทุน"
:readonly="routeName != 'addAbsence'"
/>
<q-input
class="col-8"
v-if="model == 'ลาไปศึกษา ฝึกอบรม ปฎิบัติการวิจัย หรือดูงาน'"
dense
outlined
v-model="noteReason"
label="ที่มาของหลักสูตร"
:readonly="routeName != 'addAbsence'"
/>
<q-file v-model="files" dense label="เอกสารประกอบ" outlined use-chips multiple class="q-pl-sm col-6">
<template v-slot:prepend>
<q-icon name="attach_file" color="primary" />
</template>
</q-file>
<div class="col-12 row" v-if="routeName != 'addAbsence'">
<div class="bg-grey-1 q-pa-sm col-12 row items-center text-primary">
<div class="q-pl-sm text-weight-bold text-dark">เอกสารเพมเต</div>
</div>
<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>
</q-list>
</q-card>
</div>
</div>
</q-card>
</div>
</div>
<q-separator />
<div class="row col-12 q-pa-md">
<q-space />
<q-btn unelevated dense class="q-px-md items-center btnBlue" label="บันทึก" @click="saveAbsence" />
</div>
</q-card>
</q-form>
</div>
</div>
</template>
<style scoped lang="scss">
.btnBlue {
background-color: #016987;
color: #fff;
}
</style>

View file

@ -1,321 +1,356 @@
import { defineStore } from "pinia" import { defineStore } from "pinia";
import { ref, computed } from "vue" import { ref, computed } from "vue";
import type { QTableProps } from "quasar" import type { QTableProps } from "quasar";
import type { FormLeavetMainData, OptionData, formListLeaveData } from "@/modules/05_leave/interface/index/main" import type {
import { useCounterMixin } from "@/stores/mixin" FormLeavetMainData,
OptionData,
formListLeaveData,
} from "@/modules/05_leave/interface/index/main";
import { useCounterMixin } from "@/stores/mixin";
export const useLeaveStore = defineStore("Leave", () => { export const useLeaveStore = defineStore("Leave", () => {
const tabValue = ref<string>("calendar"); const tabValue = ref<string>("calendar");
const typeLeave = ref<string|undefined>('') const typeLeave = ref<string | undefined>("");
const mixin = useCounterMixin() const mixin = useCounterMixin();
const { date2Thai } = mixin const { date2Thai } = mixin;
const LeaveType = ref<string | null>("0") const LeaveType = ref<string | null>("0");
const LeaveStatus = ref<string | null>("0") const LeaveStatus = ref<string | null>("0");
const fiscalYearyear = ref<string | null>("0") const fiscalYearyear = ref<string | null>("0");
const rows = ref<formListLeaveData[]>([]) const rows = ref<formListLeaveData[]>([]);
const DataMainOrig = ref<formListLeaveData[]>([]) // ข้อมูลหลักดั้งเดิม const DataMainOrig = ref<formListLeaveData[]>([]); // ข้อมูลหลักดั้งเดิม
async function fecthList(data: formListLeaveData[]) {
let datalist: formListLeaveData[] = data.map((e: any) => ({
no: e.no,
type: e.type,
status: e.status,
date: e.date,
year: e.year,
}))
rows.value = datalist
DataMainOrig.value = datalist
}
const DataMainUpdate = ref<formListLeaveData[]>([]) // ข้อมูลเปลี่ยนแปลง
const DataMain = (val: formListLeaveData[]) => (DataMainOrig.value = val)
const DataUpdate = (filterType: string, filterStatus: string, filterYear: string) => {
DataMainUpdate.value = []
if (filterType === "" && filterStatus === "" && filterYear === "") { async function fecthList(data: formListLeaveData[]) {
DataMainUpdate.value = DataMainOrig.value let datalist: formListLeaveData[] = data.map((e: any) => ({
} else if (filterType !== "" && filterStatus === "" && filterYear === "") { no: e.no,
DataMainUpdate.value = DataMainOrig.value.filter((item: formListLeaveData) => item.type === filterType) type: e.type,
} else if (filterType !== "" && filterStatus !== "" && filterYear === null) { status: e.status,
DataMainUpdate.value = DataMainOrig.value.filter((item: formListLeaveData) => item.type === filterType && item.status === filterStatus) date: e.date,
} else if (filterType !== "" && filterStatus === "" && filterYear !== "") { year: e.year,
DataMainUpdate.value = DataMainOrig.value.filter((item: formListLeaveData) => item.type === filterType && item.year === filterYear) }));
} else if (filterType === "" && filterStatus !== "" && filterYear === "") { rows.value = datalist;
DataMainUpdate.value = DataMainOrig.value.filter((item: formListLeaveData) => item.status === filterStatus) DataMainOrig.value = datalist;
} else if (filterType === "" && filterStatus === "" && filterYear !== "") { }
DataMainUpdate.value = DataMainOrig.value.filter((item: formListLeaveData) => item.year === filterYear)
} else if (filterType === "" && filterStatus !== "" && filterYear !== null) {
DataMainUpdate.value = DataMainOrig.value.filter((item: formListLeaveData) => item.status === filterStatus && item.year === filterYear)
} else if (filterType !== "" && filterStatus !== "" && filterYear === "") {
DataMainUpdate.value = DataMainOrig.value.filter((item: formListLeaveData) => item.status === filterStatus && item.type === filterType)
} else if (filterType !== "" && filterStatus !== "" && filterYear !== null) {
DataMainUpdate.value = DataMainOrig.value.filter((item: formListLeaveData) => item.type === filterType && item.status === filterStatus && item.year === filterYear)
} else if (filterType == "0" && filterStatus == "0" && filterYear !== null) {
DataMainUpdate.value = DataMainOrig.value
}
}
//--------------|ฟิลเตอร์|--------------------------------------// const DataMainUpdate = ref<formListLeaveData[]>([]); // ข้อมูลเปลี่ยนแปลง
const searchFilterTable = async () => { const DataMain = (val: formListLeaveData[]) => (DataMainOrig.value = val);
rows.value = [] const DataUpdate = (
filterType: string,
filterStatus: string,
filterYear: string
) => {
DataMainUpdate.value = [];
if (LeaveType.value !== undefined && LeaveType.value !== null) { if (filterType === "" && filterStatus === "" && filterYear === "") {
await DataUpdate(LeaveType.value === "0" ? "all" : LeaveType.value!, LeaveStatus.value === "0" ? "all" : LeaveStatus.value!, fiscalYearyear.value === "0" ? "all" : fiscalYearyear.value!) DataMainUpdate.value = DataMainOrig.value;
let filteredData = DataMainOrig.value } else if (filterType !== "" && filterStatus === "" && filterYear === "") {
if (LeaveType.value !== "0") { DataMainUpdate.value = DataMainOrig.value.filter(
filteredData = filteredData.filter((item: formListLeaveData) => item.type === LeaveType.value) (item: formListLeaveData) => item.type === filterType
} );
if (LeaveStatus.value !== "0") { } else if (
filteredData = filteredData.filter((item: formListLeaveData) => item.status === LeaveStatus.value) filterType !== "" &&
} filterStatus !== "" &&
if (fiscalYearyear.value !== "0") { filterYear === null
filteredData = filteredData.filter((item: formListLeaveData) => item.year === fiscalYearyear.value) ) {
} DataMainUpdate.value = DataMainOrig.value.filter(
const dataArr: formListLeaveData[] = filteredData.map((e: any) => ({ (item: formListLeaveData) =>
no: e.no, item.type === filterType && item.status === filterStatus
type: convertType(e.type) || '', );
status: convertStatus(e.status) || '', } else if (filterType !== "" && filterStatus === "" && filterYear !== "") {
date: date2Thai(new Date(e.date)), DataMainUpdate.value = DataMainOrig.value.filter(
year: e.year !== undefined ? e.year : '' (item: formListLeaveData) =>
})); item.type === filterType && item.year === filterYear
rows.value = dataArr );
} } else if (filterType === "" && filterStatus !== "" && filterYear === "") {
} DataMainUpdate.value = DataMainOrig.value.filter(
(item: formListLeaveData) => item.status === filterStatus
);
} else if (filterType === "" && filterStatus === "" && filterYear !== "") {
DataMainUpdate.value = DataMainOrig.value.filter(
(item: formListLeaveData) => item.year === filterYear
);
} else if (
filterType === "" &&
filterStatus !== "" &&
filterYear !== null
) {
DataMainUpdate.value = DataMainOrig.value.filter(
(item: formListLeaveData) =>
item.status === filterStatus && item.year === filterYear
);
} else if (filterType !== "" && filterStatus !== "" && filterYear === "") {
DataMainUpdate.value = DataMainOrig.value.filter(
(item: formListLeaveData) =>
item.status === filterStatus && item.type === filterType
);
} else if (
filterType !== "" &&
filterStatus !== "" &&
filterYear !== null
) {
DataMainUpdate.value = DataMainOrig.value.filter(
(item: formListLeaveData) =>
item.type === filterType &&
item.status === filterStatus &&
item.year === filterYear
);
} else if (
filterType == "0" &&
filterStatus == "0" &&
filterYear !== null
) {
DataMainUpdate.value = DataMainOrig.value;
}
};
const filterSelector = (val: any, update: Function, refData: string) => { //--------------|ฟิลเตอร์|--------------------------------------//
switch (refData) { const searchFilterTable = async () => {
case "fiscalyearOP": rows.value = [];
update(() => {
fiscalyearOP.value = fiscalyearOP.value.filter((v: any) => v.name.indexOf(val) > -1)
})
break
case "LeaveTypeOption":
update(() => {
typeOptions.value = typeOptions.value.filter((v: any) => v.name.indexOf(val) > -1)
})
break
case "LeaveStatusOption":
update(() => {
statusOptions.value = statusOptions.value.filter((v: any) => v.name.indexOf(val) > -1)
})
break
default:
break
}
}
const fiscalyearOP = ref<OptionData[]>([ if (LeaveType.value !== undefined && LeaveType.value !== null) {
{ id: "0", name: "ทั้งหมด" }, await DataUpdate(
{ id: "1", name: "2566" }, LeaveType.value === "0" ? "all" : LeaveType.value!,
{ id: "2", name: "2567" }, LeaveStatus.value === "0" ? "all" : LeaveStatus.value!,
{ id: "2", name: "2568" }, fiscalYearyear.value === "0" ? "all" : fiscalYearyear.value!
]) );
let filteredData = DataMainOrig.value;
if (LeaveType.value !== "0") {
filteredData = filteredData.filter(
(item: formListLeaveData) => item.type === LeaveType.value
);
}
if (LeaveStatus.value !== "0") {
filteredData = filteredData.filter(
(item: formListLeaveData) => item.status === LeaveStatus.value
);
}
if (fiscalYearyear.value !== "0") {
filteredData = filteredData.filter(
(item: formListLeaveData) => item.year === fiscalYearyear.value
);
}
const dataArr: formListLeaveData[] = filteredData.map((e: any) => ({
no: e.no,
type: convertType(e.type) || "",
status: convertStatus(e.status) || "",
date: date2Thai(new Date(e.date)),
year: e.year !== undefined ? e.year : "",
}));
rows.value = dataArr;
}
};
function convertType(val: string) { /**
switch (val) { *
case "0": * @param val
return "ทั้งหมด" * @param update
case "1": * @param refData
return "ลาป่วย" */
case "2": const filterSelector = (val: any, update: Function, refData: string) => {
return "ลากิจส่วนตัว" switch (refData) {
case "3": case "fiscalyearOP":
return "ลาคลอดบุตร" update(() => {
case "4": fiscalyearOP.value = fiscalyearOP.value.filter(
return "ลาไปช่วยเหลือภริยาที่คลอดบุตร" (v: any) => v.name.indexOf(val) > -1
case "5": );
return "ลาอุปสมบทหรือลาประกอบพิธีฮัจย์ฯ" });
case "6": break;
return "ลาเข้ารับการตรวจเลือกหรือเข้ารับการเตรียมพล" case "LeaveTypeOption":
case "7": update(() => {
return "ลาไปศึกษา ฝึกอบรม ปฎิบัติการวิจัย หรือดูงาน" typeOptions.value = typeOptions.value.filter(
case "8": (v: any) => v.name.indexOf(val) > -1
return "ลาไปปฎิบัติงานในองค์การระหว่างประเทศ" );
case "9": });
return "ลาติดตามคู่สมรส" break;
case "10": case "LeaveStatusOption":
return "ลาไปฟื้นฟูสมรรถภาพด้านอาชีพ" update(() => {
} statusOptions.value = statusOptions.value.filter(
} (v: any) => v.name.indexOf(val) > -1
function convertStatus(val: string) { );
switch (val) { });
case "0": break;
return "ทั้งหมด" default:
case "1": break;
return "อนุมัติ" }
case "2": };
return "ไม่อนุมัติ"
case "3":
return "อยู่ระหว่างดำเนินการ"
case "4":
return "ใหม่"
}
}
function convertYear(val: string) {
switch (val) {
case "0":
return "ทั้งหมด"
case "1":
return "2566"
case "2":
return "2567"
case "3":
return "2568"
case "4":
return "2569"
}
}
const optionsSpecific = ref([ /** filter ปี */
{ id: 's0', name: "ลาไปศึกษาต่อ" }, const fiscalyearOP = ref<OptionData[]>([
{ id: 's1', name: "ลาฝึกอบรม" }, { id: "0", name: "ทั้งหมด" },
{ id: 's2', name: "ลาปฎิบัติการวิจัย" }, { id: "1", name: "2566" },
{ id: 's3', name: "ลาดูงาน" }, { id: "2", name: "2567" },
]); { id: "2", name: "2568" },
const optionsOrdination = ref([ ]);
{ id: '0', name: "ลาอุปสมบท" },
{ id: '1', name: "ลาประกอบพิธีฮัจย์" },
]);
const typeOptions = ref<OptionData[]>([
{ id: "0", name: "ทั้งหมด" },
{ id: "1", name: "ลาป่วย" },
{ id: "2", name: "ลากิจส่วนตัว" },
{ id: "3", name: "ลาคลอดบุตร" },
{ id: "4", name: "ลาไปช่วยเหลือภริยาที่คลอดบุตร" },
{ id: "5", name: "ลาอุปสมบทหรือลาประกอบพิธีฮัจย์ฯ" },
{ id: "6", name: "ลาเข้ารับการตรวจเลือกหรือเข้ารับการเตรียมพล" },
{ id: "7", name: "ลาไปศึกษา ฝึกอบรม ปฎิบัติการวิจัย หรือดูงาน" },
{ id: "8", name: "ลาไปปฎิบัติงานในองค์การระหว่างประเทศ" },
{ id: "9", name: "ลาติดตามคู่สมรส" },
{ id: "10", name: "ลาไปฟื้นฟูสมรรถภาพด้านอาชีพ" },
])
const options = ref<OptionData[]>([
{ id: '0', name: "ลาป่วย" },
{ id: '1', name: "ลากิจส่วนตัว" },
{ id: '2', name: "ลาคลอดบุตร" },
{ id: '3', name: "ลาไปช่วยเหลือภริยาที่คลอดบุตร" },
{ id: '4', name: "ลาพักผ่อน" },
{ id: '5', name: "ลาอุปสมบทหรือลาประกอบพิธีฮัจย์ฯ" },
{ id: '6', name: "ลาเข้ารับการตรวจเลือกหรือเข้ารับการเตรียมพล" },
{ id: '7', name: "ลาไปศึกษา ฝึกอบรม ปฎิบัติการวิจัย หรือดูงาน" },
{ id: '8', name: "ลาไปปฎิบัติงานในองค์การระหว่างประเทศ" },
{ id: '9', name: "ลาติดตามคู่สมรส" },
{ id: '10', name: "ลาไปฟื้นฟูสมรรถภาพด้านอาชีพ" },
]);
const statusOptions = ref<OptionData[]>([
{ id: "0", name: "ทั้งหมด" },
{ id: "1", name: "อนุมัติ" },
{ id: "2", name: "ไม่อนุมัติ" },
{ id: "3", name: "อยู่ระหว่างดำเนินการ" },
{ id: "4", name: "ใหม่" },
])
const visibleColumns = ref<String[]>(["no", "type", "date", "status"])
const columns = ref<QTableProps["columns"]>([
{
name: "no",
align: "left",
label: "ลำดับ",
sortable: true,
field: "no",
headerStyle: "font-size: 14px",
style: "font-size: 14px; width:5%;",
},
{
name: "type",
align: "left",
label: "ประเภทการลา",
sortable: true,
field: "type",
headerStyle: "font-size: 14px",
style: "font-size: 14px; width:15%;",
},
{
name: "date",
align: "left",
label: "วันที่ยื่นใบลา",
sortable: true,
field: "date",
headerStyle: "font-size: 14px",
style: "font-size: 14px; width:15%;",
},
{
name: "status",
align: "left",
label: "สถานะ",
sortable: true,
field: "status",
headerStyle: "font-size: 14px",
style: "font-size: 14px; width:10%;",
},
])
function typeConvert(item: string,subitem:any) {
console.log('first',item)
if (item !== '5' && item !== '7') {
typeLeave.value = convertSubtitle(item);
}else if(item === '5'){
typeLeave.value = convertSubtitleInfo(subitem);
}else if(item === '7'){ /**
typeLeave.value = convertSubtitleInfo2(subitem); *
} * @param val
} * @returns
*/
function convertType(val: string) {
if (val == "0") return "ทั้งหมด";
else return options.value.find((x) => x.id == val)?.name;
}
function convertSubtitle(val: string) { /** รายการประเภทการลาของ ลาไปศึกษา ฝึกอบรม ปฎิบัติการวิจัย หรือดูงาน*/
if (val) { const optionsSpecific = ref([
switch (val) { { id: "s0", name: "ลาไปศึกษาต่อ" },
case "0": return "ลาป่วย"; { id: "s1", name: "ลาฝึกอบรม" },
case "1": return "ลากิจส่วนตัว"; { id: "s2", name: "ลาปฎิบัติการวิจัย" },
case "2": return "ลาคลอดบุตร"; { id: "s3", name: "ลาดูงาน" },
case "3": return "ลาไปช่วยเหลือภริยาที่คลอดบุตร"; ]);
case "4": return "ลาพักผ่อน";
case "5": return "ลาอุปสมบทหรือลาประกอบพิธีฮัจย์ฯ";
case "6": return "ลาเข้ารับการตรวจเลือกหรือเข้ารับการเตรียมพล";
case "7": return "ลาไปศึกษา ฝึกอบรม ปฎิบัติการวิจัย หรือดูงาน";
case "8": return "ลาไปปฎิบัติงานในองค์การระหว่างประเทศ";
case "9": return "ลาติดตามคู่สมรส";
case "10": return "ลาไปฟื้นฟูสมรรถภาพด้านอาชีพ";
}
}
}
function convertSubtitleInfo(val: string) {
if (val) {
switch (val) {
case "0": return "ลาอุปสมบท";
case "1": return "ลาประกอบพิธีฮัจย์";
}
}
}
function convertSubtitleInfo2(val: string) {
if (val) {
switch (val) {
case "s0": return "ลาไปศึกษาต่อ";
case "s1": return "ลาฝึกอบรม";
case "s2": return "ลาปฎิบัติการวิจัย";
case "s3": return "ลาดูงาน";
}
}
}
return { /** รายการประเภทการลาของ ลาอุปสมบทหรือลาประกอบพิธีฮัจย์ฯ*/
tabValue, const optionsOrdination = ref([
typeOptions, { id: "0", name: "ลาอุปสมบท" },
optionsSpecific, { id: "1", name: "ลาประกอบพิธีฮัจย์" },
statusOptions, ]);
DataMain,
DataMainUpdate, /** รายการข้อมูลประเภทใบลา */
DataUpdate, const options = ref<OptionData[]>([
DataMainOrig, { id: "1", name: "ลาป่วย" },
visibleColumns, { id: "2", name: "ลากิจส่วนตัว" },
columns, { id: "3", name: "ลาคลอดบุตร" },
rows, { id: "4", name: "ลาไปช่วยเหลือภริยาที่คลอดบุตร" },
LeaveType, { id: "5", name: "ลาพักผ่อน" },
LeaveStatus, { id: "6", name: "ลาอุปสมบทหรือลาประกอบพิธีฮัจย์ฯ" },
fecthList, { id: "7", name: "ลาเข้ารับการตรวจเลือกหรือเข้ารับการเตรียมพล" },
filterSelector, { id: "8", name: "ลาไปศึกษา ฝึกอบรม ปฎิบัติการวิจัย หรือดูงาน" },
searchFilterTable, { id: "9", name: "ลาไปปฎิบัติงานในองค์การระหว่างประเทศ" },
fiscalyearOP, { id: "10", name: "ลาติดตามคู่สมรส" },
fiscalYearyear, { id: "11", name: "ลาไปฟื้นฟูสมรรถภาพด้านอาชีพ" },
options, ]);
optionsOrdination,
typeConvert, /** filter ประเภทการลา */
typeLeave const typeOptions = ref<OptionData[]>([
} { id: "0", name: "ทั้งหมด" },
}) ...options.value,
]);
/** สถานะของการลา */
const statusOptions = ref<OptionData[]>([
{ id: "0", name: "ทั้งหมด" },
{ id: "1", name: "อนุมัติ" },
{ id: "2", name: "ไม่อนุมัติ" },
{ id: "3", name: "อยู่ระหว่างดำเนินการ" },
{ id: "4", name: "ใหม่" },
]);
/**
*
* @param val
* @returns
*/
function convertStatus(val: string) {
if (val == "0") return "ทั้งหมด";
else return statusOptions.value.find((x) => x.id == val)?.name;
}
/** data table filter & column ของรายการลา */
const visibleColumns = ref<String[]>(["no", "type", "date", "status"]);
const columns = ref<QTableProps["columns"]>([
{
name: "no",
align: "left",
label: "ลำดับ",
sortable: true,
field: "no",
headerStyle: "font-size: 14px",
style: "font-size: 14px; width:5%;",
},
{
name: "type",
align: "left",
label: "ประเภทการลา",
sortable: true,
field: "type",
headerStyle: "font-size: 14px",
style: "font-size: 14px; width:15%;",
},
{
name: "date",
align: "left",
label: "วันที่ยื่นใบลา",
sortable: true,
field: "date",
headerStyle: "font-size: 14px",
style: "font-size: 14px; width:15%;",
},
{
name: "status",
align: "left",
label: "สถานะ",
sortable: true,
field: "status",
headerStyle: "font-size: 14px",
style: "font-size: 14px; width:10%;",
},
]);
/**
*
* @param item
* @param subitem
*/
function typeConvert(item: string, subitem: any) {
// console.log('first',item)
if (item !== "6" && item !== "8") {
typeLeave.value = convertSubtitle(item);
} else if (item === "6") {
typeLeave.value = convertSubtitleInfo(subitem);
} else if (item === "8") {
typeLeave.value = convertSubtitleInfo2(subitem);
}
}
/**
*
* @param val
* @returns
*/
function convertSubtitle(val: string) {
return options.value.find((x) => x.id == val)?.name;
}
/**
*
* @param val
* @returns
*/
function convertSubtitleInfo(val: string) {
return optionsOrdination.value.find((x) => x.id == val)?.name;
}
/**
*
* @param val
* @returns
*/
function convertSubtitleInfo2(val: string) {
return optionsSpecific.value.find((x) => x.id == val)?.name;
}
return {
tabValue,
typeOptions,
optionsSpecific,
statusOptions,
DataMain,
DataMainUpdate,
DataUpdate,
DataMainOrig,
visibleColumns,
columns,
rows,
LeaveType,
LeaveStatus,
fecthList,
filterSelector,
searchFilterTable,
fiscalyearOP,
fiscalYearyear,
options,
optionsOrdination,
typeConvert,
typeLeave,
};
});

View file

@ -1,147 +1,206 @@
<script setup lang="ts"> <script setup lang="ts">
import { ref, onMounted, computed } from "vue" import { ref, onMounted, computed } from "vue";
import { useQuasar } from "quasar" import { useQuasar } from "quasar";
import { useRouter, useRoute } from "vue-router" import { useRouter, useRoute } from "vue-router";
import Form from "@/modules/05_leave/componenst/Forms/Form.vue" import FormPart2 from "@/modules/05_leave/componenst/Forms/Form.vue";
import Form3 from "@/modules/05_leave/componenst/Forms/01_SickForm.vue" import SickForm from "@/modules/05_leave/componenst/Forms/01_SickForm.vue";
import FormBirth from "@/modules/05_leave/componenst/Forms/03_Birth.vue" import FormBirth from "@/modules/05_leave/componenst/Forms/03_Birth.vue";
import Form4 from "@/modules/05_leave/componenst/Forms/04_HelpWifeBirthForm.vue" import HelpWifeBirthForm from "@/modules/05_leave/componenst/Forms/04_HelpWifeBirthForm.vue";
import Form5 from "@/modules/05_leave/componenst/Forms/05_VacationForm.vue" import VacationForm from "@/modules/05_leave/componenst/Forms/05_VacationForm.vue";
import Form6 from "@/modules/05_leave/componenst/Forms/06_OrdinationForm.vue" import OrdinationForm from "@/modules/05_leave/componenst/Forms/06_OrdinationForm.vue";
import Form7 from "@/modules/05_leave/componenst/Forms/07_HajjForm.vue" import HajjForm from "@/modules/05_leave/componenst/Forms/07_HajjForm.vue";
import Form8 from "@/modules/05_leave/componenst/Forms/08_MilitaryForm.vue" import MilitaryForm from "@/modules/05_leave/componenst/Forms/08_MilitaryForm.vue";
import Form9 from "@/modules/05_leave/componenst/Forms/09_StudyForm.vue" import StudyForm from "@/modules/05_leave/componenst/Forms/09_StudyForm.vue";
import Form10 from "@/modules/05_leave/componenst/Forms/10_TrainForm.vue" import TrainForm from "@/modules/05_leave/componenst/Forms/10_TrainForm.vue";
import Form11 from "@/modules/05_leave/componenst/Forms/11_WorkInternationalForm.vue" import WorkInternationalForm from "@/modules/05_leave/componenst/Forms/11_WorkInternationalForm.vue";
import Form12 from "@/modules/05_leave/componenst/Forms/12_FollowSpouseForm.vue" import FollowSpouseForm from "@/modules/05_leave/componenst/Forms/12_FollowSpouseForm.vue";
import Form13 from "@/modules/05_leave/componenst/Forms/13_RehabilitationForm.vue" import RehabilitationForm from "@/modules/05_leave/componenst/Forms/13_RehabilitationForm.vue";
import { useLeaveStore } from "@/modules/05_leave/store" import { useLeaveStore } from "@/modules/05_leave/store";
import http from "@/plugins/http" import http from "@/plugins/http";
import config from "@/app.config" import config from "@/app.config";
import type { QForm } from "quasar" import type { QForm } from "quasar";
import { useCounterMixin } from "@/stores/mixin" import { useCounterMixin } from "@/stores/mixin";
const dataStore = useLeaveStore() const dataStore = useLeaveStore();
const mixin = useCounterMixin() const mixin = useCounterMixin();
const { date2Thai, dialogConfirm } = mixin const { date2Thai, dialogConfirm } = mixin;
const router = useRouter() const router = useRouter();
const route = useRoute() const route = useRoute();
const myform = ref<QForm | null>(null) const myform = ref<QForm | null>(null);
const $q = useQuasar() const $q = useQuasar();
const model = ref<string>("") const model = ref<string>("");
const modelSpecific = ref<string>("") const modelSpecific = ref<string>("");
// onMounted(() => {}); // onMounted(() => {});
const saveAbsence = () => { const saveAbsence = () => {
$q.dialog({ $q.dialog({
title: "ยืนยันการยื่นข้อมูลลาออก", title: "ยืนยันการยื่นข้อมูลลาออก",
message: "ต้องการยื่นข้อมูลลาออกนี้ใช่หรือไม่?", message: "ต้องการยื่นข้อมูลลาออกนี้ใช่หรือไม่?",
cancel: { cancel: {
flat: true, flat: true,
color: "negative", color: "negative",
}, },
persistent: true, persistent: true,
}) })
.onOk(() => { .onOk(() => {
// createFormresign() // createFormresign()
if (model.value !== "7") { if (model.value !== "7") {
console.log(1) console.log(1);
} else if (model.value === "7") { } else if (model.value === "7") {
console.log(2) console.log(2);
} }
router.push(`/leave`) router.push(`/leave`);
}) })
.onCancel(() => {}) .onCancel(() => {})
.onDismiss(() => {}) .onDismiss(() => {});
} };
/** ฟังก์ชั่น บันทึก */ /** ฟังก์ชั่น บันทึก */
const onSubmit = async () => { const onSubmit = async () => {
dialogConfirm($q, async () => {}, "ยืนยันการยื่นใบลา", "ต้องการยืนยันการยื่นใบลานี้ใช่หรือไม่ ?") dialogConfirm(
$q,
async () => {},
"ยืนยันการยื่นใบลา",
"ต้องการยืนยันการยื่นใบลานี้ใช่หรือไม่ ?"
);
console.log("save") console.log("save");
} };
</script> </script>
<template> <template>
<div class="col-12 row justify-center"> <div class="col-12 row justify-center">
<div class="col-xs-12 col-sm-12 col-md-11"> <div class="col-xs-12 col-sm-12 col-md-11">
<div class="toptitle text-white col-12 row items-center"> <div class="toptitle text-white col-12 row items-center">
<q-btn to="/leave" icon="mdi-arrow-left" unelevated round dense flat color="primary" class="q-mr-sm" /> <q-btn
<div>นใบลา</div> to="/leave"
</div> icon="mdi-arrow-left"
unelevated
round
dense
flat
color="primary"
class="q-mr-sm"
/>
<div>นใบลา</div>
</div>
<q-form ref="myform" class="col-12"> <q-form ref="myform" class="col-12">
<q-card bordered> <q-card bordered>
<div class="col-12 row q-col-gutter-md q-pa-md"> <div class="col-12 row q-col-gutter-md q-pa-md">
<div class="col-xs-12 col-sm-12"> <div class="col-xs-12 col-sm-12">
<div style="display: flex; align-items: center"> <div style="display: flex; align-items: center">
<q-icon name="mdi-numeric-1-circle" size="20px" color="primary" /> <q-icon
<div class="q-pl-sm text-weight-bold text-dark">เลอกประเภทการลา</div> name="mdi-numeric-1-circle"
</div> size="20px"
<div class="q-py-sm q-px-lg"> color="primary"
<div class="row"> />
<q-select <div class="q-pl-sm text-weight-bold text-dark">
dense เลอกประเภทการลา
class="col-12 col-sm-6 col-md-4" </div>
outlined </div>
v-model="model" <div class="q-py-sm q-px-lg">
:options="dataStore.options" <div class="row">
option-value="id" <q-select
option-label="name" dense
emit-value class="col-12 col-sm-6 col-md-4"
map-options outlined
prefix="ประเภทใบลา :" v-model="model"
@update:model-value="dataStore.typeConvert(model, null)" :options="dataStore.options"
/> option-value="id"
</div> option-label="name"
<div class="row q-mt-sm"> emit-value
<div class="col-12 col-sm-6 col-md-3" v-if="model === '5' || model === '7'"> map-options
<q-select prefix="ประเภทใบลา :"
dense @update:model-value="
outlined dataStore.typeConvert(model, null), (modelSpecific = '')
v-model="modelSpecific" "
:options="model === '5' ? dataStore.optionsOrdination : dataStore.optionsSpecific" />
option-value="id" </div>
option-label="name" <div class="row q-mt-sm">
emit-value <div
map-options class="col-12 col-sm-6 col-md-3"
prefix="ประเภทใบลา :" v-if="model === '6' || model === '8'"
@update:model-value="dataStore.typeConvert(model, modelSpecific)" >
/> <q-select
</div> dense
</div> outlined
v-model="modelSpecific"
:options="
model === '6'
? dataStore.optionsOrdination
: dataStore.optionsSpecific
"
option-value="id"
option-label="name"
emit-value
map-options
prefix="ประเภทการลา :"
@update:model-value="
dataStore.typeConvert(model, modelSpecific)
"
/>
</div>
</div>
<!-- v-if (ลาอปสมบทหรอลาประกอบพจย||ลาไปศกษา กอบรม ปฎการว หรอดงาน) --> <!-- v-if (ลาอปสมบทหรอลาประกอบพจย||ลาไปศกษา กอบรม ปฎการว หรอดงาน) -->
</div> </div>
<div> <div>
<div style="display: flex; align-items: center"> <div style="display: flex; align-items: center">
<q-icon name="mdi-numeric-2-circle" size="20px" color="primary" /> <q-icon
<div class="q-pl-sm text-weight-bold text-dark">อมลการลา</div> name="mdi-numeric-2-circle"
</div> size="20px"
<Form :model="model" /> color="primary"
</div> />
</div> <div class="q-pl-sm text-weight-bold text-dark">
<div v-if="model" class="col-12"> อมลการลา
<Form3 :on-submit="onSubmit" v-if="model === '0' || model === '1'" /> </div>
<FormBirth :on-submit="onSubmit" v-if="model === '2'" /> </div>
<Form4 :on-submit="onSubmit" v-if="model === '3'" /> <FormPart2 :model="model" />
<Form5 :on-submit="onSubmit" v-if="model === '4'" /> </div>
<Form6 :on-submit="onSubmit" v-if="model === '5' && modelSpecific === '0'" /> </div>
<Form7 :on-submit="onSubmit" v-if="model === '5' && modelSpecific === '1'" /> <div v-if="model" class="col-12">
<Form8 :on-submit="onSubmit" v-if="model === '6'" style="width: 100%" /> <SickForm
<Form9 :on-submit="onSubmit" v-if="model === '7' && modelSpecific === 's0'" style="width: 100%" /> :on-submit="onSubmit"
<Form10 :on-submit="onSubmit" v-if="model === '7' && modelSpecific != 's0' && modelSpecific != ''" /> v-if="model === '1' || model === '2'"
<Form11 :on-submit="onSubmit" v-if="model === '8'" /> />
<Form12 :on-submit="onSubmit" v-if="model === '9'" /> <FormBirth :on-submit="onSubmit" v-if="model === '3'" />
<Form13 :on-submit="onSubmit" v-if="model === '10'" /> <HelpWifeBirthForm :on-submit="onSubmit" v-if="model === '4'" />
</div> <VacationForm :on-submit="onSubmit" v-if="model === '5'" />
</div> <OrdinationForm
</q-card> :on-submit="onSubmit"
</q-form> v-if="model === '6' && modelSpecific === '0'"
</div> />
</div> <HajjForm
:on-submit="onSubmit"
v-if="model === '6' && modelSpecific === '1'"
/>
<MilitaryForm
:on-submit="onSubmit"
v-if="model === '7'"
style="width: 100%"
/>
<StudyForm
:on-submit="onSubmit"
v-if="model === '8' && modelSpecific === 's0'"
style="width: 100%"
/>
<TrainForm
:on-submit="onSubmit"
v-if="
model === '8' && modelSpecific != 's0' && modelSpecific != ''
"
/>
<WorkInternationalForm :on-submit="onSubmit" v-if="model === '9'" />
<FollowSpouseForm :on-submit="onSubmit" v-if="model === '10'" />
<RehabilitationForm :on-submit="onSubmit" v-if="model === '11'" />
</div>
</div>
</q-card>
</q-form>
</div>
</div>
</template> </template>

View file

@ -1,360 +1,332 @@
<script setup lang="ts"> <script setup lang="ts">
import type { QTableProps } from "quasar" import type { QTableProps } from "quasar";
import { defineComponent, onMounted } from "@vue/runtime-core" // import { defineComponent, onMounted } from "@vue/runtime-core";
import { reactive, ref, watch } from "vue" import { ref } from "vue";
import { useRouter } from "vue-router" import { useRouter } from "vue-router";
import subCalendarComponent from "@/modules/05_leave/componenst/Calendar.vue" import CalendarView from "@/modules/05_leave/componenst/Calendar.vue";
import subListCalendarComponent from "@/modules/05_leave/componenst/ListCalendar.vue" import ListView from "@/modules/05_leave/componenst/ListCalendar.vue";
import { useCounterMixin } from "@/stores/mixin" import { useLeaveStore } from "@/modules/05_leave/store";
import type { DataDateMonthObject } from "@/modules/05_leave/interface/request/Calendar.ts"
import { useLeaveStore } from "@/modules/05_leave/store"
const leaveStore = useLeaveStore() const leaveStore = useLeaveStore();
const { filterSelector, searchFilterTable } = leaveStore const router = useRouter();
const router = useRouter()
const dateMonth = ref<DataDateMonthObject>({
month: new Date().getMonth(),
year: new Date().getFullYear(),
})
// console.log(dateMonth.value);
const props = defineProps({
dateYear: Number, // parent
fetchDataSummaryCalendar: {
//
type: Function,
default: () => console.log("not function"),
},
})
const dateYear = ref<number>(new Date().getFullYear())
const emit = defineEmits(["update:dateYear"])
const mixin = useCounterMixin() //
const { monthYear2Thai } = mixin
/**
* แปลง และเดอนเปนภาษาไทย
* @param val datepicker แบบเลอกปและเดอน
*/
const monthYearThai = (val: DataDateMonthObject) => {
if (val == null) return ""
else return monthYear2Thai(val.month, val.year)
}
const updateMonth = async (e: DataDateMonthObject) => {
console.log(dateMonth.value)
if (e != null) {
dateYear.value = e.year
emit("update:dateYear", e.year)
await props.fetchDataSummaryCalendar()
}
console.log(dateMonth.value)
}
const value = ref(90)
const itemPie = ref([ const itemPie = ref([
{ {
text: "ลาป่วย", text: "ลาป่วย",
color: "text-pink-5", color: "text-pink-5",
value: 90, value: 90,
all: "10", all: "10",
use: "9", use: "9",
remain: "1", remain: "1",
}, },
{ {
text: "ลากิจส่วนตัว", text: "ลากิจส่วนตัว",
color: "text-deep-purple", color: "text-deep-purple",
value: 80, value: 80,
all: "12", all: "12",
use: "9", use: "9",
remain: "3", remain: "3",
}, },
{ {
text: "ลาพักผ่อน", text: "ลาพักผ่อน",
color: "text-indigo", color: "text-indigo",
value: 78, value: 78,
all: "20", all: "20",
use: "17", use: "17",
remain: "3", remain: "3",
}, },
]) ]);
const data = ref(false);
const data = ref(false)
const columns = ref<QTableProps["columns"]>([ const columns = ref<QTableProps["columns"]>([
{ {
name: "no", name: "id",
align: "left", align: "left",
label: "ลำดับ", label: "ลำดับ",
sortable: true, sortable: true,
field: "no", field: "id",
headerStyle: "font-size: 14px", headerStyle: "font-size: 14px",
style: "font-size: 14px; width:5%;", style: "font-size: 14px; width:5%;",
}, },
{ {
name: "type", name: "name",
align: "left", align: "left",
label: "ประเภทการลา", label: "ประเภทการลา",
sortable: true, sortable: true,
field: "type", field: "name",
headerStyle: "font-size: 14px", headerStyle: "font-size: 14px",
style: "font-size: 14px; width:15%;", style: "font-size: 14px; width:15%;",
}, },
{ {
name: "numDate", name: "numDate",
align: "left", align: "left",
label: "โควตาวันลา", label: "โควตาวันลา",
sortable: true, sortable: true,
field: "numDate", field: "numDate",
headerStyle: "font-size: 14px", headerStyle: "font-size: 14px",
style: "font-size: 14px; width:15%;", style: "font-size: 14px; width:15%;",
}, },
{ {
name: "extend", name: "extend",
align: "left", align: "left",
label: "ทดวันลา", label: "ทดวันลา",
sortable: true, sortable: true,
field: "extend", field: "extend",
headerStyle: "font-size: 14px", headerStyle: "font-size: 14px",
style: "font-size: 14px; width:15%;", style: "font-size: 14px; width:15%;",
}, },
{ {
name: "use", name: "use",
align: "left", align: "left",
label: "ใช้ไป (%)", label: "ใช้ไป (%)",
sortable: true, sortable: true,
field: "use", field: "use",
headerStyle: "font-size: 14px", headerStyle: "font-size: 14px",
style: "font-size: 14px; width:15%;", style: "font-size: 14px; width:15%;",
}, },
{ {
name: "numAll", name: "numAll",
align: "left", align: "left",
label: "จำนวนยื่นขอลา (วัน)", label: "จำนวนยื่นขอลา (วัน)",
sortable: true, sortable: true,
field: "numAll", field: "numAll",
headerStyle: "font-size: 14px", headerStyle: "font-size: 14px",
style: "font-size: 14px; width:15%;", style: "font-size: 14px; width:15%;",
}, },
{ {
name: "numDone", name: "numDone",
align: "left", align: "left",
label: "จำนวนที่อนุมัติ (วัน)", label: "จำนวนที่อนุมัติ (วัน)",
sortable: true, sortable: true,
field: "numDone", field: "numDone",
headerStyle: "font-size: 14px", headerStyle: "font-size: 14px",
style: "font-size: 14px; width:15%;", style: "font-size: 14px; width:15%;",
}, },
{ {
name: "numNot", name: "numNot",
align: "left", align: "left",
label: "จำนวนที่ไม่อนุมัติ (วัน)", label: "จำนวนที่ไม่อนุมัติ (วัน)",
sortable: true, sortable: true,
field: "numNot", field: "numNot",
headerStyle: "font-size: 14px", headerStyle: "font-size: 14px",
style: "font-size: 14px; width:15%;", style: "font-size: 14px; width:15%;",
}, },
{ {
name: "numCancel", name: "numCancel",
align: "left", align: "left",
label: "จำนวนที่ยกเลิก (วัน)", label: "จำนวนที่ยกเลิก (วัน)",
sortable: true, sortable: true,
field: "numCancel", field: "numCancel",
headerStyle: "font-size: 14px", headerStyle: "font-size: 14px",
style: "font-size: 14px; width:15%;", style: "font-size: 14px; width:15%;",
}, },
]) ]);
const rows = ref<any>([
{ no: "1", type: "ลาป่วย" }, const pagination = ref({ rowsPerPage: 10 });
{ no: "2", type: "ลากิจส่วนตัว" },
{ no: "3", type: "ลาคลอดบุตร" },
{ no: "4", type: "ลาช่วยเหลือภริยาที่คลอดบุตร" },
{ no: "5", type: "ลาพักผ่อน" },
{ no: "6", type: "ลาอุปสมบทหรือการลาประกอบพิธีฮัจย์ฯ" },
{ no: "7", type: "ลาเข้ารับการตรวจเลือกหรือเข้ารับการเตรียมพล" },
{ no: "8", type: "ลาไปศึกษา ฝึกอบรม ปฏิบัติการวิจัย หรือดูงาน" },
{ no: "9", type: "ลาไปปฏิบัติงานในองค์การระหว่างประเทศ" },
{ no: "10", type: "ลาติดตามคู่สมรส" },
{ no: "11", type: "ลาฟื้นฟูสมรรถภาพด้านอาชีพ" },
])
const pagination = ref({ rowsPerPage: 11 })
const addAbsence = async () => { const addAbsence = async () => {
router.push(`/leave/add`) router.push(`/leave/add`);
} };
</script> </script>
<template> <template>
<div class="col-12 row justify-center"> <div class="col-12 row justify-center">
<div class="col-xs-12 col-sm-12 col-md-11"> <div class="col-xs-12 col-sm-12 col-md-11">
<div class="toptitle text-white col-12 row items-center"> <div class="toptitle text-white col-12 row items-center">
<q-btn icon="mdi-arrow-left" unelevated round dense flat color="primary" class="q-mr-sm" @click="router.go(-1)" /> <q-btn
<div>รายการลา</div> icon="mdi-arrow-left"
</div> unelevated
</div> round
<div class="col-xs-12 col-sm-12 col-md-11 row q-col-gutter-md"> dense
<div class="row col-12 q-col-gutter-sm"> flat
<div class="col-xs-12 col-sm-9 col-md-9 row"> color="primary"
<q-card bordered class="q-pa-md col-12"> class="q-mr-sm"
<div class="row col-12"> @click="router.go(-1)"
<div class="row items-center"> />
<!-- filter เลอกเดอนป --> <div>รายการลา</div>
<datepicker </div>
v-model="dateMonth" </div>
:locale="'th'"
autoApply
month-picker
:enableTimePicker="false"
v-if="leaveStore.tabValue === 'calendar'"
@update:modelValue="updateMonth"
>
<template #year="{ year }">{{ year + 543 }}</template>
<template #year-overlay-value="{ value }">{{ parseInt(value + 543) }}</template>
<template #trigger>
<q-input :model-value="monthYearThai(dateMonth)" dense outlined style="width: 130px">
<template v-slot:prepend>
<q-icon name="event" class="cursor-pointer" style="color: var(--q-primary)"> </q-icon>
</template>
</q-input>
</template>
</datepicker>
<q-select
v-if="leaveStore.tabValue === 'list'"
outlined
dense
lazy-rules
v-model="leaveStore.fiscalYearyear"
:label="`${'ปี พ.ศ.'}`"
emit-value
map-options
option-label="name"
:options="leaveStore.fiscalyearOP"
option-value="id"
hide-bottom-space
style="min-width: 150px"
class="col-xs-12 col-sm-auto"
@update:model-value="searchFilterTable"
@filter="(inputValue:any,
doneFn:Function) => filterSelector(inputValue, doneFn,'fiscalyearOP'
) "
/>
<!-- filter เลอกป -->
<!-- <datepicker v-model="dateYear" :locale="'th'" autoApply year-picker :enableTimePicker="false" v-if="leaveStore.tabValue === 'list'">
<template #year="{ year }">{{ year + 543 }}</template>
<template #year-overlay-value="{ value }">{{ parseInt(value + 543) }}</template>
<template #trigger>
<q-input :model-value="dateYear + 543" dense outlined style="width: 100px" hide-bottom-space>
<template v-slot:prepend>
<q-icon name="event" class="cursor-pointer" style="color: var(--q-primary)"> </q-icon>
</template>
</q-input>
</template>
</datepicker> -->
<div class="q-ml-sm">
<!-- icon เพมวนหย -->
<q-btn round dense flat size="13px" class="q-px-sm" @click="addAbsence">
<q-icon name="mdi-plus" size="22px" color="primary" />
<q-tooltip>นใบลา</q-tooltip>
</q-btn>
</div>
</div>
<q-space />
<div class="justify-center row items-center">
<!-- tab ปแบบแสดงวนหย ปฏนกบรายการ -->
<q-tabs v-model="leaveStore.tabValue" indicator-color="transparent" align="left" active-color="activetab" class="text-nativetab" inline-label dense>
<q-btn
name="calendar"
round
size="12px"
flat
icon="mdi-calendar-month"
@click="leaveStore.tabValue = 'calendar'"
:color="leaveStore.tabValue == 'calendar' ? 'primary' : 'grey-6'"
class="q-mr-sm"
>
<q-tooltip>ปฏ</q-tooltip>
</q-btn>
<q-separator vertical inset />
<q-btn
name="list"
round
size="12px"
flat
icon="mdi-format-list-bulleted"
@click="leaveStore.tabValue = 'list'"
:color="leaveStore.tabValue == 'list' ? 'primary' : 'grey-6'"
class="q-ml-sm"
>
<q-tooltip>รายการ</q-tooltip>
</q-btn>
</q-tabs>
</div>
</div>
<div class="col-12">
<subCalendarComponent :dateYear="dateMonth.year" :dateMonth="dateMonth.month" v-if="leaveStore.tabValue === 'calendar'" />
</div>
<div class="col-12"> <div class="col-xs-12 col-sm-12 col-md-11 row q-col-gutter-md">
<subListCalendarComponent v-if="leaveStore.tabValue === 'list'" /> <!-- สถการลา -->
</div> <div class="col-12 row">
</q-card> <q-card bordered class="col-12 row caedNone">
</div> <q-card class="row col-12 items-center q-px-md q-py-sm">
<div class="col-xs-12 col-sm-3 col-md-3 row"> <div class="text-weight-bold">สถการลา</div>
<q-card bordered class="col-12 row caedNone"> <q-space />
<div class="col-12 row"> <q-btn
<q-card class="row col-12 items-center q-px-md q-py-sm"> dense
<div class="text-weight-bold">สถการลา</div> flat
<q-space /> class="text-blue"
<q-btn dense flat class="text-blue" icon="mdi-chart-line-variant" @click="data = true" label="ตารางสถิติการลา" /> icon="mdi-chart-line-variant"
</q-card> @click="data = true"
<div bordered class="col-12 row justify-center q-px-md q-pb-md" v-for="(item, index) in itemPie" :key="index"> label="ตารางสถิติการลา"
<q-card bordered flat class="col-12 row q-pt-md justify-center shadow-0"> />
<q-knob readonly v-model="item.value" show-value size="70px" :thickness="0.15" track-color="grey-3" :class="`${item.color}`"> </q-card>
<span class="text-subtitle2 text-weight-bold">{{ item.value }}%</span> <div
</q-knob> bordered
<div class="col-12 text-center text-weight-medium q-py-xs"> class="col-4 row justify-center q-px-md q-pb-md"
{{ item.text }} v-for="(item, index) in itemPie"
</div> :key="index"
<div class="col-12 row bg-grey-1 no-wrap text-dark text-body2 items-center borderTop"> >
<div class="col-4 column q-pa-xs text-center"> <q-card
<span class="text-weight-bold">{{ item.all }}</span> bordered
<span class="text-grey-7 text-caption">ได</span> flat
</div> class="col-12 row q-pt-md justify-center shadow-0"
<q-separator vertical /> >
<div class="col-4 column q-pa-xs text-center"> <q-knob
<span class="text-weight-bold">{{ item.use }}</span> readonly
<span class="text-grey-7 text-caption">ใชไป</span> v-model="item.value"
</div> show-value
<q-separator vertical /> size="70px"
<div class="col-4 column q-pa-xs text-center"> :thickness="0.15"
<span class="text-weight-bold">{{ item.remain }}</span> track-color="grey-3"
<span class="text-grey-7 text-caption">คงเหล</span> :class="`${item.color}`"
</div> >
</div> <span class="text-subtitle2 text-weight-bold"
</q-card> >{{ item.value }}%</span
</div> >
</div> </q-knob>
</q-card> <div class="col-12 text-center text-weight-medium q-py-xs">
</div> {{ item.text }}
</div> </div>
</div> <div
</div> class="col-12 row bg-grey-1 no-wrap text-dark text-body2 items-center borderTop"
<!-- modal ตารางสถการลา --> >
<q-dialog v-model="data" persistent> <div class="col-4 column q-pa-xs text-center">
<q-card style="min-width: 85%"> <span class="text-weight-bold">{{ item.all }}</span>
<q-card-section class="row items-center q-pa-sm"> <span class="text-grey-7 text-caption">ได</span>
<div class="text-bold q-pl-sm">ตารางสถการลา</div> </div>
<q-space /> <q-separator vertical />
<q-btn icon="close" unelevated round dense v-close-popup style="color: #ff8080; background-color: #ffdede" /> <div class="col-4 column q-pa-xs text-center">
</q-card-section> <span class="text-weight-bold">{{ item.use }}</span>
<q-separator /> <span class="text-grey-7 text-caption">ใชไป</span>
<q-card-section class="q-p-md row"> </div>
<q-table flat bordered dense :rows="rows" :columns="columns" row-key="name" class="col-12" hide-bottom v-model:pagination="pagination" /> <q-separator vertical />
</q-card-section> <div class="col-4 column q-pa-xs text-center">
</q-card> <span class="text-weight-bold">{{ item.remain }}</span>
</q-dialog> <span class="text-grey-7 text-caption">คงเหล</span>
</div>
</div>
</q-card>
</div>
</q-card>
</div>
<div class="row col-12 q-col-gutter-sm">
<!-- แสดงปฏ -->
<div class="col-12 row">
<q-card bordered class="q-pa-md col-12">
<div class="row col-12">
<div class="row items-center">
<div class="q-ml-sm">
<q-btn
round
dense
flat
size="13px"
class="q-px-sm"
@click="addAbsence"
>
<q-icon name="mdi-plus" size="22px" color="blue" />
<q-tooltip>นใบลา</q-tooltip>
</q-btn>
</div>
</div>
<q-space />
<div class="justify-center row items-center">
<!-- tab ปแบบแสดงวนหย ปฏนกบรายการ -->
<q-tabs
v-model="leaveStore.tabValue"
indicator-color="transparent"
align="left"
active-color="activetab"
class="text-nativetab"
inline-label
dense
>
<q-btn
name="calendar"
round
size="12px"
flat
icon="mdi-calendar-month"
@click="leaveStore.tabValue = 'calendar'"
:color="
leaveStore.tabValue == 'calendar' ? 'primary' : 'grey-6'
"
class="q-mr-sm"
>
<q-tooltip>ปฏ</q-tooltip>
</q-btn>
<q-separator vertical inset />
<q-btn
name="list"
round
size="12px"
flat
icon="mdi-format-list-bulleted"
@click="leaveStore.tabValue = 'list'"
:color="
leaveStore.tabValue == 'list' ? 'primary' : 'grey-6'
"
class="q-ml-sm"
>
<q-tooltip>รายการ</q-tooltip>
</q-btn>
</q-tabs>
</div>
</div>
<div class="col-12">
<CalendarView v-if="leaveStore.tabValue === 'calendar'" />
</div>
<div class="col-12">
<ListView v-if="leaveStore.tabValue === 'list'" />
</div>
</q-card>
</div>
</div>
</div>
</div>
<!-- modal ตารางสถการลา -->
<q-dialog v-model="data" persistent>
<q-card style="min-width: 85%">
<q-card-section class="row items-center q-pa-sm">
<div class="text-bold q-pl-sm">ตารางสถการลา</div>
<q-space />
<q-btn
icon="close"
unelevated
round
dense
v-close-popup
style="color: #ff8080; background-color: #ffdede"
/>
</q-card-section>
<q-separator />
<q-card-section class="q-p-md row">
<q-table
flat
bordered
dense
:rows="leaveStore.options"
:columns="columns"
row-key="name"
class="col-12"
hide-bottom
v-model:pagination="pagination"
/>
</q-card-section>
</q-card>
</q-dialog>
</template> </template>
<style scoped> <style scoped>
.borderTop { .borderTop {
border-top: 1px solid #ededed; border-top: 1px solid #ededed;
border-bottom: 1px solid #ededed; border-bottom: 1px solid #ededed;
} }
</style> </style>