Skip to content

Commit

Permalink
Merge pull request Expensify#39190 from Expensify/neil-track-distance
Browse files Browse the repository at this point in the history
Track distance expenses
  • Loading branch information
thienlnam authored Apr 10, 2024
2 parents 796a0ab + 454aaa0 commit 342b16d
Show file tree
Hide file tree
Showing 14 changed files with 43 additions and 30 deletions.
4 changes: 3 additions & 1 deletion src/CONST.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ import dateAdd from 'date-fns/add';
import dateSubtract from 'date-fns/sub';
import Config from 'react-native-config';
import * as KeyCommand from 'react-native-key-command';
import type {ValueOf} from 'type-fest';
import * as Url from './libs/Url';
import SCREENS from './SCREENS';

Expand Down Expand Up @@ -4334,7 +4335,8 @@ const CONST = {
} as const;

type Country = keyof typeof CONST.ALL_COUNTRIES;
type IOUType = ValueOf<typeof CONST.IOU.TYPE>;

export type {Country};
export type {Country, IOUType};

export default CONST;
7 changes: 3 additions & 4 deletions src/components/MoneyRequestConfirmationList.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -223,13 +223,12 @@ function MoneyRequestConfirmationList({
const theme = useTheme();
const styles = useThemeStyles();
const {translate, toLocaleDigit} = useLocalize();
const {canUseP2PDistanceRequests, canUseViolations} = usePermissions();
const {canUseViolations} = usePermissions();
const currentUserPersonalDetails = useCurrentUserPersonalDetails();

const isTypeRequest = iouType === CONST.IOU.TYPE.REQUEST;
const isSplitBill = iouType === CONST.IOU.TYPE.SPLIT;
const isTypeSend = iouType === CONST.IOU.TYPE.SEND;
const canEditDistance = isTypeRequest || (canUseP2PDistanceRequests && isSplitBill);

const isSplitWithScan = isSplitBill && isScanRequest;

Expand Down Expand Up @@ -719,7 +718,7 @@ function MoneyRequestConfirmationList({
)}
{isDistanceRequest && (
<MenuItemWithTopDescription
shouldShowRightIcon={!isReadOnly && canEditDistance}
shouldShowRightIcon={!isReadOnly}
title={iouMerchant}
description={translate('common.distance')}
style={styles.moneyRequestMenuItem}
Expand All @@ -735,7 +734,7 @@ function MoneyRequestConfirmationList({
),
)
}
disabled={didConfirm || !canEditDistance}
disabled={didConfirm}
interactive={!isReadOnly}
/>
)}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -253,13 +253,12 @@ function MoneyTemporaryForRefactorRequestConfirmationList({
const theme = useTheme();
const styles = useThemeStyles();
const {translate, toLocaleDigit} = useLocalize();
const {canUseP2PDistanceRequests, canUseViolations} = usePermissions();
const {canUseViolations} = usePermissions();

const isTypeRequest = iouType === CONST.IOU.TYPE.REQUEST;
const isTypeSplit = iouType === CONST.IOU.TYPE.SPLIT;
const isTypeSend = iouType === CONST.IOU.TYPE.SEND;
const isTypeTrackExpense = iouType === CONST.IOU.TYPE.TRACK_EXPENSE;
const canEditDistance = isTypeRequest || (canUseP2PDistanceRequests && isTypeSplit);

const {unit, rate, currency} = mileageRate;
const distance = lodashGet(transaction, 'routes.route0.distance', 0);
Expand Down Expand Up @@ -741,7 +740,7 @@ function MoneyTemporaryForRefactorRequestConfirmationList({
item: (
<MenuItemWithTopDescription
key={translate('common.distance')}
shouldShowRightIcon={!isReadOnly && canEditDistance}
shouldShowRightIcon={!isReadOnly}
title={isMerchantEmpty ? '' : iouMerchant}
description={translate('common.distance')}
style={[styles.moneyRequestMenuItem]}
Expand All @@ -752,7 +751,7 @@ function MoneyTemporaryForRefactorRequestConfirmationList({
)
}
// eslint-disable-next-line @typescript-eslint/prefer-nullish-coalescing
disabled={didConfirm || !canEditDistance}
disabled={didConfirm}
interactive={!isReadOnly}
/>
),
Expand Down
7 changes: 4 additions & 3 deletions src/hooks/usePermissions.ts
Original file line number Diff line number Diff line change
@@ -1,12 +1,13 @@
import {useContext, useMemo} from 'react';
import {BetasContext} from '@components/OnyxProvider';
import Permissions from '@libs/Permissions';
import type {IOUType} from '@src/CONST';

type PermissionKey = keyof typeof Permissions;
type UsePermissions = Partial<Record<PermissionKey, boolean>>;
let permissionKey: PermissionKey;

export default function usePermissions(): UsePermissions {
export default function usePermissions(iouType: IOUType | undefined = undefined): UsePermissions {
const betas = useContext(BetasContext);
return useMemo(() => {
const permissions: UsePermissions = {};
Expand All @@ -15,10 +16,10 @@ export default function usePermissions(): UsePermissions {
if (betas) {
const checkerFunction = Permissions[permissionKey];

permissions[permissionKey] = checkerFunction(betas);
permissions[permissionKey] = checkerFunction(betas, iouType);
}
}

return permissions;
}, [betas]);
}, [betas, iouType]);
}
6 changes: 3 additions & 3 deletions src/languages/en.ts
Original file line number Diff line number Diff line change
Expand Up @@ -600,12 +600,12 @@ export default {
splitBill: 'Split Bill',
splitScan: 'Split Receipt',
splitDistance: 'Split Distance',
trackManual: 'Track Expense',
trackScan: 'Track Receipt',
trackDistance: 'Track Distance',
sendMoney: 'Send Money',
assignTask: 'Assign Task',
shortcut: 'Shortcut',
trackManual: 'Track Manual',
trackScan: 'Track Scan',
trackDistance: 'Track Distance',
},
iou: {
amount: 'Amount',
Expand Down
6 changes: 3 additions & 3 deletions src/languages/es.ts
Original file line number Diff line number Diff line change
Expand Up @@ -599,9 +599,9 @@ export default {
sendMoney: 'Enviar Dinero',
assignTask: 'Assignar Tarea',
shortcut: 'Acceso Directo',
trackManual: 'Seguimiento de Gastos',
trackScan: 'Seguimiento de Recibo',
trackDistance: 'Seguimiento de Distancia',
trackManual: 'Crear Gasto',
trackScan: 'Crear Recibo',
trackDistance: 'Crear Gasto por desplazamiento',
},
iou: {
amount: 'Importe',
Expand Down
1 change: 1 addition & 0 deletions src/libs/API/parameters/TrackExpenseParams.ts
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ type TrackExpenseParams = {
gpsPoints?: string;
transactionThreadReportID: string;
createdReportActionIDForThread: string;
waypoints?: string;
};

export default TrackExpenseParams;
6 changes: 4 additions & 2 deletions src/libs/Permissions.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import type {OnyxEntry} from 'react-native-onyx';
import CONST from '@src/CONST';
import type {IOUType} from '@src/CONST';
import type Beta from '@src/types/onyx/Beta';

function canUseAllBetas(betas: OnyxEntry<Beta[]>): boolean {
Expand All @@ -26,8 +27,9 @@ function canUseTrackExpense(betas: OnyxEntry<Beta[]>): boolean {
return !!betas?.includes(CONST.BETAS.TRACK_EXPENSE) || canUseAllBetas(betas);
}

function canUseP2PDistanceRequests(betas: OnyxEntry<Beta[]>): boolean {
return !!betas?.includes(CONST.BETAS.P2P_DISTANCE_REQUESTS) || canUseAllBetas(betas);
function canUseP2PDistanceRequests(betas: OnyxEntry<Beta[]>, iouType: IOUType | undefined): boolean {
// Allow using P2P distance request for TrackExpense outside of the beta, because that project doesn't want to be limited by the more cautious P2P distance beta
return !!betas?.includes(CONST.BETAS.P2P_DISTANCE_REQUESTS) || canUseAllBetas(betas) || iouType === CONST.IOU.TYPE.TRACK_EXPENSE;
}

function canUseWorkflowsDelayedSubmission(betas: OnyxEntry<Beta[]>): boolean {
Expand Down
2 changes: 2 additions & 0 deletions src/libs/actions/IOU.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2375,6 +2375,7 @@ function trackExpense(
policyTagList?: OnyxEntry<OnyxTypes.PolicyTagList>,
policyCategories?: OnyxEntry<OnyxTypes.PolicyCategories>,
gpsPoints?: GPSPoint,
validWaypoints?: WaypointCollection,
) {
const isMoneyRequestReport = ReportUtils.isMoneyRequestReport(report);
const currentChatReport = isMoneyRequestReport ? ReportUtils.getReport(report.chatReportID) : report;
Expand Down Expand Up @@ -2437,6 +2438,7 @@ function trackExpense(
gpsPoints: gpsPoints ? JSON.stringify(gpsPoints) : undefined,
transactionThreadReportID,
createdReportActionIDForThread,
waypoints: validWaypoints ? JSON.stringify(validWaypoints) : undefined,
};

API.write(WRITE_COMMANDS.TRACK_EXPENSE, parameters, onyxData);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -104,16 +104,16 @@ const getQuickActionTitle = (action: QuickActionName): TranslationPaths => {
return 'quickAction.splitScan';
case CONST.QUICK_ACTIONS.SPLIT_DISTANCE:
return 'quickAction.splitDistance';
case CONST.QUICK_ACTIONS.SEND_MONEY:
return 'quickAction.sendMoney';
case CONST.QUICK_ACTIONS.ASSIGN_TASK:
return 'quickAction.assignTask';
case CONST.QUICK_ACTIONS.TRACK_MANUAL:
return 'quickAction.trackManual';
case CONST.QUICK_ACTIONS.TRACK_SCAN:
return 'quickAction.trackScan';
case CONST.QUICK_ACTIONS.TRACK_DISTANCE:
return 'quickAction.trackDistance';
case CONST.QUICK_ACTIONS.SEND_MONEY:
return 'quickAction.sendMoney';
case CONST.QUICK_ACTIONS.ASSIGN_TASK:
return 'quickAction.assignTask';
default:
return '' as TranslationPaths;
}
Expand Down
5 changes: 3 additions & 2 deletions src/pages/iou/request/IOURequestStartPage.js
Original file line number Diff line number Diff line change
Expand Up @@ -82,7 +82,7 @@ function IOURequestStartPage({
};
const transactionRequestType = useRef(TransactionUtils.getRequestType(transaction));
const previousIOURequestType = usePrevious(transactionRequestType.current);
const {canUseP2PDistanceRequests} = usePermissions();
const {canUseP2PDistanceRequests} = usePermissions(iouType);
const isFromGlobalCreate = _.isEmpty(report.reportID);

useFocusEffect(
Expand Down Expand Up @@ -110,7 +110,8 @@ function IOURequestStartPage({

const isExpenseChat = ReportUtils.isPolicyExpenseChat(report);
const isExpenseReport = ReportUtils.isExpenseReport(report);
const shouldDisplayDistanceRequest = iouType !== CONST.IOU.TYPE.TRACK_EXPENSE && (canUseP2PDistanceRequests || isExpenseChat || isExpenseReport || isFromGlobalCreate);

const shouldDisplayDistanceRequest = canUseP2PDistanceRequests || isExpenseChat || isExpenseReport || isFromGlobalCreate;

// Allow the user to create the request if we are creating the request in global menu or the report can create the request
const isAllowedToCreateRequest = _.isEmpty(report.reportID) || ReportUtils.canCreateRequest(report, policy, iouType);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -86,7 +86,7 @@ function MoneyTemporaryForRefactorRequestParticipantsSelector({
const referralContentType = iouType === CONST.IOU.TYPE.SEND ? CONST.REFERRAL_PROGRAM.CONTENT_TYPES.SEND_MONEY : CONST.REFERRAL_PROGRAM.CONTENT_TYPES.MONEY_REQUEST;
const {isOffline} = useNetwork();
const personalDetails = usePersonalDetails();
const {canUseP2PDistanceRequests} = usePermissions();
const {canUseP2PDistanceRequests} = usePermissions(iouType);
const {options, areOptionsInitialized} = useOptionsList({
shouldInitialize: didScreenTransitionEnd,
});
Expand Down Expand Up @@ -267,7 +267,10 @@ function MoneyTemporaryForRefactorRequestParticipantsSelector({
// the app from crashing on native when you try to do this, we'll going to hide the button if you have a workspace and other participants
const hasPolicyExpenseChatParticipant = _.some(participants, (participant) => participant.isPolicyExpenseChat);
const shouldShowSplitBillErrorMessage = participants.length > 1 && hasPolicyExpenseChatParticipant;
const isAllowedToSplit = (canUseP2PDistanceRequests || iouRequestType !== CONST.IOU.REQUEST_TYPE.DISTANCE) && iouType !== CONST.IOU.TYPE.SEND;

// canUseP2PDistanceRequests is true if the iouType is track expense, but we don't want to allow splitting distance with track expense yet
const isAllowedToSplit =
(canUseP2PDistanceRequests || iouRequestType !== CONST.IOU.REQUEST_TYPE.DISTANCE) && (iouType !== CONST.IOU.TYPE.SEND || iouType !== CONST.IOU.TYPE.TRACK_EXPENSE);

const handleConfirmSelection = useCallback(
(keyEvent, option) => {
Expand Down
1 change: 1 addition & 0 deletions src/pages/iou/request/step/IOURequestStepConfirmation.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -228,6 +228,7 @@ function IOURequestStepConfirmation({
policyTags,
policyCategories,
gpsPoints,
Object.keys(transaction?.comment?.waypoints ?? {}).length ? TransactionUtils.getValidWaypoints(transaction.comment.waypoints, true) : undefined,
);
},
[report, transaction, currentUserPersonalDetails.login, currentUserPersonalDetails.accountID, transactionTaxCode, transactionTaxAmount, policy, policyTags, policyCategories],
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -85,7 +85,7 @@ function MoneyRequestParticipantsSelector({
const referralContentType = iouType === CONST.IOU.TYPE.SEND ? CONST.REFERRAL_PROGRAM.CONTENT_TYPES.SEND_MONEY : CONST.REFERRAL_PROGRAM.CONTENT_TYPES.MONEY_REQUEST;
const {isOffline} = useNetwork();
const personalDetails = usePersonalDetails();
const {canUseP2PDistanceRequests} = usePermissions();
const {canUseP2PDistanceRequests} = usePermissions(iouType);
const {options, areOptionsInitialized} = useOptionsList();

const maxParticipantsReached = participants.length === CONST.REPORT.MAXIMUM_PARTICIPANTS;
Expand Down Expand Up @@ -259,7 +259,9 @@ function MoneyRequestParticipantsSelector({
// the app from crashing on native when you try to do this, we'll going to show error message if you have a workspace and other participants
const hasPolicyExpenseChatParticipant = _.some(participants, (participant) => participant.isPolicyExpenseChat);
const shouldShowSplitBillErrorMessage = participants.length > 1 && hasPolicyExpenseChatParticipant;
const isAllowedToSplit = (canUseP2PDistanceRequests || !isDistanceRequest) && iouType !== CONST.IOU.TYPE.SEND;

// canUseP2PDistanceRequests is true if the iouType is track expense, but we don't want to allow splitting distance with track expense yet
const isAllowedToSplit = (canUseP2PDistanceRequests || !isDistanceRequest) && (iouType !== CONST.IOU.TYPE.SEND || iouType !== CONST.IOU.TYPE.TRACK_EXPENSE);

const handleConfirmSelection = useCallback(
(keyEvent, option) => {
Expand Down

0 comments on commit 342b16d

Please sign in to comment.