diff --git a/src/components/Shared/MassActions/TasksMassActionsDropdown.test.tsx b/src/components/Shared/MassActions/TasksMassActionsDropdown.test.tsx index 78408a4db..a1f94569e 100644 --- a/src/components/Shared/MassActions/TasksMassActionsDropdown.test.tsx +++ b/src/components/Shared/MassActions/TasksMassActionsDropdown.test.tsx @@ -103,7 +103,7 @@ describe('TasksMassActionsDropdown', () => { queryByText, getByLabelText, getByRole, - findByLabelText, + findByRole, } = render(); expect(queryByText('Edit Tasks')).not.toBeInTheDocument(); @@ -120,7 +120,7 @@ describe('TasksMassActionsDropdown', () => { 'Appointment', ), ); - userEvent.click(await findByLabelText('Action')); + userEvent.click(await findByRole('combobox', { name: 'Action' })); userEvent.click( within(getByRole('listbox', { hidden: true, name: 'Action' })).getByText( 'In Person', diff --git a/src/components/Task/MassActions/EditTasks/MassActionsEditTasksModal.test.tsx b/src/components/Task/MassActions/EditTasks/MassActionsEditTasksModal.test.tsx index 7808fcf54..1d557a10b 100644 --- a/src/components/Task/MassActions/EditTasks/MassActionsEditTasksModal.test.tsx +++ b/src/components/Task/MassActions/EditTasks/MassActionsEditTasksModal.test.tsx @@ -86,47 +86,80 @@ describe('MassActionsEditTasksModal', () => { ); expect(getByText('Blank fields will not be affected!')).toBeInTheDocument(); }); -}); + it('shows correct Action field options based on the Task Type', async () => { + const handleClose = jest.fn(); + const { queryByText, findByRole } = render( + + + + + + + + + , + ); + const taskTypeField = await findByRole('combobox', { name: 'Task Type' }); + const actionField = await findByRole('combobox', { name: 'Action' }); -it('shows correct Action field options based on the Task Type', async () => { - const handleClose = jest.fn(); - const { queryByText, findByRole } = render( - - - - - - - - - , - ); - const taskTypeField = await findByRole('combobox', { name: 'Task Type' }); - const actionField = await findByRole('combobox', { name: 'Action' }); + expect(actionField).toBeDisabled(); - expect(actionField).toBeDisabled(); + userEvent.click(taskTypeField); + userEvent.click(await findByRole('option', { name: 'Appointment' })); + userEvent.click(actionField); + userEvent.click(await findByRole('option', { name: 'In Person' })); - userEvent.click(taskTypeField); - userEvent.click(await findByRole('option', { name: 'Appointment' })); - userEvent.click(actionField); - userEvent.click(await findByRole('option', { name: 'In Person' })); + userEvent.click(taskTypeField); + userEvent.click(await findByRole('option', { name: 'Partner Care' })); + await waitFor(() => { + expect(queryByText('In Person')).not.toBeInTheDocument(); + }); + userEvent.click(actionField); + userEvent.click(await findByRole('option', { name: 'Digital Newsletter' })); - userEvent.click(taskTypeField); - userEvent.click(await findByRole('option', { name: 'Partner Care' })); - await waitFor(() => { - expect(queryByText('In Person')).not.toBeInTheDocument(); + userEvent.clear(taskTypeField); + await waitFor(() => { + expect(queryByText('In Person')).not.toBeInTheDocument(); + }); + expect(actionField).toBeDisabled(); }); - userEvent.click(actionField); - userEvent.click(await findByRole('option', { name: 'Digital Newsletter' })); - userEvent.clear(taskTypeField); - await waitFor(() => { - expect(queryByText('In Person')).not.toBeInTheDocument(); + it('requires task action when task phase is selected', async () => { + const handleClose = jest.fn(); + const { getByText, findByRole } = render( + + + + + + + + + , + ); + const taskTypeField = await findByRole('combobox', { name: 'Task Type' }); + const actionField = await findByRole('combobox', { name: 'Action' }); + + userEvent.click(taskTypeField); + userEvent.click(await findByRole('option', { name: 'Appointment' })); + + await waitFor(() => expect(getByText('Save')).toBeDisabled()); + + userEvent.click(taskTypeField); + userEvent.click(await findByRole('option', { name: 'Appointment' })); + userEvent.click(actionField); + userEvent.click(await findByRole('option', { name: 'In Person' })); + + await waitFor(() => expect(getByText('Save')).not.toBeDisabled()); }); - expect(actionField).toBeDisabled(); }); diff --git a/src/components/Task/MassActions/EditTasks/MassActionsEditTasksModal.tsx b/src/components/Task/MassActions/EditTasks/MassActionsEditTasksModal.tsx index bfeebb29c..db8400a5f 100644 --- a/src/components/Task/MassActions/EditTasks/MassActionsEditTasksModal.tsx +++ b/src/components/Task/MassActions/EditTasks/MassActionsEditTasksModal.tsx @@ -1,4 +1,4 @@ -import React, { ReactElement } from 'react'; +import React, { ReactElement, useRef } from 'react'; import { Alert, Checkbox, @@ -37,7 +37,13 @@ import { IncompleteWarning } from '../IncompleteWarning/IncompleteWarning'; const massActionsEditTasksSchema = yup.object({ subject: yup.string().nullable(), taskPhase: yup.mixed().nullable(), - activityType: yup.mixed().nullable(), + activityType: yup + .mixed() + .nullable() + .when('taskPhase', { + is: (value: any) => !!value, + then: yup.mixed().required('Must select a Task Action'), + }), userId: yup.string().nullable(), startAt: nullableDateTime(), noDueDate: yup.boolean().required(), @@ -62,9 +68,14 @@ export const MassActionsEditTasksModal: React.FC< const [createTaskComment] = useCreateTaskCommentMutation(); const { update } = useUpdateTasksQueries(); const { taskPhases, activitiesByPhase } = usePhaseData(); + const activityRef = useRef(null); const { enqueueSnackbar } = useSnackbar(); + const focusActivity = (): void => { + setTimeout(() => activityRef?.current?.focus(), 50); + }; + const onSubmit = async (fields: Attributes) => { const { noDueDate, body } = fields; const formattedFields: Partial = {}; @@ -142,9 +153,12 @@ export const MassActionsEditTasksModal: React.FC< }, handleChange, handleSubmit, + handleBlur, setFieldValue, isSubmitting, isValid, + touched, + errors, }): ReactElement => (
@@ -170,7 +184,9 @@ export const MassActionsEditTasksModal: React.FC< onChange={(phase) => { setFieldValue('taskPhase', phase); setFieldValue('activityType', ''); + focusActivity(); }} + onBlur={handleBlur('taskPhase')} /> @@ -185,6 +201,10 @@ export const MassActionsEditTasksModal: React.FC< } // None and null are distinct values: null leaves the action unchanged and None changes the action to None preserveNone + required={!!taskPhase} + touched={touched} + errors={errors} + inputRef={activityRef} /> diff --git a/src/components/Task/Modal/Form/Inputs/ActivityTypeAutocomplete/ActivityTypeAutocomplete.tsx b/src/components/Task/Modal/Form/Inputs/ActivityTypeAutocomplete/ActivityTypeAutocomplete.tsx index 2ad9ec4a8..3bebebfee 100644 --- a/src/components/Task/Modal/Form/Inputs/ActivityTypeAutocomplete/ActivityTypeAutocomplete.tsx +++ b/src/components/Task/Modal/Form/Inputs/ActivityTypeAutocomplete/ActivityTypeAutocomplete.tsx @@ -44,7 +44,6 @@ export const ActivityTypeAutocomplete: React.FC = ({ return ( openOnFocus - autoHighlight autoSelect value={value === null || typeof value === 'undefined' ? null : value} options={sortedOptions} diff --git a/src/components/Task/Modal/Form/Inputs/ActivityTypeAutocomplete/AssigneeAutocomplete/AssigneeAutocomplete.tsx b/src/components/Task/Modal/Form/Inputs/ActivityTypeAutocomplete/AssigneeAutocomplete/AssigneeAutocomplete.tsx index 93511d9b1..30d2e35ec 100644 --- a/src/components/Task/Modal/Form/Inputs/ActivityTypeAutocomplete/AssigneeAutocomplete/AssigneeAutocomplete.tsx +++ b/src/components/Task/Modal/Form/Inputs/ActivityTypeAutocomplete/AssigneeAutocomplete/AssigneeAutocomplete.tsx @@ -25,7 +25,6 @@ export const AssigneeAutocomplete: React.FC = ({ return ( user.id)} getOptionLabel={(userId) => { const user = users.find(({ user }) => user.id === userId)?.user; diff --git a/src/utils/functions/getLocalizedResultStrings.ts b/src/utils/functions/getLocalizedResultStrings.ts index 998e87bf8..3bac039e7 100644 --- a/src/utils/functions/getLocalizedResultStrings.ts +++ b/src/utils/functions/getLocalizedResultStrings.ts @@ -37,7 +37,7 @@ export const getLocalizedResultString = ( return t('No Response Yet'); case DisplayResultEnum.AppointmentResultNotInterested: - return t('Does not want to meet'); + return t('Not Interested'); case DisplayResultEnum.InitiationResultCircleBack: return t("Can't meet right now - circle back");