From cd8ca07937025d621e7fb6802526e2a64b08aff5 Mon Sep 17 00:00:00 2001 From: Yogesh Bhatt Date: Sat, 7 Oct 2023 12:53:52 +0530 Subject: [PATCH 001/698] Convert StatePicker modal to StateSelection page --- src/ROUTES.ts | 16 ++ .../StatePicker/StateSelectorModal.js | 112 -------------- src/components/StatePicker/index.js | 97 ------------- src/components/StateSelector.js | 87 +++++++++++ .../AppNavigator/ModalStackNavigators.js | 1 + src/libs/Navigation/linkingConfig.js | 4 + src/libs/getStateFromRoute.ts | 13 ++ src/pages/ReimbursementAccount/AddressForm.js | 4 +- src/pages/ReimbursementAccount/CompanyStep.js | 23 ++- .../ReimbursementAccountPage.js | 1 + .../Profile/PersonalDetails/AddressPage.js | 22 ++- .../PersonalDetails/StateSelectionPage.js | 137 ++++++++++++++++++ src/pages/settings/Wallet/AddDebitCardPage.js | 19 ++- src/stories/Form.stories.js | 6 +- 14 files changed, 317 insertions(+), 225 deletions(-) delete mode 100644 src/components/StatePicker/StateSelectorModal.js delete mode 100644 src/components/StatePicker/index.js create mode 100644 src/components/StateSelector.js create mode 100644 src/libs/getStateFromRoute.ts create mode 100644 src/pages/settings/Profile/PersonalDetails/StateSelectionPage.js diff --git a/src/ROUTES.ts b/src/ROUTES.ts index b2dafa643b22..642e8ec8a2d0 100644 --- a/src/ROUTES.ts +++ b/src/ROUTES.ts @@ -94,6 +94,22 @@ export default { return route; }, }, + SETTINGS_PERSONAL_DETAILS_ADDRESS_STATE: { + route: 'settings/profile/personal-details/address/state', + getRoute: (state: string, backTo?: string, label?: string, stateParamName = 'state') => { + let route = `settings/profile/personal-details/address/state?state=${state}`; + if (backTo) { + route += `&backTo=${encodeURIComponent(backTo)}`; + } + if (label) { + route += `&label=${encodeURIComponent(label)}`; + } + if (stateParamName) { + route += `&stateParamName=${encodeURIComponent(stateParamName)}`; + } + return route; + }, + }, SETTINGS_CONTACT_METHODS: 'settings/profile/contact-methods', SETTINGS_CONTACT_METHOD_DETAILS: { route: 'settings/profile/contact-methods/:contactMethod/details', diff --git a/src/components/StatePicker/StateSelectorModal.js b/src/components/StatePicker/StateSelectorModal.js deleted file mode 100644 index 378dcc4ebc8b..000000000000 --- a/src/components/StatePicker/StateSelectorModal.js +++ /dev/null @@ -1,112 +0,0 @@ -import _ from 'underscore'; -import React, {useMemo, useEffect} from 'react'; -import PropTypes from 'prop-types'; -import {CONST as COMMON_CONST} from 'expensify-common/lib/CONST'; -import CONST from '../../CONST'; -import Modal from '../Modal'; -import HeaderWithBackButton from '../HeaderWithBackButton'; -import SelectionList from '../SelectionList'; -import useLocalize from '../../hooks/useLocalize'; -import ScreenWrapper from '../ScreenWrapper'; -import styles from '../../styles/styles'; -import searchCountryOptions from '../../libs/searchCountryOptions'; -import StringUtils from '../../libs/StringUtils'; - -const propTypes = { - /** Whether the modal is visible */ - isVisible: PropTypes.bool.isRequired, - - /** State value selected */ - currentState: PropTypes.string, - - /** Function to call when the user selects a State */ - onStateSelected: PropTypes.func, - - /** Function to call when the user closes the State modal */ - onClose: PropTypes.func, - - /** The search value from the selection list */ - searchValue: PropTypes.string.isRequired, - - /** Function to call when the user types in the search input */ - setSearchValue: PropTypes.func.isRequired, - - /** Label to display on field */ - label: PropTypes.string, -}; - -const defaultProps = { - currentState: '', - onClose: () => {}, - onStateSelected: () => {}, - label: undefined, -}; - -function StateSelectorModal({currentState, isVisible, onClose, onStateSelected, searchValue, setSearchValue, label}) { - const {translate} = useLocalize(); - - useEffect(() => { - if (isVisible) { - return; - } - setSearchValue(''); - }, [isVisible, setSearchValue]); - - const countryStates = useMemo( - () => - _.map(_.keys(COMMON_CONST.STATES), (state) => { - const stateName = translate(`allStates.${state}.stateName`); - const stateISO = translate(`allStates.${state}.stateISO`); - return { - value: stateISO, - keyForList: stateISO, - text: stateName, - isSelected: currentState === stateISO, - searchValue: StringUtils.sanitizeString(`${stateISO}${stateName}`), - }; - }), - [translate, currentState], - ); - - const searchResults = searchCountryOptions(searchValue, countryStates); - const headerMessage = searchValue.trim() && !searchResults.length ? translate('common.noResultsFound') : ''; - - return ( - - - - - - - ); -} - -StateSelectorModal.propTypes = propTypes; -StateSelectorModal.defaultProps = defaultProps; -StateSelectorModal.displayName = 'StateSelectorModal'; - -export default StateSelectorModal; diff --git a/src/components/StatePicker/index.js b/src/components/StatePicker/index.js deleted file mode 100644 index f7f894af2a07..000000000000 --- a/src/components/StatePicker/index.js +++ /dev/null @@ -1,97 +0,0 @@ -import React, {useState} from 'react'; -import {View} from 'react-native'; -import PropTypes from 'prop-types'; -import _ from 'underscore'; -import {CONST as COMMON_CONST} from 'expensify-common/lib/CONST'; -import styles from '../../styles/styles'; -import MenuItemWithTopDescription from '../MenuItemWithTopDescription'; -import useLocalize from '../../hooks/useLocalize'; -import FormHelpMessage from '../FormHelpMessage'; -import StateSelectorModal from './StateSelectorModal'; -import refPropTypes from '../refPropTypes'; - -const propTypes = { - /** Error text to display */ - errorText: PropTypes.string, - - /** State to display */ - value: PropTypes.string, - - /** Callback to call when the input changes */ - onInputChange: PropTypes.func, - - /** A ref to forward to MenuItemWithTopDescription */ - forwardedRef: refPropTypes, - - /** Label to display on field */ - label: PropTypes.string, -}; - -const defaultProps = { - value: undefined, - forwardedRef: undefined, - errorText: '', - onInputChange: () => {}, - label: undefined, -}; - -function StatePicker({value, errorText, onInputChange, forwardedRef, label}) { - const {translate} = useLocalize(); - const [isPickerVisible, setIsPickerVisible] = useState(false); - const [searchValue, setSearchValue] = useState(''); - - const showPickerModal = () => { - setIsPickerVisible(true); - }; - - const hidePickerModal = () => { - setIsPickerVisible(false); - }; - - const updateStateInput = (state) => { - if (state.value !== value) { - onInputChange(state.value); - } - hidePickerModal(); - }; - - const title = value && _.keys(COMMON_CONST.STATES).includes(value) ? translate(`allStates.${value}.stateName`) : ''; - const descStyle = title.length === 0 ? styles.textNormal : null; - - return ( - - - - - - - - ); -} - -StatePicker.propTypes = propTypes; -StatePicker.defaultProps = defaultProps; -StatePicker.displayName = 'StatePicker'; - -export default React.forwardRef((props, ref) => ( - -)); diff --git a/src/components/StateSelector.js b/src/components/StateSelector.js new file mode 100644 index 000000000000..c004fb8bf375 --- /dev/null +++ b/src/components/StateSelector.js @@ -0,0 +1,87 @@ +import React, {useEffect} from 'react'; +import PropTypes from 'prop-types'; +import {View} from 'react-native'; +import _ from 'underscore'; +import {CONST as COMMON_CONST} from 'expensify-common/lib/CONST'; +import styles from '../styles/styles'; +import Navigation from '../libs/Navigation/Navigation'; +import ROUTES from '../ROUTES'; +import useLocalize from '../hooks/useLocalize'; +import MenuItemWithTopDescription from './MenuItemWithTopDescription'; +import FormHelpMessage from './FormHelpMessage'; + +const propTypes = { + /** Form error text. e.g when no country is selected */ + errorText: PropTypes.string, + + /** Callback called when the country changes. */ + onInputChange: PropTypes.func.isRequired, + + /** Current selected country */ + value: PropTypes.string, + + /** inputID used by the Form component */ + // eslint-disable-next-line react/no-unused-prop-types + inputID: PropTypes.string.isRequired, + + /** React ref being forwarded to the MenuItemWithTopDescription */ + forwardedRef: PropTypes.func, + + /** Label of state in the url */ + paramName: PropTypes.string, + + /** Label to display on field */ + label: PropTypes.string, +}; + +const defaultProps = { + errorText: '', + value: undefined, + forwardedRef: () => {}, + label: undefined, + paramName: 'state', +}; + +function StateSelector({errorText, value: stateCode, label, paramName, onInputChange, forwardedRef}) { + const {translate} = useLocalize(); + + const title = stateCode && _.keys(COMMON_CONST.STATES).includes(stateCode) ? translate(`allStates.${stateCode}.stateName`) : ''; + const descStyle = title.length === 0 ? styles.textNormal : null; + + useEffect(() => { + // This will cause the form to revalidate and remove any error related to country name + onInputChange(stateCode); + // eslint-disable-next-line react-hooks/exhaustive-deps + }, [stateCode]); + + return ( + + { + const activeRoute = Navigation.getActiveRoute(); + Navigation.navigate(ROUTES.SETTINGS_PERSONAL_DETAILS_ADDRESS_STATE.getRoute(stateCode, activeRoute, label, paramName)); + }} + /> + + + + + ); +} + +StateSelector.propTypes = propTypes; +StateSelector.defaultProps = defaultProps; +StateSelector.displayName = 'StateSelector'; + +export default React.forwardRef((props, ref) => ( + +)); diff --git a/src/libs/Navigation/AppNavigator/ModalStackNavigators.js b/src/libs/Navigation/AppNavigator/ModalStackNavigators.js index 6636702592c0..f682d438f270 100644 --- a/src/libs/Navigation/AppNavigator/ModalStackNavigators.js +++ b/src/libs/Navigation/AppNavigator/ModalStackNavigators.js @@ -127,6 +127,7 @@ const SettingsModalStackNavigator = createModalStackNavigator({ Settings_PersonalDetails_DateOfBirth: () => require('../../../pages/settings/Profile/PersonalDetails/DateOfBirthPage').default, Settings_PersonalDetails_Address: () => require('../../../pages/settings/Profile/PersonalDetails/AddressPage').default, Settings_PersonalDetails_Address_Country: () => require('../../../pages/settings/Profile/PersonalDetails/CountrySelectionPage').default, + Settings_PersonalDetails_Address_State: () => require('../../../pages/settings/Profile/PersonalDetails/StateSelectionPage').default, Settings_ContactMethods: () => require('../../../pages/settings/Profile/Contacts/ContactMethodsPage').default, Settings_ContactMethodDetails: () => require('../../../pages/settings/Profile/Contacts/ContactMethodDetailsPage').default, Settings_NewContactMethod: () => require('../../../pages/settings/Profile/Contacts/NewContactMethodPage').default, diff --git a/src/libs/Navigation/linkingConfig.js b/src/libs/Navigation/linkingConfig.js index bf069aba314e..1b39987e7257 100644 --- a/src/libs/Navigation/linkingConfig.js +++ b/src/libs/Navigation/linkingConfig.js @@ -155,6 +155,10 @@ export default { path: ROUTES.SETTINGS_PERSONAL_DETAILS_ADDRESS_COUNTRY.route, exact: true, }, + Settings_PersonalDetails_Address_State: { + path: ROUTES.SETTINGS_PERSONAL_DETAILS_ADDRESS_STATE.route, + exact: true, + }, Settings_TwoFactorAuth: { path: ROUTES.SETTINGS_2FA, exact: true, diff --git a/src/libs/getStateFromRoute.ts b/src/libs/getStateFromRoute.ts new file mode 100644 index 000000000000..ff01068eae3e --- /dev/null +++ b/src/libs/getStateFromRoute.ts @@ -0,0 +1,13 @@ +// eslint-disable-next-line you-dont-need-lodash-underscore/get +import lodashGet from 'lodash/get'; +import {CONST as COMMON_CONST} from 'expensify-common/lib/CONST'; + +type RouteProps = { + params?: Record; +}; + +export default function getStateFromRoute(route: RouteProps, stateParamName = 'state'): string { + const stateFromUrlTemp = lodashGet(route, `params.${stateParamName}`) as unknown as string; + // check if state is valid + return lodashGet(COMMON_CONST.STATES, stateFromUrlTemp) ? stateFromUrlTemp : ''; +} diff --git a/src/pages/ReimbursementAccount/AddressForm.js b/src/pages/ReimbursementAccount/AddressForm.js index d8fbc0290136..09e365b58c63 100644 --- a/src/pages/ReimbursementAccount/AddressForm.js +++ b/src/pages/ReimbursementAccount/AddressForm.js @@ -5,7 +5,7 @@ import TextInput from '../../components/TextInput'; import AddressSearch from '../../components/AddressSearch'; import styles from '../../styles/styles'; import CONST from '../../CONST'; -import StatePicker from '../../components/StatePicker'; +import StateSelector from '../../components/StateSelector'; const propTypes = { /** Translate key for Street name */ @@ -123,7 +123,7 @@ function AddressForm(props) { /> - - lodashGet(privatePersonalDetails, 'address') || {}, [privatePersonalDetails]); - const countryFromUrl = lodashGet(route, 'params.country'); + + const countryFromUrlTemp = lodashGet(route, 'params.country'); + // check if country is valid + const countryFromUrl = lodashGet(CONST.ALL_COUNTRIES, countryFromUrlTemp) ? countryFromUrlTemp : ''; + + const stateFromUrl = getStateFromRoute(route); const [currentCountry, setCurrentCountry] = useState(address.country); const zipSampleFormat = lodashGet(CONST.COUNTRY_ZIP_REGEX_DATA, [currentCountry, 'samples'], ''); const zipFormat = translate('common.zipCodeExampleFormat', {zipSampleFormat}); @@ -160,6 +166,13 @@ function AddressPage({privatePersonalDetails, route}) { handleAddressChange(countryFromUrl, 'country'); }, [countryFromUrl, handleAddressChange, currentCountry]); + useEffect(() => { + if (!stateFromUrl || stateFromUrl === state) { + return; + } + handleAddressChange(stateFromUrl, 'state'); + }, [state, handleAddressChange, stateFromUrl]); + return ( {isUSAForm ? ( - ) : ( diff --git a/src/pages/settings/Profile/PersonalDetails/StateSelectionPage.js b/src/pages/settings/Profile/PersonalDetails/StateSelectionPage.js new file mode 100644 index 000000000000..34364421b4ac --- /dev/null +++ b/src/pages/settings/Profile/PersonalDetails/StateSelectionPage.js @@ -0,0 +1,137 @@ +import React, {useState, useMemo, useCallback} from 'react'; +import PropTypes from 'prop-types'; +import _ from 'underscore'; +import {CONST as COMMON_CONST} from 'expensify-common/lib/CONST'; +import lodashGet from 'lodash/get'; +import Navigation from '../../../../libs/Navigation/Navigation'; +import ScreenWrapper from '../../../../components/ScreenWrapper'; +import HeaderWithBackButton from '../../../../components/HeaderWithBackButton'; +import SelectionList from '../../../../components/SelectionList'; +import searchCountryOptions from '../../../../libs/searchCountryOptions'; +import StringUtils from '../../../../libs/StringUtils'; +import useLocalize from '../../../../hooks/useLocalize'; +import styles from '../../../../styles/styles'; + +const propTypes = { + /** Route from navigation */ + route: PropTypes.shape({ + /** Params from the route */ + params: PropTypes.shape({ + /** Currently selected country */ + country: PropTypes.string, + + /** Route to navigate back after selecting a currency */ + backTo: PropTypes.string, + }), + }).isRequired, + + /** Navigation from react-navigation */ + navigation: PropTypes.shape({ + /** getState function retrieves the current navigation state from react-navigation's navigation property */ + getState: PropTypes.func.isRequired, + }).isRequired, +}; + +/** + * Appends or updates a query parameter in a given URL. + * + * @param {string} url - The original URL. + * @param {string} paramName - The name of the query parameter to append or update. + * @param {string} paramValue - The value of the query parameter to append or update. + * @returns {string} The updated URL with the appended or updated query parameter. + */ +function appendParam(url, paramName, paramValue) { + if (url.includes(`${paramName}=`)) { + // If parameter exists, replace it + const regex = new RegExp(`${paramName}=([^&]*)`); + return url.replace(regex, `${paramName}=${paramValue}`); + } + // If parameter doesn't exist, append it + const separator = url.includes('?') ? '&' : '?'; + return `${url}${separator}${paramName}=${paramValue}`; +} + +function StateSelectionPage({route, navigation}) { + const [searchValue, setSearchValue] = useState(''); + const {translate} = useLocalize(); + const currentState = lodashGet(route, 'params.state'); + const stateParamName = lodashGet(route, 'params.stateParamName') || 'state'; + const label = lodashGet(route, 'params.label'); + + const countryStates = useMemo( + () => + _.map(_.keys(COMMON_CONST.STATES), (state) => { + const stateName = translate(`allStates.${state}.stateName`); + const stateISO = translate(`allStates.${state}.stateISO`); + return { + value: stateISO, + keyForList: stateISO, + text: stateName, + isSelected: currentState === stateISO, + searchValue: StringUtils.sanitizeString(`${stateISO}${stateName}`), + }; + }), + [translate, currentState], + ); + + const searchResults = searchCountryOptions(searchValue, countryStates); + const headerMessage = searchValue.trim() && !searchResults.length ? translate('common.noResultsFound') : ''; + + const selectCountryState = useCallback( + (option) => { + const backTo = lodashGet(route, 'params.backTo', ''); + + // Check the navigation state and "backTo" parameter to decide navigation behavior + if (navigation.getState().routes.length === 1 && _.isEmpty(backTo)) { + // If there is only one route and "backTo" is empty, go back in navigation + Navigation.goBack(); + } else if (!_.isEmpty(backTo) && navigation.getState().routes.length === 1) { + // If "backTo" is not empty and there is only one route, go back to the specific route defined in "backTo" with a country parameter + Navigation.goBack(appendParam(backTo, stateParamName, option.value)); + } else { + // Otherwise, navigate to the specific route defined in "backTo" with a country parameter + Navigation.navigate(appendParam(backTo, stateParamName, option.value)); + } + }, + [route, navigation, stateParamName], + ); + + return ( + + { + const backTo = lodashGet(route, 'params.backTo', ''); + let backToRoute = ''; + + if (backTo) { + backToRoute = appendParam(backTo, stateParamName, currentState); + } + + Navigation.goBack(backToRoute); + }} + /> + + + + ); +} + +StateSelectionPage.displayName = 'StateSelectionPage'; +StateSelectionPage.propTypes = propTypes; + +export default StateSelectionPage; diff --git a/src/pages/settings/Wallet/AddDebitCardPage.js b/src/pages/settings/Wallet/AddDebitCardPage.js index e75c3b2c517e..201a4e763693 100644 --- a/src/pages/settings/Wallet/AddDebitCardPage.js +++ b/src/pages/settings/Wallet/AddDebitCardPage.js @@ -11,7 +11,6 @@ import useLocalize from '../../../hooks/useLocalize'; import * as PaymentMethods from '../../../libs/actions/PaymentMethods'; import * as ValidationUtils from '../../../libs/ValidationUtils'; import CheckboxWithLabel from '../../../components/CheckboxWithLabel'; -import StatePicker from '../../../components/StatePicker'; import TextInput from '../../../components/TextInput'; import CONST from '../../../CONST'; import ONYXKEYS from '../../../ONYXKEYS'; @@ -22,6 +21,8 @@ import ROUTES from '../../../ROUTES'; import usePrevious from '../../../hooks/usePrevious'; import NotFoundPage from '../../ErrorPage/NotFoundPage'; import Permissions from '../../../libs/Permissions'; +import StateSelector from '../../../components/StateSelector'; +import getStateFromRoute from '../../../libs/getStateFromRoute'; const propTypes = { /* Onyx Props */ @@ -31,6 +32,15 @@ const propTypes = { /** List of betas available to current user */ betas: PropTypes.arrayOf(PropTypes.string), + + /** Route from navigation */ + route: PropTypes.shape({ + /** Params from the route */ + params: PropTypes.shape({ + /** Currently selected country */ + country: PropTypes.string, + }), + }).isRequired, }; const defaultProps = { @@ -104,6 +114,8 @@ function DebitCardPage(props) { return ; } + const stateFromUrl = getStateFromRoute(props.route); + return ( nameOnCardRef.current && nameOnCardRef.current.focus()} @@ -182,7 +194,10 @@ function DebitCardPage(props) { containerStyles={[styles.mt4]} /> - + From 1284e59cf00621f0012d38187e0738b1e7c3e8dc Mon Sep 17 00:00:00 2001 From: Yogesh Bhatt Date: Sat, 7 Oct 2023 14:43:44 +0530 Subject: [PATCH 002/698] Incorporation state resets bugfix --- src/pages/ReimbursementAccount/CompanyStep.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/pages/ReimbursementAccount/CompanyStep.js b/src/pages/ReimbursementAccount/CompanyStep.js index ef7674894445..4bac76dbd164 100644 --- a/src/pages/ReimbursementAccount/CompanyStep.js +++ b/src/pages/ReimbursementAccount/CompanyStep.js @@ -262,7 +262,7 @@ function CompanyStep({reimbursementAccount, route, reimbursementAccountDraft, ge label={translate('companyStep.incorporationState')} shouldSaveDraft paramName="incorporationState" - value={incorporationState} + {...(incorporationState ? {value: incorporationState} : {})} /> Date: Sat, 7 Oct 2023 15:29:42 +0530 Subject: [PATCH 003/698] Modify pages to accomodate for StateSelection --- src/pages/EnablePayments/AdditionalDetailsStep.js | 15 ++++++++++++++- src/pages/EnablePayments/EnablePaymentsPage.js | 4 ++-- src/pages/ReimbursementAccount/ACHContractStep.js | 13 +++++++++++++ src/pages/ReimbursementAccount/CompanyStep.js | 4 ++-- .../ReimbursementAccountPage.js | 2 ++ src/pages/ReimbursementAccount/RequestorStep.js | 15 ++++++++++++++- .../Profile/PersonalDetails/AddressPage.js | 3 +++ .../Profile/PersonalDetails/StateSelectionPage.js | 4 ++-- src/pages/settings/Wallet/AddDebitCardPage.js | 4 ++-- 9 files changed, 54 insertions(+), 10 deletions(-) diff --git a/src/pages/EnablePayments/AdditionalDetailsStep.js b/src/pages/EnablePayments/AdditionalDetailsStep.js index c304103f69c7..f521346b5fcf 100644 --- a/src/pages/EnablePayments/AdditionalDetailsStep.js +++ b/src/pages/EnablePayments/AdditionalDetailsStep.js @@ -24,6 +24,7 @@ import Form from '../../components/Form'; import withCurrentUserPersonalDetails, {withCurrentUserPersonalDetailsPropTypes, withCurrentUserPersonalDetailsDefaultProps} from '../../components/withCurrentUserPersonalDetails'; import * as PersonalDetails from '../../libs/actions/PersonalDetails'; import OfflineIndicator from '../../components/OfflineIndicator'; +import getStateFromRoute from '../../libs/getStateFromRoute'; const propTypes = { ...withLocalizePropTypes, @@ -55,6 +56,15 @@ const propTypes = { /** Error code to determine additional behavior */ errorCode: PropTypes.string, }), + + /** Route from navigation */ + route: PropTypes.shape({ + /** Params from the route */ + params: PropTypes.shape({ + /** Currently selected state */ + state: PropTypes.string, + }), + }).isRequired, }; const defaultProps = { @@ -79,7 +89,7 @@ const fieldNameTranslationKeys = { ssnFull9: 'common.ssnFull9', }; -function AdditionalDetailsStep({walletAdditionalDetails, translate, currentUserPersonalDetails}) { +function AdditionalDetailsStep({walletAdditionalDetails, translate, route, currentUserPersonalDetails}) { const minDate = moment().subtract(CONST.DATE_BIRTH.MAX_AGE, 'Y').toDate(); const maxDate = moment().subtract(CONST.DATE_BIRTH.MIN_AGE_FOR_PAYMENT, 'Y').toDate(); const shouldAskForFullSSN = walletAdditionalDetails.errorCode === CONST.WALLET.ERROR.SSN; @@ -163,6 +173,8 @@ function AdditionalDetailsStep({walletAdditionalDetails, translate, currentUserP ); } + const state = getStateFromRoute(route); + return ( <> @@ -209,6 +221,7 @@ function AdditionalDetailsStep({walletAdditionalDetails, translate, currentUserP state: 'addressState', zipCode: 'addressZipCode', }} + values={state ? {state} : {}} translate={translate} streetTranslationKey={fieldNameTranslationKeys.addressStreet} shouldSaveDraft diff --git a/src/pages/EnablePayments/EnablePaymentsPage.js b/src/pages/EnablePayments/EnablePaymentsPage.js index f7ef2a174208..8feb8342ac8e 100644 --- a/src/pages/EnablePayments/EnablePaymentsPage.js +++ b/src/pages/EnablePayments/EnablePaymentsPage.js @@ -29,7 +29,7 @@ const defaultProps = { userWallet: {}, }; -function EnablePaymentsPage({userWallet}) { +function EnablePaymentsPage({userWallet, route}) { const {translate} = useLocalize(); const {isOffline} = useNetwork(); @@ -72,7 +72,7 @@ function EnablePaymentsPage({userWallet}) { switch (currentStep) { case CONST.WALLET.STEP.ADDITIONAL_DETAILS: case CONST.WALLET.STEP.ADDITIONAL_DETAILS_KBA: - return ; + return ; case CONST.WALLET.STEP.ONFIDO: return ; case CONST.WALLET.STEP.TERMS: diff --git a/src/pages/ReimbursementAccount/ACHContractStep.js b/src/pages/ReimbursementAccount/ACHContractStep.js index 761be71d864a..7209d6250a94 100644 --- a/src/pages/ReimbursementAccount/ACHContractStep.js +++ b/src/pages/ReimbursementAccount/ACHContractStep.js @@ -19,12 +19,22 @@ import Form from '../../components/Form'; import * as FormActions from '../../libs/actions/FormActions'; import ScreenWrapper from '../../components/ScreenWrapper'; import StepPropTypes from './StepPropTypes'; +import getStateFromRoute from '../../libs/getStateFromRoute'; const propTypes = { ...StepPropTypes, /** Name of the company */ companyName: PropTypes.string.isRequired, + + /** Route from navigation */ + route: PropTypes.shape({ + /** Params from the route */ + params: PropTypes.shape({ + /** Currently selected state */ + state: PropTypes.string, + }), + }).isRequired, }; function ACHContractStep(props) { @@ -144,6 +154,8 @@ function ACHContractStep(props) { }); }; + const state = getStateFromRoute(props.route); + return ( { return errors; }; -function RequestorStep({reimbursementAccount, shouldShowOnfido, reimbursementAccountDraft, onBackButtonPress, getDefaultStateForField}) { +function RequestorStep({reimbursementAccount, route, shouldShowOnfido, reimbursementAccountDraft, onBackButtonPress, getDefaultStateForField}) { const {translate} = useLocalize(); const defaultValues = useMemo( @@ -118,6 +128,8 @@ function RequestorStep({reimbursementAccount, shouldShowOnfido, reimbursementAcc ); } + const state = getStateFromRoute(route); + return ( Date: Sun, 8 Oct 2023 08:24:10 +0530 Subject: [PATCH 004/698] Refactor to use useGeographicalStateFromRoute hook --- src/hooks/useGeographicalStateFromRoute.ts | 7 +++++++ src/libs/getStateFromRoute.ts | 3 ++- .../EnablePayments/AdditionalDetailsStep.js | 17 ++++------------- src/pages/EnablePayments/EnablePaymentsPage.js | 4 ++-- .../ReimbursementAccount/ACHContractStep.js | 13 ++----------- src/pages/ReimbursementAccount/CompanyStep.js | 18 +++++------------- .../ReimbursementAccountPage.js | 3 --- .../ReimbursementAccount/RequestorStep.js | 17 ++++------------- .../Profile/PersonalDetails/AddressPage.js | 7 ++----- src/pages/settings/Wallet/AddDebitCardPage.js | 15 +++------------ 10 files changed, 31 insertions(+), 73 deletions(-) create mode 100644 src/hooks/useGeographicalStateFromRoute.ts diff --git a/src/hooks/useGeographicalStateFromRoute.ts b/src/hooks/useGeographicalStateFromRoute.ts new file mode 100644 index 000000000000..33866e8b0cf1 --- /dev/null +++ b/src/hooks/useGeographicalStateFromRoute.ts @@ -0,0 +1,7 @@ +import {useRoute} from '@react-navigation/native'; +import getStateFromRoute from '../libs/getStateFromRoute'; + +export default function useGeographicalStateFromRoute(stateParamName = 'state') { + const route = useRoute(); + return getStateFromRoute(route, stateParamName); +} diff --git a/src/libs/getStateFromRoute.ts b/src/libs/getStateFromRoute.ts index ff01068eae3e..19d6de46014f 100644 --- a/src/libs/getStateFromRoute.ts +++ b/src/libs/getStateFromRoute.ts @@ -3,7 +3,8 @@ import lodashGet from 'lodash/get'; import {CONST as COMMON_CONST} from 'expensify-common/lib/CONST'; type RouteProps = { - params?: Record; + // eslint-disable-next-line @typescript-eslint/no-explicit-any + params?: Record; }; export default function getStateFromRoute(route: RouteProps, stateParamName = 'state'): string { diff --git a/src/pages/EnablePayments/AdditionalDetailsStep.js b/src/pages/EnablePayments/AdditionalDetailsStep.js index 1d8691333069..5ab59899b139 100644 --- a/src/pages/EnablePayments/AdditionalDetailsStep.js +++ b/src/pages/EnablePayments/AdditionalDetailsStep.js @@ -24,7 +24,7 @@ import Form from '../../components/Form'; import withCurrentUserPersonalDetails, {withCurrentUserPersonalDetailsPropTypes, withCurrentUserPersonalDetailsDefaultProps} from '../../components/withCurrentUserPersonalDetails'; import * as PersonalDetails from '../../libs/actions/PersonalDetails'; import OfflineIndicator from '../../components/OfflineIndicator'; -import getStateFromRoute from '../../libs/getStateFromRoute'; +import useGeographicalStateFromRoute from '../../hooks/useGeographicalStateFromRoute'; const propTypes = { ...withLocalizePropTypes, @@ -56,15 +56,6 @@ const propTypes = { /** Error code to determine additional behavior */ errorCode: PropTypes.string, }), - - /** Route from navigation */ - route: PropTypes.shape({ - /** Params from the route */ - params: PropTypes.shape({ - /** Currently selected state */ - state: PropTypes.string, - }), - }).isRequired, }; const defaultProps = { @@ -89,7 +80,7 @@ const fieldNameTranslationKeys = { ssnFull9: 'common.ssnFull9', }; -function AdditionalDetailsStep({walletAdditionalDetails, route, translate, currentUserPersonalDetails}) { +function AdditionalDetailsStep({walletAdditionalDetails, translate, currentUserPersonalDetails}) { const currentDate = new Date(); const minDate = subYears(currentDate, CONST.DATE_BIRTH.MAX_AGE); const maxDate = subYears(currentDate, CONST.DATE_BIRTH.MIN_AGE_FOR_PAYMENT); @@ -155,6 +146,8 @@ function AdditionalDetailsStep({walletAdditionalDetails, route, translate, curre Wallet.updatePersonalDetails(personalDetails); }; + const state = useGeographicalStateFromRoute(); + if (!_.isEmpty(walletAdditionalDetails.questions)) { return ( diff --git a/src/pages/EnablePayments/EnablePaymentsPage.js b/src/pages/EnablePayments/EnablePaymentsPage.js index 8feb8342ac8e..f7ef2a174208 100644 --- a/src/pages/EnablePayments/EnablePaymentsPage.js +++ b/src/pages/EnablePayments/EnablePaymentsPage.js @@ -29,7 +29,7 @@ const defaultProps = { userWallet: {}, }; -function EnablePaymentsPage({userWallet, route}) { +function EnablePaymentsPage({userWallet}) { const {translate} = useLocalize(); const {isOffline} = useNetwork(); @@ -72,7 +72,7 @@ function EnablePaymentsPage({userWallet, route}) { switch (currentStep) { case CONST.WALLET.STEP.ADDITIONAL_DETAILS: case CONST.WALLET.STEP.ADDITIONAL_DETAILS_KBA: - return ; + return ; case CONST.WALLET.STEP.ONFIDO: return ; case CONST.WALLET.STEP.TERMS: diff --git a/src/pages/ReimbursementAccount/ACHContractStep.js b/src/pages/ReimbursementAccount/ACHContractStep.js index 7209d6250a94..b619abd68a33 100644 --- a/src/pages/ReimbursementAccount/ACHContractStep.js +++ b/src/pages/ReimbursementAccount/ACHContractStep.js @@ -19,22 +19,13 @@ import Form from '../../components/Form'; import * as FormActions from '../../libs/actions/FormActions'; import ScreenWrapper from '../../components/ScreenWrapper'; import StepPropTypes from './StepPropTypes'; -import getStateFromRoute from '../../libs/getStateFromRoute'; +import useGeographicalStateFromRoute from '../../hooks/useGeographicalStateFromRoute'; const propTypes = { ...StepPropTypes, /** Name of the company */ companyName: PropTypes.string.isRequired, - - /** Route from navigation */ - route: PropTypes.shape({ - /** Params from the route */ - params: PropTypes.shape({ - /** Currently selected state */ - state: PropTypes.string, - }), - }).isRequired, }; function ACHContractStep(props) { @@ -154,7 +145,7 @@ function ACHContractStep(props) { }); }; - const state = getStateFromRoute(props.route); + const state = useGeographicalStateFromRoute(); return ( diff --git a/src/pages/ReimbursementAccount/ReimbursementAccountPage.js b/src/pages/ReimbursementAccount/ReimbursementAccountPage.js index 2dc71f7b80fa..c6f53c2474f4 100644 --- a/src/pages/ReimbursementAccount/ReimbursementAccountPage.js +++ b/src/pages/ReimbursementAccount/ReimbursementAccountPage.js @@ -429,7 +429,6 @@ class ReimbursementAccountPage extends React.Component { if (currentStep === CONST.BANK_ACCOUNT.STEP.COMPANY) { return ( { return errors; }; -function RequestorStep({reimbursementAccount, route, shouldShowOnfido, reimbursementAccountDraft, onBackButtonPress, getDefaultStateForField}) { +function RequestorStep({reimbursementAccount, shouldShowOnfido, reimbursementAccountDraft, onBackButtonPress, getDefaultStateForField}) { const {translate} = useLocalize(); const defaultValues = useMemo( @@ -117,6 +108,8 @@ function RequestorStep({reimbursementAccount, route, shouldShowOnfido, reimburse ); + const state = useGeographicalStateFromRoute(); + if (shouldShowOnfido) { return ( ; } - const stateFromUrl = getStateFromRoute(props.route); - return ( nameOnCardRef.current && nameOnCardRef.current.focus()} From 0f83cff67014fc53ffa0d005247a0cc29f1a8a3f Mon Sep 17 00:00:00 2001 From: Yogesh Bhatt Date: Sat, 28 Oct 2023 02:35:21 +0530 Subject: [PATCH 005/698] move getStateFromRoute to useGeographicalStateFromRoute --- src/hooks/useGeographicalStateFromRoute.ts | 8 ++++++-- src/libs/getStateFromRoute.ts | 14 -------------- 2 files changed, 6 insertions(+), 16 deletions(-) delete mode 100644 src/libs/getStateFromRoute.ts diff --git a/src/hooks/useGeographicalStateFromRoute.ts b/src/hooks/useGeographicalStateFromRoute.ts index 33866e8b0cf1..3726499edf8f 100644 --- a/src/hooks/useGeographicalStateFromRoute.ts +++ b/src/hooks/useGeographicalStateFromRoute.ts @@ -1,7 +1,11 @@ import {useRoute} from '@react-navigation/native'; -import getStateFromRoute from '../libs/getStateFromRoute'; +// eslint-disable-next-line you-dont-need-lodash-underscore/get +import lodashGet from 'lodash/get'; +import {CONST as COMMON_CONST} from 'expensify-common/lib/CONST'; export default function useGeographicalStateFromRoute(stateParamName = 'state') { const route = useRoute(); - return getStateFromRoute(route, stateParamName); + const stateFromUrlTemp = lodashGet(route, `params.${stateParamName}`) as unknown as string; + // check if state is valid + return lodashGet(COMMON_CONST.STATES, stateFromUrlTemp) ? stateFromUrlTemp : ''; } diff --git a/src/libs/getStateFromRoute.ts b/src/libs/getStateFromRoute.ts deleted file mode 100644 index 19d6de46014f..000000000000 --- a/src/libs/getStateFromRoute.ts +++ /dev/null @@ -1,14 +0,0 @@ -// eslint-disable-next-line you-dont-need-lodash-underscore/get -import lodashGet from 'lodash/get'; -import {CONST as COMMON_CONST} from 'expensify-common/lib/CONST'; - -type RouteProps = { - // eslint-disable-next-line @typescript-eslint/no-explicit-any - params?: Record; -}; - -export default function getStateFromRoute(route: RouteProps, stateParamName = 'state'): string { - const stateFromUrlTemp = lodashGet(route, `params.${stateParamName}`) as unknown as string; - // check if state is valid - return lodashGet(COMMON_CONST.STATES, stateFromUrlTemp) ? stateFromUrlTemp : ''; -} From 0951d5d75b56a38009fe7bbd91d576bbd976cb25 Mon Sep 17 00:00:00 2001 From: Yogesh Bhatt Date: Sat, 28 Oct 2023 02:46:35 +0530 Subject: [PATCH 006/698] Add displayname to StateSelectorWithRef --- src/components/StateSelector.js | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/src/components/StateSelector.js b/src/components/StateSelector.js index c004fb8bf375..ba7705802982 100644 --- a/src/components/StateSelector.js +++ b/src/components/StateSelector.js @@ -78,10 +78,14 @@ StateSelector.propTypes = propTypes; StateSelector.defaultProps = defaultProps; StateSelector.displayName = 'StateSelector'; -export default React.forwardRef((props, ref) => ( +const StateSelectorWithRef = React.forwardRef((props, ref) => ( )); + +StateSelectorWithRef.displayName = 'StateSelectorWithRef'; + +export default StateSelectorWithRef; From 598c7c6c3378fe402e3b811a83f70b4cf16c38de Mon Sep 17 00:00:00 2001 From: Yogesh Bhatt Date: Sat, 28 Oct 2023 03:57:15 +0530 Subject: [PATCH 007/698] Fix AddressPage: State not changing on autocomplete --- src/pages/settings/Profile/PersonalDetails/AddressPage.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/pages/settings/Profile/PersonalDetails/AddressPage.js b/src/pages/settings/Profile/PersonalDetails/AddressPage.js index 1eec60d7d57f..112372abebcd 100644 --- a/src/pages/settings/Profile/PersonalDetails/AddressPage.js +++ b/src/pages/settings/Profile/PersonalDetails/AddressPage.js @@ -167,11 +167,11 @@ function AddressPage({privatePersonalDetails, route}) { }, [countryFromUrl, handleAddressChange]); useEffect(() => { - if (!stateFromUrl || stateFromUrl === state) { + if (!stateFromUrl) { return; } handleAddressChange(stateFromUrl, 'state'); - }, [state, handleAddressChange, stateFromUrl]); + }, [handleAddressChange, stateFromUrl]); return ( Date: Sat, 28 Oct 2023 04:56:23 +0530 Subject: [PATCH 008/698] Refactor StateSelector logic --- src/components/StateSelector.js | 30 +++++++++++++++---- .../EnablePayments/AdditionalDetailsStep.js | 4 --- .../ReimbursementAccount/ACHContractStep.js | 4 --- src/pages/ReimbursementAccount/CompanyStep.js | 3 +- .../ReimbursementAccount/RequestorStep.js | 4 --- src/pages/settings/Wallet/AddDebitCardPage.js | 8 +---- 6 files changed, 27 insertions(+), 26 deletions(-) diff --git a/src/components/StateSelector.js b/src/components/StateSelector.js index ba7705802982..52df1f61d7e4 100644 --- a/src/components/StateSelector.js +++ b/src/components/StateSelector.js @@ -1,4 +1,4 @@ -import React, {useEffect} from 'react'; +import React, {useEffect, useState} from 'react'; import PropTypes from 'prop-types'; import {View} from 'react-native'; import _ from 'underscore'; @@ -9,6 +9,7 @@ import ROUTES from '../ROUTES'; import useLocalize from '../hooks/useLocalize'; import MenuItemWithTopDescription from './MenuItemWithTopDescription'; import FormHelpMessage from './FormHelpMessage'; +import useGeographicalStateFromRoute from '../hooks/useGeographicalStateFromRoute'; const propTypes = { /** Form error text. e.g when no country is selected */ @@ -32,6 +33,9 @@ const propTypes = { /** Label to display on field */ label: PropTypes.string, + + /** whether to use state from url */ + useStateFromUrl: PropTypes.bool, }; const defaultProps = { @@ -40,20 +44,36 @@ const defaultProps = { forwardedRef: () => {}, label: undefined, paramName: 'state', + useStateFromUrl: true, }; -function StateSelector({errorText, value: stateCode, label, paramName, onInputChange, forwardedRef}) { +function StateSelector({errorText, useStateFromUrl, value: stateCode, label, paramName, onInputChange, forwardedRef}) { const {translate} = useLocalize(); - const title = stateCode && _.keys(COMMON_CONST.STATES).includes(stateCode) ? translate(`allStates.${stateCode}.stateName`) : ''; - const descStyle = title.length === 0 ? styles.textNormal : null; + const stateFromUrl = useGeographicalStateFromRoute(paramName); + + const [stateToDisplay, setStateToDisplay] = useState(''); + + useEffect(() => { + if (useStateFromUrl) { + // This will cause the form to revalidate and remove any error related to country name + stateFromUrl && onInputChange(stateFromUrl); + stateFromUrl && setStateToDisplay(stateFromUrl); + } + // eslint-disable-next-line react-hooks/exhaustive-deps + }, [stateFromUrl, useStateFromUrl]); useEffect(() => { // This will cause the form to revalidate and remove any error related to country name - onInputChange(stateCode); + stateCode && onInputChange(stateCode); + stateCode && setStateToDisplay(stateCode); + // eslint-disable-next-line react-hooks/exhaustive-deps }, [stateCode]); + const title = stateToDisplay && _.keys(COMMON_CONST.STATES).includes(stateToDisplay) ? translate(`allStates.${stateToDisplay}.stateName`) : ''; + const descStyle = title.length === 0 ? styles.textNormal : null; + return ( diff --git a/src/pages/ReimbursementAccount/RequestorStep.js b/src/pages/ReimbursementAccount/RequestorStep.js index 875c884420ae..86f1d5077eca 100644 --- a/src/pages/ReimbursementAccount/RequestorStep.js +++ b/src/pages/ReimbursementAccount/RequestorStep.js @@ -17,7 +17,6 @@ import Form from '../../components/Form'; import ScreenWrapper from '../../components/ScreenWrapper'; import useLocalize from '../../hooks/useLocalize'; import {reimbursementAccountPropTypes} from './reimbursementAccountPropTypes'; -import useGeographicalStateFromRoute from '../../hooks/useGeographicalStateFromRoute'; const propTypes = { onBackButtonPress: PropTypes.func.isRequired, @@ -106,8 +105,6 @@ function RequestorStep({reimbursementAccount, shouldShowOnfido, onBackButtonPres ); - const state = useGeographicalStateFromRoute(); - if (shouldShowOnfido) { return ( ; } @@ -185,10 +182,7 @@ function DebitCardPage(props) { containerStyles={[styles.mt4]} /> - + Date: Sat, 28 Oct 2023 05:02:05 +0530 Subject: [PATCH 009/698] Refactor AddressPage --- src/pages/settings/Profile/PersonalDetails/AddressPage.js | 1 + 1 file changed, 1 insertion(+) diff --git a/src/pages/settings/Profile/PersonalDetails/AddressPage.js b/src/pages/settings/Profile/PersonalDetails/AddressPage.js index 112372abebcd..1e21a210dd40 100644 --- a/src/pages/settings/Profile/PersonalDetails/AddressPage.js +++ b/src/pages/settings/Profile/PersonalDetails/AddressPage.js @@ -232,6 +232,7 @@ function AddressPage({privatePersonalDetails, route}) { {isUSAForm ? ( From 8a293b5ceeaec50be8bcd7d262a097b46b0b783f Mon Sep 17 00:00:00 2001 From: Yogesh Bhatt Date: Sat, 28 Oct 2023 05:34:30 +0530 Subject: [PATCH 010/698] linting fixes StateSelector --- src/components/StateSelector.js | 17 ++++++++++------- 1 file changed, 10 insertions(+), 7 deletions(-) diff --git a/src/components/StateSelector.js b/src/components/StateSelector.js index 52df1f61d7e4..517142527552 100644 --- a/src/components/StateSelector.js +++ b/src/components/StateSelector.js @@ -55,18 +55,21 @@ function StateSelector({errorText, useStateFromUrl, value: stateCode, label, par const [stateToDisplay, setStateToDisplay] = useState(''); useEffect(() => { - if (useStateFromUrl) { - // This will cause the form to revalidate and remove any error related to country name - stateFromUrl && onInputChange(stateFromUrl); - stateFromUrl && setStateToDisplay(stateFromUrl); - } + if (!useStateFromUrl || !stateFromUrl) return; + + // This will cause the form to revalidate and remove any error related to country name + onInputChange(stateFromUrl); + setStateToDisplay(stateFromUrl); + // eslint-disable-next-line react-hooks/exhaustive-deps }, [stateFromUrl, useStateFromUrl]); useEffect(() => { + if (!stateCode) return; + // This will cause the form to revalidate and remove any error related to country name - stateCode && onInputChange(stateCode); - stateCode && setStateToDisplay(stateCode); + onInputChange(stateCode); + setStateToDisplay(stateCode); // eslint-disable-next-line react-hooks/exhaustive-deps }, [stateCode]); From c946cbb839e04468d5c2acedaac81905bb9233a9 Mon Sep 17 00:00:00 2001 From: Yogesh Bhatt Date: Sat, 28 Oct 2023 09:07:58 +0530 Subject: [PATCH 011/698] linting --- src/components/StateSelector.js | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/src/components/StateSelector.js b/src/components/StateSelector.js index 517142527552..aaa905d8940f 100644 --- a/src/components/StateSelector.js +++ b/src/components/StateSelector.js @@ -55,7 +55,9 @@ function StateSelector({errorText, useStateFromUrl, value: stateCode, label, par const [stateToDisplay, setStateToDisplay] = useState(''); useEffect(() => { - if (!useStateFromUrl || !stateFromUrl) return; + if (!useStateFromUrl || !stateFromUrl) { + return; + } // This will cause the form to revalidate and remove any error related to country name onInputChange(stateFromUrl); @@ -65,7 +67,9 @@ function StateSelector({errorText, useStateFromUrl, value: stateCode, label, par }, [stateFromUrl, useStateFromUrl]); useEffect(() => { - if (!stateCode) return; + if (!stateCode) { + return; + } // This will cause the form to revalidate and remove any error related to country name onInputChange(stateCode); From 144eea9e55e6bc9190ab71da057a0d20e0b04e39 Mon Sep 17 00:00:00 2001 From: Yogesh Bhatt Date: Sun, 29 Oct 2023 10:28:58 +0530 Subject: [PATCH 012/698] StateSelector and related files refactoring --- src/components/StateSelector.js | 2 +- src/pages/ReimbursementAccount/CompanyStep.js | 7 +------ 2 files changed, 2 insertions(+), 7 deletions(-) diff --git a/src/components/StateSelector.js b/src/components/StateSelector.js index aaa905d8940f..c1ebdaefc493 100644 --- a/src/components/StateSelector.js +++ b/src/components/StateSelector.js @@ -34,7 +34,7 @@ const propTypes = { /** Label to display on field */ label: PropTypes.string, - /** whether to use state from url */ + /** whether to use state from url, for cases when url value is passed from parent */ useStateFromUrl: PropTypes.bool, }; diff --git a/src/pages/ReimbursementAccount/CompanyStep.js b/src/pages/ReimbursementAccount/CompanyStep.js index 7e86ebf139b2..03a222abe3d7 100644 --- a/src/pages/ReimbursementAccount/CompanyStep.js +++ b/src/pages/ReimbursementAccount/CompanyStep.js @@ -25,7 +25,6 @@ import Form from '../../components/Form'; import ScreenWrapper from '../../components/ScreenWrapper'; import StepPropTypes from './StepPropTypes'; import StateSelector from '../../components/StateSelector'; -import useGeographicalStateFromRoute from '../../hooks/useGeographicalStateFromRoute'; const propTypes = { ...StepPropTypes, @@ -140,8 +139,6 @@ function CompanyStep({reimbursementAccount, reimbursementAccountDraft, getDefaul const shouldDisableCompanyName = Boolean(bankAccountID && getDefaultStateForField('companyName')); const shouldDisableCompanyTaxID = Boolean(bankAccountID && getDefaultStateForField('companyTaxID')); - const incorporationState = useGeographicalStateFromRoute('incorporationState') || getDefaultStateForField('incorporationState'); - return ( Date: Sun, 29 Oct 2023 11:18:33 +0530 Subject: [PATCH 013/698] Fix incorrect merge --- .../Profile/PersonalDetails/AddressPage.js | 7 +------ .../PersonalDetails/StateSelectionPage.js | 16 ++++++++-------- 2 files changed, 9 insertions(+), 14 deletions(-) diff --git a/src/pages/settings/Profile/PersonalDetails/AddressPage.js b/src/pages/settings/Profile/PersonalDetails/AddressPage.js index d3b9bdfba141..9c102e566b06 100644 --- a/src/pages/settings/Profile/PersonalDetails/AddressPage.js +++ b/src/pages/settings/Profile/PersonalDetails/AddressPage.js @@ -4,12 +4,6 @@ import PropTypes from 'prop-types'; import React, {useCallback, useEffect, useMemo, useState} from 'react'; import {View} from 'react-native'; import {withOnyx} from 'react-native-onyx'; -import {CONST as COMMON_CONST} from 'expensify-common/lib/CONST'; -import lodashGet from 'lodash/get'; -import PropTypes from 'prop-types'; -import React, {useCallback, useEffect, useMemo, useState} from 'react'; -import {View} from 'react-native'; -import {withOnyx} from 'react-native-onyx'; import _ from 'underscore'; import AddressSearch from '@components/AddressSearch'; import CountrySelector from '@components/CountrySelector'; @@ -28,6 +22,7 @@ import * as PersonalDetails from '@userActions/PersonalDetails'; import CONST from '@src/CONST'; import ONYXKEYS from '@src/ONYXKEYS'; import ROUTES from '@src/ROUTES'; +import useGeographicalStateFromRoute from '@hooks/useGeographicalStateFromRoute'; const propTypes = { /* Onyx Props */ diff --git a/src/pages/settings/Profile/PersonalDetails/StateSelectionPage.js b/src/pages/settings/Profile/PersonalDetails/StateSelectionPage.js index ea443edc581d..37acb6e38397 100644 --- a/src/pages/settings/Profile/PersonalDetails/StateSelectionPage.js +++ b/src/pages/settings/Profile/PersonalDetails/StateSelectionPage.js @@ -3,14 +3,14 @@ import PropTypes from 'prop-types'; import _ from 'underscore'; import {CONST as COMMON_CONST} from 'expensify-common/lib/CONST'; import lodashGet from 'lodash/get'; -import Navigation from '../../../../libs/Navigation/Navigation'; -import ScreenWrapper from '../../../../components/ScreenWrapper'; -import HeaderWithBackButton from '../../../../components/HeaderWithBackButton'; -import SelectionList from '../../../../components/SelectionList'; -import searchCountryOptions from '../../../../libs/searchCountryOptions'; -import StringUtils from '../../../../libs/StringUtils'; -import useLocalize from '../../../../hooks/useLocalize'; -import styles from '../../../../styles/styles'; +import Navigation from '@libs/Navigation/Navigation'; +import ScreenWrapper from '@components/ScreenWrapper'; +import HeaderWithBackButton from '@components/HeaderWithBackButton'; +import SelectionList from '@components/SelectionList'; +import searchCountryOptions from '@libs/searchCountryOptions'; +import StringUtils from '@libs/StringUtils'; +import useLocalize from '@hooks/useLocalize'; +import styles from '@styles/styles'; const propTypes = { /** Route from navigation */ From 9fb4f72463d13aca2f897cbc0e17a4aa399c4b6a Mon Sep 17 00:00:00 2001 From: Yogesh Bhatt Date: Sun, 29 Oct 2023 11:22:35 +0530 Subject: [PATCH 014/698] Reverted scripts/shellCheck.sh to state at 33f15e8d85b3366b1a09bca914f61d5caa4a2fb5 --- scripts/shellCheck.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/scripts/shellCheck.sh b/scripts/shellCheck.sh index 18206a419509..d148958900d4 100755 --- a/scripts/shellCheck.sh +++ b/scripts/shellCheck.sh @@ -45,4 +45,4 @@ if [ $EXIT_CODE == 0 ]; then success "ShellCheck passed for all files!" fi -exit $EXIT_CODE \ No newline at end of file +exit $EXIT_CODE From d6a643c7b7f4db06243c420606afae458fb9ade8 Mon Sep 17 00:00:00 2001 From: Yogesh Bhatt Date: Sun, 29 Oct 2023 11:27:55 +0530 Subject: [PATCH 015/698] Linting --- src/components/StateSelector.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/components/StateSelector.js b/src/components/StateSelector.js index b5b1c3903c8c..c27c0e57e4c9 100644 --- a/src/components/StateSelector.js +++ b/src/components/StateSelector.js @@ -7,9 +7,9 @@ import styles from '@styles/styles'; import Navigation from '@libs/Navigation/Navigation'; import ROUTES from '@src/ROUTES'; import useLocalize from '@hooks/useLocalize'; +import useGeographicalStateFromRoute from '@hooks/useGeographicalStateFromRoute'; import MenuItemWithTopDescription from './MenuItemWithTopDescription'; import FormHelpMessage from './FormHelpMessage'; -import useGeographicalStateFromRoute from '@hooks/useGeographicalStateFromRoute'; const propTypes = { /** Form error text. e.g when no country is selected */ From 9bb88ee2129ebebdc9274598a72ab69ba84ce3c4 Mon Sep 17 00:00:00 2001 From: Yogesh Bhatt <65986357+ygshbht@users.noreply.github.com> Date: Tue, 31 Oct 2023 21:29:36 +0530 Subject: [PATCH 016/698] Comment formatting src/hooks/useGeographicalStateFromRoute.ts Co-authored-by: Rajat Parashar --- src/hooks/useGeographicalStateFromRoute.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/hooks/useGeographicalStateFromRoute.ts b/src/hooks/useGeographicalStateFromRoute.ts index 3726499edf8f..d86b9df6ce24 100644 --- a/src/hooks/useGeographicalStateFromRoute.ts +++ b/src/hooks/useGeographicalStateFromRoute.ts @@ -6,6 +6,6 @@ import {CONST as COMMON_CONST} from 'expensify-common/lib/CONST'; export default function useGeographicalStateFromRoute(stateParamName = 'state') { const route = useRoute(); const stateFromUrlTemp = lodashGet(route, `params.${stateParamName}`) as unknown as string; - // check if state is valid + // Check if state is valid return lodashGet(COMMON_CONST.STATES, stateFromUrlTemp) ? stateFromUrlTemp : ''; } From 5e3844785f3ef11d3bdb411078d2482490aa35bc Mon Sep 17 00:00:00 2001 From: Yogesh Bhatt Date: Tue, 31 Oct 2023 22:00:09 +0530 Subject: [PATCH 017/698] Rename useStateFomrUrl to shouldUseStateFromUrl --- src/components/StateSelector.js | 10 +++++----- .../settings/Profile/PersonalDetails/AddressPage.js | 2 +- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/src/components/StateSelector.js b/src/components/StateSelector.js index c27c0e57e4c9..fb4046ad848b 100644 --- a/src/components/StateSelector.js +++ b/src/components/StateSelector.js @@ -35,7 +35,7 @@ const propTypes = { label: PropTypes.string, /** whether to use state from url, for cases when url value is passed from parent */ - useStateFromUrl: PropTypes.bool, + shouldUseStateFromUrl: PropTypes.bool, }; const defaultProps = { @@ -44,10 +44,10 @@ const defaultProps = { forwardedRef: () => {}, label: undefined, paramName: 'state', - useStateFromUrl: true, + shouldUseStateFromUrl: true, }; -function StateSelector({errorText, useStateFromUrl, value: stateCode, label, paramName, onInputChange, forwardedRef}) { +function StateSelector({errorText, shouldUseStateFromUrl, value: stateCode, label, paramName, onInputChange, forwardedRef}) { const {translate} = useLocalize(); const stateFromUrl = useGeographicalStateFromRoute(paramName); @@ -55,7 +55,7 @@ function StateSelector({errorText, useStateFromUrl, value: stateCode, label, par const [stateToDisplay, setStateToDisplay] = useState(''); useEffect(() => { - if (!useStateFromUrl || !stateFromUrl) { + if (!shouldUseStateFromUrl || !stateFromUrl) { return; } @@ -64,7 +64,7 @@ function StateSelector({errorText, useStateFromUrl, value: stateCode, label, par setStateToDisplay(stateFromUrl); // eslint-disable-next-line react-hooks/exhaustive-deps - }, [stateFromUrl, useStateFromUrl]); + }, [stateFromUrl, shouldUseStateFromUrl]); useEffect(() => { if (!stateCode) { diff --git a/src/pages/settings/Profile/PersonalDetails/AddressPage.js b/src/pages/settings/Profile/PersonalDetails/AddressPage.js index 9c102e566b06..a9b64b2420ed 100644 --- a/src/pages/settings/Profile/PersonalDetails/AddressPage.js +++ b/src/pages/settings/Profile/PersonalDetails/AddressPage.js @@ -232,7 +232,7 @@ function AddressPage({privatePersonalDetails, route}) { {isUSAForm ? ( From 470ec03d5e71e0580643a852a14fe2ee61e4f241 Mon Sep 17 00:00:00 2001 From: Yogesh Bhatt Date: Tue, 31 Oct 2023 22:07:00 +0530 Subject: [PATCH 018/698] forwardedRef type correction StateSelector --- src/components/StateSelector.js | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/components/StateSelector.js b/src/components/StateSelector.js index fb4046ad848b..59f974251143 100644 --- a/src/components/StateSelector.js +++ b/src/components/StateSelector.js @@ -10,6 +10,7 @@ import useLocalize from '@hooks/useLocalize'; import useGeographicalStateFromRoute from '@hooks/useGeographicalStateFromRoute'; import MenuItemWithTopDescription from './MenuItemWithTopDescription'; import FormHelpMessage from './FormHelpMessage'; +import refPropTypes from './refPropTypes'; const propTypes = { /** Form error text. e.g when no country is selected */ @@ -26,7 +27,7 @@ const propTypes = { inputID: PropTypes.string.isRequired, /** React ref being forwarded to the MenuItemWithTopDescription */ - forwardedRef: PropTypes.func, + forwardedRef: refPropTypes, /** Label of state in the url */ paramName: PropTypes.string, From 8f28580d6dca027d9698a8510a0ebaf28a6ba38d Mon Sep 17 00:00:00 2001 From: Yogesh Bhatt Date: Tue, 31 Oct 2023 22:08:46 +0530 Subject: [PATCH 019/698] StateSelector: rename paramName to queryParam --- src/components/StateSelector.js | 10 +++++----- src/pages/ReimbursementAccount/CompanyStep.js | 2 +- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/src/components/StateSelector.js b/src/components/StateSelector.js index 59f974251143..13202f9d79e1 100644 --- a/src/components/StateSelector.js +++ b/src/components/StateSelector.js @@ -30,7 +30,7 @@ const propTypes = { forwardedRef: refPropTypes, /** Label of state in the url */ - paramName: PropTypes.string, + queryParam: PropTypes.string, /** Label to display on field */ label: PropTypes.string, @@ -44,14 +44,14 @@ const defaultProps = { value: undefined, forwardedRef: () => {}, label: undefined, - paramName: 'state', + queryParam: 'state', shouldUseStateFromUrl: true, }; -function StateSelector({errorText, shouldUseStateFromUrl, value: stateCode, label, paramName, onInputChange, forwardedRef}) { +function StateSelector({errorText, shouldUseStateFromUrl, value: stateCode, label, queryParam, onInputChange, forwardedRef}) { const {translate} = useLocalize(); - const stateFromUrl = useGeographicalStateFromRoute(paramName); + const stateFromUrl = useGeographicalStateFromRoute(queryParam); const [stateToDisplay, setStateToDisplay] = useState(''); @@ -92,7 +92,7 @@ function StateSelector({errorText, shouldUseStateFromUrl, value: stateCode, labe description={label || translate('common.state')} onPress={() => { const activeRoute = Navigation.getActiveRoute(); - Navigation.navigate(ROUTES.SETTINGS_PERSONAL_DETAILS_ADDRESS_STATE.getRoute(stateCode, activeRoute, label, paramName)); + Navigation.navigate(ROUTES.SETTINGS_PERSONAL_DETAILS_ADDRESS_STATE.getRoute(stateCode, activeRoute, label, queryParam)); }} /> diff --git a/src/pages/ReimbursementAccount/CompanyStep.js b/src/pages/ReimbursementAccount/CompanyStep.js index fa806521e5d0..04010f1db0c1 100644 --- a/src/pages/ReimbursementAccount/CompanyStep.js +++ b/src/pages/ReimbursementAccount/CompanyStep.js @@ -248,7 +248,7 @@ function CompanyStep({reimbursementAccount, reimbursementAccountDraft, getDefaul label={translate('companyStep.incorporationState')} defaultValue={getDefaultStateForField('incorporationState')} shouldSaveDraft - paramName="incorporationState" + queryParam="incorporationState" /> Date: Wed, 1 Nov 2023 08:24:52 +0530 Subject: [PATCH 020/698] Remove lodashGet from useGeographicalStateFromRoute --- src/hooks/useGeographicalStateFromRoute.ts | 17 ++++++++++------- 1 file changed, 10 insertions(+), 7 deletions(-) diff --git a/src/hooks/useGeographicalStateFromRoute.ts b/src/hooks/useGeographicalStateFromRoute.ts index d86b9df6ce24..112e0e8db69c 100644 --- a/src/hooks/useGeographicalStateFromRoute.ts +++ b/src/hooks/useGeographicalStateFromRoute.ts @@ -1,11 +1,14 @@ -import {useRoute} from '@react-navigation/native'; -// eslint-disable-next-line you-dont-need-lodash-underscore/get -import lodashGet from 'lodash/get'; +import {ParamListBase, RouteProp, useRoute} from '@react-navigation/native'; import {CONST as COMMON_CONST} from 'expensify-common/lib/CONST'; +type CustomParamList = ParamListBase & Record>; + export default function useGeographicalStateFromRoute(stateParamName = 'state') { - const route = useRoute(); - const stateFromUrlTemp = lodashGet(route, `params.${stateParamName}`) as unknown as string; - // Check if state is valid - return lodashGet(COMMON_CONST.STATES, stateFromUrlTemp) ? stateFromUrlTemp : ''; + const route = useRoute>(); + const stateFromUrlTemp = route.params?.[stateParamName] as string | undefined; + + if (!stateFromUrlTemp) { + return ''; + } + return COMMON_CONST.STATES[stateFromUrlTemp as keyof typeof COMMON_CONST.STATES] ? stateFromUrlTemp : ''; } From 428e48c177adcf9a77f0067114781307be11ea62 Mon Sep 17 00:00:00 2001 From: Yogesh Bhatt Date: Wed, 1 Nov 2023 08:37:52 +0530 Subject: [PATCH 021/698] StateSelectionPage appendParam restructuring --- src/libs/Url.ts | 16 +++++++++- .../PersonalDetails/StateSelectionPage.js | 32 ++++--------------- 2 files changed, 22 insertions(+), 26 deletions(-) diff --git a/src/libs/Url.ts b/src/libs/Url.ts index a21f007e8468..7e028aded60c 100644 --- a/src/libs/Url.ts +++ b/src/libs/Url.ts @@ -41,4 +41,18 @@ function hasSameExpensifyOrigin(url1: string, url2: string): boolean { } } -export {addTrailingForwardSlash, hasSameExpensifyOrigin, getPathFromURL}; +/** + * Appends or updates a query parameter in a given URL. + */ +function appendParam(url: string, paramName: string, paramValue: string) { + if (url.includes(`${paramName}=`)) { + // If parameter exists, replace it + const regex = new RegExp(`${paramName}=([^&]*)`); + return url.replace(regex, `${paramName}=${paramValue}`); + } + // If parameter doesn't exist, append it + const separator = url.includes('?') ? '&' : '?'; + return `${url}${separator}${paramName}=${paramValue}`; +} + +export {addTrailingForwardSlash, hasSameExpensifyOrigin, getPathFromURL, appendParam}; diff --git a/src/pages/settings/Profile/PersonalDetails/StateSelectionPage.js b/src/pages/settings/Profile/PersonalDetails/StateSelectionPage.js index 37acb6e38397..a506d7e61495 100644 --- a/src/pages/settings/Profile/PersonalDetails/StateSelectionPage.js +++ b/src/pages/settings/Profile/PersonalDetails/StateSelectionPage.js @@ -1,15 +1,16 @@ -import React, {useState, useMemo, useCallback} from 'react'; -import PropTypes from 'prop-types'; -import _ from 'underscore'; import {CONST as COMMON_CONST} from 'expensify-common/lib/CONST'; import lodashGet from 'lodash/get'; -import Navigation from '@libs/Navigation/Navigation'; -import ScreenWrapper from '@components/ScreenWrapper'; +import PropTypes from 'prop-types'; +import React, {useCallback, useMemo, useState} from 'react'; +import _ from 'underscore'; import HeaderWithBackButton from '@components/HeaderWithBackButton'; +import ScreenWrapper from '@components/ScreenWrapper'; import SelectionList from '@components/SelectionList'; +import useLocalize from '@hooks/useLocalize'; +import Navigation from '@libs/Navigation/Navigation'; import searchCountryOptions from '@libs/searchCountryOptions'; import StringUtils from '@libs/StringUtils'; -import useLocalize from '@hooks/useLocalize'; +import {appendParam} from '@libs/Url'; import styles from '@styles/styles'; const propTypes = { @@ -32,25 +33,6 @@ const propTypes = { }).isRequired, }; -/** - * Appends or updates a query parameter in a given URL. - * - * @param {string} url - The original URL. - * @param {string} paramName - The name of the query parameter to append or update. - * @param {string} paramValue - The value of the query parameter to append or update. - * @returns {string} The updated URL with the appended or updated query parameter. - */ -function appendParam(url, paramName, paramValue) { - if (url.includes(`${paramName}=`)) { - // If parameter exists, replace it - const regex = new RegExp(`${paramName}=([^&]*)`); - return url.replace(regex, `${paramName}=${paramValue}`); - } - // If parameter doesn't exist, append it - const separator = url.includes('?') ? '&' : '?'; - return `${url}${separator}${paramName}=${paramValue}`; -} - function StateSelectionPage({route, navigation}) { const [searchValue, setSearchValue] = useState(''); const {translate} = useLocalize(); From 7cd8b6fb2c30a45999f521355e97fdadfe6f4b2f Mon Sep 17 00:00:00 2001 From: Yogesh Bhatt Date: Wed, 1 Nov 2023 08:43:07 +0530 Subject: [PATCH 022/698] Prettier formatting --- src/components/StateSelector.js | 12 ++++++------ .../settings/Profile/PersonalDetails/AddressPage.js | 2 +- 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/src/components/StateSelector.js b/src/components/StateSelector.js index 13202f9d79e1..121037d91370 100644 --- a/src/components/StateSelector.js +++ b/src/components/StateSelector.js @@ -1,15 +1,15 @@ -import React, {useEffect, useState} from 'react'; +import {CONST as COMMON_CONST} from 'expensify-common/lib/CONST'; import PropTypes from 'prop-types'; +import React, {useEffect, useState} from 'react'; import {View} from 'react-native'; import _ from 'underscore'; -import {CONST as COMMON_CONST} from 'expensify-common/lib/CONST'; -import styles from '@styles/styles'; +import useGeographicalStateFromRoute from '@hooks/useGeographicalStateFromRoute'; +import useLocalize from '@hooks/useLocalize'; import Navigation from '@libs/Navigation/Navigation'; +import styles from '@styles/styles'; import ROUTES from '@src/ROUTES'; -import useLocalize from '@hooks/useLocalize'; -import useGeographicalStateFromRoute from '@hooks/useGeographicalStateFromRoute'; -import MenuItemWithTopDescription from './MenuItemWithTopDescription'; import FormHelpMessage from './FormHelpMessage'; +import MenuItemWithTopDescription from './MenuItemWithTopDescription'; import refPropTypes from './refPropTypes'; const propTypes = { diff --git a/src/pages/settings/Profile/PersonalDetails/AddressPage.js b/src/pages/settings/Profile/PersonalDetails/AddressPage.js index a9b64b2420ed..752c3d2984a2 100644 --- a/src/pages/settings/Profile/PersonalDetails/AddressPage.js +++ b/src/pages/settings/Profile/PersonalDetails/AddressPage.js @@ -13,6 +13,7 @@ import HeaderWithBackButton from '@components/HeaderWithBackButton'; import ScreenWrapper from '@components/ScreenWrapper'; import StateSelector from '@components/StateSelector'; import TextInput from '@components/TextInput'; +import useGeographicalStateFromRoute from '@hooks/useGeographicalStateFromRoute'; import useLocalize from '@hooks/useLocalize'; import usePrivatePersonalDetails from '@hooks/usePrivatePersonalDetails'; import Navigation from '@libs/Navigation/Navigation'; @@ -22,7 +23,6 @@ import * as PersonalDetails from '@userActions/PersonalDetails'; import CONST from '@src/CONST'; import ONYXKEYS from '@src/ONYXKEYS'; import ROUTES from '@src/ROUTES'; -import useGeographicalStateFromRoute from '@hooks/useGeographicalStateFromRoute'; const propTypes = { /* Onyx Props */ From d60ca6ccd76ca612d708d368b206364edb540400 Mon Sep 17 00:00:00 2001 From: Etotaziba Olei Date: Thu, 4 Jan 2024 01:06:47 +0100 Subject: [PATCH 023/698] remove unused split transaction draft --- src/components/MoneyRequestConfirmationList.js | 3 --- 1 file changed, 3 deletions(-) diff --git a/src/components/MoneyRequestConfirmationList.js b/src/components/MoneyRequestConfirmationList.js index 13dce9337673..5807eb66f143 100755 --- a/src/components/MoneyRequestConfirmationList.js +++ b/src/components/MoneyRequestConfirmationList.js @@ -825,9 +825,6 @@ export default compose( key: ({policyID}) => `${ONYXKEYS.COLLECTION.POLICY}${policyID}`, selector: DistanceRequestUtils.getDefaultMileageRate, }, - splitTransactionDraft: { - key: ({transactionID}) => `${ONYXKEYS.COLLECTION.SPLIT_TRANSACTION_DRAFT}${transactionID}`, - }, policy: { key: ({policyID}) => `${ONYXKEYS.COLLECTION.POLICY}${policyID}`, }, From d849ea347c5fa1c488212e54e9f68411893d76c1 Mon Sep 17 00:00:00 2001 From: Etotaziba Olei Date: Thu, 4 Jan 2024 01:08:55 +0100 Subject: [PATCH 024/698] use StepScreenWrapper and backTo for back navigation --- .../step/IOURequestStepTaxAmountPage.js | 54 +++++++------------ 1 file changed, 18 insertions(+), 36 deletions(-) diff --git a/src/pages/iou/request/step/IOURequestStepTaxAmountPage.js b/src/pages/iou/request/step/IOURequestStepTaxAmountPage.js index 8ee3abb56d00..89f592b89e38 100644 --- a/src/pages/iou/request/step/IOURequestStepTaxAmountPage.js +++ b/src/pages/iou/request/step/IOURequestStepTaxAmountPage.js @@ -1,17 +1,11 @@ import {useFocusEffect} from '@react-navigation/native'; import React, {useCallback, useRef} from 'react'; -import {View} from 'react-native'; import {withOnyx} from 'react-native-onyx'; -import FullPageNotFoundView from '@components/BlockingViews/FullPageNotFoundView'; -import HeaderWithBackButton from '@components/HeaderWithBackButton'; -import ScreenWrapper from '@components/ScreenWrapper'; import taxPropTypes from '@components/taxPropTypes'; import transactionPropTypes from '@components/transactionPropTypes'; import useLocalize from '@hooks/useLocalize'; -import useThemeStyles from '@hooks/useThemeStyles'; import compose from '@libs/compose'; import * as CurrencyUtils from '@libs/CurrencyUtils'; -import * as IOUUtils from '@libs/IOUUtils'; import Navigation from '@libs/Navigation/Navigation'; import * as TransactionUtils from '@libs/TransactionUtils'; import MoneyRequestAmountForm from '@pages/iou/steps/MoneyRequestAmountForm'; @@ -21,6 +15,7 @@ import CONST from '@src/CONST'; import ONYXKEYS from '@src/ONYXKEYS'; import ROUTES from '@src/ROUTES'; import IOURequestStepRoutePropTypes from './IOURequestStepRoutePropTypes'; +import StepScreenWrapper from './StepScreenWrapper'; import withFullTransactionOrNotFound from './withFullTransactionOrNotFound'; import withWritableReportOrNotFound from './withWritableReportOrNotFound'; @@ -61,7 +56,6 @@ function IOURequestStepTaxAmountPage({ policyTaxRates, }) { const {translate} = useLocalize(); - const styles = useThemeStyles(); const textInput = useRef(null); const isEditing = Navigation.getActiveRoute().includes('taxAmount'); @@ -82,7 +76,7 @@ function IOURequestStepTaxAmountPage({ ); const navigateBack = () => { - Navigation.goBack(isEditing ? ROUTES.MONEY_REQUEST_CONFIRMATION.getRoute(iouType, reportID) : ROUTES.HOME); + Navigation.goBack(backTo || ROUTES.HOME); }; const navigateToCurrencySelectionPage = () => { @@ -117,37 +111,25 @@ function IOURequestStepTaxAmountPage({ Navigation.navigate(ROUTES.MONEY_REQUEST_STEP_PARTICIPANTS.getRoute(iouType, transactionID, reportID)); }; - const content = ( - (textInput.current = e)} - onCurrencyButtonPress={navigateToCurrencySelectionPage} - onSubmitButtonPress={updateTaxAmount} - /> - ); - return ( - - {({safeAreaPaddingBottomStyle}) => ( - - - - {content} - - - )} - + (textInput.current = e)} + onCurrencyButtonPress={navigateToCurrencySelectionPage} + onSubmitButtonPress={updateTaxAmount} + /> + ); } From f558497bacc30d13ae591bbc1667e6809b5b5419 Mon Sep 17 00:00:00 2001 From: Etotaziba Olei Date: Thu, 4 Jan 2024 01:09:10 +0100 Subject: [PATCH 025/698] use StepScreenWrapper and backTo for back navigation --- .../request/step/IOURequestStepTaxRatePage.js | 54 +++++++------------ 1 file changed, 18 insertions(+), 36 deletions(-) diff --git a/src/pages/iou/request/step/IOURequestStepTaxRatePage.js b/src/pages/iou/request/step/IOURequestStepTaxRatePage.js index bae08cd8cb62..ba3c9c7a321c 100644 --- a/src/pages/iou/request/step/IOURequestStepTaxRatePage.js +++ b/src/pages/iou/request/step/IOURequestStepTaxRatePage.js @@ -1,9 +1,6 @@ -import PropTypes from 'prop-types'; import React from 'react'; import {withOnyx} from 'react-native-onyx'; import _ from 'underscore'; -import HeaderWithBackButton from '@components/HeaderWithBackButton'; -import ScreenWrapper from '@components/ScreenWrapper'; import TaxPicker from '@components/TaxPicker'; import taxPropTypes from '@components/taxPropTypes'; import transactionPropTypes from '@components/transactionPropTypes'; @@ -16,21 +13,14 @@ import * as TransactionUtils from '@libs/TransactionUtils'; import * as IOU from '@userActions/IOU'; import ONYXKEYS from '@src/ONYXKEYS'; import ROUTES from '@src/ROUTES'; +import IOURequestStepRoutePropTypes from './IOURequestStepRoutePropTypes'; +import StepScreenWrapper from './StepScreenWrapper'; import withFullTransactionOrNotFound from './withFullTransactionOrNotFound'; import withWritableReportOrNotFound from './withWritableReportOrNotFound'; const propTypes = { - /** Route from navigation */ - route: PropTypes.shape({ - /** Params from the route */ - params: PropTypes.shape({ - /** The type of IOU report, i.e. bill, request, send */ - iouType: PropTypes.string, - - /** The report ID of the IOU */ - reportID: PropTypes.string, - }), - }).isRequired, + /** Navigation route context info provided by react navigation */ + route: IOURequestStepRoutePropTypes.isRequired, /* Onyx Props */ /** Collection of tax rates attached to a policy */ @@ -52,16 +42,16 @@ const getTaxAmount = (taxRates, selectedTaxRate, amount) => { function IOURequestStepTaxRatePage({ route: { - params: {iouType, reportID}, + params: {iouType, reportID, backTo}, }, policyTaxRates, transaction, }) { const {translate} = useLocalize(); - function navigateBack() { - Navigation.goBack(ROUTES.MONEY_REQUEST_CONFIRMATION.getRoute(iouType, reportID)); - } + const navigateBack = () => { + Navigation.goBack(backTo || ROUTES.HOME); + }; const defaultTaxKey = policyTaxRates.defaultExternalID; const defaultTaxName = (defaultTaxKey && `${policyTaxRates.taxes[defaultTaxKey].name} (${policyTaxRates.taxes[defaultTaxKey].value}) • ${translate('common.default')}`) || ''; @@ -77,26 +67,18 @@ function IOURequestStepTaxRatePage({ }; return ( - - {({insets}) => ( - <> - navigateBack()} - /> - - - )} - + + ); } From de255d7a896b951659503bd7a483ee874d187dc8 Mon Sep 17 00:00:00 2001 From: Etotaziba Olei Date: Thu, 4 Jan 2024 09:16:34 +0100 Subject: [PATCH 026/698] remove unused transaction prop --- src/pages/iou/request/step/IOURequestStepTaxAmountPage.js | 1 - 1 file changed, 1 deletion(-) diff --git a/src/pages/iou/request/step/IOURequestStepTaxAmountPage.js b/src/pages/iou/request/step/IOURequestStepTaxAmountPage.js index 89f592b89e38..106119cff994 100644 --- a/src/pages/iou/request/step/IOURequestStepTaxAmountPage.js +++ b/src/pages/iou/request/step/IOURequestStepTaxAmountPage.js @@ -124,7 +124,6 @@ function IOURequestStepTaxAmountPage({ currency={currency} amount={transaction.taxAmount} taxAmount={getTaxAmount(transaction, policyTaxRates.defaultValue)} - transaction={transaction} ref={(e) => (textInput.current = e)} onCurrencyButtonPress={navigateToCurrencySelectionPage} onSubmitButtonPress={updateTaxAmount} From b1df50f1f0b0a9272d462484dd9827df7d9dc494 Mon Sep 17 00:00:00 2001 From: Etotaziba Olei Date: Thu, 4 Jan 2024 09:17:55 +0100 Subject: [PATCH 027/698] use policyTaxRates directly in taxPicker --- src/components/TaxPicker/index.js | 8 +++++++- src/pages/iou/request/step/IOURequestStepTaxRatePage.js | 8 +++++++- 2 files changed, 14 insertions(+), 2 deletions(-) diff --git a/src/components/TaxPicker/index.js b/src/components/TaxPicker/index.js index f25a1b84bf64..287805692bcf 100644 --- a/src/components/TaxPicker/index.js +++ b/src/components/TaxPicker/index.js @@ -1,5 +1,6 @@ import lodashGet from 'lodash/get'; import React, {useMemo, useState} from 'react'; +import {withOnyx} from 'react-native-onyx'; import _ from 'underscore'; import OptionsSelector from '@components/OptionsSelector'; import useLocalize from '@hooks/useLocalize'; @@ -8,6 +9,7 @@ import useThemeStyles from '@hooks/useThemeStyles'; import * as OptionsListUtils from '@libs/OptionsListUtils'; import * as TransactionUtils from '@libs/TransactionUtils'; import CONST from '@src/CONST'; +import ONYXKEYS from '@src/ONYXKEYS'; import {defaultProps, propTypes} from './taxPickerPropTypes'; function TaxPicker({selectedTaxRate, policyTaxRates, insets, onSubmit}) { @@ -87,4 +89,8 @@ TaxPicker.displayName = 'TaxPicker'; TaxPicker.propTypes = propTypes; TaxPicker.defaultProps = defaultProps; -export default TaxPicker; +export default withOnyx({ + policyTaxRates: { + key: ({policyID}) => `${ONYXKEYS.COLLECTION.POLICY_TAX_RATE}${policyID}`, + }, +})(TaxPicker); diff --git a/src/pages/iou/request/step/IOURequestStepTaxRatePage.js b/src/pages/iou/request/step/IOURequestStepTaxRatePage.js index ba3c9c7a321c..22f826d0457b 100644 --- a/src/pages/iou/request/step/IOURequestStepTaxRatePage.js +++ b/src/pages/iou/request/step/IOURequestStepTaxRatePage.js @@ -10,6 +10,7 @@ import * as CurrencyUtils from '@libs/CurrencyUtils'; import Navigation from '@libs/Navigation/Navigation'; import * as OptionsListUtils from '@libs/OptionsListUtils'; import * as TransactionUtils from '@libs/TransactionUtils'; +import reportPropTypes from '@pages/reportPropTypes'; import * as IOU from '@userActions/IOU'; import ONYXKEYS from '@src/ONYXKEYS'; import ROUTES from '@src/ROUTES'; @@ -28,9 +29,13 @@ const propTypes = { /** The transaction object being modified in Onyx */ transaction: transactionPropTypes, + + /** The report attached to the transaction */ + report: reportPropTypes, }; const defaultProps = { + report: {}, policyTaxRates: {}, transaction: {}, }; @@ -46,6 +51,7 @@ function IOURequestStepTaxRatePage({ }, policyTaxRates, transaction, + report, }) { const {translate} = useLocalize(); @@ -75,7 +81,7 @@ function IOURequestStepTaxRatePage({ > From 22c290eaddc9b2239995b034b84052810def0777 Mon Sep 17 00:00:00 2001 From: Etotaziba Olei Date: Thu, 4 Jan 2024 09:19:34 +0100 Subject: [PATCH 028/698] add EditRequestTaxAmount Page --- src/pages/EditRequestTaxAmountPage.js | 73 +++++++++++++++++++++++++++ 1 file changed, 73 insertions(+) create mode 100644 src/pages/EditRequestTaxAmountPage.js diff --git a/src/pages/EditRequestTaxAmountPage.js b/src/pages/EditRequestTaxAmountPage.js new file mode 100644 index 000000000000..2d10ccfe6f2b --- /dev/null +++ b/src/pages/EditRequestTaxAmountPage.js @@ -0,0 +1,73 @@ +import {useFocusEffect} from '@react-navigation/native'; +import PropTypes from 'prop-types'; +import React, {useCallback, useRef} from 'react'; +import HeaderWithBackButton from '@components/HeaderWithBackButton'; +import ScreenWrapper from '@components/ScreenWrapper'; +import useLocalize from '@hooks/useLocalize'; +import * as DeviceCapabilities from '@libs/DeviceCapabilities'; +import Navigation from '@libs/Navigation/Navigation'; +import CONST from '@src/CONST'; +import MoneyRequestAmountForm from './iou/steps/MoneyRequestAmountForm'; + +const propTypes = { + /** Transaction default amount value */ + defaultAmount: PropTypes.number.isRequired, + + /** Transaction default tax amount value */ + defaultTaxAmount: PropTypes.number.isRequired, + + /** Transaction default currency value */ + defaultCurrency: PropTypes.string.isRequired, + + /** Callback to fire when the Save button is pressed */ + onSubmit: PropTypes.func.isRequired, + + /** Callback to fire when we press on the currency */ + onNavigateToCurrency: PropTypes.func.isRequired, +}; + +function EditRequestTaxAmountPage({defaultAmount, defaultTaxAmount, defaultCurrency, onNavigateToCurrency, onSubmit}) { + const {translate} = useLocalize(); + const textInput = useRef(null); + const isEditing = Navigation.getActiveRoute().includes('taxAmount'); + + const focusTimeoutRef = useRef(null); + + useFocusEffect( + useCallback(() => { + focusTimeoutRef.current = setTimeout(() => textInput.current && textInput.current.focus(), CONST.ANIMATED_TRANSITION); + return () => { + if (!focusTimeoutRef.current) { + return; + } + clearTimeout(focusTimeoutRef.current); + }; + }, []), + ); + + return ( + + + (textInput.current = e)} + onCurrencyButtonPress={onNavigateToCurrency} + onSubmitButtonPress={onSubmit} + isEditing + /> + + ); +} + +EditRequestTaxAmountPage.propTypes = propTypes; +EditRequestTaxAmountPage.displayName = 'EditRequestTaxAmountPage'; + +export default EditRequestTaxAmountPage; From 42f79baa818863272e58e57ff6b87e7865c9b10b Mon Sep 17 00:00:00 2001 From: Etotaziba Olei Date: Thu, 4 Jan 2024 09:19:59 +0100 Subject: [PATCH 029/698] add EditRequestTaxRate Page --- src/pages/EditRequestTaxRatePage.js | 47 +++++++++++++++++++++++++++++ 1 file changed, 47 insertions(+) create mode 100644 src/pages/EditRequestTaxRatePage.js diff --git a/src/pages/EditRequestTaxRatePage.js b/src/pages/EditRequestTaxRatePage.js new file mode 100644 index 000000000000..965dfc1a65d7 --- /dev/null +++ b/src/pages/EditRequestTaxRatePage.js @@ -0,0 +1,47 @@ +import PropTypes from 'prop-types'; +import React from 'react'; +import HeaderWithBackButton from '@components/HeaderWithBackButton'; +import ScreenWrapper from '@components/ScreenWrapper'; +import TaxPicker from '@components/TaxPicker'; +import useLocalize from '@hooks/useLocalize'; +import Navigation from '@libs/Navigation/Navigation'; + +const propTypes = { + /** Transaction default tax Rate value */ + defaultTaxRate: PropTypes.string.isRequired, + + /** The policyID we are getting categories for */ + policyID: PropTypes.string.isRequired, + + /** Callback to fire when the Save button is pressed */ + onSubmit: PropTypes.func.isRequired, +}; + +function EditRequestTaxRatePage({defaultTaxRate, policyID, onSubmit}) { + const {translate} = useLocalize(); + + return ( + + {({insets}) => ( + <> + + + + )} + + ); +} + +EditRequestTaxRatePage.propTypes = propTypes; +EditRequestTaxRatePage.displayName = 'EditRequestTaxRatePage'; + +export default EditRequestTaxRatePage; From 3226d9cf8ba70e0218032197dd925d75e252faa3 Mon Sep 17 00:00:00 2001 From: Etotaziba Olei Date: Thu, 4 Jan 2024 09:23:47 +0100 Subject: [PATCH 030/698] add edit Tax amount and rate page to edit request page --- src/CONST.ts | 2 ++ src/pages/EditRequestPage.js | 39 +++++++++++++++++++++++++++++++++++- 2 files changed, 40 insertions(+), 1 deletion(-) diff --git a/src/CONST.ts b/src/CONST.ts index cec7cbc0b8a5..44bee149609f 100755 --- a/src/CONST.ts +++ b/src/CONST.ts @@ -1541,6 +1541,8 @@ const CONST = { RECEIPT: 'receipt', DISTANCE: 'distance', TAG: 'tag', + TAX_RATE: 'taxRate', + TAX_AMOUNT: 'taxAmount', }, FOOTER: { EXPENSE_MANAGEMENT_URL: `${USE_EXPENSIFY_URL}/expense-management`, diff --git a/src/pages/EditRequestPage.js b/src/pages/EditRequestPage.js index e41f30779f22..a43ddc44c492 100644 --- a/src/pages/EditRequestPage.js +++ b/src/pages/EditRequestPage.js @@ -27,6 +27,8 @@ import EditRequestDistancePage from './EditRequestDistancePage'; import EditRequestMerchantPage from './EditRequestMerchantPage'; import EditRequestReceiptPage from './EditRequestReceiptPage'; import EditRequestTagPage from './EditRequestTagPage'; +import EditRequestTaxAmountPage from './EditRequestTaxAmountPage'; +import EditRequestTaxRatePage from './EditRequestTaxRatePage'; import reportActionPropTypes from './home/report/reportActionPropTypes'; import reportPropTypes from './reportPropTypes'; @@ -61,6 +63,12 @@ const propTypes = { /** Transaction that stores the request data */ transaction: transactionPropTypes, + + /** The policy of the report */ + policy: PropTypes.shape({ + /** Is Tax tracking Enabled */ + isTaxTrackingEnabled: PropTypes.bool, + }), }; const defaultProps = { @@ -70,9 +78,10 @@ const defaultProps = { policyTags: {}, parentReportActions: {}, transaction: {}, + policy: {}, }; -function EditRequestPage({report, route, parentReport, policyCategories, policyTags, parentReportActions, transaction}) { +function EditRequestPage({report, policy, route, parentReport, policyCategories, policyTags, parentReportActions, transaction}) { const parentReportActionID = lodashGet(report, 'parentReportActionID', '0'); const parentReportAction = lodashGet(parentReportActions, parentReportActionID, {}); const { @@ -101,6 +110,9 @@ function EditRequestPage({report, route, parentReport, policyCategories, policyT // A flag for showing the tags page const shouldShowTags = isPolicyExpenseChat && (transactionTag || OptionsListUtils.hasEnabledOptions(lodashValues(policyTagList))); + // A flag for showing tax rate + const shouldShowTax = isPolicyExpenseChat && policy.isTaxTrackingEnabled; + // Decides whether to allow or disallow editing a money request useEffect(() => { // Do not dismiss the modal, when a current user can edit this property of the money request. @@ -251,6 +263,28 @@ function EditRequestPage({report, route, parentReport, policyCategories, policyT ); } + if (fieldToEdit === CONST.EDIT_REQUEST_FIELD.TAX_AMOUNT && shouldShowTax) { + return ( + {}} + onSubmit={() => {}} + /> + ); + } + + if (fieldToEdit === CONST.EDIT_REQUEST_FIELD.TAX_RATE && shouldShowTax) { + return ( + {}} + /> + ); + } + if (fieldToEdit === CONST.EDIT_REQUEST_FIELD.RECEIPT) { return ( `${ONYXKEYS.COLLECTION.POLICY_CATEGORIES}${report ? report.policyID : '0'}`, }, + policy: { + key: ({report}) => `${ONYXKEYS.COLLECTION.POLICY}${report.policyID}`, + }, policyTags: { key: ({report}) => `${ONYXKEYS.COLLECTION.POLICY_TAGS}${report ? report.policyID : '0'}`, }, From 9130f73d940ef8a8bb62fd3c8cf7914b15959dc2 Mon Sep 17 00:00:00 2001 From: Etotaziba Olei Date: Thu, 4 Jan 2024 09:24:32 +0100 Subject: [PATCH 031/698] add edit Tax amount and rate fields and route to pages --- .../ReportActionItem/MoneyRequestView.js | 39 ++++++++++++++++++- 1 file changed, 38 insertions(+), 1 deletion(-) diff --git a/src/components/ReportActionItem/MoneyRequestView.js b/src/components/ReportActionItem/MoneyRequestView.js index 514dc71ffe2c..4c8cc0c3d131 100644 --- a/src/components/ReportActionItem/MoneyRequestView.js +++ b/src/components/ReportActionItem/MoneyRequestView.js @@ -12,6 +12,7 @@ import ReceiptEmptyState from '@components/ReceiptEmptyState'; import SpacerView from '@components/SpacerView'; import Switch from '@components/Switch'; import tagPropTypes from '@components/tagPropTypes'; +import taxPropTypes from '@components/taxPropTypes'; import Text from '@components/Text'; import transactionPropTypes from '@components/transactionPropTypes'; import withCurrentUserPersonalDetails, {withCurrentUserPersonalDetailsPropTypes} from '@components/withCurrentUserPersonalDetails'; @@ -64,6 +65,10 @@ const propTypes = { /** Collection of tags attached to a policy */ policyTags: tagPropTypes, + /* Onyx Props */ + /** Collection of tax rates attached to a policy */ + policyTaxRates: taxPropTypes, + ...withCurrentUserPersonalDetailsPropTypes, }; @@ -77,9 +82,10 @@ const defaultProps = { comment: {comment: ''}, }, policyTags: {}, + policyTaxRates: {}, }; -function MoneyRequestView({report, parentReport, parentReportActions, policyCategories, shouldShowHorizontalRule, transaction, policyTags, policy}) { +function MoneyRequestView({report, parentReport, parentReportActions, policyCategories, policyTaxRates, shouldShowHorizontalRule, transaction, policyTags, policy}) { const theme = useTheme(); const styles = useThemeStyles(); const StyleUtils = useStyleUtils(); @@ -131,6 +137,9 @@ function MoneyRequestView({report, parentReport, parentReportActions, policyCate const shouldShowTag = isPolicyExpenseChat && (transactionTag || OptionsListUtils.hasEnabledOptions(lodashValues(policyTagsList))); const shouldShowBillable = isPolicyExpenseChat && (transactionBillable || !lodashGet(policy, 'disabledFields.defaultBillable', true)); + // A flag for showing tax rate + const shouldShowTax = isPolicyExpenseChat && policy.isTaxTrackingEnabled; + let amountDescription = `${translate('iou.amount')}`; if (isCardTransaction) { @@ -295,6 +304,31 @@ function MoneyRequestView({report, parentReport, parentReportActions, policyCate /> )} + {shouldShowTax && ( + + Navigation.navigate(ROUTES.EDIT_REQUEST.getRoute(report.reportID, CONST.EDIT_REQUEST_FIELD.TAX_RATE))} + /> + + )} + + {shouldShowTax && ( + + Navigation.navigate(ROUTES.EDIT_REQUEST.getRoute(report.reportID, CONST.EDIT_REQUEST_FIELD.TAX_AMOUNT))} + /> + + )} {shouldShowBillable && ( {translate('common.billable')} @@ -333,6 +367,9 @@ export default compose( policyTags: { key: ({report}) => `${ONYXKEYS.COLLECTION.POLICY_TAGS}${report.policyID}`, }, + policyTaxRates: { + key: ({report}) => `${ONYXKEYS.COLLECTION.POLICY_TAX_RATE}${report.policyID}`, + }, parentReport: { key: ({report}) => `${ONYXKEYS.COLLECTION.REPORT}${report.parentReportID}`, }, From 4b8a102c3cef9510991b97f4d96082e20eb159e0 Mon Sep 17 00:00:00 2001 From: Etotaziba Olei Date: Thu, 4 Jan 2024 09:37:44 +0100 Subject: [PATCH 032/698] fix lint --- src/pages/EditRequestTaxAmountPage.js | 1 - src/pages/EditRequestTaxRatePage.js | 1 - 2 files changed, 2 deletions(-) diff --git a/src/pages/EditRequestTaxAmountPage.js b/src/pages/EditRequestTaxAmountPage.js index 2d10ccfe6f2b..dabfdfcb519f 100644 --- a/src/pages/EditRequestTaxAmountPage.js +++ b/src/pages/EditRequestTaxAmountPage.js @@ -54,7 +54,6 @@ function EditRequestTaxAmountPage({defaultAmount, defaultTaxAmount, defaultCurre > Date: Thu, 4 Jan 2024 09:42:40 +0100 Subject: [PATCH 033/698] remove is editing check --- src/pages/EditRequestTaxAmountPage.js | 1 - 1 file changed, 1 deletion(-) diff --git a/src/pages/EditRequestTaxAmountPage.js b/src/pages/EditRequestTaxAmountPage.js index dabfdfcb519f..b5c20aa82d7c 100644 --- a/src/pages/EditRequestTaxAmountPage.js +++ b/src/pages/EditRequestTaxAmountPage.js @@ -29,7 +29,6 @@ const propTypes = { function EditRequestTaxAmountPage({defaultAmount, defaultTaxAmount, defaultCurrency, onNavigateToCurrency, onSubmit}) { const {translate} = useLocalize(); const textInput = useRef(null); - const isEditing = Navigation.getActiveRoute().includes('taxAmount'); const focusTimeoutRef = useRef(null); From 74f63f2eea05b7cb922d81867ecf95e82a7b45e4 Mon Sep 17 00:00:00 2001 From: Etotaziba Olei Date: Thu, 4 Jan 2024 13:28:12 +0100 Subject: [PATCH 034/698] complete types for policyTaxRates and Transaction --- src/types/onyx/PolicyTaxRates.ts | 25 +++++++++++++++++++++---- src/types/onyx/Transaction.ts | 3 +++ 2 files changed, 24 insertions(+), 4 deletions(-) diff --git a/src/types/onyx/PolicyTaxRates.ts b/src/types/onyx/PolicyTaxRates.ts index d549b620f51f..bc0905a0ff49 100644 --- a/src/types/onyx/PolicyTaxRates.ts +++ b/src/types/onyx/PolicyTaxRates.ts @@ -1,4 +1,4 @@ -type PolicyTaxRate = { +type TaxRate = { /** Name of a tax */ name: string; @@ -9,6 +9,23 @@ type PolicyTaxRate = { isDisabled?: boolean; }; -type PolicyTaxRates = Record; -export default PolicyTaxRate; -export type {PolicyTaxRates}; +type TaxRates = Record; +type PolicyTaxRates = { + /** Name of the tax */ + name: string; + + /** Default policy tax ID */ + defaultExternalID: string; + + /** Default value of taxes */ + defaultValue: string; + + /** Default foreign policy tax ID */ + foreignTaxDefault: string; + + /** List of tax names and values */ + taxes: TaxRates; +}; + +export default TaxRate; +export type {TaxRates, PolicyTaxRates}; diff --git a/src/types/onyx/Transaction.ts b/src/types/onyx/Transaction.ts index 53bfc36a4e47..d67aec17a845 100644 --- a/src/types/onyx/Transaction.ts +++ b/src/types/onyx/Transaction.ts @@ -94,6 +94,9 @@ type Transaction = { /** If the transaction was made in a foreign currency, we send the original amount and currency */ originalAmount?: number; originalCurrency?: string; + taxRate?: { + text: string; + }; }; export default Transaction; From f2503f4e90b1456eb143f100b7b47159bde9be79 Mon Sep 17 00:00:00 2001 From: Etotaziba Olei Date: Thu, 4 Jan 2024 13:31:22 +0100 Subject: [PATCH 035/698] add getDefaultTaxName func. in TransactionUtils --- src/libs/TransactionUtils.ts | 18 +++++++++++++++--- 1 file changed, 15 insertions(+), 3 deletions(-) diff --git a/src/libs/TransactionUtils.ts b/src/libs/TransactionUtils.ts index 615bea7ff18d..51a9f6ee188e 100644 --- a/src/libs/TransactionUtils.ts +++ b/src/libs/TransactionUtils.ts @@ -4,11 +4,12 @@ import {ValueOf} from 'type-fest'; import CONST from '@src/CONST'; import ONYXKEYS from '@src/ONYXKEYS'; import {RecentWaypoint, Report, ReportAction, Transaction} from '@src/types/onyx'; -import PolicyTaxRate, {PolicyTaxRates} from '@src/types/onyx/PolicyTaxRates'; +import TaxRate, {PolicyTaxRates, TaxRates} from '@src/types/onyx/PolicyTaxRates'; import {Comment, Receipt, Waypoint, WaypointCollection} from '@src/types/onyx/Transaction'; import {EmptyObject} from '@src/types/utils/EmptyObject'; import {isCorporateCard, isExpensifyCard} from './CardUtils'; import DateUtils from './DateUtils'; +import * as Localize from './Localize'; import * as NumberUtils from './NumberUtils'; type AdditionalTransactionChanges = {comment?: string; waypoints?: WaypointCollection}; @@ -529,13 +530,24 @@ function calculateTaxAmount(percentage: string, amount: number) { /** * Calculates count of all tax enabled options */ -function getEnabledTaxRateCount(options: PolicyTaxRates) { - return Object.values(options).filter((option: PolicyTaxRate) => !option.isDisabled).length; +function getEnabledTaxRateCount(options: TaxRates) { + return Object.values(options).filter((option: TaxRate) => !option.isDisabled).length; +} + +/** + * Calculates get's the default tax name + */ +function getDefaultTaxName(policyTaxRates: PolicyTaxRates, transaction: Transaction) { + const defaultTaxKey = policyTaxRates.defaultExternalID; + const defaultTaxName = + (defaultTaxKey && `${policyTaxRates.taxes[defaultTaxKey].name} (${policyTaxRates.taxes[defaultTaxKey].value}) • ${Localize.translateLocal('common.default')}`) || ''; + return transaction?.taxRate?.text ?? defaultTaxName; } export { buildOptimisticTransaction, calculateTaxAmount, + getDefaultTaxName, getEnabledTaxRateCount, getUpdatedTransaction, getTransaction, From f10e413a895ac554ad7e1fe6f82a0ec290634c36 Mon Sep 17 00:00:00 2001 From: Etotaziba Olei Date: Thu, 4 Jan 2024 13:32:09 +0100 Subject: [PATCH 036/698] use getDefaultTaxName --- src/components/MoneyRequestConfirmationList.js | 5 +---- .../MoneyTemporaryForRefactorRequestConfirmationList.js | 4 +--- src/pages/iou/request/step/IOURequestStepTaxRatePage.js | 4 +--- 3 files changed, 3 insertions(+), 10 deletions(-) diff --git a/src/components/MoneyRequestConfirmationList.js b/src/components/MoneyRequestConfirmationList.js index 5807eb66f143..260c27205e94 100755 --- a/src/components/MoneyRequestConfirmationList.js +++ b/src/components/MoneyRequestConfirmationList.js @@ -262,10 +262,7 @@ function MoneyRequestConfirmationList(props) { props.isDistanceRequest ? currency : props.iouCurrencyCode, ); const formattedTaxAmount = CurrencyUtils.convertToDisplayString(props.transaction.taxAmount, props.iouCurrencyCode); - - const defaultTaxKey = props.policyTaxRates.defaultExternalID; - const defaultTaxName = (defaultTaxKey && `${props.policyTaxRates.taxes[defaultTaxKey].name} (${props.policyTaxRates.taxes[defaultTaxKey].value}) • ${translate('common.default')}`) || ''; - const taxRateTitle = (props.transaction.taxRate && props.transaction.taxRate.text) || defaultTaxName; + const taxRateTitle = TransactionUtils.getDefaultTaxName(props.policyTaxRates, transaction); const isFocused = useIsFocused(); const [formError, setFormError] = useState(''); diff --git a/src/components/MoneyTemporaryForRefactorRequestConfirmationList.js b/src/components/MoneyTemporaryForRefactorRequestConfirmationList.js index 7ec95aec951f..55890c022179 100755 --- a/src/components/MoneyTemporaryForRefactorRequestConfirmationList.js +++ b/src/components/MoneyTemporaryForRefactorRequestConfirmationList.js @@ -292,9 +292,7 @@ function MoneyTemporaryForRefactorRequestConfirmationList({ ); const formattedTaxAmount = CurrencyUtils.convertToDisplayString(transaction.taxAmount, iouCurrencyCode); - const defaultTaxKey = policyTaxRates.defaultExternalID; - const defaultTaxName = (defaultTaxKey && `${policyTaxRates.taxes[defaultTaxKey].name} (${policyTaxRates.taxes[defaultTaxKey].value}) • ${translate('common.default')}`) || ''; - const taxRateTitle = (transaction.taxRate && transaction.taxRate.text) || defaultTaxName; + const taxRateTitle = TransactionUtils.getDefaultTaxName(policyTaxRates, transaction); const isFocused = useIsFocused(); const [formError, setFormError] = useState(''); diff --git a/src/pages/iou/request/step/IOURequestStepTaxRatePage.js b/src/pages/iou/request/step/IOURequestStepTaxRatePage.js index 22f826d0457b..ac25f2320684 100644 --- a/src/pages/iou/request/step/IOURequestStepTaxRatePage.js +++ b/src/pages/iou/request/step/IOURequestStepTaxRatePage.js @@ -59,9 +59,7 @@ function IOURequestStepTaxRatePage({ Navigation.goBack(backTo || ROUTES.HOME); }; - const defaultTaxKey = policyTaxRates.defaultExternalID; - const defaultTaxName = (defaultTaxKey && `${policyTaxRates.taxes[defaultTaxKey].name} (${policyTaxRates.taxes[defaultTaxKey].value}) • ${translate('common.default')}`) || ''; - const selectedTaxRate = (transaction.taxRate && transaction.taxRate.text) || defaultTaxName; + const selectedTaxRate = TransactionUtils.getDefaultTaxName(policyTaxRates, transaction); const updateTaxRates = (taxes) => { const taxAmount = getTaxAmount(policyTaxRates, taxes.text, transaction.amount); From 13dccd87ddf5d6a5aa952aed3c5c8a549e9b47a9 Mon Sep 17 00:00:00 2001 From: Etotaziba Olei Date: Thu, 4 Jan 2024 13:32:33 +0100 Subject: [PATCH 037/698] remove unused Navigation import --- src/pages/EditRequestTaxAmountPage.js | 1 - 1 file changed, 1 deletion(-) diff --git a/src/pages/EditRequestTaxAmountPage.js b/src/pages/EditRequestTaxAmountPage.js index b5c20aa82d7c..6a413bf12655 100644 --- a/src/pages/EditRequestTaxAmountPage.js +++ b/src/pages/EditRequestTaxAmountPage.js @@ -5,7 +5,6 @@ import HeaderWithBackButton from '@components/HeaderWithBackButton'; import ScreenWrapper from '@components/ScreenWrapper'; import useLocalize from '@hooks/useLocalize'; import * as DeviceCapabilities from '@libs/DeviceCapabilities'; -import Navigation from '@libs/Navigation/Navigation'; import CONST from '@src/CONST'; import MoneyRequestAmountForm from './iou/steps/MoneyRequestAmountForm'; From 7c154f116a91734baab62bbbfc6a480c7e9e9bf1 Mon Sep 17 00:00:00 2001 From: Etotaziba Olei Date: Thu, 4 Jan 2024 17:44:14 +0100 Subject: [PATCH 038/698] remove tax amount calculation implementation from requestStepAmount --- .../iou/request/step/IOURequestStepAmount.js | 47 +------------------ 1 file changed, 1 insertion(+), 46 deletions(-) diff --git a/src/pages/iou/request/step/IOURequestStepAmount.js b/src/pages/iou/request/step/IOURequestStepAmount.js index 84e0ac8533c5..531d4d4d403b 100644 --- a/src/pages/iou/request/step/IOURequestStepAmount.js +++ b/src/pages/iou/request/step/IOURequestStepAmount.js @@ -1,21 +1,15 @@ import {useFocusEffect} from '@react-navigation/native'; -import PropTypes from 'prop-types'; import React, {useCallback, useRef} from 'react'; -import {withOnyx} from 'react-native-onyx'; -import taxPropTypes from '@components/taxPropTypes'; import transactionPropTypes from '@components/transactionPropTypes'; import useLocalize from '@hooks/useLocalize'; import compose from '@libs/compose'; import * as CurrencyUtils from '@libs/CurrencyUtils'; import Navigation from '@libs/Navigation/Navigation'; -import * as ReportUtils from '@libs/ReportUtils'; import {getRequestType} from '@libs/TransactionUtils'; -import * as TransactionUtils from '@libs/TransactionUtils'; import MoneyRequestAmountForm from '@pages/iou/steps/MoneyRequestAmountForm'; import reportPropTypes from '@pages/reportPropTypes'; import * as IOU from '@userActions/IOU'; import CONST from '@src/CONST'; -import ONYXKEYS from '@src/ONYXKEYS'; import ROUTES from '@src/ROUTES'; import IOURequestStepRoutePropTypes from './IOURequestStepRoutePropTypes'; import StepScreenWrapper from './StepScreenWrapper'; @@ -32,28 +26,11 @@ const propTypes = { /** The transaction object being modified in Onyx */ transaction: transactionPropTypes, - - /* Onyx Props */ - /** Collection of tax rates attached to a policy */ - policyTaxRates: taxPropTypes, - - /** The policy of the report */ - policy: PropTypes.shape({ - /** Is Tax tracking Enabled */ - isTaxTrackingEnabled: PropTypes.bool, - }), }; const defaultProps = { report: {}, transaction: {}, - policyTaxRates: {}, - policy: {}, -}; - -const getTaxAmount = (transaction, defaultTaxValue, amount) => { - const percentage = (transaction.taxRate ? transaction.taxRate.data.value : defaultTaxValue) || ''; - return TransactionUtils.calculateTaxAmount(percentage, amount); }; function IOURequestStepAmount({ @@ -63,8 +40,6 @@ function IOURequestStepAmount({ }, transaction, transaction: {currency: originalCurrency}, - policyTaxRates, - policy, }) { const {translate} = useLocalize(); const textInput = useRef(null); @@ -72,9 +47,6 @@ function IOURequestStepAmount({ const iouRequestType = getRequestType(transaction); const currency = selectedCurrency || originalCurrency; - const isPolicyExpenseChat = ReportUtils.isPolicyExpenseChat(ReportUtils.getRootParentReport(report)); - const isTaxTrackingEnabled = isPolicyExpenseChat && policy.isTaxTrackingEnabled; - useFocusEffect( useCallback(() => { focusTimeoutRef.current = setTimeout(() => textInput.current && textInput.current.focus(), CONST.ANIMATED_TRANSITION); @@ -101,12 +73,6 @@ function IOURequestStepAmount({ const navigateToNextPage = ({amount}) => { const amountInSmallestCurrencyUnits = CurrencyUtils.convertToBackendAmount(Number.parseFloat(amount)); - if ((iouRequestType === CONST.IOU.REQUEST_TYPE.MANUAL || backTo) && isTaxTrackingEnabled) { - const taxAmount = getTaxAmount(transaction, policyTaxRates.defaultValue, amountInSmallestCurrencyUnits); - const taxAmountInSmallestCurrencyUnits = CurrencyUtils.convertToBackendAmount(Number.parseFloat(taxAmount)); - IOU.setMoneyRequestTaxAmount(transaction.transactionID, taxAmountInSmallestCurrencyUnits); - } - IOU.setMoneyRequestAmount_temporaryForRefactor(transactionID, amountInSmallestCurrencyUnits, currency || CONST.CURRENCY.USD); if (backTo) { @@ -153,15 +119,4 @@ IOURequestStepAmount.propTypes = propTypes; IOURequestStepAmount.defaultProps = defaultProps; IOURequestStepAmount.displayName = 'IOURequestStepAmount'; -export default compose( - withWritableReportOrNotFound, - withFullTransactionOrNotFound, - withOnyx({ - policyTaxRates: { - key: ({report}) => `${ONYXKEYS.COLLECTION.POLICY_TAX_RATE}${report ? report.policyID : '0'}`, - }, - policy: { - key: ({report}) => `${ONYXKEYS.COLLECTION.POLICY}${report ? report.policyID : '0'}`, - }, - }), -)(IOURequestStepAmount); +export default compose(withWritableReportOrNotFound, withFullTransactionOrNotFound)(IOURequestStepAmount); From d501ad75a419ea632796612cc5beb347706df0ac Mon Sep 17 00:00:00 2001 From: Etotaziba Olei Date: Thu, 4 Jan 2024 17:44:50 +0100 Subject: [PATCH 039/698] set tax Amount --- ...poraryForRefactorRequestConfirmationList.js | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/src/components/MoneyTemporaryForRefactorRequestConfirmationList.js b/src/components/MoneyTemporaryForRefactorRequestConfirmationList.js index 55890c022179..79dd9e679263 100755 --- a/src/components/MoneyTemporaryForRefactorRequestConfirmationList.js +++ b/src/components/MoneyTemporaryForRefactorRequestConfirmationList.js @@ -8,6 +8,7 @@ import {withOnyx} from 'react-native-onyx'; import _ from 'underscore'; import useLocalize from '@hooks/useLocalize'; import usePermissions from '@hooks/usePermissions'; +import usePrevious from '@hooks/usePrevious'; import useTheme from '@hooks/useTheme'; import useThemeStyles from '@hooks/useThemeStyles'; import compose from '@libs/compose'; @@ -202,6 +203,11 @@ const defaultProps = { policyTaxRates: {}, }; +const getTaxAmount = (transaction, defaultTaxValue) => { + const percentage = (transaction.taxRate ? transaction.taxRate.data.value : defaultTaxValue) || ''; + return TransactionUtils.calculateTaxAmount(percentage, transaction.amount); +}; + function MoneyTemporaryForRefactorRequestConfirmationList({ bankAccountRoute, canModifyParticipants, @@ -294,6 +300,8 @@ function MoneyTemporaryForRefactorRequestConfirmationList({ const taxRateTitle = TransactionUtils.getDefaultTaxName(policyTaxRates, transaction); + const previousTransactionTaxAmount = usePrevious(transaction.taxAmount); + const isFocused = useIsFocused(); const [formError, setFormError] = useState(''); @@ -351,6 +359,16 @@ function MoneyTemporaryForRefactorRequestConfirmationList({ IOU.setMoneyRequestAmount_temporaryForRefactor(transaction.transactionID, amount, currency); }, [shouldCalculateDistanceAmount, distance, rate, unit, transaction, currency]); + // calculate and set tax amount in transaction draft + useEffect(() => { + const taxAmount = getTaxAmount(transaction, policyTaxRates.defaultValue); + const amountInSmallestCurrencyUnits = CurrencyUtils.convertToBackendAmount(Number.parseFloat(taxAmount)); + if (previousTransactionTaxAmount !== transaction.taxAmount && amountInSmallestCurrencyUnits !== transaction.taxAmount) { + return; + } + IOU.setMoneyRequestTaxAmount(transaction.transactionID, amountInSmallestCurrencyUnits); + }, [policyTaxRates.defaultValue, transaction, previousTransactionTaxAmount]); + /** * Returns the participants with amount * @param {Array} participants From 13deb831497581a1a314f42e975127cb6bde2883 Mon Sep 17 00:00:00 2001 From: Etotaziba Olei Date: Thu, 4 Jan 2024 22:19:40 +0100 Subject: [PATCH 040/698] add Tax amount and Code API for updates --- src/libs/actions/IOU.js | 32 ++++++++++++++++++++++++++++++++ 1 file changed, 32 insertions(+) diff --git a/src/libs/actions/IOU.js b/src/libs/actions/IOU.js index b999435cc3e7..dc087ba42eac 100644 --- a/src/libs/actions/IOU.js +++ b/src/libs/actions/IOU.js @@ -1051,6 +1051,36 @@ function updateMoneyRequestDate(transactionID, transactionThreadReportID, val) { API.write('UpdateMoneyRequestDate', params, onyxData); } +/** + * Updates the created tax amount of a money request + * + * @param {String} transactionID + * @param {String} optimisticReportActionID + * @param {Number} val + */ +function updateMoneyRequestTaxAmount(transactionID, optimisticReportActionID, val) { + const transactionChanges = { + taxAmount: val, + }; + const {params, onyxData} = getUpdateMoneyRequestParams(transactionID, optimisticReportActionID, transactionChanges, true); + API.write('UpdateMoneyRequestTaxAmount', params, onyxData); +} + +/** + * Updates the created tax rate of a money request + * + * @param {String} transactionID + * @param {String} optimisticReportActionID + * @param {String} val + */ +function updateMoneyRequestTaxRate(transactionID, optimisticReportActionID, val) { + const transactionChanges = { + taxCode: val, + }; + const {params, onyxData} = getUpdateMoneyRequestParams(transactionID, optimisticReportActionID, transactionChanges, true); + API.write('UpdateMoneyRequestTaxRate', params, onyxData); +} + /** * Edits an existing distance request * @@ -3490,6 +3520,8 @@ export { setUpDistanceTransaction, navigateToNextPage, updateMoneyRequestDate, + updateMoneyRequestTaxAmount, + updateMoneyRequestTaxRate, updateMoneyRequestAmountAndCurrency, replaceReceipt, detachReceipt, From fc3e59356aa037f68c525100a5b83358120fe0d9 Mon Sep 17 00:00:00 2001 From: Etotaziba Olei Date: Mon, 8 Jan 2024 16:46:55 +0100 Subject: [PATCH 041/698] add function to check if tax rate has enabled options --- src/libs/OptionsListUtils.js | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/src/libs/OptionsListUtils.js b/src/libs/OptionsListUtils.js index 0dc12c720f31..3aa9ffc690bb 100644 --- a/src/libs/OptionsListUtils.js +++ b/src/libs/OptionsListUtils.js @@ -1058,6 +1058,17 @@ function getTagListSections(rawTags, recentlyUsedTags, selectedOptions, searchIn return tagSections; } +/** + * Verifies that there is at least one enabled option + * + * @param {Object[]} options - an initial strings array + * @property {boolean} [isDisabled] - Indicates if the tax rate is disabled. + * @returns {Boolean} + */ +function hasEnabledOptionsForTaxRate(options) { + return _.some(options, (option) => !option.isDisabled); +} + /** * Represents the data for a single tax rate. * @@ -1953,6 +1964,7 @@ export { getLastMessageTextForReport, getEnabledCategoriesCount, hasEnabledOptions, + hasEnabledOptionsForTaxRate, sortCategories, getCategoryOptionTree, formatMemberForList, From a6daa02f50f5ffb618e366dc6f10bbb3f7eedd4c Mon Sep 17 00:00:00 2001 From: Etotaziba Olei Date: Mon, 8 Jan 2024 16:48:15 +0100 Subject: [PATCH 042/698] add defaults for tax rate and amount and amount title --- .../ReportActionItem/MoneyRequestView.js | 16 +++++++++++++--- 1 file changed, 13 insertions(+), 3 deletions(-) diff --git a/src/components/ReportActionItem/MoneyRequestView.js b/src/components/ReportActionItem/MoneyRequestView.js index 0b662f9d3578..a38b711e7192 100644 --- a/src/components/ReportActionItem/MoneyRequestView.js +++ b/src/components/ReportActionItem/MoneyRequestView.js @@ -155,6 +155,12 @@ function MoneyRequestView({report, parentReport, parentReportActions, policyCate const isCardTransaction = TransactionUtils.isCardTransaction(transaction); const cardProgramName = isCardTransaction ? CardUtils.getCardDescription(transactionCardID) : ''; + const transactionTaxAmount = (transaction.taxAmount && transaction.taxAmount) || 0; + const formattedTaxAmount = CurrencyUtils.convertToDisplayString(transactionTaxAmount, transactionCurrency); + + const transactionTaxCode = transaction.taxCode && transaction.taxCode; + const taxRateTitle = (transactionTaxCode && policyTaxRates.taxes[transactionTaxCode].name) || ''; + // Flags for allowing or disallowing editing a money request const isSettled = ReportUtils.isSettled(moneyRequestReport.reportID); const isCancelled = moneyRequestReport && moneyRequestReport.isCancelledIOU; @@ -181,7 +187,11 @@ function MoneyRequestView({report, parentReport, parentReportActions, policyCate const shouldShowBillable = isPolicyExpenseChat && (transactionBillable || !lodashGet(policy, 'disabledFields.defaultBillable', true)); // A flag for showing tax rate - const shouldShowTax = isPolicyExpenseChat && policy.isTaxTrackingEnabled; + const shouldShowTax = + isPolicyExpenseChat && + policy && + policy.isTaxTrackingEnabled && + ((transactionTaxCode && transactionTaxAmount) || OptionsListUtils.hasEnabledOptionsForTaxRate(lodashValues(policyTaxRates.taxes))); const {getViolationsForField} = useViolations(transactionViolations); const hasViolations = useCallback((field) => canUseViolations && getViolationsForField(field).length > 0, [canUseViolations, getViolationsForField]); @@ -359,7 +369,7 @@ function MoneyRequestView({report, parentReport, parentReportActions, policyCate {shouldShowTax && ( Date: Mon, 8 Jan 2024 16:50:03 +0100 Subject: [PATCH 043/698] add defaults for tax rate and amount and amount title --- src/pages/EditRequestPage.js | 29 +++++++++++++++++++++++------ 1 file changed, 23 insertions(+), 6 deletions(-) diff --git a/src/pages/EditRequestPage.js b/src/pages/EditRequestPage.js index 7e91b6787e5f..f47950eb71ff 100644 --- a/src/pages/EditRequestPage.js +++ b/src/pages/EditRequestPage.js @@ -7,6 +7,7 @@ import FullPageNotFoundView from '@components/BlockingViews/FullPageNotFoundView import categoryPropTypes from '@components/categoryPropTypes'; import ScreenWrapper from '@components/ScreenWrapper'; import tagPropTypes from '@components/tagPropTypes'; +import taxPropTypes from '@components/taxPropTypes'; import transactionPropTypes from '@components/transactionPropTypes'; import compose from '@libs/compose'; import * as CurrencyUtils from '@libs/CurrencyUtils'; @@ -66,6 +67,10 @@ const propTypes = { /** Is Tax tracking Enabled */ isTaxTrackingEnabled: PropTypes.bool, }), + + /* Onyx Props */ + /** Collection of tax rates attached to a policy */ + policyTaxRates: taxPropTypes, }; const defaultProps = { @@ -75,9 +80,10 @@ const defaultProps = { parentReportActions: {}, transaction: {}, policy: {}, + policyTaxRates: {}, }; -function EditRequestPage({report, policy, route, policyCategories, policyTags, parentReportActions, transaction}) { +function EditRequestPage({report, policy, policyTaxRates, route, policyCategories, policyTags, parentReportActions, transaction}) { const parentReportActionID = lodashGet(report, 'parentReportActionID', '0'); const parentReportAction = lodashGet(parentReportActions, parentReportActionID, {}); const { @@ -92,6 +98,11 @@ function EditRequestPage({report, policy, route, policyCategories, policyTags, p const defaultCurrency = lodashGet(route, 'params.currency', '') || transactionCurrency; const fieldToEdit = lodashGet(route, ['params', 'field'], ''); + const transactionTaxAmount = (transaction.taxAmount && transaction.taxAmount) || 0; + + const transactionTaxCode = transaction.taxCode && transaction.taxCode; + const taxRateTitle = (transactionTaxCode && policyTaxRates.taxes[transactionTaxCode].name) || ''; + // For now, it always defaults to the first tag of the policy const policyTag = PolicyUtils.getTag(policyTags); const policyTagList = lodashGet(policyTag, 'tags', {}); @@ -267,10 +278,13 @@ function EditRequestPage({report, policy, route, policyCategories, policyTags, p if (fieldToEdit === CONST.EDIT_REQUEST_FIELD.TAX_AMOUNT && shouldShowTax) { return ( {}} + defaultAmount={transactionAmount} + defaultTaxAmount={transactionTaxAmount} + defaultCurrency={defaultCurrency} + onNavigateToCurrency={() => { + const activeRoute = encodeURIComponent(Navigation.getActiveRouteWithoutParams()); + Navigation.navigate(ROUTES.EDIT_CURRENCY_REQUEST.getRoute(report.reportID, defaultCurrency, activeRoute)); + }} onSubmit={() => {}} /> ); @@ -279,7 +293,7 @@ function EditRequestPage({report, policy, route, policyCategories, policyTags, p if (fieldToEdit === CONST.EDIT_REQUEST_FIELD.TAX_RATE && shouldShowTax) { return ( {}} /> @@ -336,6 +350,9 @@ export default compose( policyTags: { key: ({report}) => `${ONYXKEYS.COLLECTION.POLICY_TAGS}${report ? report.policyID : '0'}`, }, + policyTaxRates: { + key: ({report}) => `${ONYXKEYS.COLLECTION.POLICY_TAX_RATE}${report.policyID}`, + }, parentReportActions: { key: ({report}) => `${ONYXKEYS.COLLECTION.REPORT_ACTIONS}${report ? report.parentReportID : '0'}`, canEvict: false, From 24e7c072e69f5853ac6499d2d1345f7cf807bf7d Mon Sep 17 00:00:00 2001 From: Etotaziba Olei Date: Mon, 8 Jan 2024 17:17:19 +0100 Subject: [PATCH 044/698] add update functions to taxAmount and taxRate --- src/pages/EditRequestPage.js | 24 ++++++++++++++++++++++-- 1 file changed, 22 insertions(+), 2 deletions(-) diff --git a/src/pages/EditRequestPage.js b/src/pages/EditRequestPage.js index f47950eb71ff..df13c727e430 100644 --- a/src/pages/EditRequestPage.js +++ b/src/pages/EditRequestPage.js @@ -139,6 +139,26 @@ function EditRequestPage({report, policy, policyTaxRates, route, policyCategorie Navigation.dismissModal(report.reportID); } + const updateTaxAmount = (transactionChanges) => { + if (transactionChanges.amount === transactionTaxAmount) { + return; + } + + const newTaxAmount = CurrencyUtils.convertToBackendAmount(Number.parseFloat(transactionChanges.amount)); + IOU.updateMoneyRequestTaxAmount(transaction.transactionID, report.reportID, newTaxAmount); + Navigation.dismissModal(report.reportID); + }; + + const updateTaxRate = (transactionChanges) => { + const newTaxCode = transactionChanges.data.code; + if (newTaxCode === transactionTaxCode) { + return; + } + + IOU.updateMoneyRequestTaxRate(transaction.transactionID, report.reportID, newTaxCode); + Navigation.dismissModal(report.reportID); + }; + const saveAmountAndCurrency = useCallback( ({amount, currency: newCurrency}) => { const newAmount = CurrencyUtils.convertToBackendAmount(Number.parseFloat(amount)); @@ -285,7 +305,7 @@ function EditRequestPage({report, policy, policyTaxRates, route, policyCategorie const activeRoute = encodeURIComponent(Navigation.getActiveRouteWithoutParams()); Navigation.navigate(ROUTES.EDIT_CURRENCY_REQUEST.getRoute(report.reportID, defaultCurrency, activeRoute)); }} - onSubmit={() => {}} + onSubmit={updateTaxAmount} /> ); } @@ -295,7 +315,7 @@ function EditRequestPage({report, policy, policyTaxRates, route, policyCategorie {}} + onSubmit={updateTaxRate} /> ); } From 101aa5b69eceb36e96d8ba09d1208be8f369fbee Mon Sep 17 00:00:00 2001 From: Etotaziba Olei Date: Mon, 8 Jan 2024 19:59:18 +0100 Subject: [PATCH 045/698] update default amount and taxAmount --- src/pages/EditRequestPage.js | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/src/pages/EditRequestPage.js b/src/pages/EditRequestPage.js index df13c727e430..3f346d649bca 100644 --- a/src/pages/EditRequestPage.js +++ b/src/pages/EditRequestPage.js @@ -82,7 +82,10 @@ const defaultProps = { policy: {}, policyTaxRates: {}, }; - +const getTaxAmount = (transaction, transactionTaxCode, policyTaxRates) => { + const percentage = (transactionTaxCode ? policyTaxRates.taxes[transactionTaxCode].value : policyTaxRates.defaultValue) || ''; + return CurrencyUtils.convertToBackendAmount(Number.parseFloat(TransactionUtils.calculateTaxAmount(percentage, transaction.amount))); +}; function EditRequestPage({report, policy, policyTaxRates, route, policyCategories, policyTags, parentReportActions, transaction}) { const parentReportActionID = lodashGet(report, 'parentReportActionID', '0'); const parentReportAction = lodashGet(parentReportActions, parentReportActionID, {}); @@ -298,8 +301,8 @@ function EditRequestPage({report, policy, policyTaxRates, route, policyCategorie if (fieldToEdit === CONST.EDIT_REQUEST_FIELD.TAX_AMOUNT && shouldShowTax) { return ( { const activeRoute = encodeURIComponent(Navigation.getActiveRouteWithoutParams()); From 61bf4767d02c4f00ed8eecd6f343567dad43a5dc Mon Sep 17 00:00:00 2001 From: Etotaziba Olei Date: Tue, 9 Jan 2024 07:25:51 +0100 Subject: [PATCH 046/698] use function for tax policy --- src/components/MoneyRequestConfirmationList.js | 5 +++-- .../MoneyTemporaryForRefactorRequestConfirmationList.js | 3 ++- src/components/ReportActionItem/MoneyRequestView.js | 6 ++---- src/libs/PolicyUtils.ts | 5 +++++ src/pages/EditRequestPage.js | 5 +++-- src/types/onyx/Policy.ts | 3 +++ 6 files changed, 18 insertions(+), 9 deletions(-) diff --git a/src/components/MoneyRequestConfirmationList.js b/src/components/MoneyRequestConfirmationList.js index 260c27205e94..385d411427ba 100755 --- a/src/components/MoneyRequestConfirmationList.js +++ b/src/components/MoneyRequestConfirmationList.js @@ -20,6 +20,7 @@ import * as MoneyRequestUtils from '@libs/MoneyRequestUtils'; import Navigation from '@libs/Navigation/Navigation'; import * as OptionsListUtils from '@libs/OptionsListUtils'; import * as PolicyUtils from '@libs/PolicyUtils'; +import {isTaxPolicyEnabled} from '@libs/PolicyUtils'; import * as ReceiptUtils from '@libs/ReceiptUtils'; import * as ReportUtils from '@libs/ReportUtils'; import * as TransactionUtils from '@libs/TransactionUtils'; @@ -247,8 +248,8 @@ function MoneyRequestConfirmationList(props) { // A flag for showing the tags field const shouldShowTags = props.isPolicyExpenseChat && (props.iouTag || OptionsListUtils.hasEnabledOptions(_.values(policyTagList))); - // A flag for showing tax fields - tax rate and tax amount - const shouldShowTax = props.isPolicyExpenseChat && props.policy.isTaxTrackingEnabled; + // A flag for showing tax rate + const shouldShowTax = isTaxPolicyEnabled(props.isPolicyExpenseChat, props.policy); // A flag for showing the billable field const shouldShowBillable = !lodashGet(props.policy, 'disabledFields.defaultBillable', true); diff --git a/src/components/MoneyTemporaryForRefactorRequestConfirmationList.js b/src/components/MoneyTemporaryForRefactorRequestConfirmationList.js index 335a9e2f6801..5bd42ff11cf7 100755 --- a/src/components/MoneyTemporaryForRefactorRequestConfirmationList.js +++ b/src/components/MoneyTemporaryForRefactorRequestConfirmationList.js @@ -20,6 +20,7 @@ import * as MoneyRequestUtils from '@libs/MoneyRequestUtils'; import Navigation from '@libs/Navigation/Navigation'; import * as OptionsListUtils from '@libs/OptionsListUtils'; import * as PolicyUtils from '@libs/PolicyUtils'; +import {isTaxPolicyEnabled} from '@libs/PolicyUtils'; import * as ReceiptUtils from '@libs/ReceiptUtils'; import * as ReportUtils from '@libs/ReportUtils'; import * as TransactionUtils from '@libs/TransactionUtils'; @@ -283,7 +284,7 @@ function MoneyTemporaryForRefactorRequestConfirmationList({ const shouldShowTags = isPolicyExpenseChat && OptionsListUtils.hasEnabledOptions(_.values(policyTagList)); // A flag for showing tax rate - const shouldShowTax = isPolicyExpenseChat && policy && policy.isTaxTrackingEnabled; + const shouldShowTax = isTaxPolicyEnabled(isPolicyExpenseChat, policy); // A flag for showing the billable field const shouldShowBillable = !lodashGet(policy, 'disabledFields.defaultBillable', true); diff --git a/src/components/ReportActionItem/MoneyRequestView.js b/src/components/ReportActionItem/MoneyRequestView.js index a38b711e7192..bd22c3f42415 100644 --- a/src/components/ReportActionItem/MoneyRequestView.js +++ b/src/components/ReportActionItem/MoneyRequestView.js @@ -30,6 +30,7 @@ import * as CurrencyUtils from '@libs/CurrencyUtils'; import Navigation from '@libs/Navigation/Navigation'; import * as OptionsListUtils from '@libs/OptionsListUtils'; import * as PolicyUtils from '@libs/PolicyUtils'; +import {isTaxPolicyEnabled} from '@libs/PolicyUtils'; import * as ReceiptUtils from '@libs/ReceiptUtils'; import * as ReportActionsUtils from '@libs/ReportActionsUtils'; import * as ReportUtils from '@libs/ReportUtils'; @@ -188,10 +189,7 @@ function MoneyRequestView({report, parentReport, parentReportActions, policyCate // A flag for showing tax rate const shouldShowTax = - isPolicyExpenseChat && - policy && - policy.isTaxTrackingEnabled && - ((transactionTaxCode && transactionTaxAmount) || OptionsListUtils.hasEnabledOptionsForTaxRate(lodashValues(policyTaxRates.taxes))); + isTaxPolicyEnabled(isPolicyExpenseChat, policy) && ((transactionTaxCode && transactionTaxAmount) || OptionsListUtils.hasEnabledOptionsForTaxRate(lodashValues(policyTaxRates.taxes))); const {getViolationsForField} = useViolations(transactionViolations); const hasViolations = useCallback((field) => canUseViolations && getViolationsForField(field).length > 0, [canUseViolations, getViolationsForField]); diff --git a/src/libs/PolicyUtils.ts b/src/libs/PolicyUtils.ts index 0cab97299324..831dc625cb95 100644 --- a/src/libs/PolicyUtils.ts +++ b/src/libs/PolicyUtils.ts @@ -202,6 +202,10 @@ function isPaidGroupPolicy(policy: OnyxEntry): boolean { return policy?.type === CONST.POLICY.TYPE.TEAM || policy?.type === CONST.POLICY.TYPE.CORPORATE; } +function isTaxPolicyEnabled(isPolicyExpenseChat: boolean, policy: OnyxEntry): boolean { + return (isPolicyExpenseChat && policy?.isTaxTrackingEnabled) ?? false; +} + export { getActivePolicies, hasPolicyMemberError, @@ -215,6 +219,7 @@ export { isExpensifyTeam, isExpensifyGuideTeam, isPolicyAdmin, + isTaxPolicyEnabled, getMemberAccountIDsForWorkspace, getIneligibleInvitees, getTag, diff --git a/src/pages/EditRequestPage.js b/src/pages/EditRequestPage.js index 7f9839f39111..8f1830e43a5f 100644 --- a/src/pages/EditRequestPage.js +++ b/src/pages/EditRequestPage.js @@ -14,6 +14,7 @@ import * as CurrencyUtils from '@libs/CurrencyUtils'; import Navigation from '@libs/Navigation/Navigation'; import * as OptionsListUtils from '@libs/OptionsListUtils'; import * as PolicyUtils from '@libs/PolicyUtils'; +import {isTaxPolicyEnabled} from '@libs/PolicyUtils'; import * as ReportUtils from '@libs/ReportUtils'; import * as TransactionUtils from '@libs/TransactionUtils'; import * as IOU from '@userActions/IOU'; @@ -83,7 +84,7 @@ const defaultProps = { policyTaxRates: {}, }; const getTaxAmount = (transaction, transactionTaxCode, policyTaxRates) => { - const percentage = (transactionTaxCode ? policyTaxRates.taxes[transactionTaxCode].value : policyTaxRates.defaultValue) || ''; + const percentage = (transactionTaxCode ? policyTaxRates.taxes[transactionTaxCode].value : policyTaxRates.defaultValue) || ''; return CurrencyUtils.convertToBackendAmount(Number.parseFloat(TransactionUtils.calculateTaxAmount(percentage, transaction.amount))); }; function EditRequestPage({report, policy, policyTaxRates, route, policyCategories, policyTags, parentReportActions, transaction}) { @@ -121,7 +122,7 @@ function EditRequestPage({report, policy, policyTaxRates, route, policyCategorie const shouldShowTags = isPolicyExpenseChat && (transactionTag || OptionsListUtils.hasEnabledOptions(lodashValues(policyTagList))); // A flag for showing tax rate - const shouldShowTax = isPolicyExpenseChat && policy && policy.isTaxTrackingEnabled; + const shouldShowTax = isTaxPolicyEnabled(isPolicyExpenseChat, policy); // Decides whether to allow or disallow editing a money request useEffect(() => { diff --git a/src/types/onyx/Policy.ts b/src/types/onyx/Policy.ts index ff3a5e1dd23c..fc2eb02171da 100644 --- a/src/types/onyx/Policy.ts +++ b/src/types/onyx/Policy.ts @@ -65,6 +65,9 @@ type Policy = { /** Whether chat rooms can be created and used on this policy. Enabled manually by CQ/JS snippet. Always true for free policies. */ areChatRoomsEnabled: boolean; + /** Is Tax tracking Enabled */ + isTaxTrackingEnabled: boolean; + /** Whether policy expense chats can be created and used on this policy. Enabled manually by CQ/JS snippet. Always true for free policies. */ isPolicyExpenseChatEnabled: boolean; From e85912965de70ef3c933b9b2ed7c9d22a80f8671 Mon Sep 17 00:00:00 2001 From: Etotaziba Olei Date: Tue, 9 Jan 2024 07:35:50 +0100 Subject: [PATCH 047/698] make isTaxTrackingEnabled optional --- src/types/onyx/Policy.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/types/onyx/Policy.ts b/src/types/onyx/Policy.ts index fc2eb02171da..fc7f273de76d 100644 --- a/src/types/onyx/Policy.ts +++ b/src/types/onyx/Policy.ts @@ -66,7 +66,7 @@ type Policy = { areChatRoomsEnabled: boolean; /** Is Tax tracking Enabled */ - isTaxTrackingEnabled: boolean; + isTaxTrackingEnabled?: boolean; /** Whether policy expense chats can be created and used on this policy. Enabled manually by CQ/JS snippet. Always true for free policies. */ isPolicyExpenseChatEnabled: boolean; From fab239109cc035481c0429affee138a4ac7d01b8 Mon Sep 17 00:00:00 2001 From: Etotaziba Olei Date: Wed, 10 Jan 2024 05:08:53 +0100 Subject: [PATCH 048/698] add tax amount and code type to Transaction types --- src/types/onyx/Transaction.ts | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/types/onyx/Transaction.ts b/src/types/onyx/Transaction.ts index 399f1414db70..4aa61b8923c5 100644 --- a/src/types/onyx/Transaction.ts +++ b/src/types/onyx/Transaction.ts @@ -51,6 +51,8 @@ type Routes = Record; type Transaction = { amount: number; + taxAmount?: number; + taxCode?: string; billable: boolean; category: string; comment: Comment; From 9fd85f95026327b8f919252ba26f8320eb045bb2 Mon Sep 17 00:00:00 2001 From: Etotaziba Olei Date: Wed, 10 Jan 2024 05:11:34 +0100 Subject: [PATCH 049/698] get tax amount abs value and tax code --- src/libs/TransactionUtils.ts | 23 +++++++++++++++++++++++ 1 file changed, 23 insertions(+) diff --git a/src/libs/TransactionUtils.ts b/src/libs/TransactionUtils.ts index 5f8443b126c5..1b78d6f8ab6d 100644 --- a/src/libs/TransactionUtils.ts +++ b/src/libs/TransactionUtils.ts @@ -282,6 +282,27 @@ function getAmount(transaction: OnyxEntry, isFromExpenseReport: boo return amount ? -amount : 0; } +/** + * Return the tax amount field from the transaction. + */ +function getTaxAmount(transaction: OnyxEntry, isFromExpenseReport: boolean): number { + // IOU requests cannot have negative values but they can be stored as negative values, let's return absolute value + if (!isFromExpenseReport) { + return Math.abs(transaction?.taxAmount ?? 0); + } + + // To avoid -0 being shown, lets only change the sign if the value is other than 0. + const amount = transaction?.taxAmount ?? 0; + return amount ? -amount : 0; +} + +/** + * Return the tax code from the transaction. + */ +function getTaxCode(transaction: OnyxEntry): string { + return transaction?.taxCode ?? ''; +} + /** * Return the currency field from the transaction, return the modifiedCurrency if present. */ @@ -559,6 +580,8 @@ export { isManualRequest, isScanRequest, getAmount, + getTaxAmount, + getTaxCode, getCurrency, getDistance, getCardID, From 33cf5c438ec307cedb1fc1ef6b17691b046050b6 Mon Sep 17 00:00:00 2001 From: Etotaziba Olei Date: Wed, 10 Jan 2024 05:13:32 +0100 Subject: [PATCH 050/698] add new fields in getTransactionDetails --- src/libs/ReportUtils.ts | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/libs/ReportUtils.ts b/src/libs/ReportUtils.ts index 0d7658adf180..e4d7cb728e82 100644 --- a/src/libs/ReportUtils.ts +++ b/src/libs/ReportUtils.ts @@ -281,6 +281,8 @@ type TransactionDetails = | { created: string; amount: number; + taxAmount?: number; + taxCode?: string; currency: string; merchant: string; waypoints?: WaypointCollection; @@ -1839,6 +1841,8 @@ function getTransactionDetails(transaction: OnyxEntry, createdDateF return { created: TransactionUtils.getCreated(transaction, createdDateFormat), amount: TransactionUtils.getAmount(transaction, isNotEmptyObject(report) && isExpenseReport(report)), + taxAmount: TransactionUtils.getTaxAmount(transaction, isNotEmptyObject(report) && isExpenseReport(report)), + taxCode: TransactionUtils.getTaxCode(transaction), currency: TransactionUtils.getCurrency(transaction), comment: TransactionUtils.getDescription(transaction), merchant: TransactionUtils.getMerchant(transaction), From 9d6e5b0372519213cf0b9dd92cd7d2a3370e6e9d Mon Sep 17 00:00:00 2001 From: Etotaziba Olei Date: Wed, 10 Jan 2024 05:16:06 +0100 Subject: [PATCH 051/698] get and use new tax amount and code fields from getTransactionDetails --- .../ReportActionItem/MoneyRequestView.js | 15 ++++++------ src/pages/EditRequestPage.js | 23 +++++++------------ 2 files changed, 16 insertions(+), 22 deletions(-) diff --git a/src/components/ReportActionItem/MoneyRequestView.js b/src/components/ReportActionItem/MoneyRequestView.js index 73bbda7bd3b7..c656ff45add7 100644 --- a/src/components/ReportActionItem/MoneyRequestView.js +++ b/src/components/ReportActionItem/MoneyRequestView.js @@ -135,6 +135,8 @@ function MoneyRequestView({report, parentReport, parentReportActions, policyCate const { created: transactionDate, amount: transactionAmount, + taxAmount: transactionTaxAmount, + taxCode: transactionTaxCode, currency: transactionCurrency, comment: transactionDescription, merchant: transactionMerchant, @@ -156,11 +158,11 @@ function MoneyRequestView({report, parentReport, parentReportActions, policyCate const isCardTransaction = TransactionUtils.isCardTransaction(transaction); const cardProgramName = isCardTransaction ? CardUtils.getCardDescription(transactionCardID) : ''; - const transactionTaxAmount = (transaction.taxAmount && transaction.taxAmount) || 0; - const formattedTaxAmount = CurrencyUtils.convertToDisplayString(transactionTaxAmount, transactionCurrency); + const formattedTaxAmount = transactionTaxAmount ? CurrencyUtils.convertToDisplayString(transactionTaxAmount, transactionCurrency) : ''; - const transactionTaxCode = transaction.taxCode && transaction.taxCode; - const taxRateTitle = (transactionTaxCode && policyTaxRates.taxes[transactionTaxCode].name) || ''; + const taxName = `${policyTaxRates.taxes[transactionTaxCode].name}`; + const taxValue = `${policyTaxRates.taxes[transactionTaxCode].value}`; + const taxRateTitle = transactionTaxCode ? `${taxName} (${taxValue})` : ''; // Flags for allowing or disallowing editing a money request const isSettled = ReportUtils.isSettled(moneyRequestReport.reportID); @@ -188,8 +190,7 @@ function MoneyRequestView({report, parentReport, parentReportActions, policyCate const shouldShowBillable = isPolicyExpenseChat && (transactionBillable || !lodashGet(policy, 'disabledFields.defaultBillable', true)); // A flag for showing tax rate - const shouldShowTax = - isTaxPolicyEnabled(isPolicyExpenseChat, policy) && ((transactionTaxCode && transactionTaxAmount) || OptionsListUtils.hasEnabledOptionsForTaxRate(lodashValues(policyTaxRates.taxes))); + const shouldShowTax = isTaxPolicyEnabled(isPolicyExpenseChat, policy) && transactionTaxCode && transactionTaxAmount; const {getViolationsForField} = useViolations(transactionViolations); const hasViolations = useCallback((field) => canUseViolations && getViolationsForField(field).length > 0, [canUseViolations, getViolationsForField]); @@ -393,7 +394,7 @@ function MoneyRequestView({report, parentReport, parentReportActions, policyCate {shouldShowTax && ( { +const getTaxAmount = (transactionAmount, transactionTaxCode, policyTaxRates) => { const percentage = (transactionTaxCode ? policyTaxRates.taxes[transactionTaxCode].value : policyTaxRates.defaultValue) || ''; - return CurrencyUtils.convertToBackendAmount(Number.parseFloat(TransactionUtils.calculateTaxAmount(percentage, transaction.amount))); + return CurrencyUtils.convertToBackendAmount(Number.parseFloat(TransactionUtils.calculateTaxAmount(percentage, transactionAmount))); }; function EditRequestPage({report, policy, policyTaxRates, route, policyCategories, policyTags, parentReportActions, transaction}) { const parentReportActionID = lodashGet(report, 'parentReportActionID', '0'); const parentReportAction = lodashGet(parentReportActions, parentReportActionID, {}); const { amount: transactionAmount, + taxAmount: transactionTaxAmount, + taxCode: transactionTaxCode, currency: transactionCurrency, comment: transactionDescription, merchant: transactionMerchant, @@ -102,10 +104,9 @@ function EditRequestPage({report, policy, policyTaxRates, route, policyCategorie const defaultCurrency = lodashGet(route, 'params.currency', '') || transactionCurrency; const fieldToEdit = lodashGet(route, ['params', 'field'], ''); - const transactionTaxAmount = (transaction.taxAmount && transaction.taxAmount) || 0; - - const transactionTaxCode = transaction.taxCode && transaction.taxCode; - const taxRateTitle = (transactionTaxCode && policyTaxRates.taxes[transactionTaxCode].name) || ''; + const taxName = `${policyTaxRates.taxes[transactionTaxCode].name}`; + const taxValue = `${policyTaxRates.taxes[transactionTaxCode].value}`; + const taxRateTitle = transactionTaxCode ? `${taxName} (${taxValue})` : ''; // For now, it always defaults to the first tag of the policy const policyTag = PolicyUtils.getTag(policyTags); @@ -144,10 +145,6 @@ function EditRequestPage({report, policy, policyTaxRates, route, policyCategorie } const updateTaxAmount = (transactionChanges) => { - if (transactionChanges.amount === transactionTaxAmount) { - return; - } - const newTaxAmount = CurrencyUtils.convertToBackendAmount(Number.parseFloat(transactionChanges.amount)); IOU.updateMoneyRequestTaxAmount(transaction.transactionID, report.reportID, newTaxAmount); Navigation.dismissModal(report.reportID); @@ -155,10 +152,6 @@ function EditRequestPage({report, policy, policyTaxRates, route, policyCategorie const updateTaxRate = (transactionChanges) => { const newTaxCode = transactionChanges.data.code; - if (newTaxCode === transactionTaxCode) { - return; - } - IOU.updateMoneyRequestTaxRate(transaction.transactionID, report.reportID, newTaxCode); Navigation.dismissModal(report.reportID); }; @@ -310,7 +303,7 @@ function EditRequestPage({report, policy, policyTaxRates, route, policyCategorie return ( { const activeRoute = encodeURIComponent(Navigation.getActiveRouteWithoutParams()); From 25cb89edceac9386323076eb7eda8b53a5e9a17c Mon Sep 17 00:00:00 2001 From: Etotaziba Olei Date: Wed, 10 Jan 2024 05:29:28 +0100 Subject: [PATCH 052/698] add getTaxName to TransactionUtils --- src/libs/TransactionUtils.ts | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/src/libs/TransactionUtils.ts b/src/libs/TransactionUtils.ts index 1b78d6f8ab6d..8aa9f05f813b 100644 --- a/src/libs/TransactionUtils.ts +++ b/src/libs/TransactionUtils.ts @@ -558,7 +558,7 @@ function getEnabledTaxRateCount(options: TaxRates) { } /** - * Calculates get's the default tax name + * Get's the default tax name */ function getDefaultTaxName(policyTaxRates: PolicyTaxRates, transaction: Transaction) { const defaultTaxKey = policyTaxRates.defaultExternalID; @@ -567,9 +567,19 @@ function getDefaultTaxName(policyTaxRates: PolicyTaxRates, transaction: Transact return transaction?.taxRate?.text ?? defaultTaxName; } +/** + * Get's the tax name + */ +function getTaxName(taxes: TaxRates, transactionTaxCode: string) { + const taxName = `${taxes[transactionTaxCode].name}`; + const taxValue = `${taxes[transactionTaxCode].value}`; + return transactionTaxCode ? `${taxName} (${taxValue})` : ''; +} + export { buildOptimisticTransaction, calculateTaxAmount, + getTaxName, getDefaultTaxName, getEnabledTaxRateCount, getUpdatedTransaction, From 9a9b1820bd7d3d8b157ad0d5cdc846a36a1bbbad Mon Sep 17 00:00:00 2001 From: Etotaziba Olei Date: Wed, 10 Jan 2024 05:30:35 +0100 Subject: [PATCH 053/698] use getTaxName --- src/components/ReportActionItem/MoneyRequestView.js | 4 +--- src/pages/EditRequestPage.js | 4 +--- 2 files changed, 2 insertions(+), 6 deletions(-) diff --git a/src/components/ReportActionItem/MoneyRequestView.js b/src/components/ReportActionItem/MoneyRequestView.js index c656ff45add7..60ed51d10506 100644 --- a/src/components/ReportActionItem/MoneyRequestView.js +++ b/src/components/ReportActionItem/MoneyRequestView.js @@ -160,9 +160,7 @@ function MoneyRequestView({report, parentReport, parentReportActions, policyCate const formattedTaxAmount = transactionTaxAmount ? CurrencyUtils.convertToDisplayString(transactionTaxAmount, transactionCurrency) : ''; - const taxName = `${policyTaxRates.taxes[transactionTaxCode].name}`; - const taxValue = `${policyTaxRates.taxes[transactionTaxCode].value}`; - const taxRateTitle = transactionTaxCode ? `${taxName} (${taxValue})` : ''; + const taxRateTitle = TransactionUtils.getTaxName(policyTaxRates.taxes, transactionTaxCode); // Flags for allowing or disallowing editing a money request const isSettled = ReportUtils.isSettled(moneyRequestReport.reportID); diff --git a/src/pages/EditRequestPage.js b/src/pages/EditRequestPage.js index a3375efbbdd5..7508e0796845 100644 --- a/src/pages/EditRequestPage.js +++ b/src/pages/EditRequestPage.js @@ -104,9 +104,7 @@ function EditRequestPage({report, policy, policyTaxRates, route, policyCategorie const defaultCurrency = lodashGet(route, 'params.currency', '') || transactionCurrency; const fieldToEdit = lodashGet(route, ['params', 'field'], ''); - const taxName = `${policyTaxRates.taxes[transactionTaxCode].name}`; - const taxValue = `${policyTaxRates.taxes[transactionTaxCode].value}`; - const taxRateTitle = transactionTaxCode ? `${taxName} (${taxValue})` : ''; + const taxRateTitle = TransactionUtils.getTaxName(policyTaxRates.taxes, transactionTaxCode); // For now, it always defaults to the first tag of the policy const policyTag = PolicyUtils.getTag(policyTags); From f723d0f68bf58f750df537c856f73845d95f044a Mon Sep 17 00:00:00 2001 From: Etotaziba Olei Date: Wed, 10 Jan 2024 13:45:33 +0100 Subject: [PATCH 054/698] Update src/components/MoneyTemporaryForRefactorRequestConfirmationList.js Co-authored-by: Michael (Mykhailo) Kravchenko --- .../MoneyTemporaryForRefactorRequestConfirmationList.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/components/MoneyTemporaryForRefactorRequestConfirmationList.js b/src/components/MoneyTemporaryForRefactorRequestConfirmationList.js index 5bd42ff11cf7..85948dbaa530 100755 --- a/src/components/MoneyTemporaryForRefactorRequestConfirmationList.js +++ b/src/components/MoneyTemporaryForRefactorRequestConfirmationList.js @@ -360,7 +360,7 @@ function MoneyTemporaryForRefactorRequestConfirmationList({ IOU.setMoneyRequestAmount_temporaryForRefactor(transaction.transactionID, amount, currency); }, [shouldCalculateDistanceAmount, distance, rate, unit, transaction, currency]); - // calculate and set tax amount in transaction draft + // Calculate and set tax amount in transaction draft useEffect(() => { const taxAmount = getTaxAmount(transaction, policyTaxRates.defaultValue); const amountInSmallestCurrencyUnits = CurrencyUtils.convertToBackendAmount(Number.parseFloat(taxAmount)); From cc2831e8358a09c23db14511811df9141fcdde3c Mon Sep 17 00:00:00 2001 From: Etotaziba Olei Date: Wed, 10 Jan 2024 13:45:48 +0100 Subject: [PATCH 055/698] Update src/libs/TransactionUtils.ts Co-authored-by: Michael (Mykhailo) Kravchenko --- src/libs/TransactionUtils.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/libs/TransactionUtils.ts b/src/libs/TransactionUtils.ts index 8aa9f05f813b..87c23974ab8a 100644 --- a/src/libs/TransactionUtils.ts +++ b/src/libs/TransactionUtils.ts @@ -568,7 +568,7 @@ function getDefaultTaxName(policyTaxRates: PolicyTaxRates, transaction: Transact } /** - * Get's the tax name + * Gets the tax name */ function getTaxName(taxes: TaxRates, transactionTaxCode: string) { const taxName = `${taxes[transactionTaxCode].name}`; From 1270f49460c6e83d4e429c868723f583da8fe4ce Mon Sep 17 00:00:00 2001 From: Etotaziba Olei Date: Wed, 10 Jan 2024 13:45:56 +0100 Subject: [PATCH 056/698] Update src/libs/TransactionUtils.ts Co-authored-by: Michael (Mykhailo) Kravchenko --- src/libs/TransactionUtils.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/libs/TransactionUtils.ts b/src/libs/TransactionUtils.ts index 87c23974ab8a..64e3ab79ab2b 100644 --- a/src/libs/TransactionUtils.ts +++ b/src/libs/TransactionUtils.ts @@ -558,7 +558,7 @@ function getEnabledTaxRateCount(options: TaxRates) { } /** - * Get's the default tax name + * Gets the default tax name */ function getDefaultTaxName(policyTaxRates: PolicyTaxRates, transaction: Transaction) { const defaultTaxKey = policyTaxRates.defaultExternalID; From 37d651384db96233599b2410a582a35cca5173d0 Mon Sep 17 00:00:00 2001 From: Etotaziba Olei Date: Wed, 10 Jan 2024 13:46:42 +0100 Subject: [PATCH 057/698] Update src/types/onyx/Policy.ts Co-authored-by: Michael (Mykhailo) Kravchenko --- src/types/onyx/Policy.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/types/onyx/Policy.ts b/src/types/onyx/Policy.ts index 5d315508f35a..3a7aacd5808a 100644 --- a/src/types/onyx/Policy.ts +++ b/src/types/onyx/Policy.ts @@ -62,7 +62,7 @@ type Policy = { /** The custom units data for this policy */ customUnits?: Record; - /** Is Tax tracking Enabled */ + /** Is tax tracking enabled */ isTaxTrackingEnabled?: boolean; /** Whether policy expense chats can be created and used on this policy. Enabled manually by CQ/JS snippet. Always true for free policies. */ From 584df427d6b35fc5c2b1e70e03ef88a9429320b2 Mon Sep 17 00:00:00 2001 From: Etotaziba Olei Date: Wed, 10 Jan 2024 13:47:06 +0100 Subject: [PATCH 058/698] Update src/pages/EditRequestPage.js Co-authored-by: Michael (Mykhailo) Kravchenko --- src/pages/EditRequestPage.js | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/pages/EditRequestPage.js b/src/pages/EditRequestPage.js index 7508e0796845..46fb719d26b5 100644 --- a/src/pages/EditRequestPage.js +++ b/src/pages/EditRequestPage.js @@ -62,14 +62,13 @@ const propTypes = { /** Transaction that stores the request data */ transaction: transactionPropTypes, - + /* Onyx Props */ /** The policy of the report */ policy: PropTypes.shape({ /** Is Tax tracking Enabled */ isTaxTrackingEnabled: PropTypes.bool, }), - /* Onyx Props */ /** Collection of tax rates attached to a policy */ policyTaxRates: taxPropTypes, }; From 1e8ffbc1da439bc23602f9bd67985dbbc0c51ed2 Mon Sep 17 00:00:00 2001 From: Etotaziba Olei Date: Tue, 16 Jan 2024 10:59:42 +0100 Subject: [PATCH 059/698] fix prettier --- src/libs/actions/IOU.js | 44 ++++++++++++++++++++--------------------- 1 file changed, 22 insertions(+), 22 deletions(-) diff --git a/src/libs/actions/IOU.js b/src/libs/actions/IOU.js index 47d959db9f16..816763037c3d 100644 --- a/src/libs/actions/IOU.js +++ b/src/libs/actions/IOU.js @@ -1184,33 +1184,33 @@ function updateMoneyRequestTag(transactionID, transactionThreadReportID, tag) { } /** -* Updates the created tax amount of a money request -* -* @param {String} transactionID -* @param {String} optimisticReportActionID -* @param {Number} val -*/ + * Updates the created tax amount of a money request + * + * @param {String} transactionID + * @param {String} optimisticReportActionID + * @param {Number} val + */ function updateMoneyRequestTaxAmount(transactionID, optimisticReportActionID, val) { - const transactionChanges = { - taxAmount: val, - }; - const {params, onyxData} = getUpdateMoneyRequestParams(transactionID, optimisticReportActionID, transactionChanges, true); - API.write('UpdateMoneyRequestTaxAmount', params, onyxData); + const transactionChanges = { + taxAmount: val, + }; + const {params, onyxData} = getUpdateMoneyRequestParams(transactionID, optimisticReportActionID, transactionChanges, true); + API.write('UpdateMoneyRequestTaxAmount', params, onyxData); } /** -* Updates the created tax rate of a money request -* -* @param {String} transactionID -* @param {String} optimisticReportActionID -* @param {String} val -*/ + * Updates the created tax rate of a money request + * + * @param {String} transactionID + * @param {String} optimisticReportActionID + * @param {String} val + */ function updateMoneyRequestTaxRate(transactionID, optimisticReportActionID, val) { - const transactionChanges = { - taxCode: val, - }; - const {params, onyxData} = getUpdateMoneyRequestParams(transactionID, optimisticReportActionID, transactionChanges, true); - API.write('UpdateMoneyRequestTaxRate', params, onyxData); + const transactionChanges = { + taxCode: val, + }; + const {params, onyxData} = getUpdateMoneyRequestParams(transactionID, optimisticReportActionID, transactionChanges, true); + API.write('UpdateMoneyRequestTaxRate', params, onyxData); } /** From 404732f89f3c9c3032db907ef6b4acb47b5c9059 Mon Sep 17 00:00:00 2001 From: Aldo Canepa Date: Mon, 22 Jan 2024 13:34:48 -0300 Subject: [PATCH 060/698] Kill ReconnectToReport --- src/libs/actions/Report.ts | 59 ---------------------- src/pages/home/report/ReportActionsView.js | 29 +---------- 2 files changed, 2 insertions(+), 86 deletions(-) diff --git a/src/libs/actions/Report.ts b/src/libs/actions/Report.ts index 2ac85dfafa27..72b977d01e7d 100644 --- a/src/libs/actions/Report.ts +++ b/src/libs/actions/Report.ts @@ -767,58 +767,6 @@ function navigateToAndOpenChildReport(childReportID = '0', parentReportAction: P } } -/** Get the latest report history without marking the report as read. */ -function reconnect(reportID: string) { - const optimisticData: OnyxUpdate[] = [ - { - onyxMethod: Onyx.METHOD.MERGE, - key: `${ONYXKEYS.COLLECTION.REPORT}${reportID}`, - value: { - reportName: allReports?.[reportID]?.reportName ?? CONST.REPORT.DEFAULT_REPORT_NAME, - }, - }, - { - onyxMethod: Onyx.METHOD.MERGE, - key: `${ONYXKEYS.COLLECTION.REPORT_METADATA}${reportID}`, - value: { - isLoadingInitialReportActions: true, - isLoadingNewerReportActions: false, - isLoadingOlderReportActions: false, - }, - }, - ]; - - const successData: OnyxUpdate[] = [ - { - onyxMethod: Onyx.METHOD.MERGE, - key: `${ONYXKEYS.COLLECTION.REPORT_METADATA}${reportID}`, - value: { - isLoadingInitialReportActions: false, - }, - }, - ]; - - const failureData: OnyxUpdate[] = [ - { - onyxMethod: Onyx.METHOD.MERGE, - key: `${ONYXKEYS.COLLECTION.REPORT_METADATA}${reportID}`, - value: { - isLoadingInitialReportActions: false, - }, - }, - ]; - - type ReconnectToReportParameters = { - reportID: string; - }; - - const parameters: ReconnectToReportParameters = { - reportID, - }; - - API.write('ReconnectToReport', parameters, {optimisticData, successData, failureData}); -} - /** * Gets the older actions that have not been read yet. * Normally happens when you scroll up on a chat, and the actions have not been read yet. @@ -1095,12 +1043,6 @@ function handleReportChanged(report: OnyxEntry) { conciergeChatReportID = report.reportID; } } - - // A report can be missing a name if a comment is received via pusher event and the report does not yet exist in Onyx (eg. a new DM created with the logged in person) - // In this case, we call reconnect so that we can fetch the report data without marking it as read - if (report.reportID && report.reportName === undefined) { - reconnect(report.reportID); - } } Onyx.connect({ @@ -2654,7 +2596,6 @@ export { searchInServer, addComment, addAttachment, - reconnect, updateWelcomeMessage, updateWriteCapabilityAndNavigate, updateNotificationPreference, diff --git a/src/pages/home/report/ReportActionsView.js b/src/pages/home/report/ReportActionsView.js index 2758437a3962..d2ec0f124a62 100755 --- a/src/pages/home/report/ReportActionsView.js +++ b/src/pages/home/report/ReportActionsView.js @@ -88,10 +88,7 @@ function ReportActionsView(props) { const isFirstRender = useRef(true); const hasCachedActions = useInitialValue(() => _.size(props.reportActions) > 0); const mostRecentIOUReportActionID = useInitialValue(() => ReportActionsUtils.getMostRecentIOURequestActionID(props.reportActions)); - - const prevNetworkRef = useRef(props.network); const prevAuthTokenType = usePrevious(props.session.authTokenType); - const prevIsSmallScreenWidthRef = useRef(props.isSmallScreenWidth); const isFocused = useIsFocused(); @@ -118,36 +115,14 @@ function ReportActionsView(props) { // eslint-disable-next-line react-hooks/exhaustive-deps }, []); - useEffect(() => { - const prevNetwork = prevNetworkRef.current; - // When returning from offline to online state we want to trigger a request to OpenReport which - // will fetch the reportActions data and mark the report as read. If the report is not fully visible - // then we call ReconnectToReport which only loads the reportActions data without marking the report as read. - const wasNetworkChangeDetected = lodashGet(prevNetwork, 'isOffline') && !lodashGet(props.network, 'isOffline'); - if (wasNetworkChangeDetected) { - if (isReportFullyVisible) { - openReportIfNecessary(); - } else { - Report.reconnect(reportID); - } - } - // update ref with current network state - prevNetworkRef.current = props.network; - // eslint-disable-next-line react-hooks/exhaustive-deps - }, [props.network, props.report, isReportFullyVisible]); useEffect(() => { const wasLoginChangedDetected = prevAuthTokenType === 'anonymousAccount' && !props.session.authTokenType; if (wasLoginChangedDetected && didUserLogInDuringSession() && isUserCreatedPolicyRoom(props.report)) { - if (isReportFullyVisible) { - openReportIfNecessary(); - } else { - Report.reconnect(reportID); - } + openReportIfNecessary(); } // eslint-disable-next-line react-hooks/exhaustive-deps - }, [props.session, props.report, isReportFullyVisible]); - + }, [props.session, props.report]); useEffect(() => { const prevIsSmallScreenWidth = prevIsSmallScreenWidthRef.current; // If the view is expanded from mobile to desktop layout From 0b4b6669a894f02f91af23fcac12e66e309e9494 Mon Sep 17 00:00:00 2001 From: Aldo Canepa Date: Mon, 22 Jan 2024 16:51:10 -0300 Subject: [PATCH 061/698] Lint --- src/pages/home/report/ReportActionsView.js | 1 - 1 file changed, 1 deletion(-) diff --git a/src/pages/home/report/ReportActionsView.js b/src/pages/home/report/ReportActionsView.js index d2ec0f124a62..adb771ed4f81 100755 --- a/src/pages/home/report/ReportActionsView.js +++ b/src/pages/home/report/ReportActionsView.js @@ -115,7 +115,6 @@ function ReportActionsView(props) { // eslint-disable-next-line react-hooks/exhaustive-deps }, []); - useEffect(() => { const wasLoginChangedDetected = prevAuthTokenType === 'anonymousAccount' && !props.session.authTokenType; if (wasLoginChangedDetected && didUserLogInDuringSession() && isUserCreatedPolicyRoom(props.report)) { From fb08033cd73698250232de21554945f06a8f569e Mon Sep 17 00:00:00 2001 From: Etotaziba Olei Date: Wed, 31 Jan 2024 06:18:28 +0100 Subject: [PATCH 062/698] remove duplicate identifier --- src/types/onyx/Policy.ts | 3 --- 1 file changed, 3 deletions(-) diff --git a/src/types/onyx/Policy.ts b/src/types/onyx/Policy.ts index 23d7494f08cf..eca7e9d1ee06 100644 --- a/src/types/onyx/Policy.ts +++ b/src/types/onyx/Policy.ts @@ -76,9 +76,6 @@ type Policy = { /** The custom units data for this policy */ customUnits?: Record; - /** Is tax tracking enabled */ - isTaxTrackingEnabled?: boolean; - /** Whether chat rooms can be created and used on this policy. Enabled manually by CQ/JS snippet. Always true for free policies. */ areChatRoomsEnabled: boolean; From 70c02fd72cdb2cb34520bd5787c8bd40eef7796d Mon Sep 17 00:00:00 2001 From: Etotaziba Olei Date: Wed, 31 Jan 2024 06:37:34 +0100 Subject: [PATCH 063/698] fix lint and tsc --- src/libs/OptionsListUtils.ts | 10 ++-------- src/libs/TransactionUtils.ts | 2 +- 2 files changed, 3 insertions(+), 9 deletions(-) diff --git a/src/libs/OptionsListUtils.ts b/src/libs/OptionsListUtils.ts index d550ae4305b0..51d1bc9699ad 100644 --- a/src/libs/OptionsListUtils.ts +++ b/src/libs/OptionsListUtils.ts @@ -4,7 +4,6 @@ import Str from 'expensify-common/lib/str'; import lodashGet from 'lodash/get'; import lodashOrderBy from 'lodash/orderBy'; import lodashSet from 'lodash/set'; -import lodashSome from 'lodash/some'; import lodashSortBy from 'lodash/sortBy'; import Onyx from 'react-native-onyx'; import type {OnyxCollection, OnyxEntry} from 'react-native-onyx'; @@ -1148,13 +1147,9 @@ function getTagListSections(tags: Tag[], recentlyUsedTags: string[], selectedOpt /** * Verifies that there is at least one enabled option * - * @param {Object[]} options - an initial strings array - * @property {boolean} [isDisabled] - Indicates if the tax rate is disabled. - * @returns {Boolean} + * @param options - an initial strings array + * @returns boolean */ -function hasEnabledOptionsForTaxRate(options: TaxRates) { - return lodashSome(options, (option) => !option.isDisabled); -} /** * Transforms tax rates to a new object format - to add codes and new name with concatenated name and value. @@ -2001,7 +1996,6 @@ export { getLastMessageTextForReport, getEnabledCategoriesCount, hasEnabledOptions, - hasEnabledOptionsForTaxRate, sortCategories, getCategoryOptionTree, formatMemberForList, diff --git a/src/libs/TransactionUtils.ts b/src/libs/TransactionUtils.ts index 711ff3fbbcd2..13a77183d1c5 100644 --- a/src/libs/TransactionUtils.ts +++ b/src/libs/TransactionUtils.ts @@ -5,7 +5,7 @@ import type {ValueOf} from 'type-fest'; import CONST from '@src/CONST'; import ONYXKEYS from '@src/ONYXKEYS'; import type {RecentWaypoint, Report, ReportAction, Transaction, TransactionViolation} from '@src/types/onyx'; -import type {TaxRate, TaxRates, PolicyTaxRates} from '@src/types/onyx/PolicyTaxRates'; +import type {PolicyTaxRates, TaxRate, TaxRates} from '@src/types/onyx/PolicyTaxRates'; import type {Comment, Receipt, Waypoint, WaypointCollection} from '@src/types/onyx/Transaction'; import type {EmptyObject} from '@src/types/utils/EmptyObject'; import {isCorporateCard, isExpensifyCard} from './CardUtils'; From 8bb0b3406cdb3a294766e2c875935d757c48dc86 Mon Sep 17 00:00:00 2001 From: Etotaziba Olei Date: Wed, 31 Jan 2024 15:27:39 +0100 Subject: [PATCH 064/698] migrate EditRequestTaxAmountPage to tsc --- ...ntPage.js => EditRequestTaxAmountPage.tsx} | 24 +++++++++---------- 1 file changed, 12 insertions(+), 12 deletions(-) rename src/pages/{EditRequestTaxAmountPage.js => EditRequestTaxAmountPage.tsx} (79%) diff --git a/src/pages/EditRequestTaxAmountPage.js b/src/pages/EditRequestTaxAmountPage.tsx similarity index 79% rename from src/pages/EditRequestTaxAmountPage.js rename to src/pages/EditRequestTaxAmountPage.tsx index 6a413bf12655..7c99465fdca0 100644 --- a/src/pages/EditRequestTaxAmountPage.js +++ b/src/pages/EditRequestTaxAmountPage.tsx @@ -1,6 +1,6 @@ import {useFocusEffect} from '@react-navigation/native'; -import PropTypes from 'prop-types'; import React, {useCallback, useRef} from 'react'; +import {TextInput} from 'react-native'; import HeaderWithBackButton from '@components/HeaderWithBackButton'; import ScreenWrapper from '@components/ScreenWrapper'; import useLocalize from '@hooks/useLocalize'; @@ -8,28 +8,28 @@ import * as DeviceCapabilities from '@libs/DeviceCapabilities'; import CONST from '@src/CONST'; import MoneyRequestAmountForm from './iou/steps/MoneyRequestAmountForm'; -const propTypes = { +type EditRequestTaxAmountPageProps = { /** Transaction default amount value */ - defaultAmount: PropTypes.number.isRequired, + defaultAmount: number; /** Transaction default tax amount value */ - defaultTaxAmount: PropTypes.number.isRequired, + defaultTaxAmount: number; /** Transaction default currency value */ - defaultCurrency: PropTypes.string.isRequired, + defaultCurrency: string; /** Callback to fire when the Save button is pressed */ - onSubmit: PropTypes.func.isRequired, + onSubmit: () => void; /** Callback to fire when we press on the currency */ - onNavigateToCurrency: PropTypes.func.isRequired, + onNavigateToCurrency: () => void; }; -function EditRequestTaxAmountPage({defaultAmount, defaultTaxAmount, defaultCurrency, onNavigateToCurrency, onSubmit}) { +function EditRequestTaxAmountPage({defaultAmount, defaultTaxAmount, defaultCurrency, onNavigateToCurrency, onSubmit}: EditRequestTaxAmountPageProps) { const {translate} = useLocalize(); - const textInput = useRef(null); + const textInput = useRef(null); - const focusTimeoutRef = useRef(null); + const focusTimeoutRef = useRef(null); useFocusEffect( useCallback(() => { @@ -52,10 +52,11 @@ function EditRequestTaxAmountPage({defaultAmount, defaultTaxAmount, defaultCurre > (textInput.current = e)} + ref={textInput} onCurrencyButtonPress={onNavigateToCurrency} onSubmitButtonPress={onSubmit} isEditing @@ -64,7 +65,6 @@ function EditRequestTaxAmountPage({defaultAmount, defaultTaxAmount, defaultCurre ); } -EditRequestTaxAmountPage.propTypes = propTypes; EditRequestTaxAmountPage.displayName = 'EditRequestTaxAmountPage'; export default EditRequestTaxAmountPage; From 1f1df34f216dfce421e436f4e1282a5771982bab Mon Sep 17 00:00:00 2001 From: Etotaziba Olei Date: Wed, 31 Jan 2024 15:28:00 +0100 Subject: [PATCH 065/698] migrate EditRequestTaxRatePage to tsc --- ...uestTaxRatePage.js => EditRequestTaxRatePage.tsx} | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) rename src/pages/{EditRequestTaxRatePage.js => EditRequestTaxRatePage.tsx} (86%) diff --git a/src/pages/EditRequestTaxRatePage.js b/src/pages/EditRequestTaxRatePage.tsx similarity index 86% rename from src/pages/EditRequestTaxRatePage.js rename to src/pages/EditRequestTaxRatePage.tsx index 2a22ab087435..4991349d4225 100644 --- a/src/pages/EditRequestTaxRatePage.js +++ b/src/pages/EditRequestTaxRatePage.tsx @@ -5,18 +5,18 @@ import ScreenWrapper from '@components/ScreenWrapper'; import TaxPicker from '@components/TaxPicker'; import useLocalize from '@hooks/useLocalize'; -const propTypes = { +type EditRequestTaxRatePageProps = { /** Transaction default tax Rate value */ - defaultTaxRate: PropTypes.string.isRequired, + defaultTaxRate: string, /** The policyID we are getting categories for */ - policyID: PropTypes.string.isRequired, + policyID: string, /** Callback to fire when the Save button is pressed */ - onSubmit: PropTypes.func.isRequired, + onSubmit: () => void, }; -function EditRequestTaxRatePage({defaultTaxRate, policyID, onSubmit}) { +function EditRequestTaxRatePage({defaultTaxRate, policyID, onSubmit}: EditRequestTaxRatePageProps) { const {translate} = useLocalize(); return ( @@ -29,6 +29,7 @@ function EditRequestTaxRatePage({defaultTaxRate, policyID, onSubmit}) { <> Date: Wed, 31 Jan 2024 15:34:36 +0100 Subject: [PATCH 066/698] fix tsc errors --- src/pages/EditRequestTaxAmountPage.tsx | 4 ++-- src/pages/EditRequestTaxRatePage.tsx | 9 ++++----- 2 files changed, 6 insertions(+), 7 deletions(-) diff --git a/src/pages/EditRequestTaxAmountPage.tsx b/src/pages/EditRequestTaxAmountPage.tsx index 7c99465fdca0..437e84df652c 100644 --- a/src/pages/EditRequestTaxAmountPage.tsx +++ b/src/pages/EditRequestTaxAmountPage.tsx @@ -1,6 +1,6 @@ import {useFocusEffect} from '@react-navigation/native'; import React, {useCallback, useRef} from 'react'; -import {TextInput} from 'react-native'; +import type {TextInput} from 'react-native'; import HeaderWithBackButton from '@components/HeaderWithBackButton'; import ScreenWrapper from '@components/ScreenWrapper'; import useLocalize from '@hooks/useLocalize'; @@ -52,7 +52,7 @@ function EditRequestTaxAmountPage({defaultAmount, defaultTaxAmount, defaultCurre > void, + onSubmit: () => void; }; function EditRequestTaxRatePage({defaultTaxRate, policyID, onSubmit}: EditRequestTaxRatePageProps) { @@ -29,7 +28,7 @@ function EditRequestTaxRatePage({defaultTaxRate, policyID, onSubmit}: EditReques <> Date: Wed, 31 Jan 2024 15:35:25 +0100 Subject: [PATCH 067/698] fix lint --- src/pages/EditRequestTaxRatePage.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/pages/EditRequestTaxRatePage.tsx b/src/pages/EditRequestTaxRatePage.tsx index 778f25ae0d98..1c1dc8219ae2 100644 --- a/src/pages/EditRequestTaxRatePage.tsx +++ b/src/pages/EditRequestTaxRatePage.tsx @@ -28,7 +28,7 @@ function EditRequestTaxRatePage({defaultTaxRate, policyID, onSubmit}: EditReques <> Date: Wed, 31 Jan 2024 12:58:51 -0800 Subject: [PATCH 068/698] Delete unused params for deleted command ReconnectToReport --- src/libs/API/parameters/ReconnectToReportParams.ts | 5 ----- 1 file changed, 5 deletions(-) delete mode 100644 src/libs/API/parameters/ReconnectToReportParams.ts diff --git a/src/libs/API/parameters/ReconnectToReportParams.ts b/src/libs/API/parameters/ReconnectToReportParams.ts deleted file mode 100644 index e7701cd36ca9..000000000000 --- a/src/libs/API/parameters/ReconnectToReportParams.ts +++ /dev/null @@ -1,5 +0,0 @@ -type ReconnectToReportParams = { - reportID: string; -}; - -export default ReconnectToReportParams; From 10360a32be5e48825a62ce4fd058f494a5020cc1 Mon Sep 17 00:00:00 2001 From: Aldo Canepa Date: Wed, 31 Jan 2024 15:21:02 -0800 Subject: [PATCH 069/698] Remove ReconnectToReportParams --- src/libs/API/parameters/index.ts | 1 - src/libs/API/types.ts | 1 - 2 files changed, 2 deletions(-) diff --git a/src/libs/API/parameters/index.ts b/src/libs/API/parameters/index.ts index 039398c0fbf6..0fd627ec7f9f 100644 --- a/src/libs/API/parameters/index.ts +++ b/src/libs/API/parameters/index.ts @@ -76,7 +76,6 @@ export type {default as VerifyIdentityForBankAccountParams} from './VerifyIdenti export type {default as AnswerQuestionsForWalletParams} from './AnswerQuestionsForWalletParams'; export type {default as AddCommentOrAttachementParams} from './AddCommentOrAttachementParams'; export type {default as OptInOutToPushNotificationsParams} from './OptInOutToPushNotificationsParams'; -export type {default as ReconnectToReportParams} from './ReconnectToReportParams'; export type {default as ReadNewestActionParams} from './ReadNewestActionParams'; export type {default as MarkAsUnreadParams} from './MarkAsUnreadParams'; export type {default as TogglePinnedChatParams} from './TogglePinnedChatParams'; diff --git a/src/libs/API/types.ts b/src/libs/API/types.ts index f58ebc30b4a2..f17645a3e3ac 100644 --- a/src/libs/API/types.ts +++ b/src/libs/API/types.ts @@ -185,7 +185,6 @@ type WriteCommandParameters = { [WRITE_COMMANDS.ADD_PERSONAL_BANK_ACCOUNT]: Parameters.AddPersonalBankAccountParams; [WRITE_COMMANDS.OPT_IN_TO_PUSH_NOTIFICATIONS]: Parameters.OptInOutToPushNotificationsParams; [WRITE_COMMANDS.OPT_OUT_OF_PUSH_NOTIFICATIONS]: Parameters.OptInOutToPushNotificationsParams; - [WRITE_COMMANDS.RECONNECT_TO_REPORT]: Parameters.ReconnectToReportParams; [WRITE_COMMANDS.READ_NEWEST_ACTION]: Parameters.ReadNewestActionParams; [WRITE_COMMANDS.MARK_AS_UNREAD]: Parameters.MarkAsUnreadParams; [WRITE_COMMANDS.TOGGLE_PINNED_CHAT]: Parameters.TogglePinnedChatParams; From a73e36e5bf801b65ade15afcbf284a9b7f1f5239 Mon Sep 17 00:00:00 2001 From: Etotaziba Olei Date: Sun, 4 Feb 2024 22:20:22 +0100 Subject: [PATCH 070/698] export tax rates types in onyx types --- src/types/onyx/index.ts | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/types/onyx/index.ts b/src/types/onyx/index.ts index d0ac2ce395fa..138bc0ba2270 100644 --- a/src/types/onyx/index.ts +++ b/src/types/onyx/index.ts @@ -44,6 +44,7 @@ import type {PolicyMembers} from './PolicyMember'; import type PolicyMember from './PolicyMember'; import type {PolicyReportField, PolicyReportFields} from './PolicyReportField'; import type {PolicyTag, PolicyTags} from './PolicyTag'; +import type {PolicyTaxRates, TaxRate, TaxRates} from './PolicyTaxRates'; import type PrivatePersonalDetails from './PrivatePersonalDetails'; import type RecentlyUsedCategories from './RecentlyUsedCategories'; import type RecentlyUsedReportFields from './RecentlyUsedReportFields'; @@ -121,6 +122,9 @@ export type { PolicyMembers, PolicyTag, PolicyTags, + TaxRate, + TaxRates, + PolicyTaxRates, PrivatePersonalDetails, RecentWaypoint, RecentlyUsedCategories, From 2169530a3d81ec7afec8daea7d12b9b1fb194f57 Mon Sep 17 00:00:00 2001 From: Abdelrahman Khattab Date: Mon, 5 Feb 2024 10:38:52 +0200 Subject: [PATCH 071/698] Corrected Currency Display: Enforce Two Decimal Places in Amounts --- src/libs/CurrencyUtils.ts | 16 +++++++++++++--- src/pages/iou/steps/MoneyRequestAmountForm.js | 6 +++--- tests/unit/CurrencyUtilsTest.js | 17 ++++++++++++++--- 3 files changed, 30 insertions(+), 9 deletions(-) diff --git a/src/libs/CurrencyUtils.ts b/src/libs/CurrencyUtils.ts index 42387e03c80b..32d2e62e8af1 100644 --- a/src/libs/CurrencyUtils.ts +++ b/src/libs/CurrencyUtils.ts @@ -88,10 +88,19 @@ function convertToBackendAmount(amountAsFloat: number): number { * * @note we do not support any currencies with more than two decimal places. */ -function convertToFrontendAmount(amountAsInt: number): number { +function convertToFrontendAmountAsInteger(amountAsInt: number): number { return Math.trunc(amountAsInt) / 100.0; } +/** + * Takes an amount in "cents" as an integer and converts it to a string amount used in the frontend. + * + * @note we do not support any currencies with more than two decimal places. + */ +function convertToFrontendAmountAsString(amountAsInt: number): string { + return convertToFrontendAmountAsInteger(amountAsInt).toFixed(2); +} + /** * Given an amount in the "cents", convert it to a string for display in the UI. * The backend always handle things in "cents" (subunit equal to 1/100) @@ -105,7 +114,7 @@ function convertToDisplayString(amountInCents = 0, currency: string = CONST.CURR return Localize.translateLocal('common.tbd'); } - const convertedAmount = convertToFrontendAmount(amountInCents); + const convertedAmount = convertToFrontendAmountAsInteger(amountInCents); return NumberFormatUtils.format(BaseLocaleListener.getPreferredLocale(), convertedAmount, { style: 'currency', currency, @@ -131,7 +140,8 @@ export { getCurrencySymbol, isCurrencySymbolLTR, convertToBackendAmount, - convertToFrontendAmount, + convertToFrontendAmountAsInteger, + convertToFrontendAmountAsString, convertToDisplayString, isValidCurrencyCode, }; diff --git a/src/pages/iou/steps/MoneyRequestAmountForm.js b/src/pages/iou/steps/MoneyRequestAmountForm.js index 8775562d4476..3d140a9e16b8 100644 --- a/src/pages/iou/steps/MoneyRequestAmountForm.js +++ b/src/pages/iou/steps/MoneyRequestAmountForm.js @@ -68,7 +68,7 @@ const getNewSelection = (oldSelection, prevLength, newLength) => { }; const isAmountInvalid = (amount) => !amount.length || parseFloat(amount) < 0.01; -const isTaxAmountInvalid = (currentAmount, taxAmount, isTaxAmountForm) => isTaxAmountForm && currentAmount > CurrencyUtils.convertToFrontendAmount(taxAmount); +const isTaxAmountInvalid = (currentAmount, taxAmount, isTaxAmountForm) => isTaxAmountForm && currentAmount > CurrencyUtils.convertToFrontendAmountAsInteger(taxAmount); const AMOUNT_VIEW_ID = 'amountView'; const NUM_PAD_CONTAINER_VIEW_ID = 'numPadContainerView'; @@ -83,7 +83,7 @@ function MoneyRequestAmountForm({amount, taxAmount, currency, isEditing, forward const isTaxAmountForm = Navigation.getActiveRoute().includes('taxAmount'); const decimals = CurrencyUtils.getCurrencyDecimals(currency); - const selectedAmountAsString = amount ? CurrencyUtils.convertToFrontendAmount(amount).toString() : ''; + const selectedAmountAsString = amount ? CurrencyUtils.convertToFrontendAmountAsString(amount) : ''; const [currentAmount, setCurrentAmount] = useState(selectedAmountAsString); const [formError, setFormError] = useState(''); @@ -119,7 +119,7 @@ function MoneyRequestAmountForm({amount, taxAmount, currency, isEditing, forward }; const initializeAmount = useCallback((newAmount) => { - const frontendAmount = newAmount ? CurrencyUtils.convertToFrontendAmount(newAmount).toString() : ''; + const frontendAmount = newAmount ? CurrencyUtils.convertToFrontendAmountAsString(newAmount) : ''; setCurrentAmount(frontendAmount); setSelection({ start: frontendAmount.length, diff --git a/tests/unit/CurrencyUtilsTest.js b/tests/unit/CurrencyUtilsTest.js index 89e1e2ffb3be..c2b0a294c467 100644 --- a/tests/unit/CurrencyUtilsTest.js +++ b/tests/unit/CurrencyUtilsTest.js @@ -106,18 +106,29 @@ describe('CurrencyUtils', () => { }); }); - describe('convertToFrontendAmount', () => { + describe('convertToFrontendAmountAsInteger', () => { test.each([ [2500, 25], [2550, 25.5], [25, 0.25], [2500, 25], [2500.5, 25], // The backend should never send a decimal .5 value - ])('Correctly converts %s to amount in units handled in frontend', (amount, expectedResult) => { - expect(CurrencyUtils.convertToFrontendAmount(amount)).toBe(expectedResult); + ])('Correctly converts %s to amount in units handled in frontend as an integer', (amount, expectedResult) => { + expect(CurrencyUtils.convertToFrontendAmountAsInteger(amount)).toBe(expectedResult); }); }); + describe('convertToFrontendAmountAsString', () => { + test.each([ + [2500, '25.00'], + [2550, '25.50'], + [25, '0.25'], + [2500, '25.00'], + [2500.5, '25.00'], + ])('Correctly converts %s to amount in units handled in frontend as a string', (amount, expectedResult) => { + expect(CurrencyUtils.convertToFrontendAmountAsString(amount)).toBe(expectedResult); + }); + }); describe('convertToDisplayString', () => { test.each([ [CONST.CURRENCY.USD, 25, '$0.25'], From 3e19f56714ba0927c1d0b2cbbb4de72587b926a5 Mon Sep 17 00:00:00 2001 From: Etotaziba Olei Date: Mon, 5 Feb 2024 09:52:14 +0100 Subject: [PATCH 072/698] add PolicyTaxRates to ONYX KEYS --- src/ONYXKEYS.ts | 1 + 1 file changed, 1 insertion(+) diff --git a/src/ONYXKEYS.ts b/src/ONYXKEYS.ts index 7328fb2543ad..bf1cdacea8d9 100755 --- a/src/ONYXKEYS.ts +++ b/src/ONYXKEYS.ts @@ -460,6 +460,7 @@ type OnyxValues = { [ONYXKEYS.COLLECTION.POLICY_DRAFTS]: OnyxTypes.Policy; [ONYXKEYS.COLLECTION.POLICY_CATEGORIES]: OnyxTypes.PolicyCategories; [ONYXKEYS.COLLECTION.POLICY_TAGS]: OnyxTypes.PolicyTags; + [ONYXKEYS.COLLECTION.POLICY_TAX_RATE]: OnyxTypes.PolicyTaxRates; [ONYXKEYS.COLLECTION.POLICY_MEMBERS]: OnyxTypes.PolicyMembers; [ONYXKEYS.COLLECTION.POLICY_MEMBERS_DRAFTS]: OnyxTypes.PolicyMember; [ONYXKEYS.COLLECTION.POLICY_RECENTLY_USED_CATEGORIES]: OnyxTypes.RecentlyUsedCategories; From ec6cf4f93decac331add63ba0f631f76c384d533 Mon Sep 17 00:00:00 2001 From: Etotaziba Olei Date: Mon, 5 Feb 2024 09:52:35 +0100 Subject: [PATCH 073/698] fix typescript --- .../ReportActionItem/MoneyRequestView.tsx | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/src/components/ReportActionItem/MoneyRequestView.tsx b/src/components/ReportActionItem/MoneyRequestView.tsx index e92821f8e94c..9c1db3d07a7a 100644 --- a/src/components/ReportActionItem/MoneyRequestView.tsx +++ b/src/components/ReportActionItem/MoneyRequestView.tsx @@ -56,7 +56,7 @@ type MoneyRequestViewOnyxPropsWithoutTransaction = { /** Collection of tags attached to a policy */ policyTags: OnyxEntry; - /** Collection of tax rates attached to a policy */ + /** Collection of tax rates attached to a policy */ policyTaxRates: OnyxEntry; /** The expense report or iou report (only will have a value if this is a transaction thread) */ @@ -124,7 +124,8 @@ function MoneyRequestView({ const formattedTaxAmount = transactionTaxAmount ? CurrencyUtils.convertToDisplayString(transactionTaxAmount, transactionCurrency) : ''; - const taxRateTitle = TransactionUtils.getTaxName(policyTaxRates.taxes, transactionTaxCode); + const policyTaxRatesDescription = (policyTaxRates && policyTaxRates.name) ?? ''; + const taxRateTitle = (transactionTaxCode && policyTaxRates && TransactionUtils.getTaxName(policyTaxRates.taxes, transactionTaxCode)) ?? ''; // Flags for allowing or disallowing editing a money request const isSettled = ReportUtils.isSettled(moneyRequestReport?.reportID); @@ -155,8 +156,8 @@ function MoneyRequestView({ const shouldShowTag = isPolicyExpenseChat && (transactionTag || OptionsListUtils.hasEnabledOptions(Object.values(policyTagsList))); const shouldShowBillable = isPolicyExpenseChat && (!!transactionBillable || !(policy?.disabledFields?.defaultBillable ?? true)); - // A flag for showing tax rate - const shouldShowTax = isTaxPolicyEnabled(isPolicyExpenseChat, policy) && transactionTaxCode && transactionTaxAmount; + // A flag for showing tax rate + const shouldShowTax = isTaxPolicyEnabled(isPolicyExpenseChat, policy) && transactionTaxCode && transactionTaxAmount; const {getViolationsForField} = useViolations(transactionViolations ?? []); const hasViolations = useCallback((field: ViolationField): boolean => !!canUseViolations && getViolationsForField(field).length > 0, [canUseViolations, getViolationsForField]); @@ -370,7 +371,7 @@ function MoneyRequestView({ Date: Mon, 5 Feb 2024 10:07:04 +0100 Subject: [PATCH 074/698] use optional chaining --- src/components/ReportActionItem/MoneyRequestView.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/components/ReportActionItem/MoneyRequestView.tsx b/src/components/ReportActionItem/MoneyRequestView.tsx index 9fdcd7b5125a..2163332b507e 100644 --- a/src/components/ReportActionItem/MoneyRequestView.tsx +++ b/src/components/ReportActionItem/MoneyRequestView.tsx @@ -124,7 +124,7 @@ function MoneyRequestView({ const formattedTaxAmount = transactionTaxAmount ? CurrencyUtils.convertToDisplayString(transactionTaxAmount, transactionCurrency) : ''; - const policyTaxRatesDescription = (policyTaxRates && policyTaxRates.name) ?? ''; + const policyTaxRatesDescription = policyTaxRates?.name; const taxRateTitle = (transactionTaxCode && policyTaxRates && TransactionUtils.getTaxName(policyTaxRates.taxes, transactionTaxCode)) ?? ''; // Flags for allowing or disallowing editing a money request From 72d282fba6972d757af95451b3f19f40f47a297b Mon Sep 17 00:00:00 2001 From: Abdelrahman Khattab Date: Tue, 6 Feb 2024 22:49:57 +0200 Subject: [PATCH 075/698] fix the case where there is no decimal value passed --- src/libs/CurrencyUtils.ts | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/libs/CurrencyUtils.ts b/src/libs/CurrencyUtils.ts index 32d2e62e8af1..9e8475b0efe0 100644 --- a/src/libs/CurrencyUtils.ts +++ b/src/libs/CurrencyUtils.ts @@ -98,7 +98,8 @@ function convertToFrontendAmountAsInteger(amountAsInt: number): number { * @note we do not support any currencies with more than two decimal places. */ function convertToFrontendAmountAsString(amountAsInt: number): string { - return convertToFrontendAmountAsInteger(amountAsInt).toFixed(2); + const shouldShowDecimal = amountAsInt % 100 === 0; + return amountAsInt ? convertToFrontendAmountAsInteger(amountAsInt).toFixed(shouldShowDecimal ? 0 : 2) : ''; } /** From 8e80ffbf002b2198fc43f5c9f244515cd6ba62ec Mon Sep 17 00:00:00 2001 From: Abdelrahman Khattab Date: Tue, 6 Feb 2024 22:50:45 +0200 Subject: [PATCH 076/698] cleaning --- src/pages/iou/steps/MoneyRequestAmountForm.js | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/src/pages/iou/steps/MoneyRequestAmountForm.js b/src/pages/iou/steps/MoneyRequestAmountForm.js index 3d140a9e16b8..aec204772bc5 100644 --- a/src/pages/iou/steps/MoneyRequestAmountForm.js +++ b/src/pages/iou/steps/MoneyRequestAmountForm.js @@ -83,8 +83,7 @@ function MoneyRequestAmountForm({amount, taxAmount, currency, isEditing, forward const isTaxAmountForm = Navigation.getActiveRoute().includes('taxAmount'); const decimals = CurrencyUtils.getCurrencyDecimals(currency); - const selectedAmountAsString = amount ? CurrencyUtils.convertToFrontendAmountAsString(amount) : ''; - + const selectedAmountAsString = CurrencyUtils.convertToFrontendAmountAsString(amount); const [currentAmount, setCurrentAmount] = useState(selectedAmountAsString); const [formError, setFormError] = useState(''); const [shouldUpdateSelection, setShouldUpdateSelection] = useState(true); @@ -119,7 +118,7 @@ function MoneyRequestAmountForm({amount, taxAmount, currency, isEditing, forward }; const initializeAmount = useCallback((newAmount) => { - const frontendAmount = newAmount ? CurrencyUtils.convertToFrontendAmountAsString(newAmount) : ''; + const frontendAmount = CurrencyUtils.convertToFrontendAmountAsString(newAmount); setCurrentAmount(frontendAmount); setSelection({ start: frontendAmount.length, From 8315492b481df524ab720d2751ba9dfe8e241d29 Mon Sep 17 00:00:00 2001 From: Abdelrahman Khattab Date: Tue, 6 Feb 2024 22:57:07 +0200 Subject: [PATCH 077/698] fixing tests --- tests/unit/CurrencyUtilsTest.js | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/tests/unit/CurrencyUtilsTest.js b/tests/unit/CurrencyUtilsTest.js index c2b0a294c467..2178f029240c 100644 --- a/tests/unit/CurrencyUtilsTest.js +++ b/tests/unit/CurrencyUtilsTest.js @@ -120,10 +120,9 @@ describe('CurrencyUtils', () => { describe('convertToFrontendAmountAsString', () => { test.each([ - [2500, '25.00'], + [2500, '25'], [2550, '25.50'], [25, '0.25'], - [2500, '25.00'], [2500.5, '25.00'], ])('Correctly converts %s to amount in units handled in frontend as a string', (amount, expectedResult) => { expect(CurrencyUtils.convertToFrontendAmountAsString(amount)).toBe(expectedResult); From b3dbe2607ec04fb9b8519fc3f1ed828e0857fa96 Mon Sep 17 00:00:00 2001 From: Etotaziba Olei Date: Wed, 7 Feb 2024 09:28:57 +0100 Subject: [PATCH 078/698] add tax amount API types --- src/libs/API/types.ts | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/libs/API/types.ts b/src/libs/API/types.ts index a4ab3db9a7cd..f6ec3b8732e3 100644 --- a/src/libs/API/types.ts +++ b/src/libs/API/types.ts @@ -121,6 +121,8 @@ const WRITE_COMMANDS = { UPDATE_MONEY_REQUEST_BILLABLE: 'UpdateMoneyRequestBillable', UPDATE_MONEY_REQUEST_MERCHANT: 'UpdateMoneyRequestMerchant', UPDATE_MONEY_REQUEST_TAG: 'UpdateMoneyRequestTag', + UPDATE_MONEY_REQUEST_TAX_AMOUNT: 'UpdateMoneyRequestTaxAmount', + UPDATE_MONEY_REQUEST_TAX_RATE: 'UpdateMoneyRequestTaxRate', UPDATE_MONEY_REQUEST_DISTANCE: 'UpdateMoneyRequestDistance', UPDATE_MONEY_REQUEST_CATEGORY: 'UpdateMoneyRequestCategory', UPDATE_MONEY_REQUEST_DESCRIPTION: 'UpdateMoneyRequestDescription', @@ -259,6 +261,8 @@ type WriteCommandParameters = { [WRITE_COMMANDS.UPDATE_MONEY_REQUEST_MERCHANT]: Parameters.UpdateMoneyRequestParams; [WRITE_COMMANDS.UPDATE_MONEY_REQUEST_BILLABLE]: Parameters.UpdateMoneyRequestParams; [WRITE_COMMANDS.UPDATE_MONEY_REQUEST_TAG]: Parameters.UpdateMoneyRequestParams; + [WRITE_COMMANDS.UPDATE_MONEY_REQUEST_TAX_AMOUNT]: Parameters.UpdateMoneyRequestParams; + [WRITE_COMMANDS.UPDATE_MONEY_REQUEST_TAX_RATE]: Parameters.UpdateMoneyRequestParams; [WRITE_COMMANDS.UPDATE_MONEY_REQUEST_DISTANCE]: Parameters.UpdateMoneyRequestParams; [WRITE_COMMANDS.UPDATE_MONEY_REQUEST_CATEGORY]: Parameters.UpdateMoneyRequestParams; [WRITE_COMMANDS.UPDATE_MONEY_REQUEST_DESCRIPTION]: Parameters.UpdateMoneyRequestParams; From 0bdef874da54f3a6e8a0630f640e95d08d00928b Mon Sep 17 00:00:00 2001 From: Etotaziba Olei Date: Wed, 7 Feb 2024 09:29:48 +0100 Subject: [PATCH 079/698] update tax request types --- src/libs/actions/IOU.ts | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/libs/actions/IOU.ts b/src/libs/actions/IOU.ts index bc1a8b9dd4cf..319889f54496 100644 --- a/src/libs/actions/IOU.ts +++ b/src/libs/actions/IOU.ts @@ -1217,18 +1217,18 @@ function updateMoneyRequestTag(transactionID: string, transactionThreadReportID: } /** Updates the created tax amount of a money request */ -function updateMoneyRequestTaxAmount(transactionID: string, optimisticReportActionID: string, val: number) { +function updateMoneyRequestTaxAmount(transactionID: string, optimisticReportActionID: string, taxAmount: number) { const transactionChanges = { - taxAmount: val, + taxAmount, }; const {params, onyxData} = getUpdateMoneyRequestParams(transactionID, optimisticReportActionID, transactionChanges, true); API.write('UpdateMoneyRequestTaxAmount', params, onyxData); } /** Updates the created tax rate of a money request */ -function updateMoneyRequestTaxRate(transactionID: string, optimisticReportActionID: string, val: string) { +function updateMoneyRequestTaxRate(transactionID: string, optimisticReportActionID: string, taxCode: string) { const transactionChanges = { - taxCode: val, + taxCode, }; const {params, onyxData} = getUpdateMoneyRequestParams(transactionID, optimisticReportActionID, transactionChanges, true); API.write('UpdateMoneyRequestTaxRate', params, onyxData); From 3293311d92215d039c17f6654d8718ee94e5d46f Mon Sep 17 00:00:00 2001 From: Etotaziba Olei Date: Wed, 7 Feb 2024 11:37:57 +0100 Subject: [PATCH 080/698] add taxCode and taxAmount to getUpdatedTransaction --- src/libs/TransactionUtils.ts | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/src/libs/TransactionUtils.ts b/src/libs/TransactionUtils.ts index bce784819769..7964e8c25b78 100644 --- a/src/libs/TransactionUtils.ts +++ b/src/libs/TransactionUtils.ts @@ -204,6 +204,16 @@ function getUpdatedTransaction(transaction: Transaction, transactionChanges: Tra shouldStopSmartscan = true; } + if (Object.hasOwn(transactionChanges, 'taxAmount') && typeof transactionChanges.taxAmount === 'number') { + updatedTransaction.taxAmount = isFromExpenseReport ? -transactionChanges.taxAmount : transactionChanges.taxAmount; + shouldStopSmartscan = true; + } + + if (Object.hasOwn(transactionChanges, 'taxCode') && typeof transactionChanges.taxCode === 'string') { + updatedTransaction.taxCode = transactionChanges.taxCode; + shouldStopSmartscan = true; + } + if (Object.hasOwn(transactionChanges, 'billable') && typeof transactionChanges.billable === 'boolean') { updatedTransaction.billable = transactionChanges.billable; } @@ -237,6 +247,8 @@ function getUpdatedTransaction(transaction: Transaction, transactionChanges: Tra ...(Object.hasOwn(transactionChanges, 'billable') && {billable: CONST.RED_BRICK_ROAD_PENDING_ACTION.UPDATE}), ...(Object.hasOwn(transactionChanges, 'category') && {category: CONST.RED_BRICK_ROAD_PENDING_ACTION.UPDATE}), ...(Object.hasOwn(transactionChanges, 'tag') && {tag: CONST.RED_BRICK_ROAD_PENDING_ACTION.UPDATE}), + ...(Object.hasOwn(transactionChanges, 'taxAmount') && {taxAmount: CONST.RED_BRICK_ROAD_PENDING_ACTION.UPDATE}), + ...(Object.hasOwn(transactionChanges, 'taxCode') && {taxCode: CONST.RED_BRICK_ROAD_PENDING_ACTION.UPDATE}), }; return updatedTransaction; From 9abeb11ad5ee99e91a05a44862d006e2093777ab Mon Sep 17 00:00:00 2001 From: Etotaziba Olei Date: Wed, 7 Feb 2024 17:31:32 +0100 Subject: [PATCH 081/698] update Tax Amount Menu Item Description in ConfirmationList --- src/components/MoneyRequestConfirmationList.js | 2 +- .../MoneyTemporaryForRefactorRequestConfirmationList.js | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/components/MoneyRequestConfirmationList.js b/src/components/MoneyRequestConfirmationList.js index 596811086ee4..824652d481cf 100755 --- a/src/components/MoneyRequestConfirmationList.js +++ b/src/components/MoneyRequestConfirmationList.js @@ -810,7 +810,7 @@ function MoneyRequestConfirmationList(props) { diff --git a/src/components/MoneyTemporaryForRefactorRequestConfirmationList.js b/src/components/MoneyTemporaryForRefactorRequestConfirmationList.js index cd1874197063..902139610489 100755 --- a/src/components/MoneyTemporaryForRefactorRequestConfirmationList.js +++ b/src/components/MoneyTemporaryForRefactorRequestConfirmationList.js @@ -865,7 +865,7 @@ function MoneyTemporaryForRefactorRequestConfirmationList({ From 59768825ac3e1a1f07253269c180b5417ed9ef1b Mon Sep 17 00:00:00 2001 From: Etotaziba Olei Date: Wed, 7 Feb 2024 17:32:02 +0100 Subject: [PATCH 082/698] update Tax Amount Menu Item Description in MoneyRequestView --- src/components/ReportActionItem/MoneyRequestView.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/components/ReportActionItem/MoneyRequestView.tsx b/src/components/ReportActionItem/MoneyRequestView.tsx index a545bd99c378..7e04b3224119 100644 --- a/src/components/ReportActionItem/MoneyRequestView.tsx +++ b/src/components/ReportActionItem/MoneyRequestView.tsx @@ -390,7 +390,7 @@ function MoneyRequestView({ Date: Wed, 7 Feb 2024 17:34:15 +0100 Subject: [PATCH 083/698] add pending action for taxCode --- src/components/ReportActionItem/MoneyRequestView.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/components/ReportActionItem/MoneyRequestView.tsx b/src/components/ReportActionItem/MoneyRequestView.tsx index 7e04b3224119..927dff901158 100644 --- a/src/components/ReportActionItem/MoneyRequestView.tsx +++ b/src/components/ReportActionItem/MoneyRequestView.tsx @@ -374,7 +374,7 @@ function MoneyRequestView({ )} {shouldShowTax && ( - + Date: Wed, 7 Feb 2024 17:35:02 +0100 Subject: [PATCH 084/698] add pending action for taxAmount --- src/components/ReportActionItem/MoneyRequestView.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/components/ReportActionItem/MoneyRequestView.tsx b/src/components/ReportActionItem/MoneyRequestView.tsx index 927dff901158..e6a20977ae15 100644 --- a/src/components/ReportActionItem/MoneyRequestView.tsx +++ b/src/components/ReportActionItem/MoneyRequestView.tsx @@ -387,7 +387,7 @@ function MoneyRequestView({ )} {shouldShowTax && ( - + Date: Sun, 18 Feb 2024 23:35:27 +0200 Subject: [PATCH 085/698] keeping the user input when clicking next --- src/libs/CurrencyUtils.ts | 3 +-- src/pages/iou/steps/MoneyRequestAmountForm.js | 7 +------ 2 files changed, 2 insertions(+), 8 deletions(-) diff --git a/src/libs/CurrencyUtils.ts b/src/libs/CurrencyUtils.ts index 2e3089c355d0..d16192b808aa 100644 --- a/src/libs/CurrencyUtils.ts +++ b/src/libs/CurrencyUtils.ts @@ -97,8 +97,7 @@ function convertToFrontendAmountAsInteger(amountAsInt: number): number { * @note we do not support any currencies with more than two decimal places. */ function convertToFrontendAmountAsString(amountAsInt: number): string { - const shouldShowDecimal = amountAsInt % 100 === 0; - return amountAsInt ? convertToFrontendAmountAsInteger(amountAsInt).toFixed(shouldShowDecimal ? 0 : 2) : ''; + return amountAsInt ? convertToFrontendAmountAsInteger(amountAsInt).toFixed(2) : ''; } /** diff --git a/src/pages/iou/steps/MoneyRequestAmountForm.js b/src/pages/iou/steps/MoneyRequestAmountForm.js index 9d58fe04872f..95a3c89ade75 100644 --- a/src/pages/iou/steps/MoneyRequestAmountForm.js +++ b/src/pages/iou/steps/MoneyRequestAmountForm.js @@ -236,13 +236,8 @@ function MoneyRequestAmountForm({amount, taxAmount, currency, isEditing, forward return; } - // Update display amount string post-edit to ensure consistency with backend amount - // Reference: https://github.com/Expensify/App/issues/30505 - const backendAmount = CurrencyUtils.convertToBackendAmount(Number.parseFloat(currentAmount)); - initializeAmount(backendAmount); - onSubmitButtonPress({amount: currentAmount, currency}); - }, [onSubmitButtonPress, currentAmount, taxAmount, currency, isTaxAmountForm, formattedTaxAmount, initializeAmount]); + }, [onSubmitButtonPress, currentAmount, taxAmount, currency, isTaxAmountForm, formattedTaxAmount]); /** * Input handler to check for a forward-delete key (or keyboard shortcut) press. From 3fa6bb93d476be6d5256812b1f457a7404b50075 Mon Sep 17 00:00:00 2001 From: Abdelrahman Khattab Date: Sun, 18 Feb 2024 23:43:34 +0200 Subject: [PATCH 086/698] Fixing tests --- tests/unit/CurrencyUtilsTest.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/unit/CurrencyUtilsTest.js b/tests/unit/CurrencyUtilsTest.js index 2178f029240c..59e73488c11c 100644 --- a/tests/unit/CurrencyUtilsTest.js +++ b/tests/unit/CurrencyUtilsTest.js @@ -120,7 +120,7 @@ describe('CurrencyUtils', () => { describe('convertToFrontendAmountAsString', () => { test.each([ - [2500, '25'], + [2500, '25.00'], [2550, '25.50'], [25, '0.25'], [2500.5, '25.00'], From 68ef4f53cc8e9420bada67903b07ca9fab37cd14 Mon Sep 17 00:00:00 2001 From: Etotaziba Olei Date: Mon, 19 Feb 2024 09:26:07 +0100 Subject: [PATCH 087/698] fix bad merge for IOURequestStepAmount --- src/pages/iou/request/step/IOURequestStepAmount.js | 8 -------- 1 file changed, 8 deletions(-) diff --git a/src/pages/iou/request/step/IOURequestStepAmount.js b/src/pages/iou/request/step/IOURequestStepAmount.js index 7861cbc041e5..c360f837a0c3 100644 --- a/src/pages/iou/request/step/IOURequestStepAmount.js +++ b/src/pages/iou/request/step/IOURequestStepAmount.js @@ -1,5 +1,4 @@ import {useFocusEffect} from '@react-navigation/native'; -import lodashGet from 'lodash/get'; import PropTypes from 'prop-types'; import React, {useCallback, useEffect, useRef} from 'react'; import transactionPropTypes from '@components/transactionPropTypes'; @@ -29,10 +28,6 @@ const propTypes = { /** The transaction object being modified in Onyx */ transaction: transactionPropTypes, - /* Onyx Props */ - /** Collection of tax rates attached to a policy */ - policyTaxRates: taxPropTypes, - /** The policy of the report */ policy: PropTypes.shape({ /** @@ -69,9 +64,6 @@ function IOURequestStepAmount({ const originalCurrency = useRef(null); const iouRequestType = getRequestType(transaction); - const isPolicyExpenseChat = ReportUtils.isPolicyExpenseChat(ReportUtils.getRootParentReport(report)); - const isTaxTrackingEnabled = isPolicyExpenseChat && lodashGet(policy, 'tax.trackingEnabled', policy.isTaxTrackingEnabled); - useFocusEffect( useCallback(() => { focusTimeoutRef.current = setTimeout(() => textInput.current && textInput.current.focus(), CONST.ANIMATED_TRANSITION); From a105896eee3873b173f38583a5ab64495dd9bdc1 Mon Sep 17 00:00:00 2001 From: Etotaziba Olei Date: Mon, 19 Feb 2024 09:36:32 +0100 Subject: [PATCH 088/698] fix bad merge for EditRequestPage --- src/pages/EditRequestPage.js | 18 ++++++++++++++++-- 1 file changed, 16 insertions(+), 2 deletions(-) diff --git a/src/pages/EditRequestPage.js b/src/pages/EditRequestPage.js index ba07afae7388..77d4f8369403 100644 --- a/src/pages/EditRequestPage.js +++ b/src/pages/EditRequestPage.js @@ -89,10 +89,22 @@ const defaultProps = { policyTaxRates: {}, }; -function EditRequestPage({report, route, policy, policyCategories, policyTags, parentReportActions, transaction}) { +const getTaxAmount = (transactionAmount, transactionTaxCode, policyTaxRates) => { + const percentage = (transactionTaxCode ? policyTaxRates.taxes[transactionTaxCode].value : policyTaxRates.defaultValue) || ''; + return CurrencyUtils.convertToBackendAmount(Number.parseFloat(TransactionUtils.calculateTaxAmount(percentage, transactionAmount))); +}; + +function EditRequestPage({report, route, policy, policyTaxRates, policyCategories, policyTags, parentReportActions, transaction}) { const parentReportActionID = lodashGet(report, 'parentReportActionID', '0'); const parentReportAction = lodashGet(parentReportActions, parentReportActionID, {}); - const {amount: transactionAmount, currency: transactionCurrency, category: transactionCategory, tag: transactionTag} = ReportUtils.getTransactionDetails(transaction); + const { + amount: transactionAmount, + taxAmount: transactionTaxAmount, + taxCode: transactionTaxCode, + currency: transactionCurrency, + category: transactionCategory, + tag: transactionTag, + } = ReportUtils.getTransactionDetails(transaction); const defaultCurrency = lodashGet(route, 'params.currency', '') || transactionCurrency; const fieldToEdit = lodashGet(route, ['params', 'field'], ''); @@ -102,6 +114,8 @@ function EditRequestPage({report, route, policy, policyCategories, policyTags, p const policyTagListName = PolicyUtils.getTagListName(policyTags, tagIndex); const policyTagLists = useMemo(() => PolicyUtils.getTagLists(policyTags), [policyTags]); + const taxRateTitle = TransactionUtils.getTaxName(policyTaxRates.taxes, transactionTaxCode); + // A flag for verifying that the current report is a sub-report of a workspace chat const isPolicyExpenseChat = ReportUtils.isGroupPolicy(report); From 58af4ad224cde512a00715f21ae5732ba0aff4fd Mon Sep 17 00:00:00 2001 From: Etotaziba Olei Date: Mon, 19 Feb 2024 09:54:25 +0100 Subject: [PATCH 089/698] use trackingEnabled for chrcking if tax tracking is enabled --- src/libs/PolicyUtils.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/libs/PolicyUtils.ts b/src/libs/PolicyUtils.ts index 6b1c63785ea4..12b3d6952183 100644 --- a/src/libs/PolicyUtils.ts +++ b/src/libs/PolicyUtils.ts @@ -215,7 +215,7 @@ function isPaidGroupPolicy(policy: OnyxEntry | EmptyObject): boolean { } function isTaxPolicyEnabled(isPolicyExpenseChat: boolean, policy: OnyxEntry): boolean { - return (isPolicyExpenseChat && policy?.isTaxTrackingEnabled) ?? false; + return (isPolicyExpenseChat && (policy?.tax?.trackingEnabled || policy?.isTaxTrackingEnabled)) ?? false; } /** From 81fb82ce80bbb46da9508ce546b827918730ccb7 Mon Sep 17 00:00:00 2001 From: Etotaziba Olei Date: Mon, 19 Feb 2024 10:08:18 +0100 Subject: [PATCH 090/698] fix prettier --- src/types/onyx/index.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/types/onyx/index.ts b/src/types/onyx/index.ts index 28b26ed77c3e..59cabbe020ee 100644 --- a/src/types/onyx/index.ts +++ b/src/types/onyx/index.ts @@ -34,8 +34,8 @@ import type {PolicyCategories, PolicyCategory} from './PolicyCategory'; import type {PolicyMembers} from './PolicyMember'; import type PolicyMember from './PolicyMember'; import type {PolicyReportField, PolicyReportFields} from './PolicyReportField'; -import type {PolicyTaxRates, TaxRate, TaxRates} from './PolicyTaxRates'; import type {PolicyTag, PolicyTagList, PolicyTags} from './PolicyTag'; +import type {PolicyTaxRates, TaxRate, TaxRates} from './PolicyTaxRates'; import type PrivatePersonalDetails from './PrivatePersonalDetails'; import type RecentlyUsedCategories from './RecentlyUsedCategories'; import type RecentlyUsedReportFields from './RecentlyUsedReportFields'; From 88c091434482a37637c015ebdbae13994b8a5452 Mon Sep 17 00:00:00 2001 From: Etotaziba Olei Date: Mon, 19 Feb 2024 10:18:01 +0100 Subject: [PATCH 091/698] fix lint --- src/libs/PolicyUtils.ts | 2 +- src/pages/EditRequestPage.js | 10 ---------- .../iou/request/step/IOURequestStepAmount.js | 16 ---------------- 3 files changed, 1 insertion(+), 27 deletions(-) diff --git a/src/libs/PolicyUtils.ts b/src/libs/PolicyUtils.ts index 12b3d6952183..0a6cc9e7a35a 100644 --- a/src/libs/PolicyUtils.ts +++ b/src/libs/PolicyUtils.ts @@ -215,7 +215,7 @@ function isPaidGroupPolicy(policy: OnyxEntry | EmptyObject): boolean { } function isTaxPolicyEnabled(isPolicyExpenseChat: boolean, policy: OnyxEntry): boolean { - return (isPolicyExpenseChat && (policy?.tax?.trackingEnabled || policy?.isTaxTrackingEnabled)) ?? false; + return (isPolicyExpenseChat && (policy?.tax?.trackingEnabled ?? policy?.isTaxTrackingEnabled)) ?? false; } /** diff --git a/src/pages/EditRequestPage.js b/src/pages/EditRequestPage.js index 77d4f8369403..3653e37a6555 100644 --- a/src/pages/EditRequestPage.js +++ b/src/pages/EditRequestPage.js @@ -67,12 +67,6 @@ const propTypes = { /** Transaction that stores the request data */ transaction: transactionPropTypes, - /* Onyx Props */ - /** The policy of the report */ - policy: PropTypes.shape({ - /** Is Tax tracking Enabled */ - isTaxTrackingEnabled: PropTypes.bool, - }), /** Collection of tax rates attached to a policy */ policyTaxRates: taxPropTypes, @@ -85,7 +79,6 @@ const defaultProps = { policyTags: {}, parentReportActions: {}, transaction: {}, - policy: {}, policyTaxRates: {}, }; @@ -308,9 +301,6 @@ export default compose( policyCategories: { key: ({report}) => `${ONYXKEYS.COLLECTION.POLICY_CATEGORIES}${report ? report.policyID : '0'}`, }, - policy: { - key: ({report}) => `${ONYXKEYS.COLLECTION.POLICY}${report.policyID}`, - }, policyTags: { key: ({report}) => `${ONYXKEYS.COLLECTION.POLICY_TAGS}${report ? report.policyID : '0'}`, }, diff --git a/src/pages/iou/request/step/IOURequestStepAmount.js b/src/pages/iou/request/step/IOURequestStepAmount.js index c360f837a0c3..0bc51a517466 100644 --- a/src/pages/iou/request/step/IOURequestStepAmount.js +++ b/src/pages/iou/request/step/IOURequestStepAmount.js @@ -1,5 +1,4 @@ import {useFocusEffect} from '@react-navigation/native'; -import PropTypes from 'prop-types'; import React, {useCallback, useEffect, useRef} from 'react'; import transactionPropTypes from '@components/transactionPropTypes'; import useLocalize from '@hooks/useLocalize'; @@ -27,21 +26,6 @@ const propTypes = { /** The transaction object being modified in Onyx */ transaction: transactionPropTypes, - - /** The policy of the report */ - policy: PropTypes.shape({ - /** - * Whether or not the policy has tax tracking enabled - * - * @deprecated - use tax.trackingEnabled instead - */ - isTaxTrackingEnabled: PropTypes.bool, - - /** Whether or not the policy has tax tracking enabled */ - tax: PropTypes.shape({ - trackingEnabled: PropTypes.bool, - }), - }), }; const defaultProps = { From 0381cb36ce2533bd8772e9cd3b955e327e43d438 Mon Sep 17 00:00:00 2001 From: Etotaziba Olei Date: Mon, 19 Feb 2024 12:17:58 +0100 Subject: [PATCH 092/698] fix typecheck --- src/libs/actions/IOU.ts | 22 ++++++++++++++++++---- src/pages/EditRequestPage.js | 4 ++-- 2 files changed, 20 insertions(+), 6 deletions(-) diff --git a/src/libs/actions/IOU.ts b/src/libs/actions/IOU.ts index 2decc65456f8..7fe33ec54881 100644 --- a/src/libs/actions/IOU.ts +++ b/src/libs/actions/IOU.ts @@ -1349,20 +1349,34 @@ function updateMoneyRequestTag( } /** Updates the created tax amount of a money request */ -function updateMoneyRequestTaxAmount(transactionID: string, optimisticReportActionID: string, taxAmount: number) { +function updateMoneyRequestTaxAmount( + transactionID: string, + optimisticReportActionID: string, + taxAmount: number, + policy: OnyxEntry, + policyTagList: OnyxEntry, + policyCategories: OnyxEntry, +) { const transactionChanges = { taxAmount, }; - const {params, onyxData} = getUpdateMoneyRequestParams(transactionID, optimisticReportActionID, transactionChanges, true); + const {params, onyxData} = getUpdateMoneyRequestParams(transactionID, optimisticReportActionID, transactionChanges, policy, policyTagList, policyCategories, true); API.write('UpdateMoneyRequestTaxAmount', params, onyxData); } /** Updates the created tax rate of a money request */ -function updateMoneyRequestTaxRate(transactionID: string, optimisticReportActionID: string, taxCode: string) { +function updateMoneyRequestTaxRate( + transactionID: string, + optimisticReportActionID: string, + taxCode: string, + policy: OnyxEntry, + policyTagList: OnyxEntry, + policyCategories: OnyxEntry, +) { const transactionChanges = { taxCode, }; - const {params, onyxData} = getUpdateMoneyRequestParams(transactionID, optimisticReportActionID, transactionChanges, true); + const {params, onyxData} = getUpdateMoneyRequestParams(transactionID, optimisticReportActionID, transactionChanges, policy, policyTagList, policyCategories, true); API.write('UpdateMoneyRequestTaxRate', params, onyxData); } diff --git a/src/pages/EditRequestPage.js b/src/pages/EditRequestPage.js index 3653e37a6555..c6e239d8c766 100644 --- a/src/pages/EditRequestPage.js +++ b/src/pages/EditRequestPage.js @@ -136,13 +136,13 @@ function EditRequestPage({report, route, policy, policyTaxRates, policyCategorie const updateTaxAmount = (transactionChanges) => { const newTaxAmount = CurrencyUtils.convertToBackendAmount(Number.parseFloat(transactionChanges.amount)); - IOU.updateMoneyRequestTaxAmount(transaction.transactionID, report.reportID, newTaxAmount); + IOU.updateMoneyRequestTaxAmount(transaction.transactionID, report.reportID, newTaxAmount, policy, policyTags, policyCategories); Navigation.dismissModal(report.reportID); }; const updateTaxRate = (transactionChanges) => { const newTaxCode = transactionChanges.data.code; - IOU.updateMoneyRequestTaxRate(transaction.transactionID, report.reportID, newTaxCode); + IOU.updateMoneyRequestTaxRate(transaction.transactionID, report.reportID, newTaxCode, policy, policyTags, policyCategories); Navigation.dismissModal(report.reportID); }; From ec0eb6f7ed0d3a0cd0884cd7999fb91472702797 Mon Sep 17 00:00:00 2001 From: Yogesh Bhatt <65986357+ygshbht@users.noreply.github.com> Date: Tue, 20 Feb 2024 03:20:43 +0530 Subject: [PATCH 093/698] Comment typo fix src/pages/settings/Profile/PersonalDetails/StateSelectionPage.tsx Co-authored-by: Vit Horacek <36083550+mountiny@users.noreply.github.com> --- .../settings/Profile/PersonalDetails/StateSelectionPage.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/pages/settings/Profile/PersonalDetails/StateSelectionPage.tsx b/src/pages/settings/Profile/PersonalDetails/StateSelectionPage.tsx index 7c0320244620..d5221c98b046 100644 --- a/src/pages/settings/Profile/PersonalDetails/StateSelectionPage.tsx +++ b/src/pages/settings/Profile/PersonalDetails/StateSelectionPage.tsx @@ -68,7 +68,7 @@ function StateSelectionPage() { Navigation.goBack(appendParam(backTo, 'state', option.value)); } else { // Otherwise, navigate to the specific route defined in "backTo" with a country parameter - // @ts-expect-error Navigation.navigate does take a paraml + // @ts-expect-error Navigation.navigate does take a param Navigation.navigate(appendParam(backTo, 'state', option.value)); } }, From 07f6f2160d2670a8155708a88e38a291f6cb6ca7 Mon Sep 17 00:00:00 2001 From: Yogesh Bhatt <65986357+ygshbht@users.noreply.github.com> Date: Tue, 20 Feb 2024 03:21:40 +0530 Subject: [PATCH 094/698] Comment formatting src/pages/settings/Profile/PersonalDetails/AddressPage.js Co-authored-by: Vit Horacek <36083550+mountiny@users.noreply.github.com> --- src/pages/settings/Profile/PersonalDetails/AddressPage.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/pages/settings/Profile/PersonalDetails/AddressPage.js b/src/pages/settings/Profile/PersonalDetails/AddressPage.js index 95b006828c39..87960d1f6687 100644 --- a/src/pages/settings/Profile/PersonalDetails/AddressPage.js +++ b/src/pages/settings/Profile/PersonalDetails/AddressPage.js @@ -65,9 +65,9 @@ function AddressPage({privatePersonalDetails, route}) { usePrivatePersonalDetails(); const {translate} = useLocalize(); const address = useMemo(() => lodashGet(privatePersonalDetails, 'address') || {}, [privatePersonalDetails]); - const countryFromUrlTemp = lodashGet(route, 'params.country'); - // check if country is valid + + // Check if country is valid const countryFromUrl = lodashGet(CONST.ALL_COUNTRIES, countryFromUrlTemp) ? countryFromUrlTemp : ''; const stateFromUrl = useGeographicalStateFromRoute(); From 877740b9160d380890798ac2a6e42e52f2bc7bea Mon Sep 17 00:00:00 2001 From: Yogesh Bhatt Date: Tue, 20 Feb 2024 17:01:43 +0530 Subject: [PATCH 095/698] Fix TS errors --- src/ROUTES.ts | 17 +++++++---------- src/components/StateSelector.tsx | 1 - .../PersonalDetails/StateSelectionPage.tsx | 11 ++++++----- 3 files changed, 13 insertions(+), 16 deletions(-) diff --git a/src/ROUTES.ts b/src/ROUTES.ts index 3a4b92e9e529..1cf8eef0f4ab 100644 --- a/src/ROUTES.ts +++ b/src/ROUTES.ts @@ -133,16 +133,13 @@ const ROUTES = { }, SETTINGS_ADDRESS_STATE: { route: 'settings/profile/address/state', - getRoute: (state: string, backTo?: string, label?: string) => { - let route = `settings/profile/address/state?state=${state}`; - if (backTo) { - route += `&backTo=${encodeURIComponent(backTo)}`; - } - if (label) { - route += `&label=${encodeURIComponent(label)}`; - } - return route; - }, + + getRoute: (state?: string, backTo?: string, label?: string) => + `${getUrlWithBackToParam(`settings/profile/address/state${state ? `?state=${encodeURIComponent(state)}` : ''}`, backTo)}${ + // Nullish operator ?? doesnt seem to be a replacement for || here + // eslint-disable-next-line @typescript-eslint/prefer-nullish-coalescing + label ? `${backTo || state ? '&' : '?'}label=${encodeURIComponent(label)}` : '' + }` as const, }, SETTINGS_CONTACT_METHODS: { route: 'settings/profile/contact-methods', diff --git a/src/components/StateSelector.tsx b/src/components/StateSelector.tsx index 79c086057f88..9ddf2573f857 100644 --- a/src/components/StateSelector.tsx +++ b/src/components/StateSelector.tsx @@ -83,7 +83,6 @@ function StateSelector({errorText, shouldUseStateFromUrl = true, value: stateCod description={label || translate('common.state')} onPress={() => { const activeRoute = Navigation.getActiveRoute(); - // @ts-expect-error Navigation.navigate does take a param Navigation.navigate(ROUTES.SETTINGS_ADDRESS_STATE.getRoute(stateCode, activeRoute, label)); }} wrapperStyle={wrapperStyle} diff --git a/src/pages/settings/Profile/PersonalDetails/StateSelectionPage.tsx b/src/pages/settings/Profile/PersonalDetails/StateSelectionPage.tsx index d5221c98b046..532f4d3f97e4 100644 --- a/src/pages/settings/Profile/PersonalDetails/StateSelectionPage.tsx +++ b/src/pages/settings/Profile/PersonalDetails/StateSelectionPage.tsx @@ -12,6 +12,7 @@ import searchCountryOptions from '@libs/searchCountryOptions'; import type {CountryData} from '@libs/searchCountryOptions'; import StringUtils from '@libs/StringUtils'; import {appendParam} from '@libs/Url'; +import type {Route} from '@src/ROUTES'; type State = keyof typeof COMMON_CONST.STATES; @@ -64,12 +65,12 @@ function StateSelectionPage() { Navigation.goBack(); } else if (!_.isEmpty(backTo) && navigation.getState().routes.length === 1) { // If "backTo" is not empty and there is only one route, go back to the specific route defined in "backTo" with a country parameter - // @ts-expect-error Navigation.goBack does take a param - Navigation.goBack(appendParam(backTo, 'state', option.value)); - } else { + Navigation.goBack(appendParam(backTo, 'state', option.value) as Route); + } else if (!_.isEmpty(backTo)) { // Otherwise, navigate to the specific route defined in "backTo" with a country parameter - // @ts-expect-error Navigation.navigate does take a param - Navigation.navigate(appendParam(backTo, 'state', option.value)); + Navigation.navigate(appendParam(backTo, 'state', option.value) as Route); + } else { + Navigation.goBack(); } }, [navigation, params?.backTo], From b479e69163b26ba6cb8b5f9e339e49d45f51352a Mon Sep 17 00:00:00 2001 From: Etotaziba Olei Date: Tue, 20 Feb 2024 14:41:36 +0100 Subject: [PATCH 096/698] use taxRates from policy key for MoneyTemporaryForRefactorRequestConfirmationList --- ...TemporaryForRefactorRequestConfirmationList.js | 15 ++++++++------- 1 file changed, 8 insertions(+), 7 deletions(-) diff --git a/src/components/MoneyTemporaryForRefactorRequestConfirmationList.js b/src/components/MoneyTemporaryForRefactorRequestConfirmationList.js index 0be77a201f1f..5f4abfec7794 100755 --- a/src/components/MoneyTemporaryForRefactorRequestConfirmationList.js +++ b/src/components/MoneyTemporaryForRefactorRequestConfirmationList.js @@ -259,6 +259,7 @@ function MoneyTemporaryForRefactorRequestConfirmationList({ const {unit, rate, currency} = mileageRate; const distance = lodashGet(transaction, 'routes.route0.distance', 0); const shouldCalculateDistanceAmount = isDistanceRequest && iouAmount === 0; + const taxRates = lodashGet(policy, 'taxRates', {}); // A flag for showing the categories field const shouldShowCategories = isPolicyExpenseChat && (iouCategory || OptionsListUtils.hasEnabledOptions(_.values(policyCategories))); @@ -293,7 +294,7 @@ function MoneyTemporaryForRefactorRequestConfirmationList({ ); const formattedTaxAmount = CurrencyUtils.convertToDisplayString(transaction.taxAmount, iouCurrencyCode); - const taxRateTitle = TransactionUtils.getDefaultTaxName(policyTaxRates, transaction); + const taxRateTitle = TransactionUtils.getDefaultTaxName(taxRates, transaction); const previousTransactionTaxAmount = usePrevious(transaction.taxAmount); @@ -359,13 +360,13 @@ function MoneyTemporaryForRefactorRequestConfirmationList({ // Calculate and set tax amount in transaction draft useEffect(() => { - const taxAmount = getTaxAmount(transaction, policyTaxRates.defaultValue); + const taxAmount = getTaxAmount(transaction, taxRates.defaultValue); const amountInSmallestCurrencyUnits = CurrencyUtils.convertToBackendAmount(Number.parseFloat(taxAmount)); if (previousTransactionTaxAmount !== transaction.taxAmount && amountInSmallestCurrencyUnits !== transaction.taxAmount) { return; } IOU.setMoneyRequestTaxAmount(transaction.transactionID, amountInSmallestCurrencyUnits); - }, [policyTaxRates.defaultValue, transaction, previousTransactionTaxAmount]); + }, [taxRates.defaultValue, transaction, previousTransactionTaxAmount]); /** * Returns the participants with amount @@ -800,10 +801,10 @@ function MoneyTemporaryForRefactorRequestConfirmationList({ { item: ( Navigation.navigate(ROUTES.MONEY_REQUEST_STEP_TAX_RATE.getRoute(iouType, transaction.transactionID, reportID, Navigation.getActiveRouteWithoutParams()))} @@ -817,10 +818,10 @@ function MoneyTemporaryForRefactorRequestConfirmationList({ { item: ( Navigation.navigate(ROUTES.MONEY_REQUEST_STEP_TAX_AMOUNT.getRoute(iouType, transaction.transactionID, reportID, Navigation.getActiveRouteWithoutParams()))} From c9150473c7c9e77e0a3ec936d652eadbebf2257c Mon Sep 17 00:00:00 2001 From: Etotaziba Olei Date: Tue, 20 Feb 2024 14:45:13 +0100 Subject: [PATCH 097/698] use taxRates from policy key for MoneyTemporaryForRefactorRequestConfirmationList --- .../MoneyTemporaryForRefactorRequestConfirmationList.js | 9 --------- 1 file changed, 9 deletions(-) diff --git a/src/components/MoneyTemporaryForRefactorRequestConfirmationList.js b/src/components/MoneyTemporaryForRefactorRequestConfirmationList.js index 5f4abfec7794..ee1975220a24 100755 --- a/src/components/MoneyTemporaryForRefactorRequestConfirmationList.js +++ b/src/components/MoneyTemporaryForRefactorRequestConfirmationList.js @@ -162,10 +162,6 @@ const propTypes = { /** Collection of tags attached to a policy */ policyTags: tagPropTypes, - /* Onyx Props */ - /** Collection of tax rates attached to a policy */ - policyTaxRates: taxPropTypes, - /** Transaction that represents the money request */ transaction: transactionPropTypes, }; @@ -199,7 +195,6 @@ const defaultProps = { isDistanceRequest: false, shouldShowSmartScanFields: true, isPolicyExpenseChat: false, - policyTaxRates: {}, }; const getTaxAmount = (transaction, defaultTaxValue) => { @@ -245,7 +240,6 @@ function MoneyTemporaryForRefactorRequestConfirmationList({ session: {accountID}, shouldShowSmartScanFields, transaction, - policyTaxRates, }) { const theme = useTheme(); const styles = useThemeStyles(); @@ -950,8 +944,5 @@ export default compose( policy: { key: ({policyID}) => `${ONYXKEYS.COLLECTION.POLICY}${policyID}`, }, - policyTaxRates: { - key: ({policyID}) => `${ONYXKEYS.COLLECTION.POLICY_TAX_RATE}${policyID}`, - }, }), )(MoneyTemporaryForRefactorRequestConfirmationList); From 4e57d4ae08c18fb59b55fc4501b4c7ad6cfb57eb Mon Sep 17 00:00:00 2001 From: Etotaziba Olei Date: Tue, 20 Feb 2024 14:49:49 +0100 Subject: [PATCH 098/698] add taxRates propTypes to policy for MoneyTemporaryForRefactorRequestConfirmationList --- .../MoneyTemporaryForRefactorRequestConfirmationList.js | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/components/MoneyTemporaryForRefactorRequestConfirmationList.js b/src/components/MoneyTemporaryForRefactorRequestConfirmationList.js index ee1975220a24..c9afa52be850 100755 --- a/src/components/MoneyTemporaryForRefactorRequestConfirmationList.js +++ b/src/components/MoneyTemporaryForRefactorRequestConfirmationList.js @@ -162,6 +162,10 @@ const propTypes = { /** Collection of tags attached to a policy */ policyTags: tagPropTypes, + /* Onyx Props */ + /** Collection of tax rates attached to a policy */ + policyTaxRates: taxPropTypes, + /** Transaction that represents the money request */ transaction: transactionPropTypes, }; From 17281f6829da70f9dc828d2b0def2c5f3105868a Mon Sep 17 00:00:00 2001 From: Etotaziba Olei Date: Tue, 20 Feb 2024 14:50:44 +0100 Subject: [PATCH 099/698] remove unused Fragment import for MoneyTemporaryForRefactorRequestConfirmation --- .../MoneyTemporaryForRefactorRequestConfirmationList.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/components/MoneyTemporaryForRefactorRequestConfirmationList.js b/src/components/MoneyTemporaryForRefactorRequestConfirmationList.js index c9afa52be850..1224c12255c6 100755 --- a/src/components/MoneyTemporaryForRefactorRequestConfirmationList.js +++ b/src/components/MoneyTemporaryForRefactorRequestConfirmationList.js @@ -2,7 +2,7 @@ import {useIsFocused} from '@react-navigation/native'; import {format} from 'date-fns'; import lodashGet from 'lodash/get'; import PropTypes from 'prop-types'; -import React, {Fragment, useCallback, useEffect, useMemo, useReducer, useRef, useState} from 'react'; +import React, {useCallback, useEffect, useMemo, useReducer, useRef, useState} from 'react'; import {View} from 'react-native'; import {withOnyx} from 'react-native-onyx'; import _ from 'underscore'; From 9b3ac1296a0ce0c01eae5b9e6b2dc65546e8fd8b Mon Sep 17 00:00:00 2001 From: Etotaziba Olei Date: Tue, 20 Feb 2024 14:52:22 +0100 Subject: [PATCH 100/698] update taxAmount Description for MoneyTemporaryForRefactorRequestConfirmation --- .../MoneyTemporaryForRefactorRequestConfirmationList.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/components/MoneyTemporaryForRefactorRequestConfirmationList.js b/src/components/MoneyTemporaryForRefactorRequestConfirmationList.js index 1224c12255c6..094e2d58066e 100755 --- a/src/components/MoneyTemporaryForRefactorRequestConfirmationList.js +++ b/src/components/MoneyTemporaryForRefactorRequestConfirmationList.js @@ -819,7 +819,7 @@ function MoneyTemporaryForRefactorRequestConfirmationList({ key={`${taxRates.name}${formattedTaxAmount}`} shouldShowRightIcon={!isReadOnly} title={formattedTaxAmount} - description={taxRates.name} + description={translate('iou.taxAmount')} style={[styles.moneyRequestMenuItem]} titleStyle={styles.flex1} onPress={() => Navigation.navigate(ROUTES.MONEY_REQUEST_STEP_TAX_AMOUNT.getRoute(iouType, transaction.transactionID, reportID, Navigation.getActiveRouteWithoutParams()))} From af4783aa91236784e84eb133c691f40b6bfef9e8 Mon Sep 17 00:00:00 2001 From: Etotaziba Olei Date: Tue, 20 Feb 2024 15:01:55 +0100 Subject: [PATCH 101/698] use taxRates from policy key for MoneyRequestRequestConfirmationList --- src/components/MoneyRequestConfirmationList.js | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/components/MoneyRequestConfirmationList.js b/src/components/MoneyRequestConfirmationList.js index c5fea084674d..13a118d416a4 100755 --- a/src/components/MoneyRequestConfirmationList.js +++ b/src/components/MoneyRequestConfirmationList.js @@ -229,6 +229,7 @@ function MoneyRequestConfirmationList(props) { const {unit, rate, currency} = props.mileageRate; const distance = lodashGet(transaction, 'routes.route0.distance', 0); const shouldCalculateDistanceAmount = props.isDistanceRequest && props.iouAmount === 0; + const taxRates = lodashGet(props.policy, 'taxRates', {}); // A flag for showing the categories field const shouldShowCategories = props.isPolicyExpenseChat && (props.iouCategory || OptionsListUtils.hasEnabledOptions(_.values(props.policyCategories))); @@ -262,7 +263,7 @@ function MoneyRequestConfirmationList(props) { props.isDistanceRequest ? currency : props.iouCurrencyCode, ); const formattedTaxAmount = CurrencyUtils.convertToDisplayString(props.transaction.taxAmount, props.iouCurrencyCode); - const taxRateTitle = TransactionUtils.getDefaultTaxName(props.policyTaxRates, transaction); + const taxRateTitle = TransactionUtils.getDefaultTaxName(taxRates, transaction); const isFocused = useIsFocused(); const [formError, setFormError] = useState(''); @@ -812,7 +813,7 @@ function MoneyRequestConfirmationList(props) { From dbd68de9d793cd328281efa0a357d9f6535ca315 Mon Sep 17 00:00:00 2001 From: Etotaziba Olei Date: Tue, 20 Feb 2024 15:03:46 +0100 Subject: [PATCH 102/698] remove policyTaxRates props and ONYX key for MoneyRequestConfirmationList --- src/components/MoneyRequestConfirmationList.js | 8 -------- 1 file changed, 8 deletions(-) diff --git a/src/components/MoneyRequestConfirmationList.js b/src/components/MoneyRequestConfirmationList.js index 13a118d416a4..a71c8bc96b2c 100755 --- a/src/components/MoneyRequestConfirmationList.js +++ b/src/components/MoneyRequestConfirmationList.js @@ -167,10 +167,6 @@ const propTypes = { /** Collection of tags attached to a policy */ policyTags: tagPropTypes, - /* Onyx Props */ - /** Collection of tax rates attached to a policy */ - policyTaxRates: taxPropTypes, - /** Holds data related to Money Request view state, rather than the underlying Money Request data. */ iou: iouPropTypes, }; @@ -207,7 +203,6 @@ const defaultProps = { shouldShowSmartScanFields: true, isPolicyExpenseChat: false, iou: iouDefaultProps, - policyTaxRates: {}, }; function MoneyRequestConfirmationList(props) { @@ -882,9 +877,6 @@ export default compose( policy: { key: ({policyID}) => `${ONYXKEYS.COLLECTION.POLICY}${policyID}`, }, - policyTaxRates: { - key: ({policyID}) => `${ONYXKEYS.COLLECTION.POLICY_TAX_RATE}${policyID}`, - }, iou: { key: ONYXKEYS.IOU, }, From dfb486a9685f3d9ef279df6a51799062ef4204b4 Mon Sep 17 00:00:00 2001 From: Etotaziba Olei Date: Tue, 20 Feb 2024 15:24:43 +0100 Subject: [PATCH 103/698] update taxRates propTypes to policy for MoneyTemporaryForRefactorRequestConfirmationList --- .../MoneyTemporaryForRefactorRequestConfirmationList.js | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/src/components/MoneyTemporaryForRefactorRequestConfirmationList.js b/src/components/MoneyTemporaryForRefactorRequestConfirmationList.js index 094e2d58066e..3e4435d6c4fc 100755 --- a/src/components/MoneyTemporaryForRefactorRequestConfirmationList.js +++ b/src/components/MoneyTemporaryForRefactorRequestConfirmationList.js @@ -25,6 +25,7 @@ import * as ReceiptUtils from '@libs/ReceiptUtils'; import * as ReportUtils from '@libs/ReportUtils'; import playSound, {SOUNDS} from '@libs/Sound'; import * as TransactionUtils from '@libs/TransactionUtils'; +import {policyPropTypes} from '@pages/workspace/withPolicy'; import * as IOU from '@userActions/IOU'; import CONST from '@src/CONST'; import ONYXKEYS from '@src/ONYXKEYS'; @@ -43,7 +44,6 @@ import ReceiptEmptyState from './ReceiptEmptyState'; import SettlementButton from './SettlementButton'; import Switch from './Switch'; import tagPropTypes from './tagPropTypes'; -import taxPropTypes from './taxPropTypes'; import Text from './Text'; import transactionPropTypes from './transactionPropTypes'; import withCurrentUserPersonalDetails, {withCurrentUserPersonalDetailsDefaultProps, withCurrentUserPersonalDetailsPropTypes} from './withCurrentUserPersonalDetails'; @@ -163,8 +163,8 @@ const propTypes = { policyTags: tagPropTypes, /* Onyx Props */ - /** Collection of tax rates attached to a policy */ - policyTaxRates: taxPropTypes, + /** The policy of the report */ + policy: policyPropTypes.policy, /** Transaction that represents the money request */ transaction: transactionPropTypes, @@ -193,6 +193,7 @@ const defaultProps = { listStyles: [], policyCategories: {}, policyTags: {}, + policy: {}, transactionID: '', transaction: {}, mileageRate: {unit: CONST.CUSTOM_UNITS.DISTANCE_UNIT_MILES, rate: 0, currency: 'USD'}, From e252453fad3d53e756cf3afba491dc57747b72ba Mon Sep 17 00:00:00 2001 From: Etotaziba Olei Date: Tue, 20 Feb 2024 15:26:37 +0100 Subject: [PATCH 104/698] update taxRates propTypes to policy for MoneyRequestConfirmationList --- src/components/MoneyRequestConfirmationList.js | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/src/components/MoneyRequestConfirmationList.js b/src/components/MoneyRequestConfirmationList.js index a71c8bc96b2c..1587a4ace6f0 100755 --- a/src/components/MoneyRequestConfirmationList.js +++ b/src/components/MoneyRequestConfirmationList.js @@ -25,6 +25,7 @@ import * as ReceiptUtils from '@libs/ReceiptUtils'; import * as ReportUtils from '@libs/ReportUtils'; import * as TransactionUtils from '@libs/TransactionUtils'; import {iouDefaultProps, iouPropTypes} from '@pages/iou/propTypes'; +import {policyPropTypes} from '@pages/workspace/withPolicy'; import * as IOU from '@userActions/IOU'; import CONST from '@src/CONST'; import ONYXKEYS from '@src/ONYXKEYS'; @@ -42,7 +43,6 @@ import SettlementButton from './SettlementButton'; import ShowMoreButton from './ShowMoreButton'; import Switch from './Switch'; import tagPropTypes from './tagPropTypes'; -import taxPropTypes from './taxPropTypes'; import Text from './Text'; import transactionPropTypes from './transactionPropTypes'; import withCurrentUserPersonalDetails, {withCurrentUserPersonalDetailsDefaultProps, withCurrentUserPersonalDetailsPropTypes} from './withCurrentUserPersonalDetails'; @@ -167,6 +167,10 @@ const propTypes = { /** Collection of tags attached to a policy */ policyTags: tagPropTypes, + /* Onyx Props */ + /** The policy of the report */ + policy: policyPropTypes.policy, + /** Holds data related to Money Request view state, rather than the underlying Money Request data. */ iou: iouPropTypes, }; From a811a81bf818fcee01d3ba5255cddfd225597e88 Mon Sep 17 00:00:00 2001 From: Etotaziba Olei Date: Tue, 20 Feb 2024 15:46:36 +0100 Subject: [PATCH 105/698] add taxRates types to policy --- src/types/onyx/Policy.ts | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/types/onyx/Policy.ts b/src/types/onyx/Policy.ts index 7d4c08374b81..37ce28f93abc 100644 --- a/src/types/onyx/Policy.ts +++ b/src/types/onyx/Policy.ts @@ -1,5 +1,6 @@ import type {ValueOf} from 'type-fest'; import type CONST from '@src/CONST'; +import type {PolicyTaxRates} from '@src/types/onyx/PolicyTaxRates'; import type * as OnyxCommon from './OnyxCommon'; type Unit = 'mi' | 'km'; @@ -171,6 +172,9 @@ type Policy = { trackingEnabled: boolean; }; + /** Collection of tax rates attached to a policy */ + taxRates?: PolicyTaxRates; + /** ReportID of the admins room for this workspace */ chatReportIDAdmins?: number; From b4e61f4cfc3bb004cd8a48080d50bc13bcabf70a Mon Sep 17 00:00:00 2001 From: Etotaziba Olei Date: Tue, 20 Feb 2024 15:46:48 +0100 Subject: [PATCH 106/698] use taxRates from policy key for MoneyRequestView --- src/components/ReportActionItem/MoneyRequestView.tsx | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/components/ReportActionItem/MoneyRequestView.tsx b/src/components/ReportActionItem/MoneyRequestView.tsx index 2125610a3ea8..147d8e6ea31a 100644 --- a/src/components/ReportActionItem/MoneyRequestView.tsx +++ b/src/components/ReportActionItem/MoneyRequestView.tsx @@ -120,11 +120,11 @@ function MoneyRequestView({ const isCardTransaction = TransactionUtils.isCardTransaction(transaction); const cardProgramName = isCardTransaction && transactionCardID !== undefined ? CardUtils.getCardDescription(transactionCardID) : ''; const isApproved = ReportUtils.isReportApproved(moneyRequestReport); - + const taxRates = policy?.taxRates; const formattedTaxAmount = transactionTaxAmount ? CurrencyUtils.convertToDisplayString(transactionTaxAmount, transactionCurrency) : ''; - const policyTaxRatesDescription = policyTaxRates?.name; - const taxRateTitle = (transactionTaxCode && policyTaxRates && TransactionUtils.getTaxName(policyTaxRates.taxes, transactionTaxCode)) ?? ''; + const policyTaxRatesDescription = taxRates?.name; + const taxRateTitle = (transactionTaxCode && taxRates && TransactionUtils.getTaxName(taxRates?.taxes, transactionTaxCode)) ?? ''; // Flags for allowing or disallowing editing a money request const isSettled = ReportUtils.isSettled(moneyRequestReport?.reportID); From 0cd0f457bc6cdaa641dd155b39a869ea5d79cf44 Mon Sep 17 00:00:00 2001 From: Etotaziba Olei Date: Tue, 20 Feb 2024 15:50:14 +0100 Subject: [PATCH 107/698] remove policyTaxRates props and ONYX key for MoneyRequestView --- src/components/ReportActionItem/MoneyRequestView.tsx | 7 ------- 1 file changed, 7 deletions(-) diff --git a/src/components/ReportActionItem/MoneyRequestView.tsx b/src/components/ReportActionItem/MoneyRequestView.tsx index 147d8e6ea31a..0242c83069fd 100644 --- a/src/components/ReportActionItem/MoneyRequestView.tsx +++ b/src/components/ReportActionItem/MoneyRequestView.tsx @@ -58,9 +58,6 @@ type MoneyRequestViewOnyxPropsWithoutTransaction = { /** Collection of tags attached to a policy */ policyTagList: OnyxEntry; - /** Collection of tax rates attached to a policy */ - policyTaxRates: OnyxEntry; - /** The expense report or iou report (only will have a value if this is a transaction thread) */ parentReport: OnyxEntry; @@ -87,7 +84,6 @@ function MoneyRequestView({ transaction, policyTagList, policy, - policyTaxRates, transactionViolations, }: MoneyRequestViewProps) { const theme = useTheme(); @@ -491,9 +487,6 @@ export default withOnyx `${ONYXKEYS.COLLECTION.POLICY_TAGS}${report.policyID}`, }, - policyTaxRates: { - key: ({report}) => `${ONYXKEYS.COLLECTION.POLICY_TAX_RATE}${report.policyID}`, - }, parentReport: { key: ({report}) => `${ONYXKEYS.COLLECTION.REPORT}${report.parentReportID}`, }, From a175dac5612296883cd32c49eae9ceca45a4ef25 Mon Sep 17 00:00:00 2001 From: Etotaziba Olei Date: Tue, 20 Feb 2024 16:04:40 +0100 Subject: [PATCH 108/698] fix lint warning for MoneyRequestView --- src/types/onyx/Policy.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/types/onyx/Policy.ts b/src/types/onyx/Policy.ts index 37ce28f93abc..1ba392c6ad3c 100644 --- a/src/types/onyx/Policy.ts +++ b/src/types/onyx/Policy.ts @@ -1,6 +1,6 @@ import type {ValueOf} from 'type-fest'; import type CONST from '@src/CONST'; -import type {PolicyTaxRates} from '@src/types/onyx/PolicyTaxRates'; +import type {PolicyTaxRates} from './PolicyTaxRates'; import type * as OnyxCommon from './OnyxCommon'; type Unit = 'mi' | 'km'; From 8480869271cb762b2f0d0a8bd1b613d2728df13e Mon Sep 17 00:00:00 2001 From: Etotaziba Olei Date: Tue, 20 Feb 2024 16:21:19 +0100 Subject: [PATCH 109/698] use taxRates from policy key for taxPicker --- src/components/TaxPicker/index.js | 15 ++++++++------- 1 file changed, 8 insertions(+), 7 deletions(-) diff --git a/src/components/TaxPicker/index.js b/src/components/TaxPicker/index.js index 287805692bcf..b83d75f314aa 100644 --- a/src/components/TaxPicker/index.js +++ b/src/components/TaxPicker/index.js @@ -12,14 +12,15 @@ import CONST from '@src/CONST'; import ONYXKEYS from '@src/ONYXKEYS'; import {defaultProps, propTypes} from './taxPickerPropTypes'; -function TaxPicker({selectedTaxRate, policyTaxRates, insets, onSubmit}) { +function TaxPicker({selectedTaxRate, policy, insets, onSubmit}) { const styles = useThemeStyles(); const StyleUtils = useStyleUtils(); const {translate} = useLocalize(); const [searchValue, setSearchValue] = useState(''); - const policyTaxRatesCount = TransactionUtils.getEnabledTaxRateCount(policyTaxRates.taxes); - const isTaxRatesCountBelowThreshold = policyTaxRatesCount < CONST.TAX_RATES_LIST_THRESHOLD; + const taxRates = policy.taxRates; + const taxRatesCount = TransactionUtils.getEnabledTaxRateCount(taxRates.taxes); + const isTaxRatesCountBelowThreshold = taxRatesCount < CONST.TAX_RATES_LIST_THRESHOLD; const shouldShowTextInput = !isTaxRatesCountBelowThreshold; @@ -56,10 +57,10 @@ function TaxPicker({selectedTaxRate, policyTaxRates, insets, onSubmit}) { false, false, true, - policyTaxRates, + taxRates, ); return policyTaxRatesOptions; - }, [policyTaxRates, searchValue, selectedOptions]); + }, [taxRates, searchValue, selectedOptions]); const selectedOptionKey = lodashGet(_.filter(lodashGet(sections, '[0].data', []), (taxRate) => taxRate.searchText === selectedTaxRate)[0], 'keyForList'); @@ -90,7 +91,7 @@ TaxPicker.propTypes = propTypes; TaxPicker.defaultProps = defaultProps; export default withOnyx({ - policyTaxRates: { - key: ({policyID}) => `${ONYXKEYS.COLLECTION.POLICY_TAX_RATE}${policyID}`, + policy: { + key: ({policyID}) => `${ONYXKEYS.COLLECTION.POLICY}${policyID}`, }, })(TaxPicker); From dc0ec64db55aa607208df89f1f71a13e01a9f4f1 Mon Sep 17 00:00:00 2001 From: Etotaziba Olei Date: Tue, 20 Feb 2024 16:45:47 +0100 Subject: [PATCH 110/698] update TaxPicker PropTypes --- src/components/TaxPicker/taxPickerPropTypes.js | 14 +++++++++++--- 1 file changed, 11 insertions(+), 3 deletions(-) diff --git a/src/components/TaxPicker/taxPickerPropTypes.js b/src/components/TaxPicker/taxPickerPropTypes.js index 289b4e19aaa4..35d1866ff5d1 100644 --- a/src/components/TaxPicker/taxPickerPropTypes.js +++ b/src/components/TaxPicker/taxPickerPropTypes.js @@ -1,5 +1,6 @@ import PropTypes from 'prop-types'; import taxPropTypes from '@components/taxPropTypes'; +import safeAreaInsetPropTypes from '@pages/safeAreaInsetPropTypes'; const propTypes = { /** The selected tax rate of an expense */ @@ -8,9 +9,16 @@ const propTypes = { /** Callback to fire when a tax is pressed */ onSubmit: PropTypes.func.isRequired, - /* Onyx Props */ - /** Collection of tax rates attached to a policy */ - policyTaxRates: taxPropTypes, + policy: PropTypes.shape({ + /** Collection of tax rates attached to a policy */ + taxRates: taxPropTypes, + }), + + /** + * Safe area insets required for reflecting the portion of the view, + * that is not covered by navigation bars, tab bars, toolbars, and other ancestor views. + */ + insets: safeAreaInsetPropTypes.isRequired, }; const defaultProps = { From 94a2e3fb6e0927a49a98bad626cacb3dfc83746e Mon Sep 17 00:00:00 2001 From: Etotaziba Olei Date: Tue, 20 Feb 2024 16:47:03 +0100 Subject: [PATCH 111/698] fix prettier --- src/types/onyx/Policy.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/types/onyx/Policy.ts b/src/types/onyx/Policy.ts index 1ba392c6ad3c..90b6c0da7e8d 100644 --- a/src/types/onyx/Policy.ts +++ b/src/types/onyx/Policy.ts @@ -1,7 +1,7 @@ import type {ValueOf} from 'type-fest'; import type CONST from '@src/CONST'; -import type {PolicyTaxRates} from './PolicyTaxRates'; import type * as OnyxCommon from './OnyxCommon'; +import type {PolicyTaxRates} from './PolicyTaxRates'; type Unit = 'mi' | 'km'; From 3d5af3b73c518c4fc92db662a5187a51366cfbcc Mon Sep 17 00:00:00 2001 From: Etotaziba Olei Date: Wed, 21 Feb 2024 11:05:46 +0100 Subject: [PATCH 112/698] use taxRates from policy key for EditRequestPage --- src/pages/EditRequestPage.js | 12 +++--------- 1 file changed, 3 insertions(+), 9 deletions(-) diff --git a/src/pages/EditRequestPage.js b/src/pages/EditRequestPage.js index c6e239d8c766..b69dfcb32577 100644 --- a/src/pages/EditRequestPage.js +++ b/src/pages/EditRequestPage.js @@ -7,7 +7,6 @@ import FullPageNotFoundView from '@components/BlockingViews/FullPageNotFoundView import categoryPropTypes from '@components/categoryPropTypes'; import ScreenWrapper from '@components/ScreenWrapper'; import tagPropTypes from '@components/tagPropTypes'; -import taxPropTypes from '@components/taxPropTypes'; import transactionPropTypes from '@components/transactionPropTypes'; import compose from '@libs/compose'; import * as CurrencyUtils from '@libs/CurrencyUtils'; @@ -67,9 +66,6 @@ const propTypes = { /** Transaction that stores the request data */ transaction: transactionPropTypes, - - /** Collection of tax rates attached to a policy */ - policyTaxRates: taxPropTypes, }; const defaultProps = { @@ -79,7 +75,6 @@ const defaultProps = { policyTags: {}, parentReportActions: {}, transaction: {}, - policyTaxRates: {}, }; const getTaxAmount = (transactionAmount, transactionTaxCode, policyTaxRates) => { @@ -87,7 +82,7 @@ const getTaxAmount = (transactionAmount, transactionTaxCode, policyTaxRates) => return CurrencyUtils.convertToBackendAmount(Number.parseFloat(TransactionUtils.calculateTaxAmount(percentage, transactionAmount))); }; -function EditRequestPage({report, route, policy, policyTaxRates, policyCategories, policyTags, parentReportActions, transaction}) { +function EditRequestPage({report, route, policy, policyCategories, policyTags, parentReportActions, transaction}) { const parentReportActionID = lodashGet(report, 'parentReportActionID', '0'); const parentReportAction = lodashGet(parentReportActions, parentReportActionID, {}); const { @@ -107,6 +102,8 @@ function EditRequestPage({report, route, policy, policyTaxRates, policyCategorie const policyTagListName = PolicyUtils.getTagListName(policyTags, tagIndex); const policyTagLists = useMemo(() => PolicyUtils.getTagLists(policyTags), [policyTags]); + const policyTaxRates = lodashGet(props.policy, 'taxRates', {}); + const taxRateTitle = TransactionUtils.getTaxName(policyTaxRates.taxes, transactionTaxCode); // A flag for verifying that the current report is a sub-report of a workspace chat @@ -304,9 +301,6 @@ export default compose( policyTags: { key: ({report}) => `${ONYXKEYS.COLLECTION.POLICY_TAGS}${report ? report.policyID : '0'}`, }, - policyTaxRates: { - key: ({report}) => `${ONYXKEYS.COLLECTION.POLICY_TAX_RATE}${report.policyID}`, - }, parentReportActions: { key: ({report}) => `${ONYXKEYS.COLLECTION.REPORT_ACTIONS}${report ? report.parentReportID : '0'}`, canEvict: false, From 446c7c8427ad90306460ce799186386cd9118725 Mon Sep 17 00:00:00 2001 From: Etotaziba Olei Date: Wed, 21 Feb 2024 11:08:04 +0100 Subject: [PATCH 113/698] remove undefined props usage for EditRequestPage --- src/pages/EditRequestPage.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/pages/EditRequestPage.js b/src/pages/EditRequestPage.js index b69dfcb32577..ce52e4db3052 100644 --- a/src/pages/EditRequestPage.js +++ b/src/pages/EditRequestPage.js @@ -102,7 +102,7 @@ function EditRequestPage({report, route, policy, policyCategories, policyTags, p const policyTagListName = PolicyUtils.getTagListName(policyTags, tagIndex); const policyTagLists = useMemo(() => PolicyUtils.getTagLists(policyTags), [policyTags]); - const policyTaxRates = lodashGet(props.policy, 'taxRates', {}); + const policyTaxRates = lodashGet(policy, 'taxRates', {}); const taxRateTitle = TransactionUtils.getTaxName(policyTaxRates.taxes, transactionTaxCode); From 3e4c6c61ed756484379442ca9eae3398a9a03f9e Mon Sep 17 00:00:00 2001 From: Etotaziba Olei Date: Wed, 21 Feb 2024 12:45:38 +0100 Subject: [PATCH 114/698] use taxRates from policy key for IOURequestStepTaxAmountPage --- .../iou/request/step/IOURequestStepTaxAmountPage.js | 13 +++++-------- 1 file changed, 5 insertions(+), 8 deletions(-) diff --git a/src/pages/iou/request/step/IOURequestStepTaxAmountPage.js b/src/pages/iou/request/step/IOURequestStepTaxAmountPage.js index 491d9801c2dc..6a8fff080de7 100644 --- a/src/pages/iou/request/step/IOURequestStepTaxAmountPage.js +++ b/src/pages/iou/request/step/IOURequestStepTaxAmountPage.js @@ -29,16 +29,12 @@ const propTypes = { /** The transaction object being modified in Onyx */ transaction: transactionPropTypes, - - /* Onyx Props */ - /** Collection of tax rates attached to a policy */ - policyTaxRates: taxPropTypes, }; const defaultProps = { report: {}, + policy: {}, transaction: {}, - policyTaxRates: {}, }; const getTaxAmount = (transaction, defaultTaxValue) => { @@ -53,7 +49,7 @@ function IOURequestStepTaxAmountPage({ transaction, transaction: {currency}, report, - policyTaxRates, + policy, }) { const {translate} = useLocalize(); const textInput = useRef(null); @@ -63,6 +59,7 @@ function IOURequestStepTaxAmountPage({ const isSaveButtonPressed = useRef(false); const originalCurrency = useRef(null); + const policyTaxRates = lodashGet(policy, 'taxRates', {}); useEffect(() => { if (transaction.originalCurrency) { @@ -158,8 +155,8 @@ export default compose( withWritableReportOrNotFound, withFullTransactionOrNotFound, withOnyx({ - policyTaxRates: { - key: ({report}) => `${ONYXKEYS.COLLECTION.POLICY_TAX_RATE}${report ? report.policyID : '0'}`, + policy: { + key: ({report}) => `${ONYXKEYS.COLLECTION.POLICY}${report ? report.policyID : '0'}`, }, }), )(IOURequestStepTaxAmountPage); From 7a1cb79c716dcd91a50576223f56780e31d35d59 Mon Sep 17 00:00:00 2001 From: Etotaziba Olei Date: Wed, 21 Feb 2024 12:47:31 +0100 Subject: [PATCH 115/698] add taxRates propTypes to policy for IOURequestStepTaxAmountPage --- src/pages/iou/request/step/IOURequestStepTaxAmountPage.js | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/src/pages/iou/request/step/IOURequestStepTaxAmountPage.js b/src/pages/iou/request/step/IOURequestStepTaxAmountPage.js index 6a8fff080de7..5135f5f319b4 100644 --- a/src/pages/iou/request/step/IOURequestStepTaxAmountPage.js +++ b/src/pages/iou/request/step/IOURequestStepTaxAmountPage.js @@ -29,6 +29,12 @@ const propTypes = { /** The transaction object being modified in Onyx */ transaction: transactionPropTypes, + + /** The policy of the report */ + policy: PropTypes.shape({ + /** Collection of tax rates attached to a policy */ + taxRates: taxPropTypes, + }), }; const defaultProps = { From 7376d2e006ecf260545c41a1f73ce0fefa4bcfee Mon Sep 17 00:00:00 2001 From: Etotaziba Olei Date: Wed, 21 Feb 2024 12:50:08 +0100 Subject: [PATCH 116/698] add missing imports for IOURequestStepTaxAmountPage --- src/pages/iou/request/step/IOURequestStepTaxAmountPage.js | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/pages/iou/request/step/IOURequestStepTaxAmountPage.js b/src/pages/iou/request/step/IOURequestStepTaxAmountPage.js index 5135f5f319b4..1d5ea686e975 100644 --- a/src/pages/iou/request/step/IOURequestStepTaxAmountPage.js +++ b/src/pages/iou/request/step/IOURequestStepTaxAmountPage.js @@ -1,4 +1,6 @@ import {useFocusEffect} from '@react-navigation/native'; +import lodashGet from 'lodash/get'; +import PropTypes from 'prop-types'; import React, {useCallback, useEffect, useRef} from 'react'; import {withOnyx} from 'react-native-onyx'; import taxPropTypes from '@components/taxPropTypes'; From cd2883c47a696e5bdd3fbba36b343055c72adb58 Mon Sep 17 00:00:00 2001 From: Etotaziba Olei Date: Wed, 21 Feb 2024 12:54:36 +0100 Subject: [PATCH 117/698] add policy onyx props for IOURequestStepTaxRatePage --- src/pages/iou/request/step/IOURequestStepTaxRatePage.js | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/pages/iou/request/step/IOURequestStepTaxRatePage.js b/src/pages/iou/request/step/IOURequestStepTaxRatePage.js index f930e33f129f..79429d57cfe1 100644 --- a/src/pages/iou/request/step/IOURequestStepTaxRatePage.js +++ b/src/pages/iou/request/step/IOURequestStepTaxRatePage.js @@ -96,5 +96,8 @@ export default compose( policyTaxRates: { key: ({report}) => `${ONYXKEYS.COLLECTION.POLICY_TAX_RATE}${report ? report.policyID : '0'}`, }, + policy: { + key: ({report}) => `${ONYXKEYS.COLLECTION.POLICY}${report ? report.policyID : '0'}`, + }, }), )(IOURequestStepTaxRatePage); From 7c88b5d6a958325e4db2722cd7e664cbd22f23de Mon Sep 17 00:00:00 2001 From: Etotaziba Olei Date: Wed, 21 Feb 2024 12:56:19 +0100 Subject: [PATCH 118/698] use taxRates from policy key for IOURequestStepTaxRatePage --- src/pages/iou/request/step/IOURequestStepTaxRatePage.js | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/pages/iou/request/step/IOURequestStepTaxRatePage.js b/src/pages/iou/request/step/IOURequestStepTaxRatePage.js index 79429d57cfe1..c9f4b0cab940 100644 --- a/src/pages/iou/request/step/IOURequestStepTaxRatePage.js +++ b/src/pages/iou/request/step/IOURequestStepTaxRatePage.js @@ -35,7 +35,7 @@ const propTypes = { const defaultProps = { report: {}, - policyTaxRates: {}, + policy: {}, transaction: {}, }; @@ -48,12 +48,14 @@ function IOURequestStepTaxRatePage({ route: { params: {backTo}, }, - policyTaxRates, + policy, transaction, report, }) { const {translate} = useLocalize(); + const policyTaxRates = lodashGet(policy, 'taxRates', {}); + const navigateBack = () => { Navigation.goBack(backTo); }; From 3d18ec40de77f13cb49b88c437755c453b1cafb2 Mon Sep 17 00:00:00 2001 From: Etotaziba Olei Date: Wed, 21 Feb 2024 12:57:30 +0100 Subject: [PATCH 119/698] remove taxRates props for IOURequestStepTaxRatePage --- src/pages/iou/request/step/IOURequestStepTaxRatePage.js | 5 ----- 1 file changed, 5 deletions(-) diff --git a/src/pages/iou/request/step/IOURequestStepTaxRatePage.js b/src/pages/iou/request/step/IOURequestStepTaxRatePage.js index c9f4b0cab940..502b9e223059 100644 --- a/src/pages/iou/request/step/IOURequestStepTaxRatePage.js +++ b/src/pages/iou/request/step/IOURequestStepTaxRatePage.js @@ -2,7 +2,6 @@ import React from 'react'; import {withOnyx} from 'react-native-onyx'; import _ from 'underscore'; import TaxPicker from '@components/TaxPicker'; -import taxPropTypes from '@components/taxPropTypes'; import transactionPropTypes from '@components/transactionPropTypes'; import useLocalize from '@hooks/useLocalize'; import compose from '@libs/compose'; @@ -22,10 +21,6 @@ const propTypes = { /** Navigation route context info provided by react navigation */ route: IOURequestStepRoutePropTypes.isRequired, - /* Onyx Props */ - /** Collection of tax rates attached to a policy */ - policyTaxRates: taxPropTypes, - /** The transaction object being modified in Onyx */ transaction: transactionPropTypes, From 3c8c714bb470721a4688a383f56bcdfdf0c74dc2 Mon Sep 17 00:00:00 2001 From: Etotaziba Olei Date: Wed, 21 Feb 2024 12:58:53 +0100 Subject: [PATCH 120/698] add policy props types for IOURequestStepTaxRatePage --- src/pages/iou/request/step/IOURequestStepTaxRatePage.js | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/src/pages/iou/request/step/IOURequestStepTaxRatePage.js b/src/pages/iou/request/step/IOURequestStepTaxRatePage.js index 502b9e223059..c56d0e860f33 100644 --- a/src/pages/iou/request/step/IOURequestStepTaxRatePage.js +++ b/src/pages/iou/request/step/IOURequestStepTaxRatePage.js @@ -1,3 +1,4 @@ +import lodashGet from 'lodash/get'; import React from 'react'; import {withOnyx} from 'react-native-onyx'; import _ from 'underscore'; @@ -26,6 +27,12 @@ const propTypes = { /** The report attached to the transaction */ report: reportPropTypes, + + /** The policy of the report */ + policy: PropTypes.shape({ + /** Collection of tax rates attached to a policy */ + taxRates: taxPropTypes, + }), }; const defaultProps = { From 1df6ec5ccfdee83b0b98a7b95beb9304d6d27a2c Mon Sep 17 00:00:00 2001 From: Etotaziba Olei Date: Wed, 21 Feb 2024 13:00:17 +0100 Subject: [PATCH 121/698] remove policyTaxRates onyx keys for IOURequestStepTaxRatePage --- src/pages/iou/request/step/IOURequestStepTaxRatePage.js | 3 --- 1 file changed, 3 deletions(-) diff --git a/src/pages/iou/request/step/IOURequestStepTaxRatePage.js b/src/pages/iou/request/step/IOURequestStepTaxRatePage.js index c56d0e860f33..e8bf5915e648 100644 --- a/src/pages/iou/request/step/IOURequestStepTaxRatePage.js +++ b/src/pages/iou/request/step/IOURequestStepTaxRatePage.js @@ -97,9 +97,6 @@ export default compose( withWritableReportOrNotFound, withFullTransactionOrNotFound, withOnyx({ - policyTaxRates: { - key: ({report}) => `${ONYXKEYS.COLLECTION.POLICY_TAX_RATE}${report ? report.policyID : '0'}`, - }, policy: { key: ({report}) => `${ONYXKEYS.COLLECTION.POLICY}${report ? report.policyID : '0'}`, }, From 30ddf52f4df7212723c8a4bea5e03f6496688331 Mon Sep 17 00:00:00 2001 From: Etotaziba Olei Date: Wed, 21 Feb 2024 13:21:42 +0100 Subject: [PATCH 122/698] add missing proptypes for IOURequestStepTaxRatePage --- src/pages/iou/request/step/IOURequestStepTaxRatePage.js | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/pages/iou/request/step/IOURequestStepTaxRatePage.js b/src/pages/iou/request/step/IOURequestStepTaxRatePage.js index e8bf5915e648..694c76e87d99 100644 --- a/src/pages/iou/request/step/IOURequestStepTaxRatePage.js +++ b/src/pages/iou/request/step/IOURequestStepTaxRatePage.js @@ -1,8 +1,10 @@ import lodashGet from 'lodash/get'; +import PropTypes from 'prop-types'; import React from 'react'; import {withOnyx} from 'react-native-onyx'; import _ from 'underscore'; import TaxPicker from '@components/TaxPicker'; +import taxPropTypes from '@components/taxPropTypes'; import transactionPropTypes from '@components/transactionPropTypes'; import useLocalize from '@hooks/useLocalize'; import compose from '@libs/compose'; From aa0832653f4355e113fe6b28df2f95f6f1e0a0a3 Mon Sep 17 00:00:00 2001 From: Etotaziba Olei Date: Wed, 21 Feb 2024 14:04:30 +0100 Subject: [PATCH 123/698] remove tax rates types and keys --- src/ONYXKEYS.ts | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/ONYXKEYS.ts b/src/ONYXKEYS.ts index 2e0ea7a6c9f9..d39d9a6020be 100755 --- a/src/ONYXKEYS.ts +++ b/src/ONYXKEYS.ts @@ -279,7 +279,6 @@ const ONYXKEYS = { POLICY_CATEGORIES: 'policyCategories_', POLICY_RECENTLY_USED_CATEGORIES: 'policyRecentlyUsedCategories_', POLICY_TAGS: 'policyTags_', - POLICY_TAX_RATE: 'policyTaxRates_', POLICY_RECENTLY_USED_TAGS: 'policyRecentlyUsedTags_', POLICY_REPORT_FIELDS: 'policyReportFields_', WORKSPACE_INVITE_MEMBERS_DRAFT: 'workspaceInviteMembersDraft_', @@ -469,7 +468,6 @@ type OnyxCollectionValuesMapping = { [ONYXKEYS.COLLECTION.SELECTED_TAB]: string; [ONYXKEYS.COLLECTION.PRIVATE_NOTES_DRAFT]: string; [ONYXKEYS.COLLECTION.NEXT_STEP]: OnyxTypes.ReportNextStep; - [ONYXKEYS.COLLECTION.POLICY_TAX_RATE]: OnyxTypes.PolicyTaxRates; }; type OnyxValuesMapping = { From be1c293edaac9be71e5066c6bf193971ee11f234 Mon Sep 17 00:00:00 2001 From: Etotaziba Olei Date: Wed, 21 Feb 2024 14:14:07 +0100 Subject: [PATCH 124/698] use BaseTextInputRef for text input ref --- src/pages/EditRequestTaxAmountPage.tsx | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/src/pages/EditRequestTaxAmountPage.tsx b/src/pages/EditRequestTaxAmountPage.tsx index 437e84df652c..22ce8a4de2df 100644 --- a/src/pages/EditRequestTaxAmountPage.tsx +++ b/src/pages/EditRequestTaxAmountPage.tsx @@ -1,10 +1,10 @@ import {useFocusEffect} from '@react-navigation/native'; import React, {useCallback, useRef} from 'react'; -import type {TextInput} from 'react-native'; import HeaderWithBackButton from '@components/HeaderWithBackButton'; import ScreenWrapper from '@components/ScreenWrapper'; import useLocalize from '@hooks/useLocalize'; import * as DeviceCapabilities from '@libs/DeviceCapabilities'; +import type {BaseTextInputRef} from '@src/components/TextInput/BaseTextInput/types'; import CONST from '@src/CONST'; import MoneyRequestAmountForm from './iou/steps/MoneyRequestAmountForm'; @@ -27,7 +27,7 @@ type EditRequestTaxAmountPageProps = { function EditRequestTaxAmountPage({defaultAmount, defaultTaxAmount, defaultCurrency, onNavigateToCurrency, onSubmit}: EditRequestTaxAmountPageProps) { const {translate} = useLocalize(); - const textInput = useRef(null); + const textInput = useRef(null); const focusTimeoutRef = useRef(null); @@ -52,7 +52,6 @@ function EditRequestTaxAmountPage({defaultAmount, defaultTaxAmount, defaultCurre > Date: Thu, 22 Feb 2024 10:14:00 +0100 Subject: [PATCH 125/698] feat: create a separate route for refactor --- src/ROUTES.ts | 1 + src/SCREENS.ts | 1 + .../AppNavigator/ModalStackNavigators.tsx | 1 + src/libs/Navigation/linkingConfig/config.ts | 4 ++ .../AddPersonalBankAccountPageRefactor.tsx | 49 +++++++++++++++++++ 5 files changed, 56 insertions(+) create mode 100644 src/pages/AddPersonalBankAccountPageRefactor.tsx diff --git a/src/ROUTES.ts b/src/ROUTES.ts index c41ef521661c..024a7d1e7d57 100644 --- a/src/ROUTES.ts +++ b/src/ROUTES.ts @@ -109,6 +109,7 @@ const ROUTES = { }, SETTINGS_ADD_DEBIT_CARD: 'settings/wallet/add-debit-card', SETTINGS_ADD_BANK_ACCOUNT: 'settings/wallet/add-bank-account', + SETTINGS_ADD_BANK_ACCOUNT_REFACTOR: 'settings/wallet/add-bank-account-refactor', SETTINGS_ENABLE_PAYMENTS: 'settings/wallet/enable-payments', SETTINGS_WALLET_CARD_DIGITAL_DETAILS_UPDATE_ADDRESS: { route: 'settings/wallet/card/:domain/digital-details/update-address', diff --git a/src/SCREENS.ts b/src/SCREENS.ts index 18754a3513c1..79c2ecacfa3b 100644 --- a/src/SCREENS.ts +++ b/src/SCREENS.ts @@ -31,6 +31,7 @@ const SCREENS = { APP_DOWNLOAD_LINKS: 'Settings_App_Download_Links', ADD_DEBIT_CARD: 'Settings_Add_Debit_Card', ADD_BANK_ACCOUNT: 'Settings_Add_Bank_Account', + ADD_BANK_ACCOUNT_REFACTOR: 'Settings_Add_Bank_Account_Refactor', CLOSE: 'Settings_Close', TWO_FACTOR_AUTH: 'Settings_TwoFactorAuth', REPORT_CARD_LOST_OR_DAMAGED: 'Settings_ReportCardLostOrDamaged', diff --git a/src/libs/Navigation/AppNavigator/ModalStackNavigators.tsx b/src/libs/Navigation/AppNavigator/ModalStackNavigators.tsx index 3af123a74910..fcf215644833 100644 --- a/src/libs/Navigation/AppNavigator/ModalStackNavigators.tsx +++ b/src/libs/Navigation/AppNavigator/ModalStackNavigators.tsx @@ -236,6 +236,7 @@ const SettingsModalStackNavigator = createModalStackNavigator require('../../../pages/EnablePayments/EnablePaymentsPage').default as React.ComponentType, [SCREENS.SETTINGS.ADD_DEBIT_CARD]: () => require('../../../pages/settings/Wallet/AddDebitCardPage').default as React.ComponentType, [SCREENS.SETTINGS.ADD_BANK_ACCOUNT]: () => require('../../../pages/AddPersonalBankAccountPage').default as React.ComponentType, + [SCREENS.SETTINGS.ADD_BANK_ACCOUNT_REFACTOR]: () => require('../../../pages/AddPersonalBankAccountPageRefactor').default as React.ComponentType, [SCREENS.SETTINGS.PROFILE.STATUS]: () => require('../../../pages/settings/Profile/CustomStatus/StatusPage').default as React.ComponentType, [SCREENS.SETTINGS.PROFILE.STATUS_CLEAR_AFTER]: () => require('../../../pages/settings/Profile/CustomStatus/StatusClearAfterPage').default as React.ComponentType, [SCREENS.SETTINGS.PROFILE.STATUS_CLEAR_AFTER_DATE]: () => require('../../../pages/settings/Profile/CustomStatus/SetDatePage').default as React.ComponentType, diff --git a/src/libs/Navigation/linkingConfig/config.ts b/src/libs/Navigation/linkingConfig/config.ts index 2640025efa09..a2734b0d661f 100644 --- a/src/libs/Navigation/linkingConfig/config.ts +++ b/src/libs/Navigation/linkingConfig/config.ts @@ -156,6 +156,10 @@ const config: LinkingOptions['config'] = { path: ROUTES.SETTINGS_ADD_BANK_ACCOUNT, exact: true, }, + [SCREENS.SETTINGS.ADD_BANK_ACCOUNT_REFACTOR]: { + path: ROUTES.SETTINGS_ADD_BANK_ACCOUNT_REFACTOR, + exact: true, + }, [SCREENS.SETTINGS.PROFILE.PRONOUNS]: { path: ROUTES.SETTINGS_PRONOUNS, exact: true, diff --git a/src/pages/AddPersonalBankAccountPageRefactor.tsx b/src/pages/AddPersonalBankAccountPageRefactor.tsx new file mode 100644 index 000000000000..d643d727a309 --- /dev/null +++ b/src/pages/AddPersonalBankAccountPageRefactor.tsx @@ -0,0 +1,49 @@ +import React, {useEffect} from 'react'; +import {withOnyx} from 'react-native-onyx'; +import type {OnyxEntry} from 'react-native-onyx'; +import ScreenWrapper from '@components/ScreenWrapper'; +import useLocalize from '@hooks/useLocalize'; +import useThemeStyles from '@hooks/useThemeStyles'; +import * as BankAccounts from '@userActions/BankAccounts'; +import ONYXKEYS from '@src/ONYXKEYS'; +import type {PersonalBankAccount, PlaidData} from '@src/types/onyx'; +import BankAccountStep from "@pages/ReimbursementAccount/BankAccountStep"; + +type AddPersonalBankAccountPageWithOnyxProps = { + /** Contains plaid data */ + plaidData: OnyxEntry; + + /** The details about the Personal bank account we are adding saved in Onyx */ + personalBankAccount: OnyxEntry; +}; + +function AddPersonalBankAccountPageRefactor({personalBankAccount, plaidData}: AddPersonalBankAccountPageWithOnyxProps) { + const styles = useThemeStyles(); + const {translate} = useLocalize(); + const shouldShowSuccess = personalBankAccount?.shouldShowSuccess ?? false; + + + useEffect(() => BankAccounts.clearPersonalBankAccount, []); + + return ( + + + + ); +} + +AddPersonalBankAccountPageRefactor.displayName = 'AddPersonalBankAccountPage'; + +export default withOnyx({ + personalBankAccount: { + key: ONYXKEYS.PERSONAL_BANK_ACCOUNT, + }, + plaidData: { + key: ONYXKEYS.PLAID_DATA, + }, +})(AddPersonalBankAccountPageRefactor); From 8266baf751bead44d3b56610225c99a0d06cce80 Mon Sep 17 00:00:00 2001 From: Etotaziba Olei Date: Thu, 22 Feb 2024 12:43:38 +0100 Subject: [PATCH 126/698] update Tax picker prop Types --- src/components/TaxPicker/taxPickerPropTypes.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/components/TaxPicker/taxPickerPropTypes.js b/src/components/TaxPicker/taxPickerPropTypes.js index 35d1866ff5d1..476bd9f8eaf4 100644 --- a/src/components/TaxPicker/taxPickerPropTypes.js +++ b/src/components/TaxPicker/taxPickerPropTypes.js @@ -18,12 +18,12 @@ const propTypes = { * Safe area insets required for reflecting the portion of the view, * that is not covered by navigation bars, tab bars, toolbars, and other ancestor views. */ - insets: safeAreaInsetPropTypes.isRequired, + insets?: safeAreaInsetPropTypes.isRequired, }; const defaultProps = { selectedTaxRate: '', - policyTaxRates: {}, + policy: {}, }; export {propTypes, defaultProps}; From 7abbcb9eac173c1328a3dd36fc020baee38258f9 Mon Sep 17 00:00:00 2001 From: Etotaziba Olei Date: Thu, 22 Feb 2024 12:48:45 +0100 Subject: [PATCH 127/698] remove unexoected token --- src/components/TaxPicker/taxPickerPropTypes.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/components/TaxPicker/taxPickerPropTypes.js b/src/components/TaxPicker/taxPickerPropTypes.js index 476bd9f8eaf4..e0c15a058c0f 100644 --- a/src/components/TaxPicker/taxPickerPropTypes.js +++ b/src/components/TaxPicker/taxPickerPropTypes.js @@ -18,7 +18,7 @@ const propTypes = { * Safe area insets required for reflecting the portion of the view, * that is not covered by navigation bars, tab bars, toolbars, and other ancestor views. */ - insets?: safeAreaInsetPropTypes.isRequired, + insets: safeAreaInsetPropTypes, }; const defaultProps = { From 78f82327a02f35552706769b24761431ddd74fea Mon Sep 17 00:00:00 2001 From: Etotaziba Olei Date: Thu, 22 Feb 2024 12:54:29 +0100 Subject: [PATCH 128/698] update tax rates var --- src/pages/EditRequestPage.js | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/src/pages/EditRequestPage.js b/src/pages/EditRequestPage.js index ce52e4db3052..4ac9de3cb2f6 100644 --- a/src/pages/EditRequestPage.js +++ b/src/pages/EditRequestPage.js @@ -77,8 +77,8 @@ const defaultProps = { transaction: {}, }; -const getTaxAmount = (transactionAmount, transactionTaxCode, policyTaxRates) => { - const percentage = (transactionTaxCode ? policyTaxRates.taxes[transactionTaxCode].value : policyTaxRates.defaultValue) || ''; +const getTaxAmount = (transactionAmount, transactionTaxCode, taxRates) => { + const percentage = (transactionTaxCode ? taxRates.taxes[transactionTaxCode].value : taxRates.defaultValue) || ''; return CurrencyUtils.convertToBackendAmount(Number.parseFloat(TransactionUtils.calculateTaxAmount(percentage, transactionAmount))); }; @@ -102,9 +102,9 @@ function EditRequestPage({report, route, policy, policyCategories, policyTags, p const policyTagListName = PolicyUtils.getTagListName(policyTags, tagIndex); const policyTagLists = useMemo(() => PolicyUtils.getTagLists(policyTags), [policyTags]); - const policyTaxRates = lodashGet(policy, 'taxRates', {}); + const taxRates = lodashGet(policy, 'taxRates', {}); - const taxRateTitle = TransactionUtils.getTaxName(policyTaxRates.taxes, transactionTaxCode); + const taxRateTitle = TransactionUtils.getTaxName(taxRates.taxes, transactionTaxCode); // A flag for verifying that the current report is a sub-report of a workspace chat const isPolicyExpenseChat = ReportUtils.isGroupPolicy(report); @@ -230,7 +230,7 @@ function EditRequestPage({report, route, policy, policyCategories, policyTags, p return ( { const activeRoute = encodeURIComponent(Navigation.getActiveRouteWithoutParams()); From 60ab450b8716499fa3b18133ebdaec143e108b5e Mon Sep 17 00:00:00 2001 From: Etotaziba Olei Date: Thu, 22 Feb 2024 12:59:10 +0100 Subject: [PATCH 129/698] update tax rate name --- src/components/ReportActionItem/MoneyRequestView.tsx | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/components/ReportActionItem/MoneyRequestView.tsx b/src/components/ReportActionItem/MoneyRequestView.tsx index dfae8702abef..2cf016556429 100644 --- a/src/components/ReportActionItem/MoneyRequestView.tsx +++ b/src/components/ReportActionItem/MoneyRequestView.tsx @@ -122,7 +122,7 @@ function MoneyRequestView({ const taxRates = policy?.taxRates; const formattedTaxAmount = transactionTaxAmount ? CurrencyUtils.convertToDisplayString(transactionTaxAmount, transactionCurrency) : ''; - const policyTaxRatesDescription = taxRates?.name; + const taxRatesDescription = taxRates?.name; const taxRateTitle = (transactionTaxCode && taxRates && TransactionUtils.getTaxName(taxRates?.taxes, transactionTaxCode)) ?? ''; // Flags for allowing or disallowing editing a money request @@ -433,7 +433,7 @@ function MoneyRequestView({ Date: Thu, 22 Feb 2024 13:01:02 +0100 Subject: [PATCH 130/698] update tax rate name --- src/pages/iou/request/step/IOURequestStepTaxAmountPage.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/pages/iou/request/step/IOURequestStepTaxAmountPage.js b/src/pages/iou/request/step/IOURequestStepTaxAmountPage.js index 1d5ea686e975..907b79f6968f 100644 --- a/src/pages/iou/request/step/IOURequestStepTaxAmountPage.js +++ b/src/pages/iou/request/step/IOURequestStepTaxAmountPage.js @@ -67,7 +67,7 @@ function IOURequestStepTaxAmountPage({ const isSaveButtonPressed = useRef(false); const originalCurrency = useRef(null); - const policyTaxRates = lodashGet(policy, 'taxRates', {}); + const taxRates = lodashGet(policy, 'taxRates', {}); useEffect(() => { if (transaction.originalCurrency) { @@ -146,7 +146,7 @@ function IOURequestStepTaxAmountPage({ isEditing={isEditing} currency={currency} amount={transaction.taxAmount} - taxAmount={getTaxAmount(transaction, policyTaxRates.defaultValue)} + taxAmount={getTaxAmount(transaction, taxRates.defaultValue)} ref={(e) => (textInput.current = e)} onCurrencyButtonPress={navigateToCurrencySelectionPage} onSubmitButtonPress={updateTaxAmount} From 1127e7c58684ce9c6d0320610b673263ef4f7111 Mon Sep 17 00:00:00 2001 From: Etotaziba Olei Date: Thu, 22 Feb 2024 13:01:52 +0100 Subject: [PATCH 131/698] update tax rate name --- src/pages/iou/request/step/IOURequestStepTaxRatePage.js | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/pages/iou/request/step/IOURequestStepTaxRatePage.js b/src/pages/iou/request/step/IOURequestStepTaxRatePage.js index 694c76e87d99..241f5cccdc17 100644 --- a/src/pages/iou/request/step/IOURequestStepTaxRatePage.js +++ b/src/pages/iou/request/step/IOURequestStepTaxRatePage.js @@ -58,16 +58,16 @@ function IOURequestStepTaxRatePage({ }) { const {translate} = useLocalize(); - const policyTaxRates = lodashGet(policy, 'taxRates', {}); + const taxRates = lodashGet(policy, 'taxRates', {}); const navigateBack = () => { Navigation.goBack(backTo); }; - const selectedTaxRate = TransactionUtils.getDefaultTaxName(policyTaxRates, transaction); + const selectedTaxRate = TransactionUtils.getDefaultTaxName(taxRates, transaction); const updateTaxRates = (taxes) => { - const taxAmount = getTaxAmount(policyTaxRates, taxes.text, transaction.amount); + const taxAmount = getTaxAmount(taxRates, taxes.text, transaction.amount); const amountInSmallestCurrencyUnits = CurrencyUtils.convertToBackendAmount(Number.parseFloat(taxAmount)); IOU.setMoneyRequestTaxRate(transaction.transactionID, taxes); IOU.setMoneyRequestTaxAmount(transaction.transactionID, amountInSmallestCurrencyUnits); From 6c40f80a113ffb75682dcd2304d88b0dc61815bc Mon Sep 17 00:00:00 2001 From: Abdelrahman Khattab Date: Thu, 22 Feb 2024 14:03:32 +0200 Subject: [PATCH 132/698] Removing the amount from the useEffect dependencies --- src/pages/iou/steps/MoneyRequestAmountForm.tsx | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/pages/iou/steps/MoneyRequestAmountForm.tsx b/src/pages/iou/steps/MoneyRequestAmountForm.tsx index 555ada528ab7..934a758050b4 100644 --- a/src/pages/iou/steps/MoneyRequestAmountForm.tsx +++ b/src/pages/iou/steps/MoneyRequestAmountForm.tsx @@ -116,7 +116,7 @@ function MoneyRequestAmountForm( } }; - const initializeAmount = useCallback((newAmount) => { + const initializeAmount = useCallback((newAmount: number) => { const frontendAmount = CurrencyUtils.convertToFrontendAmountAsString(newAmount); setCurrentAmount(frontendAmount); setSelection({ @@ -132,7 +132,7 @@ function MoneyRequestAmountForm( initializeAmount(amount); // we want to re-initialize the state only when the selected tab or amount changes // eslint-disable-next-line react-hooks/exhaustive-deps - }, [selectedTab, amount]); + }, [selectedTab]); /** * Sets the selection and the amount accordingly to the value passed to the input From c9614cc5ee72f98a065619cdd8458b5ece33e68e Mon Sep 17 00:00:00 2001 From: Abdelrahman Khattab Date: Thu, 22 Feb 2024 14:06:45 +0200 Subject: [PATCH 133/698] minor change --- src/pages/iou/steps/MoneyRequestAmountForm.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/pages/iou/steps/MoneyRequestAmountForm.tsx b/src/pages/iou/steps/MoneyRequestAmountForm.tsx index 934a758050b4..ed4bb4e5deec 100644 --- a/src/pages/iou/steps/MoneyRequestAmountForm.tsx +++ b/src/pages/iou/steps/MoneyRequestAmountForm.tsx @@ -130,7 +130,7 @@ function MoneyRequestAmountForm( return; } initializeAmount(amount); - // we want to re-initialize the state only when the selected tab or amount changes + // we want to re-initialize the state only when the selected tab // eslint-disable-next-line react-hooks/exhaustive-deps }, [selectedTab]); From e7be70e76caa5d6b0be91a2218bd6977540ba669 Mon Sep 17 00:00:00 2001 From: Etotaziba Olei Date: Thu, 22 Feb 2024 13:33:50 +0100 Subject: [PATCH 134/698] add taxRates types to Policy --- src/types/onyx/Policy.ts | 38 +++++++++++++++++++++++++++++++++++++- 1 file changed, 37 insertions(+), 1 deletion(-) diff --git a/src/types/onyx/Policy.ts b/src/types/onyx/Policy.ts index f85d4e0cba05..31b2d1ac4b53 100644 --- a/src/types/onyx/Policy.ts +++ b/src/types/onyx/Policy.ts @@ -35,6 +35,42 @@ type DisabledFields = { reimbursable?: boolean; }; +type TaxRate = { + /** Name of the a tax rate. */ + name: string; + + /** The value of the tax rate. */ + value: string; + + /** The code associated with the tax rate. */ + code: string; + + /** This contains the tax name and tax value as one name */ + modifiedName: string; + + /** Indicates if the tax rate is disabled. */ + isDisabled?: boolean; +}; + +type TaxRates = Record; + +type TaxRatesWithDefault = { + /** Name of the tax */ + name: string; + + /** Default policy tax ID */ + defaultExternalID: string; + + /** Default value of taxes */ + defaultValue: string; + + /** Default foreign policy tax ID */ + foreignTaxDefault: string; + + /** List of tax names and values */ + taxes: TaxRates; +}; + // These types are for the Integration connections for a policy (eg. Quickbooks, Xero, etc). // This data is not yet used in the codebase which is why it is given a very generic type, but the data is being put into Onyx for future use. // Once the data is being used, these types should be defined appropriately. @@ -190,4 +226,4 @@ type Policy = { export default Policy; -export type {Unit, CustomUnit, Attributes, Rate}; +export type {Unit, CustomUnit, Attributes, Rate, TaxRate, TaxRates, TaxRatesWithDefault}; From 76cd4d0787575cecfffbf0be39af9ddd41a52c7c Mon Sep 17 00:00:00 2001 From: Etotaziba Olei Date: Thu, 22 Feb 2024 13:35:01 +0100 Subject: [PATCH 135/698] export policy tax rates types from onyx types --- src/types/onyx/index.ts | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/types/onyx/index.ts b/src/types/onyx/index.ts index 59cabbe020ee..9c59a89e4040 100644 --- a/src/types/onyx/index.ts +++ b/src/types/onyx/index.ts @@ -30,12 +30,12 @@ import type {PersonalDetailsList} from './PersonalDetails'; import type PersonalDetails from './PersonalDetails'; import type PlaidData from './PlaidData'; import type Policy from './Policy'; +import type {TaxRate, TaxRates, TaxRatesWithDefault} from './Policy'; import type {PolicyCategories, PolicyCategory} from './PolicyCategory'; import type {PolicyMembers} from './PolicyMember'; import type PolicyMember from './PolicyMember'; import type {PolicyReportField, PolicyReportFields} from './PolicyReportField'; import type {PolicyTag, PolicyTagList, PolicyTags} from './PolicyTag'; -import type {PolicyTaxRates, TaxRate, TaxRates} from './PolicyTaxRates'; import type PrivatePersonalDetails from './PrivatePersonalDetails'; import type RecentlyUsedCategories from './RecentlyUsedCategories'; import type RecentlyUsedReportFields from './RecentlyUsedReportFields'; @@ -108,9 +108,6 @@ export type { PolicyMembers, PolicyTag, PolicyTags, - TaxRate, - TaxRates, - PolicyTaxRates, PolicyTagList, PrivatePersonalDetails, RecentWaypoint, @@ -131,6 +128,9 @@ export type { SecurityGroup, Session, Task, + TaxRate, + TaxRates, + TaxRatesWithDefault, Transaction, TransactionViolation, TransactionViolations, From b8315690f541d4668247ca40e6c45b082d0e716b Mon Sep 17 00:00:00 2001 From: Etotaziba Olei Date: Thu, 22 Feb 2024 13:37:48 +0100 Subject: [PATCH 136/698] @update getFiltered options for taxRates --- src/libs/OptionsListUtils.ts | 44 ++++++++++++++++++------------------ 1 file changed, 22 insertions(+), 22 deletions(-) diff --git a/src/libs/OptionsListUtils.ts b/src/libs/OptionsListUtils.ts index cdda08f8497c..051c9a4cbd0f 100644 --- a/src/libs/OptionsListUtils.ts +++ b/src/libs/OptionsListUtils.ts @@ -111,8 +111,8 @@ type GetOptionsConfig = { recentlyUsedTags?: string[]; canInviteUser?: boolean; includeSelectedOptions?: boolean; - includePolicyTaxRates?: boolean; - policyTaxRates?: PolicyTaxRates; + includeTaxRates?: boolean; + taxRates?: PolicyTaxRates; transactionViolations?: OnyxCollection; }; @@ -141,7 +141,7 @@ type GetOptions = { currentUserOption: ReportUtils.OptionData | null | undefined; categoryOptions: CategorySection[]; tagOptions: CategorySection[]; - policyTaxRatesOptions: CategorySection[]; + taxRatesOptions: CategorySection[]; }; type PreviewConfig = {showChatPreviewLine?: boolean; forcePolicyNamePreview?: boolean}; @@ -1175,13 +1175,13 @@ function hasEnabledTags(policyTagList: Array /** * Transforms tax rates to a new object format - to add codes and new name with concatenated name and value. * - * @param policyTaxRates - The original tax rates object. + * @param taxRates - The original tax rates object. * @returns The transformed tax rates object.g */ -function transformedTaxRates(policyTaxRates: PolicyTaxRates | undefined): Record { - const defaultTaxKey = policyTaxRates?.defaultExternalID; +function transformedTaxRates(taxRates: PolicyTaxRates | undefined): Record { + const defaultTaxKey = taxRates?.defaultExternalID; const getModifiedName = (data: TaxRate, code: string) => `${data.name} (${data.value})${defaultTaxKey === code ? ` • ${Localize.translateLocal('common.default')}` : ''}`; - const taxes = Object.fromEntries(Object.entries(policyTaxRates?.taxes ?? {}).map(([code, data]) => [code, {...data, code, modifiedName: getModifiedName(data, code), name: data.name}])); + const taxes = Object.fromEntries(Object.entries(taxRates?.taxes ?? {}).map(([code, data]) => [code, {...data, code, modifiedName: getModifiedName(data, code), name: data.name}])); return taxes; } @@ -1210,10 +1210,10 @@ function getTaxRatesOptions(taxRates: Array>): Option[] { /** * Builds the section list for tax rates */ -function getTaxRatesSection(policyTaxRates: PolicyTaxRates | undefined, selectedOptions: Category[], searchInputValue: string): CategorySection[] { +function getTaxRatesSection(taxRates: PolicyTaxRates | undefined, selectedOptions: Category[], searchInputValue: string): CategorySection[] { const policyRatesSections = []; - const taxes = transformedTaxRates(policyTaxRates); + const taxes = transformedTaxRates(taxRates); const sortedTaxRates = sortTaxRates(taxes); const enabledTaxRates = sortedTaxRates.filter((taxRate) => !taxRate.isDisabled); @@ -1352,8 +1352,8 @@ function getOptions( canInviteUser = true, includeSelectedOptions = false, transactionViolations = {}, - includePolicyTaxRates, - policyTaxRates, + includeTaxRates, + taxRates, }: GetOptionsConfig, ): GetOptions { if (includeCategories) { @@ -1366,7 +1366,7 @@ function getOptions( currentUserOption: null, categoryOptions, tagOptions: [], - policyTaxRatesOptions: [], + taxRatesOptions: [], }; } @@ -1380,12 +1380,12 @@ function getOptions( currentUserOption: null, categoryOptions: [], tagOptions, - policyTaxRatesOptions: [], + taxRatesOptions: [], }; } - if (includePolicyTaxRates) { - const policyTaxRatesOptions = getTaxRatesSection(policyTaxRates, selectedOptions as Category[], searchInputValue); + if (includeTaxRates) { + const taxRatesOptions = getTaxRatesSection(taxRates, selectedOptions as Category[], searchInputValue); return { recentReports: [], @@ -1394,7 +1394,7 @@ function getOptions( currentUserOption: null, categoryOptions: [], tagOptions: [], - policyTaxRatesOptions, + taxRatesOptions, }; } @@ -1406,7 +1406,7 @@ function getOptions( currentUserOption: null, categoryOptions: [], tagOptions: [], - policyTaxRatesOptions: [], + taxRatesOptions: [], }; } @@ -1695,7 +1695,7 @@ function getOptions( currentUserOption, categoryOptions: [], tagOptions: [], - policyTaxRatesOptions: [], + taxRatesOptions: [], }; } @@ -1792,8 +1792,8 @@ function getFilteredOptions( recentlyUsedTags: string[] = [], canInviteUser = true, includeSelectedOptions = false, - includePolicyTaxRates = false, - policyTaxRates: PolicyTaxRates = {} as PolicyTaxRates, + includeTaxRates = false, + taxRates: PolicyTaxRates = {} as PolicyTaxRates, ) { return getOptions(reports, personalDetails, { betas, @@ -1813,8 +1813,8 @@ function getFilteredOptions( recentlyUsedTags, canInviteUser, includeSelectedOptions, - includePolicyTaxRates, - policyTaxRates, + includeTaxRates, + taxRates, }); } From 45ea252ef358198ebed4bdb5b16bb8f0b45a4e15 Mon Sep 17 00:00:00 2001 From: Etotaziba Olei Date: Thu, 22 Feb 2024 13:41:10 +0100 Subject: [PATCH 137/698] destructure taxRatesOptions from options utils --- src/components/TaxPicker/index.js | 23 ++--------------------- 1 file changed, 2 insertions(+), 21 deletions(-) diff --git a/src/components/TaxPicker/index.js b/src/components/TaxPicker/index.js index b83d75f314aa..1e01b0adca93 100644 --- a/src/components/TaxPicker/index.js +++ b/src/components/TaxPicker/index.js @@ -39,27 +39,8 @@ function TaxPicker({selectedTaxRate, policy, insets, onSubmit}) { }, [selectedTaxRate]); const sections = useMemo(() => { - const {policyTaxRatesOptions} = OptionsListUtils.getFilteredOptions( - {}, - {}, - [], - searchValue, - selectedOptions, - [], - false, - false, - false, - {}, - [], - false, - {}, - [], - false, - false, - true, - taxRates, - ); - return policyTaxRatesOptions; + const {taxRatesOptions} = OptionsListUtils.getFilteredOptions({}, {}, [], searchValue, selectedOptions, [], false, false, false, {}, [], false, {}, [], false, false, true, taxRates); + return taxRatesOptions; }, [taxRates, searchValue, selectedOptions]); const selectedOptionKey = lodashGet(_.filter(lodashGet(sections, '[0].data', []), (taxRate) => taxRate.searchText === selectedTaxRate)[0], 'keyForList'); From b3f55a88608c213f90c921591dd358634444dded Mon Sep 17 00:00:00 2001 From: Etotaziba Olei Date: Thu, 22 Feb 2024 13:50:16 +0100 Subject: [PATCH 138/698] update OptionsListUtils tax rate types --- src/libs/OptionsListUtils.ts | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/src/libs/OptionsListUtils.ts b/src/libs/OptionsListUtils.ts index 051c9a4cbd0f..22e1176293fd 100644 --- a/src/libs/OptionsListUtils.ts +++ b/src/libs/OptionsListUtils.ts @@ -22,12 +22,14 @@ import type { Report, ReportAction, ReportActions, + TaxRate, + TaxRates, + TaxRatesWithDefault, Transaction, TransactionViolation, } from '@src/types/onyx'; import type {Participant} from '@src/types/onyx/IOU'; import type * as OnyxCommon from '@src/types/onyx/OnyxCommon'; -import type {PolicyTaxRates, TaxRate, TaxRates} from '@src/types/onyx/PolicyTaxRates'; import type DeepValueOf from '@src/types/utils/DeepValueOf'; import {isEmptyObject} from '@src/types/utils/EmptyObject'; import times from '@src/utils/times'; @@ -112,7 +114,7 @@ type GetOptionsConfig = { canInviteUser?: boolean; includeSelectedOptions?: boolean; includeTaxRates?: boolean; - taxRates?: PolicyTaxRates; + taxRates?: TaxRatesWithDefault; transactionViolations?: OnyxCollection; }; @@ -1178,7 +1180,7 @@ function hasEnabledTags(policyTagList: Array * @param taxRates - The original tax rates object. * @returns The transformed tax rates object.g */ -function transformedTaxRates(taxRates: PolicyTaxRates | undefined): Record { +function transformedTaxRates(taxRates: TaxRatesWithDefault | undefined): Record { const defaultTaxKey = taxRates?.defaultExternalID; const getModifiedName = (data: TaxRate, code: string) => `${data.name} (${data.value})${defaultTaxKey === code ? ` • ${Localize.translateLocal('common.default')}` : ''}`; const taxes = Object.fromEntries(Object.entries(taxRates?.taxes ?? {}).map(([code, data]) => [code, {...data, code, modifiedName: getModifiedName(data, code), name: data.name}])); @@ -1210,7 +1212,7 @@ function getTaxRatesOptions(taxRates: Array>): Option[] { /** * Builds the section list for tax rates */ -function getTaxRatesSection(taxRates: PolicyTaxRates | undefined, selectedOptions: Category[], searchInputValue: string): CategorySection[] { +function getTaxRatesSection(taxRates: TaxRatesWithDefault | undefined, selectedOptions: Category[], searchInputValue: string): CategorySection[] { const policyRatesSections = []; const taxes = transformedTaxRates(taxRates); @@ -1793,7 +1795,7 @@ function getFilteredOptions( canInviteUser = true, includeSelectedOptions = false, includeTaxRates = false, - taxRates: PolicyTaxRates = {} as PolicyTaxRates, + taxRates: TaxRatesWithDefault = {} as TaxRatesWithDefault, ) { return getOptions(reports, personalDetails, { betas, From 09364ce2ad7c7cf7ad64063311b8458cc8e65218 Mon Sep 17 00:00:00 2001 From: Etotaziba Olei Date: Thu, 22 Feb 2024 13:52:44 +0100 Subject: [PATCH 139/698] update TransactionUtils tax rate types --- src/libs/TransactionUtils.ts | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/src/libs/TransactionUtils.ts b/src/libs/TransactionUtils.ts index 0291d5e77a8d..484acf62cf0e 100644 --- a/src/libs/TransactionUtils.ts +++ b/src/libs/TransactionUtils.ts @@ -4,8 +4,7 @@ import Onyx from 'react-native-onyx'; import type {ValueOf} from 'type-fest'; import CONST from '@src/CONST'; import ONYXKEYS from '@src/ONYXKEYS'; -import type {RecentWaypoint, Report, ReportAction, Transaction, TransactionViolation} from '@src/types/onyx'; -import type {PolicyTaxRates, TaxRate, TaxRates} from '@src/types/onyx/PolicyTaxRates'; +import type {RecentWaypoint, Report, ReportAction, TaxRate, TaxRates, TaxRatesWithDefault, Transaction, TransactionViolation} from '@src/types/onyx'; import type {Comment, Receipt, TransactionChanges, TransactionPendingFieldsKey, Waypoint, WaypointCollection} from '@src/types/onyx/Transaction'; import type {EmptyObject} from '@src/types/utils/EmptyObject'; import {isEmptyObject} from '@src/types/utils/EmptyObject'; @@ -622,7 +621,7 @@ function getEnabledTaxRateCount(options: TaxRates) { /** * Gets the default tax name */ -function getDefaultTaxName(policyTaxRates: PolicyTaxRates, transaction: Transaction) { +function getDefaultTaxName(policyTaxRates: TaxRatesWithDefault, transaction: Transaction) { const defaultTaxKey = policyTaxRates.defaultExternalID; const defaultTaxName = (defaultTaxKey && `${policyTaxRates.taxes[defaultTaxKey].name} (${policyTaxRates.taxes[defaultTaxKey].value}) • ${Localize.translateLocal('common.default')}`) || ''; From 5f123ff141789f82584ba2bae66577a404e8d762 Mon Sep 17 00:00:00 2001 From: Etotaziba Olei Date: Thu, 22 Feb 2024 13:59:54 +0100 Subject: [PATCH 140/698] update getDefaultTaxName parameter name --- src/libs/TransactionUtils.ts | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/src/libs/TransactionUtils.ts b/src/libs/TransactionUtils.ts index 484acf62cf0e..250c5650cd6d 100644 --- a/src/libs/TransactionUtils.ts +++ b/src/libs/TransactionUtils.ts @@ -621,10 +621,9 @@ function getEnabledTaxRateCount(options: TaxRates) { /** * Gets the default tax name */ -function getDefaultTaxName(policyTaxRates: TaxRatesWithDefault, transaction: Transaction) { - const defaultTaxKey = policyTaxRates.defaultExternalID; - const defaultTaxName = - (defaultTaxKey && `${policyTaxRates.taxes[defaultTaxKey].name} (${policyTaxRates.taxes[defaultTaxKey].value}) • ${Localize.translateLocal('common.default')}`) || ''; +function getDefaultTaxName(taxRates: TaxRatesWithDefault, transaction: Transaction) { + const defaultTaxKey = taxRates.defaultExternalID; + const defaultTaxName = (defaultTaxKey && `${taxRates.taxes[defaultTaxKey].name} (${taxRates.taxes[defaultTaxKey].value}) • ${Localize.translateLocal('common.default')}`) || ''; return transaction?.taxRate?.text ?? defaultTaxName; } From 071ff8b5145465c5fbc114bc58c68c96200bfdee Mon Sep 17 00:00:00 2001 From: Etotaziba Olei Date: Thu, 22 Feb 2024 14:01:43 +0100 Subject: [PATCH 141/698] update taxRates in policy types --- src/types/onyx/Policy.ts | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/types/onyx/Policy.ts b/src/types/onyx/Policy.ts index 31b2d1ac4b53..7db309194452 100644 --- a/src/types/onyx/Policy.ts +++ b/src/types/onyx/Policy.ts @@ -1,7 +1,6 @@ import type {ValueOf} from 'type-fest'; import type CONST from '@src/CONST'; import type * as OnyxCommon from './OnyxCommon'; -import type {PolicyTaxRates} from './PolicyTaxRates'; type Unit = 'mi' | 'km'; @@ -212,7 +211,7 @@ type Policy = { }; /** Collection of tax rates attached to a policy */ - taxRates?: PolicyTaxRates; + taxRates?: TaxRatesWithDefault; /** ReportID of the admins room for this workspace */ chatReportIDAdmins?: number; From 84c51b06a74820a9e41deb8d8ed3d1acae0ba26a Mon Sep 17 00:00:00 2001 From: Etotaziba Olei Date: Thu, 22 Feb 2024 14:07:30 +0100 Subject: [PATCH 142/698] update taxRates name in OptionListUtilsTest --- tests/unit/OptionsListUtilsTest.js | 33 +++++++----------------------- 1 file changed, 7 insertions(+), 26 deletions(-) diff --git a/tests/unit/OptionsListUtilsTest.js b/tests/unit/OptionsListUtilsTest.js index 00f1307ab59f..7244b7830a29 100644 --- a/tests/unit/OptionsListUtilsTest.js +++ b/tests/unit/OptionsListUtilsTest.js @@ -2063,7 +2063,7 @@ describe('OptionsListUtils', () => { const emptySearch = ''; const wrongSearch = 'bla bla'; - const policyTaxRatesWithDefault = { + const taxRatesWithDefault = { name: 'Tax', defaultExternalID: 'CODE1', defaultValue: '0%', @@ -2170,34 +2170,15 @@ describe('OptionsListUtils', () => { }, ]; - const result = OptionsListUtils.getFilteredOptions({}, {}, [], emptySearch, [], [], false, false, false, {}, [], false, {}, [], false, false, true, policyTaxRatesWithDefault); + const result = OptionsListUtils.getFilteredOptions({}, {}, [], emptySearch, [], [], false, false, false, {}, [], false, {}, [], false, false, true, taxRatesWithDefault); - expect(result.policyTaxRatesOptions).toStrictEqual(resultList); + expect(result.taxRatesOptions).toStrictEqual(resultList); - const searchResult = OptionsListUtils.getFilteredOptions({}, {}, [], search, [], [], false, false, false, {}, [], false, {}, [], false, false, true, policyTaxRatesWithDefault); - expect(searchResult.policyTaxRatesOptions).toStrictEqual(searchResultList); + const searchResult = OptionsListUtils.getFilteredOptions({}, {}, [], search, [], [], false, false, false, {}, [], false, {}, [], false, false, true, taxRatesWithDefault); + expect(searchResult.taxRatesOptions).toStrictEqual(searchResultList); - const wrongSearchResult = OptionsListUtils.getFilteredOptions( - {}, - {}, - [], - wrongSearch, - [], - [], - false, - false, - false, - {}, - [], - false, - {}, - [], - false, - false, - true, - policyTaxRatesWithDefault, - ); - expect(wrongSearchResult.policyTaxRatesOptions).toStrictEqual(wrongSearchResultList); + const wrongSearchResult = OptionsListUtils.getFilteredOptions({}, {}, [], wrongSearch, [], [], false, false, false, {}, [], false, {}, [], false, false, true, taxRatesWithDefault); + expect(wrongSearchResult.taxRatesOptions).toStrictEqual(wrongSearchResultList); }); it('formatMemberForList()', () => { From f8b66da13c5fe911a46c53b17d932d83e9b4f106 Mon Sep 17 00:00:00 2001 From: Etotaziba Olei Date: Thu, 22 Feb 2024 15:19:14 +0100 Subject: [PATCH 143/698] add taxRate and oldTaxRate to ExpenseOriginalMessage --- src/libs/ReportUtils.ts | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/libs/ReportUtils.ts b/src/libs/ReportUtils.ts index a36fc095489b..db3568ef34f7 100644 --- a/src/libs/ReportUtils.ts +++ b/src/libs/ReportUtils.ts @@ -87,6 +87,8 @@ type ExpenseOriginalMessage = { oldTag?: string; billable?: string; oldBillable?: string; + taxRate?: string; + oldTaxRate?: string; }; type SpendBreakdown = { From 2527914bfadfc75030084c691b337b1e1363eea0 Mon Sep 17 00:00:00 2001 From: Etotaziba Olei Date: Thu, 22 Feb 2024 16:10:50 +0100 Subject: [PATCH 144/698] add taxRate system message --- src/libs/ModifiedExpenseMessage.ts | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/src/libs/ModifiedExpenseMessage.ts b/src/libs/ModifiedExpenseMessage.ts index 13a58834860b..e2d0741eca43 100644 --- a/src/libs/ModifiedExpenseMessage.ts +++ b/src/libs/ModifiedExpenseMessage.ts @@ -115,6 +115,7 @@ function getForReportAction(reportID: string | undefined, reportAction: OnyxEntr 'currency' in reportActionOriginalMessage; const hasModifiedMerchant = reportActionOriginalMessage && 'oldMerchant' in reportActionOriginalMessage && 'merchant' in reportActionOriginalMessage; + if (hasModifiedAmount) { const oldCurrency = reportActionOriginalMessage?.oldCurrency ?? ''; const oldAmountValue = reportActionOriginalMessage?.oldAmount ?? 0; @@ -214,6 +215,19 @@ function getForReportAction(reportID: string | undefined, reportAction: OnyxEntr }); } + const hasModifiedTaxRate = reportActionOriginalMessage && 'oldTaxRate' in reportActionOriginalMessage && 'taxRate' in reportActionOriginalMessage; + if (hasModifiedTaxRate) { + buildMessageFragmentForValue( + reportActionOriginalMessage?.taxRate ?? '', + reportActionOriginalMessage?.oldTaxRate ?? '', + Localize.translateLocal('iou.taxRate'), + true, + setFragments, + removalFragments, + changeFragments, + ); + } + const hasModifiedBillable = reportActionOriginalMessage && 'oldBillable' in reportActionOriginalMessage && 'billable' in reportActionOriginalMessage; if (hasModifiedBillable) { buildMessageFragmentForValue( From c20c2cb1dafa61bc03c78601816632d19e2f8df8 Mon Sep 17 00:00:00 2001 From: Agata Kosior Date: Fri, 23 Feb 2024 16:58:50 +0100 Subject: [PATCH 145/698] feat: UI for step 0 --- .../AddPersonalBankAccountPageRefactor.tsx | 59 ++++++++++++++++--- .../ReimbursementAccount/BankAccountStep.js | 45 +++++++------- src/styles/index.ts | 5 ++ 3 files changed, 78 insertions(+), 31 deletions(-) diff --git a/src/pages/AddPersonalBankAccountPageRefactor.tsx b/src/pages/AddPersonalBankAccountPageRefactor.tsx index d643d727a309..ef8ca468cd60 100644 --- a/src/pages/AddPersonalBankAccountPageRefactor.tsx +++ b/src/pages/AddPersonalBankAccountPageRefactor.tsx @@ -1,13 +1,21 @@ import React, {useEffect} from 'react'; +import {View} from 'react-native'; import {withOnyx} from 'react-native-onyx'; import type {OnyxEntry} from 'react-native-onyx'; +import Button from '@components/Button'; +import HeaderWithBackButton from '@components/HeaderWithBackButton'; +import * as Expensicons from '@components/Icon/Expensicons'; +import * as Illustrations from '@components/Icon/Illustrations'; +import InteractiveStepSubHeader from '@components/InteractiveStepSubHeader'; import ScreenWrapper from '@components/ScreenWrapper'; +import Section from '@components/Section'; +import Text from '@components/Text'; import useLocalize from '@hooks/useLocalize'; import useThemeStyles from '@hooks/useThemeStyles'; import * as BankAccounts from '@userActions/BankAccounts'; +import CONST from '@src/CONST'; import ONYXKEYS from '@src/ONYXKEYS'; import type {PersonalBankAccount, PlaidData} from '@src/types/onyx'; -import BankAccountStep from "@pages/ReimbursementAccount/BankAccountStep"; type AddPersonalBankAccountPageWithOnyxProps = { /** Contains plaid data */ @@ -17,22 +25,53 @@ type AddPersonalBankAccountPageWithOnyxProps = { personalBankAccount: OnyxEntry; }; -function AddPersonalBankAccountPageRefactor({personalBankAccount, plaidData}: AddPersonalBankAccountPageWithOnyxProps) { +function AddPersonalBankAccountPageRefactor({personalBankAccount, plaidData, isPlaidDisabled, user}: AddPersonalBankAccountPageWithOnyxProps) { const styles = useThemeStyles(); const {translate} = useLocalize(); - const shouldShowSuccess = personalBankAccount?.shouldShowSuccess ?? false; - - useEffect(() => BankAccounts.clearPersonalBankAccount, []); return ( - + {}} + /> + + + +
+ + {'We will use this account to pull money into your wallet and to transfer any funds in your wallet out to you'} + + {/*{Boolean(plaidDesktopMessage) && (*/} + {/* */} + {/* {props.translate(plaidDesktopMessage)}*/} + {/* */} + {/*)}*/} +
); } @@ -46,4 +85,10 @@ export default withOnyx
- {props.translate('bankAccount.toGetStarted')} + {translate('bankAccount.toGetStarted')} {Boolean(plaidDesktopMessage) && ( - {props.translate(plaidDesktopMessage)} + {translate(plaidDesktopMessage)} )}
-
+ const exitFlow = useCallback( + (shouldContinue = false) => { + const exitReportID = personalBankAccount?.exitReportID; + const onSuccessFallbackRoute = personalBankAccount?.onSuccessFallbackRoute ?? ''; + + if (exitReportID) { + Navigation.dismissModal(exitReportID); + } else if (shouldContinue && onSuccessFallbackRoute) { + PaymentMethods.continueSetup(onSuccessFallbackRoute); + } else { + Navigation.goBack(ROUTES.SETTINGS_WALLET); + } + }, + [personalBankAccount], ); + + return ; } AddPersonalBankAccountPageRefactor.displayName = 'AddPersonalBankAccountPage'; diff --git a/src/pages/EnablePayments/AddBankAccount/AddPersonalBankAccount.tsx b/src/pages/EnablePayments/AddBankAccount/AddPersonalBankAccount.tsx new file mode 100644 index 000000000000..61a8831a9b22 --- /dev/null +++ b/src/pages/EnablePayments/AddBankAccount/AddPersonalBankAccount.tsx @@ -0,0 +1,239 @@ +// import React, {useCallback, useEffect, useMemo, useState} from 'react'; +// import {View} from 'react-native'; +// import type {OnyxEntry} from 'react-native-onyx'; +// import {withOnyx} from 'react-native-onyx'; +// import AddPlaidBankAccount from '@components/AddPlaidBankAccount'; +// import FormProvider from '@components/Form/FormProvider'; +// import HeaderWithBackButton from '@components/HeaderWithBackButton'; +// import InteractiveStepSubHeader from '@components/InteractiveStepSubHeader'; +// import ScreenWrapper from '@components/ScreenWrapper'; +// import useLocalize from '@hooks/useLocalize'; +// import useSubStep from '@hooks/useSubStep'; +// import type {SubStepProps} from '@hooks/useSubStep/types'; +// import useThemeStyles from '@hooks/useThemeStyles'; +// import getPlaidOAuthReceivedRedirectURI from '@libs/getPlaidOAuthReceivedRedirectURI'; +// import Navigation from '@navigation/Navigation'; +// import ChooseMethod from '@pages/EnablePayments/AddBankAccount/substeps/ChooseMethod'; +// import getSubstepValues from '@pages/ReimbursementAccount/utils/getSubstepValues'; +// import * as BankAccounts from '@userActions/BankAccounts'; +// import * as ReimbursementAccountUtils from '@userActions/ReimbursementAccount'; +// import CONST from '@src/CONST'; +// import ONYXKEYS from '@src/ONYXKEYS'; +// import type {ReimbursementAccountForm} from '@src/types/form'; +// import INPUT_IDS from '@src/types/form/ReimbursementAccountForm'; +// import type {ReimbursementAccount} from '@src/types/onyx'; +// import Confirmation from './substeps/Confirmation'; +// import Manual from './substeps/Manual'; +// import Plaid from './substeps/Plaid'; +// +// type BankInfoOnyxProps = { +// /** Plaid SDK token to use to initialize the widget */ +// plaidLinkToken: OnyxEntry; +// +// /** Reimbursement account from ONYX */ +// reimbursementAccount: OnyxEntry; +// +// /** The draft values of the bank account being setup */ +// reimbursementAccountDraft: OnyxEntry; +// +// policyID: string; +// }; +// +// type BankInfoProps = BankInfoOnyxProps & { +// /** Goes to the previous step */ +// onBackButtonPress: () => void; +// }; +// +// const BANK_INFO_STEP_KEYS = INPUT_IDS.BANK_INFO_STEP; +// const plaidSubsteps: Array> = [Plaid, Confirmation]; +// const receivedRedirectURI = getPlaidOAuthReceivedRedirectURI(); +// +// function AddPersonalBankAccount({onBackButtonPress, plaidData}) { +// const {translate} = useLocalize(); +// const styles = useThemeStyles(); +// +// const [selectedPlaidAccountId, setSelectedPlaidAccountId] = useState(''); +// const [isMethodChosen, setIsMethodChosen] = useState(false); +// +// const validateBankAccountForm = () => ({}); +// +// const submitBankAccountForm = useCallback(() => { +// const bankAccounts = plaidData?.bankAccounts ?? []; +// const selectedPlaidBankAccount = bankAccounts.find((bankAccount) => bankAccount.plaidAccountID === selectedPlaidAccountId); +// +// if (selectedPlaidBankAccount) { +// BankAccounts.addPersonalBankAccount(selectedPlaidBankAccount); +// } +// }, [plaidData, selectedPlaidAccountId]); +// +// return ( +// +// +// +// +// +// {isMethodChosen ? ( +// setIsMethodChosen(true)} /> +// ) : ( +// {}} +// style={[styles.mh5, styles.flex1]} +// > +// Navigation.goBack()} +// receivedRedirectURI={getPlaidOAuthReceivedRedirectURI()} +// selectedPlaidAccountID={selectedPlaidAccountId} +// isDisplayedInNewVBBA +// /> +// +// )} +// +// ); +// } +// +// AddPersonalBankAccount.displayName = 'AddPersonalBankAccount'; +// +// export default withOnyx({ +// // @ts-expect-error: ONYXKEYS.REIMBURSEMENT_ACCOUNT is conflicting with ONYXKEYS.FORMS.REIMBURSEMENT_ACCOUNT_FORM +// reimbursementAccount: { +// key: ONYXKEYS.REIMBURSEMENT_ACCOUNT, +// }, +// reimbursementAccountDraft: { +// key: ONYXKEYS.FORMS.REIMBURSEMENT_ACCOUNT_FORM_DRAFT, +// }, +// plaidLinkToken: { +// key: ONYXKEYS.PLAID_LINK_TOKEN, +// }, +// plaidData: { +// key: ONYXKEYS.PLAID_DATA, +// } +// })(AddPersonalBankAccount); + +import React, {useCallback, useEffect, useMemo} from 'react'; +import {View} from 'react-native'; +import type {OnyxEntry} from 'react-native-onyx'; +import {withOnyx} from 'react-native-onyx'; +import HeaderWithBackButton from '@components/HeaderWithBackButton'; +import InteractiveStepSubHeader from '@components/InteractiveStepSubHeader'; +import ScreenWrapper from '@components/ScreenWrapper'; +import useLocalize from '@hooks/useLocalize'; +import useSubStep from '@hooks/useSubStep'; +import type {SubStepProps} from '@hooks/useSubStep/types'; +import useThemeStyles from '@hooks/useThemeStyles'; +import CONST from '@src/CONST'; +import ONYXKEYS from '@src/ONYXKEYS'; +import type {ReimbursementAccountForm} from '@src/types/form'; +import INPUT_IDS from '@src/types/form/ReimbursementAccountForm'; +import type {ReimbursementAccount} from '@src/types/onyx'; +import Confirmation from './substeps/Confirmation'; +import Plaid from './substeps/Plaid'; +import ChooseMethod from "@pages/EnablePayments/AddBankAccount/substeps/ChooseMethod"; + +type BankInfoOnyxProps = { + /** Plaid SDK token to use to initialize the widget */ + plaidLinkToken: OnyxEntry; + + /** Reimbursement account from ONYX */ + reimbursementAccount: OnyxEntry; + + /** The draft values of the bank account being setup */ + reimbursementAccountDraft: OnyxEntry; + + policyID: string; +}; + +type BankInfoProps = BankInfoOnyxProps & { + /** Goes to the previous step */ + onBackButtonPress: () => void; +}; + +const BANK_INFO_STEP_KEYS = INPUT_IDS.BANK_INFO_STEP; +const plaidSubsteps: Array> = [ChooseMethod, Plaid, Confirmation]; + +function AddPersonalBankAccount({reimbursementAccount, reimbursementAccountDraft, plaidLinkToken, onBackButtonPress, policyID}: BankInfoProps) { + const {translate} = useLocalize(); + const styles = useThemeStyles(); + + const bankAccountID = Number(reimbursementAccount?.achData?.bankAccountID ?? '0'); + const submit = useCallback(() => { + }, [ bankAccountID, policyID]); + + const {componentToRender: SubStep, isEditing, screenIndex, nextScreen, prevScreen, moveTo} = useSubStep({bodyContent: plaidSubsteps, startFrom: 0, onFinished: submit}); + + + const handleBackButtonPress = () => { + if (screenIndex === 0) { + if (bankAccountID) { + onBackButtonPress(); + } else { + } + } else { + prevScreen(); + } + }; + + return ( + + + + + + + + ); +} + +AddPersonalBankAccount.displayName = 'AddPersonalBankAccount'; + +export default withOnyx({ + // @ts-expect-error: ONYXKEYS.REIMBURSEMENT_ACCOUNT is conflicting with ONYXKEYS.FORMS.REIMBURSEMENT_ACCOUNT_FORM + reimbursementAccount: { + key: ONYXKEYS.REIMBURSEMENT_ACCOUNT, + }, + reimbursementAccountDraft: { + key: ONYXKEYS.FORMS.REIMBURSEMENT_ACCOUNT_FORM_DRAFT, + }, + plaidLinkToken: { + key: ONYXKEYS.PLAID_LINK_TOKEN, + }, + personalBankAccount: { + key: ONYXKEYS.PERSONAL_BANK_ACCOUNT, + }, + plaidData: { + key: ONYXKEYS.PLAID_DATA, + }, +})(AddPersonalBankAccount); + diff --git a/src/pages/EnablePayments/AddBankAccount/substeps/ChooseMethod.tsx b/src/pages/EnablePayments/AddBankAccount/substeps/ChooseMethod.tsx new file mode 100644 index 000000000000..2cd2394ff68c --- /dev/null +++ b/src/pages/EnablePayments/AddBankAccount/substeps/ChooseMethod.tsx @@ -0,0 +1,88 @@ +import React, {useEffect} from 'react'; +import {View} from 'react-native'; +import {withOnyx} from 'react-native-onyx'; +import type {OnyxEntry} from 'react-native-onyx'; +import Button from '@components/Button'; +import HeaderWithBackButton from '@components/HeaderWithBackButton'; +import * as Expensicons from '@components/Icon/Expensicons'; +import * as Illustrations from '@components/Icon/Illustrations'; +import InteractiveStepSubHeader from '@components/InteractiveStepSubHeader'; +import ScreenWrapper from '@components/ScreenWrapper'; +import Section from '@components/Section'; +import Text from '@components/Text'; +import TextLink from '@components/TextLink'; +import useLocalize from '@hooks/useLocalize'; +import useThemeStyles from '@hooks/useThemeStyles'; +import getPlaidDesktopMessage from '@libs/getPlaidDesktopMessage'; +import * as BankAccounts from '@userActions/BankAccounts'; +import CONFIG from '@src/CONFIG'; +import ONYXKEYS from '@src/ONYXKEYS'; +import ROUTES from '@src/ROUTES'; +import type {PersonalBankAccount, PlaidData} from '@src/types/onyx'; + +type AddPersonalBankAccountPageWithOnyxProps = { + /** Contains plaid data */ + plaidData: OnyxEntry; + + /** The details about the Personal bank account we are adding saved in Onyx */ + personalBankAccount: OnyxEntry; +}; + +const plaidDesktopMessage = getPlaidDesktopMessage(); +const bankAccountRoute = `${CONFIG.EXPENSIFY.NEW_EXPENSIFY_URL}${ROUTES.SETTINGS_ADD_BANK_ACCOUNT_REFACTOR}`; + +function ChooseMethod({isPlaidDisabled, user, onNext}: AddPersonalBankAccountPageWithOnyxProps) { + const styles = useThemeStyles(); + const {translate} = useLocalize(); + useEffect(() => BankAccounts.clearPersonalBankAccount, []); + + return ( +
+ + {translate('bankAccount.addBankAccountBodyPt1')} + + + {translate('bankAccount.addBankAccountBodyPt2')} + + {!!plaidDesktopMessage && ( + + {translate(plaidDesktopMessage)} + + )} +
+ ); +} + +ChooseMethod.displayName = 'AddPersonalBankAccountPage'; + +export default withOnyx({ + personalBankAccount: { + key: ONYXKEYS.PERSONAL_BANK_ACCOUNT, + }, + plaidData: { + key: ONYXKEYS.PLAID_DATA, + }, + isPlaidDisabled: { + key: ONYXKEYS.IS_PLAID_DISABLED, + }, + user: { + key: ONYXKEYS.USER, + }, +})(ChooseMethod); diff --git a/src/pages/EnablePayments/AddBankAccount/substeps/Confirmation.tsx b/src/pages/EnablePayments/AddBankAccount/substeps/Confirmation.tsx new file mode 100644 index 000000000000..b128d6dc75e8 --- /dev/null +++ b/src/pages/EnablePayments/AddBankAccount/substeps/Confirmation.tsx @@ -0,0 +1,112 @@ +import React, {useMemo} from 'react'; +import {ScrollView, View} from 'react-native'; +import type {OnyxEntry} from 'react-native-onyx'; +import {withOnyx} from 'react-native-onyx'; +import Button from '@components/Button'; +import DotIndicatorMessage from '@components/DotIndicatorMessage'; +import MenuItemWithTopDescription from '@components/MenuItemWithTopDescription'; +import Text from '@components/Text'; +import useLocalize from '@hooks/useLocalize'; +import useNetwork from '@hooks/useNetwork'; +import type {SubStepProps} from '@hooks/useSubStep/types'; +import useThemeStyles from '@hooks/useThemeStyles'; +import * as ErrorUtils from '@libs/ErrorUtils'; +import getSubstepValues from '@pages/ReimbursementAccount/utils/getSubstepValues'; +import CONST from '@src/CONST'; +import ONYXKEYS from '@src/ONYXKEYS'; +import type {ReimbursementAccountForm} from '@src/types/form'; +import INPUT_IDS from '@src/types/form/ReimbursementAccountForm'; +import type {ReimbursementAccount} from '@src/types/onyx'; + +type ConfirmationOnyxProps = { + /** Reimbursement account from ONYX */ + reimbursementAccount: OnyxEntry; + + /** The draft values of the bank account being setup */ + reimbursementAccountDraft: OnyxEntry; +}; + +type ConfirmationProps = ConfirmationOnyxProps & SubStepProps; + +const BANK_INFO_STEP_KEYS = INPUT_IDS.BANK_INFO_STEP; +const BANK_INFO_STEP_INDEXES = CONST.REIMBURSEMENT_ACCOUNT_SUBSTEP_INDEX.BANK_ACCOUNT; + +function Confirmation({reimbursementAccount, reimbursementAccountDraft, onNext, onMove}: ConfirmationProps) { + const {translate} = useLocalize(); + const styles = useThemeStyles(); + const {isOffline} = useNetwork(); + + const isLoading = reimbursementAccount?.isLoading ?? false; + const setupType = reimbursementAccount?.achData?.subStep ?? ''; + const bankAccountID = Number(reimbursementAccount?.achData?.bankAccountID ?? '0'); + const values = useMemo(() => getSubstepValues(BANK_INFO_STEP_KEYS, reimbursementAccountDraft, reimbursementAccount ?? {}), [reimbursementAccount, reimbursementAccountDraft]); + const error = ErrorUtils.getLatestErrorMessage(reimbursementAccount ?? {}); + + const handleModifyAccountNumbers = () => { + onMove(BANK_INFO_STEP_INDEXES.ACCOUNT_NUMBERS); + }; + + return ( + + {translate('bankAccount.letsDoubleCheck')} + {translate('bankAccount.thisBankAccount')} + {setupType === CONST.BANK_ACCOUNT.SUBSTEP.MANUAL && ( + + + + + + )} + {setupType === CONST.BANK_ACCOUNT.SUBSTEP.PLAID && ( + + )} + + {error && error.length > 0 && ( + + )} +