Merge branch 'develop' into devTee

This commit is contained in:
setthawutttty 2025-08-06 14:40:54 +07:00
commit e9504b30b1
64 changed files with 3479 additions and 3455 deletions

View file

@ -1,5 +1,5 @@
<script setup lang="ts"> <script setup lang="ts">
import { computed } from "vue"; import { ref } from "vue";
/** importType*/ /** importType*/
import type { QTableProps } from "quasar"; import type { QTableProps } from "quasar";
@ -8,29 +8,55 @@ const columns = defineModel<QTableProps["columns"]>("columns", {
required: true, required: true,
}); });
/** จำนวนคอลัมน์ */ const rows = ref<Array<{ id: string; name: string }>>([
const skeletonColumns = computed(() => columns.value?.length || 5); {
id: "",
name: "",
},
]);
/** ตัวอย่างการใช้งาน */ /** ตัวอย่างการใช้งาน */
/// <SkeletonTable v-if="isLoading" :columns="columns" /> /// <SkeletonTable v-if="isLoading" :columns="columns" />
</script> </script>
<template> <template>
<q-markup-table flat bordered> <d-table
<thead> flat
<tr> bordered
<th v-for="(n, idx) in skeletonColumns" :key="idx" style="width: 150px"> :columns="columns"
<q-skeleton type="text" /> :rows="rows"
</th> row-key="id"
</tr> hide-pagination
</thead> >
<template v-slot:body="props">
<q-tr :props="props" class="cursor-pointer">
<q-td v-for="col in props.cols" :key="col.name" :props="props">
<div>
<q-skeleton type="text" width="80px" />
</div>
</q-td>
</q-tr>
</template>
<tbody> <template v-slot:item="props">
<tr v-for="n in 5" :key="n" :class="n % 2 === 0 ? 'bg-grey-2' : ''"> <div class="q-mb-xs col-xs-12 col-sm-6 col-md-4 col-lg-3">
<td v-for="(col, idx) in skeletonColumns" :key="idx"> <q-card bordered flat>
<q-skeleton type="text" width="80px" /> <q-list dense class="q-mt-lg relative-position">
</td> <q-item v-for="col in props.cols" :key="col.name">
</tr> <q-item-section>
</tbody> <q-item-label class="text-grey-6 text-weight-medium">{{
</q-markup-table> col.label
}}</q-item-label>
</q-item-section>
<q-item-section>
<q-item-label class="text-dark text-weight-medium">
<q-skeleton type="text" />
</q-item-label>
</q-item-section>
</q-item>
</q-list>
</q-card>
</div>
</template>
</d-table>
</template> </template>

View file

@ -10,7 +10,6 @@ import type { Permission } from "@/components/Workflow/interface/index/Main";
import type { DataListState } from "@/components/Workflow/interface/response/Main"; import type { DataListState } from "@/components/Workflow/interface/response/Main";
import DialogSelectPerson from "@/components/Workflow/DialogSelectPerson.vue"; import DialogSelectPerson from "@/components/Workflow/DialogSelectPerson.vue";
import Keycloak from "keycloak-js";
const $q = useQuasar(); const $q = useQuasar();
const { dialogConfirm, showLoader, hideLoader, messageError } = const { dialogConfirm, showLoader, hideLoader, messageError } =
@ -31,6 +30,7 @@ const stateId = ref<string>(""); //id state ปัจุบัน
const state = ref<number>(1); //state const state = ref<number>(1); //state
const isPermission = ref<boolean>(true); // Workflow const isPermission = ref<boolean>(true); // Workflow
const KeycloakId = ref<string>(""); const KeycloakId = ref<string>("");
const isLoading = ref<boolean>(false); //
const permission = ref<Permission>({ const permission = ref<Permission>({
isChangeState: false, /// isChangeState: false, ///
@ -48,6 +48,7 @@ const itemState = ref<DataListState[]>([]);
/** ฟังก์ชันเรียกข้อมูล Workflow ที่อยู่ปัจุบัน*/ /** ฟังก์ชันเรียกข้อมูล Workflow ที่อยู่ปัจุบัน*/
async function fetchCheckState() { async function fetchCheckState() {
isLoading.value = true;
await http await http
.post(config.API.workflow + `check-user-now`, { .post(config.API.workflow + `check-user-now`, {
refId: id, refId: id,
@ -74,6 +75,9 @@ async function fetchCheckState() {
}) })
.catch(() => { .catch(() => {
isPermission.value = false; isPermission.value = false;
})
.finally(() => {
isLoading.value = false;
}); });
} }
@ -129,7 +133,22 @@ defineExpose({
<div class="q-pl-sm text-weight-bold text-dark">สถานะการดำเนนเรอง</div> <div class="q-pl-sm text-weight-bold text-dark">สถานะการดำเนนเรอง</div>
</div> </div>
<div class="col-12"><q-separator /></div> <div class="col-12"><q-separator /></div>
<q-card-section> <q-card-section class="col-12 q-px-lg q-py-md" v-if="isLoading">
<q-timeline color="primary">
<q-timeline-entry
v-for="(step, index) in 4"
:key="index"
:icon="`mdi-numeric-${index + 1}`"
color="grey-4"
>
<template #title>
<q-skeleton type="rect" width="150px" height="20px" />
</template>
</q-timeline-entry>
</q-timeline>
</q-card-section>
<q-card-section v-else>
<div class="q-px-lg q-py-md"> <div class="q-px-lg q-py-md">
<q-timeline color="primary"> <q-timeline color="primary">
<q-timeline-entry <q-timeline-entry

View file

@ -26,8 +26,9 @@ const { showLoader, hideLoader, date2Thai, messageError } = mixin;
const fullname = ref<string>(""); // const fullname = ref<string>(""); //
const inboxList = ref<InboxDetail[]>([]); // const inboxList = ref<InboxDetail[]>([]); //
const idInboxActive = ref<string>(); // Id const idInboxActive = ref<string>(); // Id
// const isLoadingInbox = ref<boolean>(true); //
//
const filteredItems = computed(() => { const filteredItems = computed(() => {
const isOfficer = dataStore.officerType === "OFFICER"; const isOfficer = dataStore.officerType === "OFFICER";
const conditions: Record<string, boolean> = { const conditions: Record<string, boolean> = {
@ -148,7 +149,10 @@ const items = ref<MenuMainList[]>([
* @param index หนาทโหลดขอม * @param index หนาทโหลดขอม
*/ */
const fetchlistInbox = async (index: number) => { const fetchlistInbox = async (index: number) => {
index === 1 && showLoader(); if (index === 1) {
isLoadingInbox.value = true; //
}
index != 0 && index != 0 &&
(await http (await http
.get(config.API.msgInbox + `?page=${index}&pageSize=${10}`) .get(config.API.msgInbox + `?page=${index}&pageSize=${10}`)
@ -173,7 +177,7 @@ const fetchlistInbox = async (index: number) => {
} }
}) })
.finally(() => { .finally(() => {
hideLoader(); isLoadingInbox.value = false;
})); }));
}; };
@ -249,11 +253,17 @@ const totalInbox = ref<number>(0); // จำนวนข้อความทั
*/ */
async function onLoad(index: number, done: Function) { async function onLoad(index: number, done: Function) {
const num = index === 1 ? 0 : index++; const num = index === 1 ? 0 : index++;
if (inboxList.value.length < totalInbox.value) { try {
setTimeout(() => { // infinite scroll
fetchlistInbox(num); if (inboxList.value.length >= totalInbox.value) {
done(); done(true);
}, 3000); return;
}
await fetchlistInbox(num);
done();
} catch (error) {
done(true);
} }
} }
@ -284,7 +294,16 @@ onMounted(async () => {
v-for="(item, j) in filteredItems" v-for="(item, j) in filteredItems"
:key="j" :key="j"
> >
<q-card bordered @click="goToPage(item.path)" class="noactive col-12"> <q-card v-if="dataStore.isLoadingMenu" bordered class="col-12">
<q-skeleton width="100%" height="180px" />
</q-card>
<q-card
v-else
bordered
@click="goToPage(item.path)"
class="noactive col-12"
>
<div class="col-12"> <div class="col-12">
<q-avatar <q-avatar
:color="item.color" :color="item.color"
@ -323,12 +342,28 @@ onMounted(async () => {
กลองขอความ กลองขอความ
</div> </div>
<q-space /> <q-space />
<div class="text-grey-5" style="font-size: 12px"> <div v-if="isLoadingInbox">
<q-skeleton type="text" width="80px" />
</div>
<div v-else class="text-grey-5" style="font-size: 12px">
งหมด {{ totalInbox }} อความ งหมด {{ totalInbox }} อความ
</div> </div>
</div> </div>
<div <div
v-if="totalInbox != 0" class="q-pa-sm"
v-if="isLoadingInbox"
style="height: calc(100% - 60px)"
>
<div v-for="(item, index) in 3">
<q-skeleton type="text" width="10%" class="text-subtitle1" />
<q-skeleton type="text" width="50%" class="text-subtitle1" />
<q-skeleton type="text" class="text-caption" />
</div>
</div>
<div
v-if="totalInbox != 0 && !isLoadingInbox"
ref="scrollTargetRef" ref="scrollTargetRef"
style="max-height: 90%; overflow: auto" style="max-height: 90%; overflow: auto"
> >
@ -400,7 +435,11 @@ onMounted(async () => {
</q-infinite-scroll> </q-infinite-scroll>
</div> </div>
<q-banner rounded class="bg-amber-1 text-center q-mx-sm" v-else> <q-banner
rounded
class="bg-amber-1 text-center q-mx-sm"
v-else-if="totalInbox === 0 && !isLoadingInbox"
>
<div class="text-yellow-10"> <div class="text-yellow-10">
<q-icon <q-icon
name="mdi-alert-box" name="mdi-alert-box"

View file

@ -26,7 +26,7 @@ import DialogDetail from "@/modules/05_leave/components/DialogDetail.vue";
const $q = useQuasar(); const $q = useQuasar();
const store = useLeaveStore(); const store = useLeaveStore();
const mixin = useCounterMixin(); const mixin = useCounterMixin();
const { showLoader, hideLoader, messageError, monthYear2Thai } = mixin; const { messageError, monthYear2Thai } = mixin;
const emit = defineEmits(["update:dateYear"]); const emit = defineEmits(["update:dateYear"]);
const mainData = ref<DataCalendar[]>([]); const mainData = ref<DataCalendar[]>([]);
@ -37,10 +37,10 @@ const leaveId = ref<string>("");
/** filter calendar left */ /** filter calendar left */
const filterLists = ref<any>([]); const filterLists = ref<any>([]);
const filterVal = ref<any>([keycloakId.value]); const filterVal = ref<any>([keycloakId.value]);
const isLoading = ref<boolean>(false);
const isLoadingHoliday = ref<boolean>(false);
/** /** Option ของปฏิทิน */
* Option ของปฏ
*/
const fullCalendar = ref<any>(); //ref calendar const fullCalendar = ref<any>(); //ref calendar
const calendarOptions = ref<any>({ const calendarOptions = ref<any>({
plugins: [ plugins: [
@ -76,6 +76,7 @@ const dateMonth = ref<DataDateMonthObject>({
/** function เรียกข้อมูล calendar*/ /** function เรียกข้อมูล calendar*/
async function fetchDataCalendar() { async function fetchDataCalendar() {
isLoading.value = true;
await http await http
.post(config.API.leaveCalendar(), { .post(config.API.leaveCalendar(), {
year: dateMonth.value.year, year: dateMonth.value.year,
@ -119,6 +120,9 @@ async function fetchDataCalendar() {
}) })
.catch((err) => { .catch((err) => {
messageError($q, err); messageError($q, err);
})
.finally(() => {
isLoading.value = false;
}); });
} }
@ -126,6 +130,7 @@ async function fetchDataCalendar() {
* fetch นหยดในปฏ * fetch นหยดในปฏ
*/ */
async function fetchData() { async function fetchData() {
isLoadingHoliday.value = true;
await http await http
.get( .get(
config.API.listHolidayHistoryYearMonth( config.API.listHolidayHistoryYearMonth(
@ -154,6 +159,9 @@ async function fetchData() {
}) })
.catch((e) => { .catch((e) => {
messageError($q, e); messageError($q, e);
})
.finally(() => {
isLoadingHoliday.value = false;
}); });
} }
@ -193,7 +201,6 @@ async function updateMonth() {
} catch (error) { } catch (error) {
messageError($q, error); messageError($q, error);
} finally { } finally {
hideLoader();
} }
} }
@ -215,7 +222,6 @@ async function onClickClose() {
watch( watch(
() => filterVal.value, () => filterVal.value,
async () => { async () => {
showLoader();
const eventData = filterVal.value.map((item: any) => { const eventData = filterVal.value.map((item: any) => {
return mainData.value return mainData.value
.filter( .filter(
@ -236,14 +242,13 @@ watch(
const allEventData = [].concat(...eventData); const allEventData = [].concat(...eventData);
calendarOptions.value.events = allEventData; calendarOptions.value.events = allEventData;
await fetchData(); await fetchData();
hideLoader();
} }
); );
/**Hook */ /**Hook */
onMounted(async () => { onMounted(async () => {
try { try {
showLoader(); isLoading.value = true;
// keycloakId // keycloakId
const user = await tokenParsed(); const user = await tokenParsed();
keycloakId.value = await (user ? user.sub : ""); keycloakId.value = await (user ? user.sub : "");
@ -253,7 +258,7 @@ onMounted(async () => {
} catch (error) { } catch (error) {
messageError($q, error); messageError($q, error);
} finally { } finally {
hideLoader(); isLoading.value = false;
} }
}); });
</script> </script>
@ -262,7 +267,8 @@ onMounted(async () => {
<div class="row"> <div class="row">
<div class="col-xs-12 col-md-3 q-mt-sm q-pr-sm row"> <div class="col-xs-12 col-md-3 q-mt-sm q-pr-sm row">
<q-card class="col-12" flat bordered> <q-card class="col-12" flat bordered>
<q-scroll-area style="height: 38vw"> <q-skeleton height="100%" square v-if="isLoading" />
<q-scroll-area style="height: 38vw" v-else>
<div class="q-gutter-sm col-12"> <div class="q-gutter-sm col-12">
<q-list class="rounded-borders q-pt-sm" dense> <q-list class="rounded-borders q-pt-sm" dense>
<q-item <q-item
@ -333,7 +339,13 @@ onMounted(async () => {
</q-card> </q-card>
<div class="main-content"> <div class="main-content">
<q-skeleton
height="100%"
square
v-if="isLoading || isLoadingHoliday"
/>
<FullCalendar <FullCalendar
v-else
ref="fullCalendar" ref="fullCalendar"
class="demo-app-calendar" class="demo-app-calendar"
:options="calendarOptions" :options="calendarOptions"

View file

@ -164,6 +164,7 @@ const formDataCancle = reactive<FromCancelDetail>({
leaveRangeEnd: "", leaveRangeEnd: "",
leaveDirectorComment: "", leaveDirectorComment: "",
}); });
const isLoading = ref<boolean>(false);
/** form ขอยกเลิก*/ /** form ขอยกเลิก*/
const formDelete = reactive<FormDelete>({ const formDelete = reactive<FormDelete>({
@ -187,7 +188,7 @@ const formDeleteRef: FormDeleteRef = {
* @param id การลา * @param id การลา
*/ */
async function fetchDataDetail(id: string) { async function fetchDataDetail(id: string) {
showLoader(); isLoading.value = true;
await http await http
.get(config.API.leaveUserId(id), {}) .get(config.API.leaveUserId(id), {})
.then((res) => { .then((res) => {
@ -280,7 +281,7 @@ async function fetchDataDetail(id: string) {
messageError($q, err); messageError($q, err);
}) })
.finally(() => { .finally(() => {
hideLoader(); isLoading.value = false;
}); });
} }
@ -308,10 +309,7 @@ function checkLeaveType(leaveTypeId: string) {
checkForm.value = "FormHajj"; checkForm.value = "FormHajj";
} else if (type === "LV-007") { } else if (type === "LV-007") {
checkForm.value = "FormCheckSelect"; checkForm.value = "FormCheckSelect";
} else if ( } else if (type === "LV-008" && formData.leaveSubTypeName === "ศึกษาต่อ") {
type === "LV-008" &&
formData.leaveSubTypeName === "ศึกษาต่อ"
) {
checkForm.value = "FormStudy"; checkForm.value = "FormStudy";
} else if ( } else if (
(type === "LV-008" && formData.leaveSubTypeName === "ฝึกอบรม") || (type === "LV-008" && formData.leaveSubTypeName === "ฝึกอบรม") ||
@ -334,7 +332,7 @@ function checkLeaveType(leaveTypeId: string) {
* @param id ยกเลกการลา * @param id ยกเลกการลา
*/ */
async function fetchDataCancelDetail(id: string) { async function fetchDataCancelDetail(id: string) {
showLoader(); isLoading.value = true;
await http await http
.get(config.API.leaveCancelById(id)) .get(config.API.leaveCancelById(id))
.then((res) => { .then((res) => {
@ -362,7 +360,7 @@ async function fetchDataCancelDetail(id: string) {
messageError($q, err); messageError($q, err);
}) })
.finally(() => { .finally(() => {
hideLoader(); isLoading.value = false;
}); });
} }
@ -401,7 +399,8 @@ async function onSubmit() {
formData.append("doc", formDelete.doc); formData.append("doc", formDelete.doc);
await http await http
.post(config.API.leaveCancelById(id), formData) .post(config.API.leaveCancelById(id), formData)
.then(() => { .then(async () => {
await props.fetchDataTable?.();
success($q, "บันทึกข้อมูลสำเร็จ"); success($q, "บันทึกข้อมูลสำเร็จ");
props.onClickClose?.(); props.onClickClose?.();
}) })
@ -409,7 +408,6 @@ async function onSubmit() {
messageError($q, err); messageError($q, err);
}) })
.finally(() => { .finally(() => {
props.fetchDataTable?.();
hideLoader(); hideLoader();
}); });
} }
@ -445,7 +443,9 @@ watch(
<q-separator /> <q-separator />
<q-card-section class="scroll" style="max-height: 60vh"> <q-card-section class="scroll" style="max-height: 60vh">
<div class="row"> <q-skeleton height="400px" square v-if="isLoading" />
<div class="row" v-else>
<div <div
flat flat
:class=" :class="
@ -571,6 +571,7 @@ watch(
label="ยืนยัน" label="ยืนยัน"
unelevated unelevated
color="secondary" color="secondary"
:loading="isLoading"
@click="onClickSave" @click="onClickSave"
/> />
</q-card-section> </q-card-section>
@ -584,7 +585,8 @@ watch(
<q-separator /> <q-separator />
<q-card-section class="q-p-md row q-gutter-y-md"> <q-card-section class="q-p-md row q-gutter-y-md">
<div flat class="col-12"> <q-skeleton height="400px" width="100%" square v-if="isLoading" />
<div flat class="col-12" v-else>
<div class="col-12 q-col-gutter-sm row items-center"></div> <div class="col-12 q-col-gutter-sm row items-center"></div>
<FormCancel :data="formDataCancle" /> <FormCancel :data="formDataCancle" />
</div> </div>

View file

@ -30,6 +30,7 @@ const year = ref<number>(new Date().getFullYear());
const type = ref<string>("00000000-0000-0000-0000-000000000000"); const type = ref<string>("00000000-0000-0000-0000-000000000000");
const status = ref<string>("ALL"); const status = ref<string>("ALL");
const filter = ref<string>(""); const filter = ref<string>("");
const isLoading = ref<boolean>(false);
/** pagination*/ /** pagination*/
const maxPage = ref<number>(1); const maxPage = ref<number>(1);
@ -38,7 +39,7 @@ const pageSize = ref<number>(10);
const total = ref<number>(0); const total = ref<number>(0);
/** function เรียกข้อมูลการลา*/ /** function เรียกข้อมูลการลา*/
async function fetchDataTable() { async function fetchDataTable() {
showLoader(); isLoading.value = true;
const body = { const body = {
year: year.value, //*( .) year: year.value, //*( .)
type: LeaveData.type, //*Id type: LeaveData.type, //*Id
@ -59,7 +60,7 @@ async function fetchDataTable() {
messageError($q, err); messageError($q, err);
}) })
.finally(() => { .finally(() => {
hideLoader(); isLoading.value = false;
}); });
} }
@ -128,10 +129,10 @@ async function onClickClose() {
*/ */
async function updateFilterTable(y: number, t: string, s: string, k: string) { async function updateFilterTable(y: number, t: string, s: string, k: string) {
if (t && s) { if (t && s) {
year.value = await y; year.value = y;
type.value = await t; type.value = t;
status.value = await s; status.value = s;
filter.value = await k; filter.value = k;
await fetchDataTable(); await fetchDataTable();
} }
} }
@ -142,7 +143,7 @@ async function updateFilterTable(y: number, t: string, s: string, k: string) {
* @param ps แถวตอหน * @param ps แถวตอหน
*/ */
async function updatePagination(p: number, ps: number) { async function updatePagination(p: number, ps: number) {
(page.value = await p), (pageSize.value = await ps); (page.value = p), (pageSize.value = ps);
await fetchDataTable(); await fetchDataTable();
} }
@ -168,15 +169,8 @@ function convert(val: any) {
* เรยกฟงกนทงหมดตอนเรยกใชไฟล * เรยกฟงกนทงหมดตอนเรยกใชไฟล
*/ */
onMounted(async () => { onMounted(async () => {
try { await fectOptionType();
showLoader(); await fetchDataTable();
await fectOptionType();
await fetchDataTable();
} catch (error) {
messageError($q, error);
} finally {
hideLoader();
}
}); });
</script> </script>
<template> <template>
@ -194,6 +188,7 @@ onMounted(async () => {
:pageSize="pageSize" :pageSize="pageSize"
:leaveType="leaveType" :leaveType="leaveType"
:total="total" :total="total"
:isloadingData="isLoading"
> >
<template #columns="props"> <template #columns="props">
<q-tr :props="props" class="cursor-pointer"> <q-tr :props="props" class="cursor-pointer">

View file

@ -3,6 +3,7 @@ import { ref, useAttrs, watch } from "vue";
import { useQuasar } from "quasar"; import { useQuasar } from "quasar";
import { useLeaveStore } from "@/modules/05_leave/store"; import { useLeaveStore } from "@/modules/05_leave/store";
import SkeletonTable from "@/components/SkeletonTable.vue";
const $q = useQuasar(); const $q = useQuasar();
const attrs = ref<any>(useAttrs()); const attrs = ref<any>(useAttrs());
@ -15,7 +16,6 @@ const props = defineProps({
pass: Number, pass: Number,
notpass: Number, notpass: Number,
total: Number, total: Number,
name: String, name: String,
icon: String, icon: String,
inputvisible: Array, inputvisible: Array,
@ -34,6 +34,10 @@ const props = defineProps({
type: Object, type: Object,
require: true, require: true,
}, },
isloadingData: {
type: Boolean,
default: false,
},
}); });
/** /**
@ -48,9 +52,7 @@ const emit = defineEmits([
const table = ref<any>(null); const table = ref<any>(null);
/** /** ตั้งค่า pagination*/
* งค pagination
*/
const currentPage = ref<number>(1); const currentPage = ref<number>(1);
const pagination = ref({ const pagination = ref({
sortBy: "dateSendLeave", sortBy: "dateSendLeave",
@ -235,7 +237,9 @@ watch([() => currentPage.value, () => pagination.value.rowsPerPage], () => {
</q-card> </q-card>
</div> </div>
<div> <div>
<SkeletonTable v-if="isloadingData" :columns="leaveStore.columns" />
<d-table <d-table
v-else
ref="table" ref="table"
flat flat
bordered bordered

View file

@ -118,11 +118,11 @@ const columns = ref<QTableProps["columns"]>([
}, },
]); ]);
const isloading = ref<boolean>(false); const isloadingSummary = ref<boolean>(false);
/** function เรียกข้อมูลตารางสถิติการลา*/ /** function เรียกข้อมูลตารางสถิติการลา*/
async function fetchStatsTable() { async function fetchStatsTable() {
isloading.value = true; isloadingSummary.value = true;
await http await http
.get(config.API.leaveStats()) .get(config.API.leaveStats())
.then((res) => { .then((res) => {
@ -171,11 +171,12 @@ async function fetchStatsTable() {
leaveCountReject: e.leaveCountReject, leaveCountReject: e.leaveCountReject,
leaveCountDelete: e.leaveCountDelete, leaveCountDelete: e.leaveCountDelete,
})); }));
isloading.value = false;
}) })
.catch((err) => { .catch((err) => {
messageError($q, err); messageError($q, err);
isloading.value = true; })
.finally(() => {
isloadingSummary.value = false;
}); });
} }
@ -215,7 +216,7 @@ onMounted(async () => {
<div class="col-xs-12 col-sm-12 col-md-11 row"> <div class="col-xs-12 col-sm-12 col-md-11 row">
<!-- สถการลา --> <!-- สถการลา -->
<div class="col-12 row q-pb-sm"> <div class="col-12 row q-pb-sm">
<q-card bordered class="col-12 row" v-if="!isloading"> <q-card bordered class="col-12 row" v-if="!isloadingSummary">
<div class="row col-12 items-center q-px-md q-py-sm"> <div class="row col-12 items-center q-px-md q-py-sm">
<div class="text-weight-bold">สถการลา</div> <div class="text-weight-bold">สถการลา</div>
<q-space /> <q-space />
@ -278,6 +279,7 @@ onMounted(async () => {
</q-card> </q-card>
</div> </div>
</div> </div>
<div class="col-6 row"> <div class="col-6 row">
<div <div
bordered bordered

View file

@ -198,7 +198,7 @@ const formDataStep1 = ref<PersonInformation>();
* @param id id ประเม * @param id id ประเม
*/ */
async function fetchDataStep1(id: string) { async function fetchDataStep1(id: string) {
showLoader(); // showLoader();
showLoadStatus.value = false; showLoadStatus.value = false;
await http await http
.get(config.API.evaluationCheckspecByid(id)) .get(config.API.evaluationCheckspecByid(id))
@ -211,9 +211,6 @@ async function fetchDataStep1(id: string) {
}) })
.finally(() => { .finally(() => {
showLoadStatus.value = true; showLoadStatus.value = true;
setTimeout(() => {
hideLoader();
}, 3000);
}); });
} }
@ -581,7 +578,9 @@ async function saveStep7() {
.then(() => { .then(() => {
route.params.id && fetchCheckStep(route.params.id.toString()); route.params.id && fetchCheckStep(route.params.id.toString());
}) })
.catch(() => {}) .catch((err) => {
messageError($q, err);
})
.finally(() => { .finally(() => {
hideLoader(); hideLoader();
}); });

View file

@ -1,5 +1,5 @@
<script setup lang="ts"> <script setup lang="ts">
import { reactive, onMounted } from "vue"; import { reactive, ref, onMounted } from "vue";
import { useRouter } from "vue-router"; import { useRouter } from "vue-router";
import { useQuasar } from "quasar"; import { useQuasar } from "quasar";
@ -25,11 +25,12 @@ const formData = reactive<FormCommandSe>({
commanderAbovePosition: "", commanderAbovePosition: "",
}); });
/** const isLoading = ref(false);
* นยนการบนทกขอม
*/ /** ยืนยันการบันทึกข้อมูล */
function onSubmit() { function onSubmit() {
dialogConfirm($q, () => { dialogConfirm($q, async () => {
showLoader();
const body = { const body = {
...formData, ...formData,
citizenId: dataPerson.formData.citizenId, citizenId: dataPerson.formData.citizenId,
@ -40,8 +41,7 @@ function onSubmit() {
posNo: dataPerson.formData.posNo, posNo: dataPerson.formData.posNo,
birthDate: dataPerson.formData.birthDate, birthDate: dataPerson.formData.birthDate,
}; };
showLoader(); await http
http
.post(config.API.evaluationExpertise, body) .post(config.API.evaluationExpertise, body)
.then((res) => { .then((res) => {
router.push(`/evaluate/detail/expertise/${res.data.result.id}`); router.push(`/evaluate/detail/expertise/${res.data.result.id}`);
@ -55,12 +55,10 @@ function onSubmit() {
}); });
} }
/** /** ฟังก์ชันดึงข้อมูลรายชื่อ ผู้บังคับบัญชาชั้นต้น */
* fetch รายช งคบบญชาชนต, async function getData() {
*/ isLoading.value = true;
function getData() { await http
showLoader();
http
.get(config.API.orgSearchCommander()) .get(config.API.orgSearchCommander())
.then(async (res) => { .then(async (res) => {
const data = await res.data.result; const data = await res.data.result;
@ -74,12 +72,12 @@ function getData() {
messageError($q, e); messageError($q, e);
}) })
.finally(() => { .finally(() => {
hideLoader(); isLoading.value = false;
}); });
} }
onMounted(() => { onMounted(async () => {
getData(); await getData();
}); });
</script> </script>
@ -103,7 +101,14 @@ onMounted(() => {
</div> </div>
<div class="col-xs-12 col-sm-12 col-md-11 row q-col-gutter-md"> <div class="col-xs-12 col-sm-12 col-md-11 row q-col-gutter-md">
<div class="col-12"> <div class="col-12">
<q-card bordered> <q-skeleton
v-if="isLoading"
height="230px"
square
style="border-radius: 8px"
/>
<q-card bordered v-else>
<div class="col-12 row q-pa-md q-col-gutter-y-md"> <div class="col-12 row q-pa-md q-col-gutter-y-md">
<div class="col-12"> <div class="col-12">
<q-card bordered class="col-12"> <q-card bordered class="col-12">

File diff suppressed because it is too large Load diff

View file

@ -16,6 +16,7 @@ const { showLoader, hideLoader, messageError, formatDatePosition } =
const modal = defineModel<boolean>("modal", { required: true }); const modal = defineModel<boolean>("modal", { required: true });
const isLoading = ref<boolean>(false);
const cardData = ref<CardDataPos[]>([ const cardData = ref<CardDataPos[]>([
{ {
label: "ระยะเวลาดำรงตำแหน่งในสายงาน", label: "ระยะเวลาดำรงตำแหน่งในสายงาน",
@ -36,7 +37,7 @@ function onClosePopup() {
} }
async function fetchDataPosition() { async function fetchDataPosition() {
showLoader(); isLoading.value = true;
await http await http
.get(config.API.salaryTenurePosition("")) .get(config.API.salaryTenurePosition(""))
.then((res) => { .then((res) => {
@ -76,7 +77,7 @@ async function fetchDataPosition() {
messageError($q, err); messageError($q, err);
}) })
.finally(() => { .finally(() => {
hideLoader(); isLoading.value = false;
}); });
} }
@ -98,7 +99,19 @@ watch(modal, (v) => {
<q-separator /> <q-separator />
<q-card-section> <q-card-section>
<div class="row q-col-gutter-sm q-pb-sm"> <div class="row q-col-gutter-sm q-pb-sm">
<div class="col" v-for="(item, index) in cardData" :key="index"> <q-skeleton
v-if="isLoading"
type="Qcard"
width="100%"
height="240px"
/>
<div
v-else
class="col"
v-for="(item, index) in cardData"
:key="index"
>
<q-card bordered class="col-12" style="border: 1px solid #d6dee1"> <q-card bordered class="col-12" style="border: 1px solid #d6dee1">
<div class="col-12 text-weight-medium bg-grey-1 q-py-xs q-px-md"> <div class="col-12 text-weight-medium bg-grey-1 q-py-xs q-px-md">
{{ item.label }} {{ item.label }}

View file

@ -8,6 +8,7 @@ import config from "@/app.config";
import http from "@/plugins/http"; import http from "@/plugins/http";
import { useEvaluateStore } from "@/modules/06_evaluate/store"; import { useEvaluateStore } from "@/modules/06_evaluate/store";
import { useCounterMixin } from "@/stores/mixin"; import { useCounterMixin } from "@/stores/mixin";
import SkeletonTable from "@/components/SkeletonTable.vue";
/** use*/ /** use*/
const $q = useQuasar(); const $q = useQuasar();
@ -37,6 +38,10 @@ const props = defineProps({
type: Function, type: Function,
require: true, require: true,
}, },
isLoading: {
type: Boolean,
default: false,
},
}); });
const emit = defineEmits(["update:pagination"]); const emit = defineEmits(["update:pagination"]);
@ -135,7 +140,9 @@ onMounted(() => {
</script> </script>
<template> <template>
<SkeletonTable v-if="isLoading" :columns="columns" />
<d-table <d-table
v-else
ref="table" ref="table"
flat flat
bordered bordered

View file

@ -37,6 +37,7 @@ const formData = reactive<FormSpec>({
isHaveProLicense: false, // isHaveProLicense: false, //
isHaveMinPeriodOrHoldPos: false, // ] isHaveMinPeriodOrHoldPos: false, // ]
}); });
const isLoading = ref<boolean>(false);
/** function อัปเดทตรวจสอบคุณสมบัติ*/ /** function อัปเดทตรวจสอบคุณสมบัติ*/
async function updateValue() { async function updateValue() {
@ -48,6 +49,7 @@ async function updateValue() {
* @param data ตรวจสอบคณสมบ * @param data ตรวจสอบคณสมบ
*/ */
async function fetchCheckSpec(data: PersonInformation) { async function fetchCheckSpec(data: PersonInformation) {
isLoading.value = true;
formData.isEducationalQft = data.isEducationalQft; formData.isEducationalQft = data.isEducationalQft;
formData.isGovermantServiceHtr = data.isGovermantServiceHtr; formData.isGovermantServiceHtr = data.isGovermantServiceHtr;
formData.isOperatingExp = data.isOperatingExp; formData.isOperatingExp = data.isOperatingExp;
@ -55,6 +57,7 @@ async function fetchCheckSpec(data: PersonInformation) {
formData.isHaveSpecificQft = data.isHaveSpecificQft; formData.isHaveSpecificQft = data.isHaveSpecificQft;
formData.isHaveProLicense = data.isHaveProLicense; formData.isHaveProLicense = data.isHaveProLicense;
formData.isHaveMinPeriodOrHoldPos = data.isHaveMinPeriodOrHoldPos; formData.isHaveMinPeriodOrHoldPos = data.isHaveMinPeriodOrHoldPos;
isLoading.value = false;
} }
/** /**
@ -87,7 +90,14 @@ onMounted(() => {
</script> </script>
<template> <template>
<div class="q-pa-sm"> <q-skeleton
v-if="isLoading"
class="q-mb-md"
type="Qcard"
width="100%"
height="100%"
/>
<div class="q-pa-sm" v-else>
<q-list dense> <q-list dense>
<q-item v-ripple class="listItem"> <q-item v-ripple class="listItem">
<q-item-section avatar> <q-item-section avatar>

View file

@ -52,6 +52,7 @@ const formTemplates = ref<any[]>([
fileName: "1-แบบพิจารณาคุณสมบัติบุคคล", fileName: "1-แบบพิจารณาคุณสมบัติบุคคล",
downloadFile: "", downloadFile: "",
file: null, file: null,
isLoading: false,
}, },
{ {
code: "EV1_006", code: "EV1_006",
@ -60,6 +61,7 @@ const formTemplates = ref<any[]>([
fileName: "2-แบบแสดงรายละเอียดการเสนอผลงาน", fileName: "2-แบบแสดงรายละเอียดการเสนอผลงาน",
downloadFile: "", downloadFile: "",
file: null, file: null,
isLoading: false,
}, },
{ {
code: "EV1_008", code: "EV1_008",
@ -68,6 +70,7 @@ const formTemplates = ref<any[]>([
fileName: "4-แบบประเมินคุณลักษณะบุคคล", fileName: "4-แบบประเมินคุณลักษณะบุคคล",
downloadFile: "", downloadFile: "",
file: null, file: null,
isLoading: false,
}, },
{ {
code: "EV1_010", code: "EV1_010",
@ -76,6 +79,7 @@ const formTemplates = ref<any[]>([
fileName: "6-ผลงานที่จะส่งประเมิน (เอกสารหมายเลข 11)", fileName: "6-ผลงานที่จะส่งประเมิน (เอกสารหมายเลข 11)",
downloadFile: "", downloadFile: "",
file: null, file: null,
isLoading: false,
}, },
]); ]);
@ -96,6 +100,7 @@ const numOfPages = ref<number>(0);
const page = ref<number>(1); const page = ref<number>(1);
const pdfSrc = ref<any>(); const pdfSrc = ref<any>();
const profile = ref<any>(); const profile = ref<any>();
const isLoading = ref<boolean>(false);
/** function ไปหน้าต่อไปของรายงาน */ /** function ไปหน้าต่อไปของรายงาน */
function nextPage() { function nextPage() {
@ -201,8 +206,9 @@ async function uploadfile(uploadUrl: string, file: any) {
* function fecth รายชอผเซนเอกสาร * function fecth รายชอผเซนเอกสาร
* @param id evaluate ID * @param id evaluate ID
*/ */
function fetcheSigner(id: string) { async function fetcheSigner(id: string) {
http isLoading.value = true;
await http
.get(config.API.evaluationSignerDoc1(id)) .get(config.API.evaluationSignerDoc1(id))
.then((res) => { .then((res) => {
const data = res.data.result; const data = res.data.result;
@ -220,9 +226,12 @@ function fetcheSigner(id: string) {
formCommand.subject = data.subject; formCommand.subject = data.subject;
store.statusUpload = true; store.statusUpload = true;
}) })
.catch(() => { .catch(async () => {
store.statusUpload = false; store.statusUpload = false;
getCommander(); await getCommander();
})
.finally(() => {
isLoading.value = false;
}); });
} }
@ -247,6 +256,11 @@ async function fetchCheckSpec(id: string) {
* @param fileName อไฟล * @param fileName อไฟล
*/ */
async function downloadFile(fileName: string) { async function downloadFile(fileName: string) {
const loadingKey = formTemplates.value.findIndex(
(item) => item.fileName === fileName
);
formTemplates.value[loadingKey].isLoading = true;
await http await http
.get(config.API.loadFileDocument("เล่ม 1", evaluateId.value, fileName)) .get(config.API.loadFileDocument("เล่ม 1", evaluateId.value, fileName))
.then((res) => { .then((res) => {
@ -264,6 +278,7 @@ async function downloadFile(fileName: string) {
}; };
emit("update:form", formCommand, ref); emit("update:form", formCommand, ref);
formTemplates.value[loadingKey].isLoading = false;
}); });
} }
@ -316,29 +331,16 @@ watch(
/**lifecycle Hooks*/ /**lifecycle Hooks*/
onMounted(async () => { onMounted(async () => {
const user = await tokenParsed();
try { try {
showLoader();
await Promise.all([ await Promise.all([
fetcheSigner(evaluateId.value), fetcheSigner(evaluateId.value),
fetchCheckSpec(evaluateId.value), fetchCheckSpec(evaluateId.value),
formTemplates.value.forEach((e) => { formTemplates.value.forEach((e) => {
downloadFile(e.fileName); downloadFile(e.fileName);
}), }),
// downloadFile("1-"),
// downloadFile("2-"),
// downloadFile(
// "3- ( )"
// ),
// downloadFile("4-"),
// downloadFile("5- ( 9)"),
// downloadFile("6- ( 11)"),
]); ]);
} catch (error) { } catch (error) {
console.log(error); console.log(error);
} finally {
hideLoader();
} }
}); });
</script> </script>
@ -347,7 +349,8 @@ onMounted(async () => {
<div class="col-12 q-pa-sm"> <div class="col-12 q-pa-sm">
<!-- ผลงาน --> <!-- ผลงาน -->
<div class="col-12"> <div class="col-12">
<q-card bordered class="cardSp1 col-12"> <q-skeleton type="Qcard" height="100px" v-if="isLoading" class="q-mb-sm" />
<q-card v-else bordered class="cardSp1 col-12">
<div class="text-weight-medium bg-grey-1 col-12 q-py-sm q-px-md"> <div class="text-weight-medium bg-grey-1 col-12 q-py-sm q-px-md">
ผลงาน ผลงาน
</div> </div>
@ -422,7 +425,8 @@ onMounted(async () => {
<!-- เลอกผเซนเอกสาร --> <!-- เลอกผเซนเอกสาร -->
<div class="col-12"> <div class="col-12">
<q-card bordered class="cardSp1 col-12"> <q-skeleton type="Qcard" height="200px" v-if="isLoading" />
<q-card v-else bordered class="cardSp1 col-12">
<div class="text-weight-medium bg-grey-1 q-py-sm q-px-md"> <div class="text-weight-medium bg-grey-1 q-py-sm q-px-md">
เลอกผเซนเอกสาร เลอกผเซนเอกสาร
</div> </div>
@ -573,14 +577,16 @@ onMounted(async () => {
</div> </div>
<!-- v-if="store.statusUpload --> <!-- v-if="store.statusUpload -->
<div class="row q-col-gutter-sm"> <div class="row q-col-gutter-sm q-mt-sm">
<div <div
class="col-6" class="col-6"
v-if="store.currentStep === 2" v-if="store.currentStep === 2"
v-for="(item, index) in formTemplates" v-for="(item, index) in formTemplates"
:key="index" :key="index"
> >
<q-card bordered class="cardSp1"> <q-skeleton type="Qcard" height="100px" v-if="item.isLoading" />
<q-card bordered class="cardSp1" v-else>
<div <div
class="text-weight-medium bg-grey-1 q-py-sm q-pl-md q-pr-sm col-12 row items-center" class="text-weight-medium bg-grey-1 q-py-sm q-pl-md q-pr-sm col-12 row items-center"
> >
@ -662,541 +668,6 @@ onMounted(async () => {
</div> </div>
</q-card> </q-card>
</div> </div>
<!-- แบบพจารณาคณสมบคคล -->
<!-- <div class="col-6" v-if="store.currentStep === 2">
<q-card bordered class="cardSp1">
<div
class="text-weight-medium bg-grey-1 q-py-sm q-pl-md q-pr-sm col-12 row items-center"
>
<div>แบบพจารณาคณสมบคคล</div>
<q-space />
<div>
<q-btn
flat
dense
icon="download"
color="indigo"
@click="
onClickDowloadFile(
'EV1_005',
'template-1',
'แบบพิจารณาคุณสมบัติบุคคล'
)
"
>
<q-tooltip> ดาวนโหลดตนแบบ </q-tooltip></q-btn
>
</div>
<div>
<q-btn
v-if="downloadFile1 != ''"
:href="downloadFile1"
target="_blank"
class="q-ml-sm"
color="blue"
flat
dense
icon="visibility"
>
<q-tooltip> ไฟลเอกสาร </q-tooltip></q-btn
>
</div>
</div>
<div class="col-12"><q-separator /></div>
<div class="row">
<div class="col-12 q-pa-sm">
<div class="row q-col-gutter-md col-12">
<q-file
ref="fileEvaluation1Ref"
v-model="fileEvaluation1"
:disable="!store.statusUpload"
class="col-xs-12 col-sm-12"
label="อัปโหลดไฟล์"
outlined
dense
lazy-rules
hide-bottom-space
accept=".pdf"
:rules="
downloadFile1 === ''
? [(val:any) => !!val || 'กรุณาเลือกไฟล์']
: []
"
>
<template v-slot:prepend>
<q-icon name="attach_file" />
</template>
<template v-slot:after>
<q-btn
:disable="!store.statusUpload"
flat
round
dense
color="primary"
icon="mdi-upload"
@click="
fetchPathUpload(
'เล่ม 1',
evaluateId,
'1-แบบพิจารณาคุณสมบัติบุคคล',
fileEvaluation1
)
"
><q-tooltip>ปโหลดไฟล</q-tooltip></q-btn
>
</template>
</q-file>
</div>
</div>
</div>
</q-card>
</div> -->
<!-- แบบแสดงรายละเอยดการเสนอผลงาน -->
<!-- <div class="col-6" v-if="store.currentStep === 2">
<q-card bordered class="cardSp1">
<div
class="text-weight-medium bg-grey-1 q-py-sm q-pl-md q-pr-sm col-12 row items-center"
>
<div>แบบแสดงรายละเอยดการเสนอผลงาน</div>
<q-space />
<div>
<q-btn
flat
dense
icon="download"
color="indigo"
@click="
onClickDowloadFile(
'EV1_006',
'template-2',
'แบบแสดงรายละเอียดการเสนอผลงาน'
)
"
>
<q-tooltip> ดาวนโหลดตนแบบ </q-tooltip></q-btn
>
</div>
<div>
<q-btn
v-if="downloadFile2 != ''"
:href="downloadFile2"
target="_blank"
class="q-ml-sm"
color="blue"
flat
dense
icon="visibility"
>
<q-tooltip> ไฟลเอกสาร </q-tooltip></q-btn
>
</div>
</div>
<div class="col-12"><q-separator /></div>
<div class="row">
<div class="col-12 q-pa-sm">
<div class="row q-col-gutter-md col-12">
<q-file
ref="fileEvaluation2Ref"
v-model="fileEvaluation2"
:disable="!store.statusUpload"
class="col-12"
outlined
dense
label="อัปโหลดไฟล์"
lazy-rules
accept=".pdf"
hide-bottom-space
:rules="
downloadFile2 === ''
? [(val:any) => !!val || 'กรุณาเลือกไฟล์']
: []
"
>
<template v-slot:prepend>
<q-icon name="attach_file" />
</template>
<template v-slot:after>
<q-btn
:disable="!store.statusUpload"
flat
round
dense
color="primary"
icon="mdi-upload"
@click="
fetchPathUpload(
'เล่ม 1',
evaluateId,
'2-แบบแสดงรายละเอียดการเสนอผลงาน',
fileEvaluation2
)
"
><q-tooltip>ปโหลดไฟล</q-tooltip></q-btn
>
</template>
</q-file>
</div>
</div>
</div>
</q-card>
</div> -->
<!-- แบบตรวจสอบความถกตองครบถวนของขอมลเพอประกอบการคดเลอกบคคล (เอกสารแบบ ) -->
<!-- <div class="col-6" v-if="store.currentStep === 2">
<q-card bordered class="cardSp1">
<div
class="col-12 row text-weight-medium bg-grey-1 q-py-sm q-pl-md q-pr-sm no-wrap"
>
<div>
แบบตรวจสอบความถกตองครบถวนของขอมลเพอประกอบการคดเลอกบคคล
(เอกสารแบบ .)
</div>
<q-space />
<div>
<q-btn
flat
dense
icon="download"
color="indigo"
@click="
onClickDowloadFile(
'EV1_007',
'template-3',
'แบบตรวจสอบความถูกต้องครบถ้วนของข้อมูลเพื่อประกอบการคัดเลือกบุคคล (เอกสารแบบ ก)'
)
"
>
<q-tooltip> ดาวนโหลดตนแบบ </q-tooltip></q-btn
>
</div>
<div v-if="downloadFile3 != ''">
<q-btn
:href="downloadFile3"
target="_blank"
flat
dense
icon="visibility"
class="q-ml-sm"
color="blue"
>
<q-tooltip> ไฟลเอกสาร </q-tooltip></q-btn
>
</div>
</div>
<div class="col-12"><q-separator /></div>
<div class="row">
<div class="col-12 q-pa-sm">
<q-file
ref="fileEvaluation3Ref"
v-model="fileEvaluation3"
:disable="!store.statusUpload"
class="col-12"
outlined
dense
lazy-rules
hide-bottom-space
accept=".pdf"
:rules="
downloadFile3 === ''
? [(val:any) => !!val || 'กรุณาเลือกไฟล์']
: []
"
label="อัปโหลดไฟล์"
>
<template v-slot:prepend>
<q-icon name="attach_file" />
</template>
<template v-slot:after>
<q-btn
:disable="!store.statusUpload"
flat
round
dense
color="primary"
icon="mdi-upload"
@click="
fetchPathUpload(
'เล่ม 1',
evaluateId,
'3-แบบตรวจสอบความถูกต้องครบถ้วนของข้อมูลเพื่อประกอบการคัดเลือกบุคคล (เอกสารแบบ ก)',
fileEvaluation3
)
"
><q-tooltip>ปโหลดไฟล</q-tooltip></q-btn
>
</template>
</q-file>
</div>
</div>
</q-card>
</div> -->
<!-- แบบสรปขอมลของผขอรบการคดเลอก (เอกสารหมายเลข 9) -->
<!-- <div class="col-6" v-if="store.currentStep === 2">
<q-card bordered class="cardSp1">
<div
class="col-12 row text-weight-medium bg-grey-1 q-py-sm q-pl-md q-pr-sm no-wrap"
>
<div class="col-7">
แบบสรปขอมลของผขอรบการคดเลอก (เอกสารหมายเลข 9)
</div>
<q-space />
<div>
<q-btn
flat
dense
icon="download"
color="indigo"
@click="
onClickDowloadFile(
'EV1_009',
'template-5',
'แบบสรุปข้อมูลของผู้ขอรับการคัดเลือก (เอกสารหมายเลข 9)'
)
"
><q-tooltip> ดาวนโหลดตนแบบ </q-tooltip></q-btn
>
</div>
<div>
<q-btn
v-if="downloadFile5 != ''"
:href="downloadFile5"
target="_blank"
flat
dense
icon="visibility"
class="q-ml-sm"
color="blue"
>
<q-tooltip> ไฟลเอกสาร </q-tooltip></q-btn
>
</div>
</div>
<div class="col-12"><q-separator /></div>
<div class="row">
<div class="col-12 q-pa-sm">
<q-file
ref="fileEvaluation5Ref"
v-model="fileEvaluation5"
:disable="!store.statusUpload"
class="col-12"
outlined
dense
lazy-rules
accept=".pdf"
hide-bottom-space
label="อัปโหลดไฟล์"
:rules="
downloadFile5 === ''
? [(val:any) => !!val || 'กรุณาเลือกไฟล์']
: []
"
>
<template v-slot:prepend>
<q-icon name="attach_file" />
</template>
<template v-slot:after>
<q-btn
:disable="!store.statusUpload"
flat
round
dense
color="primary"
icon="mdi-upload"
@click="
fetchPathUpload(
'เล่ม 1',
evaluateId,
'5-แบบสรุปข้อมูลของผู้ขอรับการคัดเลือก (เอกสารหมายเลข 9)',
fileEvaluation5
)
"
><q-tooltip>ปโหลดไฟล</q-tooltip></q-btn
>
</template>
</q-file>
</div>
</div>
</q-card>
</div> -->
<!-- แบบประเมนคณลกษณะบคคล -->
<!-- <div class="col-6" v-if="store.currentStep === 2">
<q-card bordered class="cardSp1">
<div
class="col-12 row text-weight-medium bg-grey-1 q-py-sm q-pl-md q-pr-sm items-center"
>
<div>แบบประเมนคณลกษณะบคคล</div>
<q-space />
<div>
<q-btn
flat
dense
icon="download"
color="indigo"
@click="
onClickDowloadFile(
'EV1_008',
'template-4',
'แบบประเมินคุณลักษณะบุคคล'
)
"
>
<q-tooltip> ดาวนโหลดตนแบบ </q-tooltip></q-btn
>
</div>
<div>
<q-btn
v-if="downloadFile4 != ''"
:href="downloadFile4"
target="_blank"
flat
dense
icon="visibility"
class="q-ml-sm"
color="blue"
>
<q-tooltip> ไฟลเอกสาร </q-tooltip></q-btn
>
</div>
</div>
<div class="col-12"><q-separator /></div>
<div class="row">
<div class="col-12 q-pa-sm">
<q-file
ref="fileEvaluation4Ref"
v-model="fileEvaluation4"
:disable="!store.statusUpload"
class="col-12"
outlined
dense
lazy-rules
hide-bottom-space
accept=".pdf"
label="อัปโหลดไฟล์"
:rules="
downloadFile4 === ''
? [(val:any) => !!val || 'กรุณาเลือกไฟล์']
: []
"
>
<template v-slot:prepend>
<q-icon name="attach_file" />
</template>
<template v-slot:after>
<q-btn
flat
round
dense
:disable="!store.statusUpload"
color="primary"
icon="mdi-upload"
@click="
fetchPathUpload(
'เล่ม 1',
evaluateId,
'4-แบบประเมินคุณลักษณะบุคคล',
fileEvaluation4
)
"
><q-tooltip>ปโหลดไฟล</q-tooltip></q-btn
>
</template>
</q-file>
</div>
</div>
</q-card>
</div> -->
<!--ผลงานทจะสงประเม (เอกสารหมายเลข 11) -->
<!-- <div class="col-6" v-if="store.currentStep === 2">
<q-card bordered class="cardSp1">
<div
class="col-12 row text-weight-medium bg-grey-1 q-py-sm q-pl-md q-pr-sm items-center"
>
<div>ผลงานทจะสงประเม (เอกสารหมายเลข 11)</div>
<q-space />
<div>
<q-btn
flat
dense
icon="download"
color="indigo"
@click="
onClickDowloadFile(
'EV1_010',
'template-6',
'ผลงานที่จะส่งประเมิน (เอกสารหมายเลข 11)'
)
"
>
<q-tooltip> ดาวนโหลดตนแบบ </q-tooltip></q-btn
>
</div>
<div>
<q-btn
v-if="downloadFile6 != ''"
:href="downloadFile6"
target="_blank"
flat
dense
icon="visibility"
class="q-ml-sm"
color="blue"
>
<q-tooltip> ไฟลเอกสาร </q-tooltip></q-btn
>
</div>
</div>
<div class="col-12"><q-separator /></div>
<div class="row">
<div class="col-12 q-pa-sm">
<q-file
ref="fileEvaluation6Ref"
v-model="fileEvaluation6"
:disable="!store.statusUpload"
class="col-12"
outlined
hide-bottom-space
dense
lazy-rules
label="อัปโหลดไฟล์"
accept=".pdf"
:rules="
downloadFile6 === ''
? [(val:any) => !!val || 'กรุณาเลือกไฟล์']
: []
"
>
<template v-slot:prepend>
<q-icon name="attach_file" />
</template>
<template v-slot:after>
<q-btn
:disable="!store.statusUpload"
flat
round
dense
color="primary"
icon="mdi-upload"
@click="
fetchPathUpload(
'เล่ม 1',
evaluateId,
'6-ผลงานที่จะส่งประเมิน (เอกสารหมายเลข 11)',
fileEvaluation6
)
"
><q-tooltip>ปโหลดไฟล</q-tooltip></q-btn
>
</template>
</q-file>
</div>
</div>
</q-card>
</div> -->
</div> </div>
</div> </div>

View file

@ -13,7 +13,7 @@ const $q = useQuasar();
const store = useEvaluateStore(); const store = useEvaluateStore();
const mixin = useCounterMixin(); const mixin = useCounterMixin();
const route = useRoute(); const route = useRoute();
const { showLoader, hideLoader, messageError } = mixin; const { messageError } = mixin;
/** id ประเมิน*/ /** id ประเมิน*/
const evaluateId = ref<string>(route.params.id.toString()); const evaluateId = ref<string>(route.params.id.toString());
@ -21,6 +21,7 @@ const evaluateId = ref<string>(route.params.id.toString());
/** emit*/ /** emit*/
const emit = defineEmits(["update:file"]); const emit = defineEmits(["update:file"]);
const isLoading = ref(false);
const selectedItem = ref(1); const selectedItem = ref(1);
const formTemplates = ref([ const formTemplates = ref([
{ {
@ -55,8 +56,10 @@ function handleItemClick(itemNumber: number) {
* function เรกยเอกสาร * function เรกยเอกสาร
* @param fileName อเอกสาร * @param fileName อเอกสาร
*/ */
async function fetchDocument(fileName: string) { async function fetchDocument(fileName: string, forceDownload = false) {
showLoader(); if (forceDownload) {
isLoading.value = true;
}
evaluateId.value && evaluateId.value &&
(await http (await http
.get(config.API.loadFileDocument("เล่ม 1", evaluateId.value, fileName)) .get(config.API.loadFileDocument("เล่ม 1", evaluateId.value, fileName))
@ -67,7 +70,7 @@ async function fetchDocument(fileName: string) {
messageError($q, err); messageError($q, err);
}) })
.finally(() => { .finally(() => {
hideLoader(); isLoading.value = false;
})); }));
} }
@ -95,7 +98,10 @@ async function downloadFile(url: string) {
/** HooK lifecycle*/ /** HooK lifecycle*/
onMounted(async () => { onMounted(async () => {
await fetchDocument(formTemplates.value[selectedItem.value - 1].fileName); await fetchDocument(
formTemplates.value[selectedItem.value - 1].fileName,
true
);
}); });
</script> </script>
@ -111,7 +117,8 @@ onMounted(async () => {
@click="handleItemClick(index + 1)" @click="handleItemClick(index + 1)"
class="cursor-pointer" class="cursor-pointer"
> >
<q-item-section>{{ item.title }}</q-item-section> <q-skeleton v-if="isLoading" type="text" width="100%" />
<q-item-section v-else>{{ item.title }}</q-item-section>
</q-item> </q-item>
</q-list> </q-list>
</template> </template>

View file

@ -1,6 +1,6 @@
<script setup lang="ts"> <script setup lang="ts">
import { ref, onMounted } from "vue"; import { ref, onMounted } from "vue";
import { useQuasar } from "quasar"; import { is, useQuasar } from "quasar";
import axios from "axios"; import axios from "axios";
import http from "@/plugins/http"; import http from "@/plugins/http";
@ -23,6 +23,7 @@ const formTemplates = ref<any[]>([
fileName: "1-แบบพิจารณาคุณสมบัติบุคคล (ฉบับแก้ไข)", fileName: "1-แบบพิจารณาคุณสมบัติบุคคล (ฉบับแก้ไข)",
downloadFile: "", downloadFile: "",
file: null, file: null,
isLoading: false,
}, },
{ {
code: "EV1_006", code: "EV1_006",
@ -31,6 +32,7 @@ const formTemplates = ref<any[]>([
fileName: "2-แบบแสดงรายละเอียดการเสนอผลงาน (ฉบับแก้ไข)", fileName: "2-แบบแสดงรายละเอียดการเสนอผลงาน (ฉบับแก้ไข)",
downloadFile: "", downloadFile: "",
file: null, file: null,
isLoading: false,
}, },
{ {
code: "EV1_008", code: "EV1_008",
@ -39,6 +41,7 @@ const formTemplates = ref<any[]>([
fileName: "4-แบบประเมินคุณลักษณะบุคคล (ฉบับแก้ไข)", fileName: "4-แบบประเมินคุณลักษณะบุคคล (ฉบับแก้ไข)",
downloadFile: "", downloadFile: "",
file: null, file: null,
isLoading: false,
}, },
{ {
code: "EV1_010", code: "EV1_010",
@ -47,6 +50,7 @@ const formTemplates = ref<any[]>([
fileName: "6-ผลงานที่จะส่งประเมิน (เอกสารหมายเลข 11) (ฉบับแก้ไข)", fileName: "6-ผลงานที่จะส่งประเมิน (เอกสารหมายเลข 11) (ฉบับแก้ไข)",
downloadFile: "", downloadFile: "",
file: null, file: null,
isLoading: false,
}, },
]); ]);
@ -181,6 +185,10 @@ async function uploadfile(uploadUrl: string, file: any) {
* @param fileName อไฟล * @param fileName อไฟล
*/ */
async function downloadFile(fileName: string) { async function downloadFile(fileName: string) {
const loadingKey = formTemplates.value.findIndex(
(item) => item.fileName === fileName
);
formTemplates.value[loadingKey].isLoading = true;
await http await http
.get(config.API.loadFileDocument("เล่ม 1", evaluateId.value, fileName)) .get(config.API.loadFileDocument("เล่ม 1", evaluateId.value, fileName))
.then((res) => { .then((res) => {
@ -190,13 +198,15 @@ async function downloadFile(fileName: string) {
if (index !== -1) { if (index !== -1) {
formTemplates.value[index].downloadFile = res.data.downloadUrl; formTemplates.value[index].downloadFile = res.data.downloadUrl;
} }
})
.finally(() => {
formTemplates.value[loadingKey].isLoading = false;
}); });
} }
/**lifecycle Hooks*/ /**lifecycle Hooks*/
onMounted(async () => { onMounted(async () => {
try { try {
showLoader();
await Promise.all([ await Promise.all([
fetcheSigner(evaluateId.value), fetcheSigner(evaluateId.value),
fetchCheckSpec(evaluateId.value), fetchCheckSpec(evaluateId.value),
@ -206,8 +216,6 @@ onMounted(async () => {
]); ]);
} catch (error) { } catch (error) {
console.log(error); console.log(error);
} finally {
hideLoader();
} }
}); });
</script> </script>
@ -226,7 +234,13 @@ onMounted(async () => {
<div class="row q-col-gutter-sm q-pa-sm"> <div class="row q-col-gutter-sm q-pa-sm">
<div class="col-6" v-for="(item, index) in formTemplates" :key="index"> <div class="col-6" v-for="(item, index) in formTemplates" :key="index">
<q-skeleton
type="Qcard"
:height="store.currentStep !== 4 ? '50px' : '100px'"
v-if="item.isLoading"
/>
<q-card <q-card
v-else
bordered bordered
class="cardSp1" class="cardSp1"
v-if=" v-if="

View file

@ -12,7 +12,7 @@ import type { FileObject } from "@/modules/06_evaluate/interface/main";
const $q = useQuasar(); const $q = useQuasar();
const mixins = useCounterMixin(); const mixins = useCounterMixin();
const route = useRoute(); const route = useRoute();
const { date2Thai, success, showLoader, hideLoader } = mixins; const { date2Thai, success, showLoader, hideLoader, messageError } = mixins;
/** id ประเมิน*/ /** id ประเมิน*/
const evaluateId = ref<string>(route.params.id.toString()); const evaluateId = ref<string>(route.params.id.toString());
@ -20,6 +20,7 @@ const evaluateId = ref<string>(route.params.id.toString());
const dateStartAnnounce = ref<string | null>(date2Thai(new Date())); const dateStartAnnounce = ref<string | null>(date2Thai(new Date()));
const dateEndAnnounce = ref<string | null>(date2Thai(new Date())); const dateEndAnnounce = ref<string | null>(date2Thai(new Date()));
const statusFile = ref<boolean>(false); const statusFile = ref<boolean>(false);
const isLoading = ref<boolean>(false);
/** เอกสารประกาศผลการคัดเลือกบุคคล*/ /** เอกสารประกาศผลการคัดเลือกบุคคล*/
const items = ref<FileObject[]>([ const items = ref<FileObject[]>([
@ -44,22 +45,16 @@ const items = ref<FileObject[]>([
]); ]);
/** fuinction เรียกข้อมูลลิงก์ดาวนฺโหลด*/ /** fuinction เรียกข้อมูลลิงก์ดาวนฺโหลด*/
function onClickfetchDocument(fileName: string, type: string) { async function onClickfetchDocument(fileName: string, type: string) {
if (evaluateId.value) { if (evaluateId.value) {
showLoader(); await http
http
.get(config.API.loadFileDocument("เล่ม 1", evaluateId.value, fileName)) .get(config.API.loadFileDocument("เล่ม 1", evaluateId.value, fileName))
.then((res) => { .then((res) => {
const downloadUrl = res.data.downloadUrl; const downloadUrl = res.data.downloadUrl;
type === "COPPY" && coppyLink(downloadUrl); type === "COPPY" && coppyLink(downloadUrl);
type === "CHECK" && (statusFile.value = true); type === "CHECK" && (statusFile.value = true);
}) })
.catch(() => {}) .catch(() => {});
.finally(() => {
setTimeout(() => {
hideLoader();
}, 1500);
});
} }
} }
@ -71,9 +66,10 @@ async function coppyLink(link: string) {
} }
/** function เรียกข้อมูลวันที่ประกาศ*/ /** function เรียกข้อมูลวันที่ประกาศ*/
function fetchCheckDate() { async function fetchCheckDate() {
isLoading.value = true;
evaluateId.value && evaluateId.value &&
http (await http
.get(config.API.evaluationCheckDate(evaluateId.value)) .get(config.API.evaluationCheckDate(evaluateId.value))
.then((res) => { .then((res) => {
const data = res.data.result; const data = res.data.result;
@ -82,7 +78,12 @@ function fetchCheckDate() {
endDate.setDate(endDate.getDate() + 30); endDate.setDate(endDate.getDate() + 30);
dateEndAnnounce.value = date2Thai(endDate); dateEndAnnounce.value = date2Thai(endDate);
}) })
.catch(() => {}); .catch((err) => {
messageError($q, err);
})
.finally(() => {
isLoading.value = false;
}));
} }
/** Hook lifecycle*/ /** Hook lifecycle*/
@ -91,10 +92,16 @@ onMounted(async () => {
await onClickfetchDocument("บันทึกแจ้งผลการประกาศคัดเลือก", "CHECK"); await onClickfetchDocument("บันทึกแจ้งผลการประกาศคัดเลือก", "CHECK");
}); });
</script> </script>
`
<template> <template>
<div class="row col-12 q-pa-sm"> <div class="row col-12 q-pa-sm">
<div class="row col-12 q-col-gutter-sm"> <q-skeleton
v-if="isLoading"
type="Qcard"
style="width: 100%; height: 300px"
/>
<div v-else class="row col-12 q-col-gutter-sm">
<div class="col-12 text-center"> <div class="col-12 text-center">
<q-banner rounded class="text-weight-bold text-red-14 bg-red-1"> <q-banner rounded class="text-weight-bold text-red-14 bg-red-1">
<div class="text-weight-bold"> <div class="text-weight-bold">

View file

@ -50,6 +50,10 @@ const formCommand = reactive<FormCommand>({
const modalView = ref<boolean>(false); const modalView = ref<boolean>(false);
const isLoading = ref<boolean>(false); //
const isLoadingFile = ref<boolean>(false);
const isLoadingDate = ref<boolean>(false);
/** function อัปเดท ผลงาน,ผู้เซ็นเอกสาร*/ /** function อัปเดท ผลงาน,ผู้เซ็นเอกสาร*/
function updateInput(value: any) { function updateInput(value: any) {
const ref = { const ref = {
@ -85,16 +89,18 @@ async function fetchPathUpload(
showLoader(); showLoader();
await http await http
.post(config.API.loadPathDocument(volume, id), body) .post(config.API.loadPathDocument(volume, id), body)
.then((res) => { .then(async (res) => {
const foundKey: string | undefined = Object.keys(res.data).find( const foundKey: string | undefined = Object.keys(res.data).find(
(key) => (key) =>
res.data[key]?.fileName !== undefined && res.data[key]?.fileName !== undefined &&
res.data[key]?.fileName !== "" res.data[key]?.fileName !== ""
); );
foundKey && uploadfile(res.data[foundKey]?.uploadUrl, file); foundKey && (await uploadfile(res.data[foundKey]?.uploadUrl, file));
}) })
.catch((err) => { .catch((err) => {
messageError($q, err); messageError($q, err);
})
.finally(() => {
hideLoader(); hideLoader();
}); });
} }
@ -129,7 +135,7 @@ async function uploadfile(uploadUrl: string, file: any) {
* @param id ประเม * @param id ประเม
*/ */
async function fetcheSigner(id: string) { async function fetcheSigner(id: string) {
showLoader(); isLoading.value = true;
await http await http
.get(config.API.evaluationSignerDoc2(id)) .get(config.API.evaluationSignerDoc2(id))
.then((res) => { .then((res) => {
@ -148,40 +154,43 @@ async function fetcheSigner(id: string) {
formCommand.author = data.authorDoc2; formCommand.author = data.authorDoc2;
formCommand.subject = data.subjectDoc2; formCommand.subject = data.subjectDoc2;
formCommand.assignedPosition = data.assignedPosition; formCommand.assignedPosition = data.assignedPosition;
assignedPosLevel.value = data.assignedPosLevel; assignedPosLevel.value = data.assignedPosLevel;
store.statusUpload6 = data.isUpdated; store.statusUpload6 = data.isUpdated;
}) })
.catch((err) => { .catch((err) => {
messageError($q, err); messageError($q, err);
// store.statusUpload6 = false;
// getCommander();
}) })
.finally(() => { .finally(() => {
hideLoader(); isLoading.value = false;
}); });
} }
const dateEndPrepareDoc2 = ref<string | null>(date2Thai(new Date())); const dateEndPrepareDoc2 = ref<string | null>(date2Thai(new Date()));
/** functoin เรียกข้อมูลวันสุดท้ายของการส่งผลงาน*/ /** functoin เรียกข้อมูลวันสุดท้ายของการส่งผลงาน*/
async function fetchCheckDate() { async function fetchCheckDate() {
evaluateId.value && if (!evaluateId.value) return;
(await http isLoadingDate.value = true;
.get(config.API.evaluationCheckDate(evaluateId.value)) await http
.then((res) => { .get(config.API.evaluationCheckDate(evaluateId.value))
const data = res.data.result; .then((res) => {
const data = res.data.result;
const endDate = new Date(data.dateEndAnnounce); const endDate = new Date(data.dateEndAnnounce);
endDate.setDate(endDate.getDate() + 180); endDate.setDate(endDate.getDate() + 180);
dateEndPrepareDoc2.value = date2Thai(endDate); dateEndPrepareDoc2.value = date2Thai(endDate);
}) })
.catch((err) => {})); .catch((err) => {
messageError($q, err);
})
.finally(() => {
isLoadingDate.value = false;
});
} }
const downloadUrl = ref<string>(""); const downloadUrl = ref<string>("");
/** function เช็คไฟล์อัปโหลด*/ /** function เช็คไฟล์อัปโหลด*/
async function checkDoc() { async function checkDoc() {
isLoadingFile.value = true;
await http await http
.get( .get(
config.API.loadFileDocument("เล่ม 2", evaluateId.value, "1-เอกสารเล่ม 2") config.API.loadFileDocument("เล่ม 2", evaluateId.value, "1-เอกสารเล่ม 2")
@ -195,26 +204,10 @@ async function checkDoc() {
}; };
emit("update:form", formCommand, ref); emit("update:form", formCommand, ref);
isLoadingFile.value = false;
}); });
} }
// function getCommander() {
// http
// .get(config.API.searchCommander)
// .then((res) => {
// const data = res.data.result;
// formCommand.commanderFullname = data.commanderFullname;
// formCommand.commanderPosition = data.commanderPosition;
// formCommand.commanderAboveFullname = data.commanderAboveFullname;
// formCommand.commanderAbovePosition = data.commanderAbovePosition;
// formCommand.commanderOrg = data.commanderOrg;
// formCommand.commanderAboveOrg = data.commanderAboveOrg;
// })
// .catch((e) => {
// messageError($q, e);
// });
// }
function onAddSubject() { function onAddSubject() {
formCommand.subject.push(""); formCommand.subject.push("");
} }
@ -256,9 +249,10 @@ onMounted(async () => {
<template> <template>
<div class="row col-12 q-pa-sm"> <div class="row col-12 q-pa-sm">
<div class="row q-col-gutter-sm"> <div class="row col-12 q-col-gutter-sm">
<div class="col-12 text-center"> <div class="col-12 text-center">
<q-banner rounded class="text-weight-bold text-red-14 bg-red-1"> <q-skeleton v-if="isLoadingDate" type="Qcard" height="50px" />
<q-banner v-else rounded class="text-weight-bold text-red-14 bg-red-1">
<div class="text-weight-bold"> <div class="text-weight-bold">
<q-icon name="info_outline" color="red-14" size="24px" /> <q-icon name="info_outline" color="red-14" size="24px" />
นสดทายของการสงผลงานคอวนท {{ dateEndPrepareDoc2 }} นสดทายของการสงผลงานคอวนท {{ dateEndPrepareDoc2 }}
@ -268,7 +262,14 @@ onMounted(async () => {
<!-- ผลงาน --> <!-- ผลงาน -->
<div class="col-12"> <div class="col-12">
<q-card bordered class="shadow-0" style="border: 1px solid #d6dee1"> <q-skeleton v-if="isLoading" type="Qcard" height="200px" width="100%" />
<q-card
v-else
bordered
class="shadow-0"
style="border: 1px solid #d6dee1"
>
<div class="text-weight-medium bg-grey-1 q-py-sm q-px-md">ผลงาน</div> <div class="text-weight-medium bg-grey-1 q-py-sm q-px-md">ผลงาน</div>
<div class="col-12"><q-separator /></div> <div class="col-12"><q-separator /></div>
<div class="col-12 q-pa-sm"> <div class="col-12 q-pa-sm">
@ -372,7 +373,13 @@ onMounted(async () => {
<!-- เลอกผเซนเอกสาร --> <!-- เลอกผเซนเอกสาร -->
<div class="col-12"> <div class="col-12">
<q-card bordered class="shadow-0" style="border: 1px solid #d6dee1"> <q-skeleton v-if="isLoading" type="Qcard" height="200px" width="100%" />
<q-card
v-else
bordered
class="shadow-0"
style="border: 1px solid #d6dee1"
>
<div class="text-weight-medium bg-grey-1 q-py-sm q-px-md"> <div class="text-weight-medium bg-grey-1 q-py-sm q-px-md">
เลอกผเซนเอกสาร เลอกผเซนเอกสาร
</div> </div>
@ -541,7 +548,13 @@ onMounted(async () => {
<!-- ปไฟล --> <!-- ปไฟล -->
<div class="col-12" v-if="store.currentStep === 6"> <div class="col-12" v-if="store.currentStep === 6">
<q-card bordered class="shadow-0" style="border: 1px solid #d6dee1"> <q-skeleton type="Qcard" height="100px" v-if="isLoadingFile" />
<q-card
v-else
bordered
class="shadow-0"
style="border: 1px solid #d6dee1"
>
<div class="col-12 row bg-grey-1"> <div class="col-12 row bg-grey-1">
<div class="text-weight-medium q-py-sm q-px-md">เอกสารเล 2</div> <div class="text-weight-medium q-py-sm q-px-md">เอกสารเล 2</div>
<q-space /> <q-space />

View file

@ -13,7 +13,7 @@ import { useCounterMixin } from "@/stores/mixin";
const $q = useQuasar(); const $q = useQuasar();
const mixin = useCounterMixin(); const mixin = useCounterMixin();
const route = useRoute(); const route = useRoute();
const { showLoader, hideLoader, messageError } = mixin; const { messageError } = mixin;
/** emit*/ /** emit*/
const emit = defineEmits(["update:file"]); const emit = defineEmits(["update:file"]);
@ -22,28 +22,25 @@ const emit = defineEmits(["update:file"]);
const evaluateId = ref<string>(route.params.id.toString()); const evaluateId = ref<string>(route.params.id.toString());
const selectedItem = ref(1); const selectedItem = ref(1);
const isLoading = ref(false);
/** function เรีกยเอกสาร*/ /** function เรีกยเอกสาร*/
async function fetchDocument() { async function fetchDocument() {
showLoader(); if (!evaluateId.value) return;
evaluateId.value && isLoading.value = true;
(await http await http
.get( .get(
config.API.loadFileDocument( config.API.loadFileDocument("เล่ม 2", evaluateId.value, "1-เอกสารเล่ม 2")
"เล่ม 2", )
evaluateId.value, .then(async (res) => {
"1-เอกสารเล่ม 2" await downloadFile(res.data.downloadUrl);
) })
) .catch((err) => {
.then(async (res) => { messageError($q, err);
await downloadFile(res.data.downloadUrl); })
}) .finally(() => {
.catch((err) => { isLoading.value = false;
messageError($q, err); });
})
.finally(() => {
hideLoader();
}));
} }
/** /**
@ -84,7 +81,9 @@ onMounted(async () => {
active-class="text-primary" active-class="text-primary"
class="cursor-pointer" class="cursor-pointer"
> >
<q-item-section>เอกสารเล 2</q-item-section> <q-skeleton v-if="isLoading" type="text" width="100%" />
<q-item-section v-else>เอกสารเล่ม 2</q-item-section>
</q-item> </q-item>
</q-list> </q-list>
</template> </template>

View file

@ -107,9 +107,11 @@ async function uploadfile(uploadUrl: string, file: any) {
} }
const downloadUrl = ref<string>(""); const downloadUrl = ref<string>("");
const isLoadingFile = ref<boolean>(false);
/** function เช็คไฟล์อัปโหลด*/ /** function เช็คไฟล์อัปโหลด*/
function checkDoc() { async function checkDoc() {
http isLoadingFile.value = true;
await http
.get( .get(
config.API.loadFileDocument( config.API.loadFileDocument(
"เล่ม 2", "เล่ม 2",
@ -119,6 +121,9 @@ function checkDoc() {
) )
.then((res: any) => { .then((res: any) => {
downloadUrl.value = res.data.downloadUrl; downloadUrl.value = res.data.downloadUrl;
})
.finally(() => {
isLoadingFile.value = false;
}); });
} }
@ -148,12 +153,9 @@ async function fetcheSigner(id: string) {
/** lifecycleHook*/ /** lifecycleHook*/
onMounted(async () => { onMounted(async () => {
try { try {
showLoader();
await Promise.all([checkDoc(), fetcheSigner(evaluateId.value)]); await Promise.all([checkDoc(), fetcheSigner(evaluateId.value)]);
} catch (error) { } catch (error) {
console.log(error); console.log(error);
} finally {
hideLoader();
} }
}); });
</script> </script>
@ -178,7 +180,12 @@ onMounted(async () => {
(store.currentStep !== 8 && downloadUrl) || store.currentStep == 8 (store.currentStep !== 8 && downloadUrl) || store.currentStep == 8
" "
> >
<q-card class="shadow-0" bordered> <q-skeleton
type="Qcard"
:height="store.currentStep !== 8 ? '50px' : '100px'"
v-if="isLoadingFile"
/>
<q-card v-else class="shadow-0" bordered>
<div class="row col-12 bg-grey-1 q-px-sm q-py-xs items-center"> <div class="row col-12 bg-grey-1 q-px-sm q-py-xs items-center">
<div class="text-weight-medium">เอกสารเล 2 (ฉบบแกไข)</div> <div class="text-weight-medium">เอกสารเล 2 (ฉบบแกไข)</div>
<q-space /> <q-space />

View file

@ -9,12 +9,15 @@ import config from "@/app.config";
import { useCounterMixin } from "@/stores/mixin"; import { useCounterMixin } from "@/stores/mixin";
import HeaderDialog from "@/components/DialogHeader.vue"; import HeaderDialog from "@/components/DialogHeader.vue";
import SkeletonTable from "@/components/SkeletonTable.vue";
const $q = useQuasar(); const $q = useQuasar();
const route = useRoute(); const route = useRoute();
const mixins = useCounterMixin(); const mixins = useCounterMixin();
const { showLoader, hideLoader, date2Thai, messageError } = mixins; const { showLoader, hideLoader, date2Thai, messageError } = mixins;
const isLoading = ref<boolean>(false);
const evaluateId = computed(() => { const evaluateId = computed(() => {
const id = route.params.id ? route.params.id.toString() : ""; const id = route.params.id ? route.params.id.toString() : "";
return id; return id;
@ -85,7 +88,7 @@ async function fetchListHistory(id: string) {
minute: "2-digit", minute: "2-digit",
second: "2-digit", second: "2-digit",
}; };
showLoader(); isLoading.value = true;
await http await http
.get(config.API.evaluationHistory(id)) .get(config.API.evaluationHistory(id))
.then((res) => { .then((res) => {
@ -104,7 +107,7 @@ async function fetchListHistory(id: string) {
messageError($q, err); messageError($q, err);
}) })
.finally(() => { .finally(() => {
hideLoader(); isLoading.value = false;
}); });
} }
@ -124,7 +127,9 @@ watch(
<q-card-section> <q-card-section>
<div class="col-xs-12 col-sm-12 col-md-12 row q-col-gutter-md"> <div class="col-xs-12 col-sm-12 col-md-12 row q-col-gutter-md">
<div class="col-12"> <div class="col-12">
<q-table <SkeletonTable v-if="isLoading" :columns="columns" />
<d-table
v-else
ref="table" ref="table"
flat flat
bordered bordered
@ -161,7 +166,7 @@ watch(
</q-td> </q-td>
</q-tr> </q-tr>
</template> </template>
</q-table> </d-table>
</div> </div>
</div> </div>
</q-card-section> </q-card-section>
@ -169,31 +174,4 @@ watch(
</q-dialog> </q-dialog>
</template> </template>
<style lang="scss" scoped> <style lang="scss" scoped></style>
.custom-header-table {
height: auto;
.q-table tr:nth-child(odd) td {
background: white;
}
.q-table tr:nth-child(even) td {
background: #f8f8f8;
}
.q-table thead tr {
background: #ecebeb;
}
.q-table thead tr th {
position: sticky;
z-index: 1;
}
/* this will be the loading indicator */
.q-table thead tr:last-child th {
/* height of all previous header rows */
top: 48px;
}
.q-table thead tr:first-child th {
top: 0;
}
}
</style>

View file

@ -1,4 +1,6 @@
<script setup lang="ts"> <script setup lang="ts">
import SkeletonTable from "@/components/SkeletonTable.vue";
const props = defineProps({ const props = defineProps({
columns: { columns: {
type: Array as () => any[], type: Array as () => any[],
@ -8,12 +10,18 @@ const props = defineProps({
type: Array as () => any[], type: Array as () => any[],
require: true, require: true,
}, },
isLoading: {
type: Boolean,
default: false,
},
}); });
</script> </script>
<template> <template>
<div class="q-pa-sm row col-12"> <div class="q-pa-sm row col-12">
<SkeletonTable class="col-12" v-if="isLoading" :columns="props.columns" />
<d-table <d-table
v-else
ref="table" ref="table"
flat flat
bordered bordered

View file

@ -2,7 +2,7 @@ div
<script setup lang="ts"> <script setup lang="ts">
import { reactive, onMounted, ref } from "vue"; import { reactive, onMounted, ref } from "vue";
import { useRoute } from "vue-router"; import { useRoute } from "vue-router";
import { useQuasar } from "quasar"; import { is, useQuasar } from "quasar";
import http from "@/plugins/http"; import http from "@/plugins/http";
import config from "@/app.config"; import config from "@/app.config";
@ -21,6 +21,7 @@ import type {
/** importComponents*/ /** importComponents*/
import TableData from "@/modules/06_evaluate/components/viewstep/tableStep1.vue"; import TableData from "@/modules/06_evaluate/components/viewstep/tableStep1.vue";
import HeaderDialog from "@/components/DialogHeader.vue"; import HeaderDialog from "@/components/DialogHeader.vue";
import SkeletonTable from "@/components/SkeletonTable.vue";
/** use*/ /** use*/
const mixin = useCounterMixin(); const mixin = useCounterMixin();
@ -29,8 +30,7 @@ const storeEva = useEvaluateStore();
const storeData = useDataStore(); const storeData = useDataStore();
const $q = useQuasar(); const $q = useQuasar();
const route = useRoute(); const route = useRoute();
const { showLoader, hideLoader, messageError, date2Thai, findOrgNameHtml } = const { messageError, date2Thai, findOrgNameHtml } = mixin;
mixin;
const { const {
columnsCertificates, columnsCertificates,
columnSalaries, columnSalaries,
@ -76,8 +76,19 @@ const formDetail = reactive<any>({
honor: [], honor: [],
}); });
const isLoading = reactive({
loadDetail: false,
loadEducation: false,
loadCertificate: false,
loadSalary: false,
loadTraining: false,
loadAssessment: false,
loadExperience: false,
});
/** function เรียกข้อมูลตรวจสอบคุณสมบัติ*/ /** function เรียกข้อมูลตรวจสอบคุณสมบัติ*/
async function fetchDetail() { async function fetchDetail() {
isLoading.loadDetail = true;
try { try {
if (!storeData.dataprofilePosition) { if (!storeData.dataprofilePosition) {
const res = await http.get(config.API.profilePosition()); const res = await http.get(config.API.profilePosition());
@ -87,6 +98,8 @@ async function fetchDetail() {
} }
} catch (error) { } catch (error) {
messageError($q, error); messageError($q, error);
} finally {
isLoading.loadDetail = false;
} }
} }
@ -109,58 +122,113 @@ async function updateFormDetail(data: DataProfile) {
formDetail.posExecutive = data.posExecutiveName; formDetail.posExecutive = data.posExecutiveName;
formDetail.positionArea = data.positionArea; formDetail.positionArea = data.positionArea;
await fetchDataAllDetail(); await fetchDataAllDetail();
emit("update:formDeital", formDetail); emit("update:formDeital", formDetail);
} }
async function fetchDataAllDetail() { async function fetchDataAllDetail() {
// //
http.get(config.API.dataUserEducations).then((res) => { isLoading.loadEducation = true;
formDetail.educations = res.data.result; http
}); .get(config.API.dataUserEducations)
.then((res) => {
formDetail.educations = res.data.result;
})
.catch((e) => {
messageError($q, e);
})
.then(() => {
isLoading.loadEducation = false;
});
// //
http.get(config.API.dataUserCertificate("certificate")).then((res) => { isLoading.loadCertificate = true;
formDetail.certificates = res.data.result.map((e: CertificatesForm) => ({ http
certificateNo: e.certificateNo, .get(config.API.dataUserCertificate("certificate"))
certificateType: e.certificateType, .then((res) => {
expireDate: e.expireDate, formDetail.certificates = res.data.result.map((e: CertificatesForm) => ({
issueDate: e.issueDate, certificateNo: e.certificateNo,
issuer: e.issuer, certificateType: e.certificateType,
})); expireDate: e.expireDate,
}); issueDate: e.issueDate,
issuer: e.issuer,
}));
})
.catch((e) => {
messageError($q, e);
})
.finally(() => {
isLoading.loadCertificate = false;
});
// //
http.get(config.API.dataUserSalaryPosition).then((res) => { isLoading.loadSalary = true;
formDetail.salaries = res.data.result; http
}); .get(config.API.dataUserSalaryPosition)
.then((res) => {
formDetail.salaries = res.data.result;
})
.catch((e) => {
messageError($q, e);
})
.finally(() => {
isLoading.loadSalary = false;
});
// //
http.get(config.API.dataUserCertificate("training")).then((res) => { isLoading.loadTraining = true;
formDetail.trainings = res.data.result.map((e: any) => ({ http
dateOrder: e.dateOrder, .get(config.API.dataUserCertificate("training"))
department: e.department, .then((res) => {
duration: e.duration, formDetail.trainings = res.data.result.map((e: any) => ({
endDate: e.endDate, dateOrder: e.dateOrder,
name: e.name, department: e.department,
numberOrder: e.numberOrder, duration: e.duration,
place: e.place, endDate: e.endDate,
startDate: e.startDate, name: e.name,
topic: e.topic, numberOrder: e.numberOrder,
yearly: e.yearly, place: e.place,
})); startDate: e.startDate,
}); topic: e.topic,
yearly: e.yearly,
}));
})
.catch((e) => {
messageError($q, e);
})
.finally(() => {
isLoading.loadTraining = false;
});
http.get(config.API.dataUserPerformance).then((res) => { //
formDetail.assessments = res.data.result.map((e: any) => ({ isLoading.loadExperience = true;
...e, http
isAdd: false, .get(config.API.dataUserPerformance)
})); .then((res) => {
}); formDetail.assessments = res.data.result.map((e: any) => ({
...e,
isAdd: false,
}));
})
.catch((e) => {
messageError($q, e);
})
.finally(() => {
isLoading.loadExperience = false;
});
http.get(config.API.dataUserPortfolio).then((res) => { //
formDetail.experience = res.data.result; isLoading.loadExperience = true;
}); http
.get(config.API.dataUserPortfolio)
.then((res) => {
formDetail.experience = res.data.result;
})
.catch((e) => {
messageError($q, e);
})
.finally(() => {
isLoading.loadExperience = false;
});
} }
/** /**
@ -168,40 +236,52 @@ async function fetchDataAllDetail() {
* @param id ประเม * @param id ประเม
*/ */
async function fetchCheckSpec(data: any) { async function fetchCheckSpec(data: any) {
formDetail.userId = data.id; isLoading.loadEducation = true;
formDetail.citizenId = data.citizenId; isLoading.loadCertificate = true;
formDetail.prefix = data.prefix; isLoading.loadSalary = true;
formDetail.fullName = data.fullName; isLoading.loadTraining = true;
formDetail.position = data.position; isLoading.loadExperience = true;
formDetail.oc = data.oc; try {
formDetail.salary = data.salary ? formattedNumber(data.salary) : ""; formDetail.userId = data.id;
formDetail.positionLevel = data.positionLevel; formDetail.citizenId = data.citizenId;
formDetail.posNo = data.posNo; formDetail.prefix = data.prefix;
formDetail.birthDate = data.birthDate; formDetail.fullName = data.fullName;
formDetail.educations = data.educations; formDetail.position = data.position;
formDetail.oc = data.oc;
formDetail.certificates = data.certificates.map((e: CertificatesForm) => ({ formDetail.salary = data.salary ? formattedNumber(data.salary) : "";
certificateNo: e.certificateNo, formDetail.positionLevel = data.positionLevel;
certificateType: e.certificateType, formDetail.posNo = data.posNo;
expireDate: date2Thai(e.expireDate), formDetail.birthDate = data.birthDate;
issueDate: date2Thai(e.issueDate), formDetail.educations = data.educations;
issuer: e.issuer, formDetail.certificates = data.certificates.map((e: CertificatesForm) => ({
})); certificateNo: e.certificateNo,
formDetail.salaries = data.salaries; certificateType: e.certificateType,
formDetail.trainings = data.trainings.map((e: any) => ({ expireDate: date2Thai(e.expireDate),
dateOrder: date2Thai(e.dateOrder), issueDate: date2Thai(e.issueDate),
department: e.department, issuer: e.issuer,
duration: e.duration, }));
endDate: date2Thai(e.endDate), formDetail.salaries = data.salaries;
name: e.name, formDetail.trainings = data.trainings.map((e: any) => ({
numberOrder: e.numberOrder, dateOrder: date2Thai(e.dateOrder),
place: e.place, department: e.department,
startDate: date2Thai(e.startDate), duration: e.duration,
topic: e.topic, endDate: date2Thai(e.endDate),
yearly: e.yearly, name: e.name,
})); numberOrder: e.numberOrder,
formDetail.assessments = data.performances; place: e.place,
formDetail.experience = data.portfolios; startDate: date2Thai(e.startDate),
topic: e.topic,
yearly: e.yearly,
}));
formDetail.assessments = data.performances;
formDetail.experience = data.portfolios;
} finally {
isLoading.loadEducation = false;
isLoading.loadCertificate = false;
isLoading.loadSalary = false;
isLoading.loadTraining = false;
isLoading.loadExperience = false;
}
} }
/** /**
@ -218,6 +298,7 @@ function formattedNumber(x: number) {
/** get data */ /** get data */
function getData() { function getData() {
isLoading.loadDetail = true;
http http
.get(config.API.dataUserGovernment) .get(config.API.dataUserGovernment)
.then(async (res) => { .then(async (res) => {
@ -229,6 +310,9 @@ function getData() {
}) })
.catch((e) => { .catch((e) => {
messageError($q, e); messageError($q, e);
})
.finally(() => {
isLoading.loadDetail = false;
}); });
} }
@ -298,7 +382,6 @@ function onDeletePerformance(index: number) {
onMounted(async () => { onMounted(async () => {
try { try {
showLoader();
const promises = []; const promises = [];
if (route.name === "evaluate-add") { if (route.name === "evaluate-add") {
@ -315,7 +398,6 @@ onMounted(async () => {
} catch (error) { } catch (error) {
console.log(error); console.log(error);
} finally { } finally {
hideLoader();
} }
}); });
</script> </script>
@ -327,7 +409,10 @@ onMounted(async () => {
:style="$q.screen.lt.sm ? '' : 'height: 60vh; overflow: scroll;'" :style="$q.screen.lt.sm ? '' : 'height: 60vh; overflow: scroll;'"
> >
<div class="row col-12"> <div class="row col-12">
<q-card class="col-12 cardSp1" bordered> <div class="col-12" v-if="isLoading.loadDetail">
<q-skeleton type="Qcard" height="200px" class="q-mb-md" />
</div>
<q-card v-else class="col-12 cardSp1" bordered>
<div class="text-weight-bold row items-center bg-grey-2 col-12"> <div class="text-weight-bold row items-center bg-grey-2 col-12">
<span class="q-ml-lg q-my-sm">อมลสวนต</span> <span class="q-ml-lg q-my-sm">อมลสวนต</span>
</div> </div>
@ -430,7 +515,10 @@ onMounted(async () => {
</div> </div>
</q-card> </q-card>
<q-card class="col-12 cardSp1" bordered> <div class="col-12" v-if="isLoading.loadEducation">
<q-skeleton type="Qcard" height="200px" class="q-mb-md" />
</div>
<q-card v-else class="col-12 cardSp1" bordered>
<div class="text-weight-bold row items-center bg-grey-2 col-12"> <div class="text-weight-bold row items-center bg-grey-2 col-12">
<span class="q-ml-lg q-my-sm">ประวการศกษา </span> <span class="q-ml-lg q-my-sm">ประวการศกษา </span>
</div> </div>
@ -571,6 +659,7 @@ onMounted(async () => {
class="col-12" class="col-12"
:columns="columnsCertificates" :columns="columnsCertificates"
:row="formDetail.certificates" :row="formDetail.certificates"
:is-loading="isLoading.loadCertificate"
/> />
</q-card> </q-card>
@ -579,8 +668,14 @@ onMounted(async () => {
<span class="q-ml-lg q-my-sm">ประวการรบราชการ</span> <span class="q-ml-lg q-my-sm">ประวการรบราชการ</span>
</div> </div>
<div class="col-12"><q-separator /></div> <div class="col-12"><q-separator /></div>
<div class="col-10"> <div class="col-10">
<SkeletonTable
v-if="isLoading.loadSalary"
:columns="columnSalaries"
/>
<d-table <d-table
v-else
ref="table" ref="table"
row-key="id" row-key="id"
flat flat
@ -637,6 +732,7 @@ onMounted(async () => {
class="col-12" class="col-12"
:columns="columnTraining" :columns="columnTraining"
:row="formDetail.trainings" :row="formDetail.trainings"
:is-loading="isLoading.loadTraining"
/> />
</q-card> </q-card>
@ -649,6 +745,7 @@ onMounted(async () => {
class="col-12" class="col-12"
:columns="columnExperience" :columns="columnExperience"
:row="formDetail.experience" :row="formDetail.experience"
:is-loading="isLoading.loadExperience"
/> />
</q-card> </q-card>
@ -671,7 +768,13 @@ onMounted(async () => {
<div class="col-12"><q-separator /></div> <div class="col-12"><q-separator /></div>
<div class="col-10"> <div class="col-10">
<div class="q-pa-sm row col-12"> <div class="q-pa-sm row col-12">
<SkeletonTable
v-if="isLoading.loadExperience"
:columns="columnAssessments"
class="col-12"
/>
<d-table <d-table
v-else
flat flat
bordered bordered
:columns="columnAssessments" :columns="columnAssessments"

View file

@ -23,9 +23,10 @@ const mixin = useCounterMixin();
const store = useEvaluateStore(); const store = useEvaluateStore();
const dataStore = useDataStore(); const dataStore = useDataStore();
const router = useRouter(); const router = useRouter();
const { showLoader, hideLoader, messageError } = mixin; const { messageError } = mixin;
/** ตัวแปร*/ /** ตัวแปร*/
const isLoading = ref<boolean>(false);
const modal = ref<boolean>(false); const modal = ref<boolean>(false);
const menu = ref<ListMenu>(); const menu = ref<ListMenu>();
const listMenu = ref<ListMenu[]>([ const listMenu = ref<ListMenu[]>([
@ -73,7 +74,8 @@ function openExpert() {
/** function เรียกรายการประเมิน*/ /** function เรียกรายการประเมิน*/
async function fetchEvaluteList() { async function fetchEvaluteList() {
showLoader(); isLoading.value = true;
const body = { const body = {
page: pagination.value.page, page: pagination.value.page,
pageSize: pagination.value.rowsPerPage, pageSize: pagination.value.rowsPerPage,
@ -93,7 +95,7 @@ async function fetchEvaluteList() {
messageError($q, err); messageError($q, err);
}) })
.finally(() => { .finally(() => {
hideLoader(); isLoading.value = false;
}); });
} }
@ -326,6 +328,7 @@ onMounted(async () => {
v-model:total="total" v-model:total="total"
v-model:total-list="totalList" v-model:total-list="totalList"
v-model:pagination="pagination" v-model:pagination="pagination"
:isLoading="isLoading"
/> />
</div> </div>
</q-card> </q-card>

View file

@ -1,19 +1,20 @@
<script setup lang="ts"> <script setup lang="ts">
import { ref, reactive, onMounted, computed } from "vue"; import { ref, reactive, onMounted, computed } from "vue";
import { useCounterMixin } from "@/stores/mixin"; import { is, useQuasar, type QTableProps } from "quasar";
import { useDataStore } from "@/stores/data";
import { useQuasar, type QTableColumn, type QTableProps } from "quasar";
import http from "@/plugins/http"; import http from "@/plugins/http";
import config from "@/app.config"; import config from "@/app.config";
import { useCounterMixin } from "@/stores/mixin";
import { useDataStore } from "@/stores/data";
import DialogHistory from "@/modules/10_registry/Dialog/DialogHistory.vue"; /** import Type */
import type { InformationData } from "@/interface/Main"; import type { InformationData } from "@/interface/Main";
const link = ref<string>(""); /** import Component */
import DialogHistory from "@/modules/10_registry/Dialog/DialogHistory.vue";
const $q = useQuasar(); const $q = useQuasar();
const dataStore = useDataStore(); const dataStore = useDataStore();
const mixin = useCounterMixin();
const { const {
showLoader, showLoader,
hideLoader, hideLoader,
@ -21,16 +22,23 @@ const {
date2Thai, date2Thai,
dialogConfirm, dialogConfirm,
success, success,
} = mixin; } = useCounterMixin();
const editPhone = ref<boolean>(false);
const editEmail = ref<boolean>(false);
const rowsHistory = ref<any[]>([]);
const rowsHistoryData = ref<any[]>([]);
const modalHistory = ref<boolean>(false);
const phone = ref<string>("");
const email = ref<string>("");
const link = ref<string>(""); // link
const editPhone = ref<boolean>(false); //
const editEmail = ref<boolean>(false); //
const rowsHistory = ref<any[]>([]); //
const rowsHistoryData = ref<any[]>([]); // ( filter)
const modalHistory = ref<boolean>(false); // modal
const phone = ref<string>(""); //
const email = ref<string>(""); //
const isLoading = ref<boolean>(false); //
const isLoadingHistory = ref<boolean>(false); //
const mainEmail = ref<string>(""); //
const mainPhone = ref<string>(""); //
const isValidPhone = ref<boolean>(true); // validate
const isValidEmail = ref<boolean>(true); // validate
const emailVerify = ref<string | null>(null); //
/** ตัวแปรข้อมูล */ /** ตัวแปรข้อมูล */
const formDataInformation = reactive<InformationData>({ const formDataInformation = reactive<InformationData>({
rank: "", // rank: "", //
@ -48,8 +56,6 @@ const formDataInformation = reactive<InformationData>({
phone: "", // phone: "", //
email: "", email: "",
}); });
const emailVerify = ref<string | null>(null);
const visibleColumnsHistory = ref<string[]>([ const visibleColumnsHistory = ref<string[]>([
"citizenId", "citizenId",
"prefix", "prefix",
@ -237,27 +243,19 @@ const columnsHistory = ref<QTableProps["columns"]>([
}, },
]); ]);
function onHistory() { /** ตรวจสอบอีเมล */
modalHistory.value = true;
}
const mainEmail = ref<string>("");
const mainPhone = ref<string>("");
const isCheckEmail = computed(() => { const isCheckEmail = computed(() => {
return mainEmail.value === formDataInformation.email ? true : false; return mainEmail.value === formDataInformation.email ? true : false;
}); });
/** ตรวจสอบเบอร์โทร */
const isCheckPhone = computed(() => { const isCheckPhone = computed(() => {
console.log("mainPhone", mainPhone.value);
console.log("formDataInformation", formDataInformation.phone);
return mainPhone.value === formDataInformation.phone ? true : false; return mainPhone.value === formDataInformation.phone ? true : false;
}); });
/** get data */ /** ฟังก์ชันดึงข้อมูลประวัติส่วนตัว */
async function getData() { async function getData() {
showLoader(); isLoading.value = true;
await http await http
.get(config.API.dataUserInformationByType(link.value)) .get(config.API.dataUserInformationByType(link.value))
.then(async (res) => { .then(async (res) => {
@ -285,24 +283,27 @@ async function getData() {
phone.value = data.phone; phone.value = data.phone;
emailVerify.value = data.statusEmail; emailVerify.value = data.statusEmail;
hideLoader();
}) })
.catch((e) => { .catch((e) => {
messageError($q, e); messageError($q, e);
hideLoader();
}) })
.finally(() => {}); .finally(() => {
isLoading.value = false;
});
} }
/** get history */ /** ฟังก์ชันดึงข้อมูลประวัติการแก้ไข */
function getHistory() { async function getHistory() {
isLoadingHistory.value = true;
rowsHistory.value = [];
rowsHistoryData.value = [];
const url = const url =
dataStore.officerType == "OFFICER" dataStore.officerType == "OFFICER"
? config.API.dataUserInformatioHistory("") ? config.API.dataUserInformatioHistory("")
: config.API.dataUserInformatioHistory("-employee"); : config.API.dataUserInformatioHistory("-employee");
showLoader();
http await http
.get(url) .get(url)
.then((res) => { .then((res) => {
const data = res.data.result; const data = res.data.result;
@ -313,14 +314,16 @@ function getHistory() {
messageError($q, e); messageError($q, e);
}) })
.finally(() => { .finally(() => {
hideLoader(); isLoadingHistory.value = false;
}); });
} }
const isValidPhone = ref<boolean>(true); // validate /** ฟังก์ชันเปิด modal ประวัติการแก้ไขข้อมูลส่วนตัว */
const isValidEmail = ref<boolean>(true); // validate function onHistory() {
modalHistory.value = true;
}
/** บันทึกเบอร์โทร */ /** ฟังก์ชันบันทึกเบอร์โทร */
async function onSavePhone() { async function onSavePhone() {
if (!formDataInformation.phone || formDataInformation.phone.length != 10) { if (!formDataInformation.phone || formDataInformation.phone.length != 10) {
isValidPhone.value = false; isValidPhone.value = false;
@ -353,7 +356,7 @@ async function onSavePhone() {
} }
} }
/** บันทึก email */ /** ฟังก์ชันบันทึก email */
async function onSaveEmail() { async function onSaveEmail() {
if (!formDataInformation.email) { if (!formDataInformation.email) {
isValidEmail.value = false; isValidEmail.value = false;
@ -388,6 +391,7 @@ onMounted(async () => {
await getData(); await getData();
}); });
</script> </script>
<template> <template>
<div class="col-12"> <div class="col-12">
<q-toolbar class="q-px-none"> <q-toolbar class="q-px-none">
@ -402,13 +406,17 @@ onMounted(async () => {
dense dense
round round
size="14px" size="14px"
:loading="isLoading"
@click="onHistory" @click="onHistory"
> >
<q-tooltip>ประวแกไขขอมลสวนต</q-tooltip> <q-tooltip>ประวแกไขขอมลสวนต</q-tooltip>
</q-btn> </q-btn>
</q-toolbar> </q-toolbar>
<q-card bordered class="bg-grey-1 q-pa-md"> <q-card bordered class="bg-grey-1 q-pa-md">
<div class="row"> <div v-if="isLoading">
<q-skeleton height="160px" />
</div>
<div v-else class="row">
<div class="col-12 col-sm-12 col-md-6 q-gutter-y-sm"> <div class="col-12 col-sm-12 col-md-6 q-gutter-y-sm">
<div class="row"> <div class="row">
<div class="col-4 text-grey-6 text-weight-medium"> <div class="col-4 text-grey-6 text-weight-medium">
@ -670,5 +678,6 @@ onMounted(async () => {
:rows-data="rowsHistoryData" :rows-data="rowsHistoryData"
:visibleColumns="visibleColumnsHistory" :visibleColumns="visibleColumnsHistory"
:columns="columnsHistory" :columns="columnsHistory"
:is-loading="isLoadingHistory"
/> />
</template> </template>

View file

@ -1,33 +1,29 @@
<script setup lang="ts"> <script setup lang="ts">
import { useCounterMixin } from "@/stores/mixin";
import { useDataStore } from "@/stores/data";
import { useQuasar, type QTableProps } from "quasar";
import { ref, onMounted } from "vue"; import { ref, onMounted } from "vue";
import { useCounterMixin } from "@/stores/mixin";
import { useDataStore } from "@/stores/data";
import http from "@/plugins/http"; import http from "@/plugins/http";
import config from "@/app.config"; import config from "@/app.config";
/** import type*/
import { useQuasar, type QTableProps } from "quasar";
import type { ChangNameRows } from "@/modules/10_registry/interface/response/01_Information"; import type { ChangNameRows } from "@/modules/10_registry/interface/response/01_Information";
import DialogHistory from "@/modules/10_registry/Dialog/DialogHistory.vue";
const link = ref<string>(""); /** import component */
import SkeletonTable from "@/components/SkeletonTable.vue";
const $q = useQuasar(); const $q = useQuasar();
const mixin = useCounterMixin();
const dataStore = useDataStore(); const dataStore = useDataStore();
const { showLoader, hideLoader, messageError, date2Thai, onSearchDataTable } = const { showLoader, hideLoader, messageError, date2Thai, onSearchDataTable } =
mixin; useCounterMixin();
const rows = ref<ChangNameRows[]>([]);
const rowsData = ref<ChangNameRows[]>([]);
const idByrow = ref<string>("");
const filter = ref<string>("");
const rowsHistory = ref<ChangNameRows[]>([]);
const rowsHistoryData = ref<ChangNameRows[]>([]);
const mode = ref<boolean>($q.screen.gt.xs);
const modalHistory = ref<boolean>(false);
/** ตัวแปรข้อมูล */
const mode = ref<boolean>($q.screen.gt.xs); // true = desktop mode, false = mobile mode
const isLoading = ref<boolean>(false); //
const link = ref<string>(""); // -
const rows = ref<ChangNameRows[]>([]); // -
const rowsData = ref<ChangNameRows[]>([]); // -
const filter = ref<string>(""); //
const visibleColumns = ref<string[]>([ const visibleColumns = ref<string[]>([
"prefix", "prefix",
"firstName", "firstName",
@ -98,93 +94,10 @@ const pagination = ref({
sortBy: "lastUpdatedAt", sortBy: "lastUpdatedAt",
}); });
const visibleColumnsHistory = ref<string[]>([ /** ฟังก์ชันดึงข้อมูลประวัติการเปลี่ยนชื่อ */
"prefix",
"firstName",
"lastName",
"status",
"lastUpdateFullName",
"lastUpdatedAt",
]);
const columnsHistory = ref<QTableProps["columns"]>([
{
name: "prefix",
align: "left",
label: "คำนำหน้าชื่อ",
sortable: true,
field: "prefix",
headerStyle: "font-size: 14px",
style: "font-size: 14px",
sort: (a: string, b: string) =>
a.localeCompare(b, undefined, { numeric: true, sensitivity: "base" }),
},
{
name: "firstName",
align: "left",
label: "ชื่อ",
sortable: true,
field: "firstName",
headerStyle: "font-size: 14px",
style: "font-size: 14px",
sort: (a: string, b: string) =>
a.localeCompare(b, undefined, { numeric: true, sensitivity: "base" }),
},
{
name: "lastName",
align: "left",
label: "นามสกุล",
sortable: true,
field: "lastName",
headerStyle: "font-size: 14px",
style: "font-size: 14px",
sort: (a: string, b: string) =>
a.localeCompare(b, undefined, { numeric: true, sensitivity: "base" }),
},
{
name: "status",
align: "left",
label: "สถานะการเปลี่ยนชื่อ",
sortable: true,
field: "status",
headerStyle: "font-size: 14px",
style: "font-size: 14px",
sort: (a: string, b: string) =>
a.localeCompare(b, undefined, { numeric: true, sensitivity: "base" }),
},
{
name: "lastUpdateFullName",
align: "left",
label: "ผู้ดำเนินการ",
sortable: true,
field: "lastUpdateFullName",
headerStyle: "font-size: 14px",
style: "font-size: 14px",
sort: (a: string, b: string) =>
a.localeCompare(b, undefined, { numeric: true, sensitivity: "base" }),
},
{
name: "lastUpdatedAt",
align: "left",
label: "วันที่แก้ไข",
sortable: true,
field: "lastUpdatedAt",
format: (v) => date2Thai(v),
headerStyle: "font-size: 14px",
style: "font-size: 14px",
sort: (a: string, b: string) =>
a.localeCompare(b, undefined, { numeric: true, sensitivity: "base" }),
},
]);
function onHistory(id: string) {
modalHistory.value = true;
idByrow.value = id;
}
/** get data */
async function getData() { async function getData() {
showLoader(); isLoading.value = true;
http await http
.get(config.API.dataUserChangeNameByType(link.value)) .get(config.API.dataUserChangeNameByType(link.value))
.then((res) => { .then((res) => {
const data = res.data.result; const data = res.data.result;
@ -195,33 +108,11 @@ async function getData() {
messageError($q, e); messageError($q, e);
}) })
.finally(() => { .finally(() => {
setTimeout(() => { isLoading.value = false;
hideLoader();
}, 2000);
});
}
/** get history */
function getHistory() {
showLoader();
http
.get(
config.API.dataUserChangeNameHistoryByType(link.value) +
`/${idByrow.value}`
)
.then((res) => {
const data = res.data.result;
rowsHistory.value = data;
rowsHistoryData.value = data;
})
.catch((e) => {
messageError($q, e);
})
.finally(() => {
hideLoader();
}); });
} }
/** ฟังก์ชันค้นหาข้อมูลในตาราง */
function onSearch() { function onSearch() {
rows.value = onSearchDataTable( rows.value = onSearchDataTable(
filter.value, filter.value,
@ -230,9 +121,10 @@ function onSearch() {
); );
} }
/** /***
* งกโหลไฟลเอกสารหลกฐาน * งกดาวนโหลไฟลเอกสารหลกฐาน
* @param id รายการทองการโหลด * @param id รายการทองการโหลด
* @param profileId รหสโปรไฟลของผใช
*/ */
async function onDownloadFile(id: string, profileId: string) { async function onDownloadFile(id: string, profileId: string) {
showLoader(); showLoader();
@ -263,8 +155,8 @@ onMounted(async () => {
await getData(); await getData();
}); });
</script> </script>
<template> <template>
<!-- v-if="mode" -->
<div class="col-12"> <div class="col-12">
<q-toolbar class="q-px-none q-mt-md"> <q-toolbar class="q-px-none q-mt-md">
<span class="text-blue-6 text-weight-bold text-body1" <span class="text-blue-6 text-weight-bold text-body1"
@ -301,97 +193,96 @@ onMounted(async () => {
:display-value="$q.lang.table.columns" :display-value="$q.lang.table.columns"
/> />
</q-toolbar> </q-toolbar>
<d-table
flat
dense
bordered
virtual-scroll
:rows="rows.length !== 0 ? rows : []"
:columns="columns"
:grid="!mode"
:rows-per-page-options="[10, 25, 50, 100]"
:visible-columns="visibleColumns"
:virtual-scroll-sticky-size-start="48"
v-model:pagination="pagination"
>
<template v-slot:header="props">
<q-tr :props="props">
<q-th v-for="col in props.cols" :key="col.name" :props="props">
<span class="text-weight-medium">{{ col.label }}</span>
</q-th>
<q-th auto-width />
</q-tr>
</template>
<template v-if="mode" v-slot:body="props"> <div v-if="isLoading">
<q-tr :props="props" class="cursor-pointer"> <SkeletonTable :columns="columns" />
<q-td v-for="(col, index) in props.cols" :key="col.name"> </div>
<div v-if="col.name == 'no'">
{{ props.rowIndex + 1 }} <div class="col-12" v-else>
</div> <d-table
<div v-else> flat
{{ col.value ? col.value : "-" }} dense
</div> bordered
</q-td> virtual-scroll
<q-td auto-width> :rows="rows.length !== 0 ? rows : []"
<q-btn :columns="columns"
color="green" :grid="!mode"
flat :rows-per-page-options="[10, 25, 50, 100]"
dense :visible-columns="visibleColumns"
round :virtual-scroll-sticky-size-start="48"
icon="mdi-file-document-outline" v-model:pagination="pagination"
@click="onDownloadFile(props.row.id, props.row.profileId)" >
> <template v-slot:header="props">
<q-tooltip>ดาวนโหลด</q-tooltip> <q-tr :props="props">
</q-btn> <q-th v-for="col in props.cols" :key="col.name" :props="props">
</q-td> <span class="text-weight-medium">{{ col.label }}</span>
</q-tr> </q-th>
</template> <q-th auto-width />
<template v-else v-slot:item="props"> </q-tr>
<div class="q-mb-xs col-xs-12 col-sm-6 col-md-4 col-lg-3"> </template>
<q-card bordered flat>
<q-list dense class="q-mt-lg relative-position"> <template v-if="mode" v-slot:body="props">
<q-td auto-width> <q-tr :props="props" class="cursor-pointer">
<q-btn <q-td v-for="(col, index) in props.cols" :key="col.name">
color="green" <div v-if="col.name == 'no'">
flat {{ props.rowIndex + 1 }}
dense </div>
round <div v-else>
class="absolute_button" {{ col.value ? col.value : "-" }}
icon="mdi-file-document-outline" </div>
@click="onDownloadFile(props.row.id, props.row.profileId)" </q-td>
> <q-td auto-width>
<q-tooltip>ดาวนโหลด</q-tooltip> <q-btn
</q-btn> color="green"
</q-td> flat
<q-item v-for="col in props.cols" :key="col.name"> dense
<q-item-section> round
<q-item-label class="text-grey-6 text-weight-medium">{{ icon="mdi-file-document-outline"
col.label @click="onDownloadFile(props.row.id, props.row.profileId)"
}}</q-item-label> >
</q-item-section> <q-tooltip>ดาวนโหลด</q-tooltip>
<q-item-section> </q-btn>
<q-item-label class="text-dark text-weight-medium">{{ </q-td>
col.value ? col.value : "-" </q-tr>
}}</q-item-label> </template>
</q-item-section> <template v-else v-slot:item="props">
</q-item> <div class="q-mb-xs col-xs-12 col-sm-6 col-md-4 col-lg-3">
</q-list> <q-card bordered flat>
</q-card> <q-list dense class="q-mt-lg relative-position">
</div> <q-td auto-width>
</template> <q-btn
</d-table> color="green"
flat
dense
round
class="absolute_button"
icon="mdi-file-document-outline"
@click="onDownloadFile(props.row.id, props.row.profileId)"
>
<q-tooltip>ดาวนโหลด</q-tooltip>
</q-btn>
</q-td>
<q-item v-for="col in props.cols" :key="col.name">
<q-item-section>
<q-item-label class="text-grey-6 text-weight-medium">{{
col.label
}}</q-item-label>
</q-item-section>
<q-item-section>
<q-item-label class="text-dark text-weight-medium">{{
col.value ? col.value : "-"
}}</q-item-label>
</q-item-section>
</q-item>
</q-list>
</q-card>
</div>
</template>
</d-table>
</div>
</div> </div>
<DialogHistory
v-model:modal="modalHistory"
:title="'ประวัติแก้ไขการเปลี่ยนชื่อ-นามสกุล'"
:getData="getHistory"
:rows="rowsHistory"
:rows-data="rowsHistoryData"
:visibleColumns="visibleColumnsHistory"
:columns="columnsHistory"
/>
</template> </template>
<style scoped> <style scoped>
.absolute_button { .absolute_button {
position: absolute; position: absolute;

View file

@ -6,8 +6,8 @@ import http from "@/plugins/http";
import config from "@/app.config"; import config from "@/app.config";
import { useCounterMixin } from "@/stores/mixin"; import { useCounterMixin } from "@/stores/mixin";
import { useDataStore } from "@/stores/data"; import { useDataStore } from "@/stores/data";
import { useRegistryInFormationStore } from "@/modules/10_registry/store/registry";
/** import type */
import type { import type {
Address, Address,
Provinces, Provinces,
@ -15,28 +15,26 @@ import type {
SubDistricts, SubDistricts,
} from "@/modules/10_registry/interface/response/01_Information"; } from "@/modules/10_registry/interface/response/01_Information";
//history dialog /** import component */
import DialogHistory from "@/modules/10_registry/Dialog/DialogHistory.vue"; import DialogHistory from "@/modules/10_registry/Dialog/DialogHistory.vue";
import SkeletonAddress from "@/modules/10_registry/components/skeleton/Address.vue";
const link = ref<string>("");
const store = useRegistryInFormationStore();
const dataStore = useDataStore();
const rowsHistory = ref<any[]>([]);
const rowsHistoryData = ref<any[]>([]);
const $q = useQuasar(); const $q = useQuasar();
const mixin = useCounterMixin(); const dataStore = useDataStore();
const { showLoader, hideLoader, messageError, date2Thai } = mixin; const { messageError, date2Thai } = useCounterMixin();
const modalHistory = ref<boolean>(false);
/** ตัวแปรข้อมูล */
const isLoading = ref<boolean>(false); //
const isLoadingHistory = ref<boolean>(false); //
const link = ref<string>(""); //
const rowsHistory = ref<any[]>([]); //
const rowsHistoryData = ref<any[]>([]); //
const modalHistory = ref<boolean>(false); //
const formData = reactive({ const formData = reactive({
registrationAddress: "", // registrationAddress: "", //
registrationProvince: "", // registrationProvince: "", //
registrationDistrict: "", // / registrationDistrict: "", // /
registrationSubDistrict: "", // / registrationSubDistrict: "", // /
registrationZipCode: "", // registrationZipCode: "", //
currentAddress: "", // currentAddress: "", //
currentProvince: "", // currentProvince: "", //
currentDistrict: "", // / currentDistrict: "", // /
@ -44,11 +42,11 @@ const formData = reactive({
currentZipCode: "", // currentZipCode: "", //
}); });
const provinceData = ref<Provinces[]>([]); const provinceData = ref<Provinces[]>([]); //
const districtRegistration = ref<Districts[]>([]); const districtRegistration = ref<Districts[]>([]); // /
const districtCurrent = ref<Districts[]>([]); const districtCurrent = ref<Districts[]>([]); // /
const subDistrictRegistration = ref<SubDistricts[]>([]); const subDistrictRegistration = ref<SubDistricts[]>([]); // /
const subDistrictCurrent = ref<SubDistricts[]>([]); const subDistrictCurrent = ref<SubDistricts[]>([]); // /
const visibleColumnsHistory = ref<string[]>([ const visibleColumnsHistory = ref<string[]>([
"currentAddress", "currentAddress",
@ -65,7 +63,6 @@ const visibleColumnsHistory = ref<string[]>([
"lastUpdateFullName", "lastUpdateFullName",
"lastUpdatedAt", "lastUpdatedAt",
]); ]);
const columnsHistory = ref<QTableProps["columns"]>([ const columnsHistory = ref<QTableProps["columns"]>([
{ {
name: "registrationAddress", name: "registrationAddress",
@ -217,21 +214,18 @@ const columnsHistory = ref<QTableProps["columns"]>([
}, },
]); ]);
function onHistory() { /** ฟังก์ชันดึงข้อมูลที่อยู่ */
modalHistory.value = true;
}
/** get data */
async function getData() { async function getData() {
showLoader(); await http
http
.get(config.API.dataUserAddressByType(link.value)) .get(config.API.dataUserAddressByType(link.value))
.then((res) => { .then(async (res) => {
const data: Address = res.data.result; const data: Address = res.data.result;
fetchDistrict(data.registrationProvinceId, "1"); await Promise.all([
fetchDistrict(data.currentProvinceId, "2"); fetchDistrict(data.registrationProvinceId, "1"),
fetchSubDistrict(data.registrationDistrictId, "1"); fetchDistrict(data.currentProvinceId, "2"),
fetchSubDistrict(data.currentDistrictId, "2"); fetchSubDistrict(data.registrationDistrictId, "1"),
fetchSubDistrict(data.currentDistrictId, "2"),
]);
formData.registrationAddress = data.registrationAddress; formData.registrationAddress = data.registrationAddress;
formData.registrationProvince = data.registrationProvinceId; formData.registrationProvince = data.registrationProvinceId;
@ -247,42 +241,41 @@ async function getData() {
}) })
.catch((e) => { .catch((e) => {
messageError($q, e); messageError($q, e);
})
.finally(() => {
setTimeout(() => {
hideLoader();
}, 2000);
}); });
} }
/** get history */ /** ฟังก์ชันดึงข้อมูลประวัติที่อยู่ */
function getHistory() { async function getHistory() {
isLoadingHistory.value = true;
rowsHistory.value = [];
rowsHistoryData.value = [];
const url = const url =
dataStore.officerType == "OFFICER" dataStore.officerType == "OFFICER"
? config.API.dataUserHistory("") ? config.API.dataUserHistory("")
: config.API.dataUserHistory("-employee"); : config.API.dataUserHistory("-employee");
showLoader();
http await http
.get(url) .get(url)
.then((res) => { .then((res) => {
const data = res.data.result; const data = res.data.result;
rowsHistory.value = data; rowsHistory.value = data;
console.log("🚀 ~ .then ~ data:", data);
rowsHistoryData.value = data; rowsHistoryData.value = data;
}) })
.catch((e) => { .catch((e) => {
messageError($q, e); messageError($q, e);
}) })
.finally(() => { .finally(() => {
hideLoader(); isLoadingHistory.value = false;
}); });
} }
/** function onHistory() {
*function fetch อมลจงหว modalHistory.value = true;
*/ }
function fetchProvince() {
http /** ฟังก์ชันดึงข้อมูลจังหวัด */
async function fetchProvince() {
await http
.get(config.API.profileNewProvince) .get(config.API.profileNewProvince)
.then((res) => { .then((res) => {
const data = res.data.result; const data = res.data.result;
@ -294,13 +287,13 @@ function fetchProvince() {
} }
/** /**
* function fetch อมลอำเภอ * งกนดอมลอำเภอ
* @param id งหว * @param id งหว
* @param position อยตามทะเบยนบาน,อยจจ * @param position อยตามทะเบยนบาน,อยจจ
*/ */
function fetchDistrict(id: string | null, position: string) { async function fetchDistrict(id: string | null, position: string) {
if (!id) return; if (!id) return;
http await http
.get(config.API.profileNewDistrictByPId(id)) .get(config.API.profileNewDistrictByPId(id))
.then((res) => { .then((res) => {
const data = res.data.result.districts; const data = res.data.result.districts;
@ -316,13 +309,13 @@ function fetchDistrict(id: string | null, position: string) {
} }
/** /**
* function fetch อมลอำเภ * งกนดอมลอำเภ
* @param id อำเภอ * @param id อำเภอ
* @param position อยตามทะเบยนบาน,อยจจ * @param position อยตามทะเบยนบาน,อยจจ
*/ */
function fetchSubDistrict(id: string | null, position: string) { async function fetchSubDistrict(id: string | null, position: string) {
if (!id) return; if (!id) return;
http await http
.get(config.API.profileNewSubDistrictByDId(id)) .get(config.API.profileNewSubDistrictByDId(id))
.then((res) => { .then((res) => {
const data = res.data.result.subDistricts; const data = res.data.result.subDistricts;
@ -338,8 +331,8 @@ function fetchSubDistrict(id: string | null, position: string) {
} }
/** /**
* function แปลงชอจงหว * งกแปลงชอจงหว
* @param id * @param id รหสจงหว
*/ */
function convertProvinceName(id: string) { function convertProvinceName(id: string) {
const province = provinceData.value.find((e: Provinces) => e.id === id); const province = provinceData.value.find((e: Provinces) => e.id === id);
@ -347,8 +340,8 @@ function convertProvinceName(id: string) {
} }
/** /**
* function แปลงชออำเภอ * งกแปลงชออำเภอ
* @param id * @param id รหสอำเภอ
*/ */
function convertDistrictName(id: string, type: string) { function convertDistrictName(id: string, type: string) {
const data = const data =
@ -358,8 +351,8 @@ function convertDistrictName(id: string, type: string) {
} }
/** /**
* function แปลงชอตำบล * งก แปลงชอตำบล
* @param id * @param id รหสตำบล
*/ */
function convertSubDistrictName(id: string, type: string) { function convertSubDistrictName(id: string, type: string) {
const data = const data =
@ -369,9 +362,14 @@ function convertSubDistrictName(id: string, type: string) {
} }
onMounted(async () => { onMounted(async () => {
isLoading.value = true;
link.value = await dataStore.getProFileType(); link.value = await dataStore.getProFileType();
await fetchProvince(); try {
await getData(); await fetchProvince();
await getData();
} finally {
isLoading.value = false;
}
}); });
</script> </script>
<template> <template>
@ -386,6 +384,7 @@ onMounted(async () => {
dense dense
round round
size="14px" size="14px"
:loading="isLoading"
@click="onHistory" @click="onHistory"
> >
<q-tooltip>ประวอมลทอย</q-tooltip> <q-tooltip>ประวอมลทอย</q-tooltip>
@ -402,7 +401,8 @@ onMounted(async () => {
</q-item> </q-item>
<q-separator /> <q-separator />
<q-card-section> <q-card-section>
<div class="col-12 col-sm-12 col-md-6 q-gutter-y-sm"> <SkeletonAddress v-if="isLoading" />
<div v-else class="col-12 col-sm-12 col-md-6 q-gutter-y-sm">
<div class="row"> <div class="row">
<div class="col-5 text-grey-6 text-weight-medium"> <div class="col-5 text-grey-6 text-weight-medium">
อยตามทะเบยนบาน อยตามทะเบยนบาน
@ -481,7 +481,8 @@ onMounted(async () => {
</q-item> </q-item>
<q-separator /> <q-separator />
<q-card-section> <q-card-section>
<div class="col-12 col-sm-12 col-md-6 q-gutter-y-sm"> <SkeletonAddress v-if="isLoading" />
<div v-else class="col-12 col-sm-12 col-md-6 q-gutter-y-sm">
<div class="row"> <div class="row">
<div class="col-5 text-grey-6 text-weight-medium"> <div class="col-5 text-grey-6 text-weight-medium">
อยจจ อยจจ
@ -547,5 +548,6 @@ onMounted(async () => {
:rows-data="rowsHistoryData" :rows-data="rowsHistoryData"
:visibleColumns="visibleColumnsHistory" :visibleColumns="visibleColumnsHistory"
:columns="columnsHistory" :columns="columnsHistory"
:is-loading="isLoadingHistory"
/> />
</template> </template>

View file

@ -1,33 +1,28 @@
<script setup lang="ts"> <script setup lang="ts">
import { useQuasar, type QTableProps } from "quasar";
import { ref, reactive, onMounted } from "vue"; import { ref, reactive, onMounted } from "vue";
import { useQuasar, type QTableProps } from "quasar";
import http from "@/plugins/http"; import http from "@/plugins/http";
import config from "@/app.config"; import config from "@/app.config";
import { useRegistryInFormationStore } from "@/modules/10_registry/store/registry";
import { useDataStore } from "@/stores/data"; import { useDataStore } from "@/stores/data";
import { useCounterMixin } from "@/stores/mixin"; import { useCounterMixin } from "@/stores/mixin";
import type { FormChildren } from "@/modules/10_registry/interface/index/Family"; import type { FormChildren } from "@/modules/10_registry/interface/index/Family";
import DialogHistory from "@/modules/10_registry/Dialog/DialogHistory.vue"; import DialogHistory from "@/modules/10_registry/Dialog/DialogHistory.vue";
import SkeletonFamily from "@/modules/10_registry/components/skeleton/Family.vue";
const link = ref<string>("");
const $q = useQuasar(); const $q = useQuasar();
const mixin = useCounterMixin();
const { showLoader, hideLoader, messageError, date2Thai } = mixin;
const idFamily = ref<string>("");
const store = useRegistryInFormationStore();
const dataStore = useDataStore(); const dataStore = useDataStore();
const rowsHistory = ref<any[]>([]); const { messageError, date2Thai } = useCounterMixin();
const rowsHistoryData = ref<any[]>([]);
const typeForm = ref<string>(""); const link = ref<string>(""); //
const modalHistory = ref<boolean>(false); const idFamily = ref<string>(""); // ID
/** ตัวแปรข้อมูล */ const rowsHistory = ref<any[]>([]); //
const rowsHistoryData = ref<any[]>([]); //
const fatherData = reactive<any>({ const typeForm = ref<string>(""); // (father, mother, couple, children)
const modalHistory = ref<boolean>(false); //
const fatherData = reactive({
isLive: null, isLive: null,
citizenId: "", citizenId: "",
prefix: "", prefix: "",
@ -36,7 +31,7 @@ const fatherData = reactive<any>({
job: "", job: "",
profileId: "", profileId: "",
}); });
const motherData = reactive<any>({ const motherData = reactive({
isLive: null, isLive: null,
citizenId: "", citizenId: "",
prefix: "", prefix: "",
@ -45,7 +40,7 @@ const motherData = reactive<any>({
job: "", job: "",
profileId: "", profileId: "",
}); });
const coupleData = reactive<any>({ const coupleData = reactive({
isLive: null, isLive: null,
citizenId: "", citizenId: "",
prefix: "", prefix: "",
@ -56,7 +51,6 @@ const coupleData = reactive<any>({
statusMarital: "", statusMarital: "",
profileId: "", profileId: "",
}); });
const childData = ref<FormChildren[]>([]); const childData = ref<FormChildren[]>([]);
const visibleColumnsHistory = ref<string[]>([ const visibleColumnsHistory = ref<string[]>([
@ -161,21 +155,26 @@ const columnsHistory = ref<QTableProps["columns"]>([
}, },
]); ]);
const checkFatherData = ref<boolean>(false); const checkFatherData = ref<boolean>(false); //
const checkMotherData = ref<boolean>(false); const checkMotherData = ref<boolean>(false); //
const checkCoupleData = ref<boolean>(false); const checkCoupleData = ref<boolean>(false); //
const checkChildData = ref<boolean>(false); const checkChildData = ref<boolean>(false); //
function onHistory(type: string, id: string) { const isLoadingHistory = ref<boolean>(false); //
modalHistory.value = true; const isLoading = reactive({
typeForm.value = type; father: false,
idFamily.value = id ? id : "user"; mother: false,
} couple: false,
});
/** get data */ /**
* งกนดงขอมลสมาชกในครอบคร
* @param type ประเภทขอม (father, mother, couple, children)
*/
async function getData(type: string) { async function getData(type: string) {
showLoader(); (isLoading as any)[type] = true;
http
await http
.get(config.API.dataUserFamilyByType(link.value, type)) .get(config.API.dataUserFamilyByType(link.value, type))
.then((res) => { .then((res) => {
const data = res.data.result; const data = res.data.result;
@ -219,14 +218,24 @@ async function getData(type: string) {
messageError($q, e); messageError($q, e);
}) })
.finally(() => { .finally(() => {
setTimeout(() => { (isLoading as any)[type] = false;
hideLoader();
}, 2000);
}); });
} }
/** get history */ /**
function getHistory() { * งกนเปดประวการแกไขขอม
* @param type ประเภทขอม (father, mother, couple, children)
* @param id ID ของครอบคร (ใชสำหรบบตร)
*/
function onHistory(type: string, id: string) {
modalHistory.value = true;
typeForm.value = type;
idFamily.value = id ? id : "user";
}
/** ฟังก์ชันดึงประวัติการแก้ไขข้อมูล */
async function getHistory() {
isLoadingHistory.value = true;
rowsHistory.value = []; rowsHistory.value = [];
rowsHistoryData.value = []; rowsHistoryData.value = [];
const url = const url =
@ -238,8 +247,7 @@ function getHistory() {
idFamily.value idFamily.value
); );
showLoader(); await http
http
.get(url) .get(url)
.then((res) => { .then((res) => {
const data = res.data.result; const data = res.data.result;
@ -261,7 +269,7 @@ function getHistory() {
messageError($q, e); messageError($q, e);
}) })
.finally(() => { .finally(() => {
hideLoader(); isLoadingHistory.value = false;
}); });
} }
@ -292,12 +300,14 @@ onMounted(async () => {
flat flat
dense dense
round round
:isLoading="isLoading.father"
size="14px" size="14px"
@click="onHistory('father', '')" @click="onHistory('father', '')"
> >
<q-tooltip>ประวการแกไขขอมลบดา</q-tooltip> <q-tooltip>ประวการแกไขขอมลบดา</q-tooltip>
</q-btn> </q-btn>
<div class="col-12"> <SkeletonFamily v-if="isLoading.father" :type="'father'" />
<div class="col-12" v-else>
<q-card bordered class="bg-grey-1 q-pa-sm"> <q-card bordered class="bg-grey-1 q-pa-sm">
<div class="row"> <div class="row">
<div class="col-12 col-sm-12 col-md-12 q-gutter-y-sm"> <div class="col-12 col-sm-12 col-md-12 q-gutter-y-sm">
@ -366,11 +376,13 @@ onMounted(async () => {
dense dense
round round
size="14px" size="14px"
:isLoading="isLoading.mother"
@click="onHistory('mother', '')" @click="onHistory('mother', '')"
> >
<q-tooltip>ประวการแกไขขอมลมารดา</q-tooltip> <q-tooltip>ประวการแกไขขอมลมารดา</q-tooltip>
</q-btn> </q-btn>
<div class="col-12"> <SkeletonFamily v-if="isLoading.mother" :type="'mother'" />
<div v-else class="col-12">
<q-card bordered class="bg-grey-1 q-pa-sm"> <q-card bordered class="bg-grey-1 q-pa-sm">
<div class="row"> <div class="row">
<div class="col-12 col-sm-12 col-md-12 q-gutter-y-sm"> <div class="col-12 col-sm-12 col-md-12 q-gutter-y-sm">
@ -441,12 +453,14 @@ onMounted(async () => {
flat flat
dense dense
round round
:isLoading="isLoading.couple"
size="14px" size="14px"
@click="onHistory('couple', '')" @click="onHistory('couple', '')"
> >
<q-tooltip>ประวการแกไขขอมลคสมรส</q-tooltip> <q-tooltip>ประวการแกไขขอมลคสมรส</q-tooltip>
</q-btn> </q-btn>
<div class="col-12"> <SkeletonFamily v-if="isLoading.couple" :type="'couple'" />
<div v-else class="col-12">
<q-card bordered class="bg-grey-1 q-pa-sm"> <q-card bordered class="bg-grey-1 q-pa-sm">
<div class="row"> <div class="row">
<div class="col-12 col-sm-12 col-md-6 q-gutter-y-sm"> <div class="col-12 col-sm-12 col-md-6 q-gutter-y-sm">
@ -632,6 +646,7 @@ onMounted(async () => {
? columnsHistory ? columnsHistory
: columnsHistory?.filter((e) => e.name !== 'lastNameOld') : columnsHistory?.filter((e) => e.name !== 'lastNameOld')
" "
:is-loading="isLoadingHistory"
/> />
</template> </template>

View file

@ -1,35 +1,33 @@
<script setup lang="ts"> <script setup lang="ts">
import { useCounterMixin } from "@/stores/mixin";
import { useQuasar, type QTableProps } from "quasar";
import { ref, onMounted } from "vue"; import { ref, onMounted } from "vue";
import { useDataStore } from "@/stores/data"; import { useQuasar, type QTableProps } from "quasar";
//history dialog
import http from "@/plugins/http"; import http from "@/plugins/http";
import config from "@/app.config"; import config from "@/app.config";
import { useDataStore } from "@/stores/data";
import { useCounterMixin } from "@/stores/mixin";
import type { EducationProfile } from "@/modules/10_registry/interface/index/Main"; import type { EducationProfile } from "@/modules/10_registry/interface/index/Main";
import DialogHistory from "@/modules/10_registry/Dialog/DialogHistory.vue"; import DialogHistory from "@/modules/10_registry/Dialog/DialogHistory.vue";
import SkeletonTable from "@/components/SkeletonTable.vue";
const link = ref<string>(""); const link = ref<string>("");
const $q = useQuasar(); const $q = useQuasar();
const mixin = useCounterMixin(); const mixin = useCounterMixin();
const dataStore = useDataStore(); const dataStore = useDataStore();
const { showLoader, hideLoader, messageError, date2Thai, onSearchDataTable } = const { messageError, date2Thai, onSearchDataTable } = mixin;
mixin;
const rows = ref<EducationProfile[]>([]);
const rowsData = ref<EducationProfile[]>([]);
const rowsHistory = ref<EducationProfile[]>([]);
const rowsHistoryData = ref<EducationProfile[]>([]);
const idByRow = ref<string>("");
const filter = ref<string>("");
const mode = ref<boolean>($q.screen.gt.xs);
const modalHistory = ref<boolean>(false);
/** ตัวแปรข้อมูล */
const isLoading = ref<boolean>(false); //
const isLoadingHistory = ref<boolean>(false); //
const rows = ref<EducationProfile[]>([]); //
const rowsData = ref<EducationProfile[]>([]); //
const rowsHistory = ref<EducationProfile[]>([]); //
const rowsHistoryData = ref<EducationProfile[]>([]); //
const idByRow = ref<string>(""); // ID
const filter = ref<string>(""); //
const mode = ref<boolean>($q.screen.gt.xs); // true = desktop mode, false = mobile mode
const modalHistory = ref<boolean>(false); //
const visibleColumns = ref<string[]>([ const visibleColumns = ref<string[]>([
"educationLevel", "educationLevel",
"institute", "institute",
@ -266,10 +264,26 @@ const columns = ref<QTableProps["columns"]>([
a.localeCompare(b, undefined, { numeric: true, sensitivity: "base" }), a.localeCompare(b, undefined, { numeric: true, sensitivity: "base" }),
}, },
]); ]);
const pagination = ref({ const visibleColumnsHistory = ref<string[]>([
// sortBy: "lastUpdatedAt", "educationLevel",
}); "institute",
"degree",
"field",
"gpa",
"country",
"duration",
"durationYear",
"other",
"fundName",
"isEducation",
"isHigh",
"endDate",
"startDate",
"finishDate",
"note",
"lastUpdateFullName",
"lastUpdatedAt",
]);
const columnsHistory = ref<QTableProps["columns"]>([ const columnsHistory = ref<QTableProps["columns"]>([
{ {
name: "educationLevel", name: "educationLevel",
@ -486,37 +500,11 @@ const columnsHistory = ref<QTableProps["columns"]>([
a.localeCompare(b, undefined, { numeric: true, sensitivity: "base" }), a.localeCompare(b, undefined, { numeric: true, sensitivity: "base" }),
}, },
]); ]);
const visibleColumnsHistory = ref<string[]>([
"educationLevel",
"institute",
"degree",
"field",
"gpa",
"country",
"duration",
"durationYear",
"other",
"fundName",
"isEducation",
"isHigh",
"endDate",
"startDate",
"finishDate",
"note",
"lastUpdateFullName",
"lastUpdatedAt",
]);
/** เปิด dialog ประวัติ */ /** ฟังก์ชันดึงข้อมูลการศึกษา */
function onHistory(id: string) {
modalHistory.value = true;
idByRow.value = id;
}
/** get data */
async function getData() { async function getData() {
showLoader(); isLoading.value = true;
http await http
.get(config.API.dataUserEducationsByType(link.value)) .get(config.API.dataUserEducationsByType(link.value))
.then((res) => { .then((res) => {
const data = res.data.result; const data = res.data.result;
@ -527,16 +515,25 @@ async function getData() {
messageError($q, e); messageError($q, e);
}) })
.finally(() => { .finally(() => {
setTimeout(() => { isLoading.value = false;
hideLoader();
}, 2000);
}); });
} }
/**
* เป dialog ประวการศกษา
* @param id ID ของแถวทกเลอกสำหรบดประว
*/
function onHistory(id: string) {
modalHistory.value = true;
idByRow.value = id;
}
/** get history */ /** get history */
function getHistory() { async function getHistory() {
showLoader(); isLoadingHistory.value = true
http rowsHistory.value = [];
rowsHistoryData.value = [];
await http
.get(config.API.dataUserEducationsHistoryByType(link.value, idByRow.value)) .get(config.API.dataUserEducationsHistoryByType(link.value, idByRow.value))
.then((res) => { .then((res) => {
const data = res.data.result; const data = res.data.result;
@ -547,10 +544,11 @@ function getHistory() {
messageError($q, e); messageError($q, e);
}) })
.finally(() => { .finally(() => {
hideLoader(); isLoadingHistory.value = false;
}); });
} }
/** ฟังก์ชันค้นหาข้อมูลการศึกษา */
function onSearch() { function onSearch() {
rows.value = onSearchDataTable( rows.value = onSearchDataTable(
filter.value, filter.value,
@ -561,7 +559,6 @@ function onSearch() {
onMounted(async () => { onMounted(async () => {
link.value = await dataStore.getProFileType(); link.value = await dataStore.getProFileType();
await getData(); await getData();
}); });
</script> </script>
@ -603,7 +600,10 @@ onMounted(async () => {
:display-value="$q.lang.table.columns" :display-value="$q.lang.table.columns"
/> />
</q-toolbar> </q-toolbar>
<SkeletonTable v-if="isLoading" :columns="columns" />
<d-table <d-table
v-else
flat flat
dense dense
bordered bordered
@ -614,7 +614,6 @@ onMounted(async () => {
:rows-per-page-options="[10, 25, 50, 100]" :rows-per-page-options="[10, 25, 50, 100]"
:visible-columns="visibleColumns" :visible-columns="visibleColumns"
:virtual-scroll-sticky-size-start="48" :virtual-scroll-sticky-size-start="48"
v-model:pagination="pagination"
> >
<template v-slot:header="props"> <template v-slot:header="props">
<q-tr :props="props"> <q-tr :props="props">
@ -687,6 +686,7 @@ onMounted(async () => {
</template> </template>
</d-table> </d-table>
</div> </div>
<DialogHistory <DialogHistory
v-model:modal="modalHistory" v-model:modal="modalHistory"
:title="'ประวัติแก้ไขประวัติการศึกษา'" :title="'ประวัติแก้ไขประวัติการศึกษา'"
@ -695,6 +695,7 @@ onMounted(async () => {
:rows-data="rowsHistoryData" :rows-data="rowsHistoryData"
:visibleColumns="visibleColumnsHistory" :visibleColumns="visibleColumnsHistory"
:columns="columnsHistory" :columns="columnsHistory"
:is-loading="isLoadingHistory"
/> />
</template> </template>

View file

@ -1,33 +1,35 @@
<script setup lang="ts"> <script setup lang="ts">
import { useQuasar, type QTableProps } from "quasar";
import { ref, onMounted } from "vue"; import { ref, onMounted } from "vue";
import { useQuasar, type QTableProps } from "quasar";
import http from "@/plugins/http"; import http from "@/plugins/http";
import config from "@/app.config"; import config from "@/app.config";
import { useCounterMixin } from "@/stores/mixin"; import { useCounterMixin } from "@/stores/mixin";
import { useDataStore } from "@/stores/data"; import { useDataStore } from "@/stores/data";
/** import type */
import type { AbilityRows } from "@/modules/10_registry/interface/index/Main"; import type { AbilityRows } from "@/modules/10_registry/interface/index/Main";
//history dialog
import DialogHistory from "@/modules/10_registry/Dialog/DialogHistory.vue";
const link = ref<string>(""); /** import components */
const rows = ref<AbilityRows[]>([]); import DialogHistory from "@/modules/10_registry/Dialog/DialogHistory.vue";
const rowsData = ref<AbilityRows[]>([]); import SkeletonTable from "@/components/SkeletonTable.vue";
const rowsHistory = ref<AbilityRows[]>([]);
const rowsHistoryData = ref<AbilityRows[]>([]);
const idByRow = ref<string>("");
const filter = ref<string>("");
const $q = useQuasar(); const $q = useQuasar();
const mode = ref<boolean>($q.screen.gt.xs);
const mixin = useCounterMixin();
const dataStore = useDataStore(); const dataStore = useDataStore();
const { showLoader, hideLoader, messageError, date2Thai, onSearchDataTable } = const { showLoader, hideLoader, messageError, date2Thai, onSearchDataTable } =
mixin; useCounterMixin();
const modalHistory = ref<boolean>(false);
/** ตัวแปรข้อมูล */
const mode = ref<boolean>($q.screen.gt.xs); // true = desktop mode, false = mobile mode
const link = ref<string>(""); //
const isLoading = ref<boolean>(false); //
const isLoadingHistory = ref<boolean>(false); //
const rows = ref<AbilityRows[]>([]); //
const rowsData = ref<AbilityRows[]>([]); //
const rowsHistory = ref<AbilityRows[]>([]); //
const rowsHistoryData = ref<AbilityRows[]>([]); //
const idByRow = ref<string>(""); // id
const filter = ref<string>(""); //
const modalHistory = ref<boolean>(false); // modal
const visibleColumns = ref<string[]>([ const visibleColumns = ref<string[]>([
"field", "field",
"detail", "detail",
@ -187,14 +189,9 @@ const columnsHistory = ref<QTableProps["columns"]>([
}, },
]); ]);
function onHistory(id: string) { /** ฟังก์ชันดึงข้อมูล */
modalHistory.value = true;
idByRow.value = id;
}
/** get data */
async function getData() { async function getData() {
showLoader(); isLoading.value = true;
http http
.get(config.API.dataUserAbilityByType(link.value)) .get(config.API.dataUserAbilityByType(link.value))
.then((res) => { .then((res) => {
@ -206,16 +203,25 @@ async function getData() {
messageError($q, e); messageError($q, e);
}) })
.finally(() => { .finally(() => {
setTimeout(() => { isLoading.value = false;
hideLoader();
}, 2000);
}); });
} }
/** get history */ /**
function getHistory() { * งกนเป modal ประวการแกไขความสามารถพเศษ
showLoader(); * @param id ID ของแถวทองการดประว
http */
function onHistory(id: string) {
modalHistory.value = true;
idByRow.value = id;
}
/** ฟังก์ชันดึงข้อมูลประวัติการแก้ไขความสามารถพิเศษ */
async function getHistory() {
isLoadingHistory.value = true;
rowsHistory.value = [];
rowsHistoryData.value = [];
await http
.get(config.API.dataUserAbilityHistoryByType(link.value, idByRow.value)) .get(config.API.dataUserAbilityHistoryByType(link.value, idByRow.value))
.then((res) => { .then((res) => {
const data = res.data.result; const data = res.data.result;
@ -226,10 +232,11 @@ function getHistory() {
messageError($q, e); messageError($q, e);
}) })
.finally(() => { .finally(() => {
hideLoader(); isLoadingHistory.value = false;
}); });
} }
/** ฟังก์ชันค้นหาข้อมูล */
function onSearch() { function onSearch() {
rows.value = onSearchDataTable( rows.value = onSearchDataTable(
filter.value, filter.value,
@ -241,6 +248,7 @@ function onSearch() {
/** /**
* งกนโหลไฟลเอกสารหลกฐาน * งกนโหลไฟลเอกสารหลกฐาน
* @param id รายการทองการโหลด * @param id รายการทองการโหลด
* @param profileId ID ของโปรไฟลองการโหลด
*/ */
async function onDownloadFile(id: string, profileId: string) { async function onDownloadFile(id: string, profileId: string) {
showLoader(); showLoader();
@ -272,7 +280,6 @@ onMounted(async () => {
}); });
</script> </script>
<template> <template>
<!-- v-if="mode" -->
<div class="col-12"> <div class="col-12">
<q-toolbar class="q-px-none q-mt-md"> <q-toolbar class="q-px-none q-mt-md">
<span class="text-blue-6 text-weight-bold text-body1" <span class="text-blue-6 text-weight-bold text-body1"
@ -309,7 +316,10 @@ onMounted(async () => {
:display-value="$q.lang.table.columns" :display-value="$q.lang.table.columns"
/> />
</q-toolbar> </q-toolbar>
<SkeletonTable v-if="isLoading" :columns="columns" />
<d-table <d-table
v-else
flat flat
dense dense
bordered bordered
@ -422,6 +432,7 @@ onMounted(async () => {
</template> </template>
</d-table> </d-table>
</div> </div>
<DialogHistory <DialogHistory
v-model:modal="modalHistory" v-model:modal="modalHistory"
:title="'ประวัติแก้ไขความสามารถพิเศษ'" :title="'ประวัติแก้ไขความสามารถพิเศษ'"
@ -430,8 +441,10 @@ onMounted(async () => {
:rows-data="rowsHistoryData" :rows-data="rowsHistoryData"
:visibleColumns="visibleColumnsHistory" :visibleColumns="visibleColumnsHistory"
:columns="columnsHistory" :columns="columnsHistory"
:is-loading="isLoadingHistory"
/> />
</template> </template>
<style scoped> <style scoped>
.absolute_button { .absolute_button {
position: absolute; position: absolute;

View file

@ -7,30 +7,26 @@ import config from "@/app.config";
import { useCounterMixin } from "@/stores/mixin"; import { useCounterMixin } from "@/stores/mixin";
import { useDataStore } from "@/stores/data"; import { useDataStore } from "@/stores/data";
import { useRegistryInFormationStore } from "@/modules/10_registry/store/registry";
import type { import type {
ProfileAppointment, ProfileAppointment,
FormDataGovernment, FormDataGovernment,
} from "@/modules/10_registry/interface/index/Main"; } from "@/modules/10_registry/interface/index/Main";
//history dialog
/** import components */
import DialogHistory from "@/modules/10_registry/Dialog/DialogHistory.vue"; import DialogHistory from "@/modules/10_registry/Dialog/DialogHistory.vue";
import GovernmentSkeleton from "@/modules/10_registry/components/skeleton/Government.vue";
const link = ref<string>("");
const $q = useQuasar(); const $q = useQuasar();
const mixin = useCounterMixin();
const dataPerson = useDataStore(); const dataPerson = useDataStore();
const checkType = ref<boolean>( const { messageError, date2Thai, dateToISO } = useCounterMixin();
dataPerson.officerType == "OFFICER" ? true : false
);
const store = useRegistryInFormationStore();
const { showLoader, hideLoader, messageError, date2Thai, dateToISO } = mixin;
const rowsHistory = ref<ProfileAppointment[]>([]); const link = ref<string>(""); //
const rowsHistoryData = ref<ProfileAppointment[]>([]); const isLoading = ref<boolean>(false); //
const modalHistory = ref<boolean>(false); const isLoadingHistory = ref<boolean>(false); //
const rowsHistory = ref<ProfileAppointment[]>([]); //
const rowsHistoryData = ref<ProfileAppointment[]>([]); //
const modalHistory = ref<boolean>(false); // modal
/** ตัวแปรข้อมูล */
const formData = reactive<FormDataGovernment>({ const formData = reactive<FormDataGovernment>({
org: "", org: "",
positionField: "", positionField: "",
@ -138,7 +134,6 @@ const columnsHistory = ref<QTableProps["columns"]>([
]); ]);
/** ไม่เเน่ใจ ใช้เเบบไหน คอมเม้นไว้ก่อน */ /** ไม่เเน่ใจ ใช้เเบบไหน คอมเม้นไว้ก่อน */
// const columnsHistory = ref<QTableProps["columns"]>([ // const columnsHistory = ref<QTableProps["columns"]>([
// { // {
// name: "oc", // name: "oc",
@ -343,15 +338,14 @@ const columnsHistory = ref<QTableProps["columns"]>([
// a.localeCompare(b, undefined, { numeric: true, sensitivity: "base" }), // a.localeCompare(b, undefined, { numeric: true, sensitivity: "base" }),
// }, // },
// ]); // ]);
const checkType = ref<boolean>(
dataPerson.officerType == "OFFICER" ? true : false
);
function onHistory() { /** ฟังก์ชันดึงข้อมูล */
modalHistory.value = true; async function getData() {
} isLoading.value = true;
await http
/** get data */
function getData() {
showLoader();
http
.get(config.API.dataUserGovernmentByType(link.value)) .get(config.API.dataUserGovernmentByType(link.value))
.then((res) => { .then((res) => {
const data = res.data.result; const data = res.data.result;
@ -378,18 +372,25 @@ function getData() {
messageError($q, e); messageError($q, e);
}) })
.finally(() => { .finally(() => {
hideLoader(); isLoading.value = false;
}); });
} }
/** get history */ /** ฟังก์ชันเปิด modal ประวัติข้อมูล */
function getHistory() { function onHistory() {
modalHistory.value = true;
}
/** ฟังก์ชันดึงประวัติข้อมูลราชการ */
async function getHistory() {
isLoadingHistory.value = true;
rowsHistory.value = [];
rowsHistoryData.value = [];
const url = const url =
dataPerson.officerType == "OFFICER" dataPerson.officerType == "OFFICER"
? config.API.dataUserGovernmentHistory("") ? config.API.dataUserGovernmentHistory("")
: config.API.dataUserGovernmentHistory("-employee"); : config.API.dataUserGovernmentHistory("-employee");
showLoader(); await http
http
.get(url) .get(url)
.then((res) => { .then((res) => {
const data = res.data.result; const data = res.data.result;
@ -400,13 +401,13 @@ function getHistory() {
messageError($q, e); messageError($q, e);
}) })
.finally(() => { .finally(() => {
hideLoader(); isLoadingHistory.value = false;
}); });
} }
onMounted(async () => { onMounted(async () => {
link.value = await dataPerson.getProFileType(); link.value = await dataPerson.getProFileType();
getData(); await getData();
}); });
</script> </script>
<template> <template>
@ -421,12 +422,15 @@ onMounted(async () => {
dense dense
round round
size="14px" size="14px"
:isLoading="isLoading"
@click="onHistory" @click="onHistory"
> >
<q-tooltip>ประวอมลราชการ</q-tooltip> <q-tooltip>ประวอมลราชการ</q-tooltip>
</q-btn> </q-btn>
</q-toolbar> </q-toolbar>
<q-card bordered class="bg-grey-1 q-pa-md"> <GovernmentSkeleton v-if="isLoading" />
<q-card v-else bordered class="bg-grey-1 q-pa-md">
<div class="row q-col-gutter-y-sm"> <div class="row q-col-gutter-y-sm">
<div class="col-12 col-sm-12 col-md-6"> <div class="col-12 col-sm-12 col-md-6">
<div class="row q-col-gutter-y-sm"> <div class="row q-col-gutter-y-sm">
@ -584,5 +588,6 @@ onMounted(async () => {
:rows-data="rowsHistoryData" :rows-data="rowsHistoryData"
:visibleColumns="visibleColumnsHistory" :visibleColumns="visibleColumnsHistory"
:columns="columnsHistory" :columns="columnsHistory"
:is-loading="isLoadingHistory"
/> />
</template> </template>

View file

@ -1,38 +1,36 @@
<script setup lang="ts"> <script setup lang="ts">
import { useCounterMixin } from "@/stores/mixin";
import { useQuasar, type QTableProps } from "quasar";
import { ref, onMounted } from "vue"; import { ref, onMounted } from "vue";
import { useQuasar, type QTableProps } from "quasar";
import http from "@/plugins/http"; import http from "@/plugins/http";
import config from "@/app.config"; import config from "@/app.config";
import { useCounterMixin } from "@/stores/mixin";
import { useDataStore } from "@/stores/data"; import { useDataStore } from "@/stores/data";
import { useRegistryDataStore } from "@/modules/10_registry/store/Main"; import { useRegistryDataStore } from "@/modules/10_registry/store/Main";
import type { DisciplineDetail } from "@/modules/10_registry/interface/index/Main"; import type { DisciplineDetail } from "@/modules/10_registry/interface/index/Main";
import DialogHistory from "@/modules/10_registry/Dialog/DialogHistory.vue"; import DialogHistory from "@/modules/10_registry/Dialog/DialogHistory.vue";
import SkeletonTable from "@/components/SkeletonTable.vue";
const link = ref<string>("");
const $q = useQuasar(); const $q = useQuasar();
const mixin = useCounterMixin();
const dataStore = useDataStore(); const dataStore = useDataStore();
const { getPathUploadFlie } = useRegistryDataStore(); const { getPathUploadFlie } = useRegistryDataStore();
const { showLoader, hideLoader, messageError, date2Thai, onSearchDataTable } = const { showLoader, hideLoader, messageError, date2Thai, onSearchDataTable } =
mixin; useCounterMixin();
const rows = ref<DisciplineDetail[]>([]);
const rowsData = ref<DisciplineDetail[]>([]);
const idByRow = ref<string>("");
const filter = ref<string>("");
const rowsHistory = ref<DisciplineDetail[]>([]);
const rowsHistoryData = ref<DisciplineDetail[]>([]);
const mode = ref<boolean>($q.screen.gt.xs); const mode = ref<boolean>($q.screen.gt.xs);
const link = ref<string>(""); //
const fileGroup = ref<string>("เอกสารวินัย"); const isLoading = ref<boolean>(false); //
const isLoadingHistory = ref<boolean>(false); // ;
const modalHistory = ref<boolean>(false); const rows = ref<DisciplineDetail[]>([]); //
/** ตัวแปรข้อมูล */ const rowsData = ref<DisciplineDetail[]>([]); //
const idByRow = ref<string>(""); // ID
const filter = ref<string>(""); //
const rowsHistory = ref<DisciplineDetail[]>([]); //
const rowsHistoryData = ref<DisciplineDetail[]>([]); //
const fileGroup = ref<string>("เอกสารวินัย"); //
const modalHistory = ref<boolean>(false); // / modal
const visibleColumns = ref<string[]>([ const visibleColumns = ref<string[]>([
"level", "level",
"detail", "detail",
@ -142,15 +140,10 @@ const pagination = ref({
sortBy: "lastUpdatedAt", sortBy: "lastUpdatedAt",
}); });
function onHistory(id: string) { /** ฟังก์ชันสำหรับดึงข้อมูลวินัย */
modalHistory.value = true; async function getData() {
idByRow.value = id; isLoading.value = true;
} await http
/** get data */
function getData() {
showLoader();
http
.get(config.API.dataUserDisciplineByType(link.value)) .get(config.API.dataUserDisciplineByType(link.value))
.then((res) => { .then((res) => {
const data = res.data.result; const data = res.data.result;
@ -161,14 +154,25 @@ function getData() {
messageError($q, e); messageError($q, e);
}) })
.finally(() => { .finally(() => {
hideLoader(); isLoading.value = false;
}); });
} }
/** get history */ /**
function getHistory() { * เป modal ประวการแกไข
showLoader(); * @param id ID ของแถวทองการดประว
http */
function onHistory(id: string) {
modalHistory.value = true;
idByRow.value = id;
}
/** ฟังก์ชันสำหรับดึงข้อมูลประวัติการแก้ไข */
async function getHistory() {
isLoadingHistory.value = true;
rowsHistory.value = [];
rowsHistoryData.value = [];
await http
.get(config.API.dataUserDisciplineHistoryByType(link.value, idByRow.value)) .get(config.API.dataUserDisciplineHistoryByType(link.value, idByRow.value))
.then((res) => { .then((res) => {
const data = res.data.result; const data = res.data.result;
@ -179,15 +183,28 @@ function getHistory() {
messageError($q, e); messageError($q, e);
}) })
.finally(() => { .finally(() => {
hideLoader(); isLoadingHistory.value = false;
}); });
} }
/**
* งกนดาวนโหลดไฟลเอกสารหลกฐาน
* @param id ID ของไฟลองการดาวนโหลด
* @param profileId ID ของโปรไฟล
*/
async function onDownloadFile(id: string, profileId: string) { async function onDownloadFile(id: string, profileId: string) {
const data = await getPathUploadFlie(fileGroup.value, profileId, id); showLoader();
window.open(data.downloadUrl, "_blank"); try {
const data = await getPathUploadFlie(fileGroup.value, profileId, id);
window.open(data.downloadUrl, "_blank");
} catch (e) {
messageError($q, e);
} finally {
hideLoader();
}
} }
/** ฟังก์ชันค้นหาข้อมูลในตาราง */
function onSearch() { function onSearch() {
rows.value = onSearchDataTable( rows.value = onSearchDataTable(
filter.value, filter.value,
@ -198,7 +215,7 @@ function onSearch() {
onMounted(async () => { onMounted(async () => {
link.value = await dataStore.getProFileType(); link.value = await dataStore.getProFileType();
getData(); await getData();
}); });
</script> </script>
<template> <template>
@ -237,7 +254,9 @@ onMounted(async () => {
:display-value="$q.lang.table.columns" :display-value="$q.lang.table.columns"
/> />
</q-toolbar> </q-toolbar>
<SkeletonTable v-if="isLoading" :columns="columns" />
<d-table <d-table
v-else
flat flat
dense dense
bordered bordered
@ -349,6 +368,7 @@ onMounted(async () => {
</template> </template>
</d-table> </d-table>
</div> </div>
<DialogHistory <DialogHistory
v-model:modal="modalHistory" v-model:modal="modalHistory"
:title="'ประวัติแก้ไขวินัย'" :title="'ประวัติแก้ไขวินัย'"
@ -357,6 +377,7 @@ onMounted(async () => {
:rows-data="rowsHistoryData" :rows-data="rowsHistoryData"
:visibleColumns="visibleColumns" :visibleColumns="visibleColumns"
:columns="columns" :columns="columns"
:is-loading="isLoadingHistory"
/> />
</template> </template>
<style scoped> <style scoped>

View file

@ -1,34 +1,32 @@
<script setup lang="ts"> <script setup lang="ts">
import { useCounterMixin } from "@/stores/mixin";
import { useQuasar, type QTableProps } from "quasar";
import { ref, onMounted } from "vue"; import { ref, onMounted } from "vue";
import { useQuasar, type QTableProps } from "quasar";
import http from "@/plugins/http"; import http from "@/plugins/http";
import config from "@/app.config"; import config from "@/app.config";
import { useCounterMixin } from "@/stores/mixin";
import { useDataStore } from "@/stores/data"; import { useDataStore } from "@/stores/data";
import type { LeaveFormType } from "@/modules/10_registry/interface/index/Main"; import type { LeaveFormType } from "@/modules/10_registry/interface/index/Main";
import DialogHistory from "@/modules/10_registry/Dialog/DialogHistory.vue"; import DialogHistory from "@/modules/10_registry/Dialog/DialogHistory.vue";
import SkeletonTable from "@/components/SkeletonTable.vue";
const link = ref<string>("");
const $q = useQuasar(); const $q = useQuasar();
const mixin = useCounterMixin();
const dataStore = useDataStore(); const dataStore = useDataStore();
const { showLoader, hideLoader, messageError, date2Thai, onSearchDataTable } = const { messageError, date2Thai, onSearchDataTable } = useCounterMixin();
mixin;
const idByRow = ref<string>("");
const rows = ref<LeaveFormType[]>([]);
const rowsData = ref<LeaveFormType[]>([]);
const filter = ref<string>("");
const rowsHistory = ref<any[]>([]);
const rowsHistoryData = ref<any[]>([]);
const mode = ref<boolean>($q.screen.gt.xs); const mode = ref<boolean>($q.screen.gt.xs);
const link = ref<string>(""); //
const modalHistory = ref<boolean>(false); const isLoading = ref<boolean>(false); //
/** ตัวแปรข้อมูล */ const isLoadingHistory = ref<boolean>(false); //
const rows = ref<LeaveFormType[]>([]); //
const rowsData = ref<LeaveFormType[]>([]); // ()
const filter = ref<string>(""); //
const idByRow = ref<string>(""); // id
const rowsHistory = ref<LeaveFormType[]>([]); //
const rowsHistoryData = ref<LeaveFormType[]>([]); // ()
const modalHistory = ref<boolean>(false); // modal
const visibleColumns = ref<string[]>([ const visibleColumns = ref<string[]>([
"no", "no",
"typeLeave", "typeLeave",
@ -39,7 +37,6 @@ const visibleColumns = ref<string[]>([
"lastUpdateFullName", "lastUpdateFullName",
"lastUpdatedAt", "lastUpdatedAt",
]); ]);
const columns = ref<QTableProps["columns"]>([ const columns = ref<QTableProps["columns"]>([
{ {
name: "no", name: "no",
@ -136,7 +133,6 @@ const columns = ref<QTableProps["columns"]>([
const pagination = ref({ const pagination = ref({
sortBy: "lastUpdatedAt", sortBy: "lastUpdatedAt",
}); });
const visibleColumnsHistory = ref<string[]>([ const visibleColumnsHistory = ref<string[]>([
"no", "no",
"typeLeave", "typeLeave",
@ -243,15 +239,10 @@ const columnsHistory = ref<QTableProps["columns"]>([
}, },
]); ]);
function onHistory(id: string) { /** ฟังก์ชันสำหรับดึงข้อมูลการลา */
modalHistory.value = true; async function getData() {
idByRow.value = id; isLoading.value = true;
} await http
/** get data */
function getData() {
showLoader();
http
.get(config.API.dataUserLeaveByType(link.value)) .get(config.API.dataUserLeaveByType(link.value))
.then((res) => { .then((res) => {
const data = res.data.result; const data = res.data.result;
@ -275,14 +266,25 @@ function getData() {
messageError($q, e); messageError($q, e);
}) })
.finally(() => { .finally(() => {
hideLoader(); isLoading.value = false;
}); });
} }
/** get history */ /**
function getHistory() { * งกนสำหรบเป modal ประวการลา
showLoader(); * @param id ID ของการลา
http */
function onHistory(id: string) {
modalHistory.value = true;
idByRow.value = id;
}
/** ฟังก์ชันสำหรับดึงข้อมูลประวัติการลา */
async function getHistory() {
isLoadingHistory.value = true;
rowsHistory.value = [];
rowsHistoryData.value = [];
await http
.get(config.API.dataUserLeaveHistoryByType(link.value, idByRow.value)) .get(config.API.dataUserLeaveHistoryByType(link.value, idByRow.value))
.then((res) => { .then((res) => {
const data = res.data.result; const data = res.data.result;
@ -306,10 +308,15 @@ function getHistory() {
messageError($q, e); messageError($q, e);
}) })
.finally(() => { .finally(() => {
hideLoader(); isLoadingHistory.value = false;
}); });
} }
/**
* งกนสำหรบแสดงสถานะการลา
* @param val าสถานะการลา
* @return สถานะการลาในรปแบบขอความ
*/
function statusLeave(val: string) { function statusLeave(val: string) {
switch (val) { switch (val) {
case "waitting": case "waitting":
@ -325,6 +332,11 @@ function statusLeave(val: string) {
} }
} }
/**
* งกนสำหรบแปลงชวงวนทเปนรปแบบไทย
* @param val วงวนทองการแปลงเปนรปแบบไทย
* @return วงวนทในรปแบบไทย
*/
function dateThaiRange(val: [Date, Date]) { function dateThaiRange(val: [Date, Date]) {
if (val === null) { if (val === null) {
} else if (date2Thai(val[0]) === date2Thai(val[1])) { } else if (date2Thai(val[0]) === date2Thai(val[1])) {
@ -334,6 +346,7 @@ function dateThaiRange(val: [Date, Date]) {
} }
} }
/** ฟังก์ชันสำหรับค้นหาข้อมูลในตาราง */
function onSearch() { function onSearch() {
rows.value = onSearchDataTable( rows.value = onSearchDataTable(
filter.value, filter.value,
@ -344,11 +357,10 @@ function onSearch() {
onMounted(async () => { onMounted(async () => {
link.value = await dataStore.getProFileType(); link.value = await dataStore.getProFileType();
getData(); await getData();
}); });
</script> </script>
<template> <template>
<!-- v-if="mode" -->
<div class="col-12"> <div class="col-12">
<q-toolbar class="q-px-none q-mt-md"> <q-toolbar class="q-px-none q-mt-md">
<span class="text-blue-6 text-weight-bold text-body1">การลา</span> <span class="text-blue-6 text-weight-bold text-body1">การลา</span>
@ -383,7 +395,10 @@ onMounted(async () => {
:display-value="$q.lang.table.columns" :display-value="$q.lang.table.columns"
/> />
</q-toolbar> </q-toolbar>
<SkeletonTable v-if="isLoading" :columns="columns" />
<d-table <d-table
v-else
flat flat
dense dense
bordered bordered
@ -494,6 +509,7 @@ onMounted(async () => {
</template> </template>
</d-table> </d-table>
</div> </div>
<DialogHistory <DialogHistory
v-model:modal="modalHistory" v-model:modal="modalHistory"
:title="'ประวัติแก้ไขการลา'" :title="'ประวัติแก้ไขการลา'"
@ -503,6 +519,7 @@ onMounted(async () => {
:visibleColumns="visibleColumnsHistory" :visibleColumns="visibleColumnsHistory"
:columns="columnsHistory" :columns="columnsHistory"
:type="'Leave'" :type="'Leave'"
:is-loading="isLoadingHistory"
/> />
</template> </template>
<style scoped> <style scoped>

View file

@ -1,35 +1,36 @@
<script setup lang="ts"> <script setup lang="ts">
import { useCounterMixin } from "@/stores/mixin"; import { ref, onMounted } from "vue";
import { useQuasar, type QTableProps } from "quasar"; import { useQuasar, type QTableProps } from "quasar";
import { ref, reactive, onMounted } from "vue";
import http from "@/plugins/http"; import http from "@/plugins/http";
import config from "@/app.config"; import config from "@/app.config";
import { useCounterMixin } from "@/stores/mixin";
import { useDataStore } from "@/stores/data"; import { useDataStore } from "@/stores/data";
import { useRegistryDataStore } from "@/modules/10_registry/store/Main"; import { useRegistryDataStore } from "@/modules/10_registry/store/Main";
import type { DutyFormType } from "@/modules/10_registry/interface/index/Main"; import type { DutyFormType } from "@/modules/10_registry/interface/index/Main";
//history dialog
import DialogHistory from "@/modules/10_registry/Dialog/DialogHistory.vue";
const link = ref<string>(""); import DialogHistory from "@/modules/10_registry/Dialog/DialogHistory.vue";
const dataStore = useDataStore(); import SkeletonTable from "@/components/SkeletonTable.vue";
const idByRow = ref<string>("");
const rows = ref<DutyFormType[]>([]);
const rowsData = ref<DutyFormType[]>([]);
const filter = ref<string>("");
const rowsHistory = ref<DutyFormType[]>([]);
const rowsHistoryData = ref<DutyFormType[]>([]);
const $q = useQuasar(); const $q = useQuasar();
const mode = ref<any>($q.screen.gt.xs); const dataStore = useDataStore();
const mixin = useCounterMixin();
const { getPathUploadFlie } = useRegistryDataStore(); const { getPathUploadFlie } = useRegistryDataStore();
const { showLoader, hideLoader, messageError, date2Thai, onSearchDataTable } = const { showLoader, hideLoader, messageError, date2Thai, onSearchDataTable } =
mixin; useCounterMixin();
const modalHistory = ref<boolean>(false);
/** ตัวแปรข้อมูล */
const mode = ref<any>($q.screen.gt.xs); // true = desktop, false = mobile
const link = ref<string>(""); //
const isLoading = ref<boolean>(false); //
const isLoadingHistory = ref<boolean>(false); //
const rows = ref<DutyFormType[]>([]); //
const rowsData = ref<DutyFormType[]>([]); //
const filter = ref<string>(""); //
const idByRow = ref<string>(""); // id
const rowsHistory = ref<DutyFormType[]>([]); //
const rowsHistoryData = ref<DutyFormType[]>([]); //
const modalHistory = ref<boolean>(false); // / modal
const fileGroup = ref<string>("เอกสารปฏิบัติราชการพิเศษ"); //
const visibleColumns = ref<string[]>([ const visibleColumns = ref<string[]>([
"dateStart", "dateStart",
"dateEnd", "dateEnd",
@ -137,7 +138,6 @@ const columns = ref<QTableProps["columns"]>([
const pagination = ref({ const pagination = ref({
sortBy: "lastUpdatedAt", sortBy: "lastUpdatedAt",
}); });
const visibleColumnsHistory = ref<string[]>([ const visibleColumnsHistory = ref<string[]>([
"dateStart", "dateStart",
"dateEnd", "dateEnd",
@ -243,17 +243,10 @@ const columnsHistory = ref<QTableProps["columns"]>([
}, },
]); ]);
const fileGroup = ref<string>("เอกสารปฏิบัติราชการพิเศษ"); /** ฟังก์ชันสำหรับดึงข้อมูลปฏิบัติราชการ */
async function getData() {
function onHistory(id: string) { isLoading.value = true;
modalHistory.value = true; await http
idByRow.value = id;
}
/** get data */
function getData() {
showLoader();
http
.get(config.API.dataUserDutyByType(link.value)) .get(config.API.dataUserDutyByType(link.value))
.then((res) => { .then((res) => {
const data = res.data.result; const data = res.data.result;
@ -264,14 +257,25 @@ function getData() {
messageError($q, e); messageError($q, e);
}) })
.finally(() => { .finally(() => {
hideLoader(); isLoading.value = false;
}); });
} }
/** get history */ /**
function getHistory() { * งกนสำหรบเป modal ประวการแกไข
showLoader(); * @param id ID ของแถวทเลอก
http */
function onHistory(id: string) {
modalHistory.value = true;
idByRow.value = id;
}
/** ฟังก์ชันสำหรับดึงข้อมูลประวัติการแก้ไข */
async function getHistory() {
isLoadingHistory.value = true;
rowsHistory.value = [];
rowsHistoryData.value = [];
await http
.get(config.API.dataUserDutyHistoryByType(link.value, idByRow.value)) .get(config.API.dataUserDutyHistoryByType(link.value, idByRow.value))
.then((res) => { .then((res) => {
const data = res.data.result; const data = res.data.result;
@ -282,15 +286,28 @@ function getHistory() {
messageError($q, e); messageError($q, e);
}) })
.finally(() => { .finally(() => {
hideLoader(); isLoadingHistory.value = false;
}); });
} }
/**
* งกนสำหรบดาวนโหลดไฟล
* @param id ID ของแถวทเลอก
* @param profileId ID ของโปรไฟลเลอก
*/
async function onDownloadFile(id: string, profileId: string) { async function onDownloadFile(id: string, profileId: string) {
const data = await getPathUploadFlie(fileGroup.value, profileId, id); showLoader();
window.open(data.downloadUrl, "_blank"); try {
const data = await getPathUploadFlie(fileGroup.value, profileId, id);
window.open(data.downloadUrl, "_blank");
} catch (e) {
messageError($q, e);
} finally {
hideLoader();
}
} }
/** ฟังก์ชันสำหรับค้นหาข้อมูลในตาราง*/
function onSearch() { function onSearch() {
rows.value = onSearchDataTable( rows.value = onSearchDataTable(
filter.value, filter.value,
@ -301,11 +318,10 @@ function onSearch() {
onMounted(async () => { onMounted(async () => {
link.value = await dataStore.getProFileType(); link.value = await dataStore.getProFileType();
getData(); await getData();
}); });
</script> </script>
<template> <template>
<!-- v-if="mode" -->
<div class="col-12"> <div class="col-12">
<q-toolbar class="q-px-none q-mt-md"> <q-toolbar class="q-px-none q-mt-md">
<span class="text-blue-6 text-weight-bold text-body1" <span class="text-blue-6 text-weight-bold text-body1"
@ -342,7 +358,9 @@ onMounted(async () => {
:display-value="$q.lang.table.columns" :display-value="$q.lang.table.columns"
/> />
</q-toolbar> </q-toolbar>
<SkeletonTable v-if="isLoading" :columns="columns" />
<d-table <d-table
v-else
flat flat
dense dense
bordered bordered
@ -464,6 +482,7 @@ onMounted(async () => {
:rows-data="rowsHistoryData" :rows-data="rowsHistoryData"
:visibleColumns="visibleColumnsHistory" :visibleColumns="visibleColumnsHistory"
:columns="columnsHistory" :columns="columnsHistory"
:is-loading="isLoadingHistory"
/> />
</template> </template>
<style scoped> <style scoped>

View file

@ -1,36 +1,36 @@
<script setup lang="ts"> <script setup lang="ts">
import { useCounterMixin } from "@/stores/mixin";
import { useQuasar, type QTableProps } from "quasar";
import { ref, onMounted } from "vue"; import { ref, onMounted } from "vue";
import { useQuasar, type QTableProps } from "quasar";
import http from "@/plugins/http"; import http from "@/plugins/http";
import config from "@/app.config"; import config from "@/app.config";
import { useCounterMixin } from "@/stores/mixin";
import { useDataStore } from "@/stores/data"; import { useDataStore } from "@/stores/data";
import type { DutyFormType } from "@/modules/10_registry/interface/index/Main"; import type { DutyFormType } from "@/modules/10_registry/interface/index/Main";
//history dialog
/** import components */
import DialogHistory from "@/modules/10_registry/Dialog/DialogHistory.vue"; import DialogHistory from "@/modules/10_registry/Dialog/DialogHistory.vue";
import SkeletonTable from "@/components/SkeletonTable.vue";
const link = ref<string>("");
const dataStore = useDataStore();
const idByRow = ref<string>("");
const rows = ref<DutyFormType[]>([]);
const rowsData = ref<DutyFormType[]>([]);
const filter = ref<string>("");
const rowsHistory = ref<DutyFormType[]>([]);
const rowsHistoryData = ref<DutyFormType[]>([]);
const $q = useQuasar(); const $q = useQuasar();
const mode = ref<any>($q.screen.gt.xs); const dataStore = useDataStore();
const mixin = useCounterMixin(); const { messageError, date2Thai, onSearchDataTable } = useCounterMixin();
const { showLoader, hideLoader, messageError, date2Thai, onSearchDataTable } =
mixin;
const modalHistory = ref<boolean>(false); const mode = ref<boolean>($q.screen.gt.xs); // true if screen is larger than xs
const link = ref<string>(""); //
const isLoading = ref<boolean>(false); //
const isLoadingHistory = ref<boolean>(false); //
const rows = ref<DutyFormType[]>([]); //
const rowsData = ref<DutyFormType[]>([]); //
const filter = ref<string>(""); //
const idByRow = ref<string>(""); // id
const rowsHistory = ref<DutyFormType[]>([]); //
const rowsHistoryData = ref<DutyFormType[]>([]); //
const modalHistory = ref<boolean>(false); // modal
const checkType = ref<boolean>( const checkType = ref<boolean>(
dataStore.officerType == "OFFICER" ? true : false dataStore.officerType == "OFFICER" ? true : false
); );
/** ตัวแปรข้อมูล */
const visibleColumns = ref<String[]>([ const visibleColumns = ref<String[]>([
"dateStart", "dateStart",
"dateEnd", "dateEnd",
@ -103,10 +103,6 @@ const columns = ref<QTableProps["columns"]>([
a.localeCompare(b, undefined, { numeric: true, sensitivity: "base" }), a.localeCompare(b, undefined, { numeric: true, sensitivity: "base" }),
}, },
]); ]);
const pagination = ref({
sortBy: "lastUpdatedAt",
});
const visibleColumnsHistory = ref<string[]>([ const visibleColumnsHistory = ref<string[]>([
"dateStart", "dateStart",
"dateEnd", "dateEnd",
@ -116,7 +112,6 @@ const visibleColumnsHistory = ref<string[]>([
"lastUpdateFullName", "lastUpdateFullName",
"lastUpdatedAt", "lastUpdatedAt",
]); ]);
const columnsHistory = ref<QTableProps["columns"]>([ const columnsHistory = ref<QTableProps["columns"]>([
{ {
name: "dateStart", name: "dateStart",
@ -188,16 +183,14 @@ const columnsHistory = ref<QTableProps["columns"]>([
format: (v) => date2Thai(v, false, true), format: (v) => date2Thai(v, false, true),
}, },
]); ]);
const pagination = ref({
sortBy: "lastUpdatedAt",
});
function onHistory(id: string) { /** ฟังก์ชันสำหรับดึงข้อมูล */
modalHistory.value = true; async function getData() {
idByRow.value = id; isLoading.value = true;
} await http
/** get data */
function getData() {
showLoader();
http
.get(config.API.dataUserActpositionByType(link.value)) .get(config.API.dataUserActpositionByType(link.value))
.then((res) => { .then((res) => {
const data = res.data.result; const data = res.data.result;
@ -208,14 +201,25 @@ function getData() {
messageError($q, e); messageError($q, e);
}) })
.finally(() => { .finally(() => {
hideLoader(); isLoading.value = false;
}); });
} }
/** get history */ /**
function getHistory() { * เป modal ประวการแกไข
showLoader(); * @param id ID ของแถวทองการดประว
http */
function onHistory(id: string) {
modalHistory.value = true;
idByRow.value = id;
}
/** ฟังก์ชันสำหรับดึงข้อมูลประวัติ */
async function getHistory() {
isLoadingHistory.value = true;
rowsHistory.value = [];
rowsHistoryData.value = [];
await http
.get(config.API.dataUserActpositionHistoryByType(link.value, idByRow.value)) .get(config.API.dataUserActpositionHistoryByType(link.value, idByRow.value))
.then((res) => { .then((res) => {
const data = res.data.result; const data = res.data.result;
@ -226,10 +230,11 @@ function getHistory() {
messageError($q, e); messageError($q, e);
}) })
.finally(() => { .finally(() => {
hideLoader(); isLoadingHistory.value = false;
}); });
} }
/** ฟังก์ชันสำหรับค้นหาข้อมูล */
function onSearch() { function onSearch() {
rows.value = onSearchDataTable( rows.value = onSearchDataTable(
filter.value, filter.value,
@ -240,12 +245,11 @@ function onSearch() {
onMounted(async () => { onMounted(async () => {
link.value = await dataStore.getProFileType(); link.value = await dataStore.getProFileType();
getData(); await getData();
}); });
</script> </script>
<template> <template>
<!-- v-if="mode" -->
<div class="col-12"> <div class="col-12">
<q-toolbar class="q-px-none q-mt-md"> <q-toolbar class="q-px-none q-mt-md">
<span class="text-blue-6 text-weight-bold text-body1" <span class="text-blue-6 text-weight-bold text-body1"
@ -282,7 +286,10 @@ onMounted(async () => {
:display-value="$q.lang.table.columns" :display-value="$q.lang.table.columns"
/> />
</q-toolbar> </q-toolbar>
<SkeletonTable v-if="isLoading" :columns="columns" />
<d-table <d-table
v-else
flat flat
dense dense
bordered bordered
@ -363,6 +370,7 @@ onMounted(async () => {
</template> </template>
</d-table> </d-table>
</div> </div>
<DialogHistory <DialogHistory
v-model:modal="modalHistory" v-model:modal="modalHistory"
:title="'ประวัติแก้ไขรักษาการในตำแหน่ง'" :title="'ประวัติแก้ไขรักษาการในตำแหน่ง'"
@ -371,6 +379,7 @@ onMounted(async () => {
:rows-data="rowsHistoryData" :rows-data="rowsHistoryData"
:visibleColumns="visibleColumnsHistory" :visibleColumns="visibleColumnsHistory"
:columns="columnsHistory" :columns="columnsHistory"
:is-loading="isLoadingHistory"
/> />
</template> </template>

View file

@ -1,33 +1,35 @@
<script setup lang="ts"> <script setup lang="ts">
import { useCounterMixin } from "@/stores/mixin";
import { useQuasar, type QTableProps } from "quasar";
import { ref, onMounted } from "vue"; import { ref, onMounted } from "vue";
import { useQuasar, type QTableProps } from "quasar";
import http from "@/plugins/http"; import http from "@/plugins/http";
import config from "@/app.config"; import config from "@/app.config";
import { useCounterMixin } from "@/stores/mixin";
import { useDataStore } from "@/stores/data"; import { useDataStore } from "@/stores/data";
import type { DutyFormType } from "@/modules/10_registry/interface/index/Main"; import type { DutyFormType } from "@/modules/10_registry/interface/index/Main";
//history dialog
/** import components */
import DialogHistory from "@/modules/10_registry/Dialog/DialogHistory.vue"; import DialogHistory from "@/modules/10_registry/Dialog/DialogHistory.vue";
import SkeletonTable from "@/components/SkeletonTable.vue";
const $q = useQuasar();
const link = ref<string>(""); const link = ref<string>("");
const dataStore = useDataStore(); const dataStore = useDataStore();
const idByRow = ref<string>("");
const rows = ref<DutyFormType[]>([]);
const rowsData = ref<DutyFormType[]>([]);
const filter = ref<string>("");
const rowsHistory = ref<DutyFormType[]>([]);
const rowsHistoryData = ref<DutyFormType[]>([]);
const $q = useQuasar();
const mode = ref<any>($q.screen.gt.xs);
const mixin = useCounterMixin();
const { showLoader, hideLoader, messageError, date2Thai, onSearchDataTable } = const { showLoader, hideLoader, messageError, date2Thai, onSearchDataTable } =
mixin; useCounterMixin();
const modalHistory = ref<boolean>(false);
/** ตัวแปรข้อมูล */
const mode = ref<boolean>($q.screen.gt.xs); // false;
const isLoading = ref<boolean>(false); //
const isLoadingHistory = ref<boolean>(false); //
const rows = ref<DutyFormType[]>([]); //
const rowsData = ref<DutyFormType[]>([]); //
const filter = ref<string>(""); //
const idByRow = ref<string>(""); // id
const rowsHistory = ref<DutyFormType[]>([]); //
const rowsHistoryData = ref<DutyFormType[]>([]); //
const modalHistory = ref<boolean>(false); // modal
const visibleColumns = ref<string[]>([ const visibleColumns = ref<string[]>([
"commandName", "commandName",
"agency", "agency",
@ -135,7 +137,6 @@ const columns = ref<QTableProps["columns"]>([
const pagination = ref({ const pagination = ref({
sortBy: "lastUpdatedAt", sortBy: "lastUpdatedAt",
}); });
const visibleColumnsHistory = ref<string[]>([ const visibleColumnsHistory = ref<string[]>([
"commandName", "commandName",
"agency", "agency",
@ -241,15 +242,10 @@ const columnsHistory = ref<QTableProps["columns"]>([
}, },
]); ]);
function onHistory(id: string) { /** ฟังก์ชันดึงข้อมูลช่วยราชการ */
modalHistory.value = true; async function getData() {
idByRow.value = id; isLoading.value = true;
} await http
/** get data */
function getData() {
showLoader();
http
.get(config.API.dataUserAssistanceByType(link.value)) .get(config.API.dataUserAssistanceByType(link.value))
.then((res) => { .then((res) => {
const data = res.data.result; const data = res.data.result;
@ -260,14 +256,25 @@ function getData() {
messageError($q, e); messageError($q, e);
}) })
.finally(() => { .finally(() => {
hideLoader(); isLoading.value = false;
}); });
} }
/** get history */ /**
function getHistory() { * งกนเป modal ประวการแกไข
showLoader(); * @param id ID ของแถวทองการดประว
http */
function onHistory(id: string) {
modalHistory.value = true;
idByRow.value = id;
}
/** ฟังก์ชันดึงข้อมูลประวัติการแก้ไข */
async function getHistory() {
isLoadingHistory.value = true;
rowsHistory.value = [];
rowsHistoryData.value = [];
await http
.get(config.API.dataUserAssistanceHistoryByType(link.value, idByRow.value)) .get(config.API.dataUserAssistanceHistoryByType(link.value, idByRow.value))
.then((res) => { .then((res) => {
const data = res.data.result; const data = res.data.result;
@ -278,13 +285,14 @@ function getHistory() {
messageError($q, e); messageError($q, e);
}) })
.finally(() => { .finally(() => {
hideLoader(); isLoadingHistory.value = false;
}); });
} }
/** /**
* งกนโหลไฟลเอกสารหลกฐาน * งกนโหลไฟลเอกสารหลกฐาน
* @param id รายการทองการโหลด * @param id รายการทองการโหลด
* @param profileId ID ของโปรไฟล
*/ */
async function onDownloadFile(id: string, profileId: string) { async function onDownloadFile(id: string, profileId: string) {
showLoader(); showLoader();
@ -310,6 +318,7 @@ async function onDownloadFile(id: string, profileId: string) {
}); });
} }
/** ฟังก์ชันค้นหาข้อมูลในตาราง */
function onSearch() { function onSearch() {
rows.value = onSearchDataTable( rows.value = onSearchDataTable(
filter.value, filter.value,
@ -320,11 +329,10 @@ function onSearch() {
onMounted(async () => { onMounted(async () => {
link.value = await dataStore.getProFileType(); link.value = await dataStore.getProFileType();
getData(); await getData();
}); });
</script> </script>
<template> <template>
<!-- v-if="mode" -->
<div class="col-12"> <div class="col-12">
<q-toolbar class="q-px-none q-mt-md"> <q-toolbar class="q-px-none q-mt-md">
<span class="text-blue-6 text-weight-bold text-body1">วยราชการ</span> <span class="text-blue-6 text-weight-bold text-body1">วยราชการ</span>
@ -359,7 +367,10 @@ onMounted(async () => {
:display-value="$q.lang.table.columns" :display-value="$q.lang.table.columns"
/> />
</q-toolbar> </q-toolbar>
<SkeletonTable v-if="isLoading" :columns="columns" />
<d-table <d-table
v-else
flat flat
dense dense
bordered bordered
@ -469,6 +480,7 @@ onMounted(async () => {
</template> </template>
</d-table> </d-table>
</div> </div>
<DialogHistory <DialogHistory
v-model:modal="modalHistory" v-model:modal="modalHistory"
:title="'ประวัติแก้ไขรายการช่วยราชการ'" :title="'ประวัติแก้ไขรายการช่วยราชการ'"
@ -477,6 +489,7 @@ onMounted(async () => {
:rows-data="rowsHistoryData" :rows-data="rowsHistoryData"
:visibleColumns="visibleColumnsHistory" :visibleColumns="visibleColumnsHistory"
:columns="columnsHistory" :columns="columnsHistory"
:is-loading="isLoadingHistory"
/> />
</template> </template>
<style scoped> <style scoped>

View file

@ -1,49 +1,49 @@
<script setup lang="ts"> <script setup lang="ts">
import { useQuasar, type QTableColumn } from "quasar"; import { useQuasar, type QTableColumn } from "quasar";
import { ref, onMounted, computed } from "vue"; import { ref, onMounted, computed, reactive } from "vue";
import http from "@/plugins/http"; import http from "@/plugins/http";
import config from "@/app.config"; import config from "@/app.config";
import { useCounterMixin } from "@/stores/mixin"; import { useCounterMixin } from "@/stores/mixin";
import { useDataStore } from "@/stores/data"; import { useDataStore } from "@/stores/data";
import { useGovernmentPosDataStore } from "@/modules/10_registry/store/Position";
import type { import type {
SalaryFormType, SalaryFormType,
CardDataPos, CardDataPos,
} from "@/modules/10_registry/interface/index/Main"; } from "@/modules/10_registry/interface/index/Main";
import type { DataCommandCode } from "@/modules/10_registry/interface/response/Main";
//history dialog /**import components*/
import DialogHistory from "@/modules/10_registry/Dialog/DialogHistory.vue"; import DialogHistory from "@/modules/10_registry/Dialog/DialogHistory.vue";
import SkeletonTable from "@/components/SkeletonTable.vue";
const link = ref<string>("");
const $q = useQuasar(); const $q = useQuasar();
const dataPerson = useDataStore(); const dataPerson = useDataStore();
const store = useGovernmentPosDataStore();
const mixin = useCounterMixin();
const { const {
showLoader,
hideLoader,
messageError, messageError,
date2Thai, date2Thai,
onSearchDataTable, onSearchDataTable,
formatDatePosition, formatDatePosition,
findOrgName, findOrgName,
findOrgNameHtml, findOrgNameHtml,
} = mixin; } = useCounterMixin();
const idByRow = ref<string>("");
const rows = ref<SalaryFormType[]>([]);
const rowsData = ref<SalaryFormType[]>([]);
const filter = ref<string>("");
const rowsHistory = ref<SalaryFormType[]>([]);
const rowsHistoryData = ref<SalaryFormType[]>([]);
const mode = ref<boolean>($q.screen.gt.xs);
const checkType = ref<boolean>( const checkType = ref<boolean>(
dataPerson.officerType == "OFFICER" ? true : false dataPerson.officerType == "OFFICER" ? true : false
); ); //
const modalHistory = ref<boolean>(false); const mode = ref<boolean>($q.screen.gt.xs); // xs
const isLoading = reactive({
position: false, //
tenure: false, //
});
const isLoadingHistory = ref<boolean>(false); //
const link = ref<string>(""); // link
const rows = ref<SalaryFormType[]>([]); //
const rowsData = ref<SalaryFormType[]>([]); //
const idByRow = ref<string>(""); // id
const filter = ref<string>(""); // input
const rowsHistory = ref<SalaryFormType[]>([]); //
const rowsHistoryData = ref<SalaryFormType[]>([]); //
const modalHistory = ref<boolean>(false); // dialog
const cardData = ref<CardDataPos[]>([ const cardData = ref<CardDataPos[]>([
{ {
label: "ระยะเวลาดำรงตำแหน่งในสายงาน", label: "ระยะเวลาดำรงตำแหน่งในสายงาน",
@ -58,7 +58,6 @@ const cardData = ref<CardDataPos[]>([
data: [], data: [],
}, },
]); ]);
const baseColumns = ref<QTableColumn[]>([ const baseColumns = ref<QTableColumn[]>([
{ {
name: "commandDateAffect", name: "commandDateAffect",
@ -315,7 +314,6 @@ const baseVisibleColumns = ref<string[]>([
"lastUpdateFullName", "lastUpdateFullName",
"lastUpdatedAt", "lastUpdatedAt",
]); ]);
const columns = computed<QTableColumn[]>(() => { const columns = computed<QTableColumn[]>(() => {
if (!checkType.value) { if (!checkType.value) {
if (baseColumns.value) { if (baseColumns.value) {
@ -349,59 +347,9 @@ const columnsHistory = computed<QTableColumn[]>(() => {
}); });
const visibleColumnsHistory = ref<string[]>(baseVisibleColumns.value); const visibleColumnsHistory = ref<string[]>(baseVisibleColumns.value);
/** เปิด dialog ประวัติ*/ /** ฟังก์ชันดึงข้อมูลระยะเวลาดำรงตำแหน่ง */
function onHistory(id: string) {
modalHistory.value = true;
idByRow.value = id;
}
/** get data */
function getData() {
showLoader();
http
.get(config.API.dataUserPosition(link.value))
.then((res) => {
const data = res.data.result;
rows.value = data;
rowsData.value = data;
})
.catch((e) => {
messageError($q, e);
})
.finally(() => {
hideLoader();
});
}
/** get history */
function getHistory() {
showLoader();
http
.get(config.API.dataUserSalaryHistoryByType(link.value, idByRow.value))
.then((res) => {
const data = res.data.result;
rowsHistory.value = data;
rowsHistoryData.value = data;
})
.catch((e) => {
messageError($q, e);
})
.finally(() => {
hideLoader();
});
}
function onSearch() {
rows.value = onSearchDataTable(
filter.value,
rowsData.value,
columns.value ? columns.value : []
);
}
async function fetchDataTenure() { async function fetchDataTenure() {
console.log(link.value); isLoading.tenure = true;
await http await http
.get(config.API.salaryTenurePosition(link.value)) .get(config.API.salaryTenurePosition(link.value))
.then((res) => { .then((res) => {
@ -440,40 +388,78 @@ async function fetchDataTenure() {
}) })
.catch((err) => { .catch((err) => {
messageError($q, err); messageError($q, err);
})
.finally(() => {
isLoading.tenure = false;
}); });
} }
/** function fetch ข้อมูลประเภทคำสั่ง*/ /** ฟังก์ชันดึงข้อมูล */
async function fetchDataCommandCode() { async function getData() {
if (store.commandCodeData.length > 0) return false; isLoading.position = true;
await http await http
.get(config.API.orgCommandCode) .get(config.API.dataUserPosition(link.value))
.then((res) => { .then((res) => {
const data = res.data.result; const data = res.data.result;
const DataCommandCode = data.filter((e: DataCommandCode) => rows.value = data;
store.positionCode.includes(e.code) rowsData.value = data;
);
const options = DataCommandCode.map((e: DataCommandCode) => ({
id: e.code.toString(),
name: e.name,
}));
store.commandCodeData = options;
}) })
.catch((err) => { .catch((e) => {
messageError($q, err); messageError($q, e);
})
.finally(() => {
isLoading.position = false;
}); });
} }
/**
* เป dialog ประว
* @param id id ของแถวทองการดประว
*/
function onHistory(id: string) {
modalHistory.value = true;
idByRow.value = id;
}
/** ฟังก์ชันดึงข้อมูลประวัติ */
async function getHistory() {
isLoadingHistory.value = true;
rowsHistory.value = [];
rowsHistoryData.value = [];
await http
.get(config.API.dataUserSalaryHistoryByType(link.value, idByRow.value))
.then((res) => {
const data = res.data.result;
rowsHistory.value = data;
rowsHistoryData.value = data;
})
.catch((e) => {
messageError($q, e);
})
.finally(() => {
isLoadingHistory.value = false;
});
}
/** ฟังก์ชันค้นหาข้อมูลในตาราง */
function onSearch() {
rows.value = onSearchDataTable(
filter.value,
rowsData.value,
columns.value ? columns.value : []
);
}
onMounted(async () => { onMounted(async () => {
link.value = await dataPerson.getProFileType(); try {
if (link.value === "-employee") { link.value = await dataPerson.getProFileType();
cardData.value.splice(2, 1); if (link.value === "-employee") {
cardData.value.splice(2, 1);
}
await Promise.all([getData(), fetchDataTenure()]);
} catch (error) {
messageError($q, error);
} }
getData();
fetchDataTenure();
fetchDataCommandCode();
}); });
</script> </script>
@ -492,7 +478,15 @@ onMounted(async () => {
</div> </div>
<div class="col-12"><q-separator /></div> <div class="col-12"><q-separator /></div>
<q-card-section class="q-pt-none" style="min-height: 200px"> <q-card-section class="q-pt-none" style="min-height: 200px">
<li v-for="data in item.data">{{ data.name }} {{ data.time }}</li> <q-skeleton
v-if="isLoading.tenure"
type="text"
class="q-mb-sm"
style="width: 100%"
/>
<li v-else v-for="data in item.data">
{{ data.name }} {{ data.time }}
</li>
</q-card-section> </q-card-section>
</q-card> </q-card>
</div> </div>
@ -532,7 +526,9 @@ onMounted(async () => {
</div> </div>
<div class="col-12 q-mt-sm"> <div class="col-12 q-mt-sm">
<SkeletonTable v-if="isLoading.position" :columns="columns" />
<d-table <d-table
v-else
flat flat
dense dense
bordered bordered
@ -664,6 +660,7 @@ onMounted(async () => {
:rows-data="rowsHistoryData" :rows-data="rowsHistoryData"
:visibleColumns="visibleColumnsHistory" :visibleColumns="visibleColumnsHistory"
:columns="columnsHistory" :columns="columnsHistory"
:is-loading="isLoadingHistory"
/> />
</template> </template>
<style scoped> <style scoped>

View file

@ -1,6 +1,6 @@
<script setup lang="ts"> <script setup lang="ts">
import { useQuasar, type QTableColumn } from "quasar";
import { ref, onMounted, computed } from "vue"; import { ref, onMounted, computed } from "vue";
import { useQuasar, type QTableColumn } from "quasar";
import http from "@/plugins/http"; import http from "@/plugins/http";
import config from "@/app.config"; import config from "@/app.config";
@ -9,40 +9,33 @@ import { useDataStore } from "@/stores/data";
import type { SalaryFormType } from "@/modules/10_registry/interface/index/Main"; import type { SalaryFormType } from "@/modules/10_registry/interface/index/Main";
//history dialog
import DialogHistory from "@/modules/10_registry/Dialog/DialogHistory.vue"; import DialogHistory from "@/modules/10_registry/Dialog/DialogHistory.vue";
import SkeletonTable from "@/components/SkeletonTable.vue";
const link = ref<string>("");
const $q = useQuasar(); const $q = useQuasar();
const dataPerson = useDataStore(); const dataPerson = useDataStore();
const mixin = useCounterMixin();
const { const {
showLoader,
hideLoader,
messageError, messageError,
date2Thai, date2Thai,
onSearchDataTable, onSearchDataTable,
findOrgName, findOrgName,
findOrgNameHtml, findOrgNameHtml,
} = mixin; } = useCounterMixin();
const idByRow = ref<string>("");
const rows = ref<SalaryFormType[]>([]);
const rowsData = ref<SalaryFormType[]>([]);
const filter = ref<string>("");
const rowsHistory = ref<SalaryFormType[]>([]);
const rowsHistoryData = ref<SalaryFormType[]>([]);
const mode = ref<boolean>($q.screen.gt.xs);
const checkType = ref<boolean>(
dataPerson.officerType == "OFFICER" ? true : false
);
const modalHistory = ref<boolean>(false);
/** ตัวแปรข้อมูล */
const mode = ref<boolean>($q.screen.gt.xs); //
const link = ref<string>(""); //
const isLoading = ref<boolean>(false); //
const isLoadingHistory = ref<boolean>(false); //
const rows = ref<SalaryFormType[]>([]); //
const rowsData = ref<SalaryFormType[]>([]); // ()
const filter = ref<string>(""); //
const idByRow = ref<string>(""); //id
const rowsHistory = ref<SalaryFormType[]>([]); //
const rowsHistoryData = ref<SalaryFormType[]>([]); // ()
const modalHistory = ref<boolean>(false); // dialog
const salaryText = computed(() => { const salaryText = computed(() => {
return link.value == "" ? "เงินเดือน" : "ค่าจ้าง"; return link.value == "" ? "เงินเดือน" : "ค่าจ้าง";
}); });
const baseColumns = ref<QTableColumn[]>([ const baseColumns = ref<QTableColumn[]>([
{ {
name: "commandDateAffect", name: "commandDateAffect",
@ -330,20 +323,6 @@ const visibleColumns = ref<string[]>([
"lastUpdateFullName", "lastUpdateFullName",
"lastUpdatedAt", "lastUpdatedAt",
]); ]);
const columns = computed(() => {
if (link.value === "-employee") {
if (baseColumns.value) {
return baseColumns.value.filter(
(column) =>
column.name !== "positionSalaryAmount" &&
column.name !== "mouthSalaryAmount"
);
}
}
return baseColumns.value;
});
const visibleColumnsHistory = ref<string[]>([ const visibleColumnsHistory = ref<string[]>([
"commandDateAffect", "commandDateAffect",
"posNumCodeSit", "posNumCodeSit",
@ -363,20 +342,6 @@ const visibleColumnsHistory = ref<string[]>([
"lastUpdateFullName", "lastUpdateFullName",
"lastUpdatedAt", "lastUpdatedAt",
]); ]);
const columnsHistory = computed(() => {
if (link.value === "-employee") {
if (baseColumnsHistory.value) {
return baseColumnsHistory.value.filter(
(column: QTableColumn) =>
column.name !== "positionSalaryAmount" &&
column.name !== "mouthSalaryAmount"
);
}
}
return baseColumns.value;
});
const baseColumnsHistory = ref<QTableColumn[]>([ const baseColumnsHistory = ref<QTableColumn[]>([
{ {
name: "commandDateAffect", name: "commandDateAffect",
@ -639,16 +604,36 @@ const baseColumnsHistory = ref<QTableColumn[]>([
}, },
]); ]);
/** เปิด dialog ประวัติ*/ const columns = computed(() => {
function onHistory(id: string) { if (link.value === "-employee") {
modalHistory.value = true; if (baseColumns.value) {
idByRow.value = id; return baseColumns.value.filter(
} (column) =>
column.name !== "positionSalaryAmount" &&
column.name !== "mouthSalaryAmount"
);
}
}
return baseColumns.value;
});
/** get data */ const columnsHistory = computed(() => {
function getData() { if (link.value === "-employee") {
showLoader(); if (baseColumnsHistory.value) {
http return baseColumnsHistory.value.filter(
(column: QTableColumn) =>
column.name !== "positionSalaryAmount" &&
column.name !== "mouthSalaryAmount"
);
}
}
return baseColumns.value;
});
/*** ฟังก์ชันสำหรับดึงข้อมูล */
async function getData() {
isLoading.value = true;
await http
.get(config.API.dataUserSalaryByType(link.value)) .get(config.API.dataUserSalaryByType(link.value))
.then((res) => { .then((res) => {
const data = res.data.result; const data = res.data.result;
@ -659,13 +644,24 @@ function getData() {
messageError($q, e); messageError($q, e);
}) })
.finally(() => { .finally(() => {
hideLoader(); isLoading.value = false;
}); });
} }
/** get history */ /**
function getHistory() { * งกนสำหรบเป dialog ประวการแกไข
showLoader(); * @param id id ของแถวทเลอก
*/
function onHistory(id: string) {
modalHistory.value = true;
idByRow.value = id;
}
/** ฟังก์ชันสำหรับดึงข้อมูลประวัติการแก้ไข */
async function getHistory() {
isLoadingHistory.value = true;
rowsHistory.value = [];
rowsHistoryData.value = [];
http http
.get(config.API.dataUserSalaryHistoryByType(link.value, idByRow.value)) .get(config.API.dataUserSalaryHistoryByType(link.value, idByRow.value))
.then((res) => { .then((res) => {
@ -677,10 +673,11 @@ function getHistory() {
messageError($q, e); messageError($q, e);
}) })
.finally(() => { .finally(() => {
hideLoader(); isLoadingHistory.value = false;
}); });
} }
/** ฟังก์ชันสำหรับค้นหาข้อมูลในตาราง */
function onSearch() { function onSearch() {
rows.value = onSearchDataTable( rows.value = onSearchDataTable(
filter.value, filter.value,
@ -691,11 +688,10 @@ function onSearch() {
onMounted(async () => { onMounted(async () => {
link.value = await dataPerson.getProFileType(); link.value = await dataPerson.getProFileType();
getData(); await getData();
}); });
</script> </script>
<template> <template>
<!-- v-if="mode" -->
<div class="col-12"> <div class="col-12">
<q-toolbar class="q-px-none"> <q-toolbar class="q-px-none">
<span class="text-blue-6 text-weight-bold text-body1">{{ <span class="text-blue-6 text-weight-bold text-body1">{{
@ -732,7 +728,10 @@ onMounted(async () => {
:display-value="$q.lang.table.columns" :display-value="$q.lang.table.columns"
/> />
</q-toolbar> </q-toolbar>
<SkeletonTable v-if="isLoading" :columns="columns" />
<d-table <d-table
v-else
flat flat
dense dense
bordered bordered
@ -851,6 +850,7 @@ onMounted(async () => {
</template> </template>
</d-table> </d-table>
</div> </div>
<DialogHistory <DialogHistory
v-model:modal="modalHistory" v-model:modal="modalHistory"
:title="`ประวัติแก้ไข${salaryText}`" :title="`ประวัติแก้ไข${salaryText}`"
@ -859,8 +859,10 @@ onMounted(async () => {
:rows-data="rowsHistoryData" :rows-data="rowsHistoryData"
:visibleColumns="visibleColumnsHistory" :visibleColumns="visibleColumnsHistory"
:columns="columnsHistory" :columns="columnsHistory"
:is-loading="isLoadingHistory"
/> />
</template> </template>
<style scoped> <style scoped>
.absolute_button { .absolute_button {
position: absolute; position: absolute;

View file

@ -1,37 +1,39 @@
<script setup lang="ts"> <script setup lang="ts">
import { ref, onMounted, computed } from "vue"; import { ref, onMounted, computed } from "vue";
import { useCounterMixin } from "@/stores/mixin";
import { useQuasar, type QTableProps } from "quasar"; import { useQuasar, type QTableProps } from "quasar";
import http from "@/plugins/http"; import http from "@/plugins/http";
import config from "@/app.config"; import config from "@/app.config";
import { useCounterMixin } from "@/stores/mixin";
import { useDataStore } from "@/stores/data"; import { useDataStore } from "@/stores/data";
import { useRegistryDataStore } from "@/modules/10_registry/store/Main"; import { useRegistryDataStore } from "@/modules/10_registry/store/Main";
import type { NopaidFormType } from "@/modules/10_registry/interface/index/Main"; import type { NopaidFormType } from "@/modules/10_registry/interface/index/Main";
import DialogHistory from "@/modules/10_registry/Dialog/DialogHistory.vue"; import DialogHistory from "@/modules/10_registry/Dialog/DialogHistory.vue";
import SkeletonTable from "@/components/SkeletonTable.vue";
const link = ref<string>("");
const dataPerson = useDataStore();
const idByRow = ref<string>("");
const rows = ref<NopaidFormType[]>([]);
const rowsData = ref<NopaidFormType[]>([]);
const filter = ref<string>("");
const rowsHistory = ref<NopaidFormType[]>([]);
const rowsHistoryData = ref<NopaidFormType[]>([]);
const $q = useQuasar(); const $q = useQuasar();
const mode = ref<boolean>($q.screen.gt.xs); const dataPerson = useDataStore();
const mixin = useCounterMixin();
const { showLoader, hideLoader, messageError, date2Thai, onSearchDataTable } =
mixin;
const { getPathUploadFlie } = useRegistryDataStore(); const { getPathUploadFlie } = useRegistryDataStore();
const { showLoader, hideLoader, messageError, date2Thai, onSearchDataTable } =
useCounterMixin();
const modalHistory = ref<boolean>(false); const mode = ref<boolean>($q.screen.gt.xs); //
const link = ref<string>(""); //
const isLoading = ref<boolean>(false); //
const isLoadingHistory = ref<boolean>(false); //
const rows = ref<NopaidFormType[]>([]); //
const rowsData = ref<NopaidFormType[]>([]); //
const filter = ref<string>(""); //
const idByRow = ref<string>(""); //
const rowsHistory = ref<NopaidFormType[]>([]); //
const rowsHistoryData = ref<NopaidFormType[]>([]); //
const modalHistory = ref<boolean>(false); //
//
const salaryText = computed(() => { const salaryText = computed(() => {
return link.value == "" ? "เงินเดือน" : "ค่าจ้าง"; return link.value == "" ? "เงินเดือน" : "ค่าจ้าง";
}); });
const visibleColumns = ref<string[]>([ const visibleColumns = ref<string[]>([
"date", "date",
"detail", "detail",
@ -41,7 +43,6 @@ const visibleColumns = ref<string[]>([
"lastUpdateFullName", "lastUpdateFullName",
"lastUpdatedAt", "lastUpdatedAt",
]); ]);
const columns = ref<QTableProps["columns"]>([ const columns = ref<QTableProps["columns"]>([
{ {
name: "date", name: "date",
@ -128,7 +129,6 @@ const columns = ref<QTableProps["columns"]>([
const pagination = ref({ const pagination = ref({
sortBy: "lastUpdatedAt", sortBy: "lastUpdatedAt",
}); });
const visibleColumnsHistory = ref<string[]>([ const visibleColumnsHistory = ref<string[]>([
"date", "date",
"reference", "reference",
@ -138,7 +138,6 @@ const visibleColumnsHistory = ref<string[]>([
"lastUpdateFullName", "lastUpdateFullName",
"lastUpdatedAt", "lastUpdatedAt",
]); ]);
const columnsHistory = ref<QTableProps["columns"]>([ const columnsHistory = ref<QTableProps["columns"]>([
{ {
name: "date", name: "date",
@ -221,18 +220,12 @@ const columnsHistory = ref<QTableProps["columns"]>([
a.localeCompare(b, undefined, { numeric: true, sensitivity: "base" }), a.localeCompare(b, undefined, { numeric: true, sensitivity: "base" }),
}, },
]); ]);
const fileGroup = ref<string>(`เอกสารบันทึกวันที่ไม่ได้รับ${salaryText.value}`); //
const fileGroup = ref<string>(`เอกสารบันทึกวันที่ไม่ได้รับ${salaryText.value}`); /** ฟังก์ชันสำหรับดึงข้อมูล */
async function getData() {
function onHistory(id: string) { isLoading.value = true;
modalHistory.value = true; await http
idByRow.value = id;
}
/** get data */
function getData() {
showLoader();
http
.get(config.API.dataUserNopaidByType(link.value)) .get(config.API.dataUserNopaidByType(link.value))
.then((res) => { .then((res) => {
const data = res.data.result; const data = res.data.result;
@ -243,14 +236,25 @@ function getData() {
messageError($q, e); messageError($q, e);
}) })
.finally(() => { .finally(() => {
hideLoader(); isLoading.value = false;
}); });
} }
/** get history */ /**
function getHistory() { * งกนสำหรบเปดประวการแกไข
showLoader(); * @param id รหสของแถวทกเลอกสำหรบประว
http */
function onHistory(id: string) {
modalHistory.value = true;
idByRow.value = id;
}
/** ฟังก์ชันสำหรับดึงข้อมูลประวัติการแก้ไข */
async function getHistory() {
isLoadingHistory.value = true;
rowsHistory.value = [];
rowsHistoryData.value = [];
await http
.get( .get(
config.API.dataUserSalaryNopaidHistoryByType(link.value, idByRow.value) config.API.dataUserSalaryNopaidHistoryByType(link.value, idByRow.value)
) )
@ -263,15 +267,28 @@ function getHistory() {
messageError($q, e); messageError($q, e);
}) })
.finally(() => { .finally(() => {
hideLoader(); isLoadingHistory.value = false;
}); });
} }
/**
* งกนสำหรบดาวนโหลดไฟล
* @param id รหสของแถวทกเลอกสำหรบดาวนโหลด
* @param profileId รหสโปรไฟลของผใช
*/
async function onDownloadFile(id: string, profileId: string) { async function onDownloadFile(id: string, profileId: string) {
const data = await getPathUploadFlie(fileGroup.value, profileId, id); showLoader();
window.open(data.downloadUrl, "_blank"); try {
const data = await getPathUploadFlie(fileGroup.value, profileId, id);
window.open(data.downloadUrl, "_blank");
} catch (e) {
messageError($q, e);
} finally {
hideLoader();
}
} }
/** ฟังก์ชันสำหรับค้นหาข้อมูล */
function onSearch() { function onSearch() {
rows.value = onSearchDataTable( rows.value = onSearchDataTable(
filter.value, filter.value,
@ -282,11 +299,10 @@ function onSearch() {
onMounted(async () => { onMounted(async () => {
link.value = await dataPerson.getProFileType(); link.value = await dataPerson.getProFileType();
getData(); await getData();
}); });
</script> </script>
<template> <template>
<!-- v-if="mode" -->
<div class="col-12"> <div class="col-12">
<q-toolbar class="q-px-none q-mt-md"> <q-toolbar class="q-px-none q-mt-md">
<span class="text-blue-6 text-weight-bold text-body1">{{ <span class="text-blue-6 text-weight-bold text-body1">{{
@ -323,7 +339,10 @@ onMounted(async () => {
:display-value="$q.lang.table.columns" :display-value="$q.lang.table.columns"
/> />
</q-toolbar> </q-toolbar>
<SkeletonTable v-if="isLoading" :columns="columns" />
<d-table <d-table
v-else
flat flat
dense dense
bordered bordered
@ -448,6 +467,7 @@ onMounted(async () => {
:rows-data="rowsHistoryData" :rows-data="rowsHistoryData"
:visibleColumns="visibleColumnsHistory" :visibleColumns="visibleColumnsHistory"
:columns="columnsHistory" :columns="columnsHistory"
:is-loading="isLoadingHistory"
/> />
</template> </template>
<style scoped> <style scoped>

View file

@ -1,37 +1,35 @@
<script setup lang="ts"> <script setup lang="ts">
import { useCounterMixin } from "@/stores/mixin"; import { ref, onMounted } from "vue";
import { useQuasar, type QTableProps } from "quasar"; import { useQuasar, type QTableProps } from "quasar";
import { ref, reactive, onMounted } from "vue";
import http from "@/plugins/http"; import http from "@/plugins/http";
import config from "@/app.config"; import config from "@/app.config";
import { useCounterMixin } from "@/stores/mixin";
import { useDataStore } from "@/stores/data"; import { useDataStore } from "@/stores/data";
import { useRegistryDataStore } from "@/modules/10_registry/store/Main"; import { useRegistryDataStore } from "@/modules/10_registry/store/Main";
import type { CertificateDetail } from "@/modules/10_registry/interface/index/Main"; import type { CertificateDetail } from "@/modules/10_registry/interface/index/Main";
//history dialog
import DialogHistory from "@/modules/10_registry/Dialog/DialogHistory.vue"; import DialogHistory from "@/modules/10_registry/Dialog/DialogHistory.vue";
import SkeletonTable from "@/components/SkeletonTable.vue";
const link = ref<string>("");
const $q = useQuasar(); const $q = useQuasar();
const dataPerson = useDataStore(); const dataPerson = useDataStore();
const mixin = useCounterMixin();
const { showLoader, hideLoader, messageError, date2Thai, onSearchDataTable } =
mixin;
const { getPathUploadFlie } = useRegistryDataStore(); const { getPathUploadFlie } = useRegistryDataStore();
const { showLoader, hideLoader, messageError, date2Thai, onSearchDataTable } =
useCounterMixin();
const idByRow = ref<string>(""); const mode = ref<boolean>($q.screen.gt.xs); //
const rows = ref<CertificateDetail[]>([]); const link = ref<string>(""); //
const rowsData = ref<CertificateDetail[]>([]); const isLoading = ref<boolean>(false); //
const filter = ref<string>(""); const isLoadingHistory = ref<boolean>(false); //
const rowsHistory = ref<CertificateDetail[]>([]); const rows = ref<CertificateDetail[]>([]); //
const rowsHistoryData = ref<CertificateDetail[]>([]); const rowsData = ref<CertificateDetail[]>([]); //
const mode = ref<boolean>($q.screen.gt.xs); const filter = ref<string>(""); //
const idByRow = ref<string>(""); // id
const modalHistory = ref<boolean>(false); const rowsHistory = ref<CertificateDetail[]>([]); //
/** ตัวแปรข้อมูล */ const rowsHistoryData = ref<CertificateDetail[]>([]); //
const modalHistory = ref<boolean>(false); /// modal
const visibleColumns = ref<string[]>([ const visibleColumns = ref<string[]>([
"certificateType", "certificateType",
"issuer", "issuer",
@ -126,7 +124,6 @@ const columns = ref<QTableProps["columns"]>([
const pagination = ref({ const pagination = ref({
sortBy: "lastUpdatedAt", sortBy: "lastUpdatedAt",
}); });
const visibleColumnsHistory = ref<string[]>([ const visibleColumnsHistory = ref<string[]>([
"certificateType", "certificateType",
"issuer", "issuer",
@ -218,18 +215,12 @@ const columnsHistory = ref<QTableProps["columns"]>([
a.localeCompare(b, undefined, { numeric: true, sensitivity: "base" }), a.localeCompare(b, undefined, { numeric: true, sensitivity: "base" }),
}, },
]); ]);
const fileGroup = ref<string>("เอกสารใบอนุญาตประกอบวิชาชีพ"); //
const fileGroup = ref<string>("เอกสารใบอนุญาตประกอบวิชาชีพ"); /** ฟังก์ชันสำหรับดึงข้อมูลใบอนุญาตประกอบวิชาชีพ */
async function getData() {
function onHistory(id: string) { isLoading.value = true;
modalHistory.value = true; await http
idByRow.value = id;
}
/** get data */
function getData() {
showLoader();
http
.get(config.API.dataUserCertificateByType(link.value, "certificate")) .get(config.API.dataUserCertificateByType(link.value, "certificate"))
.then((res) => { .then((res) => {
const data = res.data.result; const data = res.data.result;
@ -240,14 +231,25 @@ function getData() {
messageError($q, e); messageError($q, e);
}) })
.finally(() => { .finally(() => {
hideLoader(); isLoading.value = false;
}); });
} }
/** get history */ /**
function getHistory() { * งกนสำหรบเป modal แสดงประวการแกไขใบอนญาต
showLoader(); * @param id ID ของแถวทเลอก
http */
function onHistory(id: string) {
modalHistory.value = true;
idByRow.value = id;
}
/** ฟังก์ชันสำหรับดึงข้อมูลประวัติการแก้ไขใบอนุญาต */
async function getHistory() {
isLoadingHistory.value = true;
rowsHistory.value = [];
rowsHistoryData.value = [];
await http
.get( .get(
config.API.dataUserCertificateHistoryByType( config.API.dataUserCertificateHistoryByType(
link.value, link.value,
@ -264,15 +266,28 @@ function getHistory() {
messageError($q, e); messageError($q, e);
}) })
.finally(() => { .finally(() => {
hideLoader(); isLoadingHistory.value = false;
}); });
} }
/**
* งกนสำหรบดาวนโหลดไฟล
* @param id ID ของไฟลองการดาวนโหลด
* @param profileId ID ของโปรไฟล
*/
async function onDownloadFile(id: string, profileId: string) { async function onDownloadFile(id: string, profileId: string) {
const data = await getPathUploadFlie(fileGroup.value, profileId, id); showLoader();
window.open(data.downloadUrl, "_blank"); try {
const data = await getPathUploadFlie(fileGroup.value, profileId, id);
window.open(data.downloadUrl, "_blank");
} catch (error) {
messageError($q, error);
} finally {
hideLoader();
}
} }
/** ฟังก์ชันสำหรับค้นหาข้อมูลในตาราง */
function onSearch() { function onSearch() {
rows.value = onSearchDataTable( rows.value = onSearchDataTable(
filter.value, filter.value,
@ -283,11 +298,10 @@ function onSearch() {
onMounted(async () => { onMounted(async () => {
link.value = await dataPerson.getProFileType(); link.value = await dataPerson.getProFileType();
getData(); await getData();
}); });
</script> </script>
<template> <template>
<!-- v-if="mode" -->
<div class="col-12"> <div class="col-12">
<q-toolbar class="q-px-none"> <q-toolbar class="q-px-none">
<span class="text-blue-6 text-weight-bold text-body1" <span class="text-blue-6 text-weight-bold text-body1"
@ -324,7 +338,10 @@ onMounted(async () => {
:display-value="$q.lang.table.columns" :display-value="$q.lang.table.columns"
/> />
</q-toolbar> </q-toolbar>
<SkeletonTable v-if="isLoading" :columns="columns" />
<d-table <d-table
v-else
flat flat
dense dense
bordered bordered
@ -445,6 +462,7 @@ onMounted(async () => {
:rows-data="rowsHistoryData" :rows-data="rowsHistoryData"
:visibleColumns="visibleColumnsHistory" :visibleColumns="visibleColumnsHistory"
:columns="columnsHistory" :columns="columnsHistory"
:is-loading="isLoadingHistory"
/> />
</template> </template>
<style scoped> <style scoped>

View file

@ -1,34 +1,33 @@
<script setup lang="ts"> <script setup lang="ts">
import { useCounterMixin } from "@/stores/mixin";
import { useQuasar, type QTableProps } from "quasar";
import { ref, onMounted } from "vue"; import { ref, onMounted } from "vue";
import { useQuasar, type QTableProps } from "quasar";
import http from "@/plugins/http"; import http from "@/plugins/http";
import config from "@/app.config"; import config from "@/app.config";
import { useDataStore } from "@/stores/data"; import { useDataStore } from "@/stores/data";
import { useCounterMixin } from "@/stores/mixin";
import type { TrainingFormType } from "@/modules/10_registry/interface/index/Main"; import type { TrainingFormType } from "@/modules/10_registry/interface/index/Main";
//history dialog //history dialog
import DialogHistory from "@/modules/10_registry/Dialog/DialogHistory.vue"; import DialogHistory from "@/modules/10_registry/Dialog/DialogHistory.vue";
import SkeletonTable from "@/components/SkeletonTable.vue";
const link = ref<string>("");
const dataPerson = useDataStore();
const idByRow = ref<string>("");
const rows = ref<TrainingFormType[]>([]);
const rowsData = ref<TrainingFormType[]>([]);
const filter = ref<string>("");
const rowsHistory = ref<TrainingFormType[]>([]);
const rowsHistoryData = ref<TrainingFormType[]>([]);
const $q = useQuasar(); const $q = useQuasar();
const mode = ref<boolean>($q.screen.gt.xs); const dataPerson = useDataStore();
const mixin = useCounterMixin(); const { messageError, date2Thai, onSearchDataTable } = useCounterMixin();
const { showLoader, hideLoader, messageError, date2Thai, onSearchDataTable } =
mixin;
const modalHistory = ref<boolean>(false);
/** ตัวแปรข้อมูล */
const mode = ref<boolean>($q.screen.gt.xs); //
const link = ref<string>(""); //
const isLoading = ref<boolean>(false); //
const isLoadingHistory = ref<boolean>(false); //
const rows = ref<TrainingFormType[]>([]); // /
const rowsData = ref<TrainingFormType[]>([]); // /
const filter = ref<string>(""); //
const idByRow = ref<string>(""); // id
const rowsHistory = ref<TrainingFormType[]>([]); // /
const rowsHistoryData = ref<TrainingFormType[]>([]); // /
const modalHistory = ref<boolean>(false); // / modal /
const visibleColumns = ref<string[]>([ const visibleColumns = ref<string[]>([
"name", // "name", //
"topic", // "topic", //
@ -187,7 +186,6 @@ const columns = ref<QTableProps["columns"]>([
const pagination = ref({ const pagination = ref({
sortBy: "lastUpdatedAt", sortBy: "lastUpdatedAt",
}); });
const visibleColumnsHistory = ref<string[]>([ const visibleColumnsHistory = ref<string[]>([
"name", // "name", //
"topic", // "topic", //
@ -343,15 +341,11 @@ const columnsHistory = ref<QTableProps["columns"]>([
a.localeCompare(b, undefined, { numeric: true, sensitivity: "base" }), a.localeCompare(b, undefined, { numeric: true, sensitivity: "base" }),
}, },
]); ]);
function onHistory(id: string) {
modalHistory.value = true;
idByRow.value = id;
}
/** get data */ /** get data */
function getData() { async function getData() {
showLoader(); isLoading.value = true;
http await http
.get(config.API.dataUserCertificateByType(link.value, "training")) .get(config.API.dataUserCertificateByType(link.value, "training"))
.then((res) => { .then((res) => {
const data = res.data.result; const data = res.data.result;
@ -362,14 +356,25 @@ function getData() {
messageError($q, e); messageError($q, e);
}) })
.finally(() => { .finally(() => {
hideLoader(); isLoading.value = false;
}); });
} }
/** get history */ /**
function getHistory() { * เป modal แสดงประวการแกไขการฝกอบรม/งาน
showLoader(); * @param id ID ของแถวทเลอก
http */
function onHistory(id: string) {
modalHistory.value = true;
idByRow.value = id;
}
/** ฟังก์ชันสำหรับดึงข้อมูลประวัติการแก้ไขการฝึกอบรม/ดูงาน */
async function getHistory() {
isLoadingHistory.value = true;
rowsHistory.value = [];
rowsHistoryData.value = [];
await http
.get( .get(
config.API.dataUserCertificateHistoryByType( config.API.dataUserCertificateHistoryByType(
link.value, link.value,
@ -386,10 +391,11 @@ function getHistory() {
messageError($q, e); messageError($q, e);
}) })
.finally(() => { .finally(() => {
hideLoader(); isLoadingHistory.value = false;
}); });
} }
/** ฟังก์ชันสำหรับค้นหาข้อมูลในตาราง */
function onSearch() { function onSearch() {
rows.value = onSearchDataTable( rows.value = onSearchDataTable(
filter.value, filter.value,
@ -400,11 +406,10 @@ function onSearch() {
onMounted(async () => { onMounted(async () => {
link.value = await dataPerson.getProFileType(); link.value = await dataPerson.getProFileType();
getData(); await getData();
}); });
</script> </script>
<template> <template>
<!-- v-if="mode" -->
<div class="col-12"> <div class="col-12">
<q-toolbar class="q-px-none q-mt-md"> <q-toolbar class="q-px-none q-mt-md">
<span class="text-blue-6 text-weight-bold text-body1" <span class="text-blue-6 text-weight-bold text-body1"
@ -441,7 +446,10 @@ onMounted(async () => {
:display-value="$q.lang.table.columns" :display-value="$q.lang.table.columns"
/> />
</q-toolbar> </q-toolbar>
<SkeletonTable v-if="isLoading" :columns="columns" />
<d-table <d-table
v-else
flat flat
dense dense
bordered bordered
@ -517,6 +525,7 @@ onMounted(async () => {
</template> </template>
</d-table> </d-table>
</div> </div>
<DialogHistory <DialogHistory
v-model:modal="modalHistory" v-model:modal="modalHistory"
:title="'ประวัติแก้ไขการฝึกอบรม/ดูงาน'" :title="'ประวัติแก้ไขการฝึกอบรม/ดูงาน'"
@ -525,8 +534,10 @@ onMounted(async () => {
:rows-data="rowsHistoryData" :rows-data="rowsHistoryData"
:visibleColumns="visibleColumnsHistory" :visibleColumns="visibleColumnsHistory"
:columns="columnsHistory" :columns="columnsHistory"
:is-loading="isLoadingHistory"
/> />
</template> </template>
<style scoped> <style scoped>
.absolute_button { .absolute_button {
position: absolute; position: absolute;

View file

@ -1,6 +1,6 @@
<script setup lang="ts"> <script setup lang="ts">
import { useQuasar, type QTableProps } from "quasar";
import { ref, onMounted } from "vue"; import { ref, onMounted } from "vue";
import { useQuasar, type QTableProps } from "quasar";
import http from "@/plugins/http"; import http from "@/plugins/http";
import config from "@/app.config"; import config from "@/app.config";
@ -10,27 +10,26 @@ import { useRegistryDataStore } from "@/modules/10_registry/store/Main";
import type { InsigniaFormType } from "@/modules/10_registry/interface/index/Main"; import type { InsigniaFormType } from "@/modules/10_registry/interface/index/Main";
//history dialog
import DialogHistory from "@/modules/10_registry/Dialog/DialogHistory.vue"; import DialogHistory from "@/modules/10_registry/Dialog/DialogHistory.vue";
import SkeletonTable from "@/components/SkeletonTable.vue";
const link = ref<string>("");
const dataPerson = useDataStore();
const idByRow = ref<string>("");
const rows = ref<InsigniaFormType[]>([]);
const rowsData = ref<InsigniaFormType[]>([]);
const filter = ref<string>("");
const rowsHistory = ref<InsigniaFormType[]>([]);
const rowsHistoryData = ref<InsigniaFormType[]>([]);
const $q = useQuasar(); const $q = useQuasar();
const mode = ref<boolean>($q.screen.gt.xs); const dataPerson = useDataStore();
const mixin = useCounterMixin();
const { showLoader, hideLoader, messageError, date2Thai, onSearchDataTable } =
mixin;
const { getPathUploadFlie } = useRegistryDataStore(); const { getPathUploadFlie } = useRegistryDataStore();
const { showLoader, hideLoader, messageError, date2Thai, onSearchDataTable } =
useCounterMixin();
const modalHistory = ref<boolean>(false); const mode = ref<boolean>($q.screen.gt.xs); //
/** ตัวแปรข้อมูล */ const link = ref<string>(""); //
const isLoading = ref<boolean>(false); //
const isLoadingHistory = ref<boolean>(false); //
const idByRow = ref<string>(""); // id
const rows = ref<InsigniaFormType[]>([]); //
const rowsData = ref<InsigniaFormType[]>([]); //
const filter = ref<string>(""); //
const rowsHistory = ref<InsigniaFormType[]>([]); //
const rowsHistoryData = ref<InsigniaFormType[]>([]); //
const modalHistory = ref<boolean>(false); // / modal
const visibleColumns = ref<String[]>([ const visibleColumns = ref<String[]>([
"insignia", "insignia",
"insigniaType", "insigniaType",
@ -239,7 +238,6 @@ const columns = ref<QTableProps["columns"]>([
const pagination = ref({ const pagination = ref({
sortBy: "lastUpdatedAt", sortBy: "lastUpdatedAt",
}); });
const visibleColumnsHistory = ref<string[]>([ const visibleColumnsHistory = ref<string[]>([
"insignia", "insignia",
"insigniaType", "insigniaType",
@ -433,18 +431,12 @@ const columnsHistory = ref<QTableProps["columns"]>([
a.localeCompare(b, undefined, { numeric: true, sensitivity: "base" }), a.localeCompare(b, undefined, { numeric: true, sensitivity: "base" }),
}, },
]); ]);
const fileGroup = ref<string>("เครื่องราชฯ"); //
const fileGroup = ref<string>("เครื่องราชฯ"); /** ฟังก์ชันสำหรับดึงข้อมูลเครื่องราชฯ */
async function getData() {
function onHistory(id: string) { isLoading.value = true;
modalHistory.value = true; await http
idByRow.value = id;
}
/** get data */
function getData() {
showLoader();
http
.get(config.API.dataUserCertificateByType(link.value, "insignia")) .get(config.API.dataUserCertificateByType(link.value, "insignia"))
.then((res) => { .then((res) => {
const data = res.data.result; const data = res.data.result;
@ -455,14 +447,25 @@ function getData() {
messageError($q, e); messageError($q, e);
}) })
.finally(() => { .finally(() => {
hideLoader(); isLoading.value = false;
}); });
} }
/** get history */ /**
function getHistory() { * งกนสำหรบเป modal ประวการแกไขเครองราชฯ
showLoader(); * @param id ID ของแถวทเลอก
http */
function onHistory(id: string) {
modalHistory.value = true;
idByRow.value = id;
}
/** ฟังก์ชันสำหรับดึงข้อมูลประวัติการแก้ไขเครื่องราชฯ */
async function getHistory() {
isLoadingHistory.value = true;
rowsHistory.value = [];
rowsHistoryData.value = [];
await http
.get( .get(
config.API.dataUserCertificateHistoryByType( config.API.dataUserCertificateHistoryByType(
link.value, link.value,
@ -479,15 +482,28 @@ function getHistory() {
messageError($q, e); messageError($q, e);
}) })
.finally(() => { .finally(() => {
hideLoader(); isLoadingHistory.value = false;
}); });
} }
/**
* งกนสำหรบดาวนโหลดไฟล
* @param id ID ของไฟลองการดาวนโหลด
* @param profileId ID ของโปรไฟล
*/
async function onDownloadFile(id: string, profileId: string) { async function onDownloadFile(id: string, profileId: string) {
const data = await getPathUploadFlie(fileGroup.value, profileId, id); showLoader();
window.open(data.downloadUrl, "_blank"); try {
const data = await getPathUploadFlie(fileGroup.value, profileId, id);
window.open(data.downloadUrl, "_blank");
} catch (error) {
messageError($q, error);
} finally {
hideLoader();
}
} }
/** ฟังก์ชันสำหรับค้นหาข้อมูลในตาราง */
function onSearch() { function onSearch() {
rows.value = onSearchDataTable( rows.value = onSearchDataTable(
filter.value, filter.value,
@ -498,11 +514,10 @@ function onSearch() {
onMounted(async () => { onMounted(async () => {
link.value = await dataPerson.getProFileType(); link.value = await dataPerson.getProFileType();
getData(); await getData();
}); });
</script> </script>
<template> <template>
<!-- v-if="mode" -->
<div class="col-12"> <div class="col-12">
<q-toolbar class="q-px-none q-mt-md"> <q-toolbar class="q-px-none q-mt-md">
<span class="text-blue-6 text-weight-bold text-body1" <span class="text-blue-6 text-weight-bold text-body1"
@ -539,7 +554,10 @@ onMounted(async () => {
:display-value="$q.lang.table.columns" :display-value="$q.lang.table.columns"
/> />
</q-toolbar> </q-toolbar>
<SkeletonTable v-if="isLoading" :columns="columns" />
<d-table <d-table
v-else
flat flat
dense dense
bordered bordered
@ -674,8 +692,10 @@ onMounted(async () => {
:visibleColumns="visibleColumnsHistory" :visibleColumns="visibleColumnsHistory"
:columns="columnsHistory" :columns="columnsHistory"
:type="'insignia'" :type="'insignia'"
:is-loading="isLoadingHistory"
/> />
</template> </template>
<style scoped> <style scoped>
.absolute_button { .absolute_button {
position: absolute; position: absolute;

View file

@ -1,38 +1,36 @@
<script setup lang="ts"> <script setup lang="ts">
import { ref, onMounted } from "vue";
import { useQuasar, type QTableProps } from "quasar"; import { useQuasar, type QTableProps } from "quasar";
import { ref, reactive, onMounted } from "vue";
import http from "@/plugins/http"; import http from "@/plugins/http";
import config from "@/app.config"; import config from "@/app.config";
import { useCounterMixin } from "@/stores/mixin"; import { useCounterMixin } from "@/stores/mixin";
import { useDataStore } from "@/stores/data"; import { useDataStore } from "@/stores/data";
import { useRegistryInFormationStore } from "@/modules/10_registry/store/registry";
import { useRegistryDataStore } from "@/modules/10_registry/store/Main"; import { useRegistryDataStore } from "@/modules/10_registry/store/Main";
import type { HonorFormData } from "@/modules/10_registry/interface/index/Main"; import type { HonorFormData } from "@/modules/10_registry/interface/index/Main";
//history dialog //history dialog
import DialogHistory from "@/modules/10_registry/Dialog/DialogHistory.vue"; import DialogHistory from "@/modules/10_registry/Dialog/DialogHistory.vue";
import SkeletonTable from "@/components/SkeletonTable.vue";
const link = ref<string>("");
const dataPerson = useDataStore();
const idByRow = ref<string>("");
const store = useRegistryInFormationStore();
const rows = ref<HonorFormData[]>([]);
const rowsData = ref<HonorFormData[]>([]);
const filter = ref<string>("");
const rowsHistory = ref<HonorFormData[]>([]);
const rowsHistoryData = ref<HonorFormData[]>([]);
const $q = useQuasar(); const $q = useQuasar();
const mode = ref<boolean>($q.screen.gt.xs); const dataPerson = useDataStore();
const mixin = useCounterMixin();
const { showLoader, hideLoader, messageError, date2Thai, onSearchDataTable } =
mixin;
const { getPathUploadFlie } = useRegistryDataStore(); const { getPathUploadFlie } = useRegistryDataStore();
const { showLoader, hideLoader, messageError, date2Thai, onSearchDataTable } =
useCounterMixin();
const modalHistory = ref<boolean>(false); const mode = ref<boolean>($q.screen.gt.xs); //
/** ตัวแปรข้อมูล */ const link = ref<string>(""); //
const isLoading = ref<boolean>(false); //
const isLoadingHistory = ref<boolean>(false); //
const rows = ref<HonorFormData[]>([]); //
const rowsData = ref<HonorFormData[]>([]); //
const filter = ref<string>(""); //
const idByRow = ref<string>(""); // id
const rowsHistory = ref<HonorFormData[]>([]); //
const rowsHistoryData = ref<HonorFormData[]>([]); //
const modalHistory = ref<boolean>(false); // / modal
const visibleColumns = ref<String[]>([ const visibleColumns = ref<String[]>([
"issuer", "issuer",
"detail", "detail",
@ -127,7 +125,6 @@ const columns = ref<QTableProps["columns"]>([
const pagination = ref({ const pagination = ref({
sortBy: "lastUpdatedAt", sortBy: "lastUpdatedAt",
}); });
const visibleColumnsHistory = ref<string[]>([ const visibleColumnsHistory = ref<string[]>([
"issuer", "issuer",
"detail", "detail",
@ -219,18 +216,12 @@ const columnsHistory = ref<QTableProps["columns"]>([
a.localeCompare(b, undefined, { numeric: true, sensitivity: "base" }), a.localeCompare(b, undefined, { numeric: true, sensitivity: "base" }),
}, },
]); ]);
const fileGroup = ref<string>("ประกาศเกียรติคุณ"); //
const fileGroup = ref<string>("ประกาศเกียรติคุณ"); /** ฟังก์ชันสำหรับดึงข้อมูลประกาศเกียรติคุณ */
async function getData() {
function onHistory(id: string) { isLoading.value = true;
modalHistory.value = true; await http
idByRow.value = id;
}
/** get data */
function getData() {
showLoader();
http
.get(config.API.dataUserCertificateByType(link.value, "honor")) .get(config.API.dataUserCertificateByType(link.value, "honor"))
.then((res) => { .then((res) => {
const data = res.data.result; const data = res.data.result;
@ -241,18 +232,30 @@ function getData() {
messageError($q, e); messageError($q, e);
}) })
.finally(() => { .finally(() => {
hideLoader(); isLoading.value = false;
}); });
} }
/**
* เป modal ประวการแกไข
* @param id ID ของแถวทเลอก
*/
function onHistory(id: string) {
modalHistory.value = true;
idByRow.value = id;
}
/** get history */ /** get history */
function getHistory() { async function getHistory() {
isLoadingHistory.value = true;
rowsHistory.value = [];
rowsHistoryData.value = [];
const url = const url =
dataPerson.officerType == "OFFICER" dataPerson.officerType == "OFFICER"
? config.API.dataUserHonorHistory("honor", "", idByRow.value) ? config.API.dataUserHonorHistory("honor", "", idByRow.value)
: config.API.dataUserHonorHistory("honor", "-employee", idByRow.value); : config.API.dataUserHonorHistory("honor", "-employee", idByRow.value);
showLoader();
http await http
.get(url) .get(url)
.then((res) => { .then((res) => {
const data = res.data.result; const data = res.data.result;
@ -263,15 +266,28 @@ function getHistory() {
messageError($q, e); messageError($q, e);
}) })
.finally(() => { .finally(() => {
hideLoader(); isLoadingHistory.value = false;
}); });
} }
/**
* งกนสำหรบดาวนโหลดไฟล
* @param id ID ของไฟลองการดาวนโหลด
* @param profileId id ของโปรไฟล
*/
async function onDownloadFile(id: string, profileId: string) { async function onDownloadFile(id: string, profileId: string) {
const data = await getPathUploadFlie(fileGroup.value, profileId, id); showLoader();
window.open(data.downloadUrl, "_blank"); try {
const data = await getPathUploadFlie(fileGroup.value, profileId, id);
window.open(data.downloadUrl, "_blank");
} catch (error) {
messageError($q, error);
} finally {
hideLoader();
}
} }
/** ฟังก์ชันสำหรับค้นหาข้อมูลในตาราง */
function onSearch() { function onSearch() {
rows.value = onSearchDataTable( rows.value = onSearchDataTable(
filter.value, filter.value,
@ -282,11 +298,10 @@ function onSearch() {
onMounted(async () => { onMounted(async () => {
link.value = await dataPerson.getProFileType(); link.value = await dataPerson.getProFileType();
getData(); await getData();
}); });
</script> </script>
<template> <template>
<!-- v-if="mode" -->
<div class="col-12"> <div class="col-12">
<q-toolbar class="q-px-none q-mt-md"> <q-toolbar class="q-px-none q-mt-md">
<span class="text-blue-6 text-weight-bold text-body1" <span class="text-blue-6 text-weight-bold text-body1"
@ -323,7 +338,10 @@ onMounted(async () => {
:display-value="$q.lang.table.columns" :display-value="$q.lang.table.columns"
/> />
</q-toolbar> </q-toolbar>
<SkeletonTable v-if="isLoading" :columns="columns" />
<d-table <d-table
v-else
flat flat
dense dense
bordered bordered
@ -445,6 +463,7 @@ onMounted(async () => {
:rows-data="rowsHistoryData" :rows-data="rowsHistoryData"
:visibleColumns="visibleColumnsHistory" :visibleColumns="visibleColumnsHistory"
:columns="columnsHistory" :columns="columnsHistory"
:is-loading="isLoadingHistory"
/> />
</template> </template>
<style scoped> <style scoped>

View file

@ -1,6 +1,6 @@
<script setup lang="ts"> <script setup lang="ts">
import { ref, onMounted } from "vue";
import { useQuasar, type QTableProps } from "quasar"; import { useQuasar, type QTableProps } from "quasar";
import { ref, reactive, onMounted } from "vue";
import http from "@/plugins/http"; import http from "@/plugins/http";
import config from "@/app.config"; import config from "@/app.config";
@ -12,31 +12,28 @@ import type {
DataOption, DataOption,
} from "@/modules/10_registry/interface/index/Main"; } from "@/modules/10_registry/interface/index/Main";
//history dialog
import DialogHistory from "@/modules/10_registry/Dialog/DialogHistory.vue"; import DialogHistory from "@/modules/10_registry/Dialog/DialogHistory.vue";
import SkeletonTable from "@/components/SkeletonTable.vue";
const link = ref<string>("");
const dataPerson = useDataStore();
const idByRow = ref<string>("");
const rows = ref<AssessmentsFormType[]>([]);
const rowsData = ref<AssessmentsFormType[]>([]);
const filter = ref<string>("");
const rowsHistory = ref<AssessmentsFormType[]>([]);
const rowsHistoryData = ref<AssessmentsFormType[]>([]);
const $q = useQuasar(); const $q = useQuasar();
const mode = ref<boolean>($q.screen.gt.xs); const dataPerson = useDataStore();
const mixin = useCounterMixin(); const { messageError, date2Thai, onSearchDataTable } = useCounterMixin();
const { showLoader, hideLoader, messageError, date2Thai, onSearchDataTable } =
mixin;
const mode = ref<boolean>($q.screen.gt.xs); //
const link = ref<string>(""); //
const rows = ref<AssessmentsFormType[]>([]); //
const rowsData = ref<AssessmentsFormType[]>([]); //
const filter = ref<string>(""); //
const idByRow = ref<string>(""); // id
const rowsHistory = ref<AssessmentsFormType[]>([]); //
const rowsHistoryData = ref<AssessmentsFormType[]>([]); //
const isLoading = ref<boolean>(false); //
const isLoadingHistory = ref<boolean>(false); //
const periodOp = ref<DataOption[]>([ const periodOp = ref<DataOption[]>([
{ id: "OCT", name: "ตุลาคม" }, { id: "OCT", name: "ตุลาคม" },
{ id: "APR", name: "เมษายน" }, { id: "APR", name: "เมษายน" },
]); ]);
const modalHistory = ref<boolean>(false); // modal
const modalHistory = ref<boolean>(false);
/** ตัวแปรข้อมูล */
const columns = ref<QTableProps["columns"]>([ const columns = ref<QTableProps["columns"]>([
{ {
name: "date", name: "date",
@ -328,7 +325,6 @@ const visibleColumnsHistory = ref<string[]>([
const pagination = ref({ const pagination = ref({
sortBy: "lastUpdatedAt", sortBy: "lastUpdatedAt",
}); });
const visibleColumns = ref<string[]>([ const visibleColumns = ref<string[]>([
"point1Total", "point1Total",
"year", "year",
@ -344,15 +340,10 @@ const visibleColumns = ref<string[]>([
"lastUpdatedAt", "lastUpdatedAt",
]); ]);
function onHistory(id: string) { /** ฟังก์ชันดึงข้อมูล */
modalHistory.value = true; async function getData() {
idByRow.value = id; isLoading.value = true;
} await http
/** get data */
function getData() {
showLoader();
http
.get(config.API.dataUserCertificateByType(link.value, "assessments")) .get(config.API.dataUserCertificateByType(link.value, "assessments"))
.then((res) => { .then((res) => {
const data = res.data.result; const data = res.data.result;
@ -363,14 +354,25 @@ function getData() {
messageError($q, e); messageError($q, e);
}) })
.finally(() => { .finally(() => {
hideLoader(); isLoading.value = false;
}); });
} }
/** get history */ /**
function getHistory() { * งกนเป modal ประวการแกไข
showLoader(); * @param id - id ของแถวทเลอก
http */
function onHistory(id: string) {
modalHistory.value = true;
idByRow.value = id;
}
/** ฟังก์ชันดึงข้อมูลประวัติการแก้ไข */
async function getHistory() {
isLoadingHistory.value = true;
rowsHistory.value = [];
rowsHistoryData.value = [];
await http
.get( .get(
config.API.dataUserCertificateHistoryByType( config.API.dataUserCertificateHistoryByType(
link.value, link.value,
@ -387,10 +389,14 @@ function getHistory() {
messageError($q, e); messageError($q, e);
}) })
.finally(() => { .finally(() => {
hideLoader(); isLoadingHistory.value = false;
}); });
} }
/**
* งกนตรวจสอบชวงคะแนน
* @param val - าทองการตรวจสอบ
*/
function textRangePoint(val: number | undefined) { function textRangePoint(val: number | undefined) {
if (val == undefined) val = -1; if (val == undefined) val = -1;
if (val < 60.0) return "(คะแนนต่ำกว่าร้อยละ 60.00)"; if (val < 60.0) return "(คะแนนต่ำกว่าร้อยละ 60.00)";
@ -401,6 +407,10 @@ function textRangePoint(val: number | undefined) {
else return ""; else return "";
} }
/**
* งกนตรวจสอบคะแนน
* @param val - าทองการตรวจสอบ
*/
function textPoint(val: number | undefined) { function textPoint(val: number | undefined) {
if (val == undefined) val = -1; if (val == undefined) val = -1;
if (val < 60.0) return "ต้องปรับปรุง"; if (val < 60.0) return "ต้องปรับปรุง";
@ -440,6 +450,7 @@ onMounted(async () => {
v-model="filter" v-model="filter"
label="ค้นหา" label="ค้นหา"
style="max-width: 200px" style="max-width: 200px"
@keydown.enter.prevent="onSearch"
> >
<template v-slot:append> <template v-slot:append>
<q-icon name="search" /> <q-icon name="search" />
@ -461,7 +472,10 @@ onMounted(async () => {
:display-value="$q.lang.table.columns" :display-value="$q.lang.table.columns"
/> />
</q-toolbar> </q-toolbar>
<SkeletonTable v-if="isLoading" :columns="columns" />
<d-table <d-table
v-else
flat flat
dense dense
bordered bordered
@ -545,6 +559,7 @@ onMounted(async () => {
</template> </template>
</d-table> </d-table>
</div> </div>
<DialogHistory <DialogHistory
v-model:modal="modalHistory" v-model:modal="modalHistory"
:title="'ประวัติแก้ไขผลการประเมินการปฏิบัติราชการ'" :title="'ประวัติแก้ไขผลการประเมินการปฏิบัติราชการ'"
@ -553,8 +568,10 @@ onMounted(async () => {
:rows-data="rowsHistoryData" :rows-data="rowsHistoryData"
:visibleColumns="visibleColumnsHistory" :visibleColumns="visibleColumnsHistory"
:columns="columnsHistory" :columns="columnsHistory"
:is-loading="isLoadingHistory"
/> />
</template> </template>
<style scoped> <style scoped>
.absolute_button { .absolute_button {
position: absolute; position: absolute;

View file

@ -1,34 +1,28 @@
<script setup lang="ts"> <script setup lang="ts">
import { useCounterMixin } from "@/stores/mixin"; import { ref, onMounted } from "vue";
import { useQuasar, type QTableProps } from "quasar"; import { useQuasar, type QTableProps } from "quasar";
import { ref, reactive, onMounted } from "vue";
import http from "@/plugins/http"; import http from "@/plugins/http";
import config from "@/app.config"; import config from "@/app.config";
import { useCounterMixin } from "@/stores/mixin";
import { useDataStore } from "@/stores/data"; import { useDataStore } from "@/stores/data";
import DialogDevelop from "@/modules/10_registry/Dialog/DialogDevelopmant.vue"; import DialogDevelop from "@/modules/10_registry/Dialog/DialogDevelopmant.vue";
import SkeletonTable from "@/components/SkeletonTable.vue";
const typeIDP = ref<string>("");
const link = ref<string>("");
const dataPerson = useDataStore();
const idByRow = ref<string>("");
const rows = ref<any[]>([]);
const rowsData = ref<any[]>([]);
const filter = ref<string>("");
const rowsHistory = ref<any[]>([]);
const rowsHistoryData = ref<any[]>([]);
const $q = useQuasar(); const $q = useQuasar();
const mode = ref<boolean>($q.screen.gt.xs); const dataPerson = useDataStore();
const mixin = useCounterMixin(); const { messageError, date2Thai, onSearchDataTable } = useCounterMixin();
const { showLoader, hideLoader, messageError, date2Thai, onSearchDataTable } =
mixin;
const modalDevelop = ref<boolean>(false);
const kpiDevelopmentId = ref<string>("");
const modalHistory = ref<boolean>(false);
/** ตัวแปรข้อมูล */
const mode = ref<boolean>($q.screen.gt.xs); //
const typeIDP = ref<string>(""); //
const link = ref<string>(""); //
const isLoading = ref<boolean>(false); //
const rows = ref<any[]>([]); //
const rowsData = ref<any[]>([]); //
const filter = ref<string>(""); //
const modalDevelop = ref<boolean>(false); // / Dialog
const kpiDevelopmentId = ref<string>(""); // ID
const visibleColumns = ref<string[]>([ const visibleColumns = ref<string[]>([
"no", "no",
"name", "name",
@ -39,7 +33,6 @@ const visibleColumns = ref<string[]>([
"lastUpdateFullName", "lastUpdateFullName",
"lastUpdatedAt", "lastUpdatedAt",
]); ]);
const columns = ref<QTableProps["columns"]>([ const columns = ref<QTableProps["columns"]>([
{ {
name: "no", name: "no",
@ -130,21 +123,15 @@ const columns = ref<QTableProps["columns"]>([
a.localeCompare(b, undefined, { numeric: true, sensitivity: "base" }), a.localeCompare(b, undefined, { numeric: true, sensitivity: "base" }),
}, },
]); ]);
const paginationPlan = ref({ const paginationPlan = ref({
page: 1, page: 1,
rowsPerPage: 10, rowsPerPage: 10,
}); });
function onHistory(id: string) { /** ฟังก์ชันดึงข้อมูล */
modalHistory.value = true; async function getData() {
idByRow.value = id; isLoading.value = true;
} await http
/** get data */
function getData() {
showLoader();
http
.get(config.API.developmentUserByType(link.value)) .get(config.API.developmentUserByType(link.value))
.then((res) => { .then((res) => {
const data = res.data.result; const data = res.data.result;
@ -155,31 +142,7 @@ function getData() {
messageError($q, e); messageError($q, e);
}) })
.finally(() => { .finally(() => {
hideLoader(); isLoading.value = false;
});
}
/** get history */
function getHistory() {
showLoader();
http
.get(
config.API.dataUserCertificateHistoryByType(
link.value,
"assessments",
idByRow.value
)
)
.then((res) => {
const data = res.data.result;
rowsHistory.value = data;
rowsHistoryData.value = data;
})
.catch((e) => {
messageError($q, e);
})
.finally(() => {
hideLoader();
}); });
} }
@ -193,6 +156,7 @@ function openDialogDevelop(data: any) {
typeIDP.value = data.type; typeIDP.value = data.type;
} }
/** ฟังก์ชันค้นหาข้อมูล */
function onSearch() { function onSearch() {
rows.value = onSearchDataTable( rows.value = onSearchDataTable(
filter.value, filter.value,
@ -203,12 +167,13 @@ function onSearch() {
onMounted(async () => { onMounted(async () => {
link.value = await dataPerson.getProFileType(); link.value = await dataPerson.getProFileType();
getData(); await getData();
}); });
</script> </script>
<template> <template>
<!-- v-if="mode" --> <!-- v-if="mode" -->
<div class="col-12" v-if="dataPerson.officerType == 'OFFICER'"> <!-- v-if="dataPerson.officerType == 'OFFICER'" -->
<div class="col-12">
<q-toolbar class="q-px-none q-mt-md"> <q-toolbar class="q-px-none q-mt-md">
<span class="text-blue-6 text-weight-bold text-body1" <span class="text-blue-6 text-weight-bold text-body1"
>การพฒนารายบคคล (Individual Development Plan)</span >การพฒนารายบคคล (Individual Development Plan)</span
@ -244,7 +209,9 @@ onMounted(async () => {
:display-value="$q.lang.table.columns" :display-value="$q.lang.table.columns"
/> />
</q-toolbar> </q-toolbar>
<SkeletonTable v-if="isLoading" :columns="columns" />
<d-table <d-table
v-else
flat flat
dense dense
bordered bordered

View file

@ -1,5 +1,5 @@
<script setup lang="ts"> <script setup lang="ts">
import { useQuasar, type QTableProps } from "quasar"; import { is, useQuasar, type QTableProps } from "quasar";
import { ref, onMounted } from "vue"; import { ref, onMounted } from "vue";
import http from "@/plugins/http"; import http from "@/plugins/http";
@ -9,16 +9,16 @@ import { useDataStore } from "@/stores/data";
import type { OtherFormType } from "@/modules/10_registry/interface/index/Main"; import type { OtherFormType } from "@/modules/10_registry/interface/index/Main";
//history dialog
import DialogHistory from "@/modules/10_registry/Dialog/DialogHistory.vue"; import DialogHistory from "@/modules/10_registry/Dialog/DialogHistory.vue";
import SkeletonTable from "@/components/SkeletonTable.vue";
const $q = useQuasar();
const dataPerson = useDataStore();
const { messageError, date2Thai, onSearchDataTable } = useCounterMixin();
const link = ref<string>(""); const link = ref<string>("");
const $q = useQuasar(); const isLoading = ref<boolean>(false);
const mixin = useCounterMixin(); const isLoadingHistory = ref<boolean>(false);
const dataPerson = useDataStore();
const { showLoader, hideLoader, messageError, date2Thai, onSearchDataTable } =
mixin;
const idByRow = ref<string>(""); const idByRow = ref<string>("");
const rows = ref<OtherFormType[]>([]); const rows = ref<OtherFormType[]>([]);
const rowsData = ref<OtherFormType[]>([]); const rowsData = ref<OtherFormType[]>([]);
@ -26,10 +26,7 @@ const filter = ref<string>("");
const rowsHistory = ref<OtherFormType[]>([]); const rowsHistory = ref<OtherFormType[]>([]);
const rowsHistoryData = ref<OtherFormType[]>([]); const rowsHistoryData = ref<OtherFormType[]>([]);
const mode = ref<boolean>($q.screen.gt.xs); const mode = ref<boolean>($q.screen.gt.xs);
const modalHistory = ref<boolean>(false); const modalHistory = ref<boolean>(false);
/** ตัวแปรข้อมูล */
const visibleColumns = ref<string[]>([ const visibleColumns = ref<string[]>([
"date", "date",
"detail", "detail",
@ -85,7 +82,6 @@ const columns = ref<QTableProps["columns"]>([
const pagination = ref({ const pagination = ref({
sortBy: "lastUpdatedAt", sortBy: "lastUpdatedAt",
}); });
const visibleColumnsHistory = ref<string[]>([ const visibleColumnsHistory = ref<string[]>([
"date", "date",
"detail", "detail",
@ -139,15 +135,10 @@ const columnsHistory = ref<QTableProps["columns"]>([
}, },
]); ]);
function onHistory(id: string) { /** ฟังก์ชันดึงข้อมูล */
modalHistory.value = true; async function getData() {
idByRow.value = id; isLoading.value = true;
} await http
/** get data */
function getData() {
showLoader();
http
.get(config.API.dataUserOtherByType(link.value)) .get(config.API.dataUserOtherByType(link.value))
.then((res) => { .then((res) => {
const data = res.data.result; const data = res.data.result;
@ -156,14 +147,27 @@ function getData() {
}) })
.catch((e) => { .catch((e) => {
messageError($q, e); messageError($q, e);
hideLoader(); })
.finally(() => {
isLoading.value = false;
}); });
} }
/** get history */ /**
function getHistory() { * งกนเปดโมดลดประว
showLoader(); * @param id ID ของแถวทองการดประว
http */
function onHistory(id: string) {
modalHistory.value = true;
idByRow.value = id;
}
/** ฟังก์ชันดึงประวัติการแก้ไขข้อมูลอื่นๆ */
async function getHistory() {
isLoadingHistory.value = true;
rowsHistory.value = [];
rowsHistoryData.value = [];
await http
.get(config.API.dataUserOtherHistoryByType(link.value, idByRow.value)) .get(config.API.dataUserOtherHistoryByType(link.value, idByRow.value))
.then((res) => { .then((res) => {
const data = res.data.result; const data = res.data.result;
@ -174,10 +178,11 @@ function getHistory() {
messageError($q, e); messageError($q, e);
}) })
.finally(() => { .finally(() => {
hideLoader(); isLoadingHistory.value = false;
}); });
} }
/** ฟังก์ชันค้นหาข้อมูลในตาราง */
function onSearch() { function onSearch() {
rows.value = onSearchDataTable( rows.value = onSearchDataTable(
filter.value, filter.value,
@ -188,11 +193,10 @@ function onSearch() {
onMounted(async () => { onMounted(async () => {
link.value = await dataPerson.getProFileType(); link.value = await dataPerson.getProFileType();
getData(); await getData();
}); });
</script> </script>
<template> <template>
<!-- v-if="mode" -->
<div class="col-12"> <div class="col-12">
<q-toolbar class="q-px-none"> <q-toolbar class="q-px-none">
<span class="text-blue-6 text-weight-bold text-body1">อมลอนๆ</span> <span class="text-blue-6 text-weight-bold text-body1">อมลอนๆ</span>
@ -227,7 +231,10 @@ onMounted(async () => {
:display-value="$q.lang.table.columns" :display-value="$q.lang.table.columns"
/> />
</q-toolbar> </q-toolbar>
<SkeletonTable v-if="isLoading" :columns="columns" />
<d-table <d-table
v-else
flat flat
dense dense
bordered bordered
@ -310,6 +317,7 @@ onMounted(async () => {
</template> </template>
</d-table> </d-table>
</div> </div>
<DialogHistory <DialogHistory
v-model:modal="modalHistory" v-model:modal="modalHistory"
:title="'ประวัติแก้ไขข้อมูลอื่นๆ'" :title="'ประวัติแก้ไขข้อมูลอื่นๆ'"
@ -318,6 +326,7 @@ onMounted(async () => {
:rows-data="rowsHistoryData" :rows-data="rowsHistoryData"
:visibleColumns="visibleColumnsHistory" :visibleColumns="visibleColumnsHistory"
:columns="columnsHistory" :columns="columnsHistory"
:is-loading="isLoadingHistory"
/> />
</template> </template>
<style scoped> <style scoped>

View file

@ -1,7 +1,7 @@
<script setup lang="ts"> <script setup lang="ts">
import { useCounterMixin } from "@/stores/mixin"; import { useCounterMixin } from "@/stores/mixin";
import { useQuasar, type QTableProps } from "quasar"; import { is, useQuasar } from "quasar";
import { ref, reactive, onMounted } from "vue"; import { ref, onMounted } from "vue";
import http from "@/plugins/http"; import http from "@/plugins/http";
import config from "@/app.config"; import config from "@/app.config";
@ -9,23 +9,17 @@ import { useRegistryInFormationStore } from "@/modules/10_registry/store/registr
import type { FileFormType } from "@/modules/10_registry/interface/index/Main"; import type { FileFormType } from "@/modules/10_registry/interface/index/Main";
const fileList = ref<FileFormType[]>([]);
const store = useRegistryInFormationStore();
const $q = useQuasar(); const $q = useQuasar();
const mixin = useCounterMixin(); const store = useRegistryInFormationStore();
const { showLoader, hideLoader, messageError, date2Thai } = mixin; const { showLoader, hideLoader, messageError } = useCounterMixin();
const modalHistory = ref<boolean>(false); const isLoading = ref<boolean>(false);
/** ตัวแปรข้อมูล */ const fileList = ref<FileFormType[]>([]);
function onHistory() { /** ฟังก์ชันดึงข้อมูลไฟล์ */
modalHistory.value = true; async function getData() {
} isLoading.value = true;
await http
/** get data */
function getData() {
showLoader();
http
.get( .get(
config.API.fileByFileUser( config.API.fileByFileUser(
"ระบบทะเบียนประวัติ", "ระบบทะเบียนประวัติ",
@ -41,9 +35,7 @@ function getData() {
messageError($q, e); messageError($q, e);
}) })
.finally(() => { .finally(() => {
setTimeout(() => { isLoading.value = false;
hideLoader();
}, 1500);
}); });
} }
@ -51,9 +43,9 @@ function getData() {
* ดาวนโหลดลงคไฟล * ดาวนโหลดลงคไฟล
* @param fileName file name * @param fileName file name
*/ */
function downloadFile(fileName: string) { async function downloadFile(fileName: string) {
showLoader(); showLoader();
http await http
.get( .get(
config.API.fileByFile( config.API.fileByFile(
"ระบบทะเบียนประวัติ", "ระบบทะเบียนประวัติ",
@ -69,7 +61,7 @@ function downloadFile(fileName: string) {
.catch((e) => { .catch((e) => {
messageError($q, e); messageError($q, e);
}) })
.finally(async () => { .finally(() => {
hideLoader(); hideLoader();
}); });
} }
@ -78,8 +70,8 @@ onMounted(() => {
getData(); getData();
}); });
</script> </script>
<template> <template>
<!-- v-if="mode" -->
<div class="col-12"> <div class="col-12">
<q-toolbar class="q-px-none q-mt-md"> <q-toolbar class="q-px-none q-mt-md">
<span class="text-blue-6 text-weight-bold text-body1">เอกสารหลกฐาน</span> <span class="text-blue-6 text-weight-bold text-body1">เอกสารหลกฐาน</span>
@ -89,7 +81,12 @@ onMounted(() => {
ไฟลเอกสารหลกฐาน ไฟลเอกสารหลกฐาน
</div> </div>
<div class="col-12"><q-separator /></div> <div class="col-12"><q-separator /></div>
<div class="row col-12 q-col-gutter-y-sm q-pa-sm">
<div v-if="isLoading" class="col-12 q-pa-sm">
<q-skeleton type="QSlider" />
</div>
<div v-else class="row col-12 q-col-gutter-y-sm q-pa-sm">
<div v-if="fileList.length > 0" class="col-xs-12 row"> <div v-if="fileList.length > 0" class="col-xs-12 row">
<q-list class="full-width rounded-borders" bordered separator> <q-list class="full-width rounded-borders" bordered separator>
<q-item <q-item
@ -124,6 +121,7 @@ onMounted(() => {
</q-card> </q-card>
</div> </div>
</template> </template>
<style scoped> <style scoped>
.absolute_button { .absolute_button {
position: absolute; position: absolute;

View file

@ -9,23 +9,17 @@ import { useRegistryInFormationStore } from "@/modules/10_registry/store/registr
import type { FileFormType } from "@/modules/10_registry/interface/index/Main"; import type { FileFormType } from "@/modules/10_registry/interface/index/Main";
const fileList = ref<FileFormType[]>([]);
const store = useRegistryInFormationStore();
const $q = useQuasar(); const $q = useQuasar();
const mixin = useCounterMixin(); const store = useRegistryInFormationStore();
const { showLoader, hideLoader, messageError, date2Thai } = mixin; const { showLoader, hideLoader, messageError } = useCounterMixin();
const modalHistory = ref<boolean>(false); const isLoading = ref<boolean>(false);
/** ตัวแปรข้อมูล */ const fileList = ref<FileFormType[]>([]);
function onHistory() { /** ฟังก์ชันดึงข้อมูลไฟล์ */
modalHistory.value = true; async function getData() {
} isLoading.value = true;
await http
/** get data */
function getData() {
showLoader();
http
.get( .get(
config.API.fileByFileUser( config.API.fileByFileUser(
"ระบบทะเบียนประวัติ", "ระบบทะเบียนประวัติ",
@ -41,9 +35,7 @@ function getData() {
messageError($q, e); messageError($q, e);
}) })
.finally(() => { .finally(() => {
setTimeout(() => { isLoading.value = false;
hideLoader();
}, 1500);
}); });
} }
@ -51,9 +43,9 @@ function getData() {
* ดาวนโหลดลงคไฟล * ดาวนโหลดลงคไฟล
* @param fileName file name * @param fileName file name
*/ */
function downloadFile(fileName: string) { async function downloadFile(fileName: string) {
showLoader(); showLoader();
http await http
.get( .get(
config.API.fileByFile( config.API.fileByFile(
"ระบบทะเบียนประวัติ", "ระบบทะเบียนประวัติ",
@ -69,7 +61,7 @@ function downloadFile(fileName: string) {
.catch((e) => { .catch((e) => {
messageError($q, e); messageError($q, e);
}) })
.finally(async () => { .finally(() => {
hideLoader(); hideLoader();
}); });
} }
@ -89,7 +81,11 @@ onMounted(() => {
ไฟลเอกสาร ..7 ไฟลเอกสาร ..7
</div> </div>
<div class="col-12"><q-separator /></div> <div class="col-12"><q-separator /></div>
<div class="row col-12 q-col-gutter-y-sm q-pa-sm"> <div v-if="isLoading" class="col-12 q-pa-sm">
<q-skeleton type="QSlider" />
</div>
<div v-else class="row col-12 q-col-gutter-y-sm q-pa-sm">
<div v-if="fileList.length > 0" class="col-xs-12 row"> <div v-if="fileList.length > 0" class="col-xs-12 row">
<q-list class="full-width rounded-borders" bordered separator> <q-list class="full-width rounded-borders" bordered separator>
<q-item <q-item

View file

@ -1,35 +1,48 @@
<script setup lang="ts"> <script setup lang="ts">
import { ref, watch } from "vue"; import { ref, watch } from "vue";
import DialogHeader from "@/components/DialogHeader.vue";
import type { QTableProps } from "quasar";
import { useCounterMixin } from "@/stores/mixin"; import { useCounterMixin } from "@/stores/mixin";
const type = ref<string>(""); /** import type */
const mixin = useCounterMixin(); import type { QTableProps } from "quasar";
const { date2Thai, onSearchDataTable, findOrgNameHtml } = mixin;
const modal = defineModel<boolean>("modal", { required: true });
const title = defineModel<string>("title", { required: true });
const filter = ref<string>(""); /** import component */
import DialogHeader from "@/components/DialogHeader.vue";
import SkeletonTable from "@/components/SkeletonTable.vue";
const rows = defineModel<any>("rows"); const { date2Thai, onSearchDataTable, findOrgNameHtml } = useCounterMixin();
const rowsData = defineModel<any>("rowsData");
const columns = defineModel<QTableProps["columns"]>("columns"); /** define model */
const visibleColumns = defineModel<string[]>("visibleColumns"); const modal = defineModel<boolean>("modal", { required: true }); // modal visibility
const isLoading = defineModel<boolean>("isLoading", { required: true }); // loading state
const title = defineModel<string>("title", { required: true }); // dialog title
const rows = defineModel<any[]>("rows"); // data rows for the table
const rowsData = defineModel<any[]>("rowsData"); // raw data for the table
const columns = defineModel<QTableProps["columns"]>("columns"); // table columns definition
const visibleColumns = defineModel<string[]>("visibleColumns"); // visible columns in the table
/** define props */
const props = defineProps({
getData: Function, // function to fetch data
type: String, // type of data (e.g., "Leave", "insignia")
});
const type = ref<string>(""); //
const filter = ref<string>(""); // filter input for searching
const pagination = ref({ const pagination = ref({
sortBy: "lastUpdatedAt", sortBy: "lastUpdatedAt",
}); });
const props = defineProps({ /** ปิด Dialog และรีเซ็ตค่า */
getData: Function,
type: String,
});
function close() { function close() {
modal.value = false; modal.value = false;
filter.value = ""; filter.value = "";
} }
/**
* งกนแปลงวนทเปนรปแบบไทย
* @param val - date range value
*/
function dateThaiRange(val: [Date, Date]) { function dateThaiRange(val: [Date, Date]) {
if (val === null) { if (val === null) {
} else if (date2Thai(val[0]) === date2Thai(val[1])) { } else if (date2Thai(val[0]) === date2Thai(val[1])) {
@ -39,6 +52,10 @@ function dateThaiRange(val: [Date, Date]) {
} }
} }
/**
* งกนแปลงสถานะการลาเปนขอความท
* @param val สถานะการลา
*/
function statusLeave(val: string) { function statusLeave(val: string) {
switch (val) { switch (val) {
case "waitting": case "waitting":
@ -54,10 +71,11 @@ function statusLeave(val: string) {
} }
} }
/** ฟังก์ชันค้นหาข้อมูลในตาราง */
function onSearch() { function onSearch() {
rows.value = onSearchDataTable( rows.value = onSearchDataTable(
filter.value, filter.value,
rowsData.value, rowsData.value ? rowsData.value : [],
columns.value ? columns.value : [] columns.value ? columns.value : []
); );
} }
@ -111,141 +129,148 @@ watch(
/> />
</div> </div>
</div> </div>
<div v-if="isLoading">
<SkeletonTable :columns="columns" />
</div>
<d-table <div v-else class="col-12">
flat <d-table
dense flat
bordered dense
virtual-scroll bordered
:rows="rows" virtual-scroll
:columns="columns" :rows="rows"
:rows-per-page-options="[10, 25, 50, 100]" :columns="columns"
:visible-columns="visibleColumns" :rows-per-page-options="[10, 25, 50, 100]"
:virtual-scroll-sticky-size-start="48" :visible-columns="visibleColumns"
v-model:pagination="pagination" :virtual-scroll-sticky-size-start="48"
> v-model:pagination="pagination"
<template v-slot:header="props"> >
<q-tr :props="props"> <template v-slot:header="props">
<q-th v-for="col in props.cols" :key="col.name" :props="props"> <q-tr :props="props">
<span class="text-weight-medium">{{ col.label }}</span> <q-th v-for="col in props.cols" :key="col.name" :props="props">
</q-th> <span class="text-weight-medium">{{ col.label }}</span>
</q-tr> </q-th>
</template> </q-tr>
</template>
<template v-slot:body="props"> <template v-slot:body="props">
<q-tr :props="props" class="cursor-pointer"> <q-tr :props="props" class="cursor-pointer">
<q-td v-for="(col, index) in props.cols" :key="col.name"> <q-td v-for="(col, index) in props.cols" :key="col.name">
<div v-if="col.name == 'no'"> <div v-if="col.name == 'no'">
{{ props.rowIndex + 1 }} {{ props.rowIndex + 1 }}
</div> </div>
<div v-else-if="col.name == 'insignia' && type == 'insignia'"> <div v-else-if="col.name == 'insignia' && type == 'insignia'">
{{ props.row.insignia ? `${props.row.insignia.name} ` : "-" {{ props.row.insignia ? `${props.row.insignia.name} ` : "-"
}}{{ }}{{
props.row.insignia.shortName props.row.insignia.shortName
? `(${props.row.insignia.shortName})` ? `(${props.row.insignia.shortName})`
: "" : ""
}} }}
</div> </div>
<div v-else-if="col.name == 'dateLeave' && type == 'Leave'"> <div v-else-if="col.name == 'dateLeave' && type == 'Leave'">
{{ {{
dateThaiRange([ dateThaiRange([
props.row.dateStartLeave, props.row.dateStartLeave,
props.row.dateEndLeave, props.row.dateEndLeave,
]) ])
}} }}
</div> </div>
<div v-else-if="col.name == 'status' && type == 'Leave'"> <div v-else-if="col.name == 'status' && type == 'Leave'">
{{ props.row.status ? statusLeave(props.row.status) : "-" }} {{ props.row.status ? statusLeave(props.row.status) : "-" }}
</div> </div>
<div v-else-if="col.name == 'organization'"> <div v-else-if="col.name == 'organization'">
{{ {{
props.row props.row
? findOrgNameHtml({ ? findOrgNameHtml({
root: props.row.orgRoot, root: props.row.orgRoot,
child1: props.row.orgChild1, child1: props.row.orgChild1,
child2: props.row.orgChild2, child2: props.row.orgChild2,
child3: props.row.orgChild3, child3: props.row.orgChild3,
child4: props.row.orgChild4, child4: props.row.orgChild4,
}) })
: "-" : "-"
}} }}
</div> </div>
<div v-else> <div v-else>
{{ col.value ? col.value : "-" }} {{ col.value ? col.value : "-" }}
</div> </div>
</q-td> </q-td>
</q-tr> </q-tr>
</template> </template>
<template v-slot:item="props"> <template v-slot:item="props">
<div <div
class="q-pa-xs col-xs-12 col-sm-6 col-md-4 col-lg-3 grid-style-transition" 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-pt-md"> <q-card bordered flat class="q-pt-md">
<q-list dense> <q-list dense>
<q-item v-for="col in props.cols" :key="col.name"> <q-item v-for="col in props.cols" :key="col.name">
<q-item-section class="fix_top"> <q-item-section class="fix_top">
<q-item-label class="text-grey-6 text-weight-medium">{{ <q-item-label class="text-grey-6 text-weight-medium">{{
col.label col.label
}}</q-item-label> }}</q-item-label>
</q-item-section> </q-item-section>
<q-item-section <q-item-section
v-if="col.name == 'insignia' && type == 'insignia'" v-if="col.name == 'insignia' && type == 'insignia'"
class="fix_top" class="fix_top"
>
<q-item-label class="text-dark text-weight-medium">
{{
props.row.insignia
? `${props.row.insignia.name} `
: "-"
}}{{
props.row.insignia.shortName
? `(${props.row.insignia.shortName})`
: ""
}}</q-item-label
> >
</q-item-section> <q-item-label class="text-dark text-weight-medium">
<q-item-section {{
v-else-if="col.name == 'dateLeave' && type == 'Leave'" props.row.insignia
class="fix_top" ? `${props.row.insignia.name} `
> : "-"
<q-item-label class="text-dark text-weight-medium"> }}{{
{{ props.row.insignia.shortName
dateThaiRange([ ? `(${props.row.insignia.shortName})`
props.row.dateStartLeave, : ""
props.row.dateEndLeave, }}</q-item-label
]) >
}}</q-item-label </q-item-section>
<q-item-section
v-else-if="col.name == 'dateLeave' && type == 'Leave'"
class="fix_top"
> >
</q-item-section> <q-item-label class="text-dark text-weight-medium">
<q-item-section {{
v-else-if="col.name == 'status' && type == 'Leave'" dateThaiRange([
class="fix_top" props.row.dateStartLeave,
> props.row.dateEndLeave,
<q-item-label class="text-dark text-weight-medium"> ])
{{ }}</q-item-label
props.row.status ? statusLeave(props.row.status) : "-" >
}}</q-item-label </q-item-section>
<q-item-section
v-else-if="col.name == 'status' && type == 'Leave'"
class="fix_top"
> >
</q-item-section> <q-item-label class="text-dark text-weight-medium">
<q-item-section v-else class="fix_top"> {{
<q-item-label class="text-dark text-weight-medium">{{ props.row.status
col.value ? col.value : "-" ? statusLeave(props.row.status)
}}</q-item-label> : "-"
</q-item-section> }}</q-item-label
</q-item> >
</q-list> </q-item-section>
</q-card> <q-item-section v-else class="fix_top">
</div> <q-item-label class="text-dark text-weight-medium">{{
</template> col.value ? col.value : "-"
<template v-slot:no-data> }}</q-item-label>
<div </q-item-section>
class="full-width row flex-center q-pa-sm rounded-borders text-weight-medium" </q-item>
> </q-list>
<span> ไมพบขอม </span> </q-card>
</div> </div>
</template> </template>
</d-table> <template v-slot:no-data>
<div
class="full-width row flex-center q-pa-sm rounded-borders text-weight-medium"
>
<span> ไมพบขอม </span>
</div>
</template>
</d-table>
</div>
</q-card-section> </q-card-section>
</q-card> </q-card>
</q-dialog> </q-dialog>

View file

@ -12,9 +12,7 @@ import DialogHeader from "@/components/DialogHeader.vue";
import { useRequestEditStore } from "@/modules/10_registry/store/RequestEdit"; import { useRequestEditStore } from "@/modules/10_registry/store/RequestEdit";
import { useCounterMixin } from "@/stores/mixin"; import { useCounterMixin } from "@/stores/mixin";
/** /** use*/
* use
*/
const $q = useQuasar(); const $q = useQuasar();
const link = ref<string>(""); const link = ref<string>("");
const store = useRequestEditStore(); const store = useRequestEditStore();
@ -22,24 +20,23 @@ const dataStore = useDataStore();
const { dialogConfirm, showLoader, hideLoader, messageError, success } = const { dialogConfirm, showLoader, hideLoader, messageError, success } =
useCounterMixin(); useCounterMixin();
/** /** props*/
* props
*/
const modalInfo = ref<boolean>(false); const modalInfo = ref<boolean>(false);
const modal = defineModel<boolean>("modal", { required: true }); const modal = defineModel<boolean>("modal", { required: true });
const props = defineProps({ const props = defineProps({
fetchData: { type: Function, requied: true }, fetchData: { type: Function, required: true },
}); });
const isReadOnly = ref<boolean>(false); const isReadOnly = ref<boolean>(false); //
const profileId = ref<string>(""); const profileId = ref<string>(""); // profileId q
const formData = reactive({ const formData = reactive({
topic: "", topic: "",
detail: "", detail: "",
document: null, document: null,
}); });
const topicOption = ref<string[]>(store.optionTopic); const topicOption = ref<string[]>(store.optionTopic); //
/** function ปิด Dialog และเคลียร์ข้อมูล */
function closeDialog() { function closeDialog() {
modal.value = false; modal.value = false;
formData.topic = ""; formData.topic = "";
@ -47,9 +44,7 @@ function closeDialog() {
formData.document = null; formData.document = null;
} }
/** /** function ยืนยันการยื่นคำร้องขอแก้ไขข้อมูล */
* function นยนการยนคำรองขอแกไขขอม
*/
function onSubmit() { function onSubmit() {
dialogConfirm( dialogConfirm(
$q, $q,
@ -65,17 +60,18 @@ function onSubmit() {
}) })
.then(async (res) => { .then(async (res) => {
if (formData.document) { if (formData.document) {
createURLUpload(res.data.result, formData.document); await createURLUpload(res.data.result, formData.document);
} else { } else {
formData.document = null; formData.document = null;
await props.fetchData?.(); await props.fetchData?.();
await success($q, "บันทึกข้อมูลสำเร็จ"); await success($q, "บันทึกข้อมูลสำเร็จ");
closeDialog(); closeDialog();
hideLoader();
} }
}) })
.catch((err) => { .catch((err) => {
messageError($q, err); messageError($q, err);
})
.finally(() => {
hideLoader(); hideLoader();
}); });
}, },
@ -86,10 +82,12 @@ function onSubmit() {
/** /**
* function สราง URL ปโหลไฟลเอกสารหลกฐาน * function สราง URL ปโหลไฟลเอกสารหลกฐาน
* @param id คำรองขอแกไขขอม
* @param file ไฟลปโหลด
*/ */
function createURLUpload(id: string, file: any) { async function createURLUpload(id: string, file: any) {
const fileName = { fileName: file.name }; const fileName = { fileName: file.name };
http await http
.post( .post(
config.API.file( config.API.file(
"ระบบทะเบียนประวัติ", "ระบบทะเบียนประวัติ",
@ -108,7 +106,7 @@ function createURLUpload(id: string, file: any) {
res.data[key]?.fileName !== "" res.data[key]?.fileName !== ""
); );
foundKey && foundKey &&
uploadFileDoc(res.data[foundKey]?.uploadUrl, formData.document); (await uploadFileDoc(res.data[foundKey]?.uploadUrl, formData.document));
}) })
.catch((err) => { .catch((err) => {
messageError($q, err); messageError($q, err);
@ -117,32 +115,29 @@ function createURLUpload(id: string, file: any) {
/** /**
* function สำหรบอพโหลดไฟลเอกสารหลกฐาน * function สำหรบอพโหลดไฟลเอกสารหลกฐาน
* @param uploadUrl URL สำหรบอปโหลดไฟล
* @param file ไฟลปโหลด
*/ */
function uploadFileDoc(uploadUrl: string, file: any) { async function uploadFileDoc(uploadUrl: string, file: any) {
showLoader(); await axios
axios
.put(uploadUrl, file, { .put(uploadUrl, file, {
headers: { headers: {
"Content-Type": file.type, "Content-Type": file.type,
}, },
}) })
.then(async (res) => { .then(async () => {
await props.fetchData?.(); await props.fetchData?.();
await success($q, "บันทึกข้อมูลสำเร็จ"); await success($q, "บันทึกข้อมูลสำเร็จ");
closeDialog(); closeDialog();
}) })
.catch((e) => { .catch((e) => {
messageError($q, e); messageError($q, e);
hideLoader();
})
.finally(() => {
hideLoader();
}); });
} }
/** /**
* class input * function สำหรบจดการ class ของ input
* @param val * @param val าทใชในการกำหนด class
*/ */
function classInput(val: boolean) { function classInput(val: boolean) {
return { return {
@ -164,9 +159,7 @@ function filterOption(val: string, update: Function) {
}); });
} }
/** /** function fetch profileId */
* function fetch profileId
*/
async function fetchProfile() { async function fetchProfile() {
try { try {
isReadOnly.value = dataStore.officerType === "OFFICER"; isReadOnly.value = dataStore.officerType === "OFFICER";

View file

@ -0,0 +1,40 @@
<template>
<div class="col-12 col-sm-12 col-md-6 q-gutter-y-sm">
<div class="row">
<div class="col-5 text-grey-6 text-weight-medium">
อยตามทะเบยนบาน
</div>
<div class="col-7">
<q-skeleton type="text" />
</div>
</div>
<div class="row">
<div class="col-5 text-grey-6 text-weight-medium">งหว</div>
<div class="col-7">
<q-skeleton type="text" />
</div>
</div>
<div class="row">
<div class="col-5 text-grey-6 text-weight-medium">เขต / อำเภอ</div>
<div class="col-7">
<q-skeleton type="text" />
</div>
</div>
<div class="row">
<div class="col-5 text-grey-6 text-weight-medium">แขวง / ตำบล</div>
<div class="col-7">
<q-skeleton type="text" />
</div>
</div>
<div class="row">
<div class="col-5 text-grey-6 text-weight-medium">รหสไปรษณ</div>
<div class="col-7">
<q-skeleton type="text" />
</div>
</div>
</div>
</template>

View file

@ -0,0 +1,103 @@
<script setup lang="ts">
const type = defineModel("type", {
type: String,
default: "",
});
</script>
<template>
<div class="col-12" v-if="type === 'couple'">
<q-card bordered class="bg-grey-1 q-pa-sm">
<div class="row">
<div class="col-12 col-sm-12 col-md-6 q-gutter-y-sm">
<div class="row">
<div class="col-5 text-grey-6 text-weight-medium">
สถานภาพการสมรส
</div>
<div class="col-7">
<q-skeleton type="text" />
</div>
</div>
<div class="row">
<div class="col-5 text-grey-6 text-weight-medium">
เลขประจำตวประชาชน
</div>
<div class="col-7">
<q-skeleton type="text" />
</div>
</div>
<div class="row">
<div class="col-5 text-grey-6 text-weight-medium">-นามสก</div>
<div class="col-7">
<q-skeleton type="text" />
</div>
</div>
<div class="row">
<div class="col-5 text-grey-6 text-weight-medium">นามสกลเด</div>
<div class="col-7">
<q-skeleton type="text" />
</div>
</div>
</div>
<div class="col-12 col-sm-12 col-md-6 q-gutter-y-sm">
<div class="row">
<div class="col-5 text-grey-6 text-weight-medium">
สถานภาพการม
</div>
<div class="col-7">
<q-skeleton type="text" />
</div>
</div>
<div class="row">
<div class="col-5 text-grey-6 text-weight-medium">อาช</div>
<div class="col-7">
<q-skeleton type="text" />
</div>
</div>
</div>
</div>
</q-card>
</div>
<div class="col-12" v-else>
<q-card bordered class="bg-grey-1 q-pa-sm">
<div class="row">
<div class="col-12 col-sm-12 col-md-12 q-gutter-y-sm">
<div class="row">
<div class="col-5 text-grey-6 text-weight-medium">
เลขประจำตวประชาชน
</div>
<div class="col-7">
<q-skeleton type="text" />
</div>
</div>
<div class="row">
<div class="col-5 text-grey-6 text-weight-medium">-นามสก</div>
<div class="col-7">
<q-skeleton type="text" />
</div>
</div>
<div class="row">
<div class="col-5 text-grey-6 text-weight-medium">
สถานภาพการม
</div>
<div class="col-7">
<q-skeleton type="text" />
</div>
</div>
<div class="row">
<div class="col-5 text-grey-6 text-weight-medium">อาช</div>
<div class="col-7">
<q-skeleton type="text" />
</div>
</div>
</div>
</div>
</q-card>
</div>
</template>

View file

@ -0,0 +1,110 @@
<template>
<q-card bordered class="bg-grey-1 q-pa-md">
<div class="row q-col-gutter-y-sm">
<div class="col-12 col-sm-12 col-md-6">
<div class="row q-col-gutter-y-sm">
<div class="col-5 text-grey-6 text-weight-medium">งก</div>
<div class="col-7 text-html">
<q-skeleton class="q-mb-sm" type="text" />
</div>
<div class="col-5 text-grey-6 text-weight-medium">
<q-skeleton class="q-mb-sm" type="text" />
</div>
<div class="col-7">
<q-skeleton class="q-mb-sm" type="text" />
</div>
<div class="col-5 text-grey-6 text-weight-medium">
<q-skeleton class="q-mb-sm" type="text" />
</div>
<div class="col-7">
<q-skeleton class="q-mb-sm" type="text" />
</div>
</div>
</div>
<div class="col-12 col-sm-12 col-md-6">
<div class="row q-col-gutter-y-sm">
<div class="col-5 text-grey-6 text-weight-medium">
<q-skeleton class="q-mb-sm" type="text" />
</div>
<div class="col-7">
<q-skeleton class="q-mb-sm" type="text" />
</div>
<div class="col-5 text-grey-6 text-weight-medium">
<q-skeleton class="q-mb-sm" type="text" />
</div>
<div class="col-7">
<q-skeleton class="q-mb-sm" type="text" />
</div>
<div class="col-5 text-grey-6 text-weight-medium">าน/สาขา</div>
<div class="col-7">
<q-skeleton class="q-mb-sm" type="text" />
</div>
</div>
</div>
</div>
<q-separator class="q-my-md" />
<div class="row">
<div class="col-12 col-sm-12 col-md-6 q-gutter-y-sm">
<div class="row">
<div class="col-6 text-grey-6 text-weight-medium">
นทงบรรจ
</div>
<div class="col-6">
<q-skeleton class="q-mb-sm" type="text" />
</div>
</div>
<div class="row">
<div class="col-6 text-grey-6 text-weight-medium">
นทเรมปฏราชการ
</div>
<div class="col-6">
<q-skeleton class="q-mb-sm" type="text" />
</div>
</div>
<div class="row">
<div class="col-6 text-grey-6 text-weight-medium">
นครบเกษยณอาย
</div>
<div class="col-6">
<q-skeleton class="q-mb-sm" type="text" />
</div>
</div>
<div class="row">
<div class="col-6 text-grey-6 text-weight-medium">
นทเกษยณอายราชการตามกฏหมาย
</div>
<div class="col-6">
<q-skeleton class="q-mb-sm" type="text" />
</div>
</div>
</div>
<div class="col-12 col-sm-12 col-md-6 q-gutter-y-sm">
<div class="row">
<div class="col-5 text-grey-6 text-weight-medium">อายราชการ</div>
<div class="col-7">
<q-skeleton class="q-mb-sm" type="text" />
</div>
</div>
<div class="row">
<div class="col-5 text-grey-6 text-weight-medium">ขาดราชการ</div>
<div class="col-7">
<q-skeleton class="q-mb-sm" type="text" />
</div>
</div>
<div class="row">
<div class="col-5 text-grey-6 text-weight-medium">
อายราชการเกอก
</div>
<div class="col-7">
<q-skeleton class="q-mb-sm" type="text" />
</div>
</div>
</div>
</div>
</q-card>
</template>

View file

@ -2,12 +2,12 @@
import { useRouter } from "vue-router"; import { useRouter } from "vue-router";
/** component */ /** component */
import Information from "@/modules/10_registry/01_Information/01_Information.vue"; import Information from "@/modules/10_registry/01_Information/01_Information.vue"; //
import ChangeName from "@/modules/10_registry/01_Information/02_ChangeName.vue"; import ChangeName from "@/modules/10_registry/01_Information/02_ChangeName.vue"; //-
import Address from "@/modules/10_registry/01_Information/03_Address.vue"; import Address from "@/modules/10_registry/01_Information/03_Address.vue"; //
import Family from "@/modules/10_registry/01_Information/04_Family.vue"; import Family from "@/modules/10_registry/01_Information/04_Family.vue"; //
import Educations from "@/modules/10_registry/01_Information/05_Educations.vue"; import Educations from "@/modules/10_registry/01_Information/05_Educations.vue"; //
import Ability from "@/modules/10_registry/01_Information/06_Ability.vue"; import Ability from "@/modules/10_registry/01_Information/06_Ability.vue"; //
const router = useRouter(); const router = useRouter();
</script> </script>

View file

@ -1,44 +1,51 @@
<script setup lang="ts"> <script setup lang="ts">
import { ref, computed } from "vue"; import { ref, computed, onMounted } from "vue";
import { useCounterMixin } from "@/stores/mixin"; import { useQuasar } from "quasar";
import { useDataStore } from "@/stores/data";
import { useRegistryInFormationStore } from "@/modules/10_registry/store/registry";
import genReport from "@/plugins/genreport";
// import http from "@/plugins/http";
import config from "@/app.config";
import genReport from "@/plugins/genreport";
import { useRouter } from "vue-router";
import { useRegistryInFormationStore } from "@/modules/10_registry/store/registry";
import { useDataStore } from "@/stores/data";
import { useCounterMixin } from "@/stores/mixin";
/** import components */
import InformationPage from "@/modules/10_registry/tabs/01_information.vue"; import InformationPage from "@/modules/10_registry/tabs/01_information.vue";
import GovernmentPage from "@/modules/10_registry/tabs/02_government.vue"; import GovernmentPage from "@/modules/10_registry/tabs/02_government.vue";
import SalaryPage from "@/modules/10_registry/tabs/03_salary.vue"; import SalaryPage from "@/modules/10_registry/tabs/03_salary.vue";
import Certificate from "@/modules/10_registry/tabs/04_Achievement.vue"; import Certificate from "@/modules/10_registry/tabs/04_Achievement.vue";
import OtherPage from "@/modules/10_registry/tabs/05_other.vue"; import OtherPage from "@/modules/10_registry/tabs/05_other.vue";
import { useRouter } from "vue-router";
import http from "@/plugins/http";
import config from "@/app.config";
import { useQuasar } from "quasar";
const store = useRegistryInFormationStore();
const $q = useQuasar(); const $q = useQuasar();
const dataStore = useDataStore();
const mixin = useCounterMixin();
const { messageError, showLoader, hideLoader } = mixin;
const router = useRouter(); const router = useRouter();
const tab = ref<string>("information"); const store = useRegistryInFormationStore();
const dataStore = useDataStore();
const { messageError, showLoader, hideLoader } = useCounterMixin();
const tab = ref<string>("information"); //
const sizeImg = ref<string>(""); //
/** ข้อความแสดงชื่อเงินเดือนหรือค่าจ้าง */
const salaryText = computed(() => { const salaryText = computed(() => {
return dataStore.officerType == "OFFICER" ? "เงินเดือน" : "ค่าจ้าง"; return dataStore.officerType == "OFFICER" ? "เงินเดือน" : "ค่าจ้าง";
}); });
const sizeImg = ref<string>(""); /**
function onResize(size: any) { * งกนจดการขนาดของรปภาพโปรไฟล
* @param size ขนาดทไดจาก q-resize-observer
*/
function onResize(size: { width: number; height: number }) {
const width = size.width > 100 ? 100 : size.width; const width = size.width > 100 ? 100 : size.width;
sizeImg.value = `${width}px`; sizeImg.value = `${width}px`;
} }
function onMobile(type: string) { /**
router.push(`/registry/${type}`); * งกนดาวนโหลดไฟล ..7/..1 หรอประวแบบย
} * @param type ประเภทไฟลองการดาวนโหลด
* FULL: ..7/..1
* SHORT: ประวแบบย
*/
async function onClickDownloadKp7(type: string) { async function onClickDownloadKp7(type: string) {
showLoader(); showLoader();
const url = const url =
@ -66,19 +73,19 @@ async function onClickDownloadKp7(type: string) {
}); });
} }
/** /** ฟังชั่นกลับหน้าหลัก*/
* งชนกลบหนาหล
*/
const clickBack = () => { const clickBack = () => {
router.push(`/`); router.push(`/`);
}; };
/** /** ฟังก์ชัน redirect ไปหน้ารายการคำร้องขอแก้ไขข้อมูล*/
* function redirect ไปหนารายการคำรองขอแกไขขอม
*/
function redirectToPagePetition() { function redirectToPagePetition() {
router.push(`/registry/request-edit`); router.push(`/registry/request-edit`);
} }
function onMobile(type: string) {
router.push(`/registry/${type}`);
}
</script> </script>
<template> <template>
@ -106,7 +113,40 @@ function redirectToPagePetition() {
</div> </div>
<div v-if="$q.screen.gt.xs" class="row q-col-gutter-md"> <div v-if="$q.screen.gt.xs" class="row q-col-gutter-md">
<div class="col-3"> <div class="col-3">
<q-card bordered> <q-card v-if="dataStore.isLoadingProfile" bordered>
<q-resize-observer @resize="onResize" />
<q-card-section>
<div class="relative-position" style="height: 120px">
<div class="absolute-center">
<q-skeleton type="QAvatar" :size="sizeImg || '100px'" />
</div>
</div>
<div class="column items-center q-mt-md q-mb-sm q-gutter-sm">
<q-skeleton type="text" width="120px" />
<q-skeleton type="text" width="150px" />
<q-skeleton type="text" width="100px" />
<q-skeleton type="text" width="50px" />
</div>
</q-card-section>
<q-list separator class="q-mt-md">
<q-item v-for="i in 2" :key="i">
<q-item-section>
<q-skeleton type="text" />
</q-item-section>
<q-item-section>
<q-skeleton type="text" />
</q-item-section>
</q-item>
</q-list>
<q-card-section class="q-gutter-y-sm">
<q-skeleton type="QBtn" class="full-width" height="48px" />
<q-skeleton type="QBtn" class="full-width" height="48px" />
</q-card-section>
</q-card>
<q-card v-else bordered>
<q-resize-observer @resize="onResize" /> <q-resize-observer @resize="onResize" />
<q-card-section> <q-card-section>
<div class="relative-position" style="height: 120px"> <div class="relative-position" style="height: 120px">
@ -220,8 +260,6 @@ function redirectToPagePetition() {
<q-separator /> <q-separator />
<!-- รายการเเตละหน -->
<q-tab-panels v-model="tab" animated> <q-tab-panels v-model="tab" animated>
<q-tab-panel name="information"> <q-tab-panel name="information">
<InformationPage /> <InformationPage />
@ -248,7 +286,41 @@ function redirectToPagePetition() {
</div> </div>
<div v-else> <div v-else>
<q-card bordered> <q-card v-if="dataStore.isLoadingProfile" bordered>
<q-resize-observer @resize="onResize" />
<q-card-section>
<div class="relative-position" style="height: 120px">
<div class="absolute-center">
<q-skeleton type="QAvatar" :size="sizeImg || '100px'" />
</div>
</div>
<div class="column items-center q-mt-md q-mb-lg q-gutter-sm">
<q-skeleton type="text" width="120px" />
<q-skeleton type="text" width="150px" />
<q-skeleton type="text" width="100px" />
<q-skeleton type="text" width="50px" />
</div>
<div class="row justify-center q-gutter-x-lg">
<q-skeleton type="QRadio" size="48px" />
<q-skeleton type="QRadio" size="48px" />
</div>
<q-list separator class="q-mt-md">
<q-item v-for="i in 5" :key="i">
<q-item-section>
<q-skeleton type="text" width="120px" height="16px" />
</q-item-section>
<q-item-section avatar>
<q-skeleton type="QIcon" size="24px" />
</q-item-section>
</q-item>
</q-list>
</q-card-section>
</q-card>
<q-card v-else bordered>
<q-resize-observer @resize="onResize" /> <q-resize-observer @resize="onResize" />
<q-card-section> <q-card-section>
<div class="text-center q-mt-md"> <div class="text-center q-mt-md">

View file

@ -1,5 +1,5 @@
<script setup lang="ts"> <script setup lang="ts">
import { ref, onMounted, watch } from "vue"; import { ref, onMounted } from "vue";
import { useQuasar } from "quasar"; import { useQuasar } from "quasar";
import { useRouter, useRoute } from "vue-router"; import { useRouter, useRoute } from "vue-router";
@ -37,8 +37,11 @@ const statusOptionMain = ref<DataOption[]>(
); );
const statusOption = ref<DataOption[]>(statusOptionMain.value); // const statusOption = ref<DataOption[]>(statusOptionMain.value); //
const isLoading = ref<boolean>(false); //
async function fetchData() { async function fetchData() {
showLoader(); // showLoader();
isLoading.value = true;
await http await http
.get(config.API.requestEditByType(link.value) + `${requestId.value}`) .get(config.API.requestEditByType(link.value) + `${requestId.value}`)
.then(async (res) => { .then(async (res) => {
@ -56,9 +59,10 @@ async function fetchData() {
}) })
.catch((err) => { .catch((err) => {
messageError($q, err); messageError($q, err);
hideLoader();
}) })
.finally(() => {}); .finally(() => {
isLoading.value = false;
});
} }
const checkFile = ref<null | false | "img" | "doc">(null); // null , false , "img" , "doc" const checkFile = ref<null | false | "img" | "doc">(null); // null , false , "img" , "doc"
@ -154,7 +158,37 @@ onMounted(async () => {
</div> </div>
</div> </div>
<div class="col-12"><q-separator /></div> <div class="col-12"><q-separator /></div>
<q-card-section class="col-12">
<q-card-section v-if="isLoading" class="col-12">
<div class="row q-col-gutter-sm">
<!-- นทนขอ Skeleton -->
<div class="col-md-2 col-xs-12">
<q-skeleton type="QInput" height="40px" />
</div>
<!-- เรอง Skeleton -->
<div class="col-md-10 col-xs-12">
<q-skeleton type="QInput" height="40px" />
</div>
<!-- รายละเอยด Skeleton -->
<div class="col-12">
<q-skeleton type="QInput" height="160px" />
</div>
<!-- ไฟล Skeleton -->
<div class="col-12 q-mt-md">
<q-skeleton
type="rect"
width="120px"
height="20px"
class="q-mb-sm"
/>
</div>
</div>
</q-card-section>
<q-card-section v-else class="col-12">
<div class="row q-col-gutter-sm"> <div class="row q-col-gutter-sm">
<!-- นทนขอ --> <!-- นทนขอ -->
<div class="col-md-2 col-xs-12"> <div class="col-md-2 col-xs-12">
@ -265,7 +299,19 @@ onMounted(async () => {
<div class="q-pl-sm text-weight-bold text-dark">สถานะคำรอง</div> <div class="q-pl-sm text-weight-bold text-dark">สถานะคำรอง</div>
</div> </div>
<div class="col-12"><q-separator /></div> <div class="col-12"><q-separator /></div>
<q-card-section class="col-12"> <q-card-section v-if="isLoading" class="col-12">
<div class="row q-col-gutter-sm">
<div class="col-12">
<q-skeleton type="QInput" height="40px" />
</div>
<div class="col-12">
<q-skeleton type="QInput" height="160px" />
</div>
</div>
</q-card-section>
<q-card-section v-else class="col-12">
<div class="row q-col-gutter-sm"> <div class="row q-col-gutter-sm">
<div class="col-xs-12 col-md-12"> <div class="col-xs-12 col-md-12">
<q-select <q-select
@ -312,6 +358,7 @@ onMounted(async () => {
<div class="col-12 q-mt-sm"> <div class="col-12 q-mt-sm">
<Workflow <Workflow
v-if="dataStore.officerType && requestId"
ref="workflowRef" ref="workflowRef"
:id="requestId" :id="requestId"
:sys-name=" :sys-name="

View file

@ -6,10 +6,10 @@ import http from "@/plugins/http";
import { useDataStore } from "@/stores/data"; import { useDataStore } from "@/stores/data";
import { useQuasar } from "quasar"; import { useQuasar } from "quasar";
import { useRouter } from "vue-router"; import { useRouter } from "vue-router";
import { useRequestEditStore } from "@/modules/10_registry/store/RequestEdit";
import { useCounterMixin } from "@/stores/mixin";
/** /**importType*/
* importType
*/
import type { QTableProps } from "quasar"; import type { QTableProps } from "quasar";
import type { import type {
DataOption, DataOption,
@ -17,39 +17,26 @@ import type {
} from "@/modules/10_registry/interface/index/Main"; } from "@/modules/10_registry/interface/index/Main";
import type { DataRequest } from "@/modules/10_registry/interface/response/Main"; import type { DataRequest } from "@/modules/10_registry/interface/response/Main";
/** /** importComponents*/
* importComponents
*/
import DialogAddRequestEdit from "@/modules/10_registry/components/DialogAddRequestEdit.vue"; import DialogAddRequestEdit from "@/modules/10_registry/components/DialogAddRequestEdit.vue";
import SkeletonTable from "@/components/SkeletonTable.vue";
/** /** use */
* importStore
*/
import { useRequestEditStore } from "@/modules/10_registry/store/RequestEdit";
import { useCounterMixin } from "@/stores/mixin";
/**
* use
*/
const $q = useQuasar(); const $q = useQuasar();
const store = useRequestEditStore(); const store = useRequestEditStore();
const link = ref<string>(""); const link = ref<string>("");
const router = useRouter(); const router = useRouter();
const dataStore = useDataStore(); const dataStore = useDataStore();
const { showLoader, hideLoader, messageError, dialogRemove, success } = const { messageError } = useCounterMixin();
useCounterMixin();
/** /** ตัวแปร*/
* วแปร
*/
const modalPetiton = ref<boolean>(false); const modalPetiton = ref<boolean>(false);
const status = ref<string>(""); const status = ref<string>("");
const keyword = ref<string>(""); const keyword = ref<string>("");
const statusOption = ref<DataOption[]>(store.optionStatus); const statusOption = ref<DataOption[]>(store.optionStatus);
const isLoading = ref<boolean>(false);
/** /** Table*/
* Table
*/
const rows = ref<DataRequest[]>([]); const rows = ref<DataRequest[]>([]);
const page = ref<number>(1); const page = ref<number>(1);
const pageSize = ref<number>(10); const pageSize = ref<number>(10);
@ -124,32 +111,26 @@ const visibleColumns = ref<string[]>([
"remark", "remark",
]); ]);
/** /** function กลับไปหน้าทะเบียนประวัติ*/
* function กลบไปหนาทะเบยนประว
*/
function onclickBackPage() { function onclickBackPage() {
router.push(`/registry`); router.push(`/registry`);
} }
/** /** function กดเพิ่มรายการยื่นคำร้องขอแก้ไขข้อมูล*/
* function กดเพมรายการยนคำรองขอแกไขขอม
*/
function onClickAdd() { function onClickAdd() {
modalPetiton.value = true; modalPetiton.value = true;
} }
/** /** function fetch รายการข้อมูลการยื่นคำร้องขอแก้ไขข้อมูล*/
* function fetch รายการขอมลการยนคำรองขอแกไขขอม async function fetchListRequset() {
*/
function fetchListRequset() {
let queryParams = { let queryParams = {
page: page.value, page: page.value,
pageSize: pageSize.value, pageSize: pageSize.value,
status: status.value, status: status.value,
keyword: keyword.value, keyword: keyword.value,
}; };
showLoader(); isLoading.value = true;
http await http
.get(config.API.requestEditByType(link.value) + `user`, { .get(config.API.requestEditByType(link.value) + `user`, {
params: queryParams, params: queryParams,
}) })
@ -163,21 +144,17 @@ function fetchListRequset() {
messageError($q, err); messageError($q, err);
}) })
.finally(() => { .finally(() => {
hideLoader(); isLoading.value = false;
}); });
} }
/** /** function เลือกสถานะคำร้อง*/
* function เลอกสถานะคำรอง
*/
function updateStatusValue() { function updateStatusValue() {
page.value = 1; page.value = 1;
fetchListRequset(); fetchListRequset();
} }
/** /** function เคลียร์ข้อมูลสถานะคำร้อง*/
* function เคลยรอมลสถานะคำรอง
*/
function clearStatus() { function clearStatus() {
status.value = ""; status.value = "";
statusOption.value = store.optionStatus; statusOption.value = store.optionStatus;
@ -197,80 +174,15 @@ function filterOption(val: string, update: Function) {
}); });
} }
/**
* function พเดทขนาดหนาใน pagination
* @param newPagination อมลใหมของ pagination
*/
function updatePageSizePagination(newPagination: NewPagination) { function updatePageSizePagination(newPagination: NewPagination) {
page.value = 1; page.value = 1;
pageSize.value = newPagination.rowsPerPage; pageSize.value = newPagination.rowsPerPage;
} }
/**
* function หาชอไฟล
* @param id รายการยนคำรองขอแกไขขอม
*/
function onDownloadFile(id: string) {
showLoader();
http
.get(
config.API.file(
"ระบบทะเบียนประวัติ",
"เอกสารหลักฐานคำร้องขอแก้ไขข้อมูล",
id
)
)
.then((res) => {
if (res.data.length !== 0) {
downloadUrl(id, res.data[0].fileName);
} else {
hideLoader();
}
})
.catch((e) => {
messageError($q, e);
hideLoader();
});
}
/**
* function โหลดไฟล
* @param id รายการยนคำรองขอแกไขขอม
* @param fileName อไฟล
*/
function downloadUrl(id: string, fileName: string) {
http
.get(
config.API.fileByFile(
"ระบบทะเบียนประวัติ",
"เอกสารหลักฐานคำร้องขอแก้ไขข้อมูล",
id,
fileName
)
)
.then((res) => {
window.open(res.data.downloadUrl, "_blank");
})
.catch((e) => {
messageError($q, e);
})
.finally(() => {
hideLoader();
});
}
// function onDeleteLidt(id: string) {
// dialogRemove($q, () => {
// showLoader();
// http
// .delete(config.API.requestEdit + `${id}`)
// .then(async (res) => {
// await fetchListRequset();
// await success($q, "");
// })
// .catch((err) => {
// messageError($q, err);
// hideLoader();
// });
// });
// }
watch( watch(
() => pageSize.value, () => pageSize.value,
() => { () => {
@ -381,7 +293,9 @@ onMounted(async () => {
</div> </div>
</div> </div>
<div class="col-12"> <div class="col-12">
<SkeletonTable v-if="isLoading" :columns="columns" />
<d-table <d-table
v-else
:columns="columns" :columns="columns"
:rows="rows" :rows="rows"
row-key="id" row-key="id"
@ -411,36 +325,11 @@ onMounted(async () => {
<div v-if="col.name == 'no'"> <div v-if="col.name == 'no'">
{{ props.rowIndex + 1 }} {{ props.rowIndex + 1 }}
</div> </div>
<!-- <div v-else-if="col.name === 'document'">
<q-btn
icon="mdi-download"
round
dense
flat
color="primary"
size="12px"
@click.stop.pervent="onDownloadFile(props.row.id)"
>
<q-tooltip>หลกฐานอางอ</q-tooltip>
</q-btn>
</div> -->
<div v-else class="table_ellipsis2"> <div v-else class="table_ellipsis2">
{{ col.value ? col.value : "-" }} {{ col.value ? col.value : "-" }}
</div> </div>
</q-td> </q-td>
<!-- <q-td>
<q-btn
v-if="props.row.status === 'PENDING'"
flat
round
color="red"
icon="mdi-delete"
size="12px"
@click="onDeleteLidt(props.row.id)"
>
<q-tooltip>ลบคำรองขอแกไขขอม</q-tooltip>
</q-btn>
</q-td> -->
</q-tr> </q-tr>
</template> </template>
<template v-slot:pagination="scope"> <template v-slot:pagination="scope">

View file

@ -29,6 +29,7 @@ const dataSource = ref(); // ข้อมูล Chart
const idActive = ref<string>(""); const idActive = ref<string>("");
const dataSourceLock = ref(); // Chart home const dataSourceLock = ref(); // Chart home
const scrollContainer = ref<HTMLElement | null>(null); const scrollContainer = ref<HTMLElement | null>(null);
const isLoading = ref<boolean>(false);
/** /**
* สราง Path Breadcrumbs * สราง Path Breadcrumbs
@ -150,7 +151,7 @@ async function fetchStructChart(
type: string, type: string,
status: boolean = false status: boolean = false
) { ) {
showLoader(); isLoading.value = true;
await http await http
.get(config.API.orgStructChart(id, type)) .get(config.API.orgStructChart(id, type))
.then((res) => { .then((res) => {
@ -168,7 +169,7 @@ async function fetchStructChart(
messageError($q, err); messageError($q, err);
}) })
.finally(() => { .finally(() => {
hideLoader(); isLoading.value = false;
}); });
} }
@ -236,7 +237,19 @@ onMounted(async () => {
<div class="col-xs-12 col-sm-12 col-md-11 row q-col-gutter-md"> <div class="col-xs-12 col-sm-12 col-md-11 row q-col-gutter-md">
<div class="col-12 row"> <div class="col-12 row">
<q-card bordered class="col-12 row caedNone"> <q-card bordered class="col-12 row caedNone">
<div class="q-pa-sm row wrap items-center"> <!-- Skeleton สำหร Toolbar -->
<div v-if="isLoading" class="q-pa-sm row wrap items-center col-12">
<q-skeleton type="circle" size="40px" />
<q-skeleton type="circle" size="40px" class="q-ml-sm" />
<q-skeleton
type="rect"
width="300px"
height="40px"
class="q-ml-md"
/>
</div>
<div v-else class="q-pa-sm row wrap items-center">
<q-btn <q-btn
flat flat
:diasble="isLoadBtn" :diasble="isLoadBtn"
@ -276,7 +289,53 @@ onMounted(async () => {
<q-separator /> <q-separator />
</div> </div>
<!-- Organization Chart Skeleton -->
<div <div
v-if="isLoading"
class="q-pt-md col-12"
style="height: 70vh; overflow: hidden"
>
<div class="row justify-center q-mb-lg">
<!-- Main Department Skeleton -->
<div class="col-auto">
<q-skeleton
type="rect"
width="300px"
height="80px"
class="rounded-borders"
/>
</div>
</div>
<!-- Sub Departments Skeleton -->
<div class="row justify-center q-col-gutter-md">
<div v-for="i in 5" :key="i" class="col-auto">
<div class="column items-center">
<q-skeleton
type="rect"
width="200px"
height="60px"
class="rounded-borders q-mb-md"
/>
<!-- Sub Items Skeleton -->
<div class="column q-gutter-xs">
<q-skeleton
v-for="j in 3"
:key="j"
type="rect"
width="180px"
height="35px"
class="rounded-borders"
/>
</div>
</div>
</div>
</div>
</div>
<div
v-else
id="structChart" id="structChart"
ref="scrollContainer" ref="scrollContainer"
style=" style="

View file

@ -13,9 +13,7 @@ const router = useRouter();
const mixin = useCounterMixin(); const mixin = useCounterMixin();
const { success, messageError, showLoader, hideLoader, dialogConfirm } = mixin; const { success, messageError, showLoader, hideLoader, dialogConfirm } = mixin;
/** /** ตัวแปรที่ใช้งาน */
* วแปรทใชงาน
*/
const route = useRoute(); const route = useRoute();
const files = ref<any>(); const files = ref<any>();
const name = ref<string>(""); const name = ref<string>("");
@ -24,60 +22,74 @@ const id = ref<string>("");
const routeName = router.currentRoute.value.name; const routeName = router.currentRoute.value.name;
const fileList = ref<any[]>([]); const fileList = ref<any[]>([]);
const saveData = async () => { const isLoading = ref<boolean>(false);
dialogConfirm( const isLoadingFile = ref<boolean>(false);
$q,
() => {
createTransfer();
},
"ยืนยันการบันทึกข้อมูล",
"ต้องการยืนยันการบันทึกข้อมูลใช่หรือไม่"
);
};
/**
* งกนสรางขอโอน
*/
const createTransfer = async () => {
showLoader();
await http
.post(config.API.portfolio, { name: name.value, detail: detail.value })
.then(async (res) => {
uploadFiles(res.data.result);
})
.catch((e) => {
messageError($q, e);
hideLoader();
});
};
/** /**
* งกนเรยกขอมลจาก Api * งกนเรยกขอมลจาก Api
* @param id ไอดของขอม * @param id ไอดของขอม
*/ */
const fecthData = async (id: string) => { async function fetchData(id: string) {
showLoader(); isLoading.value = true;
await http await http
.get(config.API.portfolioId(id)) .get(config.API.portfolioId(id))
.then((res: any) => { .then(async (res) => {
let data = res.data.result; let data = res.data.result;
name.value = data.name; name.value = data.name;
detail.value = data.detail; detail.value = data.detail;
fetchFile();
}) })
.catch((e: any) => { .catch((e) => {
messageError($q, e); messageError($q, e);
hideLoader(); })
.finally(() => {
isLoading.value = false;
}); });
}; }
/** ฟังก์ชั่นรายการเอกสาร */
async function fetchFile() {
isLoadingFile.value = true;
await http
.get(config.API.file("ระบบผลงาน", "เอกสารผลงาน", id.value))
.then((res) => {
fileList.value = res.data;
})
.catch((e) => {
messageError($q, e);
})
.finally(() => {
isLoadingFile.value = false;
});
}
function onSubmit() {
dialogConfirm(
$q,
async () => {
showLoader();
await http
.post(config.API.portfolio, { name: name.value, detail: detail.value })
.then(async (res) => {
await uploadFiles(res.data.result);
})
.catch((e) => {
messageError($q, e);
})
.finally(() => {
hideLoader();
});
},
"ยืนยันการบันทึกข้อมูล",
"ต้องการยืนยันการบันทึกข้อมูลใช่หรือไม่"
);
}
/** /**
* function ปโหลดไฟล * งกปโหลดไฟล
* @param id ผลงาน * @param id ผลงาน
*/ */
function uploadFiles(id: string) { async function uploadFiles(id: string) {
showLoader(); await http
http
.post(config.API.file("ระบบผลงาน", "เอกสารผลงาน", id), { .post(config.API.file("ระบบผลงาน", "เอกสารผลงาน", id), {
replace: true, replace: true,
fileList: [ fileList: [
@ -92,23 +104,21 @@ function uploadFiles(id: string) {
res.data[key]?.fileName !== undefined && res.data[key]?.fileName !== undefined &&
res.data[key]?.fileName !== "" res.data[key]?.fileName !== ""
); );
foundKey && uploadFileURL(res.data[foundKey]?.uploadUrl); foundKey && (await uploadFileURL(res.data[foundKey]?.uploadUrl));
}) })
.catch((err) => { .catch((err) => {
messageError($q, err); messageError($q, err);
hideLoader();
}); });
} }
/** /**
* function นทกไฟล * งกนทกไฟล
* @param uploadUrl นทกไฟล * @param uploadUrl นทกไฟล
*/ */
function uploadFileURL(uploadUrl: string) { async function uploadFileURL(uploadUrl: string) {
const Data = new FormData(); const Data = new FormData();
Data.append("file", files.value); Data.append("file", files.value);
showLoader(); await axios
axios
.put(uploadUrl, files.value, { .put(uploadUrl, files.value, {
headers: { headers: {
"Content-Type": files.value.type, "Content-Type": files.value.type,
@ -122,29 +132,10 @@ function uploadFileURL(uploadUrl: string) {
messageError($q, e); messageError($q, e);
}) })
.finally(() => { .finally(() => {
hideLoader();
files.value = null; files.value = null;
}); });
} }
/**
*function fetch รายการเอกสาร
*/
function fetchFile() {
showLoader();
http
.get(config.API.file("ระบบผลงาน", "เอกสารผลงาน", id.value))
.then((res) => {
fileList.value = res.data;
})
.catch((e) => {
messageError($q, e);
})
.finally(() => {
hideLoader();
});
}
/** /**
* งกนดาวโหลดอปโหลดไฟล * งกนดาวโหลดอปโหลดไฟล
* @param fileName อไฟล * @param fileName อไฟล
@ -165,13 +156,11 @@ function fileOpen(fileName: string) {
}); });
} }
/** /** Hook Lifecycle ที่ทำงานเมื่อ component ถูก mount*/
* เรยกฟงกนทงหมดตอนเรยกใชไฟล onMounted(async () => {
*/
onMounted(() => {
if (route.params.id !== undefined) { if (route.params.id !== undefined) {
id.value = route.params.id.toString(); id.value = route.params.id.toString();
fecthData(id.value); await Promise.all([fetchData(id.value), fetchFile()]);
} }
}); });
</script> </script>
@ -197,9 +186,17 @@ onMounted(() => {
class="col-12" class="col-12"
greedy greedy
@submit.prevent @submit.prevent
@validation-success="saveData" @validation-success="onSubmit"
> >
<q-card bordered> <q-card bordered v-if="isLoading">
<div class="q-pa-md">
<div class="q-gutter-md">
<q-skeleton height="40px" />
<q-skeleton height="150px" />
</div>
</div>
</q-card>
<q-card bordered v-else>
<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 class="col-12 row q-pa-sm q-col-gutter-sm"> <div class="col-12 row q-pa-sm q-col-gutter-sm">
@ -246,6 +243,7 @@ onMounted(() => {
<q-icon name="attach_file" /> </template <q-icon name="attach_file" /> </template
></q-file> ></q-file>
</div> </div>
<div class="col-12 row" v-if="routeName != 'addPortfolio'"> <div class="col-12 row" v-if="routeName != 'addPortfolio'">
<q-card bordered flat class="full-width"> <q-card bordered flat class="full-width">
<div <div
@ -256,7 +254,8 @@ onMounted(() => {
</div> </div>
</div> </div>
<q-separator /> <q-separator />
<q-list separator> <q-skeleton v-if="isLoadingFile" type="QSlider" />
<q-list v-else separator>
<q-item v-for="file in fileList" :key="file.key"> <q-item v-for="file in fileList" :key="file.key">
<q-item-section> <q-item-section>
{{ file.fileName }} {{ file.fileName }}

View file

@ -9,6 +9,9 @@ import { useRouter } from "vue-router";
import { useCounterMixin } from "@/stores/mixin"; import { useCounterMixin } from "@/stores/mixin";
import type { PortfolioRowsType } from "@/modules/13_portfolio/interface/Main"; import type { PortfolioRowsType } from "@/modules/13_portfolio/interface/Main";
import SkeletonTable from "@/components/SkeletonTable.vue";
const $q = useQuasar(); const $q = useQuasar();
const router = useRouter(); const router = useRouter();
const mixin = useCounterMixin(); const mixin = useCounterMixin();
@ -27,9 +30,8 @@ const pagination = ref({
page: 1, page: 1,
rowsPerPage: 10, rowsPerPage: 10,
}); });
/**
* เพมหวขอตาราง const isLoading = ref<boolean>(false);
*/
const filter = ref<string>(""); const filter = ref<string>("");
const rows = ref<PortfolioRowsType[]>([]); const rows = ref<PortfolioRowsType[]>([]);
const rowsData = ref<PortfolioRowsType[]>([]); const rowsData = ref<PortfolioRowsType[]>([]);
@ -64,9 +66,9 @@ const columns = ref<QTableProps["columns"]>([
}, },
]); ]);
// /** ฟังก์ชั่นนำข้อมูลรายการเอกสาร/ผลงาน */
async function fecthList() { async function fecthList() {
showLoader(); isLoading.value = true;
await http await http
.get(config.API.portfolio) .get(config.API.portfolio)
.then((res) => { .then((res) => {
@ -77,20 +79,16 @@ async function fecthList() {
messageError($q, e); messageError($q, e);
}) })
.finally(() => { .finally(() => {
hideLoader(); isLoading.value = false;
}); });
} }
/** /** ฟังก์ชั่นกดเพิ่มไปหน้าเพิ่มขอโอน*/
* งกนกดเพมไปหนาเพมขอโอน
*/
async function clickAdd() { async function clickAdd() {
router.push(`/portfolio/add`); router.push(`/portfolio/add`);
} }
/** /** ฟังก์ชั่นกดย้อนกลับ*/
* งกนกดยอนกล
*/
function clickBack() { function clickBack() {
router.push(`/`); router.push(`/`);
} }
@ -100,21 +98,25 @@ function clickBack() {
* @param id id row * @param id id row
*/ */
function onDelete(id: string) { function onDelete(id: string) {
dialogRemove($q, () => { dialogRemove($q, async () => {
showLoader(); showLoader();
http await http
.delete(config.API.portfolioId(id)) .delete(config.API.portfolioId(id))
.then((res) => { .then(async () => {
await fecthList();
success($q, "ลบข้อมูลสำเร็จ"); success($q, "ลบข้อมูลสำเร็จ");
fecthList();
}) })
.catch((err) => { .catch((err) => {
messageError($q, err); messageError($q, err);
})
.finally(() => {
hideLoader(); hideLoader();
}); });
}); });
} }
/** ฟังก์ชั่นค้นหาข้อมูลในตาราง */
function onSearch() { function onSearch() {
rows.value = onSearchDataTable( rows.value = onSearchDataTable(
filter.value, filter.value,
@ -123,9 +125,7 @@ function onSearch() {
); );
} }
/** /** Hook Lifecycle */
* เรยกฟงกนทงหมดตอนเรยกใชไฟล
*/
onMounted(async () => { onMounted(async () => {
await fecthList(); await fecthList();
}); });
@ -198,7 +198,9 @@ onMounted(async () => {
</q-select> </q-select>
</div> </div>
</div> </div>
<div>
<SkeletonTable v-if="isLoading" :columns="columns" />
<div class="col-12" v-else>
<d-table <d-table
flat flat
bordered bordered

View file

@ -10,20 +10,18 @@ import { useIndividualDevelopmentPlan } from "@/modules/14_IDP/store"; // ดึ
import type { DataOption, RowsListMain } from "@/modules/14_IDP/interface/Main"; import type { DataOption, RowsListMain } from "@/modules/14_IDP/interface/Main";
import SkeletonTable from "@/components/SkeletonTable.vue";
const $q = useQuasar(); const $q = useQuasar();
const router = useRouter(); const router = useRouter();
const mixin = useCounterMixin(); const mixin = useCounterMixin();
const store = useIndividualDevelopmentPlan(); const store = useIndividualDevelopmentPlan();
const { showLoader, hideLoader, messageError, success, dialogRemove } = mixin; const { showLoader, hideLoader, messageError, success, dialogRemove } = mixin;
const idRow = ref<string>(""); const isLoading = ref<boolean>(false);
const isEdit = ref<boolean>(false);
const modalAdd = ref<boolean>(false); // dialog #Add
const filterKeyword = ref<string>(""); const filterKeyword = ref<string>("");
const status = ref<string>("ALL"); // const status = ref<string>("ALL"); //
const statusOptions = ref<DataOption[]>(store.optionStatus); const statusOptions = ref<DataOption[]>(store.optionStatus);
/** pagination */
const rows = ref<RowsListMain[]>([]); const rows = ref<RowsListMain[]>([]);
const total = ref<number>(0); const total = ref<number>(0);
const totalList = ref<number>(1); const totalList = ref<number>(1);
@ -33,7 +31,6 @@ const pagination = ref({
page: 1, page: 1,
rowsPerPage: 10, rowsPerPage: 10,
}); });
const visibleColumns = ref<string[]>([ const visibleColumns = ref<string[]>([
"no", "no",
"name", "name",
@ -157,14 +154,6 @@ function filterOption(val: string, update: Function) {
}); });
} }
/**
* function เคลยรอมลสถานะคำรอง
*/
function clearStatus() {
status.value = "ALL";
statusOptions.value = store.optionStatus;
}
/** ฟังชั่น เปิด popup */ /** ฟังชั่น เปิด popup */
function openAdd() { function openAdd() {
router.push("/idp-registry"); router.push("/idp-registry");
@ -172,21 +161,24 @@ function openAdd() {
function onDelete(id: string) { function onDelete(id: string) {
dialogRemove($q, async () => { dialogRemove($q, async () => {
showLoader();
await http await http
.delete(config.API.developmentRequest + `/${id}`) .delete(config.API.developmentRequest + `/${id}`)
.then(async (res) => { .then(async () => {
success($q, "ลบข้อมูลสำเร็จ");
await getListData(); await getListData();
success($q, "ลบข้อมูลสำเร็จ");
}) })
.catch((e) => { .catch((e) => {
messageError($q, e); messageError($q, e);
}) })
.finally(() => {}); .finally(() => {
hideLoader();
});
}); });
} }
/** list รายการ */ /** list รายการ */
async function getListData() { async function getListData() {
showLoader(); isLoading.value = true;
await http await http
.get( .get(
config.API.developmentRequest + config.API.developmentRequest +
@ -199,31 +191,33 @@ async function getListData() {
totalList.value = Math.ceil(dataTotal / pagination.value.rowsPerPage); totalList.value = Math.ceil(dataTotal / pagination.value.rowsPerPage);
total.value = dataTotal; total.value = dataTotal;
rows.value = data; rows.value = data;
hideLoader();
}) })
.catch((e) => { .catch((e) => {
hideLoader(); messageError($q, e);
}) })
.finally(() => {}); .finally(() => {
isLoading.value = false;
});
} }
/** /**
* function หาชอไฟล * function หาชอไฟล
* @param id รายการยนคำรองขอแกไขขอม * @param id รายการยนคำรองขอแกไขขอม
*/ */
function onDownloadFile(id: string) { async function onDownloadFile(id: string) {
showLoader(); showLoader();
http await http
.get(config.API.file("IDP", "ยื่นคำร้องขอเพิ่มข้อมูลการพัฒนารายบุคคล", id)) .get(config.API.file("IDP", "ยื่นคำร้องขอเพิ่มข้อมูลการพัฒนารายบุคคล", id))
.then((res) => { .then(async (res) => {
if (res.data.length !== 0) { if (res.data.length !== 0) {
downloadUrl(id, res.data[0].fileName); await downloadUrl(id, res.data[0].fileName);
} else { } else {
hideLoader();
} }
}) })
.catch((e) => { .catch((e) => {
messageError($q, e); messageError($q, e);
})
.finally(() => {
hideLoader(); hideLoader();
}); });
} }
@ -233,8 +227,8 @@ function onDownloadFile(id: string) {
* @param id รายการยนคำรองขอแกไขขอม * @param id รายการยนคำรองขอแกไขขอม
* @param fileName อไฟล * @param fileName อไฟล
*/ */
function downloadUrl(id: string, fileName: string) { async function downloadUrl(id: string, fileName: string) {
http await http
.get( .get(
config.API.fileByFile( config.API.fileByFile(
"IDP", "IDP",
@ -248,9 +242,6 @@ function downloadUrl(id: string, fileName: string) {
}) })
.catch((e) => { .catch((e) => {
messageError($q, e); messageError($q, e);
})
.finally(() => {
hideLoader();
}); });
} }
@ -374,8 +365,10 @@ onMounted(async () => {
/> />
</div> </div>
<div> <div class="col-12">
<SkeletonTable v-if="isLoading" :columns="columns" />
<d-table <d-table
v-else
:columns="columns" :columns="columns"
:rows="rows" :rows="rows"
row-key="id" row-key="id"

View file

@ -17,13 +17,14 @@ import type {
} from "@/modules/14_IDP/interface/Main"; } from "@/modules/14_IDP/interface/Main";
const $q = useQuasar(); const $q = useQuasar();
const { dialogConfirm, showLoader, hideLoader, messageError, success } =
useCounterMixin();
const dataStore = useDataStore();
const idRow = ref<string>("");
const router = useRouter(); const router = useRouter();
const route = useRoute(); const route = useRoute();
const dataStore = useDataStore();
const { dialogConfirm, showLoader, hideLoader, messageError, success } =
useCounterMixin();
const idRow = ref<string>("");
const isLoading = ref<boolean>(false);
const isReadOnly = ref<boolean>(false); const isReadOnly = ref<boolean>(false);
const isEdit = ref<boolean>(false); // / const isEdit = ref<boolean>(false); // /
const requestId = ref<string>( const requestId = ref<string>(
@ -204,7 +205,7 @@ function downloadUrl(id: string, fileName: string) {
} }
function onSubmit() { function onSubmit() {
dialogConfirm($q, () => { dialogConfirm($q, async () => {
showLoader(); showLoader();
const body = { const body = {
name: formData.topic, name: formData.topic,
@ -219,16 +220,17 @@ function onSubmit() {
isDevelopment10: isDevelopment10.value, isDevelopment10: isDevelopment10.value,
developmentProjects: formData.development, developmentProjects: formData.development,
}; };
http await http
.post(config.API.developmentRequest, body) .post(config.API.developmentRequest, body)
.then(async (res) => { .then(async (res) => {
await createURLUpload(res.data.result, formData.document); await createURLUpload(res.data.result, formData.document);
}) })
.catch((e) => { .catch((e) => {
messageError($q, e); messageError($q, e);
hideLoader();
}) })
.finally(() => {}); .finally(() => {
hideLoader();
});
}); });
} }
@ -256,7 +258,6 @@ async function createURLUpload(id: string, file: any) {
}) })
.catch((err) => { .catch((err) => {
messageError($q, err); messageError($q, err);
hideLoader();
}); });
} }
@ -270,21 +271,18 @@ async function uploadFileDoc(uploadUrl: string, file: any) {
"Content-Type": file.type, "Content-Type": file.type,
}, },
}) })
.then(async (res) => { .then(async () => {
success($q, `บันทึกข้อมูลสำเร็จ`); success($q, `บันทึกข้อมูลสำเร็จ`);
router.push("/idp"); router.push("/idp");
hideLoader();
}) })
.catch((e) => { .catch((e) => {
messageError($q, e); messageError($q, e);
hideLoader(); });
})
.finally(() => {});
} }
function getDetail() { async function getDetail() {
showLoader(); isLoading.value = true;
http await http
.get(config.API.developmentRequest + `/user/${idRow.value}`) .get(config.API.developmentRequest + `/user/${idRow.value}`)
.then((res) => { .then((res) => {
const data = res.data.result; const data = res.data.result;
@ -301,7 +299,7 @@ function getDetail() {
messageError($q, e); messageError($q, e);
}) })
.finally(() => { .finally(() => {
hideLoader(); isLoading.value = false;
}); });
} }
@ -339,7 +337,13 @@ onMounted(() => {
<q-card bordered> <q-card bordered>
<q-form greedy @submit.prevent @validation-success="onSubmit"> <q-form greedy @submit.prevent @validation-success="onSubmit">
<q-card-section> <q-card-section>
<div class="row q-col-gutter-sm"> <div v-if="isLoading" class="q-gutter-md">
<q-skeleton height="150px" />
<q-skeleton height="150px" />
<q-skeleton height="150px" />
</div>
<div v-else class="row q-col-gutter-sm">
<div class="col-12"> <div class="col-12">
<div class="row q-col-gutter-sm"> <div class="row q-col-gutter-sm">
<div class="col-12"> <div class="col-12">
@ -539,6 +543,7 @@ onMounted(() => {
</div> </div>
</div> </div>
</q-card-section> </q-card-section>
<q-separator v-if="!isEdit" /> <q-separator v-if="!isEdit" />
<q-card-actions align="right" v-if="!isEdit"> <q-card-actions align="right" v-if="!isEdit">
<q-btn label="บันทึก" color="secondary" type="submit" <q-btn label="บันทึก" color="secondary" type="submit"

View file

@ -9,6 +9,8 @@ import { useCounterMixin } from "./mixin";
import type { ProfileData, DataProfile } from "@/interface/Main"; import type { ProfileData, DataProfile } from "@/interface/Main";
export const useDataStore = defineStore("dataMain", () => { export const useDataStore = defineStore("dataMain", () => {
const isLoadingMenu = ref<boolean>(false);
const isLoadingProfile = ref<boolean>(false);
const dataProfile = ref<any>(); const dataProfile = ref<any>();
const storeRegistry = useRegistryInFormationStore(); const storeRegistry = useRegistryInFormationStore();
const $q = useQuasar(); const $q = useQuasar();
@ -102,6 +104,7 @@ export const useDataStore = defineStore("dataMain", () => {
} }
async function getData(dataPerson: any) { async function getData(dataPerson: any) {
isLoadingProfile.value = true;
const data = await dataPerson; const data = await dataPerson;
dataprofilePosition.value = data; dataprofilePosition.value = data;
profileId.value = data.profileId; profileId.value = data.profileId;
@ -130,9 +133,11 @@ export const useDataStore = defineStore("dataMain", () => {
formData.org = findOrgName(data); formData.org = findOrgName(data);
storeRegistry.profileId = data.profileId; storeRegistry.profileId = data.profileId;
storeRegistry.citizenId = data.citizenId; storeRegistry.citizenId = data.citizenId;
isLoadingProfile.value = false;
} }
async function getProFileType() { async function getProFileType() {
isLoadingMenu.value = true;
if (officerType.value == "") { if (officerType.value == "") {
await http await http
.get(config.API.proFileType) .get(config.API.proFileType)
@ -144,6 +149,8 @@ export const useDataStore = defineStore("dataMain", () => {
messageError($q, e); messageError($q, e);
}); });
} }
isLoadingMenu.value = false;
return convertEmType(officerType.value); return convertEmType(officerType.value);
} }
@ -172,6 +179,8 @@ export const useDataStore = defineStore("dataMain", () => {
dataProfile, dataProfile,
profileId, profileId,
dataprofilePosition, dataprofilePosition,
isLoadingMenu,
isLoadingProfile,
}; };
}); });