Skip to content

Commit

Permalink
chore: add fields validations
Browse files Browse the repository at this point in the history
  • Loading branch information
dougfabris committed Oct 15, 2024
1 parent 6d91d9e commit 7a13b75
Show file tree
Hide file tree
Showing 3 changed files with 25 additions and 32 deletions.
Original file line number Diff line number Diff line change
@@ -1,14 +1,12 @@
import type { ILivechatContact, Serialized } from '@rocket.chat/core-typings';
import { Box, IconButton, Tabs, TabsItem } from '@rocket.chat/fuselage';
import { UserAvatar } from '@rocket.chat/ui-avatar';
// import type { RouteName } from '@rocket.chat/ui-contexts';
import { useTranslation, useEndpoint, usePermission, useRouter, useRouteParameter } from '@rocket.chat/ui-contexts';
import { useQuery } from '@tanstack/react-query';
import React from 'react';

import { ContextualbarHeader, ContextualbarIcon, ContextualbarTitle, ContextualbarClose } from '../../../../components/Contextualbar';
import { useFormatDate } from '../../../../hooks/useFormatDate';
// import { FormSkeleton } from '../directory/components/FormSkeleton';
import { useContactRoute } from '../../hooks/useContactRoute';
import ContactInfoChannels from '../tabs/ContactInfoChannels';
import ContactInfoDetails from '../tabs/ContactInfoDetails';
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,6 @@ import React from 'react';

import { ContextualbarSkeleton } from '../../../../components/Contextualbar';
import ContactInfo from './ContactInfo';
// import { FormSkeleton } from '../directory/components/FormSkeleton';

type ContactInfoWithDataProps = {
id: string;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -71,7 +71,7 @@ const EditContactInfo = ({ id, contactData, onClose, onCancel }: ContactNewEditP

const canViewCustomFields = hasAtLeastOnePermission(['view-livechat-room-customfields', 'edit-livechat-room-customfields']);

const getContactBy = useEndpoint('GET', '/v1/omnichannel/contact.search');
const getContact = useEndpoint('GET', '/v1/omnichannel/contacts.get');
const createContact = useEndpoint('POST', '/v1/omnichannel/contacts');
const updateContact = useEndpoint('POST', '/v1/omnichannel/contacts.update');

Expand All @@ -85,11 +85,11 @@ const EditContactInfo = ({ id, contactData, onClose, onCancel }: ContactNewEditP
const {
formState: { errors, isSubmitting },
control,
watch,
handleSubmit,
setError,
} = useForm<ContactFormData>({
mode: 'onChange',
reValidateMode: 'onChange',
mode: 'onBlur',
reValidateMode: 'onBlur',
defaultValues: initialValue,
});

Expand All @@ -111,40 +111,30 @@ const EditContactInfo = ({ id, contactData, onClose, onCancel }: ContactNewEditP
name: 'phones',
});

const validateEmailFormat = (email: string): boolean | string => {
if (!email || email === initialValue.email) {
return true;
}
const { emails, phones } = watch();

const validateEmailFormat = async (emailValue: string) => {
const currentEmails = emails.map(({ address }) => address);
const isDuplicated = currentEmails.filter((email) => email === emailValue).length > 1;

if (!validateEmail(email)) {
if (!validateEmail(emailValue)) {
return t('error-invalid-email-address');
}

return true;
const { contact } = await getContact({ email: emailValue });
return (!contact || contact._id === id) && !isDuplicated ? true : t('Email_already_exists');
};

const validateContactField = async (name: 'phone' | 'email', value: string, optional = true) => {
if ((optional && !value) || value === initialValue[name]) {
return true;
}
const validatePhone = async (phoneValue: string) => {
const currentPhones = phones.map(({ phoneNumber }) => phoneNumber);
const isDuplicated = currentPhones.filter((phone) => phone === phoneValue).length > 1;

const query = { [name]: value } as Record<'phone' | 'email', string>;
const { contact } = await getContactBy(query);
return !contact || contact._id === id;
const { contact } = await getContact({ phone: phoneValue });
return (!contact || contact._id === id) && !isDuplicated ? true : t('Phone_already_exists');
};

const validateName = (v: string): string | boolean => (!v.trim() ? t('Required_field', { field: t('Name') }) : true);

const validateAsync = async ({ phone = '', email = '' } = {}) => {
const isEmailValid = await validateContactField('email', email);
const isPhoneValid = await validateContactField('phone', phone);

!isEmailValid && setError('email', { message: t('Email_already_exists') });
!isPhoneValid && setError('phone', { message: t('Phone_already_exists') });

return isEmailValid && isPhoneValid;
};

const handleSave = async (data: ContactFormData): Promise<void> => {
const { name, phones, emails, customFields, contactManager } = data;

Expand Down Expand Up @@ -212,7 +202,10 @@ const EditContactInfo = ({ id, contactData, onClose, onCancel }: ContactNewEditP
<Controller
name={`emails.${index}.address`}
control={control}
rules={{ required: t('The_field_is_required', t('Email')), validate: validateEmailFormat }}
rules={{
required: t('Required_field', { field: t('Email') }),
validate: validateEmailFormat,
}}
render={({ field }) => <TextInput {...field} error={errors.emails?.[index]?.address?.message} />}
/>
<IconButton small onClick={() => removeEmail(index)} mis={8} icon='trash' />
Expand All @@ -232,7 +225,10 @@ const EditContactInfo = ({ id, contactData, onClose, onCancel }: ContactNewEditP
<Controller
name={`phones.${index}.phoneNumber`}
control={control}
rules={{ required: t('The_field_is_required', t('Phone')) }}
rules={{
required: t('Required_field', { field: t('Phone') }),
validate: validatePhone,
}}
render={({ field }) => <TextInput {...field} error={errors.phones?.[index]?.message} />}
/>
<IconButton small onClick={() => removePhone(index)} mis={8} icon='trash' />
Expand Down

0 comments on commit 7a13b75

Please sign in to comment.