ui ประวัติการศึกษา

This commit is contained in:
Kittapath 2023-03-16 00:35:08 +07:00
parent 792f30d606
commit 0157bf51b9
46 changed files with 1500 additions and 1642 deletions

34
src/api/index.ts Normal file
View file

@ -0,0 +1,34 @@
/**config api */
import { ref } from "vue";
const env = ref<string>(process.env.NODE_ENV || "development");
// if (process.env.VUE_APP_TEST) {
// env = "test";
// }
const config = ref<any>({
development: {
API_URI: "https://localhost:7006/api/v1",
// API_URI: "https://wsh.frappet.com",
MEET_URI: "meet.frappet.com",
},
test: {
API_URI: "http://localhost:5010/api/v1",
MEET_URI: "meet.frappet.com",
},
production: {
// API_URI: "https://localhost:5010",
API_URI: `${window.location.protocol}//api-${window.location.host}/api/v1`,
MEET_URI: "meet.frappet.com",
},
});
const API_URI = ref<string>(config.value[env.value].API_URI);
const MEET_URI = ref<string>(config.value[env.value].MEET_URI);
export default {
env: env.value,
config: config.value,
API_URI: API_URI.value,
MEET_URI: MEET_URI.value,
};

View file

@ -0,0 +1,7 @@
import env from '../index'
const dashbord = `${env.API_URI}/dashbord/`
export default {
countDashbordSubHistory: (type: number) => `${dashbord}${type}`,
countDashbordHistory: `${dashbord}`
}

11
src/app.config.ts Normal file
View file

@ -0,0 +1,11 @@
/**ใช้รวมไฟล์ย่อยๆ ของ api แต่ละไฟล์ */
import manageOrganization from './api/manage/api.organization'
const API = {
...manageOrganization
}
export default {
API: API
}

View file

@ -0,0 +1,126 @@
<template>
<q-card-actions class="text-primary q-py-sm">
<q-btn
flat
round
icon="mdi-menu-left"
@click="clickPrevious"
v-if="modalEdit == true"
:disable="previous == false"
:color="!previous ? 'grey-7' : 'public'"
/>
<q-btn
flat
round
icon="mdi-menu-right"
@click="clickNext"
v-if="modalEdit == true"
:disable="next == false"
:color="!next ? 'grey-7' : 'public'"
/>
<q-space />
<q-btn
v-if="!editvisible"
flat
round
:disabled="editvisible"
:color="editvisible ? 'grey-7' : 'primary'"
@click="edit"
icon="mdi-pencil-outline"
>
<q-tooltip>แกไขขอม</q-tooltip>
</q-btn>
<div v-else>
<q-btn
flat
round
:disabled="!editvisible"
:outline="!editvisible"
:color="!editvisible ? 'grey-7' : 'red'"
@click="cancel()"
icon="mdi-undo"
v-if="modalEdit == true"
>
<q-tooltip>ยกเล</q-tooltip>
</q-btn>
<q-btn
flat
round
:disabled="!editvisible"
:color="!editvisible ? 'grey-7' : 'public'"
@click="checkSave"
icon="mdi-content-save-outline"
>
<q-tooltip>นท</q-tooltip>
</q-btn>
</div>
</q-card-actions>
</template>
<script setup lang="ts">
import { ref, useAttrs } from "vue";
const props = defineProps({
editvisible: Boolean,
next: Boolean,
previous: Boolean,
modalEdit: Boolean,
clickNext: {
type: Function,
default: () => console.log("not function"),
},
clickPrevious: {
type: Function,
default: () => console.log("not function"),
},
cancel: {
type: Function,
default: () => console.log("not function"),
},
edit: {
type: Function,
default: () => console.log("not function"),
},
save: {
type: Function,
default: () => console.log("not function"),
},
validate: {
type: Function,
default: () => console.log("not function"),
},
});
const emit = defineEmits([
"update:editvisible",
"update:next",
"update:previous",
]);
const updateEdit = (value: Boolean) => {
emit("update:editvisible", value);
};
const cancel = async () => {
props.cancel();
};
const edit = async () => {
updateEdit(!props.editvisible);
props.edit();
};
const checkSave = () => {
props.validate();
props.save();
// if (myForm.value !== null) {
// myForm.value.validate().then((success) => {
// if (success) {
// }
// });
// }
};
const clickNext = async () => {
await props.clickNext();
};
const clickPrevious = async () => {
await props.clickPrevious();
};
</script>

View file

@ -0,0 +1,32 @@
<template>
<q-card-section class="row items-center col-12 q-py-sm">
<div class="row col-11">
<div class="text-bold">{{ tittle }}</div>
</div>
<q-space />
<!-- <div class="row col-1"> -->
<q-btn
icon="close"
unelevated
round
dense
@click="close"
style="color: #ff8080; background-color: #ffdede"
/>
<!-- </div> -->
</q-card-section>
</template>
<script setup lang="ts">
import { ref, useAttrs } from "vue";
const props = defineProps({
tittle: String,
close: {
type: Function,
default: () => console.log("not function"),
},
});
const close = async () => {
props.close();
};
</script>

View file

@ -0,0 +1,92 @@
<template>
<q-dialog
:model-value="modalError"
persistent
@update:model-value="updateClose"
>
<q-card class="q-pa-sm">
<q-card-section class="row items-center">
<div class="q-pr-md">
<q-avatar
icon="mdi-alert-circle-outline"
font-size="25px"
size="lg"
color="red-1"
text-color="red"
/>
</div>
<div class="col text-dark">
<span class="text-bold">{{ modalErrorTittle }}</span>
<br />
<span>{{ modalErrorDetail }}</span>
</div>
</q-card-section>
<q-card-actions align="right" class="bg-white text-teal">
<q-btn
label="ตกลง"
color="primary"
@click="updateClose"
v-close-popup
/>
</q-card-actions>
</q-card>
</q-dialog>
</template>
<script setup lang="ts">
import { ref, useAttrs } from "vue";
const props = defineProps({
modalError: Boolean,
modalErrorTittle: String,
modalErrorDetail: String,
close: {
type: Function,
default: () => console.log("not function"),
},
});
const emit = defineEmits([
"update:modalError",
"update:modalErrorTittle",
"update:modalErrorDetail",
]);
const updateClose = () => {
emit("update:modalError", false);
emit("update:modalErrorTittle", "");
emit("update:modalErrorDetail", "");
props.close();
};
</script>
<style lang="scss">
.icon-color {
color: #4154b3;
}
.custom-header-table {
max-height: 64vh;
.q-table tr:nth-child(odd) td {
background: white;
}
.q-table tr:nth-child(even) td {
background: #f6f6f6ae;
}
.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>

199
src/components/Table.vue Normal file
View file

@ -0,0 +1,199 @@
<template>
<div class="q-pb-sm row">
<!-- -->
<HeaderTop
v-model:edit="editBtn"
:header="name"
:icon="icon"
:add="checkAdd"
:addData="true"
:history="false"
v-if="nameHeader"
/>
<q-btn size="12px" flat round color="add" @click="add" icon="mdi-plus">
<q-tooltip>เพมขอม</q-tooltip>
</q-btn>
<q-space />
<div class="items-center" style="display: flex">
<!-- นหาขอความใน table -->
<q-input
standout
dense
:model-value="inputfilter"
ref="filterRef"
@update:model-value="updateInput"
outlined
debounce="300"
placeholder="ค้นหา"
style="max-width: 200px"
class="q-ml-sm"
>
<template v-slot:append>
<q-icon v-if="inputfilter == ''" name="search" />
<q-icon
v-if="inputfilter !== ''"
name="clear"
class="cursor-pointer"
@click="resetFilter"
/>
</template>
</q-input>
<!-- แสดงคอลมนใน table -->
<q-select
:model-value="inputvisible"
@update:model-value="updateVisible"
:display-value="$q.lang.table.columns"
multiple
outlined
dense
:options="attrs.columns"
options-dense
option-value="name"
map-options
emit-value
style="min-width: 150px"
class="gt-xs q-ml-sm"
/>
</div>
</div>
<q-table
ref="table"
flat
bordered
class="custom-header-table"
v-bind="attrs"
virtual-scroll
:virtual-scroll-sticky-size-start="48"
dense
:pagination-label="paginationLabel"
:pagination="initialPagination"
:rows-per-page-options="[0]"
>
<template v-slot:header="props">
<q-tr :props="props">
<q-th v-for="col in props.cols" :key="col.name" :props="props">
<span class="text-weight-medium">{{ col.label }}</span>
</q-th>
</q-tr>
</template>
<template #body="props">
<slot v-bind="props" name="columns"></slot>
</template>
</q-table>
</template>
<script setup lang="ts">
import { ref, useAttrs } from 'vue'
import HeaderTop from '@/components/top.vue'
import type { Pagination } from '@/modules/01_exam/interface/index/Main'
const attrs = ref<any>(useAttrs())
const table = ref<any>(null)
const filterRef = ref<any>(null)
const editBtn = ref<boolean>(false)
const initialPagination = ref<Pagination>({
// descending: false,
rowsPerPage: 0
})
const props = defineProps({
inputfilter: String,
name: String,
icon: String,
inputvisible: Array,
editvisible: Boolean,
nameHeader: Boolean,
edit: {
type: Function,
default: () => console.log('not function')
},
add: {
type: Function,
default: () => console.log('not function')
},
cancel: {
type: Function,
default: () => console.log('not function')
},
validate: {
type: Function,
default: () => console.log('not function')
}
})
const emit = defineEmits(['update:inputfilter', 'update:inputvisible', 'update:editvisible'])
const updateEdit = (value: Boolean) => {
emit('update:editvisible', value)
}
const updateInput = (value: string | number | null) => {
emit('update:inputfilter', value)
}
const updateVisible = (value: []) => {
emit('update:inputvisible', value)
}
const paginationLabel = (start: string, end: string, total: string) => {
return start + '-' + end + ' ใน ' + total
}
const checkAdd = () => {
// props.validate();
props.add()
}
const edit = async () => {
updateEdit(!props.editvisible)
props.edit()
}
const cancel = async () => {
updateEdit(!props.editvisible)
props.cancel()
}
const resetFilter = () => {
// reset X
emit('update:inputfilter', '')
filterRef.value.focus()
}
const add = () => {
props.add()
}
</script>
<style lang="scss">
.icon-color {
color: #4154b3;
}
.custom-header-table {
max-height: 64vh;
.q-table tr:nth-child(odd) td {
background: white;
}
.q-table tr:nth-child(even) td {
background: #f6f6f6ae;
}
.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>

172
src/components/top.vue Normal file
View file

@ -0,0 +1,172 @@
<template>
<div class="flex items-center">
<div class="flex items-center">
<q-icon :name="icon" size="1.5em" color="grey-5" class="q-mr-md" />
<div
class="text-weight-medium text-dark col-12 row items-center text-header"
>
{{ header }}
</div>
</div>
<div class="q-gutter-sm q-mx-sm" v-if="addData == false">
<!-- <q-btn
dense
outline
label="แก้ไข"
icon="mdi-pencil-outline"
iconsize
v-if="!edit"
@click="ClickEdit"
>
<q-tooltip>แกไขขอม</q-tooltip>
</q-btn> -->
<q-btn
size="12px"
v-if="!edit"
flat
round
:disabled="edit"
:color="edit ? 'grey-7' : 'primary'"
@click="ClickEdit"
icon="mdi-pencil-outline"
>
<q-tooltip>แกไขขอม</q-tooltip>
</q-btn>
<!-- <q-btn
color="primary"
dense
label="บันทึก"
icon="mdi-content-save"
v-if="edit"
@click="save"
>
<q-tooltip>นทกขอม</q-tooltip>
</q-btn> -->
<q-btn
size="12px"
flat
round
v-if="edit"
:disabled="!edit"
:color="!edit ? 'grey-7' : 'public'"
@click="save"
icon="mdi-content-save-outline"
>
<q-tooltip>นทกขอม</q-tooltip>
</q-btn>
<!-- <q-btn
style="background: white; color: red"
dense
label="ยกเลิก"
icon="mdi-close-outline"
v-if="edit"
@click="ClickCancel"
>
<q-tooltip>ยกเล</q-tooltip>
</q-btn> -->
<q-btn
size="12px"
flat
round
v-if="edit"
:disabled="!edit"
:color="!edit ? 'grey-7' : 'red'"
@click="ClickCancel"
icon="mdi-undo"
>
<q-tooltip>ยกเล</q-tooltip>
</q-btn>
</div>
<div class="q-pl-sm" v-else>
<q-btn size="12px" flat round color="add" @click="add" icon="mdi-plus">
<q-tooltip>เพมขอม</q-tooltip>
</q-btn>
</div>
<q-space/>
<q-btn
color="info"
flat
dense
round
size="14px"
icon="mdi-history"
v-if="history"
>
<q-tooltip>ประว{{header}}</q-tooltip>
</q-btn>
</div>
</template>
<script setup lang="ts">
import { ref, useAttrs } from "vue";
const props = defineProps({
header: {
type: String,
default: "ข้อความ",
required: true,
},
icon: {
type: String,
default: "mdi-help",
required: true,
},
edit: {
type: Boolean,
default: true,
required: true,
},
history: {
type: Boolean,
default: true,
required: true,
},
addData: {
type: Boolean,
defualt: false,
},
add: {
type: Function,
default: () => console.log("not function"),
},
save: {
type: Function,
default: () => console.log("not function"),
},
deleted: {
type: Function,
default: () => console.log("not function"),
},
cancel: {
type: Function,
default: () => console.log("not function"),
},
});
const emit = defineEmits(["update:edit"]);
const updateEdit = (value: any) => {
emit("update:edit", value);
};
const ClickEdit = () => {
updateEdit(!props.edit);
};
const ClickCancel = () => {
updateEdit(!props.edit);
props.cancel();
};
const save = () => {
props.save();
};
const add = () => {
props.add();
};
</script>
<style scoped>
/* .q-btn >>> .q-icon {
font-size: 20px;
} */
</style>

View file

@ -38,5 +38,17 @@ app.component(
'data-table',
defineAsyncComponent(() => import('./components/TableView.vue'))
)
app.component(
'notifyError',
defineAsyncComponent(() => import('./components/NotifyError.vue'))
)
app.component(
'datepicker',
defineAsyncComponent(() => import('@vuepic/vue-datepicker'))
)
app.component(
'full-loader',
defineAsyncComponent(() => import('./plugins/FullLoader.vue'))
)
app.mount('#app')

View file

@ -0,0 +1,4 @@
<template>
<div></div>
</template>
<script setup lang="ts"></script>

View file

@ -0,0 +1,554 @@
<!-- card ประวการศกษา -->
<template>
<q-card flat bordered class="col-12 q-px-lg q-py-md">
<q-form ref="myForm">
<ProfileTable
:rows="rows"
:columns="columns"
:filter="filter"
:visible-columns="visibleColumns"
v-model:inputfilter="filter"
v-model:inputvisible="visibleColumns"
:add="clickAdd"
:nameHeader="false"
>
<template #columns="props">
<q-tr :props="props">
<q-td
v-for="col in props.cols"
:key="col.name"
:props="props"
@click="selectData(props)"
class="cursor-pointer"
>
<div v-if="col.name == 'start'" class="">
{{ col.value + 543 }}
</div>
<div v-else-if="col.name == 'end'" class="">
{{ col.value + 543 }}
</div>
<div v-else class="">
{{ col.value }}
</div>
</q-td>
</q-tr>
</template>
</ProfileTable>
</q-form>
</q-card>
<!-- popup Edit window-->
<q-dialog v-model="modal" persistent>
<q-card style="width: 600px">
<q-form ref="myForm">
<DialogHeader tittle="ประวัติการศึกษา" :close="clickClose" />
<q-separator />
<q-card-section class="q-p-sm">
<div class="row col-12 items-center q-col-gutter-x-xs q-col-gutter-y-xs">
<div class="col-xs-6 col-sm-6 col-md-6">
<q-select
:class="getClass(edit)"
hide-bottom-space
:outlined="edit"
dense
lazy-rules
:readonly="!edit"
:borderless="!edit"
v-model="qualificationId"
:rules="[(val) => !!val || `${'กรุณาเลือกระดับการศึกษา'}`]"
:label="`${'ระดับการศึกษา'}`"
@update:modelValue="clickEditRow"
emit-value
map-options
option-label="name"
:options="qualificationOptions"
option-value="id"
/>
</div>
<div class="col-xs-6 col-sm-6 col-md-6">
<q-input
:class="getClass(edit)"
hide-bottom-space
:outlined="edit"
dense
lazy-rules
:readonly="!edit"
:borderless="!edit"
v-model="name"
:rules="[(val) => !!val || `${'กรุณากรอกสถานศึกษา'}`]"
:label="`${'สถานศึกษา'}`"
@update:modelValue="clickEditRow"
/>
</div>
<div class="col-xs-6 col-sm-6 col-md-6">
<q-input
:class="getClass(edit)"
hide-bottom-space
:outlined="edit"
dense
lazy-rules
:readonly="!edit"
:borderless="!edit"
v-model="major"
:rules="[(val) => !!val || `${'กรุณากรอกสาขา/วิชาเอก'}`]"
:label="`${'สาขา/วิชาเอก'}`"
@update:modelValue="clickEditRow"
/>
</div>
</div>
</q-card-section>
<q-separator />
<DialogFooter
:cancel="clickCancel"
:edit="clickEdit"
:save="clickSave"
:validate="validateData"
:clickNext="clickNext"
:clickPrevious="clickPrevious"
v-model:editvisible="edit"
v-model:next="next"
v-model:previous="previous"
v-model:modalEdit="modalEdit"
/>
</q-form>
</q-card>
</q-dialog>
<notifyError
:modalError="modalError"
:modalErrorTittle="modalErrorTittle"
:modalErrorDetail="modalErrorDetail"
:close="closeModalError"
></notifyError>
</template>
<script setup lang="ts">
import { onMounted, ref, watch } from 'vue'
import { useExamDataStore } from '@/modules/01_exam/store'
import ProfileTable from '@/components/Table.vue'
import DialogHeader from '@/components/DialogHeader.vue'
import DialogFooter from '@/components/DialogFooter.vue'
import { useQuasar } from 'quasar'
import type {
RequestItemsObject,
Columns,
DataProps
} from '@/modules/01_exam/interface/request/Education'
import type { ResponseObject } from '@/modules/01_exam/interface/response/Education'
import type { DataOption } from '@/modules/01_exam/interface/index/Main'
import http from '@/plugins/http'
import config from '@/app.config'
const props = defineProps({
loader: {
// main refresh data
type: Boolean,
required: true
}
})
const $q = useQuasar()
const store = useExamDataStore()
const { examData, changeExamColumns } = store
const loader = ref<boolean>(false)
const id = ref<string>()
const qualification = ref<string>()
const qualificationId = ref<string>()
const qualificationOptions = ref<DataOption[]>([])
const major = ref<string>()
const scores = ref<number | null>()
const name = ref<string>()
const duration = ref<any>()
const myForm = ref<any>() //form data input
const edit = ref<boolean>(false) // dialog
const modal = ref<boolean>(false) //modal add detail
const modalEdit = ref<boolean>(false) //modal
const rawItem = ref<RequestItemsObject>() // row
const rowIndex = ref<number>(0) //index row
const previous = ref<boolean>() //
const next = ref<boolean>() //
const editRow = ref<boolean>(false) //
const rawHistory = ref<RequestItemsObject[]>([]) //raw data history
const modalError = ref<boolean>(false) // modal error
const modalErrorTittle = ref<string>('') // tittle modal error
const modalErrorDetail = ref<string>('') // detail modal error
const statusCode = ref<number>()
const checkValidate = ref<boolean>(false) //validate data
const closeModalError = () => {
modalError.value = false
if (statusCode.value != 404) {
// fetchData();
}
}
const emit = defineEmits(['update:loader'])
const rows = ref<RequestItemsObject[]>([
{
id: '1',
qualificationId: 'ปริญญาตรี',
qualification: 'ปริญญาตรี',
major: 'คอมพิวเตอร์',
scores: 3.99,
name: 'มหาลัยเอ',
duration: 2015
},
{
id: '2',
qualificationId: 'ปริญญาเอก',
qualification: 'ปริญญาเอก',
major: 'คอมพิวเตอร์',
scores: 3.54,
name: 'มหาลัยบี',
duration: 2015
}
])
const filter = ref<string>('') //search data table
const visibleColumns = ref<String[]>([])
examData.education.columns.length == 0
? (visibleColumns.value = ['qualification', 'major', 'scores', 'name', 'duration'])
: (visibleColumns.value = examData.education.columns)
const columns = ref<Columns>([
{
name: 'qualification',
align: 'left',
label: 'วุฒิที่ได้รับ',
sortable: true,
field: 'qualification',
headerStyle: 'font-size: 14px',
style: 'font-size: 14px'
},
{
name: 'major',
align: 'left',
label: 'สาขาวิชา/วิชาเอก',
sortable: true,
field: 'major',
headerStyle: 'font-size: 14px',
style: 'font-size: 14px'
},
{
name: 'scores',
align: 'left',
label: 'คะแนนเฉลี่ยตลอดหลักสูตร',
sortable: true,
field: 'scores',
headerStyle: 'font-size: 14px',
style: 'font-size: 14px'
},
{
name: 'name',
align: 'left',
label: 'ชื่อสถานศึกษา',
sortable: true,
field: 'name',
headerStyle: 'font-size: 14px',
style: 'font-size: 14px'
},
{
name: 'duration',
align: 'left',
label: 'ระยะเวลา',
sortable: true,
field: 'duration',
headerStyle: 'font-size: 14px',
style: 'font-size: 14px'
}
])
watch(loader, (count: boolean, prevCount: boolean) => {
emit('update:loader', count)
})
watch(visibleColumns, async (count: String[], prevCount: String[]) => {
await changeExamColumns('education', count)
})
onMounted(async () => {
// await fetchData()
// await fetchQualification()
rawHistory.value = rows.value
})
const fetchQualification = async () => {
// loader.value = true;
await http
.get(config.API.educationQualification)
.then((res) => {
const data = res.data.result
let option: DataOption[] = []
data.map((r: any) => {
option.push({ id: r.id.toString(), name: r.name.toString() })
})
qualificationOptions.value = option
})
.catch((e: any) => {})
.finally(() => {
// loader.value = false;
})
}
const fetchData = async () => {}
/**
* กดดอมลกอนหน
*/
const clickPrevious = () => {
edit.value = false
rowIndex.value -= 1
const row = rows.value[rowIndex.value]
qualification.value = row.qualification
qualificationId.value = row.qualificationId
major.value = row.major
scores.value = row.scores
name.value = row.name
duration.value = row.duration
id.value = row.id
checkRowPage()
}
/**
* กดดอมลตอไป
*/
const clickNext = () => {
edit.value = false
rowIndex.value += 1
const row = rows.value[rowIndex.value]
qualification.value = row.qualification
qualificationId.value = row.qualificationId
major.value = row.major
scores.value = row.scores
name.value = row.name
duration.value = row.duration
id.value = row.id
checkRowPage()
}
/**
* กดดอมลตอไป
*/
const getData = () => {
const row = rows.value[rowIndex.value]
qualification.value = row.qualification
qualificationId.value = row.qualificationId
major.value = row.major
scores.value = row.scores
name.value = row.name
duration.value = row.duration
id.value = row.id
}
/**
* เชคปมดอม อน อไป าตองแสดงไหม
*/
const checkRowPage = () => {
editRow.value = false
next.value = true
previous.value = true
if (rowIndex.value + 1 >= rows.value.length) {
next.value = false
}
if (rowIndex.value - 1 < 0) {
previous.value = false
}
}
/**
* กดปมแกไขใน dialog
*/
const clickEdit = () => {
next.value = false
previous.value = false
}
/**
* กดปมเพมดานบน table
*/
const clickAdd = () => {
addData()
}
/**
* กดบนทกใน dialog
*/
const clickSave = async () => {
myForm.value.validate().then(async (result: boolean) => {
if (result) {
if (modalEdit.value) {
await editData()
} else {
await saveData()
}
}
})
}
/**
* นทกเพมขอม
*/
const saveData = async () => {
modal.value = false
// loader.value = true;
// await http
// .post(config.API.xxxxxxxxxxxxxxx, {
// xxx: "xxx",
// })
// .then((res) => {
// success($q, "");
// })
// .catch((e) => {
// modalError.value = true;
// modalErrorTittle.value = "";
// modalErrorDetail.value = e.response.data.message;
// statusCode.value = e.response.data.status;
// })
// .finally(async () => {
// modal.value = false;
// await fetchData();
// });
}
/**
* นทกแกไขขอม
*/
const editData = async () => {
edit.value = false
// loader.value = true;
// await http
// .post(config.API.xxxxxxxxxxxxxxx(id.value), {
// xxx: "xxx",
// })
// .then((res) => {
// success($q, "");
// })
// .catch((e) => {
// modalError.value = true;
// modalErrorTittle.value = "";
// modalErrorDetail.value = e.response.data.message;
// statusCode.value = e.response.data.status;
// })
// .finally(async () => {
// edit.value = false;
// await fetchData();
// });
}
/**
* กดป dialog
*/
const clickClose = async () => {
if (editRow.value == true) {
$q.dialog({
title: `ข้อมูลมีการแก้ไข`,
message: `ยืนยันการบันทึกข้อมูลใช่หรือไม่?`,
cancel: 'ยกเลิก',
ok: 'ยืนยัน',
persistent: true
}).onOk(async () => {
modal.value = false
next.value = false
previous.value = false
await getData()
})
} else {
modal.value = false
next.value = false
previous.value = false
}
}
/**
* กดเลอกขอมลทจะแกไข
* @param props props ใน row เลอก
*/
const selectData = (props: DataProps) => {
modalEdit.value = true
modal.value = true
edit.value = false
rawItem.value = props.row
rowIndex.value = props.rowIndex
qualification.value = props.row.qualification
qualificationId.value = props.row.qualificationId
major.value = props.row.major
scores.value = props.row.scores
name.value = props.row.name
duration.value = props.row.duration
id.value = props.row.id
checkRowPage()
}
/**
* กดปมเพมบน table
*/
const addData = () => {
modalEdit.value = false
modal.value = true
edit.value = true
qualification.value = ''
qualificationId.value = ''
major.value = ''
scores.value = null
name.value = ''
duration.value = ''
}
/**
* งกนปมยกเลกการแกไขขอม
*/
const clickCancel = async () => {
if (editRow.value == true) {
$q.dialog({
title: `ข้อมูลมีการแก้ไข`,
message: `ยืนยันการบันทึกข้อมูลใช่หรือไม่?`,
cancel: 'ยกเลิก',
ok: 'ยืนยัน',
persistent: true
}).onOk(async () => {
edit.value = false
checkRowPage()
await getData()
})
} else {
edit.value = false
checkRowPage()
}
}
/**
* เชความการแกไขขอม
*/
const clickEditRow = () => {
editRow.value = true
}
/**
* validate input ใน dialog
*/
const validateData = async () => {
checkValidate.value = true
await myForm.value.validate().then((result: boolean) => {
if (result == false) {
checkValidate.value = false
}
})
}
/**
* class ดรปแบบแสดงระหวางขอมลทแกไขหรอแสดงเฉยๆ
* @param val อม input สำหรบแกไขหรอไม
*/
const getClass = (val: boolean) => {
return {
'full-width inputgreen cursor-pointer': val,
'full-width cursor-pointer': !val
}
}
</script>
<style lang="scss">
.modalfix {
position: fixed !important;
}
</style>

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,4 @@
<template>
<div></div>
</template>
<script setup lang="ts"></script>

View file

@ -1,29 +0,0 @@
interface DataProps {
row: RequestItemsObject;
rowIndex: number;
}
//ข้อมูล
interface RequestItemsObject {
id: string;
name: string;
certiNumber: string;
start: Date;
end: Date;
}
//columns
interface Columns {
[index: number]: {
name: String;
align: String;
label: String;
sortable: Boolean;
field: String;
headerStyle: String;
style: String;
};
}
export type { RequestItemsObject, Columns, DataProps };

View file

@ -1,27 +0,0 @@
interface DataProps {
row: RequestItemsObject;
rowIndex: number;
}
//ข้อมูล
interface RequestItemsObject {
id: string;
receiveDate: Date;
detail: string;
agency: string;
}
//columns
interface Columns {
[index: number]: {
name: String;
align: String;
label: String;
sortable: Boolean;
field: String;
headerStyle: String;
style: String;
};
}
export type { RequestItemsObject, Columns, DataProps };

View file

@ -1,29 +0,0 @@
interface DataProps {
row: RequestItemsObject;
rowIndex: number;
}
//ข้อมูล
interface RequestItemsObject {
id: string;
date: Date;
status: string;
level: string;
refNo: string;
refDate: Date;
}
//columns
interface Columns {
[index: number]: {
name: String;
align: String;
label: String;
sortable: Boolean;
field: String;
headerStyle: String;
style: String;
};
}
export type { RequestItemsObject, Columns, DataProps };

View file

@ -1,19 +0,0 @@
//ข้อมูล
interface RequestItemsObject {
name: String;
}
//columns
interface Columns {
[index: number]: {
name: String;
align: String;
label: String;
sortable: Boolean;
field: String;
headerStyle: String;
style: String;
};
}
export type { RequestItemsObject, Columns };

View file

@ -1,31 +1,30 @@
interface DataProps {
row: RequestItemsObject;
rowIndex: number;
row: RequestItemsObject
rowIndex: number
}
//ข้อมูล
interface RequestItemsObject {
id: string;
level: string;
levelId: string;
name: string;
start: number;
end: number;
education: string;
major: string;
id: string
qualificationId: string
qualification: string
major: string
scores: number | null
name: string
duration: any
}
//columns
interface Columns {
[index: number]: {
name: String;
align: String;
label: String;
sortable: Boolean;
field: String;
headerStyle: String;
style: String;
};
name: String
align: String
label: String
sortable: Boolean
field: String
headerStyle: String
style: String
}
}
export type { RequestItemsObject, Columns, DataProps };
export type { RequestItemsObject, Columns, DataProps }

View file

@ -1,36 +0,0 @@
interface DataProps {
row: RequestItemsObject;
rowIndex: number;
}
//ข้อมูล
interface RequestItemsObject {
id: string;
year: number;
receiveDate: Date;
insigniaType: string;
insigniaTypeId: string;
insignia: string;
insigniaId: string;
no: string;
gazetteNo: string;
volume: string;
book: string;
section: string;
page: string;
}
//columns
interface Columns {
[index: number]: {
name: String;
align: String;
label: String;
sortable: Boolean;
field: String;
headerStyle: String;
style: String;
};
}
export type { RequestItemsObject, Columns, DataProps };

View file

@ -1,38 +0,0 @@
interface DataProps {
row: RequestItemsObject;
rowIndex: number;
}
//ข้อมูล
interface RequestItemsObject {
id: string;
year: number;
holiday: string;
sick: string;
government: string;
late: string;
other: string;
business: string;
maternity: string;
helpMaternity: string;
ordination: string;
study: string;
international: string;
spouse: string;
rehabilitation: string;
}
//columns
interface Columns {
[index: number]: {
name: String;
align: String;
label: String;
sortable: Boolean;
field: String;
headerStyle: String;
style: String;
};
}
export type { RequestItemsObject, Columns, DataProps };

View file

@ -1,25 +0,0 @@
interface DataProps {
row: RequestItemsObject;
rowIndex: number;
}
//ข้อมูล
interface RequestItemsObject {
id: string;
detail: string;
}
//columns
interface Columns {
[index: number]: {
name: String;
align: String;
label: String;
sortable: Boolean;
field: String;
headerStyle: String;
style: String;
};
}
export type { RequestItemsObject, Columns, DataProps };

View file

@ -1,27 +0,0 @@
interface DataProps {
row: RequestItemsObject;
rowIndex: number;
}
//ข้อมูล
interface RequestItemsObject {
id: string;
date: Date;
detail: string;
reference: string;
}
//columns
interface Columns {
[index: number]: {
name: String;
align: String;
label: String;
sortable: Boolean;
field: String;
headerStyle: String;
style: String;
};
}
export type { RequestItemsObject, Columns, DataProps };

View file

@ -1,33 +0,0 @@
interface DataProps {
row: RequestItemsObject;
rowIndex: number;
}
//ข้อมูล
interface RequestItemsObject {
id: string;
date: Date;
position: string;
positionId: string;
posNo: string;
posNoId: string;
level: string;
levelId: string;
salary: string;
reference: string;
}
//columns
interface Columns {
[index: number]: {
name: String;
align: String;
label: String;
sortable: Boolean;
field: String;
headerStyle: String;
style: String;
};
}
export type { RequestItemsObject, Columns, DataProps };

View file

@ -1,27 +0,0 @@
interface DataProps {
row: RequestItemsObject;
rowIndex: number;
}
//ข้อมูล
interface RequestItemsObject {
id: string;
side: string;
detail: string;
note: string;
}
//columns
interface Columns {
[index: number]: {
name: String;
align: String;
label: String;
sortable: Boolean;
field: String;
headerStyle: String;
style: String;
};
}
export type { RequestItemsObject, Columns, DataProps };

View file

@ -1,31 +0,0 @@
interface DataProps {
row: RequestItemsObject;
rowIndex: number;
}
//ข้อมูล
interface RequestItemsObject {
id: string;
course: string;
start: Date;
end: Date;
location: string;
detail: string;
organize: string;
gen: string;
}
//columns
interface Columns {
[index: number]: {
name: String;
align: String;
label: String;
sortable: Boolean;
field: String;
headerStyle: String;
style: String;
};
}
export type { RequestItemsObject, Columns, DataProps };

View file

@ -1,28 +0,0 @@
interface DataProps {
row: RequestItemsObject;
rowIndex: number;
}
//ข้อมูล
interface RequestItemsObject {
id: string;
start: Date;
end: Date;
detail: string;
reference: string;
}
//columns
interface Columns {
[index: number]: {
name: String;
align: String;
label: String;
sortable: Boolean;
field: String;
headerStyle: String;
style: String;
};
}
export type { RequestItemsObject, Columns, DataProps };

View file

@ -1,11 +0,0 @@
//ข้อมูล
interface ResponseObject {
id: string;
date: Date;
status: string;
level: string;
refNo: string;
refDate: Date;
}
export type { ResponseObject };

View file

@ -1,9 +0,0 @@
//ข้อมูล
interface ResponseObject {
id: string;
receiveDate: Date;
detail: string;
agency: string;
}
export type { ResponseObject };

View file

@ -1,11 +0,0 @@
//ข้อมูล
interface ResponseObject {
id: string;
date: Date;
status: string;
level: string;
refNo: string;
refDate: Date;
}
export type { ResponseObject };

View file

@ -1,6 +0,0 @@
//ข้อมูล
interface ResponseObject {
name: String;
}
export type { ResponseObject };

View file

@ -1,13 +1,12 @@
//ข้อมูล
interface ResponseObject {
id: string;
level: string;
levelId: string;
name: string;
start: number;
end: number;
education: string;
major: string;
id: string
qualificationId: string
qualification: string
major: string
scores: number | null
name: string
duration: any
}
export type { ResponseObject };
export type { ResponseObject }

View file

@ -1,18 +0,0 @@
//ข้อมูล
interface ResponseObject {
id: string;
year: number;
receiveDate: Date;
insigniaType: string;
insigniaTypeId: string;
insignia: string;
insigniaId: string;
no: string;
gazetteNo: string;
volume: string;
book: string;
section: string;
page: string;
}
export type { ResponseObject };

View file

@ -1,20 +0,0 @@
//ข้อมูล
interface ResponseObject {
id: string;
year: number;
holiday: string;
sick: string;
government: string;
late: string;
other: string;
business: string;
maternity: string;
helpMaternity: string;
ordination: string;
study: string;
international: string;
spouse: string;
rehabilitation: string;
}
export type { ResponseObject };

View file

@ -1,7 +0,0 @@
//ข้อมูล
interface ResponseObject {
id: string;
detail: string;
}
export type { ResponseObject };

View file

@ -1,9 +0,0 @@
//ข้อมูล
interface ResponseObject {
id: string;
date: Date;
detail: string;
reference: string;
}
export type { ResponseObject };

View file

@ -1,15 +0,0 @@
//ข้อมูล
interface ResponseObject {
id: string;
date: Date;
position: string;
positionId: string;
posNo: string;
posNoId: string;
level: string;
levelId: string;
salary: string;
reference: string;
}
export type { ResponseObject };

View file

@ -1,9 +0,0 @@
//ข้อมูล
interface ResponseObject {
id: string;
side: string;
detail: string;
note: string;
}
export type { ResponseObject };

View file

@ -1,13 +0,0 @@
//ข้อมูล
interface ResponseObject {
id: string;
course: string;
start: Date;
end: Date;
location: string;
detail: string;
organize: string;
gen: string;
}
export type { ResponseObject };

View file

@ -1,10 +0,0 @@
//ข้อมูล
interface ResponseObject {
id: string;
start: Date;
end: Date;
detail: string;
reference: string;
}
export type { ResponseObject };

View file

@ -4,14 +4,17 @@ import { defineStore } from 'pinia'
export const useExamDataStore = defineStore('exam', () => {
interface exam {
main: { columns: String[] }
education: { columns: String[] }
}
const examData = ref<exam>({
main: { columns: [] }
main: { columns: [] },
education: { columns: [] }
})
const changeExamColumns = (system: String, val: String[]) => {
if (system == 'main') examData.value.main.columns = val
if (system == 'education') examData.value.education.columns = val
localStorage.setItem('exam', JSON.stringify(examData.value))
}

View file

@ -0,0 +1,21 @@
<!-- แสดง ui การโหลด -->
<template>
<div>
<q-inner-loading :showing="loaderVisibility">
<q-spinner-cube size="80px" color="primary" />
</q-inner-loading>
</div>
</template>
<script setup lang="ts">
import { watch, ref } from "vue";
const props = defineProps({
visibility: Boolean,
});
const loaderVisibility = ref<boolean>(props.visibility);
watch(props, (count, prevCount) => {
loaderVisibility.value = props.visibility;
});
</script>

25
src/plugins/axios.ts Normal file
View file

@ -0,0 +1,25 @@
import axios from "axios"
import config from "process"
// import { dotnetPath } from "../path/axiosPath";
// import { getToken } from "@baloise/vue-keycloak";
import keycloak from "../plugins/keycloak"
const axiosInstance = axios.create({
withCredentials: false,
})
// axiosInstance.defaults.baseURL = dotnetPath;
axiosInstance.interceptors.request.use(
async (config) => {
const token = await keycloak.token
config.headers = {
Authorization: `Bearer ${token}`,
}
return config
},
(error) => {
Promise.reject(error)
}
)
export default axiosInstance

45
src/plugins/http.ts Normal file
View file

@ -0,0 +1,45 @@
import Axios, { type AxiosRequestConfig, type AxiosResponse } from "axios";
import keycloak from "./keycloak";
const http = Axios.create({
timeout: 1000000000, // เพิ่มค่า timeout
headers: {
"X-Requested-With": "XMLHttpRequest",
},
});
http.interceptors.request.use(
async function (config: AxiosRequestConfig<any>) {
await keycloak.updateToken(1);
config.headers = config.headers ?? {};
const token = keycloak.token;
// const token = localStorage.getItem("access_token")
// const token =
// "eyJhbGciOiJSUzI1NiIsInR5cCIgOiAiSldUIiwia2lkIiA6ICIxU2VKV2dVRFVlNXZwNS13Q1ZHaG9lT2l4bDJTTkdKemthLU5ZN211NXZJIn0.eyJleHAiOjE2NzI0MTI1NDksImlhdCI6MTY3MjM3NjU0OSwiYXV0aF90aW1lIjoxNjcyMzc2NTQ5LCJqdGkiOiI1MTVhY2IwNC1jODQ3LTQzM2YtYjUxOC03ODUzMzJhY2ZjNWYiLCJpc3MiOiJodHRwczovL2tleWNsb2FrLmZyYXBwZXQuc3lub2xvZ3kubWUvYXV0aC9yZWFsbXMvYm1hLWVociIsImF1ZCI6ImFjY291bnQiLCJzdWIiOiJlZmM5YjRlMC1mZGU2LTQ1NDQtYmU1OS1lMTA0MjEwMjUzZjAiLCJ0eXAiOiJCZWFyZXIiLCJhenAiOiJibWEtZWhyIiwibm9uY2UiOiI3NjMyMGI3ZS0xZTMxLTQ5ODYtYWIzOC1iOTUyYjFlODY3OGYiLCJzZXNzaW9uX3N0YXRlIjoiMDZlNTBkZjktNzAyNi00ZGIwLTkxMjgtMWY3Y2FiYTRkNDEyIiwiYWNyIjoiMSIsImFsbG93ZWQtb3JpZ2lucyI6WyJodHRwczovL2xvY2FsaG9zdDo3MDA2Il0sInJlYWxtX2FjY2VzcyI6eyJyb2xlcyI6WyJkZWZhdWx0LXJvbGVzLWJtYS1laHIiLCJvZmZsaW5lX2FjY2VzcyIsImFkbWluIiwidW1hX2F1dGhvcml6YXRpb24iXX0sInJlc291cmNlX2FjY2VzcyI6eyJhY2NvdW50Ijp7InJvbGVzIjpbIm1hbmFnZS1hY2NvdW50IiwibWFuYWdlLWFjY291bnQtbGlua3MiLCJ2aWV3LXByb2ZpbGUiXX19LCJzY29wZSI6Im9wZW5pZCBlbWFpbCBwcm9maWxlIiwic2lkIjoiMDZlNTBkZjktNzAyNi00ZGIwLTkxMjgtMWY3Y2FiYTRkNDEyIiwiZW1haWxfdmVyaWZpZWQiOnRydWUsInJvbGUiOlsiZGVmYXVsdC1yb2xlcy1ibWEtZWhyIiwib2ZmbGluZV9hY2Nlc3MiLCJhZG1pbiIsInVtYV9hdXRob3JpemF0aW9uIl0sIm5hbWUiOiJTeXN0ZW0gQWRtaW5pc3RyYXRvciIsInByZWZlcnJlZF91c2VybmFtZSI6ImFkbWluIiwiZ2l2ZW5fbmFtZSI6IlN5c3RlbSIsImZhbWlseV9uYW1lIjoiQWRtaW5pc3RyYXRvciIsImVtYWlsIjoiYWRtaW5AbG9jYWxob3N0In0.xmfJ3pzI-jLYsaiFXyjTW7gfAEpvUmMVsp9BsB1CfRCVOKiGBbuZhnQY8W-1SWVAx1NjJ55L-zMHPK6hk1dRPLbEse3DlIBZw04W9j8m-Wz3eqdHf_UCjmrXb8qAwkeq0Iaxq9mVfJJeQWeKhFBi-Ff8ek4hCXTYDICXS8ny_BaC5WkyrefHQ2xBqQjwRyoxsg4IoVMjXYNb8L9A-4BNlRfs928SqgFYCRlF5h6zw_rC0XoLrGTmqeacBdpey-r3j2g_lTqWy8mQg2T9s65IDqW3kFPOsr0SVO88sjlFbN9Et0L57RmiqORk_RwzbWg-_Yb6dOuolXsnjBOhOoTzkA";
if (token) config.headers.Authorization = `Bearer ${token}`;
return config;
},
function (error: any) {
return Promise.reject(error);
}
);
http.interceptors.response.use(
function (response: AxiosResponse<any, any>) {
return response;
},
function (error: any) {
if (typeof error !== undefined) {
// eslint-disable-next-line no-prototype-builtins
if (error.hasOwnProperty("response")) {
if (error.response.status === 401 || error.response.status === 403) {
// Store.commit("SET_ERROR_MESSAGE", error.response.data.message);
// Store.commit("REMOVE_ACCESS_TOKEN")
}
}
}
return Promise.reject(error);
}
);
export default http;

23
src/plugins/keycloak.ts Normal file
View file

@ -0,0 +1,23 @@
/**
* front connect to keycloak
*/
import Keycloak from "keycloak-js";
// import config from "../app.config";
// import http from "../shared/http";
// import router from "../router";
const initOptions = {
// url: "https://keycloak.frappet.synology.me/auth/",
// realm: "bma-ehr",
// clientId: "bma-ehr-vue3",
url: "https://identity.frappet.com/",
realm: "bma-ehr",
clientId: "bma-ehr-vue3",
}; //option keycloak ที่จะ connect
const keycloak = Keycloak(initOptions);
keycloak.onAuthSuccess = () => {}; //เพิ่มlogin สำเร็จจะมาทำฟังก์ชันนี้
await keycloak.init({ checkLoginIframe: false }); //ทำการ connect keycloak
export default keycloak;