Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
35 commits
Select commit Hold shift + click to select a range
a1688cb
Create time expenses in workspace reports
mhawryluk Dec 19, 2025
c10f99a
Add IS_TIME_TRACKING_ENABLED constant
mhawryluk Dec 22, 2025
44cb7d1
Small improvements to the time expense creation flow
mhawryluk Dec 22, 2025
29d307c
Accept count and rate in requestMoney action for time expenses
mhawryluk Dec 22, 2025
9ac4350
Reorganize translations
mhawryluk Dec 22, 2025
d71fc1e
Merge branch 'main' into feat/create-time-expense-workspace
mhawryluk Dec 22, 2025
7a639a8
Add translations
mhawryluk Dec 23, 2025
c0eeb2d
IOURequestStepHours improvements
mhawryluk Dec 23, 2025
99bef2a
Remove isTimeTrackingEnabled from policy more_features for now
mhawryluk Dec 23, 2025
901fd0d
Small fix
mhawryluk Dec 23, 2025
9502dd3
Show error when clicking next with invalid hour count entered in IOUR…
mhawryluk Dec 23, 2025
0199290
Merge branch 'main' into feat/create-time-expense-workspace
mhawryluk Jan 7, 2026
2de5465
Bring back the time tracking beta
mhawryluk Jan 7, 2026
8e59527
Change computeTimeAmount to treat rate as being a formatted number in…
mhawryluk Jan 7, 2026
c7088fe
Merge branch 'main' into feat/create-time-expense-workspace
mhawryluk Jan 8, 2026
099d0cd
Use convertToBackendAmount for policy rate
mhawryluk Jan 8, 2026
8353fbe
Merge branch 'main' into feat/create-time-expense-workspace
mhawryluk Jan 8, 2026
865ff55
Adjust code for the modified requestMoney api
mhawryluk Jan 8, 2026
be93234
Remove unused import after merge
mhawryluk Jan 8, 2026
9849924
Pass type and unit to buildOptimisticTransaction
mhawryluk Jan 8, 2026
bc5315e
Merge branch 'main' into feat/create-time-expense-workspace
mhawryluk Jan 9, 2026
5ccbf8d
Fix after merge
mhawryluk Jan 9, 2026
e2ccc93
Clear time tab input after switching tabs in Create expense RHP
mhawryluk Jan 9, 2026
73e3a21
Small refactor
mhawryluk Jan 9, 2026
c68ce35
Another tiny IOURequestStepHours refactor
mhawryluk Jan 9, 2026
e56d8ff
Remove unnecessary screen
mhawryluk Jan 9, 2026
2a4eaef
Use constant for hour unit
mhawryluk Jan 9, 2026
1a14e81
Merge branch 'main' into feat/create-time-expense-workspace
mhawryluk Jan 12, 2026
b5cda50
Fix submodule
mhawryluk Jan 12, 2026
232e23d
Implement review suggestions
mhawryluk Jan 12, 2026
aa78697
Merge branch 'main' into feat/create-time-expense-workspace
mhawryluk Jan 12, 2026
8de435e
Fix eslint
mhawryluk Jan 12, 2026
71f7c19
Change copy hours to hour when count equals 1
mhawryluk Jan 12, 2026
9425062
Add updated translations
mhawryluk Jan 12, 2026
0311056
Merge branch 'main' into feat/create-time-expense-workspace
mhawryluk Jan 13, 2026
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
5 changes: 5 additions & 0 deletions src/CONST/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -729,6 +729,7 @@ const CONST = {
IS_TRAVEL_VERIFIED: 'isTravelVerified',
TRAVEL_INVOICING: 'travelInvoicing',
EXPENSIFY_CARD_EU_UK: 'expensifyCardEuUk',
TIME_TRACKING: 'timeTracking',
EUR_BILLING: 'eurBilling',
NO_OPTIMISTIC_TRANSACTION_THREADS: 'noOptimisticTransactionThreads',
UBER_FOR_BUSINESS: 'uberForBusiness',
Expand Down Expand Up @@ -2927,6 +2928,7 @@ const CONST = {
DISTANCE_MANUAL: 'distance-manual',
DISTANCE_GPS: 'distance-gps',
DISTANCE_ODOMETER: 'distance-odometer',
TIME: 'time',
},
EXPENSE_TYPE: {
DISTANCE: 'distance',
Expand All @@ -2939,6 +2941,7 @@ const CONST = {
DISTANCE_MANUAL: 'distance-manual',
DISTANCE_GPS: 'distance-gps',
DISTANCE_ODOMETER: 'distance-odometer',
TIME: 'time',
},

REPORT_ACTION_TYPE: {
Expand Down Expand Up @@ -5522,6 +5525,7 @@ const CONST = {
DISTANCE_MANUAL: 'distance-manual',
DISTANCE_GPS: 'distance-gps',
DISTANCE_ODOMETER: 'distance-odometer',
TIME: 'time',
},

STATUS_TEXT_MAX_LENGTH: 100,
Expand Down Expand Up @@ -6665,6 +6669,7 @@ const CONST = {
MAX_TAX_RATE_DECIMAL_PLACES: 4,
MIN_TAX_RATE_DECIMAL_PLACES: 2,
DISTANCE_DECIMAL_PLACES: 2,
HOURS_DECIMAL_PLACES: 2,

DOWNLOADS_PATH: '/Downloads',
DOWNLOADS_TIMEOUT: 5000,
Expand Down
5 changes: 5 additions & 0 deletions src/ROUTES.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1269,6 +1269,11 @@ const ROUTES = {
getRoute: (action: IOUAction, iouType: IOUType, transactionID: string, reportID: string, backToReport?: string) =>
`create/${iouType as string}/start/${transactionID}/${reportID}/per-diem/${backToReport ?? ''}` as const,
},
MONEY_REQUEST_CREATE_TAB_TIME: {
route: 'time/:backToReport?',
getRoute: (action: IOUAction, iouType: IOUType, transactionID: string, reportID: string, backToReport?: string) =>
`create/${iouType as string}/start/${transactionID}/${reportID}/time/${backToReport ?? ''}` as const,
},

MONEY_REQUEST_RECEIPT_VIEW: {
route: 'receipt-view/:transactionID',
Expand Down
9 changes: 7 additions & 2 deletions src/components/MoneyRequestConfirmationList.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -158,6 +158,9 @@ type MoneyRequestConfirmationListProps = {
/** Whether the expense is a per diem expense */
isPerDiemRequest?: boolean;

/** Whether the expense is a time expense */
isTimeRequest?: boolean;

/** Whether we're editing a split expense */
isEditingSplitBill?: boolean;

Expand Down Expand Up @@ -249,6 +252,7 @@ function MoneyRequestConfirmationList({
iouIsReimbursable = true,
onToggleReimbursable,
showRemoveExpenseConfirmModal,
isTimeRequest = false,
}: MoneyRequestConfirmationListProps) {
const [policyCategoriesReal] = useOnyx(`${ONYXKEYS.COLLECTION.POLICY_CATEGORIES}${policyID}`, {canBeMissing: true});
const [policyTags] = useOnyx(`${ONYXKEYS.COLLECTION.POLICY_TAGS}${policyID}`, {canBeMissing: true});
Expand Down Expand Up @@ -347,7 +351,7 @@ function MoneyRequestConfirmationList({

const policyTagLists = useMemo(() => getTagLists(policyTags), [policyTags]);

const shouldShowTax = isTaxTrackingEnabled(isPolicyExpenseChat, policy, isDistanceRequest, isPerDiemRequest);
const shouldShowTax = isTaxTrackingEnabled(isPolicyExpenseChat, policy, isDistanceRequest, isPerDiemRequest, isTimeRequest);

// Update the tax code when the default changes (for example, because the transaction currency changed)
const defaultTaxCode = getDefaultTaxCode(policy, transaction) ?? '';
Expand Down Expand Up @@ -1233,5 +1237,6 @@ export default memo(
prevProps.hasSmartScanFailed === nextProps.hasSmartScanFailed &&
prevProps.reportActionID === nextProps.reportActionID &&
prevProps.action === nextProps.action &&
prevProps.shouldDisplayReceipt === nextProps.shouldDisplayReceipt,
prevProps.shouldDisplayReceipt === nextProps.shouldDisplayReceipt &&
prevProps.isTimeRequest === nextProps.isTimeRequest,
);
3 changes: 3 additions & 0 deletions src/components/TabSelector/TabSelector.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,7 @@ const MEMOIZED_LAZY_TAB_SELECTOR_ICONS = [
'Percent',
'Crosshair',
'Meter',
'Clock',
] as const;

function getIconTitleAndTestID(
Expand Down Expand Up @@ -95,6 +96,8 @@ function getIconTitleAndTestID(
return {icon: icons.Percent, title: translate('iou.percent'), testID: 'split-percentage'};
case CONST.TAB.SPLIT.DATE:
return {icon: icons.CalendarSolid, title: translate('iou.date'), testID: 'split-date'};
case CONST.TAB_REQUEST.TIME:
return {icon: icons.Clock, title: translate('iou.time'), testID: 'time'};
default:
throw new Error(`Route ${route} has no icon nor title set.`);
}
Expand Down
1 change: 1 addition & 0 deletions src/languages/de.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1466,6 +1466,7 @@ const translations: TranslationDeepObject<typeof en> = {
splitDateRange: ({startDate, endDate, count}: SplitDateRangeParams) => `${startDate} bis ${endDate} (${count} Tage)`,
splitByDate: 'Nach Datum aufteilen',
routedDueToDEW: ({to}: RoutedDueToDEWParams) => `bericht aufgrund eines benutzerdefinierten Genehmigungsworkflows an ${to} weitergeleitet`,
timeTracking: {hoursAt: (hours: number, rate: string) => `${hours} ${hours === 1 ? 'Stunde' : 'Stunden'} @ ${rate} / Stunde`, hrs: 'Std.'},
},
transactionMerge: {
listPage: {
Expand Down
4 changes: 4 additions & 0 deletions src/languages/en.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1446,6 +1446,10 @@ const translations = {
},
chooseWorkspace: 'Choose a workspace',
routedDueToDEW: ({to}: RoutedDueToDEWParams) => `report routed to ${to} due to custom approval workflow`,
timeTracking: {
hoursAt: (hours: number, rate: string) => `${hours} ${hours === 1 ? 'hour' : 'hours'} @ ${rate} / hour`,
hrs: 'hrs',
},
},
transactionMerge: {
listPage: {
Expand Down
4 changes: 4 additions & 0 deletions src/languages/es.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1178,6 +1178,10 @@ const translations: TranslationDeepObject<typeof en> = {
},
chooseWorkspace: 'Elige un espacio de trabajo',
routedDueToDEW: ({to}: RoutedDueToDEWParams) => `informe enviado a ${to} debido a un flujo de aprobación personalizado`,
timeTracking: {
hoursAt: (hours: number, rate: string) => `${hours} ${hours === 1 ? 'hora' : 'horas'} a ${rate} / hora`,
hrs: 'h',
},
},
transactionMerge: {
listPage: {
Expand Down
1 change: 1 addition & 0 deletions src/languages/fr.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1467,6 +1467,7 @@ const translations: TranslationDeepObject<typeof en> = {
splitDateRange: ({startDate, endDate, count}: SplitDateRangeParams) => `Du ${startDate} au ${endDate} (${count} jours)`,
splitByDate: 'Scinder par date',
routedDueToDEW: ({to}: RoutedDueToDEWParams) => `rapport acheminé vers ${to} en raison d'un workflow d'approbation personnalisé`,
timeTracking: {hoursAt: (hours: number, rate: string) => `${hours} ${hours === 1 ? 'heure' : 'heures'} @ ${rate} / heure`, hrs: 'h'},
},
transactionMerge: {
listPage: {
Expand Down
1 change: 1 addition & 0 deletions src/languages/it.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1461,6 +1461,7 @@ const translations: TranslationDeepObject<typeof en> = {
splitDateRange: ({startDate, endDate, count}: SplitDateRangeParams) => `${startDate} a ${endDate} (${count} giorni)`,
splitByDate: 'Dividi per data',
routedDueToDEW: ({to}: RoutedDueToDEWParams) => `rapporto inoltrato a ${to} a causa del flusso di lavoro di approvazione personalizzato`,
timeTracking: {hoursAt: (hours: number, rate: string) => `${hours} ${hours === 1 ? 'ora' : 'ore'} @ ${rate} / ora`, hrs: 'ore'},
},
transactionMerge: {
listPage: {
Expand Down
1 change: 1 addition & 0 deletions src/languages/ja.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1460,6 +1460,7 @@ const translations: TranslationDeepObject<typeof en> = {
splitDateRange: ({startDate, endDate, count}: SplitDateRangeParams) => `${startDate} から ${endDate} まで(${count} 日間)`,
splitByDate: '日付で分割',
routedDueToDEW: ({to}: RoutedDueToDEWParams) => `カスタム承認ワークフローにより、${to} 宛にルーティングされたレポート`,
timeTracking: {hoursAt: (hours: number, rate: string) => `${hours} ${hours === 1 ? '時間' : '時間'} @ ${rate} / 時間`, hrs: '時間'},
},
transactionMerge: {
listPage: {
Expand Down
1 change: 1 addition & 0 deletions src/languages/nl.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1460,6 +1460,7 @@ const translations: TranslationDeepObject<typeof en> = {
splitDateRange: ({startDate, endDate, count}: SplitDateRangeParams) => `${startDate} tot ${endDate} (${count} dagen)`,
splitByDate: 'Splitsen op datum',
routedDueToDEW: ({to}: RoutedDueToDEWParams) => `rapport doorgestuurd naar ${to} vanwege aangepaste goedkeuringsworkflow`,
timeTracking: {hoursAt: (hours: number, rate: string) => `${hours} ${hours === 1 ? 'uur' : 'uren'} @ ${rate} / uur`, hrs: 'uur'},
},
transactionMerge: {
listPage: {
Expand Down
1 change: 1 addition & 0 deletions src/languages/pl.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1458,6 +1458,7 @@ const translations: TranslationDeepObject<typeof en> = {
splitDateRange: ({startDate, endDate, count}: SplitDateRangeParams) => `${startDate} do ${endDate} (${count} dni)`,
splitByDate: 'Podziel według daty',
routedDueToDEW: ({to}: RoutedDueToDEWParams) => `raport przekazany do ${to} z powodu niestandardowego procesu zatwierdzania`,
timeTracking: {hoursAt: (hours: number, rate: string) => `${hours} ${hours === 1 ? 'godzina' : 'godziny'} @ ${rate} / godzinę`, hrs: 'godz.'},
},
transactionMerge: {
listPage: {
Expand Down
1 change: 1 addition & 0 deletions src/languages/pt-BR.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1457,6 +1457,7 @@ const translations: TranslationDeepObject<typeof en> = {
splitDateRange: ({startDate, endDate, count}: SplitDateRangeParams) => `${startDate} a ${endDate} (${count} dias)`,
splitByDate: 'Dividir por data',
routedDueToDEW: ({to}: RoutedDueToDEWParams) => `relatório encaminhado para ${to} devido ao fluxo de trabalho de aprovação personalizado`,
timeTracking: {hoursAt: (hours: number, rate: string) => `${hours} ${hours === 1 ? 'hora' : 'horas'} @ ${rate} / hora`, hrs: 'h'},
},
transactionMerge: {
listPage: {
Expand Down
1 change: 1 addition & 0 deletions src/languages/zh-hans.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1435,6 +1435,7 @@ const translations: TranslationDeepObject<typeof en> = {
splitDateRange: ({startDate, endDate, count}: SplitDateRangeParams) => `${startDate} 至 ${endDate}(${count} 天)`,
splitByDate: '按日期拆分',
routedDueToDEW: ({to}: RoutedDueToDEWParams) => `报告因自定义审批工作流而转发至 ${to}`,
timeTracking: {hoursAt: (hours: number, rate: string) => `${hours} ${hours === 1 ? '小时' : '小时'} @ ${rate} / 小时`, hrs: '小时'},
},
transactionMerge: {
listPage: {
Expand Down
3 changes: 3 additions & 0 deletions src/libs/Navigation/linkingConfig/config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1444,6 +1444,9 @@ const config: LinkingOptions<RootNavigatorParamList>['config'] = {
'per-diem': {
path: ROUTES.MONEY_REQUEST_CREATE_TAB_PER_DIEM.route,
},
time: {
path: ROUTES.MONEY_REQUEST_CREATE_TAB_TIME.route,
},
},
},
[SCREENS.MONEY_REQUEST.DISTANCE_CREATE]: {
Expand Down
11 changes: 11 additions & 0 deletions src/libs/PolicyUtils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@
import {hasSynchronizationErrorMessage, isConnectionUnverified} from './actions/connections';
import {shouldShowQBOReimbursableExportDestinationAccountError} from './actions/connections/QuickbooksOnline';
import {getCategoryApproverRule} from './CategoryUtils';
import {convertToBackendAmount} from './CurrencyUtils';
import Navigation from './Navigation/Navigation';
import {isOffline as isOfflineNetworkStore} from './Network/NetworkStore';
import {formatMemberForList} from './OptionsListUtils';
Expand All @@ -59,7 +60,7 @@

let allPolicies: OnyxCollection<Policy>;

Onyx.connect({

Check warning on line 63 in src/libs/PolicyUtils.ts

View workflow job for this annotation

GitHub Actions / Changed files ESLint check

Onyx.connect() is deprecated. Use useOnyx() hook instead and pass the data as parameters to a pure function
key: ONYXKEYS.COLLECTION.POLICY,
waitForCollectionCallback: true,
callback: (value) => (allPolicies = value),
Expand Down Expand Up @@ -1672,6 +1673,14 @@
];
}

function isTimeTrackingEnabled(policy: OnyxEntry<Policy>): boolean {
return !!policy?.units?.time?.enabled;
}

function getDefaultTimeTrackingRate(policy: Policy): number | undefined {
return policy.units?.time?.rate ? convertToBackendAmount(policy.units?.time?.rate) : undefined;
}

export {
canEditTaxRate,
escapeTagName,
Expand Down Expand Up @@ -1835,6 +1844,8 @@
getTravelStep,
getActivePoliciesWithExpenseChatAndPerDiemEnabledAndHasRates,
isDefaultTagName,
isTimeTrackingEnabled,
getDefaultTimeTrackingRate,
};

export type {MemberEmailsToAccountIDs};
18 changes: 18 additions & 0 deletions src/libs/TimeTrackingUtils.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
import type {LocalizedTranslate} from '@components/LocaleContextProvider';
import {convertToDisplayString} from './CurrencyUtils';

/**
* Computes the transaction amount for given hourly rate (in cents) and hour count.
*/
function computeTimeAmount(rateInCents: number, count: number): number {
return Math.round(rateInCents * count);
}

/**
* Creates an automatic merchant value for time requests.
*/
function formatTimeMerchant(hours: number, rate: number, currency: string, translate: LocalizedTranslate): string {
return translate('iou.timeTracking.hoursAt', hours, convertToDisplayString(rate, currency));
}

export {computeTimeAmount, formatTimeMerchant};
26 changes: 26 additions & 0 deletions src/libs/TransactionUtils/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -114,6 +114,10 @@
distance?: number;
odometerStart?: number;
odometerEnd?: number;
type?: ValueOf<typeof CONST.TRANSACTION.TYPE>;
count?: number;
rate?: number;
unit?: ValueOf<typeof CONST.TIME_TRACKING.UNIT>;
};

type BuildOptimisticTransactionParams = {
Expand All @@ -126,7 +130,7 @@
};

let deprecatedAllReports: OnyxCollection<Report> = {};
Onyx.connect({

Check warning on line 133 in src/libs/TransactionUtils/index.ts

View workflow job for this annotation

GitHub Actions / Changed files ESLint check

Onyx.connect() is deprecated. Use useOnyx() hook instead and pass the data as parameters to a pure function
key: ONYXKEYS.COLLECTION.REPORT,
waitForCollectionCallback: true,
callback: (value) => {
Expand All @@ -135,7 +139,7 @@
});

let deprecatedAllTransactionViolations: OnyxCollection<TransactionViolations> = {};
Onyx.connect({

Check warning on line 142 in src/libs/TransactionUtils/index.ts

View workflow job for this annotation

GitHub Actions / Changed files ESLint check

Onyx.connect() is deprecated. Use useOnyx() hook instead and pass the data as parameters to a pure function
key: ONYXKEYS.COLLECTION.TRANSACTION_VIOLATIONS,
waitForCollectionCallback: true,
callback: (value) => (deprecatedAllTransactionViolations = value),
Expand Down Expand Up @@ -235,6 +239,12 @@
}

function isTimeRequest(transaction: OnyxEntry<Transaction>): boolean {
// This is used during the expense creation flow before the transaction has been saved to the server
if (lodashHas(transaction, 'iouRequestType')) {
return transaction?.iouRequestType === CONST.IOU.REQUEST_TYPE.TIME;
}

// This is the case for transaction objects once they have been saved to the server
return transaction?.comment?.type === CONST.TRANSACTION.TYPE.TIME;
}
Comment on lines 241 to 249
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

should we favor the comment here?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

all the other types favor the iouRequestType. do you think there is a situation where this could be an issue?


Expand All @@ -261,6 +271,9 @@
if (isPerDiemRequest(transaction)) {
return CONST.IOU.REQUEST_TYPE.PER_DIEM;
}
if (isTimeRequest(transaction)) {
return CONST.IOU.REQUEST_TYPE.TIME;
}

return CONST.IOU.REQUEST_TYPE.MANUAL;
}
Expand Down Expand Up @@ -390,6 +403,10 @@
pendingAction = CONST.RED_BRICK_ROAD_PENDING_ACTION.ADD,
odometerStart,
odometerEnd,
type,
count,
rate,
unit,
} = transactionParams;
// transactionIDs are random, positive, 64-bit numeric strings.
// Because JS can only handle 53-bit numbers, transactionIDs are strings in the front-end (just like reportActionID)
Expand Down Expand Up @@ -439,6 +456,15 @@
lodashSet(commentJSON, 'customUnit', customUnit);
}

if (type === CONST.TRANSACTION.TYPE.TIME) {
commentJSON.units = {
count,
rate,
unit,
};
commentJSON.type = type;
}

return {
...(!isEmptyObject(pendingFields) ? {pendingFields} : {}),
transactionID,
Expand Down
18 changes: 18 additions & 0 deletions src/libs/actions/IOU/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -740,7 +740,7 @@
};

let allPersonalDetails: OnyxTypes.PersonalDetailsList = {};
Onyx.connect({

Check warning on line 743 in src/libs/actions/IOU/index.ts

View workflow job for this annotation

GitHub Actions / Changed files ESLint check

Onyx.connect() is deprecated. Use useOnyx() hook instead and pass the data as parameters to a pure function
key: ONYXKEYS.PERSONAL_DETAILS_LIST,
callback: (value) => {
allPersonalDetails = value ?? {};
Expand Down Expand Up @@ -839,7 +839,7 @@
};

let allTransactions: NonNullable<OnyxCollection<OnyxTypes.Transaction>> = {};
Onyx.connect({

Check warning on line 842 in src/libs/actions/IOU/index.ts

View workflow job for this annotation

GitHub Actions / Changed files ESLint check

Onyx.connect() is deprecated. Use useOnyx() hook instead and pass the data as parameters to a pure function
key: ONYXKEYS.COLLECTION.TRANSACTION,
waitForCollectionCallback: true,
callback: (value) => {
Expand All @@ -853,7 +853,7 @@
});

let allTransactionDrafts: NonNullable<OnyxCollection<OnyxTypes.Transaction>> = {};
Onyx.connect({

Check warning on line 856 in src/libs/actions/IOU/index.ts

View workflow job for this annotation

GitHub Actions / Changed files ESLint check

Onyx.connect() is deprecated. Use useOnyx() hook instead and pass the data as parameters to a pure function
key: ONYXKEYS.COLLECTION.TRANSACTION_DRAFT,
waitForCollectionCallback: true,
callback: (value) => {
Expand All @@ -862,7 +862,7 @@
});

let allTransactionViolations: NonNullable<OnyxCollection<OnyxTypes.TransactionViolations>> = {};
Onyx.connect({

Check warning on line 865 in src/libs/actions/IOU/index.ts

View workflow job for this annotation

GitHub Actions / Changed files ESLint check

Onyx.connect() is deprecated. Use useOnyx() hook instead and pass the data as parameters to a pure function
key: ONYXKEYS.COLLECTION.TRANSACTION_VIOLATIONS,
waitForCollectionCallback: true,
callback: (value) => {
Expand All @@ -876,7 +876,7 @@
});

let allNextSteps: NonNullable<OnyxCollection<OnyxTypes.ReportNextStepDeprecated>> = {};
Onyx.connect({

Check warning on line 879 in src/libs/actions/IOU/index.ts

View workflow job for this annotation

GitHub Actions / Changed files ESLint check

Onyx.connect() is deprecated. Use useOnyx() hook instead and pass the data as parameters to a pure function
key: ONYXKEYS.COLLECTION.NEXT_STEP,
waitForCollectionCallback: true,
callback: (value) => {
Expand All @@ -885,7 +885,7 @@
});

let allReports: OnyxCollection<OnyxTypes.Report>;
Onyx.connect({

Check warning on line 888 in src/libs/actions/IOU/index.ts

View workflow job for this annotation

GitHub Actions / Changed files ESLint check

Onyx.connect() is deprecated. Use useOnyx() hook instead and pass the data as parameters to a pure function
key: ONYXKEYS.COLLECTION.REPORT,
waitForCollectionCallback: true,
callback: (value) => {
Expand All @@ -894,7 +894,7 @@
});

let allReportNameValuePairs: OnyxCollection<OnyxTypes.ReportNameValuePairs>;
Onyx.connect({

Check warning on line 897 in src/libs/actions/IOU/index.ts

View workflow job for this annotation

GitHub Actions / Changed files ESLint check

Onyx.connect() is deprecated. Use useOnyx() hook instead and pass the data as parameters to a pure function
key: ONYXKEYS.COLLECTION.REPORT_NAME_VALUE_PAIRS,
waitForCollectionCallback: true,
callback: (value) => {
Expand Down Expand Up @@ -1280,6 +1280,14 @@
Onyx.merge(`${ONYXKEYS.COLLECTION.TRANSACTION_DRAFT}${transactionID}`, {pendingFields});
}

function setMoneyRequestTimeRate(transactionID: string, rate: number, isDraft: boolean) {
Onyx.merge(`${isDraft ? ONYXKEYS.COLLECTION.TRANSACTION_DRAFT : ONYXKEYS.COLLECTION.TRANSACTION}${transactionID}`, {comment: {units: {rate}}});
}

function setMoneyRequestTimeCount(transactionID: string, count: number, isDraft: boolean) {
Onyx.merge(`${isDraft ? ONYXKEYS.COLLECTION.TRANSACTION_DRAFT : ONYXKEYS.COLLECTION.TRANSACTION}${transactionID}`, {comment: {units: {count}}});
}

/**
* Sets the category for a money request transaction draft.
* @param transactionID - The transaction ID
Expand Down Expand Up @@ -3031,6 +3039,10 @@
linkedTrackedExpenseReportAction,
pendingAction,
pendingFields = {},
type,
count,
rate,
unit,
} = transactionParams;

const payerEmail = addSMSDomainIfPhoneNumber(participant.login ?? '');
Expand Down Expand Up @@ -3161,6 +3173,10 @@
pendingAction,
pendingFields: isDistanceRequest && !isManualDistanceRequest ? {waypoints: CONST.RED_BRICK_ROAD_PENDING_ACTION.ADD, ...pendingFields} : pendingFields,
reimbursable: isPolicyExpenseChat ? reimbursable : true,
type,
count,
rate,
unit,
},
isDemoTransactionParam: isSelectedManagerMcTest(participant.login) || transactionParams.receipt?.isTestDriveReceipt,
});
Expand Down Expand Up @@ -14652,6 +14668,8 @@
getUserAccountID,
getReceiptError,
getSearchOnyxUpdate,
setMoneyRequestTimeRate,
setMoneyRequestTimeCount,
};
export type {
GPSPoint as GpsPoint,
Expand Down
2 changes: 2 additions & 0 deletions src/pages/iou/request/IOURequestRedirectToStartPage.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,8 @@ function IOURequestRedirectToStartPage({
Navigation.navigate(ROUTES.DISTANCE_REQUEST_CREATE_TAB_GPS.getRoute(CONST.IOU.ACTION.CREATE, iouType, CONST.IOU.OPTIMISTIC_TRANSACTION_ID, optimisticReportID));
} else if (iouRequestType === CONST.IOU.REQUEST_TYPE.DISTANCE_ODOMETER) {
Navigation.navigate(ROUTES.DISTANCE_REQUEST_CREATE_TAB_ODOMETER.getRoute(CONST.IOU.ACTION.CREATE, iouType, CONST.IOU.OPTIMISTIC_TRANSACTION_ID, optimisticReportID));
} else if (iouRequestType === CONST.IOU.REQUEST_TYPE.TIME) {
Navigation.navigate(ROUTES.MONEY_REQUEST_CREATE_TAB_TIME.getRoute(CONST.IOU.ACTION.CREATE, iouType, CONST.IOU.OPTIMISTIC_TRANSACTION_ID, optimisticReportID));
}

// This useEffect should only run on mount which is why there are no dependencies being passed in the second parameter
Expand Down
Loading
Loading