Skip to content

Commit

Permalink
Confirm all and Confirm single
Browse files Browse the repository at this point in the history
  • Loading branch information
dr-bizz committed Jun 25, 2024
1 parent eb907de commit bd2e5a1
Show file tree
Hide file tree
Showing 4 changed files with 311 additions and 2 deletions.
19 changes: 17 additions & 2 deletions src/components/Tool/FixMailingAddresses/Contact.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ import { useUpdateCache } from 'src/hooks/useUpdateCache';
import { dateFormatShort } from 'src/lib/intlFormat';
import { contactPartnershipStatus } from 'src/utils/contacts/contactPartnershipStatus';
import theme from '../../../theme';
import { emptyAddress } from './FixMailingAddresses';
import { HandleSingleConfirmProps, emptyAddress } from './FixMailingAddresses';
import { ContactAddressFragment } from './GetInvalidAddresses.generated';

const ContactHeader = styled(CardHeader)(() => ({
Expand Down Expand Up @@ -117,6 +117,12 @@ interface Props {
openEditAddressModal: (address: ContactAddressFragment, id: string) => void;
openNewAddressModal: (address: ContactAddressFragment, id: string) => void;
setContactFocus: SetContactFocus;
handleSingleConfirm: ({
addresses,
id,
name,
onlyErrorOnce,
}: HandleSingleConfirmProps) => void;
}

const Contact: React.FC<Props> = ({
Expand All @@ -128,6 +134,7 @@ const Contact: React.FC<Props> = ({
openEditAddressModal,
openNewAddressModal,
setContactFocus,
handleSingleConfirm,
}) => {
const { t } = useTranslation();
const locale = useLocale();
Expand Down Expand Up @@ -161,6 +168,10 @@ const Contact: React.FC<Props> = ({
});
};

const handleConfirm = () => {
handleSingleConfirm({ addresses, id, name });
};

const handleContactNameClick = () => {
setContactFocus(id);
};
Expand All @@ -176,7 +187,11 @@ const Contact: React.FC<Props> = ({
/>
}
action={
<Button variant="contained" className={classes.confirmButon}>
<Button
variant="contained"
className={classes.confirmButon}
onClick={handleConfirm}
>
<Icon path={mdiCheckboxMarkedCircle} size={0.8} />
{t('Confirm')}
</Button>
Expand Down
130 changes: 130 additions & 0 deletions src/components/Tool/FixMailingAddresses/FixMailingAddresses.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -427,4 +427,134 @@ describe('FixSendNewsletter', () => {
expect(setContactFocus).toHaveBeenCalledWith(contactId);
});
});

describe('handleSingleConfirm()', () => {
it('should fire handleSingleConfirm', async () => {
const { getAllByRole, getByText, queryByTestId } = render(
<Components
mocks={{
InvalidAddresses: {
...mockInvalidAddressesResponse.InvalidAddresses,
},
}}
/>,
);
await waitFor(() =>
expect(queryByTestId('loading')).not.toBeInTheDocument(),
);
userEvent.click(getAllByRole('button', { name: 'Confirm' })[0]);

const name = 'Baggins, Frodo';
await waitFor(() => expect(getByText(name)).toBeInTheDocument());

// TODO: Fix when GraphQL is fixed
await waitFor(() =>
expect(mockEnqueue).toHaveBeenCalledWith(
`${name} - Error while saving addresses. undefined`,
{
variant: 'error',
},
),
);

// await waitFor(() =>
// expect(queryByText(name)).not.toBeInTheDocument(),
// );
});
});

describe('handleBulkConfirm()', () => {
it('should fire handleSingleConfirm', async () => {
process.env.APP_NAME = 'MPDX';
const { getByRole, queryByTestId } = render(
<Components
mocks={{
InvalidAddresses: {
...mockInvalidAddressesResponse.InvalidAddresses,
},
}}
/>,
);
await waitFor(() =>
expect(queryByTestId('loading')).not.toBeInTheDocument(),
);
userEvent.click(getByRole('button', { name: 'Confirm 1 as MPDX' }));

await waitFor(() =>
expect(getByRole('heading', { name: 'Confirm' })).toBeInTheDocument(),
);

userEvent.click(getByRole('button', { name: 'Yes' }));

// TODO: Fix when GraphQL is fixed
const name = 'Baggins, Frodo';
await waitFor(() => {
expect(mockEnqueue).toHaveBeenCalledWith(
`Error updating contact ${name}`,
{
variant: 'error',
autoHideDuration: 7000,
},
);
expect(mockEnqueue).toHaveBeenCalledWith(
`Error when updating 1 contact(s)`,
{
variant: 'error',
},
);
});

// await waitFor(() =>
// expect(queryByText(name)).not.toBeInTheDocument(),
// );
});
});

it('should fire handleSingleConfirm', async () => {
process.env.APP_NAME = 'MPDX';
const { getByRole, queryByTestId } = render(
<Components
mocks={{
InvalidAddresses: {
...mockInvalidAddressesResponse.InvalidAddresses,
},
}}
/>,
);
await waitFor(() =>
expect(queryByTestId('loading')).not.toBeInTheDocument(),
);
const name = 'Baggins, Frodo';
userEvent.click(getByRole('combobox'));
userEvent.click(getByRole('option', { name: 'DataServer' }));

userEvent.click(getByRole('button', { name: 'Confirm 1 as DataServer' }));

await waitFor(() =>
expect(getByRole('heading', { name: 'Confirm' })).toBeInTheDocument(),
);

userEvent.click(getByRole('button', { name: 'Yes' }));

// TODO: Fix when GraphQL is fixed
await waitFor(() => {
expect(mockEnqueue).toHaveBeenCalledWith(
`Error updating contact ${name}`,
{
variant: 'error',
autoHideDuration: 7000,
},
);
expect(mockEnqueue).toHaveBeenCalledWith(
`Error when updating 1 contact(s)`,
{
variant: 'error',
},
);
});

// await waitFor(() =>
// expect(queryByText(name)).not.toBeInTheDocument(),
// );
});
});
141 changes: 141 additions & 0 deletions src/components/Tool/FixMailingAddresses/FixMailingAddresses.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -13,11 +13,13 @@ import {
SelectChangeEvent,
Typography,
} from '@mui/material';
import { useSnackbar } from 'notistack';
import { Trans, useTranslation } from 'react-i18next';
import { makeStyles } from 'tss-react/mui';
import { SetContactFocus } from 'pages/accountLists/[accountListId]/tools/useToolsHelper';
import { DynamicAddAddressModal } from 'src/components/Contacts/ContactDetails/ContactDetailsTab/Mailing/AddAddressModal/DynamicAddAddressModal';
import { DynamicEditContactAddressModal } from 'src/components/Contacts/ContactDetails/ContactDetailsTab/Mailing/EditContactAddressModal/DynamicEditContactAddressModal';
import { Confirmation } from 'src/components/common/Modal/Confirmation/Confirmation';
import theme from '../../../theme';
import NoData from '../NoData';
import Contact from './Contact';
Expand All @@ -26,8 +28,16 @@ import {
InvalidAddressesDocument,
InvalidAddressesQuery,
useInvalidAddressesQuery,
useUpdateContactAddressMutation,
} from './GetInvalidAddresses.generated';

export type HandleSingleConfirmProps = {
addresses: ContactAddressFragment[];
id: string;
name: string;
onlyErrorOnce?: boolean;
};

const useStyles = makeStyles()(() => ({
container: {
padding: theme.spacing(3),
Expand Down Expand Up @@ -131,9 +141,122 @@ const FixSendNewsletter: React.FC<Props> = ({
const [selectedAddress, setSelectedAddress] = useState(emptyAddress);
const [selectedContactId, setSelectedContactId] = useState('');
const [defaultSource, setDefaultSource] = useState(appName);
const [openBulkConfirmModal, setOpenBulkConfirmModal] = useState(false);

const { data, loading } = useInvalidAddressesQuery({
variables: { accountListId },
});
const [updateAddress] = useUpdateContactAddressMutation();
const { enqueueSnackbar } = useSnackbar();

const handleSingleConfirm = async ({
addresses,
id,
name,
onlyErrorOnce = false,
}: HandleSingleConfirmProps) => {
const errors: string[] = [];

for (let idx = 0; idx < addresses.length; idx++) {
const address = addresses[idx];

await updateAddress({
variables: {
accountListId,
attributes: {
id: address.id,
validValues: true,
// TODO: Fix the Graph QL Input
primaryMailingAddress: address.primaryMailingAddress,
},
},
update(cache) {
if (idx === addresses.length - 1 && !errors.length) {
cache.evict({ id: `Contact:${id}` });
}
},
onError(error) {
errors.push(
`${name} - ${t('Error while saving addresses.')} ${error.cause}`,
);
},
});
}

if (errors.length) {
if (onlyErrorOnce) {
enqueueSnackbar(t(`Error updating contact ${name}`), {
variant: 'error',
autoHideDuration: 7000,
});
} else {
errors.forEach((error) => {
enqueueSnackbar(error, { variant: 'error' });
});
}
return { success: false };
} else {
enqueueSnackbar(t(`Updated contact ${name}`), { variant: 'success' });
return { success: true };
}
};

const handleBulkConfirm = async () => {
try {
const callsByContact: (() => Promise<{ success: boolean }>)[] = [];
data?.contacts?.nodes.forEach((contact) => {
const primaryAddress = contact.addresses.nodes.find(
(address) =>
address.source === defaultSource ||
(defaultSource === appName && address.source === 'MPDX'),
);
if (primaryAddress) {
const addresses: ContactAddressFragment[] = [];
contact.addresses.nodes.forEach((address) => {
addresses.push({
...address,
primaryMailingAddress: address.id === primaryAddress?.id,
});
});
const callContactMutation = () =>
handleSingleConfirm({
addresses,
id: contact.id,
name: contact.name,
onlyErrorOnce: true,
});
callsByContact.push(callContactMutation);
}
});

if (callsByContact.length) {
const results = await Promise.all(callsByContact.map((call) => call()));

const failedUpdates = results.filter(
(result) => !result.success,
).length;
const successfulUpdates = results.length - failedUpdates;

if (successfulUpdates) {
enqueueSnackbar(t(`Updated ${successfulUpdates} contact(s)`), {
variant: 'success',
});
}
if (failedUpdates) {
enqueueSnackbar(
t(`Error when updating ${failedUpdates} contact(s)`),
{
variant: 'error',
},
);
}
} else {
enqueueSnackbar(t(`No contacts were updated`), { variant: 'warning' });
}
} catch (error) {
enqueueSnackbar(t(`Error updating contacts`), { variant: 'error' });
}
};

const handleUpdateCacheForDeleteAddress = useCallback(
(cache: ApolloCache<unknown>, data) => {
Expand Down Expand Up @@ -213,6 +336,10 @@ const FixSendNewsletter: React.FC<Props> = ({
setDefaultSource(event.target.value);
};

const handleBulkConfirmModalClose = () => {
setOpenBulkConfirmModal(false);
};

const totalContacts = data?.contacts?.nodes?.length || 0;

return (
Expand Down Expand Up @@ -273,6 +400,7 @@ const FixSendNewsletter: React.FC<Props> = ({
<Button
variant="contained"
className={classes.confirmAllButton}
onClick={() => setOpenBulkConfirmModal(true)}
>
<Icon
path={mdiCheckboxMarkedCircle}
Expand Down Expand Up @@ -303,6 +431,7 @@ const FixSendNewsletter: React.FC<Props> = ({
handleModalOpen(ModalEnum.New, address, contactId)
}
setContactFocus={setContactFocus}
handleSingleConfirm={handleSingleConfirm}
/>
))}
</Grid>
Expand Down Expand Up @@ -341,6 +470,18 @@ const FixSendNewsletter: React.FC<Props> = ({
handleUpdateCache={handleUpdateCacheForAddAddress}
/>
)}
{openBulkConfirmModal && (
<Confirmation
isOpen={true}
title={t('Confirm')}
message={t(
`You are updating all contacts visible on this page, setting the first {{source}} address as the primary address. If no such address exists the contact will not be updated. Are you sure you want to do this?`,
{ source: defaultSource },
)}
handleClose={handleBulkConfirmModalClose}
mutation={handleBulkConfirm}
/>
)}
</Box>
);
};
Expand Down
Loading

0 comments on commit bd2e5a1

Please sign in to comment.