feat: Improve Contact list (#10522)

This commit is contained in:
Sivin Varghese
2024-12-03 07:53:41 +05:30
committed by GitHub
parent 86bd339a47
commit 062587487a
6 changed files with 66 additions and 40 deletions

View File

@@ -214,6 +214,10 @@ const resetValidation = () => {
v$.value.$reset(); v$.value.$reset();
}; };
const resetForm = () => {
Object.assign(state, defaultState);
};
watch(() => props.contactData, prepareStateBasedOnProps, { watch(() => props.contactData, prepareStateBasedOnProps, {
immediate: true, immediate: true,
deep: true, deep: true,
@@ -224,6 +228,7 @@ defineExpose({
state, state,
resetValidation, resetValidation,
isFormInvalid, isFormInvalid,
resetForm,
}); });
</script> </script>
@@ -261,7 +266,7 @@ defineExpose({
:placeholder="item.placeholder" :placeholder="item.placeholder"
:message-type="getMessageType(item.key)" :message-type="getMessageType(item.key)"
:custom-input-class="`h-8 !pt-1 !pb-1 ${ :custom-input-class="`h-8 !pt-1 !pb-1 ${
!isDetailsView ? '[&:not(.error)]:!border-transparent' : '' !isDetailsView ? '[&:not(.error,.focus)]:!border-transparent' : ''
}`" }`"
class="w-full" class="w-full"
@input=" @input="

View File

@@ -27,11 +27,16 @@ const handleDialogConfirm = async () => {
emit('create', contact.value); emit('create', contact.value);
}; };
const onSuccess = () => {
contactsFormRef.value?.resetForm();
dialogRef.value.close();
};
const closeDialog = () => { const closeDialog = () => {
dialogRef.value.close(); dialogRef.value.close();
}; };
defineExpose({ dialogRef, contactsFormRef }); defineExpose({ dialogRef, contactsFormRef, onSuccess });
</script> </script>
<template> <template>

View File

@@ -7,6 +7,10 @@ import { useAlert, useTrack } from 'dashboard/composables';
import { CONTACTS_EVENTS } from 'dashboard/helper/AnalyticsHelper/events'; import { CONTACTS_EVENTS } from 'dashboard/helper/AnalyticsHelper/events';
import filterQueryGenerator from 'dashboard/helper/filterQueryGenerator'; import filterQueryGenerator from 'dashboard/helper/filterQueryGenerator';
import contactFilterItems from 'dashboard/routes/dashboard/contacts/contactFilterItems'; import contactFilterItems from 'dashboard/routes/dashboard/contacts/contactFilterItems';
import {
DuplicateContactException,
ExceptionWithMessage,
} from 'shared/helpers/CustomErrors';
import { generateValuesForEditCustomViews } from 'dashboard/helper/customViewsHelper'; import { generateValuesForEditCustomViews } from 'dashboard/helper/customViewsHelper';
import countries from 'shared/constants/countries'; import countries from 'shared/constants/countries';
import { import {
@@ -23,38 +27,14 @@ import DeleteSegmentDialog from 'dashboard/components-next/Contacts/ContactsForm
import ContactsFilter from 'dashboard/components-next/filter/ContactsFilter.vue'; import ContactsFilter from 'dashboard/components-next/filter/ContactsFilter.vue';
const props = defineProps({ const props = defineProps({
showSearch: { showSearch: { type: Boolean, default: true },
type: Boolean, searchValue: { type: String, default: '' },
default: true, activeSort: { type: String, default: 'last_activity_at' },
}, activeOrdering: { type: String, default: '' },
searchValue: { headerTitle: { type: String, default: '' },
type: String, segmentsId: { type: [String, Number], default: 0 },
default: '', activeSegment: { type: Object, default: null },
}, hasAppliedFilters: { type: Boolean, default: false },
activeSort: {
type: String,
default: 'last_activity_at',
},
activeOrdering: {
type: String,
default: '',
},
headerTitle: {
type: String,
default: '',
},
segmentsId: {
type: [String, Number],
default: 0,
},
activeSegment: {
type: Object,
default: null,
},
hasAppliedFilters: {
type: Boolean,
default: false,
},
}); });
const emit = defineEmits([ const emit = defineEmits([
@@ -99,8 +79,26 @@ const openDeleteSegmentDialog = () =>
deleteSegmentDialogRef.value?.dialogRef.open(); deleteSegmentDialogRef.value?.dialogRef.open();
const onCreate = async contact => { const onCreate = async contact => {
try {
await store.dispatch('contacts/create', contact); await store.dispatch('contacts/create', contact);
createNewContactDialogRef.value?.dialogRef.close(); createNewContactDialogRef.value?.onSuccess();
useAlert(
t('CONTACTS_LAYOUT.HEADER.ACTIONS.CONTACT_CREATION.SUCCESS_MESSAGE')
);
} catch (error) {
const i18nPrefix = 'CONTACTS_LAYOUT.HEADER.ACTIONS.CONTACT_CREATION';
if (error instanceof DuplicateContactException) {
if (error.data.includes('email')) {
useAlert(t(`${i18nPrefix}.EMAIL_ADDRESS_DUPLICATE`));
} else if (error.data.includes('phone_number')) {
useAlert(t(`${i18nPrefix}.PHONE_NUMBER_DUPLICATE`));
}
} else if (error instanceof ExceptionWithMessage) {
useAlert(error.data);
} else {
useAlert(t(`${i18nPrefix}.ERROR_MESSAGE`));
}
}
}; };
const onImport = async file => { const onImport = async file => {
@@ -135,11 +133,19 @@ const onCreateSegment = async payload => {
...payload, ...payload,
query: segmentsQuery.value, query: segmentsQuery.value,
}; };
await store.dispatch('customViews/create', payloadData); const response = await store.dispatch('customViews/create', payloadData);
createSegmentDialogRef.value?.dialogRef.close(); createSegmentDialogRef.value?.dialogRef.close();
useAlert( useAlert(
t('CONTACTS_LAYOUT.HEADER.ACTIONS.FILTERS.CREATE_SEGMENT.SUCCESS_MESSAGE') t('CONTACTS_LAYOUT.HEADER.ACTIONS.FILTERS.CREATE_SEGMENT.SUCCESS_MESSAGE')
); );
const segmentId = response?.data?.id;
if (!segmentId) return;
// Navigate to the created segment
router.push({
name: 'contacts_dashboard_segments_index',
params: { segmentId },
query: { page: 1 },
});
} catch { } catch {
useAlert( useAlert(
t('CONTACTS_LAYOUT.HEADER.ACTIONS.FILTERS.CREATE_SEGMENT.ERROR_MESSAGE') t('CONTACTS_LAYOUT.HEADER.ACTIONS.FILTERS.CREATE_SEGMENT.ERROR_MESSAGE')

View File

@@ -91,13 +91,18 @@ const activeCountry = computed(() =>
const inputBorderClass = computed(() => { const inputBorderClass = computed(() => {
const errorClass = const errorClass =
'border-n-ruby-8 dark:border-n-ruby-8 hover:border-n-ruby-9 dark:hover:border-n-ruby-9 disabled:border-n-ruby-8 dark:disabled:border-n-ruby-8'; 'border-n-ruby-8 dark:border-n-ruby-8 hover:border-n-ruby-9 dark:hover:border-n-ruby-9 disabled:border-n-ruby-8 dark:disabled:border-n-ruby-8';
const focusClass =
'has-[:focus]:border-n-brand dark:has-[:focus]:border-n-brand';
if (!props.showBorder) { if (!props.showBorder) {
return hasError.value ? errorClass : 'border-transparent'; if (hasError.value) return errorClass;
return `border-transparent ${focusClass}`;
} }
if (hasError.value) { if (hasError.value) {
return errorClass; return errorClass;
} }
return 'has-[:focus]:border-n-brand dark:has-[:focus]:border-n-brand border-n-weak dark:border-n-weak hover:border-n-slate-6 dark:hover:border-n-slate-6 disabled:border-n-weak dark:disabled:border-n-weak'; return `${focusClass} border-n-weak dark:border-n-weak hover:border-n-slate-6 dark:hover:border-n-slate-6 disabled:border-n-weak dark:disabled:border-n-weak`;
}); });
const phoneNumberError = computed(() => { const phoneNumberError = computed(() => {

View File

@@ -401,7 +401,11 @@
"ADD_CONTACT": "Add contact", "ADD_CONTACT": "Add contact",
"EXPORT_CONTACT": "Export contacts", "EXPORT_CONTACT": "Export contacts",
"IMPORT_CONTACT": "Import contacts", "IMPORT_CONTACT": "Import contacts",
"SAVE_CONTACT": "Save contact" "SAVE_CONTACT": "Save contact",
"EMAIL_ADDRESS_DUPLICATE": "This email address is in use for another contact.",
"PHONE_NUMBER_DUPLICATE": "This phone number is in use for another contact.",
"SUCCESS_MESSAGE": "Contact saved successfully",
"ERROR_MESSAGE": "Unable to save contact. Please try again later."
}, },
"IMPORT_CONTACT": { "IMPORT_CONTACT": {
"TITLE": "Import contacts", "TITLE": "Import contacts",

View File

@@ -70,6 +70,7 @@ export const actions = {
data: response.data, data: response.data,
filterType: FILTER_KEYS[obj.filter_type], filterType: FILTER_KEYS[obj.filter_type],
}); });
return response;
} catch (error) { } catch (error) {
const errorMessage = error?.response?.data?.message; const errorMessage = error?.response?.data?.message;
throw new Error(errorMessage); throw new Error(errorMessage);