From fa74ef0a209f4d023ffa2f5c97bfdf4d9019ef85 Mon Sep 17 00:00:00 2001
From: Abdelrahman Khattab <abzokhattab@gmail.com>
Date: Tue, 25 Nov 2025 15:43:39 +0100
Subject: [PATCH 01/49] Bring overLimitForwardsTo configuration into New
 Expensify

---
 src/ROUTES.ts                                 |  12 +
 src/SCREENS.ts                                |   2 +
 src/components/ApprovalWorkflowSection.tsx    |  69 +++--
 src/languages/en.ts                           |  17 ++
 src/languages/es.ts                           |  17 ++
 .../ModalStackNavigators/index.tsx            |   4 +
 .../RELATIONS/WORKSPACE_TO_RHP.ts             |   2 +
 src/libs/Navigation/linkingConfig/config.ts   |   6 +
 src/libs/Navigation/types.ts                  |  12 +
 src/libs/WorkflowUtils.ts                     |  21 +-
 .../workflows/WorkspaceWorkflowsPage.tsx      |   1 +
 .../approvals/ApprovalWorkflowEditor.tsx      |  10 +-
 ...aceWorkflowsApprovalsApprovalLimitPage.tsx | 238 ++++++++++++++++++
 ...orkspaceWorkflowsApprovalsApproverPage.tsx |   9 +-
 ...orkflowsApprovalsOverLimitApproverPage.tsx | 158 ++++++++++++
 src/types/onyx/ApprovalWorkflow.ts            |  10 +
 16 files changed, 560 insertions(+), 28 deletions(-)
 create mode 100644 src/pages/workspace/workflows/approvals/WorkspaceWorkflowsApprovalsApprovalLimitPage.tsx
 create mode 100644 src/pages/workspace/workflows/approvals/WorkspaceWorkflowsApprovalsOverLimitApproverPage.tsx

diff --git a/src/ROUTES.ts b/src/ROUTES.ts
index f69d235c0700..429c6929a6b6 100644
--- a/src/ROUTES.ts
+++ b/src/ROUTES.ts
@@ -1672,6 +1672,18 @@ const ROUTES = {
             // eslint-disable-next-line no-restricted-syntax -- Legacy route generation
             getUrlWithBackToParam(`workspaces/${policyID}/workflows/approvals/approver?approverIndex=${approverIndex}` as const, backTo),
     },
+    WORKSPACE_WORKFLOWS_APPROVALS_APPROVAL_LIMIT: {
+        route: 'workspaces/:policyID/workflows/approvals/approval-limit',
+        getRoute: (policyID: string, approverIndex: number, backTo?: string) =>
+            // eslint-disable-next-line no-restricted-syntax -- Legacy route generation
+            getUrlWithBackToParam(`workspaces/${policyID}/workflows/approvals/approval-limit?approverIndex=${approverIndex}` as const, backTo),
+    },
+    WORKSPACE_WORKFLOWS_APPROVALS_OVER_LIMIT_APPROVER: {
+        route: 'workspaces/:policyID/workflows/approvals/over-limit-approver',
+        getRoute: (policyID: string, approverIndex: number, backTo?: string) =>
+            // eslint-disable-next-line no-restricted-syntax -- Legacy route generation
+            getUrlWithBackToParam(`workspaces/${policyID}/workflows/approvals/over-limit-approver?approverIndex=${approverIndex}` as const, backTo),
+    },
     WORKSPACE_WORKFLOWS_PAYER: {
         route: 'workspaces/:policyID/workflows/payer',
         getRoute: (policyId: string) => `workspaces/${policyId}/workflows/payer` as const,
diff --git a/src/SCREENS.ts b/src/SCREENS.ts
index 966881477b22..9b56318441b7 100644
--- a/src/SCREENS.ts
+++ b/src/SCREENS.ts
@@ -642,6 +642,8 @@ const SCREENS = {
         WORKFLOWS_APPROVALS_EDIT: 'Workspace_Approvals_Edit',
         WORKFLOWS_APPROVALS_EXPENSES_FROM: 'Workspace_Workflows_Approvals_Expenses_From',
         WORKFLOWS_APPROVALS_APPROVER: 'Workspace_Workflows_Approvals_Approver',
+        WORKFLOWS_APPROVALS_APPROVAL_LIMIT: 'Workspace_Workflows_Approvals_Approval_Limit',
+        WORKFLOWS_APPROVALS_OVER_LIMIT_APPROVER: 'Workspace_Workflows_Approvals_Over_Limit_Approver',
         WORKFLOWS_AUTO_REPORTING_FREQUENCY: 'Workspace_Workflows_Auto_Reporting_Frequency',
         WORKFLOWS_AUTO_REPORTING_MONTHLY_OFFSET: 'Workspace_Workflows_Auto_Reporting_Monthly_Offset',
         WORKFLOWS_CONNECT_EXISTING_BANK_ACCOUNT: 'Workspace_Workflows_Connect_Existing_Bank_Account',
diff --git a/src/components/ApprovalWorkflowSection.tsx b/src/components/ApprovalWorkflowSection.tsx
index 00118eda37a9..0d1bcabe06c4 100644
--- a/src/components/ApprovalWorkflowSection.tsx
+++ b/src/components/ApprovalWorkflowSection.tsx
@@ -6,8 +6,11 @@ import useLocalize from '@hooks/useLocalize';
 import useResponsiveLayout from '@hooks/useResponsiveLayout';
 import useTheme from '@hooks/useTheme';
 import useThemeStyles from '@hooks/useThemeStyles';
+import {convertToDisplayString} from '@libs/CurrencyUtils';
 import {sortAlphabetically} from '@libs/OptionsListUtils';
+import CONST from '@src/CONST';
 import type ApprovalWorkflow from '@src/types/onyx/ApprovalWorkflow';
+import type {Approver} from '@src/types/onyx/ApprovalWorkflow';
 import Icon from './Icon';
 // eslint-disable-next-line no-restricted-imports
 import * as Expensicons from './Icon/Expensicons';
@@ -21,9 +24,12 @@ type ApprovalWorkflowSectionProps = {
 
     /** A function that is called when the section is pressed */
     onPress: () => void;
+
+    /** Currency used for formatting approval limits */
+    currency?: string;
 };
 
-function ApprovalWorkflowSection({approvalWorkflow, onPress}: ApprovalWorkflowSectionProps) {
+function ApprovalWorkflowSection({approvalWorkflow, onPress, currency = CONST.CURRENCY.USD}: ApprovalWorkflowSectionProps) {
     const icons = useMemoizedLazyExpensifyIcons(['Users', 'UserCheck'] as const);
     const styles = useThemeStyles();
     const theme = useTheme();
@@ -37,6 +43,23 @@ function ApprovalWorkflowSection({approvalWorkflow, onPress}: ApprovalWorkflowSe
         [approvalWorkflow.approvers.length, toLocaleOrdinal, translate],
     );
 
+    const getApprovalLimitDescription = useCallback(
+        (approver: Approver): string | undefined => {
+            if (!approver.approvalLimit || !approver.overLimitForwardsTo) {
+                return undefined;
+            }
+
+            const formattedAmount = convertToDisplayString(approver.approvalLimit, currency);
+            const approverDisplayName = Str.removeSMSDomain(approver.overLimitForwardsTo);
+
+            return translate('workflowsApprovalLimitPage.forwardLimitDescription', {
+                approvalLimit: formattedAmount,
+                approverName: approverDisplayName,
+            });
+        },
+        [currency, translate],
+    );
+
     const members = useMemo(() => {
         if (approvalWorkflow.isDefault) {
             return translate('workspace.common.everyone');
@@ -86,26 +109,30 @@ function ApprovalWorkflowSection({approvalWorkflow, onPress}: ApprovalWorkflowSe
                     shouldRemoveBackground
                 />
 
-                {approvalWorkflow.approvers.map((approver, index) => (
-                    // eslint-disable-next-line react/no-array-index-key
-                    <View key={`approver-${approver.email}-${index}`}>
-                        <View style={styles.workflowApprovalVerticalLine} />
-                        <MenuItem
-                            title={approverTitle(index)}
-                            style={styles.p0}
-                            titleStyle={styles.textLabelSupportingNormal}
-                            descriptionTextStyle={[styles.textNormalThemeText, styles.lineHeightXLarge]}
-                            description={Str.removeSMSDomain(approver.displayName)}
-                            icon={icons.UserCheck}
-                            iconHeight={20}
-                            iconWidth={20}
-                            numberOfLinesDescription={1}
-                            iconFill={theme.icon}
-                            onPress={onPress}
-                            shouldRemoveBackground
-                        />
-                    </View>
-                ))}
+                {approvalWorkflow.approvers.map((approver, index) => {
+                    const approvalLimitDescription = getApprovalLimitDescription(approver);
+                    return (
+                        // eslint-disable-next-line react/no-array-index-key
+                        <View key={`approver-${approver.email}-${index}`}>
+                            <View style={styles.workflowApprovalVerticalLine} />
+                            <MenuItem
+                                title={approverTitle(index)}
+                                style={styles.p0}
+                                titleStyle={styles.textLabelSupportingNormal}
+                                descriptionTextStyle={[styles.textNormalThemeText, styles.lineHeightXLarge]}
+                                description={Str.removeSMSDomain(approver.displayName)}
+                                icon={icons.UserCheck}
+                                iconHeight={20}
+                                iconWidth={20}
+                                numberOfLinesDescription={1}
+                                iconFill={theme.icon}
+                                onPress={onPress}
+                                shouldRemoveBackground
+                                helperText={approvalLimitDescription}
+                            />
+                        </View>
+                    );
+                })}
             </View>
             <Icon
                 src={expensifyIcons.ArrowRight}
diff --git a/src/languages/en.ts b/src/languages/en.ts
index dbf65a7a62c8..87cf839d693e 100755
--- a/src/languages/en.ts
+++ b/src/languages/en.ts
@@ -2266,6 +2266,23 @@ const translations = {
         genericErrorMessage: "The approver couldn't be changed. Please try again or contact support.",
         header: 'Send to this member for approval:',
     },
+    workflowsApprovalLimitPage: {
+        title: 'Approver',
+        header: '(Optional) Want to add an approval limit?',
+        description: ({approverName}: {approverName: string}) =>
+            `Add another approver when <strong>${approverName}</strong> is approver and report exceeds the amount below:`,
+        reportAmountLabel: 'Report amount',
+        additionalApproverLabel: 'Additional approver',
+        skip: 'Skip',
+        next: 'Next',
+        enterAmountError: 'Please enter a valid amount',
+        enterApproverError: 'Please enter an approver',
+        enterBothError: 'Enter a report amount and additional approver',
+        circularReferenceError: ({approverName}: {approverName: string}) =>
+            `<strong>${approverName}</strong> already approves reports in this workflow. Choose a different approver to avoid a circular workflow.`,
+        forwardLimitDescription: ({approvalLimit, approverName}: {approvalLimit: string; approverName: string}) =>
+            `Reports above ${approvalLimit} forward to ${approverName}`,
+    },
     workflowsPayerPage: {
         title: 'Authorized payer',
         genericErrorMessage: 'The authorized payer could not be changed. Please try again.',
diff --git a/src/languages/es.ts b/src/languages/es.ts
index 7ad1473b0224..b63c807bdd81 100644
--- a/src/languages/es.ts
+++ b/src/languages/es.ts
@@ -1909,6 +1909,23 @@ ${amount} para ${merchant} - ${date}`,
         genericErrorMessage: 'El aprobador no pudo ser cambiado. Por favor, inténtelo de nuevo o contacte al soporte.',
         header: 'Enviar a este miembro para su aprobación:',
     },
+    workflowsApprovalLimitPage: {
+        title: 'Aprobador',
+        header: '(Opcional) ¿Quieres añadir un límite de aprobación?',
+        description: ({approverName}: {approverName: string}) =>
+            `Añadir otro aprobador cuando <strong>${approverName}</strong> es aprobador y el informe excede el monto a continuación:`,
+        reportAmountLabel: 'Monto del informe',
+        additionalApproverLabel: 'Aprobador adicional',
+        skip: 'Omitir',
+        next: 'Siguiente',
+        enterAmountError: 'Por favor ingrese un monto válido',
+        enterApproverError: 'Por favor ingrese un aprobador',
+        enterBothError: 'Ingrese un monto del informe y un aprobador adicional',
+        circularReferenceError: ({approverName}: {approverName: string}) =>
+            `<strong>${approverName}</strong> ya aprueba informes en este flujo de trabajo. Elija un aprobador diferente para evitar un flujo de trabajo circular.`,
+        forwardLimitDescription: ({approvalLimit, approverName}: {approvalLimit: string; approverName: string}) =>
+            `Informes por encima de ${approvalLimit} se envían a ${approverName}`,
+    },
     workflowsPayerPage: {
         title: 'Pagador autorizado',
         genericErrorMessage: 'El pagador autorizado no se pudo cambiar. Por favor, inténtalo mas tarde.',
diff --git a/src/libs/Navigation/AppNavigator/ModalStackNavigators/index.tsx b/src/libs/Navigation/AppNavigator/ModalStackNavigators/index.tsx
index 2b8a6bd45529..41286a32d2df 100644
--- a/src/libs/Navigation/AppNavigator/ModalStackNavigators/index.tsx
+++ b/src/libs/Navigation/AppNavigator/ModalStackNavigators/index.tsx
@@ -413,6 +413,10 @@ const SettingsModalStackNavigator = createModalStackNavigator<SettingsNavigatorP
     [SCREENS.WORKSPACE.WORKFLOWS_APPROVALS_EXPENSES_FROM]: () =>
         require<ReactComponentModule>('../../../../pages/workspace/workflows/approvals/WorkspaceWorkflowsApprovalsExpensesFromPage').default,
     [SCREENS.WORKSPACE.WORKFLOWS_APPROVALS_APPROVER]: () => require<ReactComponentModule>('../../../../pages/workspace/workflows/approvals/WorkspaceWorkflowsApprovalsApproverPage').default,
+    [SCREENS.WORKSPACE.WORKFLOWS_APPROVALS_APPROVAL_LIMIT]: () =>
+        require<ReactComponentModule>('../../../../pages/workspace/workflows/approvals/WorkspaceWorkflowsApprovalsApprovalLimitPage').default,
+    [SCREENS.WORKSPACE.WORKFLOWS_APPROVALS_OVER_LIMIT_APPROVER]: () =>
+        require<ReactComponentModule>('../../../../pages/workspace/workflows/approvals/WorkspaceWorkflowsApprovalsOverLimitApproverPage').default,
     [SCREENS.WORKSPACE.INVITE_MESSAGE]: () => require<ReactComponentModule>('../../../../pages/workspace/WorkspaceInviteMessagePage').default,
     [SCREENS.WORKSPACE.INVITE_MESSAGE_ROLE]: () => require<ReactComponentModule>('../../../../pages/workspace/WorkspaceInviteMessageRolePage').default,
     [SCREENS.WORKSPACE.WORKFLOWS_PAYER]: () => require<ReactComponentModule>('../../../../pages/workspace/workflows/WorkspaceWorkflowsPayerPage').default,
diff --git a/src/libs/Navigation/linkingConfig/RELATIONS/WORKSPACE_TO_RHP.ts b/src/libs/Navigation/linkingConfig/RELATIONS/WORKSPACE_TO_RHP.ts
index 3bb9ceba4f8b..4b5c2ae202f3 100755
--- a/src/libs/Navigation/linkingConfig/RELATIONS/WORKSPACE_TO_RHP.ts
+++ b/src/libs/Navigation/linkingConfig/RELATIONS/WORKSPACE_TO_RHP.ts
@@ -30,6 +30,8 @@ const WORKSPACE_TO_RHP: Partial<Record<keyof WorkspaceSplitNavigatorParamList, s
         SCREENS.WORKSPACE.WORKFLOWS_APPROVALS_EDIT,
         SCREENS.WORKSPACE.WORKFLOWS_APPROVALS_EXPENSES_FROM,
         SCREENS.WORKSPACE.WORKFLOWS_APPROVALS_APPROVER,
+        SCREENS.WORKSPACE.WORKFLOWS_APPROVALS_APPROVAL_LIMIT,
+        SCREENS.WORKSPACE.WORKFLOWS_APPROVALS_OVER_LIMIT_APPROVER,
         SCREENS.WORKSPACE.WORKFLOWS_AUTO_REPORTING_FREQUENCY,
         SCREENS.WORKSPACE.WORKFLOWS_AUTO_REPORTING_MONTHLY_OFFSET,
         SCREENS.WORKSPACE.WORKFLOWS_PAYER,
diff --git a/src/libs/Navigation/linkingConfig/config.ts b/src/libs/Navigation/linkingConfig/config.ts
index 74662cbff8ef..2f129a214c6b 100644
--- a/src/libs/Navigation/linkingConfig/config.ts
+++ b/src/libs/Navigation/linkingConfig/config.ts
@@ -777,6 +777,12 @@ const config: LinkingOptions<RootNavigatorParamList>['config'] = {
                         [SCREENS.WORKSPACE.WORKFLOWS_APPROVALS_APPROVER]: {
                             path: ROUTES.WORKSPACE_WORKFLOWS_APPROVALS_APPROVER.route,
                         },
+                        [SCREENS.WORKSPACE.WORKFLOWS_APPROVALS_APPROVAL_LIMIT]: {
+                            path: ROUTES.WORKSPACE_WORKFLOWS_APPROVALS_APPROVAL_LIMIT.route,
+                        },
+                        [SCREENS.WORKSPACE.WORKFLOWS_APPROVALS_OVER_LIMIT_APPROVER]: {
+                            path: ROUTES.WORKSPACE_WORKFLOWS_APPROVALS_OVER_LIMIT_APPROVER.route,
+                        },
                         [SCREENS.WORKSPACE.INVITE_MESSAGE]: {
                             path: ROUTES.WORKSPACE_INVITE_MESSAGE.route,
                         },
diff --git a/src/libs/Navigation/types.ts b/src/libs/Navigation/types.ts
index 7e824f63d55d..565d9fbe42e5 100644
--- a/src/libs/Navigation/types.ts
+++ b/src/libs/Navigation/types.ts
@@ -2271,6 +2271,18 @@ type WorkspaceSplitNavigatorParamList = {
         // eslint-disable-next-line no-restricted-syntax -- `backTo` usages in this file are legacy. Do not add new `backTo` params to screens. See contributingGuides/NAVIGATION.md
         backTo?: Routes;
     };
+    [SCREENS.WORKSPACE.WORKFLOWS_APPROVALS_APPROVAL_LIMIT]: {
+        policyID: string;
+        approverIndex: number;
+        // eslint-disable-next-line no-restricted-syntax -- `backTo` usages in this file are legacy. Do not add new `backTo` params to screens. See contributingGuides/NAVIGATION.md
+        backTo?: Routes;
+    };
+    [SCREENS.WORKSPACE.WORKFLOWS_APPROVALS_OVER_LIMIT_APPROVER]: {
+        policyID: string;
+        approverIndex: number;
+        // eslint-disable-next-line no-restricted-syntax -- `backTo` usages in this file are legacy. Do not add new `backTo` params to screens. See contributingGuides/NAVIGATION.md
+        backTo?: Routes;
+    };
     [SCREENS.WORKSPACE.WORKFLOWS_AUTO_REPORTING_FREQUENCY]: {
         policyID: string;
     };
diff --git a/src/libs/WorkflowUtils.ts b/src/libs/WorkflowUtils.ts
index 72f0b7b4582a..e3fd67a1e1d6 100644
--- a/src/libs/WorkflowUtils.ts
+++ b/src/libs/WorkflowUtils.ts
@@ -52,12 +52,15 @@ function calculateApprovers({employees, firstEmail, personalDetailsByEmail}: Get
         }
 
         const isCircularReference = currentApproverEmails.has(nextEmail);
+        const employee = employees[nextEmail];
         approvers.push({
             email: nextEmail,
-            forwardsTo: employees[nextEmail].forwardsTo,
+            forwardsTo: employee.forwardsTo,
             avatar: personalDetailsByEmail[nextEmail]?.avatar,
             displayName: personalDetailsByEmail[nextEmail]?.displayName ?? nextEmail,
             isCircularReference,
+            approvalLimit: employee.approvalLimit,
+            overLimitForwardsTo: employee.overLimitForwardsTo,
         });
 
         // If we've already seen this approver, break to prevent infinite loop
@@ -255,17 +258,25 @@ function convertApprovalWorkflowToPolicyEmployees({
     for (const [index, approver] of approvalWorkflow.approvers.entries()) {
         const nextApprover = approvalWorkflow.approvers.at(index + 1);
         const forwardsTo = type === CONST.APPROVAL_WORKFLOW.TYPE.REMOVE ? '' : (nextApprover?.email ?? '');
+        const approvalLimit = type === CONST.APPROVAL_WORKFLOW.TYPE.REMOVE ? undefined : approver.approvalLimit;
+        const overLimitForwardsTo = type === CONST.APPROVAL_WORKFLOW.TYPE.REMOVE ? '' : (approver.overLimitForwardsTo ?? '');
 
-        // For every approver, we check if the forwardsTo field has changed.
-        // If it has, we update the employee list with the new forwardsTo value.
-        if (previousEmployeeList[approver.email]?.forwardsTo === forwardsTo) {
+        // For every approver, we check if the forwardsTo, approvalLimit, or overLimitForwardsTo fields have changed.
+        const previousEmployee = previousEmployeeList[approver.email];
+        const forwardsToChanged = previousEmployee?.forwardsTo !== forwardsTo;
+        const approvalLimitChanged = previousEmployee?.approvalLimit !== approvalLimit;
+        const overLimitForwardsToChanged = previousEmployee?.overLimitForwardsTo !== overLimitForwardsTo;
+
+        if (!forwardsToChanged && !approvalLimitChanged && !overLimitForwardsToChanged) {
             continue;
         }
 
-        const previousPendingAction = previousEmployeeList[approver.email]?.pendingAction;
+        const previousPendingAction = previousEmployee?.pendingAction;
         updatedEmployeeList[approver.email] = {
             email: approver.email,
             forwardsTo,
+            ...(approvalLimit !== undefined ? {approvalLimit} : {}),
+            ...(overLimitForwardsTo ? {overLimitForwardsTo} : {}),
             pendingAction: previousPendingAction === CONST.RED_BRICK_ROAD_PENDING_ACTION.DELETE ? previousPendingAction : pendingAction,
             pendingFields: {
                 forwardsTo: pendingAction,
diff --git a/src/pages/workspace/workflows/WorkspaceWorkflowsPage.tsx b/src/pages/workspace/workflows/WorkspaceWorkflowsPage.tsx
index a9e5827b71a9..b7ec78757792 100644
--- a/src/pages/workspace/workflows/WorkspaceWorkflowsPage.tsx
+++ b/src/pages/workspace/workflows/WorkspaceWorkflowsPage.tsx
@@ -273,6 +273,7 @@ function WorkspaceWorkflowsPage({policy, route}: WorkspaceWorkflowsPageProps) {
                                 <ApprovalWorkflowSection
                                     approvalWorkflow={workflow}
                                     onPress={() => Navigation.navigate(ROUTES.WORKSPACE_WORKFLOWS_APPROVALS_EDIT.getRoute(route.params.policyID, workflow.approvers.at(0)?.email ?? ''))}
+                                    currency={policy?.outputCurrency}
                                 />
                             </OfflineWithFeedback>
                         ))}
diff --git a/src/pages/workspace/workflows/approvals/ApprovalWorkflowEditor.tsx b/src/pages/workspace/workflows/approvals/ApprovalWorkflowEditor.tsx
index 9bfa7ec7fbb3..4b1a017d2ba4 100644
--- a/src/pages/workspace/workflows/approvals/ApprovalWorkflowEditor.tsx
+++ b/src/pages/workspace/workflows/approvals/ApprovalWorkflowEditor.tsx
@@ -107,10 +107,18 @@ function ApprovalWorkflowEditor({approvalWorkflow, removeApprovalWorkflow, polic
 
     const editApprover = useCallback(
         (approverIndex: number) => {
+            const approver = approvalWorkflow.approvers.at(approverIndex);
             const backTo = approvalWorkflow.action === CONST.APPROVAL_WORKFLOW.ACTION.CREATE ? ROUTES.WORKSPACE_WORKFLOWS_APPROVALS_NEW.getRoute(policyID) : undefined;
+
+            // If the approver has an approval limit set, navigate to the approval limit page for editing
+            if (approver?.approvalLimit && approver?.overLimitForwardsTo) {
+                Navigation.navigate(ROUTES.WORKSPACE_WORKFLOWS_APPROVALS_APPROVAL_LIMIT.getRoute(policyID, approverIndex, backTo));
+                return;
+            }
+
             Navigation.navigate(ROUTES.WORKSPACE_WORKFLOWS_APPROVALS_APPROVER.getRoute(policyID, approverIndex, backTo));
         },
-        [approvalWorkflow.action, policyID],
+        [approvalWorkflow.action, approvalWorkflow.approvers, policyID],
     );
 
     // User should be allowed to add additional approver only if they upgraded to Control Plan, otherwise redirected to the Upgrade Page
diff --git a/src/pages/workspace/workflows/approvals/WorkspaceWorkflowsApprovalsApprovalLimitPage.tsx b/src/pages/workspace/workflows/approvals/WorkspaceWorkflowsApprovalsApprovalLimitPage.tsx
new file mode 100644
index 000000000000..1de61736491c
--- /dev/null
+++ b/src/pages/workspace/workflows/approvals/WorkspaceWorkflowsApprovalsApprovalLimitPage.tsx
@@ -0,0 +1,238 @@
+import {Str} from 'expensify-common';
+import React, {useCallback, useMemo, useState} from 'react';
+import {View} from 'react-native';
+import AmountForm from '@components/AmountForm';
+import FullPageNotFoundView from '@components/BlockingViews/FullPageNotFoundView';
+import Button from '@components/Button';
+import DotIndicatorMessage from '@components/DotIndicatorMessage';
+import HeaderWithBackButton from '@components/HeaderWithBackButton';
+import MenuItemWithTopDescription from '@components/MenuItemWithTopDescription';
+import RenderHTML from '@components/RenderHTML';
+import ScreenWrapper from '@components/ScreenWrapper';
+import ScrollView from '@components/ScrollView';
+import Text from '@components/Text';
+import useBottomSafeSafeAreaPaddingStyle from '@hooks/useBottomSafeSafeAreaPaddingStyle';
+import useLocalize from '@hooks/useLocalize';
+import useOnyx from '@hooks/useOnyx';
+import usePolicy from '@hooks/usePolicy';
+import useThemeStyles from '@hooks/useThemeStyles';
+import {convertToBackendAmount, convertToFrontendAmountAsString} from '@libs/CurrencyUtils';
+import Navigation from '@libs/Navigation/Navigation';
+import type {PlatformStackScreenProps} from '@libs/Navigation/PlatformStackNavigation/types';
+import type {WorkspaceSplitNavigatorParamList} from '@libs/Navigation/types';
+import {goBackFromInvalidPolicy, isPendingDeletePolicy, isPolicyAdmin} from '@libs/PolicyUtils';
+import AccessOrNotFoundWrapper from '@pages/workspace/AccessOrNotFoundWrapper';
+import withPolicyAndFullscreenLoading from '@pages/workspace/withPolicyAndFullscreenLoading';
+import type {WithPolicyAndFullscreenLoadingProps} from '@pages/workspace/withPolicyAndFullscreenLoading';
+import {setApprovalWorkflowApprover} from '@userActions/Workflow';
+import CONST from '@src/CONST';
+import ONYXKEYS from '@src/ONYXKEYS';
+import ROUTES from '@src/ROUTES';
+import type SCREENS from '@src/SCREENS';
+import {personalDetailsByEmailSelector} from '@src/selectors/PersonalDetails';
+import {isEmptyObject} from '@src/types/utils/EmptyObject';
+
+type WorkspaceWorkflowsApprovalsApprovalLimitPageProps = WithPolicyAndFullscreenLoadingProps &
+    PlatformStackScreenProps<WorkspaceSplitNavigatorParamList, typeof SCREENS.WORKSPACE.WORKFLOWS_APPROVALS_APPROVAL_LIMIT>;
+
+function WorkspaceWorkflowsApprovalsApprovalLimitPage({policy, isLoadingReportData = true, route}: WorkspaceWorkflowsApprovalsApprovalLimitPageProps) {
+    const styles = useThemeStyles();
+    const {translate} = useLocalize();
+    const policyFromHook = usePolicy(route.params.policyID);
+    const [approvalWorkflow] = useOnyx(ONYXKEYS.APPROVAL_WORKFLOW, {canBeMissing: true});
+    const [personalDetailsByEmail] = useOnyx(ONYXKEYS.PERSONAL_DETAILS_LIST, {
+        canBeMissing: true,
+        selector: personalDetailsByEmailSelector,
+    });
+
+    const approverIndex = Number(route.params.approverIndex) ?? 0;
+    const currentApprover = approvalWorkflow?.approvers?.[approverIndex];
+    const currency = policyFromHook?.outputCurrency ?? CONST.CURRENCY.USD;
+
+    const [approvalLimit, setApprovalLimit] = useState<string>(() => {
+        if (currentApprover?.approvalLimit) {
+            return convertToFrontendAmountAsString(currentApprover.approvalLimit, currency);
+        }
+        return '';
+    });
+
+    const [hasSubmitted, setHasSubmitted] = useState(false);
+
+    // Read the overLimitForwardsTo directly from the current approver in the workflow
+    // This ensures we get the updated value after returning from the approver selector
+    const selectedApproverEmail = currentApprover?.overLimitForwardsTo ?? '';
+
+    const selectedApproverDisplayName = useMemo(() => {
+        if (!selectedApproverEmail) {
+            return '';
+        }
+        const personalDetails = personalDetailsByEmail?.[selectedApproverEmail];
+        return Str.removeSMSDomain(personalDetails?.displayName ?? selectedApproverEmail);
+    }, [selectedApproverEmail, personalDetailsByEmail]);
+
+    // Check if selected approver already exists in the workflow (circular reference)
+    const isCircularReference = useMemo(() => {
+        if (!selectedApproverEmail || !approvalWorkflow?.approvers) {
+            return false;
+        }
+        return approvalWorkflow.approvers.some((approver) => approver?.email === selectedApproverEmail);
+    }, [selectedApproverEmail, approvalWorkflow?.approvers]);
+
+    // eslint-disable-next-line rulesdir/no-negated-variables
+    const shouldShowNotFoundView = (isEmptyObject(policy) && !isLoadingReportData) || !isPolicyAdmin(policy) || isPendingDeletePolicy(policy);
+
+    const hasAmount = approvalLimit.length > 0 && Number(approvalLimit) > 0;
+    const hasApprover = selectedApproverEmail.length > 0;
+
+    // Determine which error type to show based on the state
+    // When both are empty: show only the combined error at bottom
+    // When only one is empty: show error on that specific field
+    const bothEmpty = !hasAmount && !hasApprover;
+    const onlyAmountEmpty = !hasAmount && hasApprover;
+    const onlyApproverEmpty = hasAmount && !hasApprover;
+
+    // Bottom error message - only shown when both fields are empty
+    const bottomErrorMessage = hasSubmitted && bothEmpty ? translate('workflowsApprovalLimitPage.enterBothError') : '';
+
+    // Field-level errors - only shown when the OTHER field has a value
+    const amountErrorText = hasSubmitted && onlyAmountEmpty ? translate('workflowsApprovalLimitPage.enterAmountError') : undefined;
+    const approverErrorText = useMemo(() => {
+        if (isCircularReference) {
+            return translate('workflowsApprovalLimitPage.circularReferenceError', {approverName: selectedApproverDisplayName});
+        }
+        if (hasSubmitted && onlyApproverEmpty) {
+            return translate('workflowsApprovalLimitPage.enterApproverError');
+        }
+        return undefined;
+    }, [hasSubmitted, onlyApproverEmpty, isCircularReference, selectedApproverDisplayName, translate]);
+
+    const handleSkip = useCallback(() => {
+        Navigation.navigate(ROUTES.WORKSPACE_WORKFLOWS_APPROVALS_NEW.getRoute(route.params.policyID));
+    }, [route.params.policyID]);
+
+    const handleNext = useCallback(() => {
+        setHasSubmitted(true);
+
+        if (!hasAmount || !hasApprover || isCircularReference) {
+            return;
+        }
+
+        if (!approvalWorkflow || !currentApprover) {
+            return;
+        }
+
+        const limitInCents = convertToBackendAmount(Number.parseFloat(approvalLimit));
+
+        // Update the approver with the approval limit and overLimitForwardsTo
+        setApprovalWorkflowApprover({
+            approver: {
+                ...currentApprover,
+                approvalLimit: limitInCents,
+                overLimitForwardsTo: selectedApproverEmail,
+            },
+            approverIndex,
+            currentApprovalWorkflow: approvalWorkflow,
+            policy: policyFromHook,
+            personalDetailsByEmail,
+        });
+
+        Navigation.navigate(ROUTES.WORKSPACE_WORKFLOWS_APPROVALS_NEW.getRoute(route.params.policyID));
+    }, [approvalLimit, selectedApproverEmail, isCircularReference, approvalWorkflow, currentApprover, approverIndex, policyFromHook, personalDetailsByEmail, route.params.policyID]);
+
+    const navigateToApproverSelector = useCallback(() => {
+        // Navigate to the over-limit approver selector page
+        Navigation.navigate(ROUTES.WORKSPACE_WORKFLOWS_APPROVALS_OVER_LIMIT_APPROVER.getRoute(route.params.policyID, approverIndex));
+    }, [route.params.policyID, approverIndex]);
+
+    const buttonContainerStyle = useBottomSafeSafeAreaPaddingStyle({addBottomSafeAreaPadding: true, style: [styles.mh5, styles.mb5]});
+
+    const approverDisplayName = currentApprover ? Str.removeSMSDomain(currentApprover.displayName) : '';
+
+    return (
+        <AccessOrNotFoundWrapper
+            policyID={route.params.policyID}
+            featureName={CONST.POLICY.MORE_FEATURES.ARE_WORKFLOWS_ENABLED}
+        >
+            <ScreenWrapper
+                enableEdgeToEdgeBottomSafeAreaPadding
+                testID={WorkspaceWorkflowsApprovalsApprovalLimitPage.displayName}
+            >
+                <FullPageNotFoundView
+                    shouldShow={shouldShowNotFoundView}
+                    subtitleKey={isEmptyObject(policy) ? undefined : 'workspace.common.notAuthorized'}
+                    onBackButtonPress={goBackFromInvalidPolicy}
+                    onLinkPress={goBackFromInvalidPolicy}
+                    addBottomSafeAreaPadding
+                >
+                    <HeaderWithBackButton
+                        title={translate('workflowsApprovalLimitPage.title')}
+                        onBackButtonPress={() => Navigation.goBack(ROUTES.WORKSPACE_WORKFLOWS_APPROVALS_APPROVER.getRoute(route.params.policyID, approverIndex))}
+                    />
+                    <ScrollView
+                        style={styles.flex1}
+                        contentContainerStyle={styles.flexGrow1}
+                    >
+                        <View style={[styles.mh5, styles.flex1]}>
+                            <Text style={[styles.textHeadlineH1, styles.mv3]}>{translate('workflowsApprovalLimitPage.header')}</Text>
+                            <View style={styles.mb5}>
+                                <RenderHTML html={translate('workflowsApprovalLimitPage.description', {approverName: approverDisplayName})} />
+                            </View>
+
+                            <View style={styles.mb4}>
+                                <AmountForm
+                                    label={translate('workflowsApprovalLimitPage.reportAmountLabel')}
+                                    currency={currency}
+                                    value={approvalLimit}
+                                    onInputChange={setApprovalLimit}
+                                    isCurrencyPressable={false}
+                                    displayAsTextInput
+                                    errorText={amountErrorText}
+                                />
+                            </View>
+
+                            <MenuItemWithTopDescription
+                                title={selectedApproverDisplayName}
+                                titleStyle={styles.textNormalThemeText}
+                                description={translate('workflowsApprovalLimitPage.additionalApproverLabel')}
+                                descriptionTextStyle={selectedApproverDisplayName ? styles.textLabelSupportingNormal : undefined}
+                                onPress={navigateToApproverSelector}
+                                shouldShowRightIcon
+                                wrapperStyle={styles.sectionMenuItemTopDescription}
+                                brickRoadIndicator={approverErrorText ? CONST.BRICK_ROAD_INDICATOR_STATUS.ERROR : undefined}
+                                errorText={approverErrorText}
+                                shouldRenderErrorAsHTML
+                            />
+                        </View>
+
+                        {!!bottomErrorMessage && (
+                            <DotIndicatorMessage
+                                type="error"
+                                messages={{error: bottomErrorMessage}}
+                                style={[styles.mh5, styles.mb3]}
+                            />
+                        )}
+                    </ScrollView>
+
+                    <View style={buttonContainerStyle}>
+                        <Button
+                            large
+                            text={translate('workflowsApprovalLimitPage.skip')}
+                            onPress={handleSkip}
+                            style={styles.mb3}
+                        />
+                        <Button
+                            large
+                            success
+                            text={translate('workflowsApprovalLimitPage.next')}
+                            onPress={handleNext}
+                        />
+                    </View>
+                </FullPageNotFoundView>
+            </ScreenWrapper>
+        </AccessOrNotFoundWrapper>
+    );
+}
+
+WorkspaceWorkflowsApprovalsApprovalLimitPage.displayName = 'WorkspaceWorkflowsApprovalsApprovalLimitPage';
+
+export default withPolicyAndFullscreenLoading(WorkspaceWorkflowsApprovalsApprovalLimitPage);
diff --git a/src/pages/workspace/workflows/approvals/WorkspaceWorkflowsApprovalsApproverPage.tsx b/src/pages/workspace/workflows/approvals/WorkspaceWorkflowsApprovalsApproverPage.tsx
index 485e6a7cfa49..f50bc18f9e60 100644
--- a/src/pages/workspace/workflows/approvals/WorkspaceWorkflowsApprovalsApproverPage.tsx
+++ b/src/pages/workspace/workflows/approvals/WorkspaceWorkflowsApprovalsApproverPage.tsx
@@ -160,8 +160,15 @@ function WorkspaceWorkflowsApprovalsApproverPage({policy, personalDetails, isLoa
                 });
             }
 
+            const isRemovingApprover = selectedApproverEmail === approver?.login;
             if (isInitialCreationFlow) {
-                Navigation.navigate(ROUTES.WORKSPACE_WORKFLOWS_APPROVALS_NEW.getRoute(route.params.policyID));
+                // If removing an approver during creation, go back to the create page
+                // Otherwise, navigate to the approval limit page to optionally set a limit
+                if (isRemovingApprover) {
+                    Navigation.navigate(ROUTES.WORKSPACE_WORKFLOWS_APPROVALS_NEW.getRoute(route.params.policyID));
+                } else {
+                    Navigation.navigate(ROUTES.WORKSPACE_WORKFLOWS_APPROVALS_APPROVAL_LIMIT.getRoute(route.params.policyID, approverIndex));
+                }
             } else {
                 goBack();
             }
diff --git a/src/pages/workspace/workflows/approvals/WorkspaceWorkflowsApprovalsOverLimitApproverPage.tsx b/src/pages/workspace/workflows/approvals/WorkspaceWorkflowsApprovalsOverLimitApproverPage.tsx
new file mode 100644
index 000000000000..248e4eac64cc
--- /dev/null
+++ b/src/pages/workspace/workflows/approvals/WorkspaceWorkflowsApprovalsOverLimitApproverPage.tsx
@@ -0,0 +1,158 @@
+import React, {useCallback, useMemo} from 'react';
+import type {SelectionListApprover} from '@components/ApproverSelectionList';
+import ApproverSelectionList from '@components/ApproverSelectionList';
+import Text from '@components/Text';
+import {useMemoizedLazyExpensifyIcons} from '@hooks/useLazyAsset';
+import useLocalize from '@hooks/useLocalize';
+import useOnyx from '@hooks/useOnyx';
+import useThemeStyles from '@hooks/useThemeStyles';
+import Navigation from '@libs/Navigation/Navigation';
+import type {PlatformStackScreenProps} from '@libs/Navigation/PlatformStackNavigation/types';
+import type {WorkspaceSplitNavigatorParamList} from '@libs/Navigation/types';
+import {getMemberAccountIDsForWorkspace} from '@libs/PolicyUtils';
+import AccessOrNotFoundWrapper from '@pages/workspace/AccessOrNotFoundWrapper';
+import MemberRightIcon from '@pages/workspace/MemberRightIcon';
+import withPolicyAndFullscreenLoading from '@pages/workspace/withPolicyAndFullscreenLoading';
+import type {WithPolicyAndFullscreenLoadingProps} from '@pages/workspace/withPolicyAndFullscreenLoading';
+import {setApprovalWorkflowApprover} from '@userActions/Workflow';
+import CONST from '@src/CONST';
+import ONYXKEYS from '@src/ONYXKEYS';
+import ROUTES from '@src/ROUTES';
+import type SCREENS from '@src/SCREENS';
+import {personalDetailsByEmailSelector} from '@src/selectors/PersonalDetails';
+import isLoadingOnyxValue from '@src/types/utils/isLoadingOnyxValue';
+
+type WorkspaceWorkflowsApprovalsOverLimitApproverPageProps = WithPolicyAndFullscreenLoadingProps &
+    PlatformStackScreenProps<WorkspaceSplitNavigatorParamList, typeof SCREENS.WORKSPACE.WORKFLOWS_APPROVALS_OVER_LIMIT_APPROVER>;
+
+function WorkspaceWorkflowsApprovalsOverLimitApproverPage({policy, personalDetails, isLoadingReportData = true, route}: WorkspaceWorkflowsApprovalsOverLimitApproverPageProps) {
+    const styles = useThemeStyles();
+    const {translate} = useLocalize();
+    const [approvalWorkflow, approvalWorkflowMetadata] = useOnyx(ONYXKEYS.APPROVAL_WORKFLOW, {canBeMissing: true});
+    const isApprovalWorkflowLoading = isLoadingOnyxValue(approvalWorkflowMetadata);
+    const [personalDetailsByEmail] = useOnyx(ONYXKEYS.PERSONAL_DETAILS_LIST, {
+        canBeMissing: true,
+        selector: personalDetailsByEmailSelector,
+    });
+    const expensifyIcons = useMemoizedLazyExpensifyIcons(['FallbackAvatar'] as const);
+
+    const approverIndex = Number(route.params.approverIndex) ?? 0;
+    const currentApprover = approvalWorkflow?.approvers?.[approverIndex];
+
+    const employeeList = policy?.employeeList;
+    const approversFromWorkflow = approvalWorkflow?.approvers;
+
+    // Build a list of available approvers, excluding those already in the workflow chain
+    const allApprovers: SelectionListApprover[] = useMemo(() => {
+        if (isApprovalWorkflowLoading || !employeeList) {
+            return [];
+        }
+
+        return Object.values(employeeList)
+            .map((employee): SelectionListApprover | null => {
+                const email = employee.email;
+
+                if (!email) {
+                    return null;
+                }
+
+                // Do not allow selecting an approver that's already in the workflow chain
+                // This prevents circular references
+                const isEmailAlreadyInApprovers = approversFromWorkflow?.some((approver) => approver?.email === email);
+                if (isEmailAlreadyInApprovers) {
+                    return null;
+                }
+
+                const policyMemberEmailsToAccountIDs = getMemberAccountIDsForWorkspace(employeeList);
+                const accountID = Number(policyMemberEmailsToAccountIDs[email] ?? '');
+                const {avatar, displayName = email, login} = personalDetails?.[accountID] ?? {};
+
+                return {
+                    text: displayName,
+                    alternateText: email,
+                    keyForList: email,
+                    isSelected: currentApprover?.overLimitForwardsTo === email,
+                    login: email,
+                    icons: [{source: avatar ?? expensifyIcons.FallbackAvatar, type: CONST.ICON_TYPE_AVATAR, name: displayName, id: accountID}],
+                    rightElement: (
+                        <MemberRightIcon
+                            role={employee.role}
+                            owner={policy?.owner}
+                            login={login}
+                        />
+                    ),
+                };
+            })
+            .filter((approver): approver is SelectionListApprover => !!approver);
+    }, [isApprovalWorkflowLoading, employeeList, approversFromWorkflow, personalDetails, policy?.owner, currentApprover?.overLimitForwardsTo, expensifyIcons.FallbackAvatar]);
+
+    const shouldShowListEmptyContent = !!approvalWorkflow && !isApprovalWorkflowLoading;
+
+    const goBack = useCallback(() => {
+        Navigation.goBack(ROUTES.WORKSPACE_WORKFLOWS_APPROVALS_APPROVAL_LIMIT.getRoute(route.params.policyID, approverIndex));
+    }, [route.params.policyID, approverIndex]);
+
+    const selectApprover = useCallback(
+        (approvers: SelectionListApprover[]) => {
+            const selectedApprover = approvers.at(0);
+            if (!selectedApprover?.login || !approvalWorkflow || !currentApprover) {
+                return;
+            }
+
+            const policyMemberEmailsToAccountIDs = getMemberAccountIDsForWorkspace(employeeList);
+            const accountID = Number(selectedApprover.login ? policyMemberEmailsToAccountIDs[selectedApprover.login] : '');
+            const {avatar, displayName = selectedApprover.login} = personalDetails?.[accountID] ?? {};
+
+            // Update the current approver with the selected over-limit approver
+            setApprovalWorkflowApprover({
+                approver: {
+                    ...currentApprover,
+                    overLimitForwardsTo: selectedApprover.login,
+                },
+                approverIndex,
+                currentApprovalWorkflow: approvalWorkflow,
+                policy,
+                personalDetailsByEmail,
+            });
+
+            goBack();
+        },
+        [approvalWorkflow, currentApprover, employeeList, personalDetails, approverIndex, policy, personalDetailsByEmail, goBack],
+    );
+
+    const subtitle = useMemo(
+        () =>
+            !shouldShowListEmptyContent && (
+                <Text style={[styles.textHeadlineH1, styles.mh5, styles.mv3]}>{translate('workflowsApprovalLimitPage.additionalApproverLabel')}</Text>
+            ),
+        [shouldShowListEmptyContent, translate, styles.textHeadlineH1, styles.mh5, styles.mv3],
+    );
+
+    return (
+        <AccessOrNotFoundWrapper
+            policyID={route.params.policyID}
+            featureName={CONST.POLICY.MORE_FEATURES.ARE_WORKFLOWS_ENABLED}
+        >
+            <ApproverSelectionList
+                testID={WorkspaceWorkflowsApprovalsOverLimitApproverPage.displayName}
+                headerTitle={translate('workflowsApprovalLimitPage.additionalApproverLabel')}
+                subtitle={subtitle}
+                isLoadingReportData={isLoadingReportData}
+                policy={policy}
+                initiallyFocusedOptionKey={currentApprover?.overLimitForwardsTo}
+                shouldShowNotFoundViewLink
+                allApprovers={allApprovers}
+                onBackButtonPress={goBack}
+                shouldShowListEmptyContent={shouldShowListEmptyContent}
+                listEmptyContentSubtitle={translate('workflowsPage.emptyContent.approverSubtitle')}
+                allowMultipleSelection={false}
+                onSelectApprover={selectApprover}
+            />
+        </AccessOrNotFoundWrapper>
+    );
+}
+
+WorkspaceWorkflowsApprovalsOverLimitApproverPage.displayName = 'WorkspaceWorkflowsApprovalsOverLimitApproverPage';
+
+export default withPolicyAndFullscreenLoading(WorkspaceWorkflowsApprovalsOverLimitApproverPage);
+
diff --git a/src/types/onyx/ApprovalWorkflow.ts b/src/types/onyx/ApprovalWorkflow.ts
index f508e7f22420..baceaacee16f 100644
--- a/src/types/onyx/ApprovalWorkflow.ts
+++ b/src/types/onyx/ApprovalWorkflow.ts
@@ -35,6 +35,16 @@ type Approver = {
      * example: A -> B -> C -> A (cycle)
      */
     isCircularReference?: boolean;
+
+    /**
+     * If report total is above this limit, the report will be forwarded to 'overLimitForwardsTo' instead of 'forwardsTo'
+     */
+    approvalLimit?: number;
+
+    /**
+     * Email of the user this user forwards all approved reports to when report total is above 'approvalLimit'
+     */
+    overLimitForwardsTo?: string;
 };
 
 /**

From b6cf974bdce06ab799889fd312512606147a6f9a Mon Sep 17 00:00:00 2001
From: Abdelrahman Khattab <abzokhattab@gmail.com>
Date: Tue, 25 Nov 2025 15:47:29 +0100
Subject: [PATCH 02/49] cleaning up

---
 src/libs/WorkflowUtils.ts                             |  5 -----
 .../workflows/approvals/ApprovalWorkflowEditor.tsx    |  1 -
 .../WorkspaceWorkflowsApprovalsApprovalLimitPage.tsx  | 11 -----------
 .../WorkspaceWorkflowsApprovalsApproverPage.tsx       |  4 ----
 ...rkspaceWorkflowsApprovalsOverLimitApproverPage.tsx | 10 +---------
 5 files changed, 1 insertion(+), 30 deletions(-)

diff --git a/src/libs/WorkflowUtils.ts b/src/libs/WorkflowUtils.ts
index e3fd67a1e1d6..98406e397adf 100644
--- a/src/libs/WorkflowUtils.ts
+++ b/src/libs/WorkflowUtils.ts
@@ -63,13 +63,11 @@ function calculateApprovers({employees, firstEmail, personalDetailsByEmail}: Get
             overLimitForwardsTo: employee.overLimitForwardsTo,
         });
 
-        // If we've already seen this approver, break to prevent infinite loop
         if (isCircularReference) {
             break;
         }
         currentApproverEmails.add(nextEmail);
 
-        // If there is a forwardsTo, set the next approver to the forwardsTo
         nextEmail = employees[nextEmail].forwardsTo;
     }
 
@@ -261,7 +259,6 @@ function convertApprovalWorkflowToPolicyEmployees({
         const approvalLimit = type === CONST.APPROVAL_WORKFLOW.TYPE.REMOVE ? undefined : approver.approvalLimit;
         const overLimitForwardsTo = type === CONST.APPROVAL_WORKFLOW.TYPE.REMOVE ? '' : (approver.overLimitForwardsTo ?? '');
 
-        // For every approver, we check if the forwardsTo, approvalLimit, or overLimitForwardsTo fields have changed.
         const previousEmployee = previousEmployeeList[approver.email];
         const forwardsToChanged = previousEmployee?.forwardsTo !== forwardsTo;
         const approvalLimitChanged = previousEmployee?.approvalLimit !== approvalLimit;
@@ -287,8 +284,6 @@ function convertApprovalWorkflowToPolicyEmployees({
     for (const {email} of approvalWorkflow.members) {
         const submitsTo = type === CONST.APPROVAL_WORKFLOW.TYPE.REMOVE ? '' : (firstApprover.email ?? '');
 
-        // For every member, we check if the submitsTo field has changed.
-        // If it has, we update the employee list with the new submitsTo value.
         if (previousEmployeeList[email]?.submitsTo === submitsTo) {
             continue;
         }
diff --git a/src/pages/workspace/workflows/approvals/ApprovalWorkflowEditor.tsx b/src/pages/workspace/workflows/approvals/ApprovalWorkflowEditor.tsx
index 4b1a017d2ba4..c1ace65a9e10 100644
--- a/src/pages/workspace/workflows/approvals/ApprovalWorkflowEditor.tsx
+++ b/src/pages/workspace/workflows/approvals/ApprovalWorkflowEditor.tsx
@@ -110,7 +110,6 @@ function ApprovalWorkflowEditor({approvalWorkflow, removeApprovalWorkflow, polic
             const approver = approvalWorkflow.approvers.at(approverIndex);
             const backTo = approvalWorkflow.action === CONST.APPROVAL_WORKFLOW.ACTION.CREATE ? ROUTES.WORKSPACE_WORKFLOWS_APPROVALS_NEW.getRoute(policyID) : undefined;
 
-            // If the approver has an approval limit set, navigate to the approval limit page for editing
             if (approver?.approvalLimit && approver?.overLimitForwardsTo) {
                 Navigation.navigate(ROUTES.WORKSPACE_WORKFLOWS_APPROVALS_APPROVAL_LIMIT.getRoute(policyID, approverIndex, backTo));
                 return;
diff --git a/src/pages/workspace/workflows/approvals/WorkspaceWorkflowsApprovalsApprovalLimitPage.tsx b/src/pages/workspace/workflows/approvals/WorkspaceWorkflowsApprovalsApprovalLimitPage.tsx
index 1de61736491c..31bdca2eb3e5 100644
--- a/src/pages/workspace/workflows/approvals/WorkspaceWorkflowsApprovalsApprovalLimitPage.tsx
+++ b/src/pages/workspace/workflows/approvals/WorkspaceWorkflowsApprovalsApprovalLimitPage.tsx
@@ -58,8 +58,6 @@ function WorkspaceWorkflowsApprovalsApprovalLimitPage({policy, isLoadingReportDa
 
     const [hasSubmitted, setHasSubmitted] = useState(false);
 
-    // Read the overLimitForwardsTo directly from the current approver in the workflow
-    // This ensures we get the updated value after returning from the approver selector
     const selectedApproverEmail = currentApprover?.overLimitForwardsTo ?? '';
 
     const selectedApproverDisplayName = useMemo(() => {
@@ -70,7 +68,6 @@ function WorkspaceWorkflowsApprovalsApprovalLimitPage({policy, isLoadingReportDa
         return Str.removeSMSDomain(personalDetails?.displayName ?? selectedApproverEmail);
     }, [selectedApproverEmail, personalDetailsByEmail]);
 
-    // Check if selected approver already exists in the workflow (circular reference)
     const isCircularReference = useMemo(() => {
         if (!selectedApproverEmail || !approvalWorkflow?.approvers) {
             return false;
@@ -84,17 +81,11 @@ function WorkspaceWorkflowsApprovalsApprovalLimitPage({policy, isLoadingReportDa
     const hasAmount = approvalLimit.length > 0 && Number(approvalLimit) > 0;
     const hasApprover = selectedApproverEmail.length > 0;
 
-    // Determine which error type to show based on the state
-    // When both are empty: show only the combined error at bottom
-    // When only one is empty: show error on that specific field
     const bothEmpty = !hasAmount && !hasApprover;
     const onlyAmountEmpty = !hasAmount && hasApprover;
     const onlyApproverEmpty = hasAmount && !hasApprover;
 
-    // Bottom error message - only shown when both fields are empty
     const bottomErrorMessage = hasSubmitted && bothEmpty ? translate('workflowsApprovalLimitPage.enterBothError') : '';
-
-    // Field-level errors - only shown when the OTHER field has a value
     const amountErrorText = hasSubmitted && onlyAmountEmpty ? translate('workflowsApprovalLimitPage.enterAmountError') : undefined;
     const approverErrorText = useMemo(() => {
         if (isCircularReference) {
@@ -123,7 +114,6 @@ function WorkspaceWorkflowsApprovalsApprovalLimitPage({policy, isLoadingReportDa
 
         const limitInCents = convertToBackendAmount(Number.parseFloat(approvalLimit));
 
-        // Update the approver with the approval limit and overLimitForwardsTo
         setApprovalWorkflowApprover({
             approver: {
                 ...currentApprover,
@@ -140,7 +130,6 @@ function WorkspaceWorkflowsApprovalsApprovalLimitPage({policy, isLoadingReportDa
     }, [approvalLimit, selectedApproverEmail, isCircularReference, approvalWorkflow, currentApprover, approverIndex, policyFromHook, personalDetailsByEmail, route.params.policyID]);
 
     const navigateToApproverSelector = useCallback(() => {
-        // Navigate to the over-limit approver selector page
         Navigation.navigate(ROUTES.WORKSPACE_WORKFLOWS_APPROVALS_OVER_LIMIT_APPROVER.getRoute(route.params.policyID, approverIndex));
     }, [route.params.policyID, approverIndex]);
 
diff --git a/src/pages/workspace/workflows/approvals/WorkspaceWorkflowsApprovalsApproverPage.tsx b/src/pages/workspace/workflows/approvals/WorkspaceWorkflowsApprovalsApproverPage.tsx
index f50bc18f9e60..637c580e68ad 100644
--- a/src/pages/workspace/workflows/approvals/WorkspaceWorkflowsApprovalsApproverPage.tsx
+++ b/src/pages/workspace/workflows/approvals/WorkspaceWorkflowsApprovalsApproverPage.tsx
@@ -75,13 +75,11 @@ function WorkspaceWorkflowsApprovalsApproverPage({policy, personalDetails, isLoa
                     return null;
                 }
 
-                // Do not allow the same email to be added twice
                 const isEmailAlreadyInApprovers = approversFromWorkflow?.some((approver, index) => approver?.email === email && index !== approverIndex);
                 if (isEmailAlreadyInApprovers && selectedApproverEmail !== email) {
                     return null;
                 }
 
-                // Do not allow the default approver to be added as the first approver
                 if (!isDefault && approverIndex === 0 && defaultApprover === email) {
                     return null;
                 }
@@ -162,8 +160,6 @@ function WorkspaceWorkflowsApprovalsApproverPage({policy, personalDetails, isLoa
 
             const isRemovingApprover = selectedApproverEmail === approver?.login;
             if (isInitialCreationFlow) {
-                // If removing an approver during creation, go back to the create page
-                // Otherwise, navigate to the approval limit page to optionally set a limit
                 if (isRemovingApprover) {
                     Navigation.navigate(ROUTES.WORKSPACE_WORKFLOWS_APPROVALS_NEW.getRoute(route.params.policyID));
                 } else {
diff --git a/src/pages/workspace/workflows/approvals/WorkspaceWorkflowsApprovalsOverLimitApproverPage.tsx b/src/pages/workspace/workflows/approvals/WorkspaceWorkflowsApprovalsOverLimitApproverPage.tsx
index 248e4eac64cc..435172ed9494 100644
--- a/src/pages/workspace/workflows/approvals/WorkspaceWorkflowsApprovalsOverLimitApproverPage.tsx
+++ b/src/pages/workspace/workflows/approvals/WorkspaceWorkflowsApprovalsOverLimitApproverPage.tsx
@@ -42,7 +42,6 @@ function WorkspaceWorkflowsApprovalsOverLimitApproverPage({policy, personalDetai
     const employeeList = policy?.employeeList;
     const approversFromWorkflow = approvalWorkflow?.approvers;
 
-    // Build a list of available approvers, excluding those already in the workflow chain
     const allApprovers: SelectionListApprover[] = useMemo(() => {
         if (isApprovalWorkflowLoading || !employeeList) {
             return [];
@@ -56,8 +55,6 @@ function WorkspaceWorkflowsApprovalsOverLimitApproverPage({policy, personalDetai
                     return null;
                 }
 
-                // Do not allow selecting an approver that's already in the workflow chain
-                // This prevents circular references
                 const isEmailAlreadyInApprovers = approversFromWorkflow?.some((approver) => approver?.email === email);
                 if (isEmailAlreadyInApprovers) {
                     return null;
@@ -103,7 +100,6 @@ function WorkspaceWorkflowsApprovalsOverLimitApproverPage({policy, personalDetai
             const accountID = Number(selectedApprover.login ? policyMemberEmailsToAccountIDs[selectedApprover.login] : '');
             const {avatar, displayName = selectedApprover.login} = personalDetails?.[accountID] ?? {};
 
-            // Update the current approver with the selected over-limit approver
             setApprovalWorkflowApprover({
                 approver: {
                     ...currentApprover,
@@ -121,10 +117,7 @@ function WorkspaceWorkflowsApprovalsOverLimitApproverPage({policy, personalDetai
     );
 
     const subtitle = useMemo(
-        () =>
-            !shouldShowListEmptyContent && (
-                <Text style={[styles.textHeadlineH1, styles.mh5, styles.mv3]}>{translate('workflowsApprovalLimitPage.additionalApproverLabel')}</Text>
-            ),
+        () => !shouldShowListEmptyContent && <Text style={[styles.textHeadlineH1, styles.mh5, styles.mv3]}>{translate('workflowsApprovalLimitPage.additionalApproverLabel')}</Text>,
         [shouldShowListEmptyContent, translate, styles.textHeadlineH1, styles.mh5, styles.mv3],
     );
 
@@ -155,4 +148,3 @@ function WorkspaceWorkflowsApprovalsOverLimitApproverPage({policy, personalDetai
 WorkspaceWorkflowsApprovalsOverLimitApproverPage.displayName = 'WorkspaceWorkflowsApprovalsOverLimitApproverPage';
 
 export default withPolicyAndFullscreenLoading(WorkspaceWorkflowsApprovalsOverLimitApproverPage);
-

From b3834745cd33b36281628be9c51651f4a2fab150 Mon Sep 17 00:00:00 2001
From: Abdelrahman Khattab <abzokhattab@gmail.com>
Date: Tue, 25 Nov 2025 15:54:52 +0100
Subject: [PATCH 03/49] refactoring

---
 ...aceWorkflowsApprovalsApprovalLimitPage.tsx | 23 +++++++++----------
 ...orkflowsApprovalsOverLimitApproverPage.tsx |  7 +++---
 2 files changed, 15 insertions(+), 15 deletions(-)

diff --git a/src/pages/workspace/workflows/approvals/WorkspaceWorkflowsApprovalsApprovalLimitPage.tsx b/src/pages/workspace/workflows/approvals/WorkspaceWorkflowsApprovalsApprovalLimitPage.tsx
index 31bdca2eb3e5..f351809aa27a 100644
--- a/src/pages/workspace/workflows/approvals/WorkspaceWorkflowsApprovalsApprovalLimitPage.tsx
+++ b/src/pages/workspace/workflows/approvals/WorkspaceWorkflowsApprovalsApprovalLimitPage.tsx
@@ -14,7 +14,6 @@ import Text from '@components/Text';
 import useBottomSafeSafeAreaPaddingStyle from '@hooks/useBottomSafeSafeAreaPaddingStyle';
 import useLocalize from '@hooks/useLocalize';
 import useOnyx from '@hooks/useOnyx';
-import usePolicy from '@hooks/usePolicy';
 import useThemeStyles from '@hooks/useThemeStyles';
 import {convertToBackendAmount, convertToFrontendAmountAsString} from '@libs/CurrencyUtils';
 import Navigation from '@libs/Navigation/Navigation';
@@ -38,16 +37,16 @@ type WorkspaceWorkflowsApprovalsApprovalLimitPageProps = WithPolicyAndFullscreen
 function WorkspaceWorkflowsApprovalsApprovalLimitPage({policy, isLoadingReportData = true, route}: WorkspaceWorkflowsApprovalsApprovalLimitPageProps) {
     const styles = useThemeStyles();
     const {translate} = useLocalize();
-    const policyFromHook = usePolicy(route.params.policyID);
     const [approvalWorkflow] = useOnyx(ONYXKEYS.APPROVAL_WORKFLOW, {canBeMissing: true});
     const [personalDetailsByEmail] = useOnyx(ONYXKEYS.PERSONAL_DETAILS_LIST, {
         canBeMissing: true,
         selector: personalDetailsByEmailSelector,
     });
 
+    const policyID = route.params.policyID;
     const approverIndex = Number(route.params.approverIndex) ?? 0;
     const currentApprover = approvalWorkflow?.approvers?.[approverIndex];
-    const currency = policyFromHook?.outputCurrency ?? CONST.CURRENCY.USD;
+    const currency = policy?.outputCurrency ?? CONST.CURRENCY.USD;
 
     const [approvalLimit, setApprovalLimit] = useState<string>(() => {
         if (currentApprover?.approvalLimit) {
@@ -98,8 +97,8 @@ function WorkspaceWorkflowsApprovalsApprovalLimitPage({policy, isLoadingReportDa
     }, [hasSubmitted, onlyApproverEmpty, isCircularReference, selectedApproverDisplayName, translate]);
 
     const handleSkip = useCallback(() => {
-        Navigation.navigate(ROUTES.WORKSPACE_WORKFLOWS_APPROVALS_NEW.getRoute(route.params.policyID));
-    }, [route.params.policyID]);
+        Navigation.navigate(ROUTES.WORKSPACE_WORKFLOWS_APPROVALS_NEW.getRoute(policyID));
+    }, [policyID]);
 
     const handleNext = useCallback(() => {
         setHasSubmitted(true);
@@ -122,16 +121,16 @@ function WorkspaceWorkflowsApprovalsApprovalLimitPage({policy, isLoadingReportDa
             },
             approverIndex,
             currentApprovalWorkflow: approvalWorkflow,
-            policy: policyFromHook,
+            policy,
             personalDetailsByEmail,
         });
 
-        Navigation.navigate(ROUTES.WORKSPACE_WORKFLOWS_APPROVALS_NEW.getRoute(route.params.policyID));
-    }, [approvalLimit, selectedApproverEmail, isCircularReference, approvalWorkflow, currentApprover, approverIndex, policyFromHook, personalDetailsByEmail, route.params.policyID]);
+        Navigation.navigate(ROUTES.WORKSPACE_WORKFLOWS_APPROVALS_NEW.getRoute(policyID));
+    }, [approvalLimit, selectedApproverEmail, isCircularReference, approvalWorkflow, currentApprover, approverIndex, policy, personalDetailsByEmail, policyID]);
 
     const navigateToApproverSelector = useCallback(() => {
-        Navigation.navigate(ROUTES.WORKSPACE_WORKFLOWS_APPROVALS_OVER_LIMIT_APPROVER.getRoute(route.params.policyID, approverIndex));
-    }, [route.params.policyID, approverIndex]);
+        Navigation.navigate(ROUTES.WORKSPACE_WORKFLOWS_APPROVALS_OVER_LIMIT_APPROVER.getRoute(policyID, approverIndex));
+    }, [policyID, approverIndex]);
 
     const buttonContainerStyle = useBottomSafeSafeAreaPaddingStyle({addBottomSafeAreaPadding: true, style: [styles.mh5, styles.mb5]});
 
@@ -139,7 +138,7 @@ function WorkspaceWorkflowsApprovalsApprovalLimitPage({policy, isLoadingReportDa
 
     return (
         <AccessOrNotFoundWrapper
-            policyID={route.params.policyID}
+            policyID={policyID}
             featureName={CONST.POLICY.MORE_FEATURES.ARE_WORKFLOWS_ENABLED}
         >
             <ScreenWrapper
@@ -155,7 +154,7 @@ function WorkspaceWorkflowsApprovalsApprovalLimitPage({policy, isLoadingReportDa
                 >
                     <HeaderWithBackButton
                         title={translate('workflowsApprovalLimitPage.title')}
-                        onBackButtonPress={() => Navigation.goBack(ROUTES.WORKSPACE_WORKFLOWS_APPROVALS_APPROVER.getRoute(route.params.policyID, approverIndex))}
+                        onBackButtonPress={() => Navigation.goBack(ROUTES.WORKSPACE_WORKFLOWS_APPROVALS_APPROVER.getRoute(policyID, approverIndex))}
                     />
                     <ScrollView
                         style={styles.flex1}
diff --git a/src/pages/workspace/workflows/approvals/WorkspaceWorkflowsApprovalsOverLimitApproverPage.tsx b/src/pages/workspace/workflows/approvals/WorkspaceWorkflowsApprovalsOverLimitApproverPage.tsx
index 435172ed9494..8e8f82b5c82e 100644
--- a/src/pages/workspace/workflows/approvals/WorkspaceWorkflowsApprovalsOverLimitApproverPage.tsx
+++ b/src/pages/workspace/workflows/approvals/WorkspaceWorkflowsApprovalsOverLimitApproverPage.tsx
@@ -36,6 +36,7 @@ function WorkspaceWorkflowsApprovalsOverLimitApproverPage({policy, personalDetai
     });
     const expensifyIcons = useMemoizedLazyExpensifyIcons(['FallbackAvatar'] as const);
 
+    const policyID = route.params.policyID;
     const approverIndex = Number(route.params.approverIndex) ?? 0;
     const currentApprover = approvalWorkflow?.approvers?.[approverIndex];
 
@@ -86,8 +87,8 @@ function WorkspaceWorkflowsApprovalsOverLimitApproverPage({policy, personalDetai
     const shouldShowListEmptyContent = !!approvalWorkflow && !isApprovalWorkflowLoading;
 
     const goBack = useCallback(() => {
-        Navigation.goBack(ROUTES.WORKSPACE_WORKFLOWS_APPROVALS_APPROVAL_LIMIT.getRoute(route.params.policyID, approverIndex));
-    }, [route.params.policyID, approverIndex]);
+        Navigation.goBack(ROUTES.WORKSPACE_WORKFLOWS_APPROVALS_APPROVAL_LIMIT.getRoute(policyID, approverIndex));
+    }, [policyID, approverIndex]);
 
     const selectApprover = useCallback(
         (approvers: SelectionListApprover[]) => {
@@ -123,7 +124,7 @@ function WorkspaceWorkflowsApprovalsOverLimitApproverPage({policy, personalDetai
 
     return (
         <AccessOrNotFoundWrapper
-            policyID={route.params.policyID}
+            policyID={policyID}
             featureName={CONST.POLICY.MORE_FEATURES.ARE_WORKFLOWS_ENABLED}
         >
             <ApproverSelectionList

From 1fcfb7a2d61b75459d1f42a06a39132b258f4206 Mon Sep 17 00:00:00 2001
From: Abdelrahman Khattab <abzokhattab@gmail.com>
Date: Tue, 25 Nov 2025 16:00:29 +0100
Subject: [PATCH 04/49] refactoring comments

---
 src/libs/WorkflowUtils.ts                                     | 4 ++++
 .../workspace/workflows/approvals/ApprovalWorkflowEditor.tsx  | 1 +
 .../approvals/WorkspaceWorkflowsApprovalsApproverPage.tsx     | 3 +++
 3 files changed, 8 insertions(+)

diff --git a/src/libs/WorkflowUtils.ts b/src/libs/WorkflowUtils.ts
index 98406e397adf..0958d5842ff6 100644
--- a/src/libs/WorkflowUtils.ts
+++ b/src/libs/WorkflowUtils.ts
@@ -63,11 +63,13 @@ function calculateApprovers({employees, firstEmail, personalDetailsByEmail}: Get
             overLimitForwardsTo: employee.overLimitForwardsTo,
         });
 
+        // If we've already seen this approver, break to prevent infinite loop
         if (isCircularReference) {
             break;
         }
         currentApproverEmails.add(nextEmail);
 
+        // If there is a forwardsTo, set the next approver to the forwardsTo
         nextEmail = employees[nextEmail].forwardsTo;
     }
 
@@ -284,6 +286,8 @@ function convertApprovalWorkflowToPolicyEmployees({
     for (const {email} of approvalWorkflow.members) {
         const submitsTo = type === CONST.APPROVAL_WORKFLOW.TYPE.REMOVE ? '' : (firstApprover.email ?? '');
 
+        // For every member, we check if the submitsTo field has changed.
+        // If it has, we update the employee list with the new submitsTo value.
         if (previousEmployeeList[email]?.submitsTo === submitsTo) {
             continue;
         }
diff --git a/src/pages/workspace/workflows/approvals/ApprovalWorkflowEditor.tsx b/src/pages/workspace/workflows/approvals/ApprovalWorkflowEditor.tsx
index c1ace65a9e10..4b1a017d2ba4 100644
--- a/src/pages/workspace/workflows/approvals/ApprovalWorkflowEditor.tsx
+++ b/src/pages/workspace/workflows/approvals/ApprovalWorkflowEditor.tsx
@@ -110,6 +110,7 @@ function ApprovalWorkflowEditor({approvalWorkflow, removeApprovalWorkflow, polic
             const approver = approvalWorkflow.approvers.at(approverIndex);
             const backTo = approvalWorkflow.action === CONST.APPROVAL_WORKFLOW.ACTION.CREATE ? ROUTES.WORKSPACE_WORKFLOWS_APPROVALS_NEW.getRoute(policyID) : undefined;
 
+            // If the approver has an approval limit set, navigate to the approval limit page for editing
             if (approver?.approvalLimit && approver?.overLimitForwardsTo) {
                 Navigation.navigate(ROUTES.WORKSPACE_WORKFLOWS_APPROVALS_APPROVAL_LIMIT.getRoute(policyID, approverIndex, backTo));
                 return;
diff --git a/src/pages/workspace/workflows/approvals/WorkspaceWorkflowsApprovalsApproverPage.tsx b/src/pages/workspace/workflows/approvals/WorkspaceWorkflowsApprovalsApproverPage.tsx
index 637c580e68ad..b78753160d16 100644
--- a/src/pages/workspace/workflows/approvals/WorkspaceWorkflowsApprovalsApproverPage.tsx
+++ b/src/pages/workspace/workflows/approvals/WorkspaceWorkflowsApprovalsApproverPage.tsx
@@ -75,11 +75,13 @@ function WorkspaceWorkflowsApprovalsApproverPage({policy, personalDetails, isLoa
                     return null;
                 }
 
+                // Do not allow the same email to be added twice
                 const isEmailAlreadyInApprovers = approversFromWorkflow?.some((approver, index) => approver?.email === email && index !== approverIndex);
                 if (isEmailAlreadyInApprovers && selectedApproverEmail !== email) {
                     return null;
                 }
 
+                // Do not allow the default approver to be added as the first approver
                 if (!isDefault && approverIndex === 0 && defaultApprover === email) {
                     return null;
                 }
@@ -160,6 +162,7 @@ function WorkspaceWorkflowsApprovalsApproverPage({policy, personalDetails, isLoa
 
             const isRemovingApprover = selectedApproverEmail === approver?.login;
             if (isInitialCreationFlow) {
+                // Navigate to approval limit page to optionally set a limit, or back to create page if removing
                 if (isRemovingApprover) {
                     Navigation.navigate(ROUTES.WORKSPACE_WORKFLOWS_APPROVALS_NEW.getRoute(route.params.policyID));
                 } else {

From be2c8eaf88a3d313207017f6855c2a5c367888e2 Mon Sep 17 00:00:00 2001
From: Abdelrahman Khattab <abzokhattab@gmail.com>
Date: Tue, 25 Nov 2025 18:09:08 +0100
Subject: [PATCH 05/49] fixing eslint

---
 src/pages/workspace/withPolicy.tsx | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/src/pages/workspace/withPolicy.tsx b/src/pages/workspace/withPolicy.tsx
index af306528aec6..f16f9421f1d9 100644
--- a/src/pages/workspace/withPolicy.tsx
+++ b/src/pages/workspace/withPolicy.tsx
@@ -29,6 +29,8 @@ type PolicyRouteName =
     | typeof SCREENS.WORKSPACE.WORKFLOWS_APPROVALS_EDIT
     | typeof SCREENS.WORKSPACE.WORKFLOWS_APPROVALS_EXPENSES_FROM
     | typeof SCREENS.WORKSPACE.WORKFLOWS_APPROVALS_APPROVER
+    | typeof SCREENS.WORKSPACE.WORKFLOWS_APPROVALS_APPROVAL_LIMIT
+    | typeof SCREENS.WORKSPACE.WORKFLOWS_APPROVALS_OVER_LIMIT_APPROVER
     | typeof SCREENS.WORKSPACE.WORKFLOWS_AUTO_REPORTING_MONTHLY_OFFSET
     | typeof SCREENS.WORKSPACE.WORKFLOWS_AUTO_REPORTING_FREQUENCY
     | typeof SCREENS.WORKSPACE.MEMBER_DETAILS

From caa2cd3cc4bd3da4fb0bafff8d801ad469d5f268 Mon Sep 17 00:00:00 2001
From: Abdelrahman Khattab <abzokhattab@gmail.com>
Date: Tue, 25 Nov 2025 18:29:47 +0100
Subject: [PATCH 06/49] fixing other translations

---
 src/languages/de.ts      | 16 ++++++++++++++++
 src/languages/en.ts      |  6 ++----
 src/languages/es.ts      |  6 ++----
 src/languages/fr.ts      | 17 +++++++++++++++++
 src/languages/it.ts      | 16 ++++++++++++++++
 src/languages/ja.ts      | 15 +++++++++++++++
 src/languages/nl.ts      | 17 +++++++++++++++++
 src/languages/pl.ts      | 16 ++++++++++++++++
 src/languages/pt-BR.ts   | 16 ++++++++++++++++
 src/languages/zh-hans.ts | 14 ++++++++++++++
 10 files changed, 131 insertions(+), 8 deletions(-)

diff --git a/src/languages/de.ts b/src/languages/de.ts
index 5269db290fe3..be3411e49c2b 100644
--- a/src/languages/de.ts
+++ b/src/languages/de.ts
@@ -2178,6 +2178,22 @@ ${amount} für ${merchant} - ${date}`,
         genericErrorMessage: 'Der Genehmiger konnte nicht geändert werden. Bitte versuchen Sie es erneut oder kontaktieren Sie den Support.',
         header: 'An dieses Mitglied zur Genehmigung senden:',
     },
+    workflowsApprovalLimitPage: {
+        title: 'Genehmiger',
+        header: '(Optional) Möchten Sie ein Genehmigungslimit hinzufügen?',
+        description: ({approverName}: {approverName: string}) =>
+            `Fügen Sie einen weiteren Genehmiger hinzu, wenn <strong>${approverName}</strong> Genehmiger ist und der Bericht den folgenden Betrag überschreitet:`,
+        reportAmountLabel: 'Berichtsbetrag',
+        additionalApproverLabel: 'Zusätzlicher Genehmiger',
+        skip: 'Überspringen',
+        next: 'Weiter',
+        enterAmountError: 'Bitte geben Sie einen gültigen Betrag ein',
+        enterApproverError: 'Bitte geben Sie einen Genehmiger ein',
+        enterBothError: 'Geben Sie einen Berichtsbetrag und einen zusätzlichen Genehmiger ein',
+        circularReferenceError: ({approverName}: {approverName: string}) =>
+            `<strong>${approverName}</strong> genehmigt bereits Berichte in diesem Workflow. Wählen Sie einen anderen Genehmiger, um einen zirkulären Workflow zu vermeiden.`,
+        forwardLimitDescription: ({approvalLimit, approverName}: {approvalLimit: string; approverName: string}) => `Berichte über ${approvalLimit} werden an ${approverName} weitergeleitet`,
+    },
     workflowsPayerPage: {
         title: 'Autorisierter Zahler',
         genericErrorMessage: 'Der autorisierte Zahler konnte nicht geändert werden. Bitte versuchen Sie es erneut.',
diff --git a/src/languages/en.ts b/src/languages/en.ts
index 87cf839d693e..dac6a9205f8f 100755
--- a/src/languages/en.ts
+++ b/src/languages/en.ts
@@ -2269,8 +2269,7 @@ const translations = {
     workflowsApprovalLimitPage: {
         title: 'Approver',
         header: '(Optional) Want to add an approval limit?',
-        description: ({approverName}: {approverName: string}) =>
-            `Add another approver when <strong>${approverName}</strong> is approver and report exceeds the amount below:`,
+        description: ({approverName}: {approverName: string}) => `Add another approver when <strong>${approverName}</strong> is approver and report exceeds the amount below:`,
         reportAmountLabel: 'Report amount',
         additionalApproverLabel: 'Additional approver',
         skip: 'Skip',
@@ -2280,8 +2279,7 @@ const translations = {
         enterBothError: 'Enter a report amount and additional approver',
         circularReferenceError: ({approverName}: {approverName: string}) =>
             `<strong>${approverName}</strong> already approves reports in this workflow. Choose a different approver to avoid a circular workflow.`,
-        forwardLimitDescription: ({approvalLimit, approverName}: {approvalLimit: string; approverName: string}) =>
-            `Reports above ${approvalLimit} forward to ${approverName}`,
+        forwardLimitDescription: ({approvalLimit, approverName}: {approvalLimit: string; approverName: string}) => `Reports above ${approvalLimit} forward to ${approverName}`,
     },
     workflowsPayerPage: {
         title: 'Authorized payer',
diff --git a/src/languages/es.ts b/src/languages/es.ts
index b63c807bdd81..42d003775ac5 100644
--- a/src/languages/es.ts
+++ b/src/languages/es.ts
@@ -1912,8 +1912,7 @@ ${amount} para ${merchant} - ${date}`,
     workflowsApprovalLimitPage: {
         title: 'Aprobador',
         header: '(Opcional) ¿Quieres añadir un límite de aprobación?',
-        description: ({approverName}: {approverName: string}) =>
-            `Añadir otro aprobador cuando <strong>${approverName}</strong> es aprobador y el informe excede el monto a continuación:`,
+        description: ({approverName}: {approverName: string}) => `Añadir otro aprobador cuando <strong>${approverName}</strong> es aprobador y el informe excede el monto a continuación:`,
         reportAmountLabel: 'Monto del informe',
         additionalApproverLabel: 'Aprobador adicional',
         skip: 'Omitir',
@@ -1923,8 +1922,7 @@ ${amount} para ${merchant} - ${date}`,
         enterBothError: 'Ingrese un monto del informe y un aprobador adicional',
         circularReferenceError: ({approverName}: {approverName: string}) =>
             `<strong>${approverName}</strong> ya aprueba informes en este flujo de trabajo. Elija un aprobador diferente para evitar un flujo de trabajo circular.`,
-        forwardLimitDescription: ({approvalLimit, approverName}: {approvalLimit: string; approverName: string}) =>
-            `Informes por encima de ${approvalLimit} se envían a ${approverName}`,
+        forwardLimitDescription: ({approvalLimit, approverName}: {approvalLimit: string; approverName: string}) => `Informes por encima de ${approvalLimit} se envían a ${approverName}`,
     },
     workflowsPayerPage: {
         title: 'Pagador autorizado',
diff --git a/src/languages/fr.ts b/src/languages/fr.ts
index 72b5dc213939..4a73389cf7ee 100644
--- a/src/languages/fr.ts
+++ b/src/languages/fr.ts
@@ -2178,6 +2178,23 @@ ${amount} pour ${merchant} - ${date}`,
         genericErrorMessage: "L'approbateur n'a pas pu être modifié. Veuillez réessayer ou contacter le support.",
         header: 'Envoyer à ce membre pour approbation :',
     },
+    workflowsApprovalLimitPage: {
+        title: 'Approbateur',
+        header: "(Optionnel) Voulez-vous ajouter une limite d'approbation ?",
+        description: ({approverName}: {approverName: string}) =>
+            `Ajoutez un autre approbateur lorsque <strong>${approverName}</strong> est approbateur et que le rapport dépasse le montant ci-dessous :`,
+        reportAmountLabel: 'Montant du rapport',
+        additionalApproverLabel: 'Approbateur supplémentaire',
+        skip: 'Passer',
+        next: 'Suivant',
+        enterAmountError: 'Veuillez entrer un montant valide',
+        enterApproverError: 'Veuillez entrer un approbateur',
+        enterBothError: 'Entrez un montant de rapport et un approbateur supplémentaire',
+        circularReferenceError: ({approverName}: {approverName: string}) =>
+            `<strong>${approverName}</strong> approuve déjà des rapports dans ce flux de travail. Choisissez un autre approbateur pour éviter un flux circulaire.`,
+        forwardLimitDescription: ({approvalLimit, approverName}: {approvalLimit: string; approverName: string}) =>
+            `Les rapports supérieurs à ${approvalLimit} sont transférés à ${approverName}`,
+    },
     workflowsPayerPage: {
         title: 'Payeur autorisé',
         genericErrorMessage: "Le payeur autorisé n'a pas pu être modifié. Veuillez réessayer.",
diff --git a/src/languages/it.ts b/src/languages/it.ts
index c8664e61dcaa..94ae986aebdf 100644
--- a/src/languages/it.ts
+++ b/src/languages/it.ts
@@ -2170,6 +2170,22 @@ ${amount} per ${merchant} - ${date}`,
         genericErrorMessage: "L'approvatore non può essere modificato. Per favore riprova o contatta il supporto.",
         header: "Invia a questo membro per l'approvazione:",
     },
+    workflowsApprovalLimitPage: {
+        title: 'Approvatore',
+        header: '(Opzionale) Vuoi aggiungere un limite di approvazione?',
+        description: ({approverName}: {approverName: string}) => `Aggiungi un altro approvatore quando <strong>${approverName}</strong> è approvatore e il report supera l'importo seguente:`,
+        reportAmountLabel: 'Importo del report',
+        additionalApproverLabel: 'Approvatore aggiuntivo',
+        skip: 'Salta',
+        next: 'Avanti',
+        enterAmountError: 'Inserisci un importo valido',
+        enterApproverError: 'Inserisci un approvatore',
+        enterBothError: 'Inserisci un importo del report e un approvatore aggiuntivo',
+        circularReferenceError: ({approverName}: {approverName: string}) =>
+            `<strong>${approverName}</strong> approva già i report in questo flusso di lavoro. Scegli un approvatore diverso per evitare un flusso circolare.`,
+        forwardLimitDescription: ({approvalLimit, approverName}: {approvalLimit: string; approverName: string}) =>
+            `I report superiori a ${approvalLimit} vengono inoltrati a ${approverName}`,
+    },
     workflowsPayerPage: {
         title: 'Pagatore autorizzato',
         genericErrorMessage: 'Il pagatore autorizzato non può essere modificato. Per favore riprova.',
diff --git a/src/languages/ja.ts b/src/languages/ja.ts
index 5457f36e66b8..1b4a7bbff71c 100644
--- a/src/languages/ja.ts
+++ b/src/languages/ja.ts
@@ -2162,6 +2162,21 @@ ${date} - ${merchant}に${amount}`,
         genericErrorMessage: '承認者を変更できませんでした。もう一度お試しいただくか、サポートにお問い合わせください。',
         header: 'このメンバーに承認を依頼する:',
     },
+    workflowsApprovalLimitPage: {
+        title: '承認者',
+        header: '（オプション）承認限度額を追加しますか？',
+        description: ({approverName}: {approverName: string}) => `<strong>${approverName}</strong>が承認者で、レポートが以下の金額を超える場合に別の承認者を追加します：`,
+        reportAmountLabel: 'レポート金額',
+        additionalApproverLabel: '追加の承認者',
+        skip: 'スキップ',
+        next: '次へ',
+        enterAmountError: '有効な金額を入力してください',
+        enterApproverError: '承認者を入力してください',
+        enterBothError: 'レポート金額と追加の承認者を入力してください',
+        circularReferenceError: ({approverName}: {approverName: string}) =>
+            `<strong>${approverName}</strong>はすでにこのワークフローでレポートを承認しています。循環ワークフローを避けるために別の承認者を選択してください。`,
+        forwardLimitDescription: ({approvalLimit, approverName}: {approvalLimit: string; approverName: string}) => `${approvalLimit}を超えるレポートは${approverName}に転送されます`,
+    },
     workflowsPayerPage: {
         title: '承認された支払者',
         genericErrorMessage: '承認された支払者を変更できませんでした。もう一度お試しください。',
diff --git a/src/languages/nl.ts b/src/languages/nl.ts
index 483a34aa982e..6a085073c93e 100644
--- a/src/languages/nl.ts
+++ b/src/languages/nl.ts
@@ -2169,6 +2169,23 @@ ${amount} voor ${merchant} - ${date}`,
         genericErrorMessage: 'De goedkeurder kon niet worden gewijzigd. Probeer het opnieuw of neem contact op met de ondersteuning.',
         header: 'Verstuur naar dit lid voor goedkeuring:',
     },
+    workflowsApprovalLimitPage: {
+        title: 'Goedkeurder',
+        header: '(Optioneel) Wilt u een goedkeuringslimiet toevoegen?',
+        description: ({approverName}: {approverName: string}) =>
+            `Voeg een andere goedkeurder toe wanneer <strong>${approverName}</strong> goedkeurder is en het rapport het onderstaande bedrag overschrijdt:`,
+        reportAmountLabel: 'Rapportbedrag',
+        additionalApproverLabel: 'Extra goedkeurder',
+        skip: 'Overslaan',
+        next: 'Volgende',
+        enterAmountError: 'Voer een geldig bedrag in',
+        enterApproverError: 'Voer een goedkeurder in',
+        enterBothError: 'Voer een rapportbedrag en een extra goedkeurder in',
+        circularReferenceError: ({approverName}: {approverName: string}) =>
+            `<strong>${approverName}</strong> keurt al rapporten goed in deze workflow. Kies een andere goedkeurder om een circulaire workflow te vermijden.`,
+        forwardLimitDescription: ({approvalLimit, approverName}: {approvalLimit: string; approverName: string}) =>
+            `Rapporten boven ${approvalLimit} worden doorgestuurd naar ${approverName}`,
+    },
     workflowsPayerPage: {
         title: 'Geautoriseerde betaler',
         genericErrorMessage: 'De geautoriseerde betaler kon niet worden gewijzigd. Probeer het alstublieft opnieuw.',
diff --git a/src/languages/pl.ts b/src/languages/pl.ts
index dbf05dbfbe39..2a71c8daa976 100644
--- a/src/languages/pl.ts
+++ b/src/languages/pl.ts
@@ -2166,6 +2166,22 @@ ${amount} dla ${merchant} - ${date}`,
         genericErrorMessage: 'Nie można było zmienić zatwierdzającego. Spróbuj ponownie lub skontaktuj się z pomocą techniczną.',
         header: 'Wyślij do tego członka do zatwierdzenia:',
     },
+    workflowsApprovalLimitPage: {
+        title: 'Zatwierdzający',
+        header: '(Opcjonalnie) Czy chcesz dodać limit zatwierdzenia?',
+        description: ({approverName}: {approverName: string}) =>
+            `Dodaj innego zatwierdzającego, gdy <strong>${approverName}</strong> jest zatwierdzającym, a raport przekracza poniższą kwotę:`,
+        reportAmountLabel: 'Kwota raportu',
+        additionalApproverLabel: 'Dodatkowy zatwierdzający',
+        skip: 'Pomiń',
+        next: 'Dalej',
+        enterAmountError: 'Wprowadź prawidłową kwotę',
+        enterApproverError: 'Wprowadź zatwierdzającego',
+        enterBothError: 'Wprowadź kwotę raportu i dodatkowego zatwierdzającego',
+        circularReferenceError: ({approverName}: {approverName: string}) =>
+            `<strong>${approverName}</strong> już zatwierdza raporty w tym przepływie pracy. Wybierz innego zatwierdzającego, aby uniknąć cyklicznego przepływu pracy.`,
+        forwardLimitDescription: ({approvalLimit, approverName}: {approvalLimit: string; approverName: string}) => `Raporty powyżej ${approvalLimit} są przekazywane do ${approverName}`,
+    },
     workflowsPayerPage: {
         title: 'Upoważniony płatnik',
         genericErrorMessage: 'Nie udało się zmienić upoważnionego płatnika. Proszę spróbować ponownie.',
diff --git a/src/languages/pt-BR.ts b/src/languages/pt-BR.ts
index 555014f9021a..226a343e5b99 100644
--- a/src/languages/pt-BR.ts
+++ b/src/languages/pt-BR.ts
@@ -2165,6 +2165,22 @@ ${amount} para ${merchant} - ${date}`,
         genericErrorMessage: 'O aprovador não pôde ser alterado. Por favor, tente novamente ou entre em contato com o suporte.',
         header: 'Enviar para este membro para aprovação:',
     },
+    workflowsApprovalLimitPage: {
+        title: 'Aprovador',
+        header: '(Opcional) Deseja adicionar um limite de aprovação?',
+        description: ({approverName}: {approverName: string}) => `Adicione outro aprovador quando <strong>${approverName}</strong> for aprovador e o relatório exceder o valor abaixo:`,
+        reportAmountLabel: 'Valor do relatório',
+        additionalApproverLabel: 'Aprovador adicional',
+        skip: 'Pular',
+        next: 'Próximo',
+        enterAmountError: 'Por favor, insira um valor válido',
+        enterApproverError: 'Por favor, insira um aprovador',
+        enterBothError: 'Insira um valor do relatório e um aprovador adicional',
+        circularReferenceError: ({approverName}: {approverName: string}) =>
+            `<strong>${approverName}</strong> já aprova relatórios neste fluxo de trabalho. Escolha um aprovador diferente para evitar um fluxo circular.`,
+        forwardLimitDescription: ({approvalLimit, approverName}: {approvalLimit: string; approverName: string}) =>
+            `Relatórios acima de ${approvalLimit} são encaminhados para ${approverName}`,
+    },
     workflowsPayerPage: {
         title: 'Pagador autorizado',
         genericErrorMessage: 'O pagador autorizado não pôde ser alterado. Por favor, tente novamente.',
diff --git a/src/languages/zh-hans.ts b/src/languages/zh-hans.ts
index a6b93f627a1b..c773a64d67a2 100644
--- a/src/languages/zh-hans.ts
+++ b/src/languages/zh-hans.ts
@@ -2136,6 +2136,20 @@ ${merchant}的${amount} - ${date}`,
         genericErrorMessage: '无法更改审批人。请重试或联系客服。',
         header: '发送给此成员以供批准：',
     },
+    workflowsApprovalLimitPage: {
+        title: '审批人',
+        header: '（可选）是否添加审批限额？',
+        description: ({approverName}: {approverName: string}) => `当<strong>${approverName}</strong>为审批人且报告超过以下金额时，添加另一位审批人：`,
+        reportAmountLabel: '报告金额',
+        additionalApproverLabel: '额外审批人',
+        skip: '跳过',
+        next: '下一步',
+        enterAmountError: '请输入有效金额',
+        enterApproverError: '请输入审批人',
+        enterBothError: '请输入报告金额和额外审批人',
+        circularReferenceError: ({approverName}: {approverName: string}) => `<strong>${approverName}</strong>已在此工作流程中审批报告。请选择其他审批人以避免循环工作流程。`,
+        forwardLimitDescription: ({approvalLimit, approverName}: {approvalLimit: string; approverName: string}) => `超过${approvalLimit}的报告将转发给${approverName}`,
+    },
     workflowsPayerPage: {
         title: '授权付款人',
         genericErrorMessage: '授权付款人无法更改。请再试一次。',

From 6af955266c49740f7e40dc4c1594f4e3e64bc255 Mon Sep 17 00:00:00 2001
From: Abdelrahman Khattab <abzokhattab@gmail.com>
Date: Tue, 25 Nov 2025 18:35:01 +0100
Subject: [PATCH 07/49] code refactoring

---
 src/components/ApprovalWorkflowSection.tsx | 45 ++++++++++------------
 1 file changed, 21 insertions(+), 24 deletions(-)

diff --git a/src/components/ApprovalWorkflowSection.tsx b/src/components/ApprovalWorkflowSection.tsx
index 0d1bcabe06c4..3fb753e6ced3 100644
--- a/src/components/ApprovalWorkflowSection.tsx
+++ b/src/components/ApprovalWorkflowSection.tsx
@@ -109,30 +109,27 @@ function ApprovalWorkflowSection({approvalWorkflow, onPress, currency = CONST.CU
                     shouldRemoveBackground
                 />
 
-                {approvalWorkflow.approvers.map((approver, index) => {
-                    const approvalLimitDescription = getApprovalLimitDescription(approver);
-                    return (
-                        // eslint-disable-next-line react/no-array-index-key
-                        <View key={`approver-${approver.email}-${index}`}>
-                            <View style={styles.workflowApprovalVerticalLine} />
-                            <MenuItem
-                                title={approverTitle(index)}
-                                style={styles.p0}
-                                titleStyle={styles.textLabelSupportingNormal}
-                                descriptionTextStyle={[styles.textNormalThemeText, styles.lineHeightXLarge]}
-                                description={Str.removeSMSDomain(approver.displayName)}
-                                icon={icons.UserCheck}
-                                iconHeight={20}
-                                iconWidth={20}
-                                numberOfLinesDescription={1}
-                                iconFill={theme.icon}
-                                onPress={onPress}
-                                shouldRemoveBackground
-                                helperText={approvalLimitDescription}
-                            />
-                        </View>
-                    );
-                })}
+                {approvalWorkflow.approvers.map((approver, index) => (
+                    // eslint-disable-next-line react/no-array-index-key
+                    <View key={`approver-${approver.email}-${index}`}>
+                        <View style={styles.workflowApprovalVerticalLine} />
+                        <MenuItem
+                            title={approverTitle(index)}
+                            style={styles.p0}
+                            titleStyle={styles.textLabelSupportingNormal}
+                            descriptionTextStyle={[styles.textNormalThemeText, styles.lineHeightXLarge]}
+                            description={Str.removeSMSDomain(approver.displayName)}
+                            icon={icons.UserCheck}
+                            iconHeight={20}
+                            iconWidth={20}
+                            numberOfLinesDescription={1}
+                            iconFill={theme.icon}
+                            onPress={onPress}
+                            shouldRemoveBackground
+                            helperText={getApprovalLimitDescription(approver)}
+                        />
+                    </View>
+                ))}
             </View>
             <Icon
                 src={expensifyIcons.ArrowRight}

From b8d5cbeafd0dfa9556bbb33a813d80ba35ce2bd9 Mon Sep 17 00:00:00 2001
From: Abdelrahman Khattab <abzokhattab@gmail.com>
Date: Tue, 25 Nov 2025 19:04:01 +0100
Subject: [PATCH 08/49] fixing some bugs and fix eslint errs

---
 src/components/ApprovalWorkflowSection.tsx    | 12 ++++-
 src/libs/WorkflowUtils.ts                     |  3 +-
 ...aceWorkflowsApprovalsApprovalLimitPage.tsx | 49 +++++++++++++++++--
 ...orkflowsApprovalsOverLimitApproverPage.tsx | 14 +-----
 4 files changed, 58 insertions(+), 20 deletions(-)

diff --git a/src/components/ApprovalWorkflowSection.tsx b/src/components/ApprovalWorkflowSection.tsx
index 3fb753e6ced3..250bc31d206a 100644
--- a/src/components/ApprovalWorkflowSection.tsx
+++ b/src/components/ApprovalWorkflowSection.tsx
@@ -3,12 +3,15 @@ import React, {useCallback, useMemo} from 'react';
 import {View} from 'react-native';
 import {useMemoizedLazyExpensifyIcons} from '@hooks/useLazyAsset';
 import useLocalize from '@hooks/useLocalize';
+import useOnyx from '@hooks/useOnyx';
 import useResponsiveLayout from '@hooks/useResponsiveLayout';
 import useTheme from '@hooks/useTheme';
 import useThemeStyles from '@hooks/useThemeStyles';
 import {convertToDisplayString} from '@libs/CurrencyUtils';
 import {sortAlphabetically} from '@libs/OptionsListUtils';
 import CONST from '@src/CONST';
+import ONYXKEYS from '@src/ONYXKEYS';
+import {personalDetailsByEmailSelector} from '@src/selectors/PersonalDetails';
 import type ApprovalWorkflow from '@src/types/onyx/ApprovalWorkflow';
 import type {Approver} from '@src/types/onyx/ApprovalWorkflow';
 import Icon from './Icon';
@@ -36,6 +39,10 @@ function ApprovalWorkflowSection({approvalWorkflow, onPress, currency = CONST.CU
     const {translate, toLocaleOrdinal, localeCompare} = useLocalize();
     const {shouldUseNarrowLayout} = useResponsiveLayout();
     const expensifyIcons = useMemoizedLazyExpensifyIcons(['ArrowRight'] as const);
+    const [personalDetailsByEmail] = useOnyx(ONYXKEYS.PERSONAL_DETAILS_LIST, {
+        canBeMissing: true,
+        selector: personalDetailsByEmailSelector,
+    });
 
     const approverTitle = useCallback(
         (index: number) =>
@@ -50,14 +57,15 @@ function ApprovalWorkflowSection({approvalWorkflow, onPress, currency = CONST.CU
             }
 
             const formattedAmount = convertToDisplayString(approver.approvalLimit, currency);
-            const approverDisplayName = Str.removeSMSDomain(approver.overLimitForwardsTo);
+            const overLimitApproverDetails = personalDetailsByEmail?.[approver.overLimitForwardsTo];
+            const approverDisplayName = Str.removeSMSDomain(overLimitApproverDetails?.displayName ?? approver.overLimitForwardsTo);
 
             return translate('workflowsApprovalLimitPage.forwardLimitDescription', {
                 approvalLimit: formattedAmount,
                 approverName: approverDisplayName,
             });
         },
-        [currency, translate],
+        [currency, translate, personalDetailsByEmail],
     );
 
     const members = useMemo(() => {
diff --git a/src/libs/WorkflowUtils.ts b/src/libs/WorkflowUtils.ts
index 0958d5842ff6..e7bbcb618132 100644
--- a/src/libs/WorkflowUtils.ts
+++ b/src/libs/WorkflowUtils.ts
@@ -261,6 +261,7 @@ function convertApprovalWorkflowToPolicyEmployees({
         const approvalLimit = type === CONST.APPROVAL_WORKFLOW.TYPE.REMOVE ? undefined : approver.approvalLimit;
         const overLimitForwardsTo = type === CONST.APPROVAL_WORKFLOW.TYPE.REMOVE ? '' : (approver.overLimitForwardsTo ?? '');
 
+        // For every approver, we check if the forwardsTo, approvalLimit, or overLimitForwardsTo fields have changed.
         const previousEmployee = previousEmployeeList[approver.email];
         const forwardsToChanged = previousEmployee?.forwardsTo !== forwardsTo;
         const approvalLimitChanged = previousEmployee?.approvalLimit !== approvalLimit;
@@ -275,7 +276,7 @@ function convertApprovalWorkflowToPolicyEmployees({
             email: approver.email,
             forwardsTo,
             ...(approvalLimit !== undefined ? {approvalLimit} : {}),
-            ...(overLimitForwardsTo ? {overLimitForwardsTo} : {}),
+            ...(overLimitForwardsToChanged ? {overLimitForwardsTo} : {}),
             pendingAction: previousPendingAction === CONST.RED_BRICK_ROAD_PENDING_ACTION.DELETE ? previousPendingAction : pendingAction,
             pendingFields: {
                 forwardsTo: pendingAction,
diff --git a/src/pages/workspace/workflows/approvals/WorkspaceWorkflowsApprovalsApprovalLimitPage.tsx b/src/pages/workspace/workflows/approvals/WorkspaceWorkflowsApprovalsApprovalLimitPage.tsx
index f351809aa27a..c1e6a1f56714 100644
--- a/src/pages/workspace/workflows/approvals/WorkspaceWorkflowsApprovalsApprovalLimitPage.tsx
+++ b/src/pages/workspace/workflows/approvals/WorkspaceWorkflowsApprovalsApprovalLimitPage.tsx
@@ -45,6 +45,8 @@ function WorkspaceWorkflowsApprovalsApprovalLimitPage({policy, isLoadingReportDa
 
     const policyID = route.params.policyID;
     const approverIndex = Number(route.params.approverIndex) ?? 0;
+    const backTo = route.params?.backTo;
+    const isEditFlow = approvalWorkflow?.action === CONST.APPROVAL_WORKFLOW.ACTION.EDIT;
     const currentApprover = approvalWorkflow?.approvers?.[approverIndex];
     const currency = policy?.outputCurrency ?? CONST.CURRENCY.USD;
 
@@ -97,8 +99,27 @@ function WorkspaceWorkflowsApprovalsApprovalLimitPage({policy, isLoadingReportDa
     }, [hasSubmitted, onlyApproverEmpty, isCircularReference, selectedApproverDisplayName, translate]);
 
     const handleSkip = useCallback(() => {
-        Navigation.navigate(ROUTES.WORKSPACE_WORKFLOWS_APPROVALS_NEW.getRoute(policyID));
-    }, [policyID]);
+        // Clear any existing approval limit when skipping
+        if (approvalWorkflow && currentApprover && (currentApprover.approvalLimit || currentApprover.overLimitForwardsTo)) {
+            setApprovalWorkflowApprover({
+                approver: {
+                    ...currentApprover,
+                    approvalLimit: undefined,
+                    overLimitForwardsTo: '',
+                },
+                approverIndex,
+                currentApprovalWorkflow: approvalWorkflow,
+                policy,
+                personalDetailsByEmail,
+            });
+        }
+
+        if (isEditFlow) {
+            Navigation.goBack(backTo);
+        } else {
+            Navigation.navigate(ROUTES.WORKSPACE_WORKFLOWS_APPROVALS_NEW.getRoute(policyID));
+        }
+    }, [approvalWorkflow, currentApprover, approverIndex, policy, personalDetailsByEmail, isEditFlow, backTo, policyID]);
 
     const handleNext = useCallback(() => {
         setHasSubmitted(true);
@@ -125,12 +146,30 @@ function WorkspaceWorkflowsApprovalsApprovalLimitPage({policy, isLoadingReportDa
             personalDetailsByEmail,
         });
 
-        Navigation.navigate(ROUTES.WORKSPACE_WORKFLOWS_APPROVALS_NEW.getRoute(policyID));
-    }, [approvalLimit, selectedApproverEmail, isCircularReference, approvalWorkflow, currentApprover, approverIndex, policy, personalDetailsByEmail, policyID]);
+        if (isEditFlow) {
+            Navigation.goBack(backTo);
+        } else {
+            Navigation.navigate(ROUTES.WORKSPACE_WORKFLOWS_APPROVALS_NEW.getRoute(policyID));
+        }
+    }, [approvalLimit, selectedApproverEmail, isCircularReference, approvalWorkflow, currentApprover, approverIndex, policy, personalDetailsByEmail, isEditFlow, backTo, policyID]);
 
     const navigateToApproverSelector = useCallback(() => {
+        // Save the current amount to Onyx before navigating so it persists when we come back
+        if (approvalWorkflow && currentApprover && approvalLimit) {
+            const limitInCents = convertToBackendAmount(Number.parseFloat(approvalLimit));
+            setApprovalWorkflowApprover({
+                approver: {
+                    ...currentApprover,
+                    approvalLimit: limitInCents,
+                },
+                approverIndex,
+                currentApprovalWorkflow: approvalWorkflow,
+                policy,
+                personalDetailsByEmail,
+            });
+        }
         Navigation.navigate(ROUTES.WORKSPACE_WORKFLOWS_APPROVALS_OVER_LIMIT_APPROVER.getRoute(policyID, approverIndex));
-    }, [policyID, approverIndex]);
+    }, [policyID, approverIndex, approvalWorkflow, currentApprover, approvalLimit, policy, personalDetailsByEmail]);
 
     const buttonContainerStyle = useBottomSafeSafeAreaPaddingStyle({addBottomSafeAreaPadding: true, style: [styles.mh5, styles.mb5]});
 
diff --git a/src/pages/workspace/workflows/approvals/WorkspaceWorkflowsApprovalsOverLimitApproverPage.tsx b/src/pages/workspace/workflows/approvals/WorkspaceWorkflowsApprovalsOverLimitApproverPage.tsx
index 8e8f82b5c82e..b436b86f1ec1 100644
--- a/src/pages/workspace/workflows/approvals/WorkspaceWorkflowsApprovalsOverLimitApproverPage.tsx
+++ b/src/pages/workspace/workflows/approvals/WorkspaceWorkflowsApprovalsOverLimitApproverPage.tsx
@@ -41,7 +41,6 @@ function WorkspaceWorkflowsApprovalsOverLimitApproverPage({policy, personalDetai
     const currentApprover = approvalWorkflow?.approvers?.[approverIndex];
 
     const employeeList = policy?.employeeList;
-    const approversFromWorkflow = approvalWorkflow?.approvers;
 
     const allApprovers: SelectionListApprover[] = useMemo(() => {
         if (isApprovalWorkflowLoading || !employeeList) {
@@ -56,11 +55,6 @@ function WorkspaceWorkflowsApprovalsOverLimitApproverPage({policy, personalDetai
                     return null;
                 }
 
-                const isEmailAlreadyInApprovers = approversFromWorkflow?.some((approver) => approver?.email === email);
-                if (isEmailAlreadyInApprovers) {
-                    return null;
-                }
-
                 const policyMemberEmailsToAccountIDs = getMemberAccountIDsForWorkspace(employeeList);
                 const accountID = Number(policyMemberEmailsToAccountIDs[email] ?? '');
                 const {avatar, displayName = email, login} = personalDetails?.[accountID] ?? {};
@@ -82,7 +76,7 @@ function WorkspaceWorkflowsApprovalsOverLimitApproverPage({policy, personalDetai
                 };
             })
             .filter((approver): approver is SelectionListApprover => !!approver);
-    }, [isApprovalWorkflowLoading, employeeList, approversFromWorkflow, personalDetails, policy?.owner, currentApprover?.overLimitForwardsTo, expensifyIcons.FallbackAvatar]);
+    }, [isApprovalWorkflowLoading, employeeList, personalDetails, policy?.owner, currentApprover?.overLimitForwardsTo, expensifyIcons.FallbackAvatar]);
 
     const shouldShowListEmptyContent = !!approvalWorkflow && !isApprovalWorkflowLoading;
 
@@ -97,10 +91,6 @@ function WorkspaceWorkflowsApprovalsOverLimitApproverPage({policy, personalDetai
                 return;
             }
 
-            const policyMemberEmailsToAccountIDs = getMemberAccountIDsForWorkspace(employeeList);
-            const accountID = Number(selectedApprover.login ? policyMemberEmailsToAccountIDs[selectedApprover.login] : '');
-            const {avatar, displayName = selectedApprover.login} = personalDetails?.[accountID] ?? {};
-
             setApprovalWorkflowApprover({
                 approver: {
                     ...currentApprover,
@@ -114,7 +104,7 @@ function WorkspaceWorkflowsApprovalsOverLimitApproverPage({policy, personalDetai
 
             goBack();
         },
-        [approvalWorkflow, currentApprover, employeeList, personalDetails, approverIndex, policy, personalDetailsByEmail, goBack],
+        [approvalWorkflow, currentApprover, approverIndex, policy, personalDetailsByEmail, goBack],
     );
 
     const subtitle = useMemo(

From 1721985833ef8614d15f6a7f08fcaf8f74fd16e9 Mon Sep 17 00:00:00 2001
From: Abdelrahman Khattab <abzokhattab@gmail.com>
Date: Tue, 2 Dec 2025 14:54:01 +0100
Subject: [PATCH 09/49] feat: Add approval limit editing support for workflow
 approvers

---
 src/components/AmountForm.tsx                 |   5 +
 src/components/ApprovalWorkflowSection.tsx    |  45 +++---
 src/components/NumberWithSymbolForm.tsx       |   5 +
 src/languages/de.ts                           |  10 +-
 src/languages/en.ts                           |  11 +-
 src/languages/es.ts                           |  21 ++-
 src/languages/fr.ts                           |  10 +-
 src/languages/it.ts                           |  11 +-
 src/languages/ja.ts                           |  11 +-
 src/languages/nl.ts                           |  10 +-
 src/languages/pl.ts                           |  10 +-
 src/languages/pt-BR.ts                        |  11 +-
 src/languages/zh-hans.ts                      |   9 +-
 src/libs/WorkflowUtils.ts                     |   2 +-
 src/libs/actions/Workflow.ts                  |  11 ++
 .../approvals/ApprovalWorkflowEditor.tsx      |  19 ++-
 ...aceWorkflowsApprovalsApprovalLimitPage.tsx | 148 ++++++++++++++----
 ...orkspaceWorkflowsApprovalsApproverPage.tsx |  70 +++++----
 .../WorkspaceWorkflowsApprovalsEditPage.tsx   |   7 +
 ...orkflowsApprovalsOverLimitApproverPage.tsx |  28 +++-
 src/styles/index.ts                           |   4 +
 src/types/onyx/ApprovalWorkflow.ts            |   2 +-
 src/types/onyx/PolicyEmployee.ts              |   4 +-
 23 files changed, 329 insertions(+), 135 deletions(-)

diff --git a/src/components/AmountForm.tsx b/src/components/AmountForm.tsx
index e7c6c53325b1..6a303ff283dc 100644
--- a/src/components/AmountForm.tsx
+++ b/src/components/AmountForm.tsx
@@ -43,6 +43,9 @@ type AmountFormProps = {
     /** Whether to hide the currency symbol */
     hideCurrencySymbol?: boolean;
 
+    /** Whether the input should be disabled */
+    disabled?: boolean;
+
     /** Reference to the outer element */
     ref?: ForwardedRef<BaseTextInputRef>;
 } & Pick<BaseTextInputProps, 'autoFocus' | 'autoGrowExtraSpace' | 'autoGrowMarginSide'>;
@@ -62,6 +65,7 @@ function AmountForm({
     label,
     decimals: decimalsProp,
     hideCurrencySymbol = false,
+    disabled = false,
     autoFocus,
     autoGrowExtraSpace,
     autoGrowMarginSide,
@@ -99,6 +103,7 @@ function AmountForm({
             autoFocus={autoFocus}
             autoGrowExtraSpace={autoGrowExtraSpace}
             autoGrowMarginSide={autoGrowMarginSide}
+            disabled={disabled}
         />
     );
 }
diff --git a/src/components/ApprovalWorkflowSection.tsx b/src/components/ApprovalWorkflowSection.tsx
index 250bc31d206a..fbca289305ea 100644
--- a/src/components/ApprovalWorkflowSection.tsx
+++ b/src/components/ApprovalWorkflowSection.tsx
@@ -117,27 +117,30 @@ function ApprovalWorkflowSection({approvalWorkflow, onPress, currency = CONST.CU
                     shouldRemoveBackground
                 />
 
-                {approvalWorkflow.approvers.map((approver, index) => (
-                    // eslint-disable-next-line react/no-array-index-key
-                    <View key={`approver-${approver.email}-${index}`}>
-                        <View style={styles.workflowApprovalVerticalLine} />
-                        <MenuItem
-                            title={approverTitle(index)}
-                            style={styles.p0}
-                            titleStyle={styles.textLabelSupportingNormal}
-                            descriptionTextStyle={[styles.textNormalThemeText, styles.lineHeightXLarge]}
-                            description={Str.removeSMSDomain(approver.displayName)}
-                            icon={icons.UserCheck}
-                            iconHeight={20}
-                            iconWidth={20}
-                            numberOfLinesDescription={1}
-                            iconFill={theme.icon}
-                            onPress={onPress}
-                            shouldRemoveBackground
-                            helperText={getApprovalLimitDescription(approver)}
-                        />
-                    </View>
-                ))}
+                {approvalWorkflow.approvers.map((approver, index) => {
+                    const approvalLimitDescription = getApprovalLimitDescription(approver);
+                    return (
+                        // eslint-disable-next-line react/no-array-index-key
+                        <View key={`approver-${approver.email}-${index}`}>
+                            <View style={styles.workflowApprovalVerticalLine} />
+                            <MenuItem
+                                title={approverTitle(index)}
+                                style={styles.p0}
+                                titleStyle={styles.textLabelSupportingNormal}
+                                descriptionTextStyle={[styles.textNormalThemeText, styles.lineHeightXLarge]}
+                                description={Str.removeSMSDomain(approver.displayName)}
+                                icon={icons.UserCheck}
+                                iconHeight={20}
+                                iconWidth={20}
+                                numberOfLinesDescription={1}
+                                iconFill={theme.icon}
+                                onPress={onPress}
+                                shouldRemoveBackground
+                            />
+                            {!!approvalLimitDescription && <Text style={[styles.textLabelSupporting, styles.workflowApprovalLimitText]}>{approvalLimitDescription}</Text>}
+                        </View>
+                    );
+                })}
             </View>
             <Icon
                 src={expensifyIcons.ArrowRight}
diff --git a/src/components/NumberWithSymbolForm.tsx b/src/components/NumberWithSymbolForm.tsx
index 9bfbc8f74db4..f851a3f66e86 100644
--- a/src/components/NumberWithSymbolForm.tsx
+++ b/src/components/NumberWithSymbolForm.tsx
@@ -81,6 +81,9 @@ type NumberWithSymbolFormProps = {
     /** Whether to allow flipping amount */
     allowFlippingAmount?: boolean;
 
+    /** Whether the input should be disabled */
+    disabled?: boolean;
+
     /** Reference to the outer element */
     ref?: ForwardedRef<BaseTextInputRef>;
 } & Omit<TextInputWithSymbolProps, 'formattedAmount' | 'onAmountChange' | 'placeholder' | 'onSelectionChange' | 'onKeyPress' | 'onMouseDown' | 'onMouseUp'>;
@@ -142,6 +145,7 @@ function NumberWithSymbolForm({
     allowFlippingAmount = false,
     toggleNegative,
     clearNegative,
+    disabled = false,
     ref,
     ...props
 }: NumberWithSymbolFormProps) {
@@ -384,6 +388,7 @@ function NumberWithSymbolForm({
                 autoFocus={props.autoFocus}
                 autoGrowExtraSpace={props.autoGrowExtraSpace}
                 autoGrowMarginSide={props.autoGrowMarginSide}
+                disabled={disabled}
             />
         );
     }
diff --git a/src/languages/de.ts b/src/languages/de.ts
index be3411e49c2b..a741a37e21f2 100644
--- a/src/languages/de.ts
+++ b/src/languages/de.ts
@@ -2176,19 +2176,23 @@ ${amount} für ${merchant} - ${date}`,
     },
     workflowsApproverPage: {
         genericErrorMessage: 'Der Genehmiger konnte nicht geändert werden. Bitte versuchen Sie es erneut oder kontaktieren Sie den Support.',
-        header: 'An dieses Mitglied zur Genehmigung senden:',
+        title: 'Genehmiger festlegen',
+        description: 'Diese Person wird die Ausgaben genehmigen.',
     },
     workflowsApprovalLimitPage: {
         title: 'Genehmiger',
         header: '(Optional) Möchten Sie ein Genehmigungslimit hinzufügen?',
         description: ({approverName}: {approverName: string}) =>
-            `Fügen Sie einen weiteren Genehmiger hinzu, wenn <strong>${approverName}</strong> Genehmiger ist und der Bericht den folgenden Betrag überschreitet:`,
+            approverName
+                ? `Fügen Sie einen weiteren Genehmiger hinzu, wenn <strong>${approverName}</strong> Genehmiger ist und der Bericht den folgenden Betrag überschreitet:`
+                : 'Fügen Sie einen weiteren Genehmiger hinzu, wenn der Bericht den folgenden Betrag überschreitet:',
         reportAmountLabel: 'Berichtsbetrag',
         additionalApproverLabel: 'Zusätzlicher Genehmiger',
         skip: 'Überspringen',
         next: 'Weiter',
+        removeLimit: 'Limit entfernen',
         enterAmountError: 'Bitte geben Sie einen gültigen Betrag ein',
-        enterApproverError: 'Bitte geben Sie einen Genehmiger ein',
+        enterApproverError: 'Ein Genehmiger ist erforderlich, wenn Sie ein Berichtslimit haben',
         enterBothError: 'Geben Sie einen Berichtsbetrag und einen zusätzlichen Genehmiger ein',
         circularReferenceError: ({approverName}: {approverName: string}) =>
             `<strong>${approverName}</strong> genehmigt bereits Berichte in diesem Workflow. Wählen Sie einen anderen Genehmiger, um einen zirkulären Workflow zu vermeiden.`,
diff --git a/src/languages/en.ts b/src/languages/en.ts
index dac6a9205f8f..0313bb01aa37 100755
--- a/src/languages/en.ts
+++ b/src/languages/en.ts
@@ -2264,18 +2264,23 @@ const translations = {
     },
     workflowsApproverPage: {
         genericErrorMessage: "The approver couldn't be changed. Please try again or contact support.",
-        header: 'Send to this member for approval:',
+        title: 'Set approver',
+        description: 'This person will approve the expenses.',
     },
     workflowsApprovalLimitPage: {
         title: 'Approver',
         header: '(Optional) Want to add an approval limit?',
-        description: ({approverName}: {approverName: string}) => `Add another approver when <strong>${approverName}</strong> is approver and report exceeds the amount below:`,
+        description: ({approverName}: {approverName: string}) =>
+            approverName
+                ? `Add another approver when <strong>${approverName}</strong> is approver and report exceeds the amount below:`
+                : 'Add another approver when a report exceeds the amount below:',
         reportAmountLabel: 'Report amount',
         additionalApproverLabel: 'Additional approver',
         skip: 'Skip',
         next: 'Next',
+        removeLimit: 'Remove limit',
         enterAmountError: 'Please enter a valid amount',
-        enterApproverError: 'Please enter an approver',
+        enterApproverError: 'Approver is required when you have a report limit',
         enterBothError: 'Enter a report amount and additional approver',
         circularReferenceError: ({approverName}: {approverName: string}) =>
             `<strong>${approverName}</strong> already approves reports in this workflow. Choose a different approver to avoid a circular workflow.`,
diff --git a/src/languages/es.ts b/src/languages/es.ts
index 42d003775ac5..5bb6653f018b 100644
--- a/src/languages/es.ts
+++ b/src/languages/es.ts
@@ -1907,22 +1907,27 @@ ${amount} para ${merchant} - ${date}`,
     },
     workflowsApproverPage: {
         genericErrorMessage: 'El aprobador no pudo ser cambiado. Por favor, inténtelo de nuevo o contacte al soporte.',
-        header: 'Enviar a este miembro para su aprobación:',
+        title: 'Establecer aprobador',
+        description: 'Esta persona aprobará los gastos.',
     },
     workflowsApprovalLimitPage: {
         title: 'Aprobador',
         header: '(Opcional) ¿Quieres añadir un límite de aprobación?',
-        description: ({approverName}: {approverName: string}) => `Añadir otro aprobador cuando <strong>${approverName}</strong> es aprobador y el informe excede el monto a continuación:`,
-        reportAmountLabel: 'Monto del informe',
+        description: ({approverName}: {approverName: string}) =>
+            approverName
+                ? `Añadir otro aprobador cuando <strong>${approverName}</strong> es aprobador y el informe supera el importe indicado:`
+                : 'Añadir otro aprobador cuando el informe supera el importe indicado:',
+        reportAmountLabel: 'Importe del informe',
         additionalApproverLabel: 'Aprobador adicional',
         skip: 'Omitir',
         next: 'Siguiente',
-        enterAmountError: 'Por favor ingrese un monto válido',
-        enterApproverError: 'Por favor ingrese un aprobador',
-        enterBothError: 'Ingrese un monto del informe y un aprobador adicional',
+        removeLimit: 'Eliminar límite',
+        enterAmountError: 'Por favor, introduce un importe válido',
+        enterApproverError: 'Se requiere un aprobador cuando tienes un límite de informe',
+        enterBothError: 'Introduce un importe del informe y un aprobador adicional',
         circularReferenceError: ({approverName}: {approverName: string}) =>
-            `<strong>${approverName}</strong> ya aprueba informes en este flujo de trabajo. Elija un aprobador diferente para evitar un flujo de trabajo circular.`,
-        forwardLimitDescription: ({approvalLimit, approverName}: {approvalLimit: string; approverName: string}) => `Informes por encima de ${approvalLimit} se envían a ${approverName}`,
+            `<strong>${approverName}</strong> ya aprueba informes en este flujo de trabajo. Elige un aprobador diferente para evitar un flujo de trabajo circular.`,
+        forwardLimitDescription: ({approvalLimit, approverName}: {approvalLimit: string; approverName: string}) => `Los informes superiores a ${approvalLimit} se envían a ${approverName}`,
     },
     workflowsPayerPage: {
         title: 'Pagador autorizado',
diff --git a/src/languages/fr.ts b/src/languages/fr.ts
index 4a73389cf7ee..578b78bac54f 100644
--- a/src/languages/fr.ts
+++ b/src/languages/fr.ts
@@ -2176,19 +2176,23 @@ ${amount} pour ${merchant} - ${date}`,
     },
     workflowsApproverPage: {
         genericErrorMessage: "L'approbateur n'a pas pu être modifié. Veuillez réessayer ou contacter le support.",
-        header: 'Envoyer à ce membre pour approbation :',
+        title: "Définir l'approbateur",
+        description: 'Cette personne approuvera les dépenses.',
     },
     workflowsApprovalLimitPage: {
         title: 'Approbateur',
         header: "(Optionnel) Voulez-vous ajouter une limite d'approbation ?",
         description: ({approverName}: {approverName: string}) =>
-            `Ajoutez un autre approbateur lorsque <strong>${approverName}</strong> est approbateur et que le rapport dépasse le montant ci-dessous :`,
+            approverName
+                ? `Ajoutez un autre approbateur lorsque <strong>${approverName}</strong> est approbateur et que le rapport dépasse le montant ci-dessous :`
+                : 'Ajoutez un autre approbateur lorsque le rapport dépasse le montant ci-dessous :',
         reportAmountLabel: 'Montant du rapport',
         additionalApproverLabel: 'Approbateur supplémentaire',
         skip: 'Passer',
         next: 'Suivant',
+        removeLimit: 'Supprimer la limite',
         enterAmountError: 'Veuillez entrer un montant valide',
-        enterApproverError: 'Veuillez entrer un approbateur',
+        enterApproverError: 'Un approbateur est requis lorsque vous avez une limite de rapport',
         enterBothError: 'Entrez un montant de rapport et un approbateur supplémentaire',
         circularReferenceError: ({approverName}: {approverName: string}) =>
             `<strong>${approverName}</strong> approuve déjà des rapports dans ce flux de travail. Choisissez un autre approbateur pour éviter un flux circulaire.`,
diff --git a/src/languages/it.ts b/src/languages/it.ts
index 94ae986aebdf..6795fbebd8e0 100644
--- a/src/languages/it.ts
+++ b/src/languages/it.ts
@@ -2168,18 +2168,23 @@ ${amount} per ${merchant} - ${date}`,
     },
     workflowsApproverPage: {
         genericErrorMessage: "L'approvatore non può essere modificato. Per favore riprova o contatta il supporto.",
-        header: "Invia a questo membro per l'approvazione:",
+        title: 'Imposta approvatore',
+        description: 'Questa persona approverà le spese.',
     },
     workflowsApprovalLimitPage: {
         title: 'Approvatore',
         header: '(Opzionale) Vuoi aggiungere un limite di approvazione?',
-        description: ({approverName}: {approverName: string}) => `Aggiungi un altro approvatore quando <strong>${approverName}</strong> è approvatore e il report supera l'importo seguente:`,
+        description: ({approverName}: {approverName: string}) =>
+            approverName
+                ? `Aggiungi un altro approvatore quando <strong>${approverName}</strong> è approvatore e il report supera l'importo seguente:`
+                : "Aggiungi un altro approvatore quando il report supera l'importo seguente:",
         reportAmountLabel: 'Importo del report',
         additionalApproverLabel: 'Approvatore aggiuntivo',
         skip: 'Salta',
         next: 'Avanti',
+        removeLimit: 'Rimuovi limite',
         enterAmountError: 'Inserisci un importo valido',
-        enterApproverError: 'Inserisci un approvatore',
+        enterApproverError: 'Un approvatore è richiesto quando hai un limite di report',
         enterBothError: 'Inserisci un importo del report e un approvatore aggiuntivo',
         circularReferenceError: ({approverName}: {approverName: string}) =>
             `<strong>${approverName}</strong> approva già i report in questo flusso di lavoro. Scegli un approvatore diverso per evitare un flusso circolare.`,
diff --git a/src/languages/ja.ts b/src/languages/ja.ts
index 1b4a7bbff71c..ee0afbe3395f 100644
--- a/src/languages/ja.ts
+++ b/src/languages/ja.ts
@@ -2160,18 +2160,23 @@ ${date} - ${merchant}に${amount}`,
     },
     workflowsApproverPage: {
         genericErrorMessage: '承認者を変更できませんでした。もう一度お試しいただくか、サポートにお問い合わせください。',
-        header: 'このメンバーに承認を依頼する:',
+        title: '承認者を設定',
+        description: 'この人が経費を承認します。',
     },
     workflowsApprovalLimitPage: {
         title: '承認者',
         header: '（オプション）承認限度額を追加しますか？',
-        description: ({approverName}: {approverName: string}) => `<strong>${approverName}</strong>が承認者で、レポートが以下の金額を超える場合に別の承認者を追加します：`,
+        description: ({approverName}: {approverName: string}) =>
+            approverName
+                ? `<strong>${approverName}</strong>が承認者で、レポートが以下の金額を超える場合に別の承認者を追加します：`
+                : 'レポートが以下の金額を超える場合に別の承認者を追加します：',
         reportAmountLabel: 'レポート金額',
         additionalApproverLabel: '追加の承認者',
         skip: 'スキップ',
         next: '次へ',
+        removeLimit: '制限を削除',
         enterAmountError: '有効な金額を入力してください',
-        enterApproverError: '承認者を入力してください',
+        enterApproverError: 'レポート制限がある場合は承認者が必要です',
         enterBothError: 'レポート金額と追加の承認者を入力してください',
         circularReferenceError: ({approverName}: {approverName: string}) =>
             `<strong>${approverName}</strong>はすでにこのワークフローでレポートを承認しています。循環ワークフローを避けるために別の承認者を選択してください。`,
diff --git a/src/languages/nl.ts b/src/languages/nl.ts
index 6a085073c93e..4f2af1622ff1 100644
--- a/src/languages/nl.ts
+++ b/src/languages/nl.ts
@@ -2167,19 +2167,23 @@ ${amount} voor ${merchant} - ${date}`,
     },
     workflowsApproverPage: {
         genericErrorMessage: 'De goedkeurder kon niet worden gewijzigd. Probeer het opnieuw of neem contact op met de ondersteuning.',
-        header: 'Verstuur naar dit lid voor goedkeuring:',
+        title: 'Goedkeurder instellen',
+        description: 'Deze persoon zal de uitgaven goedkeuren.',
     },
     workflowsApprovalLimitPage: {
         title: 'Goedkeurder',
         header: '(Optioneel) Wilt u een goedkeuringslimiet toevoegen?',
         description: ({approverName}: {approverName: string}) =>
-            `Voeg een andere goedkeurder toe wanneer <strong>${approverName}</strong> goedkeurder is en het rapport het onderstaande bedrag overschrijdt:`,
+            approverName
+                ? `Voeg een andere goedkeurder toe wanneer <strong>${approverName}</strong> goedkeurder is en het rapport het onderstaande bedrag overschrijdt:`
+                : 'Voeg een andere goedkeurder toe wanneer het rapport het onderstaande bedrag overschrijdt:',
         reportAmountLabel: 'Rapportbedrag',
         additionalApproverLabel: 'Extra goedkeurder',
         skip: 'Overslaan',
         next: 'Volgende',
+        removeLimit: 'Limiet verwijderen',
         enterAmountError: 'Voer een geldig bedrag in',
-        enterApproverError: 'Voer een goedkeurder in',
+        enterApproverError: 'Een goedkeurder is vereist wanneer u een rapportlimiet heeft',
         enterBothError: 'Voer een rapportbedrag en een extra goedkeurder in',
         circularReferenceError: ({approverName}: {approverName: string}) =>
             `<strong>${approverName}</strong> keurt al rapporten goed in deze workflow. Kies een andere goedkeurder om een circulaire workflow te vermijden.`,
diff --git a/src/languages/pl.ts b/src/languages/pl.ts
index 2a71c8daa976..47b029d4bde0 100644
--- a/src/languages/pl.ts
+++ b/src/languages/pl.ts
@@ -2164,19 +2164,23 @@ ${amount} dla ${merchant} - ${date}`,
     },
     workflowsApproverPage: {
         genericErrorMessage: 'Nie można było zmienić zatwierdzającego. Spróbuj ponownie lub skontaktuj się z pomocą techniczną.',
-        header: 'Wyślij do tego członka do zatwierdzenia:',
+        title: 'Ustaw zatwierdzającego',
+        description: 'Ta osoba zatwierdzi wydatki.',
     },
     workflowsApprovalLimitPage: {
         title: 'Zatwierdzający',
         header: '(Opcjonalnie) Czy chcesz dodać limit zatwierdzenia?',
         description: ({approverName}: {approverName: string}) =>
-            `Dodaj innego zatwierdzającego, gdy <strong>${approverName}</strong> jest zatwierdzającym, a raport przekracza poniższą kwotę:`,
+            approverName
+                ? `Dodaj innego zatwierdzającego, gdy <strong>${approverName}</strong> jest zatwierdzającym, a raport przekracza poniższą kwotę:`
+                : 'Dodaj innego zatwierdzającego, gdy raport przekracza poniższą kwotę:',
         reportAmountLabel: 'Kwota raportu',
         additionalApproverLabel: 'Dodatkowy zatwierdzający',
         skip: 'Pomiń',
         next: 'Dalej',
+        removeLimit: 'Usuń limit',
         enterAmountError: 'Wprowadź prawidłową kwotę',
-        enterApproverError: 'Wprowadź zatwierdzającego',
+        enterApproverError: 'Zatwierdzający jest wymagany, gdy masz limit raportu',
         enterBothError: 'Wprowadź kwotę raportu i dodatkowego zatwierdzającego',
         circularReferenceError: ({approverName}: {approverName: string}) =>
             `<strong>${approverName}</strong> już zatwierdza raporty w tym przepływie pracy. Wybierz innego zatwierdzającego, aby uniknąć cyklicznego przepływu pracy.`,
diff --git a/src/languages/pt-BR.ts b/src/languages/pt-BR.ts
index 226a343e5b99..2fab7687e794 100644
--- a/src/languages/pt-BR.ts
+++ b/src/languages/pt-BR.ts
@@ -2163,18 +2163,23 @@ ${amount} para ${merchant} - ${date}`,
     },
     workflowsApproverPage: {
         genericErrorMessage: 'O aprovador não pôde ser alterado. Por favor, tente novamente ou entre em contato com o suporte.',
-        header: 'Enviar para este membro para aprovação:',
+        title: 'Definir aprovador',
+        description: 'Esta pessoa aprovará as despesas.',
     },
     workflowsApprovalLimitPage: {
         title: 'Aprovador',
         header: '(Opcional) Deseja adicionar um limite de aprovação?',
-        description: ({approverName}: {approverName: string}) => `Adicione outro aprovador quando <strong>${approverName}</strong> for aprovador e o relatório exceder o valor abaixo:`,
+        description: ({approverName}: {approverName: string}) =>
+            approverName
+                ? `Adicione outro aprovador quando <strong>${approverName}</strong> for aprovador e o relatório exceder o valor abaixo:`
+                : 'Adicione outro aprovador quando o relatório exceder o valor abaixo:',
         reportAmountLabel: 'Valor do relatório',
         additionalApproverLabel: 'Aprovador adicional',
         skip: 'Pular',
         next: 'Próximo',
+        removeLimit: 'Remover limite',
         enterAmountError: 'Por favor, insira um valor válido',
-        enterApproverError: 'Por favor, insira um aprovador',
+        enterApproverError: 'Um aprovador é necessário quando você tem um limite de relatório',
         enterBothError: 'Insira um valor do relatório e um aprovador adicional',
         circularReferenceError: ({approverName}: {approverName: string}) =>
             `<strong>${approverName}</strong> já aprova relatórios neste fluxo de trabalho. Escolha um aprovador diferente para evitar um fluxo circular.`,
diff --git a/src/languages/zh-hans.ts b/src/languages/zh-hans.ts
index c773a64d67a2..d14775bec6aa 100644
--- a/src/languages/zh-hans.ts
+++ b/src/languages/zh-hans.ts
@@ -2134,18 +2134,21 @@ ${merchant}的${amount} - ${date}`,
     },
     workflowsApproverPage: {
         genericErrorMessage: '无法更改审批人。请重试或联系客服。',
-        header: '发送给此成员以供批准：',
+        title: '设置审批人',
+        description: '此人将审批费用。',
     },
     workflowsApprovalLimitPage: {
         title: '审批人',
         header: '（可选）是否添加审批限额？',
-        description: ({approverName}: {approverName: string}) => `当<strong>${approverName}</strong>为审批人且报告超过以下金额时，添加另一位审批人：`,
+        description: ({approverName}: {approverName: string}) =>
+            approverName ? `当<strong>${approverName}</strong>为审批人且报告超过以下金额时，添加另一位审批人：` : '当报告超过以下金额时，添加另一位审批人：',
         reportAmountLabel: '报告金额',
         additionalApproverLabel: '额外审批人',
         skip: '跳过',
         next: '下一步',
+        removeLimit: '移除限额',
         enterAmountError: '请输入有效金额',
-        enterApproverError: '请输入审批人',
+        enterApproverError: '设置报告限额时需要审批人',
         enterBothError: '请输入报告金额和额外审批人',
         circularReferenceError: ({approverName}: {approverName: string}) => `<strong>${approverName}</strong>已在此工作流程中审批报告。请选择其他审批人以避免循环工作流程。`,
         forwardLimitDescription: ({approvalLimit, approverName}: {approvalLimit: string; approverName: string}) => `超过${approvalLimit}的报告将转发给${approverName}`,
diff --git a/src/libs/WorkflowUtils.ts b/src/libs/WorkflowUtils.ts
index e7bbcb618132..b37ac71bfd5b 100644
--- a/src/libs/WorkflowUtils.ts
+++ b/src/libs/WorkflowUtils.ts
@@ -275,7 +275,7 @@ function convertApprovalWorkflowToPolicyEmployees({
         updatedEmployeeList[approver.email] = {
             email: approver.email,
             forwardsTo,
-            ...(approvalLimit !== undefined ? {approvalLimit} : {}),
+            ...(approvalLimitChanged ? {approvalLimit} : {}),
             ...(overLimitForwardsToChanged ? {overLimitForwardsTo} : {}),
             pendingAction: previousPendingAction === CONST.RED_BRICK_ROAD_PENDING_ACTION.DELETE ? previousPendingAction : pendingAction,
             pendingFields: {
diff --git a/src/libs/actions/Workflow.ts b/src/libs/actions/Workflow.ts
index 77d4008b3709..41c71b7098a2 100644
--- a/src/libs/actions/Workflow.ts
+++ b/src/libs/actions/Workflow.ts
@@ -267,7 +267,18 @@ function setApprovalWorkflowApprover({approver, approverIndex, currentApprovalWo
     // Check if the approver forwards to other approvers and add them to the list
     if (policy.employeeList[approver.email]?.forwardsTo) {
         const additionalApprovers = calculateApprovers({employees: policy.employeeList, firstEmail: approver.email, personalDetailsByEmail});
+
         approvers.splice(approverIndex, approvers.length, ...additionalApprovers);
+
+        // Preserve the new approvalLimit and overLimitForwardsTo values that were passed in,
+        // since calculateApprovers reads from stale policy data
+        if (approvers[approverIndex]) {
+            approvers[approverIndex] = {
+                ...approvers[approverIndex],
+                approvalLimit: approver.approvalLimit,
+                overLimitForwardsTo: approver.overLimitForwardsTo,
+            };
+        }
     }
 
     // Always clear the additional approver error when an approver is added
diff --git a/src/pages/workspace/workflows/approvals/ApprovalWorkflowEditor.tsx b/src/pages/workspace/workflows/approvals/ApprovalWorkflowEditor.tsx
index 4b1a017d2ba4..7f67bd2230fc 100644
--- a/src/pages/workspace/workflows/approvals/ApprovalWorkflowEditor.tsx
+++ b/src/pages/workspace/workflows/approvals/ApprovalWorkflowEditor.tsx
@@ -105,20 +105,19 @@ function ApprovalWorkflowEditor({approvalWorkflow, removeApprovalWorkflow, polic
         Navigation.navigate(ROUTES.WORKSPACE_WORKFLOWS_APPROVALS_EXPENSES_FROM.getRoute(policyID, backTo));
     }, [approvalWorkflow.action, policyID]);
 
+    const firstApprover = approvalWorkflow.approvers.at(0)?.email ?? '';
+
     const editApprover = useCallback(
         (approverIndex: number) => {
-            const approver = approvalWorkflow.approvers.at(approverIndex);
-            const backTo = approvalWorkflow.action === CONST.APPROVAL_WORKFLOW.ACTION.CREATE ? ROUTES.WORKSPACE_WORKFLOWS_APPROVALS_NEW.getRoute(policyID) : undefined;
-
-            // If the approver has an approval limit set, navigate to the approval limit page for editing
-            if (approver?.approvalLimit && approver?.overLimitForwardsTo) {
-                Navigation.navigate(ROUTES.WORKSPACE_WORKFLOWS_APPROVALS_APPROVAL_LIMIT.getRoute(policyID, approverIndex, backTo));
-                return;
+            if (approvalWorkflow.action === CONST.APPROVAL_WORKFLOW.ACTION.CREATE) {
+                Navigation.navigate(ROUTES.WORKSPACE_WORKFLOWS_APPROVALS_APPROVER.getRoute(policyID, approverIndex, ROUTES.WORKSPACE_WORKFLOWS_APPROVALS_NEW.getRoute(policyID)));
+            } else {
+                Navigation.navigate(
+                    ROUTES.WORKSPACE_WORKFLOWS_APPROVALS_APPROVAL_LIMIT.getRoute(policyID, approverIndex, ROUTES.WORKSPACE_WORKFLOWS_APPROVALS_EDIT.getRoute(policyID, firstApprover)),
+                );
             }
-
-            Navigation.navigate(ROUTES.WORKSPACE_WORKFLOWS_APPROVALS_APPROVER.getRoute(policyID, approverIndex, backTo));
         },
-        [approvalWorkflow.action, approvalWorkflow.approvers, policyID],
+        [approvalWorkflow.action, policyID, firstApprover],
     );
 
     // User should be allowed to add additional approver only if they upgraded to Control Plan, otherwise redirected to the Upgrade Page
diff --git a/src/pages/workspace/workflows/approvals/WorkspaceWorkflowsApprovalsApprovalLimitPage.tsx b/src/pages/workspace/workflows/approvals/WorkspaceWorkflowsApprovalsApprovalLimitPage.tsx
index c1e6a1f56714..f45638b5b4b5 100644
--- a/src/pages/workspace/workflows/approvals/WorkspaceWorkflowsApprovalsApprovalLimitPage.tsx
+++ b/src/pages/workspace/workflows/approvals/WorkspaceWorkflowsApprovalsApprovalLimitPage.tsx
@@ -6,6 +6,8 @@ import FullPageNotFoundView from '@components/BlockingViews/FullPageNotFoundView
 import Button from '@components/Button';
 import DotIndicatorMessage from '@components/DotIndicatorMessage';
 import HeaderWithBackButton from '@components/HeaderWithBackButton';
+import {Trashcan} from '@components/Icon/Expensicons';
+import MenuItem from '@components/MenuItem';
 import MenuItemWithTopDescription from '@components/MenuItemWithTopDescription';
 import RenderHTML from '@components/RenderHTML';
 import ScreenWrapper from '@components/ScreenWrapper';
@@ -70,11 +72,11 @@ function WorkspaceWorkflowsApprovalsApprovalLimitPage({policy, isLoadingReportDa
     }, [selectedApproverEmail, personalDetailsByEmail]);
 
     const isCircularReference = useMemo(() => {
-        if (!selectedApproverEmail || !approvalWorkflow?.approvers) {
+        if (!selectedApproverEmail || !currentApprover?.email) {
             return false;
         }
-        return approvalWorkflow.approvers.some((approver) => approver?.email === selectedApproverEmail);
-    }, [selectedApproverEmail, approvalWorkflow?.approvers]);
+        return currentApprover.email === selectedApproverEmail;
+    }, [selectedApproverEmail, currentApprover?.email]);
 
     // eslint-disable-next-line rulesdir/no-negated-variables
     const shouldShowNotFoundView = (isEmptyObject(policy) && !isLoadingReportData) || !isPolicyAdmin(policy) || isPendingDeletePolicy(policy);
@@ -86,25 +88,32 @@ function WorkspaceWorkflowsApprovalsApprovalLimitPage({policy, isLoadingReportDa
     const onlyAmountEmpty = !hasAmount && hasApprover;
     const onlyApproverEmpty = hasAmount && !hasApprover;
 
-    const bottomErrorMessage = hasSubmitted && bothEmpty ? translate('workflowsApprovalLimitPage.enterBothError') : '';
-    const amountErrorText = hasSubmitted && onlyAmountEmpty ? translate('workflowsApprovalLimitPage.enterAmountError') : undefined;
+    const approverDisplayName = currentApprover ? Str.removeSMSDomain(currentApprover.displayName) : '';
+    const isApproverSelected = isEditFlow ? approverDisplayName.length > 0 : true;
+    const areLimitFieldsDisabled = isEditFlow && !isApproverSelected;
+    const shouldShowRemoveLimitRow = isEditFlow && (hasAmount || hasApprover);
+
+    // In edit mode, user can save with both empty (removes limit). In create mode, show error on submit.
+    const bottomErrorMessage = hasSubmitted && bothEmpty && !isEditFlow ? translate('workflowsApprovalLimitPage.enterBothError') : '';
+    const amountErrorText = onlyAmountEmpty ? translate('workflowsApprovalLimitPage.enterAmountError') : undefined;
     const approverErrorText = useMemo(() => {
         if (isCircularReference) {
             return translate('workflowsApprovalLimitPage.circularReferenceError', {approverName: selectedApproverDisplayName});
         }
-        if (hasSubmitted && onlyApproverEmpty) {
+        if (onlyApproverEmpty) {
             return translate('workflowsApprovalLimitPage.enterApproverError');
         }
         return undefined;
-    }, [hasSubmitted, onlyApproverEmpty, isCircularReference, selectedApproverDisplayName, translate]);
+    }, [onlyApproverEmpty, isCircularReference, selectedApproverDisplayName, translate]);
 
     const handleSkip = useCallback(() => {
-        // Clear any existing approval limit when skipping
-        if (approvalWorkflow && currentApprover && (currentApprover.approvalLimit || currentApprover.overLimitForwardsTo)) {
+        setApprovalLimit('');
+
+        if (approvalWorkflow && currentApprover) {
             setApprovalWorkflowApprover({
                 approver: {
                     ...currentApprover,
-                    approvalLimit: undefined,
+                    approvalLimit: null,
                     overLimitForwardsTo: '',
                 },
                 approverIndex,
@@ -124,11 +133,25 @@ function WorkspaceWorkflowsApprovalsApprovalLimitPage({policy, isLoadingReportDa
     const handleNext = useCallback(() => {
         setHasSubmitted(true);
 
-        if (!hasAmount || !hasApprover || isCircularReference) {
+        const hasValidationError = isCircularReference || onlyAmountEmpty || onlyApproverEmpty || (!isEditFlow && bothEmpty);
+        if (hasValidationError || !approvalWorkflow || !currentApprover) {
             return;
         }
 
-        if (!approvalWorkflow || !currentApprover) {
+        // In edit mode with both empty, clear the limit (same as Remove limit)
+        if (isEditFlow && bothEmpty) {
+            setApprovalWorkflowApprover({
+                approver: {
+                    ...currentApprover,
+                    approvalLimit: null,
+                    overLimitForwardsTo: '',
+                },
+                approverIndex,
+                currentApprovalWorkflow: approvalWorkflow,
+                policy,
+                personalDetailsByEmail,
+            });
+            Navigation.goBack(backTo);
             return;
         }
 
@@ -151,10 +174,24 @@ function WorkspaceWorkflowsApprovalsApprovalLimitPage({policy, isLoadingReportDa
         } else {
             Navigation.navigate(ROUTES.WORKSPACE_WORKFLOWS_APPROVALS_NEW.getRoute(policyID));
         }
-    }, [approvalLimit, selectedApproverEmail, isCircularReference, approvalWorkflow, currentApprover, approverIndex, policy, personalDetailsByEmail, isEditFlow, backTo, policyID]);
+    }, [
+        approvalLimit,
+        selectedApproverEmail,
+        isCircularReference,
+        onlyAmountEmpty,
+        onlyApproverEmpty,
+        bothEmpty,
+        isEditFlow,
+        approvalWorkflow,
+        currentApprover,
+        approverIndex,
+        policy,
+        personalDetailsByEmail,
+        backTo,
+        policyID,
+    ]);
 
     const navigateToApproverSelector = useCallback(() => {
-        // Save the current amount to Onyx before navigating so it persists when we come back
         if (approvalWorkflow && currentApprover && approvalLimit) {
             const limitInCents = convertToBackendAmount(Number.parseFloat(approvalLimit));
             setApprovalWorkflowApprover({
@@ -168,12 +205,28 @@ function WorkspaceWorkflowsApprovalsApprovalLimitPage({policy, isLoadingReportDa
                 personalDetailsByEmail,
             });
         }
-        Navigation.navigate(ROUTES.WORKSPACE_WORKFLOWS_APPROVALS_OVER_LIMIT_APPROVER.getRoute(policyID, approverIndex));
-    }, [policyID, approverIndex, approvalWorkflow, currentApprover, approvalLimit, policy, personalDetailsByEmail]);
+        Navigation.navigate(ROUTES.WORKSPACE_WORKFLOWS_APPROVALS_OVER_LIMIT_APPROVER.getRoute(policyID, approverIndex, backTo));
+    }, [policyID, approverIndex, approvalWorkflow, currentApprover, approvalLimit, policy, personalDetailsByEmail, backTo]);
 
-    const buttonContainerStyle = useBottomSafeSafeAreaPaddingStyle({addBottomSafeAreaPadding: true, style: [styles.mh5, styles.mb5]});
+    const navigateToApproverChange = useCallback(() => {
+        if (approvalWorkflow && currentApprover) {
+            const limitInCents = approvalLimit ? convertToBackendAmount(Number.parseFloat(approvalLimit)) : currentApprover.approvalLimit;
+            setApprovalWorkflowApprover({
+                approver: {
+                    ...currentApprover,
+                    approvalLimit: limitInCents,
+                    overLimitForwardsTo: selectedApproverEmail || currentApprover.overLimitForwardsTo,
+                },
+                approverIndex,
+                currentApprovalWorkflow: approvalWorkflow,
+                policy,
+                personalDetailsByEmail,
+            });
+        }
+        Navigation.navigate(ROUTES.WORKSPACE_WORKFLOWS_APPROVALS_APPROVER.getRoute(policyID, approverIndex, backTo));
+    }, [policyID, approverIndex, backTo, approvalWorkflow, currentApprover, approvalLimit, selectedApproverEmail, policy, personalDetailsByEmail]);
 
-    const approverDisplayName = currentApprover ? Str.removeSMSDomain(currentApprover.displayName) : '';
+    const buttonContainerStyle = useBottomSafeSafeAreaPaddingStyle({addBottomSafeAreaPadding: true, style: [styles.mh5, styles.mb5]});
 
     return (
         <AccessOrNotFoundWrapper
@@ -192,18 +245,37 @@ function WorkspaceWorkflowsApprovalsApprovalLimitPage({policy, isLoadingReportDa
                     addBottomSafeAreaPadding
                 >
                     <HeaderWithBackButton
-                        title={translate('workflowsApprovalLimitPage.title')}
-                        onBackButtonPress={() => Navigation.goBack(ROUTES.WORKSPACE_WORKFLOWS_APPROVALS_APPROVER.getRoute(policyID, approverIndex))}
+                        title={isEditFlow ? translate('workflowsPage.approver') : translate('workflowsApprovalLimitPage.title')}
+                        onBackButtonPress={() => Navigation.goBack(backTo)}
                     />
                     <ScrollView
                         style={styles.flex1}
                         contentContainerStyle={styles.flexGrow1}
                     >
                         <View style={[styles.mh5, styles.flex1]}>
-                            <Text style={[styles.textHeadlineH1, styles.mv3]}>{translate('workflowsApprovalLimitPage.header')}</Text>
-                            <View style={styles.mb5}>
-                                <RenderHTML html={translate('workflowsApprovalLimitPage.description', {approverName: approverDisplayName})} />
-                            </View>
+                            {isEditFlow ? (
+                                <>
+                                    <MenuItemWithTopDescription
+                                        title={approverDisplayName}
+                                        titleStyle={styles.textNormalThemeText}
+                                        description={translate('workflowsPage.approver')}
+                                        descriptionTextStyle={approverDisplayName ? styles.textLabelSupportingNormal : undefined}
+                                        onPress={navigateToApproverChange}
+                                        shouldShowRightIcon
+                                        wrapperStyle={styles.sectionMenuItemTopDescription}
+                                    />
+                                    <View style={[styles.mt3, styles.mb5]}>
+                                        <RenderHTML html={translate('workflowsApprovalLimitPage.description', {approverName: approverDisplayName})} />
+                                    </View>
+                                </>
+                            ) : (
+                                <>
+                                    <Text style={[styles.textHeadlineH1, styles.mv3]}>{translate('workflowsApprovalLimitPage.header')}</Text>
+                                    <View style={styles.mb5}>
+                                        <RenderHTML html={translate('workflowsApprovalLimitPage.description', {approverName: approverDisplayName})} />
+                                    </View>
+                                </>
+                            )}
 
                             <View style={styles.mb4}>
                                 <AmountForm
@@ -214,6 +286,7 @@ function WorkspaceWorkflowsApprovalsApprovalLimitPage({policy, isLoadingReportDa
                                     isCurrencyPressable={false}
                                     displayAsTextInput
                                     errorText={amountErrorText}
+                                    disabled={areLimitFieldsDisabled}
                                 />
                             </View>
 
@@ -228,7 +301,18 @@ function WorkspaceWorkflowsApprovalsApprovalLimitPage({policy, isLoadingReportDa
                                 brickRoadIndicator={approverErrorText ? CONST.BRICK_ROAD_INDICATOR_STATUS.ERROR : undefined}
                                 errorText={approverErrorText}
                                 shouldRenderErrorAsHTML
+                                disabled={areLimitFieldsDisabled}
+                                shouldGreyOutWhenDisabled
                             />
+
+                            {shouldShowRemoveLimitRow && (
+                                <MenuItem
+                                    title={translate('workflowsApprovalLimitPage.removeLimit')}
+                                    icon={Trashcan}
+                                    onPress={handleSkip}
+                                    wrapperStyle={styles.sectionMenuItemTopDescription}
+                                />
+                            )}
                         </View>
 
                         {!!bottomErrorMessage && (
@@ -241,16 +325,18 @@ function WorkspaceWorkflowsApprovalsApprovalLimitPage({policy, isLoadingReportDa
                     </ScrollView>
 
                     <View style={buttonContainerStyle}>
-                        <Button
-                            large
-                            text={translate('workflowsApprovalLimitPage.skip')}
-                            onPress={handleSkip}
-                            style={styles.mb3}
-                        />
+                        {!isEditFlow && (
+                            <Button
+                                large
+                                text={translate('workflowsApprovalLimitPage.skip')}
+                                onPress={handleSkip}
+                                style={styles.mb3}
+                            />
+                        )}
                         <Button
                             large
                             success
-                            text={translate('workflowsApprovalLimitPage.next')}
+                            text={isEditFlow ? translate('common.save') : translate('workflowsApprovalLimitPage.next')}
                             onPress={handleNext}
                         />
                     </View>
diff --git a/src/pages/workspace/workflows/approvals/WorkspaceWorkflowsApprovalsApproverPage.tsx b/src/pages/workspace/workflows/approvals/WorkspaceWorkflowsApprovalsApproverPage.tsx
index b78753160d16..aa4712a22b96 100644
--- a/src/pages/workspace/workflows/approvals/WorkspaceWorkflowsApprovalsApproverPage.tsx
+++ b/src/pages/workspace/workflows/approvals/WorkspaceWorkflowsApprovalsApproverPage.tsx
@@ -140,46 +140,54 @@ function WorkspaceWorkflowsApprovalsApproverPage({policy, personalDetails, isLoa
     const toggleApprover = useCallback(
         (approvers: SelectionListApprover[]) => {
             const approver = approvers.at(0);
-            if (selectedApproverEmail === approver?.login) {
+            const isRemovingApprover = approvers.length === 0;
+
+            if (isRemovingApprover) {
                 clearApprovalWorkflowApprover({approverIndex, currentApprovalWorkflow});
-            } else {
-                const newSelectedEmail = approver?.login ?? '';
-                const policyMemberEmailsToAccountIDs = getMemberAccountIDsForWorkspace(employeeList);
-                const accountID = Number(newSelectedEmail ? policyMemberEmailsToAccountIDs[newSelectedEmail] : '');
-                const {avatar, displayName = newSelectedEmail} = personalDetails?.[accountID] ?? {};
-                setApprovalWorkflowApprover({
-                    approver: {
-                        email: newSelectedEmail,
-                        avatar,
-                        displayName,
-                    },
-                    approverIndex,
-                    currentApprovalWorkflow,
-                    policy,
-                    personalDetailsByEmail,
-                });
+                goBack();
+                return;
             }
 
-            const isRemovingApprover = selectedApproverEmail === approver?.login;
-            if (isInitialCreationFlow) {
-                // Navigate to approval limit page to optionally set a limit, or back to create page if removing
-                if (isRemovingApprover) {
-                    Navigation.navigate(ROUTES.WORKSPACE_WORKFLOWS_APPROVALS_NEW.getRoute(route.params.policyID));
-                } else {
-                    Navigation.navigate(ROUTES.WORKSPACE_WORKFLOWS_APPROVALS_APPROVAL_LIMIT.getRoute(route.params.policyID, approverIndex));
-                }
-            } else {
+            const newSelectedEmail = approver?.login ?? '';
+            const policyMemberEmailsToAccountIDs = getMemberAccountIDsForWorkspace(employeeList);
+            const accountID = Number(newSelectedEmail ? policyMemberEmailsToAccountIDs[newSelectedEmail] : '');
+            const {avatar, displayName = newSelectedEmail} = personalDetails?.[accountID] ?? {};
+            const existingApprover = currentApprovalWorkflow?.approvers?.[approverIndex];
+
+            setApprovalWorkflowApprover({
+                approver: {
+                    email: newSelectedEmail,
+                    avatar,
+                    displayName,
+                    approvalLimit: existingApprover?.approvalLimit,
+                    overLimitForwardsTo: existingApprover?.overLimitForwardsTo,
+                },
+                approverIndex,
+                currentApprovalWorkflow,
+                policy,
+                personalDetailsByEmail,
+            });
+
+            if (approvalWorkflow?.action === CONST.APPROVAL_WORKFLOW.ACTION.EDIT) {
                 goBack();
+                return;
             }
+
+            Navigation.navigate(
+                ROUTES.WORKSPACE_WORKFLOWS_APPROVALS_APPROVAL_LIMIT.getRoute(route.params.policyID, approverIndex, ROUTES.WORKSPACE_WORKFLOWS_APPROVALS_NEW.getRoute(route.params.policyID)),
+            );
         },
-        [selectedApproverEmail, isInitialCreationFlow, approverIndex, currentApprovalWorkflow, employeeList, personalDetails, policy, route.params.policyID, goBack, personalDetailsByEmail],
+        [approverIndex, currentApprovalWorkflow, employeeList, personalDetails, policy, route.params.policyID, goBack, personalDetailsByEmail, approvalWorkflow?.action],
     );
 
     const subtitle = useMemo(
-        () =>
-            approvalWorkflow?.action === CONST.APPROVAL_WORKFLOW.ACTION.CREATE &&
-            !shouldShowListEmptyContent && <Text style={[styles.textHeadlineH1, styles.mh5, styles.mv3]}>{translate('workflowsApproverPage.header')}</Text>,
-        [approvalWorkflow?.action, shouldShowListEmptyContent, translate, styles.textHeadlineH1, styles.mh5, styles.mv3],
+        () => (
+            <>
+                <Text style={[styles.textHeadlineH1, styles.mh5, styles.mv3]}>{translate('workflowsApproverPage.title')}</Text>
+                <Text style={[styles.mh5, styles.mb3, styles.textSupporting]}>{translate('workflowsApproverPage.description')}</Text>
+            </>
+        ),
+        [translate, styles.textHeadlineH1, styles.mh5, styles.mv3, styles.mb3, styles.textSupporting],
     );
 
     return (
diff --git a/src/pages/workspace/workflows/approvals/WorkspaceWorkflowsApprovalsEditPage.tsx b/src/pages/workspace/workflows/approvals/WorkspaceWorkflowsApprovalsEditPage.tsx
index f21b0b381b33..f874f81ea58b 100644
--- a/src/pages/workspace/workflows/approvals/WorkspaceWorkflowsApprovalsEditPage.tsx
+++ b/src/pages/workspace/workflows/approvals/WorkspaceWorkflowsApprovalsEditPage.tsx
@@ -39,6 +39,7 @@ function WorkspaceWorkflowsApprovalsEditPage({policy, isLoadingReportData = true
     const [initialApprovalWorkflow, setInitialApprovalWorkflow] = useState<ApprovalWorkflow | undefined>();
     const [isDeleteModalVisible, setIsDeleteModalVisible] = useState(false);
     const formRef = useRef<ScrollView>(null);
+    const isDeleting = useRef(false);
 
     const updateApprovalWorkflowCallback = useCallback(() => {
         if (!approvalWorkflow || !initialApprovalWorkflow) {
@@ -64,6 +65,8 @@ function WorkspaceWorkflowsApprovalsEditPage({policy, isLoadingReportData = true
             return;
         }
 
+        // Mark as deleting to prevent the useEffect from clearing the workflow and causing a blink
+        isDeleting.current = true;
         setIsDeleteModalVisible(false);
         Navigation.dismissModal();
         // eslint-disable-next-line @typescript-eslint/no-deprecated
@@ -103,6 +106,10 @@ function WorkspaceWorkflowsApprovalsEditPage({policy, isLoadingReportData = true
         }
 
         if (!currentApprovalWorkflow) {
+            // Don't clear if we're in the middle of deleting - this prevents the UI from blinking
+            if (isDeleting.current) {
+                return;
+            }
             return clearApprovalWorkflow();
         }
 
diff --git a/src/pages/workspace/workflows/approvals/WorkspaceWorkflowsApprovalsOverLimitApproverPage.tsx b/src/pages/workspace/workflows/approvals/WorkspaceWorkflowsApprovalsOverLimitApproverPage.tsx
index b436b86f1ec1..917cec4dc1e7 100644
--- a/src/pages/workspace/workflows/approvals/WorkspaceWorkflowsApprovalsOverLimitApproverPage.tsx
+++ b/src/pages/workspace/workflows/approvals/WorkspaceWorkflowsApprovalsOverLimitApproverPage.tsx
@@ -38,6 +38,7 @@ function WorkspaceWorkflowsApprovalsOverLimitApproverPage({policy, personalDetai
 
     const policyID = route.params.policyID;
     const approverIndex = Number(route.params.approverIndex) ?? 0;
+    const backTo = route.params?.backTo;
     const currentApprover = approvalWorkflow?.approvers?.[approverIndex];
 
     const employeeList = policy?.employeeList;
@@ -81,13 +82,34 @@ function WorkspaceWorkflowsApprovalsOverLimitApproverPage({policy, personalDetai
     const shouldShowListEmptyContent = !!approvalWorkflow && !isApprovalWorkflowLoading;
 
     const goBack = useCallback(() => {
-        Navigation.goBack(ROUTES.WORKSPACE_WORKFLOWS_APPROVALS_APPROVAL_LIMIT.getRoute(policyID, approverIndex));
-    }, [policyID, approverIndex]);
+        Navigation.goBack(ROUTES.WORKSPACE_WORKFLOWS_APPROVALS_APPROVAL_LIMIT.getRoute(policyID, approverIndex, backTo));
+    }, [policyID, approverIndex, backTo]);
 
     const selectApprover = useCallback(
         (approvers: SelectionListApprover[]) => {
             const selectedApprover = approvers.at(0);
-            if (!selectedApprover?.login || !approvalWorkflow || !currentApprover) {
+
+            if (!approvalWorkflow || !currentApprover) {
+                return;
+            }
+
+            // If empty array, the same approver was tapped again to unselect
+            if (approvers.length === 0) {
+                setApprovalWorkflowApprover({
+                    approver: {
+                        ...currentApprover,
+                        overLimitForwardsTo: '',
+                    },
+                    approverIndex,
+                    currentApprovalWorkflow: approvalWorkflow,
+                    policy,
+                    personalDetailsByEmail,
+                });
+                goBack();
+                return;
+            }
+
+            if (!selectedApprover?.login) {
                 return;
             }
 
diff --git a/src/styles/index.ts b/src/styles/index.ts
index ffeb578b3192..3d4e2d322be6 100644
--- a/src/styles/index.ts
+++ b/src/styles/index.ts
@@ -5188,6 +5188,10 @@ const staticStyles = (theme: ThemeColors) =>
             backgroundColor: theme.border,
         },
 
+        workflowApprovalLimitText: {
+            marginLeft: variables.componentSizeNormal + 12,
+        },
+
         integrationIcon: {
             overflow: 'hidden',
             borderRadius: variables.buttonBorderRadius,
diff --git a/src/types/onyx/ApprovalWorkflow.ts b/src/types/onyx/ApprovalWorkflow.ts
index baceaacee16f..b5c6d84728ca 100644
--- a/src/types/onyx/ApprovalWorkflow.ts
+++ b/src/types/onyx/ApprovalWorkflow.ts
@@ -39,7 +39,7 @@ type Approver = {
     /**
      * If report total is above this limit, the report will be forwarded to 'overLimitForwardsTo' instead of 'forwardsTo'
      */
-    approvalLimit?: number;
+    approvalLimit?: number | null;
 
     /**
      * Email of the user this user forwards all approved reports to when report total is above 'approvalLimit'
diff --git a/src/types/onyx/PolicyEmployee.ts b/src/types/onyx/PolicyEmployee.ts
index 3ba9633fee44..fd16fc684126 100644
--- a/src/types/onyx/PolicyEmployee.ts
+++ b/src/types/onyx/PolicyEmployee.ts
@@ -18,8 +18,8 @@ type PolicyEmployee = OnyxCommon.OnyxValueWithOfflineFeedback<{
     /** Email of the user */
     email?: string;
 
-    /** Determines if this employee should approve a report. If report total > approvalLimit, next approver will be 'overLimitForwardsTo', otherwise 'forwardsTo' */
-    approvalLimit?: number;
+    /** Determines if this employee should approve a report. If report total > approvalLimit, next approver will be 'overLimitForwardsTo', otherwise 'forwardsTo'. Set to null to clear. */
+    approvalLimit?: number | null;
 
     /** Email of the user this user forwards all approved reports to (when report total under 'approvalLimit' or when 'overLimitForwardsTo' is not set) */
     forwardsTo?: string;

From 8ddb742947cdc49279e1400634c3dac449ad3d65 Mon Sep 17 00:00:00 2001
From: Abdelrahman Khattab <abzokhattab@gmail.com>
Date: Tue, 2 Dec 2025 15:23:54 +0100
Subject: [PATCH 10/49] fixing eslint

---
 src/libs/actions/Workflow.ts | 5 +++--
 1 file changed, 3 insertions(+), 2 deletions(-)

diff --git a/src/libs/actions/Workflow.ts b/src/libs/actions/Workflow.ts
index 8ffb24e0a9f4..9378513b59b4 100644
--- a/src/libs/actions/Workflow.ts
+++ b/src/libs/actions/Workflow.ts
@@ -231,9 +231,10 @@ function setApprovalWorkflowApprover({approver, approverIndex, currentApprovalWo
 
         // Preserve the new approvalLimit and overLimitForwardsTo values that were passed in,
         // since calculateApprovers reads from stale policy data
-        if (approvers[approverIndex]) {
+        const existingApprover = approvers.at(approverIndex);
+        if (existingApprover) {
             approvers[approverIndex] = {
-                ...approvers[approverIndex],
+                ...existingApprover,
                 approvalLimit: approver.approvalLimit,
                 overLimitForwardsTo: approver.overLimitForwardsTo,
             };

From 00a9d4f056583f0a55d33dff768b12c42de840e3 Mon Sep 17 00:00:00 2001
From: Abdelrahman Khattab <abzokhattab@gmail.com>
Date: Tue, 2 Dec 2025 15:39:00 +0100
Subject: [PATCH 11/49] fixing tests

---
 tests/unit/WorkflowUtilsTest.ts | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/tests/unit/WorkflowUtilsTest.ts b/tests/unit/WorkflowUtilsTest.ts
index 4a245f08e11b..f7a647fe7612 100644
--- a/tests/unit/WorkflowUtilsTest.ts
+++ b/tests/unit/WorkflowUtilsTest.ts
@@ -33,6 +33,8 @@ function buildApprover(accountID: number, approver: Partial<Approver> = {}): App
         avatar: 'https://d2k5nsl2zxldvw.cloudfront.net/images/avatars/avatar_7.png',
         displayName: `${accountID}@example.com User`,
         isCircularReference: false,
+        approvalLimit: undefined,
+        overLimitForwardsTo: undefined,
         ...approver,
     };
 }

From 09f7b3ef2d47416ba139994b0947e2577e152684 Mon Sep 17 00:00:00 2001
From: Abdelrahman Khattab <abzokhattab@gmail.com>
Date: Tue, 2 Dec 2025 16:05:54 +0100
Subject: [PATCH 12/49] fixing tests

---
 ios/Podfile.lock                | 22 ++++------------------
 tests/unit/WorkflowUtilsTest.ts | 16 +++++++---------
 2 files changed, 11 insertions(+), 27 deletions(-)

diff --git a/ios/Podfile.lock b/ios/Podfile.lock
index 57f5c67f64a1..e310992e763f 100644
--- a/ios/Podfile.lock
+++ b/ios/Podfile.lock
@@ -524,7 +524,6 @@ PODS:
     - React-jsinspectorcdp
     - React-jsitooling
     - React-perflogger
-    - React-rendererconsistency
     - React-runtimeexecutor
     - React-runtimescheduler
     - React-utils
@@ -550,7 +549,6 @@ PODS:
     - React-jsinspectorcdp
     - React-jsitooling
     - React-perflogger
-    - React-rendererconsistency
     - React-runtimeexecutor
     - React-runtimescheduler
     - React-utils
@@ -575,7 +573,6 @@ PODS:
     - React-jsinspectorcdp
     - React-jsitooling
     - React-perflogger
-    - React-rendererconsistency
     - React-runtimeexecutor
     - React-runtimescheduler
     - React-utils
@@ -602,7 +599,6 @@ PODS:
     - React-jsinspectorcdp
     - React-jsitooling
     - React-perflogger
-    - React-rendererconsistency
     - React-runtimeexecutor
     - React-runtimescheduler
     - React-utils
@@ -628,7 +624,6 @@ PODS:
     - React-jsinspectorcdp
     - React-jsitooling
     - React-perflogger
-    - React-rendererconsistency
     - React-runtimeexecutor
     - React-runtimescheduler
     - React-utils
@@ -654,7 +649,6 @@ PODS:
     - React-jsinspectorcdp
     - React-jsitooling
     - React-perflogger
-    - React-rendererconsistency
     - React-runtimeexecutor
     - React-runtimescheduler
     - React-utils
@@ -680,7 +674,6 @@ PODS:
     - React-jsinspectorcdp
     - React-jsitooling
     - React-perflogger
-    - React-rendererconsistency
     - React-runtimeexecutor
     - React-runtimescheduler
     - React-utils
@@ -706,7 +699,6 @@ PODS:
     - React-jsinspectorcdp
     - React-jsitooling
     - React-perflogger
-    - React-rendererconsistency
     - React-runtimeexecutor
     - React-runtimescheduler
     - React-utils
@@ -732,7 +724,6 @@ PODS:
     - React-jsinspectorcdp
     - React-jsitooling
     - React-perflogger
-    - React-rendererconsistency
     - React-runtimeexecutor
     - React-runtimescheduler
     - React-utils
@@ -758,7 +749,6 @@ PODS:
     - React-jsinspectorcdp
     - React-jsitooling
     - React-perflogger
-    - React-rendererconsistency
     - React-runtimeexecutor
     - React-runtimescheduler
     - React-utils
@@ -784,7 +774,6 @@ PODS:
     - React-jsinspectorcdp
     - React-jsitooling
     - React-perflogger
-    - React-rendererconsistency
     - React-runtimeexecutor
     - React-runtimescheduler
     - React-utils
@@ -810,7 +799,6 @@ PODS:
     - React-jsinspectorcdp
     - React-jsitooling
     - React-perflogger
-    - React-rendererconsistency
     - React-runtimeexecutor
     - React-runtimescheduler
     - React-utils
@@ -836,7 +824,6 @@ PODS:
     - React-jsinspectorcdp
     - React-jsitooling
     - React-perflogger
-    - React-rendererconsistency
     - React-runtimeexecutor
     - React-runtimescheduler
     - React-utils
@@ -862,7 +849,6 @@ PODS:
     - React-jsinspectorcdp
     - React-jsitooling
     - React-perflogger
-    - React-rendererconsistency
     - React-runtimeexecutor
     - React-runtimescheduler
     - React-utils
@@ -4646,7 +4632,7 @@ SPEC CHECKSUMS:
   AirshipServiceExtension: 50d11b2f62c4a490d4e81a1c36f70e2ecb70a27e
   AppAuth: d4f13a8fe0baf391b2108511793e4b479691fb73
   AppLogs: 3bc4e9b141dbf265b9464409caaa40416a9ee0e0
-  boost: 659a89341ea4ab3df8259733813b52f26d8be9a5
+  boost: 7e761d76ca2ce687f7cc98e698152abd03a18f90
   DoubleConversion: cb417026b2400c8f53ae97020b2be961b59470cb
   EXAV: ae28256069c4cdde93d185c007d8f68d92902c2e
   EXConstants: a95804601ee4a6aa7800645f9b070d753b1142b3
@@ -4715,7 +4701,7 @@ SPEC CHECKSUMS:
   React: 2073376f47c71b7e9a0af7535986a77522ce1049
   React-callinvoker: 751b6f2c83347a0486391c3f266f291f0f53b27e
   React-Codegen: 4b8b4817cea7a54b83851d4c1f91f79aa73de30a
-  React-Core: aeebd9b37ac383279f610f1e53f66b9931686a41
+  React-Core: dff5d29973349b11dd6631c9498456d75f846d5e
   React-CoreModules: c0ae04452e4c5d30e06f8e94692a49107657f537
   React-cxxreact: 376fd672c95dfb64ad5cc246e6a1e9edb78dec4c
   React-debug: d4955c86870792887ed695df6ebf0e94e39dc7e1
@@ -4767,7 +4753,7 @@ SPEC CHECKSUMS:
   react-native-webview: cdce419e8022d0ef6f07db21890631258e7a9e6e
   React-NativeModulesApple: 8c7eb6057b00c191a11ad5ced41826ec5a0e4d78
   React-oscompat: 93b5535ea7f7dff46aaee4f78309a70979bdde9d
-  React-perflogger: e7dcbfcb796d346be7936b75740c3e27a4bb3977
+  React-perflogger: 5536d2df3d18fe0920263466f7b46a56351c0510
   React-performancetimeline: c6c9393c1a0453a51e1852e3531defe60790b36c
   React-RCTActionSheet: 42195ae666e6d79b4af2346770f765b7c29435b9
   React-RCTAnimation: fa103ccc3503b1ed8dedca7e62e7823937748843
@@ -4782,7 +4768,7 @@ SPEC CHECKSUMS:
   React-RCTSettings: 71f5c7fd7b5f4e725a4e2114a4b4373d0e46048f
   React-RCTText: b94d4699b49285bee22b8ebf768924d607eccee3
   React-RCTVibration: 6e3993c4f6c36a3899059f9a9ead560ddaf5a7d7
-  React-rendererconsistency: bef28690433e2b4bb00c2f884b22b86e61a430f2
+  React-rendererconsistency: 612d0f6603d9837bb1236d7fd5194203b35c8799
   React-renderercss: e5c2c3b84976f7a587cde8423c671db07a6a77da
   React-rendererdebug: cc7a6131733605b8897754f72c0c35c79f77da9e
   React-RuntimeApple: 3f96102fc1ebf738d36719cdce5422a5769293fb
diff --git a/tests/unit/WorkflowUtilsTest.ts b/tests/unit/WorkflowUtilsTest.ts
index f7a647fe7612..d17683c78c0f 100644
--- a/tests/unit/WorkflowUtilsTest.ts
+++ b/tests/unit/WorkflowUtilsTest.ts
@@ -33,8 +33,6 @@ function buildApprover(accountID: number, approver: Partial<Approver> = {}): App
         avatar: 'https://d2k5nsl2zxldvw.cloudfront.net/images/avatars/avatar_7.png',
         displayName: `${accountID}@example.com User`,
         isCircularReference: false,
-        approvalLimit: undefined,
-        overLimitForwardsTo: undefined,
         ...approver,
     };
 }
@@ -433,7 +431,7 @@ describe('WorkflowUtils', () => {
             const convertedEmployees = WorkflowUtils.convertApprovalWorkflowToPolicyEmployees({previousEmployeeList: {}, approvalWorkflow, type: 'create'});
 
             expect(convertedEmployees).toEqual({
-                '1@example.com': buildPolicyEmployee(1, {forwardsTo: '', submitsTo: '1@example.com', pendingFields: {submitsTo: 'add'}}),
+                '1@example.com': buildPolicyEmployee(1, {forwardsTo: '', overLimitForwardsTo: '', submitsTo: '1@example.com', pendingFields: {submitsTo: 'add'}}),
                 '2@example.com': buildPolicyEmployee(2, {submitsTo: '1@example.com', pendingFields: {submitsTo: 'add'}}),
             });
         });
@@ -448,9 +446,9 @@ describe('WorkflowUtils', () => {
             const convertedEmployees = WorkflowUtils.convertApprovalWorkflowToPolicyEmployees({previousEmployeeList: {}, approvalWorkflow, type: 'create'});
 
             expect(convertedEmployees).toEqual({
-                '1@example.com': buildPolicyEmployee(1, {forwardsTo: '2@example.com', pendingFields: {forwardsTo: 'add'}}),
-                '2@example.com': buildPolicyEmployee(2, {forwardsTo: '3@example.com', pendingFields: {forwardsTo: 'add'}}),
-                '3@example.com': buildPolicyEmployee(3, {forwardsTo: '', pendingFields: {forwardsTo: 'add'}}),
+                '1@example.com': buildPolicyEmployee(1, {forwardsTo: '2@example.com', overLimitForwardsTo: '', pendingFields: {forwardsTo: 'add'}}),
+                '2@example.com': buildPolicyEmployee(2, {forwardsTo: '3@example.com', overLimitForwardsTo: '', pendingFields: {forwardsTo: 'add'}}),
+                '3@example.com': buildPolicyEmployee(3, {forwardsTo: '', overLimitForwardsTo: '', pendingFields: {forwardsTo: 'add'}}),
                 '4@example.com': buildPolicyEmployee(4, {submitsTo: '1@example.com', pendingFields: {submitsTo: 'add'}}),
                 '5@example.com': buildPolicyEmployee(5, {submitsTo: '1@example.com', pendingFields: {submitsTo: 'add'}}),
                 '6@example.com': buildPolicyEmployee(6, {submitsTo: '1@example.com', pendingFields: {submitsTo: 'add'}}),
@@ -467,9 +465,9 @@ describe('WorkflowUtils', () => {
             const convertedEmployees = WorkflowUtils.convertApprovalWorkflowToPolicyEmployees({previousEmployeeList: {}, approvalWorkflow, type: 'remove'});
 
             expect(convertedEmployees).toEqual({
-                '1@example.com': buildPolicyEmployee(1, {forwardsTo: '', pendingAction: 'update', pendingFields: {forwardsTo: 'update'}}),
-                '2@example.com': buildPolicyEmployee(2, {forwardsTo: '', pendingAction: 'update', pendingFields: {forwardsTo: 'update'}}),
-                '3@example.com': buildPolicyEmployee(3, {forwardsTo: '', pendingAction: 'update', pendingFields: {forwardsTo: 'update'}}),
+                '1@example.com': buildPolicyEmployee(1, {forwardsTo: '', overLimitForwardsTo: '', pendingAction: 'update', pendingFields: {forwardsTo: 'update'}}),
+                '2@example.com': buildPolicyEmployee(2, {forwardsTo: '', overLimitForwardsTo: '', pendingAction: 'update', pendingFields: {forwardsTo: 'update'}}),
+                '3@example.com': buildPolicyEmployee(3, {forwardsTo: '', overLimitForwardsTo: '', pendingAction: 'update', pendingFields: {forwardsTo: 'update'}}),
                 '4@example.com': buildPolicyEmployee(4, {submitsTo: '', pendingAction: 'update', pendingFields: {submitsTo: 'update'}}),
                 '5@example.com': buildPolicyEmployee(5, {submitsTo: '', pendingAction: 'update', pendingFields: {submitsTo: 'update'}}),
                 '6@example.com': buildPolicyEmployee(6, {submitsTo: '', pendingAction: 'update', pendingFields: {submitsTo: 'update'}}),

From 4067eb230298bb00654a83b8988e01ad5bdd2952 Mon Sep 17 00:00:00 2001
From: Abdelrahman Khattab <abzokhattab@gmail.com>
Date: Tue, 2 Dec 2025 16:08:07 +0100
Subject: [PATCH 13/49] revert podfile.lock

---
 ios/Podfile.lock | 24 +++++++++++++++++++-----
 1 file changed, 19 insertions(+), 5 deletions(-)

diff --git a/ios/Podfile.lock b/ios/Podfile.lock
index e310992e763f..fe6a3764e75a 100644
--- a/ios/Podfile.lock
+++ b/ios/Podfile.lock
@@ -524,6 +524,7 @@ PODS:
     - React-jsinspectorcdp
     - React-jsitooling
     - React-perflogger
+    - React-rendererconsistency
     - React-runtimeexecutor
     - React-runtimescheduler
     - React-utils
@@ -549,6 +550,7 @@ PODS:
     - React-jsinspectorcdp
     - React-jsitooling
     - React-perflogger
+    - React-rendererconsistency
     - React-runtimeexecutor
     - React-runtimescheduler
     - React-utils
@@ -573,6 +575,7 @@ PODS:
     - React-jsinspectorcdp
     - React-jsitooling
     - React-perflogger
+    - React-rendererconsistency
     - React-runtimeexecutor
     - React-runtimescheduler
     - React-utils
@@ -599,6 +602,7 @@ PODS:
     - React-jsinspectorcdp
     - React-jsitooling
     - React-perflogger
+    - React-rendererconsistency
     - React-runtimeexecutor
     - React-runtimescheduler
     - React-utils
@@ -624,6 +628,7 @@ PODS:
     - React-jsinspectorcdp
     - React-jsitooling
     - React-perflogger
+    - React-rendererconsistency
     - React-runtimeexecutor
     - React-runtimescheduler
     - React-utils
@@ -649,6 +654,7 @@ PODS:
     - React-jsinspectorcdp
     - React-jsitooling
     - React-perflogger
+    - React-rendererconsistency
     - React-runtimeexecutor
     - React-runtimescheduler
     - React-utils
@@ -674,6 +680,7 @@ PODS:
     - React-jsinspectorcdp
     - React-jsitooling
     - React-perflogger
+    - React-rendererconsistency
     - React-runtimeexecutor
     - React-runtimescheduler
     - React-utils
@@ -699,6 +706,7 @@ PODS:
     - React-jsinspectorcdp
     - React-jsitooling
     - React-perflogger
+    - React-rendererconsistency
     - React-runtimeexecutor
     - React-runtimescheduler
     - React-utils
@@ -724,6 +732,7 @@ PODS:
     - React-jsinspectorcdp
     - React-jsitooling
     - React-perflogger
+    - React-rendererconsistency
     - React-runtimeexecutor
     - React-runtimescheduler
     - React-utils
@@ -749,6 +758,7 @@ PODS:
     - React-jsinspectorcdp
     - React-jsitooling
     - React-perflogger
+    - React-rendererconsistency
     - React-runtimeexecutor
     - React-runtimescheduler
     - React-utils
@@ -774,6 +784,7 @@ PODS:
     - React-jsinspectorcdp
     - React-jsitooling
     - React-perflogger
+    - React-rendererconsistency
     - React-runtimeexecutor
     - React-runtimescheduler
     - React-utils
@@ -799,6 +810,7 @@ PODS:
     - React-jsinspectorcdp
     - React-jsitooling
     - React-perflogger
+    - React-rendererconsistency
     - React-runtimeexecutor
     - React-runtimescheduler
     - React-utils
@@ -824,6 +836,7 @@ PODS:
     - React-jsinspectorcdp
     - React-jsitooling
     - React-perflogger
+    - React-rendererconsistency
     - React-runtimeexecutor
     - React-runtimescheduler
     - React-utils
@@ -849,6 +862,7 @@ PODS:
     - React-jsinspectorcdp
     - React-jsitooling
     - React-perflogger
+    - React-rendererconsistency
     - React-runtimeexecutor
     - React-runtimescheduler
     - React-utils
@@ -4632,7 +4646,7 @@ SPEC CHECKSUMS:
   AirshipServiceExtension: 50d11b2f62c4a490d4e81a1c36f70e2ecb70a27e
   AppAuth: d4f13a8fe0baf391b2108511793e4b479691fb73
   AppLogs: 3bc4e9b141dbf265b9464409caaa40416a9ee0e0
-  boost: 7e761d76ca2ce687f7cc98e698152abd03a18f90
+  boost: 659a89341ea4ab3df8259733813b52f26d8be9a5
   DoubleConversion: cb417026b2400c8f53ae97020b2be961b59470cb
   EXAV: ae28256069c4cdde93d185c007d8f68d92902c2e
   EXConstants: a95804601ee4a6aa7800645f9b070d753b1142b3
@@ -4701,7 +4715,7 @@ SPEC CHECKSUMS:
   React: 2073376f47c71b7e9a0af7535986a77522ce1049
   React-callinvoker: 751b6f2c83347a0486391c3f266f291f0f53b27e
   React-Codegen: 4b8b4817cea7a54b83851d4c1f91f79aa73de30a
-  React-Core: dff5d29973349b11dd6631c9498456d75f846d5e
+  React-Core: aeebd9b37ac383279f610f1e53f66b9931686a41
   React-CoreModules: c0ae04452e4c5d30e06f8e94692a49107657f537
   React-cxxreact: 376fd672c95dfb64ad5cc246e6a1e9edb78dec4c
   React-debug: d4955c86870792887ed695df6ebf0e94e39dc7e1
@@ -4753,7 +4767,7 @@ SPEC CHECKSUMS:
   react-native-webview: cdce419e8022d0ef6f07db21890631258e7a9e6e
   React-NativeModulesApple: 8c7eb6057b00c191a11ad5ced41826ec5a0e4d78
   React-oscompat: 93b5535ea7f7dff46aaee4f78309a70979bdde9d
-  React-perflogger: 5536d2df3d18fe0920263466f7b46a56351c0510
+  React-perflogger: e7dcbfcb796d346be7936b75740c3e27a4bb3977
   React-performancetimeline: c6c9393c1a0453a51e1852e3531defe60790b36c
   React-RCTActionSheet: 42195ae666e6d79b4af2346770f765b7c29435b9
   React-RCTAnimation: fa103ccc3503b1ed8dedca7e62e7823937748843
@@ -4768,7 +4782,7 @@ SPEC CHECKSUMS:
   React-RCTSettings: 71f5c7fd7b5f4e725a4e2114a4b4373d0e46048f
   React-RCTText: b94d4699b49285bee22b8ebf768924d607eccee3
   React-RCTVibration: 6e3993c4f6c36a3899059f9a9ead560ddaf5a7d7
-  React-rendererconsistency: 612d0f6603d9837bb1236d7fd5194203b35c8799
+  React-rendererconsistency: bef28690433e2b4bb00c2f884b22b86e61a430f2
   React-renderercss: e5c2c3b84976f7a587cde8423c671db07a6a77da
   React-rendererdebug: cc7a6131733605b8897754f72c0c35c79f77da9e
   React-RuntimeApple: 3f96102fc1ebf738d36719cdce5422a5769293fb
@@ -4819,4 +4833,4 @@ SPEC CHECKSUMS:
 
 PODFILE CHECKSUM: 7b7e42d39b30be7ca4c68c5272e2cbf2a740695b
 
-COCOAPODS: 1.16.2
+COCOAPODS: 1.16.2
\ No newline at end of file

From 546e9fb048db10d5f8ea2e0c0e18777937b46d82 Mon Sep 17 00:00:00 2001
From: Abdelrahman Khattab <abzokhattab@gmail.com>
Date: Tue, 2 Dec 2025 16:09:42 +0100
Subject: [PATCH 14/49] minor edit

---
 ios/Podfile.lock | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/ios/Podfile.lock b/ios/Podfile.lock
index fe6a3764e75a..57f5c67f64a1 100644
--- a/ios/Podfile.lock
+++ b/ios/Podfile.lock
@@ -4833,4 +4833,4 @@ SPEC CHECKSUMS:
 
 PODFILE CHECKSUM: 7b7e42d39b30be7ca4c68c5272e2cbf2a740695b
 
-COCOAPODS: 1.16.2
\ No newline at end of file
+COCOAPODS: 1.16.2

From f3eebdec1064d30024eb91c4a399513817f3d7eb Mon Sep 17 00:00:00 2001
From: Abdelrahman Khattab <abzokhattab@gmail.com>
Date: Tue, 2 Dec 2025 17:10:22 +0100
Subject: [PATCH 15/49] code refactoring

---
 src/components/ApprovalWorkflowSection.tsx    |  2 +-
 ...aceWorkflowsApprovalsApprovalLimitPage.tsx |  2 --
 ...orkspaceWorkflowsApprovalsApproverPage.tsx | 27 +++++++++----------
 3 files changed, 14 insertions(+), 17 deletions(-)

diff --git a/src/components/ApprovalWorkflowSection.tsx b/src/components/ApprovalWorkflowSection.tsx
index 7d4d0a50f7bb..16bf633513f6 100644
--- a/src/components/ApprovalWorkflowSection.tsx
+++ b/src/components/ApprovalWorkflowSection.tsx
@@ -51,7 +51,7 @@ function ApprovalWorkflowSection({approvalWorkflow, onPress, currency = CONST.CU
 
     const getApprovalLimitDescription = useCallback(
         (approver: Approver): string | undefined => {
-            if (!approver.approvalLimit || !approver.overLimitForwardsTo) {
+            if (approver.approvalLimit == null || !approver.overLimitForwardsTo) {
                 return undefined;
             }
 
diff --git a/src/pages/workspace/workflows/approvals/WorkspaceWorkflowsApprovalsApprovalLimitPage.tsx b/src/pages/workspace/workflows/approvals/WorkspaceWorkflowsApprovalsApprovalLimitPage.tsx
index f45638b5b4b5..e103dbdf99f6 100644
--- a/src/pages/workspace/workflows/approvals/WorkspaceWorkflowsApprovalsApprovalLimitPage.tsx
+++ b/src/pages/workspace/workflows/approvals/WorkspaceWorkflowsApprovalsApprovalLimitPage.tsx
@@ -107,8 +107,6 @@ function WorkspaceWorkflowsApprovalsApprovalLimitPage({policy, isLoadingReportDa
     }, [onlyApproverEmpty, isCircularReference, selectedApproverDisplayName, translate]);
 
     const handleSkip = useCallback(() => {
-        setApprovalLimit('');
-
         if (approvalWorkflow && currentApprover) {
             setApprovalWorkflowApprover({
                 approver: {
diff --git a/src/pages/workspace/workflows/approvals/WorkspaceWorkflowsApprovalsApproverPage.tsx b/src/pages/workspace/workflows/approvals/WorkspaceWorkflowsApprovalsApproverPage.tsx
index 8a04b41744e7..3f67f5596001 100644
--- a/src/pages/workspace/workflows/approvals/WorkspaceWorkflowsApprovalsApproverPage.tsx
+++ b/src/pages/workspace/workflows/approvals/WorkspaceWorkflowsApprovalsApproverPage.tsx
@@ -29,9 +29,8 @@ type WorkspaceWorkflowsApprovalsApproverPageProps = WithPolicyAndFullscreenLoadi
 function WorkspaceWorkflowsApprovalsApproverPage({policy, personalDetails, isLoadingReportData = true, route}: WorkspaceWorkflowsApprovalsApproverPageProps) {
     const styles = useThemeStyles();
     const {translate} = useLocalize();
-    const [approvalWorkflow, approvalWorkflowMetadata] = useOnyx(ONYXKEYS.APPROVAL_WORKFLOW, {canBeMissing: true});
+    const [currentApprovalWorkflow, approvalWorkflowMetadata] = useOnyx(ONYXKEYS.APPROVAL_WORKFLOW, {canBeMissing: true});
     const isApprovalWorkflowLoading = isLoadingOnyxValue(approvalWorkflowMetadata);
-    const [currentApprovalWorkflow] = useOnyx(ONYXKEYS.APPROVAL_WORKFLOW, {canBeMissing: true});
     const [personalDetailsByEmail] = useOnyx(ONYXKEYS.PERSONAL_DETAILS_LIST, {
         canBeMissing: true,
         selector: personalDetailsByEmailSelector,
@@ -39,24 +38,24 @@ function WorkspaceWorkflowsApprovalsApproverPage({policy, personalDetails, isLoa
     const [selectedApproverEmail, setSelectedApproverEmail] = useState<string | undefined>(undefined);
 
     const approverIndex = Number(route.params.approverIndex) ?? 0;
-    const isInitialCreationFlow = approvalWorkflow?.action === CONST.APPROVAL_WORKFLOW.ACTION.CREATE && !route.params.backTo;
+    const isInitialCreationFlow = currentApprovalWorkflow?.action === CONST.APPROVAL_WORKFLOW.ACTION.CREATE && !route.params.backTo;
     const defaultApprover = getDefaultApprover(policy);
-    const firstApprover = approvalWorkflow?.approvers?.[0]?.email ?? '';
+    const firstApprover = currentApprovalWorkflow?.approvers?.[0]?.email ?? '';
     const rhpRoutes = useNavigationState((state) => state.routes);
 
     useEffect(() => {
-        const currentApprover = approvalWorkflow?.approvers[approverIndex];
+        const currentApprover = currentApprovalWorkflow?.approvers[approverIndex];
         if (!currentApprover) {
             return;
         }
 
         setSelectedApproverEmail(currentApprover.email);
-    }, [approvalWorkflow?.approvers, approverIndex]);
+    }, [currentApprovalWorkflow?.approvers, approverIndex]);
 
     const employeeList = policy?.employeeList;
-    const approversFromWorkflow = approvalWorkflow?.approvers;
-    const isDefault = approvalWorkflow?.isDefault;
-    const membersEmail = useMemo(() => approvalWorkflow?.members.map((member) => member.email), [approvalWorkflow?.members]);
+    const approversFromWorkflow = currentApprovalWorkflow?.approvers;
+    const isDefault = currentApprovalWorkflow?.isDefault;
+    const membersEmail = useMemo(() => currentApprovalWorkflow?.members.map((member) => member.email), [currentApprovalWorkflow?.members]);
     const allApprovers: SelectionListApprover[] = useMemo(() => {
         if (isApprovalWorkflowLoading || !employeeList) {
             return [];
@@ -120,20 +119,20 @@ function WorkspaceWorkflowsApprovalsApproverPage({policy, personalDetails, isLoa
         personalDetails,
     ]);
 
-    const shouldShowListEmptyContent = !!approvalWorkflow && !isApprovalWorkflowLoading;
+    const shouldShowListEmptyContent = !!currentApprovalWorkflow && !isApprovalWorkflowLoading;
 
     const goBack = useCallback(() => {
         let backTo;
         if (isInitialCreationFlow) {
             backTo = ROUTES.WORKSPACE_WORKFLOWS_APPROVALS_EXPENSES_FROM.getRoute(route.params.policyID);
             clearApprovalWorkflowApprovers();
-        } else if (approvalWorkflow?.action === CONST.APPROVAL_WORKFLOW.ACTION.EDIT) {
+        } else if (currentApprovalWorkflow?.action === CONST.APPROVAL_WORKFLOW.ACTION.EDIT) {
             backTo = rhpRoutes.length > 1 ? undefined : ROUTES.WORKSPACE_WORKFLOWS_APPROVALS_EDIT.getRoute(route.params.policyID, firstApprover);
         } else {
             backTo = ROUTES.WORKSPACE_WORKFLOWS_APPROVALS_NEW.getRoute(route.params.policyID);
         }
         Navigation.goBack(backTo);
-    }, [isInitialCreationFlow, approvalWorkflow?.action, route.params.policyID, rhpRoutes.length, firstApprover]);
+    }, [isInitialCreationFlow, currentApprovalWorkflow?.action, route.params.policyID, rhpRoutes.length, firstApprover]);
 
     const toggleApprover = useCallback(
         (approvers: SelectionListApprover[]) => {
@@ -166,7 +165,7 @@ function WorkspaceWorkflowsApprovalsApproverPage({policy, personalDetails, isLoa
                 personalDetailsByEmail,
             });
 
-            if (approvalWorkflow?.action === CONST.APPROVAL_WORKFLOW.ACTION.EDIT) {
+            if (currentApprovalWorkflow?.action === CONST.APPROVAL_WORKFLOW.ACTION.EDIT) {
                 goBack();
                 return;
             }
@@ -175,7 +174,7 @@ function WorkspaceWorkflowsApprovalsApproverPage({policy, personalDetails, isLoa
                 ROUTES.WORKSPACE_WORKFLOWS_APPROVALS_APPROVAL_LIMIT.getRoute(route.params.policyID, approverIndex, ROUTES.WORKSPACE_WORKFLOWS_APPROVALS_NEW.getRoute(route.params.policyID)),
             );
         },
-        [approverIndex, currentApprovalWorkflow, employeeList, personalDetails, policy, route.params.policyID, goBack, personalDetailsByEmail, approvalWorkflow?.action],
+        [approverIndex, currentApprovalWorkflow, employeeList, personalDetails, policy, route.params.policyID, goBack, personalDetailsByEmail],
     );
 
     const subtitle = useMemo(

From 3843aec78a80c6e463e5b32a825ea2ae712b8daa Mon Sep 17 00:00:00 2001
From: Abdelrahman Khattab <abzokhattab@gmail.com>
Date: Tue, 2 Dec 2025 17:18:27 +0100
Subject: [PATCH 16/49] refactoring

---
 src/libs/WorkflowUtils.ts                     |  4 +++-
 ...aceWorkflowsApprovalsApprovalLimitPage.tsx |  2 +-
 ...orkspaceWorkflowsApprovalsApproverPage.tsx |  2 +-
 ...orkflowsApprovalsOverLimitApproverPage.tsx | 23 ++++++++++++++++---
 4 files changed, 25 insertions(+), 6 deletions(-)

diff --git a/src/libs/WorkflowUtils.ts b/src/libs/WorkflowUtils.ts
index cac472ba3ade..745a795316a1 100644
--- a/src/libs/WorkflowUtils.ts
+++ b/src/libs/WorkflowUtils.ts
@@ -280,7 +280,9 @@ function convertApprovalWorkflowToPolicyEmployees({
             ...(overLimitForwardsToChanged ? {overLimitForwardsTo} : {}),
             pendingAction: previousPendingAction === CONST.RED_BRICK_ROAD_PENDING_ACTION.DELETE ? previousPendingAction : pendingAction,
             pendingFields: {
-                forwardsTo: pendingAction,
+                ...(forwardsToChanged ? {forwardsTo: pendingAction} : {}),
+                ...(approvalLimitChanged ? {approvalLimit: pendingAction} : {}),
+                ...(overLimitForwardsToChanged ? {overLimitForwardsTo: pendingAction} : {}),
             },
         };
     }
diff --git a/src/pages/workspace/workflows/approvals/WorkspaceWorkflowsApprovalsApprovalLimitPage.tsx b/src/pages/workspace/workflows/approvals/WorkspaceWorkflowsApprovalsApprovalLimitPage.tsx
index e103dbdf99f6..7b03d29e2a63 100644
--- a/src/pages/workspace/workflows/approvals/WorkspaceWorkflowsApprovalsApprovalLimitPage.tsx
+++ b/src/pages/workspace/workflows/approvals/WorkspaceWorkflowsApprovalsApprovalLimitPage.tsx
@@ -46,7 +46,7 @@ function WorkspaceWorkflowsApprovalsApprovalLimitPage({policy, isLoadingReportDa
     });
 
     const policyID = route.params.policyID;
-    const approverIndex = Number(route.params.approverIndex) ?? 0;
+    const approverIndex = Number(route.params.approverIndex ?? 0);
     const backTo = route.params?.backTo;
     const isEditFlow = approvalWorkflow?.action === CONST.APPROVAL_WORKFLOW.ACTION.EDIT;
     const currentApprover = approvalWorkflow?.approvers?.[approverIndex];
diff --git a/src/pages/workspace/workflows/approvals/WorkspaceWorkflowsApprovalsApproverPage.tsx b/src/pages/workspace/workflows/approvals/WorkspaceWorkflowsApprovalsApproverPage.tsx
index 3f67f5596001..7552c82d6bcd 100644
--- a/src/pages/workspace/workflows/approvals/WorkspaceWorkflowsApprovalsApproverPage.tsx
+++ b/src/pages/workspace/workflows/approvals/WorkspaceWorkflowsApprovalsApproverPage.tsx
@@ -37,7 +37,7 @@ function WorkspaceWorkflowsApprovalsApproverPage({policy, personalDetails, isLoa
     });
     const [selectedApproverEmail, setSelectedApproverEmail] = useState<string | undefined>(undefined);
 
-    const approverIndex = Number(route.params.approverIndex) ?? 0;
+    const approverIndex = Number(route.params.approverIndex ?? 0);
     const isInitialCreationFlow = currentApprovalWorkflow?.action === CONST.APPROVAL_WORKFLOW.ACTION.CREATE && !route.params.backTo;
     const defaultApprover = getDefaultApprover(policy);
     const firstApprover = currentApprovalWorkflow?.approvers?.[0]?.email ?? '';
diff --git a/src/pages/workspace/workflows/approvals/WorkspaceWorkflowsApprovalsOverLimitApproverPage.tsx b/src/pages/workspace/workflows/approvals/WorkspaceWorkflowsApprovalsOverLimitApproverPage.tsx
index 917cec4dc1e7..bb5614989e3a 100644
--- a/src/pages/workspace/workflows/approvals/WorkspaceWorkflowsApprovalsOverLimitApproverPage.tsx
+++ b/src/pages/workspace/workflows/approvals/WorkspaceWorkflowsApprovalsOverLimitApproverPage.tsx
@@ -37,17 +37,21 @@ function WorkspaceWorkflowsApprovalsOverLimitApproverPage({policy, personalDetai
     const expensifyIcons = useMemoizedLazyExpensifyIcons(['FallbackAvatar'] as const);
 
     const policyID = route.params.policyID;
-    const approverIndex = Number(route.params.approverIndex) ?? 0;
+    const approverIndex = Number(route.params.approverIndex ?? 0);
     const backTo = route.params?.backTo;
     const currentApprover = approvalWorkflow?.approvers?.[approverIndex];
 
     const employeeList = policy?.employeeList;
+    const isDefault = approvalWorkflow?.isDefault;
+    const membersEmail = useMemo(() => approvalWorkflow?.members.map((member) => member.email), [approvalWorkflow?.members]);
 
     const allApprovers: SelectionListApprover[] = useMemo(() => {
         if (isApprovalWorkflowLoading || !employeeList) {
             return [];
         }
 
+        const policyMemberEmailsToAccountIDs = getMemberAccountIDsForWorkspace(employeeList);
+
         return Object.values(employeeList)
             .map((employee): SelectionListApprover | null => {
                 const email = employee.email;
@@ -56,7 +60,10 @@ function WorkspaceWorkflowsApprovalsOverLimitApproverPage({policy, personalDetai
                     return null;
                 }
 
-                const policyMemberEmailsToAccountIDs = getMemberAccountIDsForWorkspace(employeeList);
+                if (!isDefault && policy?.preventSelfApproval && membersEmail?.includes(email)) {
+                    return null;
+                }
+
                 const accountID = Number(policyMemberEmailsToAccountIDs[email] ?? '');
                 const {avatar, displayName = email, login} = personalDetails?.[accountID] ?? {};
 
@@ -77,7 +84,17 @@ function WorkspaceWorkflowsApprovalsOverLimitApproverPage({policy, personalDetai
                 };
             })
             .filter((approver): approver is SelectionListApprover => !!approver);
-    }, [isApprovalWorkflowLoading, employeeList, personalDetails, policy?.owner, currentApprover?.overLimitForwardsTo, expensifyIcons.FallbackAvatar]);
+    }, [
+        isApprovalWorkflowLoading,
+        employeeList,
+        personalDetails,
+        policy?.owner,
+        policy?.preventSelfApproval,
+        currentApprover?.overLimitForwardsTo,
+        expensifyIcons.FallbackAvatar,
+        isDefault,
+        membersEmail,
+    ]);
 
     const shouldShowListEmptyContent = !!approvalWorkflow && !isApprovalWorkflowLoading;
 

From 0b454c3de96e5cf6133927756fb5b7e18914e560 Mon Sep 17 00:00:00 2001
From: Abdelrahman Khattab <abzokhattab@gmail.com>
Date: Tue, 2 Dec 2025 18:13:24 +0100
Subject: [PATCH 17/49] code refactoring

---
 src/libs/WorkflowUtils.ts                                       | 2 +-
 .../approvals/WorkspaceWorkflowsApprovalsApprovalLimitPage.tsx  | 2 +-
 .../approvals/WorkspaceWorkflowsApprovalsApproverPage.tsx       | 2 +-
 .../WorkspaceWorkflowsApprovalsOverLimitApproverPage.tsx        | 2 +-
 4 files changed, 4 insertions(+), 4 deletions(-)

diff --git a/src/libs/WorkflowUtils.ts b/src/libs/WorkflowUtils.ts
index 745a795316a1..4e7203f29823 100644
--- a/src/libs/WorkflowUtils.ts
+++ b/src/libs/WorkflowUtils.ts
@@ -259,7 +259,7 @@ function convertApprovalWorkflowToPolicyEmployees({
     for (const [index, approver] of approvalWorkflow.approvers.entries()) {
         const nextApprover = approvalWorkflow.approvers.at(index + 1);
         const forwardsTo = type === CONST.APPROVAL_WORKFLOW.TYPE.REMOVE ? '' : (nextApprover?.email ?? '');
-        const approvalLimit = type === CONST.APPROVAL_WORKFLOW.TYPE.REMOVE ? undefined : approver.approvalLimit;
+        const approvalLimit = type === CONST.APPROVAL_WORKFLOW.TYPE.REMOVE ? null : approver.approvalLimit;
         const overLimitForwardsTo = type === CONST.APPROVAL_WORKFLOW.TYPE.REMOVE ? '' : (approver.overLimitForwardsTo ?? '');
 
         // For every approver, we check if the forwardsTo, approvalLimit, or overLimitForwardsTo fields have changed.
diff --git a/src/pages/workspace/workflows/approvals/WorkspaceWorkflowsApprovalsApprovalLimitPage.tsx b/src/pages/workspace/workflows/approvals/WorkspaceWorkflowsApprovalsApprovalLimitPage.tsx
index 7b03d29e2a63..e103dbdf99f6 100644
--- a/src/pages/workspace/workflows/approvals/WorkspaceWorkflowsApprovalsApprovalLimitPage.tsx
+++ b/src/pages/workspace/workflows/approvals/WorkspaceWorkflowsApprovalsApprovalLimitPage.tsx
@@ -46,7 +46,7 @@ function WorkspaceWorkflowsApprovalsApprovalLimitPage({policy, isLoadingReportDa
     });
 
     const policyID = route.params.policyID;
-    const approverIndex = Number(route.params.approverIndex ?? 0);
+    const approverIndex = Number(route.params.approverIndex) ?? 0;
     const backTo = route.params?.backTo;
     const isEditFlow = approvalWorkflow?.action === CONST.APPROVAL_WORKFLOW.ACTION.EDIT;
     const currentApprover = approvalWorkflow?.approvers?.[approverIndex];
diff --git a/src/pages/workspace/workflows/approvals/WorkspaceWorkflowsApprovalsApproverPage.tsx b/src/pages/workspace/workflows/approvals/WorkspaceWorkflowsApprovalsApproverPage.tsx
index 7552c82d6bcd..3f67f5596001 100644
--- a/src/pages/workspace/workflows/approvals/WorkspaceWorkflowsApprovalsApproverPage.tsx
+++ b/src/pages/workspace/workflows/approvals/WorkspaceWorkflowsApprovalsApproverPage.tsx
@@ -37,7 +37,7 @@ function WorkspaceWorkflowsApprovalsApproverPage({policy, personalDetails, isLoa
     });
     const [selectedApproverEmail, setSelectedApproverEmail] = useState<string | undefined>(undefined);
 
-    const approverIndex = Number(route.params.approverIndex ?? 0);
+    const approverIndex = Number(route.params.approverIndex) ?? 0;
     const isInitialCreationFlow = currentApprovalWorkflow?.action === CONST.APPROVAL_WORKFLOW.ACTION.CREATE && !route.params.backTo;
     const defaultApprover = getDefaultApprover(policy);
     const firstApprover = currentApprovalWorkflow?.approvers?.[0]?.email ?? '';
diff --git a/src/pages/workspace/workflows/approvals/WorkspaceWorkflowsApprovalsOverLimitApproverPage.tsx b/src/pages/workspace/workflows/approvals/WorkspaceWorkflowsApprovalsOverLimitApproverPage.tsx
index bb5614989e3a..aa3b7dcf5928 100644
--- a/src/pages/workspace/workflows/approvals/WorkspaceWorkflowsApprovalsOverLimitApproverPage.tsx
+++ b/src/pages/workspace/workflows/approvals/WorkspaceWorkflowsApprovalsOverLimitApproverPage.tsx
@@ -37,7 +37,7 @@ function WorkspaceWorkflowsApprovalsOverLimitApproverPage({policy, personalDetai
     const expensifyIcons = useMemoizedLazyExpensifyIcons(['FallbackAvatar'] as const);
 
     const policyID = route.params.policyID;
-    const approverIndex = Number(route.params.approverIndex ?? 0);
+    const approverIndex = Number(route.params.approverIndex) ?? 0;
     const backTo = route.params?.backTo;
     const currentApprover = approvalWorkflow?.approvers?.[approverIndex];
 

From cff931f2986bf9a3f5aaae1a3242de72cee87397 Mon Sep 17 00:00:00 2001
From: Abdelrahman Khattab <abzokhattab@gmail.com>
Date: Tue, 2 Dec 2025 18:19:35 +0100
Subject: [PATCH 18/49] raising workflowsutils test coverage

---
 tests/unit/WorkflowUtilsTest.ts | 164 ++++++++++++++++++++++++++++++--
 1 file changed, 158 insertions(+), 6 deletions(-)

diff --git a/tests/unit/WorkflowUtilsTest.ts b/tests/unit/WorkflowUtilsTest.ts
index d17683c78c0f..9fb761622e15 100644
--- a/tests/unit/WorkflowUtilsTest.ts
+++ b/tests/unit/WorkflowUtilsTest.ts
@@ -194,6 +194,49 @@ describe('WorkflowUtils', () => {
                 buildApprover(1, {forwardsTo: '1@example.com', isCircularReference: true}),
             ]);
         });
+
+        it('Should include approvalLimit and overLimitForwardsTo in approver objects', () => {
+            const employees: PolicyEmployeeList = {
+                '1@example.com': {
+                    email: '1@example.com',
+                    forwardsTo: '2@example.com',
+                    approvalLimit: 50000,
+                    overLimitForwardsTo: '3@example.com',
+                },
+                '2@example.com': {
+                    email: '2@example.com',
+                    forwardsTo: undefined,
+                    approvalLimit: 100000,
+                    overLimitForwardsTo: '3@example.com',
+                },
+                '3@example.com': {
+                    email: '3@example.com',
+                    forwardsTo: undefined,
+                },
+            };
+
+            const approvers = WorkflowUtils.calculateApprovers({employees, firstEmail: '1@example.com', personalDetailsByEmail});
+
+            expect(approvers).toEqual([
+                buildApprover(1, {forwardsTo: '2@example.com', approvalLimit: 50000, overLimitForwardsTo: '3@example.com'}),
+                buildApprover(2, {approvalLimit: 100000, overLimitForwardsTo: '3@example.com'}),
+            ]);
+        });
+
+        it('Should handle null approvalLimit correctly', () => {
+            const employees: PolicyEmployeeList = {
+                '1@example.com': {
+                    email: '1@example.com',
+                    forwardsTo: undefined,
+                    approvalLimit: null,
+                    overLimitForwardsTo: '',
+                },
+            };
+
+            const approvers = WorkflowUtils.calculateApprovers({employees, firstEmail: '1@example.com', personalDetailsByEmail});
+
+            expect(approvers).toEqual([buildApprover(1, {approvalLimit: null, overLimitForwardsTo: ''})]);
+        });
     });
 
     describe('convertPolicyEmployeesToApprovalWorkflows', () => {
@@ -446,9 +489,9 @@ describe('WorkflowUtils', () => {
             const convertedEmployees = WorkflowUtils.convertApprovalWorkflowToPolicyEmployees({previousEmployeeList: {}, approvalWorkflow, type: 'create'});
 
             expect(convertedEmployees).toEqual({
-                '1@example.com': buildPolicyEmployee(1, {forwardsTo: '2@example.com', overLimitForwardsTo: '', pendingFields: {forwardsTo: 'add'}}),
-                '2@example.com': buildPolicyEmployee(2, {forwardsTo: '3@example.com', overLimitForwardsTo: '', pendingFields: {forwardsTo: 'add'}}),
-                '3@example.com': buildPolicyEmployee(3, {forwardsTo: '', overLimitForwardsTo: '', pendingFields: {forwardsTo: 'add'}}),
+                '1@example.com': buildPolicyEmployee(1, {forwardsTo: '2@example.com', overLimitForwardsTo: '', pendingFields: {forwardsTo: 'add', overLimitForwardsTo: 'add'}}),
+                '2@example.com': buildPolicyEmployee(2, {forwardsTo: '3@example.com', overLimitForwardsTo: '', pendingFields: {forwardsTo: 'add', overLimitForwardsTo: 'add'}}),
+                '3@example.com': buildPolicyEmployee(3, {forwardsTo: '', overLimitForwardsTo: '', pendingFields: {forwardsTo: 'add', overLimitForwardsTo: 'add'}}),
                 '4@example.com': buildPolicyEmployee(4, {submitsTo: '1@example.com', pendingFields: {submitsTo: 'add'}}),
                 '5@example.com': buildPolicyEmployee(5, {submitsTo: '1@example.com', pendingFields: {submitsTo: 'add'}}),
                 '6@example.com': buildPolicyEmployee(6, {submitsTo: '1@example.com', pendingFields: {submitsTo: 'add'}}),
@@ -465,14 +508,123 @@ describe('WorkflowUtils', () => {
             const convertedEmployees = WorkflowUtils.convertApprovalWorkflowToPolicyEmployees({previousEmployeeList: {}, approvalWorkflow, type: 'remove'});
 
             expect(convertedEmployees).toEqual({
-                '1@example.com': buildPolicyEmployee(1, {forwardsTo: '', overLimitForwardsTo: '', pendingAction: 'update', pendingFields: {forwardsTo: 'update'}}),
-                '2@example.com': buildPolicyEmployee(2, {forwardsTo: '', overLimitForwardsTo: '', pendingAction: 'update', pendingFields: {forwardsTo: 'update'}}),
-                '3@example.com': buildPolicyEmployee(3, {forwardsTo: '', overLimitForwardsTo: '', pendingAction: 'update', pendingFields: {forwardsTo: 'update'}}),
+                '1@example.com': buildPolicyEmployee(1, {
+                    forwardsTo: '',
+                    approvalLimit: null,
+                    overLimitForwardsTo: '',
+                    pendingAction: 'update',
+                    pendingFields: {forwardsTo: 'update', approvalLimit: 'update', overLimitForwardsTo: 'update'},
+                }),
+                '2@example.com': buildPolicyEmployee(2, {
+                    forwardsTo: '',
+                    approvalLimit: null,
+                    overLimitForwardsTo: '',
+                    pendingAction: 'update',
+                    pendingFields: {forwardsTo: 'update', approvalLimit: 'update', overLimitForwardsTo: 'update'},
+                }),
+                '3@example.com': buildPolicyEmployee(3, {
+                    forwardsTo: '',
+                    approvalLimit: null,
+                    overLimitForwardsTo: '',
+                    pendingAction: 'update',
+                    pendingFields: {forwardsTo: 'update', approvalLimit: 'update', overLimitForwardsTo: 'update'},
+                }),
                 '4@example.com': buildPolicyEmployee(4, {submitsTo: '', pendingAction: 'update', pendingFields: {submitsTo: 'update'}}),
                 '5@example.com': buildPolicyEmployee(5, {submitsTo: '', pendingAction: 'update', pendingFields: {submitsTo: 'update'}}),
                 '6@example.com': buildPolicyEmployee(6, {submitsTo: '', pendingAction: 'update', pendingFields: {submitsTo: 'update'}}),
             });
         });
+
+        it('Should include approvalLimit and overLimitForwardsTo when creating workflow with limits', () => {
+            const approvalWorkflow: ApprovalWorkflow = {
+                members: [buildMember(2)],
+                approvers: [buildApprover(1, {approvalLimit: 50000, overLimitForwardsTo: '3@example.com'})],
+                isDefault: false,
+            };
+
+            const convertedEmployees = WorkflowUtils.convertApprovalWorkflowToPolicyEmployees({previousEmployeeList: {}, approvalWorkflow, type: 'create'});
+
+            expect(convertedEmployees).toEqual({
+                '1@example.com': buildPolicyEmployee(1, {
+                    forwardsTo: '',
+                    approvalLimit: 50000,
+                    overLimitForwardsTo: '3@example.com',
+                    pendingFields: {forwardsTo: 'add', approvalLimit: 'add', overLimitForwardsTo: 'add'},
+                }),
+                '2@example.com': buildPolicyEmployee(2, {submitsTo: '1@example.com', pendingFields: {submitsTo: 'add'}}),
+            });
+        });
+
+        it('Should set approvalLimit to null when removing workflow (not undefined)', () => {
+            const previousEmployeeList: PolicyEmployeeList = {
+                '1@example.com': {
+                    email: '1@example.com',
+                    forwardsTo: '2@example.com',
+                    approvalLimit: 50000,
+                    overLimitForwardsTo: '3@example.com',
+                },
+            };
+            const approvalWorkflow: ApprovalWorkflow = {
+                members: [],
+                approvers: [buildApprover(1, {forwardsTo: '2@example.com', approvalLimit: 50000, overLimitForwardsTo: '3@example.com'})],
+                isDefault: false,
+            };
+
+            const convertedEmployees = WorkflowUtils.convertApprovalWorkflowToPolicyEmployees({previousEmployeeList, approvalWorkflow, type: 'remove'});
+
+            // approvalLimit should be null (not undefined) so it gets sent to the API and clears the field
+            expect(convertedEmployees['1@example.com']?.approvalLimit).toBeNull();
+            expect(convertedEmployees['1@example.com']?.overLimitForwardsTo).toBe('');
+        });
+
+        it('Should include pendingFields for approvalLimit and overLimitForwardsTo when they change', () => {
+            const previousEmployeeList: PolicyEmployeeList = {
+                '1@example.com': {
+                    email: '1@example.com',
+                    forwardsTo: '',
+                    approvalLimit: 50000,
+                    overLimitForwardsTo: '3@example.com',
+                },
+            };
+            const approvalWorkflow: ApprovalWorkflow = {
+                members: [],
+                approvers: [buildApprover(1, {approvalLimit: 100000, overLimitForwardsTo: '4@example.com'})],
+                isDefault: false,
+            };
+
+            const convertedEmployees = WorkflowUtils.convertApprovalWorkflowToPolicyEmployees({previousEmployeeList, approvalWorkflow, type: 'update'});
+
+            // pendingFields should include the fields that changed (forwardsTo didn't change since it's '' -> '')
+            expect(convertedEmployees['1@example.com']?.pendingFields).toEqual({
+                approvalLimit: 'update',
+                overLimitForwardsTo: 'update',
+            });
+            expect(convertedEmployees['1@example.com']?.approvalLimit).toBe(100000);
+            expect(convertedEmployees['1@example.com']?.overLimitForwardsTo).toBe('4@example.com');
+        });
+
+        it('Should not include unchanged fields in pendingFields', () => {
+            const previousEmployeeList: PolicyEmployeeList = {
+                '1@example.com': {
+                    email: '1@example.com',
+                    forwardsTo: '',
+                    approvalLimit: 50000,
+                    overLimitForwardsTo: '3@example.com',
+                },
+            };
+            const approvalWorkflow: ApprovalWorkflow = {
+                members: [],
+                approvers: [buildApprover(1, {approvalLimit: 50000, overLimitForwardsTo: '4@example.com'})],
+                isDefault: false,
+            };
+
+            const convertedEmployees = WorkflowUtils.convertApprovalWorkflowToPolicyEmployees({previousEmployeeList, approvalWorkflow, type: 'update'});
+
+            // Only overLimitForwardsTo changed, so only that should be in pendingFields
+            expect(convertedEmployees['1@example.com']?.pendingFields).toEqual({
+                overLimitForwardsTo: 'update',
+            });
+        });
     });
 
     describe('updateWorkflowDataOnApproverRemoval', () => {

From 1144b86ee16eff466cdcfee329760dd98ece2a45 Mon Sep 17 00:00:00 2001
From: Abdelrahman Khattab <abzokhattab@gmail.com>
Date: Tue, 2 Dec 2025 19:15:24 +0100
Subject: [PATCH 19/49] code refactoring

---
 src/components/ApprovalWorkflowSection.tsx    | 67 +++++---------
 src/libs/WorkflowUtils.ts                     | 28 ++++++
 .../approvals/ApprovalWorkflowEditor.tsx      | 12 +++
 src/styles/index.ts                           |  2 +-
 tests/unit/WorkflowUtilsTest.ts               | 92 +++++++++++++++++++
 5 files changed, 156 insertions(+), 45 deletions(-)

diff --git a/src/components/ApprovalWorkflowSection.tsx b/src/components/ApprovalWorkflowSection.tsx
index 16bf633513f6..988b82092fdd 100644
--- a/src/components/ApprovalWorkflowSection.tsx
+++ b/src/components/ApprovalWorkflowSection.tsx
@@ -7,13 +7,12 @@ import useOnyx from '@hooks/useOnyx';
 import useResponsiveLayout from '@hooks/useResponsiveLayout';
 import useTheme from '@hooks/useTheme';
 import useThemeStyles from '@hooks/useThemeStyles';
-import {convertToDisplayString} from '@libs/CurrencyUtils';
 import {sortAlphabetically} from '@libs/OptionsListUtils';
+import {getApprovalLimitDescription} from '@libs/WorkflowUtils';
 import CONST from '@src/CONST';
 import ONYXKEYS from '@src/ONYXKEYS';
 import {personalDetailsByEmailSelector} from '@src/selectors/PersonalDetails';
 import type ApprovalWorkflow from '@src/types/onyx/ApprovalWorkflow';
-import type {Approver} from '@src/types/onyx/ApprovalWorkflow';
 import Icon from './Icon';
 // eslint-disable-next-line no-restricted-imports
 import * as Expensicons from './Icon/Expensicons';
@@ -49,24 +48,6 @@ function ApprovalWorkflowSection({approvalWorkflow, onPress, currency = CONST.CU
         [approvalWorkflow.approvers.length, toLocaleOrdinal, translate],
     );
 
-    const getApprovalLimitDescription = useCallback(
-        (approver: Approver): string | undefined => {
-            if (approver.approvalLimit == null || !approver.overLimitForwardsTo) {
-                return undefined;
-            }
-
-            const formattedAmount = convertToDisplayString(approver.approvalLimit, currency);
-            const overLimitApproverDetails = personalDetailsByEmail?.[approver.overLimitForwardsTo];
-            const approverDisplayName = Str.removeSMSDomain(overLimitApproverDetails?.displayName ?? approver.overLimitForwardsTo);
-
-            return translate('workflowsApprovalLimitPage.forwardLimitDescription', {
-                approvalLimit: formattedAmount,
-                approverName: approverDisplayName,
-            });
-        },
-        [currency, translate, personalDetailsByEmail],
-    );
-
     const members = useMemo(() => {
         if (approvalWorkflow.isDefault) {
             return translate('workspace.common.everyone');
@@ -116,30 +97,28 @@ function ApprovalWorkflowSection({approvalWorkflow, onPress, currency = CONST.CU
                     shouldRemoveBackground
                 />
 
-                {approvalWorkflow.approvers.map((approver, index) => {
-                    const approvalLimitDescription = getApprovalLimitDescription(approver);
-                    return (
-                        // eslint-disable-next-line react/no-array-index-key
-                        <View key={`approver-${approver.email}-${index}`}>
-                            <View style={styles.workflowApprovalVerticalLine} />
-                            <MenuItem
-                                title={approverTitle(index)}
-                                style={styles.p0}
-                                titleStyle={styles.textLabelSupportingNormal}
-                                descriptionTextStyle={[styles.textNormalThemeText, styles.lineHeightXLarge]}
-                                description={Str.removeSMSDomain(approver.displayName)}
-                                icon={icons.UserCheck}
-                                iconHeight={20}
-                                iconWidth={20}
-                                numberOfLinesDescription={1}
-                                iconFill={theme.icon}
-                                onPress={onPress}
-                                shouldRemoveBackground
-                            />
-                            {!!approvalLimitDescription && <Text style={[styles.textLabelSupporting, styles.workflowApprovalLimitText]}>{approvalLimitDescription}</Text>}
-                        </View>
-                    );
-                })}
+                {approvalWorkflow.approvers.map((approver, index) => (
+                    // eslint-disable-next-line react/no-array-index-key
+                    <View key={`approver-${approver.email}-${index}`}>
+                        <View style={styles.workflowApprovalVerticalLine} />
+                        <MenuItem
+                            title={approverTitle(index)}
+                            style={styles.p0}
+                            titleStyle={styles.textLabelSupportingNormal}
+                            descriptionTextStyle={[styles.textNormalThemeText, styles.lineHeightXLarge]}
+                            description={Str.removeSMSDomain(approver.displayName)}
+                            icon={icons.UserCheck}
+                            iconHeight={20}
+                            iconWidth={20}
+                            numberOfLinesDescription={1}
+                            iconFill={theme.icon}
+                            onPress={onPress}
+                            shouldRemoveBackground
+                            helperText={getApprovalLimitDescription({approver, currency, translate, personalDetailsByEmail})}
+                            helperTextStyle={styles.workflowApprovalLimitText}
+                        />
+                    </View>
+                ))}
             </View>
             <Icon
                 src={Expensicons.ArrowRight}
diff --git a/src/libs/WorkflowUtils.ts b/src/libs/WorkflowUtils.ts
index 4e7203f29823..389512d638c0 100644
--- a/src/libs/WorkflowUtils.ts
+++ b/src/libs/WorkflowUtils.ts
@@ -1,3 +1,4 @@
+import {Str} from 'expensify-common';
 import lodashMapKeys from 'lodash/mapKeys';
 import type {OnyxEntry} from 'react-native-onyx';
 import type {ValueOf} from 'type-fest';
@@ -11,6 +12,7 @@ import type PersonalDetails from '@src/types/onyx/PersonalDetails';
 import type Policy from '@src/types/onyx/Policy';
 import type {PolicyEmployeeList} from '@src/types/onyx/PolicyEmployee';
 import {isBankAccountPartiallySetup} from './BankAccountUtils';
+import {convertToDisplayString} from './CurrencyUtils';
 import {getDefaultApprover} from './PolicyUtils';
 
 const INITIAL_APPROVAL_WORKFLOW: ApprovalWorkflowOnyx = {
@@ -460,10 +462,36 @@ function getEligibleExistingBusinessBankAccounts(bankAccountList: BankAccountLis
     });
 }
 
+type GetApprovalLimitDescriptionParams = {
+    approver: Approver | undefined;
+    currency: string;
+    translate: LocaleContextProps['translate'];
+    personalDetailsByEmail: PersonalDetailsList | undefined;
+};
+
+/**
+ * Get the approval limit description for an approver (e.g., "Reports above $1,000 forward to John Doe")
+ */
+function getApprovalLimitDescription({approver, currency, translate, personalDetailsByEmail}: GetApprovalLimitDescriptionParams): string | undefined {
+    if (approver?.approvalLimit == null || !approver?.overLimitForwardsTo) {
+        return undefined;
+    }
+
+    const formattedAmount = convertToDisplayString(approver.approvalLimit, currency);
+    const overLimitApproverDetails = personalDetailsByEmail?.[approver.overLimitForwardsTo];
+    const approverDisplayName = Str.removeSMSDomain(overLimitApproverDetails?.displayName ?? approver.overLimitForwardsTo);
+
+    return translate('workflowsApprovalLimitPage.forwardLimitDescription', {
+        approvalLimit: formattedAmount,
+        approverName: approverDisplayName,
+    });
+}
+
 export {
     calculateApprovers,
     convertPolicyEmployeesToApprovalWorkflows,
     convertApprovalWorkflowToPolicyEmployees,
+    getApprovalLimitDescription,
     getEligibleExistingBusinessBankAccounts,
     INITIAL_APPROVAL_WORKFLOW,
     updateWorkflowDataOnApproverRemoval,
diff --git a/src/pages/workspace/workflows/approvals/ApprovalWorkflowEditor.tsx b/src/pages/workspace/workflows/approvals/ApprovalWorkflowEditor.tsx
index 7f67bd2230fc..e274c200f880 100644
--- a/src/pages/workspace/workflows/approvals/ApprovalWorkflowEditor.tsx
+++ b/src/pages/workspace/workflows/approvals/ApprovalWorkflowEditor.tsx
@@ -12,12 +12,16 @@ import OfflineWithFeedback from '@components/OfflineWithFeedback';
 import ScrollView from '@components/ScrollView';
 import Text from '@components/Text';
 import useLocalize from '@hooks/useLocalize';
+import useOnyx from '@hooks/useOnyx';
 import useThemeStyles from '@hooks/useThemeStyles';
 import Navigation from '@libs/Navigation/Navigation';
 import {sortAlphabetically} from '@libs/OptionsListUtils';
 import {isControlPolicy} from '@libs/PolicyUtils';
+import {getApprovalLimitDescription} from '@libs/WorkflowUtils';
 import CONST from '@src/CONST';
+import ONYXKEYS from '@src/ONYXKEYS';
 import ROUTES from '@src/ROUTES';
+import {personalDetailsByEmailSelector} from '@src/selectors/PersonalDetails';
 import type {ApprovalWorkflowOnyx, Policy} from '@src/types/onyx';
 import type {Approver} from '@src/types/onyx/ApprovalWorkflow';
 import type {PendingAction} from '@src/types/onyx/OnyxCommon';
@@ -42,7 +46,12 @@ type ApprovalWorkflowEditorProps = {
 function ApprovalWorkflowEditor({approvalWorkflow, removeApprovalWorkflow, policy, policyID, ref}: ApprovalWorkflowEditorProps) {
     const styles = useThemeStyles();
     const {translate, toLocaleOrdinal, localeCompare} = useLocalize();
+    const [personalDetailsByEmail] = useOnyx(ONYXKEYS.PERSONAL_DETAILS_LIST, {
+        canBeMissing: true,
+        selector: personalDetailsByEmailSelector,
+    });
     const approverCount = approvalWorkflow.approvers.length;
+    const currency = policy?.outputCurrency ?? CONST.CURRENCY.USD;
 
     const approverDescription = useCallback(
         (index: number) => (approverCount > 1 ? `${toLocaleOrdinal(index + 1, true)} ${translate('workflowsPage.approver').toLowerCase()}` : `${translate('workflowsPage.approver')}`),
@@ -166,6 +175,7 @@ function ApprovalWorkflowEditor({approvalWorkflow, removeApprovalWorkflow, polic
                         !errorText && approvalWorkflow.usedApproverEmails.some((approverEmail) => approverEmail === approver?.email)
                             ? translate('workflowsPage.approverInMultipleWorkflows')
                             : undefined;
+                    const approvalLimitDescription = getApprovalLimitDescription({approver, currency, translate, personalDetailsByEmail});
 
                     return (
                         <OfflineWithFeedback
@@ -186,6 +196,8 @@ function ApprovalWorkflowEditor({approvalWorkflow, removeApprovalWorkflow, polic
                                 brickRoadIndicator={errorText ? CONST.BRICK_ROAD_INDICATOR_STATUS.ERROR : undefined}
                                 errorText={errorText}
                                 shouldRenderErrorAsHTML
+                                helperText={approvalLimitDescription}
+                                helperTextStyle={styles.pl0}
                             />
                         </OfflineWithFeedback>
                     );
diff --git a/src/styles/index.ts b/src/styles/index.ts
index a721046db09a..27dd28269875 100644
--- a/src/styles/index.ts
+++ b/src/styles/index.ts
@@ -5214,7 +5214,7 @@ const staticStyles = (theme: ThemeColors) =>
         },
 
         workflowApprovalLimitText: {
-            marginLeft: variables.componentSizeNormal + 12,
+            marginLeft: 32,
         },
 
         integrationIcon: {
diff --git a/tests/unit/WorkflowUtilsTest.ts b/tests/unit/WorkflowUtilsTest.ts
index 9fb761622e15..285b93caa531 100644
--- a/tests/unit/WorkflowUtilsTest.ts
+++ b/tests/unit/WorkflowUtilsTest.ts
@@ -794,4 +794,96 @@ describe('WorkflowUtils', () => {
             expect(updateWorkflowDataOnApproverRemoval).toEqual([approvalWorkflow1, {...approvalWorkflow2, removeApprovalWorkflow: true}]);
         });
     });
+
+    describe('getApprovalLimitDescription', () => {
+        const mockTranslate = jest.fn((key: string, params?: Record<string, string>) => {
+            if (key === 'workflowsApprovalLimitPage.forwardLimitDescription') {
+                return `Reports above ${params?.approvalLimit} forward to ${params?.approverName}`;
+            }
+            return key;
+        });
+
+        beforeEach(() => {
+            mockTranslate.mockClear();
+        });
+
+        it('Should return undefined when approver is undefined', () => {
+            const result = WorkflowUtils.getApprovalLimitDescription({
+                approver: undefined,
+                currency: 'USD',
+                translate: mockTranslate as unknown as Parameters<typeof WorkflowUtils.getApprovalLimitDescription>[0]['translate'],
+                personalDetailsByEmail: {},
+            });
+
+            expect(result).toBeUndefined();
+        });
+
+        it('Should return undefined when approvalLimit is null', () => {
+            const approver = buildApprover(1, {approvalLimit: null, overLimitForwardsTo: '2@example.com'});
+
+            const result = WorkflowUtils.getApprovalLimitDescription({
+                approver,
+                currency: 'USD',
+                translate: mockTranslate as unknown as Parameters<typeof WorkflowUtils.getApprovalLimitDescription>[0]['translate'],
+                personalDetailsByEmail: {},
+            });
+
+            expect(result).toBeUndefined();
+        });
+
+        it('Should return undefined when approvalLimit is undefined', () => {
+            const approver = buildApprover(1, {approvalLimit: undefined, overLimitForwardsTo: '2@example.com'});
+
+            const result = WorkflowUtils.getApprovalLimitDescription({
+                approver,
+                currency: 'USD',
+                translate: mockTranslate as unknown as Parameters<typeof WorkflowUtils.getApprovalLimitDescription>[0]['translate'],
+                personalDetailsByEmail: {},
+            });
+
+            expect(result).toBeUndefined();
+        });
+
+        it('Should return undefined when overLimitForwardsTo is missing', () => {
+            const approver = buildApprover(1, {approvalLimit: 50000, overLimitForwardsTo: undefined});
+
+            const result = WorkflowUtils.getApprovalLimitDescription({
+                approver,
+                currency: 'USD',
+                translate: mockTranslate as unknown as Parameters<typeof WorkflowUtils.getApprovalLimitDescription>[0]['translate'],
+                personalDetailsByEmail: {},
+            });
+
+            expect(result).toBeUndefined();
+        });
+
+        it('Should return description when approvalLimit and overLimitForwardsTo are set', () => {
+            const approver = buildApprover(1, {approvalLimit: 50000, overLimitForwardsTo: '2@example.com'});
+
+            const result = WorkflowUtils.getApprovalLimitDescription({
+                approver,
+                currency: 'USD',
+                translate: mockTranslate as unknown as Parameters<typeof WorkflowUtils.getApprovalLimitDescription>[0]['translate'],
+                personalDetailsByEmail: {},
+            });
+
+            expect(result).toBe('Reports above $500.00 forward to 2@example.com');
+        });
+
+        it('Should use display name from personalDetails when available', () => {
+            const approver = buildApprover(1, {approvalLimit: 100000, overLimitForwardsTo: '2@example.com'});
+            const personalDetailsWithEmail: PersonalDetailsList = {
+                '2@example.com': {accountID: 2, displayName: 'John Doe'},
+            };
+
+            const result = WorkflowUtils.getApprovalLimitDescription({
+                approver,
+                currency: 'USD',
+                translate: mockTranslate as unknown as Parameters<typeof WorkflowUtils.getApprovalLimitDescription>[0]['translate'],
+                personalDetailsByEmail: personalDetailsWithEmail,
+            });
+
+            expect(result).toBe('Reports above $1,000.00 forward to John Doe');
+        });
+    });
 });

From ad84c7b4f8a81047d1b21f5f0f3600c6701c13b7 Mon Sep 17 00:00:00 2001
From: Abdelrahman Khattab <abzokhattab@gmail.com>
Date: Tue, 2 Dec 2025 21:47:48 +0100
Subject: [PATCH 20/49] fixing workflowApprovalLimitText bottom padding

---
 src/styles/index.ts | 1 +
 1 file changed, 1 insertion(+)

diff --git a/src/styles/index.ts b/src/styles/index.ts
index 27dd28269875..85071ce97798 100644
--- a/src/styles/index.ts
+++ b/src/styles/index.ts
@@ -5215,6 +5215,7 @@ const staticStyles = (theme: ThemeColors) =>
 
         workflowApprovalLimitText: {
             marginLeft: 32,
+            paddingBottom: 0,
         },
 
         integrationIcon: {

From 99088527887034e1f11cf3a7543aeba6fe7577a4 Mon Sep 17 00:00:00 2001
From: Abdelrahman Khattab <abzokhattab@gmail.com>
Date: Wed, 3 Dec 2025 20:02:27 +0100
Subject: [PATCH 21/49] refactor the approver limit page

---
 ...aceWorkflowsApprovalsApprovalLimitPage.tsx | 148 ++++++++----------
 ...orkflowsApprovalsOverLimitApproverPage.tsx |   7 +
 2 files changed, 75 insertions(+), 80 deletions(-)

diff --git a/src/pages/workspace/workflows/approvals/WorkspaceWorkflowsApprovalsApprovalLimitPage.tsx b/src/pages/workspace/workflows/approvals/WorkspaceWorkflowsApprovalsApprovalLimitPage.tsx
index e103dbdf99f6..f1ea209269ba 100644
--- a/src/pages/workspace/workflows/approvals/WorkspaceWorkflowsApprovalsApprovalLimitPage.tsx
+++ b/src/pages/workspace/workflows/approvals/WorkspaceWorkflowsApprovalsApprovalLimitPage.tsx
@@ -1,5 +1,5 @@
 import {Str} from 'expensify-common';
-import React, {useCallback, useMemo, useState} from 'react';
+import React, {useCallback, useEffect, useMemo, useState} from 'react';
 import {View} from 'react-native';
 import AmountForm from '@components/AmountForm';
 import FullPageNotFoundView from '@components/BlockingViews/FullPageNotFoundView';
@@ -52,16 +52,23 @@ function WorkspaceWorkflowsApprovalsApprovalLimitPage({policy, isLoadingReportDa
     const currentApprover = approvalWorkflow?.approvers?.[approverIndex];
     const currency = policy?.outputCurrency ?? CONST.CURRENCY.USD;
 
-    const [approvalLimit, setApprovalLimit] = useState<string>(() => {
+    const selectedApproverEmail = currentApprover?.overLimitForwardsTo ?? '';
+
+    const defaultApprovalLimit = useMemo(() => {
         if (currentApprover?.approvalLimit) {
             return convertToFrontendAmountAsString(currentApprover.approvalLimit, currency);
         }
         return '';
-    });
+    }, [currentApprover?.approvalLimit, currency]);
 
+    const [approvalLimit, setApprovalLimit] = useState(defaultApprovalLimit);
     const [hasSubmitted, setHasSubmitted] = useState(false);
 
-    const selectedApproverEmail = currentApprover?.overLimitForwardsTo ?? '';
+    useEffect(() => {
+        if (selectedApproverEmail) {
+            setHasSubmitted(false);
+        }
+    }, [selectedApproverEmail]);
 
     const selectedApproverDisplayName = useMemo(() => {
         if (!selectedApproverEmail) {
@@ -71,40 +78,22 @@ function WorkspaceWorkflowsApprovalsApprovalLimitPage({policy, isLoadingReportDa
         return Str.removeSMSDomain(personalDetails?.displayName ?? selectedApproverEmail);
     }, [selectedApproverEmail, personalDetailsByEmail]);
 
-    const isCircularReference = useMemo(() => {
-        if (!selectedApproverEmail || !currentApprover?.email) {
-            return false;
-        }
-        return currentApprover.email === selectedApproverEmail;
-    }, [selectedApproverEmail, currentApprover?.email]);
-
     // eslint-disable-next-line rulesdir/no-negated-variables
     const shouldShowNotFoundView = (isEmptyObject(policy) && !isLoadingReportData) || !isPolicyAdmin(policy) || isPendingDeletePolicy(policy);
 
+    const approverDisplayName = currentApprover ? Str.removeSMSDomain(currentApprover.displayName) : '';
+    const isApproverSelected = isEditFlow ? approverDisplayName.length > 0 : true;
+    const areLimitFieldsDisabled = isEditFlow && !isApproverSelected;
+
     const hasAmount = approvalLimit.length > 0 && Number(approvalLimit) > 0;
     const hasApprover = selectedApproverEmail.length > 0;
-
     const bothEmpty = !hasAmount && !hasApprover;
     const onlyAmountEmpty = !hasAmount && hasApprover;
     const onlyApproverEmpty = hasAmount && !hasApprover;
 
-    const approverDisplayName = currentApprover ? Str.removeSMSDomain(currentApprover.displayName) : '';
-    const isApproverSelected = isEditFlow ? approverDisplayName.length > 0 : true;
-    const areLimitFieldsDisabled = isEditFlow && !isApproverSelected;
-    const shouldShowRemoveLimitRow = isEditFlow && (hasAmount || hasApprover);
-
-    // In edit mode, user can save with both empty (removes limit). In create mode, show error on submit.
-    const bottomErrorMessage = hasSubmitted && bothEmpty && !isEditFlow ? translate('workflowsApprovalLimitPage.enterBothError') : '';
-    const amountErrorText = onlyAmountEmpty ? translate('workflowsApprovalLimitPage.enterAmountError') : undefined;
-    const approverErrorText = useMemo(() => {
-        if (isCircularReference) {
-            return translate('workflowsApprovalLimitPage.circularReferenceError', {approverName: selectedApproverDisplayName});
-        }
-        if (onlyApproverEmpty) {
-            return translate('workflowsApprovalLimitPage.enterApproverError');
-        }
-        return undefined;
-    }, [onlyApproverEmpty, isCircularReference, selectedApproverDisplayName, translate]);
+    const amountError = hasSubmitted && onlyAmountEmpty ? translate('workflowsApprovalLimitPage.enterAmountError') : undefined;
+    const approverErrorText = hasSubmitted && onlyApproverEmpty ? translate('workflowsApprovalLimitPage.enterApproverError') : undefined;
+    const bottomError = hasSubmitted && bothEmpty && !isEditFlow ? translate('workflowsApprovalLimitPage.enterBothError') : undefined;
 
     const handleSkip = useCallback(() => {
         if (approvalWorkflow && currentApprover) {
@@ -128,15 +117,11 @@ function WorkspaceWorkflowsApprovalsApprovalLimitPage({policy, isLoadingReportDa
         }
     }, [approvalWorkflow, currentApprover, approverIndex, policy, personalDetailsByEmail, isEditFlow, backTo, policyID]);
 
-    const handleNext = useCallback(() => {
-        setHasSubmitted(true);
-
-        const hasValidationError = isCircularReference || onlyAmountEmpty || onlyApproverEmpty || (!isEditFlow && bothEmpty);
-        if (hasValidationError || !approvalWorkflow || !currentApprover) {
+    const handleSubmit = useCallback(() => {
+        if (!approvalWorkflow || !currentApprover) {
             return;
         }
 
-        // In edit mode with both empty, clear the limit (same as Remove limit)
         if (isEditFlow && bothEmpty) {
             setApprovalWorkflowApprover({
                 approver: {
@@ -153,6 +138,11 @@ function WorkspaceWorkflowsApprovalsApprovalLimitPage({policy, isLoadingReportDa
             return;
         }
 
+        if (bothEmpty || onlyAmountEmpty || onlyApproverEmpty) {
+            setHasSubmitted(true);
+            return;
+        }
+
         const limitInCents = convertToBackendAmount(Number.parseFloat(approvalLimit));
 
         setApprovalWorkflowApprover({
@@ -173,12 +163,11 @@ function WorkspaceWorkflowsApprovalsApprovalLimitPage({policy, isLoadingReportDa
             Navigation.navigate(ROUTES.WORKSPACE_WORKFLOWS_APPROVALS_NEW.getRoute(policyID));
         }
     }, [
-        approvalLimit,
-        selectedApproverEmail,
-        isCircularReference,
+        bothEmpty,
         onlyAmountEmpty,
         onlyApproverEmpty,
-        bothEmpty,
+        approvalLimit,
+        selectedApproverEmail,
         isEditFlow,
         approvalWorkflow,
         currentApprover,
@@ -189,43 +178,43 @@ function WorkspaceWorkflowsApprovalsApprovalLimitPage({policy, isLoadingReportDa
         policyID,
     ]);
 
-    const navigateToApproverSelector = useCallback(() => {
-        if (approvalWorkflow && currentApprover && approvalLimit) {
-            const limitInCents = convertToBackendAmount(Number.parseFloat(approvalLimit));
-            setApprovalWorkflowApprover({
-                approver: {
-                    ...currentApprover,
-                    approvalLimit: limitInCents,
-                },
-                approverIndex,
-                currentApprovalWorkflow: approvalWorkflow,
-                policy,
-                personalDetailsByEmail,
-            });
+    const handleAmountChange = useCallback((value: string) => {
+        setApprovalLimit(value);
+        setHasSubmitted(false);
+    }, []);
+
+    const saveCurrentStateToOnyx = useCallback(() => {
+        if (!approvalWorkflow || !currentApprover) {
+            return;
         }
+        const limitInCents = approvalLimit ? convertToBackendAmount(Number.parseFloat(approvalLimit)) : null;
+        setApprovalWorkflowApprover({
+            approver: {
+                ...currentApprover,
+                approvalLimit: limitInCents,
+                overLimitForwardsTo: selectedApproverEmail,
+            },
+            approverIndex,
+            currentApprovalWorkflow: approvalWorkflow,
+            policy,
+            personalDetailsByEmail,
+        });
+    }, [approvalWorkflow, currentApprover, approvalLimit, selectedApproverEmail, approverIndex, policy, personalDetailsByEmail]);
+
+    const navigateToApproverSelector = useCallback(() => {
+        saveCurrentStateToOnyx();
         Navigation.navigate(ROUTES.WORKSPACE_WORKFLOWS_APPROVALS_OVER_LIMIT_APPROVER.getRoute(policyID, approverIndex, backTo));
-    }, [policyID, approverIndex, approvalWorkflow, currentApprover, approvalLimit, policy, personalDetailsByEmail, backTo]);
+    }, [saveCurrentStateToOnyx, policyID, approverIndex, backTo]);
 
     const navigateToApproverChange = useCallback(() => {
-        if (approvalWorkflow && currentApprover) {
-            const limitInCents = approvalLimit ? convertToBackendAmount(Number.parseFloat(approvalLimit)) : currentApprover.approvalLimit;
-            setApprovalWorkflowApprover({
-                approver: {
-                    ...currentApprover,
-                    approvalLimit: limitInCents,
-                    overLimitForwardsTo: selectedApproverEmail || currentApprover.overLimitForwardsTo,
-                },
-                approverIndex,
-                currentApprovalWorkflow: approvalWorkflow,
-                policy,
-                personalDetailsByEmail,
-            });
-        }
+        saveCurrentStateToOnyx();
         Navigation.navigate(ROUTES.WORKSPACE_WORKFLOWS_APPROVALS_APPROVER.getRoute(policyID, approverIndex, backTo));
-    }, [policyID, approverIndex, backTo, approvalWorkflow, currentApprover, approvalLimit, selectedApproverEmail, policy, personalDetailsByEmail]);
+    }, [saveCurrentStateToOnyx, policyID, approverIndex, backTo]);
 
     const buttonContainerStyle = useBottomSafeSafeAreaPaddingStyle({addBottomSafeAreaPadding: true, style: [styles.mh5, styles.mb5]});
 
+    const shouldShowRemoveLimitRow = isEditFlow && (hasAmount || hasApprover);
+
     return (
         <AccessOrNotFoundWrapper
             policyID={policyID}
@@ -280,11 +269,11 @@ function WorkspaceWorkflowsApprovalsApprovalLimitPage({policy, isLoadingReportDa
                                     label={translate('workflowsApprovalLimitPage.reportAmountLabel')}
                                     currency={currency}
                                     value={approvalLimit}
-                                    onInputChange={setApprovalLimit}
+                                    onInputChange={handleAmountChange}
                                     isCurrencyPressable={false}
                                     displayAsTextInput
-                                    errorText={amountErrorText}
                                     disabled={areLimitFieldsDisabled}
+                                    errorText={amountError}
                                 />
                             </View>
 
@@ -298,7 +287,6 @@ function WorkspaceWorkflowsApprovalsApprovalLimitPage({policy, isLoadingReportDa
                                 wrapperStyle={styles.sectionMenuItemTopDescription}
                                 brickRoadIndicator={approverErrorText ? CONST.BRICK_ROAD_INDICATOR_STATUS.ERROR : undefined}
                                 errorText={approverErrorText}
-                                shouldRenderErrorAsHTML
                                 disabled={areLimitFieldsDisabled}
                                 shouldGreyOutWhenDisabled
                             />
@@ -312,16 +300,16 @@ function WorkspaceWorkflowsApprovalsApprovalLimitPage({policy, isLoadingReportDa
                                 />
                             )}
                         </View>
-
-                        {!!bottomErrorMessage && (
-                            <DotIndicatorMessage
-                                type="error"
-                                messages={{error: bottomErrorMessage}}
-                                style={[styles.mh5, styles.mb3]}
-                            />
-                        )}
                     </ScrollView>
 
+                    {!!bottomError && (
+                        <DotIndicatorMessage
+                            type="error"
+                            messages={{error: bottomError}}
+                            style={[styles.mh5, styles.mb3]}
+                        />
+                    )}
+
                     <View style={buttonContainerStyle}>
                         {!isEditFlow && (
                             <Button
@@ -335,7 +323,7 @@ function WorkspaceWorkflowsApprovalsApprovalLimitPage({policy, isLoadingReportDa
                             large
                             success
                             text={isEditFlow ? translate('common.save') : translate('workflowsApprovalLimitPage.next')}
-                            onPress={handleNext}
+                            onPress={handleSubmit}
                         />
                     </View>
                 </FullPageNotFoundView>
diff --git a/src/pages/workspace/workflows/approvals/WorkspaceWorkflowsApprovalsOverLimitApproverPage.tsx b/src/pages/workspace/workflows/approvals/WorkspaceWorkflowsApprovalsOverLimitApproverPage.tsx
index aa3b7dcf5928..75476883ada0 100644
--- a/src/pages/workspace/workflows/approvals/WorkspaceWorkflowsApprovalsOverLimitApproverPage.tsx
+++ b/src/pages/workspace/workflows/approvals/WorkspaceWorkflowsApprovalsOverLimitApproverPage.tsx
@@ -45,6 +45,8 @@ function WorkspaceWorkflowsApprovalsOverLimitApproverPage({policy, personalDetai
     const isDefault = approvalWorkflow?.isDefault;
     const membersEmail = useMemo(() => approvalWorkflow?.members.map((member) => member.email), [approvalWorkflow?.members]);
 
+    const currentApproverEmail = currentApprover?.email;
+
     const allApprovers: SelectionListApprover[] = useMemo(() => {
         if (isApprovalWorkflowLoading || !employeeList) {
             return [];
@@ -64,6 +66,10 @@ function WorkspaceWorkflowsApprovalsOverLimitApproverPage({policy, personalDetai
                     return null;
                 }
 
+                if (email === currentApproverEmail) {
+                    return null;
+                }
+
                 const accountID = Number(policyMemberEmailsToAccountIDs[email] ?? '');
                 const {avatar, displayName = email, login} = personalDetails?.[accountID] ?? {};
 
@@ -94,6 +100,7 @@ function WorkspaceWorkflowsApprovalsOverLimitApproverPage({policy, personalDetai
         expensifyIcons.FallbackAvatar,
         isDefault,
         membersEmail,
+        currentApproverEmail,
     ]);
 
     const shouldShowListEmptyContent = !!approvalWorkflow && !isApprovalWorkflowLoading;

From 1841e82a4aa79da61a8e048e359aad2ee4140636 Mon Sep 17 00:00:00 2001
From: Abdelrahman Khattab <abzokhattab@gmail.com>
Date: Thu, 4 Dec 2025 00:27:30 +0100
Subject: [PATCH 22/49] fixing goback naviagtion bug in approver page

---
 ...paceWorkflowsApprovalsApprovalLimitPage.tsx |  8 +++++---
 ...WorkspaceWorkflowsApprovalsApproverPage.tsx | 18 +++++++++++-------
 2 files changed, 16 insertions(+), 10 deletions(-)

diff --git a/src/pages/workspace/workflows/approvals/WorkspaceWorkflowsApprovalsApprovalLimitPage.tsx b/src/pages/workspace/workflows/approvals/WorkspaceWorkflowsApprovalsApprovalLimitPage.tsx
index f1ea209269ba..14f666ce3f56 100644
--- a/src/pages/workspace/workflows/approvals/WorkspaceWorkflowsApprovalsApprovalLimitPage.tsx
+++ b/src/pages/workspace/workflows/approvals/WorkspaceWorkflowsApprovalsApprovalLimitPage.tsx
@@ -65,9 +65,10 @@ function WorkspaceWorkflowsApprovalsApprovalLimitPage({policy, isLoadingReportDa
     const [hasSubmitted, setHasSubmitted] = useState(false);
 
     useEffect(() => {
-        if (selectedApproverEmail) {
-            setHasSubmitted(false);
+        if (!selectedApproverEmail) {
+            return;
         }
+        setHasSubmitted(false);
     }, [selectedApproverEmail]);
 
     const selectedApproverDisplayName = useMemo(() => {
@@ -208,7 +209,8 @@ function WorkspaceWorkflowsApprovalsApprovalLimitPage({policy, isLoadingReportDa
 
     const navigateToApproverChange = useCallback(() => {
         saveCurrentStateToOnyx();
-        Navigation.navigate(ROUTES.WORKSPACE_WORKFLOWS_APPROVALS_APPROVER.getRoute(policyID, approverIndex, backTo));
+        const approvalLimitBackTo = ROUTES.WORKSPACE_WORKFLOWS_APPROVALS_APPROVAL_LIMIT.getRoute(policyID, approverIndex, backTo);
+        Navigation.navigate(ROUTES.WORKSPACE_WORKFLOWS_APPROVALS_APPROVER.getRoute(policyID, approverIndex, approvalLimitBackTo));
     }, [saveCurrentStateToOnyx, policyID, approverIndex, backTo]);
 
     const buttonContainerStyle = useBottomSafeSafeAreaPaddingStyle({addBottomSafeAreaPadding: true, style: [styles.mh5, styles.mb5]});
diff --git a/src/pages/workspace/workflows/approvals/WorkspaceWorkflowsApprovalsApproverPage.tsx b/src/pages/workspace/workflows/approvals/WorkspaceWorkflowsApprovalsApproverPage.tsx
index 3f67f5596001..c9c342b7a0c7 100644
--- a/src/pages/workspace/workflows/approvals/WorkspaceWorkflowsApprovalsApproverPage.tsx
+++ b/src/pages/workspace/workflows/approvals/WorkspaceWorkflowsApprovalsApproverPage.tsx
@@ -19,7 +19,7 @@ import type {WithPolicyAndFullscreenLoadingProps} from '@pages/workspace/withPol
 import CONST from '@src/CONST';
 import ONYXKEYS from '@src/ONYXKEYS';
 import ROUTES from '@src/ROUTES';
-import type SCREENS from '@src/SCREENS';
+import SCREENS from '@src/SCREENS';
 import {personalDetailsByEmailSelector} from '@src/selectors/PersonalDetails';
 import isLoadingOnyxValue from '@src/types/utils/isLoadingOnyxValue';
 
@@ -165,16 +165,20 @@ function WorkspaceWorkflowsApprovalsApproverPage({policy, personalDetails, isLoa
                 personalDetailsByEmail,
             });
 
-            if (currentApprovalWorkflow?.action === CONST.APPROVAL_WORKFLOW.ACTION.EDIT) {
-                goBack();
+            const isLimitPageInStack = rhpRoutes.some((rhpRoute) => rhpRoute.name === SCREENS.WORKSPACE.WORKFLOWS_APPROVALS_APPROVAL_LIMIT);
+            if (isLimitPageInStack) {
+                Navigation.goBack();
                 return;
             }
 
-            Navigation.navigate(
-                ROUTES.WORKSPACE_WORKFLOWS_APPROVALS_APPROVAL_LIMIT.getRoute(route.params.policyID, approverIndex, ROUTES.WORKSPACE_WORKFLOWS_APPROVALS_NEW.getRoute(route.params.policyID)),
-            );
+            const backToRoute =
+                currentApprovalWorkflow?.action === CONST.APPROVAL_WORKFLOW.ACTION.EDIT
+                    ? ROUTES.WORKSPACE_WORKFLOWS_APPROVALS_EDIT.getRoute(route.params.policyID, firstApprover)
+                    : ROUTES.WORKSPACE_WORKFLOWS_APPROVALS_NEW.getRoute(route.params.policyID);
+
+            Navigation.navigate(ROUTES.WORKSPACE_WORKFLOWS_APPROVALS_APPROVAL_LIMIT.getRoute(route.params.policyID, approverIndex, backToRoute));
         },
-        [approverIndex, currentApprovalWorkflow, employeeList, personalDetails, policy, route.params.policyID, goBack, personalDetailsByEmail],
+        [approverIndex, currentApprovalWorkflow, employeeList, personalDetails, policy, route.params.policyID, goBack, personalDetailsByEmail, firstApprover, rhpRoutes],
     );
 
     const subtitle = useMemo(

From 398e0ac1d3faac8a5f412768ff4cc913f96c2a42 Mon Sep 17 00:00:00 2001
From: Abdelrahman Khattab <abzokhattab@gmail.com>
Date: Thu, 4 Dec 2025 22:42:56 +0100
Subject: [PATCH 23/49] code refactoring

---
 ...aceWorkflowsApprovalsApprovalLimitPage.tsx | 109 ++++++++----------
 1 file changed, 46 insertions(+), 63 deletions(-)

diff --git a/src/pages/workspace/workflows/approvals/WorkspaceWorkflowsApprovalsApprovalLimitPage.tsx b/src/pages/workspace/workflows/approvals/WorkspaceWorkflowsApprovalsApprovalLimitPage.tsx
index 14f666ce3f56..3e9980d86873 100644
--- a/src/pages/workspace/workflows/approvals/WorkspaceWorkflowsApprovalsApprovalLimitPage.tsx
+++ b/src/pages/workspace/workflows/approvals/WorkspaceWorkflowsApprovalsApprovalLimitPage.tsx
@@ -31,6 +31,7 @@ import ONYXKEYS from '@src/ONYXKEYS';
 import ROUTES from '@src/ROUTES';
 import type SCREENS from '@src/SCREENS';
 import {personalDetailsByEmailSelector} from '@src/selectors/PersonalDetails';
+import type {Approver} from '@src/types/onyx/ApprovalWorkflow';
 import {isEmptyObject} from '@src/types/utils/EmptyObject';
 
 type WorkspaceWorkflowsApprovalsApprovalLimitPageProps = WithPolicyAndFullscreenLoadingProps &
@@ -46,7 +47,7 @@ function WorkspaceWorkflowsApprovalsApprovalLimitPage({policy, isLoadingReportDa
     });
 
     const policyID = route.params.policyID;
-    const approverIndex = Number(route.params.approverIndex) ?? 0;
+    const approverIndex = Number(route.params.approverIndex) || 0;
     const backTo = route.params?.backTo;
     const isEditFlow = approvalWorkflow?.action === CONST.APPROVAL_WORKFLOW.ACTION.EDIT;
     const currentApprover = approvalWorkflow?.approvers?.[approverIndex];
@@ -96,27 +97,44 @@ function WorkspaceWorkflowsApprovalsApprovalLimitPage({policy, isLoadingReportDa
     const approverErrorText = hasSubmitted && onlyApproverEmpty ? translate('workflowsApprovalLimitPage.enterApproverError') : undefined;
     const bottomError = hasSubmitted && bothEmpty && !isEditFlow ? translate('workflowsApprovalLimitPage.enterBothError') : undefined;
 
-    const handleSkip = useCallback(() => {
-        if (approvalWorkflow && currentApprover) {
+    const navigateAfterCompletion = useCallback(() => {
+        if (isEditFlow) {
+            Navigation.goBack(backTo);
+            return;
+        }
+        Navigation.navigate(ROUTES.WORKSPACE_WORKFLOWS_APPROVALS_NEW.getRoute(policyID));
+    }, [isEditFlow, backTo, policyID]);
+
+    const updateCurrentApprover = useCallback(
+        (update: Partial<Approver>) => {
+            if (!approvalWorkflow || !currentApprover) {
+                return;
+            }
             setApprovalWorkflowApprover({
                 approver: {
                     ...currentApprover,
-                    approvalLimit: null,
-                    overLimitForwardsTo: '',
+                    ...update,
                 },
                 approverIndex,
                 currentApprovalWorkflow: approvalWorkflow,
                 policy,
                 personalDetailsByEmail,
             });
-        }
+        },
+        [approvalWorkflow, currentApprover, approverIndex, policy, personalDetailsByEmail],
+    );
 
-        if (isEditFlow) {
-            Navigation.goBack(backTo);
-        } else {
-            Navigation.navigate(ROUTES.WORKSPACE_WORKFLOWS_APPROVALS_NEW.getRoute(policyID));
-        }
-    }, [approvalWorkflow, currentApprover, approverIndex, policy, personalDetailsByEmail, isEditFlow, backTo, policyID]);
+    const resetApprovalLimit = useCallback(() => {
+        updateCurrentApprover({
+            approvalLimit: null,
+            overLimitForwardsTo: '',
+        });
+    }, [updateCurrentApprover]);
+
+    const handleSkip = useCallback(() => {
+        resetApprovalLimit();
+        navigateAfterCompletion();
+    }, [resetApprovalLimit, navigateAfterCompletion]);
 
     const handleSubmit = useCallback(() => {
         if (!approvalWorkflow || !currentApprover) {
@@ -124,18 +142,8 @@ function WorkspaceWorkflowsApprovalsApprovalLimitPage({policy, isLoadingReportDa
         }
 
         if (isEditFlow && bothEmpty) {
-            setApprovalWorkflowApprover({
-                approver: {
-                    ...currentApprover,
-                    approvalLimit: null,
-                    overLimitForwardsTo: '',
-                },
-                approverIndex,
-                currentApprovalWorkflow: approvalWorkflow,
-                policy,
-                personalDetailsByEmail,
-            });
-            Navigation.goBack(backTo);
+            resetApprovalLimit();
+            navigateAfterCompletion();
             return;
         }
 
@@ -145,38 +153,23 @@ function WorkspaceWorkflowsApprovalsApprovalLimitPage({policy, isLoadingReportDa
         }
 
         const limitInCents = convertToBackendAmount(Number.parseFloat(approvalLimit));
-
-        setApprovalWorkflowApprover({
-            approver: {
-                ...currentApprover,
-                approvalLimit: limitInCents,
-                overLimitForwardsTo: selectedApproverEmail,
-            },
-            approverIndex,
-            currentApprovalWorkflow: approvalWorkflow,
-            policy,
-            personalDetailsByEmail,
+        updateCurrentApprover({
+            approvalLimit: limitInCents,
+            overLimitForwardsTo: selectedApproverEmail,
         });
-
-        if (isEditFlow) {
-            Navigation.goBack(backTo);
-        } else {
-            Navigation.navigate(ROUTES.WORKSPACE_WORKFLOWS_APPROVALS_NEW.getRoute(policyID));
-        }
+        navigateAfterCompletion();
     }, [
+        approvalWorkflow,
+        currentApprover,
+        isEditFlow,
         bothEmpty,
         onlyAmountEmpty,
         onlyApproverEmpty,
         approvalLimit,
         selectedApproverEmail,
-        isEditFlow,
-        approvalWorkflow,
-        currentApprover,
-        approverIndex,
-        policy,
-        personalDetailsByEmail,
-        backTo,
-        policyID,
+        resetApprovalLimit,
+        navigateAfterCompletion,
+        updateCurrentApprover,
     ]);
 
     const handleAmountChange = useCallback((value: string) => {
@@ -185,22 +178,12 @@ function WorkspaceWorkflowsApprovalsApprovalLimitPage({policy, isLoadingReportDa
     }, []);
 
     const saveCurrentStateToOnyx = useCallback(() => {
-        if (!approvalWorkflow || !currentApprover) {
-            return;
-        }
         const limitInCents = approvalLimit ? convertToBackendAmount(Number.parseFloat(approvalLimit)) : null;
-        setApprovalWorkflowApprover({
-            approver: {
-                ...currentApprover,
-                approvalLimit: limitInCents,
-                overLimitForwardsTo: selectedApproverEmail,
-            },
-            approverIndex,
-            currentApprovalWorkflow: approvalWorkflow,
-            policy,
-            personalDetailsByEmail,
+        updateCurrentApprover({
+            approvalLimit: limitInCents,
+            overLimitForwardsTo: selectedApproverEmail,
         });
-    }, [approvalWorkflow, currentApprover, approvalLimit, selectedApproverEmail, approverIndex, policy, personalDetailsByEmail]);
+    }, [approvalLimit, selectedApproverEmail, updateCurrentApprover]);
 
     const navigateToApproverSelector = useCallback(() => {
         saveCurrentStateToOnyx();

From f634b5bc3634376c0f6eae929ed94e3751fe75d7 Mon Sep 17 00:00:00 2001
From: Abdelrahman Khattab <abzokhattab@gmail.com>
Date: Thu, 4 Dec 2025 23:23:19 +0100
Subject: [PATCH 24/49] fixing goback in the approver page

---
 ...orkspaceWorkflowsApprovalsApprovalLimitPage.tsx | 14 ++++++++++++--
 .../WorkspaceWorkflowsApprovalsApproverPage.tsx    |  6 ++++--
 2 files changed, 16 insertions(+), 4 deletions(-)

diff --git a/src/pages/workspace/workflows/approvals/WorkspaceWorkflowsApprovalsApprovalLimitPage.tsx b/src/pages/workspace/workflows/approvals/WorkspaceWorkflowsApprovalsApprovalLimitPage.tsx
index 3e9980d86873..ad0828731974 100644
--- a/src/pages/workspace/workflows/approvals/WorkspaceWorkflowsApprovalsApprovalLimitPage.tsx
+++ b/src/pages/workspace/workflows/approvals/WorkspaceWorkflowsApprovalsApprovalLimitPage.tsx
@@ -92,9 +92,18 @@ function WorkspaceWorkflowsApprovalsApprovalLimitPage({policy, isLoadingReportDa
     const bothEmpty = !hasAmount && !hasApprover;
     const onlyAmountEmpty = !hasAmount && hasApprover;
     const onlyApproverEmpty = hasAmount && !hasApprover;
+    const isCircularReference = hasApprover && currentApprover?.email === selectedApproverEmail;
 
     const amountError = hasSubmitted && onlyAmountEmpty ? translate('workflowsApprovalLimitPage.enterAmountError') : undefined;
-    const approverErrorText = hasSubmitted && onlyApproverEmpty ? translate('workflowsApprovalLimitPage.enterApproverError') : undefined;
+    const approverErrorText = useMemo(() => {
+        if (hasSubmitted && isCircularReference) {
+            return translate('workflowsApprovalLimitPage.circularReferenceError', {approverName: selectedApproverDisplayName});
+        }
+        if (hasSubmitted && onlyApproverEmpty) {
+            return translate('workflowsApprovalLimitPage.enterApproverError');
+        }
+        return undefined;
+    }, [hasSubmitted, isCircularReference, onlyApproverEmpty, translate, selectedApproverDisplayName]);
     const bottomError = hasSubmitted && bothEmpty && !isEditFlow ? translate('workflowsApprovalLimitPage.enterBothError') : undefined;
 
     const navigateAfterCompletion = useCallback(() => {
@@ -147,7 +156,7 @@ function WorkspaceWorkflowsApprovalsApprovalLimitPage({policy, isLoadingReportDa
             return;
         }
 
-        if (bothEmpty || onlyAmountEmpty || onlyApproverEmpty) {
+        if (bothEmpty || onlyAmountEmpty || onlyApproverEmpty || isCircularReference) {
             setHasSubmitted(true);
             return;
         }
@@ -165,6 +174,7 @@ function WorkspaceWorkflowsApprovalsApprovalLimitPage({policy, isLoadingReportDa
         bothEmpty,
         onlyAmountEmpty,
         onlyApproverEmpty,
+        isCircularReference,
         approvalLimit,
         selectedApproverEmail,
         resetApprovalLimit,
diff --git a/src/pages/workspace/workflows/approvals/WorkspaceWorkflowsApprovalsApproverPage.tsx b/src/pages/workspace/workflows/approvals/WorkspaceWorkflowsApprovalsApproverPage.tsx
index c9c342b7a0c7..b612437b38f9 100644
--- a/src/pages/workspace/workflows/approvals/WorkspaceWorkflowsApprovalsApproverPage.tsx
+++ b/src/pages/workspace/workflows/approvals/WorkspaceWorkflowsApprovalsApproverPage.tsx
@@ -171,12 +171,14 @@ function WorkspaceWorkflowsApprovalsApproverPage({policy, personalDetails, isLoa
                 return;
             }
 
-            const backToRoute =
+            const approverPageBackTo =
                 currentApprovalWorkflow?.action === CONST.APPROVAL_WORKFLOW.ACTION.EDIT
                     ? ROUTES.WORKSPACE_WORKFLOWS_APPROVALS_EDIT.getRoute(route.params.policyID, firstApprover)
                     : ROUTES.WORKSPACE_WORKFLOWS_APPROVALS_NEW.getRoute(route.params.policyID);
 
-            Navigation.navigate(ROUTES.WORKSPACE_WORKFLOWS_APPROVALS_APPROVAL_LIMIT.getRoute(route.params.policyID, approverIndex, backToRoute));
+            const limitPageBackTo = ROUTES.WORKSPACE_WORKFLOWS_APPROVALS_APPROVER.getRoute(route.params.policyID, approverIndex, approverPageBackTo);
+
+            Navigation.navigate(ROUTES.WORKSPACE_WORKFLOWS_APPROVALS_APPROVAL_LIMIT.getRoute(route.params.policyID, approverIndex, limitPageBackTo));
         },
         [approverIndex, currentApprovalWorkflow, employeeList, personalDetails, policy, route.params.policyID, goBack, personalDetailsByEmail, firstApprover, rhpRoutes],
     );

From e9fe538dfafcfe320d530edb417ab71670b673f4 Mon Sep 17 00:00:00 2001
From: Abdelrahman Khattab <abzokhattab@gmail.com>
Date: Fri, 5 Dec 2025 00:07:05 +0100
Subject: [PATCH 25/49] resetting the limit and additional approver when the
 main approval is unset

---
 src/components/NumberWithSymbolForm.tsx                   | 8 ++++++++
 .../WorkspaceWorkflowsApprovalsApprovalLimitPage.tsx      | 4 ++++
 2 files changed, 12 insertions(+)

diff --git a/src/components/NumberWithSymbolForm.tsx b/src/components/NumberWithSymbolForm.tsx
index af04f5d9bce7..94253d1a1331 100644
--- a/src/components/NumberWithSymbolForm.tsx
+++ b/src/components/NumberWithSymbolForm.tsx
@@ -154,6 +154,14 @@ function NumberWithSymbolForm({
     const numberRef = useRef<string | undefined>(undefined);
     const [currentNumber, setCurrentNumber] = useState(typeof number === 'string' ? number : '');
 
+    useEffect(() => {
+        const newNumber = typeof number === 'string' ? number : '';
+        if (newNumber !== currentNumber) {
+            setCurrentNumber(newNumber);
+        }
+        // eslint-disable-next-line react-compiler/react-compiler, react-hooks/exhaustive-deps
+    }, [number]);
+
     const [shouldUpdateSelection, setShouldUpdateSelection] = useState(true);
 
     const isFocused = useIsFocused();
diff --git a/src/pages/workspace/workflows/approvals/WorkspaceWorkflowsApprovalsApprovalLimitPage.tsx b/src/pages/workspace/workflows/approvals/WorkspaceWorkflowsApprovalsApprovalLimitPage.tsx
index ad0828731974..7b4c47003dd0 100644
--- a/src/pages/workspace/workflows/approvals/WorkspaceWorkflowsApprovalsApprovalLimitPage.tsx
+++ b/src/pages/workspace/workflows/approvals/WorkspaceWorkflowsApprovalsApprovalLimitPage.tsx
@@ -72,6 +72,10 @@ function WorkspaceWorkflowsApprovalsApprovalLimitPage({policy, isLoadingReportDa
         setHasSubmitted(false);
     }, [selectedApproverEmail]);
 
+    useEffect(() => {
+        setApprovalLimit(defaultApprovalLimit);
+    }, [defaultApprovalLimit]);
+
     const selectedApproverDisplayName = useMemo(() => {
         if (!selectedApproverEmail) {
             return '';

From cc3ff222e80b5d0f32d3e93c70905707fb44a005 Mon Sep 17 00:00:00 2001
From: Abdelrahman Khattab <abzokhattab@gmail.com>
Date: Fri, 5 Dec 2025 16:04:02 +0100
Subject: [PATCH 26/49] making approvel description same as exisitng hittext

---
 .../workspace/workflows/approvals/ApprovalWorkflowEditor.tsx | 5 +----
 1 file changed, 1 insertion(+), 4 deletions(-)

diff --git a/src/pages/workspace/workflows/approvals/ApprovalWorkflowEditor.tsx b/src/pages/workspace/workflows/approvals/ApprovalWorkflowEditor.tsx
index e274c200f880..0ad6c9c83d9e 100644
--- a/src/pages/workspace/workflows/approvals/ApprovalWorkflowEditor.tsx
+++ b/src/pages/workspace/workflows/approvals/ApprovalWorkflowEditor.tsx
@@ -174,8 +174,7 @@ function ApprovalWorkflowEditor({approvalWorkflow, removeApprovalWorkflow, polic
                     const hintText =
                         !errorText && approvalWorkflow.usedApproverEmails.some((approverEmail) => approverEmail === approver?.email)
                             ? translate('workflowsPage.approverInMultipleWorkflows')
-                            : undefined;
-                    const approvalLimitDescription = getApprovalLimitDescription({approver, currency, translate, personalDetailsByEmail});
+                            : getApprovalLimitDescription({approver, currency, translate, personalDetailsByEmail});
 
                     return (
                         <OfflineWithFeedback
@@ -196,8 +195,6 @@ function ApprovalWorkflowEditor({approvalWorkflow, removeApprovalWorkflow, polic
                                 brickRoadIndicator={errorText ? CONST.BRICK_ROAD_INDICATOR_STATUS.ERROR : undefined}
                                 errorText={errorText}
                                 shouldRenderErrorAsHTML
-                                helperText={approvalLimitDescription}
-                                helperTextStyle={styles.pl0}
                             />
                         </OfflineWithFeedback>
                     );

From 8ffd7e1ed76f6e9389a8e1ebb25a19cf7fe856cf Mon Sep 17 00:00:00 2001
From: Abdelrahman Khattab <abzokhattab@gmail.com>
Date: Fri, 5 Dec 2025 17:03:08 +0100
Subject: [PATCH 27/49] cleanup: revert circularRferenceError

---
 src/languages/de.ts                                      | 2 --
 src/languages/en.ts                                      | 2 --
 src/languages/es.ts                                      | 2 --
 src/languages/fr.ts                                      | 2 --
 src/languages/it.ts                                      | 2 --
 src/languages/ja.ts                                      | 2 --
 src/languages/nl.ts                                      | 2 --
 src/languages/pl.ts                                      | 2 --
 src/languages/pt-BR.ts                                   | 2 --
 src/languages/zh-hans.ts                                 | 1 -
 .../WorkspaceWorkflowsApprovalsApprovalLimitPage.tsx     | 9 ++-------
 .../WorkspaceWorkflowsApprovalsApproverPage.tsx          | 5 ++---
 12 files changed, 4 insertions(+), 29 deletions(-)

diff --git a/src/languages/de.ts b/src/languages/de.ts
index 3036227fbb80..9c937cf79c94 100644
--- a/src/languages/de.ts
+++ b/src/languages/de.ts
@@ -2198,8 +2198,6 @@ ${amount} für ${merchant} - ${date}`,
         enterAmountError: 'Bitte geben Sie einen gültigen Betrag ein',
         enterApproverError: 'Ein Genehmiger ist erforderlich, wenn Sie ein Berichtslimit haben',
         enterBothError: 'Geben Sie einen Berichtsbetrag und einen zusätzlichen Genehmiger ein',
-        circularReferenceError: ({approverName}: {approverName: string}) =>
-            `<strong>${approverName}</strong> genehmigt bereits Berichte in diesem Workflow. Wählen Sie einen anderen Genehmiger, um einen zirkulären Workflow zu vermeiden.`,
         forwardLimitDescription: ({approvalLimit, approverName}: {approvalLimit: string; approverName: string}) => `Berichte über ${approvalLimit} werden an ${approverName} weitergeleitet`,
     },
     workflowsPayerPage: {
diff --git a/src/languages/en.ts b/src/languages/en.ts
index a6a1620fe8c4..84c01ef9f807 100755
--- a/src/languages/en.ts
+++ b/src/languages/en.ts
@@ -2298,8 +2298,6 @@ const translations = {
         enterAmountError: 'Please enter a valid amount',
         enterApproverError: 'Approver is required when you have a report limit',
         enterBothError: 'Enter a report amount and additional approver',
-        circularReferenceError: ({approverName}: {approverName: string}) =>
-            `<strong>${approverName}</strong> already approves reports in this workflow. Choose a different approver to avoid a circular workflow.`,
         forwardLimitDescription: ({approvalLimit, approverName}: {approvalLimit: string; approverName: string}) => `Reports above ${approvalLimit} forward to ${approverName}`,
     },
     workflowsPayerPage: {
diff --git a/src/languages/es.ts b/src/languages/es.ts
index a01ed0cb1c28..79ccf93be0e4 100644
--- a/src/languages/es.ts
+++ b/src/languages/es.ts
@@ -1940,8 +1940,6 @@ ${amount} para ${merchant} - ${date}`,
         enterAmountError: 'Por favor, introduce un importe válido',
         enterApproverError: 'Se requiere un aprobador cuando tienes un límite de informe',
         enterBothError: 'Introduce un importe del informe y un aprobador adicional',
-        circularReferenceError: ({approverName}: {approverName: string}) =>
-            `<strong>${approverName}</strong> ya aprueba informes en este flujo de trabajo. Elige un aprobador diferente para evitar un flujo de trabajo circular.`,
         forwardLimitDescription: ({approvalLimit, approverName}: {approvalLimit: string; approverName: string}) => `Los informes superiores a ${approvalLimit} se envían a ${approverName}`,
     },
     workflowsPayerPage: {
diff --git a/src/languages/fr.ts b/src/languages/fr.ts
index 916b9985331e..24267133da3b 100644
--- a/src/languages/fr.ts
+++ b/src/languages/fr.ts
@@ -2198,8 +2198,6 @@ ${amount} pour ${merchant} - ${date}`,
         enterAmountError: 'Veuillez entrer un montant valide',
         enterApproverError: 'Un approbateur est requis lorsque vous avez une limite de rapport',
         enterBothError: 'Entrez un montant de rapport et un approbateur supplémentaire',
-        circularReferenceError: ({approverName}: {approverName: string}) =>
-            `<strong>${approverName}</strong> approuve déjà des rapports dans ce flux de travail. Choisissez un autre approbateur pour éviter un flux circulaire.`,
         forwardLimitDescription: ({approvalLimit, approverName}: {approvalLimit: string; approverName: string}) =>
             `Les rapports supérieurs à ${approvalLimit} sont transférés à ${approverName}`,
     },
diff --git a/src/languages/it.ts b/src/languages/it.ts
index 292a3a2d59eb..4cbd4f04a96d 100644
--- a/src/languages/it.ts
+++ b/src/languages/it.ts
@@ -2191,8 +2191,6 @@ ${amount} per ${merchant} - ${date}`,
         enterAmountError: 'Inserisci un importo valido',
         enterApproverError: 'Un approvatore è richiesto quando hai un limite di report',
         enterBothError: 'Inserisci un importo del report e un approvatore aggiuntivo',
-        circularReferenceError: ({approverName}: {approverName: string}) =>
-            `<strong>${approverName}</strong> approva già i report in questo flusso di lavoro. Scegli un approvatore diverso per evitare un flusso circolare.`,
         forwardLimitDescription: ({approvalLimit, approverName}: {approvalLimit: string; approverName: string}) =>
             `I report superiori a ${approvalLimit} vengono inoltrati a ${approverName}`,
     },
diff --git a/src/languages/ja.ts b/src/languages/ja.ts
index acd8c3d2c2a1..3568ff120966 100644
--- a/src/languages/ja.ts
+++ b/src/languages/ja.ts
@@ -2182,8 +2182,6 @@ ${date} - ${merchant}に${amount}`,
         enterAmountError: '有効な金額を入力してください',
         enterApproverError: 'レポート制限がある場合は承認者が必要です',
         enterBothError: 'レポート金額と追加の承認者を入力してください',
-        circularReferenceError: ({approverName}: {approverName: string}) =>
-            `<strong>${approverName}</strong>はすでにこのワークフローでレポートを承認しています。循環ワークフローを避けるために別の承認者を選択してください。`,
         forwardLimitDescription: ({approvalLimit, approverName}: {approvalLimit: string; approverName: string}) => `${approvalLimit}を超えるレポートは${approverName}に転送されます`,
     },
     workflowsPayerPage: {
diff --git a/src/languages/nl.ts b/src/languages/nl.ts
index 6032e22d68b2..e91de3f4cde6 100644
--- a/src/languages/nl.ts
+++ b/src/languages/nl.ts
@@ -2189,8 +2189,6 @@ ${amount} voor ${merchant} - ${date}`,
         enterAmountError: 'Voer een geldig bedrag in',
         enterApproverError: 'Een goedkeurder is vereist wanneer u een rapportlimiet heeft',
         enterBothError: 'Voer een rapportbedrag en een extra goedkeurder in',
-        circularReferenceError: ({approverName}: {approverName: string}) =>
-            `<strong>${approverName}</strong> keurt al rapporten goed in deze workflow. Kies een andere goedkeurder om een circulaire workflow te vermijden.`,
         forwardLimitDescription: ({approvalLimit, approverName}: {approvalLimit: string; approverName: string}) =>
             `Rapporten boven ${approvalLimit} worden doorgestuurd naar ${approverName}`,
     },
diff --git a/src/languages/pl.ts b/src/languages/pl.ts
index 0829dc653b3c..5b18e747ea5b 100644
--- a/src/languages/pl.ts
+++ b/src/languages/pl.ts
@@ -2186,8 +2186,6 @@ ${amount} dla ${merchant} - ${date}`,
         enterAmountError: 'Wprowadź prawidłową kwotę',
         enterApproverError: 'Zatwierdzający jest wymagany, gdy masz limit raportu',
         enterBothError: 'Wprowadź kwotę raportu i dodatkowego zatwierdzającego',
-        circularReferenceError: ({approverName}: {approverName: string}) =>
-            `<strong>${approverName}</strong> już zatwierdza raporty w tym przepływie pracy. Wybierz innego zatwierdzającego, aby uniknąć cyklicznego przepływu pracy.`,
         forwardLimitDescription: ({approvalLimit, approverName}: {approvalLimit: string; approverName: string}) => `Raporty powyżej ${approvalLimit} są przekazywane do ${approverName}`,
     },
     workflowsPayerPage: {
diff --git a/src/languages/pt-BR.ts b/src/languages/pt-BR.ts
index 83fd7896ea87..375cc198f19e 100644
--- a/src/languages/pt-BR.ts
+++ b/src/languages/pt-BR.ts
@@ -2185,8 +2185,6 @@ ${amount} para ${merchant} - ${date}`,
         enterAmountError: 'Por favor, insira um valor válido',
         enterApproverError: 'Um aprovador é necessário quando você tem um limite de relatório',
         enterBothError: 'Insira um valor do relatório e um aprovador adicional',
-        circularReferenceError: ({approverName}: {approverName: string}) =>
-            `<strong>${approverName}</strong> já aprova relatórios neste fluxo de trabalho. Escolha um aprovador diferente para evitar um fluxo circular.`,
         forwardLimitDescription: ({approvalLimit, approverName}: {approvalLimit: string; approverName: string}) =>
             `Relatórios acima de ${approvalLimit} são encaminhados para ${approverName}`,
     },
diff --git a/src/languages/zh-hans.ts b/src/languages/zh-hans.ts
index f76772981235..c1f6accd3d5d 100644
--- a/src/languages/zh-hans.ts
+++ b/src/languages/zh-hans.ts
@@ -2154,7 +2154,6 @@ ${merchant}的${amount} - ${date}`,
         enterAmountError: '请输入有效金额',
         enterApproverError: '设置报告限额时需要审批人',
         enterBothError: '请输入报告金额和额外审批人',
-        circularReferenceError: ({approverName}: {approverName: string}) => `<strong>${approverName}</strong>已在此工作流程中审批报告。请选择其他审批人以避免循环工作流程。`,
         forwardLimitDescription: ({approvalLimit, approverName}: {approvalLimit: string; approverName: string}) => `超过${approvalLimit}的报告将转发给${approverName}`,
     },
     workflowsPayerPage: {
diff --git a/src/pages/workspace/workflows/approvals/WorkspaceWorkflowsApprovalsApprovalLimitPage.tsx b/src/pages/workspace/workflows/approvals/WorkspaceWorkflowsApprovalsApprovalLimitPage.tsx
index 7b4c47003dd0..801f4ead8618 100644
--- a/src/pages/workspace/workflows/approvals/WorkspaceWorkflowsApprovalsApprovalLimitPage.tsx
+++ b/src/pages/workspace/workflows/approvals/WorkspaceWorkflowsApprovalsApprovalLimitPage.tsx
@@ -96,18 +96,14 @@ function WorkspaceWorkflowsApprovalsApprovalLimitPage({policy, isLoadingReportDa
     const bothEmpty = !hasAmount && !hasApprover;
     const onlyAmountEmpty = !hasAmount && hasApprover;
     const onlyApproverEmpty = hasAmount && !hasApprover;
-    const isCircularReference = hasApprover && currentApprover?.email === selectedApproverEmail;
 
     const amountError = hasSubmitted && onlyAmountEmpty ? translate('workflowsApprovalLimitPage.enterAmountError') : undefined;
     const approverErrorText = useMemo(() => {
-        if (hasSubmitted && isCircularReference) {
-            return translate('workflowsApprovalLimitPage.circularReferenceError', {approverName: selectedApproverDisplayName});
-        }
         if (hasSubmitted && onlyApproverEmpty) {
             return translate('workflowsApprovalLimitPage.enterApproverError');
         }
         return undefined;
-    }, [hasSubmitted, isCircularReference, onlyApproverEmpty, translate, selectedApproverDisplayName]);
+    }, [hasSubmitted, onlyApproverEmpty, translate]);
     const bottomError = hasSubmitted && bothEmpty && !isEditFlow ? translate('workflowsApprovalLimitPage.enterBothError') : undefined;
 
     const navigateAfterCompletion = useCallback(() => {
@@ -160,7 +156,7 @@ function WorkspaceWorkflowsApprovalsApprovalLimitPage({policy, isLoadingReportDa
             return;
         }
 
-        if (bothEmpty || onlyAmountEmpty || onlyApproverEmpty || isCircularReference) {
+        if (bothEmpty || onlyAmountEmpty || onlyApproverEmpty) {
             setHasSubmitted(true);
             return;
         }
@@ -178,7 +174,6 @@ function WorkspaceWorkflowsApprovalsApprovalLimitPage({policy, isLoadingReportDa
         bothEmpty,
         onlyAmountEmpty,
         onlyApproverEmpty,
-        isCircularReference,
         approvalLimit,
         selectedApproverEmail,
         resetApprovalLimit,
diff --git a/src/pages/workspace/workflows/approvals/WorkspaceWorkflowsApprovalsApproverPage.tsx b/src/pages/workspace/workflows/approvals/WorkspaceWorkflowsApprovalsApproverPage.tsx
index ce4c2b0e30a1..e351ff4fd59e 100644
--- a/src/pages/workspace/workflows/approvals/WorkspaceWorkflowsApprovalsApproverPage.tsx
+++ b/src/pages/workspace/workflows/approvals/WorkspaceWorkflowsApprovalsApproverPage.tsx
@@ -142,15 +142,14 @@ function WorkspaceWorkflowsApprovalsApproverPage({policy, personalDetails, isLoa
             const policyMemberEmailsToAccountIDs = getMemberAccountIDsForWorkspace(employeeList);
             const accountID = Number(newSelectedEmail ? policyMemberEmailsToAccountIDs[newSelectedEmail] : '');
             const {avatar, displayName = newSelectedEmail} = personalDetails?.[accountID] ?? {};
-            const existingApprover = currentApprovalWorkflow?.approvers?.[approverIndex];
 
             setApprovalWorkflowApprover({
                 approver: {
                     email: newSelectedEmail,
                     avatar,
                     displayName,
-                    approvalLimit: existingApprover?.approvalLimit,
-                    overLimitForwardsTo: existingApprover?.overLimitForwardsTo,
+                    approvalLimit: null,
+                    overLimitForwardsTo: '',
                 },
                 approverIndex,
                 currentApprovalWorkflow,

From 354709ec97556794782fca6277b3c0e34c0e96cd Mon Sep 17 00:00:00 2001
From: Abdelrahman Khattab <abzokhattab@gmail.com>
Date: Fri, 5 Dec 2025 19:35:06 +0100
Subject: [PATCH 28/49] fix navigation bugs

---
 .../approvals/ApprovalWorkflowEditor.tsx      |  9 +++++++--
 ...aceWorkflowsApprovalsApprovalLimitPage.tsx | 20 ++++++++++++++-----
 ...orkspaceWorkflowsApprovalsApproverPage.tsx | 10 ++++++----
 3 files changed, 28 insertions(+), 11 deletions(-)

diff --git a/src/pages/workspace/workflows/approvals/ApprovalWorkflowEditor.tsx b/src/pages/workspace/workflows/approvals/ApprovalWorkflowEditor.tsx
index 0ad6c9c83d9e..608acef874cf 100644
--- a/src/pages/workspace/workflows/approvals/ApprovalWorkflowEditor.tsx
+++ b/src/pages/workspace/workflows/approvals/ApprovalWorkflowEditor.tsx
@@ -131,6 +131,11 @@ function ApprovalWorkflowEditor({approvalWorkflow, removeApprovalWorkflow, polic
 
     // User should be allowed to add additional approver only if they upgraded to Control Plan, otherwise redirected to the Upgrade Page
     const addAdditionalApprover = useCallback(() => {
+        const backTo =
+            approvalWorkflow.action === CONST.APPROVAL_WORKFLOW.ACTION.EDIT
+                ? ROUTES.WORKSPACE_WORKFLOWS_APPROVALS_EDIT.getRoute(policyID, firstApprover)
+                : ROUTES.WORKSPACE_WORKFLOWS_APPROVALS_NEW.getRoute(policyID);
+
         if (!isControlPolicy(policy) && approverCount > 0) {
             Navigation.navigate(
                 ROUTES.WORKSPACE_UPGRADE.getRoute(
@@ -141,8 +146,8 @@ function ApprovalWorkflowEditor({approvalWorkflow, removeApprovalWorkflow, polic
             );
             return;
         }
-        Navigation.navigate(ROUTES.WORKSPACE_WORKFLOWS_APPROVALS_APPROVER.getRoute(policyID, approverCount, ROUTES.WORKSPACE_WORKFLOWS_APPROVALS_NEW.getRoute(policyID)));
-    }, [approverCount, policy, policyID]);
+        Navigation.navigate(ROUTES.WORKSPACE_WORKFLOWS_APPROVALS_APPROVER.getRoute(policyID, approverCount, backTo));
+    }, [approvalWorkflow.action, approverCount, firstApprover, policy, policyID]);
 
     return (
         <ScrollView
diff --git a/src/pages/workspace/workflows/approvals/WorkspaceWorkflowsApprovalsApprovalLimitPage.tsx b/src/pages/workspace/workflows/approvals/WorkspaceWorkflowsApprovalsApprovalLimitPage.tsx
index 801f4ead8618..4fe1425e5d7d 100644
--- a/src/pages/workspace/workflows/approvals/WorkspaceWorkflowsApprovalsApprovalLimitPage.tsx
+++ b/src/pages/workspace/workflows/approvals/WorkspaceWorkflowsApprovalsApprovalLimitPage.tsx
@@ -25,7 +25,7 @@ import {goBackFromInvalidPolicy, isPendingDeletePolicy, isPolicyAdmin} from '@li
 import AccessOrNotFoundWrapper from '@pages/workspace/AccessOrNotFoundWrapper';
 import withPolicyAndFullscreenLoading from '@pages/workspace/withPolicyAndFullscreenLoading';
 import type {WithPolicyAndFullscreenLoadingProps} from '@pages/workspace/withPolicyAndFullscreenLoading';
-import {setApprovalWorkflowApprover} from '@userActions/Workflow';
+import {clearApprovalWorkflowApprover, setApprovalWorkflowApprover} from '@userActions/Workflow';
 import CONST from '@src/CONST';
 import ONYXKEYS from '@src/ONYXKEYS';
 import ROUTES from '@src/ROUTES';
@@ -106,13 +106,16 @@ function WorkspaceWorkflowsApprovalsApprovalLimitPage({policy, isLoadingReportDa
     }, [hasSubmitted, onlyApproverEmpty, translate]);
     const bottomError = hasSubmitted && bothEmpty && !isEditFlow ? translate('workflowsApprovalLimitPage.enterBothError') : undefined;
 
+    const firstApprover = approvalWorkflow?.approvers?.at(0)?.email ?? '';
+
     const navigateAfterCompletion = useCallback(() => {
         if (isEditFlow) {
-            Navigation.goBack(backTo);
+            // In edit mode, always go directly to the Edit page when saving
+            Navigation.goBack(ROUTES.WORKSPACE_WORKFLOWS_APPROVALS_EDIT.getRoute(policyID, firstApprover));
             return;
         }
         Navigation.navigate(ROUTES.WORKSPACE_WORKFLOWS_APPROVALS_NEW.getRoute(policyID));
-    }, [isEditFlow, backTo, policyID]);
+    }, [isEditFlow, policyID, firstApprover]);
 
     const updateCurrentApprover = useCallback(
         (update: Partial<Approver>) => {
@@ -146,7 +149,13 @@ function WorkspaceWorkflowsApprovalsApprovalLimitPage({policy, isLoadingReportDa
     }, [resetApprovalLimit, navigateAfterCompletion]);
 
     const handleSubmit = useCallback(() => {
-        if (!approvalWorkflow || !currentApprover) {
+        if (!approvalWorkflow) {
+            return;
+        }
+
+        if (!currentApprover) {
+            clearApprovalWorkflowApprover({approverIndex, currentApprovalWorkflow: approvalWorkflow});
+            navigateAfterCompletion();
             return;
         }
 
@@ -171,6 +180,7 @@ function WorkspaceWorkflowsApprovalsApprovalLimitPage({policy, isLoadingReportDa
         approvalWorkflow,
         currentApprover,
         isEditFlow,
+        approverIndex,
         bothEmpty,
         onlyAmountEmpty,
         onlyApproverEmpty,
@@ -227,7 +237,7 @@ function WorkspaceWorkflowsApprovalsApprovalLimitPage({policy, isLoadingReportDa
                 >
                     <HeaderWithBackButton
                         title={isEditFlow ? translate('workflowsPage.approver') : translate('workflowsApprovalLimitPage.title')}
-                        onBackButtonPress={() => Navigation.goBack(backTo)}
+                        onBackButtonPress={() => Navigation.goBack()}
                     />
                     <ScrollView
                         style={styles.flex1}
diff --git a/src/pages/workspace/workflows/approvals/WorkspaceWorkflowsApprovalsApproverPage.tsx b/src/pages/workspace/workflows/approvals/WorkspaceWorkflowsApprovalsApproverPage.tsx
index e351ff4fd59e..439ed74d7aff 100644
--- a/src/pages/workspace/workflows/approvals/WorkspaceWorkflowsApprovalsApproverPage.tsx
+++ b/src/pages/workspace/workflows/approvals/WorkspaceWorkflowsApprovalsApproverPage.tsx
@@ -37,7 +37,9 @@ function WorkspaceWorkflowsApprovalsApproverPage({policy, personalDetails, isLoa
         selector: personalDetailsByEmailSelector,
     });
     const approverIndex = Number(route.params.approverIndex) ?? 0;
-    const isInitialCreationFlow = currentApprovalWorkflow?.action === CONST.APPROVAL_WORKFLOW.ACTION.CREATE && !route.params.backTo;
+    const backTo = route.params.backTo;
+    const isInitialCreationFlow = currentApprovalWorkflow?.action === CONST.APPROVAL_WORKFLOW.ACTION.CREATE && !backTo;
+    const isComingFromLimitPage = backTo?.includes(ROUTES.WORKSPACE_WORKFLOWS_APPROVALS_APPROVAL_LIMIT.route) ?? false;
     const defaultApprover = getDefaultApprover(policy);
     const firstApprover = currentApprovalWorkflow?.approvers?.[0]?.email ?? '';
     const rhpRoutes = useNavigationState((state) => state.routes);
@@ -157,8 +159,8 @@ function WorkspaceWorkflowsApprovalsApproverPage({policy, personalDetails, isLoa
                 personalDetailsByEmail,
             });
 
-            const isLimitPageInStack = rhpRoutes.some((rhpRoute) => rhpRoute.name === SCREENS.WORKSPACE.WORKFLOWS_APPROVALS_APPROVAL_LIMIT);
-            if (isLimitPageInStack) {
+            // If we came from the Limit page (changing approver), go back to it
+            if (isComingFromLimitPage) {
                 Navigation.goBack();
                 return;
             }
@@ -172,7 +174,7 @@ function WorkspaceWorkflowsApprovalsApproverPage({policy, personalDetails, isLoa
 
             Navigation.navigate(ROUTES.WORKSPACE_WORKFLOWS_APPROVALS_APPROVAL_LIMIT.getRoute(route.params.policyID, approverIndex, limitPageBackTo));
         },
-        [approverIndex, currentApprovalWorkflow, employeeList, personalDetails, policy, route.params.policyID, goBack, personalDetailsByEmail, firstApprover, rhpRoutes],
+        [approverIndex, currentApprovalWorkflow, employeeList, personalDetails, policy, route.params.policyID, goBack, personalDetailsByEmail, firstApprover, isComingFromLimitPage],
     );
 
     const subtitle = useMemo(

From 80a4a04185365689a1764d184aebb337c44efb48 Mon Sep 17 00:00:00 2001
From: Abdelrahman Khattab <abzokhattab@gmail.com>
Date: Fri, 5 Dec 2025 20:06:26 +0100
Subject: [PATCH 29/49] fixing eslint

---
 .../WorkspaceWorkflowsApprovalsApproverPage.tsx      | 12 ++++++------
 1 file changed, 6 insertions(+), 6 deletions(-)

diff --git a/src/pages/workspace/workflows/approvals/WorkspaceWorkflowsApprovalsApproverPage.tsx b/src/pages/workspace/workflows/approvals/WorkspaceWorkflowsApprovalsApproverPage.tsx
index 439ed74d7aff..b89bfce86e16 100644
--- a/src/pages/workspace/workflows/approvals/WorkspaceWorkflowsApprovalsApproverPage.tsx
+++ b/src/pages/workspace/workflows/approvals/WorkspaceWorkflowsApprovalsApproverPage.tsx
@@ -19,7 +19,7 @@ import type {WithPolicyAndFullscreenLoadingProps} from '@pages/workspace/withPol
 import CONST from '@src/CONST';
 import ONYXKEYS from '@src/ONYXKEYS';
 import ROUTES from '@src/ROUTES';
-import SCREENS from '@src/SCREENS';
+import type SCREENS from '@src/SCREENS';
 import {personalDetailsByEmailSelector} from '@src/selectors/PersonalDetails';
 import isLoadingOnyxValue from '@src/types/utils/isLoadingOnyxValue';
 
@@ -117,16 +117,16 @@ function WorkspaceWorkflowsApprovalsApproverPage({policy, personalDetails, isLoa
     const shouldShowListEmptyContent = !!currentApprovalWorkflow && !isApprovalWorkflowLoading;
 
     const goBack = useCallback(() => {
-        let backTo;
+        let backToRoute;
         if (isInitialCreationFlow) {
-            backTo = ROUTES.WORKSPACE_WORKFLOWS_APPROVALS_EXPENSES_FROM.getRoute(route.params.policyID);
+            backToRoute = ROUTES.WORKSPACE_WORKFLOWS_APPROVALS_EXPENSES_FROM.getRoute(route.params.policyID);
             clearApprovalWorkflowApprovers();
         } else if (currentApprovalWorkflow?.action === CONST.APPROVAL_WORKFLOW.ACTION.EDIT) {
-            backTo = rhpRoutes.length > 1 ? undefined : ROUTES.WORKSPACE_WORKFLOWS_APPROVALS_EDIT.getRoute(route.params.policyID, firstApprover);
+            backToRoute = rhpRoutes.length > 1 ? undefined : ROUTES.WORKSPACE_WORKFLOWS_APPROVALS_EDIT.getRoute(route.params.policyID, firstApprover);
         } else {
-            backTo = ROUTES.WORKSPACE_WORKFLOWS_APPROVALS_NEW.getRoute(route.params.policyID);
+            backToRoute = ROUTES.WORKSPACE_WORKFLOWS_APPROVALS_NEW.getRoute(route.params.policyID);
         }
-        Navigation.goBack(backTo);
+        Navigation.goBack(backToRoute);
     }, [isInitialCreationFlow, currentApprovalWorkflow?.action, route.params.policyID, rhpRoutes.length, firstApprover]);
 
     const toggleApprover = useCallback(

From 550bb147a7a6feb1411d85e90ad4b0622c3dff78 Mon Sep 17 00:00:00 2001
From: Abdelrahman Khattab <abzokhattab@gmail.com>
Date: Sat, 6 Dec 2025 14:45:29 +0100
Subject: [PATCH 30/49] Replace useEffect with render-phase sync in
 NumberWithSymbolForm

---
 src/components/NumberWithSymbolForm.tsx | 7 ++++---
 1 file changed, 4 insertions(+), 3 deletions(-)

diff --git a/src/components/NumberWithSymbolForm.tsx b/src/components/NumberWithSymbolForm.tsx
index 94253d1a1331..4f2bc4879b48 100644
--- a/src/components/NumberWithSymbolForm.tsx
+++ b/src/components/NumberWithSymbolForm.tsx
@@ -152,15 +152,16 @@ function NumberWithSymbolForm({
 
     const textInput = useRef<BaseTextInputRef | null>(null);
     const numberRef = useRef<string | undefined>(undefined);
+    const prevNumberProp = useRef(number);
     const [currentNumber, setCurrentNumber] = useState(typeof number === 'string' ? number : '');
 
-    useEffect(() => {
+    if (number !== prevNumberProp.current) {
+        prevNumberProp.current = number;
         const newNumber = typeof number === 'string' ? number : '';
         if (newNumber !== currentNumber) {
             setCurrentNumber(newNumber);
         }
-        // eslint-disable-next-line react-compiler/react-compiler, react-hooks/exhaustive-deps
-    }, [number]);
+    }
 
     const [shouldUpdateSelection, setShouldUpdateSelection] = useState(true);
 

From 1ca54ed5712df89f0bc8c576103cc7bbbd934a08 Mon Sep 17 00:00:00 2001
From: Abdelrahman Khattab <abzokhattab@gmail.com>
Date: Sat, 6 Dec 2025 16:07:44 +0100
Subject: [PATCH 31/49] refactor: simplify approvals navigation and remove
 `backTo` usage

---
 src/ROUTES.ts                                 | 12 +++----
 src/SCREENS.ts                                |  1 +
 .../ModalStackNavigators/index.tsx            |  1 +
 .../RELATIONS/WORKSPACE_TO_RHP.ts             |  1 +
 src/libs/Navigation/linkingConfig/config.ts   |  3 ++
 src/libs/Navigation/types.ts                  |  8 ++---
 src/pages/workspace/withPolicy.tsx            |  1 +
 .../approvals/ApprovalWorkflowEditor.tsx      |  6 ++--
 ...aceWorkflowsApprovalsApprovalLimitPage.tsx | 11 +++---
 ...orkspaceWorkflowsApprovalsApproverPage.tsx | 34 ++++++++-----------
 ...orkflowsApprovalsOverLimitApproverPage.tsx |  5 ++-
 11 files changed, 40 insertions(+), 43 deletions(-)

diff --git a/src/ROUTES.ts b/src/ROUTES.ts
index 90260f062827..ee65a18f8d1b 100644
--- a/src/ROUTES.ts
+++ b/src/ROUTES.ts
@@ -1694,17 +1694,17 @@ const ROUTES = {
             // eslint-disable-next-line no-restricted-syntax -- Legacy route generation
             getUrlWithBackToParam(`workspaces/${policyID}/workflows/approvals/approver?approverIndex=${approverIndex}` as const, backTo),
     },
+    WORKSPACE_WORKFLOWS_APPROVALS_APPROVER_CHANGE: {
+        route: 'workspaces/:policyID/workflows/approvals/approver-change',
+        getRoute: (policyID: string, approverIndex: number) => `workspaces/${policyID}/workflows/approvals/approver-change?approverIndex=${approverIndex}` as const,
+    },
     WORKSPACE_WORKFLOWS_APPROVALS_APPROVAL_LIMIT: {
         route: 'workspaces/:policyID/workflows/approvals/approval-limit',
-        getRoute: (policyID: string, approverIndex: number, backTo?: string) =>
-            // eslint-disable-next-line no-restricted-syntax -- Legacy route generation
-            getUrlWithBackToParam(`workspaces/${policyID}/workflows/approvals/approval-limit?approverIndex=${approverIndex}` as const, backTo),
+        getRoute: (policyID: string, approverIndex: number) => `workspaces/${policyID}/workflows/approvals/approval-limit?approverIndex=${approverIndex}` as const,
     },
     WORKSPACE_WORKFLOWS_APPROVALS_OVER_LIMIT_APPROVER: {
         route: 'workspaces/:policyID/workflows/approvals/over-limit-approver',
-        getRoute: (policyID: string, approverIndex: number, backTo?: string) =>
-            // eslint-disable-next-line no-restricted-syntax -- Legacy route generation
-            getUrlWithBackToParam(`workspaces/${policyID}/workflows/approvals/over-limit-approver?approverIndex=${approverIndex}` as const, backTo),
+        getRoute: (policyID: string, approverIndex: number) => `workspaces/${policyID}/workflows/approvals/over-limit-approver?approverIndex=${approverIndex}` as const,
     },
     WORKSPACE_WORKFLOWS_PAYER: {
         route: 'workspaces/:policyID/workflows/payer',
diff --git a/src/SCREENS.ts b/src/SCREENS.ts
index 1ece5081277e..3287cb1ea1a1 100644
--- a/src/SCREENS.ts
+++ b/src/SCREENS.ts
@@ -652,6 +652,7 @@ const SCREENS = {
         WORKFLOWS_APPROVALS_EDIT: 'Workspace_Approvals_Edit',
         WORKFLOWS_APPROVALS_EXPENSES_FROM: 'Workspace_Workflows_Approvals_Expenses_From',
         WORKFLOWS_APPROVALS_APPROVER: 'Workspace_Workflows_Approvals_Approver',
+        WORKFLOWS_APPROVALS_APPROVER_CHANGE: 'Workspace_Workflows_Approvals_Approver_Change',
         WORKFLOWS_APPROVALS_APPROVAL_LIMIT: 'Workspace_Workflows_Approvals_Approval_Limit',
         WORKFLOWS_APPROVALS_OVER_LIMIT_APPROVER: 'Workspace_Workflows_Approvals_Over_Limit_Approver',
         WORKFLOWS_AUTO_REPORTING_FREQUENCY: 'Workspace_Workflows_Auto_Reporting_Frequency',
diff --git a/src/libs/Navigation/AppNavigator/ModalStackNavigators/index.tsx b/src/libs/Navigation/AppNavigator/ModalStackNavigators/index.tsx
index 29244d51fd2d..49295f76f8f4 100644
--- a/src/libs/Navigation/AppNavigator/ModalStackNavigators/index.tsx
+++ b/src/libs/Navigation/AppNavigator/ModalStackNavigators/index.tsx
@@ -475,6 +475,7 @@ const SettingsModalStackNavigator = createModalStackNavigator<SettingsNavigatorP
     [SCREENS.WORKSPACE.WORKFLOWS_APPROVALS_EXPENSES_FROM]: () =>
         require<ReactComponentModule>('../../../../pages/workspace/workflows/approvals/WorkspaceWorkflowsApprovalsExpensesFromPage').default,
     [SCREENS.WORKSPACE.WORKFLOWS_APPROVALS_APPROVER]: () => require<ReactComponentModule>('../../../../pages/workspace/workflows/approvals/WorkspaceWorkflowsApprovalsApproverPage').default,
+    [SCREENS.WORKSPACE.WORKFLOWS_APPROVALS_APPROVER_CHANGE]: () => require<ReactComponentModule>('../../../../pages/workspace/workflows/approvals/WorkspaceWorkflowsApprovalsApproverPage').default,
     [SCREENS.WORKSPACE.WORKFLOWS_APPROVALS_APPROVAL_LIMIT]: () =>
         require<ReactComponentModule>('../../../../pages/workspace/workflows/approvals/WorkspaceWorkflowsApprovalsApprovalLimitPage').default,
     [SCREENS.WORKSPACE.WORKFLOWS_APPROVALS_OVER_LIMIT_APPROVER]: () =>
diff --git a/src/libs/Navigation/linkingConfig/RELATIONS/WORKSPACE_TO_RHP.ts b/src/libs/Navigation/linkingConfig/RELATIONS/WORKSPACE_TO_RHP.ts
index 0d928793449f..9f8566156aae 100755
--- a/src/libs/Navigation/linkingConfig/RELATIONS/WORKSPACE_TO_RHP.ts
+++ b/src/libs/Navigation/linkingConfig/RELATIONS/WORKSPACE_TO_RHP.ts
@@ -30,6 +30,7 @@ const WORKSPACE_TO_RHP: Partial<Record<keyof WorkspaceSplitNavigatorParamList, s
         SCREENS.WORKSPACE.WORKFLOWS_APPROVALS_EDIT,
         SCREENS.WORKSPACE.WORKFLOWS_APPROVALS_EXPENSES_FROM,
         SCREENS.WORKSPACE.WORKFLOWS_APPROVALS_APPROVER,
+        SCREENS.WORKSPACE.WORKFLOWS_APPROVALS_APPROVER_CHANGE,
         SCREENS.WORKSPACE.WORKFLOWS_APPROVALS_APPROVAL_LIMIT,
         SCREENS.WORKSPACE.WORKFLOWS_APPROVALS_OVER_LIMIT_APPROVER,
         SCREENS.WORKSPACE.WORKFLOWS_AUTO_REPORTING_FREQUENCY,
diff --git a/src/libs/Navigation/linkingConfig/config.ts b/src/libs/Navigation/linkingConfig/config.ts
index 17e85c6f4ba7..a194fa6a6b51 100644
--- a/src/libs/Navigation/linkingConfig/config.ts
+++ b/src/libs/Navigation/linkingConfig/config.ts
@@ -781,6 +781,9 @@ const config: LinkingOptions<RootNavigatorParamList>['config'] = {
                         [SCREENS.WORKSPACE.WORKFLOWS_APPROVALS_APPROVER]: {
                             path: ROUTES.WORKSPACE_WORKFLOWS_APPROVALS_APPROVER.route,
                         },
+                        [SCREENS.WORKSPACE.WORKFLOWS_APPROVALS_APPROVER_CHANGE]: {
+                            path: ROUTES.WORKSPACE_WORKFLOWS_APPROVALS_APPROVER_CHANGE.route,
+                        },
                         [SCREENS.WORKSPACE.WORKFLOWS_APPROVALS_APPROVAL_LIMIT]: {
                             path: ROUTES.WORKSPACE_WORKFLOWS_APPROVALS_APPROVAL_LIMIT.route,
                         },
diff --git a/src/libs/Navigation/types.ts b/src/libs/Navigation/types.ts
index feb93d74c024..446f5764a72f 100644
--- a/src/libs/Navigation/types.ts
+++ b/src/libs/Navigation/types.ts
@@ -2282,17 +2282,17 @@ type WorkspaceSplitNavigatorParamList = {
         // eslint-disable-next-line no-restricted-syntax -- `backTo` usages in this file are legacy. Do not add new `backTo` params to screens. See contributingGuides/NAVIGATION.md
         backTo?: Routes;
     };
+    [SCREENS.WORKSPACE.WORKFLOWS_APPROVALS_APPROVER_CHANGE]: {
+        policyID: string;
+        approverIndex: number;
+    };
     [SCREENS.WORKSPACE.WORKFLOWS_APPROVALS_APPROVAL_LIMIT]: {
         policyID: string;
         approverIndex: number;
-        // eslint-disable-next-line no-restricted-syntax -- `backTo` usages in this file are legacy. Do not add new `backTo` params to screens. See contributingGuides/NAVIGATION.md
-        backTo?: Routes;
     };
     [SCREENS.WORKSPACE.WORKFLOWS_APPROVALS_OVER_LIMIT_APPROVER]: {
         policyID: string;
         approverIndex: number;
-        // eslint-disable-next-line no-restricted-syntax -- `backTo` usages in this file are legacy. Do not add new `backTo` params to screens. See contributingGuides/NAVIGATION.md
-        backTo?: Routes;
     };
     [SCREENS.WORKSPACE.WORKFLOWS_AUTO_REPORTING_FREQUENCY]: {
         policyID: string;
diff --git a/src/pages/workspace/withPolicy.tsx b/src/pages/workspace/withPolicy.tsx
index f16f9421f1d9..6660ee521208 100644
--- a/src/pages/workspace/withPolicy.tsx
+++ b/src/pages/workspace/withPolicy.tsx
@@ -29,6 +29,7 @@ type PolicyRouteName =
     | typeof SCREENS.WORKSPACE.WORKFLOWS_APPROVALS_EDIT
     | typeof SCREENS.WORKSPACE.WORKFLOWS_APPROVALS_EXPENSES_FROM
     | typeof SCREENS.WORKSPACE.WORKFLOWS_APPROVALS_APPROVER
+    | typeof SCREENS.WORKSPACE.WORKFLOWS_APPROVALS_APPROVER_CHANGE
     | typeof SCREENS.WORKSPACE.WORKFLOWS_APPROVALS_APPROVAL_LIMIT
     | typeof SCREENS.WORKSPACE.WORKFLOWS_APPROVALS_OVER_LIMIT_APPROVER
     | typeof SCREENS.WORKSPACE.WORKFLOWS_AUTO_REPORTING_MONTHLY_OFFSET
diff --git a/src/pages/workspace/workflows/approvals/ApprovalWorkflowEditor.tsx b/src/pages/workspace/workflows/approvals/ApprovalWorkflowEditor.tsx
index 608acef874cf..7968f1f422f8 100644
--- a/src/pages/workspace/workflows/approvals/ApprovalWorkflowEditor.tsx
+++ b/src/pages/workspace/workflows/approvals/ApprovalWorkflowEditor.tsx
@@ -121,12 +121,10 @@ function ApprovalWorkflowEditor({approvalWorkflow, removeApprovalWorkflow, polic
             if (approvalWorkflow.action === CONST.APPROVAL_WORKFLOW.ACTION.CREATE) {
                 Navigation.navigate(ROUTES.WORKSPACE_WORKFLOWS_APPROVALS_APPROVER.getRoute(policyID, approverIndex, ROUTES.WORKSPACE_WORKFLOWS_APPROVALS_NEW.getRoute(policyID)));
             } else {
-                Navigation.navigate(
-                    ROUTES.WORKSPACE_WORKFLOWS_APPROVALS_APPROVAL_LIMIT.getRoute(policyID, approverIndex, ROUTES.WORKSPACE_WORKFLOWS_APPROVALS_EDIT.getRoute(policyID, firstApprover)),
-                );
+                Navigation.navigate(ROUTES.WORKSPACE_WORKFLOWS_APPROVALS_APPROVAL_LIMIT.getRoute(policyID, approverIndex));
             }
         },
-        [approvalWorkflow.action, policyID, firstApprover],
+        [approvalWorkflow.action, policyID],
     );
 
     // User should be allowed to add additional approver only if they upgraded to Control Plan, otherwise redirected to the Upgrade Page
diff --git a/src/pages/workspace/workflows/approvals/WorkspaceWorkflowsApprovalsApprovalLimitPage.tsx b/src/pages/workspace/workflows/approvals/WorkspaceWorkflowsApprovalsApprovalLimitPage.tsx
index 4fe1425e5d7d..f7931c1ef5c6 100644
--- a/src/pages/workspace/workflows/approvals/WorkspaceWorkflowsApprovalsApprovalLimitPage.tsx
+++ b/src/pages/workspace/workflows/approvals/WorkspaceWorkflowsApprovalsApprovalLimitPage.tsx
@@ -48,7 +48,6 @@ function WorkspaceWorkflowsApprovalsApprovalLimitPage({policy, isLoadingReportDa
 
     const policyID = route.params.policyID;
     const approverIndex = Number(route.params.approverIndex) || 0;
-    const backTo = route.params?.backTo;
     const isEditFlow = approvalWorkflow?.action === CONST.APPROVAL_WORKFLOW.ACTION.EDIT;
     const currentApprover = approvalWorkflow?.approvers?.[approverIndex];
     const currency = policy?.outputCurrency ?? CONST.CURRENCY.USD;
@@ -206,14 +205,14 @@ function WorkspaceWorkflowsApprovalsApprovalLimitPage({policy, isLoadingReportDa
 
     const navigateToApproverSelector = useCallback(() => {
         saveCurrentStateToOnyx();
-        Navigation.navigate(ROUTES.WORKSPACE_WORKFLOWS_APPROVALS_OVER_LIMIT_APPROVER.getRoute(policyID, approverIndex, backTo));
-    }, [saveCurrentStateToOnyx, policyID, approverIndex, backTo]);
+        Navigation.navigate(ROUTES.WORKSPACE_WORKFLOWS_APPROVALS_OVER_LIMIT_APPROVER.getRoute(policyID, approverIndex));
+    }, [saveCurrentStateToOnyx, policyID, approverIndex]);
 
     const navigateToApproverChange = useCallback(() => {
         saveCurrentStateToOnyx();
-        const approvalLimitBackTo = ROUTES.WORKSPACE_WORKFLOWS_APPROVALS_APPROVAL_LIMIT.getRoute(policyID, approverIndex, backTo);
-        Navigation.navigate(ROUTES.WORKSPACE_WORKFLOWS_APPROVALS_APPROVER.getRoute(policyID, approverIndex, approvalLimitBackTo));
-    }, [saveCurrentStateToOnyx, policyID, approverIndex, backTo]);
+        // Use the dedicated route for changing approver - it will go BACK to this page after selection
+        Navigation.navigate(ROUTES.WORKSPACE_WORKFLOWS_APPROVALS_APPROVER_CHANGE.getRoute(policyID, approverIndex));
+    }, [saveCurrentStateToOnyx, policyID, approverIndex]);
 
     const buttonContainerStyle = useBottomSafeSafeAreaPaddingStyle({addBottomSafeAreaPadding: true, style: [styles.mh5, styles.mb5]});
 
diff --git a/src/pages/workspace/workflows/approvals/WorkspaceWorkflowsApprovalsApproverPage.tsx b/src/pages/workspace/workflows/approvals/WorkspaceWorkflowsApprovalsApproverPage.tsx
index b89bfce86e16..0f7775c5c8d6 100644
--- a/src/pages/workspace/workflows/approvals/WorkspaceWorkflowsApprovalsApproverPage.tsx
+++ b/src/pages/workspace/workflows/approvals/WorkspaceWorkflowsApprovalsApproverPage.tsx
@@ -19,12 +19,12 @@ import type {WithPolicyAndFullscreenLoadingProps} from '@pages/workspace/withPol
 import CONST from '@src/CONST';
 import ONYXKEYS from '@src/ONYXKEYS';
 import ROUTES from '@src/ROUTES';
-import type SCREENS from '@src/SCREENS';
+import SCREENS from '@src/SCREENS';
 import {personalDetailsByEmailSelector} from '@src/selectors/PersonalDetails';
 import isLoadingOnyxValue from '@src/types/utils/isLoadingOnyxValue';
 
 type WorkspaceWorkflowsApprovalsApproverPageProps = WithPolicyAndFullscreenLoadingProps &
-    PlatformStackScreenProps<WorkspaceSplitNavigatorParamList, typeof SCREENS.WORKSPACE.WORKFLOWS_APPROVALS_APPROVER>;
+    PlatformStackScreenProps<WorkspaceSplitNavigatorParamList, typeof SCREENS.WORKSPACE.WORKFLOWS_APPROVALS_APPROVER | typeof SCREENS.WORKSPACE.WORKFLOWS_APPROVALS_APPROVER_CHANGE>;
 
 function WorkspaceWorkflowsApprovalsApproverPage({policy, personalDetails, isLoadingReportData = true, route}: WorkspaceWorkflowsApprovalsApproverPageProps) {
     const styles = useThemeStyles();
@@ -37,12 +37,13 @@ function WorkspaceWorkflowsApprovalsApproverPage({policy, personalDetails, isLoa
         selector: personalDetailsByEmailSelector,
     });
     const approverIndex = Number(route.params.approverIndex) ?? 0;
-    const backTo = route.params.backTo;
-    const isInitialCreationFlow = currentApprovalWorkflow?.action === CONST.APPROVAL_WORKFLOW.ACTION.CREATE && !backTo;
-    const isComingFromLimitPage = backTo?.includes(ROUTES.WORKSPACE_WORKFLOWS_APPROVALS_APPROVAL_LIMIT.route) ?? false;
+    const rhpRoutes = useNavigationState((state) => state.routes);
     const defaultApprover = getDefaultApprover(policy);
     const firstApprover = currentApprovalWorkflow?.approvers?.[0]?.email ?? '';
-    const rhpRoutes = useNavigationState((state) => state.routes);
+
+    const isChangeApproverRoute = route.name === SCREENS.WORKSPACE.WORKFLOWS_APPROVALS_APPROVER_CHANGE;
+    const backTo = 'backTo' in route.params ? route.params.backTo : undefined;
+    const isInitialCreationFlow = currentApprovalWorkflow?.action === CONST.APPROVAL_WORKFLOW.ACTION.CREATE && !backTo;
     const currentApprover = currentApprovalWorkflow?.approvers[approverIndex];
     const selectedApproverEmail = currentApprover?.email;
 
@@ -159,22 +160,15 @@ function WorkspaceWorkflowsApprovalsApproverPage({policy, personalDetails, isLoa
                 personalDetailsByEmail,
             });
 
-            // If we came from the Limit page (changing approver), go back to it
-            if (isComingFromLimitPage) {
-                Navigation.goBack();
-                return;
+            // If this is the change approver route, go back to the Approval Limit page
+            // Otherwise, navigate forward to set the approval limit
+            if (isChangeApproverRoute) {
+                Navigation.goBack(ROUTES.WORKSPACE_WORKFLOWS_APPROVALS_APPROVAL_LIMIT.getRoute(route.params.policyID, approverIndex));
+            } else {
+                Navigation.navigate(ROUTES.WORKSPACE_WORKFLOWS_APPROVALS_APPROVAL_LIMIT.getRoute(route.params.policyID, approverIndex));
             }
-
-            const approverPageBackTo =
-                currentApprovalWorkflow?.action === CONST.APPROVAL_WORKFLOW.ACTION.EDIT
-                    ? ROUTES.WORKSPACE_WORKFLOWS_APPROVALS_EDIT.getRoute(route.params.policyID, firstApprover)
-                    : ROUTES.WORKSPACE_WORKFLOWS_APPROVALS_NEW.getRoute(route.params.policyID);
-
-            const limitPageBackTo = ROUTES.WORKSPACE_WORKFLOWS_APPROVALS_APPROVER.getRoute(route.params.policyID, approverIndex, approverPageBackTo);
-
-            Navigation.navigate(ROUTES.WORKSPACE_WORKFLOWS_APPROVALS_APPROVAL_LIMIT.getRoute(route.params.policyID, approverIndex, limitPageBackTo));
         },
-        [approverIndex, currentApprovalWorkflow, employeeList, personalDetails, policy, route.params.policyID, goBack, personalDetailsByEmail, firstApprover, isComingFromLimitPage],
+        [approverIndex, currentApprovalWorkflow, employeeList, personalDetails, policy, route.params.policyID, goBack, personalDetailsByEmail, isChangeApproverRoute],
     );
 
     const subtitle = useMemo(
diff --git a/src/pages/workspace/workflows/approvals/WorkspaceWorkflowsApprovalsOverLimitApproverPage.tsx b/src/pages/workspace/workflows/approvals/WorkspaceWorkflowsApprovalsOverLimitApproverPage.tsx
index 75476883ada0..78871fc890fe 100644
--- a/src/pages/workspace/workflows/approvals/WorkspaceWorkflowsApprovalsOverLimitApproverPage.tsx
+++ b/src/pages/workspace/workflows/approvals/WorkspaceWorkflowsApprovalsOverLimitApproverPage.tsx
@@ -38,7 +38,6 @@ function WorkspaceWorkflowsApprovalsOverLimitApproverPage({policy, personalDetai
 
     const policyID = route.params.policyID;
     const approverIndex = Number(route.params.approverIndex) ?? 0;
-    const backTo = route.params?.backTo;
     const currentApprover = approvalWorkflow?.approvers?.[approverIndex];
 
     const employeeList = policy?.employeeList;
@@ -106,8 +105,8 @@ function WorkspaceWorkflowsApprovalsOverLimitApproverPage({policy, personalDetai
     const shouldShowListEmptyContent = !!approvalWorkflow && !isApprovalWorkflowLoading;
 
     const goBack = useCallback(() => {
-        Navigation.goBack(ROUTES.WORKSPACE_WORKFLOWS_APPROVALS_APPROVAL_LIMIT.getRoute(policyID, approverIndex, backTo));
-    }, [policyID, approverIndex, backTo]);
+        Navigation.goBack(ROUTES.WORKSPACE_WORKFLOWS_APPROVALS_APPROVAL_LIMIT.getRoute(policyID, approverIndex));
+    }, [policyID, approverIndex]);
 
     const selectApprover = useCallback(
         (approvers: SelectionListApprover[]) => {

From b636f8d74b184fb178306039ec47212a75af8435 Mon Sep 17 00:00:00 2001
From: Abdelrahman Khattab <abzokhattab@gmail.com>
Date: Sat, 6 Dec 2025 16:40:58 +0100
Subject: [PATCH 32/49] fixing eslint

---
 src/languages/fr.ts                                            | 2 +-
 .../Navigation/AppNavigator/ModalStackNavigators/index.tsx     | 3 ++-
 2 files changed, 3 insertions(+), 2 deletions(-)

diff --git a/src/languages/fr.ts b/src/languages/fr.ts
index ff2e3ab2ed60..6eb950f40d98 100644
--- a/src/languages/fr.ts
+++ b/src/languages/fr.ts
@@ -2356,7 +2356,7 @@ ${amount} pour ${merchant} - ${date}`,
     },
     workflowsApproverPage: {
         genericErrorMessage: 'Le valideur n’a pas pu être modifié. Veuillez réessayer ou contacter l’assistance.',
-        header: 'Envoyer à ce membre pour approbation :',
+        title: 'Définir l’approbateur',
         description: 'Cette personne approuvera les dépenses.',
     },
     workflowsApprovalLimitPage: {
diff --git a/src/libs/Navigation/AppNavigator/ModalStackNavigators/index.tsx b/src/libs/Navigation/AppNavigator/ModalStackNavigators/index.tsx
index 49295f76f8f4..b1cc626aa53b 100644
--- a/src/libs/Navigation/AppNavigator/ModalStackNavigators/index.tsx
+++ b/src/libs/Navigation/AppNavigator/ModalStackNavigators/index.tsx
@@ -475,7 +475,8 @@ const SettingsModalStackNavigator = createModalStackNavigator<SettingsNavigatorP
     [SCREENS.WORKSPACE.WORKFLOWS_APPROVALS_EXPENSES_FROM]: () =>
         require<ReactComponentModule>('../../../../pages/workspace/workflows/approvals/WorkspaceWorkflowsApprovalsExpensesFromPage').default,
     [SCREENS.WORKSPACE.WORKFLOWS_APPROVALS_APPROVER]: () => require<ReactComponentModule>('../../../../pages/workspace/workflows/approvals/WorkspaceWorkflowsApprovalsApproverPage').default,
-    [SCREENS.WORKSPACE.WORKFLOWS_APPROVALS_APPROVER_CHANGE]: () => require<ReactComponentModule>('../../../../pages/workspace/workflows/approvals/WorkspaceWorkflowsApprovalsApproverPage').default,
+    [SCREENS.WORKSPACE.WORKFLOWS_APPROVALS_APPROVER_CHANGE]: () =>
+        require<ReactComponentModule>('../../../../pages/workspace/workflows/approvals/WorkspaceWorkflowsApprovalsApproverPage').default,
     [SCREENS.WORKSPACE.WORKFLOWS_APPROVALS_APPROVAL_LIMIT]: () =>
         require<ReactComponentModule>('../../../../pages/workspace/workflows/approvals/WorkspaceWorkflowsApprovalsApprovalLimitPage').default,
     [SCREENS.WORKSPACE.WORKFLOWS_APPROVALS_OVER_LIMIT_APPROVER]: () =>

From ce7e410bda82a7b4af0eeb9da2a8a321839cc4be Mon Sep 17 00:00:00 2001
From: Abdelrahman Khattab <abzokhattab@gmail.com>
Date: Mon, 8 Dec 2025 22:43:34 +0100
Subject: [PATCH 33/49] NumberWithSymbolForm refactor

---
 src/components/NumberWithSymbolForm.tsx | 7 ++-----
 1 file changed, 2 insertions(+), 5 deletions(-)

diff --git a/src/components/NumberWithSymbolForm.tsx b/src/components/NumberWithSymbolForm.tsx
index f6a81443951c..e63c43694736 100644
--- a/src/components/NumberWithSymbolForm.tsx
+++ b/src/components/NumberWithSymbolForm.tsx
@@ -143,7 +143,6 @@ function NumberWithSymbolForm({
     allowFlippingAmount = false,
     toggleNegative,
     clearNegative,
-    disabled = false,
     ref,
     disabled,
     ...props
@@ -153,11 +152,10 @@ function NumberWithSymbolForm({
 
     const textInput = useRef<BaseTextInputRef | null>(null);
     const numberRef = useRef<string | undefined>(undefined);
-    const prevNumberProp = useRef(number);
+    const prevNumber = usePrevious(number);
     const [currentNumber, setCurrentNumber] = useState(typeof number === 'string' ? number : '');
 
-    if (number !== prevNumberProp.current) {
-        prevNumberProp.current = number;
+    if (number !== prevNumber) {
         const newNumber = typeof number === 'string' ? number : '';
         if (newNumber !== currentNumber) {
             setCurrentNumber(newNumber);
@@ -396,7 +394,6 @@ function NumberWithSymbolForm({
                 autoFocus={props.autoFocus}
                 autoGrowExtraSpace={props.autoGrowExtraSpace}
                 autoGrowMarginSide={props.autoGrowMarginSide}
-                disabled={disabled}
             />
         );
     }

From 68065220f5a77b1d8396a92883ada4386b9262a8 Mon Sep 17 00:00:00 2001
From: Abdelrahman Khattab <abzokhattab@gmail.com>
Date: Mon, 8 Dec 2025 22:47:27 +0100
Subject: [PATCH 34/49] using useMemoizedLazyExpensifyIcons for icons

---
 .../WorkspaceWorkflowsApprovalsApprovalLimitPage.tsx         | 5 +++--
 1 file changed, 3 insertions(+), 2 deletions(-)

diff --git a/src/pages/workspace/workflows/approvals/WorkspaceWorkflowsApprovalsApprovalLimitPage.tsx b/src/pages/workspace/workflows/approvals/WorkspaceWorkflowsApprovalsApprovalLimitPage.tsx
index f7931c1ef5c6..c199b35905be 100644
--- a/src/pages/workspace/workflows/approvals/WorkspaceWorkflowsApprovalsApprovalLimitPage.tsx
+++ b/src/pages/workspace/workflows/approvals/WorkspaceWorkflowsApprovalsApprovalLimitPage.tsx
@@ -6,7 +6,6 @@ import FullPageNotFoundView from '@components/BlockingViews/FullPageNotFoundView
 import Button from '@components/Button';
 import DotIndicatorMessage from '@components/DotIndicatorMessage';
 import HeaderWithBackButton from '@components/HeaderWithBackButton';
-import {Trashcan} from '@components/Icon/Expensicons';
 import MenuItem from '@components/MenuItem';
 import MenuItemWithTopDescription from '@components/MenuItemWithTopDescription';
 import RenderHTML from '@components/RenderHTML';
@@ -14,6 +13,7 @@ import ScreenWrapper from '@components/ScreenWrapper';
 import ScrollView from '@components/ScrollView';
 import Text from '@components/Text';
 import useBottomSafeSafeAreaPaddingStyle from '@hooks/useBottomSafeSafeAreaPaddingStyle';
+import {useMemoizedLazyExpensifyIcons} from '@hooks/useLazyAsset';
 import useLocalize from '@hooks/useLocalize';
 import useOnyx from '@hooks/useOnyx';
 import useThemeStyles from '@hooks/useThemeStyles';
@@ -40,6 +40,7 @@ type WorkspaceWorkflowsApprovalsApprovalLimitPageProps = WithPolicyAndFullscreen
 function WorkspaceWorkflowsApprovalsApprovalLimitPage({policy, isLoadingReportData = true, route}: WorkspaceWorkflowsApprovalsApprovalLimitPageProps) {
     const styles = useThemeStyles();
     const {translate} = useLocalize();
+    const icons = useMemoizedLazyExpensifyIcons(['Trashcan'] as const);
     const [approvalWorkflow] = useOnyx(ONYXKEYS.APPROVAL_WORKFLOW, {canBeMissing: true});
     const [personalDetailsByEmail] = useOnyx(ONYXKEYS.PERSONAL_DETAILS_LIST, {
         canBeMissing: true,
@@ -297,7 +298,7 @@ function WorkspaceWorkflowsApprovalsApprovalLimitPage({policy, isLoadingReportDa
                             {shouldShowRemoveLimitRow && (
                                 <MenuItem
                                     title={translate('workflowsApprovalLimitPage.removeLimit')}
-                                    icon={Trashcan}
+                                    icon={icons.Trashcan}
                                     onPress={handleSkip}
                                     wrapperStyle={styles.sectionMenuItemTopDescription}
                                 />

From f8de83b6c18b87428379ff8c103d765868153b4f Mon Sep 17 00:00:00 2001
From: Abdelrahman Khattab <abzokhattab@gmail.com>
Date: Mon, 8 Dec 2025 22:55:00 +0100
Subject: [PATCH 35/49] fixing eslint and icons refactoring

---
 .../Icon/chunks/expensify-icons.chunk.ts          |  2 ++
 src/components/NumberWithSymbolForm.tsx           | 15 ++++++++-------
 2 files changed, 10 insertions(+), 7 deletions(-)

diff --git a/src/components/Icon/chunks/expensify-icons.chunk.ts b/src/components/Icon/chunks/expensify-icons.chunk.ts
index 68d8253c0977..c403b89cc76d 100644
--- a/src/components/Icon/chunks/expensify-icons.chunk.ts
+++ b/src/components/Icon/chunks/expensify-icons.chunk.ts
@@ -163,6 +163,7 @@ import Phone from '@assets/images/phone.svg';
 import Pin from '@assets/images/pin.svg';
 import Plane from '@assets/images/plane.svg';
 import Play from '@assets/images/play.svg';
+import PlusMinus from '@assets/images/plus-minus.svg';
 import Plus from '@assets/images/plus.svg';
 import Printer from '@assets/images/printer.svg';
 import Profile from '@assets/images/profile.svg';
@@ -361,6 +362,7 @@ const Expensicons = {
     Pin,
     Play,
     Plus,
+    PlusMinus,
     Printer,
     Profile,
     QBOSquare,
diff --git a/src/components/NumberWithSymbolForm.tsx b/src/components/NumberWithSymbolForm.tsx
index e63c43694736..cd9a2e02a146 100644
--- a/src/components/NumberWithSymbolForm.tsx
+++ b/src/components/NumberWithSymbolForm.tsx
@@ -3,6 +3,7 @@ import type {ForwardedRef} from 'react';
 import React, {useCallback, useEffect, useImperativeHandle, useRef, useState} from 'react';
 import type {NativeSyntheticEvent} from 'react-native';
 import {View} from 'react-native';
+import {useMemoizedLazyExpensifyIcons} from '@hooks/useLazyAsset';
 import useLocalize from '@hooks/useLocalize';
 import {useMouseContext} from '@hooks/useMouseContext';
 import usePrevious from '@hooks/usePrevious';
@@ -25,7 +26,6 @@ import CONST from '@src/CONST';
 import BigNumberPad from './BigNumberPad';
 import Button from './Button';
 import FormHelpMessage from './FormHelpMessage';
-import * as Expensicons from './Icon/Expensicons';
 import ScrollView from './ScrollView';
 import TextInput from './TextInput';
 import isTextInputFocused from './TextInput/BaseTextInput/isTextInputFocused';
@@ -149,6 +149,7 @@ function NumberWithSymbolForm({
 }: NumberWithSymbolFormProps) {
     const styles = useThemeStyles();
     const {toLocaleDigit, numberFormat, translate} = useLocalize();
+    const icons = useMemoizedLazyExpensifyIcons(['DownArrow', 'PlusMinus'] as const);
 
     const textInput = useRef<BaseTextInputRef | null>(null);
     const numberRef = useRef<string | undefined>(undefined);
@@ -234,11 +235,11 @@ function NumberWithSymbolForm({
             let hasSelectionBeenSet = false;
             const strippedNumber = stripCommaFromAmount(finalNumber);
             numberRef.current = strippedNumber;
-            setCurrentNumber((prevNumber) => {
-                const isForwardDelete = prevNumber.length > strippedNumber.length && forwardDeletePressedRef.current;
+            setCurrentNumber((prevCurrentNumber) => {
+                const isForwardDelete = prevCurrentNumber.length > strippedNumber.length && forwardDeletePressedRef.current;
                 if (!hasSelectionBeenSet) {
                     hasSelectionBeenSet = true;
-                    setSelection((prevSelection) => getNewSelection(prevSelection, isForwardDelete ? strippedNumber.length : prevNumber.length, strippedNumber.length));
+                    setSelection((prevSelection) => getNewSelection(prevSelection, isForwardDelete ? strippedNumber.length : prevCurrentNumber.length, strippedNumber.length));
                     willSelectionBeUpdatedManually.current = false;
                 }
                 return strippedNumber;
@@ -480,7 +481,7 @@ function NumberWithSymbolForm({
                             <Button
                                 shouldShowRightIcon
                                 small
-                                iconRight={Expensicons.DownArrow}
+                                iconRight={icons.DownArrow}
                                 onPress={onSymbolButtonPress}
                                 style={styles.minWidth18}
                                 isContentCentered
@@ -505,7 +506,7 @@ function NumberWithSymbolForm({
                     <Button
                         shouldShowRightIcon
                         small
-                        iconRight={Expensicons.DownArrow}
+                        iconRight={icons.DownArrow}
                         onPress={onSymbolButtonPress}
                         style={styles.minWidth18}
                         isContentCentered
@@ -516,7 +517,7 @@ function NumberWithSymbolForm({
                     <Button
                         shouldShowRightIcon
                         small
-                        iconRight={Expensicons.PlusMinus}
+                        iconRight={icons.PlusMinus}
                         onPress={toggleNegative}
                         style={styles.minWidth18}
                         isContentCentered

From 5d3e709ee0f951a36de575dbcc8809f7d906d499 Mon Sep 17 00:00:00 2001
From: Abdelrahman Khattab <abzokhattab@gmail.com>
Date: Tue, 9 Dec 2025 01:45:46 +0100
Subject: [PATCH 36/49] Allow skipping approval limit when both fields are
 empty

---
 ...WorkspaceWorkflowsApprovalsApprovalLimitPage.tsx | 13 ++-----------
 1 file changed, 2 insertions(+), 11 deletions(-)

diff --git a/src/pages/workspace/workflows/approvals/WorkspaceWorkflowsApprovalsApprovalLimitPage.tsx b/src/pages/workspace/workflows/approvals/WorkspaceWorkflowsApprovalsApprovalLimitPage.tsx
index c199b35905be..8f0221b038b5 100644
--- a/src/pages/workspace/workflows/approvals/WorkspaceWorkflowsApprovalsApprovalLimitPage.tsx
+++ b/src/pages/workspace/workflows/approvals/WorkspaceWorkflowsApprovalsApprovalLimitPage.tsx
@@ -104,7 +104,6 @@ function WorkspaceWorkflowsApprovalsApprovalLimitPage({policy, isLoadingReportDa
         }
         return undefined;
     }, [hasSubmitted, onlyApproverEmpty, translate]);
-    const bottomError = hasSubmitted && bothEmpty && !isEditFlow ? translate('workflowsApprovalLimitPage.enterBothError') : undefined;
 
     const firstApprover = approvalWorkflow?.approvers?.at(0)?.email ?? '';
 
@@ -159,13 +158,13 @@ function WorkspaceWorkflowsApprovalsApprovalLimitPage({policy, isLoadingReportDa
             return;
         }
 
-        if (isEditFlow && bothEmpty) {
+        if (bothEmpty) {
             resetApprovalLimit();
             navigateAfterCompletion();
             return;
         }
 
-        if (bothEmpty || onlyAmountEmpty || onlyApproverEmpty) {
+        if (onlyAmountEmpty || onlyApproverEmpty) {
             setHasSubmitted(true);
             return;
         }
@@ -306,14 +305,6 @@ function WorkspaceWorkflowsApprovalsApprovalLimitPage({policy, isLoadingReportDa
                         </View>
                     </ScrollView>
 
-                    {!!bottomError && (
-                        <DotIndicatorMessage
-                            type="error"
-                            messages={{error: bottomError}}
-                            style={[styles.mh5, styles.mb3]}
-                        />
-                    )}
-
                     <View style={buttonContainerStyle}>
                         {!isEditFlow && (
                             <Button

From 7e71aa03bd4a4b153196758a5f9bd97e264f81c3 Mon Sep 17 00:00:00 2001
From: abzowork <abzokhattab@gmail.com>
Date: Wed, 10 Dec 2025 16:03:09 +0100
Subject: [PATCH 37/49] code refactoring

---
 src/libs/Navigation/types.ts                                   | 2 ++
 .../approvals/WorkspaceWorkflowsApprovalsApprovalLimitPage.tsx | 3 +--
 .../approvals/WorkspaceWorkflowsApprovalsApproverPage.tsx      | 3 +--
 .../approvals/WorkspaceWorkflowsApprovalsCreatePage.tsx        | 2 +-
 4 files changed, 5 insertions(+), 5 deletions(-)

diff --git a/src/libs/Navigation/types.ts b/src/libs/Navigation/types.ts
index 9707d7309d6a..54cd275892cc 100644
--- a/src/libs/Navigation/types.ts
+++ b/src/libs/Navigation/types.ts
@@ -2307,6 +2307,8 @@ type WorkspaceSplitNavigatorParamList = {
     [SCREENS.WORKSPACE.WORKFLOWS_APPROVALS_APPROVER_CHANGE]: {
         policyID: string;
         approverIndex: number;
+        // eslint-disable-next-line no-restricted-syntax -- `backTo` usages in this file are legacy. Do not add new `backTo` params to screens. See contributingGuides/NAVIGATION.md
+        backTo?: Routes;
     };
     [SCREENS.WORKSPACE.WORKFLOWS_APPROVALS_APPROVAL_LIMIT]: {
         policyID: string;
diff --git a/src/pages/workspace/workflows/approvals/WorkspaceWorkflowsApprovalsApprovalLimitPage.tsx b/src/pages/workspace/workflows/approvals/WorkspaceWorkflowsApprovalsApprovalLimitPage.tsx
index 8f0221b038b5..835f582c5012 100644
--- a/src/pages/workspace/workflows/approvals/WorkspaceWorkflowsApprovalsApprovalLimitPage.tsx
+++ b/src/pages/workspace/workflows/approvals/WorkspaceWorkflowsApprovalsApprovalLimitPage.tsx
@@ -4,7 +4,6 @@ import {View} from 'react-native';
 import AmountForm from '@components/AmountForm';
 import FullPageNotFoundView from '@components/BlockingViews/FullPageNotFoundView';
 import Button from '@components/Button';
-import DotIndicatorMessage from '@components/DotIndicatorMessage';
 import HeaderWithBackButton from '@components/HeaderWithBackButton';
 import MenuItem from '@components/MenuItem';
 import MenuItemWithTopDescription from '@components/MenuItemWithTopDescription';
@@ -23,8 +22,8 @@ import type {PlatformStackScreenProps} from '@libs/Navigation/PlatformStackNavig
 import type {WorkspaceSplitNavigatorParamList} from '@libs/Navigation/types';
 import {goBackFromInvalidPolicy, isPendingDeletePolicy, isPolicyAdmin} from '@libs/PolicyUtils';
 import AccessOrNotFoundWrapper from '@pages/workspace/AccessOrNotFoundWrapper';
-import withPolicyAndFullscreenLoading from '@pages/workspace/withPolicyAndFullscreenLoading';
 import type {WithPolicyAndFullscreenLoadingProps} from '@pages/workspace/withPolicyAndFullscreenLoading';
+import withPolicyAndFullscreenLoading from '@pages/workspace/withPolicyAndFullscreenLoading';
 import {clearApprovalWorkflowApprover, setApprovalWorkflowApprover} from '@userActions/Workflow';
 import CONST from '@src/CONST';
 import ONYXKEYS from '@src/ONYXKEYS';
diff --git a/src/pages/workspace/workflows/approvals/WorkspaceWorkflowsApprovalsApproverPage.tsx b/src/pages/workspace/workflows/approvals/WorkspaceWorkflowsApprovalsApproverPage.tsx
index 8cee4cc78bab..3c8e54593056 100644
--- a/src/pages/workspace/workflows/approvals/WorkspaceWorkflowsApprovalsApproverPage.tsx
+++ b/src/pages/workspace/workflows/approvals/WorkspaceWorkflowsApprovalsApproverPage.tsx
@@ -42,8 +42,7 @@ function WorkspaceWorkflowsApprovalsApproverPage({policy, personalDetails, isLoa
     const firstApprover = currentApprovalWorkflow?.approvers?.[0]?.email ?? '';
 
     const isChangeApproverRoute = route.name === SCREENS.WORKSPACE.WORKFLOWS_APPROVALS_APPROVER_CHANGE;
-    const backTo = 'backTo' in route.params ? route.params.backTo : undefined;
-    const isInitialCreationFlow = currentApprovalWorkflow?.action === CONST.APPROVAL_WORKFLOW.ACTION.CREATE && !backTo;
+    const isInitialCreationFlow = currentApprovalWorkflow?.action === CONST.APPROVAL_WORKFLOW.ACTION.CREATE && !route.params?.backTo;
     const currentApprover = currentApprovalWorkflow?.approvers[approverIndex];
     const selectedApproverEmail = currentApprover?.email;
 
diff --git a/src/pages/workspace/workflows/approvals/WorkspaceWorkflowsApprovalsCreatePage.tsx b/src/pages/workspace/workflows/approvals/WorkspaceWorkflowsApprovalsCreatePage.tsx
index 0e9ec6bfd382..6fffbea9d9dc 100644
--- a/src/pages/workspace/workflows/approvals/WorkspaceWorkflowsApprovalsCreatePage.tsx
+++ b/src/pages/workspace/workflows/approvals/WorkspaceWorkflowsApprovalsCreatePage.tsx
@@ -70,7 +70,7 @@ function WorkspaceWorkflowsApprovalsCreatePage({policy, isLoadingReportData = tr
                 >
                     <HeaderWithBackButton
                         title={translate('workflowsCreateApprovalsPage.title')}
-                        onBackButtonPress={() => Navigation.goBack(ROUTES.WORKSPACE_WORKFLOWS_APPROVALS_APPROVER.getRoute(route.params.policyID, 0))}
+                        onBackButtonPress={() => Navigation.goBack(ROUTES.WORKSPACE_WORKFLOWS_APPROVALS_APPROVAL_LIMIT.getRoute(route.params.policyID, 0))}
                     />
                     {!!approvalWorkflow && (
                         <>

From 8c29485b9e6249f45eb2900b8ea6e1094524f0e3 Mon Sep 17 00:00:00 2001
From: Abdelrahman Khattab <abzokhattab@gmail.com>
Date: Sat, 13 Dec 2025 04:28:37 +0100
Subject: [PATCH 38/49] refactor: states optimizations

---
 src/components/NumberWithSymbolForm.tsx        |  6 +++---
 ...paceWorkflowsApprovalsApprovalLimitPage.tsx | 18 +++++-------------
 2 files changed, 8 insertions(+), 16 deletions(-)

diff --git a/src/components/NumberWithSymbolForm.tsx b/src/components/NumberWithSymbolForm.tsx
index cd9a2e02a146..6748bbe395f1 100644
--- a/src/components/NumberWithSymbolForm.tsx
+++ b/src/components/NumberWithSymbolForm.tsx
@@ -153,15 +153,15 @@ function NumberWithSymbolForm({
 
     const textInput = useRef<BaseTextInputRef | null>(null);
     const numberRef = useRef<string | undefined>(undefined);
-    const prevNumber = usePrevious(number);
     const [currentNumber, setCurrentNumber] = useState(typeof number === 'string' ? number : '');
 
-    if (number !== prevNumber) {
+    // sync currentNumber with number prop when it changes externally
+    useEffect(() => {
         const newNumber = typeof number === 'string' ? number : '';
         if (newNumber !== currentNumber) {
             setCurrentNumber(newNumber);
         }
-    }
+    }, [number]);
 
     const [shouldUpdateSelection, setShouldUpdateSelection] = useState(true);
 
diff --git a/src/pages/workspace/workflows/approvals/WorkspaceWorkflowsApprovalsApprovalLimitPage.tsx b/src/pages/workspace/workflows/approvals/WorkspaceWorkflowsApprovalsApprovalLimitPage.tsx
index 835f582c5012..a504d75a337e 100644
--- a/src/pages/workspace/workflows/approvals/WorkspaceWorkflowsApprovalsApprovalLimitPage.tsx
+++ b/src/pages/workspace/workflows/approvals/WorkspaceWorkflowsApprovalsApprovalLimitPage.tsx
@@ -1,5 +1,5 @@
 import {Str} from 'expensify-common';
-import React, {useCallback, useEffect, useMemo, useState} from 'react';
+import React, {useCallback, useMemo, useState} from 'react';
 import {View} from 'react-native';
 import AmountForm from '@components/AmountForm';
 import FullPageNotFoundView from '@components/BlockingViews/FullPageNotFoundView';
@@ -61,19 +61,10 @@ function WorkspaceWorkflowsApprovalsApprovalLimitPage({policy, isLoadingReportDa
         return '';
     }, [currentApprover?.approvalLimit, currency]);
 
-    const [approvalLimit, setApprovalLimit] = useState(defaultApprovalLimit);
+    const [editedApprovalLimit, setEditedApprovalLimit] = useState<string | null>(null);
     const [hasSubmitted, setHasSubmitted] = useState(false);
 
-    useEffect(() => {
-        if (!selectedApproverEmail) {
-            return;
-        }
-        setHasSubmitted(false);
-    }, [selectedApproverEmail]);
-
-    useEffect(() => {
-        setApprovalLimit(defaultApprovalLimit);
-    }, [defaultApprovalLimit]);
+    const approvalLimit = editedApprovalLimit ?? defaultApprovalLimit;
 
     const selectedApproverDisplayName = useMemo(() => {
         if (!selectedApproverEmail) {
@@ -190,7 +181,7 @@ function WorkspaceWorkflowsApprovalsApprovalLimitPage({policy, isLoadingReportDa
     ]);
 
     const handleAmountChange = useCallback((value: string) => {
-        setApprovalLimit(value);
+        setEditedApprovalLimit(value);
         setHasSubmitted(false);
     }, []);
 
@@ -200,6 +191,7 @@ function WorkspaceWorkflowsApprovalsApprovalLimitPage({policy, isLoadingReportDa
             approvalLimit: limitInCents,
             overLimitForwardsTo: selectedApproverEmail,
         });
+        setHasSubmitted(false);
     }, [approvalLimit, selectedApproverEmail, updateCurrentApprover]);
 
     const navigateToApproverSelector = useCallback(() => {

From 3af08653dae6f6678469629c69171d6f302ef632 Mon Sep 17 00:00:00 2001
From: Abdelrahman Khattab <abzokhattab@gmail.com>
Date: Sat, 13 Dec 2025 04:36:27 +0100
Subject: [PATCH 39/49] Remove manual memoization for React Compiler compliance

---
 ...aceWorkflowsApprovalsApprovalLimitPage.tsx | 107 +++++++-----------
 ...orkflowsApprovalsOverLimitApproverPage.tsx |  91 ++++++---------
 2 files changed, 75 insertions(+), 123 deletions(-)

diff --git a/src/pages/workspace/workflows/approvals/WorkspaceWorkflowsApprovalsApprovalLimitPage.tsx b/src/pages/workspace/workflows/approvals/WorkspaceWorkflowsApprovalsApprovalLimitPage.tsx
index a504d75a337e..25853891c0c7 100644
--- a/src/pages/workspace/workflows/approvals/WorkspaceWorkflowsApprovalsApprovalLimitPage.tsx
+++ b/src/pages/workspace/workflows/approvals/WorkspaceWorkflowsApprovalsApprovalLimitPage.tsx
@@ -1,5 +1,5 @@
 import {Str} from 'expensify-common';
-import React, {useCallback, useMemo, useState} from 'react';
+import React, {useState} from 'react';
 import {View} from 'react-native';
 import AmountForm from '@components/AmountForm';
 import FullPageNotFoundView from '@components/BlockingViews/FullPageNotFoundView';
@@ -54,25 +54,15 @@ function WorkspaceWorkflowsApprovalsApprovalLimitPage({policy, isLoadingReportDa
 
     const selectedApproverEmail = currentApprover?.overLimitForwardsTo ?? '';
 
-    const defaultApprovalLimit = useMemo(() => {
-        if (currentApprover?.approvalLimit) {
-            return convertToFrontendAmountAsString(currentApprover.approvalLimit, currency);
-        }
-        return '';
-    }, [currentApprover?.approvalLimit, currency]);
+    const defaultApprovalLimit = currentApprover?.approvalLimit ? convertToFrontendAmountAsString(currentApprover.approvalLimit, currency) : '';
 
     const [editedApprovalLimit, setEditedApprovalLimit] = useState<string | null>(null);
     const [hasSubmitted, setHasSubmitted] = useState(false);
 
     const approvalLimit = editedApprovalLimit ?? defaultApprovalLimit;
 
-    const selectedApproverDisplayName = useMemo(() => {
-        if (!selectedApproverEmail) {
-            return '';
-        }
-        const personalDetails = personalDetailsByEmail?.[selectedApproverEmail];
-        return Str.removeSMSDomain(personalDetails?.displayName ?? selectedApproverEmail);
-    }, [selectedApproverEmail, personalDetailsByEmail]);
+    const selectedApproverPersonalDetails = selectedApproverEmail ? personalDetailsByEmail?.[selectedApproverEmail] : undefined;
+    const selectedApproverDisplayName = selectedApproverEmail ? Str.removeSMSDomain(selectedApproverPersonalDetails?.displayName ?? selectedApproverEmail) : '';
 
     // eslint-disable-next-line rulesdir/no-negated-variables
     const shouldShowNotFoundView = (isEmptyObject(policy) && !isLoadingReportData) || !isPolicyAdmin(policy) || isPendingDeletePolicy(policy);
@@ -88,56 +78,48 @@ function WorkspaceWorkflowsApprovalsApprovalLimitPage({policy, isLoadingReportDa
     const onlyApproverEmpty = hasAmount && !hasApprover;
 
     const amountError = hasSubmitted && onlyAmountEmpty ? translate('workflowsApprovalLimitPage.enterAmountError') : undefined;
-    const approverErrorText = useMemo(() => {
-        if (hasSubmitted && onlyApproverEmpty) {
-            return translate('workflowsApprovalLimitPage.enterApproverError');
-        }
-        return undefined;
-    }, [hasSubmitted, onlyApproverEmpty, translate]);
+    const approverErrorText = hasSubmitted && onlyApproverEmpty ? translate('workflowsApprovalLimitPage.enterApproverError') : undefined;
 
     const firstApprover = approvalWorkflow?.approvers?.at(0)?.email ?? '';
 
-    const navigateAfterCompletion = useCallback(() => {
+    const navigateAfterCompletion = () => {
         if (isEditFlow) {
             // In edit mode, always go directly to the Edit page when saving
             Navigation.goBack(ROUTES.WORKSPACE_WORKFLOWS_APPROVALS_EDIT.getRoute(policyID, firstApprover));
             return;
         }
         Navigation.navigate(ROUTES.WORKSPACE_WORKFLOWS_APPROVALS_NEW.getRoute(policyID));
-    }, [isEditFlow, policyID, firstApprover]);
-
-    const updateCurrentApprover = useCallback(
-        (update: Partial<Approver>) => {
-            if (!approvalWorkflow || !currentApprover) {
-                return;
-            }
-            setApprovalWorkflowApprover({
-                approver: {
-                    ...currentApprover,
-                    ...update,
-                },
-                approverIndex,
-                currentApprovalWorkflow: approvalWorkflow,
-                policy,
-                personalDetailsByEmail,
-            });
-        },
-        [approvalWorkflow, currentApprover, approverIndex, policy, personalDetailsByEmail],
-    );
+    };
 
-    const resetApprovalLimit = useCallback(() => {
+    const updateCurrentApprover = (update: Partial<Approver>) => {
+        if (!approvalWorkflow || !currentApprover) {
+            return;
+        }
+        setApprovalWorkflowApprover({
+            approver: {
+                ...currentApprover,
+                ...update,
+            },
+            approverIndex,
+            currentApprovalWorkflow: approvalWorkflow,
+            policy,
+            personalDetailsByEmail,
+        });
+    };
+
+    const resetApprovalLimit = () => {
         updateCurrentApprover({
             approvalLimit: null,
             overLimitForwardsTo: '',
         });
-    }, [updateCurrentApprover]);
+    };
 
-    const handleSkip = useCallback(() => {
+    const handleSkip = () => {
         resetApprovalLimit();
         navigateAfterCompletion();
-    }, [resetApprovalLimit, navigateAfterCompletion]);
+    };
 
-    const handleSubmit = useCallback(() => {
+    const handleSubmit = () => {
         if (!approvalWorkflow) {
             return;
         }
@@ -165,45 +147,32 @@ function WorkspaceWorkflowsApprovalsApprovalLimitPage({policy, isLoadingReportDa
             overLimitForwardsTo: selectedApproverEmail,
         });
         navigateAfterCompletion();
-    }, [
-        approvalWorkflow,
-        currentApprover,
-        isEditFlow,
-        approverIndex,
-        bothEmpty,
-        onlyAmountEmpty,
-        onlyApproverEmpty,
-        approvalLimit,
-        selectedApproverEmail,
-        resetApprovalLimit,
-        navigateAfterCompletion,
-        updateCurrentApprover,
-    ]);
-
-    const handleAmountChange = useCallback((value: string) => {
+    };
+
+    const handleAmountChange = (value: string) => {
         setEditedApprovalLimit(value);
         setHasSubmitted(false);
-    }, []);
+    };
 
-    const saveCurrentStateToOnyx = useCallback(() => {
+    const saveCurrentStateToOnyx = () => {
         const limitInCents = approvalLimit ? convertToBackendAmount(Number.parseFloat(approvalLimit)) : null;
         updateCurrentApprover({
             approvalLimit: limitInCents,
             overLimitForwardsTo: selectedApproverEmail,
         });
         setHasSubmitted(false);
-    }, [approvalLimit, selectedApproverEmail, updateCurrentApprover]);
+    };
 
-    const navigateToApproverSelector = useCallback(() => {
+    const navigateToApproverSelector = () => {
         saveCurrentStateToOnyx();
         Navigation.navigate(ROUTES.WORKSPACE_WORKFLOWS_APPROVALS_OVER_LIMIT_APPROVER.getRoute(policyID, approverIndex));
-    }, [saveCurrentStateToOnyx, policyID, approverIndex]);
+    };
 
-    const navigateToApproverChange = useCallback(() => {
+    const navigateToApproverChange = () => {
         saveCurrentStateToOnyx();
         // Use the dedicated route for changing approver - it will go BACK to this page after selection
         Navigation.navigate(ROUTES.WORKSPACE_WORKFLOWS_APPROVALS_APPROVER_CHANGE.getRoute(policyID, approverIndex));
-    }, [saveCurrentStateToOnyx, policyID, approverIndex]);
+    };
 
     const buttonContainerStyle = useBottomSafeSafeAreaPaddingStyle({addBottomSafeAreaPadding: true, style: [styles.mh5, styles.mb5]});
 
diff --git a/src/pages/workspace/workflows/approvals/WorkspaceWorkflowsApprovalsOverLimitApproverPage.tsx b/src/pages/workspace/workflows/approvals/WorkspaceWorkflowsApprovalsOverLimitApproverPage.tsx
index 78871fc890fe..9cd1c62454b6 100644
--- a/src/pages/workspace/workflows/approvals/WorkspaceWorkflowsApprovalsOverLimitApproverPage.tsx
+++ b/src/pages/workspace/workflows/approvals/WorkspaceWorkflowsApprovalsOverLimitApproverPage.tsx
@@ -1,4 +1,4 @@
-import React, {useCallback, useMemo} from 'react';
+import React from 'react';
 import type {SelectionListApprover} from '@components/ApproverSelectionList';
 import ApproverSelectionList from '@components/ApproverSelectionList';
 import Text from '@components/Text';
@@ -42,11 +42,11 @@ function WorkspaceWorkflowsApprovalsOverLimitApproverPage({policy, personalDetai
 
     const employeeList = policy?.employeeList;
     const isDefault = approvalWorkflow?.isDefault;
-    const membersEmail = useMemo(() => approvalWorkflow?.members.map((member) => member.email), [approvalWorkflow?.members]);
+    const membersEmail = approvalWorkflow?.members.map((member) => member.email);
 
     const currentApproverEmail = currentApprover?.email;
 
-    const allApprovers: SelectionListApprover[] = useMemo(() => {
+    const allApprovers: SelectionListApprover[] = (() => {
         if (isApprovalWorkflowLoading || !employeeList) {
             return [];
         }
@@ -89,73 +89,56 @@ function WorkspaceWorkflowsApprovalsOverLimitApproverPage({policy, personalDetai
                 };
             })
             .filter((approver): approver is SelectionListApprover => !!approver);
-    }, [
-        isApprovalWorkflowLoading,
-        employeeList,
-        personalDetails,
-        policy?.owner,
-        policy?.preventSelfApproval,
-        currentApprover?.overLimitForwardsTo,
-        expensifyIcons.FallbackAvatar,
-        isDefault,
-        membersEmail,
-        currentApproverEmail,
-    ]);
+    })();
 
     const shouldShowListEmptyContent = !!approvalWorkflow && !isApprovalWorkflowLoading;
 
-    const goBack = useCallback(() => {
+    const goBack = () => {
         Navigation.goBack(ROUTES.WORKSPACE_WORKFLOWS_APPROVALS_APPROVAL_LIMIT.getRoute(policyID, approverIndex));
-    }, [policyID, approverIndex]);
-
-    const selectApprover = useCallback(
-        (approvers: SelectionListApprover[]) => {
-            const selectedApprover = approvers.at(0);
-
-            if (!approvalWorkflow || !currentApprover) {
-                return;
-            }
-
-            // If empty array, the same approver was tapped again to unselect
-            if (approvers.length === 0) {
-                setApprovalWorkflowApprover({
-                    approver: {
-                        ...currentApprover,
-                        overLimitForwardsTo: '',
-                    },
-                    approverIndex,
-                    currentApprovalWorkflow: approvalWorkflow,
-                    policy,
-                    personalDetailsByEmail,
-                });
-                goBack();
-                return;
-            }
-
-            if (!selectedApprover?.login) {
-                return;
-            }
+    };
 
+    const selectApprover = (approvers: SelectionListApprover[]) => {
+        const selectedApprover = approvers.at(0);
+
+        if (!approvalWorkflow || !currentApprover) {
+            return;
+        }
+
+        // If empty array, the same approver was tapped again to unselect
+        if (approvers.length === 0) {
             setApprovalWorkflowApprover({
                 approver: {
                     ...currentApprover,
-                    overLimitForwardsTo: selectedApprover.login,
+                    overLimitForwardsTo: '',
                 },
                 approverIndex,
                 currentApprovalWorkflow: approvalWorkflow,
                 policy,
                 personalDetailsByEmail,
             });
-
             goBack();
-        },
-        [approvalWorkflow, currentApprover, approverIndex, policy, personalDetailsByEmail, goBack],
-    );
+            return;
+        }
 
-    const subtitle = useMemo(
-        () => !shouldShowListEmptyContent && <Text style={[styles.textHeadlineH1, styles.mh5, styles.mv3]}>{translate('workflowsApprovalLimitPage.additionalApproverLabel')}</Text>,
-        [shouldShowListEmptyContent, translate, styles.textHeadlineH1, styles.mh5, styles.mv3],
-    );
+        if (!selectedApprover?.login) {
+            return;
+        }
+
+        setApprovalWorkflowApprover({
+            approver: {
+                ...currentApprover,
+                overLimitForwardsTo: selectedApprover.login,
+            },
+            approverIndex,
+            currentApprovalWorkflow: approvalWorkflow,
+            policy,
+            personalDetailsByEmail,
+        });
+
+        goBack();
+    };
+
+    const subtitle = !shouldShowListEmptyContent && <Text style={[styles.textHeadlineH1, styles.mh5, styles.mv3]}>{translate('workflowsApprovalLimitPage.additionalApproverLabel')}</Text>;
 
     return (
         <AccessOrNotFoundWrapper

From 3de91ed8d9191cfd80f12560281493e9b520f675 Mon Sep 17 00:00:00 2001
From: Abdelrahman Khattab <abzokhattab@gmail.com>
Date: Sat, 13 Dec 2025 04:42:46 +0100
Subject: [PATCH 40/49] minor edit

---
 .../approvals/WorkspaceWorkflowsApprovalsApproverPage.tsx   | 6 ++++--
 1 file changed, 4 insertions(+), 2 deletions(-)

diff --git a/src/pages/workspace/workflows/approvals/WorkspaceWorkflowsApprovalsApproverPage.tsx b/src/pages/workspace/workflows/approvals/WorkspaceWorkflowsApprovalsApproverPage.tsx
index 3c8e54593056..4ae26b785f74 100644
--- a/src/pages/workspace/workflows/approvals/WorkspaceWorkflowsApprovalsApproverPage.tsx
+++ b/src/pages/workspace/workflows/approvals/WorkspaceWorkflowsApprovalsApproverPage.tsx
@@ -49,12 +49,14 @@ function WorkspaceWorkflowsApprovalsApproverPage({policy, personalDetails, isLoa
     const employeeList = policy?.employeeList;
     const approversFromWorkflow = currentApprovalWorkflow?.approvers;
     const isDefault = currentApprovalWorkflow?.isDefault;
-    const membersEmail = useMemo(() => currentApprovalWorkflow?.members.map((member) => member.email), [currentApprovalWorkflow?.members]);
+
     const allApprovers: SelectionListApprover[] = useMemo(() => {
         if (isApprovalWorkflowLoading || !employeeList) {
             return [];
         }
 
+        const membersEmail = currentApprovalWorkflow?.members?.map((member) => member.email);
+
         return Object.values(employeeList)
             .map((employee): SelectionListApprover | null => {
                 const email = employee.email;
@@ -110,7 +112,7 @@ function WorkspaceWorkflowsApprovalsApproverPage({policy, personalDetails, isLoa
         isDefault,
         policy?.preventSelfApproval,
         policy?.owner,
-        membersEmail,
+        currentApprovalWorkflow?.members,
         approversFromWorkflow,
         selectedApproverEmail,
         approverIndex,

From 09e02305912f3388bbaed0c86d78e94f7dbd4f37 Mon Sep 17 00:00:00 2001
From: Abdelrahman Khattab <abzokhattab@gmail.com>
Date: Sat, 13 Dec 2025 05:02:22 +0100
Subject: [PATCH 41/49] fix: clear approval limit when additional approver is
 removed

---
 src/components/NumberWithSymbolForm.tsx                     | 6 +++---
 .../WorkspaceWorkflowsApprovalsApprovalLimitPage.tsx        | 2 +-
 .../WorkspaceWorkflowsApprovalsOverLimitApproverPage.tsx    | 1 +
 3 files changed, 5 insertions(+), 4 deletions(-)

diff --git a/src/components/NumberWithSymbolForm.tsx b/src/components/NumberWithSymbolForm.tsx
index 6748bbe395f1..234e5d3459d7 100644
--- a/src/components/NumberWithSymbolForm.tsx
+++ b/src/components/NumberWithSymbolForm.tsx
@@ -235,11 +235,11 @@ function NumberWithSymbolForm({
             let hasSelectionBeenSet = false;
             const strippedNumber = stripCommaFromAmount(finalNumber);
             numberRef.current = strippedNumber;
-            setCurrentNumber((prevCurrentNumber) => {
-                const isForwardDelete = prevCurrentNumber.length > strippedNumber.length && forwardDeletePressedRef.current;
+            setCurrentNumber((prevNumber) => {
+                const isForwardDelete = prevNumber.length > strippedNumber.length && forwardDeletePressedRef.current;
                 if (!hasSelectionBeenSet) {
                     hasSelectionBeenSet = true;
-                    setSelection((prevSelection) => getNewSelection(prevSelection, isForwardDelete ? strippedNumber.length : prevCurrentNumber.length, strippedNumber.length));
+                    setSelection((prevSelection) => getNewSelection(prevSelection, isForwardDelete ? strippedNumber.length : prevNumber.length, strippedNumber.length));
                     willSelectionBeUpdatedManually.current = false;
                 }
                 return strippedNumber;
diff --git a/src/pages/workspace/workflows/approvals/WorkspaceWorkflowsApprovalsApprovalLimitPage.tsx b/src/pages/workspace/workflows/approvals/WorkspaceWorkflowsApprovalsApprovalLimitPage.tsx
index 25853891c0c7..f605f05d4056 100644
--- a/src/pages/workspace/workflows/approvals/WorkspaceWorkflowsApprovalsApprovalLimitPage.tsx
+++ b/src/pages/workspace/workflows/approvals/WorkspaceWorkflowsApprovalsApprovalLimitPage.tsx
@@ -160,6 +160,7 @@ function WorkspaceWorkflowsApprovalsApprovalLimitPage({policy, isLoadingReportDa
             approvalLimit: limitInCents,
             overLimitForwardsTo: selectedApproverEmail,
         });
+        setEditedApprovalLimit(null);
         setHasSubmitted(false);
     };
 
@@ -170,7 +171,6 @@ function WorkspaceWorkflowsApprovalsApprovalLimitPage({policy, isLoadingReportDa
 
     const navigateToApproverChange = () => {
         saveCurrentStateToOnyx();
-        // Use the dedicated route for changing approver - it will go BACK to this page after selection
         Navigation.navigate(ROUTES.WORKSPACE_WORKFLOWS_APPROVALS_APPROVER_CHANGE.getRoute(policyID, approverIndex));
     };
 
diff --git a/src/pages/workspace/workflows/approvals/WorkspaceWorkflowsApprovalsOverLimitApproverPage.tsx b/src/pages/workspace/workflows/approvals/WorkspaceWorkflowsApprovalsOverLimitApproverPage.tsx
index 9cd1c62454b6..64ba0ae3d19a 100644
--- a/src/pages/workspace/workflows/approvals/WorkspaceWorkflowsApprovalsOverLimitApproverPage.tsx
+++ b/src/pages/workspace/workflows/approvals/WorkspaceWorkflowsApprovalsOverLimitApproverPage.tsx
@@ -110,6 +110,7 @@ function WorkspaceWorkflowsApprovalsOverLimitApproverPage({policy, personalDetai
                 approver: {
                     ...currentApprover,
                     overLimitForwardsTo: '',
+                    approvalLimit: null,
                 },
                 approverIndex,
                 currentApprovalWorkflow: approvalWorkflow,

From 26a6dc939987c4969ca43d2d1623181ac9710704 Mon Sep 17 00:00:00 2001
From: Abdelrahman Khattab <abzokhattab@gmail.com>
Date: Sun, 14 Dec 2025 21:55:24 +0100
Subject: [PATCH 42/49] refactor: use Onyx state instead of backTo param for
 approval workflow navigation

---
 src/ROUTES.ts                                 |  8 ++------
 src/libs/Navigation/types.ts                  |  6 ------
 src/libs/WorkflowUtils.ts                     |  1 +
 src/libs/actions/Workflow.ts                  |  6 ++++++
 .../approvals/ApprovalWorkflowEditor.tsx      | 20 ++++---------------
 ...aceWorkflowsApprovalsApprovalLimitPage.tsx |  4 +++-
 ...orkspaceWorkflowsApprovalsApproverPage.tsx |  2 +-
 ...paceWorkflowsApprovalsExpensesFromPage.tsx |  2 +-
 src/types/onyx/ApprovalWorkflow.ts            |  5 +++++
 9 files changed, 23 insertions(+), 31 deletions(-)

diff --git a/src/ROUTES.ts b/src/ROUTES.ts
index 26e709b25356..b51224ec08de 100644
--- a/src/ROUTES.ts
+++ b/src/ROUTES.ts
@@ -1714,15 +1714,11 @@ const ROUTES = {
     },
     WORKSPACE_WORKFLOWS_APPROVALS_EXPENSES_FROM: {
         route: 'workspaces/:policyID/workflows/approvals/expenses-from',
-
-        // eslint-disable-next-line no-restricted-syntax -- Legacy route generation
-        getRoute: (policyID: string, backTo?: string) => getUrlWithBackToParam(`workspaces/${policyID}/workflows/approvals/expenses-from` as const, backTo),
+        getRoute: (policyID: string) => `workspaces/${policyID}/workflows/approvals/expenses-from` as const,
     },
     WORKSPACE_WORKFLOWS_APPROVALS_APPROVER: {
         route: 'workspaces/:policyID/workflows/approvals/approver',
-        getRoute: (policyID: string, approverIndex: number, backTo?: string) =>
-            // eslint-disable-next-line no-restricted-syntax -- Legacy route generation
-            getUrlWithBackToParam(`workspaces/${policyID}/workflows/approvals/approver?approverIndex=${approverIndex}` as const, backTo),
+        getRoute: (policyID: string, approverIndex: number) => `workspaces/${policyID}/workflows/approvals/approver?approverIndex=${approverIndex}` as const,
     },
     WORKSPACE_WORKFLOWS_APPROVALS_APPROVER_CHANGE: {
         route: 'workspaces/:policyID/workflows/approvals/approver-change',
diff --git a/src/libs/Navigation/types.ts b/src/libs/Navigation/types.ts
index f730b49b57b9..2abfbd82d6b4 100644
--- a/src/libs/Navigation/types.ts
+++ b/src/libs/Navigation/types.ts
@@ -2324,20 +2324,14 @@ type WorkspaceSplitNavigatorParamList = {
     };
     [SCREENS.WORKSPACE.WORKFLOWS_APPROVALS_EXPENSES_FROM]: {
         policyID: string;
-        // eslint-disable-next-line no-restricted-syntax -- `backTo` usages in this file are legacy. Do not add new `backTo` params to screens. See contributingGuides/NAVIGATION.md
-        backTo?: Routes;
     };
     [SCREENS.WORKSPACE.WORKFLOWS_APPROVALS_APPROVER]: {
         policyID: string;
         approverIndex: number;
-        // eslint-disable-next-line no-restricted-syntax -- `backTo` usages in this file are legacy. Do not add new `backTo` params to screens. See contributingGuides/NAVIGATION.md
-        backTo?: Routes;
     };
     [SCREENS.WORKSPACE.WORKFLOWS_APPROVALS_APPROVER_CHANGE]: {
         policyID: string;
         approverIndex: number;
-        // eslint-disable-next-line no-restricted-syntax -- `backTo` usages in this file are legacy. Do not add new `backTo` params to screens. See contributingGuides/NAVIGATION.md
-        backTo?: Routes;
     };
     [SCREENS.WORKSPACE.WORKFLOWS_APPROVALS_APPROVAL_LIMIT]: {
         policyID: string;
diff --git a/src/libs/WorkflowUtils.ts b/src/libs/WorkflowUtils.ts
index f916b923e6af..031218096701 100644
--- a/src/libs/WorkflowUtils.ts
+++ b/src/libs/WorkflowUtils.ts
@@ -23,6 +23,7 @@ const INITIAL_APPROVAL_WORKFLOW: ApprovalWorkflowOnyx = {
     isDefault: false,
     action: CONST.APPROVAL_WORKFLOW.ACTION.CREATE,
     originalApprovers: [],
+    isInitialFlow: true,
 };
 
 type GetApproversParams = {
diff --git a/src/libs/actions/Workflow.ts b/src/libs/actions/Workflow.ts
index 9378513b59b4..2f7d8f708b86 100644
--- a/src/libs/actions/Workflow.ts
+++ b/src/libs/actions/Workflow.ts
@@ -283,6 +283,11 @@ function clearApprovalWorkflowApprovers() {
     Onyx.merge(ONYXKEYS.APPROVAL_WORKFLOW, {approvers: []});
 }
 
+/** Set whether the user is in the initial creation flow */
+function setApprovalWorkflowIsInitialFlow(isInitialFlow: boolean) {
+    Onyx.merge(ONYXKEYS.APPROVAL_WORKFLOW, {isInitialFlow});
+}
+
 function setApprovalWorkflow(approvalWorkflow: NullishDeep<ApprovalWorkflowOnyx>) {
     Onyx.set(ONYXKEYS.APPROVAL_WORKFLOW, approvalWorkflow);
 }
@@ -334,4 +339,5 @@ export {
     clearApprovalWorkflowApprovers,
     clearApprovalWorkflow,
     validateApprovalWorkflow,
+    setApprovalWorkflowIsInitialFlow,
 };
diff --git a/src/pages/workspace/workflows/approvals/ApprovalWorkflowEditor.tsx b/src/pages/workspace/workflows/approvals/ApprovalWorkflowEditor.tsx
index dedc7506d8d8..92dbabe3c00c 100644
--- a/src/pages/workspace/workflows/approvals/ApprovalWorkflowEditor.tsx
+++ b/src/pages/workspace/workflows/approvals/ApprovalWorkflowEditor.tsx
@@ -110,17 +110,10 @@ function ApprovalWorkflowEditor({approvalWorkflow, removeApprovalWorkflow, polic
         [approvalWorkflow.approvers, approvalWorkflow.errors, translate],
     );
 
-    const editMembers = useCallback(() => {
-        const backTo = approvalWorkflow.action === CONST.APPROVAL_WORKFLOW.ACTION.CREATE ? ROUTES.WORKSPACE_WORKFLOWS_APPROVALS_NEW.getRoute(policyID) : undefined;
-        Navigation.navigate(ROUTES.WORKSPACE_WORKFLOWS_APPROVALS_EXPENSES_FROM.getRoute(policyID, backTo));
-    }, [approvalWorkflow.action, policyID]);
-
-    const firstApprover = approvalWorkflow.approvers.at(0)?.email ?? '';
-
     const editApprover = useCallback(
         (approverIndex: number) => {
             if (approvalWorkflow.action === CONST.APPROVAL_WORKFLOW.ACTION.CREATE) {
-                Navigation.navigate(ROUTES.WORKSPACE_WORKFLOWS_APPROVALS_APPROVER.getRoute(policyID, approverIndex, ROUTES.WORKSPACE_WORKFLOWS_APPROVALS_NEW.getRoute(policyID)));
+                Navigation.navigate(ROUTES.WORKSPACE_WORKFLOWS_APPROVALS_APPROVER.getRoute(policyID, approverIndex));
             } else {
                 Navigation.navigate(ROUTES.WORKSPACE_WORKFLOWS_APPROVALS_APPROVAL_LIMIT.getRoute(policyID, approverIndex));
             }
@@ -130,11 +123,6 @@ function ApprovalWorkflowEditor({approvalWorkflow, removeApprovalWorkflow, polic
 
     // User should be allowed to add additional approver only if they upgraded to Control Plan, otherwise redirected to the Upgrade Page
     const addAdditionalApprover = useCallback(() => {
-        const backTo =
-            approvalWorkflow.action === CONST.APPROVAL_WORKFLOW.ACTION.EDIT
-                ? ROUTES.WORKSPACE_WORKFLOWS_APPROVALS_EDIT.getRoute(policyID, firstApprover)
-                : ROUTES.WORKSPACE_WORKFLOWS_APPROVALS_NEW.getRoute(policyID);
-
         if (!isControlPolicy(policy) && approverCount > 0) {
             Navigation.navigate(
                 ROUTES.WORKSPACE_UPGRADE.getRoute(
@@ -145,8 +133,8 @@ function ApprovalWorkflowEditor({approvalWorkflow, removeApprovalWorkflow, polic
             );
             return;
         }
-        Navigation.navigate(ROUTES.WORKSPACE_WORKFLOWS_APPROVALS_APPROVER.getRoute(policyID, approverCount, backTo));
-    }, [approvalWorkflow.action, approverCount, firstApprover, policy, policyID]);
+        Navigation.navigate(ROUTES.WORKSPACE_WORKFLOWS_APPROVALS_APPROVER.getRoute(policyID, approverCount));
+    }, [approverCount, policy, policyID]);
 
     return (
         <ScrollView
@@ -165,7 +153,7 @@ function ApprovalWorkflowEditor({approvalWorkflow, removeApprovalWorkflow, polic
                     numberOfLinesTitle={4}
                     description={translate('workflowsExpensesFromPage.title')}
                     descriptionTextStyle={!!members && styles.textLabelSupportingNormal}
-                    onPress={editMembers}
+                    onPress={() => Navigation.navigate(ROUTES.WORKSPACE_WORKFLOWS_APPROVALS_EXPENSES_FROM.getRoute(policyID))}
                     wrapperStyle={[styles.sectionMenuItemTopDescription]}
                     errorText={approvalWorkflow?.errors?.members ? translate(approvalWorkflow.errors.members) : undefined}
                     brickRoadIndicator={approvalWorkflow?.errors?.members ? CONST.BRICK_ROAD_INDICATOR_STATUS.ERROR : undefined}
diff --git a/src/pages/workspace/workflows/approvals/WorkspaceWorkflowsApprovalsApprovalLimitPage.tsx b/src/pages/workspace/workflows/approvals/WorkspaceWorkflowsApprovalsApprovalLimitPage.tsx
index f605f05d4056..12fad8d969bb 100644
--- a/src/pages/workspace/workflows/approvals/WorkspaceWorkflowsApprovalsApprovalLimitPage.tsx
+++ b/src/pages/workspace/workflows/approvals/WorkspaceWorkflowsApprovalsApprovalLimitPage.tsx
@@ -24,7 +24,7 @@ import {goBackFromInvalidPolicy, isPendingDeletePolicy, isPolicyAdmin} from '@li
 import AccessOrNotFoundWrapper from '@pages/workspace/AccessOrNotFoundWrapper';
 import type {WithPolicyAndFullscreenLoadingProps} from '@pages/workspace/withPolicyAndFullscreenLoading';
 import withPolicyAndFullscreenLoading from '@pages/workspace/withPolicyAndFullscreenLoading';
-import {clearApprovalWorkflowApprover, setApprovalWorkflowApprover} from '@userActions/Workflow';
+import {clearApprovalWorkflowApprover, setApprovalWorkflowApprover, setApprovalWorkflowIsInitialFlow} from '@userActions/Workflow';
 import CONST from '@src/CONST';
 import ONYXKEYS from '@src/ONYXKEYS';
 import ROUTES from '@src/ROUTES';
@@ -88,6 +88,8 @@ function WorkspaceWorkflowsApprovalsApprovalLimitPage({policy, isLoadingReportDa
             Navigation.goBack(ROUTES.WORKSPACE_WORKFLOWS_APPROVALS_EDIT.getRoute(policyID, firstApprover));
             return;
         }
+        // Mark that we've completed the initial wizard flow before navigating to the summary page
+        setApprovalWorkflowIsInitialFlow(false);
         Navigation.navigate(ROUTES.WORKSPACE_WORKFLOWS_APPROVALS_NEW.getRoute(policyID));
     };
 
diff --git a/src/pages/workspace/workflows/approvals/WorkspaceWorkflowsApprovalsApproverPage.tsx b/src/pages/workspace/workflows/approvals/WorkspaceWorkflowsApprovalsApproverPage.tsx
index 4ae26b785f74..17e37dea226e 100644
--- a/src/pages/workspace/workflows/approvals/WorkspaceWorkflowsApprovalsApproverPage.tsx
+++ b/src/pages/workspace/workflows/approvals/WorkspaceWorkflowsApprovalsApproverPage.tsx
@@ -42,7 +42,7 @@ function WorkspaceWorkflowsApprovalsApproverPage({policy, personalDetails, isLoa
     const firstApprover = currentApprovalWorkflow?.approvers?.[0]?.email ?? '';
 
     const isChangeApproverRoute = route.name === SCREENS.WORKSPACE.WORKFLOWS_APPROVALS_APPROVER_CHANGE;
-    const isInitialCreationFlow = currentApprovalWorkflow?.action === CONST.APPROVAL_WORKFLOW.ACTION.CREATE && !route.params?.backTo;
+    const isInitialCreationFlow = currentApprovalWorkflow?.action === CONST.APPROVAL_WORKFLOW.ACTION.CREATE && currentApprovalWorkflow?.isInitialFlow;
     const currentApprover = currentApprovalWorkflow?.approvers[approverIndex];
     const selectedApproverEmail = currentApprover?.email;
 
diff --git a/src/pages/workspace/workflows/approvals/WorkspaceWorkflowsApprovalsExpensesFromPage.tsx b/src/pages/workspace/workflows/approvals/WorkspaceWorkflowsApprovalsExpensesFromPage.tsx
index bf2ec37543b2..c5039734cc3f 100644
--- a/src/pages/workspace/workflows/approvals/WorkspaceWorkflowsApprovalsExpensesFromPage.tsx
+++ b/src/pages/workspace/workflows/approvals/WorkspaceWorkflowsApprovalsExpensesFromPage.tsx
@@ -41,7 +41,7 @@ function WorkspaceWorkflowsApprovalsExpensesFromPage({policy, isLoadingReportDat
 
     // eslint-disable-next-line rulesdir/no-negated-variables
     const shouldShowNotFoundView = (isEmptyObject(policy) && !isLoadingReportData) || !isPolicyAdmin(policy) || isPendingDeletePolicy(policy);
-    const isInitialCreationFlow = approvalWorkflow?.action === CONST.APPROVAL_WORKFLOW.ACTION.CREATE && !route.params.backTo;
+    const isInitialCreationFlow = approvalWorkflow?.action === CONST.APPROVAL_WORKFLOW.ACTION.CREATE && approvalWorkflow?.isInitialFlow;
     const shouldShowListEmptyContent = !isLoadingApprovalWorkflow && approvalWorkflow && approvalWorkflow.availableMembers.length === 0;
     const firstApprover = approvalWorkflow?.originalApprovers?.[0]?.email ?? '';
 
diff --git a/src/types/onyx/ApprovalWorkflow.ts b/src/types/onyx/ApprovalWorkflow.ts
index b5c6d84728ca..226577ffc585 100644
--- a/src/types/onyx/ApprovalWorkflow.ts
+++ b/src/types/onyx/ApprovalWorkflow.ts
@@ -129,6 +129,11 @@ type ApprovalWorkflowOnyx = Omit<ApprovalWorkflow, 'approvers'> & {
      * List of original approvers in the workflow
      */
     originalApprovers: Approver[];
+
+    /**
+     * Whether the user is in the initial creation flow
+     */
+    isInitialFlow?: boolean;
 };
 
 export default ApprovalWorkflow;

From c872aad2fa7a4d79f25c0b652cf331db470567b7 Mon Sep 17 00:00:00 2001
From: Abdelrahman Khattab <abzokhattab@gmail.com>
Date: Tue, 16 Dec 2025 17:28:13 +0100
Subject: [PATCH 43/49] fixing pipeline

---
 src/components/ApprovalWorkflowSection.tsx | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/src/components/ApprovalWorkflowSection.tsx b/src/components/ApprovalWorkflowSection.tsx
index d2e758de82cb..ed250d1950c4 100644
--- a/src/components/ApprovalWorkflowSection.tsx
+++ b/src/components/ApprovalWorkflowSection.tsx
@@ -29,7 +29,7 @@ type ApprovalWorkflowSectionProps = {
     currency?: string;
 };
 
-function ApprovalWorkflowSection({approvalWorkflow, onPress}: ApprovalWorkflowSectionProps) {
+function ApprovalWorkflowSection({approvalWorkflow, onPress, currency = CONST.CURRENCY.USD}: ApprovalWorkflowSectionProps) {
     const icons = useMemoizedLazyExpensifyIcons(['ArrowRight', 'Lightbulb', 'Users', 'UserCheck']);
     const styles = useThemeStyles();
     const theme = useTheme();

From ce5b1be67b66a0b53cd03ffee3be5aae6d622dde Mon Sep 17 00:00:00 2001
From: Abdelrahman Khattab <abzokhattab@gmail.com>
Date: Tue, 16 Dec 2025 17:39:19 +0100
Subject: [PATCH 44/49] fixing ts

---
 .../approvals/WorkspaceWorkflowsApprovalsApproverPage.tsx     | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/src/pages/workspace/workflows/approvals/WorkspaceWorkflowsApprovalsApproverPage.tsx b/src/pages/workspace/workflows/approvals/WorkspaceWorkflowsApprovalsApproverPage.tsx
index 564e64113b17..7966b6c6e8d9 100644
--- a/src/pages/workspace/workflows/approvals/WorkspaceWorkflowsApprovalsApproverPage.tsx
+++ b/src/pages/workspace/workflows/approvals/WorkspaceWorkflowsApprovalsApproverPage.tsx
@@ -142,7 +142,7 @@ function WorkspaceWorkflowsApprovalsApproverPage({policy, personalDetails, isLoa
             const isRemovingApprover = approvers.length === 0;
 
             if (isRemovingApprover) {
-                clearApprovalWorkflowApprover({approverIndex, approvalWorkflow});
+                clearApprovalWorkflowApprover({approverIndex, currentApprovalWorkflow: approvalWorkflow});
                 goBack();
                 return;
             }
@@ -161,7 +161,7 @@ function WorkspaceWorkflowsApprovalsApproverPage({policy, personalDetails, isLoa
                     overLimitForwardsTo: '',
                 },
                 approverIndex,
-                approvalWorkflow,
+                currentApprovalWorkflow: approvalWorkflow,
                 policy,
                 personalDetailsByEmail,
             });

From b36fe0955c8569886413ab8cde1bde5cef61e705 Mon Sep 17 00:00:00 2001
From: Abdelrahman Khattab <abzokhattab@gmail.com>
Date: Wed, 17 Dec 2025 22:24:04 +0100
Subject: [PATCH 45/49] enable submit on enter + fix nav issue when having one
 approval and unslecting it

---
 src/components/AmountForm.tsx                                | 4 +++-
 src/components/NumberWithSymbolForm.tsx                      | 5 +++++
 .../WorkspaceWorkflowsApprovalsApprovalLimitPage.tsx         | 3 ++-
 3 files changed, 10 insertions(+), 2 deletions(-)

diff --git a/src/components/AmountForm.tsx b/src/components/AmountForm.tsx
index 6a303ff283dc..33e9f9188e8d 100644
--- a/src/components/AmountForm.tsx
+++ b/src/components/AmountForm.tsx
@@ -48,7 +48,7 @@ type AmountFormProps = {
 
     /** Reference to the outer element */
     ref?: ForwardedRef<BaseTextInputRef>;
-} & Pick<BaseTextInputProps, 'autoFocus' | 'autoGrowExtraSpace' | 'autoGrowMarginSide'>;
+} & Pick<BaseTextInputProps, 'autoFocus' | 'autoGrowExtraSpace' | 'autoGrowMarginSide' | 'onSubmitEditing'>;
 
 /**
  * Wrapper around NumberWithSymbolForm with currency handling.
@@ -69,6 +69,7 @@ function AmountForm({
     autoFocus,
     autoGrowExtraSpace,
     autoGrowMarginSide,
+    onSubmitEditing,
     ref,
 }: AmountFormProps) {
     const styles = useThemeStyles();
@@ -103,6 +104,7 @@ function AmountForm({
             autoFocus={autoFocus}
             autoGrowExtraSpace={autoGrowExtraSpace}
             autoGrowMarginSide={autoGrowMarginSide}
+            onSubmitEditing={onSubmitEditing}
             disabled={disabled}
         />
     );
diff --git a/src/components/NumberWithSymbolForm.tsx b/src/components/NumberWithSymbolForm.tsx
index 234e5d3459d7..a2371e29db72 100644
--- a/src/components/NumberWithSymbolForm.tsx
+++ b/src/components/NumberWithSymbolForm.tsx
@@ -84,6 +84,9 @@ type NumberWithSymbolFormProps = {
 
     /** Reference to the outer element */
     ref?: ForwardedRef<BaseTextInputRef>;
+
+    /** Callback when the user presses the submit key (Enter) */
+    onSubmitEditing?: () => void;
 } & Omit<TextInputWithSymbolProps, 'formattedAmount' | 'onAmountChange' | 'placeholder' | 'onSelectionChange' | 'onKeyPress' | 'onMouseDown' | 'onMouseUp'>;
 
 type NumberWithSymbolFormRef = {
@@ -145,6 +148,7 @@ function NumberWithSymbolForm({
     clearNegative,
     ref,
     disabled,
+    onSubmitEditing,
     ...props
 }: NumberWithSymbolFormProps) {
     const styles = useThemeStyles();
@@ -395,6 +399,7 @@ function NumberWithSymbolForm({
                 autoFocus={props.autoFocus}
                 autoGrowExtraSpace={props.autoGrowExtraSpace}
                 autoGrowMarginSide={props.autoGrowMarginSide}
+                onSubmitEditing={onSubmitEditing}
             />
         );
     }
diff --git a/src/pages/workspace/workflows/approvals/WorkspaceWorkflowsApprovalsApprovalLimitPage.tsx b/src/pages/workspace/workflows/approvals/WorkspaceWorkflowsApprovalsApprovalLimitPage.tsx
index 12fad8d969bb..d4deec335897 100644
--- a/src/pages/workspace/workflows/approvals/WorkspaceWorkflowsApprovalsApprovalLimitPage.tsx
+++ b/src/pages/workspace/workflows/approvals/WorkspaceWorkflowsApprovalsApprovalLimitPage.tsx
@@ -80,7 +80,7 @@ function WorkspaceWorkflowsApprovalsApprovalLimitPage({policy, isLoadingReportDa
     const amountError = hasSubmitted && onlyAmountEmpty ? translate('workflowsApprovalLimitPage.enterAmountError') : undefined;
     const approverErrorText = hasSubmitted && onlyApproverEmpty ? translate('workflowsApprovalLimitPage.enterApproverError') : undefined;
 
-    const firstApprover = approvalWorkflow?.approvers?.at(0)?.email ?? '';
+    const firstApprover = approvalWorkflow?.originalApprovers?.at(0)?.email ?? '';
 
     const navigateAfterCompletion = () => {
         if (isEditFlow) {
@@ -239,6 +239,7 @@ function WorkspaceWorkflowsApprovalsApprovalLimitPage({policy, isLoadingReportDa
                                     displayAsTextInput
                                     disabled={areLimitFieldsDisabled}
                                     errorText={amountError}
+                                    onSubmitEditing={handleSubmit}
                                 />
                             </View>
 

From 2eaadc32eb063daf65c54c9b64cd84093eb81ea7 Mon Sep 17 00:00:00 2001
From: Abdelrahman Khattab <abzokhattab@gmail.com>
Date: Wed, 17 Dec 2025 22:28:36 +0100
Subject: [PATCH 46/49] fixing react complience pipeline

---
 src/components/ApprovalWorkflowSection.tsx    |  23 ++--
 src/components/NumberWithSymbolForm.tsx       | 104 +++++++++---------
 .../WorkspaceWorkflowsApprovalsCreatePage.tsx |   6 +-
 .../WorkspaceWorkflowsApprovalsEditPage.tsx   |  16 +--
 4 files changed, 69 insertions(+), 80 deletions(-)

diff --git a/src/components/ApprovalWorkflowSection.tsx b/src/components/ApprovalWorkflowSection.tsx
index ed250d1950c4..a037a6004430 100644
--- a/src/components/ApprovalWorkflowSection.tsx
+++ b/src/components/ApprovalWorkflowSection.tsx
@@ -1,5 +1,5 @@
 import {Str} from 'expensify-common';
-import React, {useCallback, useMemo} from 'react';
+import React from 'react';
 import {View} from 'react-native';
 import {useMemoizedLazyExpensifyIcons} from '@hooks/useLazyAsset';
 import useLocalize from '@hooks/useLocalize';
@@ -40,21 +40,14 @@ function ApprovalWorkflowSection({approvalWorkflow, onPress, currency = CONST.CU
         selector: personalDetailsByEmailSelector,
     });
 
-    const approverTitle = useCallback(
-        (index: number) =>
-            approvalWorkflow.approvers.length > 1 ? `${toLocaleOrdinal(index + 1, true)} ${translate('workflowsPage.approver').toLowerCase()}` : `${translate('workflowsPage.approver')}`,
-        [approvalWorkflow.approvers.length, toLocaleOrdinal, translate],
-    );
-
-    const members = useMemo(() => {
-        if (approvalWorkflow.isDefault) {
-            return translate('workspace.common.everyone');
-        }
+    const approverTitle = (index: number) =>
+        approvalWorkflow.approvers.length > 1 ? `${toLocaleOrdinal(index + 1, true)} ${translate('workflowsPage.approver').toLowerCase()}` : `${translate('workflowsPage.approver')}`;
 
-        return sortAlphabetically(approvalWorkflow.members, 'displayName', localeCompare)
-            .map((m) => Str.removeSMSDomain(m.displayName))
-            .join(', ');
-    }, [approvalWorkflow.isDefault, approvalWorkflow.members, translate, localeCompare]);
+    const members = approvalWorkflow.isDefault
+        ? translate('workspace.common.everyone')
+        : sortAlphabetically(approvalWorkflow.members, 'displayName', localeCompare)
+              .map((m) => Str.removeSMSDomain(m.displayName))
+              .join(', ');
 
     return (
         <PressableWithoutFeedback
diff --git a/src/components/NumberWithSymbolForm.tsx b/src/components/NumberWithSymbolForm.tsx
index 4701e8a91bd5..1c58ae9f69ec 100644
--- a/src/components/NumberWithSymbolForm.tsx
+++ b/src/components/NumberWithSymbolForm.tsx
@@ -1,6 +1,6 @@
 import {useIsFocused} from '@react-navigation/native';
 import type {ForwardedRef} from 'react';
-import React, {useCallback, useEffect, useImperativeHandle, useRef, useState} from 'react';
+import React, {useEffect, useImperativeHandle, useRef, useState} from 'react';
 import type {NativeSyntheticEvent} from 'react-native';
 import {View} from 'react-native';
 import {useMemoizedLazyExpensifyIcons} from '@hooks/useLazyAsset';
@@ -191,9 +191,9 @@ function NumberWithSymbolForm({
         setMouseUp();
     };
 
-    const clearSelection = useCallback(() => {
+    const clearSelection = () => {
         setSelection({start: selection.end, end: selection.end});
-    }, [selection.end]);
+    };
 
     /**
      * Event occurs when a user presses a mouse button over an DOM element.
@@ -219,39 +219,36 @@ function NumberWithSymbolForm({
      * Sets the selection and the number accordingly to the number passed to the input
      * @param newNumber - Changed number from user input
      */
-    const setNewNumber = useCallback(
-        (newNumber: string) => {
-            // Remove spaces from the newNumber number because Safari on iOS adds spaces when pasting a copied number
-            // More info: https://github.com/Expensify/App/issues/16974
-            const newNumberWithoutSpaces = stripSpacesFromAmount(newNumber);
-            const rawFinalNumber = newNumberWithoutSpaces.includes('.') ? stripCommaFromAmount(newNumberWithoutSpaces) : replaceCommasWithPeriod(newNumberWithoutSpaces);
-
-            const finalNumber = handleNegativeAmountFlipping(rawFinalNumber, allowFlippingAmount, toggleNegative);
-
-            // Use a shallow copy of selection to trigger setSelection
-            // More info: https://github.com/Expensify/App/issues/16385
-            if (!validateAmount(finalNumber, decimals, maxLength)) {
-                setSelection((prevSelection) => ({...prevSelection}));
-                return;
-            }
+    const setNewNumber = (newNumber: string) => {
+        // Remove spaces from the newNumber number because Safari on iOS adds spaces when pasting a copied number
+        // More info: https://github.com/Expensify/App/issues/16974
+        const newNumberWithoutSpaces = stripSpacesFromAmount(newNumber);
+        const rawFinalNumber = newNumberWithoutSpaces.includes('.') ? stripCommaFromAmount(newNumberWithoutSpaces) : replaceCommasWithPeriod(newNumberWithoutSpaces);
 
-            willSelectionBeUpdatedManually.current = true;
-            let hasSelectionBeenSet = false;
-            const strippedNumber = stripCommaFromAmount(finalNumber);
-            numberRef.current = strippedNumber;
-            setCurrentNumber((prevNumber) => {
-                const isForwardDelete = prevNumber.length > strippedNumber.length && forwardDeletePressedRef.current;
-                if (!hasSelectionBeenSet) {
-                    hasSelectionBeenSet = true;
-                    setSelection((prevSelection) => getNewSelection(prevSelection, isForwardDelete ? strippedNumber.length : prevNumber.length, strippedNumber.length));
-                    willSelectionBeUpdatedManually.current = false;
-                }
-                return strippedNumber;
-            });
-            onInputChange?.(strippedNumber);
-        },
-        [decimals, maxLength, onInputChange, allowFlippingAmount, toggleNegative],
-    );
+        const finalNumber = handleNegativeAmountFlipping(rawFinalNumber, allowFlippingAmount, toggleNegative);
+
+        // Use a shallow copy of selection to trigger setSelection
+        // More info: https://github.com/Expensify/App/issues/16385
+        if (!validateAmount(finalNumber, decimals, maxLength)) {
+            setSelection((prevSelection) => ({...prevSelection}));
+            return;
+        }
+
+        willSelectionBeUpdatedManually.current = true;
+        let hasSelectionBeenSet = false;
+        const strippedNumber = stripCommaFromAmount(finalNumber);
+        numberRef.current = strippedNumber;
+        setCurrentNumber((prevNumber) => {
+            const isForwardDelete = prevNumber.length > strippedNumber.length && forwardDeletePressedRef.current;
+            if (!hasSelectionBeenSet) {
+                hasSelectionBeenSet = true;
+                setSelection((prevSelection) => getNewSelection(prevSelection, isForwardDelete ? strippedNumber.length : prevNumber.length, strippedNumber.length));
+                willSelectionBeUpdatedManually.current = false;
+            }
+            return strippedNumber;
+        });
+        onInputChange?.(strippedNumber);
+    };
 
     /**
      * Set a new number number properly formatted, used for the TextInput
@@ -303,37 +300,34 @@ function NumberWithSymbolForm({
      * Update number with number or Backspace pressed for BigNumberPad.
      * Validate new number with decimal number regex up to 6 digits and 2 decimal digit to enable Next button
      */
-    const updateValueNumberPad = useCallback(
-        (key: string) => {
-            if (shouldUpdateSelection && !isTextInputFocused(textInput)) {
-                textInput.current?.focus();
-            }
-            // Backspace button is pressed
-            if (key === '<' || key === 'Backspace') {
-                if (currentNumber.length > 0) {
-                    const selectionStart = selection.start === selection.end ? selection.start - 1 : selection.start;
-                    const newNumber = `${currentNumber.substring(0, selectionStart)}${currentNumber.substring(selection.end)}`;
-                    setNewNumber(addLeadingZero(newNumber));
-                }
-                return;
+    const updateValueNumberPad = (key: string) => {
+        if (shouldUpdateSelection && !isTextInputFocused(textInput)) {
+            textInput.current?.focus();
+        }
+        // Backspace button is pressed
+        if (key === '<' || key === 'Backspace') {
+            if (currentNumber.length > 0) {
+                const selectionStart = selection.start === selection.end ? selection.start - 1 : selection.start;
+                const newNumber = `${currentNumber.substring(0, selectionStart)}${currentNumber.substring(selection.end)}`;
+                setNewNumber(addLeadingZero(newNumber));
             }
-            const newNumber = addLeadingZero(`${currentNumber.substring(0, selection.start)}${key}${currentNumber.substring(selection.end)}`);
-            setNewNumber(newNumber);
-        },
-        [currentNumber, selection.start, selection.end, shouldUpdateSelection, setNewNumber],
-    );
+            return;
+        }
+        const newNumber = addLeadingZero(`${currentNumber.substring(0, selection.start)}${key}${currentNumber.substring(selection.end)}`);
+        setNewNumber(newNumber);
+    };
 
     /**
      * Update long press number, to remove items pressing on <
      *
      * @param value - Changed text from user input
      */
-    const updateLongPressHandlerState = useCallback((value: boolean) => {
+    const updateLongPressHandlerState = (value: boolean) => {
         setShouldUpdateSelection(!value);
         if (!value && !isTextInputFocused(textInput)) {
             textInput.current?.focus();
         }
-    }, []);
+    };
 
     /**
      * Input handler to check for a forward-delete key (or keyboard shortcut) press.
diff --git a/src/pages/workspace/workflows/approvals/WorkspaceWorkflowsApprovalsCreatePage.tsx b/src/pages/workspace/workflows/approvals/WorkspaceWorkflowsApprovalsCreatePage.tsx
index f1b6280ce980..5ab0dc20f946 100644
--- a/src/pages/workspace/workflows/approvals/WorkspaceWorkflowsApprovalsCreatePage.tsx
+++ b/src/pages/workspace/workflows/approvals/WorkspaceWorkflowsApprovalsCreatePage.tsx
@@ -1,4 +1,4 @@
-import React, {useCallback, useRef} from 'react';
+import React, {useRef} from 'react';
 // eslint-disable-next-line no-restricted-imports
 import type {ScrollView} from 'react-native';
 import FullPageNotFoundView from '@components/BlockingViews/FullPageNotFoundView';
@@ -37,7 +37,7 @@ function WorkspaceWorkflowsApprovalsCreatePage({policy, isLoadingReportData = tr
     // eslint-disable-next-line rulesdir/no-negated-variables
     const shouldShowNotFoundView = (isEmptyObject(policy) && !isLoadingReportData) || !isPolicyAdmin(policy) || isPendingDeletePolicy(policy);
 
-    const createApprovalWorkflow = useCallback(() => {
+    const createApprovalWorkflow = () => {
         if (!approvalWorkflow) {
             return;
         }
@@ -48,7 +48,7 @@ function WorkspaceWorkflowsApprovalsCreatePage({policy, isLoadingReportData = tr
 
         createApprovalWorkflowAction(approvalWorkflow, policy);
         Navigation.dismissModal();
-    }, [approvalWorkflow, policy]);
+    };
 
     const submitButtonContainerStyles = useBottomSafeSafeAreaPaddingStyle({addBottomSafeAreaPadding: true, style: [styles.mb5, styles.mh5]});
 
diff --git a/src/pages/workspace/workflows/approvals/WorkspaceWorkflowsApprovalsEditPage.tsx b/src/pages/workspace/workflows/approvals/WorkspaceWorkflowsApprovalsEditPage.tsx
index 459665e8b3eb..2e429a0c4a11 100644
--- a/src/pages/workspace/workflows/approvals/WorkspaceWorkflowsApprovalsEditPage.tsx
+++ b/src/pages/workspace/workflows/approvals/WorkspaceWorkflowsApprovalsEditPage.tsx
@@ -1,4 +1,4 @@
-import React, {useCallback, useEffect, useMemo, useRef, useState} from 'react';
+import React, {useEffect, useRef, useState} from 'react';
 // eslint-disable-next-line no-restricted-imports
 import type {ScrollView} from 'react-native';
 import {InteractionManager} from 'react-native';
@@ -41,7 +41,7 @@ function WorkspaceWorkflowsApprovalsEditPage({policy, isLoadingReportData = true
     const formRef = useRef<ScrollView>(null);
     const isDeleting = useRef(false);
 
-    const updateApprovalWorkflowCallback = useCallback(() => {
+    const updateApprovalWorkflowCallback = () => {
         if (!approvalWorkflow || !initialApprovalWorkflow) {
             return;
         }
@@ -58,9 +58,9 @@ function WorkspaceWorkflowsApprovalsEditPage({policy, isLoadingReportData = true
         InteractionManager.runAfterInteractions(() => {
             updateApprovalWorkflow(approvalWorkflow, membersToRemove, approversToRemove, policy);
         });
-    }, [approvalWorkflow, initialApprovalWorkflow, policy]);
+    };
 
-    const removeApprovalWorkflowCallback = useCallback(() => {
+    const removeApprovalWorkflowCallback = () => {
         if (!initialApprovalWorkflow) {
             return;
         }
@@ -74,9 +74,9 @@ function WorkspaceWorkflowsApprovalsEditPage({policy, isLoadingReportData = true
             // Remove the approval workflow using the initial data as it could be already edited
             removeApprovalWorkflow(initialApprovalWorkflow, policy);
         });
-    }, [initialApprovalWorkflow, policy]);
+    };
 
-    const {currentApprovalWorkflow, defaultWorkflowMembers, usedApproverEmails} = useMemo(() => {
+    const getApprovalWorkflowData = () => {
         if (!policy || !personalDetails) {
             return {};
         }
@@ -94,7 +94,9 @@ function WorkspaceWorkflowsApprovalsEditPage({policy, isLoadingReportData = true
             usedApproverEmails: result.usedApproverEmails,
             currentApprovalWorkflow: result.approvalWorkflows.find((workflow) => workflow.approvers.at(0)?.email === firstApprover),
         };
-    }, [personalDetails, policy, route.params.firstApproverEmail, localeCompare]);
+    };
+
+    const {currentApprovalWorkflow, defaultWorkflowMembers, usedApproverEmails} = getApprovalWorkflowData();
 
     // eslint-disable-next-line rulesdir/no-negated-variables
     const shouldShowNotFoundView = (isEmptyObject(policy) && !isLoadingReportData) || !isPolicyAdmin(policy) || isPendingDeletePolicy(policy) || !currentApprovalWorkflow;

From fdae2c62b6c142c00cfcf85667bcc700b7d26419 Mon Sep 17 00:00:00 2001
From: Abdelrahman Khattab <abzokhattab@gmail.com>
Date: Wed, 17 Dec 2025 22:44:32 +0100
Subject: [PATCH 47/49] fixing ts

---
 src/components/AmountForm.tsx | 5 ++++-
 1 file changed, 4 insertions(+), 1 deletion(-)

diff --git a/src/components/AmountForm.tsx b/src/components/AmountForm.tsx
index 4b6303b61b1c..a9d15ec83897 100644
--- a/src/components/AmountForm.tsx
+++ b/src/components/AmountForm.tsx
@@ -48,7 +48,10 @@ type AmountFormProps = {
 
     /** Reference to the outer element */
     ref?: ForwardedRef<BaseTextInputRef>;
-} & Pick<BaseTextInputProps, 'autoFocus' | 'autoGrowExtraSpace' | 'autoGrowMarginSide' | 'onSubmitEditing'>;
+
+    /** Callback when the user presses the submit key (Enter) */
+    onSubmitEditing?: () => void;
+} & Pick<BaseTextInputProps, 'autoFocus' | 'autoGrowExtraSpace' | 'autoGrowMarginSide'>;
 
 /**
  * Wrapper around NumberWithSymbolForm with currency handling.

From 903aff9922447381a0bcf37717326c8d50268f17 Mon Sep 17 00:00:00 2001
From: Abdelrahman Khattab <abzokhattab@gmail.com>
Date: Wed, 17 Dec 2025 23:00:48 +0100
Subject: [PATCH 48/49] fixing enterApproverError msg

---
 src/languages/de.ts    | 2 +-
 src/languages/en.ts    | 2 +-
 src/languages/es.ts    | 2 +-
 src/languages/fr.ts    | 2 +-
 src/languages/it.ts    | 2 +-
 src/languages/ja.ts    | 2 +-
 src/languages/nl.ts    | 2 +-
 src/languages/pl.ts    | 2 +-
 src/languages/pt-BR.ts | 2 +-
 9 files changed, 9 insertions(+), 9 deletions(-)

diff --git a/src/languages/de.ts b/src/languages/de.ts
index ad0760206d50..03298c5d2958 100644
--- a/src/languages/de.ts
+++ b/src/languages/de.ts
@@ -2339,7 +2339,7 @@ ${amount} für ${merchant} – ${date}`,
         next: 'Weiter',
         removeLimit: 'Limit entfernen',
         enterAmountError: 'Bitte geben Sie einen gültigen Betrag ein',
-        enterApproverError: 'Ein Genehmiger ist erforderlich, wenn Sie ein Berichtslimit haben',
+        enterApproverError: 'Ein Genehmiger ist erforderlich, wenn Sie ein Berichtslimit festlegen',
         enterBothError: 'Geben Sie einen Berichtsbetrag und einen zusätzlichen Genehmiger ein',
         forwardLimitDescription: ({approvalLimit, approverName}: {approvalLimit: string; approverName: string}) => `Berichte über ${approvalLimit} werden an ${approverName} weitergeleitet`,
     },
diff --git a/src/languages/en.ts b/src/languages/en.ts
index d96e6d01174f..bbfc668f7a1c 100755
--- a/src/languages/en.ts
+++ b/src/languages/en.ts
@@ -2291,7 +2291,7 @@ const translations = {
         next: 'Next',
         removeLimit: 'Remove limit',
         enterAmountError: 'Please enter a valid amount',
-        enterApproverError: 'Approver is required when you have a report limit',
+        enterApproverError: 'Approver is required when you set a report limit',
         enterBothError: 'Enter a report amount and additional approver',
         forwardLimitDescription: ({approvalLimit, approverName}: {approvalLimit: string; approverName: string}) => `Reports above ${approvalLimit} forward to ${approverName}`,
     },
diff --git a/src/languages/es.ts b/src/languages/es.ts
index d07fd902a923..448476270bcd 100644
--- a/src/languages/es.ts
+++ b/src/languages/es.ts
@@ -1951,7 +1951,7 @@ ${amount} para ${merchant} - ${date}`,
         next: 'Siguiente',
         removeLimit: 'Eliminar límite',
         enterAmountError: 'Por favor, introduce un importe válido',
-        enterApproverError: 'Se requiere un aprobador cuando tienes un límite de informe',
+        enterApproverError: 'Se requiere un aprobador cuando estableces un límite de informe',
         enterBothError: 'Introduce un importe del informe y un aprobador adicional',
         forwardLimitDescription: ({approvalLimit, approverName}: {approvalLimit: string; approverName: string}) => `Los informes superiores a ${approvalLimit} se envían a ${approverName}`,
     },
diff --git a/src/languages/fr.ts b/src/languages/fr.ts
index ae74c4833369..738a99c685a4 100644
--- a/src/languages/fr.ts
+++ b/src/languages/fr.ts
@@ -2342,7 +2342,7 @@ ${amount} pour ${merchant} - ${date}`,
         next: 'Suivant',
         removeLimit: 'Supprimer la limite',
         enterAmountError: 'Veuillez entrer un montant valide',
-        enterApproverError: 'Un approbateur est requis lorsque vous avez une limite de rapport',
+        enterApproverError: 'Un approbateur est requis lorsque vous définissez une limite de rapport',
         enterBothError: 'Entrez un montant de rapport et un approbateur supplémentaire',
         forwardLimitDescription: ({approvalLimit, approverName}: {approvalLimit: string; approverName: string}) =>
             `Les rapports supérieurs à ${approvalLimit} sont transférés à ${approverName}`,
diff --git a/src/languages/it.ts b/src/languages/it.ts
index 7189ece7f5ae..83c0493db8ab 100644
--- a/src/languages/it.ts
+++ b/src/languages/it.ts
@@ -2331,7 +2331,7 @@ ${amount} per ${merchant} - ${date}`,
         next: 'Avanti',
         removeLimit: 'Rimuovi limite',
         enterAmountError: 'Inserisci un importo valido',
-        enterApproverError: 'Un approvatore è richiesto quando hai un limite di report',
+        enterApproverError: 'Un approvatore è richiesto quando imposti un limite di report',
         enterBothError: 'Inserisci un importo del report e un approvatore aggiuntivo',
         forwardLimitDescription: ({approvalLimit, approverName}: {approvalLimit: string; approverName: string}) =>
             `I report superiori a ${approvalLimit} vengono inoltrati a ${approverName}`,
diff --git a/src/languages/ja.ts b/src/languages/ja.ts
index bf940336cde0..c5abf087124f 100644
--- a/src/languages/ja.ts
+++ b/src/languages/ja.ts
@@ -2324,7 +2324,7 @@ ${merchant} への ${amount}（${date}）`,
         next: '次へ',
         removeLimit: '制限を削除',
         enterAmountError: '有効な金額を入力してください',
-        enterApproverError: 'レポート制限がある場合は承認者が必要です',
+        enterApproverError: 'レポート制限を設定する場合は承認者が必要です',
         enterBothError: 'レポート金額と追加の承認者を入力してください',
         forwardLimitDescription: ({approvalLimit, approverName}: {approvalLimit: string; approverName: string}) => `${approvalLimit}を超えるレポートは${approverName}に転送されます`,
     },
diff --git a/src/languages/nl.ts b/src/languages/nl.ts
index a0b94bf5d7e8..6dc04bfbedee 100644
--- a/src/languages/nl.ts
+++ b/src/languages/nl.ts
@@ -2329,7 +2329,7 @@ ${amount} voor ${merchant} - ${date}`,
         next: 'Volgende',
         removeLimit: 'Limiet verwijderen',
         enterAmountError: 'Voer een geldig bedrag in',
-        enterApproverError: 'Een goedkeurder is vereist wanneer u een rapportlimiet heeft',
+        enterApproverError: 'Een goedkeurder is vereist wanneer u een rapportlimiet instelt',
         enterBothError: 'Voer een rapportbedrag en een extra goedkeurder in',
         forwardLimitDescription: ({approvalLimit, approverName}: {approvalLimit: string; approverName: string}) =>
             `Rapporten boven ${approvalLimit} worden doorgestuurd naar ${approverName}`,
diff --git a/src/languages/pl.ts b/src/languages/pl.ts
index ec46e47cf8d6..7c5b2a8269e3 100644
--- a/src/languages/pl.ts
+++ b/src/languages/pl.ts
@@ -2326,7 +2326,7 @@ ${amount} dla ${merchant} - ${date}`,
         next: 'Dalej',
         removeLimit: 'Usuń limit',
         enterAmountError: 'Wprowadź prawidłową kwotę',
-        enterApproverError: 'Zatwierdzający jest wymagany, gdy masz limit raportu',
+        enterApproverError: 'Zatwierdzający jest wymagany, gdy ustawisz limit raportu',
         enterBothError: 'Wprowadź kwotę raportu i dodatkowego zatwierdzającego',
         forwardLimitDescription: ({approvalLimit, approverName}: {approvalLimit: string; approverName: string}) => `Raporty powyżej ${approvalLimit} są przekazywane do ${approverName}`,
     },
diff --git a/src/languages/pt-BR.ts b/src/languages/pt-BR.ts
index 79138406db99..0ec724a55960 100644
--- a/src/languages/pt-BR.ts
+++ b/src/languages/pt-BR.ts
@@ -2326,7 +2326,7 @@ ${amount} para ${merchant} - ${date}`,
         next: 'Próximo',
         removeLimit: 'Remover limite',
         enterAmountError: 'Por favor, insira um valor válido',
-        enterApproverError: 'Um aprovador é necessário quando você tem um limite de relatório',
+        enterApproverError: 'Um aprovador é necessário quando você define um limite de relatório',
         enterBothError: 'Insira um valor do relatório e um aprovador adicional',
         forwardLimitDescription: ({approvalLimit, approverName}: {approvalLimit: string; approverName: string}) =>
             `Relatórios acima de ${approvalLimit} são encaminhados para ${approverName}`,

From c3e9f40e5d095b4f30101a5983484dea0ab7945f Mon Sep 17 00:00:00 2001
From: Abdelrahman Khattab <abzokhattab@gmail.com>
Date: Thu, 18 Dec 2025 15:28:26 +0100
Subject: [PATCH 49/49] fixing number change bug

---
 src/components/NumberWithSymbolForm.tsx | 8 ++++++--
 1 file changed, 6 insertions(+), 2 deletions(-)

diff --git a/src/components/NumberWithSymbolForm.tsx b/src/components/NumberWithSymbolForm.tsx
index 1c58ae9f69ec..3fdeeb99b425 100644
--- a/src/components/NumberWithSymbolForm.tsx
+++ b/src/components/NumberWithSymbolForm.tsx
@@ -162,9 +162,13 @@ function NumberWithSymbolForm({
     // sync currentNumber with number prop when it changes externally
     useEffect(() => {
         const newNumber = typeof number === 'string' ? number : '';
-        if (newNumber !== currentNumber) {
-            setCurrentNumber(newNumber);
+
+        if (newNumber === currentNumber || (newNumber && currentNumber && Number(newNumber) === Number(currentNumber))) {
+            return;
         }
+
+        setCurrentNumber(newNumber);
+        // eslint-disable-next-line react-compiler/react-compiler, react-hooks/exhaustive-deps
     }, [number]);
 
     const [shouldUpdateSelection, setShouldUpdateSelection] = useState(true);
