diff --git a/src/components/Contacts/ContactDetails/ContactDonationsTab/PartnershipInfo/EditPartnershipInfoModal/EditPartnershipInfoModal.test.tsx b/src/components/Contacts/ContactDetails/ContactDonationsTab/PartnershipInfo/EditPartnershipInfoModal/EditPartnershipInfoModal.test.tsx index 7f4963043..b4403125b 100644 --- a/src/components/Contacts/ContactDetails/ContactDonationsTab/PartnershipInfo/EditPartnershipInfoModal/EditPartnershipInfoModal.test.tsx +++ b/src/components/Contacts/ContactDetails/ContactDonationsTab/PartnershipInfo/EditPartnershipInfoModal/EditPartnershipInfoModal.test.tsx @@ -200,38 +200,118 @@ describe('EditPartnershipInfoModal', () => { }); it('should handle editing status | Non-Financial', async () => { - const { getByLabelText, getByText } = render( - - - - - - - - - , - ); + const { getByLabelText, getByText, getByRole, getByTestId, queryByText } = + render( + + + + + + + + + , + ); const statusInput = getByLabelText('Status'); const amountInput = getByLabelText('Amount'); - const frequencyInput = getByLabelText('Frequency'); + const frequencyInput = getByRole('combobox', { name: 'Frequency' }); + expect(statusInput.textContent).toEqual('Partner - Financial'); expect(amountInput).toHaveValue(50); expect(frequencyInput.textContent).toEqual('Every 2 Months'); + userEvent.click(statusInput); userEvent.click(getByText('Ask In Future')); - // Values get reset and inputs becomes disabled when status is not PARTNER_FINANCIAL + expect(getByTestId('removeCommitmentMessage')).toBeInTheDocument(); + userEvent.click(getByRole('button', { name: 'No' })); + + expect(amountInput).toHaveValue(50); + expect(frequencyInput.textContent).toEqual('Every 2 Months'); + expect(getByText('Every 2 Months')).toBeInTheDocument(); + + userEvent.click(statusInput); + userEvent.click(getByText('Partner - Financial')); + + userEvent.click(statusInput); + userEvent.click(getByText('Ask In Future')); + + expect(getByTestId('removeCommitmentMessage')).toBeInTheDocument(); + userEvent.click(getByRole('button', { name: 'Yes' })); + expect(amountInput).toHaveValue(0); expect(amountInput).toBeDisabled(); + expect(queryByText('Every 2 Months')).not.toBeInTheDocument(); expect(statusInput.textContent).toEqual('Ask In Future'); - // these are flaky for some reason, disabling for now - // await waitFor(() => expect(frequencyInput.textContent).toBe('')); - // await waitFor(() => expect(frequencyInput).toBeDisabled()); + userEvent.click(getByText('Save')); + await waitFor(() => + expect(mockEnqueue).toHaveBeenCalledWith( + 'Partnership information updated successfully.', + { + variant: 'success', + }, + ), + ); + expect(handleClose).toHaveBeenCalled(); + }); + + it('should handle when remove commitment warning shows', async () => { + const { getByLabelText, getByText, getByRole, getByTestId, queryByTestId } = + render( + + + + + + + + + , + ); + const statusInput = getByLabelText('Status'); + const amountInput = getByLabelText('Amount'); + const frequencyInput = getByRole('combobox', { name: 'Frequency' }); + + // Clear amount and frequency + userEvent.click(statusInput); + userEvent.click(getByText('Ask In Future')); + userEvent.click(getByRole('button', { name: 'Yes' })); + + // Due to the amount being zero, we don't show the remove commitment message + userEvent.click(statusInput); + userEvent.click(getByText('Partner - Financial')); + userEvent.click(statusInput); + userEvent.click(getByText('Ask In Future')); + expect(queryByTestId('removeCommitmentMessage')).not.toBeInTheDocument(); + + // If frequency and not amount is set we show the remove commitment message + userEvent.click(statusInput); + userEvent.click(getByText('Partner - Financial')); + userEvent.click(frequencyInput); + userEvent.click(getByText('Every 2 Months')); + expect(amountInput).toHaveValue(0); + userEvent.click(statusInput); + userEvent.click(getByText('Ask In Future')); + expect(getByTestId('removeCommitmentMessage')).toBeInTheDocument(); + + // Clear amount and frequency + userEvent.click(getByRole('button', { name: 'Yes' })); + + // If amount and not frequency is set we show the remove commitment message + userEvent.click(statusInput); + userEvent.click(getByText('Partner - Financial')); + userEvent.type(amountInput, '50'); + userEvent.click(statusInput); + userEvent.click(getByText('Ask In Future')); + expect(getByTestId('removeCommitmentMessage')).toBeInTheDocument(); userEvent.click(getByText('Save')); await waitFor(() => diff --git a/src/components/Contacts/ContactDetails/ContactDonationsTab/PartnershipInfo/EditPartnershipInfoModal/EditPartnershipInfoModal.tsx b/src/components/Contacts/ContactDetails/ContactDonationsTab/PartnershipInfo/EditPartnershipInfoModal/EditPartnershipInfoModal.tsx index a5775c246..3f43ec2ea 100644 --- a/src/components/Contacts/ContactDetails/ContactDonationsTab/PartnershipInfo/EditPartnershipInfoModal/EditPartnershipInfoModal.tsx +++ b/src/components/Contacts/ContactDetails/ContactDonationsTab/PartnershipInfo/EditPartnershipInfoModal/EditPartnershipInfoModal.tsx @@ -1,8 +1,10 @@ import React, { ReactElement, useState } from 'react'; import InfoIcon from '@mui/icons-material/InfoOutlined'; import { + Alert, Autocomplete, Box, + Button, Checkbox, CircularProgress, DialogActions, @@ -34,6 +36,7 @@ import { SendNewsletterEnum, StatusEnum, } from 'src/graphql/types.generated'; +import useGetAppSettings from 'src/hooks/useGetAppSettings'; import { nullableDateTime } from 'src/lib/formikHelpers'; import { getPledgeCurrencyOptions } from 'src/lib/getCurrencyOptions'; import { getLocalizedContactStatus } from 'src/utils/functions/getLocalizedContactStatus'; @@ -71,6 +74,13 @@ const TextFieldInteractive = styled(TextField, { }, })); +const RemoveCommitmentActions = styled(Box)(({ theme }) => ({ + display: 'flex', + justifyContent: 'flex-end', + width: '100%', + gap: theme.spacing(1), +})); + const SelectInteractive = styled(Select, { shouldForwardProp: (prop) => prop !== 'isDisabled', })<{ isDisabled?: boolean }>(({ isDisabled }) => ({ @@ -120,9 +130,12 @@ export const EditPartnershipInfoModal: React.FC< EditPartnershipInfoModalProps > = ({ contact, handleClose }) => { const { t } = useTranslation(); + const { appName } = useGetAppSettings(); const accountListId = useAccountListId(); const constants = useApiConstants(); const [referredByName, setReferredByName] = useState(''); + const [showRemoveCommitmentWarning, setShowRemoveCommitmentWarning] = + useState(false); const referredContactIds = contact.contactReferralsToMe.nodes.map( (referral) => referral.referredBy.id, ); @@ -260,16 +273,30 @@ export const EditPartnershipInfoModal: React.FC< }; const updateStatus = ( - status: StatusEnum, + newStatus: StatusEnum, setFieldValue: (name: string, value: StatusEnum | number | null) => void, + oldStatus?: StatusEnum | null, + pledgeAmount?: number | null, + pledgeFrequency?: PledgeFrequencyEnum | null, ) => { - setFieldValue('status', status); - if (status !== StatusEnum.PartnerFinancial) { - setFieldValue('pledgeAmount', 0); - setFieldValue('pledgeFrequency', null); + setFieldValue('status', newStatus); + if ( + newStatus !== StatusEnum.PartnerFinancial && + oldStatus === StatusEnum.PartnerFinancial && + ((pledgeAmount && pledgeAmount > 0) || pledgeFrequency) + ) { + setShowRemoveCommitmentWarning(true); } }; + const removeCommittedDetails = ( + setFieldValue: (name: string, value: StatusEnum | number | null) => void, + ) => { + setFieldValue('pledgeAmount', 0); + setFieldValue('pledgeFrequency', null); + setShowRemoveCommitmentWarning(false); + }; + return ( - updateStatus(e.target.value as StatusEnum, setFieldValue) + updateStatus( + e.target.value as StatusEnum, + setFieldValue, + status, + pledgeAmount, + pledgeFrequency, + ) } MenuProps={{ anchorOrigin: { @@ -357,6 +390,41 @@ export const EditPartnershipInfoModal: React.FC< + {showRemoveCommitmentWarning && ( + + + + {t( + '{{appName}} uses your contact status, commitment amount, and frequency together to calculate many things, including your progress towards your goal and notification alerts.', + { appName }, + )} + + + {t( + 'If you are switching this contact away from Partner - Financial status, their commitment amount and frequency will no longer be included in calculations. Would you like to remove their commitment amount and frequency, as well?', + )} + + + + + + + + )}