Skip to content
Merged
Show file tree
Hide file tree
Changes from 11 commits
Commits
Show all changes
20 commits
Select commit Hold shift + click to select a range
8ab23f4
Allow creating time expenses from global menu
mhawryluk Jan 16, 2026
34a3e84
Refactor and fixes
mhawryluk Jan 19, 2026
f6d3ab9
Merge branch 'main' into feat/time-expense-global-create
mhawryluk Jan 19, 2026
49e4c39
Merge branch 'feat/time-confirmation-hours-rate-edit' into feat/time-…
mhawryluk Jan 19, 2026
5eb6205
Fix eslint
mhawryluk Jan 19, 2026
52d9c44
Fix setting reportID on transaction in setMoneyRequestParticipantAsPo…
mhawryluk Jan 19, 2026
704325d
Merge branch 'main' into feat/time-expense-global-create
mhawryluk Jan 19, 2026
eb00d06
Implement review suggestions
mhawryluk Jan 20, 2026
f94caa3
Remove async from saveTime declaration
mhawryluk Jan 20, 2026
97a75f2
Fix reportID
mhawryluk Jan 20, 2026
f35e93e
Fix navigation on iOS when one workspace available in global time tab
mhawryluk Jan 20, 2026
a2579fa
Implement AI reviewer's suggestions
mhawryluk Jan 20, 2026
3f9b62d
Fix prettier
mhawryluk Jan 20, 2026
74a112f
Change IOURequestStepHours headerTitle
mhawryluk Jan 20, 2026
c8ffb45
Remove setMoneyRequestParticipantAsPolicyExpenseChat and refactor
mhawryluk Jan 20, 2026
9638050
Fix polish translation for "rate"
mhawryluk Jan 21, 2026
b18ae23
Merge branch 'main' into feat/time-expense-global-create
mhawryluk Jan 22, 2026
c4d5329
Replace two hours step routes with one route with a url parameter
mhawryluk Jan 22, 2026
9a8f960
Fix eslint
mhawryluk Jan 22, 2026
27b3ef2
Revert "Replace two hours step routes with one route with a url param…
mhawryluk Jan 23, 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/ROUTES.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1318,6 +1318,11 @@ const ROUTES = {
getRoute: (action: IOUAction, iouType: IOUType, transactionID: string | undefined, reportID: string | undefined, reportActionID?: string) =>
`${action as string}/${iouType as string}/hours/${transactionID}/${reportID}${reportActionID ? `/${reportActionID}` : ''}` as const,
},
MONEY_REQUEST_STEP_HOURS_EDIT: {
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Could we use MONEY_REQUEST_STEP_HOURS for the edit flow, like the others? The action parameter already distinguishes between edit and create flows

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

No need a new route

Copy link
Copy Markdown
Contributor Author

@mhawryluk mhawryluk Jan 21, 2026

Choose a reason for hiding this comment

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

in both cases the action parameter is "create", so the urls would be the same. I would need to add another parameter to distinguish between the two. should I?

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Ahh I understand your problem.

Copy link
Copy Markdown
Contributor

@DylanDylann DylanDylann Jan 21, 2026

Choose a reason for hiding this comment

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

@mhawryluk We also get this problem on other expense create flow. And we resolved it by checking the route name. Could you check this conversation and see If we can apply them here?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

the step after selecting a workspace would also be IOURequestStepHours and action "create". it's this one:

Nagranie.z.ekranu.2026-01-21.o.13.37.10.mov

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

@mhawryluk Ahh got it. Could we use transaction.amount or transaction.units.count to distinguish them? Or if impossible, I suggest creating a new parameter for the current route instead of creating a new route

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

I think basing it on transaction properties will not work, because we can go back from the confirmation page and then the transaction is going to be filled out. I will check this, and if that's the case then I will add a new parameter

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Thank you, @mhawryluk. Please ping me when your update is ready.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

@DylanDylann the update is ready

route: ':action/:iouType/hours-edit/:transactionID/:reportID/:reportActionID?',
getRoute: (action: IOUAction, iouType: IOUType, transactionID: string | undefined, reportID: string | undefined, reportActionID?: string) =>
Comment thread
mhawryluk marked this conversation as resolved.
`${action as string}/${iouType as string}/hours-edit/${transactionID}/${reportID}${reportActionID ? `/${reportActionID}` : ''}` as const,
},
DISTANCE_REQUEST_CREATE: {
route: ':action/:iouType/start/:transactionID/:reportID/distance-new/:backToReport?',
getRoute: (action: IOUAction, iouType: IOUType, transactionID: string, reportID: string, backToReport?: string) =>
Expand Down
1 change: 1 addition & 0 deletions src/SCREENS.ts
Original file line number Diff line number Diff line change
Expand Up @@ -334,6 +334,7 @@ const SCREENS = {
RECEIPT_PREVIEW: 'Money_Request_Receipt_preview',
STEP_TIME_RATE: 'Money_Request_Step_Time_Rate',
STEP_HOURS: 'Money_Request_Step_Hours',
STEP_HOURS_EDIT: 'Money_Request_Step_Hours_Edit',
},

TRANSACTION_DUPLICATE: {
Expand Down
2 changes: 1 addition & 1 deletion src/components/MoneyRequestConfirmationListFooter.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -616,7 +616,7 @@ function MoneyRequestConfirmationListFooter({
if (!transactionID) {
return;
}
Navigation.navigate(ROUTES.MONEY_REQUEST_STEP_HOURS.getRoute(action, iouType, transactionID, reportID, reportActionID));
Navigation.navigate(ROUTES.MONEY_REQUEST_STEP_HOURS_EDIT.getRoute(action, iouType, transactionID, reportID, reportActionID));
}}
disabled={didConfirm}
interactive={!isReadOnly}
Expand Down
3 changes: 3 additions & 0 deletions src/libs/IOUUtils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,9 @@ function navigateToStartMoneyRequestStep(requestType: IOURequestType, iouType: I
case CONST.IOU.REQUEST_TYPE.SCAN:
Navigation.goBack(ROUTES.MONEY_REQUEST_CREATE_TAB_SCAN.getRoute(CONST.IOU.ACTION.CREATE, iouType, transactionID, reportID), {compareParams: false});
break;
case CONST.IOU.REQUEST_TYPE.TIME:
Navigation.goBack(ROUTES.MONEY_REQUEST_CREATE_TAB_TIME.getRoute(CONST.IOU.ACTION.CREATE, iouType, transactionID, reportID), {compareParams: false});
break;
default:
Navigation.goBack(ROUTES.MONEY_REQUEST_CREATE_TAB_MANUAL.getRoute(CONST.IOU.ACTION.CREATE, iouType, transactionID, reportID), {compareParams: false});
break;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -187,6 +187,7 @@ const MoneyRequestModalStackNavigator = createModalStackNavigator<MoneyRequestNa
[SCREENS.SET_DEFAULT_WORKSPACE]: () => require<ReactComponentModule>('../../../../pages/SetDefaultWorkspacePage').default,
[SCREENS.MONEY_REQUEST.STEP_TIME_RATE]: () => require<ReactComponentModule>('../../../../pages/iou/request/step/IOURequestStepTimeRate').default,
[SCREENS.MONEY_REQUEST.STEP_HOURS]: () => require<ReactComponentModule>('../../../../pages/iou/request/step/IOURequestStepHours').default,
[SCREENS.MONEY_REQUEST.STEP_HOURS_EDIT]: () => require<ReactComponentModule>('../../../../pages/iou/request/step/IOURequestStepHours').default,
});

const TravelModalStackNavigator = createModalStackNavigator<TravelNavigatorParamList>({
Expand Down
1 change: 1 addition & 0 deletions src/libs/Navigation/linkingConfig/config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1525,6 +1525,7 @@ const config: LinkingOptions<RootNavigatorParamList>['config'] = {
[SCREENS.MONEY_REQUEST.STEP_SUBRATE_EDIT]: ROUTES.MONEY_REQUEST_STEP_SUBRATE_EDIT.route,
[SCREENS.MONEY_REQUEST.STEP_TIME_RATE]: ROUTES.MONEY_REQUEST_STEP_TIME_RATE.route,
[SCREENS.MONEY_REQUEST.STEP_HOURS]: ROUTES.MONEY_REQUEST_STEP_HOURS.route,
[SCREENS.MONEY_REQUEST.STEP_HOURS_EDIT]: ROUTES.MONEY_REQUEST_STEP_HOURS_EDIT.route,
[SCREENS.IOU_SEND.ENABLE_PAYMENTS]: ROUTES.IOU_SEND_ENABLE_PAYMENTS,
[SCREENS.IOU_SEND.ADD_BANK_ACCOUNT]: ROUTES.IOU_SEND_ADD_BANK_ACCOUNT,
[SCREENS.IOU_SEND.ADD_DEBIT_CARD]: ROUTES.IOU_SEND_ADD_DEBIT_CARD,
Expand Down
7 changes: 7 additions & 0 deletions src/libs/Navigation/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1958,6 +1958,13 @@ type MoneyRequestNavigatorParamList = {
reportID: string;
reportActionID: string;
};
[SCREENS.MONEY_REQUEST.STEP_HOURS_EDIT]: {
action: IOUAction;
iouType: Exclude<IOUType, typeof CONST.IOU.TYPE.REQUEST | typeof CONST.IOU.TYPE.SEND>;
transactionID: string;
reportID: string;
reportActionID: string;
};
};

type WorkspaceConfirmationNavigatorParamList = {
Expand Down
5 changes: 5 additions & 0 deletions src/libs/PolicyUtils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -60,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 @@ -107,6 +107,10 @@
});
}

function getActivePoliciesWithExpenseChatAndTimeEnabled(policies: OnyxCollection<Policy> | null, currentUserLogin: string | undefined): Policy[] {
return getActivePoliciesWithExpenseChat(policies, currentUserLogin).filter(isTimeTrackingEnabled);
}

/**
* Checks if the current user is an admin of the policy.
*/
Expand Down Expand Up @@ -1846,6 +1850,7 @@
isDefaultTagName,
isTimeTrackingEnabled,
getDefaultTimeTrackingRate,
getActivePoliciesWithExpenseChatAndTimeEnabled,
};

export type {MemberEmailsToAccountIDs};
37 changes: 37 additions & 0 deletions src/libs/actions/IOU/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -150,6 +150,7 @@
getOutstandingChildRequest,
getParsedComment,
getPersonalDetailsForAccountID,
getPolicyExpenseChat,
getReportNotificationPreference,
getReportOrDraftReport,
getReportRecipientAccountIDs,
Expand Down Expand Up @@ -756,7 +757,7 @@
tag: string | undefined;
currency: string;
taxCode: string;
taxAmount: number;

Check warning on line 760 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
shouldPlaySound?: boolean;
policyRecentlyUsedCategories?: OnyxEntry<OnyxTypes.RecentlyUsedCategories>;
policyRecentlyUsedTags: OnyxEntry<RecentlyUsedTags>;
Expand Down Expand Up @@ -858,7 +859,7 @@
callback: (value) => {
allTransactionDrafts = value ?? {};
},
});

Check warning on line 862 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

let allTransactionViolations: NonNullable<OnyxCollection<OnyxTypes.TransactionViolations>> = {};
Onyx.connect({
Expand All @@ -872,7 +873,7 @@

allTransactionViolations = value;
},
});

Check warning on line 876 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

let allReports: OnyxCollection<OnyxTypes.Report>;
Onyx.connect({
Expand All @@ -881,7 +882,7 @@
callback: (value) => {
allReports = value;
},
});

Check warning on line 885 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

let allReportNameValuePairs: OnyxCollection<OnyxTypes.ReportNameValuePairs>;
Onyx.connect({
Expand All @@ -895,7 +896,7 @@
let userAccountID = -1;
let currentUserEmail = '';
Onyx.connect({
key: ONYXKEYS.SESSION,

Check warning on line 899 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
callback: (value) => {
currentUserEmail = value?.email ?? '';
userAccountID = value?.accountID ?? CONST.DEFAULT_NUMBER_ID;
Expand All @@ -904,7 +905,7 @@

let deprecatedCurrentUserPersonalDetails: OnyxEntry<OnyxTypes.PersonalDetails>;
Onyx.connect({
key: ONYXKEYS.PERSONAL_DETAILS_LIST,

Check warning on line 908 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
callback: (value) => {
deprecatedCurrentUserPersonalDetails = value?.[userAccountID] ?? undefined;
},
Expand All @@ -914,7 +915,7 @@
Onyx.connect({
key: ONYXKEYS.COLLECTION.REPORT_ACTIONS,
waitForCollectionCallback: true,
callback: (actions) => {

Check warning on line 918 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
if (!actions) {
return;
}
Expand All @@ -923,7 +924,7 @@
});

let personalDetailsList: OnyxEntry<OnyxTypes.PersonalDetailsList>;
Onyx.connect({

Check warning on line 927 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) => (personalDetailsList = value),
});
Expand All @@ -931,7 +932,7 @@
// Use connectWithoutView because this is created for non-UI task only
let recentAttendees: OnyxEntry<Attendee[]>;
Onyx.connectWithoutView({
key: ONYXKEYS.NVP_RECENT_ATTENDEES,

Check warning on line 935 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
callback: (value) => (recentAttendees = value),
});

Expand Down Expand Up @@ -11918,6 +11919,41 @@
});
}

/**
* Sets transaction's participant and reportID to the policy's expense chat.
* Returns the policy expense chat reportID.
*/
function setMoneyRequestParticipantAsPolicyExpenseChat({
transactionID,
policyID,
currentUserAccountID,
isDraft,
participantsAutoAssigned,
}: {
transactionID: string;
policyID: string;
currentUserAccountID: number;
isDraft: boolean;
participantsAutoAssigned?: boolean;
}) {
const policyExpenseChatReportID = getPolicyExpenseChat(currentUserAccountID, policyID)?.reportID;
Onyx.merge(`${isDraft ? ONYXKEYS.COLLECTION.TRANSACTION_DRAFT : ONYXKEYS.COLLECTION.TRANSACTION}${transactionID}`, {
reportID: policyExpenseChatReportID,
participants: [
Comment thread
mhawryluk marked this conversation as resolved.
Outdated
Comment thread
mhawryluk marked this conversation as resolved.
Outdated
{
selected: true,
accountID: 0,
isPolicyExpenseChat: true,
reportID: policyExpenseChatReportID,
policyID,
},
],
participantsAutoAssigned,
});

return policyExpenseChatReportID;
}

function setMoneyRequestTaxRate(transactionID: string, taxCode: string | null) {
Onyx.merge(`${ONYXKEYS.COLLECTION.TRANSACTION_DRAFT}${transactionID}`, {taxCode});
}
Expand Down Expand Up @@ -14410,6 +14446,7 @@
getSearchOnyxUpdate,
setMoneyRequestTimeRate,
setMoneyRequestTimeCount,
setMoneyRequestParticipantAsPolicyExpenseChat,
};
export type {
GPSPoint as GpsPoint,
Expand Down
27 changes: 22 additions & 5 deletions src/pages/iou/request/IOURequestStartPage.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ import {getIsUserSubmittedExpenseOrScannedReceipt} from '@libs/OptionsListUtils'
import Performance from '@libs/Performance';
import {
getActivePoliciesWithExpenseChatAndPerDiemEnabledAndHasRates,
getActivePoliciesWithExpenseChatAndTimeEnabled,
getPerDiemCustomUnit,
hasOnlyPersonalPolicies as hasOnlyPersonalPoliciesUtil,
isTimeTrackingEnabled,
Expand All @@ -50,6 +51,7 @@ import IOURequestStepDistance from './step/IOURequestStepDistance';
import IOURequestStepHours from './step/IOURequestStepHours';
import IOURequestStepPerDiemWorkspace from './step/IOURequestStepPerDiemWorkspace';
import IOURequestStepScan from './step/IOURequestStepScan';
import IOURequestStepTimeWorkspace from './step/IOURequestStepTimeWorkspace';
import type {WithWritableReportOrNotFoundProps} from './step/withWritableReportOrNotFound';

type IOURequestStartPageProps = WithWritableReportOrNotFoundProps<typeof SCREENS.MONEY_REQUEST.CREATE> & {
Expand Down Expand Up @@ -111,6 +113,10 @@ function IOURequestStartPage({
() => getActivePoliciesWithExpenseChatAndPerDiemEnabledAndHasRates(allPolicies, currentUserPersonalDetails.login),
[allPolicies, currentUserPersonalDetails.login],
);
const policiesWithTimeEnabled = useMemo(
() => getActivePoliciesWithExpenseChatAndTimeEnabled(allPolicies, currentUserPersonalDetails.login),
[allPolicies, currentUserPersonalDetails.login],
);
const doesPerDiemPolicyExist = policiesWithPerDiemEnabledAndHasRates.length > 0;
const moreThanOnePerDiemExist = policiesWithPerDiemEnabledAndHasRates.length > 1;
const hasCurrentPolicyPerDiemEnabled = !!policy?.arePerDiemRatesEnabled;
Expand Down Expand Up @@ -247,7 +253,10 @@ function IOURequestStartPage({
},
},
);
const shouldShowTimeOption = isBetaEnabled(CONST.BETAS.TIME_TRACKING) && iouType === CONST.IOU.TYPE.SUBMIT && !isFromGlobalCreate && hasCurrentPolicyTimeTrackingEnabled;
const shouldShowTimeOption =
isBetaEnabled(CONST.BETAS.TIME_TRACKING) &&
(iouType === CONST.IOU.TYPE.SUBMIT || iouType === CONST.IOU.TYPE.CREATE) &&
((!isFromGlobalCreate && hasCurrentPolicyTimeTrackingEnabled) || (isFromGlobalCreate && !!policiesWithTimeEnabled.length));

const onBackButtonPress = () => {
navigateBack();
Expand Down Expand Up @@ -360,10 +369,18 @@ function IOURequestStartPage({
<TopTab.Screen name={CONST.TAB_REQUEST.TIME}>
{() => (
<TabScreenWithFocusTrapWrapper>
<IOURequestStepHours
route={route}
navigation={navigation}
/>
{isFromGlobalCreate && policiesWithTimeEnabled.length > 1 ? (
<IOURequestStepTimeWorkspace
route={route}
navigation={navigation}
/>
) : (
<IOURequestStepHours
route={route}
navigation={navigation}
explicitPolicyID={isFromGlobalCreate ? policiesWithTimeEnabled.at(0)?.id : undefined}
/>
)}
</TabScreenWithFocusTrapWrapper>
)}
</TopTab.Screen>
Expand Down
108 changes: 108 additions & 0 deletions src/pages/iou/request/step/BaseRequestStepWorkspace.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,108 @@
import React from 'react';
import {View} from 'react-native';
import type {OnyxCollection} from 'react-native-onyx';
import SearchBar from '@components/SearchBar';
import SelectionList from '@components/SelectionList';
import type {ListItem} from '@components/SelectionList/ListItem/types';
import UserListItem from '@components/SelectionList/ListItem/UserListItem';
import Text from '@components/Text';
import useCurrentUserPersonalDetails from '@hooks/useCurrentUserPersonalDetails';
import {useMemoizedLazyExpensifyIcons} from '@hooks/useLazyAsset';
import useLocalize from '@hooks/useLocalize';
import useOnyx from '@hooks/useOnyx';
import useSearchResults from '@hooks/useSearchResults';
import useThemeStyles from '@hooks/useThemeStyles';
import {sortWorkspacesBySelected} from '@libs/PolicyUtils';
import {getDefaultWorkspaceAvatar} from '@libs/ReportUtils';
import tokenizedSearch from '@libs/tokenizedSearch';
import CONST from '@src/CONST';
import ONYXKEYS from '@src/ONYXKEYS';
import type SCREENS from '@src/SCREENS';
import type {Policy} from '@src/types/onyx';
import type {WithFullTransactionOrNotFoundProps} from './withFullTransactionOrNotFound';
import withFullTransactionOrNotFound from './withFullTransactionOrNotFound';

type WorkspaceListItem = ListItem & {
value: string;
};

type BaseRequestStepWorkspaceProps = WithFullTransactionOrNotFoundProps<typeof SCREENS.MONEY_REQUEST.CREATE> & {
/** Function returning available workspaces for the list. */
getPolicies: (allPolicies: OnyxCollection<Policy>, currentUserLogin: string | undefined) => Policy[];

/** Function to run after selecting a workspace. */
onSelectWorkspace: (item: WorkspaceListItem, allPolicies: OnyxCollection<Policy>) => void;
};

function BaseRequestStepWorkspace({transaction, getPolicies, onSelectWorkspace}: BaseRequestStepWorkspaceProps) {
const icons = useMemoizedLazyExpensifyIcons(['FallbackWorkspaceAvatar']);
const styles = useThemeStyles();
const {translate, localeCompare} = useLocalize();

const {login: currentUserLogin} = useCurrentUserPersonalDetails();
const [allPolicies] = useOnyx(ONYXKEYS.COLLECTION.POLICY, {canBeMissing: true});
const selectedWorkspace = transaction?.participants?.[0];
const availableWorkspaces = getPolicies(allPolicies, currentUserLogin);
const workspaceOptions: WorkspaceListItem[] = availableWorkspaces
.sort((policy1, policy2) =>
sortWorkspacesBySelected(
{policyID: policy1.id, name: policy1.name},
{policyID: policy2.id, name: policy2.name},
selectedWorkspace?.policyID ? [selectedWorkspace?.policyID] : [],
localeCompare,
),
)
.map((policy) => ({
text: policy.name,
value: policy.id,
keyForList: policy.id,
icons: [
{
id: policy.id,
source: policy?.avatarURL ? policy.avatarURL : getDefaultWorkspaceAvatar(policy.name),
fallbackIcon: icons.FallbackWorkspaceAvatar,
name: policy.name,
type: CONST.ICON_TYPE_WORKSPACE,
},
],
isSelected: selectedWorkspace?.policyID === policy.id,
}));

const filterWorkspace = (workspaceOption: WorkspaceListItem, searchInput: string) => {
Comment thread
grgia marked this conversation as resolved.
const results = tokenizedSearch([workspaceOption], searchInput, (option) => [option.text ?? '']);
return results.length > 0;
};
const sortWorkspaces = (data: WorkspaceListItem[]) => data.sort((a, b) => localeCompare(a.text ?? '', b?.text ?? ''));
const [inputValue, setInputValue, filteredWorkspaceOptions] = useSearchResults(workspaceOptions, filterWorkspace, sortWorkspaces);

const selectWorkspace = (item: WorkspaceListItem) => {
onSelectWorkspace(item, allPolicies);
};

return (
<>
{workspaceOptions.length > CONST.SEARCH_ITEM_LIMIT ? (
<SearchBar
label={translate('workspace.common.findWorkspace')}
inputValue={inputValue}
onChangeText={setInputValue}
shouldShowEmptyState={workspaceOptions.length > 0 && filteredWorkspaceOptions.length === 0}
/>
) : (
<View style={[styles.optionsListSectionHeader]}>
<Text style={[styles.ph5, styles.textLabelSupporting]}>{translate('iou.chooseWorkspace')}</Text>
</View>
)}
<SelectionList
key={selectedWorkspace?.policyID}
data={filteredWorkspaceOptions}
onSelectRow={selectWorkspace}
shouldSingleExecuteRowSelect
ListItem={UserListItem}
initiallyFocusedItemKey={selectedWorkspace?.policyID}
/>
</>
);
}

export default withFullTransactionOrNotFound(BaseRequestStepWorkspace);
4 changes: 0 additions & 4 deletions src/pages/iou/request/step/IOURequestStepConfirmation.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -436,9 +436,6 @@ function IOURequestStepConfirmation({
Navigation.goBack(ROUTES.MONEY_REQUEST_STEP_SUBRATE.getRoute(action, iouType, initialTransactionID, reportID));
return;
}
if (isTimeRequest) {
return Navigation.goBack(ROUTES.MONEY_REQUEST_CREATE_TAB_TIME.getRoute(action, iouType, initialTransactionID, reportID));
}
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Why remove this block?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

this block was unnecessary, the function should correctly handle navigation without it. I added it because I noticed the navigation wasn't correct and I was inspired by perDiem, but it turned out this block introduced some bugs and the thing that was missing was adding support for "time" type in navigateToStartMoneyRequestStep

this change was already merged here: https://github.com/Expensify/App/pull/79673/files


if (transaction?.isFromGlobalCreate && !transaction.receipt?.isTestReceipt) {
// If the participants weren't automatically added to the transaction, then we should go back to the IOURequestStepParticipants.
Expand Down Expand Up @@ -480,7 +477,6 @@ function IOURequestStepConfirmation({
isMovingTransactionFromTrackExpense,
participantsAutoAssignedFromRoute,
backTo,
isTimeRequest,
]);

// When the component mounts, if there is a receipt, see if the image can be read from the disk. If not, redirect the user to the starting step of the flow.
Expand Down
Loading
Loading