refactor: misc

This commit is contained in:
puriphatt 2024-08-20 18:04:42 +07:00
parent c22e3a4c52
commit 18efaa48b6
10 changed files with 214 additions and 68 deletions

View file

@ -371,6 +371,7 @@ watch(
const today = new Date(); const today = new Date();
const date = parseAndFormatDate(v, locale); const date = parseAndFormatDate(v, locale);
birthDate = date && date > today ? today : date; birthDate = date && date > today ? today : date;
console.log(today);
} }
} }
" "

View file

@ -153,7 +153,14 @@ watch(
hide-bottom-space hide-bottom-space
class="col-6" class="col-6"
:label="$t('formDialogInputPassportRef')" :label="$t('formDialogInputPassportRef')"
v-model="previousPassportReference" :model-value="
readonly
? previousPassportReference || '-'
: previousPassportReference
"
@update:model-value="
(v) => (typeof v === 'string' ? (previousPassportReference = v) : '')
"
/> />
<q-input <q-input
lazy-rules="ondemand" lazy-rules="ondemand"

View file

@ -91,7 +91,7 @@ watch(
size="xs" size="xs"
class="q-pa-sm rounded q-mr-xs" class="q-pa-sm rounded q-mr-xs"
color="info" color="info"
name="mdi-notebook" name="mdi-notebook-outline"
style="background-color: var(--surface-3)" style="background-color: var(--surface-3)"
/> />
{{ $t(`${title}`) }} {{ $t(`${title}`) }}
@ -107,7 +107,6 @@ watch(
hide-selected hide-selected
hide-bottom-space hide-bottom-space
input-debounce="0" input-debounce="0"
v-model="visaType"
option-value="value" option-value="value"
option-label="label" option-label="label"
lazy-rules="ondemand" lazy-rules="ondemand"
@ -119,6 +118,11 @@ watch(
:for="`${prefixId}-select-visa-type`" :for="`${prefixId}-select-visa-type`"
:label="$t('formDialogInputVisaType')" :label="$t('formDialogInputVisaType')"
@filter="visaTypeFilter" @filter="visaTypeFilter"
:model-value="readonly ? visaType || '-' : visaType"
@update:model-value="
(v) => (typeof v === 'string' ? (visaType = v) : '')
"
@clear="visaType = ''"
> >
<template v-slot:no-option> <template v-slot:no-option>
<q-item> <q-item>
@ -141,7 +145,10 @@ watch(
hide-bottom-space hide-bottom-space
class="col-4" class="col-4"
:label="$t('formDialogInputVisaNo')" :label="$t('formDialogInputVisaNo')"
v-model="visaNumber" :model-value="readonly ? visaNumber || '-' : visaNumber"
@update:model-value="
(v) => (typeof v === 'string' ? (visaNumber = v) : '')
"
/> />
<!-- :rules="[ <!-- :rules="[
(val: string) => (val: string) =>
@ -181,7 +188,9 @@ watch(
? readonly ? readonly
? dateFormat(visaIssueDate) ? dateFormat(visaIssueDate)
: dateFormat(visaIssueDate, false, false, true) : dateFormat(visaIssueDate, false, false, true)
: undefined : readonly
? '-'
: undefined
" "
@update:model-value=" @update:model-value="
(v) => { (v) => {
@ -249,7 +258,9 @@ watch(
? readonly ? readonly
? dateFormat(visaExpiryDate) ? dateFormat(visaExpiryDate)
: dateFormat(visaExpiryDate, false, false, true) : dateFormat(visaExpiryDate, false, false, true)
: undefined : readonly
? '-'
: undefined
" "
@update:model-value=" @update:model-value="
(v) => { (v) => {
@ -293,7 +304,10 @@ watch(
hide-bottom-space hide-bottom-space
class="col-5" class="col-5"
:label="$t('formDialogInputVisaPlace')" :label="$t('formDialogInputVisaPlace')"
v-model="visaIssuingPlace" :model-value="readonly ? visaIssuingPlace || '-' : visaIssuingPlace"
@update:model-value="
(v) => (typeof v === 'string' ? (visaIssuingPlace = v) : '')
"
/> />
<!-- :rules="[ <!-- :rules="[
(val: string) => (val: string) =>
@ -333,7 +347,9 @@ watch(
? readonly ? readonly
? dateFormat(visaStayUntilDate) ? dateFormat(visaStayUntilDate)
: dateFormat(visaStayUntilDate, false, false, true) : dateFormat(visaStayUntilDate, false, false, true)
: undefined : readonly
? '-'
: undefined
" "
@update:model-value=" @update:model-value="
(v) => { (v) => {
@ -378,7 +394,11 @@ watch(
hide-bottom-space hide-bottom-space
class="col-5" class="col-5"
:label="$t('formDialogInputVisaTM6')" :label="$t('formDialogInputVisaTM6')"
v-model="tm6Number" :model-value="readonly ? tm6Number || '-' : tm6Number"
@update:model-value="
(v) => (typeof v === 'string' ? (tm6Number = v) : '')
"
@clear="tm6Number = ''"
/> />
<!-- :rules="[ <!-- :rules="[
(val: string) => (val: string) =>
@ -417,7 +437,9 @@ watch(
? readonly ? readonly
? dateFormat(entryDate) ? dateFormat(entryDate)
: dateFormat(entryDate, false, false, true) : dateFormat(entryDate, false, false, true)
: undefined : readonly
? '-'
: undefined
" "
@update:model-value=" @update:model-value="
(v) => { (v) => {

View file

@ -349,7 +349,7 @@ onMounted(() => {
<q-input <q-input
lazy-rules="ondemand" lazy-rules="ondemand"
mask="## #### ###### #" :mask="readonly ? '' : '## #### ###### #'"
:for="`${prefixId}-input-nrc-no`" :for="`${prefixId}-input-nrc-no`"
:dense="dense" :dense="dense"
outlined outlined
@ -357,7 +357,8 @@ onMounted(() => {
:readonly="readonly" :readonly="readonly"
class="col-6" class="col-6"
:label="$t('formDialogEmployeeNRCNo')" :label="$t('formDialogEmployeeNRCNo')"
v-model="nrcNo" :model-value="readonly ? nrcNo || '-' : nrcNo"
@update:model-value="(v) => (typeof v === 'string' ? (nrcNo = v) : '')"
/> />
</div> </div>
</div> </div>

View file

@ -82,7 +82,10 @@ function reset() {
</div> </div>
<div v-else style="width: 38.8px"></div> <div v-else style="width: 38.8px"></div>
<div class="col text-weight-bold text-center"> <div
class="col text-weight-bold text-center ellipsis"
style="width: 0px"
>
<text <text
v-if="badgeLabel" v-if="badgeLabel"
class="badge-label badge text-caption q-px-sm q-mr-sm" class="badge-label badge text-caption q-px-sm q-mr-sm"
@ -93,7 +96,9 @@ function reset() {
<text v-if="category" class="app-text-muted q-mr-sm"> <text v-if="category" class="app-text-muted q-mr-sm">
{{ category }} {{ category }}
</text> </text>
{{ title }} <span>
{{ title }}
</span>
<text <text
v-if="!!statusBranch" v-if="!!statusBranch"

View file

@ -171,6 +171,7 @@ defineEmits<{
@click="$emit('editProfile')" @click="$emit('editProfile')"
> >
<q-img <q-img
v-if="!$slots.img"
:src="data.img ?? '/no-profile.png'" :src="data.img ?? '/no-profile.png'"
style=" style="
object-fit: cover; object-fit: cover;
@ -188,6 +189,7 @@ defineEmits<{
</div> </div>
</template> </template>
</q-img> </q-img>
<slot name="img"></slot>
<q-badge <q-badge
class="absolute-bottom-right" class="absolute-bottom-right"
style=" style="

View file

@ -19,6 +19,7 @@ import useMyBranchStore from 'stores/my-branch';
const useMyBranch = useMyBranchStore(); const useMyBranch = useMyBranchStore();
const { fetchListMyBranch } = useMyBranch; const { fetchListMyBranch } = useMyBranch;
const apiBaseUrl = import.meta.env.VITE_API_BASE_URL;
interface NotificationButton { interface NotificationButton {
item: string; item: string;
@ -52,6 +53,7 @@ const filterUnread = ref(false);
const unread = ref<number>(1); const unread = ref<number>(1);
// const filterRole = ref<string[]>(); // const filterRole = ref<string[]>();
const userImage = ref<string>(); const userImage = ref<string>();
const userGender = ref('');
const canvasRef = ref(); const canvasRef = ref();
const currentLanguage = ref<string>('ไทย'); const currentLanguage = ref<string>('ไทย');
const language: { const language: {
@ -169,9 +171,12 @@ onMounted(async () => {
if (user === 'admin') return; if (user === 'admin') return;
if (uid) { if (uid) {
const res = await userStore.fetchById(uid); userImage.value = `${apiBaseUrl}/user/${uid}/image`;
if (res && res.profileImageUrl) userImage.value = res.profileImageUrl; const res = await userStore.fetchById(uid);
if (res && res.gender) {
userGender.value = res.gender;
}
} }
}); });
</script> </script>
@ -455,8 +460,9 @@ onMounted(async () => {
} }
" "
:user-image=" :user-image="
getRole()?.includes('system') ? '/img-admin.png' : ' ' getRole()?.includes('system') ? '/img-admin.png' : userImage
" "
:gender="userGender"
/> />
</div> </div>
</div> </div>

View file

@ -12,6 +12,7 @@ const filterRole = ref<string[]>();
defineProps<{ defineProps<{
userImage?: string; userImage?: string;
gender?: string;
}>(); }>();
const inputFile = document.createElement('input'); const inputFile = document.createElement('input');
@ -166,10 +167,40 @@ onMounted(async () => {
class="surface-1 bordered" class="surface-1 bordered"
:size="$q.screen.lt.sm ? '30px' : '40px'" :size="$q.screen.lt.sm ? '30px' : '40px'"
> >
<img :src="userImage" v-if="userImage" /> <q-img
:ratio="1"
class="text-center"
:src="userImage"
v-if="userImage"
>
<template #error>
<div
class="no-padding full-width full-height flex items-center justify-center"
style="
background: linear-gradient(
135deg,
rgba(43, 137, 223, 1) 0%,
rgba(230, 51, 81, 1) 100%
);
"
>
<q-img
v-if="gender"
:ratio="1"
:src="`/no-img-${gender === 'female' ? 'female' : 'man'}.png`"
></q-img>
<q-icon
v-else
name="mdi-account-outline"
color="white"
:size="$q.screen.lt.sm ? 'xs' : 'sm'"
/>
</div>
</template>
</q-img>
<q-icon <q-icon
name="mdi-account"
v-else v-else
name="mdi-account-outline"
:size="$q.screen.lt.sm ? 'xs' : 'sm'" :size="$q.screen.lt.sm ? 'xs' : 'sm'"
/> />
</q-avatar> </q-avatar>
@ -213,7 +244,7 @@ onMounted(async () => {
</div> </div>
</div> </div>
<q-menu :offset="[5, 10]"> <q-menu :offset="[5, 10]" max-width="300px">
<div <div
no-padding no-padding
class="row justify-center bordered rounded" class="row justify-center bordered rounded"
@ -240,20 +271,55 @@ onMounted(async () => {
} }
" "
> >
<img :src="userImage" v-if="userImage" /> <q-img
<q-icon name="mdi-account" v-else /> :ratio="1"
class="text-center"
:src="userImage"
v-if="userImage"
>
<template #error>
<div
class="no-padding full-width full-height flex items-center justify-center"
style="
background: linear-gradient(
135deg,
rgba(43, 137, 223, 1) 0%,
rgba(230, 51, 81, 1) 100%
);
"
>
<q-img
v-if="gender"
:ratio="1"
:src="`/no-img-${gender === 'female' ? 'female' : 'man'}.png`"
></q-img>
<q-icon
v-else
name="mdi-account-outline"
color="white"
/>
</div>
</template>
</q-img>
<q-icon name="mdi-account-outline" v-else />
</q-avatar> </q-avatar>
</div> </div>
</div> </div>
<div <div
class="text-subtitle2 q-mb-xs text-center" class="text-subtitle2 q-mb-xs text-center full-width ellipsis q-px-md"
style="margin-top: 58px" style="margin-top: 58px"
> >
<span v-if="isLoggedIn()"> <span v-if="isLoggedIn()">
{{ getName() }} {{ getName() }}
</span> </span>
<span v-else>{{ 'Guest' }}</span> <span v-else>{{ 'Guest' }}</span>
<q-tooltip>
<span v-if="isLoggedIn()">
{{ getName() }}
</span>
<span v-else>{{ 'Guest' }}</span>
</q-tooltip>
</div> </div>
<div <div
class="badge q-px-sm q-mb-md text-caption" class="badge q-px-sm q-mb-md text-caption"
@ -368,7 +434,7 @@ onMounted(async () => {
</template> </template>
<style scoped lang="scss"> <style scoped lang="scss">
.account-menu-down { .account-menu-down {
& ::before { & ::before:not(.q-icon) {
color: var(--foreground); color: var(--foreground);
} }
} }

View file

@ -55,6 +55,7 @@ const userStore = useUserStore();
const branchStore = useBranchStore(); const branchStore = useBranchStore();
const adrressStore = useAddressStore(); const adrressStore = useAddressStore();
const { data: userData } = storeToRefs(userStore); const { data: userData } = storeToRefs(userStore);
const apiBaseUrl = import.meta.env.VITE_API_BASE_URL;
const defaultFormData = { const defaultFormData = {
provinceId: null, provinceId: null,
@ -656,7 +657,7 @@ async function assignFormData(idEdit: string) {
} }
userCode.value = foundUser.code; userCode.value = foundUser.code;
urlProfile.value = foundUser.profileImageUrl; urlProfile.value = `${apiBaseUrl}/user/${foundUser.id}/image`;
isEdit.value = true; isEdit.value = true;
profileSubmit.value = true; profileSubmit.value = true;
@ -1166,50 +1167,35 @@ watch(
<div class="row items-center" style="flex-wrap: nowrap"> <div class="row items-center" style="flex-wrap: nowrap">
<div style="display: flex"> <div style="display: flex">
<div class="q-mr-md"> <div class="q-mr-md">
<q-avatar <q-avatar size="md">
size="md"
style="
background: linear-gradient(
135deg,
rgba(43, 137, 223, 1) 0%,
rgba(230, 51, 81, 1) 100%
);
"
>
<q-img <q-img
v-if="props.row.gender !== ''"
class="text-center" class="text-center"
:ratio="1" :ratio="1"
:src=" :src="`${apiBaseUrl}/user/${props.row.id}/image`"
props.row.profileImageUrl
? props.row.profileImageUrl
: props.row.userRole.includes('system')
? '/img-admin.png'
: props.row.gender === 'male'
? '/no-img-man.png'
: '/no-img-female.png'
"
> >
<template #error> <template #error>
<q-img <div
v-if=" class="no-padding full-width full-height flex items-center justify-center"
props.row.gender === 'male' || :style="`${props.row.gender ? 'background: white' : 'background: linear-gradient(135deg,rgba(43, 137, 223, 1) 0%, rgba(230, 51, 81, 1) 100%);'}`"
props.row.gender === 'female' >
" <q-img
:src=" v-if="props.row.gender"
props.row.gender === 'male' :src="
? '/no-img-man.png' props.row.gender === 'male'
: '/no-img-female.png' ? '/no-img-man.png'
" : '/no-img-female.png'
/> "
/>
<q-icon
v-else
size="sm"
name="mdi-account-outline"
style="color: white"
/>
</div>
</template> </template>
</q-img> </q-img>
<q-icon
v-else
size="sm"
name="mdi-account-outline"
style="color: white"
/>
<q-badge <q-badge
class="absolute-bottom-right no-padding" class="absolute-bottom-right no-padding"
style=" style="
@ -1496,7 +1482,49 @@ watch(
@toggle-status=" @toggle-status="
triggerChangeStatus(props.row.id, props.row.status) triggerChangeStatus(props.row.id, props.row.status)
" "
/> >
<template #img>
<q-img
class="text-center"
:ratio="1"
:src="`${apiBaseUrl}/user/${props.row.id}/image`"
style="
object-fit: cover;
width: 100%;
height: 100%;
border-radius: 50%;
"
>
<template #error>
<div
class="no-padding full-width full-height flex items-center justify-center"
style="
background: linear-gradient(
135deg,
rgba(43, 137, 223, 1) 0%,
rgba(230, 51, 81, 1) 100%
);
"
>
<q-img
v-if="props.row.gender"
:src="
props.row.gender === 'male'
? '/no-img-man.png'
: '/no-img-female.png'
"
/>
<q-icon
v-else
size="lg"
name="mdi-account-outline"
style="color: white"
/>
</div>
</template>
</q-img>
</template>
</PersonCard>
</div> </div>
</template> </template>
</q-table> </q-table>

View file

@ -680,8 +680,8 @@ const emptyCreateDialog = ref(false);
? customerStats.map((v) => ({ ? customerStats.map((v) => ({
count: count:
v.name === 'CORP' v.name === 'CORP'
? statsCustomerType?.CORP ?? 0 ? (statsCustomerType?.CORP ?? 0)
: statsCustomerType?.PERS ?? 0, : (statsCustomerType?.PERS ?? 0),
label: label:
v.name === 'CORP' v.name === 'CORP'
? 'customerLegalEntity' ? 'customerLegalEntity'
@ -2352,7 +2352,7 @@ const emptyCreateDialog = ref(false);
</template> </template>
</ImageUploadDialog> </ImageUploadDialog>
<!-- กจาง --> <!-- กจาง edit employee -->
<DrawerInfo <DrawerInfo
hide-action hide-action
v-model:drawer-open="employeeFormState.drawerModal" v-model:drawer-open="employeeFormState.drawerModal"
@ -2425,13 +2425,21 @@ const emptyCreateDialog = ref(false);
active active
use-toggle use-toggle
color="white" color="white"
icon="mdi-account-plus-outline" icon="mdi-account-outline"
bg-color="linear-gradient(135deg, rgba(43,137,223,1) 0%, rgba(230,51,81,1) 100%)" bg-color="linear-gradient(135deg, rgba(43,137,223,1) 0%, rgba(230,51,81,1) 100%)"
v-model:current-tab="employeeFormState.currentTab" v-model:current-tab="employeeFormState.currentTab"
v-model:toggle-status="currentFromDataEmployee.status" v-model:toggle-status="currentFromDataEmployee.status"
v-model:cover-url="employeeFormState.profileUrl" v-model:cover-url="employeeFormState.profileUrl"
fallback-cover="/images/employee-banner.png" fallback-cover="/images/employee-banner.png"
:img="employeeFormState.profileUrl" :title="
employeeFormState.currentEmployee
? $i18n.locale === 'en-US'
? `${employeeFormState.currentEmployee.firstNameEN} ${employeeFormState.currentEmployee.lastNameEN}`
: `${employeeFormState.currentEmployee.firstName} ${employeeFormState.currentEmployee.lastName}`
: '-'
"
:caption="currentFromDataEmployee.code"
:img="employeeFormState.profileUrl || '/images/employee-avatar.png'"
:tabs-list="[ :tabs-list="[
{ name: 'personalInfo', label: 'personalInfo' }, { name: 'personalInfo', label: 'personalInfo' },
{ name: 'healthCheck', label: 'healthCheck' }, { name: 'healthCheck', label: 'healthCheck' },