refactor: branch form

This commit is contained in:
puriphatt 2024-08-01 08:44:40 +00:00 committed by Net
parent a1f691a613
commit fb076fc074
15 changed files with 651 additions and 274 deletions

Binary file not shown.

Before

Width:  |  Height:  |  Size: 647 KiB

After

Width:  |  Height:  |  Size: 541 KiB

Before After
Before After

View file

@ -17,17 +17,26 @@ defineProps<{
</script> </script>
<template> <template>
<div class="row col-12"> <div class="row col-12">
<div class="col-md-3 col-12 app-text-muted q-pb-sm"> <div class="col-12 q-pb-sm text-weight-bold text-body1">
{{ $t(`${title}`) }} <q-icon
flat
size="xs"
class="q-pa-sm rounded q-mr-xs"
color="info"
name="mdi-phone"
style="background-color: var(--surface-3)"
/>
{{ $t(`${title}`) }}
</div> </div>
<div class="col-md-9 col-12 row q-col-gutter-md">
<div class="col-12 row q-col-gutter-sm">
<q-input <q-input
lazy-rules="ondemand" lazy-rules="ondemand"
:dense="dense" :dense="dense"
outlined outlined
:readonly="readonly" :readonly="readonly"
hide-bottom-space hide-bottom-space
class="col-md-5 col-12" class="col-md-3 col-12"
:label=" :label="
typeBranch === 'headOffice' typeBranch === 'headOffice'
? $t('formDialogInputEmailHq') ? $t('formDialogInputEmailHq')
@ -35,7 +44,11 @@ defineProps<{
" "
v-model="email" v-model="email"
for="input-email" for="input-email"
/> >
<template #prepend>
<q-icon color="primary" name="mdi-email" size="xs" class="q-mr-xs" />
</template>
</q-input>
<q-input <q-input
lazy-rules="ondemand" lazy-rules="ondemand"
@ -43,7 +56,7 @@ defineProps<{
outlined outlined
:readonly="readonly" :readonly="readonly"
hide-bottom-space hide-bottom-space
class="col-md-7 col-12" class="col-md-3 col-12"
:label=" :label="
typeBranch === 'headOffice' typeBranch === 'headOffice'
? $t('formDialogInputTelephoneHq') ? $t('formDialogInputTelephoneHq')
@ -51,7 +64,11 @@ defineProps<{
" "
v-model="telephoneNo" v-model="telephoneNo"
for="input-telephone-no" for="input-telephone-no"
/> >
<template #prepend>
<q-icon color="primary" name="mdi-phone" size="xs" class="q-mr-xs" />
</template>
</q-input>
<q-input <q-input
lazy-rules="ondemand" lazy-rules="ondemand"
@ -59,7 +76,7 @@ defineProps<{
outlined outlined
:readonly="readonly" :readonly="readonly"
hide-bottom-space hide-bottom-space
class="col-md-5 col-12" class="col-md-3 col-12"
:label="$t('formDialogInputContactName')" :label="$t('formDialogInputContactName')"
v-model="contactName" v-model="contactName"
for="input-contact-name" for="input-contact-name"
@ -71,11 +88,15 @@ defineProps<{
outlined outlined
:readonly="readonly" :readonly="readonly"
hide-bottom-space hide-bottom-space
class="col-7" class="col-3"
:label="$t('formDialogInputTelephoneContact')" :label="$t('formDialogInputTelephoneContact')"
v-model="contact" v-model="contact"
for="input-contact" for="input-contact"
/> >
<template #prepend>
<q-icon color="primary" name="mdi-phone" size="xs" class="q-mr-xs" />
</template>
</q-input>
<q-input <q-input
lazy-rules="ondemand" lazy-rules="ondemand"
@ -83,16 +104,11 @@ defineProps<{
outlined outlined
:readonly="readonly" :readonly="readonly"
hide-bottom-space hide-bottom-space
class="col-5" class="col-3"
label="Line ID" label="Line ID"
v-model="lineId" v-model="lineId"
for="input-line-id" for="input-line-id"
/> />
</div> </div>
<q-separator
v-if="separator"
class="col-12 q-mt-xl q-mb-md"
style="padding-block: 0.5px"
/>
</div> </div>
</template> </template>

View file

@ -11,25 +11,34 @@ defineProps<{
dense?: boolean; dense?: boolean;
outlined?: boolean; outlined?: boolean;
readonly?: boolean; readonly?: boolean;
separator?: boolean;
view?: boolean; view?: boolean;
}>(); }>();
</script> </script>
<template> <template>
<div class="row col-12"> <div class="row col-12">
<div class="col-md-3 col-12 app-text-muted q-pb-sm"> <div class="col-12 q-pb-sm text-weight-bold text-body1">
{{ $t(`${title}`) }} <q-icon
flat
size="xs"
class="q-pa-sm rounded q-mr-xs"
color="info"
name="mdi-office-building-outline"
style="background-color: var(--surface-3)"
/>
{{ $t(`${title}`) }}
</div> </div>
<div class="col-md-9 col-12 row q-col-gutter-md">
<div class="col-12 row q-col-gutter-sm">
<q-input <q-input
lazy-rules="ondemand" lazy-rules="ondemand"
:dense="dense" :dense="dense"
outlined outlined
readonly readonly
:disable="!readonly"
hide-bottom-space hide-bottom-space
:class="{ :class="{
'col-12': $q.screen.xs, 'col-12': $q.screen.xs,
'col-6': typeBranch == 'headOffice', 'col-3': typeBranch == 'headOffice',
'col-4': typeBranch != 'headOffice', 'col-4': typeBranch != 'headOffice',
}" }"
:label="$t('formDialogInputCode')" :label="$t('formDialogInputCode')"
@ -46,7 +55,7 @@ defineProps<{
hide-bottom-space hide-bottom-space
:class="{ :class="{
'col-12': $q.screen.xs, 'col-12': $q.screen.xs,
'col-6': typeBranch == 'headOffice', 'col-3': typeBranch == 'headOffice',
'col-4': typeBranch != 'headOffice', 'col-4': typeBranch != 'headOffice',
}" }"
:label="$t('branchLabelCode')" :label="$t('branchLabelCode')"
@ -62,7 +71,7 @@ defineProps<{
hide-bottom-space hide-bottom-space
:class="{ :class="{
'col-12': $q.screen.xs, 'col-12': $q.screen.xs,
'col-6': typeBranch === 'headOffice', 'col-3': typeBranch === 'headOffice',
'col-4': typeBranch !== 'headOffice', 'col-4': typeBranch !== 'headOffice',
}" }"
:label="$t('formDialogInputTaxNo')" :label="$t('formDialogInputTaxNo')"
@ -81,7 +90,7 @@ defineProps<{
outlined outlined
:readonly="readonly" :readonly="readonly"
hide-bottom-space hide-bottom-space
class="col-12" class="col-3"
:label=" :label="
typeBranch === 'headOffice' typeBranch === 'headOffice'
? $t('formDialogInputNameHq') ? $t('formDialogInputNameHq')
@ -103,7 +112,7 @@ defineProps<{
outlined outlined
:readonly="readonly" :readonly="readonly"
hide-bottom-space hide-bottom-space
class="col-12" class="col-3"
v-model="nameEN" v-model="nameEN"
:label=" :label="
typeBranch === 'headOffice' typeBranch === 'headOffice'
@ -119,10 +128,5 @@ defineProps<{
for="input-name-en" for="input-name-en"
/> />
</div> </div>
<q-separator
v-if="separator"
class="col-12 q-mt-xl q-mb-md"
style="padding-block: 0.5px"
/>
</div> </div>
</template> </template>

View file

@ -18,14 +18,23 @@ defineProps<{
}>(); }>();
</script> </script>
<template> <template>
<div class="col-md-3 col-12 app-text-muted"> {{ $t(`${title}`) }}</div> <div class="col-12">
<div <div class="col-12 q-pb-sm text-weight-bold text-body1">
class="col-md-9 col-12 bordered rounded row no-padding" <q-icon
:class="{ 'q-mt-lg': !$q.screen.xs, 'q-mt-sm': $q.screen.xs }" flat
> size="xs"
<div class="col-12 q-pl-md q-py-sm app-text-muted">location</div> class="q-pa-sm rounded q-mr-xs"
color="info"
name="mdi-map-legend"
style="background-color: var(--surface-3)"
/>
{{ $t(`${title}`) }}
</div>
<div v-if="!!longitude && !!latitude" class="col-12 flex flex-center"> <div class="col-12 bordered rounded column">
<div class="q-pl-md q-py-sm app-text-muted bordered-b">location</div>
<div v-if="!!longitude && !!latitude" class="col flex flex-center">
<iframe <iframe
:src="`https://maps.google.com/maps?q=${latitude}, ${longitude}&z=15&output=embed`" :src="`https://maps.google.com/maps?q=${latitude}, ${longitude}&z=15&output=embed`"
width="100%" width="100%"
@ -38,10 +47,11 @@ defineProps<{
v-else v-else
class="col-12 flex flex-center" class="col-12 flex flex-center"
style=" style="
height: 100px; height: 150px;
background-image: url(/map.png); background-image: url(/map.png);
background-position: center center; background-position: center center;
background-size: 1500px 850px; background-size: cover;
background-repeat: no-repeat;
" "
> >
<q-btn <q-btn
@ -60,10 +70,5 @@ defineProps<{
/> />
</div> </div>
</div> </div>
</div>
<q-separator
v-if="separator"
class="col-12 q-mt-xl q-mb-md"
style="padding-block: 0.5px"
/>
</template> </template>

View file

@ -16,17 +16,31 @@ defineEmits<{
}>(); }>();
</script> </script>
<template> <template>
<div class="col-md-3 col-12 app-text-muted"> {{ title }}</div> <div class="row col-12">
<div class="col-12 q-pb-sm text-weight-bold text-body1">
<q-icon
flat
size="xs"
class="q-pa-sm rounded q-mr-xs"
color="info"
name="mdi-qrcode"
style="background-color: var(--surface-3)"
/>
{{ title }}
</div>
<div <div
:class="{ :class="{
'dark-form-show-qr-code': $q.dark.isActive, 'dark-form-show-qr-code': $q.dark.isActive,
'q-mt-lg': !$q.screen.xs,
'q-mt-sm': $q.screen.xs,
}" }"
class="col-md-9 col-12 row branch-form-show-qr-code" class="col-12 row branch-form-show-qr-code"
>
<div class="col-12 flex flex-center q-py-md">
<q-img
v-if="qr"
:src="qr as string"
style="width: 150px; height: 150px"
> >
<div class="col-12 flex flex-center">
<q-img v-if="qr" :src="qr as string" style="width: 150px; height: 150px">
<template #error> <template #error>
<div <div
style="background: none" style="background: none"
@ -49,11 +63,15 @@ defineEmits<{
<Icon icon="teenyicons:add-outline" width="30px" height="50px" /> <Icon icon="teenyicons:add-outline" width="30px" height="50px" />
</q-btn> </q-btn>
</div> </div>
<div class="col-12 flex flex-center q-py-md"> <div class="col-12 flex flex-center q-pb-md">
<q-btn <q-btn
v-if="!readonly" v-if="!readonly"
:text-color="$q.dark.isActive ? 'black' : 'white'" :text-color="$q.dark.isActive ? 'black' : 'white'"
style="background: var(--blue-5); color: var(--blue-0); font-size: 12px" style="
background: var(--blue-5);
color: var(--blue-0);
font-size: 12px;
"
unelevated unelevated
rounded rounded
:label="$t('formDialogUploadQrCode')" :label="$t('formDialogUploadQrCode')"
@ -62,11 +80,7 @@ defineEmits<{
/> />
</div> </div>
</div> </div>
<q-separator </div>
v-if="separator"
class="col-12 q-mt-xl q-mb-md"
style="padding-block: 0.5px"
/>
</template> </template>
<style scoped> <style scoped>

View file

@ -18,7 +18,7 @@ defineProps<{
separator?: boolean; separator?: boolean;
employee?: boolean; employee?: boolean;
disabledRule?: boolean; disabledRule?: boolean;
id?: number; indexId?: number;
prefixId: string; prefixId: string;
}>(); }>();
@ -147,10 +147,17 @@ watch(districtId, fetchSubDistrict);
</script> </script>
<template> <template>
<div class="col-12"> <div class="col-12">
<div class="col-12 app-text-muted row items-center q-mb-md"> <div class="col-12 q-pb-sm text-weight-bold text-body1">
<span class="q-mr-lg"> <q-icon
{{ title || $t('formDialogTitlePersonnelAddress') }} size="xs"
</span> class="q-pa-sm rounded q-mr-xs"
color="info"
name="mdi-map-marker-radius"
style="background-color: var(--surface-3)"
/>
{{ title || $t('formDialogTitlePersonnelAddress') }}
<div <div
v-if="employee" v-if="employee"
class="surface-3 q-px-sm q-py-xs row" class="surface-3 q-px-sm q-py-xs row"
@ -184,13 +191,11 @@ watch(districtId, fetchSubDistrict);
</div> </div>
<div class="col-12 row q-col-gutter-y-md"> <div class="col-12 row q-col-gutter-y-md">
<div <div class="col-12 app-text-muted-2">
class="col-md-3 col-12 app-text-muted" <q-icon size="xs" class="q-mr-xs" name="mdi-map-marker" />
:class="{ 'q-pl-xl': !$q.screen.xs }"
>
{{ addressTitle || $t('formDialogTitleAddressPure') }} {{ addressTitle || $t('formDialogTitleAddressPure') }}
</div> </div>
<div class="col-md-9 col-12 row q-col-gutter-md"> <div class="col-12 row q-col-gutter-sm">
<q-input <q-input
outlined outlined
hide-bottom-space hide-bottom-space
@ -200,7 +205,7 @@ watch(districtId, fetchSubDistrict);
:dense="dense" :dense="dense"
:label="$t('address')" :label="$t('address')"
:readonly="readonly || sameWithEmployer" :readonly="readonly || sameWithEmployer"
:for="`${prefixId}-${id !== undefined ? `input-address-${id}` : 'input-address'}`" :for="`${prefixId}-${indexId !== undefined ? `input-address-${indexId}` : 'input-address'}`"
:rules=" :rules="
disabledRule disabledRule
? [] ? []
@ -231,7 +236,7 @@ watch(districtId, fetchSubDistrict);
:options="provinceOptions" :options="provinceOptions"
:readonly="readonly || sameWithEmployer" :readonly="readonly || sameWithEmployer"
:hide-dropdown-icon="readonly || sameWithEmployer" :hide-dropdown-icon="readonly || sameWithEmployer"
:for="`${prefixId}-${id !== undefined ? `select-province-${id}` : 'select-province'}`" :for="`${prefixId}-${indexId !== undefined ? `select-province-${indexId}` : 'select-province'}`"
:rules=" :rules="
disabledRule disabledRule
? [] ? []
@ -273,7 +278,7 @@ watch(districtId, fetchSubDistrict);
:options="districtOptions" :options="districtOptions"
:readonly="readonly || sameWithEmployer" :readonly="readonly || sameWithEmployer"
:hide-dropdown-icon="readonly || sameWithEmployer" :hide-dropdown-icon="readonly || sameWithEmployer"
:for="`${prefixId}-${id !== undefined ? `select-district-${id}` : 'select-district'}`" :for="`${prefixId}-${indexId !== undefined ? `select-district-${indexId}` : 'select-district'}`"
:rules=" :rules="
disabledRule disabledRule
? [] ? []
@ -314,7 +319,7 @@ watch(districtId, fetchSubDistrict);
:options="subDistrictOptions" :options="subDistrictOptions"
:readonly="readonly || sameWithEmployer" :readonly="readonly || sameWithEmployer"
:hide-dropdown-icon="readonly || sameWithEmployer" :hide-dropdown-icon="readonly || sameWithEmployer"
:for="`${prefixId}-${id !== undefined ? `select-sub-district-${id}` : 'select-sub-district'}`" :for="`${prefixId}-${indexId !== undefined ? `select-sub-district-${indexId}` : 'select-sub-district'}`"
:rules=" :rules="
disabledRule disabledRule
? [] ? []
@ -337,25 +342,25 @@ watch(districtId, fetchSubDistrict);
</q-select> </q-select>
<q-input <q-input
lazy-rules="ondemand" lazy-rules="ondemand"
:for="`${prefixId}-${id !== undefined ? `input-zip-code-${id}` : 'input-zip-code'}`" :for="`${prefixId}-${indexId !== undefined ? `input-zip-code-${indexId}` : 'input-zip-code'}`"
:dense="dense" :dense="dense"
outlined outlined
:disable="!readonly"
readonly readonly
:label="$t('zipCode')" :label="$t('zipCode')"
class="col-md-3 col-6" class="col-md-2 col-6"
v-model="zipCode" v-model="zipCode"
/> />
</div> </div>
<div
class="col-md-3 col-12 app-text-muted" <div class="col-12 app-text-muted-2">
:class="{ 'q-pl-xl': !$q.screen.xs }" <q-icon size="xs" class="q-mr-xs" name="mdi-map-marker" />
> {{ addressTitle || $t('formDialogTitleAddressPureEN') }}
{{ addressTitleEN || $t('formDialogTitleAddressPureEN') }}
</div> </div>
<div class="col-md-9 col-12 row q-col-gutter-md"> <div class="col-12 row q-col-gutter-sm">
<q-input <q-input
lazy-rules="ondemand" lazy-rules="ondemand"
:for="`${prefixId}-${id !== undefined ? `input-address-en-${id}` : 'input-address-en'}`" :for="`${prefixId}-${indexId !== undefined ? `input-address-en-${indexId}` : 'input-address-en'}`"
:dense="dense" :dense="dense"
:readonly="readonly || sameWithEmployer" :readonly="readonly || sameWithEmployer"
outlined outlined
@ -393,7 +398,7 @@ watch(districtId, fetchSubDistrict);
:options="provinceOptions" :options="provinceOptions"
:readonly="readonly || sameWithEmployer" :readonly="readonly || sameWithEmployer"
:hide-dropdown-icon="readonly || sameWithEmployer" :hide-dropdown-icon="readonly || sameWithEmployer"
:for="`${prefixId}-${id !== undefined ? `select-province-en-${id}` : 'select-province-en'}`" :for="`${prefixId}-${indexId !== undefined ? `select-province-en-${indexId}` : 'select-province-en'}`"
:rules=" :rules="
disabledRule disabledRule
? [] ? []
@ -434,7 +439,7 @@ watch(districtId, fetchSubDistrict);
:options="districtOptions" :options="districtOptions"
:readonly="readonly || sameWithEmployer" :readonly="readonly || sameWithEmployer"
:hide-dropdown-icon="readonly || sameWithEmployer" :hide-dropdown-icon="readonly || sameWithEmployer"
:for="`${prefixId}-${id !== undefined ? `select-district-en-${id}` : 'select-district-en'}`" :for="`${prefixId}-${indexId !== undefined ? `select-district-en-${indexId}` : 'select-district-en'}`"
:rules=" :rules="
disabledRule disabledRule
? [] ? []
@ -475,7 +480,7 @@ watch(districtId, fetchSubDistrict);
:options="subDistrictOptions" :options="subDistrictOptions"
:readonly="readonly || sameWithEmployer" :readonly="readonly || sameWithEmployer"
:hide-dropdown-icon="readonly || sameWithEmployer" :hide-dropdown-icon="readonly || sameWithEmployer"
:for="`${prefixId}-${id !== undefined ? `select-sub-district-en-${id}` : 'select-sub-district-en'}`" :for="`${prefixId}-${indexId !== undefined ? `select-sub-district-en-${indexId}` : 'select-sub-district-en'}`"
:rules=" :rules="
disabledRule disabledRule
? [] ? []
@ -499,23 +504,19 @@ watch(districtId, fetchSubDistrict);
<q-input <q-input
lazy-rules="ondemand" lazy-rules="ondemand"
hide-bottom-space hide-bottom-space
:for="`${prefixId}-${id !== undefined ? `input-zip-code-${id}` : 'input-zip-code'}`" :for="`${prefixId}-${indexId !== undefined ? `input-zip-code-${indexId}` : 'input-zip-code'}`"
:dense="dense" :dense="dense"
outlined outlined
readonly readonly
:disable="!readonly"
zip="zip-en" zip="zip-en"
:label="$t('zipCode')" :label="$t('zipCode')"
class="col-md-3 col-6" class="col-md-2 col-6"
v-model="zipCode" v-model="zipCode"
/> />
</div> </div>
</div> </div>
</div> </div>
<q-separator
v-if="separator"
class="col-12 q-mb-md"
style="padding-block: 0.5px; margin-top: 32px"
/>
</template> </template>
<style lang="scss" scoped> <style lang="scss" scoped>

View file

@ -69,33 +69,7 @@ const employeeTab = defineModel<string>('employeeTab');
class="row q-col-gutter-y-md surface-1 rounded bordered" class="row q-col-gutter-y-md surface-1 rounded bordered"
:class="{ 'q-pa-md': !noPaddingTab }" :class="{ 'q-pa-md': !noPaddingTab }"
> >
<slot name="information"></slot> <slot></slot>
<slot name="person"></slot>
<slot name="address" v-if="!noAddress">
<FormAddress
dense
outlined
separator
prefix-id="default"
:employee="employee"
:readonly="readonly"
:disabledRule="disabledRule"
v-model:address="address"
v-model:addressEN="addressEN"
v-model:provinceId="provinceId"
v-model:districtId="districtId"
v-model:subDistrictId="subDistrictId"
v-model:zipCode="zipCode"
v-model:same-with-employer="sameWithEmployer"
:title="titleFormAddress"
:addressTitle="addressTitle || ''"
:addressTitleEN="addressTitleEN || ''"
v-if="!$slots.address"
/>
</slot>
<slot name="qr-code"></slot>
<slot name="location"></slot>
<slot name="by-type"></slot>
</div> </div>
</div> </div>
</div> </div>

View file

@ -0,0 +1,286 @@
<script setup lang="ts">
defineProps<{
title: string;
titleFormAddress?: string;
addressTitle?: string;
addressTitleEN?: string;
addressSeparator?: boolean;
branchStatus?: string;
badgeLabel?: string;
customerLabel?: string;
badgeClass?: string;
noFooter?: boolean;
noAppBox?: boolean;
noPaddingTab?: boolean;
maxWidth?: string;
width?: string;
height?: string;
employee?: boolean;
noAddress?: boolean;
disabledRule?: boolean;
edit?: boolean;
isEdit?: boolean;
tabsList?: { name: string; label: string }[];
editData?: (...args: unknown[]) => void;
deleteData?: (...args: unknown[]) => void;
submit?: (...args: unknown[]) => void;
close?: (...args: unknown[]) => void;
undo?: (...args: unknown[]) => void;
}>();
const modal = defineModel('modal', { default: false });
const currentTab = defineModel<string>('currentTab');
</script>
<template>
<q-dialog v-model="modal" @hide="close">
<div
class="surface-1"
style="padding: 0; border-radius: var(--radius-2); height: 100%"
:style="`max-width:${$q.screen.xs ? '100%' : maxWidth ? maxWidth : '85%'}; width: ${$q.screen.xs ? '100%' : width ? width : '85%'}; height: ${height ? height : '85vh'} `"
>
<q-form
greedy
@submit.prevent
@validation-success="submit"
class="column full-height"
>
<!-- header -->
<div class="form-header q-py-sm q-px-lg">
<div class="row items-center">
<div v-if="isEdit && edit" class="row">
<q-btn
round
flat
id="closeDialog"
icon="mdi-arrow-left"
padding="xs"
class="q-mr-md"
:class="{ dark: $q.dark.isActive }"
style="color: var(--brand-1)"
@click="undo"
/>
<div style="width: 31.98px"></div>
</div>
<div v-if="!isEdit && edit">
<q-btn
round
flat
id="editDialog"
icon="mdi-pencil-outline"
padding="xs"
class="q-mr-md"
:class="{ dark: $q.dark.isActive }"
style="color: var(--brand-1)"
@click="editData"
/>
<q-btn
v-if="edit"
round
flat
id="deleteDialog"
icon="mdi-trash-can-outline"
padding="xs"
:class="{ dark: $q.dark.isActive }"
style="color: hsl(var(--negative-bg))"
@click="deleteData"
/>
</div>
<div style="width: 31.98px"></div>
<div class="col text-subtitle1 text-weight-bold text-center">
{{ title }}
<text v-if="customerLabel">
:
<text
class="text-customer"
:class="{ 'dark-text': $q.dark.isActive }"
:style="`color: ${customerLabel === 'CORP' ? 'var(--purple-8)' : 'var(--green-9)'} `"
>
{{
$t(
customerLabel === 'CORP'
? 'customerLegalEntity'
: 'customerNaturalPerson',
)
}}
</text>
</text>
<text v-if="branchStatus">
{{ branchStatus }}
</text>
<text
v-if="badgeLabel"
class="badge-label q-px-sm text-caption"
:class="badgeClass"
>
{{ badgeLabel }}
</text>
</div>
<q-btn
round
flat
id="closeDialog"
icon="mdi-close"
padding="xs"
class="close-btn"
:class="{ dark: $q.dark.isActive }"
@click="close"
/>
</div>
</div>
<!-- body -->
<div
class="col full-height column full-width"
:class="{
dark: $q.dark.isActive,
'surface-2': !employee,
'surface-tab': employee || tabsList,
}"
>
<div
v-if="tabsList && tabsList.length > 0"
class="row surface-2 q-px-md q-pt-md full-width"
style="border-bottom: 1px solid var(--brand-1)"
>
<q-tabs
inline-label
mobile-arrows
dense
class="app-text-muted full-width"
v-model="currentTab"
active-class="active-tab"
indicator-color="transparent"
align="left"
>
<q-tab
:id="`tab-${tab.label}`"
v-for="tab in tabsList"
v-bind:key="tab.name"
class="content-tab text-capitalize"
:name="tab.name"
:label="$t(tab.label)"
/>
</q-tabs>
</div>
<div class="row col full-width scroll">
<!-- prepend -->
<div class="col" v-if="$slots.prepend">
<slot name="prepend"></slot>
</div>
<!-- center -->
<div class="col column full-height">
<slot></slot>
</div>
<!-- append -->
<div class="col" v-if="$slots.append">
<slot name="append"></slot>
</div>
</div>
</div>
<!-- footer -->
<div
v-if="!noFooter"
class="form-footer row items-center full-width justify-between q-px-md q-py-md surface-1"
style="z-index: 3"
>
<div>
<slot name="footer"></slot>
</div>
<div class="row flex justify-end q-gutter-x-md">
<q-btn
id="cancelBtn"
unelevated
class="col btn-cancel-dialog"
color="grey-4"
text-color="grey-10"
@click="close"
:label="$t('cancel')"
v-close-popup
/>
<q-btn
dense
unelevated
id="submitBtn"
type="submit"
color="primary"
class="q-px-md"
:label="$t('save')"
/>
</div>
</div>
</q-form>
</div>
</q-dialog>
</template>
<style scoped lang="scss">
.close-btn {
color: hsl(var(--negative-bg));
background-color: hsla(var(--negative-bg) / 0.1);
&.dark {
background-color: transparent;
border: 1px solid hsl(var(--negative-bg));
}
}
.form-header {
border-bottom: 1px solid var(--border-color);
}
.form-body {
--_body-bg: var(--sand-0);
background-color: var(--_body-bg);
&.dark {
--_body-bg: var(--gray-10);
}
}
.form-footer {
border-top: 1px solid var(--border-color);
}
.badge-label {
display: inline-block;
border-radius: var(--radius-6);
background-color: var(--surface-2);
text-wrap: nowrap;
}
.text-customer {
--_var-filter: grayscale(30%);
filter: var(--_var-filter);
&.dark-text {
--_var-filter: grayscale(0%);
}
}
.active-tab {
color: var(--brand-1);
background-color: var(--surface-tab);
border-top: 1px solid var(--brand-1);
border-left: 1px solid var(--brand-1);
border-right: 1px solid var(--brand-1);
border-top-left-radius: var(--radius-2);
border-top-right-radius: var(--radius-2);
margin-bottom: -1.5px;
border-bottom: 3px solid var(--surface-tab);
}
.content-tab {
border-top-left-radius: var(--radius-2);
border-top-right-radius: var(--radius-2);
position: relative;
}
</style>

View file

@ -1,6 +1,5 @@
<script setup lang="ts"> <script setup lang="ts">
import { computed, ref } from 'vue'; import { ref } from 'vue';
import AppBox from './app/AppBox.vue';
withDefaults( withDefaults(
defineProps<{ defineProps<{

View file

@ -211,7 +211,6 @@ const currentTab = defineModel<string>('currentTab');
<!-- center --> <!-- center -->
<div <div
v-if="!noAppBox" v-if="!noAppBox"
bordered
class="column surface-1 bordered rounded col" class="column surface-1 bordered rounded col"
:class="`${$slots.prepend ? ($q.screen.gt.sm ? 'col-10' : 'col-12') : $slots.append ? 'col-6' : 'col-12'} ${!noPaddingTab && 'q-pt-lg q-pl-lg'} ${$q.screen.gt.sm && 'full-height scroll'}`" :class="`${$slots.prepend ? ($q.screen.gt.sm ? 'col-10' : 'col-12') : $slots.append ? 'col-6' : 'col-12'} ${!noPaddingTab && 'q-pt-lg q-pl-lg'} ${$q.screen.gt.sm && 'full-height scroll'}`"
style="padding-right: 0; padding-bottom: 16px" style="padding-right: 0; padding-bottom: 16px"

View file

@ -23,7 +23,7 @@ const props = defineProps<{
}; };
}>(); }>();
const scrollElement = ref<Element | HTMLElement>(); const currentScrollElement = ref<Element | HTMLElement>();
function handleClick(menu: Menu) { function handleClick(menu: Menu) {
const element = document.getElementById(menu.anchor); const element = document.getElementById(menu.anchor);
@ -41,9 +41,9 @@ const activeMenu = ref(props.menu.at(0)?.anchor || '');
function onScroll() { function onScroll() {
let current = ''; let current = '';
if (!scrollElement.value) return; if (!currentScrollElement.value) return;
const container = scrollElement.value; const container = currentScrollElement.value;
props.menu.forEach((v) => { props.menu.forEach((v) => {
if (!v.element) v.element = document.getElementById(v.anchor) || undefined; if (!v.element) v.element = document.getElementById(v.anchor) || undefined;
@ -56,22 +56,21 @@ function onScroll() {
current = v.anchor; current = v.anchor;
} }
}); });
activeMenu.value = current; activeMenu.value = current;
} }
onMounted(() => { onMounted(() => {
if (typeof props.scrollElement === 'string' || !props.scrollElement) { if (typeof props.scrollElement === 'string' || !props.scrollElement) {
const element = document.querySelector(props.scrollElement || 'body'); const element = document.querySelector(props.scrollElement || 'body');
if (element) scrollElement.value = element; if (element) currentScrollElement.value = element;
} else { } else {
scrollElement.value = props.scrollElement; currentScrollElement.value = props.scrollElement;
} }
scrollElement.value?.addEventListener('scroll', onScroll); currentScrollElement.value?.addEventListener('scroll', onScroll);
}); });
onUnmounted(() => { onUnmounted(() => {
scrollElement.value?.removeEventListener('scroll', onScroll); currentScrollElement.value?.removeEventListener('scroll', onScroll);
}); });
</script> </script>
@ -87,6 +86,7 @@ onUnmounted(() => {
class="side-menu__item" class="side-menu__item"
:class="{ 'side-menu__active': activeMenu === v.anchor }" :class="{ 'side-menu__active': activeMenu === v.anchor }"
v-for="v in menu" v-for="v in menu"
:key="v.anchor"
@click="handleClick(v)" @click="handleClick(v)"
> >
{{ v.name }} {{ v.name }}

View file

@ -68,6 +68,7 @@ export default {
noResults: 'No Data', noResults: 'No Data',
notRecorded: 'You have not yet saved.', notRecorded: 'You have not yet saved.',
editImage: 'Edit Image', editImage: 'Edit Image',
bankBook: 'Bank Book',
...status, ...status,
...main, ...main,
...address, ...address,

View file

@ -71,6 +71,7 @@ export default {
noResults: 'ไม่มีข้อมูล', noResults: 'ไม่มีข้อมูล',
notRecorded: 'คุณยังไม่ได้บันทึก', notRecorded: 'คุณยังไม่ได้บันทึก',
editImage: 'แก้ไขรูป', editImage: 'แก้ไขรูป',
bankBook: 'บัญชีธนาคาร',
...status, ...status,
...main, ...main,
...address, ...address,

View file

@ -17,7 +17,8 @@ import AddButton from 'components/AddButton.vue';
import TooltipComponent from 'components/TooltipComponent.vue'; import TooltipComponent from 'components/TooltipComponent.vue';
import StatCard from 'components/StatCardComponent.vue'; import StatCard from 'components/StatCardComponent.vue';
import BranchCard from 'components/01_branch-management/BranchCard.vue'; import BranchCard from 'components/01_branch-management/BranchCard.vue';
import FormDialog from 'components/FormDialog.vue'; import FormAddress from 'components/02_personnel-management/FormAddress.vue';
import DialogForm from 'components/DialogForm.vue';
import FormBranchInformation from 'components/01_branch-management/FormBranchInformation.vue'; import FormBranchInformation from 'components/01_branch-management/FormBranchInformation.vue';
import FormLocation from 'components/01_branch-management/FormLocation.vue'; import FormLocation from 'components/01_branch-management/FormLocation.vue';
import FormQr from 'components/01_branch-management/FormQr.vue'; import FormQr from 'components/01_branch-management/FormQr.vue';
@ -26,6 +27,8 @@ import FormImage from 'components/01_branch-management/FormImage.vue';
import DrawerInfo from 'components/DrawerInfo.vue'; import DrawerInfo from 'components/DrawerInfo.vue';
import InfoForm from 'components/02_personnel-management/InfoForm.vue'; import InfoForm from 'components/02_personnel-management/InfoForm.vue';
import TreeCompoent from 'src/components/TreeCompoent.vue'; import TreeCompoent from 'src/components/TreeCompoent.vue';
import ProfileBanner from 'src/components/ProfileBanner.vue';
import SideMenu from 'src/components/SideMenu.vue';
const $q = useQuasar(); const $q = useQuasar();
const { t } = useI18n(); const { t } = useI18n();
@ -1382,20 +1385,10 @@ watch(currentHq, () => {
</div> </div>
</div> </div>
<FormDialog <DialogForm
ref="formDialogRef" ref="formDialogRef"
v-model:modal="modal" v-model:modal="modal"
v-model:address="formData.address"
v-model:addressEN="formData.addressEN"
v-model:province-id="formData.provinceId"
v-model:district-id="formData.districtId"
v-model:sub-district-id="formData.subDistrictId"
v-model:zip-code="formData.zipCode"
:title="changeTitle(formType, formTypeBranch) + ' ' + currentEdit.code" :title="changeTitle(formType, formTypeBranch) + ' ' + currentEdit.code"
:titleFormAddress="$t('formDialogTitleAddress')"
:address-title="$t('formDialogAddress')"
:address-title-EN="$t('formDialogAddressEN')"
:addressSeparator="true"
:submit=" :submit="
() => { () => {
onSubmit(); onSubmit();
@ -1403,25 +1396,101 @@ watch(currentHq, () => {
" "
:close="() => (modal = false)" :close="() => (modal = false)"
> >
<template #information> <div class="q-mx-lg q-mt-lg">
<!-- title="บริษัทจ๊อบส์ เวิร์คเกอร์ เซอร์วิส จำกัด"
caption="Jobs Worker Service Co., Ltd." -->
<ProfileBanner
active
hideFade
icon="mdi-office-building-outline"
color="hsla(var(--pink-6-hsl)/1)"
bgColor="hsla(var(--pink-6-hsl)/0.15)"
@view="console.log('view')"
@edit="console.log('edit')"
:menu="[
{
icon: 'mdi-phone',
color: 'hsl(var(--info-bg))',
bgColor: 'var(--surface-1)',
},
{
icon: 'mdi-qrcode',
color: 'hsl(var(--info-bg))',
bgColor: 'var(--surface-1)',
},
{
icon: 'mdi-image-filter-hdr',
color: 'hsl(var(--info-bg))',
bgColor: 'var(--surface-1)',
},
{
icon: 'mdi-map-legend',
color: 'hsl(var(--info-bg))',
bgColor: 'var(--surface-1)',
},
]"
/>
</div>
<div
class="col surface-1 q-ma-lg rounded bordered scroll row"
id="branch-form"
>
<div class="col">
<div class="q-ma-sm fixed">
<SideMenu
:menu="[
{
name: $t('formDialogTitleInformation'),
anchor: 'information',
},
{
name: $t('formDialogTitleContact'),
anchor: 'contact',
},
{
name: $t('formDialogTitleAddress'),
anchor: 'address',
},
{
name: $t('formDialogTitleLocation'),
anchor: 'location',
},
{
name: 'QR Code',
anchor: 'qr',
},
{
name: $t('bankBook'),
anchor: 'bankBook',
},
]"
background="transparent"
:active="{
background: 'hsla(var(--blue-6-hsl) / .2)',
foreground: 'var(--blue-6)',
}"
scroll-element="#branch-form"
/>
</div>
</div>
<div class="col-10 q-pa-md q-gutter-y-xl">
<FormBranchInformation <FormBranchInformation
id="information"
v-model:code="formData.codeHeadOffice" v-model:code="formData.codeHeadOffice"
v-model:code-sub-branch="currentEdit.code" v-model:code-sub-branch="currentEdit.code"
v-model:taxNo="formData.taxNo" v-model:taxNo="formData.taxNo"
v-model:name="formData.name" v-model:name="formData.name"
v-model:nameEN="formData.nameEN" v-model:nameEN="formData.nameEN"
v-model:type-branch="formTypeBranch" v-model:type-branch="formTypeBranch"
:separator="true"
:dense="true" :dense="true"
:outlined="true" :outlined="true"
:readonly="formType === 'view'" :readonly="formType === 'view'"
:view="formType === 'view'" :view="formType === 'view'"
title="formDialogTitleInformation" title="formDialogTitleInformation"
/> />
</template>
<template #person>
<FormBranchContact <FormBranchContact
id="contact"
v-model:type-branch="formTypeBranch" v-model:type-branch="formTypeBranch"
v-model:telephone-no="formData.telephoneNo" v-model:telephone-no="formData.telephoneNo"
v-model:contact="formData.contact" v-model:contact="formData.contact"
@ -1433,10 +1502,30 @@ watch(currentHq, () => {
:dense="true" :dense="true"
:outlined="true" :outlined="true"
/> />
</template> <FormAddress
id="address"
<template #qr-code> dense
outlined
separator
prefix-id="default"
:title="$t('formDialogTitleAddress')"
v-model:address="formData.address"
v-model:addressEN="formData.addressEN"
v-model:province-id="formData.provinceId"
v-model:district-id="formData.districtId"
v-model:sub-district-id="formData.subDistrictId"
v-model:zip-code="formData.zipCode"
/>
<FormLocation
id="location"
:readonly="formType === 'view'"
:separator="true"
v-model:latitude="formData.latitude"
v-model:longitude="formData.longitude"
title="formDialogTitleLocation"
/>
<FormQr <FormQr
id="qr"
title="QR Code" title="QR Code"
:separator="true" :separator="true"
:qr="qrCodeimageUrl" :qr="qrCodeimageUrl"
@ -1447,20 +1536,7 @@ watch(currentHq, () => {
} }
" "
/> />
</template> <!-- <FormImage
<template #location>
<FormLocation
:readonly="formType === 'view'"
:separator="true"
v-model:latitude="formData.latitude"
v-model:longitude="formData.longitude"
title="formDialogTitleLocation"
/>
</template>
<template #by-type>
<FormImage
:readonly="formType === 'view'" :readonly="formType === 'view'"
v-model:image="imageUrl" v-model:image="imageUrl"
@upload=" @upload="
@ -1469,9 +1545,10 @@ watch(currentHq, () => {
} }
" "
:title="$t('formDialogTitleImg')" :title="$t('formDialogTitleImg')"
/> /> -->
</template> </div>
</FormDialog> </div>
</DialogForm>
<DrawerInfo <DrawerInfo
ref="formDialogRef" ref="formDialogRef"

View file

@ -3290,7 +3290,7 @@ watch(isMainPage, () => {
<template #address> <template #address>
<FormAddress <FormAddress
prefix-id="form-dialog" prefix-id="form-dialog"
:id="indexTab" :indexId="indexTab"
v-if=" v-if="
indexTab !== undefined && formData.customerBranch?.[indexTab] indexTab !== undefined && formData.customerBranch?.[indexTab]
" "
@ -3642,7 +3642,7 @@ watch(isMainPage, () => {
<template #address> <template #address>
<FormAddress <FormAddress
prefix-id="form-dialog" prefix-id="form-dialog"
:id="indexTab" :indexId="indexTab"
v-if=" v-if="
indexTab !== undefined && formData.customerBranch?.[indexTab] indexTab !== undefined && formData.customerBranch?.[indexTab]
" "
@ -3843,7 +3843,7 @@ watch(isMainPage, () => {
<template #address> <template #address>
<FormAddress <FormAddress
prefix-id="drawer-info-customer" prefix-id="drawer-info-customer"
:id="indexTab" :indexId="indexTab"
v-if=" v-if="
indexTab !== undefined && indexTab !== undefined &&
formData.customerBranch?.[indexTab] formData.customerBranch?.[indexTab]
@ -4071,7 +4071,7 @@ watch(isMainPage, () => {
<template #address> <template #address>
<FormAddress <FormAddress
prefix-id="drawer-info-customer-branch" prefix-id="drawer-info-customer-branch"
:id="indexTab" :indexId="indexTab"
v-if=" v-if="
indexTab !== undefined && indexTab !== undefined &&
formData.customerBranch?.[indexTab] formData.customerBranch?.[indexTab]