Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
21 commits
Select commit Hold shift + click to select a range
b3b8bec
76695: Refactor ConfirmModal usage to useConfirmModal in Report and H…
abbasifaizan70 Dec 5, 2025
20c434a
merged main
abbasifaizan70 Dec 5, 2025
572990c
Fixed lint issues
abbasifaizan70 Dec 5, 2025
900ffbf
Merge branch 'main' into 76695-refactored-confirmation-modal-in-repor…
abbasifaizan70 Dec 5, 2025
2e04112
fixed testcases
abbasifaizan70 Dec 5, 2025
87c6d3d
Merge branch '76695-refactored-confirmation-modal-in-report-and-home-…
abbasifaizan70 Dec 5, 2025
6511877
Fixed Lint issues
abbasifaizan70 Dec 5, 2025
c9448f9
Merge branch 'main' into 76695-refactored-confirmation-modal-in-repor…
abbasifaizan70 Dec 8, 2025
14dcbae
Remove empty line in FloatingActionButtonAndPopover
abbasifaizan70 Dec 8, 2025
2b9e206
fixed lint & test cases issues
abbasifaizan70 Dec 8, 2025
d0475fe
fixed lint issues
abbasifaizan70 Dec 9, 2025
0fcaf14
Merge branch 'main' into 76695-refactored-confirmation-modal-in-repor…
abbasifaizan70 Dec 9, 2025
d7817d7
fixed lint issue
abbasifaizan70 Dec 9, 2025
871c285
removed extra code
abbasifaizan70 Dec 10, 2025
3429676
Merge branch 'Expensify:main' into 76695-refactored-confirmation-moda…
abbasifaizan70 Dec 10, 2025
8eecd53
Merge branch 'main' into 76695-refactored-confirmation-modal-in-repor…
abbasifaizan70 Dec 11, 2025
8752e6b
Fixed lint issues
abbasifaizan70 Dec 11, 2025
1053048
Fixed Lint Issues
abbasifaizan70 Dec 11, 2025
cbbd56c
fixed lint issues
abbasifaizan70 Dec 11, 2025
2c4b958
Merge branch 'main' into 76695-refactored-confirmation-modal-in-repor…
abbasifaizan70 Dec 12, 2025
f8463db
fixed lint issues
abbasifaizan70 Dec 13, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 6 additions & 2 deletions src/libs/getCurrentPosition/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,17 +4,21 @@ import {GeolocationErrorCode} from './getCurrentPosition.types';
import type {GetCurrentPosition} from './getCurrentPosition.types';

const getCurrentPosition: GetCurrentPosition = async (success, error, options) => {
const foregroundPermissionResponse: PermissionResponse = await requestForegroundPermissionsAsync();
// eslint-disable-next-line @typescript-eslint/no-unsafe-assignment, @typescript-eslint/no-unsafe-call
const foregroundPermissionResponse = (await requestForegroundPermissionsAsync()) as PermissionResponse;

// eslint-disable-next-line @typescript-eslint/no-unsafe-member-access
if (foregroundPermissionResponse.status !== PermissionStatus.GRANTED) {
error({code: GeolocationErrorCode.PERMISSION_DENIED, message: 'User denied access to location.'});
return;
}

try {
// eslint-disable-next-line @typescript-eslint/no-unsafe-assignment, @typescript-eslint/no-unsafe-call
const currentPosition = await getCurrentPositionAsync(options);
// eslint-disable-next-line @typescript-eslint/no-unsafe-argument
success(currentPosition);
} catch (caughtError) {
} catch (caughtError: unknown) {
let message = 'Geolocation call failed';
let code = GeolocationErrorCode.POSITION_UNAVAILABLE;

Expand Down
42 changes: 25 additions & 17 deletions src/pages/EditReportFieldPage.tsx
Original file line number Diff line number Diff line change
@@ -1,13 +1,14 @@
import {Str} from 'expensify-common';
import React, {useState} from 'react';
import React from 'react';
import FullPageNotFoundView from '@components/BlockingViews/FullPageNotFoundView';
import ConfirmModal from '@components/ConfirmModal';
import type {FormOnyxValues} from '@components/Form/types';
import HeaderWithBackButton from '@components/HeaderWithBackButton';
import * as Expensicons from '@components/Icon/Expensicons';

Check warning on line 6 in src/pages/EditReportFieldPage.tsx

View workflow job for this annotation

GitHub Actions / Changed files ESLint check

'@components/Icon/Expensicons' import is restricted from being used by a pattern. Direct imports from Icon/Expensicons are deprecated. Please use lazy loading hooks instead. Use `useMemoizedLazyExpensifyIcons` from @hooks/useLazyAsset. See docs/LAZY_ICONS_AND_ILLUSTRATIONS.md for details

Check warning on line 6 in src/pages/EditReportFieldPage.tsx

View workflow job for this annotation

GitHub Actions / Changed files ESLint check

'@components/Icon/Expensicons' import is restricted from being used. Direct imports from @components/Icon/Expensicons are deprecated. Please use lazy loading hooks instead. Use `useMemoizedLazyExpensifyIcons` from @hooks/useLazyAsset. See docs/LAZY_ICONS_AND_ILLUSTRATIONS.md for details
import {ModalActions} from '@components/Modal/Global/ModalContext';
import {useSession} from '@components/OnyxListItemProvider';
import type {PopoverMenuItem} from '@components/PopoverMenu';
import ScreenWrapper from '@components/ScreenWrapper';
import useConfirmModal from '@hooks/useConfirmModal';
import useLocalize from '@hooks/useLocalize';
import useOnyx from '@hooks/useOnyx';
import usePermissions from '@hooks/usePermissions';
Expand Down Expand Up @@ -50,7 +51,7 @@
const [transactionViolations] = useOnyx(ONYXKEYS.COLLECTION.TRANSACTION_VIOLATIONS, {canBeMissing: true});
const hasViolations = hasViolationsReportUtils(report?.reportID, transactionViolations, session?.accountID ?? CONST.DEFAULT_NUMBER_ID, session?.email ?? '');

const [isDeleteModalVisible, setIsDeleteModalVisible] = useState(false);
const {showConfirmModal} = useConfirmModal();
const {translate} = useLocalize();
const isReportFieldTitle = isReportFieldOfTypeTitle(reportField);
const reportFieldsEnabled = ((isPaidGroupPolicyExpenseReport(report) || isInvoiceReport(report)) && !!policy?.areReportFieldsEnabled) || isReportFieldTitle;
Expand Down Expand Up @@ -78,7 +79,6 @@
};

const handleReportFieldDelete = () => {
setIsDeleteModalVisible(false);
goBack();
setTimeout(() => {
deleteReportField(report.reportID, reportField);
Expand Down Expand Up @@ -121,7 +121,27 @@
const isReportFieldDeletable = reportField.deletable && reportField?.fieldID !== CONST.REPORT_FIELD_TITLE_FIELD_ID;

if (isReportFieldDeletable) {
menuItems.push({icon: Expensicons.Trashcan, text: translate('common.delete'), onSelected: () => setIsDeleteModalVisible(true), shouldCallAfterModalHide: true});
menuItems.push({
icon: Expensicons.Trashcan,
text: translate('common.delete'),
onSelected: () => {
showConfirmModal({
title: translate('workspace.reportFields.delete'),
prompt: translate('workspace.reportFields.deleteConfirmation'),
confirmText: translate('common.delete'),
cancelText: translate('common.cancel'),
danger: true,
shouldEnableNewFocusManagement: true,
// eslint-disable-next-line rulesdir/prefer-early-return
}).then((result) => {
if (result.action !== ModalActions.CONFIRM) {
return;
}
handleReportFieldDelete();
});
},
shouldCallAfterModalHide: true,
});
}

const fieldName = Str.UCFirst(reportField.name);
Expand All @@ -139,18 +159,6 @@
onBackButtonPress={goBack}
/>

<ConfirmModal
title={translate('workspace.reportFields.delete')}
isVisible={isDeleteModalVisible}
onConfirm={handleReportFieldDelete}
onCancel={() => setIsDeleteModalVisible(false)}
prompt={translate('workspace.reportFields.deleteConfirmation')}
confirmText={translate('common.delete')}
cancelText={translate('common.cancel')}
danger
shouldEnableNewFocusManagement
/>

{(reportField.type === CONST.REPORT_FIELD_TYPES.TEXT || isReportFieldTitle) && (
<EditReportFieldText
fieldName={reportField.name}
Expand Down
80 changes: 37 additions & 43 deletions src/pages/ReportDetailsPage.tsx
Original file line number Diff line number Diff line change
@@ -1,17 +1,17 @@
import reportsSelector from '@selectors/Attributes';
import {Str} from 'expensify-common';
import React, {useCallback, useEffect, useMemo, useRef, useState} from 'react';
import React, {useCallback, useEffect, useMemo, useRef} from 'react';
import {View} from 'react-native';
import type {OnyxEntry} from 'react-native-onyx';
import type {ValueOf} from 'type-fest';
import AvatarWithImagePicker from '@components/AvatarWithImagePicker';
import FullPageNotFoundView from '@components/BlockingViews/FullPageNotFoundView';
import ConfirmModal from '@components/ConfirmModal';
import DisplayNames from '@components/DisplayNames';
import HeaderWithBackButton from '@components/HeaderWithBackButton';
import MentionReportContext from '@components/HTMLEngineProvider/HTMLRenderers/MentionReportRenderer/MentionReportContext';
import MenuItem from '@components/MenuItem';
import MenuItemWithTopDescription from '@components/MenuItemWithTopDescription';
import {ModalActions} from '@components/Modal/Global/ModalContext';
import OfflineWithFeedback from '@components/OfflineWithFeedback';
import ParentNavigationSubtitle from '@components/ParentNavigationSubtitle';
import PressableWithoutFeedback from '@components/Pressable/PressableWithoutFeedback';
Expand All @@ -23,6 +23,7 @@ import ScreenWrapper from '@components/ScreenWrapper';
import ScrollView from '@components/ScrollView';
import {useSearchContext} from '@components/Search/SearchContext';
import useAncestors from '@hooks/useAncestors';
import useConfirmModal from '@hooks/useConfirmModal';
import useCurrentUserPersonalDetails from '@hooks/useCurrentUserPersonalDetails';
import useDeleteTransactions from '@hooks/useDeleteTransactions';
import useDuplicateTransactionsAndViolations from '@hooks/useDuplicateTransactionsAndViolations';
Expand All @@ -47,7 +48,7 @@ import Parser from '@libs/Parser';
import Permissions from '@libs/Permissions';
import {isPolicyAdmin as isPolicyAdminUtil, isPolicyEmployee as isPolicyEmployeeUtil, shouldShowPolicy} from '@libs/PolicyUtils';
import {getOneTransactionThreadReportID, getOriginalMessage, getTrackExpenseActionableWhisper, isDeletedAction, isMoneyRequestAction, isTrackExpenseAction} from '@libs/ReportActionsUtils';
import {getReportName as getReportNameFromReportNameUtils} from '@libs/ReportNameUtils';
import {getReportName} from '@libs/ReportNameUtils';
import {
canDeleteCardTransactionByLiabilityType,
canDeleteTransaction,
Expand Down Expand Up @@ -153,6 +154,7 @@ type CaseID = ValueOf<typeof CASES>;
function ReportDetailsPage({policy, report, route, reportMetadata}: ReportDetailsPageProps) {
const {translate, localeCompare} = useLocalize();
const {isOffline} = useNetwork();
const {showConfirmModal} = useConfirmModal();
const {isRestrictedToPreferredPolicy, preferredPolicyID} = usePreferredPolicy();
const styles = useThemeStyles();
const expensifyIcons = useMemoizedLazyExpensifyIcons(['Users', 'Gear', 'Send', 'Folder', 'UserPlus', 'Pencil', 'Checkmark', 'Building', 'Exit', 'Bug', 'Camera', 'Trashcan'] as const);
Expand Down Expand Up @@ -181,8 +183,6 @@ function ReportDetailsPage({policy, report, route, reportMetadata}: ReportDetail
const [personalDetails] = useOnyx(ONYXKEYS.PERSONAL_DETAILS_LIST, {canBeMissing: false});
const [introSelected] = useOnyx(ONYXKEYS.NVP_INTRO_SELECTED, {canBeMissing: true});
const currentUserPersonalDetails = useCurrentUserPersonalDetails();
const [isLastMemberLeavingGroupModalVisible, setIsLastMemberLeavingGroupModalVisible] = useState(false);
const [isDeleteModalVisible, setIsDeleteModalVisible] = useState(false);
const isPolicyAdmin = useMemo(() => isPolicyAdminUtil(policy), [policy]);
const isPolicyEmployee = useMemo(() => isPolicyEmployeeUtil(report?.policyID, policy), [report?.policyID, policy]);
const isPolicyExpenseChat = useMemo(() => isPolicyExpenseChatUtil(report), [report]);
Expand Down Expand Up @@ -306,14 +306,6 @@ function ReportDetailsPage({policy, report, route, reportMetadata}: ReportDetail
const [reportAttributes] = useOnyx(ONYXKEYS.DERIVED.REPORT_ATTRIBUTES, {canBeMissing: true, selector: reportsSelector});
const isWorkspaceChat = useMemo(() => isWorkspaceChatUtil(report?.chatType ?? ''), [report?.chatType]);

useEffect(() => {
if (canDeleteRequest) {
return;
}

setIsDeleteModalVisible(false);
}, [canDeleteRequest]);

useEffect(() => {
// Do not fetch private notes if isLoadingPrivateNotes is already defined, or if the network is offline, or if the report is a self DM.
if (isPrivateNotesFetchTriggered || isOffline || isSelfDM) {
Expand All @@ -338,7 +330,7 @@ function ReportDetailsPage({policy, report, route, reportMetadata}: ReportDetail
const shouldShowLeaveButton = canLeaveChat(report, policy, !!reportNameValuePairs?.private_isArchived);
const shouldShowGoToWorkspace = shouldShowPolicy(policy, false, currentUserPersonalDetails?.email) && !policy?.isJoinRequestPending;

const reportName = isGroupChat ? getReportNameFromReportNameUtils(report, reportAttributes) : Parser.htmlToText(getReportNameFromReportNameUtils(report, reportAttributes));
const reportName = isGroupChat ? getReportName(report, reportAttributes) : Parser.htmlToText(getReportName(report, reportAttributes));
const additionalRoomDetails =
(isPolicyExpenseChat && !!report?.isOwnPolicyExpenseChat) || isExpenseReportUtil(report) || isPolicyExpenseChat || isInvoiceRoom
? chatRoomSubtitle
Expand Down Expand Up @@ -525,7 +517,19 @@ function ReportDetailsPage({policy, report, route, reportMetadata}: ReportDetail
isAnonymousAction: true,
action: () => {
if (getParticipantsAccountIDsForDisplay(report, false, true).length === 1 && isRootGroupChat) {
setIsLastMemberLeavingGroupModalVisible(true);
showConfirmModal({
danger: true,
title: translate('groupChat.lastMemberTitle'),
prompt: translate('groupChat.lastMemberWarning'),
confirmText: translate('common.leave'),
cancelText: translate('common.cancel'),
// eslint-disable-next-line rulesdir/prefer-early-return
}).then((result) => {
if (result.action !== ModalActions.CONFIRM) {
return;
}
leaveChat();
});
return;
}

Expand Down Expand Up @@ -584,6 +588,8 @@ function ReportDetailsPage({policy, report, route, reportMetadata}: ReportDetail
preferredPolicyID,
introSelected,
parentReport,
showConfirmModal,
translate,
]);

const displayNamesWithTooltips = useMemo(() => {
Expand Down Expand Up @@ -1010,37 +1016,25 @@ function ReportDetailsPage({policy, report, route, reportMetadata}: ReportDetail
key={CONST.REPORT_DETAILS_MENU_ITEM.DELETE}
icon={expensifyIcons.Trashcan}
title={caseID === CASES.DEFAULT ? translate('common.delete') : translate('reportActionContextMenu.deleteAction', {action: requestParentReportAction})}
onPress={() => setIsDeleteModalVisible(true)}
onPress={() => {
showConfirmModal({
title: caseID === CASES.DEFAULT ? translate('task.deleteTask') : translate('iou.deleteExpense', {count: 1}),
prompt: caseID === CASES.DEFAULT ? translate('task.deleteConfirmation') : translate('iou.deleteConfirmation', {count: 1}),
confirmText: translate('common.delete'),
cancelText: translate('common.cancel'),
danger: true,
shouldEnableNewFocusManagement: true,
// eslint-disable-next-line rulesdir/prefer-early-return
}).then((result) => {
if (result.action !== ModalActions.CONFIRM) {
return;
}
isTransactionDeleted.current = true;
});
}}
/>
)}
</ScrollView>
<ConfirmModal
danger
title={translate('groupChat.lastMemberTitle')}
isVisible={isLastMemberLeavingGroupModalVisible}
onConfirm={() => {
setIsLastMemberLeavingGroupModalVisible(false);
leaveChat();
}}
onCancel={() => setIsLastMemberLeavingGroupModalVisible(false)}
prompt={translate('groupChat.lastMemberWarning')}
confirmText={translate('common.leave')}
cancelText={translate('common.cancel')}
/>
<ConfirmModal
title={caseID === CASES.DEFAULT ? translate('task.deleteTask') : translate('iou.deleteExpense', {count: 1})}
isVisible={isDeleteModalVisible}
onConfirm={() => {
setIsDeleteModalVisible(false);
isTransactionDeleted.current = true;
}}
onCancel={() => setIsDeleteModalVisible(false)}
prompt={caseID === CASES.DEFAULT ? translate('task.deleteConfirmation') : translate('iou.deleteConfirmation', {count: 1})}
confirmText={translate('common.delete')}
cancelText={translate('common.cancel')}
danger
shouldEnableNewFocusManagement
/>
</FullPageNotFoundView>
</ScreenWrapper>
);
Expand Down
Loading
Loading