diff --git a/pages/accountLists/[accountListId]/tools/fix/phoneNumbers/[[...contactId]].page.test.tsx b/pages/accountLists/[accountListId]/tools/fix/phoneNumbers/[[...contactId]].page.test.tsx
index 23bae70e9..109d6806c 100644
--- a/pages/accountLists/[accountListId]/tools/fix/phoneNumbers/[[...contactId]].page.test.tsx
+++ b/pages/accountLists/[accountListId]/tools/fix/phoneNumbers/[[...contactId]].page.test.tsx
@@ -87,11 +87,4 @@ describe('FixPhoneNumbersPage', () => {
);
});
});
-
- it('should show errors', async () => {
- const { findAllByRole, findByText } = render();
-
- userEvent.clear((await findAllByRole('textbox'))[0]);
- expect(await findByText('This field is required')).toBeInTheDocument();
- });
});
diff --git a/src/components/Tool/FixEmailAddresses/FixEmailAddressPerson/FixEmailAddressPerson.tsx b/src/components/Tool/FixEmailAddresses/FixEmailAddressPerson/FixEmailAddressPerson.tsx
index 2274f5e7b..2fca8126e 100644
--- a/src/components/Tool/FixEmailAddresses/FixEmailAddressPerson/FixEmailAddressPerson.tsx
+++ b/src/components/Tool/FixEmailAddresses/FixEmailAddressPerson/FixEmailAddressPerson.tsx
@@ -544,10 +544,10 @@ export const FixEmailAddressPerson: React.FC = ({
title={t('Confirm')}
isOpen={true}
message={
-
+ <>
{t('Are you sure you wish to delete this email address:')}{' '}
{emailToDelete?.email.email}
-
+ >
}
mutation={handleDelete}
handleClose={handleDeleteEmailModalClose}
diff --git a/src/components/Tool/FixPhoneNumbers/Contact.test.tsx b/src/components/Tool/FixPhoneNumbers/Contact.test.tsx
index b59b0b5e8..660e2de53 100644
--- a/src/components/Tool/FixPhoneNumbers/Contact.test.tsx
+++ b/src/components/Tool/FixPhoneNumbers/Contact.test.tsx
@@ -1,154 +1,323 @@
import React from 'react';
import { ThemeProvider } from '@mui/material/styles';
import userEvent from '@testing-library/user-event';
+import { ApolloErgonoMockMap } from 'graphql-ergonomock';
+import { DateTime } from 'luxon';
+import { SnackbarProvider } from 'notistack';
import TestWrapper from '__tests__/util/TestWrapper';
+import { GqlMockedProvider } from '__tests__/util/graphqlMocking';
import { render, waitFor } from '__tests__/util/testingLibraryReactMock';
-import theme from '../../../theme';
-import Contact from './Contact';
+import { AppSettingsProvider } from 'src/components/common/AppSettings/AppSettingsProvider';
+import theme from 'src/theme';
+import Contact, { PhoneNumberData } from './Contact';
+import { mockInvalidPhoneNumbersResponse } from './FixPhoneNumbersMocks';
+import {
+ GetInvalidPhoneNumbersQuery,
+ PersonInvalidNumberFragment,
+} from './GetInvalidPhoneNumbers.generated';
+import { UpdatePhoneNumberMutation } from './UpdateInvalidPhoneNumbers.generated';
-const testData = {
- name: 'Test Contact',
+const accountListId = 'accountListId';
+const person: PersonInvalidNumberFragment = {
+ id: 'contactTestId',
firstName: 'Test',
lastName: 'Contact',
- avatar: 'https://www.example.com',
- id: 'testid',
- contactId: 'testid',
- isNewPhoneNumber: false,
- newPhoneNumber: '',
+ contactId: 'contactTestId',
+ avatar: '',
phoneNumbers: {
nodes: [
{
- id: '123',
- updatedAt: '2019-12-03',
- number: '3533895895',
+ id: 'number1',
+ source: 'DonorHub',
+ updatedAt: DateTime.fromISO('2021-06-21').toString(),
+ number: '123456',
primary: true,
- source: 'MPDX',
},
{
- id: '1234',
- updatedAt: '2019-12-04',
- number: '623533895895',
- primary: false,
+ id: 'number2',
source: 'MPDX',
+ updatedAt: DateTime.fromISO('2021-06-22').toString(),
+ number: '78910',
+ primary: false,
},
],
},
};
const setContactFocus = jest.fn();
-const handleDeleteModalOpenMock = jest.fn();
-const updatePhoneNumber = jest.fn();
-const setValuesMock = jest.fn();
+const mutationSpy = jest.fn();
+const handleSingleConfirm = jest.fn();
+const mockEnqueue = jest.fn();
+
+jest.mock('notistack', () => ({
+ // eslint-disable-next-line @typescript-eslint/ban-ts-comment
+ // @ts-ignore
+ ...jest.requireActual('notistack'),
+ useSnackbar: () => {
+ return {
+ enqueueSnackbar: mockEnqueue,
+ };
+ },
+}));
+
+const defaultDataState = {
+ contactTestId: {
+ phoneNumbers: person.phoneNumbers.nodes,
+ },
+} as { [key: string]: PhoneNumberData };
+
+type TestComponentProps = {
+ mocks?: ApolloErgonoMockMap;
+ dataState?: { [key: string]: PhoneNumberData };
+};
+
+const TestComponent = ({
+ mocks,
+ dataState = defaultDataState,
+}: TestComponentProps) => {
+ const handleChangeMock = jest.fn();
+ const handleChangePrimaryMock = jest.fn();
-const errors = {};
+ return (
+
+
+
+
+
+ mocks={mocks}
+ onCall={mutationSpy}
+ >
+
+
+
+
+
+
+ );
+};
-describe('FixPhoneNumbers-Contact', () => {
+describe('Fix PhoneNumber Contact', () => {
it('default', () => {
const { getByText, getByTestId, getByDisplayValue } = render(
-
-
-
-
- ,
+ ,
);
- expect(getByText(testData.name)).toBeInTheDocument();
- expect(getByTestId('textfield-testid-0')).toBeInTheDocument();
- expect(getByDisplayValue('3533895895')).toBeInTheDocument();
- expect(getByTestId('textfield-testid-1')).toBeInTheDocument();
- expect(getByDisplayValue('623533895895')).toBeInTheDocument();
+ expect(
+ getByText(`${person.firstName} ${person.lastName}`),
+ ).toBeInTheDocument();
+ expect(getByText('DonorHub (6/21/2021)')).toBeInTheDocument();
+ expect(getByTestId('textfield-contactTestId-number1')).toBeInTheDocument();
+ expect(getByDisplayValue('123456')).toBeInTheDocument();
+ expect(getByText('MPDX (6/22/2021)')).toBeInTheDocument();
+ expect(getByTestId('textfield-contactTestId-number2')).toBeInTheDocument();
+ expect(getByDisplayValue('78910')).toBeInTheDocument();
});
- it('input reset after adding an phone number', async () => {
- const { getByTestId } = render(
-
-
-
-
- ,
+ it('input reset after adding a phone number', async () => {
+ const { getByTestId, getByLabelText } = render(
+ ,
);
- const addInput = getByTestId(
- 'addNewNumberInput-testid',
- ) as HTMLInputElement;
- const addButton = getByTestId('addButton-testid');
-
- userEvent.type(addInput, '1');
+ const addInput = getByLabelText('New Phone Number');
+ const addButton = getByTestId('addButton-contactTestId');
+ userEvent.type(addInput, '000');
+ expect(addInput).toHaveValue('000');
+ userEvent.click(addButton);
await waitFor(() => {
- expect(setValuesMock).toHaveBeenCalledWith({
- people: [
- {
- ...testData,
- isNewPhoneNumber: true,
- newPhoneNumber: '1',
- },
- ],
+ expect(addInput).toHaveValue('');
+ });
+ });
+
+ describe('validation', () => {
+ it('should show an error message if there is no number', async () => {
+ const { getByLabelText, getByTestId, findByText } = render(
+ ,
+ );
+
+ const addInput = getByLabelText('New Phone Number');
+ userEvent.click(addInput);
+ userEvent.tab();
+
+ const addButton = getByTestId('addButton-contactTestId');
+ expect(addButton).toBeDisabled();
+
+ expect(
+ await findByText('This field is not a valid phone number'),
+ ).toBeVisible();
+ });
+
+ it('should show an error message if there is an invalid number', async () => {
+ const { getByLabelText, getByTestId, getByText } = render(
+ ,
+ );
+
+ const addInput = getByLabelText('New Phone Number');
+ userEvent.type(addInput, 'ab');
+ userEvent.tab();
+
+ const addButton = getByTestId('addButton-contactTestId');
+ await waitFor(() => {
+ expect(addButton).toBeDisabled();
});
+
+ expect(getByText('This field is not a valid phone number')).toBeVisible();
});
- userEvent.click(addButton);
- expect(addInput.value).toBe('');
- });
+ it('should not disable the add button', async () => {
+ const { getByLabelText, getByTestId } = render(
+ ,
+ );
- it('should call mock functions', async () => {
- const { getByTestId } = render(
-
-
-
-
- ,
- );
+ const addInput = getByLabelText('New Phone Number');
+ userEvent.type(addInput, '123');
+ userEvent.tab();
- const firstInput = getByTestId('textfield-testid-0') as HTMLInputElement;
- expect(firstInput.value).toBe('3533895895');
- userEvent.type(firstInput, '1');
+ const addButton = getByTestId('addButton-contactTestId');
+ await waitFor(() => {
+ expect(addButton).not.toBeDisabled();
+ });
+ });
- await waitFor(() => {
- expect(setValuesMock).toHaveBeenCalledWith({
- people: [
- {
- ...testData,
- phoneNumbers: {
- nodes: [
- { ...testData.phoneNumbers.nodes[0], number: '35338958951' },
- testData.phoneNumbers.nodes[1],
+ it('should show delete confirmation', async () => {
+ const { getByTestId, getByRole } = render(
+ ,
+ );
+ const deleteButton = getByTestId('delete-contactTestId-number2');
+ userEvent.click(deleteButton);
+ expect(getByRole('heading', { name: 'Confirm' })).toBeInTheDocument();
+ userEvent.click(getByRole('button', { name: 'Yes' }));
+
+ const { id, number } = person.phoneNumbers.nodes[1];
+
+ await waitFor(() => {
+ expect(mutationSpy.mock.lastCall[0].operation.operationName).toEqual(
+ 'UpdatePhoneNumber',
+ );
+ expect(mutationSpy.mock.lastCall[0].operation.variables).toEqual({
+ input: {
+ accountListId,
+ attributes: {
+ id: person.id,
+ phoneNumbers: [
+ {
+ id,
+ destroy: true,
+ },
],
},
},
- ],
+ });
+ });
+
+ await waitFor(() =>
+ expect(mockEnqueue).toHaveBeenCalledWith(
+ `Successfully deleted phone number ${number}`,
+ {
+ variant: 'success',
+ },
+ ),
+ );
+ });
+ });
+
+ describe('confirm button', () => {
+ it('should not disable confirm button if there is exactly one primary number', async () => {
+ const { getByRole, queryByRole } = render();
+
+ expect(handleSingleConfirm).toHaveBeenCalledTimes(0);
+
+ await waitFor(() => {
+ expect(queryByRole('loading')).not.toBeInTheDocument();
+ expect(getByRole('button', { name: 'Confirm' })).not.toBeDisabled();
});
+
+ userEvent.click(getByRole('button', { name: 'Confirm' }));
+
+ expect(handleSingleConfirm).toHaveBeenCalledTimes(1);
+ });
+ });
+ describe('submit button', () => {
+ it('should submit form without errors', async () => {
+ const { getByTestId } = render();
+ const textField = getByTestId('textfield-contactTestId-number2');
+ userEvent.type(textField, '123');
+ expect(textField).toHaveValue('78910123');
+ });
+ });
+
+ it('should submit form with errors', async () => {
+ const { getByTestId, getAllByTestId } = render();
+ const textInput = getByTestId('textfield-contactTestId-number2');
+ userEvent.clear(textInput);
+ expect(textInput).toHaveValue('');
+ userEvent.type(textInput, 'p');
+ expect(textInput).toHaveValue('p');
+ userEvent.click(textInput);
+
+ await waitFor(() => {
+ expect(getAllByTestId('statusSelectError')[1]).toHaveTextContent(
+ 'This field is not a valid phone number',
+ );
});
- userEvent.click(getByTestId('delete-testid-1'));
- expect(handleDeleteModalOpenMock).toHaveBeenCalled();
- userEvent.click(getByTestId(`confirmButton-${testData.id}`));
- expect(updatePhoneNumber).toHaveBeenCalled();
});
});
diff --git a/src/components/Tool/FixPhoneNumbers/Contact.tsx b/src/components/Tool/FixPhoneNumbers/Contact.tsx
index c6af90bb0..f403693df 100644
--- a/src/components/Tool/FixPhoneNumbers/Contact.tsx
+++ b/src/components/Tool/FixPhoneNumbers/Contact.tsx
@@ -1,6 +1,6 @@
-import React, { Fragment } from 'react';
+import React, { ReactElement, useMemo, useState } from 'react';
import styled from '@emotion/styled';
-import { mdiCheckboxMarkedCircle, mdiDelete, mdiLock, mdiPlus } from '@mdi/js';
+import { mdiCheckboxMarkedCircle, mdiDelete, mdiLock } from '@mdi/js';
import { Icon } from '@mdi/react';
import StarIcon from '@mui/icons-material/Star';
import StarOutlineIcon from '@mui/icons-material/StarOutline';
@@ -22,21 +22,21 @@ import {
Typography,
} from '@mui/material';
import clsx from 'clsx';
-import { FormikErrors } from 'formik';
+import { Formik } from 'formik';
import { DateTime } from 'luxon';
+import { useSnackbar } from 'notistack';
import { useTranslation } from 'react-i18next';
import { makeStyles } from 'tss-react/mui';
+import * as yup from 'yup';
import { SetContactFocus } from 'pages/accountLists/[accountListId]/tools/useToolsHelper';
-import { TabKey } from 'src/components/Contacts/ContactDetails/ContactDetails';
+import { Confirmation } from 'src/components/common/Modal/Confirmation/Confirmation';
import useGetAppSettings from 'src/hooks/useGetAppSettings';
import { useLocale } from 'src/hooks/useLocale';
import { dateFormatShort } from 'src/lib/intlFormat';
import theme from '../../../theme';
-import { FormValues, FormValuesPerson } from './FixPhoneNumbers';
-import {
- PersonInvalidNumberFragment,
- PersonPhoneNumberFragment,
-} from './GetInvalidPhoneNumbers.generated';
+import { PersonInvalidNumberFragment } from './GetInvalidPhoneNumbers.generated';
+import PhoneValidationForm from './PhoneNumberValidationForm';
+import { useUpdatePhoneNumberMutation } from './UpdateInvalidPhoneNumbers.generated';
const useStyles = makeStyles()((theme: Theme) => ({
left: {},
@@ -96,12 +96,20 @@ const useStyles = makeStyles()((theme: Theme) => ({
paddingB2: {
paddingBottom: theme.spacing(1),
},
+ phoneNumberContainer: {
+ width: '100%',
+ },
hoverHighlight: {
'&:hover': {
color: theme.palette.mpdxBlue.main,
cursor: 'pointer',
},
},
+ ContactIconContainer: {
+ margin: theme.spacing(0, 1),
+ width: theme.spacing(4),
+ height: theme.spacing(4),
+ },
}));
const ContactHeader = styled(CardHeader)(() => ({
@@ -115,465 +123,482 @@ const ContactAvatar = styled(Avatar)(() => ({
height: theme.spacing(4),
}));
+export interface PhoneNumber {
+ id: string;
+ number: string;
+ primary: boolean;
+ source: string;
+ updatedAt: string;
+}
+
+export interface PhoneNumberData {
+ phoneNumbers: PhoneNumber[];
+}
+
+interface NumberToDelete {
+ personId: string;
+ phoneNumber: PhoneNumber;
+}
+
interface Props {
- handleDelete: (
- personIndex: number,
+ person: PersonInvalidNumberFragment;
+ handleChange: (
+ personId: string,
numberIndex: number,
- phoneNumber: string,
+ newNumber: string,
) => void;
setContactFocus: SetContactFocus;
- handleUpdate: (
- values: FormValues,
- personId: string,
- personIndex: number,
+ handleSingleConfirm: (
+ person: PersonInvalidNumberFragment,
+ numbers: PhoneNumber[],
) => void;
- errors: FormikErrors;
- setValues: (values: FormValues) => void;
- values: FormValues;
- person: PersonInvalidNumberFragment;
- personIndex: number;
+ dataState: { [key: string]: PhoneNumberData };
+ handleChangePrimary: (personId: string, numberIndex: number) => void;
+ accountListId: string;
}
const Contact: React.FC = ({
- handleDelete,
- setContactFocus,
- handleUpdate,
- errors,
- setValues,
- values,
person,
- personIndex,
+ handleChange,
+ setContactFocus,
+ handleSingleConfirm,
+ dataState,
+ handleChangePrimary,
+ accountListId,
}) => {
const { t } = useTranslation();
const locale = useLocale();
+ const { enqueueSnackbar } = useSnackbar();
const { classes } = useStyles();
const { appName } = useGetAppSettings();
+ const [updatePhoneNumber] = useUpdatePhoneNumberMutation();
+ const [numberToDelete, setNumberToDelete] = useState(
+ null,
+ );
+ const { id: personId, contactId } = person;
+
+ const numbers: PhoneNumber[] = useMemo(() => {
+ return (
+ dataState[personId]?.phoneNumbers.map((number) => ({
+ ...number,
+ isValid: false,
+ personId: personId,
+ isPrimary: number.primary,
+ })) || []
+ );
+ }, [person, dataState]);
- const numbers: PersonPhoneNumberFragment[] = person.phoneNumbers.nodes || [];
const name: string = `${person.firstName} ${person.lastName}`;
+ const validationSchema = yup.object({
+ newPhone: yup
+ .string()
+ .test(
+ 'is-phone-number',
+ t('This field is not a valid phone number'),
+ (val) => typeof val === 'string' && /\d/.test(val),
+ )
+ .required(t('This field is required')),
+ });
+
const handleContactNameClick = () => {
- setContactFocus(person.contactId, TabKey.ContactDetails);
+ setContactFocus(contactId);
+ };
+
+ const handleDeleteNumberOpen = ({
+ personId,
+ phoneNumber,
+ }: NumberToDelete) => {
+ setNumberToDelete({ personId, phoneNumber });
+ };
+
+ const handleDelete = async (): Promise => {
+ if (!numberToDelete) {
+ return;
+ }
+ const { personId, phoneNumber } = numberToDelete;
+ await updatePhoneNumber({
+ variables: {
+ input: {
+ accountListId: accountListId ?? '',
+ attributes: {
+ id: personId,
+ phoneNumbers: [
+ {
+ id: phoneNumber.id,
+ destroy: true,
+ },
+ ],
+ },
+ },
+ },
+ update: (cache) => {
+ cache.evict({ id: `PhoneNumber:${phoneNumber.id}` });
+ cache.gc();
+ },
+ onCompleted: () => {
+ enqueueSnackbar(
+ t(`Successfully deleted phone number {{phoneNumber}}`, {
+ phoneNumber: phoneNumber.number,
+ }),
+ {
+ variant: 'success',
+ },
+ );
+ handleDeleteNumberModalClose();
+ },
+ onError: () => {
+ enqueueSnackbar(
+ t(`Error deleting phone number {{phoneNumber}}`, {
+ phoneNumber: phoneNumber.number,
+ }),
+ {
+ variant: 'error',
+ },
+ );
+ },
+ });
+ };
+
+ const handleDeleteNumberModalClose = (): void => {
+ setNumberToDelete(null);
};
return (
-
-
-
-
-
-
-
- }
- title={
-
-
- {name}
-
-
- }
- action={
-
- }
- >
-
-
-
-
-
-
-
-
- {t('Source')}
-
-
-
-
-
-
- {t('Primary')}
+ }
+ title={
+
+
+ {name}
-
-
-
-
+ }
+ action={
+
-
-
- {numbers.map((phoneNumber, index) => (
-
-
+
+ {t('Confirm')}
+
+ }
+ >
+
+
+
+
+
-
-
-
- {t('Source')}:
-
-
-
- {`${phoneNumber.source} (${dateFormatShort(
- DateTime.fromISO(phoneNumber.updatedAt),
- locale,
- )})`}
-
-
+
+ {t('Source')}
+
-
+
-
- {phoneNumber.primary ? (
- <>
-
-
- {t('Source')}:
-
-
-
- >
- ) : (
- <>
-
-
- {t('Source')}:
-
-
-
- {
- const updatedValues = {
- people: values.people.map(
- (personValue: FormValuesPerson) =>
- personValue === person
- ? {
- ...personValue,
- phoneNumbers: {
- nodes: numbers.map(
- (
- number: PersonPhoneNumberFragment,
- ) => ({
- ...number,
- primary:
- number ===
- phoneNumber,
- }),
- ),
- },
- }
- : personValue,
- ),
- };
- setValues(updatedValues);
- }}
- />
-
- >
- )}
+
+ {t('Primary')}
-
+
-
- ,
- ) => {
- const updatedValues = {
- people: values.people.map(
- (personValue: FormValuesPerson) =>
- personValue === person
- ? {
- ...personValue,
- phoneNumbers: {
- nodes: numbers.map(
- (
- number: PersonPhoneNumberFragment,
- ) => ({
- ...number,
- number:
- number === phoneNumber
- ? event.target.value
- : number.number,
- }),
- ),
- },
- }
- : personValue,
- ),
- };
- setValues(updatedValues);
- }}
- value={phoneNumber.number}
- disabled={phoneNumber.source !== 'MPDX'}
- />
-
-
- {phoneNumber.source === 'MPDX' ? (
-
- handleDelete(
- personIndex,
- index,
- phoneNumber.number || '',
- )
- }
- className={classes.paddingX}
+
+ {t('Phone Number')}
+
+
+
+
+ {numbers.map((phoneNumber, index) => (
+ {
+ handleChange(personId, index, values.newPhone);
+ }}
+ >
+ {({
+ values: { newPhone },
+ setFieldValue,
+ handleSubmit,
+ errors,
+ }): ReactElement => (
+ <>
+
-
-
-
-
- ) : (
-
+
+
+ {t('Source')}:
+
+
+
+ {`${phoneNumber.source} (${dateFormatShort(
+ DateTime.fromISO(phoneNumber.updatedAt),
+ locale,
+ )})`}
+
+
+
+
+
-
-
- )}
-
-
- {errors?.people?.[personIndex]?.phoneNumbers?.nodes?.[
- index
- ]?.number && (
- <>
-
-
-
+
+ {phoneNumber.primary ? (
+ <>
+
+
+ {t('Source')}:
+
+
+
+ >
+ ) : (
+ <>
+
+
+ {t('Source')}:
+
+
+
+
+ handleChangePrimary(personId, index)
+ }
+ />
+
+ >
+ )}
+
+
+
+
- {
- errors?.people?.[personIndex]?.phoneNumbers
- ?.nodes?.[index]?.number
- }
-
-
- >
- )}
-
- ))}
-
-
-
-
-
- {t('Source')}:
-
-
-
- {appName}
-
-
-
-
-
-
-
- ,
- ) => {
- const updatedValues = {
- people: values.people.map(
- (personValue: FormValuesPerson) =>
- personValue === person
- ? {
- ...personValue,
- isNewPhoneNumber: true,
- newPhoneNumber: event.target.value,
+
+
+ {
+ setFieldValue('newPhone', e.target.value);
+ handleSubmit();
+ }}
+ disabled={phoneNumber.source !== appName}
+ />
+
+ {errors.newPhone}
+
+
+ {phoneNumber.source === 'MPDX' ? (
+
+
+ handleDeleteNumberOpen({
+ personId,
+ phoneNumber,
+ })
}
- : personValue,
- ),
- };
- setValues(updatedValues);
- }}
- inputProps={{
- 'data-testid': `addNewNumberInput-${person.id}`,
- }}
- value={values.people[personIndex].newPhoneNumber}
- />
-
+ className={classes.ContactIconContainer}
+ >
+
+
+
+
+
+ ) : (
+
+
+
+
+
+ )}
+
+
+ >
+ )}
+
+ ))}
+
{
- const updatedValues = {
- people: values.people.map(
- (personValue: PersonInvalidNumberFragment) =>
- personValue === person
- ? {
- ...person,
- phoneNumbers: {
- nodes: [
- ...person.phoneNumbers.nodes,
- {
- updatedAt: DateTime.local().toISO(),
- primary: false,
- source: appName,
- number:
- values.people[personIndex]
- .newPhoneNumber,
- },
- ],
- },
- isNewPhoneNumber: false,
- newPhoneNumber: '',
- }
- : personValue,
- ),
- };
- if (values.people[personIndex].newPhoneNumber) {
- setValues(updatedValues as FormValues);
- }
- }}
- data-testid={`addButton-${person.id}`}
+ justifyContent="space-between"
+ className={classes.paddingX}
>
-
-
-
+
+
+
+ {t('Source')}:
+
+
+
+ {appName}
+
+
-
+
+
- {errors?.people?.[personIndex]?.newPhoneNumber && (
- <>
-
-
-
- {errors?.people?.[personIndex]?.newPhoneNumber}
-
-
- >
- )}
-
-
-
-
-
+
+
+
+
+
-
+ {numberToDelete && (
+
+ {t('Are you sure you wish to delete this number:')}{' '}
+ {numberToDelete?.phoneNumber.number}
+ >
+ }
+ mutation={handleDelete}
+ handleClose={handleDeleteNumberModalClose}
+ />
+ )}
+ >
);
};
diff --git a/src/components/Tool/FixPhoneNumbers/FixPhoneNumbers.test.tsx b/src/components/Tool/FixPhoneNumbers/FixPhoneNumbers.test.tsx
index b2137954f..e72442c77 100644
--- a/src/components/Tool/FixPhoneNumbers/FixPhoneNumbers.test.tsx
+++ b/src/components/Tool/FixPhoneNumbers/FixPhoneNumbers.test.tsx
@@ -8,6 +8,7 @@ import TestRouter from '__tests__/util/TestRouter';
import TestWrapper from '__tests__/util/TestWrapper';
import { GqlMockedProvider } from '__tests__/util/graphqlMocking';
import { render, waitFor } from '__tests__/util/testingLibraryReactMock';
+import { AppSettingsProvider } from 'src/components/common/AppSettings/AppSettingsProvider';
import theme from '../../../theme';
import FixPhoneNumbers from './FixPhoneNumbers';
import { GetInvalidPhoneNumbersMocks } from './FixPhoneNumbersMocks';
@@ -40,39 +41,41 @@ const Components: React.FC<{
data?: ErgonoMockShape[];
cache?: ApolloCache