Merge branch 'dev/phatt' into develop

This commit is contained in:
puriphatt 2024-04-23 11:15:48 +00:00
commit e532f23a45
8 changed files with 336 additions and 76 deletions

View file

@ -117,6 +117,7 @@ defineProps<{
<VueDatePicker
utc
autoApply
:teleport="true"
v-model="birthDate"
:locale="'th'"
:enableTimePicker="false"

View file

@ -6,6 +6,7 @@ defineProps<{
readonly?: boolean;
addressTitle?: string;
addressTitleEN?: string;
noAddress?: boolean;
}>();
const address = defineModel('address', { default: '' });
@ -38,7 +39,7 @@ const zipCode = defineModel<string>('zipCode', { default: '' });
<div class="row q-col-gutter-y-md">
<slot name="information"></slot>
<slot name="person"></slot>
<slot name="address">
<slot name="address" v-if="!noAddress">
<FormAddress
dense
outlined

View file

@ -3,9 +3,21 @@ import AppBox from './app/AppBox.vue';
withDefaults(
defineProps<{
noDetail?: boolean;
noHover?: boolean;
noBg?: boolean;
dark?: boolean;
width?: string;
color: 'purple' | 'green';
gridColumns?: number;
metadata?: { id: string; disabled: boolean };
list: {
id: string;
type: 'customerLegalEntity' | 'customerNaturalPerson';
name: string;
code: string;
detail?: { label: string; value: string }[];
};
}>(),
{
width: '300px',
@ -13,44 +25,64 @@ withDefaults(
color: 'green',
},
);
defineEmits<{
(e: 'deleteCard', id: string): void;
(e: 'updateCard', action: 'FORM' | 'INFO', id: string): void;
(e: 'enterCard', action: 'FORM' | 'INFO', id: string): void;
(e: 'toggleStatus', id: string): void;
}>();
</script>
<template>
<div class="container">
<div style="aspect-ratio: 9/16" class="flip">
<div v-if="metadata">
<div
:style="`${noBg ? 'aspect-ratio: 1.91/2' : 'aspect-ratio: 9/16'}`"
class="flip"
:class="{
'person-box__no-hover': noHover,
}"
>
<AppBox
style="padding: 0"
:class="`${$q.dark.isActive ? 'dark ' : ''} color__${color}`"
no-padding
class="surface-1 front"
bordered
:class="`${$q.dark.isActive ? 'dark ' : ''} color__${color} ${noBg ? 'front__no-bg' : ''}`"
@click="$emit('enterCard', 'INFO', metadata.id)"
>
<div class="row justify-center">
<q-card-section class="q-pt-xl img">
<div class="row justify-center relative-position">
<q-card-section class="q-pt-xl img-decoration">
<q-avatar size="100px">
<img src="https://cdn.quasar.dev/img/avatar1.jpg" />
</q-avatar>
</q-card-section>
</div>
<div class="box-title">
<div class="rounded title">คคล</div>
<div class="rounded title">{{ $t(list.type) }}</div>
</div>
<q-card-section class="no-padding">
<div class="column items-center justify-center">
<div class="row">นางสาวสดใจ แสนด</div>
<div class="row q-mb-md">HQ0001</div>
<div class="column items-center justify-center q-mb-md">
<div class="row">{{ list.name }}</div>
<div v-if="!noDetail">
{{ list.code }}
</div>
</div>
</q-card-section>
<div>
<q-scroll-area
class="front-scroll"
style="border-radius: 0px 0px 12px 12px"
>
<q-card-section v-for="v in [1, 2]" :key="v" class="overflow">
<div class="color-front-text"> บร/คคล ภาษาไทย</div>
<div>บรทเฟรปเป</div>
<div v-if="!noDetail">
<q-separator />
<div class="front-scroll">
<q-card-section
v-for="(d, j) in list.detail"
:key="j"
class="overflow"
>
<div class="text-caption app-text-muted-2">
{{ d.label }}
</div>
<div>{{ d.value }}</div>
</q-card-section>
</q-scroll-area>
</div>
</div>
</AppBox>
@ -59,6 +91,7 @@ withDefaults(
class="back"
:class="`${$q.dark.isActive ? 'dark ' : ''} color__${color}`"
bordered
@click="$emit('enterCard', 'INFO', metadata.id)"
>
<div
class="row q-pl-md q-pb-md items-center"
@ -68,18 +101,105 @@ withDefaults(
}"
style="border-radius: 12px 12px 0px 0px"
>
<q-card-section class="q-pt-xl img">
<q-btn
flat
round
padding="sm"
class="absolute-top-right dots-btn"
icon="mdi-dots-vertical"
size="sm"
@click.stop=""
>
<q-menu class="bordered">
<q-list v-close-popup>
<q-item
clickable
dense
class="row q-py-sm"
style="white-space: nowrap"
@click="$emit('enterCard', 'INFO', metadata.id)"
>
<q-icon
name="mdi-eye-outline"
class="col-3"
size="xs"
style="color: hsl(var(--green-6-hsl))"
/>
<span class="col-9 q-px-md flex items-center">
{{ $t('viewDetail') }}
</span>
</q-item>
<q-item
dense
clickable
class="row q-py-sm"
style="white-space: nowrap"
@click="$emit('updateCard', 'FORM', metadata.id)"
v-close-popup
>
<q-icon
name="mdi-pencil-outline"
class="col-3"
size="xs"
style="color: hsl(var(--cyan-6-hsl))"
/>
<span class="col-9 q-px-md flex items-center">
{{ $t('edit') }}
</span>
</q-item>
<q-item
dense
clickable
@click="$emit('deleteCard', metadata.id)"
v-close-popup
>
<q-icon
name="mdi-trash-can-outline"
size="xs"
class="col-3 app-text-negative"
/>
<span class="col-9 q-px-md flex items-center">
{{ $t('delete') }}
</span>
</q-item>
<q-item dense>
<q-item-section class="q-py-sm">
<div class="q-pa-sm surface-2 rounded">
<q-toggle
dense
size="sm"
@click="$emit('toggleStatus', metadata.id)"
:model-value="!metadata.disabled"
val="xs"
padding="none"
>
<div class="q-ml-xs">
{{
metadata.disabled
? $t('switchOnLabel')
: $t('switchOffLabel')
}}
</div>
</q-toggle>
</div>
</q-item-section>
</q-item>
</q-list>
</q-menu>
</q-btn>
<q-card-section class="q-pt-xl img-decoration">
<q-avatar size="50px">
<img src="https://cdn.quasar.dev/img/avatar1.jpg" />
</q-avatar>
</q-card-section>
<div class="col-7 q-pl-md">
<div class="row">นางสาวสขใจ แสนด</div>
<div class="row">HQ0001</div>
<div class="row">{{ list.name }}</div>
<div class="row">{{ list.code }}</div>
</div>
</div>
<q-separator />
<q-scroll-area
class="back-scroll"
:class="{
@ -104,23 +224,19 @@ withDefaults(
</template>
<style scoped>
.color-front-text {
color: var(--color-front-title);
}
.container {
width: 300px;
height: 500px;
}
.flip {
cursor: pointer;
width: 100%;
position: relative;
transition: transform 0.4s;
transform-style: preserve-3d;
&:hover {
&:not(.person-box__no-hover):hover {
cursor: pointer;
transition-delay: 0.3s;
transform: rotateY(180deg);
}
}
@ -141,7 +257,7 @@ withDefaults(
--_bg-back-detail-1: white;
--_bg-back-detail-2: hsla(var(--_color) / 0.05) !important;
.img {
.img-decoration {
background: hsl(var(--_color)) !important;
border-bottom-left-radius: 100px;
border-bottom-right-radius: 100px;
@ -160,17 +276,12 @@ withDefaults(
}
.front-scroll {
border-radius: 0px 0px 5px 5px;
background: var(--_bg-front-scroll) !important;
height: 254px;
max-width: 300px;
height: 150px;
}
.back-scroll {
height: 370px;
max-width: 300px;
border-radius: 0px 0px 15px 15px;
height: 268px;
.bg-color-text-1 {
background: var(--_bg-back-detail-1);
@ -182,19 +293,23 @@ withDefaults(
&.dark {
color: hsl(--_color-dark) !important;
background-color: transparent !important;
background-color: var(--surface-2) !important;
--_bg-back-avatar: var(--gray-11) !important;
--_bg-back-detail-1: var(--gray-9) !important;
--_bg-front-scroll: var(--gray-11);
--_bg-front-scroll: hsla(var(--_color) / 0.1) !important;
--_bg-back-detail-2: hsla(var(--_color) / 0.1) !important;
&.front__no-bg {
background-color: transparent !important;
}
}
&.color__purple {
--_color: var(--purple-11-hsl);
}
&.color__green {
--_color: var(--green-9-hsl);
--_color: var(--teal-9-hsl);
}
}
@ -204,7 +319,7 @@ withDefaults(
}
.rounded {
border-radius: 5px 5px 5px 5px;
border-radius: var(--radius-1);
}
.box-title {

View file

@ -130,12 +130,15 @@ defineEmits<{
:model-value="!v.disabled"
val="xs"
padding="none"
:label="
v.disabled
? $t('switchOnLabel')
: $t('switchOffLabel')
"
/>
>
<div class="q-ml-xs">
{{
v.disabled
? $t('switchOnLabel')
: $t('switchOffLabel')
}}
</div>
</q-toggle>
</div>
</q-item-section>
</q-item>
@ -214,11 +217,7 @@ defineEmits<{
"
>
<div v-for="(d, j) in v.detail" :key="j">
<span
:style="{
color: $q.dark.isActive ? 'var(--foreground)' : 'var(--stone-7)',
}"
>
<span class="app-text-muted-2">
{{ d.label }}
</span>
<span>{{ d.value || '-' }}</span>

View file

@ -18,6 +18,7 @@ html {
--surface-3: var(--gray-1);
--text-mute: var(--stone-5-hsl);
--text-mute-2: var(--stone-7-hsl);
--info-fg: 0 0% 100%;
--info-bg: var(--blue-6-hsl);
@ -30,6 +31,8 @@ html {
--gender-male: var(--blue-5-hsl);
--gender-female: var(--pink-7-hsl);
--customer-corp: var(--purple-11-hsl);
--customer-pers: var(--teal-9-hsl);
--shadow-color: 220 3% 15%;
--shadow-strength: 5%;
@ -51,7 +54,10 @@ html {
--surface-2: var(--gray-10);
--surface-3: var(--gray-9);
--customer-corp: var(--purple-9-hsl);
--text-mute: var(--stone-8-hsl);
--text-mute-2: var(--foreground);
--shadow-color: 220 0% 100%;
--shadow-strength: 25%;
@ -121,6 +127,10 @@ html {
color: hsl(var(--text-mute));
}
.app-text-muted-2 {
color: hsl(var(--text-mute-2));
}
.app-text-info {
color: hsl(var(--info-bg));
}
@ -165,3 +175,21 @@ html {
color: hsl(var(--positive-fg));
background-color: hsl(var(--gender-female)) !important;
}
.app-text-corp {
color: hsl(var(--customer-corp));
}
.app-bg-corp {
color: hsl(var(--customer-corp));
background-color: hsla(var(--customer-corp) / 0.2) !important;
}
.app-text-pers {
color: hsl(var(--customer-pers));
}
.app-bg-pers {
color: hsl(var(--customer-pers));
background-color: hsla(var(--customer-pers) / 0.2) !important;
}

View file

@ -136,6 +136,10 @@ onMounted(async () => {
const user = getUsername();
const uid = getUserId();
userStore.userOption.roleOpts.length === 0
? await userStore.fetchRoleOption()
: '';
const userRoles = getRole();
if (userRoles) {
filterRole.value = userRoles.filter(

View file

@ -739,9 +739,9 @@ watch(
<div class="q-ma-md">
<AppBox class="surface-1" style="padding: 0">
<PersonCard
noHover
noAction
noDetail
no-hover
no-action
no-detail
no-bg
:list="infoPersonCard"
:gridColumns="1"

View file

@ -1,6 +1,7 @@
<script setup lang="ts">
import { computed, ref } from 'vue';
import UsersDetailCardComponent from 'src/components/UsersDetailCardComponent.vue';
import SelectorList from 'components/SelectorList.vue';
import StatCardComponent from 'components/StatCardComponent.vue';
import TooltipComponent from 'components/TooltipComponent.vue';
@ -17,11 +18,14 @@ import AboutComponent from 'src/components/03_customer-management/AboutComponent
import ContactComponent from 'src/components/03_customer-management/ContactInformation.vue';
import OtherInformation from 'src/components/03_customer-management/OtherInformation.vue';
import FormBusiness from 'src/components/03_customer-management/FormBusiness.vue';
import DrawerInfo from 'src/components/DrawerInfo.vue';
import InfoForm from 'src/components/02_personnel-management/InfoForm.vue';
const statusToggle = ref<boolean>(false);
const profileSubmit = ref<boolean>(false);
const profileFile = ref<File | undefined>(undefined);
const profileUrl = ref<string | null>('');
const infoDrawer = ref(false);
const inputFile = (() => {
const element = document.createElement('input');
@ -60,15 +64,13 @@ const customerStats = [
{
id: 1,
count: 2,
name: 'นายจ้าง 1',
nameEN: 'Employer 1',
name: 'customerLegalEntity',
},
{
id: 2,
count: 3,
name: 'นายจ้าง 2',
nameEN: 'Employer 2',
name: 'customerNaturalPerson',
},
];
@ -95,8 +97,18 @@ function openDialogCustomerType() {
dialogCustomerType.value = true;
}
function openDialogInputForm() {
dialogInputForm.value = true;
function openDialogInputForm(action: 'FORM' | 'INFO' = 'FORM', id?: string) {
if (action === 'INFO') {
if (!id) return;
infoDrawer.value = true;
} else {
dialogInputForm.value = true;
}
}
function onClose() {
infoDrawer.value = false;
dialogInputForm.value = false;
}
</script>
@ -121,10 +133,12 @@ function openDialogInputForm() {
<div class="row full-width q-py-md" style="overflow-x: auto">
<StatCardComponent
v-if="customerStats"
labelI18n
:branch="
customerStats.map((v) => ({
count: v.count,
label: $i18n.locale === 'en-US' ? v.nameEN : v.name,
label: v.name,
color: v.name === 'customerLegalEntity' ? 'purple' : 'green',
}))
"
:dark="$q.dark.isActive"
@ -136,24 +150,74 @@ function openDialogInputForm() {
<!-- main -->
<AppBox bordered class="column" style="width: 100%; min-height: 70vh">
<div class="col-1 self-end">
<div class="row">
<TooltipComponent
title="customerTooltipTitle"
caption="customerTooltipCaption"
imgSrc="personnel-table-"
<div v-if="false" class="row q-mb-md justify-between">
<div class="col-1 self-end">
<div class="row">
<TooltipComponent
title="customerTooltipTitle"
caption="customerTooltipCaption"
imgSrc="personnel-table-"
/>
</div>
</div>
<div
class="col self-center"
style="display: flex; flex-grow: 1; align-items: center"
>
<AddButton
:label="'customerAdd'"
:cyanOn="true"
@trigger="openDialogCustomerType()"
/>
</div>
</div>
<div
class="col self-center"
style="display: flex; flex-grow: 1; align-items: center"
class="row full-width customer-row"
:style="`grid-template-columns: repeat(${$q.screen.lt.sm ? '1' : '4'}, 1fr)`"
>
<AddButton
:label="'customerAdd'"
:cyanOn="true"
@trigger="openDialogCustomerType()"
<UsersDetailCardComponent
color="purple"
:metadata="{ id: '1', disabled: false }"
:list="{
id: '1',
type: 'customerLegalEntity',
name: 'เจมส์ บอน',
code: 'HQ007',
detail: [
{
label: 'ชื่อบริษัท/นิติบุคคล ภาษาไทย',
value: 'บริษัทลับ',
},
{
label: 'ชื่อบริษัท/นิติบุคคล ภาษาไทย',
value: 'บริษัทลับ',
},
],
}"
@enter-card="openDialogInputForm"
/>
<UsersDetailCardComponent
color="green"
:metadata="{ id: '1', disabled: false }"
:list="{
id: '2',
type: 'customerNaturalPerson',
name: 'ขอบใจ ขอบใจ',
code: 'HQ006',
detail: [
{
label: 'ชื่อบริษัท/นิติบุคคล ภาษาไทย',
value: 'บริษัทเฟรบเป้',
},
{
label: 'ชื่อบริษัท/นิติบุคคล ภาษาไทย',
value: 'บริษัทเฟรบเป้',
},
],
}"
@enter-card="openDialogInputForm"
/>
</div>
</AppBox>
@ -233,6 +297,54 @@ function openDialogInputForm() {
</div>
</template>
</FormDialog>
<DrawerInfo
:close="() => onClose()"
title="test"
v-model:drawer-open="infoDrawer"
badgeLabel="HQ006"
badgeClass="app-bg-pers"
>
<template #info>
<InfoForm no-address>
<template #person-card>
<div class="q-ma-md">
<AppBox class="surface-1" style="padding: 0">
<UsersDetailCardComponent
no-bg
no-detail
no-hover
color="purple"
:metadata="{ id: '1', disabled: false }"
:list="{
id: '2',
type: 'customerNaturalPerson',
name: 'เจมส์ บอน',
code: 'HQ006',
detail: [
{
label: 'ชื่อบริษัท/นิติบุคคล ภาษาไทย',
value: 'บริษัทเฟรบเป้',
},
{
label: 'ชื่อบริษัท/นิติบุคคล ภาษาไทย',
value: 'บริษัทเฟรบเป้',
},
],
}"
@enter-card="openDialogInputForm"
/>
</AppBox>
</div>
</template>
</InfoForm>
</template>
</DrawerInfo>
</template>
<style scoped></style>
<style scoped>
.customer-row {
display: grid;
gap: var(--size-6);
}
</style>