feat: edit profile on drawer
This commit is contained in:
parent
23725ad730
commit
b24f785311
3 changed files with 156 additions and 188 deletions
|
|
@ -21,9 +21,11 @@ defineProps<{
|
|||
noDetail?: boolean;
|
||||
noBg?: boolean;
|
||||
detailColumnCount?: number;
|
||||
canEditProfile?: boolean;
|
||||
}>();
|
||||
|
||||
defineEmits<{
|
||||
(e: 'editProfile'): void;
|
||||
(e: 'deleteCard', id: string): void;
|
||||
(
|
||||
e: 'updateCard',
|
||||
|
|
@ -160,6 +162,12 @@ defineEmits<{
|
|||
bordered
|
||||
class="avatar"
|
||||
style="border: 2px solid var(--border-color)"
|
||||
:class="{ 'edit-profile': canEditProfile }"
|
||||
@click="
|
||||
() => {
|
||||
if (canEditProfile) $emit('editProfile');
|
||||
}
|
||||
"
|
||||
>
|
||||
<q-img
|
||||
:src="v.img"
|
||||
|
|
@ -360,4 +368,13 @@ defineEmits<{
|
|||
background-color: var(--surface-2);
|
||||
text-wrap: nowrap;
|
||||
}
|
||||
|
||||
.edit-profile {
|
||||
cursor: pointer;
|
||||
transition: opacity 0.2s ease;
|
||||
|
||||
&:hover {
|
||||
opacity: 80%;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
|
|
|||
|
|
@ -1,9 +1,11 @@
|
|||
<script setup lang="ts">
|
||||
import { ref, onMounted, watch } from 'vue';
|
||||
import { ref, onMounted, watch, computed } from 'vue';
|
||||
import { storeToRefs } from 'pinia';
|
||||
import { dialog } from 'src/stores/utils';
|
||||
import { useI18n } from 'vue-i18n';
|
||||
import useFlowStore from 'src/stores/flow';
|
||||
import useUserStore from 'stores/user';
|
||||
import useBranchStore from 'src/stores/branch';
|
||||
import { dialog } from 'src/stores/utils';
|
||||
|
||||
import {
|
||||
User,
|
||||
|
|
@ -26,9 +28,7 @@ import FormPerson from 'src/components/02_personnel-management/FormPerson.vue';
|
|||
import FormByType from 'src/components/02_personnel-management/FormByType.vue';
|
||||
import DrawerInfo from 'src/components/DrawerInfo.vue';
|
||||
import InfoForm from 'src/components/02_personnel-management/InfoForm.vue';
|
||||
import { computed } from 'vue';
|
||||
import { useI18n } from 'vue-i18n';
|
||||
import useFlowStore from 'src/stores/flow';
|
||||
import ProfileUpload from 'src/components/ProfileUpload.vue';
|
||||
|
||||
const { locale } = useI18n();
|
||||
|
||||
|
|
@ -144,6 +144,8 @@ reader.addEventListener('load', () => {
|
|||
if (typeof reader.result === 'string') {
|
||||
urlProfile.value = reader.result;
|
||||
}
|
||||
|
||||
if (infoDrawerEdit.value) infoPersonCard.value[0].img = urlProfile.value;
|
||||
});
|
||||
|
||||
watch(profileFile, () => {
|
||||
|
|
@ -229,7 +231,8 @@ function onClose() {
|
|||
brId.value = '';
|
||||
userId.value = '';
|
||||
userCode.value = '';
|
||||
urlProfile.value = '';
|
||||
urlProfile.value = undefined;
|
||||
profileFile.value = undefined;
|
||||
agencyFile.value = [];
|
||||
modal.value = false;
|
||||
isEdit.value = false;
|
||||
|
|
@ -249,121 +252,101 @@ async function onSubmit() {
|
|||
}
|
||||
|
||||
if (isEdit.value && userId.value) {
|
||||
dialog({
|
||||
color: 'primary',
|
||||
icon: 'mdi-pencil-outline',
|
||||
title: 'ยืนยันการแก้ไขข้อมูล',
|
||||
actionText: 'ตกลง',
|
||||
persistent: true,
|
||||
message: 'คุณต้องการแก้ไขข้อมูล ใช่หรือไม่',
|
||||
action: async () => {
|
||||
if (!userId.value) return;
|
||||
if (!userId.value) return;
|
||||
|
||||
const formDataEdit = {
|
||||
...formData.value,
|
||||
status: !statusToggle.value ? 'INACTIVE' : 'ACTIVE',
|
||||
} as const;
|
||||
await userStore.editById(userId.value, formDataEdit);
|
||||
const formDataEdit = {
|
||||
...formData.value,
|
||||
status: !statusToggle.value ? 'INACTIVE' : 'ACTIVE',
|
||||
} as const;
|
||||
await userStore.editById(userId.value, formDataEdit);
|
||||
|
||||
if (
|
||||
hqId.value &&
|
||||
currentUser.value?.branch[0] &&
|
||||
hqId.value !== currentUser.value.branch[0].id &&
|
||||
brId.value !== currentUser.value.branch[0].id
|
||||
) {
|
||||
await branchStore.removeUser(
|
||||
currentUser.value.branch[0].id,
|
||||
userId.value,
|
||||
);
|
||||
if (
|
||||
hqId.value &&
|
||||
currentUser.value?.branch[0] &&
|
||||
hqId.value !== currentUser.value.branch[0].id &&
|
||||
brId.value !== currentUser.value.branch[0].id
|
||||
) {
|
||||
await branchStore.removeUser(
|
||||
currentUser.value.branch[0].id,
|
||||
userId.value,
|
||||
);
|
||||
|
||||
await branchStore.addUser(
|
||||
!!brId.value ? brId.value : hqId.value,
|
||||
userId.value,
|
||||
);
|
||||
}
|
||||
await branchStore.addUser(
|
||||
!!brId.value ? brId.value : hqId.value,
|
||||
userId.value,
|
||||
);
|
||||
}
|
||||
|
||||
if (!currentUser.value?.branch[0]) {
|
||||
if (brId.value || hqId.value) {
|
||||
await branchStore.addUser(
|
||||
(!!brId.value ? brId.value : hqId.value)!,
|
||||
userId.value,
|
||||
);
|
||||
}
|
||||
}
|
||||
if (!currentUser.value?.branch[0]) {
|
||||
if (brId.value || hqId.value) {
|
||||
await branchStore.addUser(
|
||||
(!!brId.value ? brId.value : hqId.value)!,
|
||||
userId.value,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
if (userId.value && formDataEdit.userType === 'AGENCY') {
|
||||
if (!agencyFile.value) return;
|
||||
const payload: UserAttachmentCreate = {
|
||||
file: agencyFile.value,
|
||||
};
|
||||
if (userId.value && formDataEdit.userType === 'AGENCY') {
|
||||
if (!agencyFile.value) return;
|
||||
const payload: UserAttachmentCreate = {
|
||||
file: agencyFile.value,
|
||||
};
|
||||
|
||||
if (payload?.file) {
|
||||
await userStore.addAttachment(userId.value, payload);
|
||||
}
|
||||
}
|
||||
if (payload?.file) {
|
||||
await userStore.addAttachment(userId.value, payload);
|
||||
}
|
||||
}
|
||||
|
||||
userStore.fetchList({
|
||||
includeBranch: true,
|
||||
query: !!inputSearch.value ? inputSearch.value : undefined,
|
||||
userType: selectorLabel.value ?? undefined,
|
||||
});
|
||||
typeStats.value = await userStore.typeStats();
|
||||
const res = await branchStore.userStats(formData.value.userType);
|
||||
if (res) {
|
||||
userStats.value = res;
|
||||
}
|
||||
onClose();
|
||||
},
|
||||
userStore.fetchList({
|
||||
includeBranch: true,
|
||||
query: !!inputSearch.value ? inputSearch.value : undefined,
|
||||
userType: selectorLabel.value ?? undefined,
|
||||
});
|
||||
typeStats.value = await userStore.typeStats();
|
||||
const res = await branchStore.userStats(formData.value.userType);
|
||||
if (res) {
|
||||
userStats.value = res;
|
||||
}
|
||||
onClose();
|
||||
} else {
|
||||
dialog({
|
||||
color: 'primary',
|
||||
icon: 'mdi-account',
|
||||
title: 'ยืนยันการเพิ่มบุคลากร',
|
||||
actionText: 'ตกลง',
|
||||
persistent: true,
|
||||
message: 'คุณต้องการเพิ่มบุคลากร ใช่หรือไม่',
|
||||
action: async () => {
|
||||
if (!hqId.value) return;
|
||||
if (!hqId.value) return;
|
||||
|
||||
statusToggle.value
|
||||
? (formData.value.status = 'CREATED')
|
||||
: (formData.value.status = 'INACTIVE');
|
||||
statusToggle.value
|
||||
? (formData.value.status = 'CREATED')
|
||||
: (formData.value.status = 'INACTIVE');
|
||||
|
||||
const result = await userStore.create(formData.value);
|
||||
if (result) {
|
||||
await branchStore.addUser(
|
||||
!!brId.value ? brId.value : hqId.value,
|
||||
result.id,
|
||||
);
|
||||
}
|
||||
const result = await userStore.create(formData.value);
|
||||
if (result) {
|
||||
await branchStore.addUser(
|
||||
!!brId.value ? brId.value : hqId.value,
|
||||
result.id,
|
||||
);
|
||||
}
|
||||
|
||||
if (result && formData.value.userType === 'AGENCY') {
|
||||
if (!agencyFile.value) return;
|
||||
if (result && formData.value.userType === 'AGENCY') {
|
||||
if (!agencyFile.value) return;
|
||||
|
||||
const payload: UserAttachmentCreate = {
|
||||
file: agencyFile.value,
|
||||
};
|
||||
const payload: UserAttachmentCreate = {
|
||||
file: agencyFile.value,
|
||||
};
|
||||
|
||||
if (payload?.file) {
|
||||
await userStore.addAttachment(result.id, payload);
|
||||
}
|
||||
}
|
||||
if (payload?.file) {
|
||||
await userStore.addAttachment(result.id, payload);
|
||||
}
|
||||
}
|
||||
|
||||
selectorLabel.value = formData.value.userType;
|
||||
userStore.fetchList({
|
||||
includeBranch: true,
|
||||
query: !!inputSearch.value ? inputSearch.value : undefined,
|
||||
userType: selectorLabel.value ?? undefined,
|
||||
});
|
||||
typeStats.value = await userStore.typeStats();
|
||||
const res = await branchStore.userStats(formData.value.userType);
|
||||
if (res) {
|
||||
userStats.value = res;
|
||||
}
|
||||
onClose();
|
||||
},
|
||||
selectorLabel.value = formData.value.userType;
|
||||
userStore.fetchList({
|
||||
includeBranch: true,
|
||||
query: !!inputSearch.value ? inputSearch.value : undefined,
|
||||
userType: selectorLabel.value ?? undefined,
|
||||
});
|
||||
typeStats.value = await userStore.typeStats();
|
||||
const res = await branchStore.userStats(formData.value.userType);
|
||||
if (res) {
|
||||
userStats.value = res;
|
||||
}
|
||||
onClose();
|
||||
}
|
||||
flowStore.rotate();
|
||||
}
|
||||
|
|
@ -474,9 +457,13 @@ async function assignFormData(idEdit: string) {
|
|||
|
||||
userCode.value = foundUser.code;
|
||||
urlProfile.value = foundUser.profileImageUrl;
|
||||
|
||||
isEdit.value = true;
|
||||
profileSubmit.value = true;
|
||||
hqId.value && (await userStore.fetchBrOption(hqId.value));
|
||||
if (infoPersonCard.value) {
|
||||
infoPersonCard.value[0].img = foundUser.profileImageUrl;
|
||||
}
|
||||
if (formData.value.districtId) {
|
||||
await adrressStore.fetchSubDistrictByProvinceId(
|
||||
formData.value.districtId,
|
||||
|
|
@ -728,7 +715,11 @@ watch(
|
|||
v-if="currentUser"
|
||||
:category="$t('personnelTitle')"
|
||||
bg-on
|
||||
:badgeClass="formData.gender === 'male' ? 'app-bg-male' : 'app-bg-female'"
|
||||
:badgeClass="
|
||||
formData.gender === 'male'
|
||||
? 'app-bg-male text-white'
|
||||
: 'app-bg-female text-white'
|
||||
"
|
||||
:badgeLabel="userCode"
|
||||
:isEdit="infoDrawerEdit"
|
||||
:title="
|
||||
|
|
@ -757,12 +748,18 @@ watch(
|
|||
<div class="q-ma-md">
|
||||
<AppBox class="surface-1" style="padding: 0">
|
||||
<PersonCard
|
||||
:can-edit-profile="infoDrawerEdit"
|
||||
no-hover
|
||||
no-action
|
||||
no-detail
|
||||
no-bg
|
||||
:list="infoPersonCard"
|
||||
:gridColumns="1"
|
||||
@edit-profile="
|
||||
() => {
|
||||
inputFile.click();
|
||||
}
|
||||
"
|
||||
/>
|
||||
</AppBox>
|
||||
</div>
|
||||
|
|
@ -843,86 +840,12 @@ watch(
|
|||
:close="() => onClose()"
|
||||
>
|
||||
<template #prepend>
|
||||
<div class="text-center">
|
||||
<div class="upload-img-preview">
|
||||
<q-img
|
||||
v-if="urlProfile"
|
||||
:src="urlProfile"
|
||||
style="object-fit: cover; width: 100%; height: 100%"
|
||||
/>
|
||||
<q-icon
|
||||
v-else
|
||||
name="mdi-account full-height"
|
||||
size="3vw"
|
||||
style="color: var(--border-color)"
|
||||
/>
|
||||
</div>
|
||||
<div
|
||||
v-if="urlProfile && !profileSubmit"
|
||||
class="col-12 row q-mt-md q-col-gutter-x-md"
|
||||
>
|
||||
<div class="col-6">
|
||||
<q-btn
|
||||
id="btn-profile-cancel"
|
||||
dense
|
||||
unelevated
|
||||
outlined
|
||||
padding="8px"
|
||||
class="cancel-img-btn full-width"
|
||||
:label="$t('cancel')"
|
||||
@click="urlProfile = ''"
|
||||
/>
|
||||
</div>
|
||||
<div class="col-6">
|
||||
<q-btn
|
||||
id="btn-profile-save"
|
||||
dense
|
||||
unelevated
|
||||
outlined
|
||||
padding="8px"
|
||||
class="submit-img-btn full-width"
|
||||
:label="$t('save')"
|
||||
@click="profileSubmit = true"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
<q-btn
|
||||
id="btn-profile-edit"
|
||||
v-else-if="urlProfile && profileSubmit"
|
||||
dense
|
||||
unelevated
|
||||
outlined
|
||||
padding="8px"
|
||||
icon="mdi-pencil-outline"
|
||||
class="edit-img-btn q-mt-md full-width"
|
||||
:label="$t('formDialogBtnEditProfile')"
|
||||
@click.prevent="inputFile.click(), (profileSubmit = false)"
|
||||
/>
|
||||
|
||||
<q-btn
|
||||
id="btn-profile-upload"
|
||||
v-else
|
||||
dense
|
||||
unelevated
|
||||
outlined
|
||||
padding="8px"
|
||||
class="upload-img-btn q-mt-md full-width"
|
||||
:label="$t('formDialogBtnUploadProfile')"
|
||||
:class="{ dark: $q.dark.isActive }"
|
||||
@click="inputFile.click()"
|
||||
/>
|
||||
<q-separator class="col-12 q-my-md" />
|
||||
<div class="text-left q-pt-md">
|
||||
<q-toggle
|
||||
dense
|
||||
size="md"
|
||||
v-model="statusToggle"
|
||||
padding="none"
|
||||
class="q-pr-md"
|
||||
/>
|
||||
<span>{{ $t('formDialogTitleUserStatus') }}</span>
|
||||
</div>
|
||||
</div>
|
||||
<ProfileUpload
|
||||
v-model:url-profile="urlProfile"
|
||||
v-model:status-toggle="statusToggle"
|
||||
v-model:profile-submit="profileSubmit"
|
||||
@input-file="inputFile.click()"
|
||||
/>
|
||||
</template>
|
||||
|
||||
<template #information>
|
||||
|
|
|
|||
|
|
@ -269,6 +269,12 @@ const inputFile = (() => {
|
|||
const reader = new FileReader();
|
||||
reader.addEventListener('load', () => {
|
||||
if (typeof reader.result === 'string') profileUrl.value = reader.result;
|
||||
|
||||
if (infoDrawerEdit.value && currentCustomer.value)
|
||||
currentCustomer.value.imageUrl = profileUrl.value as string;
|
||||
|
||||
if (infoDrawerEmployeeEdit.value)
|
||||
infoEmployeePersonCard.value[0].img = profileUrl.value;
|
||||
});
|
||||
|
||||
element.addEventListener('change', () => {
|
||||
|
|
@ -977,6 +983,7 @@ async function assignFormDataEmployee(id: string) {
|
|||
|
||||
currentEmployeeCode.value = foundEmployee.code;
|
||||
currentEmployee.value = foundEmployee;
|
||||
|
||||
profileUrl.value = foundEmployee.profileImageUrl;
|
||||
|
||||
foundEmployee.profileImageUrl
|
||||
|
|
@ -1041,6 +1048,10 @@ async function assignFormDataEmployee(id: string) {
|
|||
} else {
|
||||
formDataEmployeeSameAddr.value = false;
|
||||
}
|
||||
|
||||
if (infoEmployeePersonCard.value) {
|
||||
infoEmployeePersonCard.value[0].img = foundEmployee.profileImageUrl;
|
||||
}
|
||||
}
|
||||
flowStore.rotate();
|
||||
}
|
||||
|
|
@ -2302,6 +2313,9 @@ watch(selectorLabel, async () => {
|
|||
"
|
||||
v-model:drawer-open="infoDrawer"
|
||||
:badgeLabel="currentCustomer?.code"
|
||||
:badgeClass="
|
||||
currentCustomer?.customerType === 'CORP' ? 'app-bg-corp' : 'app-bg-pers'
|
||||
"
|
||||
:undo="() => undo()"
|
||||
:isEdit="infoDrawerEdit"
|
||||
:close="() => onClose()"
|
||||
|
|
@ -2317,8 +2331,9 @@ watch(selectorLabel, async () => {
|
|||
<InfoForm>
|
||||
<template #person-card>
|
||||
<div class="q-ma-md">
|
||||
<AppBox class="surface-1" style="padding: 0">
|
||||
<AppBox class="surface-1 bordered-b" style="padding: 0">
|
||||
<UsersDetailCardComponent
|
||||
:can-edit-profile="infoDrawerEdit"
|
||||
:hideButton="true"
|
||||
v-if="!!currentCustomer"
|
||||
no-bg
|
||||
|
|
@ -2339,6 +2354,11 @@ watch(selectorLabel, async () => {
|
|||
status: currentCustomer.status,
|
||||
code: 'HQ006',
|
||||
}"
|
||||
@edit-profile="
|
||||
() => {
|
||||
inputFile.click();
|
||||
}
|
||||
"
|
||||
/>
|
||||
</AppBox>
|
||||
</div>
|
||||
|
|
@ -2497,7 +2517,9 @@ watch(selectorLabel, async () => {
|
|||
:title="$t('formTitleBranch', { msg: currentBranch.name })"
|
||||
v-model:drawer-open="infoDrawerBranch"
|
||||
:badgeLabel="currentBranch.code"
|
||||
badgeClass="app-bg-pers"
|
||||
:badgeClass="
|
||||
currentCustomer?.customerType === 'CORP' ? 'app-bg-corp' : 'app-bg-pers'
|
||||
"
|
||||
:undo="
|
||||
() => {
|
||||
cloneData();
|
||||
|
|
@ -2752,12 +2774,18 @@ watch(selectorLabel, async () => {
|
|||
<div class="q-ma-md">
|
||||
<AppBox class="surface-1" style="padding: 0">
|
||||
<PersonCard
|
||||
:can-edit-profile="infoDrawerEmployeeEdit"
|
||||
no-hover
|
||||
no-action
|
||||
no-detail
|
||||
no-bg
|
||||
:list="infoEmployeePersonCard"
|
||||
:gridColumns="1"
|
||||
@edit-profile="
|
||||
() => {
|
||||
inputFile.click();
|
||||
}
|
||||
"
|
||||
/>
|
||||
</AppBox>
|
||||
</div>
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue