diff --git a/src/ROUTES.ts b/src/ROUTES.ts index 8df6f8c4c7de..dd66a515578f 100644 --- a/src/ROUTES.ts +++ b/src/ROUTES.ts @@ -2503,6 +2503,12 @@ const ROUTES = { // eslint-disable-next-line no-restricted-syntax -- Legacy route generation getRoute: (backTo?: string) => getUrlWithBackToParam(`onboarding/workspace-currency`, backTo), }, + CURRENCY_SELECTION: { + route: 'workspace/confirmation/currency', + + // eslint-disable-next-line no-restricted-syntax -- Legacy route generation + getRoute: (backTo?: string) => getUrlWithBackToParam(`workspace/confirmation/currency`, backTo), + }, ONBOARDING_WORKSPACE_INVITE: { route: 'onboarding/workspace-invite', diff --git a/src/SCREENS.ts b/src/SCREENS.ts index 1ce7dd940c17..090fae7a7487 100644 --- a/src/SCREENS.ts +++ b/src/SCREENS.ts @@ -721,6 +721,10 @@ const SCREENS = { WORKSPACE_INVITE: 'Onboarding_Workspace_Invite', }, + CURRENCY: { + SELECTION: 'Currency_Selection', + }, + EXPLANATION_MODAL: { ROOT: 'Explanation_Modal_Root', }, diff --git a/src/components/CurrencySelector.tsx b/src/components/CurrencySelector.tsx index 173df982c749..1d45860f5d32 100644 --- a/src/components/CurrencySelector.tsx +++ b/src/components/CurrencySelector.tsx @@ -1,10 +1,10 @@ import {useIsFocused} from '@react-navigation/native'; -import React, {forwardRef, useEffect, useRef} from 'react'; import type {ForwardedRef} from 'react'; +import React, {forwardRef, useEffect, useRef} from 'react'; import type {View} from 'react-native'; -import type {ValueOf} from 'type-fest'; import useLocalize from '@hooks/useLocalize'; import useThemeStyles from '@hooks/useThemeStyles'; +import {getCurrencySymbol} from '@libs/CurrencyUtils'; import Navigation from '@libs/Navigation/Navigation'; import CONST from '@src/CONST'; import ROUTES from '@src/ROUTES'; @@ -15,10 +15,10 @@ type CurrencySelectorProps = { errorText?: string; /** Callback called when the currency changes. */ - onInputChange?: (value?: string) => void; + onInputChange?: (value?: string, key?: string) => void; /** Current selected currency */ - value?: ValueOf; + value?: string; /** inputID used by the Form component */ // eslint-disable-next-line react/no-unused-prop-types @@ -28,20 +28,35 @@ type CurrencySelectorProps = { onBlur?: () => void; /** object to get route details from */ - currencySelectorRoute?: typeof ROUTES.SETTINGS_SUBSCRIPTION_CHANGE_PAYMENT_CURRENCY | typeof ROUTES.SETTINGS_CHANGE_CURRENCY; + currencySelectorRoute?: typeof ROUTES.SETTINGS_SUBSCRIPTION_CHANGE_PAYMENT_CURRENCY | typeof ROUTES.SETTINGS_CHANGE_CURRENCY | typeof ROUTES.CURRENCY_SELECTION; + + /** Label for the input */ + label?: string; + + /** Whether to show currency symbol in the title */ + shouldShowCurrencySymbol?: boolean; }; function CurrencySelector( - {errorText = '', value: currency, onInputChange = () => {}, onBlur, currencySelectorRoute = ROUTES.SETTINGS_CHANGE_CURRENCY}: CurrencySelectorProps, + { + errorText = '', + value: currency, + onInputChange = () => {}, + onBlur, + currencySelectorRoute = ROUTES.SETTINGS_CHANGE_CURRENCY, + label, + shouldShowCurrencySymbol = false, + }: CurrencySelectorProps, ref: ForwardedRef, ) { const styles = useThemeStyles(); const {translate} = useLocalize(); - const currencyTitleDescStyle = currency ? styles.textNormal : null; + const currencyTitleDescStyle = currency && !shouldShowCurrencySymbol ? styles.textNormal : null; const didOpenCurrencySelector = useRef(false); const isFocused = useIsFocused(); + useEffect(() => { if (!isFocused || !didOpenCurrencySelector.current) { return; @@ -59,15 +74,19 @@ function CurrencySelector( return ( { didOpenCurrencySelector.current = true; - Navigation.navigate(currencySelectorRoute); + if (currencySelectorRoute === ROUTES.CURRENCY_SELECTION) { + Navigation.navigate(currencySelectorRoute.getRoute(Navigation.getActiveRoute())); + } else { + Navigation.navigate(currencySelectorRoute as typeof ROUTES.SETTINGS_SUBSCRIPTION_CHANGE_PAYMENT_CURRENCY | typeof ROUTES.SETTINGS_CHANGE_CURRENCY); + } }} /> ); diff --git a/src/components/WorkspaceConfirmationForm.tsx b/src/components/WorkspaceConfirmationForm.tsx index 53da5bf9eacf..9075e43224d9 100644 --- a/src/components/WorkspaceConfirmationForm.tsx +++ b/src/components/WorkspaceConfirmationForm.tsx @@ -1,10 +1,12 @@ -import React, {useCallback, useMemo, useState} from 'react'; +import React, {useCallback, useEffect, useMemo, useState} from 'react'; import {View} from 'react-native'; import useAutoFocusInput from '@hooks/useAutoFocusInput'; +import useCurrentUserPersonalDetails from '@hooks/useCurrentUserPersonalDetails'; import useLocalize from '@hooks/useLocalize'; import useOnyx from '@hooks/useOnyx'; import useThemeStyles from '@hooks/useThemeStyles'; import useWorkspaceConfirmationAvatar from '@hooks/useWorkspaceConfirmationAvatar'; +import {clearDraftValues} from '@libs/actions/FormActions'; import {generateDefaultWorkspaceName, generatePolicyID} from '@libs/actions/Policy/Policy'; import type {CustomRNImageManipulatorResult} from '@libs/cropOrRotateImage/types'; import {addErrorMessage} from '@libs/ErrorUtils'; @@ -14,10 +16,11 @@ import {getDefaultWorkspaceAvatar} from '@libs/ReportUtils'; import {isRequiredFulfilled} from '@libs/ValidationUtils'; import CONST from '@src/CONST'; import ONYXKEYS from '@src/ONYXKEYS'; +import ROUTES from '@src/ROUTES'; import INPUT_IDS from '@src/types/form/WorkspaceConfirmationForm'; import isLoadingOnyxValue from '@src/types/utils/isLoadingOnyxValue'; import AvatarWithImagePicker from './AvatarWithImagePicker'; -import CurrencyPicker from './CurrencyPicker'; +import CurrencySelector from './CurrencySelector'; import FormProvider from './Form/FormProvider'; import InputWrapper from './Form/InputWrapper'; import type {FormInputErrors, FormOnyxValues} from './Form/types'; @@ -81,12 +84,19 @@ function WorkspaceConfirmationForm({onSubmit, policyOwnerEmail = '', onBackButto const policyID = useMemo(() => generatePolicyID(), []); const [session, metadata] = useOnyx(ONYXKEYS.SESSION, {canBeMissing: false}); - const [allPersonalDetails] = useOnyx(ONYXKEYS.PERSONAL_DETAILS_LIST, {canBeMissing: false}); + const currentUserPersonalDetails = useCurrentUserPersonalDetails(); + const [draftValues] = useOnyx(ONYXKEYS.FORMS.WORKSPACE_CONFIRMATION_FORM_DRAFT, {canBeMissing: true}); const defaultWorkspaceName = generateDefaultWorkspaceName(policyOwnerEmail || session?.email); const [workspaceNameFirstCharacter, setWorkspaceNameFirstCharacter] = useState(defaultWorkspaceName ?? ''); - const userCurrency = allPersonalDetails?.[session?.accountID ?? CONST.DEFAULT_NUMBER_ID]?.localCurrencyCode ?? CONST.CURRENCY.USD; + const userCurrency = draftValues?.currency ?? currentUserPersonalDetails?.localCurrencyCode ?? CONST.CURRENCY.USD; + + useEffect(() => { + return () => { + clearDraftValues(ONYXKEYS.FORMS.WORKSPACE_CONFIRMATION_FORM); + }; + }, []); const [workspaceAvatar, setWorkspaceAvatar] = useState<{avatarUri: string | null; avatarFileName?: string | null; avatarFileType?: string | null}>({ avatarUri: null, @@ -179,10 +189,12 @@ function WorkspaceConfirmationForm({onSubmit, policyOwnerEmail = '', onBackButto diff --git a/src/libs/Navigation/AppNavigator/ModalStackNavigators/index.tsx b/src/libs/Navigation/AppNavigator/ModalStackNavigators/index.tsx index 9ecf8b75ffbe..16e26c0437ad 100644 --- a/src/libs/Navigation/AppNavigator/ModalStackNavigators/index.tsx +++ b/src/libs/Navigation/AppNavigator/ModalStackNavigators/index.tsx @@ -232,6 +232,7 @@ const ReportSettingsModalStackNavigator = createModalStackNavigator({ [SCREENS.WORKSPACE_CONFIRMATION.ROOT]: () => require('../../../../pages/workspace/WorkspaceConfirmationPage').default, + [SCREENS.CURRENCY.SELECTION]: () => require('../../../../pages/CurrencySelectionPage').default, }); const WorkspaceDuplicateModalStackNavigator = createModalStackNavigator({ diff --git a/src/libs/Navigation/linkingConfig/config.ts b/src/libs/Navigation/linkingConfig/config.ts index 4d2fb1b6b09f..34f2d473c61b 100644 --- a/src/libs/Navigation/linkingConfig/config.ts +++ b/src/libs/Navigation/linkingConfig/config.ts @@ -1263,6 +1263,7 @@ const config: LinkingOptions['config'] = { [SCREENS.RIGHT_MODAL.WORKSPACE_CONFIRMATION]: { screens: { [SCREENS.WORKSPACE_CONFIRMATION.ROOT]: ROUTES.WORKSPACE_CONFIRMATION.route, + [SCREENS.CURRENCY.SELECTION]: ROUTES.CURRENCY_SELECTION.route, }, }, [SCREENS.RIGHT_MODAL.WORKSPACE_DUPLICATE]: { diff --git a/src/libs/Navigation/types.ts b/src/libs/Navigation/types.ts index 6997cf171388..e005058e3e7d 100644 --- a/src/libs/Navigation/types.ts +++ b/src/libs/Navigation/types.ts @@ -1618,6 +1618,9 @@ type WorkspaceConfirmationNavigatorParamList = { [SCREENS.WORKSPACE_CONFIRMATION.ROOT]: { backTo?: Routes; }; + [SCREENS.CURRENCY.SELECTION]: { + backTo?: Routes; + }; }; type WorkspaceDuplicateNavigatorParamList = { diff --git a/src/libs/actions/Policy/Policy.ts b/src/libs/actions/Policy/Policy.ts index 94bf8f83ff2e..eeb9d10a73de 100644 --- a/src/libs/actions/Policy/Policy.ts +++ b/src/libs/actions/Policy/Policy.ts @@ -6329,6 +6329,13 @@ function clearPolicyTitleFieldError(policyID: string) { }); } +/** + * Set the workspace currency for the workspace confirmation form + */ +function setWorkspaceConfirmationCurrency(currency: string) { + Onyx.merge(ONYXKEYS.FORMS.WORKSPACE_CONFIRMATION_FORM_DRAFT, {currency}); +} + export { leaveWorkspace, addBillingCardAndRequestPolicyOwnerChange, @@ -6451,4 +6458,5 @@ export { updateInterestedFeatures, clearPolicyTitleFieldError, inviteWorkspaceEmployeesToUber, + setWorkspaceConfirmationCurrency, }; diff --git a/src/pages/CurrencySelectionPage.tsx b/src/pages/CurrencySelectionPage.tsx new file mode 100644 index 000000000000..d2ba92586dab --- /dev/null +++ b/src/pages/CurrencySelectionPage.tsx @@ -0,0 +1,66 @@ +import React, {useCallback} from 'react'; +import {View} from 'react-native'; +import CurrencySelectionList from '@components/CurrencySelectionList'; +import type {CurrencyListItem} from '@components/CurrencySelectionList/types'; +import HeaderWithBackButton from '@components/HeaderWithBackButton'; +import ScreenWrapper from '@components/ScreenWrapper'; +import useCurrentUserPersonalDetails from '@hooks/useCurrentUserPersonalDetails'; +import useLocalize from '@hooks/useLocalize'; +import useOnyx from '@hooks/useOnyx'; +import useThemeStyles from '@hooks/useThemeStyles'; +import {setWorkspaceConfirmationCurrency} from '@libs/actions/Policy/Policy'; +import Navigation from '@libs/Navigation/Navigation'; +import CONST from '@src/CONST'; +import ONYXKEYS from '@src/ONYXKEYS'; +import type {Route} from '@src/ROUTES'; + +type CurrencySelectionPageProps = { + route: { + params: { + backTo?: Route; + }; + }; +}; + +function CurrencySelectionPage({route}: CurrencySelectionPageProps) { + const styles = useThemeStyles(); + const {translate} = useLocalize(); + + const currentUserPersonalDetails = useCurrentUserPersonalDetails(); + const [workspaceConfirmationFormDraft] = useOnyx(ONYXKEYS.FORMS.WORKSPACE_CONFIRMATION_FORM_DRAFT, {canBeMissing: true}); + + const value = workspaceConfirmationFormDraft?.currency ?? currentUserPersonalDetails?.localCurrencyCode ?? CONST.CURRENCY.USD; + + const goBack = useCallback(() => { + const backTo = route?.params?.backTo; + Navigation.goBack(backTo); + }, [route?.params?.backTo]); + + const onSelect = useCallback( + (option: CurrencyListItem) => { + setWorkspaceConfirmationCurrency(option.currencyCode); + goBack(); + }, + [goBack], + ); + + return ( + + + + + + + ); +} + +CurrencySelectionPage.displayName = 'CurrencySelectionPage'; + +export default CurrencySelectionPage;