hrms-user/src/modules/05_leave/components/Table.vue
DESKTOP-1R2VSQH\Lenovo ThinkPad E490 1f18b56fbf fix:sortBy ,descending
- ทำ sortBy เฉพาะ API ที่มีการทำ paging
2025-09-15 13:52:27 +07:00

353 lines
9.2 KiB
Vue

<script setup lang="ts">
import { ref, useAttrs, watch } from "vue";
import { useQuasar } from "quasar";
import type { PropsTable } from "@/interface/PropsTable";
import { useLeaveStore } from "@/modules/05_leave/store";
const $q = useQuasar();
const attrs = ref<any>(useAttrs());
const leaveStore = useLeaveStore();
const { filterOption } = leaveStore;
/** รับ props มาจากหน้าหลัก */
const props = defineProps({
count: Number,
pass: Number,
notpass: Number,
total: Number,
name: String,
icon: String,
inputvisible: Array,
editvisible: Boolean,
grid: Boolean,
inputShow: Boolean,
maxPage: {
type: Number,
require: true,
},
pageSize: {
type: Number,
require: true,
},
leaveType: {
type: Object,
require: true,
},
isloadingData: {
type: Boolean,
default: false,
},
sortBy: {
type: String,
default: "dateSendLeave",
},
descending: {
type: Boolean,
default: true,
},
});
/**
* ฟังก์ชั่น emit ค่าที่กำหนด
*/
const emit = defineEmits([
"update:filter",
"update:Pagination",
"update:inputvisible",
"update:editvisible",
]);
const table = ref<any>(null);
/** ตั้งค่า pagination*/
const currentPage = ref<number>(1);
const pagination = ref<PropsTable.Pagination>({
sortBy: props.sortBy,
descending: props.descending,
page: 1,
rowsPerPage: Number(props.pageSize),
rowsNumber: Number(props.total),
});
// Watch props เพื่ออัปเดต pagination เมื่อค่าเปลี่ยน (เฉพาะ props)
watch(
() => [props.pageSize, props.total],
([newPageSize, newTotal]) => {
pagination.value.rowsPerPage = Number(newPageSize);
pagination.value.rowsNumber = Number(newTotal);
},
{ immediate: true }
);
/** filter */
const year = ref<number>(new Date().getFullYear());
const filter = ref<string>("");
/** updateVisible*/
function updateVisible(value: []) {
emit("update:inputvisible", value);
}
/** function updateFilter*/
function filterTable() {
emit(
"update:filter",
year.value,
leaveStore.type,
leaveStore.status,
filter.value
);
}
/**
* ฟังก์ชันอัปเดตการแบ่งหน้า
* @param p หน้า
* @param ps ขนาดหน้า
* @param sortBy เรียงลำดับตาม
* @param descending เรียงลำดับจากน้อยไปมาก
*/
function updatePagination(
p: number,
ps: number,
sortBy?: string,
descending?: boolean
) {
emit("update:Pagination", p, ps, sortBy, descending);
}
/**
* ฟังก์ชันรับ request จากตาราง เมื่อมีการเปลี่ยน pagination
* @param requestProps ข้อมูลการร้องขอจากตาราง
*/
function onTableRequest(requestProps: PropsTable.RequestProps) {
const newPagination = requestProps?.pagination || requestProps;
if (!newPagination?.page || !newPagination?.rowsPerPage) return;
currentPage.value = newPagination.page;
pagination.value = { ...newPagination };
updatePagination(
newPagination.page,
newPagination.rowsPerPage,
newPagination.sortBy,
newPagination.descending
);
}
</script>
<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">
<datepicker
v-if="leaveStore.tabValue === 'list'"
v-model="year"
class="col-xs-12 col-sm-auto"
:locale="'th'"
autoApply
year-picker
:enableTimePicker="false"
@update:modelValue="filterTable"
>
<template #year="{ year }">{{ year + 543 }}</template>
<template #year-overlay-value="{ value }">{{
parseInt(value + 543)
}}</template>
<template #trigger>
<q-input
dense
lazy-rules
outlined
:model-value="Number(year) + 543"
:label="`${'ปีงบประมาณ'}`"
>
<template v-slot:prepend>
<q-icon
name="event"
class="cursor-pointer"
style="color: var(--q-primary)"
>
</q-icon>
</template>
</q-input>
</template>
</datepicker>
<!-- ค้นหาข้อความใน table -->
<q-select
fill-input
hide-selected
outlined
dense
v-model="leaveStore.type"
:label="`${'ประเภทใบลา'}`"
emit-value
map-options
option-label="name"
:options="leaveStore.typeOptions"
option-value="id"
hide-bottom-space
style="min-width: 150px"
class="col-xs-12 col-sm-auto"
use-input
@update:model-value="filterTable"
@filter="(inputValue:any,
doneFn:Function) => filterOption(inputValue, doneFn,'LeaveTypeOption'
) "
typeOptionsMain
>
<template v-slot:no-option>
<q-item>
<q-item-section class="text-grey"> ไม่มีข้อมูล </q-item-section>
</q-item>
</template>
<template
v-if="leaveStore.type !== '00000000-0000-0000-0000-000000000000'"
v-slot:append
>
<q-icon
name="cancel"
@click.stop.prevent="
(leaveStore.typeOptions = leaveStore.typeOptionsMain),
(leaveStore.type = '00000000-0000-0000-0000-000000000000'),
filterTable()
"
class="cursor-pointer"
/> </template
></q-select>
<q-select
fill-input
hide-selected
outlined
dense
v-model="leaveStore.status"
:label="`${'สถานะ'}`"
emit-value
map-options
option-label="name"
:options="leaveStore.statusOptions"
option-value="id"
hide-bottom-space
style="min-width: 150px"
class="col-xs-12 col-sm-auto"
use-input
@update:model-value="filterTable"
@filter="(inputValue:any,
doneFn:Function) => filterOption(inputValue, doneFn,'LeaveStatusOption'
) "
>
<template v-slot:no-option>
<q-item>
<q-item-section class="text-grey"> ไม่มีข้อมูล </q-item-section>
</q-item>
</template>
<template v-if="leaveStore.status !== 'ALL'" v-slot:append>
<q-icon
name="cancel"
@click.stop.prevent="
(leaveStore.statusOptions = leaveStore.statusOptionsMain),
(leaveStore.status = 'ALL'),
filterTable()
"
class="cursor-pointer"
/> </template
></q-select>
<q-space />
<!-- แสดงคอลัมน์ใน 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: 140px"
class="gt-xs"
>
<template> </template>
</q-select>
</div>
</q-card>
</div>
<div>
<d-table
ref="table"
flat
bordered
v-bind="attrs"
virtual-scroll
:virtual-scroll-sticky-size-start="48"
dense
:rows-per-page-options="[10, 25, 50, 100]"
v-model:pagination="pagination"
@request="onTableRequest"
:grid="$q.screen.gt.xs ? false : true"
:loading="isloadingData"
>
<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>
<template v-slot:item="props">
<slot v-bind="props" name="item"></slot>
</template>
</d-table>
</div>
</template>
<style lang="scss" scoped>
.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>