chore: Refactor Edit contact modal to separate form (#1805)
This commit is contained in:
committed by
GitHub
parent
6bbeb005f5
commit
eec90a1319
@@ -43,7 +43,9 @@
|
|||||||
"EDIT_CONTACT": {
|
"EDIT_CONTACT": {
|
||||||
"BUTTON_LABEL": "Edit Contact",
|
"BUTTON_LABEL": "Edit Contact",
|
||||||
"TITLE": "Edit contact",
|
"TITLE": "Edit contact",
|
||||||
"DESC": "Edit contact details",
|
"DESC": "Edit contact details"
|
||||||
|
},
|
||||||
|
"CONTACT_FORM": {
|
||||||
"FORM": {
|
"FORM": {
|
||||||
"SUBMIT": "Submit",
|
"SUBMIT": "Submit",
|
||||||
"CANCEL": "Cancel",
|
"CANCEL": "Cancel",
|
||||||
|
|||||||
@@ -7,7 +7,7 @@
|
|||||||
<div v-if="browser.browser_name" class="conversation--details">
|
<div v-if="browser.browser_name" class="conversation--details">
|
||||||
<contact-details-item
|
<contact-details-item
|
||||||
v-if="location"
|
v-if="location"
|
||||||
:title="$t('EDIT_CONTACT.FORM.LOCATION.LABEL')"
|
:title="$t('CONTACT_FORM.FORM.LOCATION.LABEL')"
|
||||||
:value="location"
|
:value="location"
|
||||||
icon="ion-map"
|
icon="ion-map"
|
||||||
emoji="📍"
|
emoji="📍"
|
||||||
|
|||||||
@@ -0,0 +1,215 @@
|
|||||||
|
<template>
|
||||||
|
<form class="contact--form" @submit.prevent="handleSubmit">
|
||||||
|
<div class="row">
|
||||||
|
<div class="medium-9 columns">
|
||||||
|
<label :class="{ error: $v.name.$error }">
|
||||||
|
{{ $t('CONTACT_FORM.FORM.NAME.LABEL') }}
|
||||||
|
<input
|
||||||
|
v-model.trim="name"
|
||||||
|
type="text"
|
||||||
|
:placeholder="$t('CONTACT_FORM.FORM.NAME.PLACEHOLDER')"
|
||||||
|
@input="$v.name.$touch"
|
||||||
|
/>
|
||||||
|
</label>
|
||||||
|
|
||||||
|
<label :class="{ error: $v.email.$error }">
|
||||||
|
{{ $t('CONTACT_FORM.FORM.EMAIL_ADDRESS.LABEL') }}
|
||||||
|
<input
|
||||||
|
v-model.trim="email"
|
||||||
|
type="text"
|
||||||
|
:placeholder="$t('CONTACT_FORM.FORM.EMAIL_ADDRESS.PLACEHOLDER')"
|
||||||
|
@input="$v.email.$touch"
|
||||||
|
/>
|
||||||
|
</label>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="medium-12 columns">
|
||||||
|
<label :class="{ error: $v.description.$error }">
|
||||||
|
{{ $t('CONTACT_FORM.FORM.BIO.LABEL') }}
|
||||||
|
<textarea
|
||||||
|
v-model.trim="description"
|
||||||
|
type="text"
|
||||||
|
:placeholder="$t('CONTACT_FORM.FORM.BIO.PLACEHOLDER')"
|
||||||
|
@input="$v.description.$touch"
|
||||||
|
/>
|
||||||
|
</label>
|
||||||
|
</div>
|
||||||
|
<div class="row">
|
||||||
|
<woot-input
|
||||||
|
v-model.trim="phoneNumber"
|
||||||
|
class="medium-6 columns"
|
||||||
|
:label="$t('CONTACT_FORM.FORM.PHONE_NUMBER.LABEL')"
|
||||||
|
:placeholder="$t('CONTACT_FORM.FORM.PHONE_NUMBER.PLACEHOLDER')"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
<woot-input
|
||||||
|
v-model.trim="companyName"
|
||||||
|
class="medium-6 columns"
|
||||||
|
:label="$t('CONTACT_FORM.FORM.COMPANY_NAME.LABEL')"
|
||||||
|
:placeholder="$t('CONTACT_FORM.FORM.COMPANY_NAME.PLACEHOLDER')"
|
||||||
|
/>
|
||||||
|
<div class="medium-12 columns">
|
||||||
|
<label>
|
||||||
|
Social Profiles
|
||||||
|
</label>
|
||||||
|
<div
|
||||||
|
v-for="socialProfile in socialProfileKeys"
|
||||||
|
:key="socialProfile.key"
|
||||||
|
class="input-group"
|
||||||
|
>
|
||||||
|
<span class="input-group-label">{{ socialProfile.prefixURL }}</span>
|
||||||
|
<input
|
||||||
|
v-model="socialProfileUserNames[socialProfile.key]"
|
||||||
|
class="input-group-field"
|
||||||
|
type="text"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="modal-footer">
|
||||||
|
<div class="medium-12 columns">
|
||||||
|
<woot-submit-button
|
||||||
|
:loading="inProgress"
|
||||||
|
:button-text="$t('CONTACT_FORM.FORM.SUBMIT')"
|
||||||
|
/>
|
||||||
|
<button class="button clear" @click.prevent="onCancel">
|
||||||
|
{{ $t('CONTACT_FORM.FORM.CANCEL') }}
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</form>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
import alertMixin from 'shared/mixins/alertMixin';
|
||||||
|
import { DuplicateContactException } from 'shared/helpers/CustomErrors';
|
||||||
|
import { required } from 'vuelidate/lib/validators';
|
||||||
|
|
||||||
|
export default {
|
||||||
|
mixins: [alertMixin],
|
||||||
|
props: {
|
||||||
|
contact: {
|
||||||
|
type: Object,
|
||||||
|
default: () => ({}),
|
||||||
|
},
|
||||||
|
inProgress: {
|
||||||
|
type: Boolean,
|
||||||
|
default: false,
|
||||||
|
},
|
||||||
|
onSubmit: {
|
||||||
|
type: Function,
|
||||||
|
default: () => {},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
data() {
|
||||||
|
return {
|
||||||
|
hasADuplicateContact: false,
|
||||||
|
duplicateContact: {},
|
||||||
|
companyName: '',
|
||||||
|
description: '',
|
||||||
|
email: '',
|
||||||
|
name: '',
|
||||||
|
phoneNumber: '',
|
||||||
|
socialProfileUserNames: {
|
||||||
|
facebook: '',
|
||||||
|
twitter: '',
|
||||||
|
linkedin: '',
|
||||||
|
},
|
||||||
|
socialProfileKeys: [
|
||||||
|
{ key: 'facebook', prefixURL: 'https://facebook.com/' },
|
||||||
|
{ key: 'twitter', prefixURL: 'https://twitter.com/' },
|
||||||
|
{ key: 'linkedin', prefixURL: 'https://linkedin.com/' },
|
||||||
|
],
|
||||||
|
};
|
||||||
|
},
|
||||||
|
validations: {
|
||||||
|
name: {
|
||||||
|
required,
|
||||||
|
},
|
||||||
|
description: {},
|
||||||
|
email: {},
|
||||||
|
companyName: {},
|
||||||
|
phoneNumber: {},
|
||||||
|
bio: {},
|
||||||
|
},
|
||||||
|
|
||||||
|
watch: {
|
||||||
|
contact() {
|
||||||
|
this.setContactObject();
|
||||||
|
},
|
||||||
|
},
|
||||||
|
mounted() {
|
||||||
|
this.setContactObject();
|
||||||
|
},
|
||||||
|
methods: {
|
||||||
|
onCancel() {
|
||||||
|
this.$emit('cancel');
|
||||||
|
},
|
||||||
|
setContactObject() {
|
||||||
|
const { email: email, phone_number: phoneNumber, name } = this.contact;
|
||||||
|
const additionalAttributes = this.contact.additional_attributes || {};
|
||||||
|
|
||||||
|
this.name = name || '';
|
||||||
|
this.email = email || '';
|
||||||
|
this.phoneNumber = phoneNumber || '';
|
||||||
|
this.companyName = additionalAttributes.company_name || '';
|
||||||
|
this.description = additionalAttributes.description || '';
|
||||||
|
const {
|
||||||
|
social_profiles: socialProfiles = {},
|
||||||
|
screen_name: twitterScreenName,
|
||||||
|
} = additionalAttributes;
|
||||||
|
this.socialProfileUserNames = {
|
||||||
|
twitter: socialProfiles.twitter || twitterScreenName || '',
|
||||||
|
facebook: socialProfiles.facebook || '',
|
||||||
|
linkedin: socialProfiles.linkedin || '',
|
||||||
|
};
|
||||||
|
},
|
||||||
|
getContactObject() {
|
||||||
|
return {
|
||||||
|
id: this.contact.id,
|
||||||
|
name: this.name,
|
||||||
|
email: this.email,
|
||||||
|
phone_number: this.phoneNumber,
|
||||||
|
additional_attributes: {
|
||||||
|
...this.contact.additional_attributes,
|
||||||
|
description: this.description,
|
||||||
|
company_name: this.companyName,
|
||||||
|
social_profiles: this.socialProfileUserNames,
|
||||||
|
},
|
||||||
|
};
|
||||||
|
},
|
||||||
|
resetDuplicate() {
|
||||||
|
this.hasADuplicateContact = false;
|
||||||
|
this.duplicateContact = {};
|
||||||
|
},
|
||||||
|
async handleSubmit() {
|
||||||
|
this.resetDuplicate();
|
||||||
|
this.$v.$touch();
|
||||||
|
if (this.$v.$invalid) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
try {
|
||||||
|
await this.onSubmit(this.getContactObject());
|
||||||
|
this.showAlert(this.$t('CONTACT_FORM.SUCCESS_MESSAGE'));
|
||||||
|
} catch (error) {
|
||||||
|
if (error instanceof DuplicateContactException) {
|
||||||
|
this.hasADuplicateContact = true;
|
||||||
|
this.duplicateContact = error.data;
|
||||||
|
this.showAlert(this.$t('CONTACT_FORM.CONTACT_ALREADY_EXIST'));
|
||||||
|
} else {
|
||||||
|
this.showAlert(this.$t('CONTACT_FORM.ERROR_MESSAGE'));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
},
|
||||||
|
};
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style scoped lang="scss">
|
||||||
|
.contact--form {
|
||||||
|
padding: var(--space-normal) var(--space-large) var(--space-large);
|
||||||
|
|
||||||
|
.columns {
|
||||||
|
padding: 0 var(--space-smaller);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</style>
|
||||||
@@ -7,96 +7,23 @@
|
|||||||
"
|
"
|
||||||
:header-content="$t('EDIT_CONTACT.DESC')"
|
:header-content="$t('EDIT_CONTACT.DESC')"
|
||||||
/>
|
/>
|
||||||
<form class="edit-contact--form" @submit.prevent="onSubmit">
|
<contact-form
|
||||||
<div class="row">
|
:contact="contact"
|
||||||
<div class="medium-9 columns">
|
:in-progress="uiFlags.isUpdating"
|
||||||
<label :class="{ error: $v.name.$error }">
|
:on-submit="onSubmit"
|
||||||
{{ $t('EDIT_CONTACT.FORM.NAME.LABEL') }}
|
/>
|
||||||
<input
|
|
||||||
v-model.trim="name"
|
|
||||||
type="text"
|
|
||||||
:placeholder="$t('EDIT_CONTACT.FORM.NAME.PLACEHOLDER')"
|
|
||||||
@input="$v.name.$touch"
|
|
||||||
/>
|
|
||||||
</label>
|
|
||||||
|
|
||||||
<label :class="{ error: $v.email.$error }">
|
|
||||||
{{ $t('EDIT_CONTACT.FORM.EMAIL_ADDRESS.LABEL') }}
|
|
||||||
<input
|
|
||||||
v-model.trim="email"
|
|
||||||
type="text"
|
|
||||||
:placeholder="$t('EDIT_CONTACT.FORM.EMAIL_ADDRESS.PLACEHOLDER')"
|
|
||||||
@input="$v.email.$touch"
|
|
||||||
/>
|
|
||||||
</label>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div class="medium-12 columns">
|
|
||||||
<label :class="{ error: $v.description.$error }">
|
|
||||||
{{ $t('EDIT_CONTACT.FORM.BIO.LABEL') }}
|
|
||||||
<textarea
|
|
||||||
v-model.trim="description"
|
|
||||||
type="text"
|
|
||||||
:placeholder="$t('EDIT_CONTACT.FORM.BIO.PLACEHOLDER')"
|
|
||||||
@input="$v.description.$touch"
|
|
||||||
/>
|
|
||||||
</label>
|
|
||||||
</div>
|
|
||||||
<div class="row">
|
|
||||||
<woot-input
|
|
||||||
v-model.trim="phoneNumber"
|
|
||||||
class="medium-6 columns"
|
|
||||||
:label="$t('EDIT_CONTACT.FORM.PHONE_NUMBER.LABEL')"
|
|
||||||
:placeholder="$t('EDIT_CONTACT.FORM.PHONE_NUMBER.PLACEHOLDER')"
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
<woot-input
|
|
||||||
v-model.trim="companyName"
|
|
||||||
class="medium-6 columns"
|
|
||||||
:label="$t('EDIT_CONTACT.FORM.COMPANY_NAME.LABEL')"
|
|
||||||
:placeholder="$t('EDIT_CONTACT.FORM.COMPANY_NAME.PLACEHOLDER')"
|
|
||||||
/>
|
|
||||||
<div class="medium-12 columns">
|
|
||||||
<label>
|
|
||||||
Social Profiles
|
|
||||||
</label>
|
|
||||||
<div
|
|
||||||
v-for="socialProfile in socialProfileKeys"
|
|
||||||
:key="socialProfile.key"
|
|
||||||
class="input-group"
|
|
||||||
>
|
|
||||||
<span class="input-group-label">{{ socialProfile.prefixURL }}</span>
|
|
||||||
<input
|
|
||||||
v-model="socialProfileUserNames[socialProfile.key]"
|
|
||||||
class="input-group-field"
|
|
||||||
type="text"
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div class="modal-footer">
|
|
||||||
<div class="medium-12 columns">
|
|
||||||
<woot-submit-button
|
|
||||||
:loading="uiFlags.isUpdating"
|
|
||||||
:button-text="$t('EDIT_CONTACT.FORM.SUBMIT')"
|
|
||||||
/>
|
|
||||||
<button class="button clear" @click.prevent="onCancel">
|
|
||||||
{{ $t('EDIT_CONTACT.FORM.CANCEL') }}
|
|
||||||
</button>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</form>
|
|
||||||
</div>
|
</div>
|
||||||
</woot-modal>
|
</woot-modal>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
import alertMixin from 'shared/mixins/alertMixin';
|
|
||||||
import { DuplicateContactException } from 'shared/helpers/CustomErrors';
|
|
||||||
import { required } from 'vuelidate/lib/validators';
|
|
||||||
import { mapGetters } from 'vuex';
|
import { mapGetters } from 'vuex';
|
||||||
|
import ContactForm from './ContactForm';
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
mixins: [alertMixin],
|
components: {
|
||||||
|
ContactForm,
|
||||||
|
},
|
||||||
props: {
|
props: {
|
||||||
show: {
|
show: {
|
||||||
type: Boolean,
|
type: Boolean,
|
||||||
@@ -107,120 +34,20 @@ export default {
|
|||||||
default: () => ({}),
|
default: () => ({}),
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
data() {
|
|
||||||
return {
|
|
||||||
hasADuplicateContact: false,
|
|
||||||
duplicateContact: {},
|
|
||||||
companyName: '',
|
|
||||||
description: '',
|
|
||||||
email: '',
|
|
||||||
name: '',
|
|
||||||
phoneNumber: '',
|
|
||||||
socialProfileUserNames: {
|
|
||||||
facebook: '',
|
|
||||||
twitter: '',
|
|
||||||
linkedin: '',
|
|
||||||
},
|
|
||||||
socialProfileKeys: [
|
|
||||||
{ key: 'facebook', prefixURL: 'https://facebook.com/' },
|
|
||||||
{ key: 'twitter', prefixURL: 'https://twitter.com/' },
|
|
||||||
{ key: 'linkedin', prefixURL: 'https://linkedin.com/' },
|
|
||||||
],
|
|
||||||
};
|
|
||||||
},
|
|
||||||
validations: {
|
|
||||||
name: {
|
|
||||||
required,
|
|
||||||
},
|
|
||||||
description: {},
|
|
||||||
email: {},
|
|
||||||
companyName: {},
|
|
||||||
phoneNumber: {},
|
|
||||||
bio: {},
|
|
||||||
},
|
|
||||||
computed: {
|
computed: {
|
||||||
...mapGetters({
|
...mapGetters({
|
||||||
uiFlags: 'contacts/getUIFlags',
|
uiFlags: 'contacts/getUIFlags',
|
||||||
}),
|
}),
|
||||||
},
|
},
|
||||||
watch: {
|
|
||||||
contact() {
|
|
||||||
this.setContactObject();
|
|
||||||
},
|
|
||||||
},
|
|
||||||
mounted() {
|
|
||||||
this.setContactObject();
|
|
||||||
},
|
|
||||||
methods: {
|
methods: {
|
||||||
onCancel() {
|
onCancel() {
|
||||||
this.$emit('cancel');
|
this.$emit('cancel');
|
||||||
},
|
},
|
||||||
setContactObject() {
|
async onSubmit(contactItem) {
|
||||||
const { email: email, phone_number: phoneNumber, name } = this.contact;
|
await this.$store.dispatch('contacts/update', contactItem);
|
||||||
const additionalAttributes = this.contact.additional_attributes || {};
|
|
||||||
|
|
||||||
this.name = name || '';
|
|
||||||
this.email = email || '';
|
|
||||||
this.phoneNumber = phoneNumber || '';
|
|
||||||
this.companyName = additionalAttributes.company_name || '';
|
|
||||||
this.description = additionalAttributes.description || '';
|
|
||||||
const {
|
|
||||||
social_profiles: socialProfiles = {},
|
|
||||||
screen_name: twitterScreenName,
|
|
||||||
} = additionalAttributes;
|
|
||||||
this.socialProfileUserNames = {
|
|
||||||
twitter: socialProfiles.twitter || twitterScreenName || '',
|
|
||||||
facebook: socialProfiles.facebook || '',
|
|
||||||
linkedin: socialProfiles.linkedin || '',
|
|
||||||
};
|
|
||||||
},
|
|
||||||
getContactObject() {
|
|
||||||
return {
|
|
||||||
id: this.contact.id,
|
|
||||||
name: this.name,
|
|
||||||
email: this.email,
|
|
||||||
phone_number: this.phoneNumber,
|
|
||||||
additional_attributes: {
|
|
||||||
...this.contact.additional_attributes,
|
|
||||||
description: this.description,
|
|
||||||
company_name: this.companyName,
|
|
||||||
social_profiles: this.socialProfileUserNames,
|
|
||||||
},
|
|
||||||
};
|
|
||||||
},
|
|
||||||
resetDuplicate() {
|
|
||||||
this.hasADuplicateContact = false;
|
|
||||||
this.duplicateContact = {};
|
|
||||||
},
|
|
||||||
async onSubmit() {
|
|
||||||
this.resetDuplicate();
|
|
||||||
this.$v.$touch();
|
|
||||||
if (this.$v.$invalid) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
try {
|
|
||||||
await this.$store.dispatch('contacts/update', this.getContactObject());
|
|
||||||
this.showAlert(this.$t('EDIT_CONTACT.SUCCESS_MESSAGE'));
|
|
||||||
} catch (error) {
|
|
||||||
if (error instanceof DuplicateContactException) {
|
|
||||||
this.hasADuplicateContact = true;
|
|
||||||
this.duplicateContact = error.data;
|
|
||||||
this.showAlert(this.$t('EDIT_CONTACT.CONTACT_ALREADY_EXIST'));
|
|
||||||
} else {
|
|
||||||
this.showAlert(this.$t('EDIT_CONTACT.ERROR_MESSAGE'));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style scoped lang="scss">
|
|
||||||
.edit-contact--form {
|
|
||||||
padding: var(--space-normal) var(--space-large) var(--space-large);
|
|
||||||
|
|
||||||
.columns {
|
|
||||||
padding: 0 var(--space-smaller);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
</style>
|
|
||||||
|
|||||||
Reference in New Issue
Block a user