feat: update Person Card
This commit is contained in:
parent
e1e7eb4719
commit
4bfe1ccd34
4 changed files with 391 additions and 337 deletions
|
|
@ -102,12 +102,12 @@ function branchSetting() {}
|
||||||
side="left"
|
side="left"
|
||||||
:breakpoint="599"
|
:breakpoint="599"
|
||||||
class="column justify-between no-wrap"
|
class="column justify-between no-wrap"
|
||||||
:width="mini ? 110 : 256"
|
:width="mini ? 80 : 256"
|
||||||
>
|
>
|
||||||
<!-- :width="$q.screen.lt.sm ? $q.screen.width - 16 : 256" -->
|
<!-- :width="$q.screen.lt.sm ? $q.screen.width - 16 : 256" -->
|
||||||
<div class="scroll" style="overflow-x: hidden">
|
<div class="scroll" style="overflow-x: hidden; scrollbar-gutter: stable">
|
||||||
<div
|
<div
|
||||||
class="flex justify-center items-center q-pa-md cursor-pointer"
|
class="flex justify-center items-center q-pl-sm cursor-pointer"
|
||||||
@click="$router.push('/')"
|
@click="$router.push('/')"
|
||||||
id="btn-drawer-home"
|
id="btn-drawer-home"
|
||||||
style="height: 128px"
|
style="height: 128px"
|
||||||
|
|
@ -120,12 +120,12 @@ function branchSetting() {}
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div id="drawer-menu" class="q-px-md">
|
<div id="drawer-menu" class="q-pl-md q-mr-xs">
|
||||||
<q-item
|
<q-item
|
||||||
v-for="v in labelMenu"
|
v-for="v in labelMenu"
|
||||||
dense
|
dense
|
||||||
clickable
|
clickable
|
||||||
class="row items-center q-my-xs"
|
class="row items-center q-my-xs q-px-xs"
|
||||||
:key="v.label"
|
:key="v.label"
|
||||||
:disable="!!v.disabled"
|
:disable="!!v.disabled"
|
||||||
:class="{
|
:class="{
|
||||||
|
|
|
||||||
|
|
@ -5,7 +5,15 @@ const props = withDefaults(
|
||||||
icon: string;
|
icon: string;
|
||||||
count: number;
|
count: number;
|
||||||
label: string;
|
label: string;
|
||||||
color: 'pink' | 'purple' | 'green' | 'orange';
|
color:
|
||||||
|
| 'pink'
|
||||||
|
| 'purple'
|
||||||
|
| 'green'
|
||||||
|
| 'orange'
|
||||||
|
| 'cyan'
|
||||||
|
| 'yellow'
|
||||||
|
| 'red'
|
||||||
|
| 'magenta';
|
||||||
}[];
|
}[];
|
||||||
dark?: boolean;
|
dark?: boolean;
|
||||||
labelI18n?: boolean;
|
labelI18n?: boolean;
|
||||||
|
|
@ -79,10 +87,26 @@ const props = withDefaults(
|
||||||
--_color: var(--teal-10-hsl);
|
--_color: var(--teal-10-hsl);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.stat-card__cyan {
|
||||||
|
--_color: var(--cyan-7-hsl);
|
||||||
|
}
|
||||||
|
|
||||||
|
.stat-card__red {
|
||||||
|
--_color: var(--red-6-hsl);
|
||||||
|
}
|
||||||
|
|
||||||
|
.stat-card__yellow {
|
||||||
|
--_color: var(--orange-4-hsl);
|
||||||
|
}
|
||||||
|
|
||||||
.stat-card__orange {
|
.stat-card__orange {
|
||||||
--_color: var(--orange-5-hsl);
|
--_color: var(--orange-5-hsl);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.stat-card__magenta {
|
||||||
|
--_color: var(--pink-8-hsl);
|
||||||
|
}
|
||||||
|
|
||||||
.dark .stat-card__purple {
|
.dark .stat-card__purple {
|
||||||
--_color: var(--violet-10-hsl);
|
--_color: var(--violet-10-hsl);
|
||||||
}
|
}
|
||||||
|
|
@ -94,4 +118,8 @@ const props = withDefaults(
|
||||||
.dark .stat-card__orange {
|
.dark .stat-card__orange {
|
||||||
--_color: var(--orange-6-hsl);
|
--_color: var(--orange-6-hsl);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.dark .stat-card__magenta {
|
||||||
|
--_color: var(--pink-7-hsl);
|
||||||
|
}
|
||||||
</style>
|
</style>
|
||||||
|
|
|
||||||
|
|
@ -5,70 +5,57 @@ import AppBox from 'components/app/AppBox.vue';
|
||||||
import AppCircle from 'components/app/AppCircle.vue';
|
import AppCircle from 'components/app/AppCircle.vue';
|
||||||
|
|
||||||
defineProps<{
|
defineProps<{
|
||||||
list: {
|
data: {
|
||||||
id: string;
|
|
||||||
name: string;
|
name: string;
|
||||||
detail?: { label: string; value: string }[];
|
code: string;
|
||||||
male?: boolean;
|
male?: boolean;
|
||||||
female?: boolean;
|
female?: boolean;
|
||||||
disabled?: boolean;
|
|
||||||
badge?: string;
|
|
||||||
img?: string;
|
img?: string;
|
||||||
}[];
|
detail?: { icon: string; value: string }[];
|
||||||
gridColumns?: number;
|
};
|
||||||
|
tag?: [{ color: string; value: string }];
|
||||||
|
disabled?: boolean;
|
||||||
noHover?: boolean;
|
noHover?: boolean;
|
||||||
noAction?: boolean;
|
noAction?: boolean;
|
||||||
noDetail?: boolean;
|
|
||||||
noBg?: boolean;
|
noBg?: boolean;
|
||||||
detailColumnCount?: number;
|
|
||||||
canEditProfile?: boolean;
|
|
||||||
history?: boolean;
|
history?: boolean;
|
||||||
}>();
|
}>();
|
||||||
|
|
||||||
defineEmits<{
|
defineEmits<{
|
||||||
(e: 'editProfile'): void;
|
(e: 'editProfile'): void;
|
||||||
(e: 'history', id: string): void;
|
(e: 'history'): void;
|
||||||
(e: 'deleteCard', id: string): void;
|
(e: 'deleteCard'): void;
|
||||||
(
|
(e: 'updateCard', action: 'FORM' | 'INFO', isEdit?: boolean): void;
|
||||||
e: 'updateCard',
|
(e: 'enterCard', action: 'FORM' | 'INFO'): void;
|
||||||
action: 'FORM' | 'INFO',
|
(e: 'toggleStatus', status: boolean): void;
|
||||||
id: string,
|
|
||||||
isEdit?: boolean,
|
|
||||||
): void;
|
|
||||||
(e: 'enterCard', action: 'FORM' | 'INFO', id: string): void;
|
|
||||||
(e: 'toggleStatus', id: string, status: boolean): void;
|
|
||||||
}>();
|
}>();
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
<div
|
|
||||||
class="person-container"
|
|
||||||
:style="`grid-template-columns: repeat( ${
|
|
||||||
gridColumns
|
|
||||||
? `${gridColumns}, 1fr`
|
|
||||||
: $q.screen.gt.sm
|
|
||||||
? '4, 1fr'
|
|
||||||
: $q.screen.gt.xs
|
|
||||||
? '2, 1fr'
|
|
||||||
: '1, 1fr'
|
|
||||||
})`"
|
|
||||||
>
|
|
||||||
<AppBox
|
<AppBox
|
||||||
bordered
|
bordered
|
||||||
|
no-padding
|
||||||
class="column person-box"
|
class="column person-box"
|
||||||
:class="{
|
:class="{
|
||||||
'person-box__disabled': v.disabled,
|
'person-box__disabled': disabled,
|
||||||
'person-box__no-hover': noHover,
|
'person-box__no-hover': noHover,
|
||||||
'person-box__no-detail': noDetail,
|
'person-box__no-detail': !data.detail,
|
||||||
'person-box__no-bg': noBg,
|
'person-box__no-bg': noBg,
|
||||||
}"
|
}"
|
||||||
@click="$emit('enterCard', 'INFO', v.id)"
|
@click="$emit('enterCard', 'INFO')"
|
||||||
v-for="(v, i) in list"
|
|
||||||
:key="i"
|
|
||||||
>
|
>
|
||||||
<div class="q-pa-sm column items-center">
|
<div class="column items-center">
|
||||||
<!-- kebab menu -->
|
<!-- kebab menu -->
|
||||||
<div class="full-width text-right" v-if="!noAction">
|
<div class="full-width flex" v-if="!noAction">
|
||||||
|
<div style="margin-right: auto">
|
||||||
|
<span
|
||||||
|
class="tags"
|
||||||
|
v-for="v in tag"
|
||||||
|
:class="{ [`tags__${v.color}`]: true }"
|
||||||
|
>
|
||||||
|
{{ v.value }}
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
<q-btn
|
<q-btn
|
||||||
v-if="history"
|
v-if="history"
|
||||||
flat
|
flat
|
||||||
|
|
@ -77,7 +64,7 @@ defineEmits<{
|
||||||
padding="xs"
|
padding="xs"
|
||||||
icon="mdi-history"
|
icon="mdi-history"
|
||||||
size="sm"
|
size="sm"
|
||||||
@click.stop="$emit('history', v.id)"
|
@click.stop="$emit('history')"
|
||||||
/>
|
/>
|
||||||
|
|
||||||
<q-btn
|
<q-btn
|
||||||
|
|
@ -96,7 +83,7 @@ defineEmits<{
|
||||||
dense
|
dense
|
||||||
class="row q-py-sm"
|
class="row q-py-sm"
|
||||||
style="white-space: nowrap"
|
style="white-space: nowrap"
|
||||||
@click="$emit('enterCard', 'INFO', v.id)"
|
@click="$emit('enterCard', 'INFO')"
|
||||||
>
|
>
|
||||||
<q-icon
|
<q-icon
|
||||||
name="mdi-eye-outline"
|
name="mdi-eye-outline"
|
||||||
|
|
@ -113,7 +100,7 @@ defineEmits<{
|
||||||
clickable
|
clickable
|
||||||
class="row q-py-sm"
|
class="row q-py-sm"
|
||||||
style="white-space: nowrap"
|
style="white-space: nowrap"
|
||||||
@click="$emit('updateCard', 'INFO', v.id, true)"
|
@click="$emit('updateCard', 'INFO', true)"
|
||||||
v-close-popup
|
v-close-popup
|
||||||
>
|
>
|
||||||
<q-icon
|
<q-icon
|
||||||
|
|
@ -129,7 +116,7 @@ defineEmits<{
|
||||||
<q-item
|
<q-item
|
||||||
dense
|
dense
|
||||||
clickable
|
clickable
|
||||||
@click="$emit('deleteCard', v.id)"
|
@click="$emit('deleteCard')"
|
||||||
v-close-popup
|
v-close-popup
|
||||||
>
|
>
|
||||||
<q-icon
|
<q-icon
|
||||||
|
|
@ -147,18 +134,14 @@ defineEmits<{
|
||||||
<q-toggle
|
<q-toggle
|
||||||
dense
|
dense
|
||||||
size="sm"
|
size="sm"
|
||||||
@click="
|
@click="$emit('toggleStatus', disabled === false)"
|
||||||
$emit('toggleStatus', v.id, v.disabled === false)
|
:model-value="!disabled"
|
||||||
"
|
|
||||||
:model-value="!v.disabled"
|
|
||||||
val="xs"
|
val="xs"
|
||||||
padding="none"
|
padding="none"
|
||||||
>
|
>
|
||||||
<div class="q-ml-xs">
|
<div class="q-ml-xs">
|
||||||
{{
|
{{
|
||||||
!v.disabled
|
!disabled ? $t('switchOnLabel') : $t('switchOffLabel')
|
||||||
? $t('switchOnLabel')
|
|
||||||
: $t('switchOffLabel')
|
|
||||||
}}
|
}}
|
||||||
</div>
|
</div>
|
||||||
</q-toggle>
|
</q-toggle>
|
||||||
|
|
@ -171,98 +154,73 @@ defineEmits<{
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<!-- profile -->
|
<!-- profile -->
|
||||||
<div style="position: relative">
|
|
||||||
<AppCircle
|
<AppCircle
|
||||||
bordered
|
bordered
|
||||||
class="avatar"
|
class="avatar"
|
||||||
style="border: 2px solid var(--border-color)"
|
style="border: 2px solid var(--border-color); overflow: visible"
|
||||||
:class="{ 'edit-profile': canEditProfile }"
|
@click="$emit('editProfile')"
|
||||||
@click="
|
|
||||||
() => {
|
|
||||||
if (canEditProfile) $emit('editProfile');
|
|
||||||
}
|
|
||||||
"
|
|
||||||
>
|
>
|
||||||
<q-img
|
<q-img
|
||||||
:src="v.img"
|
:src="data.img"
|
||||||
style="object-fit: cover; width: 100%; height: 100%"
|
style="
|
||||||
|
object-fit: cover;
|
||||||
|
width: 100%;
|
||||||
|
height: 100%;
|
||||||
|
border-radius: 50%;
|
||||||
|
"
|
||||||
/>
|
/>
|
||||||
<div class="status-circle">
|
<div class="avatar__status"></div>
|
||||||
<q-icon
|
|
||||||
:name="`mdi-${v.disabled ? 'close' : 'check'}`"
|
|
||||||
:style="`color:${v.disabled ? 'var(--gray-6)' : 'white'}`"
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
</AppCircle>
|
</AppCircle>
|
||||||
</div>
|
|
||||||
|
|
||||||
<!-- name symbol -->
|
<!-- name symbol -->
|
||||||
<span class="items-center row q-my-sm">
|
<span class="items-center row">
|
||||||
{{ v.name }}
|
{{ data.name }}
|
||||||
<Icon
|
<Icon
|
||||||
class="q-pl-sm"
|
class="q-pl-xs"
|
||||||
:class="{
|
:class="{
|
||||||
'symbol-gender': v.male || v.female,
|
'symbol-gender': data.male || data.female,
|
||||||
'symbol-gender__male': !v.disabled && v.male,
|
'symbol-gender__male': !disabled && data.male,
|
||||||
'symbol-gender__female': !v.disabled && v.female,
|
'symbol-gender__female': !disabled && data.female,
|
||||||
'symbol-gender__disable': v.disabled,
|
'symbol-gender__disable': disabled,
|
||||||
}"
|
}"
|
||||||
:icon="`material-symbols:${v.male ? 'male' : 'female'}`"
|
:icon="`material-symbols:${data.male ? 'male' : 'female'}`"
|
||||||
width="24px"
|
width="24px"
|
||||||
/>
|
/>
|
||||||
<!-- <Icon class="locale q-pl-sm" icon="circle-flags:th" width="24px" /> -->
|
|
||||||
</span>
|
</span>
|
||||||
<span
|
<span style="color: hsl(var(--text-mute)); scale: 0.9">
|
||||||
v-if="v.badge"
|
{{ data.code || '-' }}
|
||||||
class="badge q-px-sm"
|
|
||||||
:class="{
|
|
||||||
'bg-gender': v.male || v.female,
|
|
||||||
'bg-gender__male': !v.disabled && v.male,
|
|
||||||
'bg-gender__female': !v.disabled && v.female,
|
|
||||||
'bg-gender__disable': v.disabled,
|
|
||||||
empty: !v.male && !v.female,
|
|
||||||
}"
|
|
||||||
>
|
|
||||||
{{ v.badge }}
|
|
||||||
</span>
|
</span>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<!-- detail -->
|
<!-- detail -->
|
||||||
<q-separator v-if="!noDetail" />
|
<q-separator v-if="data.detail" class="q-my-sm q-mx-md" />
|
||||||
<div
|
|
||||||
v-if="!noDetail"
|
<div class="row" v-for="v in data.detail" :key="v.value" v-if="data.detail">
|
||||||
class="q-pt-sm q-px-md q-pb-md person-detail rounded-b full-width"
|
<div class="column items-center" style="width: min-content">
|
||||||
:class="{
|
<div class="detail-icon">
|
||||||
'bg-gender': v.male || v.female,
|
<q-icon size="md" style="scale: 0.5" :name="v.icon" />
|
||||||
'bg-gender__light':
|
</div>
|
||||||
(!v.disabled && v.male) || (!v.disabled && v.female),
|
</div>
|
||||||
'bg-gender__male': !v.disabled && v.male,
|
<div class="col row items-center full-width">
|
||||||
'bg-gender__female': !v.disabled && v.female,
|
<span class="ellipsis">{{ v.value || '-' }}</span>
|
||||||
'bg-gender__disable': v.disabled,
|
<q-tooltip
|
||||||
}"
|
anchor="bottom left"
|
||||||
:style="
|
self="bottom left"
|
||||||
(detailColumnCount &&
|
:offset="[10, 20]"
|
||||||
`grid-template-columns: repeat(${detailColumnCount}, 1fr);`) ||
|
:delay="500"
|
||||||
''
|
|
||||||
"
|
|
||||||
>
|
>
|
||||||
<div v-for="(d, j) in v.detail" :key="j">
|
{{ v.value || '-' }}
|
||||||
<span class="app-text-muted-2">
|
</q-tooltip>
|
||||||
{{ d.label }}
|
|
||||||
</span>
|
|
||||||
<span>{{ d.value || '-' }}</span>
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</AppBox>
|
</AppBox>
|
||||||
</div>
|
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<style scoped>
|
<style scoped>
|
||||||
.person-box {
|
.person-box {
|
||||||
background-color: var(--surface-2);
|
background-color: var(--surface-1);
|
||||||
border-radius: var(--radius-2) !important;
|
|
||||||
transition: 100ms ease-in-out;
|
transition: 100ms ease-in-out;
|
||||||
padding: 0;
|
padding: var(--size-2);
|
||||||
|
|
||||||
&.person-box__disabled {
|
&.person-box__disabled {
|
||||||
opacity: 0.4;
|
opacity: 0.4;
|
||||||
|
|
@ -284,6 +242,13 @@ defineEmits<{
|
||||||
background-color: transparent;
|
background-color: transparent;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
& .detail-icon {
|
||||||
|
color: hsl(var(--text-mute-2));
|
||||||
|
background-color: hsla(var(--stone-6-hsl) / 0.15);
|
||||||
|
border-radius: 50%;
|
||||||
|
scale: 0.8;
|
||||||
|
}
|
||||||
|
|
||||||
& .bg-gender {
|
& .bg-gender {
|
||||||
color: hsla(var(--_fg));
|
color: hsla(var(--_fg));
|
||||||
background-color: hsl(var(--_bg));
|
background-color: hsl(var(--_bg));
|
||||||
|
|
@ -297,16 +262,6 @@ defineEmits<{
|
||||||
color: unset;
|
color: unset;
|
||||||
background-color: hsla(var(--_bg) / 0.1);
|
background-color: hsla(var(--_bg) / 0.1);
|
||||||
}
|
}
|
||||||
|
|
||||||
&.bg-gender__male {
|
|
||||||
--_fg: 0 100 100%;
|
|
||||||
--_bg: var(--gender-male);
|
|
||||||
}
|
|
||||||
|
|
||||||
&.bg-gender__female {
|
|
||||||
--_fg: 0 100 100%;
|
|
||||||
--_bg: var(--gender-female);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
& .symbol-gender {
|
& .symbol-gender {
|
||||||
|
|
@ -325,23 +280,6 @@ defineEmits<{
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
& .person-detail {
|
|
||||||
display: grid;
|
|
||||||
flex-grow: 1;
|
|
||||||
grid-template-columns: repeat(2, 1fr);
|
|
||||||
gap: var(--size-2);
|
|
||||||
overflow-x: scroll;
|
|
||||||
|
|
||||||
& > * {
|
|
||||||
display: flex;
|
|
||||||
flex-direction: column;
|
|
||||||
|
|
||||||
& > :first-child {
|
|
||||||
font-size: var(--font-size-0);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
& .status-circle {
|
& .status-circle {
|
||||||
width: 18px;
|
width: 18px;
|
||||||
height: 18px;
|
height: 18px;
|
||||||
|
|
@ -360,11 +298,6 @@ defineEmits<{
|
||||||
--_hover: hsl(var(--gender-male));
|
--_hover: hsl(var(--gender-male));
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
box-shadow: var(--shadow-2);
|
box-shadow: var(--shadow-2);
|
||||||
|
|
||||||
& .person-detail {
|
|
||||||
--_hover: hsl(var(--_bg));
|
|
||||||
box-shadow: inset 0em -5px hsl(var(--_bg));
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -374,17 +307,25 @@ defineEmits<{
|
||||||
}
|
}
|
||||||
|
|
||||||
.avatar {
|
.avatar {
|
||||||
block-size: 7rem;
|
block-size: 5rem;
|
||||||
|
transform: rotate(45deg);
|
||||||
|
|
||||||
|
& .avatar__status {
|
||||||
|
content: ' ';
|
||||||
|
display: block;
|
||||||
|
block-size: 1rem;
|
||||||
|
aspect-ratio: 1;
|
||||||
|
position: absolute;
|
||||||
|
border-radius: 50%;
|
||||||
|
right: -0.5rem;
|
||||||
|
border: 1px solid var(--border-color);
|
||||||
|
top: calc(50% - 0.5rem);
|
||||||
|
bottom: calc(50% - 0.5rem);
|
||||||
|
background-color: hsla(var(--positive-bg) / 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
.badge {
|
& :deep(.q-img) {
|
||||||
display: inline-block;
|
transform: rotate(-45deg);
|
||||||
border-radius: var(--radius-6);
|
|
||||||
background-color: var(--surface-2);
|
|
||||||
text-wrap: nowrap;
|
|
||||||
|
|
||||||
&.empty {
|
|
||||||
background-color: var(--surface-tab);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -396,4 +337,60 @@ defineEmits<{
|
||||||
opacity: 80%;
|
opacity: 80%;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.tags {
|
||||||
|
display: inline-block;
|
||||||
|
color: hsla(var(--_color) / 1);
|
||||||
|
background: hsla(var(--_color) / 0.15);
|
||||||
|
border-radius: var(--radius-2);
|
||||||
|
padding-inline: var(--size-2);
|
||||||
|
}
|
||||||
|
|
||||||
|
.tags__purple {
|
||||||
|
--_color: var(--violet-11-hsl);
|
||||||
|
}
|
||||||
|
|
||||||
|
.tags__pink {
|
||||||
|
--_color: var(--pink-6-hsl);
|
||||||
|
}
|
||||||
|
|
||||||
|
.tags__green {
|
||||||
|
--_color: var(--teal-10-hsl);
|
||||||
|
}
|
||||||
|
|
||||||
|
.tags__cyan {
|
||||||
|
--_color: var(--cyan-7-hsl);
|
||||||
|
}
|
||||||
|
|
||||||
|
.tags__red {
|
||||||
|
--_color: var(--red-6-hsl);
|
||||||
|
}
|
||||||
|
|
||||||
|
.tags__yellow {
|
||||||
|
--_color: var(--orange-4-hsl);
|
||||||
|
}
|
||||||
|
|
||||||
|
.tags__orange {
|
||||||
|
--_color: var(--orange-5-hsl);
|
||||||
|
}
|
||||||
|
|
||||||
|
.tags__magenta {
|
||||||
|
--_color: var(--pink-8-hsl);
|
||||||
|
}
|
||||||
|
|
||||||
|
.dark .tags__purple {
|
||||||
|
--_color: var(--violet-10-hsl);
|
||||||
|
}
|
||||||
|
|
||||||
|
.dark .tags__green {
|
||||||
|
--_color: var(--teal-8-hsl);
|
||||||
|
}
|
||||||
|
|
||||||
|
.dark .tags__orange {
|
||||||
|
--_color: var(--orange-6-hsl);
|
||||||
|
}
|
||||||
|
|
||||||
|
.dark .tags__magenta {
|
||||||
|
--_color: var(--pink-7-hsl);
|
||||||
|
}
|
||||||
</style>
|
</style>
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,7 @@
|
||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import { ref, onMounted, watch, computed } from 'vue';
|
import { ref, onMounted, watch, computed } from 'vue';
|
||||||
import { storeToRefs } from 'pinia';
|
import { storeToRefs } from 'pinia';
|
||||||
import useUtilsStore, { dialog } from 'src/stores/utils';
|
import useUtilsStore, { dialog, calculateAge } from 'src/stores/utils';
|
||||||
import { useI18n } from 'vue-i18n';
|
import { useI18n } from 'vue-i18n';
|
||||||
import useFlowStore from 'src/stores/flow';
|
import useFlowStore from 'src/stores/flow';
|
||||||
import useUserStore from 'stores/user';
|
import useUserStore from 'stores/user';
|
||||||
|
|
@ -91,7 +91,7 @@ const statusToggle = ref(true);
|
||||||
const statusFilter = ref<'all' | 'statusACTIVE' | 'statusINACTIVE'>('all');
|
const statusFilter = ref<'all' | 'statusACTIVE' | 'statusINACTIVE'>('all');
|
||||||
const inputSearch = ref('');
|
const inputSearch = ref('');
|
||||||
const userId = ref<string>();
|
const userId = ref<string>();
|
||||||
const selectorLabel = ref<string>('');
|
const selectorLabel = ref<string>('MESSENGER');
|
||||||
const hqId = ref<string>();
|
const hqId = ref<string>();
|
||||||
const brId = ref<string>();
|
const brId = ref<string>();
|
||||||
const formDialogRef = ref();
|
const formDialogRef = ref();
|
||||||
|
|
@ -170,7 +170,7 @@ const selectorList = computed(() => [
|
||||||
|
|
||||||
async function openDialog(
|
async function openDialog(
|
||||||
action?: 'FORM' | 'INFO',
|
action?: 'FORM' | 'INFO',
|
||||||
idEdit?: string,
|
id?: string,
|
||||||
isPersonEdit: boolean = false,
|
isPersonEdit: boolean = false,
|
||||||
) {
|
) {
|
||||||
if (userStore.userOption.hqOpts.length === 0) {
|
if (userStore.userOption.hqOpts.length === 0) {
|
||||||
|
|
@ -181,12 +181,12 @@ async function openDialog(
|
||||||
await userStore.fetchRoleOption();
|
await userStore.fetchRoleOption();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (idEdit && userData.value) {
|
if (id && userData.value) {
|
||||||
assignFormData(idEdit);
|
assignFormData(id);
|
||||||
isEdit.value = true;
|
isEdit.value = true;
|
||||||
|
|
||||||
if (formData.value.userType === 'AGENCY') {
|
if (formData.value.userType === 'AGENCY') {
|
||||||
const result = await userStore.fetchAttachment(idEdit);
|
const result = await userStore.fetchAttachment(id);
|
||||||
|
|
||||||
if (result) {
|
if (result) {
|
||||||
agencyFileList.value = result;
|
agencyFileList.value = result;
|
||||||
|
|
@ -201,7 +201,7 @@ async function openDialog(
|
||||||
|
|
||||||
infoDrawerEdit.value = isPersonEdit ? true : false;
|
infoDrawerEdit.value = isPersonEdit ? true : false;
|
||||||
infoDrawer.value = true;
|
infoDrawer.value = true;
|
||||||
const user = userData.value.result.find((x) => x.id === idEdit);
|
const user = userData.value.result.find((x) => x.id === id);
|
||||||
infoPersonCard.value = user
|
infoPersonCard.value = user
|
||||||
? [
|
? [
|
||||||
{
|
{
|
||||||
|
|
@ -377,7 +377,7 @@ async function assignFormData(idEdit: string) {
|
||||||
infoPersonId.value = currentUser.value.id;
|
infoPersonId.value = currentUser.value.id;
|
||||||
|
|
||||||
formData.value = {
|
formData.value = {
|
||||||
branchId: foundUser.branch[0].id,
|
branchId: foundUser.branch[0]?.id,
|
||||||
provinceId: foundUser.provinceId,
|
provinceId: foundUser.provinceId,
|
||||||
districtId: foundUser.districtId,
|
districtId: foundUser.districtId,
|
||||||
subDistrictId: foundUser.subDistrictId,
|
subDistrictId: foundUser.subDistrictId,
|
||||||
|
|
@ -556,13 +556,21 @@ watch(inputSearch, async () => await fetchUserList());
|
||||||
<div v-if="!hideStat" class="scroll q-mb-md">
|
<div v-if="!hideStat" class="scroll q-mb-md">
|
||||||
<div style="display: inline-block">
|
<div style="display: inline-block">
|
||||||
<StatCardComponent
|
<StatCardComponent
|
||||||
v-if="sortedUserStats"
|
v-if="typeStats"
|
||||||
:branch="
|
:branch="
|
||||||
sortedUserStats.map((v) => ({
|
Object.entries(typeStats).map(([key, val]) => ({
|
||||||
count: v.count,
|
count: val,
|
||||||
label: $i18n.locale === 'en-US' ? v.nameEN : v.name,
|
label: key,
|
||||||
icon: 'mdi-account',
|
icon: 'mdi-account',
|
||||||
color: v.isHeadOffice ? 'pink' : 'purple',
|
color:
|
||||||
|
(
|
||||||
|
{
|
||||||
|
USER: 'cyan',
|
||||||
|
MESSENGER: 'yellow',
|
||||||
|
DELEGATE: 'red',
|
||||||
|
AGENCY: 'magenta',
|
||||||
|
} as const
|
||||||
|
)[key] || 'pink',
|
||||||
}))
|
}))
|
||||||
"
|
"
|
||||||
:dark="$q.dark.isActive"
|
:dark="$q.dark.isActive"
|
||||||
|
|
@ -633,51 +641,69 @@ watch(inputSearch, async () => await fetchUserList());
|
||||||
</q-btn>
|
</q-btn>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="col column scroll q-pa-md">
|
<div class="col scroll">
|
||||||
<PersonCard
|
<div class="q-pa-md q-col-gutter-md row">
|
||||||
:list="
|
<div
|
||||||
userData?.result
|
v-for="v in userData?.result.filter((v) => {
|
||||||
.filter((v) => {
|
if (statusFilter === 'statusACTIVE' && v.status === 'INACTIVE') {
|
||||||
if (
|
|
||||||
statusFilter === 'statusACTIVE' &&
|
|
||||||
v.status === 'INACTIVE'
|
|
||||||
) {
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (
|
if (
|
||||||
statusFilter === 'statusINACTIVE' &&
|
statusFilter === 'statusINACTIVE' &&
|
||||||
v.status !== 'INACTIVE'
|
v.status !== 'INACTIVE'
|
||||||
) {
|
) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
})
|
})"
|
||||||
.map((v) => ({
|
:key="v.id"
|
||||||
id: v.id,
|
class="col-3"
|
||||||
img: `${v.profileImageUrl}`,
|
>
|
||||||
|
<PersonCard
|
||||||
|
:data="{
|
||||||
|
code: v.code,
|
||||||
name:
|
name:
|
||||||
$i18n.locale === 'en-US'
|
$i18n.locale === 'en-US'
|
||||||
? `${v.firstNameEN} ${v.lastNameEN}`
|
? `${v.firstNameEN} ${v.lastNameEN}`.trim()
|
||||||
: `${v.firstName} ${v.lastName}`,
|
: `${v.firstName} ${v.lastName}`.trim(),
|
||||||
|
img: v.profileImageUrl,
|
||||||
male: v.gender === 'male',
|
male: v.gender === 'male',
|
||||||
female: v.gender === 'female',
|
female: v.gender === 'female',
|
||||||
detail: [
|
detail: [
|
||||||
{ label: $t('personnelCardUserType'), value: $t(v.userType) },
|
|
||||||
{ label: $t('personnelCardTelephone'), value: v.telephoneNo },
|
|
||||||
{
|
{
|
||||||
label: $t('personnelCardAge'),
|
icon: 'mdi-phone',
|
||||||
value: userStore.calculateAge(v.birthDate as Date) || '',
|
value: v.telephoneNo,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
icon: 'mdi-clock-outline',
|
||||||
|
value: (v.birthDate && calculateAge(v.birthDate)) || '-',
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
badge: v.code,
|
}"
|
||||||
disabled: v.status === 'INACTIVE',
|
:tag="[
|
||||||
})) || []
|
{
|
||||||
"
|
color:
|
||||||
@update-card="openDialog"
|
(
|
||||||
@delete-card="onDelete"
|
{
|
||||||
@enter-card="openDialog"
|
USER: 'cyan',
|
||||||
@toggle-status="toggleStatus"
|
MESSENGER: 'yellow',
|
||||||
|
DELEGATE: 'red',
|
||||||
|
AGENCY: 'magenta',
|
||||||
|
} as const
|
||||||
|
)[v.userType] || 'pink',
|
||||||
|
value: $t(v.userType),
|
||||||
|
},
|
||||||
|
]"
|
||||||
|
:disabled="v.status === 'INACTIVE'"
|
||||||
|
@update-card="(a, b) => openDialog(a, v.id, b)"
|
||||||
|
@delete-card="onDelete(v.id)"
|
||||||
|
@enter-card="(a) => openDialog(a, v.id)"
|
||||||
|
@toggle-status="toggleStatus(v.id)"
|
||||||
/>
|
/>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
<template v-if="userData && userData.total === 0 && !inputSearch">
|
<template v-if="userData && userData.total === 0 && !inputSearch">
|
||||||
<div class="col-1 self-end">
|
<div class="col-1 self-end">
|
||||||
<div class="row">
|
<div class="row">
|
||||||
|
|
@ -807,17 +833,20 @@ watch(inputSearch, async () => await fetchUserList());
|
||||||
<AppBox class="surface-1" style="padding: 0">
|
<AppBox class="surface-1" style="padding: 0">
|
||||||
<PersonCard
|
<PersonCard
|
||||||
:can-edit-profile="infoDrawerEdit"
|
:can-edit-profile="infoDrawerEdit"
|
||||||
|
:data="{
|
||||||
|
code: currentUser.code,
|
||||||
|
name:
|
||||||
|
$i18n.locale === 'en-US'
|
||||||
|
? `${currentUser.firstNameEN} ${currentUser.lastNameEN}`.trim()
|
||||||
|
: `${currentUser.firstName} ${currentUser.lastName}`.trim(),
|
||||||
|
img: currentUser.profileImageUrl,
|
||||||
|
male: currentUser.gender === 'male',
|
||||||
|
female: currentUser.gender === 'female',
|
||||||
|
}"
|
||||||
no-hover
|
no-hover
|
||||||
no-action
|
no-action
|
||||||
no-detail
|
|
||||||
no-bg
|
no-bg
|
||||||
:list="infoPersonCard"
|
@edit-profile="inputFile.click()"
|
||||||
:gridColumns="1"
|
|
||||||
@edit-profile="
|
|
||||||
() => {
|
|
||||||
inputFile.click();
|
|
||||||
}
|
|
||||||
"
|
|
||||||
/>
|
/>
|
||||||
</AppBox>
|
</AppBox>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue