Merge branch 'ui-new' into develop
This commit is contained in:
commit
b9d54d5e01
53 changed files with 6634 additions and 2322 deletions
|
|
@ -1,6 +1,6 @@
|
|||
import { boot } from 'quasar/wrappers';
|
||||
import VueDatePicker from '@vuepic/vue-datepicker';
|
||||
import '@vuepic/vue-datepicker/dist/main.css'
|
||||
import '@vuepic/vue-datepicker/dist/main.css';
|
||||
import GlobalDialog from 'components/GlobalDialog.vue';
|
||||
import GlobalLoading from 'components/GlobalLoading.vue';
|
||||
|
||||
|
|
|
|||
|
|
@ -2,10 +2,21 @@
|
|||
defineProps<{
|
||||
inactive?: boolean;
|
||||
color?: 'none' | 'hq' | 'br';
|
||||
data: Record<string, unknown>;
|
||||
data: {
|
||||
branchLabelCode: string;
|
||||
branchLabelName: string;
|
||||
branchLabelTel: string;
|
||||
branchLabelAddress: string;
|
||||
branchLabelType: string;
|
||||
};
|
||||
metadata?: unknown;
|
||||
badgeField?: string[];
|
||||
fieldSelected?: string[];
|
||||
fieldSelected?: (
|
||||
| 'branchLabelName'
|
||||
| 'branchLabelAddress'
|
||||
| 'branchLabelTel'
|
||||
| 'branchLabelType'
|
||||
)[];
|
||||
footer?: boolean;
|
||||
}>();
|
||||
</script>
|
||||
|
|
@ -21,112 +32,124 @@ defineProps<{
|
|||
'branch-card__hq': color === 'hq',
|
||||
'branch-card__br': color === 'br',
|
||||
}"
|
||||
@click="$emit('open')"
|
||||
>
|
||||
<div class="branch-card__header">
|
||||
<div class="branch-card__wrapper">
|
||||
<div class="branch-card__icon">
|
||||
<q-icon
|
||||
size="md"
|
||||
style="scale: 0.8"
|
||||
name="mdi-office-building-outline"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
<div class="branch-card__name">
|
||||
<b>{{ data.branchLabelName }}</b>
|
||||
<small class="branch-card__code">{{ data.branchLabelCode }}</small>
|
||||
</div>
|
||||
|
||||
<div class="branch-card__action">
|
||||
<q-btn icon="mdi-dots-vertical" size="sm" dense round flat @click.stop>
|
||||
<slot name="action" />
|
||||
</q-btn>
|
||||
</div>
|
||||
</div>
|
||||
<div
|
||||
class="branch-card__row"
|
||||
:class="{
|
||||
'branch-card__header': i === 0,
|
||||
'branch-card__footer': footer && i === Object.keys(data).length - 1,
|
||||
}"
|
||||
v-for="([k, v], i) in Object.entries(data).filter(
|
||||
([key], idx) =>
|
||||
idx === 0 || (fieldSelected ? fieldSelected.includes(key) : true),
|
||||
)"
|
||||
:key="k"
|
||||
style="
|
||||
display: block;
|
||||
width: 100%;
|
||||
height: 1px;
|
||||
background: hsla(0 0% 0% / 0.1);
|
||||
margin-bottom: var(--size-2);
|
||||
"
|
||||
/>
|
||||
<div
|
||||
v-for="key in fieldSelected?.sort() || [
|
||||
'branchLabelAddress',
|
||||
'branchLabelTel',
|
||||
'branchLabelType',
|
||||
]"
|
||||
class="branch-card__data"
|
||||
>
|
||||
<div class="branch-card__label">
|
||||
<span>{{ $t(k) }}</span>
|
||||
</div>
|
||||
<div
|
||||
class="branch-card__value"
|
||||
:class="{ 'branch-card__badge': badgeField?.includes(k) }"
|
||||
style="justify-content: space-between"
|
||||
>
|
||||
<span>{{ v }}</span>
|
||||
<q-btn
|
||||
:id="`${v}-view-detail`"
|
||||
@click.stop="$emit('view-detail', metadata ?? data)"
|
||||
:label="$t('viewDetail')"
|
||||
rounded
|
||||
outline
|
||||
dense
|
||||
style="text-wrap: nowrap; max-width: 80%"
|
||||
no-caps
|
||||
class="branch-card__view-detail q-px-md text-caption"
|
||||
v-if="i === 0"
|
||||
/>
|
||||
</div>
|
||||
<div>{{ $t(key) }}</div>
|
||||
<div>{{ data[key as keyof typeof data] }}</div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<style scoped>
|
||||
.branch-card {
|
||||
--_branch-card-row-fg: 0 0% 100%;
|
||||
--_branch-card-row-bg: var(--blue-5-hsl);
|
||||
--_branch-badge-fg: var(--green-8-hsl);
|
||||
--_branch-badge-bg: var(--green-6-hsl);
|
||||
--_branch-card-fg: 0 0% 100%;
|
||||
--_branch-card-bg: var(--blue-5-hsl);
|
||||
--_branch-status-color: var(--green-6-hsl);
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
overflow: hidden;
|
||||
box-shadow: var(--shadow-2);
|
||||
padding: var(--size-3);
|
||||
|
||||
& > .branch-card__row {
|
||||
& .branch-card__header {
|
||||
display: flex;
|
||||
margin-bottom: var(--size-2);
|
||||
|
||||
& .branch-card__icon {
|
||||
background-color: hsla(var(--_branch-card-bg) / 0.15);
|
||||
border-radius: 50%;
|
||||
padding: var(--size-1);
|
||||
position: relative;
|
||||
transform: rotate(45deg);
|
||||
aspect-ratio: 1;
|
||||
|
||||
&::after {
|
||||
content: ' ';
|
||||
display: block;
|
||||
block-size: 0.5rem;
|
||||
aspect-ratio: 1;
|
||||
position: absolute;
|
||||
border-radius: 50%;
|
||||
right: -0.25rem;
|
||||
top: calc(50% - 0.25rem);
|
||||
bottom: calc(50% - 0.25rem);
|
||||
background-color: hsla(var(--_branch-status-color) / 1);
|
||||
}
|
||||
|
||||
& :deep(.q-icon) {
|
||||
transform: rotate(-45deg);
|
||||
color: hsla(var(--_branch-card-bg) / 1);
|
||||
}
|
||||
}
|
||||
|
||||
& .branch-card__name {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
flex: 1;
|
||||
padding-inline: var(--size-2);
|
||||
|
||||
& .branch-card__code {
|
||||
color: hsla(var(--text-mute) / 1);
|
||||
}
|
||||
}
|
||||
|
||||
& .branch-card__action {
|
||||
margin-left: auto;
|
||||
}
|
||||
}
|
||||
& .branch-card__data {
|
||||
display: flex;
|
||||
flex-wrap: nowrap;
|
||||
padding-inline: var(--size-4);
|
||||
padding-block: var(--size-2);
|
||||
|
||||
&:last-child {
|
||||
flex-grow: 1;
|
||||
}
|
||||
|
||||
&:nth-child(2n + 1) {
|
||||
background-color: hsla(var(--_branch-card-row-bg) / 0.1);
|
||||
}
|
||||
|
||||
&.branch-card__header,
|
||||
&.branch-card__footer {
|
||||
color: hsl(var(--_branch-card-row-fg));
|
||||
background-color: hsl(var(--_branch-card-row-bg));
|
||||
|
||||
&:deep(*) {
|
||||
font-weight: 600;
|
||||
}
|
||||
}
|
||||
|
||||
&.branch-card__header > * {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
& > .branch-card__label {
|
||||
min-width: 120px;
|
||||
width: 30%;
|
||||
}
|
||||
|
||||
&:not(.branch-card__header) .branch-card__label {
|
||||
color: hsl(var(--stone-6-hsl));
|
||||
}
|
||||
|
||||
& > .branch-card__value {
|
||||
width: 70%;
|
||||
|
||||
&.branch-card__badge > span {
|
||||
display: inline-block;
|
||||
border-radius: 999rem;
|
||||
padding-inline: var(--size-2);
|
||||
color: hsl(var(--_branch-badge-fg));
|
||||
background-color: hsla(var(--_branch-badge-bg) / 0.1);
|
||||
}
|
||||
& > :first-child {
|
||||
color: hsla(var(--text-mute) / 1);
|
||||
width: 0%;
|
||||
min-width: 40%;
|
||||
}
|
||||
}
|
||||
|
||||
&.branch-card__none {
|
||||
--_branch-card-row-bg: var(--gray-3-hsl);
|
||||
--_branch-card-bg: var(--gray-3-hsl);
|
||||
|
||||
&.branch-card__dark {
|
||||
--_branch-card-row-bg: var(--gray-9-hsl);
|
||||
--_branch-card-bg: var(--gray-9-hsl);
|
||||
}
|
||||
|
||||
&:not(.branch-card__dark) .branch-card__header {
|
||||
|
|
@ -139,17 +162,22 @@ defineProps<{
|
|||
}
|
||||
|
||||
&.branch-card__hq {
|
||||
--_branch-card-row-bg: var(--pink-6-hsl);
|
||||
--_branch-card-bg: var(--pink-6-hsl);
|
||||
}
|
||||
|
||||
&.branch-card__br {
|
||||
--_branch-card-row-bg: var(--violet-11-hsl);
|
||||
--_branch-card-bg: var(--violet-11-hsl);
|
||||
|
||||
&.branch-card__dark {
|
||||
--_branch-card-bg: var(--violet-10-hsl);
|
||||
}
|
||||
}
|
||||
|
||||
&.branch-card__inactive {
|
||||
--_branch-badge-fg: var(--red-4-hsl);
|
||||
--_branch-status-color: var(--red-4-hsl);
|
||||
--_branch-badge-bg: var(--red-4-hsl);
|
||||
filter: grayscale(40%);
|
||||
filter: grayscale(1);
|
||||
background-color: hsl(var(--gray-6-hsl) / 0.1);
|
||||
opacity: 0.5;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -139,6 +139,11 @@ const branchNo = defineModel<number>('branchNo');
|
|||
class="col-6"
|
||||
:label="$t('taxNo')"
|
||||
v-model="taxNo"
|
||||
:rules="[
|
||||
(val) =>
|
||||
(val && val.length === 13 && /[0-9]+/.test(val)) ||
|
||||
$t('formDialogInputTaxNoValidate'),
|
||||
]"
|
||||
/>
|
||||
<q-input
|
||||
for="input-registerName"
|
||||
|
|
|
|||
|
|
@ -1,4 +1,5 @@
|
|||
<script setup lang="ts">
|
||||
import { getRole } from 'src/services/keycloak';
|
||||
import { CustomerBranch } from 'src/stores/customer/types';
|
||||
import { onMounted, ref } from 'vue';
|
||||
|
||||
|
|
@ -23,7 +24,7 @@ const customerBranch = defineModel<{
|
|||
const employeeId = defineModel<string>('employeeId');
|
||||
const nrcNo = defineModel<string>('nrcNo');
|
||||
|
||||
defineProps<{
|
||||
const props = defineProps<{
|
||||
dense?: boolean;
|
||||
outlined?: boolean;
|
||||
readonly?: boolean;
|
||||
|
|
@ -38,8 +39,6 @@ defineProps<{
|
|||
defineEmits<{
|
||||
(e: 'filterOwnerBranch', val: string, update: void): void;
|
||||
}>();
|
||||
|
||||
onMounted(async () => {});
|
||||
</script>
|
||||
|
||||
<template>
|
||||
|
|
@ -63,7 +62,16 @@ onMounted(async () => {});
|
|||
option-value="id"
|
||||
v-model="registeredBranchId"
|
||||
:options="optionsBranch"
|
||||
:rules="[(val) => !!val]"
|
||||
:rules="[
|
||||
(val) => {
|
||||
const roles = getRole() || [];
|
||||
const isSpecialRole = ['admin', 'system', 'head_of_admin'].some(
|
||||
(role) => roles.includes(role),
|
||||
);
|
||||
return isSpecialRole || !!val || 'กรุณากรอกข้อมูล';
|
||||
},
|
||||
]"
|
||||
clearable
|
||||
/>
|
||||
|
||||
<q-input
|
||||
|
|
@ -89,6 +97,11 @@ onMounted(async () => {});
|
|||
class="col-6"
|
||||
:label="$t('taxNo')"
|
||||
v-model="taxNo"
|
||||
:rules="[
|
||||
(val) =>
|
||||
(val && val.length === 13 && /[0-9]+/.test(val)) ||
|
||||
$t('formDialogInputTaxNoValidate'),
|
||||
]"
|
||||
/>
|
||||
|
||||
<q-input
|
||||
|
|
|
|||
|
|
@ -1,30 +1,27 @@
|
|||
<script setup lang="ts">
|
||||
import AppBox from 'components/app/AppBox.vue';
|
||||
|
||||
import { CustomerBranch } from 'src/stores/customer/types';
|
||||
|
||||
withDefaults(
|
||||
defineProps<{
|
||||
inactive?: boolean;
|
||||
color?: 'none' | 'CORP' | 'PERS';
|
||||
|
||||
metadata?: unknown;
|
||||
badgeField?: string[];
|
||||
fieldSelected?: string[];
|
||||
footer?: boolean;
|
||||
|
||||
data: {
|
||||
customerBranchFormTab: number;
|
||||
branchName: string;
|
||||
address: string;
|
||||
telephone: string;
|
||||
businessTypePure: string;
|
||||
status: string;
|
||||
totalEmployee: number;
|
||||
};
|
||||
}>(),
|
||||
{},
|
||||
);
|
||||
<script lang="ts" setup>
|
||||
defineProps<{
|
||||
inactive?: boolean;
|
||||
color?: 'none' | 'pers' | 'corp';
|
||||
data: {
|
||||
customerBranchFormTab: number;
|
||||
branchName: string;
|
||||
address: string;
|
||||
telephone: string;
|
||||
businessTypePure: string;
|
||||
totalEmployee: number;
|
||||
};
|
||||
metadata?: unknown;
|
||||
badgeField?: string[];
|
||||
fieldSelected?: (
|
||||
| 'customerBranchFormTab'
|
||||
| 'branchName'
|
||||
| 'address'
|
||||
| 'telephone'
|
||||
| 'businessTypePure'
|
||||
| 'totalEmployee'
|
||||
)[];
|
||||
footer?: boolean;
|
||||
}>();
|
||||
</script>
|
||||
|
||||
<template>
|
||||
|
|
@ -34,114 +31,135 @@ withDefaults(
|
|||
'branch-card__dark': $q.dark.isActive,
|
||||
'branch-card__inactive': inactive,
|
||||
'branch-card__none':
|
||||
color !== 'CORP' && color !== 'PERS' && (!color || color === 'none'),
|
||||
'branch-card__CORP': color === 'CORP',
|
||||
'branch-card__PERS': color === 'PERS',
|
||||
color !== 'pers' && color !== 'corp' && (!color || color === 'none'),
|
||||
'branch-card__pers': color === 'pers',
|
||||
'branch-card__corp': color === 'corp',
|
||||
}"
|
||||
@click="$emit('open')"
|
||||
>
|
||||
<div
|
||||
class="branch-card__row"
|
||||
:class="{
|
||||
'branch-card__header': i === 0,
|
||||
'branch-card__footer': footer && i === Object.keys(data).length - 1,
|
||||
}"
|
||||
v-for="([k, v], i) in Object.entries(data).filter(
|
||||
([key], idx) =>
|
||||
idx === 0 || (fieldSelected ? fieldSelected.includes(key) : true),
|
||||
)"
|
||||
:key="k"
|
||||
>
|
||||
<div class="branch-card__label">
|
||||
<span>{{ $t(k) }}</span>
|
||||
</div>
|
||||
<div
|
||||
class="branch-card__value"
|
||||
:class="{ 'branch-card__badge': badgeField?.includes(k) }"
|
||||
style="justify-content: space-between"
|
||||
>
|
||||
<span>{{ v }}</span>
|
||||
<q-btn
|
||||
@click.stop="$emit('view-detail', metadata ?? data)"
|
||||
:label="$t('viewDetail')"
|
||||
rounded
|
||||
outline
|
||||
dense
|
||||
no-caps
|
||||
class="branch-card__view-detail q-px-md text-caption"
|
||||
v-if="i === 0"
|
||||
<div class="branch-card__header">
|
||||
<div class="branch-card__icon">
|
||||
<q-icon
|
||||
size="md"
|
||||
style="scale: 0.8"
|
||||
name="mdi-office-building-outline"
|
||||
/>
|
||||
</div>
|
||||
<div class="branch-card__name">
|
||||
<b>{{ data.branchName }}</b>
|
||||
<small class="branch-card__code">{{ data.branchName }}</small>
|
||||
</div>
|
||||
|
||||
<div class="branch-card__action">
|
||||
<q-btn
|
||||
icon="mdi-eye-outline"
|
||||
size="sm"
|
||||
dense
|
||||
round
|
||||
flat
|
||||
@click.stop="$emit('viewDetail')"
|
||||
>
|
||||
<slot name="action" />
|
||||
</q-btn>
|
||||
</div>
|
||||
</div>
|
||||
<div
|
||||
style="
|
||||
display: block;
|
||||
width: 100%;
|
||||
height: 1px;
|
||||
background: hsla(0 0% 0% / 0.1);
|
||||
margin-bottom: var(--size-2);
|
||||
"
|
||||
/>
|
||||
<div
|
||||
v-for="key in fieldSelected?.sort() || [
|
||||
'customerBranchFormTab',
|
||||
'branchName',
|
||||
'address',
|
||||
'telephone',
|
||||
'businessTypePure',
|
||||
'totalEmployee',
|
||||
]"
|
||||
class="branch-card__data"
|
||||
>
|
||||
<div>{{ $t(key) }}</div>
|
||||
<div>{{ data[key as keyof typeof data] }}</div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<style scoped>
|
||||
.branch-card {
|
||||
--_branch-card-row-fg: 0 0% 100%;
|
||||
--_branch-card-row-bg: var(--blue-5-hsl);
|
||||
--_branch-badge-fg: var(--green-8-hsl);
|
||||
--_branch-badge-bg: var(--green-6-hsl);
|
||||
--_branch-card-fg: 0 0% 100%;
|
||||
--_branch-card-bg: var(--blue-5-hsl);
|
||||
--_branch-status-color: var(--green-6-hsl);
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
overflow: hidden;
|
||||
box-shadow: var(--shadow-2);
|
||||
padding: var(--size-3);
|
||||
|
||||
& > .branch-card__row {
|
||||
& .branch-card__header {
|
||||
display: flex;
|
||||
margin-bottom: var(--size-2);
|
||||
|
||||
& .branch-card__icon {
|
||||
background-color: hsla(var(--_branch-card-bg) / 0.15);
|
||||
border-radius: 50%;
|
||||
padding: var(--size-1);
|
||||
position: relative;
|
||||
transform: rotate(45deg);
|
||||
|
||||
&::after {
|
||||
content: ' ';
|
||||
display: block;
|
||||
block-size: 0.5rem;
|
||||
aspect-ratio: 1;
|
||||
position: absolute;
|
||||
border-radius: 50%;
|
||||
right: -0.25rem;
|
||||
top: calc(50% - 0.25rem);
|
||||
bottom: calc(50% - 0.25rem);
|
||||
background-color: hsla(var(--_branch-status-color) / 1);
|
||||
}
|
||||
|
||||
& :deep(.q-icon) {
|
||||
transform: rotate(-45deg);
|
||||
color: hsla(var(--_branch-card-bg) / 1);
|
||||
}
|
||||
}
|
||||
|
||||
& .branch-card__name {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
flex: 1;
|
||||
padding-inline: var(--size-2);
|
||||
|
||||
& .branch-card__code {
|
||||
color: hsla(var(--text-mute) / 1);
|
||||
}
|
||||
}
|
||||
|
||||
& .branch-card__action {
|
||||
margin-left: auto;
|
||||
}
|
||||
}
|
||||
& .branch-card__data {
|
||||
display: flex;
|
||||
flex-wrap: nowrap;
|
||||
padding-inline: var(--size-4);
|
||||
padding-block: var(--size-2);
|
||||
|
||||
&:last-child {
|
||||
flex-grow: 1;
|
||||
}
|
||||
|
||||
&:nth-child(2n + 1) {
|
||||
background-color: hsla(var(--_branch-card-row-bg) / 0.05);
|
||||
}
|
||||
|
||||
&.branch-card__header,
|
||||
&.branch-card__footer {
|
||||
color: hsl(var(--_branch-card-row-fg));
|
||||
background-color: hsl(var(--_branch-card-row-bg));
|
||||
|
||||
&:deep(*) {
|
||||
font-weight: 600;
|
||||
}
|
||||
}
|
||||
|
||||
&.branch-card__header > * {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
& > .branch-card__label {
|
||||
min-width: 120px;
|
||||
width: 30%;
|
||||
}
|
||||
|
||||
&:not(.branch-card__header) .branch-card__label {
|
||||
color: hsl(var(--stone-6-hsl));
|
||||
}
|
||||
|
||||
& > .branch-card__value {
|
||||
width: 70%;
|
||||
|
||||
&.branch-card__badge > span {
|
||||
display: inline-block;
|
||||
border-radius: 999rem;
|
||||
padding-inline: var(--size-2);
|
||||
color: hsl(var(--_branch-badge-fg));
|
||||
background-color: hsla(var(--_branch-badge-bg) / 0.1);
|
||||
}
|
||||
& > :first-child {
|
||||
color: hsla(var(--text-mute) / 1);
|
||||
width: 0%;
|
||||
min-width: 40%;
|
||||
}
|
||||
}
|
||||
|
||||
&.branch-card__none {
|
||||
--_branch-card-row-bg: var(--gray-3-hsl);
|
||||
--_branch-card-bg: var(--gray-3-hsl);
|
||||
|
||||
&.branch-card__dark {
|
||||
--_branch-card-row-bg: var(--gray-9-hsl);
|
||||
--_branch-card-bg: var(--gray-9-hsl);
|
||||
}
|
||||
|
||||
&:not(.branch-card__dark) .branch-card__header {
|
||||
|
|
@ -153,18 +171,23 @@ withDefaults(
|
|||
}
|
||||
}
|
||||
|
||||
&.branch-card__CORP {
|
||||
--_branch-card-row-bg: var(--purple-11-hsl);
|
||||
&.branch-card__pers {
|
||||
--_branch-card-bg: var(--pink-6-hsl);
|
||||
}
|
||||
|
||||
&.branch-card__PERS {
|
||||
--_branch-card-row-bg: var(--teal-9-hsl);
|
||||
&.branch-card__corp {
|
||||
--_branch-card-bg: var(--violet-11-hsl);
|
||||
|
||||
&.branch-card__dark {
|
||||
--_branch-card-bg: var(--violet-10-hsl);
|
||||
}
|
||||
}
|
||||
|
||||
&.branch-card__inactive {
|
||||
--_branch-badge-fg: var(--red-4-hsl);
|
||||
--_branch-status-color: var(--red-4-hsl);
|
||||
--_branch-badge-bg: var(--red-4-hsl);
|
||||
filter: grayscale(40%);
|
||||
filter: grayscale(1);
|
||||
background-color: hsl(var(--gray-6-hsl) / 0.1);
|
||||
opacity: 0.5;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -3,6 +3,7 @@ import { ref, onMounted, watch } from 'vue';
|
|||
|
||||
import useCustomerStore from 'src/stores/customer';
|
||||
import useFlowStore from 'src/stores/flow';
|
||||
import useOptionStore from 'src/stores/options';
|
||||
|
||||
import { Status } from 'src/stores/types';
|
||||
import { CustomerBranch, CustomerType } from 'src/stores/customer/types';
|
||||
|
|
@ -45,9 +46,9 @@ const prop = withDefaults(
|
|||
},
|
||||
);
|
||||
|
||||
const emit = defineEmits<{
|
||||
defineEmits<{
|
||||
(e: 'back'): void;
|
||||
(e: 'viewDetail', branch: CustomerBranch[]): void;
|
||||
(e: 'viewDetail', branch: CustomerBranch, index: number): void;
|
||||
(e: 'dialog'): void;
|
||||
}>();
|
||||
|
||||
|
|
@ -185,31 +186,29 @@ watch(currentStatus, async () => {
|
|||
</div>
|
||||
</div>
|
||||
<div
|
||||
class="row q-pa-lg q-col-gutter-xl"
|
||||
class="row q-pa-md q-col-gutter-md"
|
||||
:class="{ 'justify-center': totalBranch === 0 }"
|
||||
style="min-height: 350px"
|
||||
>
|
||||
<NoData v-if="totalBranch === 0" :not-found="!!inputSearch" />
|
||||
|
||||
<div
|
||||
v-for="(br, i) in branch?.sort((a, b) => a.branchNo - b.branchNo)"
|
||||
:key="i"
|
||||
class="col-4"
|
||||
>
|
||||
<div v-for="(br, i) in branch" :key="i" class="col-4">
|
||||
<BranchCardCustomer
|
||||
:inactive="br.status === 'INACTIVE'"
|
||||
:color="customerType"
|
||||
:color="customerType === 'CORP' ? 'corp' : 'pers'"
|
||||
:badgeField="['status']"
|
||||
:data="{
|
||||
customerBranchFormTab: br.branchNo,
|
||||
branchName: br.name,
|
||||
address: br.address,
|
||||
address:
|
||||
$i18n.locale === 'en-US'
|
||||
? `${br.addressEN || ''} ${br.subDistrict?.nameEN || ''} ${br.district?.nameEN || ''} ${br.province?.nameEN || ''}`
|
||||
: `${br.address || ''} ${br.subDistrict?.name || ''} ${br.district?.name || ''} ${br.province?.name || ''}`,
|
||||
telephone: br.telephoneNo,
|
||||
businessTypePure: br.bussinessType,
|
||||
status: 'ดำเนินการอยู่',
|
||||
businessTypePure: useOptionStore().mapOption(br.bussinessType),
|
||||
totalEmployee: br._count?.employee,
|
||||
}"
|
||||
@view-detail="emit('viewDetail', [br])"
|
||||
@view-detail="$emit('viewDetail', br, i)"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
|
|
|
|||
|
|
@ -68,7 +68,7 @@ onMounted(async () => {
|
|||
<q-select
|
||||
id="select-business-type"
|
||||
emit-value
|
||||
option-value="label"
|
||||
option-value="value"
|
||||
option-label="label"
|
||||
map-options
|
||||
:dense="dense"
|
||||
|
|
@ -95,7 +95,7 @@ onMounted(async () => {
|
|||
<q-select
|
||||
id="select-job-position"
|
||||
emit-value
|
||||
option-value="label"
|
||||
option-value="value"
|
||||
option-label="label"
|
||||
map-options
|
||||
:dense="dense"
|
||||
|
|
|
|||
|
|
@ -73,10 +73,7 @@ defineProps<{
|
|||
class="col-6"
|
||||
:label="$t('formDialogInputPassportRef')"
|
||||
v-model="previousPassportReference"
|
||||
:rules="[
|
||||
(val: string) =>
|
||||
!!val || $t('inputValidate') + $t('formDialogInputPassportRef'),
|
||||
]"
|
||||
|
||||
/>
|
||||
<q-input
|
||||
for="input-passport-place"
|
||||
|
|
|
|||
|
|
@ -1,4 +1,5 @@
|
|||
<script setup lang="ts">
|
||||
import { getRole } from 'src/services/keycloak';
|
||||
import { ref, onMounted } from 'vue';
|
||||
import { useI18n } from 'vue-i18n';
|
||||
const { locale } = useI18n({ useScope: 'global' });
|
||||
|
|
@ -10,9 +11,9 @@ const name = defineModel<string>('name');
|
|||
const code = defineModel<string>('code');
|
||||
|
||||
const registeredBranchId = defineModel<string>('registeredBranchId');
|
||||
const codeOption = ref([]);
|
||||
const codeOption = ref<{ id: string; name: string }[]>([]);
|
||||
|
||||
defineProps<{
|
||||
const props = defineProps<{
|
||||
dense?: boolean;
|
||||
outlined?: boolean;
|
||||
readonly?: boolean;
|
||||
|
|
@ -31,6 +32,15 @@ onMounted(async () => {
|
|||
if (locale.value === 'th-th') {
|
||||
codeOption.value = option.tha.typeProduct;
|
||||
}
|
||||
|
||||
if(!!props.optionsBranch) {
|
||||
|
||||
|
||||
|
||||
registeredBranchId.value = props.optionsBranch[0].id ;
|
||||
}
|
||||
|
||||
|
||||
});
|
||||
</script>
|
||||
|
||||
|
|
@ -71,18 +81,25 @@ onMounted(async () => {
|
|||
map-options
|
||||
options-dense
|
||||
:label="$t('registeredBranch')"
|
||||
class="col-3"
|
||||
class="col-3 "
|
||||
option-label="name"
|
||||
option-value="id"
|
||||
v-model="registeredBranchId"
|
||||
:options="optionsBranch"
|
||||
:rules="[(val) => !!val]"
|
||||
:rules="[
|
||||
(val) => {
|
||||
const roles = getRole() || [];
|
||||
const isSpecialRole = ['admin', 'system', 'head_of_admin'].some(role => roles.includes(role));
|
||||
return isSpecialRole || !!val || 'กรุณากรอกข้อมูล';
|
||||
}
|
||||
]"
|
||||
clearable
|
||||
/>
|
||||
|
||||
<q-input
|
||||
for="input-name"
|
||||
:dense="dense"
|
||||
:outlined="!readonly"
|
||||
outlined
|
||||
:readonly="readonly"
|
||||
:borderless="readonly"
|
||||
hide-bottom-space
|
||||
|
|
@ -94,7 +111,7 @@ onMounted(async () => {
|
|||
<q-input
|
||||
for="input-detail"
|
||||
:dense="dense"
|
||||
:outlined="!readonly"
|
||||
outlined
|
||||
:readonly="readonly"
|
||||
:borderless="readonly"
|
||||
hide-bottom-space
|
||||
|
|
@ -108,7 +125,7 @@ onMounted(async () => {
|
|||
<div class="col-12">
|
||||
<q-field
|
||||
class="full-width"
|
||||
:outlined="!readonly"
|
||||
outlined
|
||||
:readonly="readonly"
|
||||
:borderless="readonly"
|
||||
:label="$t('detail')"
|
||||
|
|
@ -138,12 +155,12 @@ onMounted(async () => {
|
|||
<q-input
|
||||
for="input-process"
|
||||
:dense="dense"
|
||||
:outlined="!readonly"
|
||||
outlined
|
||||
:readonly="readonly"
|
||||
:borderless="readonly"
|
||||
hide-bottom-space
|
||||
class="col-4"
|
||||
:label="$t('processingTime')"
|
||||
:label="$t('productProcessingTime')"
|
||||
v-model="process"
|
||||
type="number"
|
||||
/>
|
||||
|
|
|
|||
|
|
@ -1,5 +1,7 @@
|
|||
<script setup lang="ts">
|
||||
import { getRole } from 'src/services/keycloak';
|
||||
import useOptionStore from 'src/stores/options';
|
||||
import { onMounted } from 'vue';
|
||||
|
||||
const optionStore = useOptionStore();
|
||||
|
||||
|
|
@ -13,7 +15,7 @@ const serviceName = defineModel<string>('serviceNameTh');
|
|||
const serviceDescription = defineModel<string>('serviceDescription');
|
||||
|
||||
const registeredBranchId = defineModel<string | null>('registeredBranchId');
|
||||
defineProps<{
|
||||
const props = defineProps<{
|
||||
dense?: boolean;
|
||||
outlined?: boolean;
|
||||
readonly?: boolean;
|
||||
|
|
@ -77,6 +79,7 @@ defineProps<{
|
|||
|
||||
<q-select
|
||||
id="input-source-nationality"
|
||||
|
||||
:dense="dense"
|
||||
outlined
|
||||
:readonly="readonly"
|
||||
|
|
@ -86,12 +89,19 @@ defineProps<{
|
|||
map-options
|
||||
options-dense
|
||||
:label="$t('registeredBranch')"
|
||||
class="col-3"
|
||||
class="col-3 "
|
||||
option-label="name"
|
||||
option-value="id"
|
||||
v-model="registeredBranchId"
|
||||
:options="optionsBranch"
|
||||
:rules="[(val) => !!val]"
|
||||
:rules="[
|
||||
(val) => {
|
||||
const roles = getRole() || [];
|
||||
const isSpecialRole = ['admin', 'system', 'head_of_admin'].some(role => roles.includes(role));
|
||||
return isSpecialRole || !!val || 'กรุณากรอกข้อมูล';
|
||||
}
|
||||
]"
|
||||
clearable
|
||||
/>
|
||||
|
||||
<q-input
|
||||
|
|
|
|||
|
|
@ -13,37 +13,40 @@ defineProps<{
|
|||
</script>
|
||||
|
||||
<template>
|
||||
<div class="col-3 app-text-muted">• {{ $t('priceeInformation') }}</div>
|
||||
<div class="col-3 app-text-muted">• {{ $t('priceInformation') }}</div>
|
||||
<div class="col-9 row q-col-gutter-md">
|
||||
<q-input
|
||||
:dense="dense"
|
||||
:outlined="!readonly"
|
||||
outlined
|
||||
:readonly="readonly"
|
||||
:borderless="readonly"
|
||||
hide-bottom-space
|
||||
class="col-4"
|
||||
type="number"
|
||||
:label="$t('salePrice')"
|
||||
v-model="price"
|
||||
/>
|
||||
|
||||
<q-input
|
||||
:dense="dense"
|
||||
:outlined="!readonly"
|
||||
outlined
|
||||
:readonly="readonly"
|
||||
:borderless="readonly"
|
||||
hide-bottom-space
|
||||
class="col-4"
|
||||
type="number"
|
||||
:label="$t('agentPrice')"
|
||||
v-model="agentPrice"
|
||||
/>
|
||||
|
||||
<q-input
|
||||
:dense="dense"
|
||||
:outlined="!readonly"
|
||||
outlined
|
||||
:readonly="readonly"
|
||||
:borderless="readonly"
|
||||
hide-bottom-space
|
||||
class="col-4"
|
||||
type="number"
|
||||
:label="$t('processingPrice')"
|
||||
v-model="serviceCharge"
|
||||
/>
|
||||
|
|
|
|||
|
|
@ -37,7 +37,7 @@ withDefaults(
|
|||
>
|
||||
<div
|
||||
class="relative-position rounded q-pb-lg"
|
||||
:style="`background-color:hsla(${color}/0.1)`"
|
||||
:style="`background-color:hsla(${color}/.2)`"
|
||||
>
|
||||
<div class="row justify-between items-center">
|
||||
<q-avatar
|
||||
|
|
|
|||
|
|
@ -42,8 +42,8 @@ withDefaults(
|
|||
<div
|
||||
bordered
|
||||
:class="{ 'is-add-product': isAddProduct }"
|
||||
class="column bordered rounded q-pa-sm no-wrap"
|
||||
style="box-shadow: var(--shadow-3); height: 20rem"
|
||||
class="column bordered rounded q-pa-sm no-wrap surface-1"
|
||||
style="height: 20rem"
|
||||
@click="$emit('select', data)"
|
||||
>
|
||||
<div class="row flex justify-between text-bold">
|
||||
|
|
|
|||
|
|
@ -9,6 +9,7 @@ defineProps<{
|
|||
<div class="row">
|
||||
<q-btn
|
||||
unelevated
|
||||
id="btn-Add"
|
||||
@click="$emit('trigger')"
|
||||
size="lg"
|
||||
class="color-btn"
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
<script setup lang="ts"></script>
|
||||
|
||||
<template>
|
||||
<q-page-sticky position="bottom-right" :offset="[30, 18]">
|
||||
<q-page-sticky position="bottom-right" :offset="[8, 8]">
|
||||
<q-fab
|
||||
id="btn-add"
|
||||
padding="xs"
|
||||
|
|
@ -9,9 +9,9 @@
|
|||
direction="up"
|
||||
color="primary"
|
||||
>
|
||||
<slot />
|
||||
|
||||
<!-- <q-fab-action padding="xs" color="primary" icon="mdi-account-plus" /> -->
|
||||
<slot>
|
||||
<q-fab-action padding="xs" color="primary" icon="mdi-account-plus" />
|
||||
</slot>
|
||||
</q-fab>
|
||||
</q-page-sticky>
|
||||
</template>
|
||||
|
|
|
|||
|
|
@ -1,9 +1,32 @@
|
|||
<script setup lang="ts">
|
||||
import { computed, onMounted, ref } from 'vue';
|
||||
import { computed, ref, onMounted } from 'vue';
|
||||
import { useRouter } from 'vue-router';
|
||||
import { storeToRefs } from 'pinia';
|
||||
import { Icon } from '@iconify/vue';
|
||||
import useMyBranch from 'stores/my-branch';
|
||||
import { getUserId, getRole } from 'src/services/keycloak';
|
||||
|
||||
defineProps<{
|
||||
mini?: boolean;
|
||||
}>();
|
||||
|
||||
onMounted(async () => {
|
||||
const uid = getUserId();
|
||||
const role = getRole();
|
||||
|
||||
if (!uid) return;
|
||||
|
||||
if (role?.includes('system')) {
|
||||
const result = await userBranch.fetchListOptionBranch();
|
||||
if (result && result.total > 0) currentMyBranch.value = result.result[0];
|
||||
}
|
||||
const result = await userBranch.fetchListMyBranch(uid);
|
||||
if (result && result.total > 0) currentMyBranch.value = result.result[0];
|
||||
});
|
||||
|
||||
const router = useRouter();
|
||||
const userBranch = useMyBranch();
|
||||
const { currentMyBranch } = storeToRefs(userBranch);
|
||||
|
||||
const currentRoute = ref<string>('');
|
||||
const currentPath = computed(() => {
|
||||
|
|
@ -79,55 +102,119 @@ const labelMenu = ref<
|
|||
]);
|
||||
|
||||
const leftDrawerOpen = defineModel<boolean>('leftDrawerOpen', {
|
||||
default: false,
|
||||
default: true,
|
||||
});
|
||||
|
||||
function navigateTo(label: string, destination: string) {
|
||||
currentRoute.value = label;
|
||||
router.push(`${destination}`);
|
||||
}
|
||||
|
||||
function branchSetting() {}
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<!-- Drawer -->
|
||||
<q-drawer
|
||||
no-swipe-open
|
||||
v-model="leftDrawerOpen"
|
||||
side="left"
|
||||
:breakpoint="599"
|
||||
:width="$q.screen.lt.md ? 200 : 300"
|
||||
class="column justify-between no-wrap"
|
||||
:width="mini ? 80 : 256"
|
||||
show-if-above
|
||||
>
|
||||
<div class="main-bar">
|
||||
<!-- :width="$q.screen.lt.sm ? $q.screen.width - 16 : 256" -->
|
||||
<div class="scroll" style="overflow-x: hidden; scrollbar-gutter: stable">
|
||||
<div
|
||||
class="column items-center justify-center q-pa-xl cursor-pointer"
|
||||
class="flex justify-center items-center q-pl-sm cursor-pointer"
|
||||
@click="$router.push('/')"
|
||||
id="btn-drawer-home"
|
||||
style="height: 128px"
|
||||
>
|
||||
<q-img src="/logo.png" style="width: 70%; height: 70%">
|
||||
<template #error>
|
||||
<img src="/logo.png" alt="" width="100%" />
|
||||
</template>
|
||||
</q-img>
|
||||
<q-img
|
||||
fit="contain"
|
||||
:src="mini ? 'logo_jws.png' : '/logo.png'"
|
||||
:style="{ filter: `brightness(${$q.dark.isActive ? '1.3' : '1'})` }"
|
||||
style="height: 64px"
|
||||
/>
|
||||
</div>
|
||||
|
||||
<div id="drawer-menu" class="q-pl-md q-mr-xs">
|
||||
<q-item
|
||||
v-for="v in labelMenu"
|
||||
dense
|
||||
clickable
|
||||
class="row items-center q-my-xs q-px-xs"
|
||||
:key="v.label"
|
||||
:disable="!!v.disabled"
|
||||
:class="{
|
||||
active: currentPath === v.route,
|
||||
'border-active': currentPath === v.route,
|
||||
dark: $q.dark.isActive,
|
||||
}"
|
||||
@click="navigateTo(v.label, v.route)"
|
||||
>
|
||||
<div class="row justify-center items-center">
|
||||
<Icon :icon="v.icon" width="24px" />
|
||||
<q-tooltip v-if="mini">
|
||||
{{ $t(v.label) }}
|
||||
</q-tooltip>
|
||||
</div>
|
||||
|
||||
<div v-if="!mini" class="q-ml-md" style="white-space: nowrap">
|
||||
{{ $t(v.label) }}
|
||||
</div>
|
||||
</q-item>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div id="drawer-menu" class="q-pr-sm">
|
||||
<q-item
|
||||
v-for="v in labelMenu"
|
||||
:key="v.label"
|
||||
clickable
|
||||
:disable="!!v.disabled"
|
||||
@click="navigateTo(v.label, v.route)"
|
||||
class="no-padding"
|
||||
:class="{ active: currentPath === v.route, dark: $q.dark.isActive }"
|
||||
<div
|
||||
class="surface-2 q-px-md q-py-sm row items-center no-wrap justify-start"
|
||||
:class="{ 'justify-center': mini }"
|
||||
style="min-height: 56px; overflow-x: hidden"
|
||||
>
|
||||
<q-avatar
|
||||
text-color="white"
|
||||
size="md"
|
||||
:style="`background-color: hsla(var(--violet-${$q.dark.isActive ? '10' : '11'}-hsl)/0.15)`"
|
||||
class="relative-position"
|
||||
>
|
||||
<q-item-section id="btn-drawer-back ">
|
||||
<q-item-label class="q-pl-lg row items-center">
|
||||
<div class="box-border-left" />
|
||||
<Icon :icon="v.icon" width="24px" class="q-mr-md" />
|
||||
{{ $t(v.label) }}
|
||||
</q-item-label>
|
||||
</q-item-section>
|
||||
</q-item>
|
||||
<q-icon
|
||||
name="mdi-home-group"
|
||||
size="sm"
|
||||
:style="`color: var(--violet-${$q.dark.isActive ? '10' : '11'})`"
|
||||
/>
|
||||
<div class="dot absolute-bottom-right" />
|
||||
</q-avatar>
|
||||
|
||||
<div
|
||||
v-if="!mini"
|
||||
class="text-caption column q-ml-sm"
|
||||
style="white-space: nowrap"
|
||||
>
|
||||
<span class="text-weight-bold">
|
||||
{{
|
||||
($i18n.locale === 'en-US'
|
||||
? currentMyBranch?.nameEN
|
||||
: currentMyBranch?.name) ?? '-'
|
||||
}}
|
||||
</span>
|
||||
<span>
|
||||
{{ currentMyBranch?.code ?? '-' }}
|
||||
</span>
|
||||
</div>
|
||||
|
||||
<q-btn
|
||||
v-if="!mini"
|
||||
dense
|
||||
flat
|
||||
rounded
|
||||
icon="mdi-cog-outline"
|
||||
size="sm"
|
||||
@click="branchSetting"
|
||||
style="margin-left: auto"
|
||||
/>
|
||||
</div>
|
||||
</q-drawer>
|
||||
</template>
|
||||
|
|
@ -135,27 +222,47 @@ function navigateTo(label: string, destination: string) {
|
|||
<style lang="scss" scoped>
|
||||
#drawer-menu :deep(.q-item) {
|
||||
color: var(--gray-6);
|
||||
border-top-right-radius: 10px;
|
||||
border-bottom-right-radius: 10px;
|
||||
border-radius: var(--radius-2);
|
||||
}
|
||||
#drawer-menu :deep(.q-item.active) {
|
||||
--_drawer-item-background-color: var(--brand-1) !important;
|
||||
background-color: var(--_drawer-item-background-color);
|
||||
color: white;
|
||||
border-left: 10px solid $secondary;
|
||||
|
||||
&.dark {
|
||||
--_drawer-item-background-color: var(--gray-10) !important;
|
||||
border: 1px solid var(--brand-1);
|
||||
border-left: 10px solid $secondary;
|
||||
.box-border-left {
|
||||
position: absolute;
|
||||
width: 10px;
|
||||
background: $secondary;
|
||||
height: 48.5px;
|
||||
top: -1px;
|
||||
left: -10px;
|
||||
}
|
||||
}
|
||||
// border-left: 10px solid $secondary;
|
||||
}
|
||||
|
||||
#drawer-menu :deep(.q-item.active)::before {
|
||||
display: block;
|
||||
position: absolute;
|
||||
content: ' ';
|
||||
background: var(--brand-2);
|
||||
border-radius: 99rem;
|
||||
width: 6px;
|
||||
left: -0.6rem;
|
||||
top: 18%;
|
||||
bottom: 18%;
|
||||
cursor: context-menu;
|
||||
}
|
||||
|
||||
:deep(.q-drawer) {
|
||||
transition: 0.1s width ease-in-out;
|
||||
background-color: transparent;
|
||||
padding: var(--size-4);
|
||||
padding-right: 0;
|
||||
}
|
||||
|
||||
:deep(.q-drawer__content) {
|
||||
border-radius: var(--radius-2);
|
||||
background: var(--surface-1);
|
||||
}
|
||||
|
||||
.dot {
|
||||
height: 10px;
|
||||
width: 10px;
|
||||
background-color: var(--teal-6);
|
||||
border-radius: 50%;
|
||||
display: inline-block;
|
||||
border: 1.5px solid white;
|
||||
}
|
||||
</style>
|
||||
|
|
|
|||
|
|
@ -1,16 +1,22 @@
|
|||
<script setup lang="ts">
|
||||
import AppBox from 'components/app/AppBox.vue';
|
||||
|
||||
const props = withDefaults(
|
||||
defineProps<{
|
||||
branch: {
|
||||
icon: string;
|
||||
count: number;
|
||||
label: string;
|
||||
color: 'pink' | 'purple' | 'green' | 'orange';
|
||||
color:
|
||||
| 'pink'
|
||||
| 'purple'
|
||||
| 'green'
|
||||
| 'orange'
|
||||
| 'cyan'
|
||||
| 'yellow'
|
||||
| 'red'
|
||||
| 'magenta';
|
||||
}[];
|
||||
dark?: boolean;
|
||||
labelI18n?: boolean;
|
||||
nowrap?: boolean;
|
||||
}>(),
|
||||
{
|
||||
labelI18n: false,
|
||||
|
|
@ -19,113 +25,101 @@ const props = withDefaults(
|
|||
</script>
|
||||
|
||||
<template>
|
||||
<div
|
||||
class="row full-width"
|
||||
style="gap: var(--size-4)"
|
||||
:class="{ dark, 'no-wrap': nowrap }"
|
||||
>
|
||||
<AppBox
|
||||
<div class="row no-wrap" style="gap: var(--size-4)" :class="{ dark }">
|
||||
<div
|
||||
v-for="v in props.branch"
|
||||
:key="v.label"
|
||||
class="bordered stat-card__wave"
|
||||
class="no-padding stat-card"
|
||||
:class="{ [`stat-card__${v.color}`]: true }"
|
||||
style="
|
||||
padding: 12px 16px;
|
||||
height: 75px;
|
||||
min-width: 232px;
|
||||
box-shadow: var(--shadow-2);
|
||||
"
|
||||
:key="v.label"
|
||||
>
|
||||
<svg
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
viewBox="0 0 1440 320"
|
||||
style="width: 100%"
|
||||
>
|
||||
<path
|
||||
class="box-path"
|
||||
d="M0,256L40,245.3C80,235,160,213,240,202.7C320,192,400,192,480,170.7C560,149,640,107,720,106.7C800,107,880,149,960,154.7C1040,160,1120,128,1200,96C1280,64,1360,32,1400,16L1440,0L1440,320L1400,320C1360,320,1280,320,1200,320C1120,320,1040,320,960,320C880,320,800,320,720,320C640,320,560,320,480,320C400,320,320,320,240,320C160,320,80,320,40,320L0,320Z"
|
||||
></path>
|
||||
</svg>
|
||||
<div class="stat-card__content row items-center q-pa-sm">
|
||||
<div class="col-4 text-center">
|
||||
<q-avatar
|
||||
size="lg"
|
||||
style="background-color: hsla(0 0% 100% /0.2)"
|
||||
text-color="white"
|
||||
:icon="v.icon"
|
||||
/>
|
||||
</div>
|
||||
<div class="col-6 justify-center column">
|
||||
<div class="col-6 ellipsis text-bold" style="width: 100%">
|
||||
{{ labelI18n ? $t(v.label) : v.label }}
|
||||
<q-tooltip
|
||||
anchor="top middle"
|
||||
self="bottom middle"
|
||||
:offset="[10, 10]"
|
||||
>
|
||||
{{ labelI18n ? $t(v.label) : v.label }}
|
||||
</q-tooltip>
|
||||
</div>
|
||||
|
||||
<div class="stat-card__content">
|
||||
<div class="text-h5 text-weight-bold">{{ v.count }}</div>
|
||||
<div class="text-weight-bold text-no-wrap">
|
||||
{{ labelI18n ? $t(v.label) : v.label }}
|
||||
<div class="col-6">{{ v.count }}</div>
|
||||
</div>
|
||||
</div>
|
||||
</AppBox>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<style scoped>
|
||||
.stat-card {
|
||||
--_color: var(--gray-6);
|
||||
display: grid;
|
||||
grid-template-columns: repeat(2, 1fr);
|
||||
}
|
||||
|
||||
@media screen and (min-width: 1024px) {
|
||||
.stat-card {
|
||||
display: flex;
|
||||
}
|
||||
}
|
||||
|
||||
@media screen and (min-width: 1920px) {
|
||||
.stat-card {
|
||||
display: flex;
|
||||
}
|
||||
}
|
||||
|
||||
.stat-card__wave {
|
||||
position: relative;
|
||||
display: flex;
|
||||
|
||||
& svg {
|
||||
width: 200px;
|
||||
position: absolute;
|
||||
left: 0px;
|
||||
bottom: 0;
|
||||
opacity: 0.1;
|
||||
|
||||
& .box-path {
|
||||
fill: var(--_color);
|
||||
fill-opacity: 1;
|
||||
}
|
||||
}
|
||||
border-radius: var(--radius-2);
|
||||
overflow: hidden;
|
||||
box-shadow: var(--shadow-2);
|
||||
}
|
||||
|
||||
.stat-card__content {
|
||||
z-index: 2;
|
||||
color: var(--_color);
|
||||
color: hsla(var(--gray-0-hsl) / 1);
|
||||
background: hsla(var(--_color) / 1);
|
||||
height: 100%;
|
||||
width: 200px;
|
||||
min-width: 200px;
|
||||
}
|
||||
|
||||
.stat-card__purple {
|
||||
--_color: var(--violet-11);
|
||||
--_color: var(--violet-11-hsl);
|
||||
}
|
||||
|
||||
.stat-card__pink {
|
||||
--_color: var(--pink-6);
|
||||
--_color: var(--pink-6-hsl);
|
||||
}
|
||||
|
||||
.stat-card__green {
|
||||
--_color: var(--teal-10);
|
||||
--_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 {
|
||||
--_color: var(--orange-5);
|
||||
--_color: var(--orange-5-hsl);
|
||||
}
|
||||
|
||||
.stat-card__magenta {
|
||||
--_color: var(--pink-8-hsl);
|
||||
}
|
||||
|
||||
.dark .stat-card__purple {
|
||||
--_color: var(--purple-7);
|
||||
--_color: var(--violet-10-hsl);
|
||||
}
|
||||
|
||||
.dark .stat-card__green {
|
||||
--_color: var(--teal-7);
|
||||
--_color: var(--teal-8-hsl);
|
||||
}
|
||||
|
||||
.dark .stat-card__orange {
|
||||
--_color: var(--orange-8);
|
||||
--_color: var(--orange-6-hsl);
|
||||
}
|
||||
|
||||
.dark .stat-card__magenta {
|
||||
--_color: var(--pink-7-hsl);
|
||||
}
|
||||
</style>
|
||||
|
|
|
|||
|
|
@ -4,6 +4,7 @@ import { CustomerBranchCreate } from 'stores/customer/types';
|
|||
|
||||
defineProps<{
|
||||
readonly?: boolean;
|
||||
edit?: boolean;
|
||||
}>();
|
||||
|
||||
const customerBranch = defineModel<CustomerBranchCreate[]>('customerBranch', {
|
||||
|
|
@ -17,6 +18,8 @@ const index = ref<number>(0);
|
|||
function addData() {
|
||||
index.value++;
|
||||
customerBranch.value.push({
|
||||
code: '',
|
||||
branchNo: undefined,
|
||||
address: '',
|
||||
addressEN: '',
|
||||
provinceId: '',
|
||||
|
|
@ -91,7 +94,8 @@ function close(index: number) {
|
|||
v-for="(v, index) in customerBranch"
|
||||
:key="index"
|
||||
:name="index"
|
||||
:label="`${$t('customerBranchFormTab')} ${index + 1}`"
|
||||
:label="`${$t('customerBranchFormTab')} `"
|
||||
:disable="tab !== index && edit"
|
||||
@click="tab = index"
|
||||
no-caps
|
||||
:class="tab === index ? '' : 'bordered-b bordered-r'"
|
||||
|
|
@ -114,7 +118,9 @@ function close(index: number) {
|
|||
<q-tab-panels v-model="tab" class="rounded-borders">
|
||||
<q-tab-panel
|
||||
:id="`tab-branch-${index}`"
|
||||
v-for="(v, index) in customerBranch"
|
||||
v-for="(v, index) in customerBranch.sort(
|
||||
(a, b) => (a.branchNo ?? 0) - (b.branchNo ?? 0),
|
||||
)"
|
||||
:key="index"
|
||||
:name="index"
|
||||
>
|
||||
|
|
|
|||
|
|
@ -315,11 +315,11 @@ defineEmits<{
|
|||
}
|
||||
}
|
||||
&.color__purple {
|
||||
--_color: var(--purple-11-hsl);
|
||||
--_color: var(--violet-11-hsl);
|
||||
}
|
||||
|
||||
&.color__green {
|
||||
--_color: var(--teal-9-hsl);
|
||||
--_color: var(--teal-10-hsl);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -5,275 +5,242 @@ import AppBox from 'components/app/AppBox.vue';
|
|||
import AppCircle from 'components/app/AppCircle.vue';
|
||||
|
||||
defineProps<{
|
||||
list: {
|
||||
id: string;
|
||||
data: {
|
||||
name: string;
|
||||
detail?: { label: string; value: string }[];
|
||||
code: string;
|
||||
male?: boolean;
|
||||
female?: boolean;
|
||||
disabled?: boolean;
|
||||
badge?: string;
|
||||
img?: string;
|
||||
}[];
|
||||
gridColumns?: number;
|
||||
detail?: { icon: string; value: string }[];
|
||||
};
|
||||
tag?: [{ color: string; value: string }];
|
||||
disabled?: boolean;
|
||||
noHover?: boolean;
|
||||
noAction?: boolean;
|
||||
noDetail?: boolean;
|
||||
noBg?: boolean;
|
||||
detailColumnCount?: number;
|
||||
canEditProfile?: boolean;
|
||||
history?: boolean;
|
||||
}>();
|
||||
|
||||
defineEmits<{
|
||||
(e: 'editProfile'): void;
|
||||
(e: 'history', id: string): void;
|
||||
(e: 'deleteCard', id: string): void;
|
||||
(
|
||||
e: 'updateCard',
|
||||
action: 'FORM' | 'INFO',
|
||||
id: string,
|
||||
isEdit?: boolean,
|
||||
): void;
|
||||
(e: 'enterCard', action: 'FORM' | 'INFO', id: string): void;
|
||||
(e: 'toggleStatus', id: string, status: boolean): void;
|
||||
(e: 'history'): void;
|
||||
(e: 'deleteCard'): void;
|
||||
(e: 'updateCard', action: 'FORM' | 'INFO', isEdit?: boolean): void;
|
||||
(e: 'enterCard', action: 'FORM' | 'INFO'): void;
|
||||
(e: 'toggleStatus', status: boolean): void;
|
||||
}>();
|
||||
</script>
|
||||
|
||||
<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
|
||||
bordered
|
||||
no-padding
|
||||
class="column person-box"
|
||||
:class="{
|
||||
'person-box__disabled': disabled,
|
||||
'person-box__no-hover': noHover,
|
||||
'person-box__no-detail': !data.detail,
|
||||
'person-box__no-bg': noBg,
|
||||
}"
|
||||
@click="$emit('enterCard', 'INFO')"
|
||||
>
|
||||
<AppBox
|
||||
bordered
|
||||
class="column person-box"
|
||||
:class="{
|
||||
'person-box__disabled': v.disabled,
|
||||
'person-box__no-hover': noHover,
|
||||
'person-box__no-detail': noDetail,
|
||||
'person-box__no-bg': noBg,
|
||||
}"
|
||||
@click="$emit('enterCard', 'INFO', v.id)"
|
||||
v-for="(v, i) in list"
|
||||
:key="i"
|
||||
>
|
||||
<div class="q-pa-sm column items-center">
|
||||
<!-- kebab menu -->
|
||||
<div class="full-width text-right" v-if="!noAction">
|
||||
<q-btn
|
||||
v-if="history"
|
||||
flat
|
||||
round
|
||||
class="app-text-muted-2"
|
||||
padding="xs"
|
||||
icon="mdi-history"
|
||||
size="sm"
|
||||
@click.stop="$emit('history', v.id)"
|
||||
/>
|
||||
|
||||
<q-btn
|
||||
flat
|
||||
round
|
||||
padding="xs"
|
||||
class="app-text-muted-2"
|
||||
icon="mdi-dots-vertical"
|
||||
size="sm"
|
||||
@click.stop
|
||||
<div class="column items-center">
|
||||
<!-- kebab menu -->
|
||||
<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 }"
|
||||
>
|
||||
<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', v.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', 'INFO', v.id, true)"
|
||||
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', v.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', v.id, v.disabled === false)
|
||||
"
|
||||
:model-value="!v.disabled"
|
||||
val="xs"
|
||||
padding="none"
|
||||
>
|
||||
<div class="q-ml-xs">
|
||||
{{
|
||||
!v.disabled
|
||||
? $t('switchOnLabel')
|
||||
: $t('switchOffLabel')
|
||||
}}
|
||||
</div>
|
||||
</q-toggle>
|
||||
</div>
|
||||
</q-item-section>
|
||||
</q-item>
|
||||
</q-list>
|
||||
</q-menu>
|
||||
</q-btn>
|
||||
</div>
|
||||
|
||||
<!-- profile -->
|
||||
<div style="position: relative">
|
||||
<AppCircle
|
||||
bordered
|
||||
class="avatar"
|
||||
style="border: 2px solid var(--border-color)"
|
||||
:class="{ 'edit-profile': canEditProfile }"
|
||||
@click="
|
||||
() => {
|
||||
if (canEditProfile) $emit('editProfile');
|
||||
}
|
||||
"
|
||||
>
|
||||
<q-img
|
||||
:src="v.img"
|
||||
style="object-fit: cover; width: 100%; height: 100%"
|
||||
/>
|
||||
<div class="status-circle">
|
||||
<q-icon
|
||||
:name="`mdi-${v.disabled ? 'close' : 'check'}`"
|
||||
:style="`color:${v.disabled ? 'var(--gray-6)' : 'white'}`"
|
||||
/>
|
||||
</div>
|
||||
</AppCircle>
|
||||
</div>
|
||||
|
||||
<!-- name symbol -->
|
||||
<span class="items-center row q-my-sm">
|
||||
{{ v.name }}
|
||||
<Icon
|
||||
class="q-pl-sm"
|
||||
:class="{
|
||||
'symbol-gender': v.male || v.female,
|
||||
'symbol-gender__male': !v.disabled && v.male,
|
||||
'symbol-gender__female': !v.disabled && v.female,
|
||||
'symbol-gender__disable': v.disabled,
|
||||
}"
|
||||
:icon="`material-symbols:${v.male ? 'male' : 'female'}`"
|
||||
width="24px"
|
||||
/>
|
||||
<!-- <Icon class="locale q-pl-sm" icon="circle-flags:th" width="24px" /> -->
|
||||
</span>
|
||||
<span
|
||||
v-if="v.badge"
|
||||
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>
|
||||
</div>
|
||||
|
||||
<!-- detail -->
|
||||
<q-separator v-if="!noDetail" />
|
||||
<div
|
||||
v-if="!noDetail"
|
||||
class="q-pt-sm q-px-md q-pb-md person-detail rounded-b full-width"
|
||||
:class="{
|
||||
'bg-gender': v.male || v.female,
|
||||
'bg-gender__light':
|
||||
(!v.disabled && v.male) || (!v.disabled && v.female),
|
||||
'bg-gender__male': !v.disabled && v.male,
|
||||
'bg-gender__female': !v.disabled && v.female,
|
||||
'bg-gender__disable': v.disabled,
|
||||
}"
|
||||
:style="
|
||||
(detailColumnCount &&
|
||||
`grid-template-columns: repeat(${detailColumnCount}, 1fr);`) ||
|
||||
''
|
||||
"
|
||||
>
|
||||
<div v-for="(d, j) in v.detail" :key="j">
|
||||
<span class="app-text-muted-2">
|
||||
{{ d.label }}
|
||||
{{ v.value }}
|
||||
</span>
|
||||
<span>{{ d.value || '-' }}</span>
|
||||
</div>
|
||||
<q-btn
|
||||
v-if="history"
|
||||
flat
|
||||
round
|
||||
class="app-text-muted-2"
|
||||
padding="xs"
|
||||
icon="mdi-history"
|
||||
size="sm"
|
||||
@click.stop="$emit('history')"
|
||||
/>
|
||||
|
||||
<q-btn
|
||||
:key="data.code"
|
||||
flat
|
||||
round
|
||||
padding="xs"
|
||||
class="app-text-muted-2"
|
||||
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.stop="$emit('enterCard', 'INFO')"
|
||||
>
|
||||
<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', 'INFO', true)"
|
||||
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')"
|
||||
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', disabled === false)"
|
||||
:model-value="!disabled"
|
||||
val="xs"
|
||||
padding="none"
|
||||
>
|
||||
<div class="q-ml-xs">
|
||||
{{
|
||||
!disabled ? $t('switchOnLabel') : $t('switchOffLabel')
|
||||
}}
|
||||
</div>
|
||||
</q-toggle>
|
||||
</div>
|
||||
</q-item-section>
|
||||
</q-item>
|
||||
</q-list>
|
||||
</q-menu>
|
||||
</q-btn>
|
||||
</div>
|
||||
|
||||
<!-- profile -->
|
||||
|
||||
<AppCircle
|
||||
bordered
|
||||
class="avatar"
|
||||
style="border: 2px solid var(--border-color); overflow: visible"
|
||||
@click="$emit('editProfile')"
|
||||
>
|
||||
<q-img
|
||||
:src="data.img ?? '/no-profile.png'"
|
||||
style="
|
||||
object-fit: cover;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
border-radius: 50%;
|
||||
"
|
||||
>
|
||||
<template #error>
|
||||
<div
|
||||
style="background: none"
|
||||
class="full-width full-height items-center justify-center flex"
|
||||
>
|
||||
<q-img src="/no-profile.png" width="5rem" />
|
||||
</div>
|
||||
</template>
|
||||
</q-img>
|
||||
<div class="avatar__status"></div>
|
||||
</AppCircle>
|
||||
|
||||
<!-- name symbol -->
|
||||
<span class="items-center row">
|
||||
{{ data.name }}
|
||||
<Icon
|
||||
v-if="data.male || data.female"
|
||||
class="q-pl-xs"
|
||||
:class="{
|
||||
'symbol-gender': data.male || data.female,
|
||||
'symbol-gender__male': !disabled && data.male,
|
||||
'symbol-gender__female': !disabled && data.female,
|
||||
'symbol-gender__disable': disabled,
|
||||
}"
|
||||
:icon="`material-symbols:${data.male ? 'male' : 'female'}`"
|
||||
width="24px"
|
||||
/>
|
||||
</span>
|
||||
<span style="color: hsl(var(--text-mute)); scale: 0.9">
|
||||
{{ data.code || '-' }}
|
||||
</span>
|
||||
</div>
|
||||
|
||||
<!-- detail -->
|
||||
<q-separator v-if="data.detail" class="q-my-sm q-mx-md" />
|
||||
|
||||
<div class="row" v-for="v in data.detail" :key="v.value" v-if="data.detail">
|
||||
<div class="column items-center" style="width: min-content">
|
||||
<div class="detail-icon">
|
||||
<q-icon size="md" style="scale: 0.5" :name="v.icon" />
|
||||
</div>
|
||||
</div>
|
||||
</AppBox>
|
||||
</div>
|
||||
<div class="col row items-center full-width">
|
||||
<span class="ellipsis">{{ v.value || '-' }}</span>
|
||||
<q-tooltip
|
||||
anchor="bottom left"
|
||||
self="bottom left"
|
||||
:offset="[10, 20]"
|
||||
:delay="500"
|
||||
>
|
||||
{{ v.value || '-' }}
|
||||
</q-tooltip>
|
||||
</div>
|
||||
</div>
|
||||
</AppBox>
|
||||
</template>
|
||||
|
||||
<style scoped>
|
||||
.person-box {
|
||||
background-color: var(--surface-2);
|
||||
border-radius: var(--radius-2) !important;
|
||||
background-color: var(--surface-1);
|
||||
transition: 100ms ease-in-out;
|
||||
padding: 0;
|
||||
padding: var(--size-2);
|
||||
|
||||
&.person-box__disabled {
|
||||
opacity: 0.4;
|
||||
opacity: 0.5;
|
||||
filter: grayscale(0.9);
|
||||
|
||||
.status-circle {
|
||||
background-color: var(--surface-1);
|
||||
}
|
||||
|
||||
.locale {
|
||||
filter: grayscale();
|
||||
}
|
||||
}
|
||||
|
||||
&.person-box__no-detail {
|
||||
|
|
@ -284,6 +251,13 @@ defineEmits<{
|
|||
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 {
|
||||
color: hsla(var(--_fg));
|
||||
background-color: hsl(var(--_bg));
|
||||
|
|
@ -297,16 +271,6 @@ defineEmits<{
|
|||
color: unset;
|
||||
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 {
|
||||
|
|
@ -325,23 +289,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 {
|
||||
width: 18px;
|
||||
height: 18px;
|
||||
|
|
@ -360,11 +307,6 @@ defineEmits<{
|
|||
--_hover: hsl(var(--gender-male));
|
||||
cursor: pointer;
|
||||
box-shadow: var(--shadow-2);
|
||||
|
||||
& .person-detail {
|
||||
--_hover: hsl(var(--_bg));
|
||||
box-shadow: inset 0em -5px hsl(var(--_bg));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -374,17 +316,25 @@ defineEmits<{
|
|||
}
|
||||
|
||||
.avatar {
|
||||
block-size: 7rem;
|
||||
}
|
||||
block-size: 5rem;
|
||||
transform: rotate(45deg);
|
||||
|
||||
.badge {
|
||||
display: inline-block;
|
||||
border-radius: var(--radius-6);
|
||||
background-color: var(--surface-2);
|
||||
text-wrap: nowrap;
|
||||
& .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);
|
||||
}
|
||||
|
||||
&.empty {
|
||||
background-color: var(--surface-tab);
|
||||
& :deep(.q-img) {
|
||||
transform: rotate(-45deg);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -396,4 +346,60 @@ defineEmits<{
|
|||
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>
|
||||
|
|
|
|||
|
|
@ -9,9 +9,9 @@ html {
|
|||
|
||||
--brand-1: #035aa1;
|
||||
--brand-2: #f50000;
|
||||
--border-color: var(--gray-4);
|
||||
--border-color: var(--gray-2);
|
||||
--foreground: black;
|
||||
--background: var(--gray-1);
|
||||
--background: var(--gray-2);
|
||||
--surface-0: var(--background);
|
||||
--surface-1: white;
|
||||
--surface-2: var(--gray-0);
|
||||
|
|
@ -46,15 +46,15 @@ html {
|
|||
}
|
||||
|
||||
:where(.dark, .body--dark) {
|
||||
--brand-1: var(--blue-5);
|
||||
--brand-1: #035aa1;
|
||||
--brand-2: #f50000;
|
||||
--border-color: var(--gray-7);
|
||||
--foreground: white;
|
||||
--background: var(--gray-10);
|
||||
--background: var(--gray-11);
|
||||
--surface-0: var(--background);
|
||||
--surface-1: var(--gray-11);
|
||||
--surface-2: var(--gray-10);
|
||||
--surface-3: var(--gray-9);
|
||||
--surface-1: var(--gray-10);
|
||||
--surface-2: var(--gray-9);
|
||||
--surface-3: var(--gray-11);
|
||||
|
||||
--surface-tab: var(--gray-9);
|
||||
|
||||
|
|
|
|||
|
|
@ -6,8 +6,8 @@ $primary: var(--brand-1);
|
|||
$secondary: var(--brand-2);
|
||||
$accent: #9c27b0;
|
||||
|
||||
$dark: var(--gray-11);
|
||||
$dark-page: var(--gray-10);
|
||||
$dark: var(--gray-10);
|
||||
$dark-page: var(--gray-11);
|
||||
|
||||
$positive: #00bd9d;
|
||||
$negative: var(--red-9);
|
||||
|
|
@ -24,6 +24,7 @@ $separator-dark-color: var(--border-color);
|
|||
}
|
||||
|
||||
.q-field__control {
|
||||
background: var(--surface-1);
|
||||
color: $primary;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -2,6 +2,7 @@ export default {
|
|||
branchManagementCaption: 'Manage All Branch',
|
||||
branchInHQ: 'Branch within the main office',
|
||||
|
||||
office: 'Office',
|
||||
branchLabel: 'Branch',
|
||||
branchHQLabel: 'Headquarters',
|
||||
branchName: 'Branch Name',
|
||||
|
|
@ -20,4 +21,6 @@ export default {
|
|||
branchLabelStatus: 'Branch Status',
|
||||
|
||||
registeredBranch: 'Registered Branch',
|
||||
|
||||
branchStatTitle: 'Summary data of branch',
|
||||
};
|
||||
|
|
|
|||
|
|
@ -8,6 +8,9 @@ export default {
|
|||
customerEmployeeTooltipCaption: 'Click + to add an employee',
|
||||
customerEmployerAdd: 'Add employer',
|
||||
customerEmployeeAdd: 'Add employee',
|
||||
|
||||
nameEmployee:'Name Employee',
|
||||
|
||||
EMPLOYER: 'Employer',
|
||||
EMPLOYEE: 'Employee',
|
||||
customerEmployerStatTitle: 'Employer data summary',
|
||||
|
|
@ -53,4 +56,7 @@ export default {
|
|||
editBy: 'Edit by',
|
||||
valueBefore: 'Before',
|
||||
valueAfter: 'After',
|
||||
|
||||
serviceWorkTotal: 'Service Work Total',
|
||||
priceInformation: 'Price Information',
|
||||
};
|
||||
|
|
|
|||
|
|
@ -6,4 +6,6 @@ export default {
|
|||
corporationEnglish: 'English company name',
|
||||
|
||||
companyOwnerName: 'Company Owner Name',
|
||||
|
||||
corporation: 'Corporation',
|
||||
};
|
||||
|
|
|
|||
|
|
@ -92,6 +92,7 @@ export default {
|
|||
formDialogInputNationality: 'Nationality',
|
||||
|
||||
formDialogTitlePersonnelAddress: 'Personnel Address',
|
||||
formDialogTitleEmployerAddress: 'Employer Address',
|
||||
formDialogTitleAddressPure: 'Address',
|
||||
formDialogTitleAddressPureEN: 'Address in English',
|
||||
|
||||
|
|
|
|||
|
|
@ -39,6 +39,8 @@ export default {
|
|||
displayField: 'Display Fields',
|
||||
deleteConfirmTitle: 'Comfirm Deletion',
|
||||
deleteConfirmMessage: 'Do you want to delete this item?',
|
||||
headquartersNotEstablished: 'You have not yet established the headquarters. You need to establish the headquarters before you can create personnel.',
|
||||
|
||||
changePassword: 'Change Password',
|
||||
signature: 'Signature',
|
||||
addSignature: 'Add Signature',
|
||||
|
|
@ -59,6 +61,9 @@ export default {
|
|||
baseOnDevice: 'Base on Device',
|
||||
person: 'Person',
|
||||
recordsPage: 'Showing {resultcurrentPage} out of {total} records',
|
||||
showing: 'Showing',
|
||||
dataSum: 'Data Summaries',
|
||||
createdAt: 'Created At',
|
||||
...status,
|
||||
...main,
|
||||
...address,
|
||||
|
|
|
|||
75
src/i18n/en-US/object.ts
Normal file
75
src/i18n/en-US/object.ts
Normal file
|
|
@ -0,0 +1,75 @@
|
|||
export default {
|
||||
branchManagement: {
|
||||
label: {
|
||||
branchManagementCaption: 'Manage All Branch',
|
||||
branchLabel: 'Branch',
|
||||
branchHQLabel: 'Headquarters',
|
||||
},
|
||||
|
||||
table: {
|
||||
title: {
|
||||
office: 'Office',
|
||||
ddress: 'Address',
|
||||
// formDialogInputTelephone: 'Telephone Number',
|
||||
telephone: 'Telephone Number',
|
||||
type: 'Type',
|
||||
},
|
||||
},
|
||||
|
||||
input: {
|
||||
label: {
|
||||
search: 'Search',
|
||||
},
|
||||
},
|
||||
|
||||
manu: {
|
||||
branchName: 'Branch Name',
|
||||
branchLabelTel: 'Branch Telephone No',
|
||||
branchLabelAddress: 'Branch Address',
|
||||
branchLabelType: 'Branch Type',
|
||||
viewDetail: 'View Detail',
|
||||
edit: 'Edit',
|
||||
delete: 'Delete',
|
||||
switchOnLabel: 'Open',
|
||||
switchOffLabel: 'Close',
|
||||
},
|
||||
},
|
||||
|
||||
formDialog: {
|
||||
section: {
|
||||
formDialogTitleInformation: 'Basic Information',
|
||||
formDialogTitleContact: 'Contact Information',
|
||||
formDialogTitleAddress: ' Head office address information',
|
||||
formDialogTitleLocation: 'Head Office Location',
|
||||
formDialogTitleImg: 'Office Image',
|
||||
subtopic: {
|
||||
formDialogAddress: 'Address in Thai',
|
||||
formDialogAddressEN: 'Address in English',
|
||||
},
|
||||
},
|
||||
input: {
|
||||
formDialogInputCode: 'Head Office Code',
|
||||
formDialogInputBrId: 'Branch Code',
|
||||
formDialogInputTaxNo: 'Tax Identification Number',
|
||||
formDialogInputNameSubBranch: 'Branch Name',
|
||||
formDialogInputNameSubBranchEn: 'Branch Name (English)',
|
||||
formDialogInputEmailSubBranch: 'Branch Contact Email',
|
||||
formDialogInputTelephoneSubBranch: 'Branch Telephone Number',
|
||||
formDialogInputContactName: 'Contact',
|
||||
formDialogInputTelephoneContact: 'Contact Telephone Number',
|
||||
address: 'Address',
|
||||
province: 'Province',
|
||||
district: 'District',
|
||||
subDistrict: 'Sub-district',
|
||||
zipCode: 'Zip Code',
|
||||
},
|
||||
|
||||
button: {
|
||||
formDialogUploadQrCode: 'Upload QR Code',
|
||||
formDialogBtnLocation: 'Start sharing location',
|
||||
formDialogBtnImg: 'Add Office Image',
|
||||
agree: 'Ok',
|
||||
cancel: 'Cancel',
|
||||
},
|
||||
},
|
||||
};
|
||||
|
|
@ -12,7 +12,7 @@ export default {
|
|||
DELEGATE: 'Delegate',
|
||||
AGENCY: 'Agency',
|
||||
|
||||
personnelStatTitle: 'Summary data of ',
|
||||
personnelStatTitle: 'Summary data',
|
||||
|
||||
personnelCardUserType: 'Type',
|
||||
personnelCardTelephone: 'Telephone',
|
||||
|
|
|
|||
|
|
@ -9,6 +9,8 @@ export default {
|
|||
|
||||
service: 'Service',
|
||||
product: 'Product',
|
||||
productGroup: 'Product Group: {name}',
|
||||
productType: 'Product Type: {name}',
|
||||
|
||||
messageTooltipNoProduct: 'No Product and Service Groups',
|
||||
messageTooltipProductCreate: 'Click + for product and service groups.',
|
||||
|
|
@ -19,8 +21,9 @@ export default {
|
|||
|
||||
productCode: 'Product Code',
|
||||
productName: 'Product Name',
|
||||
processingTime: 'Processing Time (Day)',
|
||||
priceeInformation: 'Price Information',
|
||||
productDetail: 'Product Detail',
|
||||
productProcessingTime: 'Processing Time (Day)',
|
||||
priceInformation: 'Price Information',
|
||||
salePrice: 'Sale Price',
|
||||
agentPrice: 'Agent Price',
|
||||
processingPrice: 'Processing Price',
|
||||
|
|
|
|||
|
|
@ -2,6 +2,7 @@ export default {
|
|||
branchManagementCaption: 'จัดการสาขาทั้งหมด',
|
||||
branchInHQ: 'สาขาภายในสำนักงานใหญ่',
|
||||
|
||||
office: 'สำนักงาน',
|
||||
branchLabel: 'สาขา',
|
||||
branchHQLabel: 'สำนักงานใหญ่',
|
||||
branchName: 'ชื่อสาขา',
|
||||
|
|
@ -20,4 +21,6 @@ export default {
|
|||
branchLabelStatus: 'สถานะสาขา',
|
||||
|
||||
registeredBranch: 'สาขาที่ลงทะเบียน',
|
||||
|
||||
branchStatTitle: 'สรุปจัดการสาขา',
|
||||
};
|
||||
|
|
|
|||
|
|
@ -8,6 +8,9 @@ export default {
|
|||
customerEmployeeTooltipCaption: 'คลิก + เพื่อเพิ่มลูกจ้าง',
|
||||
customerEmployerAdd: 'เพิ่มนายจ้าง',
|
||||
customerEmployeeAdd: 'เพิ่มลูกจ้าง',
|
||||
|
||||
nameEmployee:'ชื่อลูกจ้าง',
|
||||
|
||||
EMPLOYER: 'นายจ้าง',
|
||||
EMPLOYEE: 'ลูกจ้าง',
|
||||
customerEmployerStatTitle: 'สรุปจำนวนข้อมูลนายจ้าง',
|
||||
|
|
@ -61,4 +64,7 @@ export default {
|
|||
editBy: 'แก้ไขโดย',
|
||||
valueBefore: 'แก้ไขใหม่',
|
||||
valueAfter: 'ค่าเดิม',
|
||||
|
||||
serviceWorkTotal: 'จำนวนงานทั้งหมด',
|
||||
priceInformation: 'ข้อมูลราคา',
|
||||
};
|
||||
|
|
|
|||
|
|
@ -6,4 +6,6 @@ export default {
|
|||
corporationEnglish: 'ชื่อ บริษัท ภาษาอังกฤษ',
|
||||
|
||||
companyOwnerName: 'ชื่อเจ้าของบริษัท',
|
||||
|
||||
corporation: 'ชื่อ บริษัท/นิติบุคคล',
|
||||
};
|
||||
|
|
|
|||
|
|
@ -90,6 +90,7 @@ export default {
|
|||
formDialogInputNationality: 'สัญชาติ',
|
||||
|
||||
formDialogTitlePersonnelAddress: 'ข้อมูลที่อยู่พนักงาน',
|
||||
formDialogTitleEmployerAddress: 'ข้อมูลที่อยู่นายจ้าง',
|
||||
formDialogTitleAddressPure: 'ที่อยู่',
|
||||
formDialogTitleAddressPureEN: 'ที่อยู่ภาษาอังกฤษ',
|
||||
|
||||
|
|
|
|||
|
|
@ -39,6 +39,7 @@ export default {
|
|||
displayField: 'ข้อมูลที่แสดง',
|
||||
deleteConfirmTitle: 'ยืนยันการลบข้อมูล',
|
||||
deleteConfirmMessage: 'คุณต้องการลบข้อมูลใช่หรือไม่',
|
||||
headquartersNotEstablished: 'ท่านยังไม่ได้สร้างสำนักงานใหญ่ ต้องสร้างสำนักงานใหญ่ก่อนจึงจะสร้าง บุคลากรได้',
|
||||
changePassword: 'เปลี่ยนรหัสผ่าน',
|
||||
signature: 'ลายเซ็น',
|
||||
addSignature: 'เพิ่มลายเซ็น',
|
||||
|
|
@ -59,6 +60,9 @@ export default {
|
|||
baseOnDevice: 'สีตามอุปกรณ์',
|
||||
person: 'คน',
|
||||
recordsPage: 'แสดง {resultcurrentPage} รายการจาก {total} รายการ',
|
||||
showing: 'แสดงทีละ',
|
||||
dataSum: 'สรุปจำนวนข้อมูล',
|
||||
createdAt: 'สร้างเมื่อ',
|
||||
...status,
|
||||
...main,
|
||||
...address,
|
||||
|
|
|
|||
|
|
@ -9,7 +9,7 @@ export default {
|
|||
mainCustomerCaption: 'จัดการคนภายในองค์กร',
|
||||
|
||||
mainProductTitle: 'สินค้าและบริการ',
|
||||
mainProductCaption: 'รายการสินค้าและบริการ',
|
||||
mainProductCaption: 'ประเภทสินค้าและบริการ',
|
||||
|
||||
mainQuotationTitle: 'ใบเสนอราคา',
|
||||
mainQuotationCaption: 'รายการใบเสนอราคา',
|
||||
|
|
|
|||
75
src/i18n/th-th/object.ts
Normal file
75
src/i18n/th-th/object.ts
Normal file
|
|
@ -0,0 +1,75 @@
|
|||
export default {
|
||||
branchManagement: {
|
||||
label: {
|
||||
branchManagementCaption: 'จัดการทุกสาขา',
|
||||
branchLabel: 'สาขา',
|
||||
branchHQLabel: 'สำนักงานใหญ่',
|
||||
},
|
||||
|
||||
table: {
|
||||
title: {
|
||||
office: 'สำนักงาน',
|
||||
address: 'ที่อยู่',
|
||||
// formDialogInputTelephone: 'เบอร์โทรศัพท์',
|
||||
telephone: 'เบอร์โทรศัพท์',
|
||||
type: 'ประเภท',
|
||||
},
|
||||
},
|
||||
|
||||
input: {
|
||||
label: {
|
||||
search: 'ค้นหา',
|
||||
},
|
||||
},
|
||||
|
||||
manu: {
|
||||
branchName: 'ชื่อสาขา',
|
||||
branchLabelTel: 'เบอร์โทรศัพท์สาขา',
|
||||
branchLabelAddress: 'ที่อยู่สาขา',
|
||||
branchLabelType: 'ประเภทสาขา',
|
||||
viewDetail: 'ดูรายละเอียด',
|
||||
edit: 'แก้ไข',
|
||||
delete: 'ลบ',
|
||||
switchOnLabel: 'เปิด',
|
||||
switchOffLabel: 'ปิด',
|
||||
},
|
||||
},
|
||||
|
||||
formDialog: {
|
||||
section: {
|
||||
formDialogTitleInformation: 'ข้อมูลพื้นฐาน',
|
||||
formDialogTitleContact: 'ข้อมูลติดต่อ',
|
||||
formDialogTitleAddress: 'ข้อมูลที่อยู่สำนักงานใหญ่',
|
||||
formDialogTitleLocation: 'ตำแหน่งที่ตั้งสำนักงานใหญ่',
|
||||
formDialogTitleImg: 'ภาพสำนักงาน',
|
||||
subtopic: {
|
||||
formDialogAddress: 'ที่อยู่ภาษาไทย',
|
||||
formDialogAddressEN: 'ที่อยู่ภาษาอังกฤษ',
|
||||
},
|
||||
},
|
||||
input: {
|
||||
formDialogInputCode: 'รหัสสำนักงานใหญ่',
|
||||
formDialogInputBrId: 'รหัสสาขา',
|
||||
formDialogInputTaxNo: 'เลขประจำตัวผู้เสียภาษี',
|
||||
formDialogInputNameSubBranch: 'ชื่อสาขา',
|
||||
formDialogInputNameSubBranchEn: 'ชื่อสาขา (ภาษาอังกฤษ)',
|
||||
formDialogInputEmailSubBranch: 'อีเมลติดต่อสาขา',
|
||||
formDialogInputTelephoneSubBranch: 'เบอร์โทรศัพท์สาขา',
|
||||
formDialogInputContactName: 'ชื่อผู้ติดต่อ',
|
||||
formDialogInputTelephoneContact: 'เบอร์โทรศัพท์ผู้ติดต่อ',
|
||||
address: 'ที่อยู่',
|
||||
province: 'จังหวัด',
|
||||
district: 'อำเภอ',
|
||||
subDistrict: 'ตำบล',
|
||||
zipCode: 'รหัสไปรษณีย์',
|
||||
},
|
||||
|
||||
button: {
|
||||
formDialogUploadQrCode: 'อัปโหลด QR Code',
|
||||
formDialogBtnLocation: 'เริ่มแชร์ตำแหน่งที่ตั้ง',
|
||||
formDialogBtnImg: 'เพิ่มภาพสำนักงาน',
|
||||
agree: 'ตกลง',
|
||||
cancel: 'ยกเลิก',
|
||||
},
|
||||
},
|
||||
};
|
||||
|
|
@ -21,7 +21,8 @@ export default {
|
|||
|
||||
productCode: 'รหัสสินค้า',
|
||||
productName: 'ชื่อสินค้า',
|
||||
processingTime: 'ระยะเวลาดำเนินการ (วัน)',
|
||||
productDetail: 'รายละเอียดสินค้า',
|
||||
productProcessingTime: 'ระยะเวลาดำเนินการ (วัน)',
|
||||
priceeInformation: 'ข้อมูลราคา',
|
||||
salePrice: 'ราคาขาย',
|
||||
agentPrice: 'ราคาตัวแทน',
|
||||
|
|
|
|||
|
|
@ -16,6 +16,10 @@ import useOptionStore from 'src/stores/options';
|
|||
import { dialog } from 'src/stores/utils';
|
||||
import { setLocale } from 'src/utils/datetime';
|
||||
import useUtilsStore from 'src/stores/utils';
|
||||
import useMyBranchStore from 'src/stores/my-branch';
|
||||
|
||||
const useMyBranch = useMyBranchStore();
|
||||
const { fetchListMyBranch } = useMyBranch;
|
||||
|
||||
interface NotificationButton {
|
||||
item: string;
|
||||
|
|
@ -41,7 +45,10 @@ const userStore = useUserStore();
|
|||
|
||||
const rawOption = ref();
|
||||
const canvasModal = ref(false);
|
||||
|
||||
const leftDrawerOpen = ref(true);
|
||||
const leftDrawerMini = ref(false);
|
||||
|
||||
const filterUnread = ref(false);
|
||||
const unread = ref<number>(1);
|
||||
// const filterRole = ref<string[]>();
|
||||
|
|
@ -135,6 +142,8 @@ watch(
|
|||
);
|
||||
|
||||
onMounted(async () => {
|
||||
await fetchListMyBranch(getUserId() ?? '');
|
||||
|
||||
const getCurLang = localStorage.getItem('currentLanguage');
|
||||
if (getCurLang) currentLanguage.value = getCurLang;
|
||||
if (currentLanguage.value === 'English') {
|
||||
|
|
@ -169,22 +178,25 @@ onMounted(async () => {
|
|||
|
||||
<template>
|
||||
<q-layout view="lHh Lpr lFf">
|
||||
<drawer-component v-model:leftDrawerOpen="leftDrawerOpen" />
|
||||
<drawer-component
|
||||
:mini="leftDrawerMini"
|
||||
v-model:left-drawer-open="leftDrawerOpen"
|
||||
/>
|
||||
|
||||
<q-page-container class="surface-1 q-pa-md">
|
||||
<q-page-container>
|
||||
<!-- drawer control -->
|
||||
<div
|
||||
style="position: relative"
|
||||
:style="$q.screen.gt.xs ? 'z-index: 1000' : 'z-index: 10'"
|
||||
>
|
||||
<q-avatar
|
||||
<div style="position: relative; z-index: 1000" :hidden="$q.screen.lt.sm">
|
||||
<div
|
||||
size="36px"
|
||||
style="
|
||||
position: absolute;
|
||||
border-radius: 50%;
|
||||
top: 28px;
|
||||
left: -18px;
|
||||
left: -22px;
|
||||
background-color: var(--surface-1);
|
||||
border: 4px solid var(--surface-1);
|
||||
"
|
||||
class="flex items-center justify-center"
|
||||
>
|
||||
<q-btn
|
||||
flat
|
||||
|
|
@ -197,30 +209,47 @@ onMounted(async () => {
|
|||
background-color: hsl(var(--negative-bg) / 0.1);
|
||||
overflow: hidden;
|
||||
"
|
||||
@click="leftDrawerOpen = !leftDrawerOpen"
|
||||
@click="leftDrawerMini = !leftDrawerMini"
|
||||
>
|
||||
<q-icon
|
||||
:name="leftDrawerOpen ? 'mdi-backburger' : 'mdi-forwardburger'"
|
||||
:name="!leftDrawerMini ? 'mdi-backburger' : 'mdi-forwardburger'"
|
||||
size="16px"
|
||||
style="color: hsl(var(--negative-bg))"
|
||||
/>
|
||||
</q-btn>
|
||||
</q-avatar>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div
|
||||
class="surface-3 bordered rounded q-pb-lg scroll column"
|
||||
style="height: calc(100vh - 32px); flex-wrap: nowrap"
|
||||
class="surface-0 scroll column"
|
||||
style="height: 100vh; flex-wrap: nowrap; padding-bottom: var(--size-4)"
|
||||
>
|
||||
<!-- header -->
|
||||
<div
|
||||
class="q-px-lg row items-center justify-between q-pb-md surface-3 q-pt-lg"
|
||||
class="q-px-lg surface-0 row items-center justify-start q-pb-md q-pt-lg"
|
||||
style="position: sticky; top: 0; z-index: 8"
|
||||
>
|
||||
<q-btn
|
||||
v-if="$q.screen.lt.sm"
|
||||
icon="mdi-menu"
|
||||
flat
|
||||
dense
|
||||
rounded
|
||||
class="q-mr-md"
|
||||
@click="
|
||||
() => {
|
||||
leftDrawerMini = false;
|
||||
leftDrawerOpen = !leftDrawerOpen;
|
||||
}
|
||||
"
|
||||
/>
|
||||
<div class="column">
|
||||
<span
|
||||
class="title-gradient text-weight-bold"
|
||||
:class="{ 'text-h6': $q.screen.gt.xs }"
|
||||
:style="{
|
||||
filter: `brightness(${$q.dark.isActive ? '2' : '1'})`,
|
||||
}"
|
||||
>
|
||||
{{
|
||||
utilsStore.currentTitle?.title
|
||||
|
|
@ -230,16 +259,29 @@ onMounted(async () => {
|
|||
: 'Jobs Worker Service'
|
||||
}}
|
||||
</span>
|
||||
<span class="text-caption">
|
||||
{{
|
||||
utilsStore.currentTitle?.caption
|
||||
? $t(utilsStore.currentTitle?.caption)
|
||||
: ''
|
||||
}}
|
||||
</span>
|
||||
<div class="flex items-center" style="gap: var(--size-1)">
|
||||
<template v-for="(item, i) in utilsStore.currentTitle.path">
|
||||
<span
|
||||
class="text-caption cursor-pointer"
|
||||
@click="item.handler?.()"
|
||||
>
|
||||
{{
|
||||
item.text
|
||||
? $t(item.text, {
|
||||
...(item.argsi18n || {}),
|
||||
})
|
||||
: ''
|
||||
}}
|
||||
</span>
|
||||
<q-icon
|
||||
name="mdi-chevron-right"
|
||||
v-if="i + 1 !== utilsStore.currentTitle.path.length"
|
||||
/>
|
||||
</template>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="row q-gutter-x-md items-center">
|
||||
<div class="row q-gutter-x-md items-center" style="margin-left: auto">
|
||||
<!-- notification -->
|
||||
<q-btn
|
||||
round
|
||||
|
|
|
|||
File diff suppressed because it is too large
Load diff
File diff suppressed because it is too large
Load diff
File diff suppressed because it is too large
Load diff
File diff suppressed because it is too large
Load diff
|
|
@ -99,7 +99,7 @@ const menu = [
|
|||
|
||||
onMounted(() => {
|
||||
utilsStore.currentTitle.title = '';
|
||||
utilsStore.currentTitle.caption = '';
|
||||
utilsStore.currentTitle.path = [{ text: '' }];
|
||||
});
|
||||
</script>
|
||||
|
||||
|
|
|
|||
|
|
@ -33,6 +33,9 @@ export type Branch = {
|
|||
telephoneNo: string;
|
||||
lineId: string;
|
||||
contact: BranchContact[];
|
||||
_count:{
|
||||
branch:number
|
||||
}
|
||||
};
|
||||
|
||||
export type BranchWithChildren = Branch & { branch: Branch[] };
|
||||
|
|
@ -64,6 +67,6 @@ export type BranchUserStats = {
|
|||
id: string;
|
||||
nameEN: string;
|
||||
name: string;
|
||||
count: 0;
|
||||
count: number;
|
||||
isHeadOffice: boolean;
|
||||
};
|
||||
|
|
|
|||
|
|
@ -336,11 +336,13 @@ const useCustomerStore = defineStore('api-customer', () => {
|
|||
transactionId?: string;
|
||||
},
|
||||
) {
|
||||
const { code, branchNo, ...playload } = data;
|
||||
|
||||
const res = await api.put<
|
||||
Customer & {
|
||||
branch: CustomerBranch[];
|
||||
}
|
||||
>(`/customer-branch/${id}`, data, {
|
||||
>(`/customer-branch/${id}`, playload, {
|
||||
headers: {
|
||||
'X-Session-Id': flow?.sessionId,
|
||||
'X-Rtid': flow?.refTransactionId || flowStore.rtid,
|
||||
|
|
|
|||
|
|
@ -4,6 +4,7 @@ import { Status } from '../types';
|
|||
export type CustomerType = 'CORP' | 'PERS';
|
||||
|
||||
export type Customer = {
|
||||
registeredBranchId: string;
|
||||
imageUrl: string;
|
||||
id: string;
|
||||
code: string;
|
||||
|
|
@ -63,7 +64,7 @@ export type CustomerBranch = {
|
|||
|
||||
export type CustomerBranchCreate = {
|
||||
code?: string;
|
||||
branchNo: number;
|
||||
branchNo?: number;
|
||||
address: string;
|
||||
addressEN: string;
|
||||
provinceId?: string | null;
|
||||
|
|
|
|||
|
|
@ -71,7 +71,7 @@ const useEmployeeStore = defineStore('api-employee', () => {
|
|||
transactionId?: string;
|
||||
},
|
||||
) {
|
||||
const { image, ...payload } = data;
|
||||
const { code, image, ...payload } = data;
|
||||
const res = await api.post<
|
||||
Employee & { profileImageUrl: string; profileImageUploadUrl: string }
|
||||
>('/employee', payload, {
|
||||
|
|
@ -104,7 +104,7 @@ const useEmployeeStore = defineStore('api-employee', () => {
|
|||
transactionId?: string;
|
||||
},
|
||||
) {
|
||||
const { image, ...payload } = data;
|
||||
const { code, image, ...payload } = data;
|
||||
const res = await api.put<
|
||||
Employee & { imageUrl: string; profileImageUploadUrl: string }
|
||||
>(`/employee/${id}`, payload, {
|
||||
|
|
|
|||
|
|
@ -2,6 +2,8 @@ import { District, Province, SubDistrict } from '../address';
|
|||
import { Status } from '../types';
|
||||
import { User } from '../user/types';
|
||||
|
||||
import { Customer , CustomerBranch } from '../customer/types';
|
||||
|
||||
export type Employee = {
|
||||
id: string;
|
||||
code: string;
|
||||
|
|
@ -45,14 +47,16 @@ export type Employee = {
|
|||
district: District | null;
|
||||
province: Province | null;
|
||||
profileImageUrl: string | null;
|
||||
customerBranch: CustomerBranch & { customer: Customer } ;
|
||||
|
||||
};
|
||||
|
||||
export type EmployeeCreate = {
|
||||
|
||||
code: string;
|
||||
image: File | null;
|
||||
customerBranchId: string;
|
||||
|
||||
status?: Status;
|
||||
|
||||
nrcNo: string;
|
||||
|
||||
dateOfBirth: Date | null;
|
||||
|
|
|
|||
|
|
@ -8,6 +8,9 @@ import { Branch } from '../branch/types';
|
|||
import useFlowStore from '../flow';
|
||||
|
||||
const useMyBranch = defineStore('useMyBranchStore', () => {
|
||||
const myBranch = ref<Branch[]>();
|
||||
const currentMyBranch = ref<Branch>();
|
||||
|
||||
const flowStore = useFlowStore();
|
||||
async function fetchListOptionBranch<
|
||||
Options extends {
|
||||
|
|
@ -52,8 +55,37 @@ const useMyBranch = defineStore('useMyBranchStore', () => {
|
|||
return false;
|
||||
}
|
||||
|
||||
async function fetchListMyBranch(
|
||||
userId: string,
|
||||
flow?: {
|
||||
sessionId?: string;
|
||||
refTransactionId?: string;
|
||||
transactionId?: string;
|
||||
},
|
||||
) {
|
||||
const res = await api.get<Pagination<Branch[]>>(`/user/${userId}/branch`, {
|
||||
headers: {
|
||||
'X-Session-Id': flow?.sessionId,
|
||||
'X-Rtid': flow?.refTransactionId || flowStore.rtid,
|
||||
'X-Tid': flow?.transactionId,
|
||||
},
|
||||
});
|
||||
|
||||
if (!res) return false;
|
||||
if (res.status === 200) {
|
||||
myBranch.value = res.data.result;
|
||||
return res.data;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
return {
|
||||
myBranch,
|
||||
currentMyBranch,
|
||||
|
||||
fetchListOptionBranch,
|
||||
fetchListMyBranch,
|
||||
};
|
||||
});
|
||||
|
||||
|
|
|
|||
|
|
@ -23,7 +23,11 @@ import {
|
|||
import { ref } from 'vue';
|
||||
import useFlowStore from '../flow';
|
||||
|
||||
import useMyBranchStore from 'src/stores/my-branch';
|
||||
|
||||
const useProductServiceStore = defineStore('api-product-service', () => {
|
||||
const useMyBranch = useMyBranchStore();
|
||||
|
||||
// Product Type
|
||||
const flowStore = useFlowStore();
|
||||
|
||||
|
|
@ -301,6 +305,10 @@ const useProductServiceStore = defineStore('api-product-service', () => {
|
|||
v !== undefined && params.append(k, v.toString());
|
||||
}
|
||||
|
||||
if (useMyBranch.myBranch?.length !== 0 && useMyBranch.myBranch) {
|
||||
params.append('registeredBranchId', useMyBranch.myBranch[0].id);
|
||||
}
|
||||
|
||||
const query = params.toString();
|
||||
|
||||
const res = await api.get<Pagination<ProductList[]>>(
|
||||
|
|
@ -429,6 +437,10 @@ const useProductServiceStore = defineStore('api-product-service', () => {
|
|||
v !== undefined && params.append(k, v.toString());
|
||||
}
|
||||
|
||||
if (useMyBranch.myBranch?.length !== 0 && useMyBranch.myBranch) {
|
||||
params.append('registeredBranchId', useMyBranch.myBranch[0].id);
|
||||
}
|
||||
|
||||
const query = params.toString();
|
||||
|
||||
const res = await api.get<Pagination<Service[]>>(
|
||||
|
|
@ -733,6 +745,10 @@ const useProductServiceStore = defineStore('api-product-service', () => {
|
|||
v !== undefined && params.append(k, v.toString());
|
||||
}
|
||||
|
||||
if (useMyBranch.myBranch?.length !== 0 && useMyBranch.myBranch) {
|
||||
params.append('registeredBranchId', useMyBranch.myBranch[0].id);
|
||||
}
|
||||
|
||||
const query = params.toString();
|
||||
|
||||
const res = await api.get<Pagination<ServiceAndProduct[]>>(
|
||||
|
|
|
|||
|
|
@ -97,6 +97,7 @@ export type UserAttachmentDelete = {
|
|||
};
|
||||
|
||||
export type UserTypeStats = {
|
||||
[x: string]: number;
|
||||
USER: number;
|
||||
MESSENGER: number;
|
||||
DELEGATE: number;
|
||||
|
|
|
|||
|
|
@ -95,9 +95,21 @@ export function formatNumberDecimal(num: number, point: number): string {
|
|||
}
|
||||
|
||||
const useUtilsStore = defineStore('utilsStore', () => {
|
||||
const currentTitle = ref<{ title: string; caption: string }>({
|
||||
const currentTitle = ref<{
|
||||
title: string;
|
||||
path: {
|
||||
text: string;
|
||||
argsi18n?: Record<string, string>;
|
||||
handler?: () => unknown;
|
||||
}[];
|
||||
}>({
|
||||
title: '',
|
||||
caption: '',
|
||||
path: [
|
||||
{
|
||||
text: '',
|
||||
handler: () => {},
|
||||
},
|
||||
],
|
||||
});
|
||||
|
||||
return {
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue