diff --git a/pages/accountLists/[accountListId]/settings/preferences.page.test.tsx b/pages/accountLists/[accountListId]/settings/preferences.page.test.tsx index ad314571d4..1879ddc62d 100644 --- a/pages/accountLists/[accountListId]/settings/preferences.page.test.tsx +++ b/pages/accountLists/[accountListId]/settings/preferences.page.test.tsx @@ -286,9 +286,20 @@ describe('Preferences page', () => { ), ).toBeInTheDocument(); - // Home Country + // Geographic Location const skipButton = getByRole('button', { name: 'Skip Step' }); userEvent.click(skipButton); + expect( + await findByText('Are you within 50 miles of a major city?'), + ).toBeInTheDocument(); + expect( + await findByText( + 'This should be the major city within 50 miles of you. If none apply, leave this blank.', + ), + ).toBeInTheDocument(); + + // Home Country + userEvent.click(skipButton); expect( await findByText( 'This should be the place from which you are living and sending out physical communications. This will be used in exports for mailing address information.', diff --git a/pages/accountLists/[accountListId]/settings/preferences.page.tsx b/pages/accountLists/[accountListId]/settings/preferences.page.tsx index 974d80faf6..87f25d8edf 100644 --- a/pages/accountLists/[accountListId]/settings/preferences.page.tsx +++ b/pages/accountLists/[accountListId]/settings/preferences.page.tsx @@ -16,6 +16,7 @@ import { CurrencyAccordion } from 'src/components/Settings/preferences/accordion import { DefaultAccountAccordion } from 'src/components/Settings/preferences/accordions/DefaultAccountAccordion/DefaultAccountAccordion'; import { EarlyAdopterAccordion } from 'src/components/Settings/preferences/accordions/EarlyAdopterAccordion/EarlyAdopterAccordion'; import { ExportAllDataAccordion } from 'src/components/Settings/preferences/accordions/ExportAllDataAccordion/ExportAllDataAccordion'; +import { GeographicLocationAccordion } from 'src/components/Settings/preferences/accordions/GeographicLocationAccordion/GeographicLocationAccordion'; import { HomeCountryAccordion } from 'src/components/Settings/preferences/accordions/HomeCountryAccordion/HomeCountryAccordion'; import { HourToSendNotificationsAccordion } from 'src/components/Settings/preferences/accordions/HourToSendNotificationsAccordion/HourToSendNotificationsAccordion'; import { LanguageAccordion } from 'src/components/Settings/preferences/accordions/LanguageAccordion/LanguageAccordion'; @@ -51,6 +52,7 @@ const Preferences: React.FC = () => { const setupAccordions = [ PreferenceAccordion.Locale, PreferenceAccordion.MonthlyGoal, + PreferenceAccordion.GeographicLocation, PreferenceAccordion.HomeCountry, ]; const [setup, setSetup] = useState(0); @@ -139,6 +141,8 @@ const Preferences: React.FC = () => { case 1: return t('Great progress comes from great goals!'); case 2: + return t('Are you within 50 miles of a major city?'); + case 3: return t('What country are you in?'); default: return ''; @@ -254,6 +258,17 @@ const Preferences: React.FC = () => { disabled={onSetupTour && setup !== 1} handleSetupChange={handleSetupChange} /> + { } accountListId={accountListId} countries={countries} - disabled={onSetupTour && setup !== 2} + disabled={onSetupTour && setup !== 3} handleSetupChange={handleSetupChange} /> )} /> + )} diff --git a/src/components/HrTools/GoalCalculator/GoalCalculatorTestWrapper.tsx b/src/components/HrTools/GoalCalculator/GoalCalculatorTestWrapper.tsx index 2b7ed409c5..5656e81d3f 100644 --- a/src/components/HrTools/GoalCalculator/GoalCalculatorTestWrapper.tsx +++ b/src/components/HrTools/GoalCalculator/GoalCalculatorTestWrapper.tsx @@ -13,6 +13,7 @@ import { PrimaryBudgetCategoryEnum, SubBudgetCategoryEnum, } from 'src/graphql/types.generated'; +import { AccountGeographicLocationQuery } from 'src/hooks/AccountGeographicLocation.generated'; import { GoalCalculatorConstantsDocument, GoalCalculatorConstantsQuery, @@ -338,21 +339,24 @@ interface MockedGoalCalculatorTestWrapperProps { * mock every year with the static `constantsMock`. */ constantsByYear?: Record; + /** The account's currently saved geographic location preference. */ + accountGeographicLocation?: string | null; children?: React.ReactNode; } interface NoMocksGoalCalculatorTestWrapperProps { /** * Skip the `GqlMockedProvider` entirely (the test supplies its own Apollo - * provider). `onCall`, `readOnly`, `goalCalculation`, and `constantsByYear` - * only configure the mocked provider, so they are disallowed here — they - * would silently no-op. + * provider). `onCall`, `readOnly`, `goalCalculation`, `constantsByYear`, and + * `accountGeographicLocation` only configure the mocked provider, so they + * are disallowed here — they would silently no-op. */ noMocks: true; onCall?: never; readOnly?: never; goalCalculation?: never; constantsByYear?: never; + accountGeographicLocation?: never; children?: React.ReactNode; } @@ -368,6 +372,7 @@ export const GoalCalculatorTestWrapper: React.FC< readOnly = false, goalCalculation = goalCalculationMock, constantsByYear, + accountGeographicLocation = null, children, }) => { const content = {children}; @@ -388,6 +393,7 @@ export const GoalCalculatorTestWrapper: React.FC< mocks={{ GoalCalculation: { @@ -400,6 +406,13 @@ export const GoalCalculatorTestWrapper: React.FC< ? mockConstantsByYear(constantsByYear) : constantsMock, }, + AccountGeographicLocation: { + accountList: { + settings: { + geographicLocation: accountGeographicLocation, + }, + }, + }, }} onCall={onCall} > diff --git a/src/components/HrTools/GoalCalculator/SummaryReport/Steps/PresentingYourGoalStep/GoalApplicationButtonGroup.test.tsx b/src/components/HrTools/GoalCalculator/SummaryReport/Steps/PresentingYourGoalStep/GoalApplicationButtonGroup.test.tsx index d901339b4f..038b471016 100644 --- a/src/components/HrTools/GoalCalculator/SummaryReport/Steps/PresentingYourGoalStep/GoalApplicationButtonGroup.test.tsx +++ b/src/components/HrTools/GoalCalculator/SummaryReport/Steps/PresentingYourGoalStep/GoalApplicationButtonGroup.test.tsx @@ -1,12 +1,24 @@ import React from 'react'; import { render, waitFor } from '@testing-library/react'; import userEvent from '@testing-library/user-event'; -import { GoalCalculatorTestWrapper } from '../../../GoalCalculatorTestWrapper'; +import { + GoalCalculatorTestWrapper, + goalCalculationMock, +} from '../../../GoalCalculatorTestWrapper'; import { GoalApplicationButtonGroup } from './GoalApplicationButtonGroup'; const mutationSpy = jest.fn(); -const TestComponent: React.FC = () => ( - +const TestComponent: React.FC<{ geographicLocation?: string | null }> = ({ + geographicLocation, +}) => ( + ); @@ -65,4 +77,32 @@ describe('GoalApplicationButtonGroup', () => { await findByText('Successfully updated your monthly goal to $16,139!'), ).toBeInTheDocument(); }); + + it('sends geographicLocation when the goal calculation has one', async () => { + const { getByRole, findByText } = render( + , + ); + + const applyButton = getByRole('button', { name: /apply goal to mpdx/i }); + await waitFor(() => expect(applyButton).toBeEnabled()); + userEvent.click(applyButton); + + await waitFor(() => + expect(mutationSpy).toHaveGraphqlOperation('UpdateAccountPreferences', { + input: { + id: 'account-list-1', + attributes: { + id: 'account-list-1', + settings: { geographicLocation: 'Miami, FL' }, + }, + }, + }), + ); + + expect( + await findByText( + 'Successfully updated your monthly goal to $16,139 and geographic location to Miami, FL!', + ), + ).toBeInTheDocument(); + }); }); diff --git a/src/components/HrTools/GoalCalculator/SummaryReport/Steps/PresentingYourGoalStep/GoalApplicationButtonGroup.tsx b/src/components/HrTools/GoalCalculator/SummaryReport/Steps/PresentingYourGoalStep/GoalApplicationButtonGroup.tsx index f850f11b7d..90a7ea8507 100644 --- a/src/components/HrTools/GoalCalculator/SummaryReport/Steps/PresentingYourGoalStep/GoalApplicationButtonGroup.tsx +++ b/src/components/HrTools/GoalCalculator/SummaryReport/Steps/PresentingYourGoalStep/GoalApplicationButtonGroup.tsx @@ -1,50 +1,26 @@ import React, { useState } from 'react'; import { Button, CircularProgress, Stack } from '@mui/material'; -import { useSnackbar } from 'notistack'; import { useTranslation } from 'react-i18next'; -import { useUpdateAccountPreferencesMutation } from 'src/components/Settings/preferences/accordions/UpdateAccountPreferences.generated'; -import { useAccountListId } from 'src/hooks/useAccountListId'; -import { useLocale } from 'src/hooks/useLocale'; -import { currencyFormat } from 'src/lib/intlFormat'; +import { useApplyGoalAndLocation } from 'src/hooks/useApplyGoalAndLocation'; import { useGoalCalculator } from '../../../Shared/GoalCalculatorContext'; export const GoalApplicationButtonGroup: React.FC = () => { const { t } = useTranslation(); - const locale = useLocale(); - const { enqueueSnackbar } = useSnackbar(); const { goalCalculationResult, goalTotals: { overallTotal }, constants, } = useGoalCalculator(); const monthlyGoal = Math.round(overallTotal); - const [updateAccountPreferences, { loading }] = - useUpdateAccountPreferencesMutation(); - const accountListId = useAccountListId() || ''; + const geographicLocation = + goalCalculationResult.data?.goalCalculation?.geographicLocation ?? null; + const { applyMonthlyGoal, loading } = + useApplyGoalAndLocation(geographicLocation); const [buttonsHidden, setButtonsHidden] = useState(false); const onSave = async () => { - await updateAccountPreferences({ - variables: { - input: { - id: accountListId, - attributes: { - id: accountListId, - settings: { monthlyGoal }, - }, - }, - }, - onCompleted: () => { - enqueueSnackbar( - t('Successfully updated your monthly goal to {{formattedTotal}}!', { - formattedTotal: currencyFormat(monthlyGoal, 'USD', locale), - }), - { - variant: 'success', - }, - ); - }, - }); + await applyMonthlyGoal(monthlyGoal); + setButtonsHidden(true); }; if (buttonsHidden) { @@ -62,10 +38,7 @@ export const GoalApplicationButtonGroup: React.FC = () => { >