เพิ่ม ui หน้ารายการลา
This commit is contained in:
parent
7f0e41ff31
commit
060be9b843
12 changed files with 938 additions and 16 deletions
|
|
@ -2,11 +2,11 @@
|
|||
* Router ขอโอน
|
||||
*/
|
||||
|
||||
const Main = () => import("@/modules/03_retire/views/main.vue")
|
||||
const Main = () => import("@/modules/03_retire/views/Main.vue")
|
||||
|
||||
const AddRetire = () => import("@/modules/03_retire/views/addRetire.vue")
|
||||
const AddRetire = () => import("@/modules/03_retire/views/AddRetire.vue")
|
||||
|
||||
const ResultQuestionair = () => import("@/modules/03_retire/views/result.vue")
|
||||
const ResultQuestionair = () => import("@/modules/03_retire/views/Result.vue")
|
||||
|
||||
export default [
|
||||
{
|
||||
|
|
|
|||
|
|
@ -2,8 +2,8 @@
|
|||
* Router Checkin
|
||||
*/
|
||||
|
||||
const Checkin = () => import("@/modules/04_checkin/views/checkIn.vue");
|
||||
const History = () => import("@/modules/04_checkin/views/history.vue");
|
||||
const Checkin = () => import("@/modules/04_checkin/views/CheckIn.vue");
|
||||
const History = () => import("@/modules/04_checkin/views/History.vue");
|
||||
|
||||
/* const Checkout = () => import("@/modules/04_checkin/views/Checkout.vue");
|
||||
*/
|
||||
|
|
|
|||
|
|
@ -65,7 +65,7 @@
|
|||
<q-card
|
||||
bordered
|
||||
flat
|
||||
class="col-12 bg-grey-2"
|
||||
class="col-12 bg-grey-2 shadow-0"
|
||||
:style="$q.screen.gt.xs ? 'height: 350px;' : 'height: 220px;'"
|
||||
>
|
||||
<!-- <mapCheckin /> -->
|
||||
|
|
@ -86,7 +86,8 @@
|
|||
<div class="col-12 col-sm-4">
|
||||
<q-card
|
||||
flat
|
||||
class="cardImg col-12 bg-grey-2 items-center row cursor-pointer "
|
||||
bordered
|
||||
class="cardImg col-12 bg-grey-2 items-center row cursor-pointer shadow-0"
|
||||
@click="photo()"
|
||||
:style="$q.screen.gt.xs ? 'height: 350px;' : 'height: 220px;'"
|
||||
>
|
||||
|
|
@ -123,7 +124,7 @@
|
|||
</q-card>
|
||||
</div>
|
||||
<div class="col-12 q-mb-md">
|
||||
<q-card bordered flat :class="$q.screen.gt.xs ? 'q-px-md q-py-sm row items-center': 'q-pa-md row items-center'">
|
||||
<q-card bordered flat :class="$q.screen.gt.xs ? 'q-px-md q-py-sm row items-center shadow-0': 'q-pa-md row items-center shadow-0'">
|
||||
<div class="text-weight-bold">สถานที่ทำงาน</div>
|
||||
<div :class="$q.screen.gt.xs ? 'row q-gutter-md q-pl-md col-sm-6 col-md-3': 'column col-12'">
|
||||
<q-radio v-model="workplace" checked-icon="task_alt" unchecked-icon="panorama_fish_eye" val="in-place" label="ในสถานที่" />
|
||||
|
|
@ -214,7 +215,8 @@ const coordinates = ref('13° 43’ 45” N 100° 31’ 26” E');
|
|||
const workplace = ref('in-place');
|
||||
const model = ref(null);
|
||||
const options = ref(['ปฏิบัติงานที่บ้าน', 'ลืมลงเวลาปฏิบัติงาน', 'ไปประชุม/อบรม/สัมมนา/ปฏิบัติงานที่บ้านนอกสถานที่', 'ขออนุญาตออกนอกสถานที่']);
|
||||
const checkIn = ref(true);
|
||||
|
||||
const checkIn = ref(true); //เช็คการเช็คอิน ถ้าลงเวลาครั้งแรกเป็นเช็คอิน(สีเขียว) true แต่ถ้าครั้ง 2 เป็นเช็คเอ้าท์(สีแดง) false
|
||||
|
||||
const camera = ref(false);
|
||||
const dialogTime = ref(false);
|
||||
|
|
|
|||
|
|
@ -60,7 +60,7 @@
|
|||
<div
|
||||
class="q-pa-xs col-xs-12 col-sm-6 col-md-4 col-lg-3 grid-style-transition"
|
||||
>
|
||||
<q-card bordered flat class="q-py-sm">
|
||||
<q-card bordered flat class="q-py-sm shadow-0">
|
||||
<q-list dense>
|
||||
<q-item v-for="col in props.cols" :key="col.name" :props="props">
|
||||
<q-item-section>
|
||||
|
|
@ -81,7 +81,6 @@
|
|||
</Table>
|
||||
</div>
|
||||
</q-card>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
|
@ -89,7 +88,7 @@
|
|||
import type { QTableProps } from "quasar";
|
||||
import { ref } from "vue";
|
||||
import { useRouter } from "vue-router";
|
||||
import Table from "@/modules/04_checkin/componenst/tableHistory.vue"
|
||||
import Table from "@/modules/04_checkin/componenst/TableHistory.vue"
|
||||
|
||||
const router = useRouter();
|
||||
|
||||
|
|
|
|||
264
src/modules/05_leave/componenst/Calendar.vue
Normal file
264
src/modules/05_leave/componenst/Calendar.vue
Normal file
|
|
@ -0,0 +1,264 @@
|
|||
<template>
|
||||
<div class="q-mt-sm">
|
||||
<div class="row q-gutter-sm q-pb-sm main-content">
|
||||
<div class="demo-app-main">
|
||||
<FullCalendar
|
||||
ref="fullCalendar"
|
||||
class="demo-app-calendar"
|
||||
:options="calendarOptions"
|
||||
>
|
||||
<template v-slot:eventContent="arg">
|
||||
<b>{{ arg.timeText }}</b>
|
||||
<i>{{ arg.event.title }}</i>
|
||||
</template>
|
||||
</FullCalendar>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row q-col-gutter-lg justify-end">
|
||||
<div class="items-center row">
|
||||
<q-icon size="10px" color="light-green" 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="red-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" />
|
||||
<span class="text-caption text-grey-8">สถานะอยู่ระหว่างดำเนินการ</span>
|
||||
</div>
|
||||
<div class="items-center row">
|
||||
<q-icon size="10px" color="orange" name="mdi-circle" class="q-mr-sm" />
|
||||
<span class="text-caption text-grey-8">สถานะใหม่</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</template>
|
||||
<script lang="ts">
|
||||
import { ref } from "vue";
|
||||
import FullCalendar from "@fullcalendar/vue3";
|
||||
import dayGridPlugin from "@fullcalendar/daygrid";
|
||||
|
||||
import timeGridPlugin from "@fullcalendar/timegrid";
|
||||
import interactionPlugin from "@fullcalendar/interaction";
|
||||
import allLocales from "@fullcalendar/core/locales-all";
|
||||
import listPlugin from "@fullcalendar/list";
|
||||
|
||||
// import interactionPlugin from "@fullcalendar/interaction";
|
||||
export default {
|
||||
components: {
|
||||
FullCalendar, // make the <FullCalendar> tag available
|
||||
calendar() {
|
||||
return (
|
||||
this.$refs.fullCalendar as InstanceType<typeof FullCalendar>
|
||||
).getApi();
|
||||
},
|
||||
},
|
||||
setup() {
|
||||
const name = ref<string>("");
|
||||
const date = ref<Date>(new Date());
|
||||
const fullCalendar = ref<InstanceType<typeof FullCalendar>>();
|
||||
const calendarOptions = ref({
|
||||
plugins: [
|
||||
dayGridPlugin,
|
||||
timeGridPlugin,
|
||||
interactionPlugin, // needed for dateClick
|
||||
listPlugin,
|
||||
],
|
||||
buttonText: {
|
||||
listYear: "รายการ",
|
||||
dayGridMonth: "ปฏิทิน",
|
||||
test: "เพิ่มวันหยุด",
|
||||
},
|
||||
headerToolbar: null,
|
||||
initialView: "dayGridMonth",
|
||||
initialEvents: [], // alternatively, use the `events` setting to fetch from a feed
|
||||
selectable: true,
|
||||
dayMaxEvents: true,
|
||||
weekends: true,
|
||||
locale: "th",
|
||||
locales: allLocales,
|
||||
expandRows: true,
|
||||
nowIndicator: true,
|
||||
height: "100%",
|
||||
eventColor: "#e4f3ff",
|
||||
eventTextColor: "#4A5568",
|
||||
eventBorderColor: "#50a5fc",
|
||||
displayEventTime: false,
|
||||
editable: true,
|
||||
events: []
|
||||
});
|
||||
calendarOptions.value.events = [
|
||||
{ groupId: "2", title: "ลากิจส่วนตัว", start: "2023-09-10", allDay: true, color: '#E3FDDA' },
|
||||
{ groupId: "1", title: "ลาป่วย", start: "2023-09-19", allDay: true, color: '#e4f3ff' },
|
||||
{ groupId: "1", title: "ลาป่วย", start: "2023-09-20", allDay: true, color: '#FFF1CC' },
|
||||
];
|
||||
return {
|
||||
calendarOptions,
|
||||
name,
|
||||
date
|
||||
};
|
||||
},
|
||||
};
|
||||
</script>
|
||||
|
||||
<style scope lang="scss">
|
||||
.main-content {
|
||||
height: 65vh;
|
||||
}
|
||||
|
||||
.color-main {
|
||||
color: #18a259;
|
||||
}
|
||||
|
||||
.padding-content {
|
||||
padding: 10px;
|
||||
}
|
||||
|
||||
.demo-app-main {
|
||||
flex-grow: 1;
|
||||
/* padding: 3em; */
|
||||
}
|
||||
|
||||
.fc {
|
||||
/* the calendar root */
|
||||
max-width: 1100px;
|
||||
margin: 0 auto;
|
||||
background-color: white;
|
||||
border-radius: 10px;
|
||||
}
|
||||
|
||||
.fc-day-today {
|
||||
background-color: #F8F8F8 !important;
|
||||
}
|
||||
|
||||
.fc-day-today .fc-daygrid-day-number {
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
/* border: 2px solid #17a259; */
|
||||
/* border-radius: 50%;
|
||||
height: 25px;
|
||||
width: 25px;
|
||||
font-weight: bold;
|
||||
color: white !important;
|
||||
background: #17a259; */
|
||||
}
|
||||
|
||||
.fc-day-today .fc-daygrid-day-frame {
|
||||
padding: 5%;
|
||||
}
|
||||
|
||||
.fc .fc-button-group > .fc-button {
|
||||
color: black;
|
||||
background-color: #fafafa;
|
||||
border: none;
|
||||
}
|
||||
|
||||
.fc .fc-button-group > .fc-button:active {
|
||||
color: white;
|
||||
background-color: #22a15e;
|
||||
border: none;
|
||||
}
|
||||
|
||||
.fc .fc-button-group > .fc-button.fc-button-active {
|
||||
color: white;
|
||||
background-color: #22a15e;
|
||||
border: none;
|
||||
}
|
||||
|
||||
.fc-header-toolbar {
|
||||
background-color: white;
|
||||
padding: 0px 10px 0px 10px;
|
||||
border-radius: 10px 10px 0px 0px;
|
||||
}
|
||||
|
||||
.fc .fc-scrollgrid-liquid > thead {
|
||||
background-color: white;
|
||||
}
|
||||
|
||||
.dp-custom-cell {
|
||||
border-radius: 50%;
|
||||
}
|
||||
|
||||
.dp__today {
|
||||
border: 1px solid var(--q-primary);
|
||||
}
|
||||
|
||||
.dp__range_end,
|
||||
.dp__range_start,
|
||||
.dp__active_date {
|
||||
background: var(--q-primary);
|
||||
color: var(--dp-primary-text-color);
|
||||
}
|
||||
|
||||
.datepicker .q-field__label {
|
||||
padding-left: 5px;
|
||||
}
|
||||
|
||||
.datepicker .q-field__messages {
|
||||
padding-left: 20px;
|
||||
}
|
||||
|
||||
.datepicker .q-field__native {
|
||||
padding-left: 5px;
|
||||
color: var(--q-primary) !important;
|
||||
}
|
||||
|
||||
.datepicker .q-field__prepend {
|
||||
padding-left: 6px;
|
||||
}
|
||||
|
||||
.datepicker .q-field__append {
|
||||
padding-right: 6px;
|
||||
}
|
||||
|
||||
.datepicker .q-field__after {
|
||||
display: flex;
|
||||
justify-content: flex-end;
|
||||
align-items: center;
|
||||
font-weight: 500;
|
||||
}
|
||||
|
||||
.fc .fc-popover {
|
||||
z-index: 6000;
|
||||
}
|
||||
|
||||
.fc-direction-ltr .fc-daygrid-event.fc-event-end,
|
||||
.fc-direction-rtl .fc-daygrid-event.fc-event-start {
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.subName {
|
||||
display: flex;
|
||||
justify-content: flex-end;
|
||||
align-items: center;
|
||||
font-weight: 500;
|
||||
}
|
||||
|
||||
.subInput {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.fc-event {
|
||||
overflow: hidden;
|
||||
border-color: transparent !important;
|
||||
font-weight: 500;
|
||||
}
|
||||
|
||||
.fc-event-main {
|
||||
text-align: left;
|
||||
padding:0px 5px;
|
||||
}
|
||||
|
||||
.fc-direction-ltr .fc-daygrid-event.fc-event-end,
|
||||
.fc-direction-rtl .fc-daygrid-event.fc-event-start {
|
||||
padding-left: 0px;
|
||||
}
|
||||
|
||||
.fc-theme-standard td, .fc-theme-standard th{
|
||||
border: 1px solid #EBE9F1;
|
||||
}
|
||||
</style>
|
||||
97
src/modules/05_leave/componenst/ListCalendar.vue
Normal file
97
src/modules/05_leave/componenst/ListCalendar.vue
Normal file
|
|
@ -0,0 +1,97 @@
|
|||
<template>
|
||||
<Table
|
||||
:style="$q.screen.gt.xs ? 'height: 58.5vh' : ''"
|
||||
:rows="rows"
|
||||
:columns="columns"
|
||||
:filter="filter"
|
||||
:visible-columns="visibleColumns"
|
||||
v-model:inputfilter="filter"
|
||||
v-model:inputvisible="visibleColumns"
|
||||
:pagination="initialPagination"
|
||||
:inputShow="true"
|
||||
:grid="$q.screen.gt.xs ? false : true"
|
||||
>
|
||||
<template #columns="props">
|
||||
<q-tr :props="props">
|
||||
<q-td key="no" :props="props">
|
||||
{{ props.rowIndex + 1 }}
|
||||
</q-td>
|
||||
<q-td key="type" :props="props">
|
||||
{{ props.row.type }}
|
||||
</q-td>
|
||||
<q-td key="date" :props="props">
|
||||
{{ props.row.date }}
|
||||
</q-td>
|
||||
|
||||
<q-td key="status" :props="props">
|
||||
<div class="col-12 row items-center">
|
||||
<q-icon v-if="props.row.status == 'อนุมัติ'" size="10px" color="light-green" name="mdi-circle" class="q-mr-sm" />
|
||||
<q-icon v-else-if="props.row.status == 'ไม่อนุมัติ'" size="10px" color="red-6" name="mdi-circle" 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>
|
||||
<q-space/>
|
||||
<q-btn v-if="props.row.status == 'ใหม่'" label="ขอยกเลิก" size="13px" class="q-px-sm" outline dense color="orange" />
|
||||
</div>
|
||||
</q-td>
|
||||
|
||||
|
||||
</q-tr>
|
||||
</template>
|
||||
</Table>
|
||||
</template>
|
||||
<script setup lang="ts">
|
||||
import type { QTableProps } from "quasar";
|
||||
import { ref } from "vue";
|
||||
import Table from "@/modules/05_leave/componenst/Table.vue"
|
||||
|
||||
|
||||
const filter = ref<string>("")
|
||||
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%;",
|
||||
},
|
||||
])
|
||||
const rows = ref<any>([
|
||||
{no:'1',date: '20 ก.ย. 2566',type: 'ลาป่วย',status: 'ใหม่' },
|
||||
{no:'2',date: '19 ก.ย. 2566',type: 'ลาป่วย',status: 'อยู่ระหว่างดำเนินการ' },
|
||||
{no:'3',date: '10 ก.ย. 2566',type: 'ลากิจส่วนตัว',status: 'อนุมัติ' },
|
||||
])
|
||||
const initialPagination = ref({
|
||||
rowsPerPage: 0,
|
||||
})
|
||||
</script>
|
||||
225
src/modules/05_leave/componenst/Table.vue
Normal file
225
src/modules/05_leave/componenst/Table.vue
Normal file
|
|
@ -0,0 +1,225 @@
|
|||
<template>
|
||||
<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">
|
||||
<div class="items-center col-12 row q-col-gutter-sm">
|
||||
<!-- ค้นหาข้อความใน table -->
|
||||
<q-select
|
||||
outlined
|
||||
dense
|
||||
lazy-rules
|
||||
v-model="type"
|
||||
:rules="[(val) => !!val || `${'กรุณาเลือกประเภทใบลา'}`]"
|
||||
:label="`${'ประเภทใบลา'}`"
|
||||
emit-value
|
||||
map-options
|
||||
option-label="name"
|
||||
:options="typeOptions"
|
||||
option-value="id"
|
||||
hide-bottom-space
|
||||
style="min-width: 150px;"
|
||||
class="col-xs-12 col-sm-auto"
|
||||
/>
|
||||
<q-select
|
||||
outlined
|
||||
dense
|
||||
lazy-rules
|
||||
v-model="status"
|
||||
:rules="[(val) => !!val || `${'กรุณาเลือกสถานะ'}`]"
|
||||
:label="`${'สถานะ'}`"
|
||||
emit-value
|
||||
map-options
|
||||
option-label="name"
|
||||
:options="statusOptions"
|
||||
option-value="id"
|
||||
hide-bottom-space
|
||||
style="min-width: 150px;"
|
||||
class="col-xs-12 col-sm-auto"
|
||||
/>
|
||||
<q-space/>
|
||||
<q-input
|
||||
standout
|
||||
dense
|
||||
:model-value="inputfilter"
|
||||
ref="filterRef"
|
||||
@update:model-value="updateInput"
|
||||
outlined
|
||||
debounce="300"
|
||||
placeholder="ค้นหา"
|
||||
class="gt-xs"
|
||||
style="max-width: 150px"
|
||||
>
|
||||
<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"
|
||||
>
|
||||
<template> </template>
|
||||
</q-select>
|
||||
</div>
|
||||
</q-card>
|
||||
</div>
|
||||
<div>
|
||||
<q-table
|
||||
ref="table"
|
||||
flat
|
||||
bordered
|
||||
class="custom-table2"
|
||||
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" v-html="col.label" />
|
||||
</q-th>
|
||||
|
||||
</q-tr>
|
||||
</template>
|
||||
<template #body="props">
|
||||
<slot v-bind="props" name="columns"></slot>
|
||||
</template>
|
||||
</q-table>
|
||||
</div>
|
||||
</template>
|
||||
<script setup lang="ts">
|
||||
import { ref, useAttrs } from "vue";
|
||||
const attrs = ref<any>(useAttrs());
|
||||
const table = ref<any>(null);
|
||||
const filterRef = ref<any>(null);
|
||||
|
||||
const type = ref('ทั้งหมด');
|
||||
const typeOptions = ref([
|
||||
'ทั้งหมด',
|
||||
'ลาป่วย',
|
||||
'ลากิจส่วนตัว',
|
||||
'ลาคลอดบุตร',
|
||||
'ลาช่วยเหลือภริยาที่คลอดบุตร',
|
||||
'ลาพักผ่อน',
|
||||
'ลาอุปสมบทหรือการลาประกอบพิธีฮัจย์ฯ',
|
||||
'ลาเข้ารับการตรวจเลือกหรือเข้ารับการเตรียมพล',
|
||||
'ลาไปศึกษา ฝึกอบรม ปฏิบัติการวิจัย หรือดูงาน',
|
||||
'ลาไปปฏิบัติงานในองค์การระหว่างประเทศ',
|
||||
'ลาติดตามคู่สมรส',
|
||||
'ลาฟื้นฟูสมรรถภาพด้านอาชีพ'
|
||||
])
|
||||
const status = ref('ทั้งหมด');
|
||||
const statusOptions = ref([
|
||||
'อนุมัติ',
|
||||
'ไม่อนุมัติ',
|
||||
'อยู่ระหว่างดำเนินการ',
|
||||
'ใหม่',
|
||||
])
|
||||
|
||||
const initialPagination = ref({
|
||||
rowsPerPage: 0,
|
||||
});
|
||||
const yearly = ref<number>(new Date().getFullYear());
|
||||
|
||||
const props = defineProps({
|
||||
count: Number,
|
||||
pass: Number,
|
||||
notpass: Number,
|
||||
|
||||
inputfilter: String,
|
||||
name: String,
|
||||
icon: String,
|
||||
inputvisible: Array,
|
||||
editvisible: Boolean,
|
||||
grid: Boolean,
|
||||
|
||||
inputShow: Boolean,
|
||||
});
|
||||
|
||||
const emit = defineEmits([
|
||||
"update:inputfilter",
|
||||
"update:inputvisible",
|
||||
"update:editvisible",
|
||||
]);
|
||||
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 resetFilter = () => {
|
||||
// reset ค่าที่ค้นหาเมื่อกดปุ่ม X ในกล่องค้นหา
|
||||
emit("update:inputfilter", "");
|
||||
filterRef.value.focus();
|
||||
};
|
||||
|
||||
</script>
|
||||
<style lang="scss">
|
||||
.icon-color {
|
||||
color: #4154b3;
|
||||
}
|
||||
|
||||
.custom-table2 {
|
||||
.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;
|
||||
}
|
||||
|
||||
.q-table td:nth-of-type(2) {
|
||||
z-index: 3 !important;
|
||||
}
|
||||
|
||||
.q-table th:nth-of-type(2),
|
||||
.q-table td:nth-of-type(2) {
|
||||
position: sticky;
|
||||
left: 0;
|
||||
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>
|
||||
77
src/modules/05_leave/interface/request/Calendar.ts
Normal file
77
src/modules/05_leave/interface/request/Calendar.ts
Normal file
|
|
@ -0,0 +1,77 @@
|
|||
interface DataNumObject {
|
||||
id: number;
|
||||
count: number;
|
||||
name: string;
|
||||
color: string;
|
||||
}
|
||||
|
||||
interface DataDateAddObject {
|
||||
year: number;
|
||||
holidayDate: Date | string;
|
||||
name: string;
|
||||
isSpecial: boolean;
|
||||
}
|
||||
|
||||
interface DataDateMonthObject {
|
||||
month: number;
|
||||
year: number;
|
||||
}
|
||||
|
||||
//ข้อมูล
|
||||
interface RequestItemsObject {
|
||||
createdAt?: Date;
|
||||
createdFullName: string;
|
||||
createdUserId: string;
|
||||
holidayDate: Date | string;
|
||||
id: string;
|
||||
isSpecial: boolean;
|
||||
lastUpdateFullName: string;
|
||||
lastUpdateUserId: string;
|
||||
lastUpdatedAt?: Date;
|
||||
name: string;
|
||||
originalDate: Date;
|
||||
}
|
||||
|
||||
interface DataDateRowObject {
|
||||
holidayDate: Date;
|
||||
name: string;
|
||||
isSpecial: boolean;
|
||||
id: string;
|
||||
}
|
||||
|
||||
interface DataDateListsObject {
|
||||
id: string;
|
||||
dateRange: [Date, Date];
|
||||
dataRangeRow: DataDateRowObject[];
|
||||
detail: string;
|
||||
isSpecial: boolean;
|
||||
}
|
||||
|
||||
//columns
|
||||
interface Columns {
|
||||
[index: number]: {
|
||||
name: string;
|
||||
align?: string;
|
||||
label: string;
|
||||
sortable?: boolean;
|
||||
field: string | ((row: any) => any);
|
||||
headerStyle?: string;
|
||||
style?: string;
|
||||
};
|
||||
}
|
||||
|
||||
interface TabsObject {
|
||||
label: string;
|
||||
value: string;
|
||||
}
|
||||
|
||||
export type {
|
||||
DataNumObject,
|
||||
DataDateAddObject,
|
||||
DataDateMonthObject,
|
||||
RequestItemsObject,
|
||||
DataDateRowObject,
|
||||
DataDateListsObject,
|
||||
Columns,
|
||||
TabsObject,
|
||||
};
|
||||
|
|
@ -1,3 +1,18 @@
|
|||
/**
|
||||
* Router leave
|
||||
*/
|
||||
const leave = () => import("@/modules/05_leave/views/Main.vue");
|
||||
|
||||
/* const Checkout = () => import("@/modules/04_checkin/views/Checkout.vue");
|
||||
*/
|
||||
export default [
|
||||
{
|
||||
path: "/leave",
|
||||
name: "leave",
|
||||
component: leave,
|
||||
meta: {
|
||||
Auth: true,
|
||||
Key: [7],
|
||||
},
|
||||
}
|
||||
]
|
||||
230
src/modules/05_leave/views/Main.vue
Normal file
230
src/modules/05_leave/views/Main.vue
Normal file
|
|
@ -0,0 +1,230 @@
|
|||
<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="router.go(-1)" />
|
||||
<div>รายการลา</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-xs-12 col-sm-12 col-md-11 row q-col-gutter-md">
|
||||
<div class="row col-12 q-col-gutter-sm">
|
||||
<div class="col-xs-12 col-sm-9 col-md-9 row">
|
||||
<q-card bordered class="q-pa-md col-12">
|
||||
<div class="row col-12">
|
||||
<div class="row items-center">
|
||||
<!-- filter เลือกเดือนปี -->
|
||||
<datepicker
|
||||
v-model="dateMonth"
|
||||
:locale="'th'"
|
||||
autoApply
|
||||
month-picker
|
||||
:enableTimePicker="false"
|
||||
v-if="currentTab === 'calendar'"
|
||||
>
|
||||
<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
|
||||
hide-bottom-space
|
||||
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>
|
||||
|
||||
<!-- filter เลือกปี -->
|
||||
<datepicker
|
||||
v-model="dateYear"
|
||||
:locale="'th'"
|
||||
autoApply
|
||||
year-picker
|
||||
:enableTimePicker="false"
|
||||
v-if="currentTab === '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">
|
||||
<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="currentTab"
|
||||
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="currentTab = 'calendar'"
|
||||
:color="currentTab == '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="currentTab = 'list'"
|
||||
:color="currentTab == 'list' ? 'primary' : 'grey-6'"
|
||||
class="q-ml-sm"
|
||||
>
|
||||
<q-tooltip>รายการ</q-tooltip>
|
||||
</q-btn>
|
||||
</q-tabs>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-12 ">
|
||||
<subCalendarComponent v-if="currentTab === 'calendar'"/>
|
||||
</div>
|
||||
|
||||
<div class="col-12 ">
|
||||
<subListCalendarComponent v-if="currentTab === 'list'" />
|
||||
</div>
|
||||
</q-card>
|
||||
</div>
|
||||
<div class="col-xs-12 col-sm-3 col-md-3 row">
|
||||
<q-card bordered class="col-12 row caedNone">
|
||||
<div class="col-12 row">
|
||||
<q-card class="row col-12 items-center q-px-md q-py-sm">
|
||||
<div class="text-weight-bold">สถิติการลา</div>
|
||||
<q-space/>
|
||||
<q-btn dense flat class="text-blue" icon="mdi-chart-line-variant" label="ตารางสถิติการลา" />
|
||||
</q-card>
|
||||
<div bordered class="col-12 row justify-center q-px-md q-pb-md" v-for="(item,index) in itemPie" :key="index">
|
||||
<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}`"
|
||||
>
|
||||
<span class="text-subtitle2 text-weight-bold">{{ item.value }}%</span>
|
||||
</q-knob>
|
||||
<div class="col-12 text-center text-weight-medium q-py-xs">
|
||||
{{item.text}}
|
||||
</div>
|
||||
<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">
|
||||
<span class="text-weight-bold">{{ item.all }}</span>
|
||||
<span class="text-grey-7 text-caption">ทั้งหมด</span>
|
||||
</div>
|
||||
<q-separator vertical />
|
||||
<div class="col-4 column q-pa-xs text-center">
|
||||
<span class="text-weight-bold">{{ item.use }}</span>
|
||||
<span class="text-grey-7 text-caption">ใช้ไป</span>
|
||||
</div>
|
||||
<q-separator vertical />
|
||||
<div class="col-4 column q-pa-xs text-center">
|
||||
<span class="text-weight-bold">{{ item.remain }}</span>
|
||||
<span class="text-grey-7 text-caption">คงเหลือ</span>
|
||||
</div>
|
||||
</div>
|
||||
</q-card>
|
||||
</div>
|
||||
</div>
|
||||
</q-card>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
<script setup lang="ts">
|
||||
import type { QTableProps } from "quasar";
|
||||
import { defineComponent, onMounted } from "@vue/runtime-core";
|
||||
import { reactive, ref, watch } from "vue";
|
||||
import { useRouter } from "vue-router";
|
||||
import subCalendarComponent from "@/modules/05_leave/componenst/Calendar.vue";
|
||||
import subListCalendarComponent from "@/modules/05_leave/componenst/ListCalendar.vue";
|
||||
import { useCounterMixin } from "@/stores/mixin";
|
||||
import type {
|
||||
DataDateMonthObject
|
||||
} from "@/modules/05_leave/interface/request/Calendar.ts";
|
||||
|
||||
const router = useRouter();
|
||||
const currentTab = ref<string>("calendar"); //ระบุ tab ใช้งานอยู่ calendar=รายการ list=รายการ
|
||||
const dateMonth = ref<number>(new Date().getFullYear());
|
||||
const dateYear = ref<number>(new Date().getFullYear());
|
||||
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 value = ref(90);
|
||||
const itemPie = ref([
|
||||
{text: 'ลาป่วย', color: 'text-pink-5', value: 90, all: '10', use: '9', remain: '1'},
|
||||
{text: 'ลากิจส่วนตัว', color: 'text-deep-purple', value: 80, all: '12', use: '9', remain: '3'},
|
||||
{text: 'ลาพักผ่อน', color: 'text-indigo', value: 78, all: '20', use: '17', remain: '3'}
|
||||
])
|
||||
</script>
|
||||
<style>
|
||||
.borderTop{
|
||||
border-top: 1px solid #EDEDED ;
|
||||
border-bottom:1px solid #EDEDED ;
|
||||
}
|
||||
</style>
|
||||
|
|
@ -4,8 +4,9 @@ const MainLayout = () => import("@/views/MainLayout.vue")
|
|||
const Dashboard = () => import("@/modules/01_dashboard/views/Dashboard.vue")
|
||||
|
||||
import ModuleTransfer from "@/modules/02_transfer/router.ts"
|
||||
import ModuleLeave from "@/modules/03_retire/router"
|
||||
import ModuleRetire from "@/modules/03_retire/router"
|
||||
import ModuleCheckin from "@/modules/04_checkin/router.ts"
|
||||
import ModuleLeave from "@/modules/05_leave/router.ts"
|
||||
// TODO: ใช้หรือไม่?
|
||||
import keycloak from "@/plugins/keycloak"
|
||||
|
||||
|
|
@ -27,8 +28,9 @@ const router = createRouter({
|
|||
},
|
||||
},
|
||||
...ModuleTransfer,
|
||||
...ModuleLeave,
|
||||
...ModuleCheckin
|
||||
...ModuleRetire,
|
||||
...ModuleCheckin,
|
||||
...ModuleLeave
|
||||
],
|
||||
},
|
||||
],
|
||||
|
|
|
|||
|
|
@ -129,6 +129,7 @@ const doLogout = () => {
|
|||
name="leave"
|
||||
label="การลา"
|
||||
icon="mdi-calendar-blank-outline"
|
||||
@click="router.push(`/leave`)"
|
||||
/>
|
||||
</q-tabs>
|
||||
</div>
|
||||
|
|
@ -298,7 +299,13 @@ const doLogout = () => {
|
|||
icon="mdi-map-marker-check-outline"
|
||||
@click="router.push(`/check-in`)"
|
||||
/>
|
||||
<q-btn flat round color="white" icon="mdi-calendar-blank-outline" />
|
||||
<q-btn
|
||||
flat
|
||||
round
|
||||
color="white"
|
||||
icon="mdi-calendar-blank-outline"
|
||||
@click="router.push(`/leave`)"
|
||||
/>
|
||||
<q-btn flat round color="white" icon="mdi-account-outline" />
|
||||
</div>
|
||||
</q-toolbar>
|
||||
|
|
@ -366,4 +373,8 @@ const doLogout = () => {
|
|||
.q-field--outlined .q-icon {
|
||||
color: #7474747f;
|
||||
}
|
||||
|
||||
.shadow-0{
|
||||
box-shadow:none !important;
|
||||
}
|
||||
</style>
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue