chore: Refactor Edit contact modal to separate form (#1805)

This commit is contained in:
Nithin David Thomas 2021-02-19 00:10:32 +05:30 committed by GitHub
parent 6bbeb005f5
commit eec90a1319
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
4 changed files with 232 additions and 188 deletions

View file

@ -43,7 +43,9 @@
"EDIT_CONTACT": {
"BUTTON_LABEL": "Edit Contact",
"TITLE": "Edit contact",
"DESC": "Edit contact details",
"DESC": "Edit contact details"
},
"CONTACT_FORM": {
"FORM": {
"SUBMIT": "Submit",
"CANCEL": "Cancel",

View file

@ -7,7 +7,7 @@
<div v-if="browser.browser_name" class="conversation--details">
<contact-details-item
v-if="location"
:title="$t('EDIT_CONTACT.FORM.LOCATION.LABEL')"
:title="$t('CONTACT_FORM.FORM.LOCATION.LABEL')"
:value="location"
icon="ion-map"
emoji="📍"

View file

@ -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>

View file

@ -7,96 +7,23 @@
"
:header-content="$t('EDIT_CONTACT.DESC')"
/>
<form class="edit-contact--form" @submit.prevent="onSubmit">
<div class="row">
<div class="medium-9 columns">
<label :class="{ error: $v.name.$error }">
{{ $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>
<contact-form
:contact="contact"
:in-progress="uiFlags.isUpdating"
:on-submit="onSubmit"
/>
</div>
</woot-modal>
</template>
<script>
import alertMixin from 'shared/mixins/alertMixin';
import { DuplicateContactException } from 'shared/helpers/CustomErrors';
import { required } from 'vuelidate/lib/validators';
import { mapGetters } from 'vuex';
import ContactForm from './ContactForm';
export default {
mixins: [alertMixin],
components: {
ContactForm,
},
props: {
show: {
type: Boolean,
@ -107,120 +34,20 @@ export 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: {
...mapGetters({
uiFlags: 'contacts/getUIFlags',
}),
},
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 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'));
}
}
async onSubmit(contactItem) {
await this.$store.dispatch('contacts/update', contactItem);
},
},
};
</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>