client initial commit

This commit is contained in:
Methapon2001 2023-11-23 08:47:44 +07:00
parent b5f98baa2b
commit dd1547d7c2
No known key found for this signature in database
GPG key ID: 849924FEF46BD132
70 changed files with 18446 additions and 0 deletions

View file

@ -0,0 +1,220 @@
<script setup lang="ts">
import { ref } from 'vue'
const isAdvncSearchClick = ref<boolean>(false)
const optionsField = [
{ label: 'ชื่อเรื่อง (title)', value: 'title' },
{ label: 'คำสำคัญ (keyword)', value: 'keyword' },
]
const optionsOp = [
{ label: 'และ', value: 'AND' },
{ label: 'หรือ', value: 'OR' },
]
const advSearchData = ref<
{
op: 'AND' | 'OR'
field: 'title' | 'keyword'
value: string
}[]
>([])
const props = defineProps<{
field: string
value: string
keyword?: string
description?: string
searchSubmit: Function
submitSearchData: {
AND: {
field?: string
value?: string
}[]
OR: {
field: string
value: string
}[]
}
}>()
defineExpose({
clearAdvData,
advSearchData,
})
defineEmits([
'update:field',
'update:value',
'update:keyword',
'update:description',
])
function addSearchData() {
advSearchData.value.push({
op: 'AND',
field: 'title',
value: '',
})
}
function clearAdvData() {
advSearchData.value = []
}
</script>
<template>
<div>
<q-btn
outline
color="primary"
icon="mdi-tools"
label="ค้นหาขั้นสูง"
@click="() => (isAdvncSearchClick = true)"
/>
</div>
<q-dialog v-model="isAdvncSearchClick">
<q-card style="width: 1000px; max-width: 80vw">
<q-toolbar class="bg-grey-1 q-py-sm q-px-lg">
<q-toolbar-title>
<span class="text-weight-bold">นหาขนส</span>
</q-toolbar-title>
<q-btn flat round dense icon="close" v-close-popup color="red" />
</q-toolbar>
<q-separator />
<div class="col">
<q-card-section class="row q-mt-sm">
<div class="col">
<div class="row q-col-gutter-md q-mb-md items-center">
<div class="col-12 col-md-3">
<q-select
dense
outlined
emit-value
map-options
:options="optionsField"
:model-value="props.field"
@update:model-value="(value) => $emit('update:field', value)"
/>
</div>
<div class="col-12 col-md-8">
<q-input
dense
outlined
placeholder="เอกสาร"
:model-value="props.value"
@update:model-value="(value) => $emit('update:value', value)"
/>
</div>
<div class="col-1">
<q-btn
dense
color="teal"
icon="mdi-plus"
v-if="advSearchData.length === 0"
@click="addSearchData"
/>
</div>
</div>
<div
class="row q-col-gutter-md q-mb-md items-center"
v-for="(_, index) in advSearchData"
>
<div class="col-4 col-md-2">
<q-select
dense
outlined
emit-value
map-options
v-model="advSearchData[index].op"
:options="optionsOp"
/>
</div>
<div class="col-8 col-md-3">
<q-select
dense
outlined
emit-value
map-options
v-model="advSearchData[index].field"
:options="optionsField"
/>
</div>
<div class="col-12 col-md-6">
<q-input
dense
outlined
v-model="advSearchData[index].value"
placeholder="เอกสาร"
/>
</div>
<div class="col-1">
<q-btn
dense
color="teal"
icon="mdi-plus"
v-if="index === advSearchData.length - 1"
@click="addSearchData"
/>
<q-btn
dense
flat
icon="mdi-minus"
color="red"
v-if="index === advSearchData.length - 1"
@click="() => advSearchData.pop()"
/>
</div>
</div>
</div>
</q-card-section>
<q-card-section class="row q-mb-md">
<div class="col">
<span> </span>
<q-separator class="q-mb-lg" />
<div class="row q-col-gutter-md">
<div class="col-12 col-md-3 q-gutter-y-sm">
<span class="text-weight-bold">คำสำค</span>
<q-input
dense
outlined
placeholder="กรอกคำสำคัญ"
:model-value="props.keyword"
@update:model-value="
(value) => $emit('update:keyword', value)
"
/>
</div>
<div class="col-12 col-md-4 q-gutter-y-sm">
<span class="text-weight-bold">รายละเอยดของเอกสาร</span>
<q-input
dense
outlined
placeholder="กรอกรายละเอียด"
:model-value="props.description"
@update:model-value="
(value) => $emit('update:description', value)
"
/>
</div>
</div>
</div>
</q-card-section>
<q-separator />
<q-toolbar class="row justify-end">
<div class="q-py-md">
<q-btn
color="primary"
label="ค้นหา"
icon="mdi-magnify"
v-close-popup
@click="() => props.searchSubmit()"
/>
</div>
</q-toolbar>
</div>
</q-card>
</q-dialog>
</template>

View file

@ -0,0 +1,188 @@
<script setup lang="ts">
import axios from 'axios'
import { ref } from 'vue'
import { storeToRefs } from 'pinia'
import type { EhrFile } from '@/stores/tree-data'
import AdvancedSearch from '@/modules/01_user/components/AdvancedSearch.vue'
import { useSearchDataStore } from '@/stores/searched-data'
import { useLoader } from '@/stores/loader'
const loaderStore = useLoader()
const { isSearch } = storeToRefs(useSearchDataStore())
const { getFoundFile } = useSearchDataStore()
const advSearchComp = ref<InstanceType<typeof AdvancedSearch>>()
const isAdvSearchCall = ref<boolean>(false)
const optionsField = [
{ label: 'ชื่อเรื่อง (title)', value: 'title' },
{ label: 'คำสำคัญ (keyword)', value: 'keyword' },
]
const searchData = ref<{
field: string
value: string
keyword?: string
description?: string
}>({
field: 'title',
value: '',
keyword: '',
description: '',
})
const submitSearchData = ref<{
AND: {
field?: string
value?: string
}[]
OR: { field: string; value: string }[]
}>({
AND: [],
OR: [],
})
function clearSearchData() {
searchData.value = {
field: 'title',
value: '',
keyword: '',
description: '',
}
submitSearchData.value = {
AND: [],
OR: [],
}
advSearchComp.value?.clearAdvData()
isAdvSearchCall.value = false
isSearch.value = false
}
async function searchSubmit() {
submitSearchData.value = {
AND: [],
OR: [],
}
if (searchData.value.field && searchData.value) {
submitSearchData.value?.AND.push({
field: searchData.value.field,
value: searchData.value.value,
})
if (searchData.value.keyword) {
submitSearchData.value?.AND.push({
field: 'keyword',
value: searchData.value.keyword,
})
}
if (searchData.value.description) {
submitSearchData.value?.AND.push({
field: 'description',
value: searchData.value.description,
})
}
}
if (isAdvSearchCall.value) {
if (
advSearchComp.value?.advSearchData &&
advSearchComp.value.advSearchData.length > 0
) {
advSearchComp.value?.advSearchData.forEach(
(d: { field: string; value: string; op: string }) => {
if (d.field && d.value) {
if (d.op === 'AND') {
submitSearchData.value.AND.push({
field: d.field,
value: d.value,
})
} else if (d.op === 'OR') {
submitSearchData.value.OR.push({ field: d.field, value: d.value })
}
}
}
)
}
}
try {
loaderStore.show()
isAdvSearchCall.value = true
const res = await axios.post<EhrFile[]>(
`${import.meta.env.VITE_API_ENDPOINT}/search`,
submitSearchData.value
)
getFoundFile(res.data)
isSearch.value = true
} catch (error) {
console.error('Error during the request', error)
} finally {
loaderStore.hide()
}
}
</script>
<template>
<div class="q-py-lg q-px-md bg-grey-1">
<div class="row items-center q-gutter-md">
<div class="col-12 col-md-3">
<q-select
dense
outlined
emit-value
map-options
class="bg-white"
v-model="searchData.field"
:options="optionsField"
/>
</div>
<div class="col-12 col-md-grow">
<q-input
class="bg-white"
dense
outlined
v-model="searchData.value"
placeholder="เอกสาร"
@keydown.enter.prevent="searchSubmit"
/>
</div>
<div v-if="isAdvSearchCall === false">
<q-btn
class="col-12 col-md-2"
color="primary"
label="ค้นหา"
icon="mdi-magnify"
@click="() => searchSubmit()"
/>
</div>
</div>
<div
v-if="isAdvSearchCall"
class="row items-center justify-between q-gutter-y-md q-mt-xs"
>
<div>
<advanced-search
ref="advSearchComp"
:searchSubmit="searchSubmit"
:submit-search-data="submitSearchData"
v-model:field="searchData.field"
v-model:value="searchData.value"
v-model:keyword="searchData.keyword"
v-model:description="searchData.description"
/>
</div>
<div class="q-gutter-x-md">
<q-btn
color="primary"
label="ค้นหา"
icon="mdi-magnify"
@click="searchSubmit"
/>
<q-btn
color="orange-12"
label="ล้างข้อมูล"
icon="close"
@click="clearSearchData"
/>
</div>
</div>
</div>
<q-separator />
</template>

View file

@ -0,0 +1,9 @@
// const adminHomePage = () => import('@/modules/02_transfer/views/Main.vue')
export default [
{
path: '/',
name: 'UserHomePage',
component: () => import('@/modules/01_user/views/homePage.vue')
}
]

View file

@ -0,0 +1,8 @@
<script setup lang="ts">
import PageLayout from '@/components/PageLayout.vue'
</script>
<template>
<page-layout mode="user" />
</template>
<style scoped></style>

View file

@ -0,0 +1,9 @@
// const adminHomePage = () => import('@/modules/02_transfer/views/Main.vue')
export default [
{
path: '/admin',
name: 'AdminHomePage',
component: () => import('@/modules/02_admin/views/homePage.vue')
}
]

View file

@ -0,0 +1,18 @@
<script setup lang="ts">
import PageLayout from '@/components/PageLayout.vue'
</script>
<template>
<page-layout mode="admin" />
</template>
<style scoped lang="scss">
#container > [class^='col'] > * {
border: 1px solid $separator-color;
overflow: hidden;
}
#container-header {
background-color: #fafafa;
}
</style>