feat: Add avatar upload and merge EditableAvatar.vue with Avatar.vue
This commit is contained in:
@@ -192,6 +192,11 @@ const getFormBinding = key => {
|
||||
};
|
||||
|
||||
watch(() => props.contactData, updateState, { immediate: true, deep: true });
|
||||
|
||||
// Expose state to parent component for avatar upload
|
||||
defineExpose({
|
||||
state,
|
||||
});
|
||||
</script>
|
||||
|
||||
<template>
|
||||
|
||||
@@ -2,10 +2,11 @@
|
||||
import { computed, ref } from 'vue';
|
||||
import { useI18n } from 'vue-i18n';
|
||||
import { useStore } from 'dashboard/composables/store';
|
||||
import { useAlert } from 'dashboard/composables';
|
||||
import { dynamicTime } from 'shared/helpers/timeHelper';
|
||||
import { debounce } from '@chatwoot/utils';
|
||||
|
||||
import EditableAvatar from 'dashboard/components-next/avatar/EditableAvatar.vue';
|
||||
import Avatar from 'dashboard/components-next/avatar/Avatar.vue';
|
||||
import Button from 'dashboard/components-next/button/Button.vue';
|
||||
import ContactLabels from 'dashboard/components-next/Contacts/ContactLabels/ContactLabels.vue';
|
||||
import ContactsForm from 'dashboard/components-next/Contacts/ContactsForm/ContactsForm.vue';
|
||||
@@ -25,6 +26,11 @@ const store = useStore();
|
||||
|
||||
const confirmDeleteContactDialogRef = ref(null);
|
||||
|
||||
const avatarFile = ref(null);
|
||||
const avatarUrl = ref('');
|
||||
|
||||
const contactsFormRef = ref(null);
|
||||
|
||||
const selectedContactData = computed(() => {
|
||||
if (!props.selectedContact) return {};
|
||||
|
||||
@@ -43,6 +49,10 @@ const lastActivityAt = computed(() => {
|
||||
: '';
|
||||
});
|
||||
|
||||
const avatarSrc = computed(() => {
|
||||
return avatarUrl.value ? avatarUrl.value : props.selectedContact?.thumbnail;
|
||||
});
|
||||
|
||||
const updateContact = async updatedData => {
|
||||
await store.dispatch('contacts/update', updatedData);
|
||||
await store.dispatch(
|
||||
@@ -60,14 +70,51 @@ const handleFormUpdate = debounce(
|
||||
const openConfirmDeleteContactDialog = () => {
|
||||
confirmDeleteContactDialogRef.value?.dialogRef.open();
|
||||
};
|
||||
|
||||
const handleAvatarUpload = async ({ file, url }) => {
|
||||
avatarFile.value = file;
|
||||
avatarUrl.value = url;
|
||||
|
||||
try {
|
||||
await updateContact({
|
||||
...contactsFormRef.value?.state,
|
||||
avatar: file,
|
||||
isFormData: true,
|
||||
});
|
||||
useAlert(t('CONTACTS_LAYOUT.DETAILS.AVATAR.UPLOAD.SUCCESS_MESSAGE'));
|
||||
} catch {
|
||||
useAlert(t('CONTACTS_LAYOUT.DETAILS.AVATAR.UPLOAD.ERROR_MESSAGE'));
|
||||
}
|
||||
};
|
||||
|
||||
const handleAvatarDelete = async () => {
|
||||
try {
|
||||
if (props.selectedContact && props.selectedContact.id) {
|
||||
await store.dispatch('contacts/deleteAvatar', props.selectedContact.id);
|
||||
useAlert(t('CONTACTS_LAYOUT.DETAILS.AVATAR.DELETE.SUCCESS_MESSAGE'));
|
||||
}
|
||||
avatarFile.value = null;
|
||||
avatarUrl.value = '';
|
||||
} catch (error) {
|
||||
useAlert(
|
||||
error.message
|
||||
? error.message
|
||||
: t('CONTACTS_LAYOUT.DETAILS.AVATAR.DELETE.ERROR_MESSAGE')
|
||||
);
|
||||
}
|
||||
};
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<div class="flex flex-col items-start gap-8 pb-6">
|
||||
<div class="flex flex-col items-start gap-3">
|
||||
<EditableAvatar
|
||||
:src="selectedContact.thumbnail"
|
||||
<Avatar
|
||||
:src="avatarSrc"
|
||||
:name="selectedContact.name"
|
||||
:size="72"
|
||||
allow-upload
|
||||
@upload="handleAvatarUpload"
|
||||
@delete="handleAvatarDelete"
|
||||
/>
|
||||
<div class="flex flex-col gap-1">
|
||||
<h3 class="text-base font-medium text-n-slate-12">
|
||||
@@ -86,6 +133,7 @@ const openConfirmDeleteContactDialog = () => {
|
||||
<ContactLabels :contact-id="selectedContact.id" />
|
||||
</div>
|
||||
<ContactsForm
|
||||
ref="contactsFormRef"
|
||||
:contact-data="selectedContactData"
|
||||
is-details-view
|
||||
@update="handleFormUpdate"
|
||||
|
||||
Reference in New Issue
Block a user