diff --git a/src/CONST/index.ts b/src/CONST/index.ts index 77cd66f787697..6e40150047de8 100755 --- a/src/CONST/index.ts +++ b/src/CONST/index.ts @@ -2938,11 +2938,6 @@ const CONST = { APPROVE: 'approve', TRACK: 'track', }, - SPLIT_TYPE: { - AMOUNT: 'amount', - PERCENTAGE: 'percentage', - DATE: 'date', - }, AMOUNT_MAX_LENGTH: 8, DISTANCE_REQUEST_AMOUNT_MAX_LENGTH: 14, RECEIPT_STATE: { @@ -5476,6 +5471,11 @@ const CONST = { IOU_REQUEST_TYPE: 'iouRequestType', DISTANCE_REQUEST_TYPE: 'distanceRequestType', SPLIT_EXPENSE_TAB_TYPE: 'splitExpenseTabType', + SPLIT: { + AMOUNT: 'amount', + PERCENTAGE: 'percentage', + DATE: 'date', + }, SHARE: { NAVIGATOR_ID: 'ShareNavigatorID', SHARE: 'ShareTab', diff --git a/src/ONYXKEYS.ts b/src/ONYXKEYS.ts index 2474f521872c3..cd6ee05a69d08 100755 --- a/src/ONYXKEYS.ts +++ b/src/ONYXKEYS.ts @@ -687,9 +687,6 @@ const ONYXKEYS = { // Manual expense tab selector SELECTED_DISTANCE_REQUEST_TAB: 'selectedDistanceRequestTab_', - // IOU request split tab selector - SPLIT_SELECTED_TAB: 'splitSelectedTab_', - /** This is deprecated, but needed for a migration, so we still need to include it here so that it will be initialized in Onyx.init */ DEPRECATED_POLICY_MEMBER_LIST: 'policyMemberList_', @@ -1121,7 +1118,6 @@ type OnyxCollectionValuesMapping = { [ONYXKEYS.COLLECTION.POLICY_RECENTLY_USED_TAGS]: OnyxTypes.RecentlyUsedTags; [ONYXKEYS.COLLECTION.SELECTED_TAB]: OnyxTypes.SelectedTabRequest; [ONYXKEYS.COLLECTION.SELECTED_DISTANCE_REQUEST_TAB]: OnyxTypes.SelectedTabRequest; - [ONYXKEYS.COLLECTION.SPLIT_SELECTED_TAB]: OnyxTypes.SplitSelectedTabRequest; [ONYXKEYS.COLLECTION.PRIVATE_NOTES_DRAFT]: string; [ONYXKEYS.COLLECTION.NVP_EXPENSIFY_REPORT_PDF_FILENAME]: string; [ONYXKEYS.COLLECTION.NEXT_STEP]: OnyxTypes.ReportNextStepDeprecated; diff --git a/src/ROUTES.ts b/src/ROUTES.ts index 964a287fa1a0a..b40b6f32ac23e 100644 --- a/src/ROUTES.ts +++ b/src/ROUTES.ts @@ -748,18 +748,21 @@ const ROUTES = { }, }, SPLIT_EXPENSE: { - route: 'create/split-expense/overview/:reportID/:transactionID/:splitExpenseTransactionID?', + // TODO: Remove backTo from route once we have find another way to fix navigation issues with tabs + route: 'create/split-expense/overview/:reportID/:transactionID/:splitExpenseTransactionID/:backTo?', getRoute: (reportID: string | undefined, originalTransactionID: string | undefined, splitExpenseTransactionID?: string, backTo?: string) => { if (!reportID || !originalTransactionID) { Log.warn(`Invalid ${reportID}(reportID) or ${originalTransactionID}(transactionID) is used to build the SPLIT_EXPENSE route`); } + const splitExpenseTransactionIDPart = splitExpenseTransactionID ? `/${splitExpenseTransactionID}` : '/0'; + // eslint-disable-next-line no-restricted-syntax -- Legacy route generation - return getUrlWithBackToParam(`create/split-expense/overview/${reportID}/${originalTransactionID}${splitExpenseTransactionID ? `/${splitExpenseTransactionID}` : ''}`, backTo); + return getUrlWithBackToParam(`create/split-expense/overview/${reportID}/${originalTransactionID}${splitExpenseTransactionIDPart}`, backTo); }, }, SPLIT_EXPENSE_CREATE_DATE_RANGE: { - route: 'create/split-expense/create-date-range/:reportID/:transactionID/:splitExpenseTransactionID?', + route: 'create/split-expense/create-date-range/:reportID/:transactionID?', getRoute: (reportID: string | undefined, transactionID: string | undefined, backTo?: string) => { if (!reportID || !transactionID) { Log.warn(`Invalid ${reportID}(reportID) or ${transactionID}(transactionID) is used to build the SPLIT_EXPENSE_CREATE_DATE_RANGE route`); diff --git a/src/components/SelectionListWithSections/SplitListItem.tsx b/src/components/SelectionListWithSections/SplitListItem.tsx index a296d5b9f0eee..52353aebacdc1 100644 --- a/src/components/SelectionListWithSections/SplitListItem.tsx +++ b/src/components/SelectionListWithSections/SplitListItem.tsx @@ -82,7 +82,7 @@ function SplitListItem({ inputRef.current = ref; }; - const isPercentageMode = splitItem.mode === CONST.IOU.SPLIT_TYPE.PERCENTAGE; + const isPercentageMode = splitItem.mode === CONST.TAB.SPLIT.PERCENTAGE; return ( ; + mode: ValueOf; /** Percentage value to show when in percentage mode (0-100) */ percentage: number; @@ -604,7 +604,7 @@ type SplitListItemType = ListItem & /** * Function for updating value (amount or percentage based on mode) */ - onSplitExpenseValueChange: (transactionID: string, value: number, mode: ValueOf) => void; + onSplitExpenseValueChange: (transactionID: string, value: number, mode: ValueOf) => void; }; type SplitListItemProps = ListItemProps; diff --git a/src/components/TabSelector/TabSelector.tsx b/src/components/TabSelector/TabSelector.tsx index c23b711f669ea..53364fafb1e33 100644 --- a/src/components/TabSelector/TabSelector.tsx +++ b/src/components/TabSelector/TabSelector.tsx @@ -73,11 +73,11 @@ function getIconTitleAndTestID( return {icon: icons.Pencil, title: translate('tabSelector.manual'), testID: 'distanceManual'}; case CONST.TAB_REQUEST.DISTANCE_GPS: return {icon: icons.Crosshair, title: translate('tabSelector.gps'), testID: 'distanceGPS'}; - case CONST.IOU.SPLIT_TYPE.AMOUNT: + case CONST.TAB.SPLIT.AMOUNT: return {icon: icons.MoneyCircle, title: translate('iou.amount'), testID: 'split-amount'}; - case CONST.IOU.SPLIT_TYPE.PERCENTAGE: + case CONST.TAB.SPLIT.PERCENTAGE: return {icon: icons.Percent, title: translate('iou.percent'), testID: 'split-percentage'}; - case CONST.IOU.SPLIT_TYPE.DATE: + case CONST.TAB.SPLIT.DATE: return {icon: icons.CalendarSolid, title: translate('iou.date'), testID: 'split-date'}; default: throw new Error(`Route ${route} has no icon nor title set.`); diff --git a/src/libs/Navigation/OnyxTabNavigator.tsx b/src/libs/Navigation/OnyxTabNavigator.tsx index 43a281e83a0b4..0181a0a46f740 100644 --- a/src/libs/Navigation/OnyxTabNavigator.tsx +++ b/src/libs/Navigation/OnyxTabNavigator.tsx @@ -8,23 +8,22 @@ import FullScreenLoadingIndicator from '@components/FullscreenLoadingIndicator'; import type {TabSelectorProps} from '@components/TabSelector/TabSelector'; import useOnyx from '@hooks/useOnyx'; import useThemeStyles from '@hooks/useThemeStyles'; -import type {IOURequestType} from '@libs/actions/IOU'; import Tab from '@userActions/Tab'; import ONYXKEYS from '@src/ONYXKEYS'; -import type {SelectedTabRequest, SplitSelectedTabRequest} from '@src/types/onyx'; +import type {SelectedTabRequest} from '@src/types/onyx'; import type ChildrenProps from '@src/types/utils/ChildrenProps'; import isLoadingOnyxValue from '@src/types/utils/isLoadingOnyxValue'; import {defaultScreenOptions} from './OnyxTabNavigatorConfig'; -type OnyxTabNavigatorProps = ChildrenProps & { +type OnyxTabNavigatorProps = ChildrenProps & { /** ID of the tab component to be saved in onyx */ id: string; /** Name of the selected tab */ - defaultSelectedTab?: SelectedTabRequest | SplitSelectedTabRequest; + defaultSelectedTab?: TTabName; /** A function triggered when a tab has been selected */ - onTabSelected?: (newIouType: IOURequestType) => void; + onTabSelected?: (newTabName: TTabName) => void; tabBar: (props: TabSelectorProps) => React.ReactNode; @@ -89,7 +88,7 @@ const getTabNames = (children: React.ReactNode): string[] => { // This takes all the same props as MaterialTopTabsNavigator: https://reactnavigation.org/docs/material-top-tab-navigator/#props, // except ID is now required, and it gets a `selectedTab` from Onyx // It also takes 2 more optional callbacks to manage the focus trap container elements of the tab bar and the active tab -function OnyxTabNavigator({ +function OnyxTabNavigator({ id, defaultSelectedTab, tabBar: TabBar, @@ -105,7 +104,7 @@ function OnyxTabNavigator({ onTabSelect, equalWidth = false, ...rest -}: OnyxTabNavigatorProps) { +}: OnyxTabNavigatorProps) { // Mapping of tab name to focus trap container element const [focusTrapContainerElementMapping, setFocusTrapContainerElementMapping] = useState>({}); const [selectedTab, selectedTabResult] = useOnyx(`${ONYXKEYS.COLLECTION.SELECTED_TAB}${id}`, {canBeMissing: true}); @@ -182,8 +181,10 @@ function OnyxTabNavigator({ if (selectedTab === newSelectedTab) { return; } - Tab.setSelectedTab(id, newSelectedTab as SelectedTabRequest); - onTabSelected(newSelectedTab as IOURequestType); + if (newSelectedTab) { + Tab.setSelectedTab(id, newSelectedTab as TTabName); + } + onTabSelected(newSelectedTab as TTabName); }, ...(screenListeners ?? {}), }} diff --git a/src/libs/Navigation/linkingConfig/config.ts b/src/libs/Navigation/linkingConfig/config.ts index 699cd8b36fe01..a296a17d77fef 100644 --- a/src/libs/Navigation/linkingConfig/config.ts +++ b/src/libs/Navigation/linkingConfig/config.ts @@ -1478,14 +1478,14 @@ const config: LinkingOptions['config'] = { path: ROUTES.SPLIT_EXPENSE.route, exact: true, screens: { - [CONST.IOU.SPLIT_TYPE.AMOUNT]: { - path: CONST.IOU.SPLIT_TYPE.AMOUNT, + [CONST.TAB.SPLIT.AMOUNT]: { + path: CONST.TAB.SPLIT.AMOUNT, }, - [CONST.IOU.SPLIT_TYPE.PERCENTAGE]: { - path: CONST.IOU.SPLIT_TYPE.PERCENTAGE, + [CONST.TAB.SPLIT.PERCENTAGE]: { + path: CONST.TAB.SPLIT.PERCENTAGE, }, - [CONST.IOU.SPLIT_TYPE.DATE]: { - path: CONST.IOU.SPLIT_TYPE.DATE, + [CONST.TAB.SPLIT.DATE]: { + path: CONST.TAB.SPLIT.DATE, }, }, }, diff --git a/src/libs/actions/IOU.ts b/src/libs/actions/IOU.ts index c6095be3feeba..9c6e428d02b89 100644 --- a/src/libs/actions/IOU.ts +++ b/src/libs/actions/IOU.ts @@ -14516,6 +14516,8 @@ function addSplitExpenseField(transaction: OnyxEntry, dra reportID: draftTransaction?.reportID, }), ], + splitsStartDate: null, + splitsEndDate: null, }, }); } @@ -14616,6 +14618,8 @@ function removeSplitExpenseField(draftTransaction: OnyxEntry(id: string, index: TTabName) { + Onyx.merge(`${ONYXKEYS.COLLECTION.SELECTED_TAB}${id}`, index as OnyxMergeInput<`${typeof ONYXKEYS.COLLECTION.SELECTED_TAB}${string}`>); } export default { diff --git a/src/pages/iou/SplitAmountList.tsx b/src/pages/iou/SplitAmountList.tsx index ead378fae0dc0..d8ccea36f5713 100644 --- a/src/pages/iou/SplitAmountList.tsx +++ b/src/pages/iou/SplitAmountList.tsx @@ -31,7 +31,7 @@ function SplitAmountList({sections, initiallyFocusedOptionKey, onSelectRow, list ...section, data: section.data.map((item) => ({ ...item, - mode: CONST.IOU.SPLIT_TYPE.AMOUNT, + mode: CONST.TAB.SPLIT.AMOUNT, })), })); }, [sections]); diff --git a/src/pages/iou/SplitExpensePage.tsx b/src/pages/iou/SplitExpensePage.tsx index 9a376c1b85e6e..8a377b625fe20 100644 --- a/src/pages/iou/SplitExpensePage.tsx +++ b/src/pages/iou/SplitExpensePage.tsx @@ -71,7 +71,7 @@ function SplitExpensePage({route}: SplitExpensePageProps) { const searchContext = useSearchContext(); - const [selectedTab] = useOnyx(`${ONYXKEYS.COLLECTION.SPLIT_SELECTED_TAB}${CONST.TAB.SPLIT_EXPENSE_TAB_TYPE}`, {canBeMissing: true}); + const [selectedTab] = useOnyx(`${ONYXKEYS.COLLECTION.SELECTED_TAB}${CONST.TAB.SPLIT_EXPENSE_TAB_TYPE}`, {canBeMissing: true}); const [draftTransaction] = useOnyx(`${ONYXKEYS.COLLECTION.SPLIT_TRANSACTION_DRAFT}${transactionID}`, {canBeMissing: false}); const transactionReport = getReportOrDraftReport(draftTransaction?.reportID); const parentTransactionReport = getReportOrDraftReport(transactionReport?.parentReportID); @@ -111,8 +111,8 @@ function SplitExpensePage({route}: SplitExpensePageProps) { const iouActions = getIOUActionForTransactions([originalTransactionID], expenseReport?.reportID); const {iouReport} = useGetIOUReportFromReportAction(iouActions.at(0)); - const isPercentageMode = selectedTab === CONST.IOU.SPLIT_TYPE.PERCENTAGE; - const isDateMode = selectedTab === CONST.IOU.SPLIT_TYPE.DATE; + const isPercentageMode = (selectedTab as string) === CONST.TAB.SPLIT.PERCENTAGE; + const isDateMode = (selectedTab as string) === CONST.TAB.SPLIT.DATE; const childTransactions = useMemo(() => getChildTransactions(allTransactions, allReports, transactionID), [allReports, allTransactions, transactionID]); const splitFieldDataFromChildTransactions = useMemo(() => childTransactions.map((currentTransaction) => initSplitExpenseItemData(currentTransaction)), [childTransactions]); const splitFieldDataFromOriginalTransaction = useMemo(() => initSplitExpenseItemData(transaction), [transaction]); @@ -242,8 +242,8 @@ function SplitExpensePage({route}: SplitExpensePageProps) { ]); const onSplitExpenseValueChange = useCallback( - (id: string, value: number, mode: ValueOf) => { - if (mode === CONST.IOU.SPLIT_TYPE.AMOUNT || mode === CONST.IOU.SPLIT_TYPE.DATE) { + (id: string, value: number, mode: ValueOf) => { + if (mode === CONST.TAB.SPLIT.AMOUNT || mode === CONST.TAB.SPLIT.DATE) { const amountInCents = convertToBackendAmount(value); updateSplitExpenseAmountField(draftTransaction, id, amountInCents); } else { @@ -301,7 +301,7 @@ function SplitExpensePage({route}: SplitExpensePageProps) { currency: draftTransaction?.currency ?? CONST.CURRENCY.USD, transactionID: item?.transactionID ?? CONST.IOU.OPTIMISTIC_TRANSACTION_ID, currencySymbol, - mode: CONST.IOU.SPLIT_TYPE.AMOUNT, + mode: CONST.TAB.SPLIT.AMOUNT, percentage, onSplitExpenseValueChange, isSelected: splitExpenseTransactionID === item.transactionID, @@ -436,7 +436,7 @@ function SplitExpensePage({route}: SplitExpensePageProps) { ); const headerTitle = useMemo(() => { - if (splitExpenseTransactionID) { + if (Number(splitExpenseTransactionID)) { return translate('iou.editSplits'); } if (isPercentageMode) { @@ -485,10 +485,10 @@ function SplitExpensePage({route}: SplitExpensePageProps) { - + {() => ( @@ -503,7 +503,7 @@ function SplitExpensePage({route}: SplitExpensePageProps) { )} - + {() => ( @@ -518,7 +518,7 @@ function SplitExpensePage({route}: SplitExpensePageProps) { )} - + {() => ( @@ -527,6 +527,7 @@ function SplitExpensePage({route}: SplitExpensePageProps) { sections={sections} initiallyFocusedOptionKey={initiallyFocusedOptionKey ?? undefined} onSelectRow={onSelectRow} + listFooterContent={} /> {footerContent} diff --git a/src/pages/iou/SplitPercentageList.tsx b/src/pages/iou/SplitPercentageList.tsx index edc5514a37b9a..af796b288ed03 100644 --- a/src/pages/iou/SplitPercentageList.tsx +++ b/src/pages/iou/SplitPercentageList.tsx @@ -31,7 +31,7 @@ function SplitPercentageList({sections, initiallyFocusedOptionKey, onSelectRow, ...section, data: section.data.map((item) => ({ ...item, - mode: CONST.IOU.SPLIT_TYPE.PERCENTAGE, + mode: CONST.TAB.SPLIT.PERCENTAGE, })), })); }, [sections]); diff --git a/src/types/onyx/SplitSelectedTabRequest.ts b/src/types/onyx/SplitSelectedTabRequest.ts deleted file mode 100644 index b4166d63dadb7..0000000000000 --- a/src/types/onyx/SplitSelectedTabRequest.ts +++ /dev/null @@ -1,7 +0,0 @@ -import type {ValueOf} from 'type-fest'; -import type CONST from '@src/CONST'; - -/** Selectable IOU request split tabs */ -type SplitSelectedTabRequest = ValueOf; - -export default SplitSelectedTabRequest; diff --git a/src/types/onyx/index.ts b/src/types/onyx/index.ts index 2dab239af2f68..75de16dffe7c6 100644 --- a/src/types/onyx/index.ts +++ b/src/types/onyx/index.ts @@ -115,7 +115,6 @@ import type SelectedTabRequest from './SelectedTabRequest'; import type Session from './Session'; import type ShareTempFile from './ShareTempFile'; import type SidePanel from './SidePanel'; -import type SplitSelectedTabRequest from './SplitSelectedTabRequest'; import type StripeCustomerID from './StripeCustomerID'; import type SupportalPermissionDenied from './SupportalPermissionDenied'; import type Task from './Task'; @@ -230,7 +229,6 @@ export type { ScreenShareRequest, SecurityGroup, SelectedTabRequest, - SplitSelectedTabRequest, Session, Task, TaxRate,