From a047d8a5bf0ec13aef46af8998f2821133963ca4 Mon Sep 17 00:00:00 2001
From: Sachin Chavda <sachin.chavda.1024@gmail.com>
Date: Wed, 6 Nov 2024 17:08:00 +0530
Subject: [PATCH 01/31] show DelegateNoAccessModal for restricted delegate
 actions

---
 src/CONST.ts                                  |  6 ++
 src/components/AddressForm.tsx                |  6 +-
 src/components/DelegateNoAccessModal.tsx      |  8 +--
 src/components/DelegateNoAccessWrapper.tsx    | 71 +++++++++++++++++++
 src/components/Form/FormProvider.tsx          |  2 +-
 src/pages/AddressPage.tsx                     | 21 +++++-
 src/pages/settings/InitialSettingsPage.tsx    | 13 ++++
 .../Profile/Contacts/ContactMethodsPage.tsx   |  2 -
 .../Profile/Contacts/NewContactMethodPage.tsx |  7 +-
 .../PersonalDetails/DateOfBirthPage.tsx       | 21 ++++--
 .../Profile/PersonalDetails/LegalNamePage.tsx | 25 +++++--
 .../PersonalDetails/PhoneNumberPage.tsx       | 21 +++++-
 .../Security/SecuritySettingsPage.tsx         | 18 ++++-
 .../settings/Wallet/WalletPage/WalletPage.tsx | 19 +++++
 14 files changed, 212 insertions(+), 28 deletions(-)
 create mode 100644 src/components/DelegateNoAccessWrapper.tsx

diff --git a/src/CONST.ts b/src/CONST.ts
index 8a1e9cfbf67c..5c5745f7cfe6 100755
--- a/src/CONST.ts
+++ b/src/CONST.ts
@@ -4500,6 +4500,12 @@ const CONST = {
         ALL: 'all',
         SUBMITTER: 'submitter',
     },
+    DELEGATE: {
+        DENIED_ACCESS_VARIANTS: {
+            DELEGATE: 'delegate',
+            SUBMITTER: 'submitter',
+        },
+    },
     DELEGATE_ROLE_HELPDOT_ARTICLE_LINK: 'https://help.expensify.com/expensify-classic/hubs/copilots-and-delegates/',
     STRIPE_GBP_AUTH_STATUSES: {
         SUCCEEDED: 'succeeded',
diff --git a/src/components/AddressForm.tsx b/src/components/AddressForm.tsx
index 4470481d2be6..709770617fdc 100644
--- a/src/components/AddressForm.tsx
+++ b/src/components/AddressForm.tsx
@@ -56,6 +56,9 @@ type AddressFormProps = {
 
     /** A unique Onyx key identifying the form */
     formID: typeof ONYXKEYS.FORMS.GET_PHYSICAL_CARD_FORM | typeof ONYXKEYS.FORMS.HOME_ADDRESS_FORM;
+
+    /** Whether or not validation should be skipped */
+    skipValidation?: boolean;
 };
 
 function AddressForm({
@@ -70,6 +73,7 @@ function AddressForm({
     street2 = '',
     submitButtonText = '',
     zip = '',
+    skipValidation = false,
 }: AddressFormProps) {
     const styles = useThemeStyles();
     const {translate} = useLocalize();
@@ -139,7 +143,7 @@ function AddressForm({
         <FormProvider
             style={[styles.flexGrow1, styles.mh5]}
             formID={formID}
-            validate={validator}
+            validate={skipValidation ? undefined : validator}
             onSubmit={onSubmit}
             submitButtonText={submitButtonText}
             enabledWhenOffline
diff --git a/src/components/DelegateNoAccessModal.tsx b/src/components/DelegateNoAccessModal.tsx
index 442c3ec9c4e2..e1e5917ef757 100644
--- a/src/components/DelegateNoAccessModal.tsx
+++ b/src/components/DelegateNoAccessModal.tsx
@@ -1,4 +1,5 @@
 import React from 'react';
+import useDelegateUserDetails from '@hooks/useDelegateUserDetails';
 import useLocalize from '@hooks/useLocalize';
 import CONST from '@src/CONST';
 import ConfirmModal from './ConfirmModal';
@@ -8,14 +9,13 @@ import TextLink from './TextLink';
 type DelegateNoAccessModalProps = {
     isNoDelegateAccessMenuVisible: boolean;
     onClose: () => void;
-    delegatorEmail: string;
 };
 
-export default function DelegateNoAccessModal({isNoDelegateAccessMenuVisible = false, onClose, delegatorEmail = ''}: DelegateNoAccessModalProps) {
+export default function DelegateNoAccessModal({isNoDelegateAccessMenuVisible = false, onClose}: DelegateNoAccessModalProps) {
     const {translate} = useLocalize();
-    const noDelegateAccessPromptStart = translate('delegate.notAllowedMessageStart', {accountOwnerEmail: delegatorEmail});
+    const {delegatorEmail} = useDelegateUserDetails();
+    const noDelegateAccessPromptStart = translate('delegate.notAllowedMessageStart', {accountOwnerEmail: delegatorEmail ?? ''});
     const noDelegateAccessHyperLinked = translate('delegate.notAllowedMessageHyperLinked');
-
     const delegateNoAccessPrompt = (
         <Text>
             {noDelegateAccessPromptStart}
diff --git a/src/components/DelegateNoAccessWrapper.tsx b/src/components/DelegateNoAccessWrapper.tsx
new file mode 100644
index 000000000000..36e675547d7e
--- /dev/null
+++ b/src/components/DelegateNoAccessWrapper.tsx
@@ -0,0 +1,71 @@
+import React from 'react';
+import {OnyxEntry, useOnyx} from 'react-native-onyx';
+import useResponsiveLayout from '@hooks/useResponsiveLayout';
+import AccountUtils from '@libs/AccountUtils';
+import Navigation from '@libs/Navigation/Navigation';
+import NotFoundPage from '@pages/ErrorPage/NotFoundPage';
+import CONST from '@src/CONST';
+import ONYXKEYS from '@src/ONYXKEYS';
+import ROUTES from '@src/ROUTES';
+import {Account} from '@src/types/onyx';
+import callOrReturn from '@src/types/utils/callOrReturn';
+import {FullPageNotFoundViewProps} from './BlockingViews/FullPageNotFoundView';
+
+const DENIED_ACCESS_VARIANTS = {
+    [CONST.DELEGATE.DENIED_ACCESS_VARIANTS.DELEGATE]: (account: OnyxEntry<Account>) => isDelegate(account),
+    [CONST.DELEGATE.DENIED_ACCESS_VARIANTS.SUBMITTER]: (account: OnyxEntry<Account>) => isSubmitter(account),
+} as const satisfies Record<string, (account: OnyxEntry<Account>) => boolean>;
+
+type AccessDeniedVariants = keyof typeof DENIED_ACCESS_VARIANTS;
+
+type DelegateNoAccessWrapperProps = {
+    accessDeniedVariants?: AccessDeniedVariants[];
+    FullPageNotFoundViewProps?: FullPageNotFoundViewProps;
+    shouldShowFullScreenFallback?: boolean;
+    children: (() => React.ReactNode) | React.ReactNode;
+};
+
+type PageNotFoundFallbackProps = {
+    shouldShowFullScreenFallback?: boolean;
+};
+
+function isDelegate(account: OnyxEntry<Account>) {
+    const isActingAsDelegate = !!account?.delegatedAccess?.delegate;
+    return isActingAsDelegate;
+}
+
+function isSubmitter(account: OnyxEntry<Account>) {
+    const isDelegateOnlySubmitter = AccountUtils.isDelegateOnlySubmitter(account);
+    return isDelegateOnlySubmitter;
+}
+
+function PageNotFoundFallback({shouldShowFullScreenFallback}: PageNotFoundFallbackProps) {
+    const {shouldUseNarrowLayout} = useResponsiveLayout();
+    return (
+        <NotFoundPage
+            shouldForceFullScreen={shouldShowFullScreenFallback}
+            onBackButtonPress={() => {
+                if (shouldShowFullScreenFallback) {
+                    Navigation.dismissModal();
+                    return;
+                }
+                Navigation.goBack();
+            }}
+            shouldShowBackButton={!shouldShowFullScreenFallback ? shouldUseNarrowLayout : undefined}
+        />
+    );
+}
+
+function DelegateNoAccessWrapper({accessDeniedVariants = [], shouldShowFullScreenFallback, ...props}: DelegateNoAccessWrapperProps) {
+    const [account] = useOnyx(ONYXKEYS.ACCOUNT);
+    const isPageAccessDenied = accessDeniedVariants.reduce((acc, variant) => {
+        const accessDeniedFunction = DENIED_ACCESS_VARIANTS[variant];
+        return acc || accessDeniedFunction(account);
+    }, false);
+    if (isPageAccessDenied) {
+        return <PageNotFoundFallback shouldShowFullScreenFallback={shouldShowFullScreenFallback} />;
+    }
+    return callOrReturn(props.children);
+}
+
+export default DelegateNoAccessWrapper;
diff --git a/src/components/Form/FormProvider.tsx b/src/components/Form/FormProvider.tsx
index 1d66953c1070..d1b45e1d9327 100644
--- a/src/components/Form/FormProvider.tsx
+++ b/src/components/Form/FormProvider.tsx
@@ -44,7 +44,7 @@ type FormProviderProps<TFormID extends OnyxFormKey = OnyxFormKey> = FormProps<TF
     children: ((props: {inputValues: FormOnyxValues<TFormID>}) => ReactNode) | ReactNode;
 
     /** Callback to validate the form */
-    validate?: (values: FormOnyxValues<TFormID>) => FormInputErrors<TFormID>;
+    validate?: (values: FormOnyxValues<TFormID>) => FormInputErrors<TFormID> | undefined;
 
     /** Should validate function be called when input loose focus */
     shouldValidateOnBlur?: boolean;
diff --git a/src/pages/AddressPage.tsx b/src/pages/AddressPage.tsx
index 88e52409751b..670b582e08a2 100644
--- a/src/pages/AddressPage.tsx
+++ b/src/pages/AddressPage.tsx
@@ -1,6 +1,7 @@
 import React, {useCallback, useEffect, useState} from 'react';
-import type {OnyxEntry} from 'react-native-onyx';
+import {type OnyxEntry, useOnyx} from 'react-native-onyx';
 import AddressForm from '@components/AddressForm';
+import DelegateNoAccessModal from '@components/DelegateNoAccessModal';
 import FullscreenLoadingIndicator from '@components/FullscreenLoadingIndicator';
 import HeaderWithBackButton from '@components/HeaderWithBackButton';
 import ScreenWrapper from '@components/ScreenWrapper';
@@ -37,6 +38,17 @@ function AddressPage({title, address, updateAddress, isLoadingApp = true, backTo
     const [city, setCity] = useState(address?.city);
     const [zipcode, setZipcode] = useState(address?.zip);
 
+    const [account] = useOnyx(ONYXKEYS.ACCOUNT);
+    const isActingAsDelegate = !!account?.delegatedAccess?.delegate;
+    const [isNoDelegateAccessMenuVisible, setIsNoDelegateAccessMenuVisible] = useState(false);
+
+    // For delegates, modifying legal address is a restricted action.
+    // So, on pressing submit, skip validation and show delegateNoAccessModal
+    const skipValidation = isActingAsDelegate;
+    const handleSubmit = (values: FormOnyxValues<typeof ONYXKEYS.FORMS.HOME_ADDRESS_FORM>) => {
+        isActingAsDelegate ? setIsNoDelegateAccessMenuVisible(true) : updateAddress(values);
+    };
+
     useEffect(() => {
         if (!address) {
             return;
@@ -91,7 +103,7 @@ function AddressPage({title, address, updateAddress, isLoadingApp = true, backTo
             ) : (
                 <AddressForm
                     formID={ONYXKEYS.FORMS.HOME_ADDRESS_FORM}
-                    onSubmit={updateAddress}
+                    onSubmit={handleSubmit}
                     submitButtonText={translate('common.save')}
                     city={city}
                     country={currentCountry}
@@ -100,8 +112,13 @@ function AddressPage({title, address, updateAddress, isLoadingApp = true, backTo
                     street1={street1}
                     street2={street2}
                     zip={zipcode}
+                    skipValidation={skipValidation}
                 />
             )}
+            <DelegateNoAccessModal
+                isNoDelegateAccessMenuVisible={isNoDelegateAccessMenuVisible}
+                onClose={() => setIsNoDelegateAccessMenuVisible(false)}
+            />
         </ScreenWrapper>
     );
 }
diff --git a/src/pages/settings/InitialSettingsPage.tsx b/src/pages/settings/InitialSettingsPage.tsx
index 8c1d68e0a95b..3256a6dbc500 100755
--- a/src/pages/settings/InitialSettingsPage.tsx
+++ b/src/pages/settings/InitialSettingsPage.tsx
@@ -8,6 +8,7 @@ import type {ValueOf} from 'type-fest';
 import AccountSwitcher from '@components/AccountSwitcher';
 import AccountSwitcherSkeletonView from '@components/AccountSwitcherSkeletonView';
 import ConfirmModal from '@components/ConfirmModal';
+import DelegateNoAccessModal from '@components/DelegateNoAccessModal';
 import Icon from '@components/Icon';
 import * as Expensicons from '@components/Icon/Expensicons';
 import {InitialURLContext} from '@components/InitialURLContextProvider';
@@ -83,6 +84,10 @@ function InitialSettingsPage({currentUserPersonalDetails}: InitialSettingsPagePr
     const [policies] = useOnyx(ONYXKEYS.COLLECTION.POLICY);
     const [privatePersonalDetails] = useOnyx(ONYXKEYS.PRIVATE_PERSONAL_DETAILS);
 
+    const [account] = useOnyx(ONYXKEYS.ACCOUNT);
+    const isActingAsDelegate = !!account?.delegatedAccess?.delegate;
+    const [isNoDelegateAccessMenuVisible, setIsNoDelegateAccessMenuVisible] = useState(false);
+
     const network = useNetwork();
     const theme = useTheme();
     const styles = useThemeStyles();
@@ -242,6 +247,10 @@ function InitialSettingsPage({currentUserPersonalDetails}: InitialSettingsPagePr
                           }
                         : {
                               action() {
+                                  if (isActingAsDelegate) {
+                                      setIsNoDelegateAccessMenuVisible(true);
+                                      return;
+                                  }
                                   resetExitSurveyForm(() => Navigation.navigate(ROUTES.SETTINGS_EXIT_SURVEY_REASON));
                               },
                           }),
@@ -435,6 +444,10 @@ function InitialSettingsPage({currentUserPersonalDetails}: InitialSettingsPagePr
                     onCancel={() => toggleSignoutConfirmModal(false)}
                 />
             </ScrollView>
+            <DelegateNoAccessModal
+                isNoDelegateAccessMenuVisible={isNoDelegateAccessMenuVisible}
+                onClose={() => setIsNoDelegateAccessMenuVisible(false)}
+            />
         </ScreenWrapper>
     );
 }
diff --git a/src/pages/settings/Profile/Contacts/ContactMethodsPage.tsx b/src/pages/settings/Profile/Contacts/ContactMethodsPage.tsx
index 92a246949c53..dac36a15cefd 100644
--- a/src/pages/settings/Profile/Contacts/ContactMethodsPage.tsx
+++ b/src/pages/settings/Profile/Contacts/ContactMethodsPage.tsx
@@ -36,7 +36,6 @@ function ContactMethodsPage({route}: ContactMethodsPageProps) {
     const [account] = useOnyx(ONYXKEYS.ACCOUNT);
     const isActingAsDelegate = !!account?.delegatedAccess?.delegate;
     const [isNoDelegateAccessMenuVisible, setIsNoDelegateAccessMenuVisible] = useState(false);
-    const {delegatorEmail} = useDelegateUserDetails();
 
     // Sort the login names by placing the one corresponding to the default contact method as the first item before displaying the contact methods.
     // The default contact method is determined by checking against the session email (the current login).
@@ -132,7 +131,6 @@ function ContactMethodsPage({route}: ContactMethodsPageProps) {
             <DelegateNoAccessModal
                 isNoDelegateAccessMenuVisible={isNoDelegateAccessMenuVisible}
                 onClose={() => setIsNoDelegateAccessMenuVisible(false)}
-                delegatorEmail={delegatorEmail ?? ''}
             />
         </ScreenWrapper>
     );
diff --git a/src/pages/settings/Profile/Contacts/NewContactMethodPage.tsx b/src/pages/settings/Profile/Contacts/NewContactMethodPage.tsx
index c2a7e1b6712c..d23af0371ef3 100644
--- a/src/pages/settings/Profile/Contacts/NewContactMethodPage.tsx
+++ b/src/pages/settings/Profile/Contacts/NewContactMethodPage.tsx
@@ -3,6 +3,7 @@ import {Str} from 'expensify-common';
 import React, {useCallback, useEffect, useRef, useState} from 'react';
 import {View} from 'react-native';
 import {useOnyx} from 'react-native-onyx';
+import DelegateNoAccessWrapper from '@components/DelegateNoAccessWrapper';
 import DotIndicatorMessage from '@components/DotIndicatorMessage';
 import FormProvider from '@components/Form/FormProvider';
 import InputWrapper from '@components/Form/InputWrapper';
@@ -110,7 +111,8 @@ function NewContactMethodPage({route}: NewContactMethodPageProps) {
     }, [navigateBackTo]);
 
     return (
-        <AccessOrNotFoundWrapper shouldBeBlocked={isActingAsDelegate}>
+        // <AccessOrNotFoundWrapper shouldBeBlocked={isActingAsDelegate}>
+        <DelegateNoAccessWrapper accessDeniedVariants={[CONST.DELEGATE.DENIED_ACCESS_VARIANTS.DELEGATE]}>
             <ScreenWrapper
                 onEntryTransitionEnd={() => loginInputRef.current?.focus()}
                 includeSafeAreaPaddingBottom={false}
@@ -174,7 +176,8 @@ function NewContactMethodPage({route}: NewContactMethodPageProps) {
                     description={translate('contacts.enterMagicCode', {contactMethod})}
                 />
             </ScreenWrapper>
-        </AccessOrNotFoundWrapper>
+        </DelegateNoAccessWrapper>
+        // </AccessOrNotFoundWrapper>
     );
 }
 
diff --git a/src/pages/settings/Profile/PersonalDetails/DateOfBirthPage.tsx b/src/pages/settings/Profile/PersonalDetails/DateOfBirthPage.tsx
index e91093731c03..882f29d51b99 100644
--- a/src/pages/settings/Profile/PersonalDetails/DateOfBirthPage.tsx
+++ b/src/pages/settings/Profile/PersonalDetails/DateOfBirthPage.tsx
@@ -1,8 +1,9 @@
 import {subYears} from 'date-fns';
-import React, {useCallback} from 'react';
+import React, {useCallback, useState} from 'react';
 import type {OnyxEntry} from 'react-native-onyx';
-import {withOnyx} from 'react-native-onyx';
+import {useOnyx, withOnyx} from 'react-native-onyx';
 import DatePicker from '@components/DatePicker';
+import DelegateNoAccessModal from '@components/DelegateNoAccessModal';
 import FormProvider from '@components/Form/FormProvider';
 import InputWrapper from '@components/Form/InputWrapper';
 import type {FormOnyxValues} from '@components/Form/types';
@@ -16,7 +17,7 @@ import * as ValidationUtils from '@libs/ValidationUtils';
 import * as PersonalDetails from '@userActions/PersonalDetails';
 import CONST from '@src/CONST';
 import ONYXKEYS from '@src/ONYXKEYS';
-import INPUT_IDS from '@src/types/form/DateOfBirthForm';
+import INPUT_IDS, {DateOfBirthForm} from '@src/types/form/DateOfBirthForm';
 import type {PrivatePersonalDetails} from '@src/types/onyx';
 
 type DateOfBirthPageOnyxProps = {
@@ -30,6 +31,9 @@ type DateOfBirthPageProps = DateOfBirthPageOnyxProps;
 function DateOfBirthPage({privatePersonalDetails, isLoadingApp = true}: DateOfBirthPageProps) {
     const {translate} = useLocalize();
     const styles = useThemeStyles();
+    const [account] = useOnyx(ONYXKEYS.ACCOUNT);
+    const isActingAsDelegate = !!account?.delegatedAccess?.delegate;
+    const [isNoDelegateAccessMenuVisible, setIsNoDelegateAccessMenuVisible] = useState(false);
 
     /**
      * @returns An object containing the errors for each inputID
@@ -48,6 +52,13 @@ function DateOfBirthPage({privatePersonalDetails, isLoadingApp = true}: DateOfBi
 
         return errors;
     }, []);
+    // For delegates, modifying legal DOB is a restricted action.
+    // So, on pressing submit, skip validation and show delegateNoAccessModal
+
+    const skipValidation = isActingAsDelegate;
+    const handleSubmit = (DOB: DateOfBirthForm) => {
+        isActingAsDelegate ? setIsNoDelegateAccessMenuVisible(true) : PersonalDetails.updateDateOfBirth(DOB);
+    };
 
     return (
         <ScreenWrapper
@@ -64,8 +75,8 @@ function DateOfBirthPage({privatePersonalDetails, isLoadingApp = true}: DateOfBi
                 <FormProvider
                     style={[styles.flexGrow1, styles.ph5]}
                     formID={ONYXKEYS.FORMS.DATE_OF_BIRTH_FORM}
-                    validate={validate}
-                    onSubmit={PersonalDetails.updateDateOfBirth}
+                    validate={skipValidation ? undefined : validate}
+                    onSubmit={handleSubmit}
                     submitButtonText={translate('common.save')}
                     enabledWhenOffline
                 >
diff --git a/src/pages/settings/Profile/PersonalDetails/LegalNamePage.tsx b/src/pages/settings/Profile/PersonalDetails/LegalNamePage.tsx
index 99e9c910cbdf..cf9a8ec398a3 100644
--- a/src/pages/settings/Profile/PersonalDetails/LegalNamePage.tsx
+++ b/src/pages/settings/Profile/PersonalDetails/LegalNamePage.tsx
@@ -1,7 +1,8 @@
-import React, {useCallback} from 'react';
+import React, {useCallback, useState} from 'react';
 import {View} from 'react-native';
 import type {OnyxEntry} from 'react-native-onyx';
-import {withOnyx} from 'react-native-onyx';
+import {useOnyx, withOnyx} from 'react-native-onyx';
+import DelegateNoAccessModal from '@components/DelegateNoAccessModal';
 import FormProvider from '@components/Form/FormProvider';
 import InputWrapper from '@components/Form/InputWrapper';
 import type {FormOnyxValues} from '@components/Form/types';
@@ -33,12 +34,14 @@ type LegalNamePageProps = LegalNamePageOnyxProps;
 const updateLegalName = (values: PrivatePersonalDetails) => {
     PersonalDetails.updateLegalName(values.legalFirstName?.trim() ?? '', values.legalLastName?.trim() ?? '');
 };
-
 function LegalNamePage({privatePersonalDetails, isLoadingApp = true}: LegalNamePageProps) {
     const styles = useThemeStyles();
     const {translate} = useLocalize();
     const legalFirstName = privatePersonalDetails?.legalFirstName ?? '';
     const legalLastName = privatePersonalDetails?.legalLastName ?? '';
+    const [account] = useOnyx(ONYXKEYS.ACCOUNT);
+    const isActingAsDelegate = !!account?.delegatedAccess?.delegate;
+    const [isNoDelegateAccessMenuVisible, setIsNoDelegateAccessMenuVisible] = useState(false);
 
     const validate = useCallback(
         (values: FormOnyxValues<typeof ONYXKEYS.FORMS.LEGAL_NAME_FORM>) => {
@@ -83,6 +86,14 @@ function LegalNamePage({privatePersonalDetails, isLoadingApp = true}: LegalNameP
         [translate],
     );
 
+    // For delegates, modifying legal Name is a restricted action.
+    // So, on pressing submit, skip validation and show delegateNoAccessModal
+
+    const skipValidation = isActingAsDelegate;
+    const handleSubmit = (values: PrivatePersonalDetails) => {
+        isActingAsDelegate ? setIsNoDelegateAccessMenuVisible(true) : updateLegalName(values);
+    };
+
     return (
         <ScreenWrapper
             includeSafeAreaPaddingBottom={false}
@@ -99,8 +110,8 @@ function LegalNamePage({privatePersonalDetails, isLoadingApp = true}: LegalNameP
                 <FormProvider
                     style={[styles.flexGrow1, styles.ph5]}
                     formID={ONYXKEYS.FORMS.LEGAL_NAME_FORM}
-                    validate={validate}
-                    onSubmit={updateLegalName}
+                    validate={skipValidation ? undefined : validate}
+                    onSubmit={handleSubmit}
                     submitButtonText={translate('common.save')}
                     enabledWhenOffline
                 >
@@ -130,6 +141,10 @@ function LegalNamePage({privatePersonalDetails, isLoadingApp = true}: LegalNameP
                     </View>
                 </FormProvider>
             )}
+            <DelegateNoAccessModal
+                isNoDelegateAccessMenuVisible={isNoDelegateAccessMenuVisible}
+                onClose={() => setIsNoDelegateAccessMenuVisible(false)}
+            />
         </ScreenWrapper>
     );
 }
diff --git a/src/pages/settings/Profile/PersonalDetails/PhoneNumberPage.tsx b/src/pages/settings/Profile/PersonalDetails/PhoneNumberPage.tsx
index 12c6f011c6a2..536fa510ef54 100644
--- a/src/pages/settings/Profile/PersonalDetails/PhoneNumberPage.tsx
+++ b/src/pages/settings/Profile/PersonalDetails/PhoneNumberPage.tsx
@@ -1,6 +1,7 @@
 import {Str} from 'expensify-common';
-import React, {useCallback} from 'react';
+import React, {useCallback, useState} from 'react';
 import {useOnyx} from 'react-native-onyx';
+import DelegateNoAccessModal from '@components/DelegateNoAccessModal';
 import FormProvider from '@components/Form/FormProvider';
 import InputWrapper from '@components/Form/InputWrapper';
 import type {FormInputErrors, FormOnyxValues} from '@components/Form/types';
@@ -32,6 +33,10 @@ function PhoneNumberPage() {
     const validateLoginError = ErrorUtils.getEarliestErrorField(privatePersonalDetails, 'phoneNumber');
     const currenPhoneNumber = privatePersonalDetails?.phoneNumber ?? '';
 
+    const [account] = useOnyx(ONYXKEYS.ACCOUNT);
+    const isActingAsDelegate = !!account?.delegatedAccess?.delegate;
+    const [isNoDelegateAccessMenuVisible, setIsNoDelegateAccessMenuVisible] = useState(false);
+
     const updatePhoneNumber = (values: PrivatePersonalDetails) => {
         // Clear the error when the user tries to submit the form
         if (validateLoginError) {
@@ -66,6 +71,12 @@ function PhoneNumberPage() {
         },
         [translate, validateLoginError],
     );
+    // For delegates, modifying Phone Number is a restricted action.
+    // So, on pressing submit, skip validation and show delegateNoAccessModal
+    const skipValidation = isActingAsDelegate;
+    const handleSubmit = (values: PrivatePersonalDetails) => {
+        isActingAsDelegate ? setIsNoDelegateAccessMenuVisible(true) : updatePhoneNumber(values);
+    };
 
     return (
         <ScreenWrapper
@@ -83,8 +94,8 @@ function PhoneNumberPage() {
                 <FormProvider
                     style={[styles.flexGrow1, styles.ph5]}
                     formID={ONYXKEYS.FORMS.PERSONAL_DETAILS_FORM}
-                    validate={validate}
-                    onSubmit={updatePhoneNumber}
+                    validate={skipValidation ? undefined : validate}
+                    onSubmit={handleSubmit}
                     submitButtonText={translate('common.save')}
                     enabledWhenOffline
                 >
@@ -112,6 +123,10 @@ function PhoneNumberPage() {
                     </OfflineWithFeedback>
                 </FormProvider>
             )}
+            <DelegateNoAccessModal
+                isNoDelegateAccessMenuVisible={isNoDelegateAccessMenuVisible}
+                onClose={() => setIsNoDelegateAccessMenuVisible(false)}
+            />
         </ScreenWrapper>
     );
 }
diff --git a/src/pages/settings/Security/SecuritySettingsPage.tsx b/src/pages/settings/Security/SecuritySettingsPage.tsx
index cd8e7c14d882..f646725319b3 100644
--- a/src/pages/settings/Security/SecuritySettingsPage.tsx
+++ b/src/pages/settings/Security/SecuritySettingsPage.tsx
@@ -5,6 +5,7 @@ import {Dimensions, View} from 'react-native';
 import type {GestureResponderEvent} from 'react-native';
 import {useOnyx} from 'react-native-onyx';
 import ConfirmModal from '@components/ConfirmModal';
+import DelegateNoAccessModal from '@components/DelegateNoAccessModal';
 import HeaderWithBackButton from '@components/HeaderWithBackButton';
 import * as Expensicons from '@components/Icon/Expensicons';
 import {FallbackAvatar} from '@components/Icon/Expensicons';
@@ -20,6 +21,7 @@ import ScrollView from '@components/ScrollView';
 import Section from '@components/Section';
 import Text from '@components/Text';
 import TextLink from '@components/TextLink';
+import useDelegateUserDetails from '@hooks/useDelegateUserDetails';
 import useLocalize from '@hooks/useLocalize';
 import useResponsiveLayout from '@hooks/useResponsiveLayout';
 import useThemeStyles from '@hooks/useThemeStyles';
@@ -63,6 +65,10 @@ function SecuritySettingsPage() {
         anchorPositionRight: 0,
     });
 
+    const [isNoDelegateAccessMenuVisible, setIsNoDelegateAccessMenuVisible] = useState(false);
+
+    // const [account] = useOnyx(ONYXKEYS.ACCOUNT);
+    // const isActingAsDelegate = !!account?.delegatedAccess?.delegate;
     const setMenuPosition = useCallback(() => {
         if (!delegateButtonRef.current) {
             return;
@@ -92,7 +98,9 @@ function SecuritySettingsPage() {
         setShouldShowDelegatePopoverMenu(true);
         setSelectedDelegate(delegate);
     };
-
+    const showDelegateNoAccessMenu = () => {
+        setIsNoDelegateAccessMenuVisible(true);
+    };
     useLayoutEffect(() => {
         const popoverPositionListener = Dimensions.addEventListener('change', () => {
             debounce(setMenuPosition, CONST.TIMING.RESIZE_DEBOUNCE_TIME)();
@@ -111,12 +119,12 @@ function SecuritySettingsPage() {
             {
                 translationKey: 'twoFactorAuth.headerTitle',
                 icon: Expensicons.Shield,
-                action: waitForNavigate(() => Navigation.navigate(ROUTES.SETTINGS_2FA.getRoute())),
+                action: isActingAsDelegate ? showDelegateNoAccessMenu : waitForNavigate(() => Navigation.navigate(ROUTES.SETTINGS_2FA.getRoute())),
             },
             {
                 translationKey: 'closeAccountPage.closeAccount',
                 icon: Expensicons.ClosedSign,
-                action: waitForNavigate(() => Navigation.navigate(ROUTES.SETTINGS_CLOSE)),
+                action: isActingAsDelegate ? showDelegateNoAccessMenu : waitForNavigate(() => Navigation.navigate(ROUTES.SETTINGS_CLOSE)),
             },
         ];
 
@@ -333,6 +341,10 @@ function SecuritySettingsPage() {
                             />
                         </View>
                     </ScrollView>
+                    <DelegateNoAccessModal
+                        isNoDelegateAccessMenuVisible={isNoDelegateAccessMenuVisible}
+                        onClose={() => setIsNoDelegateAccessMenuVisible(false)}
+                    />
                 </>
             )}
         </ScreenWrapper>
diff --git a/src/pages/settings/Wallet/WalletPage/WalletPage.tsx b/src/pages/settings/Wallet/WalletPage/WalletPage.tsx
index 7b9366370349..79b0a434a5ad 100644
--- a/src/pages/settings/Wallet/WalletPage/WalletPage.tsx
+++ b/src/pages/settings/Wallet/WalletPage/WalletPage.tsx
@@ -7,6 +7,7 @@ import {ActivityIndicator, Dimensions, View} from 'react-native';
 import {useOnyx} from 'react-native-onyx';
 import AddPaymentMethodMenu from '@components/AddPaymentMethodMenu';
 import ConfirmModal from '@components/ConfirmModal';
+import DelegateNoAccessModal from '@components/DelegateNoAccessModal';
 import HeaderWithBackButton from '@components/HeaderWithBackButton';
 import Icon from '@components/Icon';
 import * as Expensicons from '@components/Icon/Expensicons';
@@ -22,6 +23,7 @@ import ScreenWrapper from '@components/ScreenWrapper';
 import ScrollView from '@components/ScrollView';
 import Section from '@components/Section';
 import Text from '@components/Text';
+import useDelegateUserDetails from '@hooks/useDelegateUserDetails';
 import useLocalize from '@hooks/useLocalize';
 import useNetwork from '@hooks/useNetwork';
 import usePaymentMethodState from '@hooks/usePaymentMethodState';
@@ -59,6 +61,10 @@ function WalletPage({shouldListenForResize = false}: WalletPageProps) {
     const [walletTerms] = useOnyx(ONYXKEYS.WALLET_TERMS, {initialValue: {}});
     const [isUserValidated] = useOnyx(ONYXKEYS.USER, {selector: (user) => !!user?.validated});
 
+    const [account] = useOnyx(ONYXKEYS.ACCOUNT);
+    const isActingAsDelegate = !!account?.delegatedAccess?.delegate;
+    const [isNoDelegateAccessMenuVisible, setIsNoDelegateAccessMenuVisible] = useState(false);
+
     const theme = useTheme();
     const styles = useThemeStyles();
     const {translate} = useLocalize();
@@ -179,6 +185,10 @@ function WalletPage({shouldListenForResize = false}: WalletPageProps) {
             setMenuPosition();
             return;
         }
+        if (isActingAsDelegate) {
+            setIsNoDelegateAccessMenuVisible(true);
+            return;
+        }
         setShouldShowAddPaymentMenu(true);
         setMenuPosition();
     };
@@ -499,6 +509,11 @@ function WalletPage({shouldListenForResize = false}: WalletPageProps) {
                                                         <MenuItem
                                                             ref={buttonRef as ForwardedRef<View>}
                                                             onPress={() => {
+                                                                if (isActingAsDelegate) {
+                                                                    setIsNoDelegateAccessMenuVisible(true);
+                                                                    return;
+                                                                }
+
                                                                 if (!isUserValidated) {
                                                                     Navigation.navigate(ROUTES.SETTINGS_WALLET_VERIFY_ACCOUNT.getRoute(ROUTES.SETTINGS_ENABLE_PAYMENTS));
                                                                     return;
@@ -595,6 +610,10 @@ function WalletPage({shouldListenForResize = false}: WalletPageProps) {
                 anchorRef={addPaymentMethodAnchorRef}
                 shouldShowPersonalBankAccountOption
             />
+            <DelegateNoAccessModal
+                isNoDelegateAccessMenuVisible={isNoDelegateAccessMenuVisible}
+                onClose={() => setIsNoDelegateAccessMenuVisible(false)}
+            />
         </>
     );
 }

From f33b43f4824944504a9e3c5823e6a7b9efc4890e Mon Sep 17 00:00:00 2001
From: Sachin Chavda <sachin.chavda.1024@gmail.com>
Date: Wed, 13 Nov 2024 16:22:11 +0530
Subject: [PATCH 02/31] LegalNamePage

---
 .../settings/Profile/PersonalDetails/LegalNamePage.tsx | 10 ++++++----
 1 file changed, 6 insertions(+), 4 deletions(-)

diff --git a/src/pages/settings/Profile/PersonalDetails/LegalNamePage.tsx b/src/pages/settings/Profile/PersonalDetails/LegalNamePage.tsx
index cf9a8ec398a3..4b30160f88e2 100644
--- a/src/pages/settings/Profile/PersonalDetails/LegalNamePage.tsx
+++ b/src/pages/settings/Profile/PersonalDetails/LegalNamePage.tsx
@@ -39,8 +39,7 @@ function LegalNamePage({privatePersonalDetails, isLoadingApp = true}: LegalNameP
     const {translate} = useLocalize();
     const legalFirstName = privatePersonalDetails?.legalFirstName ?? '';
     const legalLastName = privatePersonalDetails?.legalLastName ?? '';
-    const [account] = useOnyx(ONYXKEYS.ACCOUNT);
-    const isActingAsDelegate = !!account?.delegatedAccess?.delegate;
+    const [isActingAsDelegate] = useOnyx(ONYXKEYS.ACCOUNT, {selector: (account) => !!account?.delegatedAccess?.delegate});
     const [isNoDelegateAccessMenuVisible, setIsNoDelegateAccessMenuVisible] = useState(false);
 
     const validate = useCallback(
@@ -88,10 +87,13 @@ function LegalNamePage({privatePersonalDetails, isLoadingApp = true}: LegalNameP
 
     // For delegates, modifying legal Name is a restricted action.
     // So, on pressing submit, skip validation and show delegateNoAccessModal
-
     const skipValidation = isActingAsDelegate;
     const handleSubmit = (values: PrivatePersonalDetails) => {
-        isActingAsDelegate ? setIsNoDelegateAccessMenuVisible(true) : updateLegalName(values);
+        if (isActingAsDelegate) {
+            setIsNoDelegateAccessMenuVisible(true);
+            return;
+        }
+        updateLegalName(values);
     };
 
     return (

From cd5a45311afca70c4b6bd547a992ed393d676c62 Mon Sep 17 00:00:00 2001
From: Sachin Chavda <sachin.chavda.1024@gmail.com>
Date: Wed, 13 Nov 2024 16:26:06 +0530
Subject: [PATCH 03/31] DOB

---
 .../PersonalDetails/DateOfBirthPage.tsx       | 20 ++++++++++++++-----
 1 file changed, 15 insertions(+), 5 deletions(-)

diff --git a/src/pages/settings/Profile/PersonalDetails/DateOfBirthPage.tsx b/src/pages/settings/Profile/PersonalDetails/DateOfBirthPage.tsx
index 882f29d51b99..76f67e6dad36 100644
--- a/src/pages/settings/Profile/PersonalDetails/DateOfBirthPage.tsx
+++ b/src/pages/settings/Profile/PersonalDetails/DateOfBirthPage.tsx
@@ -17,7 +17,7 @@ import * as ValidationUtils from '@libs/ValidationUtils';
 import * as PersonalDetails from '@userActions/PersonalDetails';
 import CONST from '@src/CONST';
 import ONYXKEYS from '@src/ONYXKEYS';
-import INPUT_IDS, {DateOfBirthForm} from '@src/types/form/DateOfBirthForm';
+import INPUT_IDS, {type DateOfBirthForm} from '@src/types/form/DateOfBirthForm';
 import type {PrivatePersonalDetails} from '@src/types/onyx';
 
 type DateOfBirthPageOnyxProps = {
@@ -31,8 +31,10 @@ type DateOfBirthPageProps = DateOfBirthPageOnyxProps;
 function DateOfBirthPage({privatePersonalDetails, isLoadingApp = true}: DateOfBirthPageProps) {
     const {translate} = useLocalize();
     const styles = useThemeStyles();
-    const [account] = useOnyx(ONYXKEYS.ACCOUNT);
-    const isActingAsDelegate = !!account?.delegatedAccess?.delegate;
+    // const [account] = useOnyx(ONYXKEYS.ACCOUNT);
+    // const isActingAsDelegate = !!account?.delegatedAccess?.delegate;
+    const [isActingAsDelegate] = useOnyx(ONYXKEYS.ACCOUNT, {selector: (account) => !!account?.delegatedAccess?.delegate});
+
     const [isNoDelegateAccessMenuVisible, setIsNoDelegateAccessMenuVisible] = useState(false);
 
     /**
@@ -52,12 +54,16 @@ function DateOfBirthPage({privatePersonalDetails, isLoadingApp = true}: DateOfBi
 
         return errors;
     }, []);
+
     // For delegates, modifying legal DOB is a restricted action.
     // So, on pressing submit, skip validation and show delegateNoAccessModal
-
     const skipValidation = isActingAsDelegate;
     const handleSubmit = (DOB: DateOfBirthForm) => {
-        isActingAsDelegate ? setIsNoDelegateAccessMenuVisible(true) : PersonalDetails.updateDateOfBirth(DOB);
+        if (isActingAsDelegate) {
+            setIsNoDelegateAccessMenuVisible(true);
+            return;
+        }
+        PersonalDetails.updateDateOfBirth(DOB);
     };
 
     return (
@@ -90,6 +96,10 @@ function DateOfBirthPage({privatePersonalDetails, isLoadingApp = true}: DateOfBi
                     />
                 </FormProvider>
             )}
+            <DelegateNoAccessModal
+                isNoDelegateAccessMenuVisible={isNoDelegateAccessMenuVisible}
+                onClose={() => setIsNoDelegateAccessMenuVisible(false)}
+            />
         </ScreenWrapper>
     );
 }

From 61b69c188f579f9e6f2396fab0f5f4e8f36d9811 Mon Sep 17 00:00:00 2001
From: Sachin Chavda <sachin.chavda.1024@gmail.com>
Date: Wed, 13 Nov 2024 16:26:52 +0530
Subject: [PATCH 04/31] PhoneNumber

---
 .../Profile/PersonalDetails/PhoneNumberPage.tsx       | 11 ++++++++---
 1 file changed, 8 insertions(+), 3 deletions(-)

diff --git a/src/pages/settings/Profile/PersonalDetails/PhoneNumberPage.tsx b/src/pages/settings/Profile/PersonalDetails/PhoneNumberPage.tsx
index 536fa510ef54..f4eed49c8a2e 100644
--- a/src/pages/settings/Profile/PersonalDetails/PhoneNumberPage.tsx
+++ b/src/pages/settings/Profile/PersonalDetails/PhoneNumberPage.tsx
@@ -33,8 +33,9 @@ function PhoneNumberPage() {
     const validateLoginError = ErrorUtils.getEarliestErrorField(privatePersonalDetails, 'phoneNumber');
     const currenPhoneNumber = privatePersonalDetails?.phoneNumber ?? '';
 
-    const [account] = useOnyx(ONYXKEYS.ACCOUNT);
-    const isActingAsDelegate = !!account?.delegatedAccess?.delegate;
+    // const [account] = useOnyx(ONYXKEYS.ACCOUNT);
+    // const isActingAsDelegate = !!account?.delegatedAccess?.delegate;
+    const [isActingAsDelegate] = useOnyx(ONYXKEYS.ACCOUNT, {selector: (account) => account?.delegatedAccess?.delegate});
     const [isNoDelegateAccessMenuVisible, setIsNoDelegateAccessMenuVisible] = useState(false);
 
     const updatePhoneNumber = (values: PrivatePersonalDetails) => {
@@ -75,7 +76,11 @@ function PhoneNumberPage() {
     // So, on pressing submit, skip validation and show delegateNoAccessModal
     const skipValidation = isActingAsDelegate;
     const handleSubmit = (values: PrivatePersonalDetails) => {
-        isActingAsDelegate ? setIsNoDelegateAccessMenuVisible(true) : updatePhoneNumber(values);
+        if (isActingAsDelegate) {
+            setIsNoDelegateAccessMenuVisible(true);
+            return;
+        }
+        updatePhoneNumber(values);
     };
 
     return (

From feff84b83e9d103ba52e8c62b67664872766e3c8 Mon Sep 17 00:00:00 2001
From: Sachin Chavda <sachin.chavda.1024@gmail.com>
Date: Wed, 13 Nov 2024 16:27:22 +0530
Subject: [PATCH 05/31] Address

---
 src/pages/AddressPage.tsx | 15 +++++++++++----
 1 file changed, 11 insertions(+), 4 deletions(-)

diff --git a/src/pages/AddressPage.tsx b/src/pages/AddressPage.tsx
index 670b582e08a2..714f48a5e04a 100644
--- a/src/pages/AddressPage.tsx
+++ b/src/pages/AddressPage.tsx
@@ -1,5 +1,6 @@
 import React, {useCallback, useEffect, useState} from 'react';
-import {type OnyxEntry, useOnyx} from 'react-native-onyx';
+import type {OnyxEntry} from 'react-native-onyx';
+import {useOnyx} from 'react-native-onyx';
 import AddressForm from '@components/AddressForm';
 import DelegateNoAccessModal from '@components/DelegateNoAccessModal';
 import FullscreenLoadingIndicator from '@components/FullscreenLoadingIndicator';
@@ -38,15 +39,21 @@ function AddressPage({title, address, updateAddress, isLoadingApp = true, backTo
     const [city, setCity] = useState(address?.city);
     const [zipcode, setZipcode] = useState(address?.zip);
 
-    const [account] = useOnyx(ONYXKEYS.ACCOUNT);
-    const isActingAsDelegate = !!account?.delegatedAccess?.delegate;
+    // const [account] = useOnyx(ONYXKEYS.ACCOUNT);
+    // const isActingAsDelegate = !!account?.delegatedAccess?.delegate;
+    const [isActingAsDelegate] = useOnyx(ONYXKEYS.ACCOUNT, {selector: (account) => !!account?.delegatedAccess?.delegate});
     const [isNoDelegateAccessMenuVisible, setIsNoDelegateAccessMenuVisible] = useState(false);
 
     // For delegates, modifying legal address is a restricted action.
     // So, on pressing submit, skip validation and show delegateNoAccessModal
     const skipValidation = isActingAsDelegate;
     const handleSubmit = (values: FormOnyxValues<typeof ONYXKEYS.FORMS.HOME_ADDRESS_FORM>) => {
-        isActingAsDelegate ? setIsNoDelegateAccessMenuVisible(true) : updateAddress(values);
+        if (!!isActingAsDelegate) {
+            console.log('inside' + isActingAsDelegate);
+            setIsNoDelegateAccessMenuVisible(true);
+            return;
+        }
+        updateAddress(values);
     };
 
     useEffect(() => {

From 7cadc0fdaed45991debe675ce0775213aecffd88 Mon Sep 17 00:00:00 2001
From: Sachin Chavda <sachin.chavda.1024@gmail.com>
Date: Wed, 13 Nov 2024 16:28:49 +0530
Subject: [PATCH 06/31] Wallet

---
 src/pages/settings/Wallet/WalletPage/WalletPage.tsx | 4 +---
 1 file changed, 1 insertion(+), 3 deletions(-)

diff --git a/src/pages/settings/Wallet/WalletPage/WalletPage.tsx b/src/pages/settings/Wallet/WalletPage/WalletPage.tsx
index 79b0a434a5ad..35e3332bb0d6 100644
--- a/src/pages/settings/Wallet/WalletPage/WalletPage.tsx
+++ b/src/pages/settings/Wallet/WalletPage/WalletPage.tsx
@@ -23,7 +23,6 @@ import ScreenWrapper from '@components/ScreenWrapper';
 import ScrollView from '@components/ScrollView';
 import Section from '@components/Section';
 import Text from '@components/Text';
-import useDelegateUserDetails from '@hooks/useDelegateUserDetails';
 import useLocalize from '@hooks/useLocalize';
 import useNetwork from '@hooks/useNetwork';
 import usePaymentMethodState from '@hooks/usePaymentMethodState';
@@ -61,8 +60,7 @@ function WalletPage({shouldListenForResize = false}: WalletPageProps) {
     const [walletTerms] = useOnyx(ONYXKEYS.WALLET_TERMS, {initialValue: {}});
     const [isUserValidated] = useOnyx(ONYXKEYS.USER, {selector: (user) => !!user?.validated});
 
-    const [account] = useOnyx(ONYXKEYS.ACCOUNT);
-    const isActingAsDelegate = !!account?.delegatedAccess?.delegate;
+    const [isActingAsDelegate] = useOnyx(ONYXKEYS.ACCOUNT, {selector: (account) => !!account?.delegatedAccess?.delegate});
     const [isNoDelegateAccessMenuVisible, setIsNoDelegateAccessMenuVisible] = useState(false);
 
     const theme = useTheme();

From 285b06156223c48a21a03e8355084e0f88772310 Mon Sep 17 00:00:00 2001
From: Sachin Chavda <sachin.chavda.1024@gmail.com>
Date: Wed, 13 Nov 2024 16:35:46 +0530
Subject: [PATCH 07/31] cleanup

---
 src/pages/AddressPage.tsx                                      | 2 --
 src/pages/settings/Profile/PersonalDetails/DateOfBirthPage.tsx | 2 --
 src/pages/settings/Profile/PersonalDetails/LegalNamePage.tsx   | 1 +
 src/pages/settings/Profile/PersonalDetails/PhoneNumberPage.tsx | 3 +--
 4 files changed, 2 insertions(+), 6 deletions(-)

diff --git a/src/pages/AddressPage.tsx b/src/pages/AddressPage.tsx
index 714f48a5e04a..d2ea2bd03530 100644
--- a/src/pages/AddressPage.tsx
+++ b/src/pages/AddressPage.tsx
@@ -39,8 +39,6 @@ function AddressPage({title, address, updateAddress, isLoadingApp = true, backTo
     const [city, setCity] = useState(address?.city);
     const [zipcode, setZipcode] = useState(address?.zip);
 
-    // const [account] = useOnyx(ONYXKEYS.ACCOUNT);
-    // const isActingAsDelegate = !!account?.delegatedAccess?.delegate;
     const [isActingAsDelegate] = useOnyx(ONYXKEYS.ACCOUNT, {selector: (account) => !!account?.delegatedAccess?.delegate});
     const [isNoDelegateAccessMenuVisible, setIsNoDelegateAccessMenuVisible] = useState(false);
 
diff --git a/src/pages/settings/Profile/PersonalDetails/DateOfBirthPage.tsx b/src/pages/settings/Profile/PersonalDetails/DateOfBirthPage.tsx
index 76f67e6dad36..83c8ec37c5f9 100644
--- a/src/pages/settings/Profile/PersonalDetails/DateOfBirthPage.tsx
+++ b/src/pages/settings/Profile/PersonalDetails/DateOfBirthPage.tsx
@@ -31,8 +31,6 @@ type DateOfBirthPageProps = DateOfBirthPageOnyxProps;
 function DateOfBirthPage({privatePersonalDetails, isLoadingApp = true}: DateOfBirthPageProps) {
     const {translate} = useLocalize();
     const styles = useThemeStyles();
-    // const [account] = useOnyx(ONYXKEYS.ACCOUNT);
-    // const isActingAsDelegate = !!account?.delegatedAccess?.delegate;
     const [isActingAsDelegate] = useOnyx(ONYXKEYS.ACCOUNT, {selector: (account) => !!account?.delegatedAccess?.delegate});
 
     const [isNoDelegateAccessMenuVisible, setIsNoDelegateAccessMenuVisible] = useState(false);
diff --git a/src/pages/settings/Profile/PersonalDetails/LegalNamePage.tsx b/src/pages/settings/Profile/PersonalDetails/LegalNamePage.tsx
index 4b30160f88e2..86ddd5a0a64e 100644
--- a/src/pages/settings/Profile/PersonalDetails/LegalNamePage.tsx
+++ b/src/pages/settings/Profile/PersonalDetails/LegalNamePage.tsx
@@ -87,6 +87,7 @@ function LegalNamePage({privatePersonalDetails, isLoadingApp = true}: LegalNameP
 
     // For delegates, modifying legal Name is a restricted action.
     // So, on pressing submit, skip validation and show delegateNoAccessModal
+
     const skipValidation = isActingAsDelegate;
     const handleSubmit = (values: PrivatePersonalDetails) => {
         if (isActingAsDelegate) {
diff --git a/src/pages/settings/Profile/PersonalDetails/PhoneNumberPage.tsx b/src/pages/settings/Profile/PersonalDetails/PhoneNumberPage.tsx
index f4eed49c8a2e..b078dd7964dc 100644
--- a/src/pages/settings/Profile/PersonalDetails/PhoneNumberPage.tsx
+++ b/src/pages/settings/Profile/PersonalDetails/PhoneNumberPage.tsx
@@ -33,8 +33,6 @@ function PhoneNumberPage() {
     const validateLoginError = ErrorUtils.getEarliestErrorField(privatePersonalDetails, 'phoneNumber');
     const currenPhoneNumber = privatePersonalDetails?.phoneNumber ?? '';
 
-    // const [account] = useOnyx(ONYXKEYS.ACCOUNT);
-    // const isActingAsDelegate = !!account?.delegatedAccess?.delegate;
     const [isActingAsDelegate] = useOnyx(ONYXKEYS.ACCOUNT, {selector: (account) => account?.delegatedAccess?.delegate});
     const [isNoDelegateAccessMenuVisible, setIsNoDelegateAccessMenuVisible] = useState(false);
 
@@ -72,6 +70,7 @@ function PhoneNumberPage() {
         },
         [translate, validateLoginError],
     );
+
     // For delegates, modifying Phone Number is a restricted action.
     // So, on pressing submit, skip validation and show delegateNoAccessModal
     const skipValidation = isActingAsDelegate;

From 617282cd105721ad8b0b67818fa0bdca43d2cb30 Mon Sep 17 00:00:00 2001
From: Sachin Chavda <sachin.chavda.1024@gmail.com>
Date: Wed, 13 Nov 2024 16:36:50 +0530
Subject: [PATCH 08/31] Switch To OD

---
 src/pages/settings/InitialSettingsPage.tsx | 6 +++---
 1 file changed, 3 insertions(+), 3 deletions(-)

diff --git a/src/pages/settings/InitialSettingsPage.tsx b/src/pages/settings/InitialSettingsPage.tsx
index 3256a6dbc500..8da9bd8fd64e 100755
--- a/src/pages/settings/InitialSettingsPage.tsx
+++ b/src/pages/settings/InitialSettingsPage.tsx
@@ -84,8 +84,8 @@ function InitialSettingsPage({currentUserPersonalDetails}: InitialSettingsPagePr
     const [policies] = useOnyx(ONYXKEYS.COLLECTION.POLICY);
     const [privatePersonalDetails] = useOnyx(ONYXKEYS.PRIVATE_PERSONAL_DETAILS);
 
-    const [account] = useOnyx(ONYXKEYS.ACCOUNT);
-    const isActingAsDelegate = !!account?.delegatedAccess?.delegate;
+    const [isActingAsDelegate] = useOnyx(ONYXKEYS.ACCOUNT, {selector: (account) => !!account?.delegatedAccess?.delegate});
+
     const [isNoDelegateAccessMenuVisible, setIsNoDelegateAccessMenuVisible] = useState(false);
 
     const network = useNetwork();
@@ -279,7 +279,7 @@ function InitialSettingsPage({currentUserPersonalDetails}: InitialSettingsPagePr
                 },
             ],
         };
-    }, [styles.pt4, signOut, setInitialURL]);
+    }, [styles.pt4, signOut, setInitialURL, isActingAsDelegate]);
 
     /**
      * Retuns JSX.Element with menu items

From 7adfac1d27ab1bd8074160199f767116cd73e43f Mon Sep 17 00:00:00 2001
From: Sachin Chavda <sachin.chavda.1024@gmail.com>
Date: Wed, 13 Nov 2024 16:46:53 +0530
Subject: [PATCH 09/31] Payment method menuItems

---
 .../settings/Wallet/WalletPage/WalletPage.tsx    | 16 +++++++++++++---
 1 file changed, 13 insertions(+), 3 deletions(-)

diff --git a/src/pages/settings/Wallet/WalletPage/WalletPage.tsx b/src/pages/settings/Wallet/WalletPage/WalletPage.tsx
index 35e3332bb0d6..66f7772eb184 100644
--- a/src/pages/settings/Wallet/WalletPage/WalletPage.tsx
+++ b/src/pages/settings/Wallet/WalletPage/WalletPage.tsx
@@ -505,6 +505,8 @@ function WalletPage({shouldListenForResize = false}: WalletPageProps) {
 
                                                     return (
                                                         <MenuItem
+                                                            title={translate('walletPage.enableWallet')}
+                                                            icon={Expensicons.Wallet}
                                                             ref={buttonRef as ForwardedRef<View>}
                                                             onPress={() => {
                                                                 if (isActingAsDelegate) {
@@ -519,8 +521,6 @@ function WalletPage({shouldListenForResize = false}: WalletPageProps) {
                                                                 Navigation.navigate(ROUTES.SETTINGS_ENABLE_PAYMENTS);
                                                             }}
                                                             disabled={network.isOffline}
-                                                            title={translate('walletPage.enableWallet')}
-                                                            icon={Expensicons.Wallet}
                                                             wrapperStyle={[
                                                                 styles.transferBalance,
                                                                 shouldUseNarrowLayout ? styles.mhn5 : styles.mhn8,
@@ -565,6 +565,10 @@ function WalletPage({shouldListenForResize = false}: WalletPageProps) {
                                         title={translate('walletPage.setDefaultConfirmation')}
                                         icon={Expensicons.Mail}
                                         onPress={() => {
+                                            if (isActingAsDelegate) {
+                                                setIsNoDelegateAccessMenuVisible(true);
+                                                return;
+                                            }
                                             makeDefaultPaymentMethod();
                                             setShouldShowDefaultDeleteMenu(false);
                                         }}
@@ -574,7 +578,13 @@ function WalletPage({shouldListenForResize = false}: WalletPageProps) {
                                 <MenuItem
                                     title={translate('common.delete')}
                                     icon={Expensicons.Trashcan}
-                                    onPress={() => Modal.close(() => setShowConfirmDeleteModal(true))}
+                                    onPress={() => {
+                                        if (isActingAsDelegate) {
+                                            setIsNoDelegateAccessMenuVisible(true);
+                                            return;
+                                        }
+                                        Modal.close(() => setShowConfirmDeleteModal(true));
+                                    }}
                                     wrapperStyle={[styles.pv3, styles.ph5, !shouldUseNarrowLayout ? styles.sidebarPopover : {}]}
                                 />
                             </View>

From c1b09aff61a6ad91b52ec85bb1ef316e8af40c74 Mon Sep 17 00:00:00 2001
From: Sachin Chavda <sachin.chavda.1024@gmail.com>
Date: Wed, 13 Nov 2024 17:01:34 +0530
Subject: [PATCH 10/31] Payment method menuitems

---
 src/pages/settings/Wallet/WalletPage/WalletPage.tsx | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/src/pages/settings/Wallet/WalletPage/WalletPage.tsx b/src/pages/settings/Wallet/WalletPage/WalletPage.tsx
index 66f7772eb184..67da6ca7e4e5 100644
--- a/src/pages/settings/Wallet/WalletPage/WalletPage.tsx
+++ b/src/pages/settings/Wallet/WalletPage/WalletPage.tsx
@@ -566,6 +566,7 @@ function WalletPage({shouldListenForResize = false}: WalletPageProps) {
                                         icon={Expensicons.Mail}
                                         onPress={() => {
                                             if (isActingAsDelegate) {
+                                                hideDefaultDeleteMenu();
                                                 setIsNoDelegateAccessMenuVisible(true);
                                                 return;
                                             }
@@ -580,6 +581,7 @@ function WalletPage({shouldListenForResize = false}: WalletPageProps) {
                                     icon={Expensicons.Trashcan}
                                     onPress={() => {
                                         if (isActingAsDelegate) {
+                                            hideDefaultDeleteMenu();
                                             setIsNoDelegateAccessMenuVisible(true);
                                             return;
                                         }

From 6b746596504b77bb9630de7edcc47ea1a3593032 Mon Sep 17 00:00:00 2001
From: Sachin Chavda <sachin.chavda.1024@gmail.com>
Date: Wed, 13 Nov 2024 17:03:06 +0530
Subject: [PATCH 11/31] Delegate menu items

---
 .../settings/Security/SecuritySettingsPage.tsx    | 15 ++++++++++-----
 1 file changed, 10 insertions(+), 5 deletions(-)

diff --git a/src/pages/settings/Security/SecuritySettingsPage.tsx b/src/pages/settings/Security/SecuritySettingsPage.tsx
index f646725319b3..2ee9af9630c9 100644
--- a/src/pages/settings/Security/SecuritySettingsPage.tsx
+++ b/src/pages/settings/Security/SecuritySettingsPage.tsx
@@ -21,7 +21,6 @@ import ScrollView from '@components/ScrollView';
 import Section from '@components/Section';
 import Text from '@components/Text';
 import TextLink from '@components/TextLink';
-import useDelegateUserDetails from '@hooks/useDelegateUserDetails';
 import useLocalize from '@hooks/useLocalize';
 import useResponsiveLayout from '@hooks/useResponsiveLayout';
 import useThemeStyles from '@hooks/useThemeStyles';
@@ -67,8 +66,6 @@ function SecuritySettingsPage() {
 
     const [isNoDelegateAccessMenuVisible, setIsNoDelegateAccessMenuVisible] = useState(false);
 
-    // const [account] = useOnyx(ONYXKEYS.ACCOUNT);
-    // const isActingAsDelegate = !!account?.delegatedAccess?.delegate;
     const setMenuPosition = useCallback(() => {
         if (!delegateButtonRef.current) {
             return;
@@ -137,7 +134,7 @@ function SecuritySettingsPage() {
             link: '',
             wrapperStyle: [styles.sectionMenuItemTopDescription],
         }));
-    }, [translate, waitForNavigate, styles]);
+    }, [translate, waitForNavigate, styles, isActingAsDelegate]);
 
     const delegateMenuItems: MenuItemProps[] = useMemo(
         () =>
@@ -302,8 +299,12 @@ function SecuritySettingsPage() {
                                         title={translate('delegate.changeAccessLevel')}
                                         icon={Expensicons.Pencil}
                                         onPress={() => {
-                                            Navigation.navigate(ROUTES.SETTINGS_UPDATE_DELEGATE_ROLE.getRoute(selectedDelegate?.email ?? '', selectedDelegate?.role ?? ''));
                                             setShouldShowDelegatePopoverMenu(false);
+                                            if (isActingAsDelegate) {
+                                                setIsNoDelegateAccessMenuVisible(true);
+                                                return;
+                                            }
+                                            Navigation.navigate(ROUTES.SETTINGS_UPDATE_DELEGATE_ROLE.getRoute(selectedDelegate?.email ?? '', selectedDelegate?.role ?? ''));
                                             setSelectedDelegate(undefined);
                                         }}
                                         wrapperStyle={[styles.pv3, styles.ph5, !shouldUseNarrowLayout ? styles.sidebarPopover : {}]}
@@ -314,6 +315,10 @@ function SecuritySettingsPage() {
                                         onPress={() =>
                                             Modal.close(() => {
                                                 setShouldShowDelegatePopoverMenu(false);
+                                                if (isActingAsDelegate) {
+                                                    setIsNoDelegateAccessMenuVisible(true);
+                                                    return;
+                                                }
                                                 setShouldShowRemoveDelegateModal(true);
                                             })
                                         }

From c0959723544b62dff1ece709906674100276d3e2 Mon Sep 17 00:00:00 2001
From: Sachin Chavda <sachin.chavda.1024@gmail.com>
Date: Wed, 13 Nov 2024 17:09:56 +0530
Subject: [PATCH 12/31] Dependent cleanup

---
 src/components/MoneyReportHeader.tsx                         | 3 +--
 src/components/ReportActionItem/ReportPreview.tsx            | 3 +--
 .../ReportActionCompose/AttachmentPickerWithMenuItems.tsx    | 3 +--
 src/pages/settings/Profile/Contacts/ContactMethodsPage.tsx   | 5 ++---
 src/pages/settings/Profile/Contacts/NewContactMethodPage.tsx | 5 -----
 5 files changed, 5 insertions(+), 14 deletions(-)

diff --git a/src/components/MoneyReportHeader.tsx b/src/components/MoneyReportHeader.tsx
index 3caf7a15d50e..bd9a368c975a 100644
--- a/src/components/MoneyReportHeader.tsx
+++ b/src/components/MoneyReportHeader.tsx
@@ -173,7 +173,7 @@ function MoneyReportHeader({policy, report: moneyRequestReport, transactionThrea
     const isAnyTransactionOnHold = ReportUtils.hasHeldExpenses(moneyRequestReport?.reportID);
     const displayedAmount = isAnyTransactionOnHold && canAllowSettlement ? nonHeldAmount : formattedAmount;
     const isMoreContentShown = shouldShowNextStep || shouldShowStatusBar || (shouldShowAnyButton && shouldUseNarrowLayout);
-    const {isDelegateAccessRestricted, delegatorEmail} = useDelegateUserDetails();
+    const {isDelegateAccessRestricted} = useDelegateUserDetails();
     const [isNoDelegateAccessMenuVisible, setIsNoDelegateAccessMenuVisible] = useState(false);
 
     const isReportInRHP = isReportOpenInRHP(navigationRef?.getRootState());
@@ -493,7 +493,6 @@ function MoneyReportHeader({policy, report: moneyRequestReport, transactionThrea
             <DelegateNoAccessModal
                 isNoDelegateAccessMenuVisible={isNoDelegateAccessMenuVisible}
                 onClose={() => setIsNoDelegateAccessMenuVisible(false)}
-                delegatorEmail={delegatorEmail ?? ''}
             />
 
             <ConfirmModal
diff --git a/src/components/ReportActionItem/ReportPreview.tsx b/src/components/ReportActionItem/ReportPreview.tsx
index 9067f1abb11a..7124c8e7dcb6 100644
--- a/src/components/ReportActionItem/ReportPreview.tsx
+++ b/src/components/ReportActionItem/ReportPreview.tsx
@@ -191,7 +191,7 @@ function ReportPreview({
         [chatReport?.isOwnPolicyExpenseChat, policy?.harvesting?.enabled],
     );
 
-    const {isDelegateAccessRestricted, delegatorEmail} = useDelegateUserDetails();
+    const {isDelegateAccessRestricted} = useDelegateUserDetails();
     const [isNoDelegateAccessMenuVisible, setIsNoDelegateAccessMenuVisible] = useState(false);
 
     const stopAnimation = useCallback(() => setIsPaidAnimationRunning(false), []);
@@ -588,7 +588,6 @@ function ReportPreview({
             <DelegateNoAccessModal
                 isNoDelegateAccessMenuVisible={isNoDelegateAccessMenuVisible}
                 onClose={() => setIsNoDelegateAccessMenuVisible(false)}
-                delegatorEmail={delegatorEmail ?? ''}
             />
 
             {isHoldMenuVisible && !!iouReport && requestType !== undefined && (
diff --git a/src/pages/home/report/ReportActionCompose/AttachmentPickerWithMenuItems.tsx b/src/pages/home/report/ReportActionCompose/AttachmentPickerWithMenuItems.tsx
index 27ab62a0f02e..fc2a5cbcff9d 100644
--- a/src/pages/home/report/ReportActionCompose/AttachmentPickerWithMenuItems.tsx
+++ b/src/pages/home/report/ReportActionCompose/AttachmentPickerWithMenuItems.tsx
@@ -122,7 +122,7 @@ function AttachmentPickerWithMenuItems({
     const {translate} = useLocalize();
     const {windowHeight, windowWidth} = useWindowDimensions();
     const {shouldUseNarrowLayout} = useResponsiveLayout();
-    const {isDelegateAccessRestricted, delegatorEmail} = useDelegateUserDetails();
+    const {isDelegateAccessRestricted} = useDelegateUserDetails();
     const [isNoDelegateAccessMenuVisible, setIsNoDelegateAccessMenuVisible] = useState(false);
     const [policy] = useOnyx(`${ONYXKEYS.COLLECTION.POLICY}${report?.policyID}`);
     const {canUseCombinedTrackSubmit} = usePermissions();
@@ -346,7 +346,6 @@ function AttachmentPickerWithMenuItems({
                         <DelegateNoAccessModal
                             isNoDelegateAccessMenuVisible={isNoDelegateAccessMenuVisible}
                             onClose={() => setIsNoDelegateAccessMenuVisible(false)}
-                            delegatorEmail={delegatorEmail ?? ''}
                         />
                     </>
                 );
diff --git a/src/pages/settings/Profile/Contacts/ContactMethodsPage.tsx b/src/pages/settings/Profile/Contacts/ContactMethodsPage.tsx
index dac36a15cefd..16e98513a13b 100644
--- a/src/pages/settings/Profile/Contacts/ContactMethodsPage.tsx
+++ b/src/pages/settings/Profile/Contacts/ContactMethodsPage.tsx
@@ -13,7 +13,6 @@ import OfflineWithFeedback from '@components/OfflineWithFeedback';
 import ScreenWrapper from '@components/ScreenWrapper';
 import ScrollView from '@components/ScrollView';
 import Text from '@components/Text';
-import useDelegateUserDetails from '@hooks/useDelegateUserDetails';
 import useLocalize from '@hooks/useLocalize';
 import useThemeStyles from '@hooks/useThemeStyles';
 import Navigation from '@libs/Navigation/Navigation';
@@ -33,8 +32,8 @@ function ContactMethodsPage({route}: ContactMethodsPageProps) {
     const [session] = useOnyx(ONYXKEYS.SESSION);
     const loginNames = Object.keys(loginList ?? {});
     const navigateBackTo = route?.params?.backTo;
-    const [account] = useOnyx(ONYXKEYS.ACCOUNT);
-    const isActingAsDelegate = !!account?.delegatedAccess?.delegate;
+
+    const [isActingAsDelegate] = useOnyx(ONYXKEYS.ACCOUNT, {selector: (account) => !!account?.delegatedAccess?.delegate});
     const [isNoDelegateAccessMenuVisible, setIsNoDelegateAccessMenuVisible] = useState(false);
 
     // Sort the login names by placing the one corresponding to the default contact method as the first item before displaying the contact methods.
diff --git a/src/pages/settings/Profile/Contacts/NewContactMethodPage.tsx b/src/pages/settings/Profile/Contacts/NewContactMethodPage.tsx
index d23af0371ef3..b8ef3d2c198b 100644
--- a/src/pages/settings/Profile/Contacts/NewContactMethodPage.tsx
+++ b/src/pages/settings/Profile/Contacts/NewContactMethodPage.tsx
@@ -22,7 +22,6 @@ import Navigation from '@libs/Navigation/Navigation';
 import type {SettingsNavigatorParamList} from '@libs/Navigation/types';
 import {addSMSDomainIfPhoneNumber} from '@libs/PhoneNumber';
 import * as UserUtils from '@libs/UserUtils';
-import AccessOrNotFoundWrapper from '@pages/workspace/AccessOrNotFoundWrapper';
 import * as User from '@userActions/User';
 import CONST from '@src/CONST';
 import ONYXKEYS from '@src/ONYXKEYS';
@@ -43,8 +42,6 @@ function NewContactMethodPage({route}: NewContactMethodPageProps) {
     const [loginList] = useOnyx(ONYXKEYS.LOGIN_LIST);
     const loginData = loginList?.[pendingContactAction?.contactMethod ?? contactMethod];
     const validateLoginError = ErrorUtils.getLatestErrorField(loginData, 'addedLogin');
-    const [account] = useOnyx(ONYXKEYS.ACCOUNT);
-    const isActingAsDelegate = !!account?.delegatedAccess?.delegate;
 
     const navigateBackTo = route?.params?.backTo ?? ROUTES.SETTINGS_PROFILE;
 
@@ -111,7 +108,6 @@ function NewContactMethodPage({route}: NewContactMethodPageProps) {
     }, [navigateBackTo]);
 
     return (
-        // <AccessOrNotFoundWrapper shouldBeBlocked={isActingAsDelegate}>
         <DelegateNoAccessWrapper accessDeniedVariants={[CONST.DELEGATE.DENIED_ACCESS_VARIANTS.DELEGATE]}>
             <ScreenWrapper
                 onEntryTransitionEnd={() => loginInputRef.current?.focus()}
@@ -177,7 +173,6 @@ function NewContactMethodPage({route}: NewContactMethodPageProps) {
                 />
             </ScreenWrapper>
         </DelegateNoAccessWrapper>
-        // </AccessOrNotFoundWrapper>
     );
 }
 

From cb314b3b87853bd65e5c0c7c7153e576c2c94c7b Mon Sep 17 00:00:00 2001
From: Sachin Chavda <sachin.chavda.1024@gmail.com>
Date: Wed, 13 Nov 2024 18:02:39 +0530
Subject: [PATCH 13/31] SubscriptionPage

---
 .../CardSectionDataEmpty/index.tsx            | 35 ++++++++++++++-----
 .../index.tsx                                 | 34 +++++++++++++-----
 .../SubscriptionDetails/index.tsx             | 13 ++++++-
 .../SubscriptionSettings/index.tsx            | 17 ++++++++-
 .../SubscriptionSize/substeps/Size.tsx        | 24 +++++++++++--
 5 files changed, 101 insertions(+), 22 deletions(-)

diff --git a/src/pages/settings/Subscription/CardSection/CardSectionDataEmpty/index.tsx b/src/pages/settings/Subscription/CardSection/CardSectionDataEmpty/index.tsx
index 627556e7b5bd..79a200c4772c 100644
--- a/src/pages/settings/Subscription/CardSection/CardSectionDataEmpty/index.tsx
+++ b/src/pages/settings/Subscription/CardSection/CardSectionDataEmpty/index.tsx
@@ -1,26 +1,43 @@
-import React, {useCallback} from 'react';
+import React, {useCallback, useState} from 'react';
+import {useOnyx} from 'react-native-onyx';
 import Button from '@components/Button';
+import DelegateNoAccessModal from '@components/DelegateNoAccessModal';
 import useLocalize from '@hooks/useLocalize';
 import useThemeStyles from '@hooks/useThemeStyles';
 import Navigation from '@navigation/Navigation';
+import ONYXKEYS from '@src/ONYXKEYS';
 import ROUTES from '@src/ROUTES';
 
 function CardSectionDataEmpty() {
     const {translate} = useLocalize();
     const styles = useThemeStyles();
+    const [isActingAsDelegate] = useOnyx(ONYXKEYS.ACCOUNT, {selector: (account) => account?.delegatedAccess?.delegate});
+    const [isNoDelegateAccessMenuVisible, setIsNoDelegateAccessMenuVisible] = useState(false);
 
     const openAddPaymentCardScreen = useCallback(() => {
         Navigation.navigate(ROUTES.SETTINGS_SUBSCRIPTION_ADD_PAYMENT_CARD);
     }, []);
-
+    const handleAddPaymentCardPress = () => {
+        if (isActingAsDelegate) {
+            setIsNoDelegateAccessMenuVisible(true);
+            return;
+        }
+        openAddPaymentCardScreen();
+    };
     return (
-        <Button
-            text={translate('subscription.cardSection.addCardButton')}
-            onPress={openAddPaymentCardScreen}
-            style={styles.w100}
-            success
-            large
-        />
+        <>
+            <Button
+                text={translate('subscription.cardSection.addCardButton')}
+                onPress={handleAddPaymentCardPress}
+                style={styles.w100}
+                success
+                large
+            />
+            <DelegateNoAccessModal
+                isNoDelegateAccessMenuVisible={isNoDelegateAccessMenuVisible}
+                onClose={() => setIsNoDelegateAccessMenuVisible(false)}
+            />
+        </>
     );
 }
 
diff --git a/src/pages/settings/Subscription/CardSection/RequestEarlyCancellationMenuItem/index.tsx b/src/pages/settings/Subscription/CardSection/RequestEarlyCancellationMenuItem/index.tsx
index 2d1af54b5b20..4ad35dad8c45 100644
--- a/src/pages/settings/Subscription/CardSection/RequestEarlyCancellationMenuItem/index.tsx
+++ b/src/pages/settings/Subscription/CardSection/RequestEarlyCancellationMenuItem/index.tsx
@@ -1,23 +1,41 @@
-import React from 'react';
+import React, {useState} from 'react';
+import {useOnyx} from 'react-native-onyx';
+import DelegateNoAccessModal from '@components/DelegateNoAccessModal';
 import * as Expensicons from '@components/Icon/Expensicons';
 import MenuItem from '@components/MenuItem';
 import useLocalize from '@hooks/useLocalize';
 import useThemeStyles from '@hooks/useThemeStyles';
 import Navigation from '@libs/Navigation/Navigation';
+import ONYXKEYS from '@src/ONYXKEYS';
 import ROUTES from '@src/ROUTES';
 
 function RequestEarlyCancellationMenuItem() {
     const {translate} = useLocalize();
     const styles = useThemeStyles();
+    const [isActingAsDelegate] = useOnyx(ONYXKEYS.ACCOUNT, {selector: (account) => account?.delegatedAccess?.delegate});
+    const [isNoDelegateAccessMenuVisible, setIsNoDelegateAccessMenuVisible] = useState(false);
 
+    const handleRequestEarlyCancellationPress = () => {
+        if (isActingAsDelegate) {
+            setIsNoDelegateAccessMenuVisible(true);
+            return;
+        }
+        Navigation.navigate(ROUTES.SETTINGS_SUBSCRIPTION_REQUEST_EARLY_CANCELLATION);
+    };
     return (
-        <MenuItem
-            title={translate('subscription.requestEarlyCancellation.title')}
-            icon={Expensicons.CalendarSolid}
-            shouldShowRightIcon
-            wrapperStyle={styles.sectionMenuItemTopDescription}
-            onPress={() => Navigation.navigate(ROUTES.SETTINGS_SUBSCRIPTION_REQUEST_EARLY_CANCELLATION)}
-        />
+        <>
+            <MenuItem
+                title={translate('subscription.requestEarlyCancellation.title')}
+                icon={Expensicons.CalendarSolid}
+                shouldShowRightIcon
+                wrapperStyle={styles.sectionMenuItemTopDescription}
+                onPress={handleRequestEarlyCancellationPress}
+            />
+            <DelegateNoAccessModal
+                isNoDelegateAccessMenuVisible={isNoDelegateAccessMenuVisible}
+                onClose={() => setIsNoDelegateAccessMenuVisible(false)}
+            />
+        </>
     );
 }
 
diff --git a/src/pages/settings/Subscription/SubscriptionDetails/index.tsx b/src/pages/settings/Subscription/SubscriptionDetails/index.tsx
index a1fddd6c430e..31cbf3e53c3d 100644
--- a/src/pages/settings/Subscription/SubscriptionDetails/index.tsx
+++ b/src/pages/settings/Subscription/SubscriptionDetails/index.tsx
@@ -1,7 +1,8 @@
-import React from 'react';
+import React, {useState} from 'react';
 import {View} from 'react-native';
 import {useOnyx} from 'react-native-onyx';
 import Badge from '@components/Badge';
+import DelegateNoAccessModal from '@components/DelegateNoAccessModal';
 import Icon from '@components/Icon';
 import * as Illustrations from '@components/Icon/Illustrations';
 import MenuItemWithTopDescription from '@components/MenuItemWithTopDescription';
@@ -43,8 +44,14 @@ function SubscriptionDetails() {
     const [privateSubscription] = useOnyx(ONYXKEYS.NVP_PRIVATE_SUBSCRIPTION);
     const [privateTaxExempt] = useOnyx(ONYXKEYS.NVP_PRIVATE_TAX_EXEMPT);
     const [account] = useOnyx(ONYXKEYS.ACCOUNT);
+    const [isActingAsDelegate] = useOnyx(ONYXKEYS.ACCOUNT, {selector: (account) => account?.delegatedAccess?.delegate});
+    const [isNoDelegateAccessMenuVisible, setIsNoDelegateAccessMenuVisible] = useState(false);
 
     const onOptionSelected = (option: SubscriptionType) => {
+        if (privateSubscription?.type !== option && isActingAsDelegate) {
+            setIsNoDelegateAccessMenuVisible(true);
+            return;
+        }
         if (privateSubscription?.type === CONST.SUBSCRIPTION.TYPE.ANNUAL && option === CONST.SUBSCRIPTION.TYPE.PAYPERUSE && !account?.canDowngrade) {
             Navigation.navigate(ROUTES.SETTINGS_SUBSCRIPTION_SIZE.getRoute(0));
             return;
@@ -118,6 +125,10 @@ function SubscriptionDetails() {
                     {subscriptionSizeSection}
                 </OfflineWithFeedback>
             )}
+            <DelegateNoAccessModal
+                isNoDelegateAccessMenuVisible={isNoDelegateAccessMenuVisible}
+                onClose={() => setIsNoDelegateAccessMenuVisible(false)}
+            />
         </Section>
     );
 }
diff --git a/src/pages/settings/Subscription/SubscriptionSettings/index.tsx b/src/pages/settings/Subscription/SubscriptionSettings/index.tsx
index 247d82ef8ca3..3af05e1ef1cd 100644
--- a/src/pages/settings/Subscription/SubscriptionSettings/index.tsx
+++ b/src/pages/settings/Subscription/SubscriptionSettings/index.tsx
@@ -1,7 +1,8 @@
-import React from 'react';
+import React, {useState} from 'react';
 import type {StyleProp, TextStyle} from 'react-native';
 import {View} from 'react-native';
 import {useOnyx} from 'react-native-onyx';
+import DelegateNoAccessModal from '@components/DelegateNoAccessModal';
 import OfflineWithFeedback from '@components/OfflineWithFeedback';
 import Section from '@components/Section';
 import Text from '@components/Text';
@@ -26,10 +27,16 @@ function SubscriptionSettings() {
     const [privateSubscription] = useOnyx(ONYXKEYS.NVP_PRIVATE_SUBSCRIPTION);
     const preferredCurrency = usePreferredCurrency();
     const possibleCostSavings = useSubscriptionPossibleCostSavings();
+    const [isActingAsDelegate] = useOnyx(ONYXKEYS.ACCOUNT, {selector: (account) => account?.delegatedAccess?.delegate});
+    const [isNoDelegateAccessMenuVisible, setIsNoDelegateAccessMenuVisible] = useState(false);
 
     const autoRenewalDate = formatSubscriptionEndDate(privateSubscription?.endDate);
 
     const handleAutoRenewToggle = () => {
+        if (isActingAsDelegate) {
+            setIsNoDelegateAccessMenuVisible(true);
+            return;
+        }
         if (!privateSubscription?.autoRenew) {
             Subscription.updateSubscriptionAutoRenew(true);
             return;
@@ -38,6 +45,10 @@ function SubscriptionSettings() {
     };
 
     const handleAutoIncreaseToggle = () => {
+        if (isActingAsDelegate) {
+            setIsNoDelegateAccessMenuVisible(true);
+            return;
+        }
         Subscription.updateSubscriptionAddNewUsersAutomatically(!privateSubscription?.addNewUsersAutomatically);
     };
 
@@ -85,6 +96,10 @@ function SubscriptionSettings() {
                     <Text style={[styles.mutedTextLabel, styles.mt2]}>{translate('subscription.subscriptionSettings.automaticallyIncrease')}</Text>
                 </View>
             </OfflineWithFeedback>
+            <DelegateNoAccessModal
+                isNoDelegateAccessMenuVisible={isNoDelegateAccessMenuVisible}
+                onClose={() => setIsNoDelegateAccessMenuVisible(false)}
+            />
         </Section>
     );
 }
diff --git a/src/pages/settings/Subscription/SubscriptionSize/substeps/Size.tsx b/src/pages/settings/Subscription/SubscriptionSize/substeps/Size.tsx
index ed42d604181d..06b6a1b830df 100644
--- a/src/pages/settings/Subscription/SubscriptionSize/substeps/Size.tsx
+++ b/src/pages/settings/Subscription/SubscriptionSize/substeps/Size.tsx
@@ -1,6 +1,7 @@
-import React, {useCallback} from 'react';
+import React, {useCallback, useState} from 'react';
 import {View} from 'react-native';
 import {useOnyx} from 'react-native-onyx';
+import DelegateNoAccessModal from '@components/DelegateNoAccessModal';
 import FormProvider from '@components/Form/FormProvider';
 import InputWrapper from '@components/Form/InputWrapper';
 import type {FormInputErrors, FormOnyxValues} from '@components/Form/types';
@@ -23,13 +24,26 @@ function Size({onNext}: SizeProps) {
     const styles = useThemeStyles();
     const [privateSubscription] = useOnyx(ONYXKEYS.NVP_PRIVATE_SUBSCRIPTION);
     const {inputCallbackRef} = useAutoFocusInput();
+    const [isActingAsDelegate] = useOnyx(ONYXKEYS.ACCOUNT, {selector: (account) => account?.delegatedAccess?.delegate});
+    const [isNoDelegateAccessMenuVisible, setIsNoDelegateAccessMenuVisible] = useState(false);
 
-    const handleSubmit = useStepFormSubmit<typeof ONYXKEYS.FORMS.SUBSCRIPTION_SIZE_FORM>({
+    const updateValuesAndNavigateToNextStep = useStepFormSubmit<typeof ONYXKEYS.FORMS.SUBSCRIPTION_SIZE_FORM>({
         formId: ONYXKEYS.FORMS.SUBSCRIPTION_SIZE_FORM,
         fieldIds: [INPUT_IDS.SUBSCRIPTION_SIZE],
         onNext,
         shouldSaveDraft: true,
     });
+    const handleSubmit = (values: FormOnyxValues<typeof ONYXKEYS.FORMS.SUBSCRIPTION_SIZE_FORM>) => {
+        if (isActingAsDelegate) {
+            setIsNoDelegateAccessMenuVisible(true);
+            return;
+        }
+        updateValuesAndNavigateToNextStep(values);
+    };
+    
+    // For delegates, modifying subscription size is a restricted action.
+    // So, on pressing submit, skip validation and show delegateNoAccessModal
+    const skipValidation = isActingAsDelegate;
 
     const defaultValues = {
         [INPUT_IDS.SUBSCRIPTION_SIZE]: `${privateSubscription?.userCount ?? ''}`,
@@ -56,7 +70,7 @@ function Size({onNext}: SizeProps) {
             formID={ONYXKEYS.FORMS.SUBSCRIPTION_SIZE_FORM}
             submitButtonText={translate('common.next')}
             onSubmit={handleSubmit}
-            validate={validate}
+            validate={skipValidation ? undefined : validate}
             style={[styles.mh5, styles.flexGrow1]}
             enabledWhenOffline
         >
@@ -75,6 +89,10 @@ function Size({onNext}: SizeProps) {
                 <Text style={[styles.formHelp, styles.mt2]}>{translate('subscription.subscriptionSize.eachMonth')}</Text>
                 <Text style={[styles.formHelp, styles.mt2]}>{translate('subscription.subscriptionSize.note')}</Text>
             </View>
+            <DelegateNoAccessModal
+                isNoDelegateAccessMenuVisible={isNoDelegateAccessMenuVisible}
+                onClose={() => setIsNoDelegateAccessMenuVisible(false)}
+            />
         </FormProvider>
     );
 }

From 85da30ad9459e8e6bf30619112e28a82e8032317 Mon Sep 17 00:00:00 2001
From: Sachin Chavda <sachin.chavda.1024@gmail.com>
Date: Wed, 13 Nov 2024 18:14:06 +0530
Subject: [PATCH 14/31] lint

---
 src/components/DelegateNoAccessWrapper.tsx                 | 7 +++----
 .../Subscription/SubscriptionSize/substeps/Size.tsx        | 2 +-
 2 files changed, 4 insertions(+), 5 deletions(-)

diff --git a/src/components/DelegateNoAccessWrapper.tsx b/src/components/DelegateNoAccessWrapper.tsx
index 36e675547d7e..8c605f9318de 100644
--- a/src/components/DelegateNoAccessWrapper.tsx
+++ b/src/components/DelegateNoAccessWrapper.tsx
@@ -1,15 +1,14 @@
 import React from 'react';
-import {OnyxEntry, useOnyx} from 'react-native-onyx';
+import {type OnyxEntry, useOnyx} from 'react-native-onyx';
 import useResponsiveLayout from '@hooks/useResponsiveLayout';
 import AccountUtils from '@libs/AccountUtils';
 import Navigation from '@libs/Navigation/Navigation';
 import NotFoundPage from '@pages/ErrorPage/NotFoundPage';
 import CONST from '@src/CONST';
 import ONYXKEYS from '@src/ONYXKEYS';
-import ROUTES from '@src/ROUTES';
-import {Account} from '@src/types/onyx';
+import {type Account} from '@src/types/onyx';
 import callOrReturn from '@src/types/utils/callOrReturn';
-import {FullPageNotFoundViewProps} from './BlockingViews/FullPageNotFoundView';
+import {type FullPageNotFoundViewProps} from './BlockingViews/FullPageNotFoundView';
 
 const DENIED_ACCESS_VARIANTS = {
     [CONST.DELEGATE.DENIED_ACCESS_VARIANTS.DELEGATE]: (account: OnyxEntry<Account>) => isDelegate(account),
diff --git a/src/pages/settings/Subscription/SubscriptionSize/substeps/Size.tsx b/src/pages/settings/Subscription/SubscriptionSize/substeps/Size.tsx
index 06b6a1b830df..5ee477c39579 100644
--- a/src/pages/settings/Subscription/SubscriptionSize/substeps/Size.tsx
+++ b/src/pages/settings/Subscription/SubscriptionSize/substeps/Size.tsx
@@ -40,7 +40,7 @@ function Size({onNext}: SizeProps) {
         }
         updateValuesAndNavigateToNextStep(values);
     };
-    
+
     // For delegates, modifying subscription size is a restricted action.
     // So, on pressing submit, skip validation and show delegateNoAccessModal
     const skipValidation = isActingAsDelegate;

From c6a25290a70726e57beb69ea162859924c019b7b Mon Sep 17 00:00:00 2001
From: Sachin Chavda <sachin.chavda.1024@gmail.com>
Date: Wed, 13 Nov 2024 18:24:37 +0530
Subject: [PATCH 15/31] lint

---
 src/pages/AddressPage.tsx                                      | 3 +--
 src/pages/settings/Profile/PersonalDetails/DateOfBirthPage.tsx | 3 ++-
 src/pages/settings/Subscription/SubscriptionDetails/index.tsx  | 2 +-
 3 files changed, 4 insertions(+), 4 deletions(-)

diff --git a/src/pages/AddressPage.tsx b/src/pages/AddressPage.tsx
index d2ea2bd03530..ee04b2d6bee7 100644
--- a/src/pages/AddressPage.tsx
+++ b/src/pages/AddressPage.tsx
@@ -46,8 +46,7 @@ function AddressPage({title, address, updateAddress, isLoadingApp = true, backTo
     // So, on pressing submit, skip validation and show delegateNoAccessModal
     const skipValidation = isActingAsDelegate;
     const handleSubmit = (values: FormOnyxValues<typeof ONYXKEYS.FORMS.HOME_ADDRESS_FORM>) => {
-        if (!!isActingAsDelegate) {
-            console.log('inside' + isActingAsDelegate);
+        if (isActingAsDelegate) {
             setIsNoDelegateAccessMenuVisible(true);
             return;
         }
diff --git a/src/pages/settings/Profile/PersonalDetails/DateOfBirthPage.tsx b/src/pages/settings/Profile/PersonalDetails/DateOfBirthPage.tsx
index 83c8ec37c5f9..91d909007dff 100644
--- a/src/pages/settings/Profile/PersonalDetails/DateOfBirthPage.tsx
+++ b/src/pages/settings/Profile/PersonalDetails/DateOfBirthPage.tsx
@@ -17,7 +17,8 @@ import * as ValidationUtils from '@libs/ValidationUtils';
 import * as PersonalDetails from '@userActions/PersonalDetails';
 import CONST from '@src/CONST';
 import ONYXKEYS from '@src/ONYXKEYS';
-import INPUT_IDS, {type DateOfBirthForm} from '@src/types/form/DateOfBirthForm';
+import INPUT_IDS from '@src/types/form/DateOfBirthForm';
+import type {DateOfBirthForm} from '@src/types/form/DateOfBirthForm';
 import type {PrivatePersonalDetails} from '@src/types/onyx';
 
 type DateOfBirthPageOnyxProps = {
diff --git a/src/pages/settings/Subscription/SubscriptionDetails/index.tsx b/src/pages/settings/Subscription/SubscriptionDetails/index.tsx
index 31cbf3e53c3d..273900ab9fd5 100644
--- a/src/pages/settings/Subscription/SubscriptionDetails/index.tsx
+++ b/src/pages/settings/Subscription/SubscriptionDetails/index.tsx
@@ -44,7 +44,7 @@ function SubscriptionDetails() {
     const [privateSubscription] = useOnyx(ONYXKEYS.NVP_PRIVATE_SUBSCRIPTION);
     const [privateTaxExempt] = useOnyx(ONYXKEYS.NVP_PRIVATE_TAX_EXEMPT);
     const [account] = useOnyx(ONYXKEYS.ACCOUNT);
-    const [isActingAsDelegate] = useOnyx(ONYXKEYS.ACCOUNT, {selector: (account) => account?.delegatedAccess?.delegate});
+    const isActingAsDelegate = account?.delegatedAccess?.delegate;
     const [isNoDelegateAccessMenuVisible, setIsNoDelegateAccessMenuVisible] = useState(false);
 
     const onOptionSelected = (option: SubscriptionType) => {

From ead9296ac758b2cb61bb349601d37c504bffd11b Mon Sep 17 00:00:00 2001
From: Sachin Chavda <sachin.chavda.1024@gmail.com>
Date: Wed, 13 Nov 2024 18:33:59 +0530
Subject: [PATCH 16/31] lint

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

diff --git a/src/components/DelegateNoAccessWrapper.tsx b/src/components/DelegateNoAccessWrapper.tsx
index 8c605f9318de..59d4a7c90138 100644
--- a/src/components/DelegateNoAccessWrapper.tsx
+++ b/src/components/DelegateNoAccessWrapper.tsx
@@ -1,14 +1,15 @@
 import React from 'react';
-import {type OnyxEntry, useOnyx} from 'react-native-onyx';
+import {useOnyx} from 'react-native-onyx';
+import type {OnyxEntry} from 'react-native-onyx';
 import useResponsiveLayout from '@hooks/useResponsiveLayout';
 import AccountUtils from '@libs/AccountUtils';
 import Navigation from '@libs/Navigation/Navigation';
 import NotFoundPage from '@pages/ErrorPage/NotFoundPage';
 import CONST from '@src/CONST';
 import ONYXKEYS from '@src/ONYXKEYS';
-import {type Account} from '@src/types/onyx';
+import type {Account} from '@src/types/onyx';
 import callOrReturn from '@src/types/utils/callOrReturn';
-import {type FullPageNotFoundViewProps} from './BlockingViews/FullPageNotFoundView';
+import type {FullPageNotFoundViewProps} from './BlockingViews/FullPageNotFoundView';
 
 const DENIED_ACCESS_VARIANTS = {
     [CONST.DELEGATE.DENIED_ACCESS_VARIANTS.DELEGATE]: (account: OnyxEntry<Account>) => isDelegate(account),

From 853ccdee8221795fcbb68ede98811784f7155d90 Mon Sep 17 00:00:00 2001
From: Sachin Chavda <sachin.chavda.1024@gmail.com>
Date: Wed, 13 Nov 2024 18:47:21 +0530
Subject: [PATCH 17/31] cleanup

---
 src/pages/ReportDetailsPage.tsx | 1 -
 1 file changed, 1 deletion(-)

diff --git a/src/pages/ReportDetailsPage.tsx b/src/pages/ReportDetailsPage.tsx
index 9e438f0549e2..5aeaa5ea3ec9 100644
--- a/src/pages/ReportDetailsPage.tsx
+++ b/src/pages/ReportDetailsPage.tsx
@@ -941,7 +941,6 @@ function ReportDetailsPage({policies, report, route}: ReportDetailsPageProps) {
                 <DelegateNoAccessModal
                     isNoDelegateAccessMenuVisible={isNoDelegateAccessMenuVisible}
                     onClose={() => setIsNoDelegateAccessMenuVisible(false)}
-                    delegatorEmail={delegatorEmail ?? ''}
                 />
                 <ConfirmModal
                     title={translate('iou.unapproveReport')}

From 887356cbf1fbf057280f7ab311db9fbc9cbd2a77 Mon Sep 17 00:00:00 2001
From: Sachin Chavda <sachin.chavda.1024@gmail.com>
Date: Tue, 19 Nov 2024 16:27:22 +0530
Subject: [PATCH 18/31] DelegateNoAccessWrapper initial implementation

---
 src/components/DelegateNoAccessWrapper.tsx | 48 ++++++++++------------
 src/languages/en.ts                        |  1 +
 2 files changed, 22 insertions(+), 27 deletions(-)

diff --git a/src/components/DelegateNoAccessWrapper.tsx b/src/components/DelegateNoAccessWrapper.tsx
index 59d4a7c90138..6761bc0872c9 100644
--- a/src/components/DelegateNoAccessWrapper.tsx
+++ b/src/components/DelegateNoAccessWrapper.tsx
@@ -4,12 +4,11 @@ import type {OnyxEntry} from 'react-native-onyx';
 import useResponsiveLayout from '@hooks/useResponsiveLayout';
 import AccountUtils from '@libs/AccountUtils';
 import Navigation from '@libs/Navigation/Navigation';
-import NotFoundPage from '@pages/ErrorPage/NotFoundPage';
 import CONST from '@src/CONST';
 import ONYXKEYS from '@src/ONYXKEYS';
 import type {Account} from '@src/types/onyx';
 import callOrReturn from '@src/types/utils/callOrReturn';
-import type {FullPageNotFoundViewProps} from './BlockingViews/FullPageNotFoundView';
+import FullPageNotFoundView from './BlockingViews/FullPageNotFoundView';
 
 const DENIED_ACCESS_VARIANTS = {
     [CONST.DELEGATE.DENIED_ACCESS_VARIANTS.DELEGATE]: (account: OnyxEntry<Account>) => isDelegate(account),
@@ -20,15 +19,10 @@ type AccessDeniedVariants = keyof typeof DENIED_ACCESS_VARIANTS;
 
 type DelegateNoAccessWrapperProps = {
     accessDeniedVariants?: AccessDeniedVariants[];
-    FullPageNotFoundViewProps?: FullPageNotFoundViewProps;
-    shouldShowFullScreenFallback?: boolean;
+    shouldForceFullScreen?: boolean;
     children: (() => React.ReactNode) | React.ReactNode;
 };
 
-type PageNotFoundFallbackProps = {
-    shouldShowFullScreenFallback?: boolean;
-};
-
 function isDelegate(account: OnyxEntry<Account>) {
     const isActingAsDelegate = !!account?.delegatedAccess?.delegate;
     return isActingAsDelegate;
@@ -39,31 +33,31 @@ function isSubmitter(account: OnyxEntry<Account>) {
     return isDelegateOnlySubmitter;
 }
 
-function PageNotFoundFallback({shouldShowFullScreenFallback}: PageNotFoundFallbackProps) {
-    const {shouldUseNarrowLayout} = useResponsiveLayout();
-    return (
-        <NotFoundPage
-            shouldForceFullScreen={shouldShowFullScreenFallback}
-            onBackButtonPress={() => {
-                if (shouldShowFullScreenFallback) {
-                    Navigation.dismissModal();
-                    return;
-                }
-                Navigation.goBack();
-            }}
-            shouldShowBackButton={!shouldShowFullScreenFallback ? shouldUseNarrowLayout : undefined}
-        />
-    );
-}
-
-function DelegateNoAccessWrapper({accessDeniedVariants = [], shouldShowFullScreenFallback, ...props}: DelegateNoAccessWrapperProps) {
+function DelegateNoAccessWrapper({accessDeniedVariants = [], shouldForceFullScreen, ...props}: DelegateNoAccessWrapperProps) {
     const [account] = useOnyx(ONYXKEYS.ACCOUNT);
     const isPageAccessDenied = accessDeniedVariants.reduce((acc, variant) => {
         const accessDeniedFunction = DENIED_ACCESS_VARIANTS[variant];
         return acc || accessDeniedFunction(account);
     }, false);
+
     if (isPageAccessDenied) {
-        return <PageNotFoundFallback shouldShowFullScreenFallback={shouldShowFullScreenFallback} />;
+        const {shouldUseNarrowLayout} = useResponsiveLayout();
+        return (
+            <FullPageNotFoundView
+                shouldShow
+                shouldForceFullScreen={shouldForceFullScreen}
+                onBackButtonPress={() => {
+                    if (shouldUseNarrowLayout) {
+                        Navigation.dismissModal();
+                        return;
+                    }
+                    Navigation.goBack();
+                }}
+                titleKey="delegate.notAllowed"
+                subtitleKey="delegate.noAccessMessage"
+                shouldShowLink={false}
+            />
+        );
     }
     return callOrReturn(props.children);
 }
diff --git a/src/languages/en.ts b/src/languages/en.ts
index fa78b563c522..bc08dc9b70a2 100755
--- a/src/languages/en.ts
+++ b/src/languages/en.ts
@@ -5183,6 +5183,7 @@ const translations = {
         enterMagicCode: ({contactMethod}: EnterMagicCodeParams) => `Please enter the magic code sent to ${contactMethod} to add a copilot.`,
         enterMagicCodeUpdate: ({contactMethod}: EnterMagicCodeParams) => `Please enter the magic code sent to ${contactMethod} to update your copilot.`,
         notAllowed: 'Not so fast...',
+        noAccessMessage: "As a copilot, you don't have access to this page. Sorry!",
         notAllowedMessageStart: ({accountOwnerEmail}: AccountOwnerParams) => `You don't have permission to take this action for ${accountOwnerEmail} as a`,
         notAllowedMessageHyperLinked: ' copilot',
     },

From 5df885f28f9ae73930ec0314e6c17c5aff4b2f98 Mon Sep 17 00:00:00 2001
From: Sachin Chavda <sachin.chavda.1024@gmail.com>
Date: Wed, 20 Nov 2024 17:06:47 +0530
Subject: [PATCH 19/31] Add DelegateNoAccessWrapper

---
 src/languages/en.ts                           |   2 +-
 src/languages/es.ts                           |   1 +
 src/pages/AddPersonalBankAccountPage.tsx      |  70 ++++++------
 src/pages/EnablePayments/EnablePayments.tsx   |  46 ++++----
 .../ExitSurvey/ExitSurveyBookCall.tsx         | 105 ++++++++---------
 .../ExitSurvey/ExitSurveyConfirmPage.tsx      |  69 +++++------
 .../settings/ExitSurvey/ExitSurveyOffline.tsx |  22 ++--
 .../ExitSurvey/ExitSurveyReasonPage.tsx       |  85 +++++++-------
 .../ExitSurvey/ExitSurveyResponsePage.tsx     |  83 +++++++-------
 .../Profile/Contacts/NewContactMethodPage.tsx |   2 +-
 .../Security/AddDelegate/AddDelegatePage.tsx  |  37 +++---
 .../AddDelegate/ConfirmDelegatePage.tsx       |  59 +++++-----
 .../AddDelegate/SelectDelegateRolePage.tsx    |  59 +++++-----
 .../UpdateDelegateMagicCodePage.tsx           |  27 +++--
 .../UpdateDelegateRolePage.tsx                |  69 +++++------
 .../settings/Security/CloseAccountPage.tsx    | 107 +++++++++---------
 .../TwoFactorAuth/TwoFactorAuthPage.tsx       |   6 +-
 .../Subscription/PaymentCard/index.tsx        |  83 +++++++-------
 .../RequestEarlyCancellationPage/index.tsx    |  13 ++-
 19 files changed, 501 insertions(+), 444 deletions(-)

diff --git a/src/languages/en.ts b/src/languages/en.ts
index ddbe62ae4996..eeb9b99e09f7 100755
--- a/src/languages/en.ts
+++ b/src/languages/en.ts
@@ -5250,7 +5250,7 @@ const translations = {
         enterMagicCode: ({contactMethod}: EnterMagicCodeParams) => `Please enter the magic code sent to ${contactMethod} to add a copilot. It should arrive within a minute or two.`,
         enterMagicCodeUpdate: ({contactMethod}: EnterMagicCodeParams) => `Please enter the magic code sent to ${contactMethod} to update your copilot.`,
         notAllowed: 'Not so fast...',
-        noAccessMessage: "As a copilot, you don't have access to this page. Sorry!",
+        noAccessMessage: "As a copilot, you don't have access to \nthis page. Sorry!",
         notAllowedMessageStart: ({accountOwnerEmail}: AccountOwnerParams) => `You don't have permission to take this action for ${accountOwnerEmail} as a`,
         notAllowedMessageHyperLinked: ' copilot',
     },
diff --git a/src/languages/es.ts b/src/languages/es.ts
index 98cf332ed0f9..027271df9dac 100644
--- a/src/languages/es.ts
+++ b/src/languages/es.ts
@@ -5770,6 +5770,7 @@ const translations = {
         enterMagicCodeUpdate: ({contactMethod}: EnterMagicCodeParams) =>
             `Por favor, introduce el código mágico enviado a ${contactMethod} para actualizar el nivel de acceso de tu copiloto.`,
         notAllowed: 'No tan rápido...',
+        noAccessMessage: 'Como copiloto, no tienes acceso a esta página. ¡Lo sentimos!',
         notAllowedMessageStart: ({accountOwnerEmail}: AccountOwnerParams) => `No tienes permiso para realizar esta acción para ${accountOwnerEmail}`,
         notAllowedMessageHyperLinked: ' copiloto',
     },
diff --git a/src/pages/AddPersonalBankAccountPage.tsx b/src/pages/AddPersonalBankAccountPage.tsx
index 7b0a76e59922..d99db40d07ee 100644
--- a/src/pages/AddPersonalBankAccountPage.tsx
+++ b/src/pages/AddPersonalBankAccountPage.tsx
@@ -3,6 +3,7 @@ import {useOnyx} from 'react-native-onyx';
 import AddPlaidBankAccount from '@components/AddPlaidBankAccount';
 import FullPageNotFoundView from '@components/BlockingViews/FullPageNotFoundView';
 import ConfirmationPage from '@components/ConfirmationPage';
+import DelegateNoAccessWrapper from '@components/DelegateNoAccessWrapper';
 import FormProvider from '@components/Form/FormProvider';
 import InputWrapper from '@components/Form/InputWrapper';
 import HeaderWithBackButton from '@components/HeaderWithBackButton';
@@ -13,6 +14,7 @@ import getPlaidOAuthReceivedRedirectURI from '@libs/getPlaidOAuthReceivedRedirec
 import Navigation from '@libs/Navigation/Navigation';
 import * as BankAccounts from '@userActions/BankAccounts';
 import * as PaymentMethods from '@userActions/PaymentMethods';
+import CONST from '@src/CONST';
 import ONYXKEYS from '@src/ONYXKEYS';
 import ROUTES from '@src/ROUTES';
 import SCREENS from '@src/SCREENS';
@@ -77,41 +79,43 @@ function AddPersonalBankAccountPage() {
             testID={AddPersonalBankAccountPage.displayName}
         >
             <FullPageNotFoundView shouldShow={!isUserValidated}>
-                <HeaderWithBackButton
-                    title={translate('bankAccount.addBankAccount')}
-                    onBackButtonPress={exitFlow}
-                />
-                {shouldShowSuccess ? (
-                    <ConfirmationPage
-                        heading={translate('addPersonalBankAccountPage.successTitle')}
-                        description={translate('addPersonalBankAccountPage.successMessage')}
-                        shouldShowButton
-                        buttonText={translate('common.continue')}
-                        onButtonPress={() => exitFlow(true)}
+                <DelegateNoAccessWrapper accessDeniedVariants={[CONST.DELEGATE.DENIED_ACCESS_VARIANTS.DELEGATE]}>
+                    <HeaderWithBackButton
+                        title={translate('bankAccount.addBankAccount')}
+                        onBackButtonPress={exitFlow}
                     />
-                ) : (
-                    <FormProvider
-                        formID={ONYXKEYS.FORMS.PERSONAL_BANK_ACCOUNT_FORM}
-                        isSubmitButtonVisible={(plaidData?.bankAccounts ?? []).length > 0}
-                        submitButtonText={translate('common.saveAndContinue')}
-                        scrollContextEnabled
-                        onSubmit={submitBankAccountForm}
-                        validate={BankAccounts.validatePlaidSelection}
-                        style={[styles.mh5, styles.flex1]}
-                    >
-                        <InputWrapper
-                            inputID={INPUT_IDS.BANK_INFO_STEP.SELECTED_PLAID_ACCOUNT_ID}
-                            InputComponent={AddPlaidBankAccount}
-                            onSelect={setSelectedPlaidAccountId}
-                            text={translate('walletPage.chooseAccountBody')}
-                            plaidData={plaidData}
-                            isDisplayedInWalletFlow
-                            onExitPlaid={goBack}
-                            receivedRedirectURI={getPlaidOAuthReceivedRedirectURI()}
-                            selectedPlaidAccountID={selectedPlaidAccountId}
+                    {shouldShowSuccess ? (
+                        <ConfirmationPage
+                            heading={translate('addPersonalBankAccountPage.successTitle')}
+                            description={translate('addPersonalBankAccountPage.successMessage')}
+                            shouldShowButton
+                            buttonText={translate('common.continue')}
+                            onButtonPress={() => exitFlow(true)}
                         />
-                    </FormProvider>
-                )}
+                    ) : (
+                        <FormProvider
+                            formID={ONYXKEYS.FORMS.PERSONAL_BANK_ACCOUNT_FORM}
+                            isSubmitButtonVisible={(plaidData?.bankAccounts ?? []).length > 0}
+                            submitButtonText={translate('common.saveAndContinue')}
+                            scrollContextEnabled
+                            onSubmit={submitBankAccountForm}
+                            validate={BankAccounts.validatePlaidSelection}
+                            style={[styles.mh5, styles.flex1]}
+                        >
+                            <InputWrapper
+                                inputID={INPUT_IDS.BANK_INFO_STEP.SELECTED_PLAID_ACCOUNT_ID}
+                                InputComponent={AddPlaidBankAccount}
+                                onSelect={setSelectedPlaidAccountId}
+                                text={translate('walletPage.chooseAccountBody')}
+                                plaidData={plaidData}
+                                isDisplayedInWalletFlow
+                                onExitPlaid={goBack}
+                                receivedRedirectURI={getPlaidOAuthReceivedRedirectURI()}
+                                selectedPlaidAccountID={selectedPlaidAccountId}
+                            />
+                        </FormProvider>
+                    )}
+                </DelegateNoAccessWrapper>
             </FullPageNotFoundView>
         </ScreenWrapper>
     );
diff --git a/src/pages/EnablePayments/EnablePayments.tsx b/src/pages/EnablePayments/EnablePayments.tsx
index 357a2be9b1e0..a7bb3d321046 100644
--- a/src/pages/EnablePayments/EnablePayments.tsx
+++ b/src/pages/EnablePayments/EnablePayments.tsx
@@ -1,5 +1,6 @@
 import React, {useEffect} from 'react';
 import {useOnyx} from 'react-native-onyx';
+import DelegateNoAccessWrapper from '@components/DelegateNoAccessWrapper';
 import FullScreenLoadingIndicator from '@components/FullscreenLoadingIndicator';
 import HeaderWithBackButton from '@components/HeaderWithBackButton';
 import ScreenWrapper from '@components/ScreenWrapper';
@@ -44,30 +45,37 @@ function EnablePaymentsPage() {
                 includeSafeAreaPaddingBottom={false}
                 shouldEnablePickerAvoiding={false}
             >
-                <HeaderWithBackButton
-                    title={translate('personalInfoStep.personalInfo')}
-                    onBackButtonPress={() => Navigation.goBack(ROUTES.SETTINGS_WALLET, true)}
-                />
-                <FailedKYC />
+                <DelegateNoAccessWrapper accessDeniedVariants={[CONST.DELEGATE.DENIED_ACCESS_VARIANTS.DELEGATE]}>
+                    <HeaderWithBackButton
+                        title={translate('personalInfoStep.personalInfo')}
+                        onBackButtonPress={() => Navigation.goBack(ROUTES.SETTINGS_WALLET, true)}
+                    />
+                    <FailedKYC />
+                </DelegateNoAccessWrapper>
             </ScreenWrapper>
         );
     }
 
     const currentStep = isEmptyObject(bankAccountList) ? CONST.WALLET.STEP.ADD_BANK_ACCOUNT : userWallet?.currentStep || CONST.WALLET.STEP.ADDITIONAL_DETAILS;
-
-    switch (currentStep) {
-        case CONST.WALLET.STEP.ADD_BANK_ACCOUNT:
-            return <AddBankAccount />;
-        case CONST.WALLET.STEP.ADDITIONAL_DETAILS:
-        case CONST.WALLET.STEP.ADDITIONAL_DETAILS_KBA:
-            return <PersonalInfo />;
-        case CONST.WALLET.STEP.ONFIDO:
-            return <VerifyIdentity />;
-        case CONST.WALLET.STEP.TERMS:
-            return <FeesAndTerms />;
-        default:
-            return null;
-    }
+    return (
+        <DelegateNoAccessWrapper accessDeniedVariants={[CONST.DELEGATE.DENIED_ACCESS_VARIANTS.DELEGATE]}>
+            {() => {
+                switch (currentStep) {
+                    case CONST.WALLET.STEP.ADD_BANK_ACCOUNT:
+                        return <AddBankAccount />;
+                    case CONST.WALLET.STEP.ADDITIONAL_DETAILS:
+                    case CONST.WALLET.STEP.ADDITIONAL_DETAILS_KBA:
+                        return <PersonalInfo />;
+                    case CONST.WALLET.STEP.ONFIDO:
+                        return <VerifyIdentity />;
+                    case CONST.WALLET.STEP.TERMS:
+                        return <FeesAndTerms />;
+                    default:
+                        return null;
+                }
+            }}
+        </DelegateNoAccessWrapper>
+    );
 }
 
 EnablePaymentsPage.displayName = 'EnablePaymentsPage';
diff --git a/src/pages/settings/ExitSurvey/ExitSurveyBookCall.tsx b/src/pages/settings/ExitSurvey/ExitSurveyBookCall.tsx
index 93191b809ee8..10085dd7a569 100644
--- a/src/pages/settings/ExitSurvey/ExitSurveyBookCall.tsx
+++ b/src/pages/settings/ExitSurvey/ExitSurveyBookCall.tsx
@@ -1,6 +1,7 @@
 import React from 'react';
 import {View} from 'react-native';
 import Button from '@components/Button';
+import DelegateNoAccessWrapper from '@components/DelegateNoAccessWrapper';
 import FixedFooter from '@components/FixedFooter';
 import HeaderWithBackButton from '@components/HeaderWithBackButton';
 import ScreenWrapper from '@components/ScreenWrapper';
@@ -22,58 +23,60 @@ function ExitSurveyBookCallPage() {
 
     return (
         <ScreenWrapper testID={ExitSurveyBookCallPage.displayName}>
-            <HeaderWithBackButton
-                title={translate('exitSurvey.header')}
-                onBackButtonPress={() => Navigation.goBack()}
-            />
-            <View style={[styles.flex1, styles.mh5]}>
-                {isOffline && <ExitSurveyOffline />}
-                {!isOffline && (
-                    <>
-                        <Text style={[styles.headerAnonymousFooter, styles.mt3]}>{translate('exitSurvey.bookACallTitle')}</Text>
-                        <Text style={[styles.mt2]}>{translate('exitSurvey.bookACallTextTop')}</Text>
-                        <View style={styles.mv4}>
-                            {Object.values(CONST.EXIT_SURVEY.BENEFIT).map((value) => {
-                                return (
-                                    <View
-                                        key={value}
-                                        style={[styles.flexRow]}
-                                    >
-                                        <View style={styles.liDot} />
-                                        <Text>{translate(`exitSurvey.benefits.${value}`)}</Text>
-                                    </View>
-                                );
-                            })}
-                        </View>
-                        <Text>{translate('exitSurvey.bookACallTextBottom')}</Text>
-                    </>
-                )}
-            </View>
-            <FixedFooter>
-                <Button
-                    style={styles.mb3}
-                    large
-                    text={translate('exitSurvey.noThanks')}
-                    onPress={() => {
-                        Navigation.navigate(ROUTES.SETTINGS_EXIT_SURVEY_REASON.getRoute(ROUTES.SETTINGS_EXIT_SURVERY_BOOK_CALL.route));
-                    }}
-                    isDisabled={isOffline}
+            <DelegateNoAccessWrapper accessDeniedVariants={[CONST.DELEGATE.DENIED_ACCESS_VARIANTS.DELEGATE]}>
+                <HeaderWithBackButton
+                    title={translate('exitSurvey.header')}
+                    onBackButtonPress={() => Navigation.goBack()}
                 />
-                <Button
-                    success
-                    large
-                    iconRight={Expensicons.NewWindow}
-                    shouldShowRightIcon
-                    isContentCentered
-                    text={translate('exitSurvey.bookACall')}
-                    pressOnEnter
-                    onPress={() => {
-                        Navigation.dismissModal();
-                        Link.openExternalLink(CONST.EXIT_SURVEY.BOOK_MEETING_LINK);
-                    }}
-                    isDisabled={isOffline}
-                />
-            </FixedFooter>
+                <View style={[styles.flex1, styles.mh5]}>
+                    {isOffline && <ExitSurveyOffline />}
+                    {!isOffline && (
+                        <>
+                            <Text style={[styles.headerAnonymousFooter, styles.mt3]}>{translate('exitSurvey.bookACallTitle')}</Text>
+                            <Text style={[styles.mt2]}>{translate('exitSurvey.bookACallTextTop')}</Text>
+                            <View style={styles.mv4}>
+                                {Object.values(CONST.EXIT_SURVEY.BENEFIT).map((value) => {
+                                    return (
+                                        <View
+                                            key={value}
+                                            style={[styles.flexRow]}
+                                        >
+                                            <View style={styles.liDot} />
+                                            <Text>{translate(`exitSurvey.benefits.${value}`)}</Text>
+                                        </View>
+                                    );
+                                })}
+                            </View>
+                            <Text>{translate('exitSurvey.bookACallTextBottom')}</Text>
+                        </>
+                    )}
+                </View>
+                <FixedFooter>
+                    <Button
+                        style={styles.mb3}
+                        large
+                        text={translate('exitSurvey.noThanks')}
+                        onPress={() => {
+                            Navigation.navigate(ROUTES.SETTINGS_EXIT_SURVEY_REASON.getRoute(ROUTES.SETTINGS_EXIT_SURVERY_BOOK_CALL.route));
+                        }}
+                        isDisabled={isOffline}
+                    />
+                    <Button
+                        success
+                        large
+                        iconRight={Expensicons.NewWindow}
+                        shouldShowRightIcon
+                        isContentCentered
+                        text={translate('exitSurvey.bookACall')}
+                        pressOnEnter
+                        onPress={() => {
+                            Navigation.dismissModal();
+                            Link.openExternalLink(CONST.EXIT_SURVEY.BOOK_MEETING_LINK);
+                        }}
+                        isDisabled={isOffline}
+                    />
+                </FixedFooter>
+            </DelegateNoAccessWrapper>
         </ScreenWrapper>
     );
 }
diff --git a/src/pages/settings/ExitSurvey/ExitSurveyConfirmPage.tsx b/src/pages/settings/ExitSurvey/ExitSurveyConfirmPage.tsx
index 50a3bb7767c0..0f4635afab5e 100644
--- a/src/pages/settings/ExitSurvey/ExitSurveyConfirmPage.tsx
+++ b/src/pages/settings/ExitSurvey/ExitSurveyConfirmPage.tsx
@@ -5,6 +5,7 @@ import {useOnyx} from 'react-native-onyx';
 import type {OnyxEntry} from 'react-native-onyx';
 import Icon from '@components//Icon';
 import Button from '@components/Button';
+import DelegateNoAccessWrapper from '@components/DelegateNoAccessWrapper';
 import FixedFooter from '@components/FixedFooter';
 import HeaderWithBackButton from '@components/HeaderWithBackButton';
 import {MushroomTopHat} from '@components/Icon/Illustrations';
@@ -60,40 +61,42 @@ function ExitSurveyConfirmPage({route, navigation}: ExitSurveyConfirmPageProps)
 
     return (
         <ScreenWrapper testID={ExitSurveyConfirmPage.displayName}>
-            <HeaderWithBackButton
-                title={translate(shouldShowQuickTips ? 'exitSurvey.goToExpensifyClassic' : 'exitSurvey.header')}
-                onBackButtonPress={() => Navigation.goBack()}
-            />
-            <View style={[styles.flex1, styles.justifyContentCenter, styles.alignItemsCenter, styles.mh5]}>
-                {isOffline && <ExitSurveyOffline />}
-                {!isOffline && (
-                    <>
-                        <Icon
-                            src={MushroomTopHat}
-                            width={variables.mushroomTopHatWidth}
-                            height={variables.mushroomTopHatHeight}
-                        />
-                        <Text style={[styles.headerAnonymousFooter, styles.mt5, styles.textAlignCenter]}>
-                            {translate(shouldShowQuickTips ? 'exitSurvey.quickTip' : 'exitSurvey.thankYou')}
-                        </Text>
-                        <Text style={[styles.mt2, styles.textAlignCenter]}>{translate(shouldShowQuickTips ? 'exitSurvey.quickTipSubTitle' : 'exitSurvey.thankYouSubtitle')}</Text>
-                    </>
-                )}
-            </View>
-            <FixedFooter>
-                <Button
-                    success
-                    large
-                    text={translate(shouldShowQuickTips ? 'exitSurvey.takeMeToExpensifyClassic' : 'exitSurvey.goToExpensifyClassic')}
-                    pressOnEnter
-                    onPress={() => {
-                        ExitSurvey.switchToOldDot();
-                        Navigation.dismissModal();
-                        Link.openOldDotLink(CONST.OLDDOT_URLS.INBOX);
-                    }}
-                    isDisabled={isOffline}
+            <DelegateNoAccessWrapper accessDeniedVariants={[CONST.DELEGATE.DENIED_ACCESS_VARIANTS.DELEGATE]}>
+                <HeaderWithBackButton
+                    title={translate(shouldShowQuickTips ? 'exitSurvey.goToExpensifyClassic' : 'exitSurvey.header')}
+                    onBackButtonPress={() => Navigation.goBack()}
                 />
-            </FixedFooter>
+                <View style={[styles.flex1, styles.justifyContentCenter, styles.alignItemsCenter, styles.mh5]}>
+                    {isOffline && <ExitSurveyOffline />}
+                    {!isOffline && (
+                        <>
+                            <Icon
+                                src={MushroomTopHat}
+                                width={variables.mushroomTopHatWidth}
+                                height={variables.mushroomTopHatHeight}
+                            />
+                            <Text style={[styles.headerAnonymousFooter, styles.mt5, styles.textAlignCenter]}>
+                                {translate(shouldShowQuickTips ? 'exitSurvey.quickTip' : 'exitSurvey.thankYou')}
+                            </Text>
+                            <Text style={[styles.mt2, styles.textAlignCenter]}>{translate(shouldShowQuickTips ? 'exitSurvey.quickTipSubTitle' : 'exitSurvey.thankYouSubtitle')}</Text>
+                        </>
+                    )}
+                </View>
+                <FixedFooter>
+                    <Button
+                        success
+                        large
+                        text={translate(shouldShowQuickTips ? 'exitSurvey.takeMeToExpensifyClassic' : 'exitSurvey.goToExpensifyClassic')}
+                        pressOnEnter
+                        onPress={() => {
+                            ExitSurvey.switchToOldDot();
+                            Navigation.dismissModal();
+                            Link.openOldDotLink(CONST.OLDDOT_URLS.INBOX);
+                        }}
+                        isDisabled={isOffline}
+                    />
+                </FixedFooter>
+            </DelegateNoAccessWrapper>
         </ScreenWrapper>
     );
 }
diff --git a/src/pages/settings/ExitSurvey/ExitSurveyOffline.tsx b/src/pages/settings/ExitSurvey/ExitSurveyOffline.tsx
index 3363867ad4bb..c0e4b627b2a4 100644
--- a/src/pages/settings/ExitSurvey/ExitSurveyOffline.tsx
+++ b/src/pages/settings/ExitSurvey/ExitSurveyOffline.tsx
@@ -1,25 +1,29 @@
 import React, {memo} from 'react';
 import {View} from 'react-native';
+import DelegateNoAccessWrapper from '@components/DelegateNoAccessWrapper';
 import Icon from '@components/Icon';
 import {ToddBehindCloud} from '@components/Icon/Illustrations';
 import Text from '@components/Text';
 import useLocalize from '@hooks/useLocalize';
 import useThemeStyles from '@hooks/useThemeStyles';
 import variables from '@styles/variables';
+import CONST from '@src/CONST';
 
 function ExitSurveyOffline() {
     const {translate} = useLocalize();
     const styles = useThemeStyles();
     return (
-        <View style={[styles.flex1, styles.justifyContentCenter, styles.alignItemsCenter]}>
-            <Icon
-                width={variables.modalTopIconWidth}
-                height={variables.modalTopIconHeight}
-                src={ToddBehindCloud}
-            />
-            <Text style={[styles.headerAnonymousFooter, styles.textAlignCenter]}>{translate('exitSurvey.offlineTitle')}</Text>
-            <Text style={[styles.mt2, styles.textAlignCenter]}>{translate('exitSurvey.offline')}</Text>
-        </View>
+        <DelegateNoAccessWrapper accessDeniedVariants={[CONST.DELEGATE.DENIED_ACCESS_VARIANTS.DELEGATE]}>
+            <View style={[styles.flex1, styles.justifyContentCenter, styles.alignItemsCenter]}>
+                <Icon
+                    width={variables.modalTopIconWidth}
+                    height={variables.modalTopIconHeight}
+                    src={ToddBehindCloud}
+                />
+                <Text style={[styles.headerAnonymousFooter, styles.textAlignCenter]}>{translate('exitSurvey.offlineTitle')}</Text>
+                <Text style={[styles.mt2, styles.textAlignCenter]}>{translate('exitSurvey.offline')}</Text>
+            </View>
+        </DelegateNoAccessWrapper>
     );
 }
 
diff --git a/src/pages/settings/ExitSurvey/ExitSurveyReasonPage.tsx b/src/pages/settings/ExitSurvey/ExitSurveyReasonPage.tsx
index b5bdcf9ac45c..4e34fc47a6ed 100644
--- a/src/pages/settings/ExitSurvey/ExitSurveyReasonPage.tsx
+++ b/src/pages/settings/ExitSurvey/ExitSurveyReasonPage.tsx
@@ -1,6 +1,7 @@
 import React, {useEffect, useMemo, useState} from 'react';
 import type {OnyxEntry} from 'react-native-onyx';
 import {useOnyx} from 'react-native-onyx';
+import DelegateNoAccessWrapper from '@components/DelegateNoAccessWrapper';
 import FormProvider from '@components/Form/FormProvider';
 import InputWrapper from '@components/Form/InputWrapper';
 import HeaderWithBackButton from '@components/HeaderWithBackButton';
@@ -48,47 +49,49 @@ function ExitSurveyReasonPage() {
 
     return (
         <ScreenWrapper testID={ExitSurveyReasonPage.displayName}>
-            <HeaderWithBackButton
-                title={translate('exitSurvey.header')}
-                onBackButtonPress={() => Navigation.goBack()}
-            />
-            <FormProvider
-                formID={ONYXKEYS.FORMS.EXIT_SURVEY_REASON_FORM}
-                style={[styles.flex1, styles.mt3, styles.mh5]}
-                validate={() => {
-                    const errors: Errors = {};
-                    if (!reason) {
-                        errors[INPUT_IDS.REASON] = translate('common.error.fieldRequired');
-                    }
-                    return errors;
-                }}
-                onSubmit={() => {
-                    if (!reason) {
-                        return;
-                    }
-                    ExitSurvey.saveExitReason(reason);
-                    Navigation.navigate(ROUTES.SETTINGS_EXIT_SURVEY_RESPONSE.getRoute(reason, ROUTES.SETTINGS_EXIT_SURVEY_REASON.route));
-                }}
-                submitButtonText={translate('common.next')}
-                shouldValidateOnBlur
-                shouldValidateOnChange
-            >
-                {isOffline && <ExitSurveyOffline />}
-                {!isOffline && (
-                    <>
-                        <Text style={styles.headerAnonymousFooter}>{translate('exitSurvey.reasonPage.title')}</Text>
-                        <Text style={styles.mt2}>{translate('exitSurvey.reasonPage.subtitle')}</Text>
-                        <InputWrapper
-                            InputComponent={RadioButtons}
-                            inputID={INPUT_IDS.REASON}
-                            value={reason as string}
-                            items={reasons}
-                            onPress={setReason as (value: string) => void}
-                            shouldSaveDraft
-                        />
-                    </>
-                )}
-            </FormProvider>
+            <DelegateNoAccessWrapper accessDeniedVariants={[CONST.DELEGATE.DENIED_ACCESS_VARIANTS.DELEGATE]}>
+                <HeaderWithBackButton
+                    title={translate('exitSurvey.header')}
+                    onBackButtonPress={() => Navigation.goBack()}
+                />
+                <FormProvider
+                    formID={ONYXKEYS.FORMS.EXIT_SURVEY_REASON_FORM}
+                    style={[styles.flex1, styles.mt3, styles.mh5]}
+                    validate={() => {
+                        const errors: Errors = {};
+                        if (!reason) {
+                            errors[INPUT_IDS.REASON] = translate('common.error.fieldRequired');
+                        }
+                        return errors;
+                    }}
+                    onSubmit={() => {
+                        if (!reason) {
+                            return;
+                        }
+                        ExitSurvey.saveExitReason(reason);
+                        Navigation.navigate(ROUTES.SETTINGS_EXIT_SURVEY_RESPONSE.getRoute(reason, ROUTES.SETTINGS_EXIT_SURVEY_REASON.route));
+                    }}
+                    submitButtonText={translate('common.next')}
+                    shouldValidateOnBlur
+                    shouldValidateOnChange
+                >
+                    {isOffline && <ExitSurveyOffline />}
+                    {!isOffline && (
+                        <>
+                            <Text style={styles.headerAnonymousFooter}>{translate('exitSurvey.reasonPage.title')}</Text>
+                            <Text style={styles.mt2}>{translate('exitSurvey.reasonPage.subtitle')}</Text>
+                            <InputWrapper
+                                InputComponent={RadioButtons}
+                                inputID={INPUT_IDS.REASON}
+                                value={reason as string}
+                                items={reasons}
+                                onPress={setReason as (value: string) => void}
+                                shouldSaveDraft
+                            />
+                        </>
+                    )}
+                </FormProvider>
+            </DelegateNoAccessWrapper>
         </ScreenWrapper>
     );
 }
diff --git a/src/pages/settings/ExitSurvey/ExitSurveyResponsePage.tsx b/src/pages/settings/ExitSurvey/ExitSurveyResponsePage.tsx
index d33828b722eb..2ea73a1cc6db 100644
--- a/src/pages/settings/ExitSurvey/ExitSurveyResponsePage.tsx
+++ b/src/pages/settings/ExitSurvey/ExitSurveyResponsePage.tsx
@@ -1,6 +1,7 @@
 import type {StackScreenProps} from '@react-navigation/stack';
 import React, {useCallback, useEffect} from 'react';
 import {useOnyx} from 'react-native-onyx';
+import DelegateNoAccessWrapper from '@components/DelegateNoAccessWrapper';
 import FormProvider from '@components/Form/FormProvider';
 import InputWrapper from '@components/Form/InputWrapper';
 import HeaderWithBackButton from '@components/HeaderWithBackButton';
@@ -86,46 +87,48 @@ function ExitSurveyResponsePage({route, navigation}: ExitSurveyResponsePageProps
             testID={ExitSurveyResponsePage.displayName}
             shouldEnableMaxHeight
         >
-            <HeaderWithBackButton
-                title={translate('exitSurvey.header')}
-                onBackButtonPress={() => Navigation.goBack()}
-            />
-            <FormProvider
-                formID={ONYXKEYS.FORMS.EXIT_SURVEY_RESPONSE_FORM}
-                style={[styles.flex1, styles.mh5, formTopMarginsStyle, StyleUtils.getMaximumHeight(formMaxHeight)]}
-                onSubmit={submitForm}
-                submitButtonText={translate('common.next')}
-                validate={() => {
-                    const errors: Errors = {};
-                    if (!draftResponse?.trim()) {
-                        errors[INPUT_IDS.RESPONSE] = translate('common.error.fieldRequired');
-                    }
-                    return errors;
-                }}
-                shouldValidateOnBlur
-                shouldValidateOnChange
-            >
-                {isOffline && <ExitSurveyOffline />}
-                {!isOffline && (
-                    <>
-                        <Text style={textStyle}>{translate(`exitSurvey.prompts.${reason}`)}</Text>
-                        <InputWrapper
-                            InputComponent={TextInput}
-                            inputID={INPUT_IDS.RESPONSE}
-                            label={translate(`exitSurvey.responsePlaceholder`)}
-                            accessibilityLabel={translate(`exitSurvey.responsePlaceholder`)}
-                            role={CONST.ROLE.PRESENTATION}
-                            autoGrowHeight
-                            maxAutoGrowHeight={variables.textInputAutoGrowMaxHeight}
-                            maxLength={CONST.MAX_COMMENT_LENGTH}
-                            ref={inputCallbackRef}
-                            containerStyles={[baseResponseInputContainerStyle]}
-                            shouldSaveDraft
-                            shouldSubmitForm
-                        />
-                    </>
-                )}
-            </FormProvider>
+            <DelegateNoAccessWrapper accessDeniedVariants={[CONST.DELEGATE.DENIED_ACCESS_VARIANTS.DELEGATE]}>
+                <HeaderWithBackButton
+                    title={translate('exitSurvey.header')}
+                    onBackButtonPress={() => Navigation.goBack()}
+                />
+                <FormProvider
+                    formID={ONYXKEYS.FORMS.EXIT_SURVEY_RESPONSE_FORM}
+                    style={[styles.flex1, styles.mh5, formTopMarginsStyle, StyleUtils.getMaximumHeight(formMaxHeight)]}
+                    onSubmit={submitForm}
+                    submitButtonText={translate('common.next')}
+                    validate={() => {
+                        const errors: Errors = {};
+                        if (!draftResponse?.trim()) {
+                            errors[INPUT_IDS.RESPONSE] = translate('common.error.fieldRequired');
+                        }
+                        return errors;
+                    }}
+                    shouldValidateOnBlur
+                    shouldValidateOnChange
+                >
+                    {isOffline && <ExitSurveyOffline />}
+                    {!isOffline && (
+                        <>
+                            <Text style={textStyle}>{translate(`exitSurvey.prompts.${reason}`)}</Text>
+                            <InputWrapper
+                                InputComponent={TextInput}
+                                inputID={INPUT_IDS.RESPONSE}
+                                label={translate(`exitSurvey.responsePlaceholder`)}
+                                accessibilityLabel={translate(`exitSurvey.responsePlaceholder`)}
+                                role={CONST.ROLE.PRESENTATION}
+                                autoGrowHeight
+                                maxAutoGrowHeight={variables.textInputAutoGrowMaxHeight}
+                                maxLength={CONST.MAX_COMMENT_LENGTH}
+                                ref={inputCallbackRef}
+                                containerStyles={[baseResponseInputContainerStyle]}
+                                shouldSaveDraft
+                                shouldSubmitForm
+                            />
+                        </>
+                    )}
+                </FormProvider>
+            </DelegateNoAccessWrapper>
         </ScreenWrapper>
     );
 }
diff --git a/src/pages/settings/Profile/Contacts/NewContactMethodPage.tsx b/src/pages/settings/Profile/Contacts/NewContactMethodPage.tsx
index b8ef3d2c198b..7f4a99d197a8 100644
--- a/src/pages/settings/Profile/Contacts/NewContactMethodPage.tsx
+++ b/src/pages/settings/Profile/Contacts/NewContactMethodPage.tsx
@@ -169,7 +169,7 @@ function NewContactMethodPage({route}: NewContactMethodPageProps) {
                     hasMagicCodeBeenSent={!!loginData?.validateCodeSent}
                     title={translate('delegate.makeSureItIsYou')}
                     sendValidateCode={() => User.requestValidateCodeAction()}
-                    description={translate('contacts.enterMagicCode', {contactMethod})}
+                    descriptionPrimary={translate('contacts.enterMagicCode', {contactMethod})}
                 />
             </ScreenWrapper>
         </DelegateNoAccessWrapper>
diff --git a/src/pages/settings/Security/AddDelegate/AddDelegatePage.tsx b/src/pages/settings/Security/AddDelegate/AddDelegatePage.tsx
index 6f54fc098633..2a12e5183569 100644
--- a/src/pages/settings/Security/AddDelegate/AddDelegatePage.tsx
+++ b/src/pages/settings/Security/AddDelegate/AddDelegatePage.tsx
@@ -1,6 +1,7 @@
 import React, {useCallback, useEffect, useMemo, useState} from 'react';
 import {View} from 'react-native';
 import {useOnyx} from 'react-native-onyx';
+import DelegateNoAccessWrapper from '@components/DelegateNoAccessWrapper';
 import HeaderWithBackButton from '@components/HeaderWithBackButton';
 import {useBetas} from '@components/OnyxProvider';
 import {useOptionsList} from '@components/OptionListContextProvider';
@@ -129,24 +130,26 @@ function AddDelegatePage() {
             includeSafeAreaPaddingBottom={false}
             testID={AddDelegatePage.displayName}
         >
-            <HeaderWithBackButton
-                title={translate('delegate.addCopilot')}
-                onBackButtonPress={() => Navigation.goBack()}
-            />
-            <View style={[styles.flex1, styles.w100, styles.pRelative]}>
-                <SelectionList
-                    sections={areOptionsInitialized ? sections : []}
-                    ListItem={UserListItem}
-                    onSelectRow={onSelectRow}
-                    shouldSingleExecuteRowSelect
-                    onChangeText={setSearchValue}
-                    textInputValue={searchValue}
-                    headerMessage={headerMessage}
-                    textInputLabel={translate('selectionList.nameEmailOrPhoneNumber')}
-                    showLoadingPlaceholder={!areOptionsInitialized}
-                    isLoadingNewOptions={!!isSearchingForReports}
+            <DelegateNoAccessWrapper accessDeniedVariants={[CONST.DELEGATE.DENIED_ACCESS_VARIANTS.DELEGATE]}>
+                <HeaderWithBackButton
+                    title={translate('delegate.addCopilot')}
+                    onBackButtonPress={() => Navigation.goBack()}
                 />
-            </View>
+                <View style={[styles.flex1, styles.w100, styles.pRelative]}>
+                    <SelectionList
+                        sections={areOptionsInitialized ? sections : []}
+                        ListItem={UserListItem}
+                        onSelectRow={onSelectRow}
+                        shouldSingleExecuteRowSelect
+                        onChangeText={setSearchValue}
+                        textInputValue={searchValue}
+                        headerMessage={headerMessage}
+                        textInputLabel={translate('selectionList.nameEmailOrPhoneNumber')}
+                        showLoadingPlaceholder={!areOptionsInitialized}
+                        isLoadingNewOptions={!!isSearchingForReports}
+                    />
+                </View>
+            </DelegateNoAccessWrapper>
         </ScreenWrapper>
     );
 }
diff --git a/src/pages/settings/Security/AddDelegate/ConfirmDelegatePage.tsx b/src/pages/settings/Security/AddDelegate/ConfirmDelegatePage.tsx
index 8dd3996a769a..dd0a1d8f8cf1 100644
--- a/src/pages/settings/Security/AddDelegate/ConfirmDelegatePage.tsx
+++ b/src/pages/settings/Security/AddDelegate/ConfirmDelegatePage.tsx
@@ -2,6 +2,7 @@ import type {StackScreenProps} from '@react-navigation/stack';
 import React, {useState} from 'react';
 import type {ValueOf} from 'type-fest';
 import Button from '@components/Button';
+import DelegateNoAccessWrapper from '@components/DelegateNoAccessWrapper';
 import HeaderPageLayout from '@components/HeaderPageLayout';
 import {FallbackAvatar} from '@components/Icon/Expensicons';
 import MenuItem from '@components/MenuItem';
@@ -57,34 +58,36 @@ function ConfirmDelegatePage({route}: ConfirmDelegatePageProps) {
             footer={submitButton}
             childrenContainerStyles={[styles.pt3, styles.gap6]}
         >
-            <Text style={[styles.ph5]}>{translate('delegate.confirmCopilot')}</Text>
-            <MenuItem
-                avatarID={personalDetails?.accountID ?? -1}
-                iconType={CONST.ICON_TYPE_AVATAR}
-                icon={avatarIcon}
-                title={displayName}
-                description={formattedLogin}
-                interactive={false}
-            />
-            <MenuItemWithTopDescription
-                title={translate('delegate.role', {role})}
-                description={translate('delegate.accessLevel')}
-                helperText={translate('delegate.roleDescription', {role})}
-                onPress={() => Navigation.navigate(ROUTES.SETTINGS_DELEGATE_ROLE.getRoute(login, role))}
-                shouldShowRightIcon
-            />
-            <DelegateMagicCodeModal
-                login={login}
-                role={role}
-                onClose={() => {
-                    if (!showValidateActionModal) {
-                        setIsValidateCodeActionModalVisible(false);
-                        return;
-                    }
-                    Navigation.navigate(ROUTES.SETTINGS_SECURITY);
-                }}
-                isValidateCodeActionModalVisible={isValidateCodeActionModalVisible}
-            />
+            <DelegateNoAccessWrapper accessDeniedVariants={[CONST.DELEGATE.DENIED_ACCESS_VARIANTS.DELEGATE]}>
+                <Text style={[styles.ph5]}>{translate('delegate.confirmCopilot')}</Text>
+                <MenuItem
+                    avatarID={personalDetails?.accountID ?? -1}
+                    iconType={CONST.ICON_TYPE_AVATAR}
+                    icon={avatarIcon}
+                    title={displayName}
+                    description={formattedLogin}
+                    interactive={false}
+                />
+                <MenuItemWithTopDescription
+                    title={translate('delegate.role', {role})}
+                    description={translate('delegate.accessLevel')}
+                    helperText={translate('delegate.roleDescription', {role})}
+                    onPress={() => Navigation.navigate(ROUTES.SETTINGS_DELEGATE_ROLE.getRoute(login, role))}
+                    shouldShowRightIcon
+                />
+                <DelegateMagicCodeModal
+                    login={login}
+                    role={role}
+                    onClose={() => {
+                        if (!showValidateActionModal) {
+                            setIsValidateCodeActionModalVisible(false);
+                            return;
+                        }
+                        Navigation.navigate(ROUTES.SETTINGS_SECURITY);
+                    }}
+                    isValidateCodeActionModalVisible={isValidateCodeActionModalVisible}
+                />
+            </DelegateNoAccessWrapper>
         </HeaderPageLayout>
     );
 }
diff --git a/src/pages/settings/Security/AddDelegate/SelectDelegateRolePage.tsx b/src/pages/settings/Security/AddDelegate/SelectDelegateRolePage.tsx
index 4270441775cd..877ea7929981 100644
--- a/src/pages/settings/Security/AddDelegate/SelectDelegateRolePage.tsx
+++ b/src/pages/settings/Security/AddDelegate/SelectDelegateRolePage.tsx
@@ -1,5 +1,6 @@
 import type {StackScreenProps} from '@react-navigation/stack';
 import React from 'react';
+import DelegateNoAccessWrapper from '@components/DelegateNoAccessWrapper';
 import HeaderWithBackButton from '@components/HeaderWithBackButton';
 import ScreenWrapper from '@components/ScreenWrapper';
 import SelectionList from '@components/SelectionList';
@@ -34,34 +35,36 @@ function SelectDelegateRolePage({route}: SelectDelegateRolePageProps) {
             includeSafeAreaPaddingBottom={false}
             testID={SelectDelegateRolePage.displayName}
         >
-            <HeaderWithBackButton
-                title={translate('delegate.accessLevel')}
-                onBackButtonPress={() => Navigation.goBack(ROUTES.SETTINGS_ADD_DELEGATE)}
-            />
-            <SelectionList
-                isAlternateTextMultilineSupported
-                alternateTextNumberOfLines={4}
-                initiallyFocusedOptionKey={roleOptions.find((role) => role.isSelected)?.keyForList}
-                shouldUpdateFocusedIndex
-                headerContent={
-                    <Text style={[styles.ph5, styles.pb5, styles.pt3]}>
-                        <>
-                            {translate('delegate.accessLevelDescription')}{' '}
-                            <TextLink
-                                style={[styles.link]}
-                                href={CONST.COPILOT_HELP_URL}
-                            >
-                                {translate('common.learnMore')}
-                            </TextLink>
-                        </>
-                    </Text>
-                }
-                onSelectRow={(option) => {
-                    Navigation.navigate(ROUTES.SETTINGS_DELEGATE_CONFIRM.getRoute(login, option.value));
-                }}
-                sections={[{data: roleOptions}]}
-                ListItem={RadioListItem}
-            />
+            <DelegateNoAccessWrapper accessDeniedVariants={[CONST.DELEGATE.DENIED_ACCESS_VARIANTS.DELEGATE]}>
+                <HeaderWithBackButton
+                    title={translate('delegate.accessLevel')}
+                    onBackButtonPress={() => Navigation.goBack(ROUTES.SETTINGS_ADD_DELEGATE)}
+                />
+                <SelectionList
+                    isAlternateTextMultilineSupported
+                    alternateTextNumberOfLines={4}
+                    initiallyFocusedOptionKey={roleOptions.find((role) => role.isSelected)?.keyForList}
+                    shouldUpdateFocusedIndex
+                    headerContent={
+                        <Text style={[styles.ph5, styles.pb5, styles.pt3]}>
+                            <>
+                                {translate('delegate.accessLevelDescription')}{' '}
+                                <TextLink
+                                    style={[styles.link]}
+                                    href={CONST.COPILOT_HELP_URL}
+                                >
+                                    {translate('common.learnMore')}
+                                </TextLink>
+                            </>
+                        </Text>
+                    }
+                    onSelectRow={(option) => {
+                        Navigation.navigate(ROUTES.SETTINGS_DELEGATE_CONFIRM.getRoute(login, option.value));
+                    }}
+                    sections={[{data: roleOptions}]}
+                    ListItem={RadioListItem}
+                />
+            </DelegateNoAccessWrapper>
         </ScreenWrapper>
     );
 }
diff --git a/src/pages/settings/Security/AddDelegate/UpdateDelegateRole/UpdateDelegateMagicCodePage.tsx b/src/pages/settings/Security/AddDelegate/UpdateDelegateRole/UpdateDelegateMagicCodePage.tsx
index 3bc82e8d7e65..5c07981ee24e 100644
--- a/src/pages/settings/Security/AddDelegate/UpdateDelegateRole/UpdateDelegateMagicCodePage.tsx
+++ b/src/pages/settings/Security/AddDelegate/UpdateDelegateRole/UpdateDelegateMagicCodePage.tsx
@@ -2,6 +2,7 @@ import type {StackScreenProps} from '@react-navigation/stack';
 import React, {useEffect, useRef} from 'react';
 import {useOnyx} from 'react-native-onyx';
 import type {ValueOf} from 'type-fest';
+import DelegateNoAccessWrapper from '@components/DelegateNoAccessWrapper';
 import HeaderWithBackButton from '@components/HeaderWithBackButton';
 import ScreenWrapper from '@components/ScreenWrapper';
 import Text from '@components/Text';
@@ -9,7 +10,7 @@ import useLocalize from '@hooks/useLocalize';
 import useThemeStyles from '@hooks/useThemeStyles';
 import Navigation from '@libs/Navigation/Navigation';
 import type {SettingsNavigatorParamList} from '@libs/Navigation/types';
-import type CONST from '@src/CONST';
+import CONST from '@src/CONST';
 import ONYXKEYS from '@src/ONYXKEYS';
 import ROUTES from '@src/ROUTES';
 import type SCREENS from '@src/SCREENS';
@@ -52,17 +53,19 @@ function UpdateDelegateMagicCodePage({route}: UpdateDelegateMagicCodePageProps)
         >
             {({safeAreaPaddingBottomStyle}) => (
                 <>
-                    <HeaderWithBackButton
-                        title={translate('delegate.makeSureItIsYou')}
-                        onBackButtonPress={onBackButtonPress}
-                    />
-                    <Text style={[styles.mb3, styles.ph5]}>{translate('delegate.enterMagicCodeUpdate', {contactMethod: account?.primaryLogin ?? ''})}</Text>
-                    <ValidateCodeForm
-                        ref={validateCodeFormRef}
-                        delegate={login}
-                        role={role}
-                        wrapperStyle={safeAreaPaddingBottomStyle}
-                    />
+                    <DelegateNoAccessWrapper accessDeniedVariants={[CONST.DELEGATE.DENIED_ACCESS_VARIANTS.DELEGATE]}>
+                        <HeaderWithBackButton
+                            title={translate('delegate.makeSureItIsYou')}
+                            onBackButtonPress={onBackButtonPress}
+                        />
+                        <Text style={[styles.mb3, styles.ph5]}>{translate('delegate.enterMagicCodeUpdate', {contactMethod: account?.primaryLogin ?? ''})}</Text>
+                        <ValidateCodeForm
+                            ref={validateCodeFormRef}
+                            delegate={login}
+                            role={role}
+                            wrapperStyle={safeAreaPaddingBottomStyle}
+                        />
+                    </DelegateNoAccessWrapper>
                 </>
             )}
         </ScreenWrapper>
diff --git a/src/pages/settings/Security/AddDelegate/UpdateDelegateRole/UpdateDelegateRolePage.tsx b/src/pages/settings/Security/AddDelegate/UpdateDelegateRole/UpdateDelegateRolePage.tsx
index 1ac362a50457..829e723c761f 100644
--- a/src/pages/settings/Security/AddDelegate/UpdateDelegateRole/UpdateDelegateRolePage.tsx
+++ b/src/pages/settings/Security/AddDelegate/UpdateDelegateRole/UpdateDelegateRolePage.tsx
@@ -1,5 +1,6 @@
 import type {StackScreenProps} from '@react-navigation/stack';
 import React, {useEffect, useState} from 'react';
+import DelegateNoAccessWrapper from '@components/DelegateNoAccessWrapper';
 import HeaderWithBackButton from '@components/HeaderWithBackButton';
 import ScreenWrapper from '@components/ScreenWrapper';
 import SelectionList from '@components/SelectionList';
@@ -43,41 +44,43 @@ function UpdateDelegateRolePage({route}: UpdateDelegateRolePageProps) {
             includeSafeAreaPaddingBottom={false}
             testID={UpdateDelegateRolePage.displayName}
         >
-            <HeaderWithBackButton
-                title={translate('delegate.accessLevel')}
-                onBackButtonPress={() => Navigation.goBack()}
-            />
-            <SelectionList
-                isAlternateTextMultilineSupported
-                alternateTextNumberOfLines={4}
-                initiallyFocusedOptionKey={currentRole}
-                shouldUpdateFocusedIndex
-                headerContent={
-                    <Text style={[styles.ph5, styles.pb5, styles.pt3]}>
-                        <>
-                            {translate('delegate.accessLevelDescription')}{' '}
-                            <TextLink
-                                style={[styles.link]}
-                                href={CONST.COPILOT_HELP_URL}
-                            >
-                                {translate('common.learnMore')}
-                            </TextLink>
-                        </>
-                    </Text>
-                }
-                onSelectRow={(option) => {
-                    if (option.isSelected) {
-                        Navigation.dismissModal();
-                        return;
+            <DelegateNoAccessWrapper accessDeniedVariants={[CONST.DELEGATE.DENIED_ACCESS_VARIANTS.DELEGATE]}>
+                <HeaderWithBackButton
+                    title={translate('delegate.accessLevel')}
+                    onBackButtonPress={() => Navigation.goBack()}
+                />
+                <SelectionList
+                    isAlternateTextMultilineSupported
+                    alternateTextNumberOfLines={4}
+                    initiallyFocusedOptionKey={currentRole}
+                    shouldUpdateFocusedIndex
+                    headerContent={
+                        <Text style={[styles.ph5, styles.pb5, styles.pt3]}>
+                            <>
+                                {translate('delegate.accessLevelDescription')}{' '}
+                                <TextLink
+                                    style={[styles.link]}
+                                    href={CONST.COPILOT_HELP_URL}
+                                >
+                                    {translate('common.learnMore')}
+                                </TextLink>
+                            </>
+                        </Text>
                     }
+                    onSelectRow={(option) => {
+                        if (option.isSelected) {
+                            Navigation.dismissModal();
+                            return;
+                        }
 
-                    requestValidationCode();
-                    setCurrentRole(option.value);
-                    Navigation.navigate(ROUTES.SETTINGS_UPDATE_DELEGATE_ROLE_MAGIC_CODE.getRoute(login, option.value));
-                }}
-                sections={[{data: roleOptions}]}
-                ListItem={RadioListItem}
-            />
+                        requestValidationCode();
+                        setCurrentRole(option.value);
+                        Navigation.navigate(ROUTES.SETTINGS_UPDATE_DELEGATE_ROLE_MAGIC_CODE.getRoute(login, option.value));
+                    }}
+                    sections={[{data: roleOptions}]}
+                    ListItem={RadioListItem}
+                />
+            </DelegateNoAccessWrapper>
         </ScreenWrapper>
     );
 }
diff --git a/src/pages/settings/Security/CloseAccountPage.tsx b/src/pages/settings/Security/CloseAccountPage.tsx
index 1da4436ca810..bab605361c52 100644
--- a/src/pages/settings/Security/CloseAccountPage.tsx
+++ b/src/pages/settings/Security/CloseAccountPage.tsx
@@ -5,6 +5,7 @@ import {View} from 'react-native';
 import {withOnyx} from 'react-native-onyx';
 import type {OnyxEntry} from 'react-native-onyx';
 import ConfirmModal from '@components/ConfirmModal';
+import DelegateNoAccessWrapper from '@components/DelegateNoAccessWrapper';
 import FormProvider from '@components/Form/FormProvider';
 import InputWrapper from '@components/Form/InputWrapper';
 import type {FormInputErrors, FormOnyxValues} from '@components/Form/types';
@@ -84,58 +85,60 @@ function CloseAccountPage({session}: CloseAccountPageProps) {
             includeSafeAreaPaddingBottom={false}
             testID={CloseAccountPage.displayName}
         >
-            <HeaderWithBackButton
-                title={translate('closeAccountPage.closeAccount')}
-                onBackButtonPress={() => Navigation.goBack()}
-            />
-            <FormProvider
-                formID={ONYXKEYS.FORMS.CLOSE_ACCOUNT_FORM}
-                validate={validate}
-                onSubmit={showConfirmModal}
-                submitButtonText={translate('closeAccountPage.closeAccount')}
-                style={[styles.flexGrow1, styles.mh5]}
-                isSubmitActionDangerous
-            >
-                <View style={[styles.flexGrow1]}>
-                    <Text>{translate('closeAccountPage.reasonForLeavingPrompt')}</Text>
-                    <InputWrapper
-                        InputComponent={TextInput}
-                        inputID={INPUT_IDS.REASON_FOR_LEAVING}
-                        autoGrowHeight
-                        maxAutoGrowHeight={variables.textInputAutoGrowMaxHeight}
-                        label={translate('closeAccountPage.enterMessageHere')}
-                        aria-label={translate('closeAccountPage.enterMessageHere')}
-                        role={CONST.ROLE.PRESENTATION}
-                        containerStyles={[styles.mt5]}
-                    />
-                    <Text style={[styles.mt5]}>
-                        {translate('closeAccountPage.enterDefaultContactToConfirm')} <Text style={[styles.textStrong]}>{userEmailOrPhone}</Text>
-                    </Text>
-                    <InputWrapper
-                        InputComponent={TextInput}
-                        inputID={INPUT_IDS.PHONE_OR_EMAIL}
-                        autoCapitalize="none"
-                        label={translate('closeAccountPage.enterDefaultContact')}
-                        aria-label={translate('closeAccountPage.enterDefaultContact')}
-                        role={CONST.ROLE.PRESENTATION}
-                        containerStyles={[styles.mt5]}
-                        autoCorrect={false}
-                        inputMode={userEmailOrPhone && Str.isValidEmail(userEmailOrPhone) ? CONST.INPUT_MODE.EMAIL : CONST.INPUT_MODE.TEXT}
-                    />
-                    <ConfirmModal
-                        danger
-                        title={translate('closeAccountPage.closeAccountWarning')}
-                        onConfirm={onConfirm}
-                        onCancel={hideConfirmModal}
-                        isVisible={isConfirmModalVisible}
-                        prompt={translate('closeAccountPage.closeAccountPermanentlyDeleteData')}
-                        confirmText={translate('common.yesContinue')}
-                        cancelText={translate('common.cancel')}
-                        shouldDisableConfirmButtonWhenOffline
-                        shouldShowCancelButton
-                    />
-                </View>
-            </FormProvider>
+            <DelegateNoAccessWrapper accessDeniedVariants={[CONST.DELEGATE.DENIED_ACCESS_VARIANTS.DELEGATE]}>
+                <HeaderWithBackButton
+                    title={translate('closeAccountPage.closeAccount')}
+                    onBackButtonPress={() => Navigation.goBack()}
+                />
+                <FormProvider
+                    formID={ONYXKEYS.FORMS.CLOSE_ACCOUNT_FORM}
+                    validate={validate}
+                    onSubmit={showConfirmModal}
+                    submitButtonText={translate('closeAccountPage.closeAccount')}
+                    style={[styles.flexGrow1, styles.mh5]}
+                    isSubmitActionDangerous
+                >
+                    <View style={[styles.flexGrow1]}>
+                        <Text>{translate('closeAccountPage.reasonForLeavingPrompt')}</Text>
+                        <InputWrapper
+                            InputComponent={TextInput}
+                            inputID={INPUT_IDS.REASON_FOR_LEAVING}
+                            autoGrowHeight
+                            maxAutoGrowHeight={variables.textInputAutoGrowMaxHeight}
+                            label={translate('closeAccountPage.enterMessageHere')}
+                            aria-label={translate('closeAccountPage.enterMessageHere')}
+                            role={CONST.ROLE.PRESENTATION}
+                            containerStyles={[styles.mt5]}
+                        />
+                        <Text style={[styles.mt5]}>
+                            {translate('closeAccountPage.enterDefaultContactToConfirm')} <Text style={[styles.textStrong]}>{userEmailOrPhone}</Text>
+                        </Text>
+                        <InputWrapper
+                            InputComponent={TextInput}
+                            inputID={INPUT_IDS.PHONE_OR_EMAIL}
+                            autoCapitalize="none"
+                            label={translate('closeAccountPage.enterDefaultContact')}
+                            aria-label={translate('closeAccountPage.enterDefaultContact')}
+                            role={CONST.ROLE.PRESENTATION}
+                            containerStyles={[styles.mt5]}
+                            autoCorrect={false}
+                            inputMode={userEmailOrPhone && Str.isValidEmail(userEmailOrPhone) ? CONST.INPUT_MODE.EMAIL : CONST.INPUT_MODE.TEXT}
+                        />
+                        <ConfirmModal
+                            danger
+                            title={translate('closeAccountPage.closeAccountWarning')}
+                            onConfirm={onConfirm}
+                            onCancel={hideConfirmModal}
+                            isVisible={isConfirmModalVisible}
+                            prompt={translate('closeAccountPage.closeAccountPermanentlyDeleteData')}
+                            confirmText={translate('common.yesContinue')}
+                            cancelText={translate('common.cancel')}
+                            shouldDisableConfirmButtonWhenOffline
+                            shouldShowCancelButton
+                        />
+                    </View>
+                </FormProvider>
+            </DelegateNoAccessWrapper>
         </ScreenWrapper>
     );
 }
diff --git a/src/pages/settings/Security/TwoFactorAuth/TwoFactorAuthPage.tsx b/src/pages/settings/Security/TwoFactorAuth/TwoFactorAuthPage.tsx
index 99f57a5a5a9d..2d11e574ab9e 100644
--- a/src/pages/settings/Security/TwoFactorAuth/TwoFactorAuthPage.tsx
+++ b/src/pages/settings/Security/TwoFactorAuth/TwoFactorAuthPage.tsx
@@ -1,11 +1,15 @@
 import React from 'react';
 import AnimatedStepProvider from '@components/AnimatedStep/AnimatedStepProvider';
+import DelegateNoAccessWrapper from '@components/DelegateNoAccessWrapper';
+import CONST from '@src/CONST';
 import TwoFactorAuthSteps from './TwoFactorAuthSteps';
 
 function TwoFactorAuthPage() {
     return (
         <AnimatedStepProvider>
-            <TwoFactorAuthSteps />
+            <DelegateNoAccessWrapper accessDeniedVariants={[CONST.DELEGATE.DENIED_ACCESS_VARIANTS.DELEGATE]}>
+                <TwoFactorAuthSteps />
+            </DelegateNoAccessWrapper>
         </AnimatedStepProvider>
     );
 }
diff --git a/src/pages/settings/Subscription/PaymentCard/index.tsx b/src/pages/settings/Subscription/PaymentCard/index.tsx
index da977f170a9b..61178d8f5cad 100644
--- a/src/pages/settings/Subscription/PaymentCard/index.tsx
+++ b/src/pages/settings/Subscription/PaymentCard/index.tsx
@@ -2,6 +2,7 @@ import React, {useCallback, useEffect} from 'react';
 import {View} from 'react-native';
 import {useOnyx} from 'react-native-onyx';
 import PaymentCardForm from '@components/AddPaymentCard/PaymentCardForm';
+import DelegateNoAccessWrapper from '@components/DelegateNoAccessWrapper';
 import type {FormOnyxValues} from '@components/Form/types';
 import HeaderWithBackButton from '@components/HeaderWithBackButton';
 import * as Illustrations from '@components/Icon/Illustrations';
@@ -73,46 +74,48 @@ function AddPaymentCard() {
 
     return (
         <ScreenWrapper testID={AddPaymentCard.displayName}>
-            <HeaderWithBackButton title={translate('subscription.paymentCard.addPaymentCard')} />
-            <View style={styles.containerWithSpaceBetween}>
-                <PaymentCardForm
-                    shouldShowPaymentCardForm
-                    addPaymentCard={addPaymentCard}
-                    showAcceptTerms
-                    showCurrencyField
-                    currencySelectorRoute={ROUTES.SETTINGS_SUBSCRIPTION_CHANGE_PAYMENT_CURRENCY}
-                    submitButtonText={translate('subscription.paymentCard.addPaymentCard')}
-                    headerContent={<Text style={[styles.textHeadline, styles.mt3, styles.mb2, styles.ph5]}>{translate('subscription.paymentCard.enterPaymentCardDetails')}</Text>}
-                    footerContent={
-                        <>
-                            <Section
-                                icon={Illustrations.ShieldYellow}
-                                cardLayout={CARD_LAYOUT.ICON_ON_LEFT}
-                                iconContainerStyles={styles.mr4}
-                                containerStyles={[styles.mh0, styles.mt5]}
-                                renderTitle={() => (
-                                    <Text style={[styles.mutedTextLabel]}>
-                                        {translate('subscription.paymentCard.security')}{' '}
-                                        <TextLink
-                                            style={[styles.mutedTextLabel, styles.link]}
-                                            href={CONST.TERMS_URL}
-                                        >
-                                            {translate('subscription.paymentCard.learnMoreAboutSecurity')}
-                                        </TextLink>
-                                    </Text>
-                                )}
-                            />
-                            <Text style={[styles.textMicroSupporting, styles.mt3, styles.textAlignCenter, styles.mr5, styles.ml5]}>
-                                {translate(`subscription.yourPlan.${isCollect ? 'collect' : 'control'}.${isAnnual ? 'priceAnnual' : 'pricePayPerUse'}`, {
-                                    lower: convertToShortDisplayString(subscriptionPrice, preferredCurrency),
-                                    upper: convertToShortDisplayString(subscriptionPrice * CONST.SUBSCRIPTION_PRICE_FACTOR, preferredCurrency),
-                                })}
-                            </Text>
-                        </>
-                    }
-                />
-            </View>
-            <CardAuthenticationModal headerTitle={translate('subscription.authenticatePaymentCard')} />
+            <DelegateNoAccessWrapper accessDeniedVariants={[CONST.DELEGATE.DENIED_ACCESS_VARIANTS.DELEGATE]}>
+                <HeaderWithBackButton title={translate('subscription.paymentCard.addPaymentCard')} />
+                <View style={styles.containerWithSpaceBetween}>
+                    <PaymentCardForm
+                        shouldShowPaymentCardForm
+                        addPaymentCard={addPaymentCard}
+                        showAcceptTerms
+                        showCurrencyField
+                        currencySelectorRoute={ROUTES.SETTINGS_SUBSCRIPTION_CHANGE_PAYMENT_CURRENCY}
+                        submitButtonText={translate('subscription.paymentCard.addPaymentCard')}
+                        headerContent={<Text style={[styles.textHeadline, styles.mt3, styles.mb2, styles.ph5]}>{translate('subscription.paymentCard.enterPaymentCardDetails')}</Text>}
+                        footerContent={
+                            <>
+                                <Section
+                                    icon={Illustrations.ShieldYellow}
+                                    cardLayout={CARD_LAYOUT.ICON_ON_LEFT}
+                                    iconContainerStyles={styles.mr4}
+                                    containerStyles={[styles.mh0, styles.mt5]}
+                                    renderTitle={() => (
+                                        <Text style={[styles.mutedTextLabel]}>
+                                            {translate('subscription.paymentCard.security')}{' '}
+                                            <TextLink
+                                                style={[styles.mutedTextLabel, styles.link]}
+                                                href={CONST.TERMS_URL}
+                                            >
+                                                {translate('subscription.paymentCard.learnMoreAboutSecurity')}
+                                            </TextLink>
+                                        </Text>
+                                    )}
+                                />
+                                <Text style={[styles.textMicroSupporting, styles.mt3, styles.textAlignCenter, styles.mr5, styles.ml5]}>
+                                    {translate(`subscription.yourPlan.${isCollect ? 'collect' : 'control'}.${isAnnual ? 'priceAnnual' : 'pricePayPerUse'}`, {
+                                        lower: convertToShortDisplayString(subscriptionPrice, preferredCurrency),
+                                        upper: convertToShortDisplayString(subscriptionPrice * CONST.SUBSCRIPTION_PRICE_FACTOR, preferredCurrency),
+                                    })}
+                                </Text>
+                            </>
+                        }
+                    />
+                </View>
+                <CardAuthenticationModal headerTitle={translate('subscription.authenticatePaymentCard')} />
+            </DelegateNoAccessWrapper>
         </ScreenWrapper>
     );
 }
diff --git a/src/pages/settings/Subscription/RequestEarlyCancellationPage/index.tsx b/src/pages/settings/Subscription/RequestEarlyCancellationPage/index.tsx
index d74e126ff94e..561f05b5167e 100644
--- a/src/pages/settings/Subscription/RequestEarlyCancellationPage/index.tsx
+++ b/src/pages/settings/Subscription/RequestEarlyCancellationPage/index.tsx
@@ -2,6 +2,7 @@ import type {ReactNode} from 'react';
 import React, {useMemo, useState} from 'react';
 import {View} from 'react-native';
 import Button from '@components/Button';
+import DelegateNoAccessWrapper from '@components/DelegateNoAccessWrapper';
 import FeedbackSurvey from '@components/FeedbackSurvey';
 import FixedFooter from '@components/FixedFooter';
 import HeaderWithBackButton from '@components/HeaderWithBackButton';
@@ -127,11 +128,13 @@ function RequestEarlyCancellationPage() {
             shouldEnablePickerAvoiding={false}
             shouldEnableMaxHeight
         >
-            <HeaderWithBackButton
-                title={translate('subscription.requestEarlyCancellation.title')}
-                onBackButtonPress={Navigation.goBack}
-            />
-            <ScrollView contentContainerStyle={[styles.flexGrow1, styles.pt3]}>{screenContent}</ScrollView>
+            <DelegateNoAccessWrapper accessDeniedVariants={[CONST.DELEGATE.DENIED_ACCESS_VARIANTS.DELEGATE]}>
+                <HeaderWithBackButton
+                    title={translate('subscription.requestEarlyCancellation.title')}
+                    onBackButtonPress={Navigation.goBack}
+                />
+                <ScrollView contentContainerStyle={[styles.flexGrow1, styles.pt3]}>{screenContent}</ScrollView>
+            </DelegateNoAccessWrapper>
         </ScreenWrapper>
     );
 }

From 08e7be360321edb56dfdf682940428c723160574 Mon Sep 17 00:00:00 2001
From: Sachin Chavda <sachin.chavda.1024@gmail.com>
Date: Wed, 20 Nov 2024 17:11:07 +0530
Subject: [PATCH 20/31] Wrapper Use Guidelines

---
 src/components/DelegateNoAccessWrapper.tsx | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/src/components/DelegateNoAccessWrapper.tsx b/src/components/DelegateNoAccessWrapper.tsx
index 6761bc0872c9..69b09403fb42 100644
--- a/src/components/DelegateNoAccessWrapper.tsx
+++ b/src/components/DelegateNoAccessWrapper.tsx
@@ -11,7 +11,9 @@ import callOrReturn from '@src/types/utils/callOrReturn';
 import FullPageNotFoundView from './BlockingViews/FullPageNotFoundView';
 
 const DENIED_ACCESS_VARIANTS = {
+    // To Restrict All Delegates From Accessing The Page.
     [CONST.DELEGATE.DENIED_ACCESS_VARIANTS.DELEGATE]: (account: OnyxEntry<Account>) => isDelegate(account),
+    // To Restrict Only Limited Access Delegates From Accessing The Page.
     [CONST.DELEGATE.DENIED_ACCESS_VARIANTS.SUBMITTER]: (account: OnyxEntry<Account>) => isSubmitter(account),
 } as const satisfies Record<string, (account: OnyxEntry<Account>) => boolean>;
 

From 4d1b7e1ad3743fb7cfc6176827ae789c82c169c8 Mon Sep 17 00:00:00 2001
From: Sachin Chavda <sachin.chavda.1024@gmail.com>
Date: Wed, 20 Nov 2024 17:20:46 +0530
Subject: [PATCH 21/31] Cleanup and lint

---
 src/components/DelegateNoAccessWrapper.tsx    |  2 +-
 src/pages/ReportDetailsPage.tsx               |  2 +-
 .../UpdateDelegateMagicCodePage.tsx           | 28 +++++++++----------
 3 files changed, 15 insertions(+), 17 deletions(-)

diff --git a/src/components/DelegateNoAccessWrapper.tsx b/src/components/DelegateNoAccessWrapper.tsx
index 69b09403fb42..77993716aa29 100644
--- a/src/components/DelegateNoAccessWrapper.tsx
+++ b/src/components/DelegateNoAccessWrapper.tsx
@@ -41,9 +41,9 @@ function DelegateNoAccessWrapper({accessDeniedVariants = [], shouldForceFullScre
         const accessDeniedFunction = DENIED_ACCESS_VARIANTS[variant];
         return acc || accessDeniedFunction(account);
     }, false);
+    const {shouldUseNarrowLayout} = useResponsiveLayout();
 
     if (isPageAccessDenied) {
-        const {shouldUseNarrowLayout} = useResponsiveLayout();
         return (
             <FullPageNotFoundView
                 shouldShow
diff --git a/src/pages/ReportDetailsPage.tsx b/src/pages/ReportDetailsPage.tsx
index 938aa8eb0088..1bc6b79741d2 100644
--- a/src/pages/ReportDetailsPage.tsx
+++ b/src/pages/ReportDetailsPage.tsx
@@ -256,7 +256,7 @@ function ReportDetailsPage({policies, report, route}: ReportDetailsPageProps) {
 
     const [moneyRequestReportActions] = useOnyx(`${ONYXKEYS.COLLECTION.REPORT_ACTIONS}${moneyRequestReport?.reportID}`);
     const isMoneyRequestExported = ReportUtils.isExported(moneyRequestReportActions);
-    const {isDelegateAccessRestricted, delegatorEmail} = useDelegateUserDetails();
+    const {isDelegateAccessRestricted} = useDelegateUserDetails();
     const [isNoDelegateAccessMenuVisible, setIsNoDelegateAccessMenuVisible] = useState(false);
 
     const unapproveExpenseReportOrShowModal = useCallback(() => {
diff --git a/src/pages/settings/Security/AddDelegate/UpdateDelegateRole/UpdateDelegateMagicCodePage.tsx b/src/pages/settings/Security/AddDelegate/UpdateDelegateRole/UpdateDelegateMagicCodePage.tsx
index 5c07981ee24e..60a15354a0ed 100644
--- a/src/pages/settings/Security/AddDelegate/UpdateDelegateRole/UpdateDelegateMagicCodePage.tsx
+++ b/src/pages/settings/Security/AddDelegate/UpdateDelegateRole/UpdateDelegateMagicCodePage.tsx
@@ -52,21 +52,19 @@ function UpdateDelegateMagicCodePage({route}: UpdateDelegateMagicCodePageProps)
             offlineIndicatorStyle={styles.mtAuto}
         >
             {({safeAreaPaddingBottomStyle}) => (
-                <>
-                    <DelegateNoAccessWrapper accessDeniedVariants={[CONST.DELEGATE.DENIED_ACCESS_VARIANTS.DELEGATE]}>
-                        <HeaderWithBackButton
-                            title={translate('delegate.makeSureItIsYou')}
-                            onBackButtonPress={onBackButtonPress}
-                        />
-                        <Text style={[styles.mb3, styles.ph5]}>{translate('delegate.enterMagicCodeUpdate', {contactMethod: account?.primaryLogin ?? ''})}</Text>
-                        <ValidateCodeForm
-                            ref={validateCodeFormRef}
-                            delegate={login}
-                            role={role}
-                            wrapperStyle={safeAreaPaddingBottomStyle}
-                        />
-                    </DelegateNoAccessWrapper>
-                </>
+                <DelegateNoAccessWrapper accessDeniedVariants={[CONST.DELEGATE.DENIED_ACCESS_VARIANTS.DELEGATE]}>
+                    <HeaderWithBackButton
+                        title={translate('delegate.makeSureItIsYou')}
+                        onBackButtonPress={onBackButtonPress}
+                    />
+                    <Text style={[styles.mb3, styles.ph5]}>{translate('delegate.enterMagicCodeUpdate', {contactMethod: account?.primaryLogin ?? ''})}</Text>
+                    <ValidateCodeForm
+                        ref={validateCodeFormRef}
+                        delegate={login}
+                        role={role}
+                        wrapperStyle={safeAreaPaddingBottomStyle}
+                    />
+                </DelegateNoAccessWrapper>
             )}
         </ScreenWrapper>
     );

From e68f3881d3c9afc42147f8e94c85a5ec952a2f04 Mon Sep 17 00:00:00 2001
From: Sachin Chavda <sachin.chavda.1024@gmail.com>
Date: Sat, 23 Nov 2024 06:35:53 +0530
Subject: [PATCH 22/31] Cleanup

---
 src/pages/settings/Wallet/WalletPage/WalletPage.tsx | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/src/pages/settings/Wallet/WalletPage/WalletPage.tsx b/src/pages/settings/Wallet/WalletPage/WalletPage.tsx
index ea3da6c21021..9e10578ae4a9 100644
--- a/src/pages/settings/Wallet/WalletPage/WalletPage.tsx
+++ b/src/pages/settings/Wallet/WalletPage/WalletPage.tsx
@@ -3,7 +3,7 @@ import isEmpty from 'lodash/isEmpty';
 import type {ForwardedRef, RefObject} from 'react';
 import React, {useCallback, useEffect, useLayoutEffect, useRef, useState} from 'react';
 import type {GestureResponderEvent} from 'react-native';
-import {ActivityIndicator, Dimensions, InteractionManager, View} from 'react-native';
+import {ActivityIndicator, Dimensions, View} from 'react-native';
 import {useOnyx} from 'react-native-onyx';
 import AddPaymentMethodMenu from '@components/AddPaymentMethodMenu';
 import ConfirmModal from '@components/ConfirmModal';

From a7d8cb3bf9eb2c444c672b37698b05d7cfb0ae3d Mon Sep 17 00:00:00 2001
From: Sachin Chavda <sachin.chavda.1024@gmail.com>
Date: Sat, 23 Nov 2024 07:06:32 +0530
Subject: [PATCH 23/31] Revert accidental chages to ios/Podfile.lock

---
 ios/Podfile.lock | 8 ++++----
 1 file changed, 4 insertions(+), 4 deletions(-)

diff --git a/ios/Podfile.lock b/ios/Podfile.lock
index 01aefab63378..5ea5b19896e4 100644
--- a/ios/Podfile.lock
+++ b/ios/Podfile.lock
@@ -2661,7 +2661,7 @@ PODS:
     - RNSound/Core (= 0.11.2)
   - RNSound/Core (0.11.2):
     - React-Core
-  - RNSVG (15.6.0):
+  - RNSVG (15.9.0):
     - DoubleConversion
     - glog
     - hermes-engine
@@ -2681,9 +2681,9 @@ PODS:
     - ReactCodegen
     - ReactCommon/turbomodule/bridging
     - ReactCommon/turbomodule/core
-    - RNSVG/common (= 15.6.0)
+    - RNSVG/common (= 15.9.0)
     - Yoga
-  - RNSVG/common (15.6.0):
+  - RNSVG/common (15.9.0):
     - DoubleConversion
     - glog
     - hermes-engine
@@ -3295,7 +3295,7 @@ SPEC CHECKSUMS:
   RNScreens: de6e57426ba0e6cbc3fb5b4f496e7f08cb2773c2
   RNShare: bd4fe9b95d1ee89a200778cc0753ebe650154bb0
   RNSound: 6c156f925295bdc83e8e422e7d8b38d33bc71852
-  RNSVG: 1079f96b39a35753d481a20e30603fd6fc4f6fa9
+  RNSVG: b2fbe96b2bb3887752f8abc1f495953847e90384
   SDWebImage: 066c47b573f408f18caa467d71deace7c0f8280d
   SDWebImageAVIFCoder: 00310d246aab3232ce77f1d8f0076f8c4b021d90
   SDWebImageSVGCoder: 15a300a97ec1c8ac958f009c02220ac0402e936c

From 43c3e6c3ca203d41ee6761cd96c1b07e1c3d59fb Mon Sep 17 00:00:00 2001
From: Sachin Chavda <sachin.chavda.1024@gmail.com>
Date: Tue, 26 Nov 2024 01:29:50 +0530
Subject: [PATCH 24/31] Show Not So Fast.. modal on clicking private profile
 credentials

---
 src/components/AddressForm.tsx                |   6 +-
 src/pages/AddressPage.tsx                     |  63 ++++-------
 .../Profile/Contacts/NewContactMethodPage.tsx |  18 +--
 .../PersonalDetails/DateOfBirthPage.tsx       |  76 +++++--------
 .../Profile/PersonalDetails/LegalNamePage.tsx | 105 ++++++++----------
 .../PersonalDetails/PhoneNumberPage.tsx       | 100 +++++++----------
 src/pages/settings/Profile/ProfilePage.tsx    |  14 ++-
 .../Subscription/SubscriptionSize/index.tsx   |  22 ++--
 .../SubscriptionSize/substeps/Size.tsx        |  24 +---
 9 files changed, 178 insertions(+), 250 deletions(-)

diff --git a/src/components/AddressForm.tsx b/src/components/AddressForm.tsx
index 709770617fdc..4470481d2be6 100644
--- a/src/components/AddressForm.tsx
+++ b/src/components/AddressForm.tsx
@@ -56,9 +56,6 @@ type AddressFormProps = {
 
     /** A unique Onyx key identifying the form */
     formID: typeof ONYXKEYS.FORMS.GET_PHYSICAL_CARD_FORM | typeof ONYXKEYS.FORMS.HOME_ADDRESS_FORM;
-
-    /** Whether or not validation should be skipped */
-    skipValidation?: boolean;
 };
 
 function AddressForm({
@@ -73,7 +70,6 @@ function AddressForm({
     street2 = '',
     submitButtonText = '',
     zip = '',
-    skipValidation = false,
 }: AddressFormProps) {
     const styles = useThemeStyles();
     const {translate} = useLocalize();
@@ -143,7 +139,7 @@ function AddressForm({
         <FormProvider
             style={[styles.flexGrow1, styles.mh5]}
             formID={formID}
-            validate={skipValidation ? undefined : validator}
+            validate={validator}
             onSubmit={onSubmit}
             submitButtonText={submitButtonText}
             enabledWhenOffline
diff --git a/src/pages/AddressPage.tsx b/src/pages/AddressPage.tsx
index ee04b2d6bee7..f2b7497b2528 100644
--- a/src/pages/AddressPage.tsx
+++ b/src/pages/AddressPage.tsx
@@ -3,6 +3,7 @@ import type {OnyxEntry} from 'react-native-onyx';
 import {useOnyx} from 'react-native-onyx';
 import AddressForm from '@components/AddressForm';
 import DelegateNoAccessModal from '@components/DelegateNoAccessModal';
+import DelegateNoAccessWrapper from '@components/DelegateNoAccessWrapper';
 import FullscreenLoadingIndicator from '@components/FullscreenLoadingIndicator';
 import HeaderWithBackButton from '@components/HeaderWithBackButton';
 import ScreenWrapper from '@components/ScreenWrapper';
@@ -12,6 +13,7 @@ import Navigation from '@libs/Navigation/Navigation';
 import type {BackToParams} from '@libs/Navigation/types';
 import type {FormOnyxValues} from '@src/components/Form/types';
 import type {Country} from '@src/CONST';
+import CONST from '@src/CONST';
 import ONYXKEYS from '@src/ONYXKEYS';
 import INPUT_IDS from '@src/types/form/HomeAddressForm';
 import type {Address} from '@src/types/onyx/PrivatePersonalDetails';
@@ -39,20 +41,6 @@ function AddressPage({title, address, updateAddress, isLoadingApp = true, backTo
     const [city, setCity] = useState(address?.city);
     const [zipcode, setZipcode] = useState(address?.zip);
 
-    const [isActingAsDelegate] = useOnyx(ONYXKEYS.ACCOUNT, {selector: (account) => !!account?.delegatedAccess?.delegate});
-    const [isNoDelegateAccessMenuVisible, setIsNoDelegateAccessMenuVisible] = useState(false);
-
-    // For delegates, modifying legal address is a restricted action.
-    // So, on pressing submit, skip validation and show delegateNoAccessModal
-    const skipValidation = isActingAsDelegate;
-    const handleSubmit = (values: FormOnyxValues<typeof ONYXKEYS.FORMS.HOME_ADDRESS_FORM>) => {
-        if (isActingAsDelegate) {
-            setIsNoDelegateAccessMenuVisible(true);
-            return;
-        }
-        updateAddress(values);
-    };
-
     useEffect(() => {
         if (!address) {
             return;
@@ -97,32 +85,29 @@ function AddressPage({title, address, updateAddress, isLoadingApp = true, backTo
             includeSafeAreaPaddingBottom={false}
             testID={AddressPage.displayName}
         >
-            <HeaderWithBackButton
-                title={title}
-                shouldShowBackButton
-                onBackButtonPress={() => Navigation.goBack(backTo)}
-            />
-            {isLoadingApp ? (
-                <FullscreenLoadingIndicator style={[styles.flex1, styles.pRelative]} />
-            ) : (
-                <AddressForm
-                    formID={ONYXKEYS.FORMS.HOME_ADDRESS_FORM}
-                    onSubmit={handleSubmit}
-                    submitButtonText={translate('common.save')}
-                    city={city}
-                    country={currentCountry}
-                    onAddressChanged={handleAddressChange}
-                    state={state}
-                    street1={street1}
-                    street2={street2}
-                    zip={zipcode}
-                    skipValidation={skipValidation}
+            <DelegateNoAccessWrapper accessDeniedVariants={[CONST.DELEGATE.DENIED_ACCESS_VARIANTS.DELEGATE]}>
+                <HeaderWithBackButton
+                    title={title}
+                    shouldShowBackButton
+                    onBackButtonPress={() => Navigation.goBack(backTo)}
                 />
-            )}
-            <DelegateNoAccessModal
-                isNoDelegateAccessMenuVisible={isNoDelegateAccessMenuVisible}
-                onClose={() => setIsNoDelegateAccessMenuVisible(false)}
-            />
+                {isLoadingApp ? (
+                    <FullscreenLoadingIndicator style={[styles.flex1, styles.pRelative]} />
+                ) : (
+                    <AddressForm
+                        formID={ONYXKEYS.FORMS.HOME_ADDRESS_FORM}
+                        onSubmit={updateAddress}
+                        submitButtonText={translate('common.save')}
+                        city={city}
+                        country={currentCountry}
+                        onAddressChanged={handleAddressChange}
+                        state={state}
+                        street1={street1}
+                        street2={street2}
+                        zip={zipcode}
+                    />
+                )}
+            </DelegateNoAccessWrapper>
         </ScreenWrapper>
     );
 }
diff --git a/src/pages/settings/Profile/Contacts/NewContactMethodPage.tsx b/src/pages/settings/Profile/Contacts/NewContactMethodPage.tsx
index 7f4a99d197a8..ef0348273db6 100644
--- a/src/pages/settings/Profile/Contacts/NewContactMethodPage.tsx
+++ b/src/pages/settings/Profile/Contacts/NewContactMethodPage.tsx
@@ -108,13 +108,13 @@ function NewContactMethodPage({route}: NewContactMethodPageProps) {
     }, [navigateBackTo]);
 
     return (
-        <DelegateNoAccessWrapper accessDeniedVariants={[CONST.DELEGATE.DENIED_ACCESS_VARIANTS.DELEGATE]}>
-            <ScreenWrapper
-                onEntryTransitionEnd={() => loginInputRef.current?.focus()}
-                includeSafeAreaPaddingBottom={false}
-                shouldEnableMaxHeight
-                testID={NewContactMethodPage.displayName}
-            >
+        <ScreenWrapper
+            onEntryTransitionEnd={() => loginInputRef.current?.focus()}
+            includeSafeAreaPaddingBottom={false}
+            shouldEnableMaxHeight
+            testID={NewContactMethodPage.displayName}
+        >
+            <DelegateNoAccessWrapper accessDeniedVariants={[CONST.DELEGATE.DENIED_ACCESS_VARIANTS.DELEGATE]}>
                 <HeaderWithBackButton
                     title={translate('contacts.newContactMethod')}
                     onBackButtonPress={onBackButtonPress}
@@ -171,8 +171,8 @@ function NewContactMethodPage({route}: NewContactMethodPageProps) {
                     sendValidateCode={() => User.requestValidateCodeAction()}
                     descriptionPrimary={translate('contacts.enterMagicCode', {contactMethod})}
                 />
-            </ScreenWrapper>
-        </DelegateNoAccessWrapper>
+            </DelegateNoAccessWrapper>
+        </ScreenWrapper>
     );
 }
 
diff --git a/src/pages/settings/Profile/PersonalDetails/DateOfBirthPage.tsx b/src/pages/settings/Profile/PersonalDetails/DateOfBirthPage.tsx
index 950a5f826991..7e462ca60153 100644
--- a/src/pages/settings/Profile/PersonalDetails/DateOfBirthPage.tsx
+++ b/src/pages/settings/Profile/PersonalDetails/DateOfBirthPage.tsx
@@ -1,8 +1,8 @@
 import {subYears} from 'date-fns';
-import React, {useCallback, useState} from 'react';
+import React, {useCallback} from 'react';
 import {useOnyx} from 'react-native-onyx';
 import DatePicker from '@components/DatePicker';
-import DelegateNoAccessModal from '@components/DelegateNoAccessModal';
+import DelegateNoAccessWrapper from '@components/DelegateNoAccessWrapper';
 import FormProvider from '@components/Form/FormProvider';
 import InputWrapper from '@components/Form/InputWrapper';
 import type {FormOnyxValues} from '@components/Form/types';
@@ -17,17 +17,12 @@ import * as PersonalDetails from '@userActions/PersonalDetails';
 import CONST from '@src/CONST';
 import ONYXKEYS from '@src/ONYXKEYS';
 import INPUT_IDS from '@src/types/form/DateOfBirthForm';
-import type {DateOfBirthForm} from '@src/types/form/DateOfBirthForm';
 
 function DateOfBirthPage() {
     const [privatePersonalDetails] = useOnyx(ONYXKEYS.PRIVATE_PERSONAL_DETAILS);
     const [isLoadingApp] = useOnyx(ONYXKEYS.IS_LOADING_APP, {initialValue: true});
     const {translate} = useLocalize();
     const styles = useThemeStyles();
-    const [isActingAsDelegate] = useOnyx(ONYXKEYS.ACCOUNT, {selector: (account) => !!account?.delegatedAccess?.delegate});
-
-    const [isNoDelegateAccessMenuVisible, setIsNoDelegateAccessMenuVisible] = useState(false);
-
     /**
      * @returns An object containing the errors for each inputID
      */
@@ -46,51 +41,38 @@ function DateOfBirthPage() {
         return errors;
     }, []);
 
-    // For delegates, modifying legal DOB is a restricted action.
-    // So, on pressing submit, skip validation and show delegateNoAccessModal
-    const skipValidation = isActingAsDelegate;
-    const handleSubmit = (DOB: DateOfBirthForm) => {
-        if (isActingAsDelegate) {
-            setIsNoDelegateAccessMenuVisible(true);
-            return;
-        }
-        PersonalDetails.updateDateOfBirth(DOB);
-    };
-
     return (
         <ScreenWrapper
             includeSafeAreaPaddingBottom={false}
             testID={DateOfBirthPage.displayName}
         >
-            <HeaderWithBackButton
-                title={translate('common.dob')}
-                onBackButtonPress={() => Navigation.goBack()}
-            />
-            {isLoadingApp ? (
-                <FullscreenLoadingIndicator style={[styles.flex1, styles.pRelative]} />
-            ) : (
-                <FormProvider
-                    style={[styles.flexGrow1, styles.ph5]}
-                    formID={ONYXKEYS.FORMS.DATE_OF_BIRTH_FORM}
-                    validate={skipValidation ? undefined : validate}
-                    onSubmit={handleSubmit}
-                    submitButtonText={translate('common.save')}
-                    enabledWhenOffline
-                >
-                    <InputWrapper
-                        InputComponent={DatePicker}
-                        inputID={INPUT_IDS.DOB}
-                        label={translate('common.date')}
-                        defaultValue={privatePersonalDetails?.dob ?? ''}
-                        minDate={subYears(new Date(), CONST.DATE_BIRTH.MAX_AGE)}
-                        maxDate={subYears(new Date(), CONST.DATE_BIRTH.MIN_AGE)}
-                    />
-                </FormProvider>
-            )}
-            <DelegateNoAccessModal
-                isNoDelegateAccessMenuVisible={isNoDelegateAccessMenuVisible}
-                onClose={() => setIsNoDelegateAccessMenuVisible(false)}
-            />
+            <DelegateNoAccessWrapper accessDeniedVariants={[CONST.DELEGATE.DENIED_ACCESS_VARIANTS.DELEGATE]}>
+                <HeaderWithBackButton
+                    title={translate('common.dob')}
+                    onBackButtonPress={() => Navigation.goBack()}
+                />
+                {isLoadingApp ? (
+                    <FullscreenLoadingIndicator style={[styles.flex1, styles.pRelative]} />
+                ) : (
+                    <FormProvider
+                        style={[styles.flexGrow1, styles.ph5]}
+                        formID={ONYXKEYS.FORMS.DATE_OF_BIRTH_FORM}
+                        validate={validate}
+                        onSubmit={PersonalDetails.updateDateOfBirth}
+                        submitButtonText={translate('common.save')}
+                        enabledWhenOffline
+                    >
+                        <InputWrapper
+                            InputComponent={DatePicker}
+                            inputID={INPUT_IDS.DOB}
+                            label={translate('common.date')}
+                            defaultValue={privatePersonalDetails?.dob ?? ''}
+                            minDate={subYears(new Date(), CONST.DATE_BIRTH.MAX_AGE)}
+                            maxDate={subYears(new Date(), CONST.DATE_BIRTH.MIN_AGE)}
+                        />
+                    </FormProvider>
+                )}
+            </DelegateNoAccessWrapper>
         </ScreenWrapper>
     );
 }
diff --git a/src/pages/settings/Profile/PersonalDetails/LegalNamePage.tsx b/src/pages/settings/Profile/PersonalDetails/LegalNamePage.tsx
index 9c3fd83061c1..0873451eba53 100644
--- a/src/pages/settings/Profile/PersonalDetails/LegalNamePage.tsx
+++ b/src/pages/settings/Profile/PersonalDetails/LegalNamePage.tsx
@@ -1,7 +1,7 @@
-import React, {useCallback, useState} from 'react';
+import React, {useCallback} from 'react';
 import {View} from 'react-native';
 import {useOnyx} from 'react-native-onyx';
-import DelegateNoAccessModal from '@components/DelegateNoAccessModal';
+import DelegateNoAccessWrapper from '@components/DelegateNoAccessWrapper';
 import FormProvider from '@components/Form/FormProvider';
 import InputWrapper from '@components/Form/InputWrapper';
 import type {FormOnyxValues} from '@components/Form/types';
@@ -33,8 +33,6 @@ function LegalNamePage() {
     const {translate} = useLocalize();
     const legalFirstName = privatePersonalDetails?.legalFirstName ?? '';
     const legalLastName = privatePersonalDetails?.legalLastName ?? '';
-    const [isActingAsDelegate] = useOnyx(ONYXKEYS.ACCOUNT, {selector: (account) => !!account?.delegatedAccess?.delegate});
-    const [isNoDelegateAccessMenuVisible, setIsNoDelegateAccessMenuVisible] = useState(false);
 
     const validate = useCallback(
         (values: FormOnyxValues<typeof ONYXKEYS.FORMS.LEGAL_NAME_FORM>) => {
@@ -79,68 +77,55 @@ function LegalNamePage() {
         [translate],
     );
 
-    // For delegates, modifying legal Name is a restricted action.
-    // So, on pressing submit, skip validation and show delegateNoAccessModal
-    const skipValidation = isActingAsDelegate;
-    const handleSubmit = (values: PrivatePersonalDetails) => {
-        if (isActingAsDelegate) {
-            setIsNoDelegateAccessMenuVisible(true);
-            return;
-        }
-        updateLegalName(values);
-    };
-
     return (
         <ScreenWrapper
             includeSafeAreaPaddingBottom={false}
             shouldEnableMaxHeight
             testID={LegalNamePage.displayName}
         >
-            <HeaderWithBackButton
-                title={translate('privatePersonalDetails.legalName')}
-                onBackButtonPress={() => Navigation.goBack()}
-            />
-            {isLoadingApp ? (
-                <FullscreenLoadingIndicator style={[styles.flex1, styles.pRelative]} />
-            ) : (
-                <FormProvider
-                    style={[styles.flexGrow1, styles.ph5]}
-                    formID={ONYXKEYS.FORMS.LEGAL_NAME_FORM}
-                    validate={skipValidation ? undefined : validate}
-                    onSubmit={handleSubmit}
-                    submitButtonText={translate('common.save')}
-                    enabledWhenOffline
-                >
-                    <View style={[styles.mb4]}>
-                        <InputWrapper
-                            InputComponent={TextInput}
-                            inputID={INPUT_IDS.LEGAL_FIRST_NAME}
-                            name="lfname"
-                            label={translate('privatePersonalDetails.legalFirstName')}
-                            aria-label={translate('privatePersonalDetails.legalFirstName')}
-                            role={CONST.ROLE.PRESENTATION}
-                            defaultValue={legalFirstName}
-                            spellCheck={false}
-                        />
-                    </View>
-                    <View>
-                        <InputWrapper
-                            InputComponent={TextInput}
-                            inputID={INPUT_IDS.LEGAL_LAST_NAME}
-                            name="llname"
-                            label={translate('privatePersonalDetails.legalLastName')}
-                            aria-label={translate('privatePersonalDetails.legalLastName')}
-                            role={CONST.ROLE.PRESENTATION}
-                            defaultValue={legalLastName}
-                            spellCheck={false}
-                        />
-                    </View>
-                </FormProvider>
-            )}
-            <DelegateNoAccessModal
-                isNoDelegateAccessMenuVisible={isNoDelegateAccessMenuVisible}
-                onClose={() => setIsNoDelegateAccessMenuVisible(false)}
-            />
+            <DelegateNoAccessWrapper accessDeniedVariants={[CONST.DELEGATE.DENIED_ACCESS_VARIANTS.DELEGATE]}>
+                <HeaderWithBackButton
+                    title={translate('privatePersonalDetails.legalName')}
+                    onBackButtonPress={() => Navigation.goBack()}
+                />
+                {isLoadingApp ? (
+                    <FullscreenLoadingIndicator style={[styles.flex1, styles.pRelative]} />
+                ) : (
+                    <FormProvider
+                        style={[styles.flexGrow1, styles.ph5]}
+                        formID={ONYXKEYS.FORMS.LEGAL_NAME_FORM}
+                        validate={validate}
+                        onSubmit={updateLegalName}
+                        submitButtonText={translate('common.save')}
+                        enabledWhenOffline
+                    >
+                        <View style={[styles.mb4]}>
+                            <InputWrapper
+                                InputComponent={TextInput}
+                                inputID={INPUT_IDS.LEGAL_FIRST_NAME}
+                                name="lfname"
+                                label={translate('privatePersonalDetails.legalFirstName')}
+                                aria-label={translate('privatePersonalDetails.legalFirstName')}
+                                role={CONST.ROLE.PRESENTATION}
+                                defaultValue={legalFirstName}
+                                spellCheck={false}
+                            />
+                        </View>
+                        <View>
+                            <InputWrapper
+                                InputComponent={TextInput}
+                                inputID={INPUT_IDS.LEGAL_LAST_NAME}
+                                name="llname"
+                                label={translate('privatePersonalDetails.legalLastName')}
+                                aria-label={translate('privatePersonalDetails.legalLastName')}
+                                role={CONST.ROLE.PRESENTATION}
+                                defaultValue={legalLastName}
+                                spellCheck={false}
+                            />
+                        </View>
+                    </FormProvider>
+                )}
+            </DelegateNoAccessWrapper>
         </ScreenWrapper>
     );
 }
diff --git a/src/pages/settings/Profile/PersonalDetails/PhoneNumberPage.tsx b/src/pages/settings/Profile/PersonalDetails/PhoneNumberPage.tsx
index b078dd7964dc..add5eaf3dd9f 100644
--- a/src/pages/settings/Profile/PersonalDetails/PhoneNumberPage.tsx
+++ b/src/pages/settings/Profile/PersonalDetails/PhoneNumberPage.tsx
@@ -1,7 +1,7 @@
 import {Str} from 'expensify-common';
-import React, {useCallback, useState} from 'react';
+import React, {useCallback} from 'react';
 import {useOnyx} from 'react-native-onyx';
-import DelegateNoAccessModal from '@components/DelegateNoAccessModal';
+import DelegateNoAccessWrapper from '@components/DelegateNoAccessWrapper';
 import FormProvider from '@components/Form/FormProvider';
 import InputWrapper from '@components/Form/InputWrapper';
 import type {FormInputErrors, FormOnyxValues} from '@components/Form/types';
@@ -33,9 +33,6 @@ function PhoneNumberPage() {
     const validateLoginError = ErrorUtils.getEarliestErrorField(privatePersonalDetails, 'phoneNumber');
     const currenPhoneNumber = privatePersonalDetails?.phoneNumber ?? '';
 
-    const [isActingAsDelegate] = useOnyx(ONYXKEYS.ACCOUNT, {selector: (account) => account?.delegatedAccess?.delegate});
-    const [isNoDelegateAccessMenuVisible, setIsNoDelegateAccessMenuVisible] = useState(false);
-
     const updatePhoneNumber = (values: PrivatePersonalDetails) => {
         // Clear the error when the user tries to submit the form
         if (validateLoginError) {
@@ -71,66 +68,53 @@ function PhoneNumberPage() {
         [translate, validateLoginError],
     );
 
-    // For delegates, modifying Phone Number is a restricted action.
-    // So, on pressing submit, skip validation and show delegateNoAccessModal
-    const skipValidation = isActingAsDelegate;
-    const handleSubmit = (values: PrivatePersonalDetails) => {
-        if (isActingAsDelegate) {
-            setIsNoDelegateAccessMenuVisible(true);
-            return;
-        }
-        updatePhoneNumber(values);
-    };
-
     return (
         <ScreenWrapper
             includeSafeAreaPaddingBottom={false}
             shouldEnableMaxHeight
             testID={PhoneNumberPage.displayName}
         >
-            <HeaderWithBackButton
-                title={translate('common.phoneNumber')}
-                onBackButtonPress={() => Navigation.goBack()}
-            />
-            {isLoadingApp ? (
-                <FullscreenLoadingIndicator style={[styles.flex1, styles.pRelative]} />
-            ) : (
-                <FormProvider
-                    style={[styles.flexGrow1, styles.ph5]}
-                    formID={ONYXKEYS.FORMS.PERSONAL_DETAILS_FORM}
-                    validate={skipValidation ? undefined : validate}
-                    onSubmit={handleSubmit}
-                    submitButtonText={translate('common.save')}
-                    enabledWhenOffline
-                >
-                    <OfflineWithFeedback
-                        errors={validateLoginError}
-                        errorRowStyles={styles.mt2}
-                        onClose={() => PersonalDetails.clearPhoneNumberError()}
+            <DelegateNoAccessWrapper accessDeniedVariants={[CONST.DELEGATE.DENIED_ACCESS_VARIANTS.DELEGATE]}>
+                <HeaderWithBackButton
+                    title={translate('common.phoneNumber')}
+                    onBackButtonPress={() => Navigation.goBack()}
+                />
+                {isLoadingApp ? (
+                    <FullscreenLoadingIndicator style={[styles.flex1, styles.pRelative]} />
+                ) : (
+                    <FormProvider
+                        style={[styles.flexGrow1, styles.ph5]}
+                        formID={ONYXKEYS.FORMS.PERSONAL_DETAILS_FORM}
+                        validate={validate}
+                        onSubmit={updatePhoneNumber}
+                        submitButtonText={translate('common.save')}
+                        enabledWhenOffline
                     >
-                        <InputWrapper
-                            InputComponent={TextInput}
-                            inputID={INPUT_IDS.PHONE_NUMBER}
-                            name="lfname"
-                            label={translate('common.phoneNumber')}
-                            aria-label={translate('common.phoneNumber')}
-                            role={CONST.ROLE.PRESENTATION}
-                            defaultValue={phoneNumber}
-                            spellCheck={false}
-                            onBlur={() => {
-                                if (!validateLoginError) {
-                                    return;
-                                }
-                                PersonalDetails.clearPhoneNumberError();
-                            }}
-                        />
-                    </OfflineWithFeedback>
-                </FormProvider>
-            )}
-            <DelegateNoAccessModal
-                isNoDelegateAccessMenuVisible={isNoDelegateAccessMenuVisible}
-                onClose={() => setIsNoDelegateAccessMenuVisible(false)}
-            />
+                        <OfflineWithFeedback
+                            errors={validateLoginError}
+                            errorRowStyles={styles.mt2}
+                            onClose={() => PersonalDetails.clearPhoneNumberError()}
+                        >
+                            <InputWrapper
+                                InputComponent={TextInput}
+                                inputID={INPUT_IDS.PHONE_NUMBER}
+                                name="lfname"
+                                label={translate('common.phoneNumber')}
+                                aria-label={translate('common.phoneNumber')}
+                                role={CONST.ROLE.PRESENTATION}
+                                defaultValue={phoneNumber}
+                                spellCheck={false}
+                                onBlur={() => {
+                                    if (!validateLoginError) {
+                                        return;
+                                    }
+                                    PersonalDetails.clearPhoneNumberError();
+                                }}
+                            />
+                        </OfflineWithFeedback>
+                    </FormProvider>
+                )}
+            </DelegateNoAccessWrapper>
         </ScreenWrapper>
     );
 }
diff --git a/src/pages/settings/Profile/ProfilePage.tsx b/src/pages/settings/Profile/ProfilePage.tsx
index faa399598d05..fcf1987dbf37 100755
--- a/src/pages/settings/Profile/ProfilePage.tsx
+++ b/src/pages/settings/Profile/ProfilePage.tsx
@@ -1,9 +1,10 @@
-import React from 'react';
+import React, {useState} from 'react';
 import {View} from 'react-native';
 import {useOnyx} from 'react-native-onyx';
 import AvatarSkeleton from '@components/AvatarSkeleton';
 import AvatarWithImagePicker from '@components/AvatarWithImagePicker';
 import Button from '@components/Button';
+import DelegateNoAccessModal from '@components/DelegateNoAccessModal';
 import FullScreenLoadingIndicator from '@components/FullscreenLoadingIndicator';
 import HeaderWithBackButton from '@components/HeaderWithBackButton';
 import * as Expensicons from '@components/Icon/Expensicons';
@@ -56,6 +57,9 @@ function ProfilePage() {
     const privateDetails = privatePersonalDetails ?? {};
     const legalName = `${privateDetails.legalFirstName ?? ''} ${privateDetails.legalLastName ?? ''}`.trim();
 
+    const [isActingAsDelegate] = useOnyx(ONYXKEYS.ACCOUNT, {selector: (account) => !!account?.delegatedAccess?.delegate});
+    const [isNoDelegateAccessMenuVisible, setIsNoDelegateAccessMenuVisible] = useState(false);
+
     const publicOptions = [
         {
             description: translate('displayNamePage.headerTitle'),
@@ -200,7 +204,9 @@ function ProfilePage() {
                                             title={detail.title}
                                             description={detail.description}
                                             wrapperStyle={styles.sectionMenuItemTopDescription}
-                                            onPress={() => Navigation.navigate(detail.pageRoute)}
+                                            onPress={() => {
+                                                isActingAsDelegate ? setIsNoDelegateAccessMenuVisible(true) : Navigation.navigate(detail.pageRoute);
+                                            }}
                                             brickRoadIndicator={detail.brickRoadIndicator}
                                         />
                                     ))}
@@ -210,6 +216,10 @@ function ProfilePage() {
                     </View>
                 </MenuItemGroup>
             </ScrollView>
+            <DelegateNoAccessModal
+                isNoDelegateAccessMenuVisible={isNoDelegateAccessMenuVisible}
+                onClose={() => setIsNoDelegateAccessMenuVisible(false)}
+            />
         </ScreenWrapper>
     );
 }
diff --git a/src/pages/settings/Subscription/SubscriptionSize/index.tsx b/src/pages/settings/Subscription/SubscriptionSize/index.tsx
index 84cd86c60bca..7bfeaa816ff9 100644
--- a/src/pages/settings/Subscription/SubscriptionSize/index.tsx
+++ b/src/pages/settings/Subscription/SubscriptionSize/index.tsx
@@ -1,6 +1,7 @@
 import type {StackScreenProps} from '@react-navigation/stack';
 import React, {useEffect} from 'react';
 import {useOnyx} from 'react-native-onyx';
+import DelegateNoAccessWrapper from '@components/DelegateNoAccessWrapper';
 import HeaderWithBackButton from '@components/HeaderWithBackButton';
 import ScreenWrapper from '@components/ScreenWrapper';
 import useLocalize from '@hooks/useLocalize';
@@ -10,6 +11,7 @@ import Navigation from '@libs/Navigation/Navigation';
 import type {SettingsNavigatorParamList} from '@navigation/types';
 import * as FormActions from '@userActions/FormActions';
 import * as Subscription from '@userActions/Subscription';
+import CONST from '@src/CONST';
 import ONYXKEYS from '@src/ONYXKEYS';
 import type SCREENS from '@src/SCREENS';
 import INPUT_IDS from '@src/types/form/SubscriptionSizeForm';
@@ -58,15 +60,17 @@ function SubscriptionSizePage({route}: SubscriptionSizePageProps) {
             shouldEnableMaxHeight
             shouldShowOfflineIndicatorInWideScreen
         >
-            <HeaderWithBackButton
-                title={translate('subscription.subscriptionSize.title')}
-                onBackButtonPress={onBackButtonPress}
-            />
-            <SubStep
-                isEditing={canChangeSubscriptionSize}
-                onNext={nextScreen}
-                onMove={moveTo}
-            />
+            <DelegateNoAccessWrapper accessDeniedVariants={[CONST.DELEGATE.DENIED_ACCESS_VARIANTS.DELEGATE]}>
+                <HeaderWithBackButton
+                    title={translate('subscription.subscriptionSize.title')}
+                    onBackButtonPress={onBackButtonPress}
+                />
+                <SubStep
+                    isEditing={canChangeSubscriptionSize}
+                    onNext={nextScreen}
+                    onMove={moveTo}
+                />
+            </DelegateNoAccessWrapper>
         </ScreenWrapper>
     );
 }
diff --git a/src/pages/settings/Subscription/SubscriptionSize/substeps/Size.tsx b/src/pages/settings/Subscription/SubscriptionSize/substeps/Size.tsx
index 5ee477c39579..ba589e7827bd 100644
--- a/src/pages/settings/Subscription/SubscriptionSize/substeps/Size.tsx
+++ b/src/pages/settings/Subscription/SubscriptionSize/substeps/Size.tsx
@@ -1,7 +1,6 @@
-import React, {useCallback, useState} from 'react';
+import React, {useCallback} from 'react';
 import {View} from 'react-native';
 import {useOnyx} from 'react-native-onyx';
-import DelegateNoAccessModal from '@components/DelegateNoAccessModal';
 import FormProvider from '@components/Form/FormProvider';
 import InputWrapper from '@components/Form/InputWrapper';
 import type {FormInputErrors, FormOnyxValues} from '@components/Form/types';
@@ -24,8 +23,6 @@ function Size({onNext}: SizeProps) {
     const styles = useThemeStyles();
     const [privateSubscription] = useOnyx(ONYXKEYS.NVP_PRIVATE_SUBSCRIPTION);
     const {inputCallbackRef} = useAutoFocusInput();
-    const [isActingAsDelegate] = useOnyx(ONYXKEYS.ACCOUNT, {selector: (account) => account?.delegatedAccess?.delegate});
-    const [isNoDelegateAccessMenuVisible, setIsNoDelegateAccessMenuVisible] = useState(false);
 
     const updateValuesAndNavigateToNextStep = useStepFormSubmit<typeof ONYXKEYS.FORMS.SUBSCRIPTION_SIZE_FORM>({
         formId: ONYXKEYS.FORMS.SUBSCRIPTION_SIZE_FORM,
@@ -33,17 +30,6 @@ function Size({onNext}: SizeProps) {
         onNext,
         shouldSaveDraft: true,
     });
-    const handleSubmit = (values: FormOnyxValues<typeof ONYXKEYS.FORMS.SUBSCRIPTION_SIZE_FORM>) => {
-        if (isActingAsDelegate) {
-            setIsNoDelegateAccessMenuVisible(true);
-            return;
-        }
-        updateValuesAndNavigateToNextStep(values);
-    };
-
-    // For delegates, modifying subscription size is a restricted action.
-    // So, on pressing submit, skip validation and show delegateNoAccessModal
-    const skipValidation = isActingAsDelegate;
 
     const defaultValues = {
         [INPUT_IDS.SUBSCRIPTION_SIZE]: `${privateSubscription?.userCount ?? ''}`,
@@ -69,8 +55,8 @@ function Size({onNext}: SizeProps) {
         <FormProvider
             formID={ONYXKEYS.FORMS.SUBSCRIPTION_SIZE_FORM}
             submitButtonText={translate('common.next')}
-            onSubmit={handleSubmit}
-            validate={skipValidation ? undefined : validate}
+            onSubmit={updateValuesAndNavigateToNextStep}
+            validate={validate}
             style={[styles.mh5, styles.flexGrow1]}
             enabledWhenOffline
         >
@@ -89,10 +75,6 @@ function Size({onNext}: SizeProps) {
                 <Text style={[styles.formHelp, styles.mt2]}>{translate('subscription.subscriptionSize.eachMonth')}</Text>
                 <Text style={[styles.formHelp, styles.mt2]}>{translate('subscription.subscriptionSize.note')}</Text>
             </View>
-            <DelegateNoAccessModal
-                isNoDelegateAccessMenuVisible={isNoDelegateAccessMenuVisible}
-                onClose={() => setIsNoDelegateAccessMenuVisible(false)}
-            />
         </FormProvider>
     );
 }

From 79792d589448ac431c1841d0c56a501421e6ea34 Mon Sep 17 00:00:00 2001
From: Sachin Chavda <sachin.chavda.1024@gmail.com>
Date: Tue, 26 Nov 2024 02:05:46 +0530
Subject: [PATCH 25/31] lint and some cleanup

---
 src/components/Form/FormProvider.tsx                |  2 +-
 src/pages/settings/ExitSurvey/ExitSurveyOffline.tsx |  4 ----
 src/pages/settings/Profile/ProfilePage.tsx          | 12 +++++-------
 3 files changed, 6 insertions(+), 12 deletions(-)

diff --git a/src/components/Form/FormProvider.tsx b/src/components/Form/FormProvider.tsx
index 13a0ae3e533d..5c5c28b82fb9 100644
--- a/src/components/Form/FormProvider.tsx
+++ b/src/components/Form/FormProvider.tsx
@@ -45,7 +45,7 @@ type FormProviderProps<TFormID extends OnyxFormKey = OnyxFormKey> = FormProps<TF
     children: ((props: {inputValues: FormOnyxValues<TFormID>}) => ReactNode) | ReactNode;
 
     /** Callback to validate the form */
-    validate?: (values: FormOnyxValues<TFormID>) => FormInputErrors<TFormID> | undefined;
+    validate?: (values: FormOnyxValues<TFormID>) => FormInputErrors<TFormID>;
 
     /** Should validate function be called when input loose focus */
     shouldValidateOnBlur?: boolean;
diff --git a/src/pages/settings/ExitSurvey/ExitSurveyOffline.tsx b/src/pages/settings/ExitSurvey/ExitSurveyOffline.tsx
index c0e4b627b2a4..32baef58ba45 100644
--- a/src/pages/settings/ExitSurvey/ExitSurveyOffline.tsx
+++ b/src/pages/settings/ExitSurvey/ExitSurveyOffline.tsx
@@ -1,19 +1,16 @@
 import React, {memo} from 'react';
 import {View} from 'react-native';
-import DelegateNoAccessWrapper from '@components/DelegateNoAccessWrapper';
 import Icon from '@components/Icon';
 import {ToddBehindCloud} from '@components/Icon/Illustrations';
 import Text from '@components/Text';
 import useLocalize from '@hooks/useLocalize';
 import useThemeStyles from '@hooks/useThemeStyles';
 import variables from '@styles/variables';
-import CONST from '@src/CONST';
 
 function ExitSurveyOffline() {
     const {translate} = useLocalize();
     const styles = useThemeStyles();
     return (
-        <DelegateNoAccessWrapper accessDeniedVariants={[CONST.DELEGATE.DENIED_ACCESS_VARIANTS.DELEGATE]}>
             <View style={[styles.flex1, styles.justifyContentCenter, styles.alignItemsCenter]}>
                 <Icon
                     width={variables.modalTopIconWidth}
@@ -23,7 +20,6 @@ function ExitSurveyOffline() {
                 <Text style={[styles.headerAnonymousFooter, styles.textAlignCenter]}>{translate('exitSurvey.offlineTitle')}</Text>
                 <Text style={[styles.mt2, styles.textAlignCenter]}>{translate('exitSurvey.offline')}</Text>
             </View>
-        </DelegateNoAccessWrapper>
     );
 }
 
diff --git a/src/pages/settings/Profile/ProfilePage.tsx b/src/pages/settings/Profile/ProfilePage.tsx
index fcf1987dbf37..104f03e2c3ec 100755
--- a/src/pages/settings/Profile/ProfilePage.tsx
+++ b/src/pages/settings/Profile/ProfilePage.tsx
@@ -93,23 +93,23 @@ function ProfilePage() {
         {
             description: translate('privatePersonalDetails.legalName'),
             title: legalName,
-            pageRoute: ROUTES.SETTINGS_LEGAL_NAME,
+            action: () => {isActingAsDelegate ? setIsNoDelegateAccessMenuVisible(true) : Navigation.navigate(ROUTES.SETTINGS_LEGAL_NAME)},
         },
         {
             description: translate('common.dob'),
             title: privateDetails.dob ?? '',
-            pageRoute: ROUTES.SETTINGS_DATE_OF_BIRTH,
+            action: () => { isActingAsDelegate ? setIsNoDelegateAccessMenuVisible(true) : Navigation.navigate(ROUTES.SETTINGS_DATE_OF_BIRTH)},
         },
         {
             description: translate('common.phoneNumber'),
             title: privateDetails.phoneNumber ?? '',
-            pageRoute: ROUTES.SETTINGS_PHONE_NUMBER,
+            action: () => {isActingAsDelegate ? setIsNoDelegateAccessMenuVisible(true) : Navigation.navigate(ROUTES.SETTINGS_PHONE_NUMBER)},
             brickRoadIndicator: privatePersonalDetails?.errorFields?.phoneNumber ? CONST.BRICK_ROAD_INDICATOR_STATUS.ERROR : undefined,
         },
         {
             description: translate('privatePersonalDetails.address'),
             title: PersonalDetailsUtils.getFormattedAddress(privateDetails),
-            pageRoute: ROUTES.SETTINGS_ADDRESS,
+            action: () => {isActingAsDelegate ? setIsNoDelegateAccessMenuVisible(true) : Navigation.navigate(ROUTES.SETTINGS_ADDRESS)},
         },
     ];
 
@@ -204,9 +204,7 @@ function ProfilePage() {
                                             title={detail.title}
                                             description={detail.description}
                                             wrapperStyle={styles.sectionMenuItemTopDescription}
-                                            onPress={() => {
-                                                isActingAsDelegate ? setIsNoDelegateAccessMenuVisible(true) : Navigation.navigate(detail.pageRoute);
-                                            }}
+                                            onPress={detail.action}
                                             brickRoadIndicator={detail.brickRoadIndicator}
                                         />
                                     ))}

From bfe6d6e9180557ae3b0b91a17b5f756097ef71fc Mon Sep 17 00:00:00 2001
From: Sachin Chavda <sachin.chavda.1024@gmail.com>
Date: Tue, 26 Nov 2024 02:10:31 +0530
Subject: [PATCH 26/31] prettier

---
 src/pages/AddressPage.tsx                      |  2 --
 .../settings/ExitSurvey/ExitSurveyOffline.tsx  | 18 +++++++++---------
 src/pages/settings/Profile/ProfilePage.tsx     | 16 ++++++++++++----
 3 files changed, 21 insertions(+), 15 deletions(-)

diff --git a/src/pages/AddressPage.tsx b/src/pages/AddressPage.tsx
index f2b7497b2528..31cffbe9b511 100644
--- a/src/pages/AddressPage.tsx
+++ b/src/pages/AddressPage.tsx
@@ -1,8 +1,6 @@
 import React, {useCallback, useEffect, useState} from 'react';
 import type {OnyxEntry} from 'react-native-onyx';
-import {useOnyx} from 'react-native-onyx';
 import AddressForm from '@components/AddressForm';
-import DelegateNoAccessModal from '@components/DelegateNoAccessModal';
 import DelegateNoAccessWrapper from '@components/DelegateNoAccessWrapper';
 import FullscreenLoadingIndicator from '@components/FullscreenLoadingIndicator';
 import HeaderWithBackButton from '@components/HeaderWithBackButton';
diff --git a/src/pages/settings/ExitSurvey/ExitSurveyOffline.tsx b/src/pages/settings/ExitSurvey/ExitSurveyOffline.tsx
index 32baef58ba45..3363867ad4bb 100644
--- a/src/pages/settings/ExitSurvey/ExitSurveyOffline.tsx
+++ b/src/pages/settings/ExitSurvey/ExitSurveyOffline.tsx
@@ -11,15 +11,15 @@ function ExitSurveyOffline() {
     const {translate} = useLocalize();
     const styles = useThemeStyles();
     return (
-            <View style={[styles.flex1, styles.justifyContentCenter, styles.alignItemsCenter]}>
-                <Icon
-                    width={variables.modalTopIconWidth}
-                    height={variables.modalTopIconHeight}
-                    src={ToddBehindCloud}
-                />
-                <Text style={[styles.headerAnonymousFooter, styles.textAlignCenter]}>{translate('exitSurvey.offlineTitle')}</Text>
-                <Text style={[styles.mt2, styles.textAlignCenter]}>{translate('exitSurvey.offline')}</Text>
-            </View>
+        <View style={[styles.flex1, styles.justifyContentCenter, styles.alignItemsCenter]}>
+            <Icon
+                width={variables.modalTopIconWidth}
+                height={variables.modalTopIconHeight}
+                src={ToddBehindCloud}
+            />
+            <Text style={[styles.headerAnonymousFooter, styles.textAlignCenter]}>{translate('exitSurvey.offlineTitle')}</Text>
+            <Text style={[styles.mt2, styles.textAlignCenter]}>{translate('exitSurvey.offline')}</Text>
+        </View>
     );
 }
 
diff --git a/src/pages/settings/Profile/ProfilePage.tsx b/src/pages/settings/Profile/ProfilePage.tsx
index 104f03e2c3ec..dece2e67eeee 100755
--- a/src/pages/settings/Profile/ProfilePage.tsx
+++ b/src/pages/settings/Profile/ProfilePage.tsx
@@ -93,23 +93,31 @@ function ProfilePage() {
         {
             description: translate('privatePersonalDetails.legalName'),
             title: legalName,
-            action: () => {isActingAsDelegate ? setIsNoDelegateAccessMenuVisible(true) : Navigation.navigate(ROUTES.SETTINGS_LEGAL_NAME)},
+            action: () => {
+                isActingAsDelegate ? setIsNoDelegateAccessMenuVisible(true) : Navigation.navigate(ROUTES.SETTINGS_LEGAL_NAME);
+            },
         },
         {
             description: translate('common.dob'),
             title: privateDetails.dob ?? '',
-            action: () => { isActingAsDelegate ? setIsNoDelegateAccessMenuVisible(true) : Navigation.navigate(ROUTES.SETTINGS_DATE_OF_BIRTH)},
+            action: () => {
+                isActingAsDelegate ? setIsNoDelegateAccessMenuVisible(true) : Navigation.navigate(ROUTES.SETTINGS_DATE_OF_BIRTH);
+            },
         },
         {
             description: translate('common.phoneNumber'),
             title: privateDetails.phoneNumber ?? '',
-            action: () => {isActingAsDelegate ? setIsNoDelegateAccessMenuVisible(true) : Navigation.navigate(ROUTES.SETTINGS_PHONE_NUMBER)},
+            action: () => {
+                isActingAsDelegate ? setIsNoDelegateAccessMenuVisible(true) : Navigation.navigate(ROUTES.SETTINGS_PHONE_NUMBER);
+            },
             brickRoadIndicator: privatePersonalDetails?.errorFields?.phoneNumber ? CONST.BRICK_ROAD_INDICATOR_STATUS.ERROR : undefined,
         },
         {
             description: translate('privatePersonalDetails.address'),
             title: PersonalDetailsUtils.getFormattedAddress(privateDetails),
-            action: () => {isActingAsDelegate ? setIsNoDelegateAccessMenuVisible(true) : Navigation.navigate(ROUTES.SETTINGS_ADDRESS)},
+            action: () => {
+                isActingAsDelegate ? setIsNoDelegateAccessMenuVisible(true) : Navigation.navigate(ROUTES.SETTINGS_ADDRESS);
+            },
         },
     ];
 

From 97c96773cae24aeab0d27e4d1f7d7ae9f5517b01 Mon Sep 17 00:00:00 2001
From: Sachin Chavda <sachin.chavda.1024@gmail.com>
Date: Thu, 28 Nov 2024 17:26:59 +0530
Subject: [PATCH 27/31] disable single execution for special case

---
 src/pages/settings/Profile/ProfilePage.tsx    | 28 +++++++++++++++----
 .../SubscriptionDetails/index.tsx             |  4 +++
 2 files changed, 26 insertions(+), 6 deletions(-)

diff --git a/src/pages/settings/Profile/ProfilePage.tsx b/src/pages/settings/Profile/ProfilePage.tsx
index dece2e67eeee..b33f67bae3f1 100755
--- a/src/pages/settings/Profile/ProfilePage.tsx
+++ b/src/pages/settings/Profile/ProfilePage.tsx
@@ -94,21 +94,33 @@ function ProfilePage() {
             description: translate('privatePersonalDetails.legalName'),
             title: legalName,
             action: () => {
-                isActingAsDelegate ? setIsNoDelegateAccessMenuVisible(true) : Navigation.navigate(ROUTES.SETTINGS_LEGAL_NAME);
+                if (isActingAsDelegate) {
+                    setIsNoDelegateAccessMenuVisible(true);
+                    return;
+                }
+                Navigation.navigate(ROUTES.SETTINGS_LEGAL_NAME);
             },
         },
         {
             description: translate('common.dob'),
             title: privateDetails.dob ?? '',
             action: () => {
-                isActingAsDelegate ? setIsNoDelegateAccessMenuVisible(true) : Navigation.navigate(ROUTES.SETTINGS_DATE_OF_BIRTH);
+                if (isActingAsDelegate) {
+                    setIsNoDelegateAccessMenuVisible(true);
+                    return;
+                }
+                Navigation.navigate(ROUTES.SETTINGS_DATE_OF_BIRTH);
             },
         },
         {
             description: translate('common.phoneNumber'),
             title: privateDetails.phoneNumber ?? '',
             action: () => {
-                isActingAsDelegate ? setIsNoDelegateAccessMenuVisible(true) : Navigation.navigate(ROUTES.SETTINGS_PHONE_NUMBER);
+                if (isActingAsDelegate) {
+                    setIsNoDelegateAccessMenuVisible(true);
+                    return;
+                }
+                Navigation.navigate(ROUTES.SETTINGS_PHONE_NUMBER);
             },
             brickRoadIndicator: privatePersonalDetails?.errorFields?.phoneNumber ? CONST.BRICK_ROAD_INDICATOR_STATUS.ERROR : undefined,
         },
@@ -116,7 +128,11 @@ function ProfilePage() {
             description: translate('privatePersonalDetails.address'),
             title: PersonalDetailsUtils.getFormattedAddress(privateDetails),
             action: () => {
-                isActingAsDelegate ? setIsNoDelegateAccessMenuVisible(true) : Navigation.navigate(ROUTES.SETTINGS_ADDRESS);
+                if (isActingAsDelegate) {
+                    setIsNoDelegateAccessMenuVisible(true);
+                    return;
+                }
+                Navigation.navigate(ROUTES.SETTINGS_ADDRESS);
             },
         },
     ];
@@ -203,7 +219,7 @@ function ProfilePage() {
                             {isLoadingApp ? (
                                 <FullScreenLoadingIndicator style={[styles.flex1, styles.pRelative, StyleUtils.getBackgroundColorStyle(theme.cardBG)]} />
                             ) : (
-                                <>
+                                <MenuItemGroup shouldUseSingleExecution={!isActingAsDelegate}>
                                     {privateOptions.map((detail, index) => (
                                         <MenuItemWithTopDescription
                                             // eslint-disable-next-line react/no-array-index-key
@@ -216,7 +232,7 @@ function ProfilePage() {
                                             brickRoadIndicator={detail.brickRoadIndicator}
                                         />
                                     ))}
-                                </>
+                                </MenuItemGroup>
                             )}
                         </Section>
                     </View>
diff --git a/src/pages/settings/Subscription/SubscriptionDetails/index.tsx b/src/pages/settings/Subscription/SubscriptionDetails/index.tsx
index 273900ab9fd5..126ae459e723 100644
--- a/src/pages/settings/Subscription/SubscriptionDetails/index.tsx
+++ b/src/pages/settings/Subscription/SubscriptionDetails/index.tsx
@@ -61,6 +61,10 @@ function SubscriptionDetails() {
     };
 
     const onSubscriptionSizePress = () => {
+        if (isActingAsDelegate) {
+            setIsNoDelegateAccessMenuVisible(true);
+            return;
+        }
         Navigation.navigate(ROUTES.SETTINGS_SUBSCRIPTION_SIZE.getRoute(1));
     };
 

From 72d0ba31dbcec20beb1dc0ae8978ebc5d1cbe92d Mon Sep 17 00:00:00 2001
From: Sachin Chavda <sachin.chavda.1024@gmail.com>
Date: Tue, 3 Dec 2024 17:15:47 +0530
Subject: [PATCH 28/31] refactor DelegateNoAccessModal

---
 src/components/DelegateNoAccessModal.tsx | 6 ++++--
 src/languages/en.ts                      | 3 ++-
 src/languages/es.ts                      | 3 ++-
 3 files changed, 8 insertions(+), 4 deletions(-)

diff --git a/src/components/DelegateNoAccessModal.tsx b/src/components/DelegateNoAccessModal.tsx
index e1e5917ef757..088e94041e49 100644
--- a/src/components/DelegateNoAccessModal.tsx
+++ b/src/components/DelegateNoAccessModal.tsx
@@ -14,12 +14,14 @@ type DelegateNoAccessModalProps = {
 export default function DelegateNoAccessModal({isNoDelegateAccessMenuVisible = false, onClose}: DelegateNoAccessModalProps) {
     const {translate} = useLocalize();
     const {delegatorEmail} = useDelegateUserDetails();
-    const noDelegateAccessPromptStart = translate('delegate.notAllowedMessageStart', {accountOwnerEmail: delegatorEmail ?? ''});
+    const noDelegateAccessPromptStart = translate('delegate.notAllowedMessageStart');
     const noDelegateAccessHyperLinked = translate('delegate.notAllowedMessageHyperLinked');
+    const noDelegateAccessPromptEnd = translate('delegate.notAllowedMessageEnd', {accountOwnerEmail: delegatorEmail ?? ''});
     const delegateNoAccessPrompt = (
         <Text>
             {noDelegateAccessPromptStart}
-            <TextLink href={CONST.DELEGATE_ROLE_HELPDOT_ARTICLE_LINK}>{noDelegateAccessHyperLinked}</TextLink>.
+            <TextLink href={CONST.DELEGATE_ROLE_HELPDOT_ARTICLE_LINK}>{noDelegateAccessHyperLinked}</TextLink>
+            {noDelegateAccessPromptEnd}
         </Text>
     );
 
diff --git a/src/languages/en.ts b/src/languages/en.ts
index 3b4c3cae6ef5..157b4b9d1b31 100755
--- a/src/languages/en.ts
+++ b/src/languages/en.ts
@@ -5308,8 +5308,9 @@ const translations = {
         enterMagicCodeUpdate: ({contactMethod}: EnterMagicCodeParams) => `Please enter the magic code sent to ${contactMethod} to update your copilot.`,
         notAllowed: 'Not so fast...',
         noAccessMessage: "As a copilot, you don't have access to \nthis page. Sorry!",
-        notAllowedMessageStart: ({accountOwnerEmail}: AccountOwnerParams) => `You don't have permission to take this action for ${accountOwnerEmail} as a`,
+        notAllowedMessageStart: `As a`,
         notAllowedMessageHyperLinked: ' copilot',
+        notAllowedMessageEnd: ({accountOwnerEmail}: AccountOwnerParams) => ` for ${accountOwnerEmail}, you don't have permission to take this action. Sorry!`,
     },
     debug: {
         debug: 'Debug',
diff --git a/src/languages/es.ts b/src/languages/es.ts
index e2fd20ef0172..d928a632c121 100644
--- a/src/languages/es.ts
+++ b/src/languages/es.ts
@@ -5827,8 +5827,9 @@ const translations = {
             `Por favor, introduce el código mágico enviado a ${contactMethod} para actualizar el nivel de acceso de tu copiloto.`,
         notAllowed: 'No tan rápido...',
         noAccessMessage: 'Como copiloto, no tienes acceso a esta página. ¡Lo sentimos!',
-        notAllowedMessageStart: ({accountOwnerEmail}: AccountOwnerParams) => `No tienes permiso para realizar esta acción para ${accountOwnerEmail}`,
+        notAllowedMessageStart: `Como`,
         notAllowedMessageHyperLinked: ' copiloto',
+        notAllowedMessageEnd: ({accountOwnerEmail}: AccountOwnerParams) => ` de ${accountOwnerEmail}, no tienes permiso para realizar esta acción. ¡Lo siento!`,
     },
     debug: {
         debug: 'Depuración',

From 993841dadec35493eb29b345003b7d4331386922 Mon Sep 17 00:00:00 2001
From: Sachin Chavda <sachin.chavda.1024@gmail.com>
Date: Tue, 3 Dec 2024 17:17:29 +0530
Subject: [PATCH 29/31] Restrict actions for copilot - issue Expensify card,
 add company card, assign company card

---
 .../WorkspaceCompanyCardPageEmptyState.tsx    | 21 ++++++++++++++++---
 ...WorkspaceCompanyCardsListHeaderButtons.tsx | 14 ++++++++++++-
 .../companyCards/addNew/AddNewCardPage.tsx    | 15 +++++++++++++
 .../assignCard/AssignCardFeedPage.tsx         | 16 ++++++++++++++
 .../WorkspaceExpensifyCardListPage.tsx        | 18 +++++++++++++---
 .../WorkspaceExpensifyCardPageEmptyState.tsx  | 12 +++++++++++
 .../issueNew/IssueNewCardPage.tsx             | 16 ++++++++++++++
 7 files changed, 105 insertions(+), 7 deletions(-)

diff --git a/src/pages/workspace/companyCards/WorkspaceCompanyCardPageEmptyState.tsx b/src/pages/workspace/companyCards/WorkspaceCompanyCardPageEmptyState.tsx
index 65f054c4e7ce..768523f6f8c3 100644
--- a/src/pages/workspace/companyCards/WorkspaceCompanyCardPageEmptyState.tsx
+++ b/src/pages/workspace/companyCards/WorkspaceCompanyCardPageEmptyState.tsx
@@ -1,5 +1,8 @@
-import React, {useCallback} from 'react';
+import React, {useCallback, useState} from 'react';
 import {View} from 'react-native';
+import {useOnyx} from 'react-native-onyx';
+import DelegateNoAccessModal from '@components/DelegateNoAccessModal';
+import DelegateNoAccessWrapper from '@components/DelegateNoAccessWrapper';
 import FeatureList from '@components/FeatureList';
 import type {FeatureListItem} from '@components/FeatureList';
 import * as Illustrations from '@components/Icon/Illustrations';
@@ -11,6 +14,7 @@ import withPolicyAndFullscreenLoading from '@pages/workspace/withPolicyAndFullsc
 import type {WithPolicyAndFullscreenLoadingProps} from '@pages/workspace/withPolicyAndFullscreenLoading';
 import colors from '@styles/theme/colors';
 import * as CompanyCards from '@userActions/CompanyCards';
+import ONYXKEYS from '@src/ONYXKEYS';
 import ROUTES from '@src/ROUTES';
 
 const companyCardFeatures: FeatureListItem[] = [
@@ -33,7 +37,14 @@ function WorkspaceCompanyCardPageEmptyState({policy}: WithPolicyAndFullscreenLoa
     const styles = useThemeStyles();
     const {shouldUseNarrowLayout} = useResponsiveLayout();
 
-    const startFlow = useCallback(() => {
+    const [isActingAsDelegate] = useOnyx(ONYXKEYS.ACCOUNT, {selector: (account) => !!account?.delegatedAccess?.delegate});
+    const [isNoDelegateAccessMenuVisible, setIsNoDelegateAccessMenuVisible] = useState(false);
+
+    const handleCtaPress = useCallback(() => {
+        if (isActingAsDelegate) {
+            setIsNoDelegateAccessMenuVisible(true);
+            return;
+        }
         CompanyCards.clearAddNewCardFlow();
         Navigation.navigate(ROUTES.WORKSPACE_COMPANY_CARDS_ADD_NEW.getRoute(policy?.id ?? '-1'));
     }, [policy]);
@@ -46,13 +57,17 @@ function WorkspaceCompanyCardPageEmptyState({policy}: WithPolicyAndFullscreenLoa
                 subtitle={translate('workspace.moreFeatures.companyCards.subtitle')}
                 ctaText={translate('workspace.moreFeatures.companyCards.feed.ctaTitle')}
                 ctaAccessibilityLabel={translate('workspace.moreFeatures.companyCards.feed.ctaTitle')}
-                onCtaPress={startFlow}
+                onCtaPress={handleCtaPress}
                 illustrationBackgroundColor={colors.blue700}
                 illustration={Illustrations.CompanyCardsEmptyState}
                 illustrationStyle={styles.emptyStateCardIllustration}
                 illustrationContainerStyle={[styles.emptyStateCardIllustrationContainer, styles.justifyContentStart]}
                 titleStyles={styles.textHeadlineH1}
             />
+            <DelegateNoAccessModal
+                isNoDelegateAccessMenuVisible={isNoDelegateAccessMenuVisible}
+                onClose={() => setIsNoDelegateAccessMenuVisible(false)}
+            />
         </View>
     );
 }
diff --git a/src/pages/workspace/companyCards/WorkspaceCompanyCardsListHeaderButtons.tsx b/src/pages/workspace/companyCards/WorkspaceCompanyCardsListHeaderButtons.tsx
index 22b17496040e..06318defc71b 100644
--- a/src/pages/workspace/companyCards/WorkspaceCompanyCardsListHeaderButtons.tsx
+++ b/src/pages/workspace/companyCards/WorkspaceCompanyCardsListHeaderButtons.tsx
@@ -1,8 +1,9 @@
-import React from 'react';
+import React, {useState} from 'react';
 import {View} from 'react-native';
 import {useOnyx} from 'react-native-onyx';
 import Button from '@components/Button';
 import CaretWrapper from '@components/CaretWrapper';
+import DelegateNoAccessModal from '@components/DelegateNoAccessModal';
 import Icon from '@components/Icon';
 import * as Expensicons from '@components/Icon/Expensicons';
 import OfflineWithFeedback from '@components/OfflineWithFeedback';
@@ -50,7 +51,14 @@ function WorkspaceCompanyCardsListHeaderButtons({policyID, selectedFeed}: Worksp
     const [list] = useOnyx(`${ONYXKEYS.COLLECTION.WORKSPACE_CARDS_LIST}${workspaceAccountID}_${selectedFeed}`);
     const filteredCardList = CardUtils.getFilteredCardList(list);
 
+    const [isActingAsDelegate] = useOnyx(ONYXKEYS.ACCOUNT, {selector: (account) => !!account?.delegatedAccess?.delegate});
+    const [isNoDelegateAccessMenuVisible, setIsNoDelegateAccessMenuVisible] = useState(false);
+
     const handleAssignCard = () => {
+        if (isActingAsDelegate) {
+            setIsNoDelegateAccessMenuVisible(true);
+            return;
+        }
         const data: Partial<AssignCardData> = {
             bankName: selectedFeed,
         };
@@ -126,6 +134,10 @@ function WorkspaceCompanyCardsListHeaderButtons({policyID, selectedFeed}: Worksp
                     />
                 </View>
             </View>
+            <DelegateNoAccessModal
+                isNoDelegateAccessMenuVisible={isNoDelegateAccessMenuVisible}
+                onClose={() => setIsNoDelegateAccessMenuVisible(false)}
+            />
         </OfflineWithFeedback>
     );
 }
diff --git a/src/pages/workspace/companyCards/addNew/AddNewCardPage.tsx b/src/pages/workspace/companyCards/addNew/AddNewCardPage.tsx
index 2fef7016df97..7a326b56592e 100644
--- a/src/pages/workspace/companyCards/addNew/AddNewCardPage.tsx
+++ b/src/pages/workspace/companyCards/addNew/AddNewCardPage.tsx
@@ -1,5 +1,7 @@
 import React from 'react';
 import {useOnyx} from 'react-native-onyx';
+import DelegateNoAccessWrapper from '@components/DelegateNoAccessWrapper';
+import ScreenWrapper from '@components/ScreenWrapper';
 import withPolicyAndFullscreenLoading from '@pages/workspace/withPolicyAndFullscreenLoading';
 import type {WithPolicyAndFullscreenLoadingProps} from '@pages/workspace/withPolicyAndFullscreenLoading';
 import CONST from '@src/CONST';
@@ -18,6 +20,19 @@ function AddNewCardPage({policy}: WithPolicyAndFullscreenLoadingProps) {
     const [addNewCardFeed] = useOnyx(ONYXKEYS.ADD_NEW_COMPANY_CARD);
     const {currentStep} = addNewCardFeed ?? {};
 
+    const [isActingAsDelegate] = useOnyx(ONYXKEYS.ACCOUNT, {selector: (account) => !!account?.delegatedAccess?.delegate});
+
+    if (isActingAsDelegate) {
+        return (
+            <ScreenWrapper
+                testID={AddNewCardPage.displayName}
+                includeSafeAreaPaddingBottom={false}
+                shouldEnablePickerAvoiding={false}
+            >
+                <DelegateNoAccessWrapper accessDeniedVariants={[CONST.DELEGATE.DENIED_ACCESS_VARIANTS.DELEGATE]} />
+            </ScreenWrapper>
+        );
+    }
     switch (currentStep) {
         case CONST.COMPANY_CARDS.STEP.SELECT_BANK:
             return <SelectBankStep />;
diff --git a/src/pages/workspace/companyCards/assignCard/AssignCardFeedPage.tsx b/src/pages/workspace/companyCards/assignCard/AssignCardFeedPage.tsx
index 2fe757c4e36f..9a7665970587 100644
--- a/src/pages/workspace/companyCards/assignCard/AssignCardFeedPage.tsx
+++ b/src/pages/workspace/companyCards/assignCard/AssignCardFeedPage.tsx
@@ -1,6 +1,8 @@
 import type {StackScreenProps} from '@react-navigation/stack';
 import React, {useEffect} from 'react';
 import {useOnyx} from 'react-native-onyx';
+import DelegateNoAccessWrapper from '@components/DelegateNoAccessWrapper';
+import ScreenWrapper from '@components/ScreenWrapper';
 import type {SettingsNavigatorParamList} from '@navigation/types';
 import type {WithPolicyAndFullscreenLoadingProps} from '@pages/workspace/withPolicyAndFullscreenLoading';
 import withPolicyAndFullscreenLoading from '@pages/workspace/withPolicyAndFullscreenLoading';
@@ -23,6 +25,7 @@ function AssignCardFeedPage({route, policy}: AssignCardFeedPageProps) {
     const feed = route.params?.feed;
     const backTo = route.params?.backTo;
     const policyID = policy?.id ?? '-1';
+    const [isActingAsDelegate] = useOnyx(ONYXKEYS.ACCOUNT, {selector: (account) => !!account?.delegatedAccess?.delegate});
 
     useEffect(() => {
         return () => {
@@ -30,6 +33,18 @@ function AssignCardFeedPage({route, policy}: AssignCardFeedPageProps) {
         };
     }, []);
 
+    if (isActingAsDelegate) {
+        return (
+            <ScreenWrapper
+                testID={AssignCardFeedPage.displayName}
+                includeSafeAreaPaddingBottom={false}
+                shouldEnablePickerAvoiding={false}
+            >
+                <DelegateNoAccessWrapper accessDeniedVariants={[CONST.DELEGATE.DENIED_ACCESS_VARIANTS.DELEGATE]} />
+            </ScreenWrapper>
+        );
+    }
+
     switch (currentStep) {
         case CONST.COMPANY_CARD.STEP.ASSIGNEE:
             return <AssigneeStep policy={policy} />;
@@ -56,4 +71,5 @@ function AssignCardFeedPage({route, policy}: AssignCardFeedPageProps) {
     }
 }
 
+AssignCardFeedPage.displayName = 'AssignCardFeedPage';
 export default withPolicyAndFullscreenLoading(AssignCardFeedPage);
diff --git a/src/pages/workspace/expensifyCard/WorkspaceExpensifyCardListPage.tsx b/src/pages/workspace/expensifyCard/WorkspaceExpensifyCardListPage.tsx
index dede1ad95ec0..f7b53e0949f8 100644
--- a/src/pages/workspace/expensifyCard/WorkspaceExpensifyCardListPage.tsx
+++ b/src/pages/workspace/expensifyCard/WorkspaceExpensifyCardListPage.tsx
@@ -1,10 +1,11 @@
 import type {RouteProp} from '@react-navigation/native';
-import React, {useCallback, useMemo} from 'react';
+import React, {useCallback, useMemo, useState} from 'react';
 import type {ListRenderItemInfo} from 'react-native';
 import {FlatList, View} from 'react-native';
 import {useOnyx} from 'react-native-onyx';
 import type {OnyxEntry} from 'react-native-onyx';
 import Button from '@components/Button';
+import DelegateNoAccessModal from '@components/DelegateNoAccessModal';
 import HeaderWithBackButton from '@components/HeaderWithBackButton';
 import * as Expensicons from '@components/Icon/Expensicons';
 import * as Illustrations from '@components/Icon/Illustrations';
@@ -49,13 +50,20 @@ function WorkspaceExpensifyCardListPage({route, cardsList}: WorkspaceExpensifyCa
     const [personalDetails] = useOnyx(ONYXKEYS.PERSONAL_DETAILS_LIST);
     const [cardOnWaitlist] = useOnyx(`${ONYXKEYS.COLLECTION.NVP_EXPENSIFY_ON_CARD_WAITLIST}${policyID}`);
 
+    const [isActingAsDelegate] = useOnyx(ONYXKEYS.ACCOUNT, {selector: (account) => !!account?.delegatedAccess?.delegate});
+    const [isNoDelegateAccessMenuVisible, setIsNoDelegateAccessMenuVisible] = useState(false);
+
     const isBankAccountVerified = !cardOnWaitlist;
 
     const policyCurrency = useMemo(() => policy?.outputCurrency ?? CONST.CURRENCY.USD, [policy]);
 
     const sortedCards = useMemo(() => CardUtils.sortCardsByCardholderName(cardsList, personalDetails), [cardsList, personalDetails]);
 
-    const issueCard = () => {
+    const handleIssueCardPress = () => {
+        if (isActingAsDelegate) {
+            setIsNoDelegateAccessMenuVisible(true);
+            return;
+        }
         const activeRoute = Navigation.getActiveRoute();
         Navigation.navigate(ROUTES.WORKSPACE_EXPENSIFY_CARD_ISSUE_NEW.getRoute(policyID, activeRoute));
     };
@@ -64,7 +72,7 @@ function WorkspaceExpensifyCardListPage({route, cardsList}: WorkspaceExpensifyCa
         <View style={[styles.w100, styles.flexRow, styles.gap2, shouldUseNarrowLayout && styles.mb3]}>
             <Button
                 success
-                onPress={issueCard}
+                onPress={handleIssueCardPress}
                 icon={Expensicons.Plus}
                 text={translate('workspace.expensifyCard.issueCard')}
                 style={shouldUseNarrowLayout && styles.flex1}
@@ -135,6 +143,10 @@ function WorkspaceExpensifyCardListPage({route, cardsList}: WorkspaceExpensifyCa
                     ListHeaderComponent={renderListHeader}
                 />
             )}
+            <DelegateNoAccessModal
+                isNoDelegateAccessMenuVisible={isNoDelegateAccessMenuVisible}
+                onClose={() => setIsNoDelegateAccessMenuVisible(false)}
+            />
         </ScreenWrapper>
     );
 }
diff --git a/src/pages/workspace/expensifyCard/WorkspaceExpensifyCardPageEmptyState.tsx b/src/pages/workspace/expensifyCard/WorkspaceExpensifyCardPageEmptyState.tsx
index 7dc6293e23ea..58c187e9e25b 100644
--- a/src/pages/workspace/expensifyCard/WorkspaceExpensifyCardPageEmptyState.tsx
+++ b/src/pages/workspace/expensifyCard/WorkspaceExpensifyCardPageEmptyState.tsx
@@ -3,6 +3,7 @@ import React, {useCallback, useState} from 'react';
 import {View} from 'react-native';
 import {useOnyx} from 'react-native-onyx';
 import ConfirmModal from '@components/ConfirmModal';
+import DelegateNoAccessModal from '@components/DelegateNoAccessModal';
 import FeatureList from '@components/FeatureList';
 import type {FeatureListItem} from '@components/FeatureList';
 import * as Illustrations from '@components/Icon/Illustrations';
@@ -52,6 +53,9 @@ function WorkspaceExpensifyCardPageEmptyState({route, policy}: WorkspaceExpensif
     const [reimbursementAccount] = useOnyx(ONYXKEYS.REIMBURSEMENT_ACCOUNT);
     const [isCurrencyModalOpen, setIsCurrencyModalOpen] = useState(false);
 
+    const [isActingAsDelegate] = useOnyx(ONYXKEYS.ACCOUNT, {selector: (account) => !!account?.delegatedAccess?.delegate});
+    const [isNoDelegateAccessMenuVisible, setIsNoDelegateAccessMenuVisible] = useState(false);
+
     const eligibleBankAccounts = CardUtils.getEligibleBankAccountsForCard(bankAccountList ?? {});
 
     const reimbursementAccountStatus = reimbursementAccount?.achData?.state ?? '';
@@ -92,6 +96,10 @@ function WorkspaceExpensifyCardPageEmptyState({route, policy}: WorkspaceExpensif
                     ctaText={translate(isSetupUnfinished ? 'workspace.expensifyCard.finishSetup' : 'workspace.expensifyCard.issueNewCard')}
                     ctaAccessibilityLabel={translate('workspace.moreFeatures.expensifyCard.feed.ctaTitle')}
                     onCtaPress={() => {
+                        if (isActingAsDelegate) {
+                            setIsNoDelegateAccessMenuVisible(true);
+                            return;
+                        }
                         if (!Policy.isCurrencySupportedForDirectReimbursement(policy?.outputCurrency ?? '')) {
                             setIsCurrencyModalOpen(true);
                             return;
@@ -115,6 +123,10 @@ function WorkspaceExpensifyCardPageEmptyState({route, policy}: WorkspaceExpensif
                 />
                 <Text style={[styles.textMicroSupporting, styles.m5]}>{translate('workspace.expensifyCard.disclaimer')}</Text>
             </View>
+            <DelegateNoAccessModal
+                isNoDelegateAccessMenuVisible={isNoDelegateAccessMenuVisible}
+                onClose={() => setIsNoDelegateAccessMenuVisible(false)}
+            />
         </WorkspacePageWithSections>
     );
 }
diff --git a/src/pages/workspace/expensifyCard/issueNew/IssueNewCardPage.tsx b/src/pages/workspace/expensifyCard/issueNew/IssueNewCardPage.tsx
index 3fece9076cc6..126be7d4ac78 100644
--- a/src/pages/workspace/expensifyCard/issueNew/IssueNewCardPage.tsx
+++ b/src/pages/workspace/expensifyCard/issueNew/IssueNewCardPage.tsx
@@ -1,6 +1,8 @@
 import type {StackScreenProps} from '@react-navigation/stack';
 import React, {useEffect} from 'react';
 import {useOnyx} from 'react-native-onyx';
+import DelegateNoAccessWrapper from '@components/DelegateNoAccessWrapper';
+import ScreenWrapper from '@components/ScreenWrapper';
 import type {SettingsNavigatorParamList} from '@navigation/types';
 import AccessOrNotFoundWrapper from '@pages/workspace/AccessOrNotFoundWrapper';
 import type {WithPolicyAndFullscreenLoadingProps} from '@pages/workspace/withPolicyAndFullscreenLoading';
@@ -26,6 +28,8 @@ function IssueNewCardPage({policy, route}: IssueNewCardPageProps) {
     const policyID = policy?.id ?? '-1';
     const backTo = route?.params?.backTo;
 
+    const [isActingAsDelegate] = useOnyx(ONYXKEYS.ACCOUNT, {selector: (account) => !!account?.delegatedAccess?.delegate});
+
     useEffect(() => {
         Card.startIssueNewCardFlow(policyID);
     }, [policyID]);
@@ -60,6 +64,18 @@ function IssueNewCardPage({policy, route}: IssueNewCardPageProps) {
         }
     };
 
+    if (isActingAsDelegate) {
+        return (
+            <ScreenWrapper
+                testID={IssueNewCardPage.displayName}
+                includeSafeAreaPaddingBottom={false}
+                shouldEnablePickerAvoiding={false}
+            >
+                <DelegateNoAccessWrapper accessDeniedVariants={[CONST.DELEGATE.DENIED_ACCESS_VARIANTS.DELEGATE]} />
+            </ScreenWrapper>
+        );
+    }
+
     return (
         <AccessOrNotFoundWrapper
             accessVariants={[CONST.POLICY.ACCESS_VARIANTS.ADMIN, CONST.POLICY.ACCESS_VARIANTS.PAID]}

From fe02315cfd05910403b3e9938a62ca1497b270a4 Mon Sep 17 00:00:00 2001
From: Sachin Chavda <sachin.chavda.1024@gmail.com>
Date: Wed, 4 Dec 2024 22:16:24 +0530
Subject: [PATCH 30/31] Restrict Choose-bank-account-step for copilot and lint

---
 .../WorkspaceCompanyCardPageEmptyState.tsx    |  2 +-
 .../WorkspaceExpensifyCardBankAccounts.tsx    | 41 ++++++++++---------
 2 files changed, 23 insertions(+), 20 deletions(-)

diff --git a/src/pages/workspace/companyCards/WorkspaceCompanyCardPageEmptyState.tsx b/src/pages/workspace/companyCards/WorkspaceCompanyCardPageEmptyState.tsx
index b92818c49230..bb154411a46d 100644
--- a/src/pages/workspace/companyCards/WorkspaceCompanyCardPageEmptyState.tsx
+++ b/src/pages/workspace/companyCards/WorkspaceCompanyCardPageEmptyState.tsx
@@ -46,7 +46,7 @@ function WorkspaceCompanyCardPageEmptyState({policy}: WithPolicyAndFullscreenLoa
         }
         CompanyCards.clearAddNewCardFlow();
         Navigation.navigate(ROUTES.WORKSPACE_COMPANY_CARDS_ADD_NEW.getRoute(policy?.id ?? '-1'));
-    }, [policy]);
+    }, [policy, isActingAsDelegate]);
 
     return (
         <View style={[styles.mt3, shouldUseNarrowLayout ? styles.workspaceSectionMobile : styles.workspaceSection]}>
diff --git a/src/pages/workspace/expensifyCard/WorkspaceExpensifyCardBankAccounts.tsx b/src/pages/workspace/expensifyCard/WorkspaceExpensifyCardBankAccounts.tsx
index 654d7717158e..5da459be4a16 100644
--- a/src/pages/workspace/expensifyCard/WorkspaceExpensifyCardBankAccounts.tsx
+++ b/src/pages/workspace/expensifyCard/WorkspaceExpensifyCardBankAccounts.tsx
@@ -4,6 +4,7 @@ import {useOnyx} from 'react-native-onyx';
 import BlockingView from '@components/BlockingViews/BlockingView';
 import FullPageOfflineBlockingView from '@components/BlockingViews/FullPageOfflineBlockingView';
 import Button from '@components/Button';
+import DelegateNoAccessWrapper from '@components/DelegateNoAccessWrapper';
 import HeaderWithBackButton from '@components/HeaderWithBackButton';
 import getBankIcon from '@components/Icon/BankIcons';
 import * as Expensicons from '@components/Icon/Expensicons';
@@ -188,25 +189,27 @@ function WorkspaceExpensifyCardBankAccounts({route}: WorkspaceExpensifyCardBankA
                 shouldEnablePickerAvoiding={false}
                 shouldShowOfflineIndicator={false}
             >
-                <HeaderWithBackButton
-                    shouldShowBackButton
-                    onBackButtonPress={() => Navigation.goBack()}
-                    title={getHeaderButtonText()}
-                />
-                {isInVerificationState && renderVerificationStateView()}
-                {!isInVerificationState && (
-                    <FullPageOfflineBlockingView>
-                        <View style={styles.flex1}>
-                            <Text style={[styles.mh5, styles.mb3]}>{translate('workspace.expensifyCard.chooseExistingBank')}</Text>
-                            {renderBankOptions()}
-                            <MenuItem
-                                icon={Expensicons.Plus}
-                                title={translate('workspace.expensifyCard.addNewBankAccount')}
-                                onPress={handleAddBankAccount}
-                            />
-                        </View>
-                    </FullPageOfflineBlockingView>
-                )}
+                <DelegateNoAccessWrapper accessDeniedVariants={[CONST.DELEGATE.DENIED_ACCESS_VARIANTS.DELEGATE]}>
+                    <HeaderWithBackButton
+                        shouldShowBackButton
+                        onBackButtonPress={() => Navigation.goBack()}
+                        title={getHeaderButtonText()}
+                    />
+                    {isInVerificationState && renderVerificationStateView()}
+                    {!isInVerificationState && (
+                        <FullPageOfflineBlockingView>
+                            <View style={styles.flex1}>
+                                <Text style={[styles.mh5, styles.mb3]}>{translate('workspace.expensifyCard.chooseExistingBank')}</Text>
+                                {renderBankOptions()}
+                                <MenuItem
+                                    icon={Expensicons.Plus}
+                                    title={translate('workspace.expensifyCard.addNewBankAccount')}
+                                    onPress={handleAddBankAccount}
+                                />
+                            </View>
+                        </FullPageOfflineBlockingView>
+                    )}
+                </DelegateNoAccessWrapper>
             </ScreenWrapper>
         </AccessOrNotFoundWrapper>
     );

From b720e98704a498eeedcbdba5899c106c6adca25d Mon Sep 17 00:00:00 2001
From: Sachin Chavda <sachin.chavda.1024@gmail.com>
Date: Wed, 4 Dec 2024 22:57:52 +0530
Subject: [PATCH 31/31] Prettier

---
 src/pages/settings/Security/SecuritySettingsPage.tsx | 10 +++++-----
 1 file changed, 5 insertions(+), 5 deletions(-)

diff --git a/src/pages/settings/Security/SecuritySettingsPage.tsx b/src/pages/settings/Security/SecuritySettingsPage.tsx
index 68c35a4a4426..5762f557d343 100644
--- a/src/pages/settings/Security/SecuritySettingsPage.tsx
+++ b/src/pages/settings/Security/SecuritySettingsPage.tsx
@@ -212,8 +212,8 @@ function SecuritySettingsPage() {
             text: translate('delegate.changeAccessLevel'),
             icon: Expensicons.Pencil,
             onPress: () => {
-                if(isActingAsDelegate){
-                    Modal.close(()=>setIsNoDelegateAccessMenuVisible(true));
+                if (isActingAsDelegate) {
+                    Modal.close(() => setIsNoDelegateAccessMenuVisible(true));
                     return;
                 }
                 Navigation.navigate(ROUTES.SETTINGS_UPDATE_DELEGATE_ROLE.getRoute(selectedDelegate?.email ?? '', selectedDelegate?.role ?? ''));
@@ -225,9 +225,9 @@ function SecuritySettingsPage() {
         {
             text: translate('delegate.removeCopilot'),
             icon: Expensicons.Trashcan,
-            onPress: () =>{
-                if(isActingAsDelegate){
-                    Modal.close(()=>setIsNoDelegateAccessMenuVisible(true));
+            onPress: () => {
+                if (isActingAsDelegate) {
+                    Modal.close(() => setIsNoDelegateAccessMenuVisible(true));
                     return;
                 }
                 Modal.close(() => {
