feat: edit contact modal confirm discard (#199)
* feat(contact): add confirmation dialog for discarding unsaved changes in edit contact modal * chore: add GitHub Copilot instructions for project guidelines * feat(contact): update confirmation dialog logic for discarding unsaved changes in edit contact modal
This commit is contained in:
parent
b1aaf58097
commit
4ca0ef22c0
8
.github/copilot-instructions.md
vendored
Normal file
8
.github/copilot-instructions.md
vendored
Normal file
@ -0,0 +1,8 @@
|
||||
# GitHub Copilot Instructions
|
||||
|
||||
- Always include pt-BR translations for any new text added to the project.
|
||||
- fazer.ai is always styled as-is, with a dot and lowercase letters. Never use Fazer.ai
|
||||
- Always check if adding specs is necessary when modifying code.
|
||||
- Evaluate if specs added are actually needed and not redundant. Specs should not be for documentation purposes only, they should cover expected behavior.
|
||||
- Always evaluate if frontend changes are needed when modifying backend code, and vice versa.
|
||||
- NEVER use `--` in `pnpm test -- <file>`. Just do `pnpm test <file>` directly
|
||||
@ -61,7 +61,13 @@
|
||||
"EDIT_CONTACT": {
|
||||
"BUTTON_LABEL": "Edit Contact",
|
||||
"TITLE": "Edit contact",
|
||||
"DESC": "Edit contact details"
|
||||
"DESC": "Edit contact details",
|
||||
"CONFIRM_DISCARD": {
|
||||
"TITLE": "Discard changes?",
|
||||
"MESSAGE": "You have unsaved changes. Are you sure you want to discard them?",
|
||||
"YES": "Discard",
|
||||
"NO": "Keep editing"
|
||||
}
|
||||
},
|
||||
"DELETE_CONTACT": {
|
||||
"BUTTON_LABEL": "Delete Contact",
|
||||
|
||||
@ -61,7 +61,13 @@
|
||||
"EDIT_CONTACT": {
|
||||
"BUTTON_LABEL": "Editar Contato",
|
||||
"TITLE": "Editar contato",
|
||||
"DESC": "Alterar detalhes do contato"
|
||||
"DESC": "Alterar detalhes do contato",
|
||||
"CONFIRM_DISCARD": {
|
||||
"TITLE": "Descartar alterações?",
|
||||
"MESSAGE": "Você tem alterações não salvas. Tem certeza de que deseja descartá-las?",
|
||||
"YES": "Descartar",
|
||||
"NO": "Continuar editando"
|
||||
}
|
||||
},
|
||||
"DELETE_CONTACT": {
|
||||
"BUTTON_LABEL": "Excluir Contato",
|
||||
|
||||
@ -64,6 +64,7 @@ export default {
|
||||
{ key: 'github', prefixURL: 'https://github.com/' },
|
||||
{ key: 'tiktok', prefixURL: 'https://tiktok.com/@' },
|
||||
],
|
||||
initialData: null,
|
||||
};
|
||||
},
|
||||
validations: {
|
||||
@ -100,8 +101,27 @@ export default {
|
||||
}
|
||||
return '';
|
||||
},
|
||||
hasUnsavedChanges() {
|
||||
if (!this.initialData) return false;
|
||||
const socialProfilesChanged = this.socialProfileKeys.some(
|
||||
({ key }) =>
|
||||
(this.socialProfileUserNames[key] || '') !==
|
||||
(this.initialData.socialProfileUserNames[key] || '')
|
||||
);
|
||||
return (
|
||||
this.name !== this.initialData.name ||
|
||||
this.email !== this.initialData.email ||
|
||||
this.phoneNumber !== this.initialData.phoneNumber ||
|
||||
this.companyName !== this.initialData.companyName ||
|
||||
this.description !== this.initialData.description ||
|
||||
this.city !== this.initialData.city ||
|
||||
(this.country?.id || '') !== (this.initialData.countryId || '') ||
|
||||
this.avatarFile !== null ||
|
||||
socialProfilesChanged
|
||||
);
|
||||
},
|
||||
setPhoneNumber() {
|
||||
if (this.parsePhoneNumber && this.parsePhoneNumber.countryCallingCode) {
|
||||
if (this.parsePhoneNumber?.countryCallingCode) {
|
||||
return this.phoneNumber;
|
||||
}
|
||||
if (this.phoneNumber === '' && this.activeDialCode !== '') {
|
||||
@ -175,6 +195,16 @@ export default {
|
||||
github: socialProfiles.github || '',
|
||||
instagram: socialProfiles.instagram || '',
|
||||
};
|
||||
this.initialData = {
|
||||
name: this.name,
|
||||
email: this.email,
|
||||
phoneNumber: this.phoneNumber,
|
||||
companyName: this.companyName,
|
||||
description: this.description,
|
||||
city: this.city,
|
||||
countryId: this.country.id,
|
||||
socialProfileUserNames: { ...this.socialProfileUserNames },
|
||||
};
|
||||
},
|
||||
getContactObject() {
|
||||
if (this.country === null) {
|
||||
@ -253,7 +283,7 @@ export default {
|
||||
},
|
||||
async handleAvatarDelete() {
|
||||
try {
|
||||
if (this.contact && this.contact.id) {
|
||||
if (this.contact?.id) {
|
||||
await this.$store.dispatch('contacts/deleteAvatar', this.contact.id);
|
||||
useAlert(this.$t('CONTACT_FORM.DELETE_AVATAR.API.SUCCESS_MESSAGE'));
|
||||
}
|
||||
|
||||
@ -32,7 +32,15 @@ export default {
|
||||
},
|
||||
|
||||
methods: {
|
||||
onCancel() {
|
||||
async onClose() {
|
||||
const hasChanges = this.$refs.contactForm?.hasUnsavedChanges;
|
||||
if (hasChanges) {
|
||||
const shouldDiscard =
|
||||
await this.$refs.confirmDiscardDialog.showConfirmation();
|
||||
if (!shouldDiscard) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
this.$emit('cancel');
|
||||
},
|
||||
onSuccess() {
|
||||
@ -52,7 +60,7 @@ export default {
|
||||
<template>
|
||||
<woot-modal
|
||||
v-model:show="localShow"
|
||||
:on-close="onCancel"
|
||||
:on-close="onClose"
|
||||
modal-type="right-aligned"
|
||||
>
|
||||
<div class="flex flex-col h-auto overflow-auto">
|
||||
@ -63,12 +71,20 @@ export default {
|
||||
:header-content="$t('EDIT_CONTACT.DESC')"
|
||||
/>
|
||||
<ContactForm
|
||||
ref="contactForm"
|
||||
:contact="contact"
|
||||
:in-progress="uiFlags.isUpdating"
|
||||
:on-submit="onSubmit"
|
||||
@success="onSuccess"
|
||||
@cancel="onCancel"
|
||||
@cancel="onClose"
|
||||
/>
|
||||
</div>
|
||||
</woot-modal>
|
||||
<woot-confirm-modal
|
||||
ref="confirmDiscardDialog"
|
||||
:title="$t('EDIT_CONTACT.CONFIRM_DISCARD.TITLE')"
|
||||
:description="$t('EDIT_CONTACT.CONFIRM_DISCARD.MESSAGE')"
|
||||
:confirm-label="$t('EDIT_CONTACT.CONFIRM_DISCARD.YES')"
|
||||
:cancel-label="$t('EDIT_CONTACT.CONFIRM_DISCARD.NO')"
|
||||
/>
|
||||
</template>
|
||||
|
||||
Loading…
Reference in New Issue
Block a user