hrms-user/src/modules/05_leave/components/ListView.vue

489 lines
15 KiB
Vue
Raw Normal View History

<script setup lang="ts">
2024-01-11 21:25:49 +07:00
import { ref, onMounted } from "vue";
import { useQuasar } from "quasar";
2025-10-07 10:52:23 +07:00
import { useRouter } from "vue-router";
2024-09-03 17:36:59 +07:00
2024-01-11 21:25:49 +07:00
import http from "@/plugins/http";
import config from "@/app.config";
2024-09-03 17:36:59 +07:00
import { useCounterMixin } from "@/stores/mixin";
import { useLeaveStore } from "@/modules/05_leave/store";
2025-10-07 10:52:23 +07:00
import { calculateFiscalYear } from "@/utils/functions";
2024-01-11 21:25:49 +07:00
import type { LeaveType } from "@/modules/05_leave/interface/response/leave";
2024-01-11 21:25:49 +07:00
import DialogDetail from "@/modules/05_leave/components/DialogDetail.vue";
import Table from "@/modules/05_leave/components/Table.vue";
/**ตัวแปรที่ใช้ */
2024-09-03 17:36:59 +07:00
const $q = useQuasar();
2024-01-11 21:25:49 +07:00
const mixin = useCounterMixin();
const router = useRouter();
2024-09-03 17:36:59 +07:00
const LeaveData = useLeaveStore();
const { showLoader, hideLoader, messageError, dialogRemove, success } = mixin;
const modal = ref<boolean>(false);
const leaveId = ref<string>("");
2024-09-03 17:36:59 +07:00
const leaveType = ref<LeaveType[]>();
const leaveStatus = ref<string>("");
/** filter */
2025-10-07 10:52:23 +07:00
const year = ref<number>(LeaveData.fiscalYearyear);
2024-01-11 21:25:49 +07:00
const type = ref<string>("00000000-0000-0000-0000-000000000000");
const status = ref<string>("ALL");
const filter = ref<string>("");
2025-08-05 15:15:49 +07:00
const isLoading = ref<boolean>(false);
/** pagination*/
2024-01-11 21:25:49 +07:00
const maxPage = ref<number>(1);
const page = ref<number>(1);
const pageSize = ref<number>(10);
2025-05-08 17:22:50 +07:00
const total = ref<number>(0);
const sortBy = ref<string>("dateSendLeave");
const descending = ref<boolean>(true);
/** function เรียกข้อมูลการลา*/
async function fetchDataTable() {
2025-08-05 15:15:49 +07:00
isLoading.value = true;
const body = {
year: year.value, //*ปีในการยื่นขอใบลา(ใช้เป็น คศ.)
2025-05-01 15:15:52 +07:00
type: LeaveData.type, //*Id ประเภทการลา
status: LeaveData.status, //*สถานะการของลา
page: page.value.toString(), //*หน้า
pageSize: pageSize.value.toString(), //*จำนวนแถวต่อหน้า
keyword: filter.value, //keyword ค้นหา
...(sortBy.value && {
sortBy: sortBy.value,
descending: descending.value,
}),
};
await http
.post(config.API.leaveTableList(), body)
.then((res) => {
const data = res.data.result.data;
LeaveData.fetchListLeave(data);
maxPage.value = Math.ceil(res.data.result.total / pageSize.value);
2025-05-01 17:06:06 +07:00
total.value = res.data.result.total;
})
.catch((err) => {
messageError($q, err);
})
.finally(() => {
2025-08-05 15:15:49 +07:00
isLoading.value = false;
});
}
/** function เรียกประเภทการลา */
async function fectOptionType() {
2025-06-16 11:15:31 +07:00
const data = await LeaveData.fetchLeaveTypeData();
if (!data) {
return;
}
leaveType.value = data;
LeaveData.fetchLeaveType(data);
}
/**
* function openPopupDateail
* @param id การลา
* @param status การลา
*/
2024-09-03 17:36:59 +07:00
async function onClickView(id: string, status: string) {
modal.value = true;
leaveId.value = id;
leaveStatus.value = status;
2024-09-03 17:36:59 +07:00
}
/**
* function ไปหน edit
* @param id
*/
2024-09-03 17:36:59 +07:00
async function onClickEdit(id: string) {
router.push(`/leave/edit/${id}`);
2024-09-03 17:36:59 +07:00
}
/**
2025-06-16 11:15:31 +07:00
* งกนลบขอมลการลา
* @param id รายการลาทองการลบ
*/
2025-06-16 11:15:31 +07:00
function clickDelete(id: string) {
dialogRemove($q, async () => {
showLoader();
await http
.delete(config.API.leaveUserId(id))
.then(async () => {
await fetchDataTable();
success($q, "ลบข้อมูลสำเร็จ");
})
.catch((err) => {
messageError($q, err);
})
.finally(() => {
hideLoader();
});
});
2024-09-03 17:36:59 +07:00
}
/** function closePopup*/
async function onClickClose() {
modal.value = false;
}
/**
* function updateFilter
* @param y งบประมาณ
* @param t ประเภทการลา
* @param s สภานะ
* @param k คำคนหา
*/
async function updateFilterTable(y: number, t: string, s: string, k: string) {
if (t && s) {
2025-08-05 15:15:49 +07:00
year.value = y;
type.value = t;
status.value = s;
filter.value = k;
2025-10-07 10:52:23 +07:00
LeaveData.fiscalYearyear = y;
await fetchDataTable();
}
}
/**
* function updatePagination
* @param p หน
* @param ps แถวตอหน
* @param s เรยงลำดบตาม
* @param d เรยงลำดบจากนอยไปมาก
*/
async function updatePagination(p: number, ps: number, s: string, d: boolean) {
page.value = p;
pageSize.value = ps;
sortBy.value = s;
descending.value = d;
await fetchDataTable();
}
2024-07-30 16:49:17 +07:00
function convert(val: any) {
if (leaveType.value) {
const filtertype = leaveType.value.find(
(e: any) => e.id === val.leaveTypeId
);
const type = filtertype?.code;
if (type == "LV-006" && val.hajjDayStatus == false) {
2025-04-09 15:58:44 +07:00
return "ลาอุปสมบทหรือการลาประกอบพิธีฮัจญ์ฯ";
// return "ลาอุปสมบท"; รอ API
2024-07-30 16:49:17 +07:00
} else if (type == "LV-006" && val.hajjDayStatus == true) {
2025-04-09 15:58:44 +07:00
return "ลาอุปสมบทหรือการลาประกอบพิธีฮัจญ์ฯ";
// return "ลาประกอบพิธีฮัจญ์"; รอ API
2024-07-30 16:49:17 +07:00
} else {
return val.leaveTypeName;
}
}
}
/**
* เรยกฟงกนทงหมดตอนเรยกใชไฟล
*/
onMounted(async () => {
2025-10-07 10:52:23 +07:00
year.value = LeaveData.fiscalYearyear;
2025-08-05 15:15:49 +07:00
await fectOptionType();
await fetchDataTable();
2024-01-11 21:25:49 +07:00
});
</script>
<template>
<Table
:rows="LeaveData.rows"
:columns="LeaveData.columns"
:visible-columns="LeaveData.visibleColumns"
v-model:inputfilter="filter"
v-model:inputvisible="LeaveData.visibleColumns"
:inputShow="true"
:grid="$q.screen.gt.xs ? false : true"
@update:filter="updateFilterTable"
@update:Pagination="updatePagination"
:maxPage="maxPage"
:pageSize="pageSize"
:leaveType="leaveType"
2025-05-01 17:06:06 +07:00
:total="total"
:sortBy="sortBy"
:descending="descending"
2025-08-05 15:15:49 +07:00
:isloadingData="isLoading"
>
<template #columns="props">
<q-tr :props="props" class="cursor-pointer">
<q-td
key="no"
:props="props"
@click="onClickView(props.row.id, props.row.status)"
>
2025-09-01 11:25:56 +07:00
{{ props.rowIndex + 1 }}
</q-td>
<q-td
key="leaveTypeName"
:props="props"
@click="onClickView(props.row.id, props.row.status)"
>
2025-05-08 17:22:50 +07:00
{{
props.row.leaveTypeName
? `${props.row.leaveTypeName} ${
props.row.leaveSubTypeName
? `(${props.row.leaveSubTypeName})`
: ""
}`
: "-"
}}
</q-td>
<q-td
key="leaveStartDate"
:props="props"
@click="onClickView(props.row.id, props.row.status)"
>
{{ props.row.dateLeave }}
</q-td>
<q-td
key="dateSendLeave"
:props="props"
@click="onClickView(props.row.id, props.row.status)"
>
{{ props.row.dateSendLeave }}
</q-td>
2024-01-11 21:25:49 +07:00
<q-td key="status" :props="props">
<div class="col-12 row items-center">
<div @click="onClickView(props.row.id, props.row.status)">
<q-icon
v-if="props.row.status == 'DRAFT'"
size="10px"
color="light-grey"
name="mdi-circle"
class="q-mr-sm"
/>
<q-icon
v-if="props.row.status == 'APPROVE'"
size="10px"
color="light-green"
name="mdi-circle"
class="q-mr-sm"
/>
<q-icon
v-else-if="props.row.status == 'REJECT'"
size="10px"
color="red-6"
name="mdi-circle"
class="q-mr-sm"
/>
<q-icon
v-else-if="props.row.status == 'PENDING'"
size="10px"
color="light-blue-14"
name="mdi-circle"
class="q-mr-sm"
/>
<q-icon
v-else-if="props.row.status == 'NEW'"
size="10px"
color="orange"
name="mdi-circle"
class="q-mr-sm"
/>
<q-icon
2025-05-08 17:22:50 +07:00
v-if="
props.row.status == 'DELETING' || props.row.status == 'DELETE'
"
size="10px"
color="grey-10"
name="mdi-circle"
class="q-mr-sm"
/>
2024-01-11 21:25:49 +07:00
<span class="q-pr-md">{{ props.row.statusConvert }}</span>
</div>
<q-space />
2024-01-11 21:25:49 +07:00
<q-btn
v-if="
props.row.status != 'DELETE' &&
props.row.status != 'REJECT' &&
props.row.status != 'CANCEL' &&
props.row.status != 'DELETING'
"
flat
icon="mdi-dots-vertical"
color="grey-8"
for="#cancel"
dense
round
unelevated
>
<q-menu>
<q-list>
<q-item
v-if="props.row.status != 'DRAFT'"
clickable
v-close-popup
@click="onClickView(props.row.id, 'CANCEL')"
>
<q-item-section>
<q-item-label>ขอยกเล</q-item-label>
</q-item-section>
</q-item>
<q-item
v-if="props.row.status == 'DRAFT'"
clickable
v-close-popup
@click="onClickEdit(props.row.id)"
>
<q-item-section>
<q-item-label>แกไข</q-item-label>
</q-item-section>
</q-item>
<q-item
v-if="props.row.status == 'DRAFT'"
clickable
v-close-popup
@click="clickDelete(props.row.id)"
>
<q-item-section>
<q-item-label>ลบรายการการลา</q-item-label>
</q-item-section>
</q-item>
</q-list>
</q-menu>
</q-btn>
</div>
</q-td>
</q-tr>
</template>
2024-01-11 21:25:49 +07:00
<template #item="props">
<div class="q-pa-xs col-xs-12 col-sm-6 col-md-4 col-lg-3">
<q-card bordered flat>
<div class="row justify-end">
<q-btn
v-if="
props.row.status != 'DELETE' &&
props.row.status != 'REJECT' &&
props.row.status != 'CANCEL'
"
flat
icon="mdi-dots-vertical"
color="grey-8"
for="#cancel"
dense
round
unelevated
@click.pervent
>
<q-menu>
<q-list>
<q-item
clickable
v-close-popup
@click="onClickView(props.row.id, 'CANCEL')"
>
<q-item-section>
<q-item-label>ขอยกเล</q-item-label>
</q-item-section>
</q-item>
<q-item
v-if="props.row.status == 'DRAFT'"
clickable
v-close-popup
@click="onClickEdit(props.row.id)"
>
<q-item-section>
<q-item-label>แกไข</q-item-label>
</q-item-section>
</q-item>
<q-item
v-if="props.row.status == 'DRAFT'"
clickable
v-close-popup
@click="clickDelete(props.row.id)"
>
<q-item-section>
<q-item-label>ลบรายการการลา</q-item-label>
</q-item-section>
</q-item>
</q-list>
</q-menu>
</q-btn>
</div>
<q-separator />
<q-list @click.prevent="onClickView(props.row.id, props.row.status)">
<q-item
v-for="col in props.cols.filter((col:any) => col.name !== 'desc')"
:key="col.name"
>
<q-item-section>
<q-item-label caption>{{ col.label }}</q-item-label>
<q-item-label v-if="col.name === 'no'">
{{ (page - 1) * pageSize + props.rowIndex + 1 }}
</q-item-label>
<q-item-label v-if="col.name === 'status'">
<q-icon
v-if="props.row.status == 'DRAFT'"
size="10px"
color="light-grey"
name="mdi-circle"
class="q-mr-sm"
/>
<q-icon
v-if="props.row.status == 'APPROVE'"
size="10px"
color="light-green"
name="mdi-circle"
class="q-mr-sm"
/>
<q-icon
v-else-if="props.row.status == 'REJECT'"
size="10px"
color="red-6"
name="mdi-circle"
class="q-mr-sm"
/>
<q-icon
v-else-if="props.row.status == 'PENDING'"
size="10px"
color="light-blue-14"
name="mdi-circle"
class="q-mr-sm"
/>
<q-icon
v-else-if="props.row.status == 'NEW'"
size="10px"
color="orange"
name="mdi-circle"
class="q-mr-sm"
/>
<q-icon
2025-05-08 17:22:50 +07:00
v-if="
props.row.status == 'DELETING' ||
props.row.status == 'DELETE'
"
size="10px"
color="grey-10"
name="mdi-circle"
class="q-mr-sm"
/>
<span class="q-pr-md">{{ props.row.statusConvert }}</span>
</q-item-label>
<q-item-label v-else>{{ col.value }}</q-item-label>
</q-item-section>
</q-item>
</q-list>
</q-card>
</div>
</template>
</Table>
<DialogDetail
:modal="modal"
:leaveId="leaveId"
:leaveStatus="leaveStatus"
:onClickClose="onClickClose"
:leaveType="leaveType"
:fetchDataTable="fetchDataTable"
/>
</template>