From cd8ca07937025d621e7fb6802526e2a64b08aff5 Mon Sep 17 00:00:00 2001 From: Yogesh Bhatt Date: Sat, 7 Oct 2023 12:53:52 +0530 Subject: [PATCH 001/306] 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/306] 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/306] 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/306] 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/306] 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/306] 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/306] 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/306] 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/306] 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/306] 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/306] 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/306] 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/306] 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/306] 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/306] 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/306] 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/306] 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/306] 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/306] 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/306] 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/306] 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/306] 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/306] 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/306] 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/306] 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/306] 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/306] 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/306] 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/306] 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/306] 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/306] 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/306] 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/306] 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/306] 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/306] 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/306] 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/306] 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/306] 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/306] 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/306] 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/306] 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/306] 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/306] 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/306] 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/306] 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/306] 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/306] 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/306] 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/306] 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/306] 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/306] 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/306] 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/306] 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/306] 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/306] 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/306] 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/306] 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/306] 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/306] 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 fb08033cd73698250232de21554945f06a8f569e Mon Sep 17 00:00:00 2001 From: Etotaziba Olei Date: Wed, 31 Jan 2024 06:18:28 +0100 Subject: [PATCH 060/306] 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 061/306] 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 062/306] 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 063/306] 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 064/306] 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 065/306] 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: Sun, 4 Feb 2024 22:20:22 +0100 Subject: [PATCH 066/306] 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 3e19f56714ba0927c1d0b2cbbb4de72587b926a5 Mon Sep 17 00:00:00 2001 From: Etotaziba Olei Date: Mon, 5 Feb 2024 09:52:14 +0100 Subject: [PATCH 067/306] 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 068/306] 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 069/306] 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 b3dbe2607ec04fb9b8519fc3f1ed828e0857fa96 Mon Sep 17 00:00:00 2001 From: Etotaziba Olei Date: Wed, 7 Feb 2024 09:28:57 +0100 Subject: [PATCH 070/306] 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 071/306] 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 072/306] 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 073/306] 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 074/306] 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 075/306] 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 076/306] 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: Mon, 19 Feb 2024 09:26:07 +0100 Subject: [PATCH 077/306] 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 078/306] 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 079/306] 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 080/306] 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 081/306] 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 082/306] 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 083/306] 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 084/306] 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 085/306] 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 086/306] 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 087/306] 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 088/306] 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 089/306] 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 090/306] 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 091/306] 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 092/306] 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 093/306] 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 094/306] 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 095/306] 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 096/306] 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 097/306] 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 098/306] 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 099/306] 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 100/306] 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 101/306] 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 102/306] 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 103/306] 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 104/306] 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 105/306] 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 106/306] 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 107/306] 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 108/306] 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 109/306] 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 110/306] 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 111/306] 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 112/306] 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 113/306] 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 114/306] 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 12:43:38 +0100 Subject: [PATCH 115/306] 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 116/306] 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 117/306] 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 118/306] 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 119/306] 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 120/306] 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 e7be70e76caa5d6b0be91a2218bd6977540ba669 Mon Sep 17 00:00:00 2001 From: Etotaziba Olei Date: Thu, 22 Feb 2024 13:33:50 +0100 Subject: [PATCH 121/306] 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 122/306] 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 123/306] @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 124/306] 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 125/306] 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 126/306] 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 127/306] 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 128/306] 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 129/306] 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 130/306] 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 131/306] 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 a6faef416ad62d6e0c58df96dce26ce1ca1ac7b7 Mon Sep 17 00:00:00 2001 From: Yogesh Bhatt Date: Mon, 26 Feb 2024 18:17:58 +0530 Subject: [PATCH 132/306] Refactor StateSelectionPage with more explanatory comments --- .../PersonalDetails/StateSelectionPage.tsx | 21 ++++++++++++------- 1 file changed, 13 insertions(+), 8 deletions(-) diff --git a/src/pages/settings/Profile/PersonalDetails/StateSelectionPage.tsx b/src/pages/settings/Profile/PersonalDetails/StateSelectionPage.tsx index 7fe667f5b9ea..804d3de6bf13 100644 --- a/src/pages/settings/Profile/PersonalDetails/StateSelectionPage.tsx +++ b/src/pages/settings/Profile/PersonalDetails/StateSelectionPage.tsx @@ -60,17 +60,22 @@ function StateSelectionPage() { (option: CountryData) => { const backTo = 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, 'state', option.value) as Route); + // Determine navigation action based on "backTo" presence and route stack length. + if (navigation.getState().routes.length === 1) { + // If this is the only page in the navigation stack (examples include direct navigation to this page via URL or page reload). + if (_.isEmpty(backTo)) { + // No "backTo": default back navigation. + Navigation.goBack(); + } else { + // "backTo" provided: navigate back to "backTo" with state parameter. + 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 + // Most common case: Navigation stack has multiple routes and "backTo" is defined: navigate to "backTo" with state parameter. Navigation.navigate(appendParam(backTo, 'state', option.value) as Route); } else { + // This is a fallback block and should never execute if StateSelector is correctly appending the "backTo" route. + // Navigation stack has multiple routes but no "backTo" defined: default back navigation. Navigation.goBack(); } }, From c0cc219b0a3c16b888822087f624dd50184f711d Mon Sep 17 00:00:00 2001 From: Etotaziba Olei Date: Mon, 26 Feb 2024 16:53:00 +0100 Subject: [PATCH 133/306] fix lint --- .../MoneyTemporaryForRefactorRequestConfirmationList.js | 1 - 1 file changed, 1 deletion(-) diff --git a/src/components/MoneyTemporaryForRefactorRequestConfirmationList.js b/src/components/MoneyTemporaryForRefactorRequestConfirmationList.js index 1ecb22c99908..fa8d0d51990c 100755 --- a/src/components/MoneyTemporaryForRefactorRequestConfirmationList.js +++ b/src/components/MoneyTemporaryForRefactorRequestConfirmationList.js @@ -194,7 +194,6 @@ const defaultProps = { policy: {}, policyCategories: {}, policyTags: {}, - policy: {}, transactionID: '', transaction: {}, mileageRate: {unit: CONST.CUSTOM_UNITS.DISTANCE_UNIT_MILES, rate: 0, currency: 'USD'}, From 0fd03c00e0d9e3938490ac91ca9c133f55cb39ce Mon Sep 17 00:00:00 2001 From: Etotaziba Olei Date: Wed, 28 Feb 2024 01:24:49 +0100 Subject: [PATCH 134/306] add taxAmount and oldTaxAmount types 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 7c4cfbbb0cb0..63d1dd019db2 100644 --- a/src/libs/ReportUtils.ts +++ b/src/libs/ReportUtils.ts @@ -88,6 +88,8 @@ type ExpenseOriginalMessage = { oldTag?: string; billable?: string; oldBillable?: string; + oldTaxAmount?: number; + taxAmount?: number; taxRate?: string; oldTaxRate?: string; }; From 8b212f594840864fda7ea67c8aae601291e5a50e Mon Sep 17 00:00:00 2001 From: Etotaziba Olei Date: Wed, 28 Feb 2024 01:25:47 +0100 Subject: [PATCH 135/306] add taxAmount edit request system message --- src/libs/ModifiedExpenseMessage.ts | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/src/libs/ModifiedExpenseMessage.ts b/src/libs/ModifiedExpenseMessage.ts index b132c66c84c6..fb5cb7756804 100644 --- a/src/libs/ModifiedExpenseMessage.ts +++ b/src/libs/ModifiedExpenseMessage.ts @@ -215,6 +215,14 @@ function getForReportAction(reportID: string | undefined, reportAction: OnyxEntr } }); } + + const hasModifiedTaxAmount = reportActionOriginalMessage && 'oldTaxAmount' in reportActionOriginalMessage && 'taxAmount' in reportActionOriginalMessage; + if (hasModifiedTaxAmount) { + const taxAmount = CurrencyUtils.convertToDisplayString(reportActionOriginalMessage?.amount ?? 0); + const oldTaxAmountValue = reportActionOriginalMessage?.oldAmount ?? 0; + const oldTaxAmount = oldTaxAmountValue > 0 ? CurrencyUtils.convertToDisplayString(reportActionOriginalMessage?.oldTaxAmount ?? 0) : ''; + buildMessageFragmentForValue(taxAmount, oldTaxAmount, Localize.translateLocal('iou.taxAmount'), true, setFragments, removalFragments, changeFragments); + } const hasModifiedTaxRate = reportActionOriginalMessage && 'oldTaxRate' in reportActionOriginalMessage && 'taxRate' in reportActionOriginalMessage; if (hasModifiedTaxRate) { From f05fdfeab61a771569c17668105c794199e72da6 Mon Sep 17 00:00:00 2001 From: Etotaziba Olei Date: Wed, 28 Feb 2024 02:43:20 +0100 Subject: [PATCH 136/306] use taxAmount --- src/libs/ModifiedExpenseMessage.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/libs/ModifiedExpenseMessage.ts b/src/libs/ModifiedExpenseMessage.ts index fb5cb7756804..0a8df556405c 100644 --- a/src/libs/ModifiedExpenseMessage.ts +++ b/src/libs/ModifiedExpenseMessage.ts @@ -218,9 +218,9 @@ function getForReportAction(reportID: string | undefined, reportAction: OnyxEntr const hasModifiedTaxAmount = reportActionOriginalMessage && 'oldTaxAmount' in reportActionOriginalMessage && 'taxAmount' in reportActionOriginalMessage; if (hasModifiedTaxAmount) { - const taxAmount = CurrencyUtils.convertToDisplayString(reportActionOriginalMessage?.amount ?? 0); + const taxAmount = CurrencyUtils.convertToDisplayString(reportActionOriginalMessage?.taxAmount ?? 0); const oldTaxAmountValue = reportActionOriginalMessage?.oldAmount ?? 0; - const oldTaxAmount = oldTaxAmountValue > 0 ? CurrencyUtils.convertToDisplayString(reportActionOriginalMessage?.oldTaxAmount ?? 0) : ''; + const oldTaxAmount = oldTaxAmountValue > 0 ? CurrencyUtils.convertToDisplayString(oldTaxAmountValue) : ''; buildMessageFragmentForValue(taxAmount, oldTaxAmount, Localize.translateLocal('iou.taxAmount'), true, setFragments, removalFragments, changeFragments); } From 5f966270ce681e62adabf5964de09f03cb3d58a3 Mon Sep 17 00:00:00 2001 From: Etotaziba Olei Date: Wed, 28 Feb 2024 02:45:16 +0100 Subject: [PATCH 137/306] add allReports from Onyx --- src/libs/ModifiedExpenseMessage.ts | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/src/libs/ModifiedExpenseMessage.ts b/src/libs/ModifiedExpenseMessage.ts index 0a8df556405c..4ced8f0b6cf7 100644 --- a/src/libs/ModifiedExpenseMessage.ts +++ b/src/libs/ModifiedExpenseMessage.ts @@ -3,6 +3,7 @@ import type {OnyxCollection, OnyxEntry} from 'react-native-onyx'; import CONST from '@src/CONST'; import ONYXKEYS from '@src/ONYXKEYS'; import type {PolicyTagList, ReportAction} from '@src/types/onyx'; +import type * as OnyxTypes from '@src/types/onyx'; import * as CurrencyUtils from './CurrencyUtils'; import DateUtils from './DateUtils'; import * as Localize from './Localize'; @@ -24,6 +25,13 @@ Onyx.connect({ }, }); +let allReports: OnyxCollection = null; +Onyx.connect({ + key: ONYXKEYS.COLLECTION.REPORT, + waitForCollectionCallback: true, + callback: (value) => (allReports = value), +}); + /** * Builds the partial message fragment for a modified field on the expense. */ @@ -215,7 +223,7 @@ function getForReportAction(reportID: string | undefined, reportAction: OnyxEntr } }); } - + const hasModifiedTaxAmount = reportActionOriginalMessage && 'oldTaxAmount' in reportActionOriginalMessage && 'taxAmount' in reportActionOriginalMessage; if (hasModifiedTaxAmount) { const taxAmount = CurrencyUtils.convertToDisplayString(reportActionOriginalMessage?.taxAmount ?? 0); From d04d366ae7a5261b1e33e059f7b9fa49bdf74588 Mon Sep 17 00:00:00 2001 From: Etotaziba Olei Date: Wed, 28 Feb 2024 02:47:24 +0100 Subject: [PATCH 138/306] add getTaxAmount Func --- src/libs/ModifiedExpenseMessage.ts | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/src/libs/ModifiedExpenseMessage.ts b/src/libs/ModifiedExpenseMessage.ts index 4ced8f0b6cf7..9630c5220d99 100644 --- a/src/libs/ModifiedExpenseMessage.ts +++ b/src/libs/ModifiedExpenseMessage.ts @@ -99,6 +99,20 @@ function getForDistanceRequest(newDistance: string, oldDistance: string, newAmou }); } +/** + * Return the tax amount field from the transaction. + */ +function getTaxAmount(taxAmount: number, 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(taxAmount ?? 0); + } + + // To avoid -0 being shown, lets only change the sign if the value is other than 0. + const amount = taxAmount ?? 0; + return amount ? -amount : 0; +} + /** * Get the report action message when expense has been modified. * From 91aa0365088d16c637169711ef95aad6f545260e Mon Sep 17 00:00:00 2001 From: Etotaziba Olei Date: Wed, 28 Feb 2024 02:51:46 +0100 Subject: [PATCH 139/306] use getTaxAmount for taxAmount --- src/libs/ModifiedExpenseMessage.ts | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/src/libs/ModifiedExpenseMessage.ts b/src/libs/ModifiedExpenseMessage.ts index 9630c5220d99..9c398f33852a 100644 --- a/src/libs/ModifiedExpenseMessage.ts +++ b/src/libs/ModifiedExpenseMessage.ts @@ -240,7 +240,11 @@ function getForReportAction(reportID: string | undefined, reportAction: OnyxEntr const hasModifiedTaxAmount = reportActionOriginalMessage && 'oldTaxAmount' in reportActionOriginalMessage && 'taxAmount' in reportActionOriginalMessage; if (hasModifiedTaxAmount) { - const taxAmount = CurrencyUtils.convertToDisplayString(reportActionOriginalMessage?.taxAmount ?? 0); + const transactionThread = allReports?.[`${ONYXKEYS.COLLECTION.REPORT}${reportID}`] ?? null; + const iouReport = allReports?.[`${ONYXKEYS.COLLECTION.REPORT}${transactionThread?.parentReportID}`] ?? null; + const isFromExpenseReport = ReportUtils.isExpenseReport(iouReport); + + const taxAmount = CurrencyUtils.convertToDisplayString(getTaxAmount(reportActionOriginalMessage?.taxAmount ?? 0, isFromExpenseReport)); const oldTaxAmountValue = reportActionOriginalMessage?.oldAmount ?? 0; const oldTaxAmount = oldTaxAmountValue > 0 ? CurrencyUtils.convertToDisplayString(oldTaxAmountValue) : ''; buildMessageFragmentForValue(taxAmount, oldTaxAmount, Localize.translateLocal('iou.taxAmount'), true, setFragments, removalFragments, changeFragments); From dc5fc19ced1cbeade62726c18d58678728a0f5c0 Mon Sep 17 00:00:00 2001 From: Etotaziba Olei Date: Wed, 28 Feb 2024 02:52:41 +0100 Subject: [PATCH 140/306] use getTaxAmount for oldTaxAmount --- src/libs/ModifiedExpenseMessage.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/libs/ModifiedExpenseMessage.ts b/src/libs/ModifiedExpenseMessage.ts index 9c398f33852a..75bbf412012f 100644 --- a/src/libs/ModifiedExpenseMessage.ts +++ b/src/libs/ModifiedExpenseMessage.ts @@ -246,7 +246,7 @@ function getForReportAction(reportID: string | undefined, reportAction: OnyxEntr const taxAmount = CurrencyUtils.convertToDisplayString(getTaxAmount(reportActionOriginalMessage?.taxAmount ?? 0, isFromExpenseReport)); const oldTaxAmountValue = reportActionOriginalMessage?.oldAmount ?? 0; - const oldTaxAmount = oldTaxAmountValue > 0 ? CurrencyUtils.convertToDisplayString(oldTaxAmountValue) : ''; + const oldTaxAmount = oldTaxAmountValue > 0 ? CurrencyUtils.convertToDisplayString(getTaxAmount(oldTaxAmountValue, isFromExpenseReport)) : ''; buildMessageFragmentForValue(taxAmount, oldTaxAmount, Localize.translateLocal('iou.taxAmount'), true, setFragments, removalFragments, changeFragments); } From 70f9cde696ab478c08233c8e2a138951f594d714 Mon Sep 17 00:00:00 2001 From: Etotaziba Olei Date: Wed, 28 Feb 2024 02:54:14 +0100 Subject: [PATCH 141/306] format string with currency for taxAmount --- src/libs/ModifiedExpenseMessage.ts | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/libs/ModifiedExpenseMessage.ts b/src/libs/ModifiedExpenseMessage.ts index 75bbf412012f..369090070c88 100644 --- a/src/libs/ModifiedExpenseMessage.ts +++ b/src/libs/ModifiedExpenseMessage.ts @@ -243,8 +243,9 @@ function getForReportAction(reportID: string | undefined, reportAction: OnyxEntr const transactionThread = allReports?.[`${ONYXKEYS.COLLECTION.REPORT}${reportID}`] ?? null; const iouReport = allReports?.[`${ONYXKEYS.COLLECTION.REPORT}${transactionThread?.parentReportID}`] ?? null; const isFromExpenseReport = ReportUtils.isExpenseReport(iouReport); + const currency = iouReport?.currency ?? ''; - const taxAmount = CurrencyUtils.convertToDisplayString(getTaxAmount(reportActionOriginalMessage?.taxAmount ?? 0, isFromExpenseReport)); + const taxAmount = CurrencyUtils.convertToDisplayString(getTaxAmount(reportActionOriginalMessage?.taxAmount ?? 0, isFromExpenseReport), currency); const oldTaxAmountValue = reportActionOriginalMessage?.oldAmount ?? 0; const oldTaxAmount = oldTaxAmountValue > 0 ? CurrencyUtils.convertToDisplayString(getTaxAmount(oldTaxAmountValue, isFromExpenseReport)) : ''; buildMessageFragmentForValue(taxAmount, oldTaxAmount, Localize.translateLocal('iou.taxAmount'), true, setFragments, removalFragments, changeFragments); From 184a4e19c3ea041a3fab8f40840fd9dc802d537e Mon Sep 17 00:00:00 2001 From: Etotaziba Olei Date: Wed, 28 Feb 2024 02:54:52 +0100 Subject: [PATCH 142/306] format string with currency for oldTaxAmount --- src/libs/ModifiedExpenseMessage.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/libs/ModifiedExpenseMessage.ts b/src/libs/ModifiedExpenseMessage.ts index 369090070c88..c3ca42729bfb 100644 --- a/src/libs/ModifiedExpenseMessage.ts +++ b/src/libs/ModifiedExpenseMessage.ts @@ -247,7 +247,7 @@ function getForReportAction(reportID: string | undefined, reportAction: OnyxEntr const taxAmount = CurrencyUtils.convertToDisplayString(getTaxAmount(reportActionOriginalMessage?.taxAmount ?? 0, isFromExpenseReport), currency); const oldTaxAmountValue = reportActionOriginalMessage?.oldAmount ?? 0; - const oldTaxAmount = oldTaxAmountValue > 0 ? CurrencyUtils.convertToDisplayString(getTaxAmount(oldTaxAmountValue, isFromExpenseReport)) : ''; + const oldTaxAmount = oldTaxAmountValue > 0 ? CurrencyUtils.convertToDisplayString(getTaxAmount(oldTaxAmountValue, isFromExpenseReport), currency) : ''; buildMessageFragmentForValue(taxAmount, oldTaxAmount, Localize.translateLocal('iou.taxAmount'), true, setFragments, removalFragments, changeFragments); } From 55886f318345654356ba89d081ebe31d6173fc73 Mon Sep 17 00:00:00 2001 From: Etotaziba Olei Date: Wed, 28 Feb 2024 03:01:39 +0100 Subject: [PATCH 143/306] set valueInQuotes to false --- src/libs/ModifiedExpenseMessage.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/libs/ModifiedExpenseMessage.ts b/src/libs/ModifiedExpenseMessage.ts index c3ca42729bfb..1d24a403c864 100644 --- a/src/libs/ModifiedExpenseMessage.ts +++ b/src/libs/ModifiedExpenseMessage.ts @@ -248,7 +248,7 @@ function getForReportAction(reportID: string | undefined, reportAction: OnyxEntr const taxAmount = CurrencyUtils.convertToDisplayString(getTaxAmount(reportActionOriginalMessage?.taxAmount ?? 0, isFromExpenseReport), currency); const oldTaxAmountValue = reportActionOriginalMessage?.oldAmount ?? 0; const oldTaxAmount = oldTaxAmountValue > 0 ? CurrencyUtils.convertToDisplayString(getTaxAmount(oldTaxAmountValue, isFromExpenseReport), currency) : ''; - buildMessageFragmentForValue(taxAmount, oldTaxAmount, Localize.translateLocal('iou.taxAmount'), true, setFragments, removalFragments, changeFragments); + buildMessageFragmentForValue(taxAmount, oldTaxAmount, Localize.translateLocal('iou.taxAmount'), false, setFragments, removalFragments, changeFragments); } const hasModifiedTaxRate = reportActionOriginalMessage && 'oldTaxRate' in reportActionOriginalMessage && 'taxRate' in reportActionOriginalMessage; @@ -257,7 +257,7 @@ function getForReportAction(reportID: string | undefined, reportAction: OnyxEntr reportActionOriginalMessage?.taxRate ?? '', reportActionOriginalMessage?.oldTaxRate ?? '', Localize.translateLocal('iou.taxRate'), - true, + false, setFragments, removalFragments, changeFragments, From 9d9703aca82b3880f2d5b568fa6ed6440688b5e7 Mon Sep 17 00:00:00 2001 From: Etotaziba Olei Date: Wed, 28 Feb 2024 03:03:37 +0100 Subject: [PATCH 144/306] fix duplicate import --- src/libs/ModifiedExpenseMessage.ts | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/src/libs/ModifiedExpenseMessage.ts b/src/libs/ModifiedExpenseMessage.ts index 1d24a403c864..05803702f310 100644 --- a/src/libs/ModifiedExpenseMessage.ts +++ b/src/libs/ModifiedExpenseMessage.ts @@ -2,8 +2,7 @@ import Onyx from 'react-native-onyx'; import type {OnyxCollection, OnyxEntry} from 'react-native-onyx'; import CONST from '@src/CONST'; import ONYXKEYS from '@src/ONYXKEYS'; -import type {PolicyTagList, ReportAction} from '@src/types/onyx'; -import type * as OnyxTypes from '@src/types/onyx'; +import type {PolicyTagList, Report, ReportAction} from '@src/types/onyx'; import * as CurrencyUtils from './CurrencyUtils'; import DateUtils from './DateUtils'; import * as Localize from './Localize'; @@ -25,7 +24,7 @@ Onyx.connect({ }, }); -let allReports: OnyxCollection = null; +let allReports: OnyxCollection = null; Onyx.connect({ key: ONYXKEYS.COLLECTION.REPORT, waitForCollectionCallback: true, From e8e279b7fad8a11b8702bf34186683327b445892 Mon Sep 17 00:00:00 2001 From: Etotaziba Olei Date: Wed, 28 Feb 2024 03:12:16 +0100 Subject: [PATCH 145/306] handle oldTaxAmount --- src/libs/ModifiedExpenseMessage.ts | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/libs/ModifiedExpenseMessage.ts b/src/libs/ModifiedExpenseMessage.ts index 05803702f310..a6491d3025fc 100644 --- a/src/libs/ModifiedExpenseMessage.ts +++ b/src/libs/ModifiedExpenseMessage.ts @@ -245,8 +245,9 @@ function getForReportAction(reportID: string | undefined, reportAction: OnyxEntr const currency = iouReport?.currency ?? ''; const taxAmount = CurrencyUtils.convertToDisplayString(getTaxAmount(reportActionOriginalMessage?.taxAmount ?? 0, isFromExpenseReport), currency); - const oldTaxAmountValue = reportActionOriginalMessage?.oldAmount ?? 0; - const oldTaxAmount = oldTaxAmountValue > 0 ? CurrencyUtils.convertToDisplayString(getTaxAmount(oldTaxAmountValue, isFromExpenseReport), currency) : ''; + const oldTaxAmountValue = getTaxAmount(reportActionOriginalMessage?.oldTaxAmount ?? 0, isFromExpenseReport); + const oldTaxAmount = oldTaxAmountValue > 0 ? CurrencyUtils.convertToDisplayString(oldTaxAmountValue, currency) : ''; + buildMessageFragmentForValue(taxAmount, oldTaxAmount, Localize.translateLocal('iou.taxAmount'), false, setFragments, removalFragments, changeFragments); } From d783a3c690a3d513ae768b91992413ff5d2443a5 Mon Sep 17 00:00:00 2001 From: Etotaziba Olei Date: Wed, 28 Feb 2024 09:56:50 +0100 Subject: [PATCH 146/306] add isCurrencyPressable prop --- src/pages/iou/steps/MoneyRequestAmountForm.tsx | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/src/pages/iou/steps/MoneyRequestAmountForm.tsx b/src/pages/iou/steps/MoneyRequestAmountForm.tsx index cb1f73ae2207..5a5541239f42 100644 --- a/src/pages/iou/steps/MoneyRequestAmountForm.tsx +++ b/src/pages/iou/steps/MoneyRequestAmountForm.tsx @@ -33,6 +33,9 @@ type MoneyRequestAmountFormProps = { /** Whether the amount is being edited or not */ isEditing?: boolean; + /** Whether the currency symbol is pressable */ + isCurrencyPressable?: boolean; + /** Fired when back button pressed, navigates to currency selection page */ onCurrencyButtonPress: () => void; @@ -69,6 +72,7 @@ function MoneyRequestAmountForm( amount = 0, taxAmount = 0, currency = CONST.CURRENCY.USD, + isCurrencyPressable = true, isEditing = false, onCurrencyButtonPress, onSubmitButtonPress, @@ -300,7 +304,7 @@ function MoneyRequestAmountForm( setSelection({start, end}); }} onKeyPress={textInputKeyPress} - isCurrencyPressable + isCurrencyPressable={isCurrencyPressable} /> {!!formError && ( Date: Wed, 28 Feb 2024 09:57:27 +0100 Subject: [PATCH 147/306] use isCurrencyPressable prop to hide currency dropdown --- src/pages/EditRequestTaxAmountPage.tsx | 1 + 1 file changed, 1 insertion(+) diff --git a/src/pages/EditRequestTaxAmountPage.tsx b/src/pages/EditRequestTaxAmountPage.tsx index 22ce8a4de2df..ed7f14b9091e 100644 --- a/src/pages/EditRequestTaxAmountPage.tsx +++ b/src/pages/EditRequestTaxAmountPage.tsx @@ -56,6 +56,7 @@ function EditRequestTaxAmountPage({defaultAmount, defaultTaxAmount, defaultCurre amount={defaultAmount} taxAmount={defaultTaxAmount} ref={textInput} + isCurrencyPressable={false} onCurrencyButtonPress={onNavigateToCurrency} onSubmitButtonPress={onSubmit} isEditing From bddbd10fe7e4b15e5e7bd5455f90eda25c1720a9 Mon Sep 17 00:00:00 2001 From: Etotaziba Olei Date: Wed, 28 Feb 2024 09:58:56 +0100 Subject: [PATCH 148/306] make onCurrencyButtonPress optional --- 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 5a5541239f42..e073fdefae20 100644 --- a/src/pages/iou/steps/MoneyRequestAmountForm.tsx +++ b/src/pages/iou/steps/MoneyRequestAmountForm.tsx @@ -37,7 +37,7 @@ type MoneyRequestAmountFormProps = { isCurrencyPressable?: boolean; /** Fired when back button pressed, navigates to currency selection page */ - onCurrencyButtonPress: () => void; + onCurrencyButtonPress?: () => void; /** Fired when submit button pressed, saves the given amount and navigates to the next page */ onSubmitButtonPress: ({amount, currency}: {amount: string; currency: string}) => void; From c3c4a075bf0f9ccbc6dcfbe70cab1dfb3fd427bc Mon Sep 17 00:00:00 2001 From: Etotaziba Olei Date: Wed, 28 Feb 2024 10:01:14 +0100 Subject: [PATCH 149/306] remove onCurrencyButtonPress and props values --- src/pages/EditRequestTaxAmountPage.tsx | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/src/pages/EditRequestTaxAmountPage.tsx b/src/pages/EditRequestTaxAmountPage.tsx index ed7f14b9091e..a34ed8a5252d 100644 --- a/src/pages/EditRequestTaxAmountPage.tsx +++ b/src/pages/EditRequestTaxAmountPage.tsx @@ -20,12 +20,9 @@ type EditRequestTaxAmountPageProps = { /** Callback to fire when the Save button is pressed */ onSubmit: () => void; - - /** Callback to fire when we press on the currency */ - onNavigateToCurrency: () => void; }; -function EditRequestTaxAmountPage({defaultAmount, defaultTaxAmount, defaultCurrency, onNavigateToCurrency, onSubmit}: EditRequestTaxAmountPageProps) { +function EditRequestTaxAmountPage({defaultAmount, defaultTaxAmount, defaultCurrency, onSubmit}: EditRequestTaxAmountPageProps) { const {translate} = useLocalize(); const textInput = useRef(null); @@ -57,7 +54,6 @@ function EditRequestTaxAmountPage({defaultAmount, defaultTaxAmount, defaultCurre taxAmount={defaultTaxAmount} ref={textInput} isCurrencyPressable={false} - onCurrencyButtonPress={onNavigateToCurrency} onSubmitButtonPress={onSubmit} isEditing /> From 687d846c1d9815bd695895bde143a2c98c73be6e Mon Sep 17 00:00:00 2001 From: Etotaziba Olei Date: Wed, 28 Feb 2024 10:02:48 +0100 Subject: [PATCH 150/306] remove onNavigateToCurrency to Props --- src/pages/EditRequestPage.js | 4 ---- 1 file changed, 4 deletions(-) diff --git a/src/pages/EditRequestPage.js b/src/pages/EditRequestPage.js index 64fb4028516c..638b3711dc2e 100644 --- a/src/pages/EditRequestPage.js +++ b/src/pages/EditRequestPage.js @@ -206,10 +206,6 @@ function EditRequestPage({report, route, policy, policyCategories, policyTags, p defaultAmount={transactionTaxAmount} defaultTaxAmount={getTaxAmount(transactionAmount, transactionTaxCode, taxRates)} defaultCurrency={defaultCurrency} - onNavigateToCurrency={() => { - const activeRoute = encodeURIComponent(Navigation.getActiveRouteWithoutParams()); - Navigation.navigate(ROUTES.EDIT_CURRENCY_REQUEST.getRoute(report.reportID, defaultCurrency, activeRoute)); - }} onSubmit={updateTaxAmount} /> ); From 61e28f7811003c2b33d78b323e6553e589292320 Mon Sep 17 00:00:00 2001 From: Etotaziba Olei Date: Wed, 28 Feb 2024 11:02:03 +0100 Subject: [PATCH 151/306] update Tax Amount Params --- src/libs/TransactionUtils.ts | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/libs/TransactionUtils.ts b/src/libs/TransactionUtils.ts index 55bb591e3e6a..f8976d1ca450 100644 --- a/src/libs/TransactionUtils.ts +++ b/src/libs/TransactionUtils.ts @@ -306,14 +306,14 @@ function getAmount(transaction: OnyxEntry, isFromExpenseReport = fa /** * Return the tax amount field from the transaction. */ -function getTaxAmount(transaction: OnyxEntry, isFromExpenseReport: boolean): number { +function getTaxAmount(taxAmount: number, 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); + return Math.abs(taxAmount ?? 0); } // To avoid -0 being shown, lets only change the sign if the value is other than 0. - const amount = transaction?.taxAmount ?? 0; + const amount = taxAmount ?? 0; return amount ? -amount : 0; } From 64408cabc219f5d33db258a3e39163f9c13d4db5 Mon Sep 17 00:00:00 2001 From: Etotaziba Olei Date: Wed, 28 Feb 2024 11:02:35 +0100 Subject: [PATCH 152/306] update getTaxAmount args... --- src/libs/ReportUtils.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/libs/ReportUtils.ts b/src/libs/ReportUtils.ts index 63d1dd019db2..2a5c2e868c7c 100644 --- a/src/libs/ReportUtils.ts +++ b/src/libs/ReportUtils.ts @@ -2066,7 +2066,7 @@ function getTransactionDetails(transaction: OnyxEntry, createdDateF return { created: TransactionUtils.getCreated(transaction, createdDateFormat), amount: TransactionUtils.getAmount(transaction, !isEmptyObject(report) && isExpenseReport(report)), - taxAmount: TransactionUtils.getTaxAmount(transaction, !isEmptyObject(report) && isExpenseReport(report)), + taxAmount: TransactionUtils.getTaxAmount(transaction?.taxAmount ?? 0, !isEmptyObject(report) && isExpenseReport(report)), taxCode: TransactionUtils.getTaxCode(transaction), currency: TransactionUtils.getCurrency(transaction), comment: TransactionUtils.getDescription(transaction), From 211308e7fc552cf686f2c370d1f4e569f3a37dac Mon Sep 17 00:00:00 2001 From: Etotaziba Olei Date: Wed, 28 Feb 2024 11:03:05 +0100 Subject: [PATCH 153/306] remove duplicate getTaxAmount --- src/libs/ModifiedExpenseMessage.ts | 18 ++---------------- 1 file changed, 2 insertions(+), 16 deletions(-) diff --git a/src/libs/ModifiedExpenseMessage.ts b/src/libs/ModifiedExpenseMessage.ts index a6491d3025fc..2855344899f0 100644 --- a/src/libs/ModifiedExpenseMessage.ts +++ b/src/libs/ModifiedExpenseMessage.ts @@ -98,20 +98,6 @@ function getForDistanceRequest(newDistance: string, oldDistance: string, newAmou }); } -/** - * Return the tax amount field from the transaction. - */ -function getTaxAmount(taxAmount: number, 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(taxAmount ?? 0); - } - - // To avoid -0 being shown, lets only change the sign if the value is other than 0. - const amount = taxAmount ?? 0; - return amount ? -amount : 0; -} - /** * Get the report action message when expense has been modified. * @@ -244,8 +230,8 @@ function getForReportAction(reportID: string | undefined, reportAction: OnyxEntr const isFromExpenseReport = ReportUtils.isExpenseReport(iouReport); const currency = iouReport?.currency ?? ''; - const taxAmount = CurrencyUtils.convertToDisplayString(getTaxAmount(reportActionOriginalMessage?.taxAmount ?? 0, isFromExpenseReport), currency); - const oldTaxAmountValue = getTaxAmount(reportActionOriginalMessage?.oldTaxAmount ?? 0, isFromExpenseReport); + const taxAmount = CurrencyUtils.convertToDisplayString(TransactionUtils.getTaxAmount(reportActionOriginalMessage?.taxAmount ?? 0, isFromExpenseReport), currency); + const oldTaxAmountValue = TransactionUtils.getTaxAmount(reportActionOriginalMessage?.oldTaxAmount ?? 0, isFromExpenseReport); const oldTaxAmount = oldTaxAmountValue > 0 ? CurrencyUtils.convertToDisplayString(oldTaxAmountValue, currency) : ''; buildMessageFragmentForValue(taxAmount, oldTaxAmount, Localize.translateLocal('iou.taxAmount'), false, setFragments, removalFragments, changeFragments); From 7b153084d3214db17b0067e5797552eadacc10af Mon Sep 17 00:00:00 2001 From: Yogesh Bhatt <65986357+ygshbht@users.noreply.github.com> Date: Fri, 1 Mar 2024 12:03:54 +0530 Subject: [PATCH 154/306] Incorrect header space fix: src/pages/settings/Profile/PersonalDetails/StateSelectionPage.tsx Co-authored-by: Rajat --- .../settings/Profile/PersonalDetails/StateSelectionPage.tsx | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/pages/settings/Profile/PersonalDetails/StateSelectionPage.tsx b/src/pages/settings/Profile/PersonalDetails/StateSelectionPage.tsx index 804d3de6bf13..05746405adf7 100644 --- a/src/pages/settings/Profile/PersonalDetails/StateSelectionPage.tsx +++ b/src/pages/settings/Profile/PersonalDetails/StateSelectionPage.tsx @@ -86,8 +86,6 @@ function StateSelectionPage() { Date: Fri, 1 Mar 2024 12:07:11 +0530 Subject: [PATCH 155/306] Remove unused code StateSelectionPage.tsx --- .../settings/Profile/PersonalDetails/StateSelectionPage.tsx | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/pages/settings/Profile/PersonalDetails/StateSelectionPage.tsx b/src/pages/settings/Profile/PersonalDetails/StateSelectionPage.tsx index 05746405adf7..b30c9c9967c8 100644 --- a/src/pages/settings/Profile/PersonalDetails/StateSelectionPage.tsx +++ b/src/pages/settings/Profile/PersonalDetails/StateSelectionPage.tsx @@ -7,7 +7,6 @@ import ScreenWrapper from '@components/ScreenWrapper'; import SelectionList from '@components/SelectionList'; import RadioListItem from '@components/SelectionList/RadioListItem'; import useLocalize from '@hooks/useLocalize'; -import useThemeStyles from '@hooks/useThemeStyles'; import Navigation from '@libs/Navigation/Navigation'; import searchCountryOptions from '@libs/searchCountryOptions'; import type {CountryData} from '@libs/searchCountryOptions'; @@ -26,7 +25,6 @@ type RouteParams = { function StateSelectionPage() { const route = useRoute(); const navigation = useNavigation(); - const styles = useThemeStyles(); const {translate} = useLocalize(); const [searchValue, setSearchValue] = useState(''); From 9dd9dad0f9411b07e0943eb216feb0e537c91afc Mon Sep 17 00:00:00 2001 From: Etotaziba Olei Date: Mon, 4 Mar 2024 11:10:00 +0100 Subject: [PATCH 156/306] remove ts-expect-error --- src/pages/EditRequestTaxRatePage.tsx | 1 - 1 file changed, 1 deletion(-) diff --git a/src/pages/EditRequestTaxRatePage.tsx b/src/pages/EditRequestTaxRatePage.tsx index 1c1dc8219ae2..099851e92209 100644 --- a/src/pages/EditRequestTaxRatePage.tsx +++ b/src/pages/EditRequestTaxRatePage.tsx @@ -28,7 +28,6 @@ function EditRequestTaxRatePage({defaultTaxRate, policyID, onSubmit}: EditReques <> Date: Mon, 4 Mar 2024 11:29:19 +0100 Subject: [PATCH 157/306] fix tax picker types --- src/components/TaxPicker.tsx | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/components/TaxPicker.tsx b/src/components/TaxPicker.tsx index 50e534dc9f6f..cfccb7604044 100644 --- a/src/components/TaxPicker.tsx +++ b/src/components/TaxPicker.tsx @@ -2,8 +2,6 @@ import React, {useMemo, useState} from 'react'; import {withOnyx} from 'react-native-onyx'; import type {OnyxEntry} from 'react-native-onyx'; import type {EdgeInsets} from 'react-native-safe-area-context'; -import _ from 'underscore'; -import OptionsSelector from '@components/OptionsSelector'; import useLocalize from '@hooks/useLocalize'; import useStyleUtils from '@hooks/useStyleUtils'; import useThemeStyles from '@hooks/useThemeStyles'; @@ -12,6 +10,7 @@ import * as TransactionUtils from '@libs/TransactionUtils'; import CONST from '@src/CONST'; import ONYXKEYS from '@src/ONYXKEYS'; import type {Policy} from '@src/types/onyx'; +import OptionsSelector from './OptionsSelector'; type TaxPickerOnyxProps = { /** The policy which the user has access to and which the report is tied to */ @@ -23,7 +22,8 @@ type TaxPickerProps = TaxPickerOnyxProps & { selectedTaxRate?: string; /** ID of the policy */ - policyID: string; + // eslint-disable-next-line react/no-unused-prop-types + policyID?: string; /** * Safe area insets required for reflecting the portion of the view, From 84010186e9196a3a4c0fe119fb54dca1f72761f4 Mon Sep 17 00:00:00 2001 From: Etotaziba Olei Date: Wed, 6 Mar 2024 10:29:55 +0100 Subject: [PATCH 158/306] add useCallback for updateTaxAmount and updateTaxRate --- src/pages/EditRequestPage.js | 28 +++++++++++++++++----------- 1 file changed, 17 insertions(+), 11 deletions(-) diff --git a/src/pages/EditRequestPage.js b/src/pages/EditRequestPage.js index 638b3711dc2e..b428e3eaf820 100644 --- a/src/pages/EditRequestPage.js +++ b/src/pages/EditRequestPage.js @@ -125,17 +125,23 @@ function EditRequestPage({report, route, policy, policyCategories, policyTags, p }); }, [parentReportAction, fieldToEdit]); - const updateTaxAmount = (transactionChanges) => { - const newTaxAmount = CurrencyUtils.convertToBackendAmount(Number.parseFloat(transactionChanges.amount)); - 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, policy, policyTags, policyCategories); - Navigation.dismissModal(report.reportID); - }; + const updateTaxAmount = useCallback( + (transactionChanges) => { + const newTaxAmount = CurrencyUtils.convertToBackendAmount(Number.parseFloat(transactionChanges.amount)); + IOU.updateMoneyRequestTaxAmount(transaction.transactionID, report.reportID, newTaxAmount, policy, policyTags, policyCategories); + Navigation.dismissModal(report.reportID); + }, + [transaction, report, policy, policyTags, policyCategories], + ); + + const updateTaxRate = useCallback( + (transactionChanges) => { + const newTaxCode = transactionChanges.data.code; + IOU.updateMoneyRequestTaxRate(transaction.transactionID, report.reportID, newTaxCode, policy, policyTags, policyCategories); + Navigation.dismissModal(report.reportID); + }, + [transaction, report, policy, policyTags, policyCategories], + ); const saveAmountAndCurrency = useCallback( ({amount, currency: newCurrency}) => { From 484c8ca9944314e0b7c220646d171ba935d8b1a9 Mon Sep 17 00:00:00 2001 From: Etotaziba Olei Date: Wed, 6 Mar 2024 14:47:34 +0100 Subject: [PATCH 159/306] add tax types to OriginalMessageModifiedExpense --- src/types/onyx/OriginalMessage.ts | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/types/onyx/OriginalMessage.ts b/src/types/onyx/OriginalMessage.ts index 06c2d2e6abce..eaab2ee6f1ba 100644 --- a/src/types/onyx/OriginalMessage.ts +++ b/src/types/onyx/OriginalMessage.ts @@ -251,6 +251,10 @@ type OriginalMessageModifiedExpense = { category?: string; oldTag?: string; tag?: string; + oldTaxAmount?: number; + taxAmount?: number; + oldTaxRate?: string; + taxRate?: string; oldBillable?: string; billable?: string; }; From e7e62a8f6762027ae217246e144318ed6540cfcd Mon Sep 17 00:00:00 2001 From: Etotaziba Olei Date: Wed, 6 Mar 2024 14:48:19 +0100 Subject: [PATCH 160/306] update getTaxAmount func --- src/libs/TransactionUtils.ts | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/libs/TransactionUtils.ts b/src/libs/TransactionUtils.ts index f8976d1ca450..55bb591e3e6a 100644 --- a/src/libs/TransactionUtils.ts +++ b/src/libs/TransactionUtils.ts @@ -306,14 +306,14 @@ function getAmount(transaction: OnyxEntry, isFromExpenseReport = fa /** * Return the tax amount field from the transaction. */ -function getTaxAmount(taxAmount: number, isFromExpenseReport: boolean): number { +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(taxAmount ?? 0); + 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 = taxAmount ?? 0; + const amount = transaction?.taxAmount ?? 0; return amount ? -amount : 0; } From 450f849975995ef04c1cec48ccaf0100870f2042 Mon Sep 17 00:00:00 2001 From: Etotaziba Olei Date: Wed, 6 Mar 2024 14:49:19 +0100 Subject: [PATCH 161/306] add optimistic data for tax amount and code --- src/libs/ReportUtils.ts | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/src/libs/ReportUtils.ts b/src/libs/ReportUtils.ts index a82e1fe6b941..77ae89f11e54 100644 --- a/src/libs/ReportUtils.ts +++ b/src/libs/ReportUtils.ts @@ -2097,7 +2097,7 @@ function getTransactionDetails(transaction: OnyxEntry, createdDateF return { created: TransactionUtils.getCreated(transaction, createdDateFormat), amount: TransactionUtils.getAmount(transaction, !isEmptyObject(report) && isExpenseReport(report)), - taxAmount: TransactionUtils.getTaxAmount(transaction?.taxAmount ?? 0, !isEmptyObject(report) && isExpenseReport(report)), + taxAmount: TransactionUtils.getTaxAmount(transaction, !isEmptyObject(report) && isExpenseReport(report)), taxCode: TransactionUtils.getTaxCode(transaction), currency: TransactionUtils.getCurrency(transaction), comment: TransactionUtils.getDescription(transaction), @@ -2474,6 +2474,16 @@ function getModifiedExpenseOriginalMessage(oldTransaction: OnyxEntry Date: Wed, 6 Mar 2024 14:49:45 +0100 Subject: [PATCH 162/306] update modified tax amount --- src/libs/ModifiedExpenseMessage.ts | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-) diff --git a/src/libs/ModifiedExpenseMessage.ts b/src/libs/ModifiedExpenseMessage.ts index 2855344899f0..fad823a8fded 100644 --- a/src/libs/ModifiedExpenseMessage.ts +++ b/src/libs/ModifiedExpenseMessage.ts @@ -62,6 +62,14 @@ function buildMessageFragmentForValue( } } +/** + * Get the absolute value for a tax amount. + */ +function getTaxAmountAbsValue(taxAmount: number): number { + // IOU requests cannot have negative values but they can be stored as negative values, let's return absolute value + return Math.abs(taxAmount ?? 0); +} + /** * Get the message line for a modified expense. */ @@ -227,13 +235,11 @@ function getForReportAction(reportID: string | undefined, reportAction: OnyxEntr if (hasModifiedTaxAmount) { const transactionThread = allReports?.[`${ONYXKEYS.COLLECTION.REPORT}${reportID}`] ?? null; const iouReport = allReports?.[`${ONYXKEYS.COLLECTION.REPORT}${transactionThread?.parentReportID}`] ?? null; - const isFromExpenseReport = ReportUtils.isExpenseReport(iouReport); const currency = iouReport?.currency ?? ''; - const taxAmount = CurrencyUtils.convertToDisplayString(TransactionUtils.getTaxAmount(reportActionOriginalMessage?.taxAmount ?? 0, isFromExpenseReport), currency); - const oldTaxAmountValue = TransactionUtils.getTaxAmount(reportActionOriginalMessage?.oldTaxAmount ?? 0, isFromExpenseReport); + const taxAmount = CurrencyUtils.convertToDisplayString(getTaxAmountAbsValue(reportActionOriginalMessage?.taxAmount ?? 0), currency); + const oldTaxAmountValue = getTaxAmountAbsValue(reportActionOriginalMessage?.oldTaxAmount ?? 0); const oldTaxAmount = oldTaxAmountValue > 0 ? CurrencyUtils.convertToDisplayString(oldTaxAmountValue, currency) : ''; - buildMessageFragmentForValue(taxAmount, oldTaxAmount, Localize.translateLocal('iou.taxAmount'), false, setFragments, removalFragments, changeFragments); } From 452e0e06f8fa7b91372192e0a5bc7307f50e709d Mon Sep 17 00:00:00 2001 From: Etotaziba Olei Date: Wed, 6 Mar 2024 14:51:16 +0100 Subject: [PATCH 163/306] fix prettier --- src/libs/ReportUtils.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/libs/ReportUtils.ts b/src/libs/ReportUtils.ts index 77ae89f11e54..9422b20beb02 100644 --- a/src/libs/ReportUtils.ts +++ b/src/libs/ReportUtils.ts @@ -2474,9 +2474,9 @@ function getModifiedExpenseOriginalMessage(oldTransaction: OnyxEntry Date: Wed, 6 Mar 2024 15:23:42 +0100 Subject: [PATCH 164/306] select tax value and pass to original message --- src/libs/ReportUtils.ts | 16 ++++++++++++---- 1 file changed, 12 insertions(+), 4 deletions(-) diff --git a/src/libs/ReportUtils.ts b/src/libs/ReportUtils.ts index 9422b20beb02..a74ef227deb7 100644 --- a/src/libs/ReportUtils.ts +++ b/src/libs/ReportUtils.ts @@ -31,6 +31,7 @@ import type { Transaction, TransactionViolation, } from '@src/types/onyx'; +import type * as OnyxTypes from '@src/types/onyx'; import type {Participant} from '@src/types/onyx/IOU'; import type {Errors, Icon, PendingAction} from '@src/types/onyx/OnyxCommon'; import type { @@ -2438,7 +2439,12 @@ function getReportPreviewMessage( * * At the moment, we only allow changing one transaction field at a time. */ -function getModifiedExpenseOriginalMessage(oldTransaction: OnyxEntry, transactionChanges: TransactionChanges, isFromExpenseReport: boolean): ExpenseOriginalMessage { +function getModifiedExpenseOriginalMessage( + oldTransaction: OnyxEntry, + transactionChanges: TransactionChanges, + isFromExpenseReport: boolean, + policy: OnyxEntry, +): ExpenseOriginalMessage { const originalMessage: ExpenseOriginalMessage = {}; // Remark: Comment field is the only one which has new/old prefixes for the keys (newComment/ oldComment), // all others have old/- pattern such as oldCreated/created @@ -2480,8 +2486,9 @@ function getModifiedExpenseOriginalMessage(oldTransaction: OnyxEntry, transactionChanges: TransactionChanges, isFromExpenseReport: boolean, + policy: OnyxEntry, ): OptimisticModifiedExpenseReportAction { - const originalMessage = getModifiedExpenseOriginalMessage(oldTransaction, transactionChanges, isFromExpenseReport); + const originalMessage = getModifiedExpenseOriginalMessage(oldTransaction, transactionChanges, isFromExpenseReport, policy); return { actionName: CONST.REPORT.ACTIONS.TYPE.MODIFIEDEXPENSE, actorAccountID: currentUserAccountID, From f1e1f92fcbfbb695572a8f79b9190f9a37d770d4 Mon Sep 17 00:00:00 2001 From: Etotaziba Olei Date: Wed, 6 Mar 2024 15:24:10 +0100 Subject: [PATCH 165/306] pass polciy props --- src/libs/actions/IOU.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/libs/actions/IOU.ts b/src/libs/actions/IOU.ts index 86b116974091..1161b1e61b65 100644 --- a/src/libs/actions/IOU.ts +++ b/src/libs/actions/IOU.ts @@ -1200,7 +1200,7 @@ function getUpdateMoneyRequestParams( // We don't create a modified report action if we're updating the waypoints, // since there isn't actually any optimistic data we can create for them and the report action is created on the server // with the response from the MapBox API - const updatedReportAction = ReportUtils.buildOptimisticModifiedExpenseReportAction(transactionThread, transaction, transactionChanges, isFromExpenseReport); + const updatedReportAction = ReportUtils.buildOptimisticModifiedExpenseReportAction(transactionThread, transaction, transactionChanges, isFromExpenseReport, policy); if (!hasPendingWaypoints) { params.reportActionID = updatedReportAction.reportActionID; @@ -2664,7 +2664,7 @@ function editRegularMoneyRequest( const isFromExpenseReport = ReportUtils.isExpenseReport(iouReport); // STEP 2: Build new modified expense report action. - const updatedReportAction = ReportUtils.buildOptimisticModifiedExpenseReportAction(transactionThread, transaction, transactionChanges, isFromExpenseReport); + const updatedReportAction = ReportUtils.buildOptimisticModifiedExpenseReportAction(transactionThread, transaction, transactionChanges, isFromExpenseReport, policy); const updatedTransaction = transaction ? TransactionUtils.getUpdatedTransaction(transaction, transactionChanges, isFromExpenseReport) : null; // STEP 3: Compute the IOU total and update the report preview message so LHN amount owed is correct From 89358cb5d9bb3f3b86b06c32b052ebb18f4bd606 Mon Sep 17 00:00:00 2001 From: Etotaziba Olei Date: Wed, 6 Mar 2024 15:40:10 +0100 Subject: [PATCH 166/306] fix lint --- src/libs/ReportUtils.ts | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/src/libs/ReportUtils.ts b/src/libs/ReportUtils.ts index a74ef227deb7..2d8bc354c825 100644 --- a/src/libs/ReportUtils.ts +++ b/src/libs/ReportUtils.ts @@ -31,7 +31,6 @@ import type { Transaction, TransactionViolation, } from '@src/types/onyx'; -import type * as OnyxTypes from '@src/types/onyx'; import type {Participant} from '@src/types/onyx/IOU'; import type {Errors, Icon, PendingAction} from '@src/types/onyx/OnyxCommon'; import type { @@ -2443,7 +2442,7 @@ function getModifiedExpenseOriginalMessage( oldTransaction: OnyxEntry, transactionChanges: TransactionChanges, isFromExpenseReport: boolean, - policy: OnyxEntry, + policy: OnyxEntry, ): ExpenseOriginalMessage { const originalMessage: ExpenseOriginalMessage = {}; // Remark: Comment field is the only one which has new/old prefixes for the keys (newComment/ oldComment), @@ -2486,9 +2485,8 @@ function getModifiedExpenseOriginalMessage( } if ('taxCode' in transactionChanges) { - const taxRates = policy?.taxRates?.taxes; - originalMessage.oldTaxRate = taxRates && taxRates[TransactionUtils.getTaxCode(oldTransaction)].value; - originalMessage.taxRate = taxRates && transactionChanges?.taxCode && taxRates[transactionChanges.taxCode].value; + originalMessage.oldTaxRate = policy?.taxRates?.taxes[TransactionUtils.getTaxCode(oldTransaction)].value; + originalMessage.taxRate = transactionChanges?.taxCode && policy?.taxRates?.taxes[transactionChanges?.taxCode].value; } if ('billable' in transactionChanges) { @@ -3332,7 +3330,7 @@ function buildOptimisticModifiedExpenseReportAction( oldTransaction: OnyxEntry, transactionChanges: TransactionChanges, isFromExpenseReport: boolean, - policy: OnyxEntry, + policy: OnyxEntry, ): OptimisticModifiedExpenseReportAction { const originalMessage = getModifiedExpenseOriginalMessage(oldTransaction, transactionChanges, isFromExpenseReport, policy); return { From 14b7ef07bbf7ce99348facf9fef731f8abe6fee9 Mon Sep 17 00:00:00 2001 From: Etotaziba Olei Date: Thu, 7 Mar 2024 15:24:44 +0100 Subject: [PATCH 167/306] avoid redundant API call if same tax rate is selected --- src/pages/EditRequestPage.js | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/src/pages/EditRequestPage.js b/src/pages/EditRequestPage.js index b428e3eaf820..d0436b32c817 100644 --- a/src/pages/EditRequestPage.js +++ b/src/pages/EditRequestPage.js @@ -137,6 +137,12 @@ function EditRequestPage({report, route, policy, policyCategories, policyTags, p const updateTaxRate = useCallback( (transactionChanges) => { const newTaxCode = transactionChanges.data.code; + + if (!newTaxCode) { + Navigation.dismissModal(); + return; + } + IOU.updateMoneyRequestTaxRate(transaction.transactionID, report.reportID, newTaxCode, policy, policyTags, policyCategories); Navigation.dismissModal(report.reportID); }, From f1179ce504f4b27a74b1036a308da93dcc8ce02e Mon Sep 17 00:00:00 2001 From: Etotaziba Olei Date: Thu, 7 Mar 2024 15:27:37 +0100 Subject: [PATCH 168/306] avoid redundant API call if same tax amount inputed is selected --- src/pages/EditRequestPage.js | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/pages/EditRequestPage.js b/src/pages/EditRequestPage.js index d0436b32c817..c01b65932beb 100644 --- a/src/pages/EditRequestPage.js +++ b/src/pages/EditRequestPage.js @@ -128,6 +128,11 @@ function EditRequestPage({report, route, policy, policyCategories, policyTags, p const updateTaxAmount = useCallback( (transactionChanges) => { const newTaxAmount = CurrencyUtils.convertToBackendAmount(Number.parseFloat(transactionChanges.amount)); + + if (newTaxAmount === TransactionUtils.getTaxAmount(transaction)) { + Navigation.dismissModal(); + return; + } IOU.updateMoneyRequestTaxAmount(transaction.transactionID, report.reportID, newTaxAmount, policy, policyTags, policyCategories); Navigation.dismissModal(report.reportID); }, From 40583469e19a41a331e5d2b94f0c7e7979ce09dc Mon Sep 17 00:00:00 2001 From: Etotaziba Olei Date: Thu, 7 Mar 2024 16:02:35 +0100 Subject: [PATCH 169/306] do not update taxAmount more than default taxAmount based on actual expense amount --- src/pages/EditRequestPage.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/pages/EditRequestPage.js b/src/pages/EditRequestPage.js index c01b65932beb..cfde040cbdf5 100644 --- a/src/pages/EditRequestPage.js +++ b/src/pages/EditRequestPage.js @@ -77,7 +77,7 @@ const defaultProps = { const getTaxAmount = (transactionAmount, transactionTaxCode, taxRates) => { const percentage = (transactionTaxCode ? taxRates.taxes[transactionTaxCode].value : taxRates.defaultValue) || ''; - return CurrencyUtils.convertToBackendAmount(Number.parseFloat(TransactionUtils.calculateTaxAmount(percentage, transactionAmount))); + return CurrencyUtils.convertToBackendAmount(Number.parseFloat(TransactionUtils.calculateTaxAmount(percentage, Math.abs(transactionAmount)))); }; function EditRequestPage({report, route, policy, policyCategories, policyTags, parentReportActions, transaction}) { @@ -221,7 +221,7 @@ function EditRequestPage({report, route, policy, policyCategories, policyTags, p return ( From 5021d915b18ed5307619cd39d63d7ac41a52833a Mon Sep 17 00:00:00 2001 From: Etotaziba Olei Date: Thu, 7 Mar 2024 17:07:23 +0100 Subject: [PATCH 170/306] remove optional chaining --- 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 cfde040cbdf5..0498c98b087a 100644 --- a/src/pages/EditRequestPage.js +++ b/src/pages/EditRequestPage.js @@ -221,7 +221,7 @@ function EditRequestPage({report, route, policy, policyCategories, policyTags, p return ( From 397278d3665de12a40768a1ee4e789ac1ee8c56b Mon Sep 17 00:00:00 2001 From: Yogesh Bhatt Date: Thu, 7 Mar 2024 21:54:37 +0530 Subject: [PATCH 171/306] Prettier formatting --- src/pages/settings/Profile/PersonalDetails/AddressPage.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/pages/settings/Profile/PersonalDetails/AddressPage.tsx b/src/pages/settings/Profile/PersonalDetails/AddressPage.tsx index 9d9d16a6a388..77d551b283ec 100644 --- a/src/pages/settings/Profile/PersonalDetails/AddressPage.tsx +++ b/src/pages/settings/Profile/PersonalDetails/AddressPage.tsx @@ -13,8 +13,8 @@ import useThemeStyles from '@hooks/useThemeStyles'; import Navigation from '@libs/Navigation/Navigation'; import type {SettingsNavigatorParamList} from '@libs/Navigation/types'; import * as PersonalDetails from '@userActions/PersonalDetails'; -import CONST from '@src/CONST'; import type {FormOnyxValues} from '@src/components/Form/types'; +import CONST from '@src/CONST'; import type {Country} from '@src/CONST'; import ONYXKEYS from '@src/ONYXKEYS'; import type SCREENS from '@src/SCREENS'; From 5d223d69037f3e89732c855bc66f8d631f3c5f85 Mon Sep 17 00:00:00 2001 From: Yogesh Bhatt Date: Sat, 9 Mar 2024 02:21:00 +0530 Subject: [PATCH 172/306] fix: handle potential 'undefined' object issue --- .../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 b30c9c9967c8..1c3d8dd650c0 100644 --- a/src/pages/settings/Profile/PersonalDetails/StateSelectionPage.tsx +++ b/src/pages/settings/Profile/PersonalDetails/StateSelectionPage.tsx @@ -59,7 +59,7 @@ function StateSelectionPage() { const backTo = params?.backTo ?? ''; // Determine navigation action based on "backTo" presence and route stack length. - if (navigation.getState().routes.length === 1) { + if (navigation.getState()?.routes.length === 1) { // If this is the only page in the navigation stack (examples include direct navigation to this page via URL or page reload). if (_.isEmpty(backTo)) { // No "backTo": default back navigation. From 3a3c767746c199d53b2791ec1d786cb5fc7ff200 Mon Sep 17 00:00:00 2001 From: Yogesh Bhatt <65986357+ygshbht@users.noreply.github.com> Date: Sat, 9 Mar 2024 02:25:20 +0530 Subject: [PATCH 173/306] Typo fix src/components/StateSelector.tsx Co-authored-by: Vit Horacek <36083550+mountiny@users.noreply.github.com> --- src/components/StateSelector.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/components/StateSelector.tsx b/src/components/StateSelector.tsx index 9ddf2573f857..54a2066c52fa 100644 --- a/src/components/StateSelector.tsx +++ b/src/components/StateSelector.tsx @@ -15,7 +15,7 @@ import MenuItemWithTopDescription from './MenuItemWithTopDescription'; type State = keyof typeof COMMON_CONST.STATES; type StateSelectorProps = { - /** Form error text. e.g when no country is selected */ + /** Form error text. e.g when no state is selected */ errorText?: MaybePhraseKey; /** Current selected state */ From c56f8d52e6e0627f114867e6f2e65c3b44e1983e Mon Sep 17 00:00:00 2001 From: Yogesh Bhatt <65986357+ygshbht@users.noreply.github.com> Date: Sat, 9 Mar 2024 02:26:20 +0530 Subject: [PATCH 174/306] Format src/libs/Url.ts Co-authored-by: Vit Horacek <36083550+mountiny@users.noreply.github.com> --- src/libs/Url.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/libs/Url.ts b/src/libs/Url.ts index 7e028aded60c..1f402fdfc131 100644 --- a/src/libs/Url.ts +++ b/src/libs/Url.ts @@ -45,8 +45,8 @@ function hasSameExpensifyOrigin(url1: string, url2: string): boolean { * Appends or updates a query parameter in a given URL. */ function appendParam(url: string, paramName: string, paramValue: string) { + // If parameter exists, replace it if (url.includes(`${paramName}=`)) { - // If parameter exists, replace it const regex = new RegExp(`${paramName}=([^&]*)`); return url.replace(regex, `${paramName}=${paramValue}`); } From 470be54fc13bebb1596626989db54a3545c27688 Mon Sep 17 00:00:00 2001 From: Yogesh Bhatt <65986357+ygshbht@users.noreply.github.com> Date: Sat, 9 Mar 2024 02:26:48 +0530 Subject: [PATCH 175/306] Format src/libs/Url.ts Co-authored-by: Vit Horacek <36083550+mountiny@users.noreply.github.com> --- src/libs/Url.ts | 1 + 1 file changed, 1 insertion(+) diff --git a/src/libs/Url.ts b/src/libs/Url.ts index 1f402fdfc131..4e3282e7bdb3 100644 --- a/src/libs/Url.ts +++ b/src/libs/Url.ts @@ -50,6 +50,7 @@ function appendParam(url: string, paramName: string, paramValue: string) { 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}`; From 1670b66448c4d92a2eba9f5025ef11bf258c1194 Mon Sep 17 00:00:00 2001 From: Yogesh Bhatt <65986357+ygshbht@users.noreply.github.com> Date: Sat, 9 Mar 2024 02:27:25 +0530 Subject: [PATCH 176/306] Format src/pages/settings/Profile/PersonalDetails/StateSelectionPage.tsx Co-authored-by: Vit Horacek <36083550+mountiny@users.noreply.github.com> --- .../settings/Profile/PersonalDetails/StateSelectionPage.tsx | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/src/pages/settings/Profile/PersonalDetails/StateSelectionPage.tsx b/src/pages/settings/Profile/PersonalDetails/StateSelectionPage.tsx index 1c3d8dd650c0..275400b27cc0 100644 --- a/src/pages/settings/Profile/PersonalDetails/StateSelectionPage.tsx +++ b/src/pages/settings/Profile/PersonalDetails/StateSelectionPage.tsx @@ -28,9 +28,7 @@ function StateSelectionPage() { const {translate} = useLocalize(); const [searchValue, setSearchValue] = useState(''); - - const params = route.params as RouteParams | undefined; // Type assertion - + const params = route.params as RouteParams | undefined; const currentState = params?.state; const label = params?.label; From 5d2ff1eba9382350854d3512db85d099faca37eb Mon Sep 17 00:00:00 2001 From: Yogesh Bhatt <65986357+ygshbht@users.noreply.github.com> Date: Sat, 9 Mar 2024 02:27:53 +0530 Subject: [PATCH 177/306] Format src/pages/settings/Profile/PersonalDetails/AddressPage.tsx Co-authored-by: Vit Horacek <36083550+mountiny@users.noreply.github.com> --- src/pages/settings/Profile/PersonalDetails/AddressPage.tsx | 1 + 1 file changed, 1 insertion(+) diff --git a/src/pages/settings/Profile/PersonalDetails/AddressPage.tsx b/src/pages/settings/Profile/PersonalDetails/AddressPage.tsx index 77d551b283ec..7706b839b18a 100644 --- a/src/pages/settings/Profile/PersonalDetails/AddressPage.tsx +++ b/src/pages/settings/Profile/PersonalDetails/AddressPage.tsx @@ -48,6 +48,7 @@ function AddressPage({privatePersonalDetails, route}: AddressPageProps) { usePrivatePersonalDetails(); const {translate} = useLocalize(); const address = useMemo(() => privatePersonalDetails?.address, [privatePersonalDetails]); + const countryFromUrlTemp = route?.params?.country; // Check if country is valid const countryFromUrl = CONST.ALL_COUNTRIES[countryFromUrlTemp as keyof typeof CONST.ALL_COUNTRIES] ? countryFromUrlTemp : ''; From 18717ea0f1072ae10b5216481903a4415a84e9a5 Mon Sep 17 00:00:00 2001 From: Yogesh Bhatt Date: Sat, 9 Mar 2024 02:38:28 +0530 Subject: [PATCH 178/306] Comment for function useGeographicalStateFromRoute --- src/hooks/useGeographicalStateFromRoute.ts | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/hooks/useGeographicalStateFromRoute.ts b/src/hooks/useGeographicalStateFromRoute.ts index 39d3cab5f681..5015db12d458 100644 --- a/src/hooks/useGeographicalStateFromRoute.ts +++ b/src/hooks/useGeographicalStateFromRoute.ts @@ -5,6 +5,10 @@ import {CONST as COMMON_CONST} from 'expensify-common/lib/CONST'; type CustomParamList = ParamListBase & Record>; type State = keyof typeof COMMON_CONST.STATES; +/** + * Extracts the 'state' (default) query parameter from the route/ url and validates it against COMMON_CONST.STATES, returning its ISO code or `undefined`. + * Example: const stateISO = useGeographicalStateFromRoute(); // Assuming 'state' param is 'CA' or another valid state, returns the corresponding ISO code or `undefined` if invalid. + */ export default function useGeographicalStateFromRoute(stateParamName = 'state'): State | undefined { const route = useRoute>(); const stateFromUrlTemp = route.params?.[stateParamName] as string | undefined; From 3ba97a550a07ce38adbf5e397bba3e56907552b1 Mon Sep 17 00:00:00 2001 From: Yogesh Bhatt Date: Sat, 9 Mar 2024 03:58:19 +0530 Subject: [PATCH 179/306] hash append for StateSelector edge cases --- src/components/StateSelector.tsx | 12 +++++++++++- src/hooks/useGeographicalStateFromRoute.ts | 7 ++++++- .../Profile/PersonalDetails/StateSelectionPage.tsx | 7 +++++-- 3 files changed, 22 insertions(+), 4 deletions(-) diff --git a/src/components/StateSelector.tsx b/src/components/StateSelector.tsx index 54a2066c52fa..41dcc21bf47c 100644 --- a/src/components/StateSelector.tsx +++ b/src/components/StateSelector.tsx @@ -1,3 +1,5 @@ +import {useRoute} from '@react-navigation/native'; +import type {ParamListBase, RouteProp} from '@react-navigation/native'; import {CONST as COMMON_CONST} from 'expensify-common/lib/CONST'; import React, {useEffect, useState} from 'react'; import type {ForwardedRef} from 'react'; @@ -12,6 +14,8 @@ import FormHelpMessage from './FormHelpMessage'; import type {MenuItemProps} from './MenuItem'; import MenuItemWithTopDescription from './MenuItemWithTopDescription'; +type CustomParamList = ParamListBase & Record>; + type State = keyof typeof COMMON_CONST.STATES; type StateSelectorProps = { @@ -40,6 +44,12 @@ function StateSelector({errorText, shouldUseStateFromUrl = true, value: stateCod const stateFromUrl = useGeographicalStateFromRoute(); const [stateToDisplay, setStateToDisplay] = useState(''); + /** + * See {@link module:src/pages/settings/Profile/PersonalDetails/StateSelectionPage.tsx#withHash} for more information. + */ + const route = useRoute>(); + const rawStateFromUrl = route.params?.state as string | undefined; + useEffect(() => { if (!shouldUseStateFromUrl || !stateFromUrl) { return; @@ -52,7 +62,7 @@ function StateSelector({errorText, shouldUseStateFromUrl = true, value: stateCod setStateToDisplay(stateFromUrl); // eslint-disable-next-line react-hooks/exhaustive-deps - }, [stateFromUrl, shouldUseStateFromUrl]); + }, [rawStateFromUrl, shouldUseStateFromUrl]); useEffect(() => { if (!stateCode) { diff --git a/src/hooks/useGeographicalStateFromRoute.ts b/src/hooks/useGeographicalStateFromRoute.ts index 5015db12d458..6ce67c0ef93a 100644 --- a/src/hooks/useGeographicalStateFromRoute.ts +++ b/src/hooks/useGeographicalStateFromRoute.ts @@ -5,6 +5,11 @@ import {CONST as COMMON_CONST} from 'expensify-common/lib/CONST'; type CustomParamList = ParamListBase & Record>; type State = keyof typeof COMMON_CONST.STATES; +/** + * See {@link module:src/pages/settings/Profile/PersonalDetails/StateSelectionPage.tsx#withHash} for more information. + */ +const removeHash = (arg: string): string => arg.replace(/-hash-.*$/, ''); + /** * Extracts the 'state' (default) query parameter from the route/ url and validates it against COMMON_CONST.STATES, returning its ISO code or `undefined`. * Example: const stateISO = useGeographicalStateFromRoute(); // Assuming 'state' param is 'CA' or another valid state, returns the corresponding ISO code or `undefined` if invalid. @@ -16,5 +21,5 @@ export default function useGeographicalStateFromRoute(stateParamName = 'state'): if (!stateFromUrlTemp) { return; } - return COMMON_CONST.STATES[stateFromUrlTemp as State].stateISO; + return COMMON_CONST.STATES[removeHash(stateFromUrlTemp) as State].stateISO; } diff --git a/src/pages/settings/Profile/PersonalDetails/StateSelectionPage.tsx b/src/pages/settings/Profile/PersonalDetails/StateSelectionPage.tsx index 275400b27cc0..1a9a0fab9069 100644 --- a/src/pages/settings/Profile/PersonalDetails/StateSelectionPage.tsx +++ b/src/pages/settings/Profile/PersonalDetails/StateSelectionPage.tsx @@ -56,6 +56,9 @@ function StateSelectionPage() { (option: CountryData) => { const backTo = params?.backTo ?? ''; + // Add hash to param for rare cases, such as in ReimbursementAccountPage (currentStep = CONST.BANK_ACCOUNT.STEP.COMPANY), when the URL on the form page (which has the StateSelector component) already includes a state param. If the form then updates the StateInput with state data from another source and the user attempts to use StateSelector to select the same state present in the URL, it will cause the StateSelector not to detect the state change, as the URL remains the same. + const withHash = (arg: string): string => `${arg}-hash-${Math.random().toString(36).substring(2, 8)}`; + // Determine navigation action based on "backTo" presence and route stack length. if (navigation.getState()?.routes.length === 1) { // If this is the only page in the navigation stack (examples include direct navigation to this page via URL or page reload). @@ -64,11 +67,11 @@ function StateSelectionPage() { Navigation.goBack(); } else { // "backTo" provided: navigate back to "backTo" with state parameter. - Navigation.goBack(appendParam(backTo, 'state', option.value) as Route); + Navigation.goBack(appendParam(backTo, 'state', withHash(option.value)) as Route); } } else if (!_.isEmpty(backTo)) { // Most common case: Navigation stack has multiple routes and "backTo" is defined: navigate to "backTo" with state parameter. - Navigation.navigate(appendParam(backTo, 'state', option.value) as Route); + Navigation.navigate(appendParam(backTo, 'state', withHash(option.value)) as Route); } else { // This is a fallback block and should never execute if StateSelector is correctly appending the "backTo" route. // Navigation stack has multiple routes but no "backTo" defined: default back navigation. From 0dc7f49ccd5d2169d387c1b2267d7463e0b35c6e Mon Sep 17 00:00:00 2001 From: Yogesh Bhatt Date: Sat, 9 Mar 2024 04:32:25 +0530 Subject: [PATCH 180/306] Comment update useGeographicalStateFromRoute --- src/hooks/useGeographicalStateFromRoute.ts | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/hooks/useGeographicalStateFromRoute.ts b/src/hooks/useGeographicalStateFromRoute.ts index 6ce67c0ef93a..69482b8c3a3b 100644 --- a/src/hooks/useGeographicalStateFromRoute.ts +++ b/src/hooks/useGeographicalStateFromRoute.ts @@ -12,7 +12,10 @@ const removeHash = (arg: string): string => arg.replace(/-hash-.*$/, ''); /** * Extracts the 'state' (default) query parameter from the route/ url and validates it against COMMON_CONST.STATES, returning its ISO code or `undefined`. - * Example: const stateISO = useGeographicalStateFromRoute(); // Assuming 'state' param is 'CA' or another valid state, returns the corresponding ISO code or `undefined` if invalid. + * Example 1: Url: https://dev.new.expensify.com:8082/settings/profile/address?state=MO Returns: MO + * Example 2: Url: https://dev.new.expensify.com:8082/settings/profile/address?state=ASDF Returns: undefined + * Example 3: Url: https://dev.new.expensify.com:8082/settings/profile/address Returns: undefined + * Example 4: Url: https://dev.new.expensify.com:8082/settings/profile/address?state=MO-hash-a12341 Returns: MO */ export default function useGeographicalStateFromRoute(stateParamName = 'state'): State | undefined { const route = useRoute>(); From 57bcee217ff3a01861f0a0f8ac6a09bba7a4bfc3 Mon Sep 17 00:00:00 2001 From: Yogesh Bhatt Date: Sat, 9 Mar 2024 06:19:39 +0530 Subject: [PATCH 181/306] Add StateSelector to MoneyRequest Navigation stack to work for /send/new/add-debit-card --- src/ROUTES.ts | 10 ++++++++++ src/SCREENS.ts | 1 + src/components/StateSelector.tsx | 10 ++++++++-- .../Navigation/AppNavigator/ModalStackNavigators.tsx | 1 + src/libs/Navigation/linkingConfig/config.ts | 1 + src/pages/settings/Wallet/AddDebitCardPage.tsx | 5 +++++ 6 files changed, 26 insertions(+), 2 deletions(-) diff --git a/src/ROUTES.ts b/src/ROUTES.ts index 371691b7b0fd..a1b28c33d51b 100644 --- a/src/ROUTES.ts +++ b/src/ROUTES.ts @@ -423,6 +423,16 @@ const ROUTES = { getRoute: (iouType: ValueOf, transactionID: string, reportID: string) => `create/${iouType}/start/${transactionID}/${reportID}/scan` as const, }, + MONEY_REQUEST_STATE_SELECTOR: { + route: 'moneyrequest/state', + + getRoute: (state?: string, backTo?: string, label?: string) => + `${getUrlWithBackToParam(`moneyrequest/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, + }, IOU_REQUEST: 'request/new', IOU_SEND: 'send/new', IOU_SEND_ADD_BANK_ACCOUNT: 'send/new/add-bank-account', diff --git a/src/SCREENS.ts b/src/SCREENS.ts index 5121068f273f..f04b521b9876 100644 --- a/src/SCREENS.ts +++ b/src/SCREENS.ts @@ -161,6 +161,7 @@ const SCREENS = { EDIT_WAYPOINT: 'Money_Request_Edit_Waypoint', DISTANCE: 'Money_Request_Distance', RECEIPT: 'Money_Request_Receipt', + STATE_SELECTOR: 'Money_Request_State_Selector', }, IOU_SEND: { diff --git a/src/components/StateSelector.tsx b/src/components/StateSelector.tsx index 41dcc21bf47c..9de9c746c415 100644 --- a/src/components/StateSelector.tsx +++ b/src/components/StateSelector.tsx @@ -36,9 +36,15 @@ type StateSelectorProps = { /** whether to use state from url, for cases when url value is passed from parent */ shouldUseStateFromUrl?: boolean; + + /** object to get route details from */ + stateSelectorRoute?: typeof ROUTES.SETTINGS_ADDRESS_STATE | typeof ROUTES.MONEY_REQUEST_STATE_SELECTOR; }; -function StateSelector({errorText, shouldUseStateFromUrl = true, value: stateCode, label, onInputChange, wrapperStyle}: StateSelectorProps, ref: ForwardedRef) { +function StateSelector( + {errorText, shouldUseStateFromUrl = true, value: stateCode, label, onInputChange, wrapperStyle, stateSelectorRoute = ROUTES.SETTINGS_ADDRESS_STATE}: StateSelectorProps, + ref: ForwardedRef, +) { const styles = useThemeStyles(); const {translate} = useLocalize(); const stateFromUrl = useGeographicalStateFromRoute(); @@ -93,7 +99,7 @@ function StateSelector({errorText, shouldUseStateFromUrl = true, value: stateCod description={label || translate('common.state')} onPress={() => { const activeRoute = Navigation.getActiveRoute(); - Navigation.navigate(ROUTES.SETTINGS_ADDRESS_STATE.getRoute(stateCode, activeRoute, label)); + Navigation.navigate(stateSelectorRoute.getRoute(stateCode, activeRoute, label)); }} wrapperStyle={wrapperStyle} /> diff --git a/src/libs/Navigation/AppNavigator/ModalStackNavigators.tsx b/src/libs/Navigation/AppNavigator/ModalStackNavigators.tsx index b030165aca11..4ae6ddb03434 100644 --- a/src/libs/Navigation/AppNavigator/ModalStackNavigators.tsx +++ b/src/libs/Navigation/AppNavigator/ModalStackNavigators.tsx @@ -106,6 +106,7 @@ const MoneyRequestModalStackNavigator = createModalStackNavigator require('../../../pages/iou/MoneyRequestWaypointPage').default as React.ComponentType, [SCREENS.MONEY_REQUEST.DISTANCE]: () => require('../../../pages/iou/NewDistanceRequestPage').default as React.ComponentType, [SCREENS.MONEY_REQUEST.RECEIPT]: () => require('../../../pages/EditRequestReceiptPage').default as React.ComponentType, + [SCREENS.MONEY_REQUEST.STATE_SELECTOR]: () => require('../../../pages/settings/Profile/PersonalDetails/StateSelectionPage').default as React.ComponentType, }); const SplitDetailsModalStackNavigator = createModalStackNavigator({ diff --git a/src/libs/Navigation/linkingConfig/config.ts b/src/libs/Navigation/linkingConfig/config.ts index 3c00bd3c453c..cc5ae141b5a4 100644 --- a/src/libs/Navigation/linkingConfig/config.ts +++ b/src/libs/Navigation/linkingConfig/config.ts @@ -490,6 +490,7 @@ const config: LinkingOptions['config'] = { [SCREENS.IOU_SEND.ENABLE_PAYMENTS]: ROUTES.IOU_SEND_ENABLE_PAYMENTS, [SCREENS.IOU_SEND.ADD_BANK_ACCOUNT]: ROUTES.IOU_SEND_ADD_BANK_ACCOUNT, [SCREENS.IOU_SEND.ADD_DEBIT_CARD]: ROUTES.IOU_SEND_ADD_DEBIT_CARD, + [SCREENS.MONEY_REQUEST.STATE_SELECTOR]: {path: ROUTES.MONEY_REQUEST_STATE_SELECTOR.route, exact: true}, }, }, [SCREENS.RIGHT_MODAL.SPLIT_DETAILS]: { diff --git a/src/pages/settings/Wallet/AddDebitCardPage.tsx b/src/pages/settings/Wallet/AddDebitCardPage.tsx index 99f2a90abd8e..0beb3c16018d 100644 --- a/src/pages/settings/Wallet/AddDebitCardPage.tsx +++ b/src/pages/settings/Wallet/AddDebitCardPage.tsx @@ -1,3 +1,4 @@ +import {useRoute} from '@react-navigation/native'; import React, {useEffect, useRef} from 'react'; import {View} from 'react-native'; import type {OnyxEntry} from 'react-native-onyx'; @@ -22,6 +23,8 @@ import * as ValidationUtils from '@libs/ValidationUtils'; import * as PaymentMethods from '@userActions/PaymentMethods'; import CONST from '@src/CONST'; import ONYXKEYS from '@src/ONYXKEYS'; +import ROUTES from '@src/ROUTES'; +import SCREENS from '@src/SCREENS'; import type {AddDebitCardForm} from '@src/types/form'; import INPUT_IDS from '@src/types/form/AddDebitCardForm'; @@ -58,6 +61,7 @@ function DebitCardPage({formData}: DebitCardPageProps) { const {translate} = useLocalize(); const prevFormDataSetupComplete = usePrevious(!!formData?.setupComplete); const nameOnCardRef = useRef(null); + const route = useRoute(); /** * Reset the form values on the mount and unmount so that old errors don't show when this form is displayed again. @@ -200,6 +204,7 @@ function DebitCardPage({formData}: DebitCardPageProps) { /> From 9ffea05a449afe435ee0bee1ece0e8202b9f918a Mon Sep 17 00:00:00 2001 From: Yogesh Bhatt <65986357+ygshbht@users.noreply.github.com> Date: Sat, 9 Mar 2024 06:30:49 +0530 Subject: [PATCH 182/306] Formatting src/pages/settings/Profile/PersonalDetails/AddressPage.tsx Co-authored-by: Vit Horacek <36083550+mountiny@users.noreply.github.com> --- src/pages/settings/Profile/PersonalDetails/AddressPage.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/pages/settings/Profile/PersonalDetails/AddressPage.tsx b/src/pages/settings/Profile/PersonalDetails/AddressPage.tsx index 7706b839b18a..ae724ce218ad 100644 --- a/src/pages/settings/Profile/PersonalDetails/AddressPage.tsx +++ b/src/pages/settings/Profile/PersonalDetails/AddressPage.tsx @@ -48,8 +48,8 @@ function AddressPage({privatePersonalDetails, route}: AddressPageProps) { usePrivatePersonalDetails(); const {translate} = useLocalize(); const address = useMemo(() => privatePersonalDetails?.address, [privatePersonalDetails]); - const countryFromUrlTemp = route?.params?.country; + // Check if country is valid const countryFromUrl = CONST.ALL_COUNTRIES[countryFromUrlTemp as keyof typeof CONST.ALL_COUNTRIES] ? countryFromUrlTemp : ''; const stateFromUrl = useGeographicalStateFromRoute(); From d25904ca74e906302784150dd143bdbf7d0ebb33 Mon Sep 17 00:00:00 2001 From: Yogesh Bhatt <65986357+ygshbht@users.noreply.github.com> Date: Sat, 9 Mar 2024 06:31:30 +0530 Subject: [PATCH 183/306] Commnet udpate src/ROUTES.ts Co-authored-by: Vit Horacek <36083550+mountiny@users.noreply.github.com> --- src/ROUTES.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/ROUTES.ts b/src/ROUTES.ts index a1b28c33d51b..9c697f4f4cfd 100644 --- a/src/ROUTES.ts +++ b/src/ROUTES.ts @@ -136,7 +136,7 @@ const ROUTES = { 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 + // the label param can be an empty string so we cannot use a nullish ?? operator // eslint-disable-next-line @typescript-eslint/prefer-nullish-coalescing label ? `${backTo || state ? '&' : '?'}label=${encodeURIComponent(label)}` : '' }` as const, From 81f452c650071377cbaa17ab74b215ab79835f9a Mon Sep 17 00:00:00 2001 From: Yogesh Bhatt Date: Sat, 9 Mar 2024 06:33:01 +0530 Subject: [PATCH 184/306] Comment update ROUTES.ts --- src/ROUTES.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/ROUTES.ts b/src/ROUTES.ts index 9c697f4f4cfd..de06c07a0834 100644 --- a/src/ROUTES.ts +++ b/src/ROUTES.ts @@ -428,7 +428,7 @@ const ROUTES = { getRoute: (state?: string, backTo?: string, label?: string) => `${getUrlWithBackToParam(`moneyrequest/state${state ? `?state=${encodeURIComponent(state)}` : ''}`, backTo)}${ - // Nullish operator ?? doesnt seem to be a replacement for || here + // the label param can be an empty string so we cannot use a nullish ?? operator // eslint-disable-next-line @typescript-eslint/prefer-nullish-coalescing label ? `${backTo || state ? '&' : '?'}label=${encodeURIComponent(label)}` : '' }` as const, From dc35055073b34f237c9d4d6a3c589bf53ac8f892 Mon Sep 17 00:00:00 2001 From: Yogesh Bhatt <65986357+ygshbht@users.noreply.github.com> Date: Tue, 12 Mar 2024 03:11:46 +0530 Subject: [PATCH 185/306] Example update src/hooks/useGeographicalStateFromRoute.ts Co-authored-by: Vit Horacek <36083550+mountiny@users.noreply.github.com> --- src/hooks/useGeographicalStateFromRoute.ts | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/hooks/useGeographicalStateFromRoute.ts b/src/hooks/useGeographicalStateFromRoute.ts index 69482b8c3a3b..bddc2b5c9a07 100644 --- a/src/hooks/useGeographicalStateFromRoute.ts +++ b/src/hooks/useGeographicalStateFromRoute.ts @@ -12,10 +12,10 @@ const removeHash = (arg: string): string => arg.replace(/-hash-.*$/, ''); /** * Extracts the 'state' (default) query parameter from the route/ url and validates it against COMMON_CONST.STATES, returning its ISO code or `undefined`. - * Example 1: Url: https://dev.new.expensify.com:8082/settings/profile/address?state=MO Returns: MO - * Example 2: Url: https://dev.new.expensify.com:8082/settings/profile/address?state=ASDF Returns: undefined - * Example 3: Url: https://dev.new.expensify.com:8082/settings/profile/address Returns: undefined - * Example 4: Url: https://dev.new.expensify.com:8082/settings/profile/address?state=MO-hash-a12341 Returns: MO + * Example 1: Url: https://new.expensify.com/settings/profile/address?state=MO Returns: MO + * Example 2: Url: https://new.expensify.com/settings/profile/address?state=ASDF Returns: undefined + * Example 3: Url: https://new.expensify.com/settings/profile/address Returns: undefined + * Example 4: Url: https://new.expensify.com/settings/profile/address?state=MO-hash-a12341 Returns: MO */ export default function useGeographicalStateFromRoute(stateParamName = 'state'): State | undefined { const route = useRoute>(); From 78afcd5da67d02e4a51518b2edc15319ed0bf967 Mon Sep 17 00:00:00 2001 From: Yogesh Bhatt Date: Tue, 12 Mar 2024 03:15:29 +0530 Subject: [PATCH 186/306] Refactor linking config StateSelector --- src/libs/Navigation/linkingConfig/config.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/libs/Navigation/linkingConfig/config.ts b/src/libs/Navigation/linkingConfig/config.ts index 34526091e471..787a6054db80 100644 --- a/src/libs/Navigation/linkingConfig/config.ts +++ b/src/libs/Navigation/linkingConfig/config.ts @@ -490,10 +490,10 @@ const config: LinkingOptions['config'] = { [SCREENS.MONEY_REQUEST.CURRENCY]: ROUTES.MONEY_REQUEST_CURRENCY.route, [SCREENS.MONEY_REQUEST.RECEIPT]: ROUTES.MONEY_REQUEST_RECEIPT.route, [SCREENS.MONEY_REQUEST.DISTANCE]: ROUTES.MONEY_REQUEST_DISTANCE.route, + [SCREENS.MONEY_REQUEST.STATE_SELECTOR]: {path: ROUTES.MONEY_REQUEST_STATE_SELECTOR.route, exact: true}, [SCREENS.IOU_SEND.ENABLE_PAYMENTS]: ROUTES.IOU_SEND_ENABLE_PAYMENTS, [SCREENS.IOU_SEND.ADD_BANK_ACCOUNT]: ROUTES.IOU_SEND_ADD_BANK_ACCOUNT, [SCREENS.IOU_SEND.ADD_DEBIT_CARD]: ROUTES.IOU_SEND_ADD_DEBIT_CARD, - [SCREENS.MONEY_REQUEST.STATE_SELECTOR]: {path: ROUTES.MONEY_REQUEST_STATE_SELECTOR.route, exact: true}, }, }, [SCREENS.RIGHT_MODAL.SPLIT_DETAILS]: { From b52b28c227ee0e69d0dd9e4586b05548e2d3f6e7 Mon Sep 17 00:00:00 2001 From: Etotaziba Olei Date: Tue, 12 Mar 2024 10:29:14 +0100 Subject: [PATCH 187/306] check and return if same tax rate is selected --- 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 0498c98b087a..91694f5cefc3 100644 --- a/src/pages/EditRequestPage.js +++ b/src/pages/EditRequestPage.js @@ -143,7 +143,7 @@ function EditRequestPage({report, route, policy, policyCategories, policyTags, p (transactionChanges) => { const newTaxCode = transactionChanges.data.code; - if (!newTaxCode) { + if (newTaxCode === undefined || newTaxCode === TransactionUtils.getTaxCode(transaction)) { Navigation.dismissModal(); return; } From 5626316a710f8e0024d2553d7e1fcb94211c5c25 Mon Sep 17 00:00:00 2001 From: Etotaziba Olei Date: Tue, 12 Mar 2024 11:29:56 +0100 Subject: [PATCH 188/306] add option for transaction draft --- src/libs/actions/IOU.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/libs/actions/IOU.ts b/src/libs/actions/IOU.ts index b630e94a0742..3b6b306c08f3 100644 --- a/src/libs/actions/IOU.ts +++ b/src/libs/actions/IOU.ts @@ -4119,8 +4119,8 @@ function setMoneyRequestTaxRate(transactionID: string, taxRate: TaxRate) { Onyx.merge(`${ONYXKEYS.COLLECTION.TRANSACTION_DRAFT}${transactionID}`, {taxRate}); } -function setMoneyRequestTaxAmount(transactionID: string, taxAmount: number) { - Onyx.merge(`${ONYXKEYS.COLLECTION.TRANSACTION_DRAFT}${transactionID}`, {taxAmount}); +function setMoneyRequestTaxAmount(transactionID: string, taxAmount: number, isDraft: boolean) { + Onyx.merge(`${isDraft ? ONYXKEYS.COLLECTION.TRANSACTION_DRAFT : ONYXKEYS.COLLECTION.TRANSACTION}${transactionID}`, {taxAmount}); } function setMoneyRequestBillable(billable: boolean) { From 9ecc9838099ceae49f1512ffb80cfc74f3d7e86c Mon Sep 17 00:00:00 2001 From: Etotaziba Olei Date: Tue, 12 Mar 2024 11:31:40 +0100 Subject: [PATCH 189/306] optimistically update tax amount when expense amount is edited --- src/pages/EditRequestPage.js | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/pages/EditRequestPage.js b/src/pages/EditRequestPage.js index 91694f5cefc3..86cd99ed276b 100644 --- a/src/pages/EditRequestPage.js +++ b/src/pages/EditRequestPage.js @@ -77,7 +77,7 @@ const defaultProps = { const getTaxAmount = (transactionAmount, transactionTaxCode, taxRates) => { const percentage = (transactionTaxCode ? taxRates.taxes[transactionTaxCode].value : taxRates.defaultValue) || ''; - return CurrencyUtils.convertToBackendAmount(Number.parseFloat(TransactionUtils.calculateTaxAmount(percentage, Math.abs(transactionAmount)))); + return CurrencyUtils.convertToBackendAmount(Number.parseFloat(TransactionUtils.calculateTaxAmount(percentage, transactionAmount))); }; function EditRequestPage({report, route, policy, policyCategories, policyTags, parentReportActions, transaction}) { @@ -163,7 +163,8 @@ function EditRequestPage({report, route, policy, policyCategories, policyTags, p Navigation.dismissModal(); return; } - + // optimisticall set tax amount. + IOU.setMoneyRequestTaxAmount(transaction.transactionID, getTaxAmount(-newAmount, transactionTaxCode, taxRates)); IOU.updateMoneyRequestAmountAndCurrency(transaction.transactionID, report.reportID, newCurrency, newAmount, policy, policyTags, policyCategories); Navigation.dismissModal(); }, From dea2b668a900b5940d802d9c75aea19866da6a8c Mon Sep 17 00:00:00 2001 From: Etotaziba Olei Date: Tue, 12 Mar 2024 11:32:40 +0100 Subject: [PATCH 190/306] add isDraft option for IOU.setMoneyRequestTaxAmount --- src/pages/iou/request/step/IOURequestStepTaxAmountPage.js | 2 +- src/pages/iou/request/step/IOURequestStepTaxRatePage.js | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/pages/iou/request/step/IOURequestStepTaxAmountPage.js b/src/pages/iou/request/step/IOURequestStepTaxAmountPage.js index d28d350677fd..a43d3bc01c09 100644 --- a/src/pages/iou/request/step/IOURequestStepTaxAmountPage.js +++ b/src/pages/iou/request/step/IOURequestStepTaxAmountPage.js @@ -112,7 +112,7 @@ function IOURequestStepTaxAmountPage({ const updateTaxAmount = (currentAmount) => { isSaveButtonPressed.current = true; const amountInSmallestCurrencyUnits = CurrencyUtils.convertToBackendAmount(Number.parseFloat(currentAmount.amount)); - IOU.setMoneyRequestTaxAmount(transactionID, amountInSmallestCurrencyUnits); + IOU.setMoneyRequestTaxAmount(transactionID, amountInSmallestCurrencyUnits, true); IOU.setMoneyRequestCurrency_temporaryForRefactor(transactionID, currency || CONST.CURRENCY.USD, true); diff --git a/src/pages/iou/request/step/IOURequestStepTaxRatePage.js b/src/pages/iou/request/step/IOURequestStepTaxRatePage.js index f374b6986ef2..d4a2c10d24b0 100644 --- a/src/pages/iou/request/step/IOURequestStepTaxRatePage.js +++ b/src/pages/iou/request/step/IOURequestStepTaxRatePage.js @@ -71,7 +71,7 @@ function IOURequestStepTaxRatePage({ 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); + IOU.setMoneyRequestTaxAmount(transaction.transactionID, amountInSmallestCurrencyUnits, true); Navigation.goBack(backTo); }; From 72e7b681d6234096fd796317845919537e886f8c Mon Sep 17 00:00:00 2001 From: Etotaziba Olei Date: Tue, 12 Mar 2024 11:42:11 +0100 Subject: [PATCH 191/306] add useCallback missing deps --- 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 86cd99ed276b..7fcfab735248 100644 --- a/src/pages/EditRequestPage.js +++ b/src/pages/EditRequestPage.js @@ -168,7 +168,7 @@ function EditRequestPage({report, route, policy, policyCategories, policyTags, p IOU.updateMoneyRequestAmountAndCurrency(transaction.transactionID, report.reportID, newCurrency, newAmount, policy, policyTags, policyCategories); Navigation.dismissModal(); }, - [transaction, report, policy, policyTags, policyCategories], + [transaction, report, policy, policyTags, policyCategories, taxRates, transactionTaxCode], ); const saveTag = useCallback( From ecc39530deb63835402a3163ac028d2da3fd5164 Mon Sep 17 00:00:00 2001 From: Yogesh Bhatt Date: Wed, 13 Mar 2024 02:59:18 +0530 Subject: [PATCH 192/306] Revert "hash append for StateSelector edge cases" This reverts commit 3ba97a550a07ce38adbf5e397bba3e56907552b1. --- src/components/StateSelector.tsx | 12 +----------- src/hooks/useGeographicalStateFromRoute.ts | 7 +------ .../Profile/PersonalDetails/StateSelectionPage.tsx | 7 ++----- 3 files changed, 4 insertions(+), 22 deletions(-) diff --git a/src/components/StateSelector.tsx b/src/components/StateSelector.tsx index 9de9c746c415..3aff71cd9f90 100644 --- a/src/components/StateSelector.tsx +++ b/src/components/StateSelector.tsx @@ -1,5 +1,3 @@ -import {useRoute} from '@react-navigation/native'; -import type {ParamListBase, RouteProp} from '@react-navigation/native'; import {CONST as COMMON_CONST} from 'expensify-common/lib/CONST'; import React, {useEffect, useState} from 'react'; import type {ForwardedRef} from 'react'; @@ -14,8 +12,6 @@ import FormHelpMessage from './FormHelpMessage'; import type {MenuItemProps} from './MenuItem'; import MenuItemWithTopDescription from './MenuItemWithTopDescription'; -type CustomParamList = ParamListBase & Record>; - type State = keyof typeof COMMON_CONST.STATES; type StateSelectorProps = { @@ -50,12 +46,6 @@ function StateSelector( const stateFromUrl = useGeographicalStateFromRoute(); const [stateToDisplay, setStateToDisplay] = useState(''); - /** - * See {@link module:src/pages/settings/Profile/PersonalDetails/StateSelectionPage.tsx#withHash} for more information. - */ - const route = useRoute>(); - const rawStateFromUrl = route.params?.state as string | undefined; - useEffect(() => { if (!shouldUseStateFromUrl || !stateFromUrl) { return; @@ -68,7 +58,7 @@ function StateSelector( setStateToDisplay(stateFromUrl); // eslint-disable-next-line react-hooks/exhaustive-deps - }, [rawStateFromUrl, shouldUseStateFromUrl]); + }, [stateFromUrl, shouldUseStateFromUrl]); useEffect(() => { if (!stateCode) { diff --git a/src/hooks/useGeographicalStateFromRoute.ts b/src/hooks/useGeographicalStateFromRoute.ts index bddc2b5c9a07..3e85bfc2a368 100644 --- a/src/hooks/useGeographicalStateFromRoute.ts +++ b/src/hooks/useGeographicalStateFromRoute.ts @@ -5,11 +5,6 @@ import {CONST as COMMON_CONST} from 'expensify-common/lib/CONST'; type CustomParamList = ParamListBase & Record>; type State = keyof typeof COMMON_CONST.STATES; -/** - * See {@link module:src/pages/settings/Profile/PersonalDetails/StateSelectionPage.tsx#withHash} for more information. - */ -const removeHash = (arg: string): string => arg.replace(/-hash-.*$/, ''); - /** * Extracts the 'state' (default) query parameter from the route/ url and validates it against COMMON_CONST.STATES, returning its ISO code or `undefined`. * Example 1: Url: https://new.expensify.com/settings/profile/address?state=MO Returns: MO @@ -24,5 +19,5 @@ export default function useGeographicalStateFromRoute(stateParamName = 'state'): if (!stateFromUrlTemp) { return; } - return COMMON_CONST.STATES[removeHash(stateFromUrlTemp) as State].stateISO; + return COMMON_CONST.STATES[stateFromUrlTemp as State].stateISO; } diff --git a/src/pages/settings/Profile/PersonalDetails/StateSelectionPage.tsx b/src/pages/settings/Profile/PersonalDetails/StateSelectionPage.tsx index 1a9a0fab9069..275400b27cc0 100644 --- a/src/pages/settings/Profile/PersonalDetails/StateSelectionPage.tsx +++ b/src/pages/settings/Profile/PersonalDetails/StateSelectionPage.tsx @@ -56,9 +56,6 @@ function StateSelectionPage() { (option: CountryData) => { const backTo = params?.backTo ?? ''; - // Add hash to param for rare cases, such as in ReimbursementAccountPage (currentStep = CONST.BANK_ACCOUNT.STEP.COMPANY), when the URL on the form page (which has the StateSelector component) already includes a state param. If the form then updates the StateInput with state data from another source and the user attempts to use StateSelector to select the same state present in the URL, it will cause the StateSelector not to detect the state change, as the URL remains the same. - const withHash = (arg: string): string => `${arg}-hash-${Math.random().toString(36).substring(2, 8)}`; - // Determine navigation action based on "backTo" presence and route stack length. if (navigation.getState()?.routes.length === 1) { // If this is the only page in the navigation stack (examples include direct navigation to this page via URL or page reload). @@ -67,11 +64,11 @@ function StateSelectionPage() { Navigation.goBack(); } else { // "backTo" provided: navigate back to "backTo" with state parameter. - Navigation.goBack(appendParam(backTo, 'state', withHash(option.value)) as Route); + Navigation.goBack(appendParam(backTo, 'state', option.value) as Route); } } else if (!_.isEmpty(backTo)) { // Most common case: Navigation stack has multiple routes and "backTo" is defined: navigate to "backTo" with state parameter. - Navigation.navigate(appendParam(backTo, 'state', withHash(option.value)) as Route); + Navigation.navigate(appendParam(backTo, 'state', option.value) as Route); } else { // This is a fallback block and should never execute if StateSelector is correctly appending the "backTo" route. // Navigation stack has multiple routes but no "backTo" defined: default back navigation. From 713a91ce5f252da0afe33a88a3ddf030504700bb Mon Sep 17 00:00:00 2001 From: Yogesh Bhatt Date: Wed, 13 Mar 2024 03:31:40 +0530 Subject: [PATCH 193/306] Sync URL 'state' param with StateSelector value --- src/components/StateSelector.tsx | 1 + 1 file changed, 1 insertion(+) diff --git a/src/components/StateSelector.tsx b/src/components/StateSelector.tsx index 3aff71cd9f90..5e1e8591498d 100644 --- a/src/components/StateSelector.tsx +++ b/src/components/StateSelector.tsx @@ -69,6 +69,7 @@ function StateSelector( // This will cause the form to revalidate and remove any error related to state name onInputChange(stateCode); } + Navigation.setParams({state: stateCode}); setStateToDisplay(stateCode); // eslint-disable-next-line react-hooks/exhaustive-deps From 0cdee35813facc8da61e83e06ffbae738e7a7dc2 Mon Sep 17 00:00:00 2001 From: Etotaziba Olei Date: Wed, 13 Mar 2024 13:35:38 +0100 Subject: [PATCH 194/306] pass isDraft argument --- .../MoneyTemporaryForRefactorRequestConfirmationList.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/components/MoneyTemporaryForRefactorRequestConfirmationList.js b/src/components/MoneyTemporaryForRefactorRequestConfirmationList.js index aef5468241c1..64507f80fdcd 100755 --- a/src/components/MoneyTemporaryForRefactorRequestConfirmationList.js +++ b/src/components/MoneyTemporaryForRefactorRequestConfirmationList.js @@ -375,7 +375,7 @@ function MoneyTemporaryForRefactorRequestConfirmationList({ if (previousTransactionTaxAmount !== transaction.taxAmount && amountInSmallestCurrencyUnits !== transaction.taxAmount) { return; } - IOU.setMoneyRequestTaxAmount(transaction.transactionID, amountInSmallestCurrencyUnits); + IOU.setMoneyRequestTaxAmount(transaction.transactionID, amountInSmallestCurrencyUnits, true); }, [taxRates.defaultValue, transaction, previousTransactionTaxAmount]); /** From 2a76bed788590cad8f75e07a502b4ed5d745e5b9 Mon Sep 17 00:00:00 2001 From: Yogesh Bhatt <65986357+ygshbht@users.noreply.github.com> Date: Thu, 14 Mar 2024 03:48:47 +0530 Subject: [PATCH 195/306] change moneyrequest/state url to request/state Co-authored-by: Rajat --- src/ROUTES.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/ROUTES.ts b/src/ROUTES.ts index 255afc50a862..f0be85bf553f 100644 --- a/src/ROUTES.ts +++ b/src/ROUTES.ts @@ -431,7 +431,7 @@ const ROUTES = { }, MONEY_REQUEST_STATE_SELECTOR: { - route: 'moneyrequest/state', + route: 'request/state', getRoute: (state?: string, backTo?: string, label?: string) => `${getUrlWithBackToParam(`moneyrequest/state${state ? `?state=${encodeURIComponent(state)}` : ''}`, backTo)}${ From 49f2e467e50da30687754138f3da0f8e01e90e45 Mon Sep 17 00:00:00 2001 From: Yogesh Bhatt <65986357+ygshbht@users.noreply.github.com> Date: Thu, 14 Mar 2024 03:48:59 +0530 Subject: [PATCH 196/306] change moneyrequest/state url to request/state Co-authored-by: Rajat --- src/ROUTES.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/ROUTES.ts b/src/ROUTES.ts index f0be85bf553f..b19ba22d2bf3 100644 --- a/src/ROUTES.ts +++ b/src/ROUTES.ts @@ -434,7 +434,7 @@ const ROUTES = { route: 'request/state', getRoute: (state?: string, backTo?: string, label?: string) => - `${getUrlWithBackToParam(`moneyrequest/state${state ? `?state=${encodeURIComponent(state)}` : ''}`, backTo)}${ + `${getUrlWithBackToParam(`request/state${state ? `?state=${encodeURIComponent(state)}` : ''}`, backTo)}${ // the label param can be an empty string so we cannot use a nullish ?? operator // eslint-disable-next-line @typescript-eslint/prefer-nullish-coalescing label ? `${backTo || state ? '&' : '?'}label=${encodeURIComponent(label)}` : '' From d494a03f64fd1807a6f3f5bdda1b9c369a316ca2 Mon Sep 17 00:00:00 2001 From: Shridhar Goel <35566748+ShridharGoel@users.noreply.github.com> Date: Sat, 16 Mar 2024 00:59:56 +0530 Subject: [PATCH 197/306] Fix video replay issue in iOS --- src/components/VideoPlayer/BaseVideoPlayer.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/components/VideoPlayer/BaseVideoPlayer.js b/src/components/VideoPlayer/BaseVideoPlayer.js index 92d829e9d0db..14f72e389029 100644 --- a/src/components/VideoPlayer/BaseVideoPlayer.js +++ b/src/components/VideoPlayer/BaseVideoPlayer.js @@ -102,7 +102,7 @@ function BaseVideoPlayer({ const currentDuration = e.durationMillis || videoDuration * 1000; const currentPositon = e.positionMillis || 0; - if (shouldReplayVideo(e, isVideoPlaying, currentDuration, currentPositon)) { + if (shouldReplayVideo(e, isPlaying, currentDuration, currentPositon)) { videoPlayerRef.current.setStatusAsync({positionMillis: 0, shouldPlay: true}); } From d71b283ad16dbfccd8d1faa8ff2ac4441917c05e Mon Sep 17 00:00:00 2001 From: Shubham Agrawal Date: Sun, 17 Mar 2024 18:57:51 +0530 Subject: [PATCH 198/306] Refactored selection list items --- .../CalendarPicker/YearPickerModal.tsx | 1 - src/components/SelectionList/BaseListItem.tsx | 51 ------------------ .../SelectionList/RadioListItem.tsx | 40 ++++++++++++-- .../SelectionList/TableListItem.tsx | 38 +++++++++++-- src/components/SelectionList/UserListItem.tsx | 54 +++++++++++++++++-- src/components/SelectionList/index.ios.tsx | 20 ------- .../{index.android.tsx => index.native.tsx} | 1 - src/components/SelectionList/types.ts | 14 ++--- src/pages/SearchPage/index.tsx | 1 - 9 files changed, 121 insertions(+), 99 deletions(-) delete mode 100644 src/components/SelectionList/index.ios.tsx rename src/components/SelectionList/{index.android.tsx => index.native.tsx} (96%) diff --git a/src/components/DatePicker/CalendarPicker/YearPickerModal.tsx b/src/components/DatePicker/CalendarPicker/YearPickerModal.tsx index 8f5487f9c68b..6170b81073a2 100644 --- a/src/components/DatePicker/CalendarPicker/YearPickerModal.tsx +++ b/src/components/DatePicker/CalendarPicker/YearPickerModal.tsx @@ -65,7 +65,6 @@ function YearPickerModal({isVisible, years, currentYear = new Date().getFullYear onBackButtonPress={onClose} /> ({ item, pressableStyle, wrapperStyle, - selectMultipleStyle, isDisabled = false, shouldPreventDefaultFocusOnSelectRow = false, canSelectMultiple = false, onSelectRow, - onCheckboxPress, onDismissError = () => {}, rightHandSideComponent, - checkmarkPosition = CONST.DIRECTION.LEFT, keyForList, errors, pendingAction, @@ -33,7 +28,6 @@ function BaseListItem({ }: BaseListItemProps) { const theme = useTheme(); const styles = useThemeStyles(); - const StyleUtils = useStyleUtils(); const {hovered, bind} = useHover(); const rightHandSideComponentRender = () => { @@ -48,14 +42,6 @@ function BaseListItem({ return rightHandSideComponent; }; - const handleCheckboxPress = () => { - if (onCheckboxPress) { - onCheckboxPress(item); - } else { - onSelectRow(item); - } - }; - return ( onDismissError(item)} @@ -78,45 +64,8 @@ function BaseListItem({ style={pressableStyle} > - {canSelectMultiple && checkmarkPosition === CONST.DIRECTION.LEFT && ( - - - {item.isSelected && ( - - )} - - - )} - {typeof children === 'function' ? children(hovered) : children} - {canSelectMultiple && checkmarkPosition === CONST.DIRECTION.RIGHT && ( - - - - )} - {!canSelectMultiple && item.isSelected && !rightHandSideComponent && ( { + if (onCheckboxPress) { + onCheckboxPress(item); + } else { + onSelectRow(item); + } + }, [item, onCheckboxPress, onSelectRow]); + return ( <> + {canSelectMultiple && ( + + + {item.isSelected && ( + + )} + + + )} { + if (onCheckboxPress) { + onCheckboxPress(item); + } else { + onSelectRow(item); + } + }, [item, onCheckboxPress, onSelectRow]); + return ( {(hovered) => ( <> + {canSelectMultiple && ( + + + {item.isSelected && ( + + )} + + + )} {!!item.icons && ( { + if (onCheckboxPress) { + onCheckboxPress(item); + } else { + onSelectRow(item); + } + }, [item, onCheckboxPress, onSelectRow]); + return ( {(hovered?: boolean) => ( <> + {canSelectMultiple && checkmarkPosition === CONST.DIRECTION.LEFT && ( + + + {item.isSelected && ( + + )} + + + )} {!!item.icons && (item.shouldShowSubscript ? ( {!!item.rightElement && item.rightElement} + {canSelectMultiple && checkmarkPosition === CONST.DIRECTION.RIGHT && ( + + + + )} )} diff --git a/src/components/SelectionList/index.ios.tsx b/src/components/SelectionList/index.ios.tsx deleted file mode 100644 index afa1ce499ecc..000000000000 --- a/src/components/SelectionList/index.ios.tsx +++ /dev/null @@ -1,20 +0,0 @@ -import React, {forwardRef} from 'react'; -import type {ForwardedRef} from 'react'; -import {Keyboard} from 'react-native'; -import BaseSelectionList from './BaseSelectionList'; -import type {BaseSelectionListProps, ListItem, SelectionListHandle} from './types'; - -function SelectionList(props: BaseSelectionListProps, ref: ForwardedRef) { - return ( - - // eslint-disable-next-line react/jsx-props-no-spreading - {...props} - ref={ref} - onScrollBeginDrag={() => Keyboard.dismiss()} - /> - ); -} - -SelectionList.displayName = 'SelectionList'; - -export default forwardRef(SelectionList); diff --git a/src/components/SelectionList/index.android.tsx b/src/components/SelectionList/index.native.tsx similarity index 96% rename from src/components/SelectionList/index.android.tsx rename to src/components/SelectionList/index.native.tsx index f8e54b219f5b..baccdf7c6024 100644 --- a/src/components/SelectionList/index.android.tsx +++ b/src/components/SelectionList/index.native.tsx @@ -10,7 +10,6 @@ function SelectionList(props: BaseSelectionListProps Keyboard.dismiss()} /> ); diff --git a/src/components/SelectionList/types.ts b/src/components/SelectionList/types.ts index 9e9ba7e5fc27..9251eb1399f6 100644 --- a/src/components/SelectionList/types.ts +++ b/src/components/SelectionList/types.ts @@ -151,6 +151,8 @@ type RadioListItemProps = ListItemProps; type TableListItemProps = ListItemProps; +type ValidListItem = typeof RadioListItem | typeof UserListItem | typeof TableListItem; + type Section = { /** Title of the section */ title?: string; @@ -173,7 +175,7 @@ type BaseSelectionListProps = Partial & { sections: Array>> | typeof CONST.EMPTY_ARRAY; /** Default renderer for every item in the list */ - ListItem: typeof RadioListItem | typeof UserListItem | typeof TableListItem; + ListItem: ValidListItem; /** Whether this is a multi-select list */ canSelectMultiple?: boolean; @@ -259,18 +261,12 @@ type BaseSelectionListProps = Partial & { /** Whether keyboard shortcuts should be disabled */ disableKeyboardShortcuts?: boolean; - /** Whether to disable initial styling for focused option */ - disableInitialFocusOptionStyle?: boolean; - /** Styles to apply to SelectionList container */ containerStyle?: ViewStyle; /** Whether keyboard is visible on the screen */ isKeyboardShown?: boolean; - /** Whether focus event should be delayed */ - shouldDelayFocus?: boolean; - /** Component to display on the right side of each child */ rightHandSideComponent?: ((item: ListItem) => ReactElement) | ReactElement | null; @@ -289,9 +285,6 @@ type BaseSelectionListProps = Partial & { /** Styles for the list header wrapper */ listHeaderWrapperStyle?: StyleProp; - /** Whether to auto focus the Search Input */ - autoFocus?: boolean; - /** Whether to wrap long text up to 2 lines */ isRowMultilineSupported?: boolean; @@ -335,4 +328,5 @@ export type { ButtonOrCheckBoxRoles, SectionListDataType, SelectionListHandle, + ValidListItem, }; diff --git a/src/pages/SearchPage/index.tsx b/src/pages/SearchPage/index.tsx index 07096ce6c2d5..7a42db3ff2cd 100644 --- a/src/pages/SearchPage/index.tsx +++ b/src/pages/SearchPage/index.tsx @@ -169,7 +169,6 @@ function SearchPage({betas, reports, isSearchingForReports, navigation}: SearchP onChangeText={setSearchValue} headerMessage={headerMessage} onLayout={setPerformanceTimersEnd} - autoFocus onSelectRow={selectReport} showLoadingPlaceholder={!didScreenTransitionEnd || !isOptionsDataReady} footerContent={SearchPageFooterInstance} From 95c5553f67c0d2afd46c0596559cc5dea4b26382 Mon Sep 17 00:00:00 2001 From: Shubham Agrawal Date: Sun, 17 Mar 2024 19:18:51 +0530 Subject: [PATCH 199/306] Fixed icons import --- src/components/SelectionList/RadioListItem.tsx | 1 + src/components/SelectionList/TableListItem.tsx | 1 + src/components/SelectionList/UserListItem.tsx | 1 + 3 files changed, 3 insertions(+) diff --git a/src/components/SelectionList/RadioListItem.tsx b/src/components/SelectionList/RadioListItem.tsx index 489076e7b1e6..5931f76f16e4 100644 --- a/src/components/SelectionList/RadioListItem.tsx +++ b/src/components/SelectionList/RadioListItem.tsx @@ -1,6 +1,7 @@ import React, {useCallback} from 'react'; import {View} from 'react-native'; import Icon from '@components/Icon'; +import * as Expensicons from '@components/Icon/Expensicons'; import PressableWithFeedback from '@components/Pressable/PressableWithFeedback'; import TextWithTooltip from '@components/TextWithTooltip'; import useStyleUtils from '@hooks/useStyleUtils'; diff --git a/src/components/SelectionList/TableListItem.tsx b/src/components/SelectionList/TableListItem.tsx index a6490dbcd136..d8ded2ada697 100644 --- a/src/components/SelectionList/TableListItem.tsx +++ b/src/components/SelectionList/TableListItem.tsx @@ -1,6 +1,7 @@ import React, {useCallback} from 'react'; import {View} from 'react-native'; import Icon from '@components/Icon'; +import * as Expensicons from '@components/Icon/Expensicons'; import MultipleAvatars from '@components/MultipleAvatars'; import PressableWithFeedback from '@components/Pressable/PressableWithFeedback'; import TextWithTooltip from '@components/TextWithTooltip'; diff --git a/src/components/SelectionList/UserListItem.tsx b/src/components/SelectionList/UserListItem.tsx index 8de089cb9313..081d49d27d68 100644 --- a/src/components/SelectionList/UserListItem.tsx +++ b/src/components/SelectionList/UserListItem.tsx @@ -2,6 +2,7 @@ import Str from 'expensify-common/lib/str'; import React, {useCallback} from 'react'; import {View} from 'react-native'; import Icon from '@components/Icon'; +import * as Expensicons from '@components/Icon/Expensicons'; import MultipleAvatars from '@components/MultipleAvatars'; import PressableWithFeedback from '@components/Pressable/PressableWithFeedback'; import SelectCircle from '@components/SelectCircle'; From cfc67146623d405ca9f253539b335047b15fd954 Mon Sep 17 00:00:00 2001 From: Shubham Agrawal Date: Mon, 18 Mar 2024 17:19:51 +0530 Subject: [PATCH 200/306] Removed unecessary checkmark from RadioListItem --- .../SelectionList/RadioListItem.tsx | 42 +------------------ 1 file changed, 1 insertion(+), 41 deletions(-) diff --git a/src/components/SelectionList/RadioListItem.tsx b/src/components/SelectionList/RadioListItem.tsx index 5931f76f16e4..0b1f74b9d68e 100644 --- a/src/components/SelectionList/RadioListItem.tsx +++ b/src/components/SelectionList/RadioListItem.tsx @@ -1,13 +1,7 @@ -import React, {useCallback} from 'react'; +import React from 'react'; import {View} from 'react-native'; -import Icon from '@components/Icon'; -import * as Expensicons from '@components/Icon/Expensicons'; -import PressableWithFeedback from '@components/Pressable/PressableWithFeedback'; import TextWithTooltip from '@components/TextWithTooltip'; -import useStyleUtils from '@hooks/useStyleUtils'; -import useTheme from '@hooks/useTheme'; import useThemeStyles from '@hooks/useThemeStyles'; -import CONST from '@src/CONST'; import BaseListItem from './BaseListItem'; import type {RadioListItemProps} from './types'; @@ -16,25 +10,13 @@ function RadioListItem({ isFocused, showTooltip, isDisabled, - canSelectMultiple, onSelectRow, - onCheckboxPress, onDismissError, shouldPreventDefaultFocusOnSelectRow, rightHandSideComponent, isMultilineSupported = false, }: RadioListItemProps) { const styles = useThemeStyles(); - const theme = useTheme(); - const StyleUtils = useStyleUtils(); - - const handleCheckboxPress = useCallback(() => { - if (onCheckboxPress) { - onCheckboxPress(item); - } else { - onSelectRow(item); - } - }, [item, onCheckboxPress, onSelectRow]); return ( <> - {canSelectMultiple && ( - - - {item.isSelected && ( - - )} - - - )} Date: Mon, 18 Mar 2024 17:26:05 +0530 Subject: [PATCH 201/306] Removed unused file --- .../SelectionList/selectionListPropTypes.js | 203 ------------------ 1 file changed, 203 deletions(-) delete mode 100644 src/components/SelectionList/selectionListPropTypes.js diff --git a/src/components/SelectionList/selectionListPropTypes.js b/src/components/SelectionList/selectionListPropTypes.js deleted file mode 100644 index f5178112a4c3..000000000000 --- a/src/components/SelectionList/selectionListPropTypes.js +++ /dev/null @@ -1,203 +0,0 @@ -import PropTypes from 'prop-types'; -import _ from 'underscore'; -import sourcePropTypes from '@components/Image/sourcePropTypes'; -import CONST from '@src/CONST'; - -const commonListItemPropTypes = { - /** Whether this item is focused (for arrow key controls) */ - isFocused: PropTypes.bool, - - /** Style to be applied to Text */ - textStyles: PropTypes.arrayOf(PropTypes.object), - - /** Style to be applied on the alternate text */ - alternateTextStyles: PropTypes.arrayOf(PropTypes.object), - - /** Whether this item is disabled */ - isDisabled: PropTypes.bool, - - /** Whether this item should show Tooltip */ - showTooltip: PropTypes.bool.isRequired, - - /** Whether to use the Checkbox (multiple selection) instead of the Checkmark (single selection) */ - canSelectMultiple: PropTypes.bool, - - /** Callback to fire when the item is selected */ - onSelectRow: PropTypes.func.isRequired, - - /** Callback to fire when an error is dismissed */ - onDismissError: PropTypes.func, -}; - -const userListItemPropTypes = { - ...commonListItemPropTypes, - - /** The section list item */ - item: PropTypes.shape({ - /** Text to display */ - text: PropTypes.string.isRequired, - - /** Alternate text to display */ - alternateText: PropTypes.string, - - /** Key used internally by React */ - keyForList: PropTypes.string.isRequired, - - /** Whether this option is selected */ - isSelected: PropTypes.bool, - - /** Whether this option is disabled for selection */ - isDisabled: PropTypes.bool, - - /** User accountID */ - accountID: PropTypes.number, - - /** User login */ - login: PropTypes.string, - - /** Element to show on the right side of the item */ - rightElement: PropTypes.element, - - /** Icons for the user (can be multiple if it's a Workspace) */ - icons: PropTypes.arrayOf( - PropTypes.shape({ - source: PropTypes.oneOfType([PropTypes.string, sourcePropTypes]).isRequired, - name: PropTypes.string, - type: PropTypes.string, - }), - ), - - /** Errors that this user may contain */ - errors: PropTypes.objectOf(PropTypes.string), - - /** The type of action that's pending */ - pendingAction: PropTypes.oneOf(_.values(CONST.RED_BRICK_ROAD_PENDING_ACTION)), - }).isRequired, -}; - -const radioListItemPropTypes = { - ...commonListItemPropTypes, - - /** The section list item */ - item: PropTypes.shape({ - /** Text to display */ - text: PropTypes.string.isRequired, - - /** Alternate text to display */ - alternateText: PropTypes.string, - - /** Key used internally by React */ - keyForList: PropTypes.string.isRequired, - - /** Whether this option is selected */ - isSelected: PropTypes.bool, - }).isRequired, -}; - -const baseListItemPropTypes = { - ...commonListItemPropTypes, - item: PropTypes.oneOfType([PropTypes.shape(userListItemPropTypes.item), PropTypes.shape(radioListItemPropTypes.item)]), - shouldPreventDefaultFocusOnSelectRow: PropTypes.bool, -}; - -const propTypes = { - /** Sections for the section list */ - sections: PropTypes.arrayOf( - PropTypes.shape({ - /** Title of the section */ - title: PropTypes.string, - - /** The initial index of this section given the total number of options in each section's data array */ - indexOffset: PropTypes.number, - - /** Array of options */ - data: PropTypes.arrayOf(PropTypes.oneOfType([PropTypes.shape(userListItemPropTypes.item), PropTypes.shape(radioListItemPropTypes.item)])), - - /** Whether this section items disabled for selection */ - isDisabled: PropTypes.bool, - }), - ).isRequired, - - /** Whether this is a multi-select list */ - canSelectMultiple: PropTypes.bool, - - /** Callback to fire when a row is pressed */ - onSelectRow: PropTypes.func.isRequired, - - /** Callback to fire when "Select All" checkbox is pressed. Only use along with `canSelectMultiple` */ - onSelectAll: PropTypes.func, - - /** Callback to fire when an error is dismissed */ - onDismissError: PropTypes.func, - - /** Label for the text input */ - textInputLabel: PropTypes.string, - - /** Placeholder for the text input */ - textInputPlaceholder: PropTypes.string, - - /** Value for the text input */ - textInputValue: PropTypes.string, - - /** Max length for the text input */ - textInputMaxLength: PropTypes.number, - - /** Callback to fire when the text input changes */ - onChangeText: PropTypes.func, - - /** Input mode for the text input */ - inputMode: PropTypes.string, - - /** Item `keyForList` to focus initially */ - initiallyFocusedOptionKey: PropTypes.string, - - /** Callback to fire when the list is scrolled */ - onScroll: PropTypes.func, - - /** Callback to fire when the list is scrolled and the user begins dragging */ - onScrollBeginDrag: PropTypes.func, - - /** Message to display at the top of the list */ - headerMessage: PropTypes.string, - - /** Text to display on the confirm button */ - confirmButtonText: PropTypes.string, - - /** Callback to fire when the confirm button is pressed */ - onConfirm: PropTypes.func, - - /** Whether to show the vertical scroll indicator */ - showScrollIndicator: PropTypes.bool, - - /** Whether to show the loading placeholder */ - showLoadingPlaceholder: PropTypes.bool, - - /** Whether to show the default confirm button */ - showConfirmButton: PropTypes.bool, - - /** Whether to stop automatic form submission on pressing enter key or not */ - shouldStopPropagation: PropTypes.bool, - - /** Whether to prevent default focusing of options and focus the textinput when selecting an option */ - shouldPreventDefaultFocusOnSelectRow: PropTypes.bool, - - /** A ref to forward to the TextInput */ - inputRef: PropTypes.oneOfType([PropTypes.object]), - - /** Custom content to display in the header */ - headerContent: PropTypes.oneOfType([PropTypes.func, PropTypes.node]), - - /** Custom content to display in the footer */ - footerContent: PropTypes.oneOfType([PropTypes.func, PropTypes.node]), - - /** Whether to show the toolip text */ - shouldShowTooltips: PropTypes.bool, - - /** Whether to use dynamic maxToRenderPerBatch depending on the visible number of elements */ - shouldUseDynamicMaxToRenderPerBatch: PropTypes.bool, - - /** Right hand side component to display in the list item. Function has list item passed as the param */ - rightHandSideComponent: PropTypes.oneOfType([PropTypes.func, PropTypes.node]), -}; - -export {propTypes, baseListItemPropTypes, radioListItemPropTypes, userListItemPropTypes}; From 5d56fb096ca6cf1d7c346b5581fcd5939c05ad18 Mon Sep 17 00:00:00 2001 From: Jakub Szymczak Date: Mon, 18 Mar 2024 17:36:07 +0100 Subject: [PATCH 202/306] migrate jest.config --- workflow_tests/jest.config.js | 9 --------- workflow_tests/jest.config.ts | 13 +++++++++++++ 2 files changed, 13 insertions(+), 9 deletions(-) delete mode 100644 workflow_tests/jest.config.js create mode 100644 workflow_tests/jest.config.ts diff --git a/workflow_tests/jest.config.js b/workflow_tests/jest.config.js deleted file mode 100644 index cecdf8589d7f..000000000000 --- a/workflow_tests/jest.config.js +++ /dev/null @@ -1,9 +0,0 @@ -module.exports = { - verbose: true, - transform: { - '^.+\\.jsx?$': 'babel-jest', - '^.+\\.tsx?$': 'ts-jest', - }, - clearMocks: true, - resetMocks: true, -}; diff --git a/workflow_tests/jest.config.ts b/workflow_tests/jest.config.ts new file mode 100644 index 000000000000..da9dd2e15794 --- /dev/null +++ b/workflow_tests/jest.config.ts @@ -0,0 +1,13 @@ +/* eslint-disable @typescript-eslint/naming-convention */ +import type {Config} from 'jest'; + +const config: Config = { + verbose: true, + transform: { + '^.+\\.jsx?$': 'babel-jest', + }, + clearMocks: true, + resetMocks: true, +}; + +export default config; From 94702fbd9564b31afd94e78d37e54d374edd9cf2 Mon Sep 17 00:00:00 2001 From: Jakub Szymczak Date: Mon, 18 Mar 2024 17:36:27 +0100 Subject: [PATCH 203/306] migrate testBuild --- .../{testBuild.test.js => testBuild.test.ts} | 58 ++++++++++--------- 1 file changed, 31 insertions(+), 27 deletions(-) rename workflow_tests/{testBuild.test.js => testBuild.test.ts} (97%) diff --git a/workflow_tests/testBuild.test.js b/workflow_tests/testBuild.test.ts similarity index 97% rename from workflow_tests/testBuild.test.js rename to workflow_tests/testBuild.test.ts index 371759607ed5..2c676a63adfe 100644 --- a/workflow_tests/testBuild.test.js +++ b/workflow_tests/testBuild.test.ts @@ -1,12 +1,16 @@ -const path = require('path'); -const kieMockGithub = require('@kie/mock-github'); -const utils = require('./utils/utils'); -const assertions = require('./assertions/testBuildAssertions'); -const mocks = require('./mocks/testBuildMocks'); -const eAct = require('./utils/ExtendedAct'); +/* eslint-disable @typescript-eslint/naming-convention */ + +/* eslint-disable @typescript-eslint/require-await */ +import type {MockGithub} from '@kie/mock-github'; +import kieMockGithub from '@kie/mock-github'; +import path from 'path'; +import assertions from './assertions/testBuildAssertions'; +import mocks from './mocks/testBuildMocks'; +import * as eAct from './utils/ExtendedAct'; +import * as utils from './utils/utils'; jest.setTimeout(90 * 1000); -let mockGithub; +let mockGithub: MockGithub; const FILES_TO_COPY_INTO_TEST_REPO = [ ...utils.deepCopy(utils.FILES_TO_COPY_INTO_TEST_REPO), { @@ -60,7 +64,7 @@ describe('test workflow testBuild', () => { PULL_REQUEST_NUMBER: '1234', }; it('executes workflow', async () => { - const repoPath = mockGithub.repo.getPath('testTestBuildWorkflowRepo') || ''; + const repoPath = mockGithub.repo.getPath('testTestBuildWorkflowRepo') ?? ''; const workflowPath = path.join(repoPath, '.github', 'workflows', 'testBuild.yml'); let act = new eAct.ExtendedAct(repoPath, workflowPath); act = utils.setUpActParams(act, event, {}, secrets, githubToken, {}, inputs); @@ -91,7 +95,7 @@ describe('test workflow testBuild', () => { }); describe('actor is not a team member', () => { it('stops the workflow after validation', async () => { - const repoPath = mockGithub.repo.getPath('testTestBuildWorkflowRepo') || ''; + const repoPath = mockGithub.repo.getPath('testTestBuildWorkflowRepo') ?? ''; const workflowPath = path.join(repoPath, '.github', 'workflows', 'testBuild.yml'); let act = new eAct.ExtendedAct(repoPath, workflowPath); act = utils.setUpActParams(act, event, {}, secrets, githubToken, {}, inputs); @@ -123,7 +127,7 @@ describe('test workflow testBuild', () => { }); describe('PR does not have READY_TO_BUILD label', () => { it('stops the workflow after validation', async () => { - const repoPath = mockGithub.repo.getPath('testTestBuildWorkflowRepo') || ''; + const repoPath = mockGithub.repo.getPath('testTestBuildWorkflowRepo') ?? ''; const workflowPath = path.join(repoPath, '.github', 'workflows', 'testBuild.yml'); let act = new eAct.ExtendedAct(repoPath, workflowPath); act = utils.setUpActParams(act, event, {}, secrets, githubToken, {}, inputs); @@ -155,7 +159,7 @@ describe('test workflow testBuild', () => { }); describe('actor is not a team member and PR does not have READY_TO_BUILD label', () => { it('stops the workflow after validation', async () => { - const repoPath = mockGithub.repo.getPath('testTestBuildWorkflowRepo') || ''; + const repoPath = mockGithub.repo.getPath('testTestBuildWorkflowRepo') ?? ''; const workflowPath = path.join(repoPath, '.github', 'workflows', 'testBuild.yml'); let act = new eAct.ExtendedAct(repoPath, workflowPath); act = utils.setUpActParams(act, event, {}, secrets, githubToken, {}, inputs); @@ -187,7 +191,7 @@ describe('test workflow testBuild', () => { }); describe('android fails', () => { it('executes workflow, failure reflected', async () => { - const repoPath = mockGithub.repo.getPath('testTestBuildWorkflowRepo') || ''; + const repoPath = mockGithub.repo.getPath('testTestBuildWorkflowRepo') ?? ''; const workflowPath = path.join(repoPath, '.github', 'workflows', 'testBuild.yml'); let act = new eAct.ExtendedAct(repoPath, workflowPath); act = utils.setUpActParams(act, event, {}, secrets, githubToken, {}, inputs); @@ -220,7 +224,7 @@ describe('test workflow testBuild', () => { }); describe('iOS fails', () => { it('executes workflow, failure reflected', async () => { - const repoPath = mockGithub.repo.getPath('testTestBuildWorkflowRepo') || ''; + const repoPath = mockGithub.repo.getPath('testTestBuildWorkflowRepo') ?? ''; const workflowPath = path.join(repoPath, '.github', 'workflows', 'testBuild.yml'); let act = new eAct.ExtendedAct(repoPath, workflowPath); act = utils.setUpActParams(act, event, {}, secrets, githubToken, {}, inputs); @@ -253,7 +257,7 @@ describe('test workflow testBuild', () => { }); describe('desktop fails', () => { it('executes workflow, failure reflected', async () => { - const repoPath = mockGithub.repo.getPath('testTestBuildWorkflowRepo') || ''; + const repoPath = mockGithub.repo.getPath('testTestBuildWorkflowRepo') ?? ''; const workflowPath = path.join(repoPath, '.github', 'workflows', 'testBuild.yml'); let act = new eAct.ExtendedAct(repoPath, workflowPath); act = utils.setUpActParams(act, event, {}, secrets, githubToken, {}, inputs); @@ -295,7 +299,7 @@ describe('test workflow testBuild', () => { }); describe('web fails', () => { it('executes workflow, failure reflected', async () => { - const repoPath = mockGithub.repo.getPath('testTestBuildWorkflowRepo') || ''; + const repoPath = mockGithub.repo.getPath('testTestBuildWorkflowRepo') ?? ''; const workflowPath = path.join(repoPath, '.github', 'workflows', 'testBuild.yml'); let act = new eAct.ExtendedAct(repoPath, workflowPath); act = utils.setUpActParams(act, event, {}, secrets, githubToken, {}, inputs); @@ -348,7 +352,7 @@ describe('test workflow testBuild', () => { }, }; it('executes workflow, without getBranchRef', async () => { - const repoPath = mockGithub.repo.getPath('testTestBuildWorkflowRepo') || ''; + const repoPath = mockGithub.repo.getPath('testTestBuildWorkflowRepo') ?? ''; const workflowPath = path.join(repoPath, '.github', 'workflows', 'testBuild.yml'); let act = new eAct.ExtendedAct(repoPath, workflowPath); act = utils.setUpActParams(act, event, eventOptions, secrets, githubToken, {}); @@ -379,7 +383,7 @@ describe('test workflow testBuild', () => { }); describe('actor is not a team member', () => { it('stops the workflow after validation', async () => { - const repoPath = mockGithub.repo.getPath('testTestBuildWorkflowRepo') || ''; + const repoPath = mockGithub.repo.getPath('testTestBuildWorkflowRepo') ?? ''; const workflowPath = path.join(repoPath, '.github', 'workflows', 'testBuild.yml'); let act = new eAct.ExtendedAct(repoPath, workflowPath); act = utils.setUpActParams(act, event, eventOptions, secrets, githubToken, {}); @@ -411,7 +415,7 @@ describe('test workflow testBuild', () => { }); describe('PR does not have READY_TO_BUILD label', () => { it('stops the workflow after validation', async () => { - const repoPath = mockGithub.repo.getPath('testTestBuildWorkflowRepo') || ''; + const repoPath = mockGithub.repo.getPath('testTestBuildWorkflowRepo') ?? ''; const workflowPath = path.join(repoPath, '.github', 'workflows', 'testBuild.yml'); let act = new eAct.ExtendedAct(repoPath, workflowPath); act = utils.setUpActParams(act, event, eventOptions, secrets, githubToken, {}); @@ -443,7 +447,7 @@ describe('test workflow testBuild', () => { }); describe('actor is not a team member and PR does not have READY_TO_BUILD label', () => { it('stops the workflow after validation', async () => { - const repoPath = mockGithub.repo.getPath('testTestBuildWorkflowRepo') || ''; + const repoPath = mockGithub.repo.getPath('testTestBuildWorkflowRepo') ?? ''; const workflowPath = path.join(repoPath, '.github', 'workflows', 'testBuild.yml'); let act = new eAct.ExtendedAct(repoPath, workflowPath); act = utils.setUpActParams(act, event, eventOptions, secrets, githubToken, {}); @@ -486,7 +490,7 @@ describe('test workflow testBuild', () => { }, }; it('executes workflow, without getBranchRef', async () => { - const repoPath = mockGithub.repo.getPath('testTestBuildWorkflowRepo') || ''; + const repoPath = mockGithub.repo.getPath('testTestBuildWorkflowRepo') ?? ''; const workflowPath = path.join(repoPath, '.github', 'workflows', 'testBuild.yml'); let act = new eAct.ExtendedAct(repoPath, workflowPath); act = utils.setUpActParams(act, event, eventOptions, secrets, githubToken, {}); @@ -517,7 +521,7 @@ describe('test workflow testBuild', () => { }); describe('actor is not a team member', () => { it('stops the workflow after validation', async () => { - const repoPath = mockGithub.repo.getPath('testTestBuildWorkflowRepo') || ''; + const repoPath = mockGithub.repo.getPath('testTestBuildWorkflowRepo') ?? ''; const workflowPath = path.join(repoPath, '.github', 'workflows', 'testBuild.yml'); let act = new eAct.ExtendedAct(repoPath, workflowPath); act = utils.setUpActParams(act, event, eventOptions, secrets, githubToken, {}); @@ -549,7 +553,7 @@ describe('test workflow testBuild', () => { }); describe('PR does not have READY_TO_BUILD label', () => { it('stops the workflow after validation', async () => { - const repoPath = mockGithub.repo.getPath('testTestBuildWorkflowRepo') || ''; + const repoPath = mockGithub.repo.getPath('testTestBuildWorkflowRepo') ?? ''; const workflowPath = path.join(repoPath, '.github', 'workflows', 'testBuild.yml'); let act = new eAct.ExtendedAct(repoPath, workflowPath); act = utils.setUpActParams(act, event, eventOptions, secrets, githubToken, {}); @@ -581,7 +585,7 @@ describe('test workflow testBuild', () => { }); describe('actor is not a team member and PR does not have READY_TO_BUILD label', () => { it('stops the workflow after validation', async () => { - const repoPath = mockGithub.repo.getPath('testTestBuildWorkflowRepo') || ''; + const repoPath = mockGithub.repo.getPath('testTestBuildWorkflowRepo') ?? ''; const workflowPath = path.join(repoPath, '.github', 'workflows', 'testBuild.yml'); let act = new eAct.ExtendedAct(repoPath, workflowPath); act = utils.setUpActParams(act, event, eventOptions, secrets, githubToken, {}); @@ -624,7 +628,7 @@ describe('test workflow testBuild', () => { }, }; it('executes workflow, withuout getBranchRef', async () => { - const repoPath = mockGithub.repo.getPath('testTestBuildWorkflowRepo') || ''; + const repoPath = mockGithub.repo.getPath('testTestBuildWorkflowRepo') ?? ''; const workflowPath = path.join(repoPath, '.github', 'workflows', 'testBuild.yml'); let act = new eAct.ExtendedAct(repoPath, workflowPath); act = utils.setUpActParams(act, event, eventOptions, secrets, githubToken, {}); @@ -655,7 +659,7 @@ describe('test workflow testBuild', () => { }); describe('actor is not a team member', () => { it('stops the workflow after validation', async () => { - const repoPath = mockGithub.repo.getPath('testTestBuildWorkflowRepo') || ''; + const repoPath = mockGithub.repo.getPath('testTestBuildWorkflowRepo') ?? ''; const workflowPath = path.join(repoPath, '.github', 'workflows', 'testBuild.yml'); let act = new eAct.ExtendedAct(repoPath, workflowPath); act = utils.setUpActParams(act, event, eventOptions, secrets, githubToken, {}); @@ -687,7 +691,7 @@ describe('test workflow testBuild', () => { }); describe('PR does not have READY_TO_BUILD label', () => { it('stops the workflow after validation', async () => { - const repoPath = mockGithub.repo.getPath('testTestBuildWorkflowRepo') || ''; + const repoPath = mockGithub.repo.getPath('testTestBuildWorkflowRepo') ?? ''; const workflowPath = path.join(repoPath, '.github', 'workflows', 'testBuild.yml'); let act = new eAct.ExtendedAct(repoPath, workflowPath); act = utils.setUpActParams(act, event, eventOptions, secrets, githubToken, {}); @@ -719,7 +723,7 @@ describe('test workflow testBuild', () => { }); describe('actor is not a team member and PR does not have READY_TO_BUILD label', () => { it('stops the workflow after validation', async () => { - const repoPath = mockGithub.repo.getPath('testTestBuildWorkflowRepo') || ''; + const repoPath = mockGithub.repo.getPath('testTestBuildWorkflowRepo') ?? ''; const workflowPath = path.join(repoPath, '.github', 'workflows', 'testBuild.yml'); let act = new eAct.ExtendedAct(repoPath, workflowPath); act = utils.setUpActParams(act, event, eventOptions, secrets, githubToken, {}); From d6aefab946dd40cd7576b7d23be9c939bf477792 Mon Sep 17 00:00:00 2001 From: Jakub Szymczak Date: Mon, 18 Mar 2024 17:36:45 +0100 Subject: [PATCH 204/306] migrate validateGithubActions --- ....test.js => validateGithubActions.test.ts} | 20 ++++++++++--------- 1 file changed, 11 insertions(+), 9 deletions(-) rename workflow_tests/{validateGithubActions.test.js => validateGithubActions.test.ts} (87%) diff --git a/workflow_tests/validateGithubActions.test.js b/workflow_tests/validateGithubActions.test.ts similarity index 87% rename from workflow_tests/validateGithubActions.test.js rename to workflow_tests/validateGithubActions.test.ts index dfa5e9362ce7..850f21a54163 100644 --- a/workflow_tests/validateGithubActions.test.js +++ b/workflow_tests/validateGithubActions.test.ts @@ -1,12 +1,14 @@ -const path = require('path'); -const kieMockGithub = require('@kie/mock-github'); -const utils = require('./utils/utils'); -const assertions = require('./assertions/validateGithubActionsAssertions'); -const mocks = require('./mocks/validateGithubActionsMocks'); -const eAct = require('./utils/ExtendedAct'); +/* eslint-disable @typescript-eslint/require-await */ +import type {MockGithub} from '@kie/mock-github'; +import kieMockGithub from '@kie/mock-github'; +import path from 'path'; +import assertions from './assertions/validateGithubActionsAssertions'; +import mocks from './mocks/validateGithubActionsMocks'; +import * as eAct from './utils/ExtendedAct'; +import * as utils from './utils/utils'; jest.setTimeout(90 * 1000); -let mockGithub; +let mockGithub: MockGithub; const FILES_TO_COPY_INTO_TEST_REPO = [ ...utils.deepCopy(utils.FILES_TO_COPY_INTO_TEST_REPO), { @@ -47,7 +49,7 @@ describe('test workflow validateGithubActions', () => { action: 'opened', }; it('executes verification', async () => { - const repoPath = mockGithub.repo.getPath('testValidateGithubActionsWorkflowRepo') || ''; + const repoPath = mockGithub.repo.getPath('testValidateGithubActionsWorkflowRepo') ?? ''; const workflowPath = path.join(repoPath, '.github', 'workflows', 'validateGithubActions.yml'); let act = new eAct.ExtendedAct(repoPath, workflowPath); act = utils.setUpActParams(act, event, eventOptions, {}, githubToken); @@ -70,7 +72,7 @@ describe('test workflow validateGithubActions', () => { action: 'synchronize', }; it('executes verification', async () => { - const repoPath = mockGithub.repo.getPath('testValidateGithubActionsWorkflowRepo') || ''; + const repoPath = mockGithub.repo.getPath('testValidateGithubActionsWorkflowRepo') ?? ''; const workflowPath = path.join(repoPath, '.github', 'workflows', 'validateGithubActions.yml'); let act = new eAct.ExtendedAct(repoPath, workflowPath); act = utils.setUpActParams(act, event, eventOptions, {}, githubToken); From 9c18645db6ba2b9602d459bdf21cd44880cbabde Mon Sep 17 00:00:00 2001 From: Jakub Szymczak Date: Mon, 18 Mar 2024 17:37:05 +0100 Subject: [PATCH 205/306] migrate verifyPodfile --- ...yPodfile.test.js => verifyPodfile.test.ts} | 25 +++++++++++-------- 1 file changed, 14 insertions(+), 11 deletions(-) rename workflow_tests/{verifyPodfile.test.js => verifyPodfile.test.ts} (91%) diff --git a/workflow_tests/verifyPodfile.test.js b/workflow_tests/verifyPodfile.test.ts similarity index 91% rename from workflow_tests/verifyPodfile.test.js rename to workflow_tests/verifyPodfile.test.ts index de062af2a2c2..b5ccfc46c336 100644 --- a/workflow_tests/verifyPodfile.test.js +++ b/workflow_tests/verifyPodfile.test.ts @@ -1,12 +1,15 @@ -const path = require('path'); -const kieMockGithub = require('@kie/mock-github'); -const utils = require('./utils/utils'); -const assertions = require('./assertions/verifyPodfileAssertions'); -const mocks = require('./mocks/verifyPodfileMocks'); -const eAct = require('./utils/ExtendedAct'); +/* eslint-disable @typescript-eslint/require-await */ +import kieMockGithub from '@kie/mock-github'; +import type {MockGithub} from '@kie/mock-github'; +import path from 'path'; +import assertions from './assertions/verifyPodfileAssertions'; +import mocks from './mocks/verifyPodfileMocks'; +import * as eAct from './utils/ExtendedAct'; +import * as utils from './utils/utils'; jest.setTimeout(90 * 1000); -let mockGithub; +let mockGithub: MockGithub; + const FILES_TO_COPY_INTO_TEST_REPO = [ ...utils.deepCopy(utils.FILES_TO_COPY_INTO_TEST_REPO), { @@ -48,7 +51,7 @@ describe('test workflow verifyPodfile', () => { action: 'opened', }; it('executes workflow', async () => { - const repoPath = mockGithub.repo.getPath('testVerifyPodfileWorkflowRepo') || ''; + const repoPath = mockGithub.repo.getPath('testVerifyPodfileWorkflowRepo') ?? ''; const workflowPath = path.join(repoPath, '.github', 'workflows', 'verifyPodfile.yml'); let act = new eAct.ExtendedAct(repoPath, workflowPath); act = utils.setUpActParams(act, event, eventOptions, {}, githubToken); @@ -67,7 +70,7 @@ describe('test workflow verifyPodfile', () => { }); describe('actor is OSBotify', () => { it('does not execute workflow', async () => { - const repoPath = mockGithub.repo.getPath('testVerifyPodfileWorkflowRepo') || ''; + const repoPath = mockGithub.repo.getPath('testVerifyPodfileWorkflowRepo') ?? ''; const workflowPath = path.join(repoPath, '.github', 'workflows', 'verifyPodfile.yml'); let act = new eAct.ExtendedAct(repoPath, workflowPath); act = utils.setUpActParams(act, event, eventOptions, {}, githubToken); @@ -92,7 +95,7 @@ describe('test workflow verifyPodfile', () => { action: 'synchronize', }; it('executes workflow', async () => { - const repoPath = mockGithub.repo.getPath('testVerifyPodfileWorkflowRepo') || ''; + const repoPath = mockGithub.repo.getPath('testVerifyPodfileWorkflowRepo') ?? ''; const workflowPath = path.join(repoPath, '.github', 'workflows', 'verifyPodfile.yml'); let act = new eAct.ExtendedAct(repoPath, workflowPath); act = utils.setUpActParams(act, event, eventOptions, {}, githubToken); @@ -111,7 +114,7 @@ describe('test workflow verifyPodfile', () => { }); describe('actor is OSBotify', () => { it('does not execute workflow', async () => { - const repoPath = mockGithub.repo.getPath('testVerifyPodfileWorkflowRepo') || ''; + const repoPath = mockGithub.repo.getPath('testVerifyPodfileWorkflowRepo') ?? ''; const workflowPath = path.join(repoPath, '.github', 'workflows', 'verifyPodfile.yml'); let act = new eAct.ExtendedAct(repoPath, workflowPath); act = utils.setUpActParams(act, event, eventOptions, {}, githubToken); From fe4547d7ea539a7460539a9fc869375281ebcb08 Mon Sep 17 00:00:00 2001 From: Jakub Szymczak Date: Mon, 18 Mar 2024 17:37:31 +0100 Subject: [PATCH 206/306] migrate verifySignedCommits --- workflow_tests/scripts/runWorkflowTests.sh | 2 +- ...ts.test.js => verifySignedCommits.test.ts} | 21 +++++++++++-------- 2 files changed, 13 insertions(+), 10 deletions(-) rename workflow_tests/{verifySignedCommits.test.js => verifySignedCommits.test.ts} (87%) diff --git a/workflow_tests/scripts/runWorkflowTests.sh b/workflow_tests/scripts/runWorkflowTests.sh index 71ddcdceffb5..c8ee88e33e99 100755 --- a/workflow_tests/scripts/runWorkflowTests.sh +++ b/workflow_tests/scripts/runWorkflowTests.sh @@ -60,4 +60,4 @@ info 'ACT_BINARY environment variable set to an Act executable' success 'Environment setup properly - running tests' # Run tests -npm test -- --config=workflow_tests/jest.config.js --runInBand "$@" +npm test -- --config=workflow_tests/jest.config.ts --runInBand "$@" diff --git a/workflow_tests/verifySignedCommits.test.js b/workflow_tests/verifySignedCommits.test.ts similarity index 87% rename from workflow_tests/verifySignedCommits.test.js rename to workflow_tests/verifySignedCommits.test.ts index 911208e91f4a..9319829118e6 100644 --- a/workflow_tests/verifySignedCommits.test.js +++ b/workflow_tests/verifySignedCommits.test.ts @@ -1,12 +1,15 @@ -const path = require('path'); -const kieMockGithub = require('@kie/mock-github'); -const utils = require('./utils/utils'); -const assertions = require('./assertions/verifySignedCommitsAssertions'); -const mocks = require('./mocks/verifySignedCommitsMocks'); -const eAct = require('./utils/ExtendedAct'); +/* eslint-disable @typescript-eslint/require-await */ +import type {MockGithub} from '@kie/mock-github'; +import kieMockGithub from '@kie/mock-github'; +import path from 'path'; +import assertions from './assertions/verifySignedCommitsAssertions'; +import mocks from './mocks/verifySignedCommitsMocks'; +import * as eAct from './utils/ExtendedAct'; +import * as utils from './utils/utils'; jest.setTimeout(90 * 1000); -let mockGithub; +let mockGithub: MockGithub; + const FILES_TO_COPY_INTO_TEST_REPO = [ ...utils.deepCopy(utils.FILES_TO_COPY_INTO_TEST_REPO), { @@ -47,7 +50,7 @@ describe('test workflow verifySignedCommits', () => { action: 'opened', }; it('test stub', async () => { - const repoPath = mockGithub.repo.getPath('testVerifySignedCommitsWorkflowRepo') || ''; + const repoPath = mockGithub.repo.getPath('testVerifySignedCommitsWorkflowRepo') ?? ''; const workflowPath = path.join(repoPath, '.github', 'workflows', 'verifySignedCommits.yml'); let act = new eAct.ExtendedAct(repoPath, workflowPath); act = utils.setUpActParams(act, event, eventOptions, {}, githubToken); @@ -70,7 +73,7 @@ describe('test workflow verifySignedCommits', () => { action: 'synchronize', }; it('test stub', async () => { - const repoPath = mockGithub.repo.getPath('testVerifySignedCommitsWorkflowRepo') || ''; + const repoPath = mockGithub.repo.getPath('testVerifySignedCommitsWorkflowRepo') ?? ''; const workflowPath = path.join(repoPath, '.github', 'workflows', 'verifySignedCommits.yml'); let act = new eAct.ExtendedAct(repoPath, workflowPath); act = utils.setUpActParams(act, event, eventOptions, {}, githubToken); From c6f9af1d8e456f73e80cd1a2d109f8710820f361 Mon Sep 17 00:00:00 2001 From: Jakub Szymczak Date: Tue, 19 Mar 2024 17:05:47 +0100 Subject: [PATCH 207/306] fix babel not formatting test files --- workflow_tests/jest.config.ts | 2 +- workflow_tests/testBuild.test.ts | 5 ++--- workflow_tests/validateGithubActions.test.ts | 11 +++++------ workflow_tests/verifyPodfile.test.ts | 5 ++--- workflow_tests/verifySignedCommits.test.ts | 5 ++--- 5 files changed, 12 insertions(+), 16 deletions(-) diff --git a/workflow_tests/jest.config.ts b/workflow_tests/jest.config.ts index da9dd2e15794..8156e449039f 100644 --- a/workflow_tests/jest.config.ts +++ b/workflow_tests/jest.config.ts @@ -4,7 +4,7 @@ import type {Config} from 'jest'; const config: Config = { verbose: true, transform: { - '^.+\\.jsx?$': 'babel-jest', + '^.+\\.(js|jsx|ts|tsx)$': 'ts-jest', }, clearMocks: true, resetMocks: true, diff --git a/workflow_tests/testBuild.test.ts b/workflow_tests/testBuild.test.ts index 2c676a63adfe..5f09b851a5b5 100644 --- a/workflow_tests/testBuild.test.ts +++ b/workflow_tests/testBuild.test.ts @@ -1,8 +1,7 @@ /* eslint-disable @typescript-eslint/naming-convention */ /* eslint-disable @typescript-eslint/require-await */ -import type {MockGithub} from '@kie/mock-github'; -import kieMockGithub from '@kie/mock-github'; +import {MockGithub} from '@kie/mock-github'; import path from 'path'; import assertions from './assertions/testBuildAssertions'; import mocks from './mocks/testBuildMocks'; @@ -44,7 +43,7 @@ describe('test workflow testBuild', () => { beforeEach(async () => { // create a local repository and copy required files - mockGithub = new kieMockGithub.MockGithub({ + mockGithub = new MockGithub({ repo: { testTestBuildWorkflowRepo: { files: FILES_TO_COPY_INTO_TEST_REPO, diff --git a/workflow_tests/validateGithubActions.test.ts b/workflow_tests/validateGithubActions.test.ts index 850f21a54163..1fcfd95834b6 100644 --- a/workflow_tests/validateGithubActions.test.ts +++ b/workflow_tests/validateGithubActions.test.ts @@ -1,10 +1,9 @@ /* eslint-disable @typescript-eslint/require-await */ -import type {MockGithub} from '@kie/mock-github'; -import kieMockGithub from '@kie/mock-github'; +import {MockGithub} from '@kie/mock-github'; import path from 'path'; import assertions from './assertions/validateGithubActionsAssertions'; import mocks from './mocks/validateGithubActionsMocks'; -import * as eAct from './utils/ExtendedAct'; +import {ExtendedAct} from './utils/ExtendedAct'; import * as utils from './utils/utils'; jest.setTimeout(90 * 1000); @@ -29,7 +28,7 @@ describe('test workflow validateGithubActions', () => { beforeEach(async () => { // create a local repository and copy required files - mockGithub = new kieMockGithub.MockGithub({ + mockGithub = new MockGithub({ repo: { testValidateGithubActionsWorkflowRepo: { files: FILES_TO_COPY_INTO_TEST_REPO, @@ -51,7 +50,7 @@ describe('test workflow validateGithubActions', () => { it('executes verification', async () => { const repoPath = mockGithub.repo.getPath('testValidateGithubActionsWorkflowRepo') ?? ''; const workflowPath = path.join(repoPath, '.github', 'workflows', 'validateGithubActions.yml'); - let act = new eAct.ExtendedAct(repoPath, workflowPath); + let act = new ExtendedAct(repoPath, workflowPath); act = utils.setUpActParams(act, event, eventOptions, {}, githubToken); const testMockSteps = { verify: mocks.VALIDATEGITHUBACTIONS__VERIFY__STEP_MOCKS, @@ -74,7 +73,7 @@ describe('test workflow validateGithubActions', () => { it('executes verification', async () => { const repoPath = mockGithub.repo.getPath('testValidateGithubActionsWorkflowRepo') ?? ''; const workflowPath = path.join(repoPath, '.github', 'workflows', 'validateGithubActions.yml'); - let act = new eAct.ExtendedAct(repoPath, workflowPath); + let act = new ExtendedAct(repoPath, workflowPath); act = utils.setUpActParams(act, event, eventOptions, {}, githubToken); const testMockSteps = { verify: mocks.VALIDATEGITHUBACTIONS__VERIFY__STEP_MOCKS, diff --git a/workflow_tests/verifyPodfile.test.ts b/workflow_tests/verifyPodfile.test.ts index b5ccfc46c336..2748eae25542 100644 --- a/workflow_tests/verifyPodfile.test.ts +++ b/workflow_tests/verifyPodfile.test.ts @@ -1,6 +1,5 @@ /* eslint-disable @typescript-eslint/require-await */ -import kieMockGithub from '@kie/mock-github'; -import type {MockGithub} from '@kie/mock-github'; +import {MockGithub} from '@kie/mock-github'; import path from 'path'; import assertions from './assertions/verifyPodfileAssertions'; import mocks from './mocks/verifyPodfileMocks'; @@ -31,7 +30,7 @@ describe('test workflow verifyPodfile', () => { beforeEach(async () => { // create a local repository and copy required files - mockGithub = new kieMockGithub.MockGithub({ + mockGithub = new MockGithub({ repo: { testVerifyPodfileWorkflowRepo: { files: FILES_TO_COPY_INTO_TEST_REPO, diff --git a/workflow_tests/verifySignedCommits.test.ts b/workflow_tests/verifySignedCommits.test.ts index 9319829118e6..c861597368c3 100644 --- a/workflow_tests/verifySignedCommits.test.ts +++ b/workflow_tests/verifySignedCommits.test.ts @@ -1,6 +1,5 @@ /* eslint-disable @typescript-eslint/require-await */ -import type {MockGithub} from '@kie/mock-github'; -import kieMockGithub from '@kie/mock-github'; +import {MockGithub} from '@kie/mock-github'; import path from 'path'; import assertions from './assertions/verifySignedCommitsAssertions'; import mocks from './mocks/verifySignedCommitsMocks'; @@ -30,7 +29,7 @@ describe('test workflow verifySignedCommits', () => { beforeEach(async () => { // create a local repository and copy required files - mockGithub = new kieMockGithub.MockGithub({ + mockGithub = new MockGithub({ repo: { testVerifySignedCommitsWorkflowRepo: { files: FILES_TO_COPY_INTO_TEST_REPO, From 58d92f15b129ea7580164e60ef0e970c432f89e5 Mon Sep 17 00:00:00 2001 From: Yogesh Bhatt Date: Wed, 20 Mar 2024 18:39:39 +0530 Subject: [PATCH 208/306] StateSelector bugfix - for issue causing url to not update in browser url bar --- src/components/StateSelector.tsx | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/components/StateSelector.tsx b/src/components/StateSelector.tsx index 5e1e8591498d..97c8cffc3c48 100644 --- a/src/components/StateSelector.tsx +++ b/src/components/StateSelector.tsx @@ -69,7 +69,9 @@ function StateSelector( // This will cause the form to revalidate and remove any error related to state name onInputChange(stateCode); } - Navigation.setParams({state: stateCode}); + + // This enforces the state selector to use the state from address instead of the state from URL + Navigation.setParams({state: undefined}); setStateToDisplay(stateCode); // eslint-disable-next-line react-hooks/exhaustive-deps From af6c3c5dd094bdd4657eb5df943822e7e1a67d64 Mon Sep 17 00:00:00 2001 From: Yogesh Bhatt Date: Wed, 20 Mar 2024 23:36:41 +0530 Subject: [PATCH 209/306] useGeographicalStateFromRoute - check for state before accessing stateISO --- 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 3e85bfc2a368..13936ee78f5b 100644 --- a/src/hooks/useGeographicalStateFromRoute.ts +++ b/src/hooks/useGeographicalStateFromRoute.ts @@ -19,5 +19,5 @@ export default function useGeographicalStateFromRoute(stateParamName = 'state'): if (!stateFromUrlTemp) { return; } - return COMMON_CONST.STATES[stateFromUrlTemp as State].stateISO; + return COMMON_CONST.STATES[stateFromUrlTemp as State]?.stateISO; } From 24e7de9f508acfba7516482d7899149d14e66bd3 Mon Sep 17 00:00:00 2001 From: Shubham Agrawal Date: Thu, 21 Mar 2024 10:30:18 +0530 Subject: [PATCH 210/306] Fixes after merging --- src/components/SelectionList/TableListItem.tsx | 2 +- src/components/SelectionList/UserListItem.tsx | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/components/SelectionList/TableListItem.tsx b/src/components/SelectionList/TableListItem.tsx index d8ded2ada697..fa741bccbbae 100644 --- a/src/components/SelectionList/TableListItem.tsx +++ b/src/components/SelectionList/TableListItem.tsx @@ -65,7 +65,7 @@ function TableListItem({ // eslint-disable-next-line @typescript-eslint/prefer-nullish-coalescing disabled={isDisabled || item.isDisabledCheckbox} onPress={handleCheckboxPress} - style={[styles.cursorUnset, StyleUtils.getCheckboxPressableStyle(), item.isDisabledCheckbox && styles.cursorDisabled]} + style={[styles.cursorUnset, StyleUtils.getCheckboxPressableStyle(), item.isDisabledCheckbox && styles.cursorDisabled, styles.mr3]} > {item.isSelected && ( diff --git a/src/components/SelectionList/UserListItem.tsx b/src/components/SelectionList/UserListItem.tsx index 081d49d27d68..226c93bf2cf8 100644 --- a/src/components/SelectionList/UserListItem.tsx +++ b/src/components/SelectionList/UserListItem.tsx @@ -79,7 +79,7 @@ function UserListItem({ // eslint-disable-next-line @typescript-eslint/prefer-nullish-coalescing disabled={isDisabled || item.isDisabledCheckbox} onPress={handleCheckboxPress} - style={[styles.cursorUnset, StyleUtils.getCheckboxPressableStyle(), item.isDisabledCheckbox && styles.cursorDisabled]} + style={[styles.cursorUnset, StyleUtils.getCheckboxPressableStyle(), item.isDisabledCheckbox && styles.cursorDisabled, styles.mr3]} > {item.isSelected && ( From 125f18120c3dbc336c7af0a44d4a20ca923b7879 Mon Sep 17 00:00:00 2001 From: Tomasz Misiukiewicz Date: Thu, 21 Mar 2024 16:00:09 +0100 Subject: [PATCH 211/306] add client side logging tool to hidden menu --- .../ClientSideLoggingToolMenu/index.tsx | 50 +++++++++++++++++++ src/components/TestToolsModal.tsx | 2 + 2 files changed, 52 insertions(+) create mode 100644 src/components/ClientSideLoggingToolMenu/index.tsx diff --git a/src/components/ClientSideLoggingToolMenu/index.tsx b/src/components/ClientSideLoggingToolMenu/index.tsx new file mode 100644 index 000000000000..94baed584e1f --- /dev/null +++ b/src/components/ClientSideLoggingToolMenu/index.tsx @@ -0,0 +1,50 @@ +import React from 'react'; +import {withOnyx} from 'react-native-onyx'; +import type {OnyxEntry} from 'react-native-onyx'; +import Switch from '@components/Switch'; +import TestToolRow from '@components/TestToolRow'; +import * as Console from '@libs/actions/Console'; +import type {Log} from '@libs/Console'; +import ONYXKEYS from '@src/ONYXKEYS'; + +type CapturedLogs = Record; + +type ClientSideLoggingToolMenuOnyxProps = { + /** Logs captured on the current device */ + capturedLogs: OnyxEntry; + + /** Whether or not logs should be stored */ + shouldStoreLogs: OnyxEntry; +}; + +type ClientSideLoggingToolProps = ClientSideLoggingToolMenuOnyxProps; + +function ClientSideLoggingToolMenu({shouldStoreLogs, capturedLogs}: ClientSideLoggingToolProps) { + const onToggle = () => { + if (!shouldStoreLogs) { + Console.setShouldStoreLogs(true); + } else { + console.log({capturedLogs}); + Console.disableLoggingAndFlushLogs(); + } + }; + + return ( + + + + ); +} + +export default withOnyx({ + capturedLogs: { + key: ONYXKEYS.LOGS, + }, + shouldStoreLogs: { + key: ONYXKEYS.SHOULD_STORE_LOGS, + }, +})(ClientSideLoggingToolMenu); diff --git a/src/components/TestToolsModal.tsx b/src/components/TestToolsModal.tsx index 824162e63c51..4c6777a6b7d1 100644 --- a/src/components/TestToolsModal.tsx +++ b/src/components/TestToolsModal.tsx @@ -8,6 +8,7 @@ import useWindowDimensions from '@hooks/useWindowDimensions'; import toggleTestToolsModal from '@userActions/TestTool'; import CONST from '@src/CONST'; import ONYXKEYS from '@src/ONYXKEYS'; +import ClientSideLoggingToolMenu from './ClientSideLoggingToolMenu'; import Modal from './Modal'; import ProfilingToolMenu from './ProfilingToolMenu'; import TestToolMenu from './TestToolMenu'; @@ -32,6 +33,7 @@ function TestToolsModal({isTestToolsModalOpen = false}: TestToolsModalProps) { > {isDevelopment && } + From 635c74bc3427ba5d0aa67fe8ce77d7248ba97339 Mon Sep 17 00:00:00 2001 From: Etotaziba Olei Date: Thu, 21 Mar 2024 18:27:59 +0100 Subject: [PATCH 212/306] No taxRates props needed for taxPicker --- .../workspace/taxes/WorkspaceTaxesSettingsForeignCurrency.tsx | 1 - .../workspace/taxes/WorkspaceTaxesSettingsWorkspaceCurrency.tsx | 1 - 2 files changed, 2 deletions(-) diff --git a/src/pages/workspace/taxes/WorkspaceTaxesSettingsForeignCurrency.tsx b/src/pages/workspace/taxes/WorkspaceTaxesSettingsForeignCurrency.tsx index 91d543b51b09..ccd9de846b75 100644 --- a/src/pages/workspace/taxes/WorkspaceTaxesSettingsForeignCurrency.tsx +++ b/src/pages/workspace/taxes/WorkspaceTaxesSettingsForeignCurrency.tsx @@ -56,7 +56,6 @@ function WorkspaceTaxesSettingsForeignCurrency({ diff --git a/src/pages/workspace/taxes/WorkspaceTaxesSettingsWorkspaceCurrency.tsx b/src/pages/workspace/taxes/WorkspaceTaxesSettingsWorkspaceCurrency.tsx index 2fe2985daa22..0536cc8e1999 100644 --- a/src/pages/workspace/taxes/WorkspaceTaxesSettingsWorkspaceCurrency.tsx +++ b/src/pages/workspace/taxes/WorkspaceTaxesSettingsWorkspaceCurrency.tsx @@ -56,7 +56,6 @@ function WorkspaceTaxesSettingsWorkspaceCurrency({ From 576786c9c3d483b25660a834b443f306813673da Mon Sep 17 00:00:00 2001 From: Tomasz Misiukiewicz Date: Fri, 22 Mar 2024 10:31:27 +0100 Subject: [PATCH 213/306] save and share logs from hidden menu --- .../ClientSideLoggingToolMenu/index.tsx | 54 +++++++++++++++---- .../ProfilingToolMenu/index.native.tsx | 25 ++++----- src/components/TestToolsModal.tsx | 11 +++- src/libs/Console/index.ts | 27 +++++++++- src/pages/settings/AboutPage/ConsolePage.tsx | 27 +--------- 5 files changed, 92 insertions(+), 52 deletions(-) diff --git a/src/components/ClientSideLoggingToolMenu/index.tsx b/src/components/ClientSideLoggingToolMenu/index.tsx index 94baed584e1f..43f895c8068d 100644 --- a/src/components/ClientSideLoggingToolMenu/index.tsx +++ b/src/components/ClientSideLoggingToolMenu/index.tsx @@ -1,10 +1,16 @@ -import React from 'react'; +import React, {useState} from 'react'; +import {Share} from 'react-native'; import {withOnyx} from 'react-native-onyx'; import type {OnyxEntry} from 'react-native-onyx'; +import Button from '@components/Button'; import Switch from '@components/Switch'; import TestToolRow from '@components/TestToolRow'; +import Text from '@components/Text'; +import useThemeStyles from '@hooks/useThemeStyles'; import * as Console from '@libs/actions/Console'; +import {parseStringifyMessages} from '@libs/Console'; import type {Log} from '@libs/Console'; +import localFileCreate from '@libs/localFileCreate'; import ONYXKEYS from '@src/ONYXKEYS'; type CapturedLogs = Record; @@ -20,23 +26,53 @@ type ClientSideLoggingToolMenuOnyxProps = { type ClientSideLoggingToolProps = ClientSideLoggingToolMenuOnyxProps; function ClientSideLoggingToolMenu({shouldStoreLogs, capturedLogs}: ClientSideLoggingToolProps) { + const [file, setFile] = useState<{path: string; newFileName: string; size: number}>(); + const styles = useThemeStyles(); + const onToggle = () => { if (!shouldStoreLogs) { + setFile(undefined); Console.setShouldStoreLogs(true); } else { - console.log({capturedLogs}); + const logs = Object.values(capturedLogs as Log[]); + const logsWithParsedMessages = parseStringifyMessages(logs); + localFileCreate('logs', JSON.stringify(logsWithParsedMessages, null, 2)).then((localFile) => { + setFile(localFile); + }); Console.disableLoggingAndFlushLogs(); } }; + const shareLogs = () => { + if (!file) { + return; + } + + Share.share({url: file.path, title: file.newFileName}); + }; + return ( - - - + <> + + + + {!!file && ( + <> + {`path: ${file.path}`} + +