ui ประวัติทำงาน ประวัติการศึกษา

This commit is contained in:
Kittapath 2023-03-16 13:52:21 +07:00
parent 0157bf51b9
commit 9179a14ed8
18 changed files with 2162 additions and 106 deletions

14
package-lock.json generated
View file

@ -11,6 +11,7 @@
"@quasar/extras": "^1.15.11",
"@vuepic/vue-datepicker": "^4.2.1",
"keycloak-js": "^21.0.1",
"moment": "^2.29.4",
"pinia": "^2.0.32",
"quasar": "^2.11.7",
"vue": "^3.2.47",
@ -5851,6 +5852,14 @@
"ufo": "^1.1.1"
}
},
"node_modules/moment": {
"version": "2.29.4",
"resolved": "https://registry.npmjs.org/moment/-/moment-2.29.4.tgz",
"integrity": "sha512-5LC9SOxjSc2HF6vO2CyuTDNivEdoz2IvyJJGj6X8DJ0eFyfszE0QiEd+iXmBvUP3WHxSjFH/vIsA0EN00cgr8w==",
"engines": {
"node": "*"
}
},
"node_modules/ms": {
"version": "2.1.2",
"resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz",
@ -12462,6 +12471,11 @@
"ufo": "^1.1.1"
}
},
"moment": {
"version": "2.29.4",
"resolved": "https://registry.npmjs.org/moment/-/moment-2.29.4.tgz",
"integrity": "sha512-5LC9SOxjSc2HF6vO2CyuTDNivEdoz2IvyJJGj6X8DJ0eFyfszE0QiEd+iXmBvUP3WHxSjFH/vIsA0EN00cgr8w=="
},
"ms": {
"version": "2.1.2",
"resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz",

View file

@ -18,6 +18,7 @@
"@quasar/extras": "^1.15.11",
"@vuepic/vue-datepicker": "^4.2.1",
"keycloak-js": "^21.0.1",
"moment": "^2.29.4",
"pinia": "^2.0.32",
"quasar": "^2.11.7",
"vue": "^3.2.47",

View file

@ -2,24 +2,11 @@
<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"
>
<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"
@ -32,16 +19,6 @@
>
<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
@ -54,16 +31,6 @@
>
<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
@ -82,88 +49,70 @@
<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>
<q-space />
</div>
</template>
<script setup lang="ts">
import { ref, useAttrs } from "vue";
const props = defineProps({
header: {
type: String,
default: "ข้อความ",
required: true,
default: 'ข้อความ',
required: true
},
icon: {
type: String,
default: "mdi-help",
required: true,
default: 'mdi-help',
required: true
},
edit: {
type: Boolean,
default: true,
required: true,
},
history: {
type: Boolean,
default: true,
required: true,
required: true
},
addData: {
type: Boolean,
defualt: false,
defualt: false
},
add: {
type: Function,
default: () => console.log("not function"),
default: () => console.log('not function')
},
save: {
type: Function,
default: () => console.log("not function"),
default: () => console.log('not function')
},
deleted: {
type: Function,
default: () => console.log("not function"),
default: () => console.log('not function')
},
cancel: {
type: Function,
default: () => console.log("not function"),
},
});
default: () => console.log('not function')
}
})
const emit = defineEmits(["update:edit"]);
const emit = defineEmits(['update:edit'])
const updateEdit = (value: any) => {
emit("update:edit", value);
};
emit('update:edit', value)
}
const ClickEdit = () => {
updateEdit(!props.edit);
};
updateEdit(!props.edit)
}
const ClickCancel = () => {
updateEdit(!props.edit);
props.cancel();
};
updateEdit(!props.edit)
props.cancel()
}
const save = () => {
props.save();
};
props.save()
}
const add = () => {
props.add();
};
props.add()
}
</script>
<style scoped>
/* .q-btn >>> .q-icon {

View file

@ -6,6 +6,7 @@ import App from './App.vue'
import router from './router'
import quasarUserOptions from './quasar-user-options'
import '@vuepic/vue-datepicker/dist/main.css'
import 'quasar/src/css/index.sass'
import th from 'quasar/lang/th'

View file

@ -0,0 +1,233 @@
<template>
<q-card flat bordered class="col-12 q-px-lg q-py-md q-mt-md">
<!-- <HeaderTop
v-model:edit="edit"
header="ข้อมูลที่อยู่"
icon="mdi-map-marker"
:save="saveData"
/> -->
<HeaderTop
v-model:edit="edit"
header="ข้อมูลที่อยู่ปัจจุบัน"
icon="mdi-map-marker"
:save="saveData"
:history="true"
/>
<q-form ref="myform">
<div class="row col-12 items-center q-col-gutter-x-xs q-col-gutter-y-xs">
<div class="col-xs-12">
<q-input
:class="getClass(edit)"
hide-bottom-space
:outlined="edit"
dense
lazy-rules
type="textarea"
autogrow
:readonly="!edit"
:borderless="!edit"
v-model="addressData.address"
:rules="[(val) => !!val || `${'กรุณากรอก ที่อยู่'}`]"
:label="`${'ที่อยู่'}`"
/>
<!-- :filled="edit" -->
</div>
<div class="col-xs-6 col-sm-3 col-md-3">
<q-select
hide-bottom-space
:class="getClass(edit)"
:readonly="!edit"
:borderless="!edit"
:rules="[(val) => !!val || `${'กรุณาเลือก จังหวัด'}`]"
:outlined="edit"
dense
lazy-rules
v-model="addressData.provinceId"
emit-value
map-options
option-label="name"
:options="provinceOptions"
option-value="id"
:label="`${'จังหวัด'}`"
@update:model-value="(value) => selectProvince(value)"
/>
</div>
<div class="col-xs-6 col-sm-3 col-md-3">
<q-select
hide-bottom-space
:class="getClass(edit)"
:readonly="!edit"
:borderless="!edit"
:rules="[(val) => !!val || `${'กรุณาเลือก เขต / อำเภอ'}`]"
:outlined="edit"
dense
lazy-rules
v-model="addressData.districtId"
emit-value
map-options
option-label="name"
:options="districtOptions"
option-value="id"
:label="`${'เขต / อำเภอ'}`"
@update:model-value="(value) => selectDistrict(value)"
/>
</div>
<div class="col-xs-6 col-sm-3 col-md-3">
<q-select
hide-bottom-space
:class="getClass(edit)"
:readonly="!edit"
:borderless="!edit"
:rules="[(val) => !!val || `${'กรุณาเลือก ตำบล / แขวง'}`]"
:outlined="edit"
dense
lazy-rules
v-model="addressData.subdistrictId"
emit-value
map-options
option-label="name"
:options="subdistrictOptions"
option-value="id"
:label="`${'ตำบล / แขวง'}`"
@update:model-value="(value) => selectSubDistrict(value)"
/>
</div>
<div class="col-xs-6 col-sm-3 col-md-3">
<q-input
:class="getClass(edit)"
hide-bottom-space
dense
lazy-rules
readonly
borderless
v-model="codep"
:style="!edit ? '' : 'padding:0 12px;'"
:label="`${'รหัสไปรษณีย์'}`"
/>
</div>
</div>
</q-form>
</q-card>
</template>
<script setup lang="ts">
import { ref, onMounted } from 'vue'
import http from '@/plugins/http'
import config from '@/app.config'
import type { Address, DataOption, zipCodeOption } from '@/modules/01_exam/interface/index/Main'
import { defaultAddress } from '@/modules/01_exam/interface/index/Main'
import HeaderTop from '@/components/top.vue'
const edit = ref<boolean>(false)
const addressData = ref<Address>(defaultAddress)
const myform = ref<any>()
const codep = ref<string>('')
const provinceOptions = ref<DataOption[]>([])
const districtOptions = ref<DataOption[]>([])
const subdistrictOptions = ref<zipCodeOption[]>([])
const getClass = (val: boolean) => {
return {
'full-width inputgreen cursor-pointer': val,
'full-width cursor-pointer': !val
}
}
onMounted(() => {
// fetchProvince()
// fetchDistrict(addressData.value.provinceId)
})
const saveData = async () => {
await myform.value.validate().then(async (success: boolean) => {
if (success) {
} else {
}
})
}
const selectProvince = (e: string) => {
addressData.value.districtId = ''
addressData.value.subdistrictId = ''
codep.value = ''
myform.value.resetValidation()
fetchDistrict(e)
}
const selectDistrict = (e: string) => {
addressData.value.subdistrictId = ''
codep.value = ''
myform.value.resetValidation()
fetchSubDistrict(e)
}
const selectSubDistrict = (e: string) => {
const findcode = subdistrictOptions.value.filter((r) => r.id == e)
const namecode = findcode.length > 0 ? findcode[0].zipCode : ''
codep.value = namecode
}
const fetchProvince = async () => {
// loader.value = true;
await http
.get(config.API.province)
.then((res) => {
const data = res.data.result
let option: DataOption[] = []
// console.log(data);
data.map((r: any) => {
option.push({ id: r.id.toString(), name: r.name.toString() })
})
provinceOptions.value = option
})
.catch((e: any) => {})
.finally(() => {
// loader.value = false;
})
}
const fetchDistrict = async (id: string) => {
// loader.value = true;
await http
.get(config.API.listDistrict(id))
.then((res) => {
const data = res.data.result
let option: DataOption[] = []
// console.log(data);
data.map((r: any) => {
option.push({ id: r.id.toString(), name: r.name.toString() })
})
districtOptions.value = option
})
.catch((e: any) => {})
.finally(() => {
// loader.value = false;
})
}
const fetchSubDistrict = async (id: string) => {
// loader.value = true;
await http
.get(config.API.listSubDistrict(id))
.then((res) => {
const data = res.data.result
let option: zipCodeOption[] = []
// console.log(res);
data.map((r: any) => {
option.push({
id: r.id.toString(),
name: r.name.toString(),
zipCode: r.zipCode.toString()
})
})
subdistrictOptions.value = option
})
.catch((e: any) => {})
.finally(() => {
// loader.value = false;
})
}
</script>

View file

@ -1,4 +1,576 @@
<!-- card ประวการทำงาน/กงาน -->
<template>
<div></div>
<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 == 'salary'" class="">
{{ col.value.toLocaleString('en-US') }}
</div>
<div v-else-if="col.name == 'duration'" class="">
{{ dateThaiRange(col.value) }}
</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-input
:class="getClass(edit)"
hide-bottom-space
:outlined="edit"
dense
lazy-rules
:readonly="!edit"
:borderless="!edit"
v-model="location"
: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="position"
: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="salary"
:rules="[(val) => !!val || `${'กรุณากรอกเงินเดือนสุดท้ายก่อนออก'}`]"
:label="`${'เงินเดือนสุดท้ายก่อนออก'}`"
@update:modelValue="clickEditRow"
type="number"
/>
</div>
<div class="col-xs-6 col-sm-6 col-md-6">
<datepicker
:readonly="!edit"
v-model="duration"
:locale="'th'"
autoApply
range
:enableTimePicker="false"
week-start="0"
>
<template #year="{ year }">
{{ year + 543 }}
</template>
<template #year-overlay-value="{ value }">
{{ parseInt(value + 543) }}
</template>
<template #trigger>
<q-input
:class="getClass(edit)"
class="datepicker"
hide-bottom-space
:outlined="edit"
dense
lazy-rules
:borderless="!edit"
:model-value="dateThaiRange(duration)"
>
<template v-slot:prepend>
<q-icon name="event" class="cursor-pointer" style="color: var(--q-primary)">
</q-icon>
</template>
</q-input>
</template>
</datepicker>
</div>
<div class="col-xs-12 col-sm-12 col-md-12">
<q-input
:class="getClass(edit)"
hide-bottom-space
:outlined="edit"
dense
lazy-rules
:readonly="!edit"
:borderless="!edit"
v-model="reason"
:rules="[(val) => !!val || `${'กรุณากรอกเหตุผลที่ออก'}`]"
:label="`${'เหตุผลที่ออก'}`"
@update:modelValue="clickEditRow"
type="textarea"
/>
</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"></script>
<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 { useCounterMixin } from '@/stores/mixin'
import type {
RequestItemsObject,
Columns,
DataProps
} from '@/modules/01_exam/interface/request/Career'
import type { ResponseObject } from '@/modules/01_exam/interface/response/Career'
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 mixin = useCounterMixin() //
const { dateThaiRange } = mixin
const store = useExamDataStore()
const { examData, changeExamColumns } = store
const loader = ref<boolean>(false)
const id = ref<string>()
const location = ref<string>()
const position = ref<string>()
const salary = ref<number | null>()
const duration = ref<[Date, Date]>([new Date(), new Date()])
const reason = ref<string>()
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',
location: 'แอดวานซ์ อินโฟร์ เซอร์วิส',
position: 'Direct Sales Staff',
salary: 30000,
duration: [new Date('1995-04-15'), new Date('1999-02-25')],
reason: 'ไล่ออก'
},
{
id: '2',
location: 'บริษัท ทรู คอร์ปอเรชั่น จำกัด (มหาชน)',
position: 'Direct Sales Staff',
salary: 40000,
duration: [new Date('2020-06-30'), new Date('2023-10-14')],
reason: '-'
}
])
const filter = ref<string>('') //search data table
const visibleColumns = ref<String[]>([])
examData.career.columns.length == 0
? (visibleColumns.value = ['location', 'position', 'salary', 'duration', 'reason'])
: (visibleColumns.value = examData.career.columns)
const columns = ref<Columns>([
{
name: 'location',
align: 'left',
label: 'สถานที่ทำงาน/ฝึกงาน',
sortable: true,
field: 'location',
headerStyle: 'font-size: 14px',
style: 'font-size: 14px'
},
{
name: 'position',
align: 'left',
label: 'ตำแหน่ง/ลักษณะงาน',
sortable: true,
field: 'position',
headerStyle: 'font-size: 14px',
style: 'font-size: 14px'
},
{
name: 'salary',
align: 'left',
label: 'เงินเดือนสุดท้ายก่อนออก',
sortable: true,
field: 'salary',
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'
},
{
name: 'reason',
align: 'left',
label: 'เหตุผลที่ออก',
sortable: true,
field: 'reason',
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('career', count)
})
onMounted(async () => {
// await fetchData()
rawHistory.value = rows.value
})
const fetchData = async () => {}
/**
* กดดอมลกอนหน
*/
const clickPrevious = () => {
edit.value = false
rowIndex.value -= 1
const row = rows.value[rowIndex.value]
location.value = row.location
position.value = row.position
salary.value = row.salary
duration.value = row.duration
reason.value = row.reason
id.value = row.id
checkRowPage()
}
/**
* กดดอมลตอไป
*/
const clickNext = () => {
edit.value = false
rowIndex.value += 1
const row = rows.value[rowIndex.value]
location.value = row.location
position.value = row.position
salary.value = row.salary
duration.value = row.duration
reason.value = row.reason
id.value = row.id
checkRowPage()
}
/**
* กดดอมลตอไป
*/
const getData = () => {
const row = rows.value[rowIndex.value]
location.value = row.location
position.value = row.position
salary.value = row.salary
duration.value = row.duration
reason.value = row.reason
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
editRow.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
location.value = props.row.location
position.value = props.row.position
salary.value = props.row.salary
duration.value = props.row.duration
reason.value = props.row.reason
id.value = props.row.id
checkRowPage()
}
/**
* กดปมเพมบน table
*/
const addData = () => {
modalEdit.value = false
modal.value = true
edit.value = true
location.value = ''
position.value = ''
salary.value = null
duration.value = [new Date(), new Date()]
reason.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>

View file

@ -21,11 +21,8 @@
@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 v-if="col.name == 'duration'" class="">
{{ dateThaiRange(col.value) }}
</div>
<div v-else class="">
{{ col.value }}
@ -54,8 +51,8 @@
:readonly="!edit"
:borderless="!edit"
v-model="qualificationId"
:rules="[(val) => !!val || `${'กรุณาเลือกระดับการศึกษา'}`]"
:label="`${'ระดับการศึกษา'}`"
:rules="[(val) => !!val || `${'กรุณาเลือกวุฒิที่ได้รับ'}`]"
:label="`${'วุฒิที่ได้รับ'}`"
@update:modelValue="clickEditRow"
emit-value
map-options
@ -73,9 +70,25 @@
lazy-rules
:readonly="!edit"
:borderless="!edit"
v-model="name"
:rules="[(val) => !!val || `${'กรุณากรอกสถานศึกษา'}`]"
:label="`${'สถานศึกษา'}`"
v-model="major"
:rules="[(val) => !!val || `${'กรุณากรอกสาขาวิชา/วิชาเอก'}`]"
:label="`${'สาขาวิชา/วิชาเอก'}`"
@update:modelValue="clickEditRow"
/>
</div>
<div class="col-xs-6 col-sm-6 col-md-6">
<q-input
type="number"
:class="getClass(edit)"
hide-bottom-space
:outlined="edit"
dense
lazy-rules
:readonly="!edit"
:borderless="!edit"
v-model="scores"
:rules="[(val) => !!val || `${'กรุณากรอกคะแนนเฉลี่ยตลอดหลักสูตร'}`]"
:label="`${'คะแนนเฉลี่ยตลอดหลักสูตร'}`"
@update:modelValue="clickEditRow"
/>
</div>
@ -88,12 +101,47 @@
lazy-rules
:readonly="!edit"
:borderless="!edit"
v-model="major"
:rules="[(val) => !!val || `${'กรุณากรอกสาขา/วิชาเอก'}`]"
:label="`${'สาขา/วิชาเอก'}`"
v-model="name"
:rules="[(val) => !!val || `${'กรุณากรอกชื่อสถานศึกษา'}`]"
:label="`${'ชื่อสถานศึกษา'}`"
@update:modelValue="clickEditRow"
/>
</div>
<div class="col-xs-6 col-sm-6 col-md-6">
<datepicker
:readonly="!edit"
v-model="duration"
:locale="'th'"
autoApply
range
:enableTimePicker="false"
week-start="0"
>
<template #year="{ year }">
{{ year + 543 }}
</template>
<template #year-overlay-value="{ value }">
{{ parseInt(value + 543) }}
</template>
<template #trigger>
<q-input
:class="getClass(edit)"
class="datepicker"
hide-bottom-space
:outlined="edit"
dense
lazy-rules
:borderless="!edit"
:model-value="dateThaiRange(duration)"
>
<template v-slot:prepend>
<q-icon name="event" class="cursor-pointer" style="color: var(--q-primary)">
</q-icon>
</template>
</q-input>
</template>
</datepicker>
</div>
</div>
</q-card-section>
<q-separator />
@ -126,6 +174,7 @@ import ProfileTable from '@/components/Table.vue'
import DialogHeader from '@/components/DialogHeader.vue'
import DialogFooter from '@/components/DialogFooter.vue'
import { useQuasar } from 'quasar'
import { useCounterMixin } from '@/stores/mixin'
import type {
RequestItemsObject,
Columns,
@ -145,6 +194,8 @@ const props = defineProps({
})
const $q = useQuasar()
const mixin = useCounterMixin() //
const { dateThaiRange } = mixin
const store = useExamDataStore()
const { examData, changeExamColumns } = store
const loader = ref<boolean>(false)
@ -155,7 +206,7 @@ const qualificationOptions = ref<DataOption[]>([])
const major = ref<string>()
const scores = ref<number | null>()
const name = ref<string>()
const duration = ref<any>()
const duration = ref<[Date, Date]>([new Date(), new Date()])
const myForm = ref<any>() //form data input
const edit = ref<boolean>(false) // dialog
const modal = ref<boolean>(false) //modal add detail
@ -188,7 +239,7 @@ const rows = ref<RequestItemsObject[]>([
major: 'คอมพิวเตอร์',
scores: 3.99,
name: 'มหาลัยเอ',
duration: 2015
duration: [new Date('1995-04-15'), new Date('1999-02-25')]
},
{
id: '2',
@ -197,7 +248,7 @@ const rows = ref<RequestItemsObject[]>([
major: 'คอมพิวเตอร์',
scores: 3.54,
name: 'มหาลัยบี',
duration: 2015
duration: [new Date('2020-06-30'), new Date('2023-10-14')]
}
])
@ -415,6 +466,7 @@ const saveData = async () => {
*/
const editData = async () => {
edit.value = false
editRow.value = false
// loader.value = true;
// await http
@ -492,7 +544,7 @@ const addData = () => {
major.value = ''
scores.value = null
name.value = ''
duration.value = ''
duration.value = [new Date(), new Date()]
}
/**

View file

@ -21,7 +21,7 @@
<q-tab-panel name="education"><Education :loader="loader" /> </q-tab-panel>
<!-- ประวการทำงาน/กงาน -->
<q-tab-panel name="career"> <Career /></q-tab-panel>
<q-tab-panel name="career"> <Career :loader="loader" /></q-tab-panel>
<!-- ไฟล -->
<!-- <q-tab-panel name="document">

View file

@ -0,0 +1,341 @@
<template>
<q-card flat bordered class="col-12 q-px-lg q-py-md q-mt-md text-dark">
<HeaderTop
v-model:edit="edit"
header="ข้อมูลครอบครัว"
icon="mdi-account-group"
:save="saveData"
/>
<q-form ref="myform" class="col-12">
<div class="row col-12 items-center q-col-gutter-x-xs q-col-gutter-y-xs">
<div class="col-xs-6 col-sm-3 col-md-3">
<q-select
hide-bottom-space
:class="getClass(edit)"
:readonly="!edit"
:borderless="!edit"
:rules="[(val) => !!val || `${'กรุณาเลือก สถานภาพ'}`]"
:outlined="edit"
dense
lazy-rules
v-model="statusId"
emit-value
map-options
option-label="name"
:options="statusOptions"
option-value="id"
:label="`${'สถานภาพ'}`"
/>
</div>
<div class="col-xs-12 q-gutter-sm items-center flex q-my-sm">
<label class="text-weight-bold"> สมรส</label>
<q-radio
v-model="familyData.same"
checked-icon="task_alt"
unchecked-icon="panorama_fish_eye"
val="1"
label="มี"
dense
:disable="!edit"
@update:model-value="selectRadio"
/>
<q-radio
v-model="familyData.same"
checked-icon="task_alt"
unchecked-icon="panorama_fish_eye"
val="0"
label="ไม่มี"
dense
:disable="!edit"
@update:model-value="selectRadio"
/>
</div>
<div class="col-xs-12 col-sm-2 col-md-2" v-if="familyData.same == '1'">
<q-select
hide-bottom-space
:class="getClass(edit)"
:readonly="!edit"
:borderless="!edit"
:rules="[(val) => !!val || `${'กรุณาเลือก คำนำหน้า'}`]"
:outlined="edit"
dense
lazy-rules
v-model="familyData.prefixIdC"
emit-value
map-options
option-label="name"
:options="prefixOptions"
option-value="id"
:label="`${'คำนำหน้า'}`"
/>
</div>
<div class="col-xs-6 col-sm-3 col-md-3" v-if="familyData.same == '1'">
<q-input
:class="getClass(edit)"
hide-bottom-space
:outlined="edit"
dense
lazy-rules
:readonly="!edit"
:borderless="!edit"
v-model="familyData.firstnameC"
:rules="[(val) => !!val || `${'กรุณากรอก ชื่อ'}`]"
:label="`${'ชื่อ'}`"
/>
</div>
<div class="col-xs-6 col-sm-3 col-md-3" v-if="familyData.same == '1'">
<q-input
:class="getClass(edit)"
hide-bottom-space
:outlined="edit"
dense
lazy-rules
:readonly="!edit"
:borderless="!edit"
v-model="familyData.lastnameC"
:rules="[(val) => !!val || `${'กรุณากรอก นามสกุล'}`]"
:label="`${'นามสกุล'}`"
/>
</div>
<div class="col-xs-12 col-sm-2 col-md-2" v-if="familyData.same == '1'">
<q-input
:class="getClass(edit)"
hide-bottom-space
:outlined="edit"
dense
lazy-rules
:readonly="!edit"
:borderless="!edit"
v-model="familyData.occupationC"
:rules="[(val) => !!val || `${'กรุณากรอก อาชีพ'}`]"
:label="`${'อาชีพ'}`"
/>
</div>
<div class="col-xs-12 col-sm-2 col-md-2" v-if="familyData.same == '1'">
<q-input
:class="getClass(edit)"
hide-bottom-space
:outlined="edit"
dense
lazy-rules
:readonly="!edit"
:borderless="!edit"
v-model="familyData.nationalityC"
:rules="[(val) => !!val || `${'กรุณากรอก สัญชาติ'}`]"
:label="`${'สัญชาติ'}`"
/>
</div>
<div class="col-xs-12 text-weight-bold"> ดา</div>
<div class="col-xs-12 col-sm-2 col-md-2">
<q-select
hide-bottom-space
:class="getClass(edit)"
:readonly="!edit"
:borderless="!edit"
:rules="[(val) => !!val || `${'กรุณาเลือก คำนำหน้า'}`]"
:outlined="edit"
dense
lazy-rules
v-model="familyData.prefixIdM"
emit-value
map-options
option-label="name"
:options="prefixOptions"
option-value="id"
:label="`${'คำนำหน้า'}`"
/>
</div>
<div class="col-xs-6 col-sm-3 col-md-3">
<q-input
:class="getClass(edit)"
hide-bottom-space
:outlined="edit"
dense
lazy-rules
:readonly="!edit"
:borderless="!edit"
v-model="familyData.firstnameM"
:rules="[(val) => !!val || `${'กรุณากรอก ชื่อ'}`]"
:label="`${'ชื่อ'}`"
/>
</div>
<div class="col-xs-6 col-sm-3 col-md-3">
<q-input
:class="getClass(edit)"
hide-bottom-space
:outlined="edit"
dense
lazy-rules
:readonly="!edit"
:borderless="!edit"
v-model="familyData.lastnameM"
:rules="[(val) => !!val || `${'กรุณากรอก นามสกุล'}`]"
:label="`${'นามสกุล'}`"
/>
</div>
<div class="col-xs-12 col-sm-2 col-md-2">
<q-input
:class="getClass(edit)"
hide-bottom-space
:outlined="edit"
dense
lazy-rules
:readonly="!edit"
:borderless="!edit"
v-model="familyData.occupationM"
:rules="[(val) => !!val || `${'กรุณากรอก อาชีพ'}`]"
:label="`${'อาชีพ'}`"
/>
</div>
<div class="col-xs-12 col-sm-2 col-md-2">
<q-input
:class="getClass(edit)"
hide-bottom-space
:outlined="edit"
dense
lazy-rules
:readonly="!edit"
:borderless="!edit"
v-model="familyData.nationalityM"
:rules="[(val) => !!val || `${'กรุณากรอก สัญชาติ'}`]"
:label="`${'สัญชาติ'}`"
/>
</div>
<div class="col-xs-12 text-weight-bold"> มารดา</div>
<div class="col-xs-12 col-sm-2 col-md-2">
<q-select
hide-bottom-space
:class="getClass(edit)"
:readonly="!edit"
:borderless="!edit"
:rules="[(val) => !!val || `${'กรุณาเลือก คำนำหน้า'}`]"
:outlined="edit"
dense
lazy-rules
v-model="familyData.prefixIdF"
emit-value
map-options
option-label="name"
:options="prefixOptions"
option-value="id"
:label="`${'คำนำหน้า'}`"
/>
</div>
<div class="col-xs-6 col-sm-3 col-md-3">
<q-input
:class="getClass(edit)"
hide-bottom-space
:outlined="edit"
dense
lazy-rules
:readonly="!edit"
:borderless="!edit"
v-model="familyData.firstnameF"
:rules="[(val) => !!val || `${'กรุณากรอก ชื่อ'}`]"
:label="`${'ชื่อ'}`"
/>
</div>
<div class="col-xs-6 col-sm-3 col-md-3">
<q-input
:class="getClass(edit)"
hide-bottom-space
:outlined="edit"
dense
lazy-rules
:readonly="!edit"
:borderless="!edit"
v-model="familyData.lastnameF"
:rules="[(val) => !!val || `${'กรุณากรอก นามสกุล'}`]"
:label="`${'นามสกุล'}`"
/>
</div>
<div class="col-xs-12 col-sm-2 col-md-2">
<q-input
:class="getClass(edit)"
hide-bottom-space
:outlined="edit"
dense
lazy-rules
:readonly="!edit"
:borderless="!edit"
v-model="familyData.occupationF"
:rules="[(val) => !!val || `${'กรุณากรอก อาชีพ'}`]"
:label="`${'อาชีพ'}`"
/>
</div>
<div class="col-xs-12 col-sm-2 col-md-2">
<q-input
:class="getClass(edit)"
hide-bottom-space
:outlined="edit"
dense
lazy-rules
:readonly="!edit"
:borderless="!edit"
v-model="familyData.nationalityF"
:rules="[(val) => !!val || `${'กรุณากรอก สัญชาติ'}`]"
:label="`${'สัญชาติ'}`"
/>
</div>
</div>
</q-form>
</q-card>
</template>
<script setup lang="ts">
import { ref } from 'vue'
import type { PropType } from 'vue'
import { useCounterMixin } from '@/stores/mixin'
import type { Family, DataOption } from '@/modules/01_exam/interface/index/Main'
import { defaultFamily } from '@/modules/01_exam/interface/index/Main'
import HeaderTop from '@/components/top.vue'
const mixin = useCounterMixin()
const { date2Thai, calAge } = mixin
const edit = ref<boolean>(false)
const myform = ref<any>()
const familyData = ref<Family>(defaultFamily)
const statusId = ref<string>('123456789')
const statusOptions = ref<DataOption[]>([])
// const prefixOptions = ref<any>([
// { id: "1", name: "" },
// { id: "2", name: "" },
// { id: "3", name: "" },
// ]);
const props = defineProps({
prefixOptions: {
type: Array as PropType<DataOption[]>,
required: true
}
})
const getClass = (val: boolean) => {
return {
'full-width inputgreen cursor-pointer': val,
'full-width cursor-pointer': !val
}
}
const saveData = async () => {
await myform.value.validate().then(async (success: boolean) => {
if (success) {
} else {
}
})
}
const selectRadio = (e: boolean, i: any) => {
if (!e) {
familyData.value.prefixIdC = ''
familyData.value.firstnameC = ''
familyData.value.lastnameC = ''
familyData.value.occupationC = ''
}
}
</script>

View file

@ -0,0 +1,343 @@
<template>
<q-card flat bordered class="col-12 q-px-lg q-py-md">
<HeaderTop v-model:edit="edit" header="ข้อมูลส่วนตัว" icon="mdi-account" :save="saveData" />
<q-form ref="myform" class="col-12">
<div class="row col-12 items-center q-col-gutter-x-sm q-col-gutter-y-sm">
<div class="col-xs-6 col-sm-3 col-md-3">
<q-select
hide-bottom-space
:class="getClass(edit)"
:readonly="!edit"
:borderless="!edit"
:rules="[(val) => !!val || `${'กรุณาเลือก คำนำหน้า'}`]"
:outlined="edit"
dense
lazy-rules
v-model="informaData.prefixId"
emit-value
map-options
option-label="name"
:options="prefixOptions"
option-value="id"
:label="`${'คำนำหน้า'}`"
/>
</div>
<div class="col-xs-6 col-sm-3 col-md-3">
<q-input
:class="getClass(edit)"
hide-bottom-space
:outlined="edit"
dense
lazy-rules
:readonly="!edit"
:borderless="!edit"
v-model="informaData.firstname"
:rules="[(val) => !!val || `${'กรุณากรอก ชื่อ'}`]"
:label="`${'ชื่อ'}`"
/>
</div>
<div class="col-xs-6 col-sm-3 col-md-3">
<q-input
:class="getClass(edit)"
hide-bottom-space
:outlined="edit"
dense
lazy-rules
:readonly="!edit"
:borderless="!edit"
v-model="informaData.lastname"
:rules="[(val) => !!val || `${'กรุณากรอก นามสกุล'}`]"
:label="`${'นามสกุล'}`"
/>
</div>
<div class="col-xs-6 col-sm-3 col-md-3">
<q-input
:class="getClass(edit)"
hide-bottom-space
:outlined="edit"
dense
lazy-rules
:readonly="!edit"
:borderless="!edit"
v-model="informaData.nationality"
:rules="[(val) => !!val || `${'กรุณากรอก สัญชาติ'}`]"
:label="`${'สัญชาติ'}`"
/>
</div>
<div class="col-xs-6 col-sm-3 col-md-3">
<datepicker
v-model="informaData.birthDate"
:locale="'th'"
autoApply
:enableTimePicker="false"
week-start="0"
:max-date="new Date()"
>
<template #year="{ year }">
{{ year + 543 }}
</template>
<template #year-overlay-value="{ value }">
{{ parseInt(value + 543) }}
</template>
<template #trigger>
<q-input
:class="getClass(edit)"
hide-bottom-space
:outlined="edit"
dense
lazy-rules
:readonly="!edit"
:borderless="!edit"
:model-value="date2Thai(informaData.birthDate)"
:rules="[(val) => !!val || `${'กรุณาเลือก วัน/เดือน/ปี เกิด'}`]"
:label="`${'วัน/เดือน/ปี เกิด'}`"
>
<template v-slot:prepend>
<q-icon name="event" class="cursor-pointer" style="color: var(--q-primary)">
</q-icon>
</template>
</q-input>
</template>
</datepicker>
</div>
<div class="col-xs-6 col-sm-3 col-md-3">
<q-input
:class="getClass(edit)"
hide-bottom-space
dense
lazy-rules
readonly
borderless
:style="!edit ? '' : 'padding:0 12px;'"
:model-value="calAge(informaData.birthDate)"
:label="`${'อายุ'}`"
/>
</div>
<div class="col-xs-6 col-sm-3 col-md-3">
<q-input
hide-bottom-space
:outlined="edit"
dense
lazy-rules
type="tel"
:class="getClass(edit)"
:readonly="!edit"
:borderless="!edit"
v-model="informaData.tel"
:rules="[
(val) => !!val || `${'กรุณากรอก โทรศัพท์'}`,
(val) => val.length >= 9 || `${'กรุณากรอกข้อมูลโทรศัพท์ให้ครบ'}`
]"
:label="`${'โทรศัพท์'}`"
mask="#########"
/>
</div>
<div class="col-xs-6 col-sm-3 col-md-3">
<q-input
hide-bottom-space
:outlined="edit"
dense
lazy-rules
type="tel"
:class="getClass(edit)"
:readonly="!edit"
:borderless="!edit"
v-model="informaData.phone"
:rules="[
(val) => !!val || `${'กรุณากรอก โทรศัพท์มือถือ'}`,
(val) => val.length >= 10 || `${'กรุณากรอกข้อมูลโทรศัพท์มือถือให้ครบ'}`
]"
:label="`${'โทรศัพท์มือถือ'}`"
mask="##########"
/>
</div>
<div class="col-xs-6 col-sm-3 col-md-3">
<q-input
:class="getClass(edit)"
hide-bottom-space
:outlined="edit"
dense
lazy-rules
:readonly="!edit"
:borderless="!edit"
v-model="informaData.cardid"
maxlength="13"
:rules="[
(val) => !!val || `${'กรุณากรอก เลขบัตรประจำตัวประชาชน'}`,
(val) => val.length >= 13 || `${'กรุณากรอกเลขบัตรประจำตัวประชาชนให้ครบ'}`
]"
label="เลขบัตรประจำตัวประชาชน"
mask="#############"
/>
</div>
<div class="col-xs-6 col-sm-3 col-md-3">
<q-input
:class="getClass(edit)"
hide-bottom-space
:outlined="edit"
dense
lazy-rules
:readonly="!edit"
:borderless="!edit"
v-model="informaData.cardid"
:rules="[(val) => !!val || `${'กรุณากรอก ออกให้ ณ อำเภอ'}`]"
label="ออกให้ ณ อำเภอ"
/>
</div>
<div class="col-xs-6 col-sm-3 col-md-3">
<q-select
hide-bottom-space
:class="getClass(edit)"
:readonly="!edit"
:borderless="!edit"
:rules="[(val) => !!val || `${'กรุณาเลือก จังหวัด'}`]"
:outlined="edit"
dense
lazy-rules
v-model="informaData.provinceId"
emit-value
map-options
option-label="name"
:options="provinceOptions"
option-value="id"
:label="`${'จังหวัด'}`"
/>
</div>
<div class="col-xs-6 col-sm-3 col-md-3">
<datepicker
v-model="informaData.cardIdDate"
:locale="'th'"
autoApply
:enableTimePicker="false"
week-start="0"
:max-date="new Date()"
>
<template #year="{ year }">
{{ year + 543 }}
</template>
<template #year-overlay-value="{ value }">
{{ parseInt(value + 543) }}
</template>
<template #trigger>
<q-input
:class="getClass(edit)"
hide-bottom-space
:outlined="edit"
dense
lazy-rules
:readonly="!edit"
:borderless="!edit"
:model-value="date2Thai(informaData.cardIdDate)"
:rules="[(val) => !!val || `${'กรุณาเลือก วัน/เดือน/ปี'}`]"
:label="`${'วัน/เดือน/ปี'}`"
>
<template v-slot:prepend>
<q-icon name="event" class="cursor-pointer" style="color: var(--q-primary)">
</q-icon>
</template>
</q-input>
</template>
</datepicker>
</div>
<div class="col-xs-6 col-sm-3 col-md-3">
<q-input
:class="getClass(edit)"
hide-bottom-space
:outlined="edit"
dense
lazy-rules
:readonly="!edit"
:borderless="!edit"
v-model="informaData.email"
:rules="[(val) => !!val || `${'กรุณากรอก E-mail address'}`]"
label="E-mail address"
/>
</div>
</div>
</q-form>
</q-card>
</template>
<script setup lang="ts">
import { ref, onMounted } from 'vue'
import { useCounterMixin } from '@/stores/mixin'
import type { PropType } from 'vue'
import type { Information, DataOption } from '@/modules/01_exam/interface/index/Main'
import { defaultInformation } from '@/modules/01_exam/interface/index/Main'
import HeaderTop from '@/components/top.vue'
import http from '@/plugins/http'
import config from '@/app.config'
const mixin = useCounterMixin()
const { date2Thai, calAge } = mixin
const edit = ref<boolean>(false)
const informaData = ref<Information>(defaultInformation)
const provinceOptions = ref<DataOption[]>([])
const myform = ref<any>()
const props = defineProps({
prefixOptions: {
type: Array as PropType<DataOption[]>,
required: true
},
genderOptions: {
type: Array as PropType<DataOption[]>,
required: true
},
bloodOptions: {
type: Array as PropType<DataOption[]>,
required: true
},
statusOptions: {
type: Array as PropType<DataOption[]>,
required: true
},
religionOptions: {
type: Array as PropType<DataOption[]>,
required: true
},
provinceOptions: {
type: Array as PropType<DataOption[]>,
required: true
}
})
onMounted(() => {
// console.log(props);
fetchProvince()
})
const saveData = async () => {
await myform.value.validate().then(async (success: boolean) => {
if (success) {
} else {
}
})
}
const fetchProvince = async () => {
// loader.value = true;
await http
.get(config.API.province)
.then((res) => {
const data = res.data.result
let option: DataOption[] = []
// console.log(data);
data.map((r: any) => {
option.push({ id: r.id.toString(), name: r.name.toString() })
})
provinceOptions.value = option
})
.catch((e: any) => {})
.finally(() => {
// loader.value = false;
})
}
const getClass = (val: boolean) => {
return {
'full-width inputgreen cursor-pointer': val,
'full-width cursor-pointer': !val
}
}
</script>

View file

@ -1,4 +1,29 @@
<template>
<div></div>
<Information
:prefixOptions="prefixOptions"
:genderOptions="genderOptions"
:bloodOptions="bloodOptions"
:statusOptions="statusOptions"
:religionOptions="religionOptions"
:provinceOptions="provinceOptions"
/>
<Address />
<Family :prefixOptions="prefixOptions" />
</template>
<script setup lang="ts"></script>
<script setup lang="ts">
import { ref, onMounted } from 'vue'
import type { DataOption } from '@/modules/01_exam/interface/index/Main'
import Information from './Information.vue'
import Address from './Address.vue'
import Family from './Family.vue'
import http from '@/plugins/http'
import config from '@/app.config'
const loader = ref<boolean>(true)
const prefixOptions = ref<DataOption[]>([])
const bloodOptions = ref<DataOption[]>([])
const genderOptions = ref<DataOption[]>([])
const statusOptions = ref<DataOption[]>([])
const religionOptions = ref<DataOption[]>([])
const provinceOptions = ref<DataOption[]>([])
</script>

View file

@ -1,10 +1,144 @@
interface Pagination {
rowsPerPage: number;
rowsPerPage: number
}
interface DataDateMonthObject {
month: number
year: number
}
interface ChangeActive {
name: string
id: number
}
//ข้อมูลส่วนตัว
interface Information {
cardid: string
prefix: string
prefixId: string
firstname: string
lastname: string
birthDate: Date
genderId: string
bloodId: string
nationality: string
ethnicity: string
religionId: string
tel: string
phone: string
email: string
provinceId: string
cardIdDate: Date
}
interface Family {
prefixC: string // couple
prefixIdC: string
firstnameC: string
lastnameC: string
occupationC: string
nationalityC: string
prefixM: string // male
prefixIdM: string
firstnameM: string
lastnameM: string
occupationM: string
nationalityM: string
prefixF: string // female
prefixIdF: string
firstnameF: string
lastnameF: string
occupationF: string
nationalityF: string
same: string
}
interface Address {
address: string
provinceId: string
districtId: string
subdistrictId: string
addressC: string
provinceIdC: string
districtIdC: string
subdistrictIdC: string
same: string
}
interface DataOption {
id: string;
name: string;
id: string
name: string
zipCode?: string
}
export type { Pagination, DataOption };
interface zipCodeOption {
id: string
name: string
zipCode: string
}
const defaultAddress: Address = {
address: 'บ้านเลขที่ 1/2 ซอย 56 ถนนตัดใหม่',
provinceId: 'f122211c-7e35-4bbc-ad0f-b3a853ed1cea',
districtId: '16813e59-c03a-4c97-ab6f-59438a44e422',
subdistrictId: '0d21e8af-6507-4312-a214-3e5a870f856d',
addressC: 'บ้านเลขที่ 1/2 ซอย 56 ถนนตัดใหม่',
provinceIdC: 'f122211c-7e35-4bbc-ad0f-b3a853ed1cea',
districtIdC: '16813e59-c03a-4c97-ab6f-59438a44e422',
subdistrictIdC: '0d21e8af-6507-4312-a214-3e5a870f856d',
same: '0'
}
const defaultInformation: Information = {
cardid: '10238002345325',
prefix: 'นางสาว',
prefixId: '0f6dc562-e4a4-4014-9b20-5c97ea811755',
firstname: 'ณัฐกา',
lastname: 'ชมสิน',
birthDate: new Date('2002-01-01'),
genderId: 'ee1063a0-8ceb-4f9c-af06-107a58823957',
bloodId: '5c0c5185-ca99-4593-a7a3-c5ec56230e03',
nationality: 'ไทย',
ethnicity: 'ไทย',
religionId: '1fe77f89-c3b2-4b2c-b255-558375acc35b',
tel: '0914569982',
phone: '0914569982',
email: 'test@test.test',
provinceId: 'zxczxczxcasc',
cardIdDate: new Date('2000-01-10')
}
const defaultFamily: Family = {
prefixC: 'นาย',
prefixIdC: 'b3033046-20a8-46fc-9f9c-47447f49830b',
firstnameC: 'ธนาคาร',
lastnameC: 'กสิกร',
occupationC: 'ว่าง',
nationalityC: 'ไทย',
prefixM: 'นาย',
prefixIdM: 'b3033046-20a8-46fc-9f9c-47447f49830b',
firstnameM: 'ธนายุทธ',
lastnameM: 'ชมสิน',
occupationM: 'ว่าง',
nationalityM: 'ไทย',
prefixF: 'นางสาว',
prefixIdF: '0f6dc562-e4a4-4014-9b20-5c97ea811755',
firstnameF: 'ณัฐกาล',
lastnameF: 'ชมสิน',
occupationF: 'ว่าง',
nationalityF: 'ไทย',
same: '1'
}
export { defaultInformation, defaultFamily, defaultAddress }
export type {
Pagination,
DataOption,
DataDateMonthObject,
ChangeActive,
Information,
Family,
Address,
zipCodeOption
}

View file

@ -0,0 +1,29 @@
interface DataProps {
row: RequestItemsObject
rowIndex: number
}
//ข้อมูล
interface RequestItemsObject {
id: string
location: string
position: string
salary: number | null
duration: [Date, Date]
reason: 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

@ -11,7 +11,7 @@ interface RequestItemsObject {
major: string
scores: number | null
name: string
duration: any
duration: [Date, Date]
}
//columns

View file

@ -0,0 +1,11 @@
//ข้อมูล
interface ResponseObject {
id: string
location: string
position: string
salary: number | null
duration: [Date, Date]
reason: string
}
export type { ResponseObject }

View file

@ -6,7 +6,7 @@ interface ResponseObject {
major: string
scores: number | null
name: string
duration: any
duration: [Date, Date]
}
export type { ResponseObject }

View file

@ -5,16 +5,19 @@ export const useExamDataStore = defineStore('exam', () => {
interface exam {
main: { columns: String[] }
education: { columns: String[] }
career: { columns: String[] }
}
const examData = ref<exam>({
main: { columns: [] },
education: { columns: [] }
education: { columns: [] },
career: { columns: [] }
})
const changeExamColumns = (system: String, val: String[]) => {
if (system == 'main') examData.value.main.columns = val
if (system == 'education') examData.value.education.columns = val
if (system == 'career') examData.value.career.columns = val
localStorage.setItem('exam', JSON.stringify(examData.value))
}

348
src/stores/mixin.ts Normal file
View file

@ -0,0 +1,348 @@
import { ref, computed } from 'vue'
import { defineStore } from 'pinia'
import moment from 'moment'
import type { DataDateMonthObject } from '@/modules/01_exam/interface/index/Main'
export const useCounterMixin = defineStore('mixin', () => {
/**
*
*/
const calAge = (srcDate: Date, birthCal: Date = new Date(), eng: boolean = false) => {
const toDay = birthCal
const birth = new Date(srcDate)
const yearNow = toDay.getFullYear()
const monthNow = toDay.getMonth()
const dateNow = toDay.getDate()
const yearDob = birth.getFullYear()
const monthDob = birth.getMonth()
const dateDob = birth.getDate()
const lastYear = 12
const subtractDate: Object = moment().subtract(1, 'months').endOf('month')
const lastMonths = new Date(subtractDate.toString()).getDate()
let yearAge = yearNow - yearDob
let monthAge = 0
let dateAge = 0
if (monthNow >= monthDob) {
monthAge = monthNow - monthDob
} else {
yearAge--
monthAge = lastYear + monthNow - monthDob
}
if (dateNow >= dateDob) {
dateAge = dateNow - dateDob
} else {
monthAge--
dateAge = lastMonths + dateNow - dateDob
if (monthAge < 0) {
monthAge = 11
yearAge--
}
}
const age = {
years: yearAge,
months: monthAge,
days: dateAge
}
const year = eng ? 'years' : 'ปี'
const month = eng ? 'months' : 'เดือน'
const day = eng ? 'days' : 'วัน'
return `${yearAge} ${year} ${monthAge} ${month} ${dateAge} ${day}`
}
function date2Thai(srcDate: Date, isFullMonth: boolean = false, isTime: boolean = false) {
const date = new Date(srcDate)
const isValidDate = Boolean(+date)
if (!isValidDate) return srcDate.toString()
if (isValidDate && date.getFullYear() < 1000) return srcDate.toString()
const fullMonthThai = [
'มกราคม',
'กุมภาพันธ์',
'มีนาคม',
'เมษายน',
'พฤษภาคม',
'มิถุนายน',
'กรกฎาคม',
'สิงหาคม',
'กันยายน',
'ตุลาคม',
'พฤศจิกายน',
'ธันวาคม'
]
const abbrMonthThai = [
'ม.ค.',
'ก.พ.',
'มี.ค.',
'เม.ย.',
'พ.ค.',
'มิ.ย.',
'ก.ค.',
'ส.ค.',
'ก.ย.',
'ต.ค.',
'พ.ย.',
'ธ.ค.'
]
let dstYear = 0
if (date.getFullYear() > 2500) {
dstYear = date.getFullYear()
} else {
dstYear = date.getFullYear() + 543
}
let dstMonth = ''
if (isFullMonth) {
dstMonth = fullMonthThai[date.getMonth()]
} else {
dstMonth = abbrMonthThai[date.getMonth()]
}
let dstTime = ''
if (isTime) {
const H = date.getHours().toString().padStart(2, '0')
const M = date.getMinutes().toString().padStart(2, '0')
// const S = date.getSeconds().toString().padStart(2, "0")
// dstTime = " " + H + ":" + M + ":" + S + " น."
dstTime = ' ' + H + ':' + M + ' น.'
}
return date.getDate().toString().padStart(2, '0') + ' ' + dstMonth + ' ' + dstYear + dstTime
}
function monthYear2Thai(month: number, year: number, isFullMonth = false) {
const date = new Date(`${year}-${month + 1}-1`)
const fullMonthThai = [
'มกราคม',
'กุมภาพันธ์',
'มีนาคม',
'เมษายน',
'พฤษภาคม',
'มิถุนายน',
'กรกฎาคม',
'สิงหาคม',
'กันยายน',
'ตุลาคม',
'พฤศจิกายน',
'ธันวาคม'
]
const abbrMonthThai = [
'ม.ค.',
'ก.พ.',
'มี.ค.',
'เม.ย.',
'พ.ค.',
'มิ.ย.',
'ก.ค.',
'ส.ค.',
'ก.ย.',
'ต.ค.',
'พ.ย.',
'ธ.ค.'
]
let dstYear = 0
if (date.getFullYear() > 2500) {
dstYear = date.getFullYear()
} else {
dstYear = date.getFullYear() + 543
}
let dstMonth = ''
if (isFullMonth) {
dstMonth = fullMonthThai[date.getMonth()]
} else {
dstMonth = abbrMonthThai[date.getMonth()]
}
return dstMonth + ' ' + dstYear
}
function dateToISO(date: Date) {
return (
date.getFullYear() +
'-' +
appendLeadingZeroes(date.getMonth() + 1) +
'-' +
appendLeadingZeroes(date.getDate())
)
}
function appendLeadingZeroes(n: Number) {
if (n <= 9) return '0' + n
return n
}
function textToPhone(n: string) {
const p = n.substr(0, 3) + '-' + n.substr(3, 3) + '-' + n.substr(6, 4)
return p
}
function textToFax(n: string) {
const p = n.substr(0, 2) + '-' + n.substr(2, 3) + '-' + n.substr(5, 4)
return p
}
const success = (q: any, val: string) => {
// useQuasar ไม่สามารถใช้นอกไฟล์ .vue
if (val !== '') {
return q.notify({
message: val,
color: 'primary',
icon: 'mdi-information',
position: 'bottom-right',
multiLine: true,
timeout: 1000,
badgeColor: 'positive',
classes: 'my-notif-class'
})
}
}
function notify(q: any, val: string) {
if (val !== '') {
q.notify({
color: 'teal-10',
message: val,
icon: 'mdi-information',
position: 'bottom-right',
multiLine: true,
timeout: 7000,
actions: [{ label: 'ปิด', color: 'white', handler: () => {} }]
})
}
}
function notifyError(q: any, val: string) {
if (val !== '') {
q.notify({
color: 'negative',
message: val,
icon: 'mdi-alert-circle',
position: 'top',
multiLine: true,
timeout: 12000,
actions: [{ label: 'ปิด', color: 'white', handler: () => {} }]
})
}
}
const dateText = (val: Date) => {
if (val != null) {
return date2Thai(val)
} else {
return '-'
}
}
const weekThai = (val: Number) => {
switch (val) {
case 0:
return 'วันอาทิตย์'
case 1:
return 'วันจันทร์'
case 2:
return 'วันอังคาร'
case 3:
return 'วันพุธ'
case 4:
return 'วันพฤหัสบดี'
case 5:
return 'วันศุกร์'
case 6:
return 'วันเสาร์'
default:
return '-'
}
}
const genColor15 = (val: number) => {
val = val % 15
switch (val) {
case 1:
return 'pink'
case 2:
return 'purple'
case 3:
return 'deep-purple'
case 4:
return 'indigo'
case 5:
return 'blue'
case 6:
return 'light-blue'
case 7:
return 'cyan'
case 8:
return 'teal'
case 9:
return 'green'
case 10:
return 'light-green'
case 11:
return 'amber'
case 12:
return 'orange'
case 13:
return 'deep-orange'
case 14:
return 'brown'
case 0:
return 'blue-grey'
default:
return ''
}
}
/**
* 2
* @param val
*/
const dateThaiRange = (val: [Date, Date]) => {
if (val === null) {
return ''
} else if (date2Thai(val[0]) === date2Thai(val[1])) {
return `${date2Thai(val[0])}`
} else {
return `${date2Thai(val[0])} - ${date2Thai(val[1])}`
}
}
/**
* 2
* @param val
*/
const monthThaiRange = (val: DataDateMonthObject[]) => {
if (val === null || val[0] === null || val[1] === null) {
return ''
} else if (
monthYear2Thai(val[0].month, val[0].year) === monthYear2Thai(val[1].month, val[1].year)
) {
return `${monthYear2Thai(val[0].month, val[0].year)}`
} else {
return `${monthYear2Thai(val[0].month, val[0].year)} - ${monthYear2Thai(
val[1].month,
val[1].year
)}`
}
}
return {
calAge,
date2Thai,
dateToISO,
notify,
notifyError,
dateText,
monthYear2Thai,
success,
weekThai,
genColor15,
textToPhone,
textToFax,
dateThaiRange,
monthThaiRange
}
})