From a33274b0f14aca64e8b9d5d337efac86670249f2 Mon Sep 17 00:00:00 2001
From: Blazej Kustra <blazej.kustra@swmansion.com>
Date: Wed, 20 Nov 2024 10:11:36 +0100
Subject: [PATCH 01/75] Create trip details screen

---
 src/ROUTES.ts                                 |  4 +++
 src/SCREENS.ts                                |  1 +
 .../ModalStackNavigators/index.tsx            |  1 +
 src/libs/Navigation/linkingConfig/config.ts   |  1 +
 src/pages/Travel/TripDetails.tsx              | 36 +++++++++++++++++++
 5 files changed, 43 insertions(+)
 create mode 100644 src/pages/Travel/TripDetails.tsx

diff --git a/src/ROUTES.ts b/src/ROUTES.ts
index d8f8b0f91105..f324d4af6d2e 100644
--- a/src/ROUTES.ts
+++ b/src/ROUTES.ts
@@ -1343,6 +1343,10 @@ const ROUTES = {
     TRAVEL_MY_TRIPS: 'travel',
     TRAVEL_TCS: 'travel/terms',
     TRACK_TRAINING_MODAL: 'track-training',
+    TRAVEL_TRIP_DETAILS: {
+        route: 'r/:reportID/trip/:transactionID',
+        getRoute: (reportID: string, transactionID: string) => `r/${reportID}/trip/${transactionID}` as const,
+    },
     ONBOARDING_ROOT: {
         route: 'onboarding',
         getRoute: (backTo?: string) => getUrlWithBackToParam(`onboarding`, backTo),
diff --git a/src/SCREENS.ts b/src/SCREENS.ts
index 5fd64b0fc0d0..f6a53da3f199 100644
--- a/src/SCREENS.ts
+++ b/src/SCREENS.ts
@@ -27,6 +27,7 @@ const SCREENS = {
     TRAVEL: {
         MY_TRIPS: 'Travel_MyTrips',
         TCS: 'Travel_TCS',
+        TRIP_DETAILS: 'Trip_Details',
     },
     SEARCH: {
         CENTRAL_PANE: 'Search_Central_Pane',
diff --git a/src/libs/Navigation/AppNavigator/ModalStackNavigators/index.tsx b/src/libs/Navigation/AppNavigator/ModalStackNavigators/index.tsx
index 9295281755e5..05bec49e9bd9 100644
--- a/src/libs/Navigation/AppNavigator/ModalStackNavigators/index.tsx
+++ b/src/libs/Navigation/AppNavigator/ModalStackNavigators/index.tsx
@@ -105,6 +105,7 @@ const MoneyRequestModalStackNavigator = createModalStackNavigator<MoneyRequestNa
 const TravelModalStackNavigator = createModalStackNavigator<TravelNavigatorParamList>({
     [SCREENS.TRAVEL.MY_TRIPS]: () => require<ReactComponentModule>('../../../../pages/Travel/MyTripsPage').default,
     [SCREENS.TRAVEL.TCS]: () => require<ReactComponentModule>('../../../../pages/Travel/TravelTerms').default,
+    [SCREENS.TRAVEL.TRIP_DETAILS]: () => require<ReactComponentModule>('../../../pages/TripDetails').default,
 });
 
 const SplitDetailsModalStackNavigator = createModalStackNavigator<SplitDetailsNavigatorParamList>({
diff --git a/src/libs/Navigation/linkingConfig/config.ts b/src/libs/Navigation/linkingConfig/config.ts
index 476711c7c116..2d1511789c24 100644
--- a/src/libs/Navigation/linkingConfig/config.ts
+++ b/src/libs/Navigation/linkingConfig/config.ts
@@ -1320,6 +1320,7 @@ const config: LinkingOptions<RootStackParamList>['config'] = {
                     screens: {
                         [SCREENS.TRAVEL.MY_TRIPS]: ROUTES.TRAVEL_MY_TRIPS,
                         [SCREENS.TRAVEL.TCS]: ROUTES.TRAVEL_TCS,
+                        [SCREENS.TRAVEL.TRIP_DETAILS]: ROUTES.TRAVEL_TRIP_DETAILS,
                     },
                 },
                 [SCREENS.RIGHT_MODAL.SEARCH_REPORT]: {
diff --git a/src/pages/Travel/TripDetails.tsx b/src/pages/Travel/TripDetails.tsx
new file mode 100644
index 000000000000..8c3d1bbadfc1
--- /dev/null
+++ b/src/pages/Travel/TripDetails.tsx
@@ -0,0 +1,36 @@
+import React from 'react';
+import {NativeModules} from 'react-native';
+import FullPageNotFoundView from '@components/BlockingViews/FullPageNotFoundView';
+import HeaderWithBackButton from '@components/HeaderWithBackButton';
+import ScreenWrapper from '@components/ScreenWrapper';
+import useLocalize from '@hooks/useLocalize';
+import usePermissions from '@hooks/usePermissions';
+
+function TripDetails() {
+    const {translate} = useLocalize();
+    const {canUseSpotnanaTravel} = usePermissions();
+
+    return (
+        <ScreenWrapper
+            includeSafeAreaPaddingBottom={false}
+            shouldEnablePickerAvoiding={false}
+            shouldEnableMaxHeight
+            testID={TripDetails.displayName}
+            shouldShowOfflineIndicatorInWideScreen
+        >
+            <FullPageNotFoundView
+                shouldForceFullScreen
+                shouldShow={!canUseSpotnanaTravel && !NativeModules.HybridAppModule}
+            >
+                <HeaderWithBackButton
+                    title={translate('travel.header')}
+                    shouldShowBackButton
+                />
+            </FullPageNotFoundView>
+        </ScreenWrapper>
+    );
+}
+
+TripDetails.displayName = 'TripDetails';
+
+export default TripDetails;

From 15c9ae36fc845f298078a1f28939064158088b7b Mon Sep 17 00:00:00 2001
From: Blazej Kustra <blazej.kustra@swmansion.com>
Date: Wed, 20 Nov 2024 10:11:49 +0100
Subject: [PATCH 02/75] Add translation for trip support

---
 src/languages/en.ts | 1 +
 src/languages/es.ts | 1 +
 2 files changed, 2 insertions(+)

diff --git a/src/languages/en.ts b/src/languages/en.ts
index c1067e195985..ec0e49353bbb 100755
--- a/src/languages/en.ts
+++ b/src/languages/en.ts
@@ -2424,6 +2424,7 @@ const translations = {
         hotel: 'Hotel',
         car: 'Car',
         viewTrip: 'View trip',
+        tripSupport: 'Trip support',
         viewTripDetails: 'View trip details',
         trip: 'Trip',
         trips: 'Trips',
diff --git a/src/languages/es.ts b/src/languages/es.ts
index f7af1be45139..623afb1ff16a 100644
--- a/src/languages/es.ts
+++ b/src/languages/es.ts
@@ -2448,6 +2448,7 @@ const translations = {
         hotel: 'Hotel',
         car: 'Auto',
         viewTrip: 'Ver viaje',
+        tripSupport: 'Soporte de Viaje',
         viewTripDetails: 'Ver detalles del viaje',
         trip: 'Viaje',
         trips: 'Viajes',

From 3ae7f986f7fee31a3f065e2b2be31aece0c3ed49 Mon Sep 17 00:00:00 2001
From: Blazej Kustra <blazej.kustra@swmansion.com>
Date: Wed, 20 Nov 2024 10:16:31 +0100
Subject: [PATCH 03/75] Add undefined type for trip details

---
 src/libs/Navigation/types.ts | 1 +
 1 file changed, 1 insertion(+)

diff --git a/src/libs/Navigation/types.ts b/src/libs/Navigation/types.ts
index 5877c9c10218..caa5ff5d1a06 100644
--- a/src/libs/Navigation/types.ts
+++ b/src/libs/Navigation/types.ts
@@ -1380,6 +1380,7 @@ type RightModalNavigatorParamList = {
 
 type TravelNavigatorParamList = {
     [SCREENS.TRAVEL.MY_TRIPS]: undefined;
+    [SCREENS.TRAVEL.TRIP_DETAILS]: undefined;
 };
 
 type FullScreenNavigatorParamList = {

From d2e1df5cf70c7bf112174a58369352fff890b69e Mon Sep 17 00:00:00 2001
From: Blazej Kustra <blazej.kustra@swmansion.com>
Date: Wed, 20 Nov 2024 12:39:33 +0100
Subject: [PATCH 04/75] Fix navigation config

---
 src/libs/Navigation/AppNavigator/ModalStackNavigators/index.tsx | 2 +-
 src/libs/Navigation/linkingConfig/config.ts                     | 2 +-
 2 files changed, 2 insertions(+), 2 deletions(-)

diff --git a/src/libs/Navigation/AppNavigator/ModalStackNavigators/index.tsx b/src/libs/Navigation/AppNavigator/ModalStackNavigators/index.tsx
index 05bec49e9bd9..beb030ccb09d 100644
--- a/src/libs/Navigation/AppNavigator/ModalStackNavigators/index.tsx
+++ b/src/libs/Navigation/AppNavigator/ModalStackNavigators/index.tsx
@@ -105,7 +105,7 @@ const MoneyRequestModalStackNavigator = createModalStackNavigator<MoneyRequestNa
 const TravelModalStackNavigator = createModalStackNavigator<TravelNavigatorParamList>({
     [SCREENS.TRAVEL.MY_TRIPS]: () => require<ReactComponentModule>('../../../../pages/Travel/MyTripsPage').default,
     [SCREENS.TRAVEL.TCS]: () => require<ReactComponentModule>('../../../../pages/Travel/TravelTerms').default,
-    [SCREENS.TRAVEL.TRIP_DETAILS]: () => require<ReactComponentModule>('../../../pages/TripDetails').default,
+    [SCREENS.TRAVEL.TRIP_DETAILS]: () => require<ReactComponentModule>('../../../../pages/Travel/TripDetails').default,
 });
 
 const SplitDetailsModalStackNavigator = createModalStackNavigator<SplitDetailsNavigatorParamList>({
diff --git a/src/libs/Navigation/linkingConfig/config.ts b/src/libs/Navigation/linkingConfig/config.ts
index 2d1511789c24..317c1e15e04f 100644
--- a/src/libs/Navigation/linkingConfig/config.ts
+++ b/src/libs/Navigation/linkingConfig/config.ts
@@ -1320,7 +1320,7 @@ const config: LinkingOptions<RootStackParamList>['config'] = {
                     screens: {
                         [SCREENS.TRAVEL.MY_TRIPS]: ROUTES.TRAVEL_MY_TRIPS,
                         [SCREENS.TRAVEL.TCS]: ROUTES.TRAVEL_TCS,
-                        [SCREENS.TRAVEL.TRIP_DETAILS]: ROUTES.TRAVEL_TRIP_DETAILS,
+                        [SCREENS.TRAVEL.TRIP_DETAILS]: ROUTES.TRAVEL_TRIP_DETAILS.route,
                     },
                 },
                 [SCREENS.RIGHT_MODAL.SEARCH_REPORT]: {

From 7394a09389a39b499723e05548285e930ea34b9f Mon Sep 17 00:00:00 2001
From: Blazej Kustra <blazej.kustra@swmansion.com>
Date: Fri, 22 Nov 2024 14:19:35 +0100
Subject: [PATCH 05/75] Link the correct backTo on trip details screen

---
 src/ROUTES.ts                                        |  2 +-
 src/components/ReportActionItem/MoneyRequestView.tsx | 10 +++-------
 2 files changed, 4 insertions(+), 8 deletions(-)

diff --git a/src/ROUTES.ts b/src/ROUTES.ts
index f324d4af6d2e..920e328ebfff 100644
--- a/src/ROUTES.ts
+++ b/src/ROUTES.ts
@@ -1345,7 +1345,7 @@ const ROUTES = {
     TRACK_TRAINING_MODAL: 'track-training',
     TRAVEL_TRIP_DETAILS: {
         route: 'r/:reportID/trip/:transactionID',
-        getRoute: (reportID: string, transactionID: string) => `r/${reportID}/trip/${transactionID}` as const,
+        getRoute: (reportID: string, transactionID: string, backTo?: string) => getUrlWithBackToParam(`r/${reportID}/trip/${transactionID}`, backTo),
     },
     ONBOARDING_ROOT: {
         route: 'onboarding',
diff --git a/src/components/ReportActionItem/MoneyRequestView.tsx b/src/components/ReportActionItem/MoneyRequestView.tsx
index 381f01aadd89..1533a7515a98 100644
--- a/src/components/ReportActionItem/MoneyRequestView.tsx
+++ b/src/components/ReportActionItem/MoneyRequestView.tsx
@@ -34,7 +34,6 @@ import ViolationsUtils from '@libs/Violations/ViolationsUtils';
 import Navigation from '@navigation/Navigation';
 import AnimatedEmptyStateBackground from '@pages/home/report/AnimatedEmptyStateBackground';
 import * as IOU from '@userActions/IOU';
-import * as Link from '@userActions/Link';
 import * as Transaction from '@userActions/Transaction';
 import CONST from '@src/CONST';
 import type {TranslationPaths} from '@src/languages/types';
@@ -84,7 +83,6 @@ function MoneyRequestView({report, shouldShowAnimatedBackground, readonly = fals
     const session = useSession();
     const {isOffline} = useNetwork();
     const {translate, toLocaleDigit} = useLocalize();
-    const [activePolicyID] = useOnyx(ONYXKEYS.NVP_ACTIVE_POLICY_ID);
     const parentReportID = report?.parentReportID ?? '-1';
     const policyID = report?.policyID ?? '-1';
     const [parentReport] = useOnyx(`${ONYXKEYS.COLLECTION.REPORT}${parentReportID}`);
@@ -696,11 +694,9 @@ function MoneyRequestView({report, shouldShowAnimatedBackground, readonly = fals
                     <MenuItem
                         title={translate('travel.viewTripDetails')}
                         icon={Expensicons.Suitcase}
-                        iconRight={Expensicons.NewWindow}
-                        shouldShowRightIcon
-                        onPress={() => {
-                            Link.openTravelDotLink(activePolicyID, CONST.TRIP_ID_PATH(tripID));
-                        }}
+                        onPress={() =>
+                            Navigation.navigate(ROUTES.TRAVEL_TRIP_DETAILS.getRoute(report?.reportID ?? '-1', transaction?.transactionID ?? '-1', Navigation.getReportRHPActiveRoute()))
+                        }
                     />
                 )}
                 {shouldShowAttendees && (

From 2c9d2a8c72caa65b5b28a7f5a2294ae00ea975d5 Mon Sep 17 00:00:00 2001
From: Blazej Kustra <blazej.kustra@swmansion.com>
Date: Fri, 22 Nov 2024 16:21:06 +0100
Subject: [PATCH 06/75] Access data and fix
 getTripIDFromTransactionParentReportID

---
 src/CONST.ts                                  |  2 +-
 .../ReportActionItem/MoneyRequestView.tsx     |  2 +-
 src/libs/Navigation/types.ts                  |  6 ++-
 src/libs/ReportUtils.ts                       |  6 +--
 src/pages/Travel/TripDetails.tsx              | 50 ++++++++++++++++++-
 5 files changed, 58 insertions(+), 8 deletions(-)

diff --git a/src/CONST.ts b/src/CONST.ts
index ee70e3b29668..80b52c65bfcf 100755
--- a/src/CONST.ts
+++ b/src/CONST.ts
@@ -4427,7 +4427,7 @@ const CONST = {
     BOOK_TRAVEL_DEMO_URL: 'https://calendly.com/d/ck2z-xsh-q97/expensify-travel-demo-travel-page',
     TRAVEL_DOT_URL: 'https://travel.expensify.com',
     STAGING_TRAVEL_DOT_URL: 'https://staging.travel.expensify.com',
-    TRIP_ID_PATH: (tripID: string) => `trips/${tripID}`,
+    TRIP_ID_PATH: (tripID?: string) => (tripID ? `trips/${tripID}` : undefined),
     SPOTNANA_TMC_ID: '8e8e7258-1cf3-48c0-9cd1-fe78a6e31eed',
     STAGING_SPOTNANA_TMC_ID: '7a290c6e-5328-4107-aff6-e48765845b81',
     SCREEN_READER_STATES: {
diff --git a/src/components/ReportActionItem/MoneyRequestView.tsx b/src/components/ReportActionItem/MoneyRequestView.tsx
index 1533a7515a98..6bc356dd6f15 100644
--- a/src/components/ReportActionItem/MoneyRequestView.tsx
+++ b/src/components/ReportActionItem/MoneyRequestView.tsx
@@ -186,7 +186,7 @@ function MoneyRequestView({report, shouldShowAnimatedBackground, readonly = fals
     const shouldShowAttendees = useMemo(() => TransactionUtils.shouldShowAttendees(iouType, policy), [iouType, policy]);
 
     const shouldShowTax = isTaxTrackingEnabled(isPolicyExpenseChat, policy, isDistanceRequest);
-    const tripID = ReportUtils.getTripIDFromTransactionParentReport(parentReport);
+    const tripID = ReportUtils.getTripIDFromTransactionParentReportID(parentReport?.parentReportID);
     const shouldShowViewTripDetails = TransactionUtils.hasReservationList(transaction) && !!tripID;
 
     const {getViolationsForField} = useViolations(transactionViolations ?? [], isReceiptBeingScanned || !ReportUtils.isPaidGroupPolicy(report));
diff --git a/src/libs/Navigation/types.ts b/src/libs/Navigation/types.ts
index caa5ff5d1a06..469d20d15bbc 100644
--- a/src/libs/Navigation/types.ts
+++ b/src/libs/Navigation/types.ts
@@ -1380,7 +1380,11 @@ type RightModalNavigatorParamList = {
 
 type TravelNavigatorParamList = {
     [SCREENS.TRAVEL.MY_TRIPS]: undefined;
-    [SCREENS.TRAVEL.TRIP_DETAILS]: undefined;
+    [SCREENS.TRAVEL.TRIP_DETAILS]: {
+        reportID: string;
+        transactionID: string;
+        backTo?: string;
+    };
 };
 
 type FullScreenNavigatorParamList = {
diff --git a/src/libs/ReportUtils.ts b/src/libs/ReportUtils.ts
index 36095b7d88ec..72f11f4a3150 100644
--- a/src/libs/ReportUtils.ts
+++ b/src/libs/ReportUtils.ts
@@ -8030,8 +8030,8 @@ function getTripTransactions(tripRoomReportID: string | undefined, reportFieldTo
     return tripTransactionReportIDs.flatMap((reportID) => reportsTransactions[reportID ?? ''] ?? []);
 }
 
-function getTripIDFromTransactionParentReport(transactionParentReport: OnyxEntry<Report> | undefined | null): string | undefined {
-    return getReportOrDraftReport(transactionParentReport?.parentReportID)?.tripData?.tripID;
+function getTripIDFromTransactionParentReportID(transactionParentReportID: string | undefined): string | undefined {
+    return getReportOrDraftReport(transactionParentReportID)?.tripData?.tripID;
 }
 
 /**
@@ -8700,7 +8700,7 @@ export {
     updateReportPreview,
     temporary_getMoneyRequestOptions,
     getTripTransactions,
-    getTripIDFromTransactionParentReport,
+    getTripIDFromTransactionParentReportID,
     buildOptimisticInvoiceReport,
     getInvoiceChatByParticipants,
     shouldShowMerchantColumn,
diff --git a/src/pages/Travel/TripDetails.tsx b/src/pages/Travel/TripDetails.tsx
index 8c3d1bbadfc1..dab130bde1aa 100644
--- a/src/pages/Travel/TripDetails.tsx
+++ b/src/pages/Travel/TripDetails.tsx
@@ -1,15 +1,41 @@
+import type {StackScreenProps} from '@react-navigation/stack';
 import React from 'react';
 import {NativeModules} from 'react-native';
+import {useOnyx} from 'react-native-onyx';
 import FullPageNotFoundView from '@components/BlockingViews/FullPageNotFoundView';
 import HeaderWithBackButton from '@components/HeaderWithBackButton';
+import * as Expensicons from '@components/Icon/Expensicons';
+import MenuItem from '@components/MenuItem';
 import ScreenWrapper from '@components/ScreenWrapper';
 import useLocalize from '@hooks/useLocalize';
 import usePermissions from '@hooks/usePermissions';
+import useTheme from '@hooks/useTheme';
+import useThemeStyles from '@hooks/useThemeStyles';
+import type {TravelNavigatorParamList} from '@libs/Navigation/types';
+import * as ReportUtils from '@libs/ReportUtils';
+import * as Link from '@userActions/Link';
+import CONST from '@src/CONST';
+import ONYXKEYS from '@src/ONYXKEYS';
+import type SCREENS from '@src/SCREENS';
 
-function TripDetails() {
+type TripDetailsProps = StackScreenProps<TravelNavigatorParamList, typeof SCREENS.TRAVEL.TRIP_DETAILS>;
+
+function TripDetails({route}: TripDetailsProps) {
+    const styles = useThemeStyles();
+    const theme = useTheme();
     const {translate} = useLocalize();
     const {canUseSpotnanaTravel} = usePermissions();
 
+    const [activePolicyID] = useOnyx(ONYXKEYS.NVP_ACTIVE_POLICY_ID);
+    const [transaction] = useOnyx(`${ONYXKEYS.COLLECTION.TRANSACTION}${route.params.transactionID}`);
+    const [report] = useOnyx(`${ONYXKEYS.COLLECTION.REPORT}${route.params.reportID}`);
+    const [parentReport] = useOnyx(`${ONYXKEYS.COLLECTION.REPORT}${report?.parentReportID ?? '-1'}`);
+    const tripID = ReportUtils.getTripIDFromTransactionParentReportID(parentReport?.parentReportID);
+
+    console.log(`transaction = `, transaction);
+    console.log(`report = `, report);
+    console.log(`parentReport = `, parentReport);
+
     return (
         <ScreenWrapper
             includeSafeAreaPaddingBottom={false}
@@ -23,9 +49,29 @@ function TripDetails() {
                 shouldShow={!canUseSpotnanaTravel && !NativeModules.HybridAppModule}
             >
                 <HeaderWithBackButton
-                    title={translate('travel.header')}
+                    title={translate('common.details')}
                     shouldShowBackButton
                 />
+                <MenuItem
+                    title={translate('travel.flightDetails.modifyTrip')}
+                    icon={Expensicons.Pencil}
+                    iconFill={theme.iconSuccessFill}
+                    iconRight={Expensicons.NewWindow}
+                    shouldShowRightIcon
+                    onPress={() => {
+                        Link.openTravelDotLink(activePolicyID, CONST.TRIP_ID_PATH(tripID));
+                    }}
+                />
+                <MenuItem
+                    title={translate('travel.tripSupport')}
+                    icon={Expensicons.Phone}
+                    iconFill={theme.iconSuccessFill}
+                    iconRight={Expensicons.NewWindow}
+                    shouldShowRightIcon
+                    onPress={() => {
+                        Link.openTravelDotLink(activePolicyID, CONST.TRIP_ID_PATH(tripID));
+                    }}
+                />
             </FullPageNotFoundView>
         </ScreenWrapper>
     );

From 610ed48107fc58b2dc04a569aaec214da5ab5ffc Mon Sep 17 00:00:00 2001
From: Blazej Kustra <blazej.kustra@swmansion.com>
Date: Mon, 25 Nov 2024 12:04:05 +0100
Subject: [PATCH 07/75] Add english translations

---
 src/languages/en.ts | 25 +++++++++++++++++++++++++
 1 file changed, 25 insertions(+)

diff --git a/src/languages/en.ts b/src/languages/en.ts
index ec0e49353bbb..e525ac717729 100755
--- a/src/languages/en.ts
+++ b/src/languages/en.ts
@@ -2421,9 +2421,34 @@ const translations = {
             error: 'You must accept the Terms & Conditions for travel to continue',
         },
         flight: 'Flight',
+        flightDetails: {
+            layover: 'layover',
+            takeOff: 'Take-off',
+            landing: 'Landing',
+            passenger: 'Passenger',
+            seat: 'Seat',
+            class: 'Cabin Class',
+            recordLocator: 'Record locator',
+        },
         hotel: 'Hotel',
+        hotelDetails: {
+            checkIn: 'Check-in',
+            checkOut: 'Check-out',
+            roomType: 'Room type',
+            cancellation: 'Cancellation policy',
+            confirmation: 'Confirmation number',
+        },
         car: 'Car',
+        carDetails: {
+            pickUp: 'Pick-up',
+            dropOff: 'Drop-off',
+            driver: 'Driver',
+            carType: 'Car type',
+            cancellation: 'Cancellation policy',
+            confirmation: 'Confirmation number',
+        },
         viewTrip: 'View trip',
+        modifyTrip: 'Modify trip',
         tripSupport: 'Trip support',
         viewTripDetails: 'View trip details',
         trip: 'Trip',

From 644243cc5815c134ed7624000e4103b38f94498f Mon Sep 17 00:00:00 2001
From: Blazej Kustra <blazej.kustra@swmansion.com>
Date: Mon, 25 Nov 2024 17:33:49 +0100
Subject: [PATCH 08/75] Make reservationType optional in getTripReservationIcon
 function

---
 src/libs/TripReservationUtils.ts | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/src/libs/TripReservationUtils.ts b/src/libs/TripReservationUtils.ts
index f2ce5113af81..9fd850ab161b 100644
--- a/src/libs/TripReservationUtils.ts
+++ b/src/libs/TripReservationUtils.ts
@@ -50,7 +50,7 @@ Onyx.connect({
     },
 });
 
-function getTripReservationIcon(reservationType: ReservationType): IconAsset {
+function getTripReservationIcon(reservationType?: ReservationType): IconAsset {
     switch (reservationType) {
         case CONST.RESERVATION_TYPE.FLIGHT:
             return Expensicons.Plane;

From d5dd2afc853a01393f909472368798583fcc06f4 Mon Sep 17 00:00:00 2001
From: Blazej Kustra <blazej.kustra@swmansion.com>
Date: Mon, 25 Nov 2024 17:33:56 +0100
Subject: [PATCH 09/75] Add arrivalGate and cityName fields to Reservation and
 ReservationTimeDetails types

---
 src/types/onyx/Transaction.ts | 9 +++++++++
 1 file changed, 9 insertions(+)

diff --git a/src/types/onyx/Transaction.ts b/src/types/onyx/Transaction.ts
index 4c7e4facd94d..0183286510f6 100644
--- a/src/types/onyx/Transaction.ts
+++ b/src/types/onyx/Transaction.ts
@@ -236,6 +236,12 @@ type Reservation = {
 
     /** Payment type of the reservation */
     paymentType?: string;
+
+    /** Arrival gate details */
+    arrivalGate?: {
+        /** Arrival terminal number */
+        terminal: string;
+    };
 };
 
 /** Model of trip reservation time details */
@@ -257,6 +263,9 @@ type ReservationTimeDetails = {
 
     /** Timezone offset */
     timezoneOffset?: string;
+
+    /** City name */
+    cityName?: string;
 };
 
 /** Model of airline company details */

From 6c89f5a3f21c2723f18b6b1cab1fc664275c441b Mon Sep 17 00:00:00 2001
From: Blazej Kustra <blazej.kustra@swmansion.com>
Date: Mon, 25 Nov 2024 17:34:13 +0100
Subject: [PATCH 10/75] Enhance getFormattedTransportDate function to support
 shorter date format

---
 src/libs/DateUtils.ts | 14 +++++++++-----
 1 file changed, 9 insertions(+), 5 deletions(-)

diff --git a/src/libs/DateUtils.ts b/src/libs/DateUtils.ts
index 2cab87639d2f..11482aec46b5 100644
--- a/src/libs/DateUtils.ts
+++ b/src/libs/DateUtils.ts
@@ -798,15 +798,19 @@ function getFormattedReservationRangeDate(date1: Date, date2: Date): string {
 /**
  * Returns a formatted date of departure.
  * Dates are formatted as follows:
- * 1. When the date refers to the current day: Departs on Sunday, Mar 17 at 8:00
- * 2. When the date refers not to the current day: Departs on Wednesday, Mar 17, 2023 at 8:00
+ * 1. When the date refers to the current year: Departs on Sunday, Mar 17 at 8:00. When shorter is true, the output is: Mar 17, 8:00 AM
+ * 2. When the date refers not to the current year: Departs on Wednesday, Mar 17, 2023 at 8:00. When shorter is true, the output is: Mar 17, 2023 8:00 AM
  */
-function getFormattedTransportDate(date: Date): string {
+function getFormattedTransportDate(date: Date, shorter = false): string {
     const {translateLocal} = Localize;
     if (isThisYear(date)) {
-        return `${translateLocal('travel.departs')} ${format(date, 'EEEE, MMM d')} ${translateLocal('common.conjunctionAt')} ${format(date, 'HH:MM')}`;
+        return shorter
+            ? format(date, 'MMM d, h:mm a')
+            : `${translateLocal('travel.departs')} ${format(date, 'EEEE, MMM d')} ${translateLocal('common.conjunctionAt')} ${format(date, 'HH:MM')}`;
     }
-    return `${translateLocal('travel.departs')} ${format(date, 'EEEE, MMM d, yyyy')} ${translateLocal('common.conjunctionAt')} ${format(date, 'HH:MM')}`;
+    return shorter
+        ? format(date, 'MMM d, yyyy, h:mm a')
+        : `${translateLocal('travel.departs')} ${format(date, 'EEEE, MMM d, yyyy')} ${translateLocal('common.conjunctionAt')} ${format(date, 'HH:MM')}`;
 }
 
 function doesDateBelongToAPastYear(date: string): boolean {

From b47f8a2f28ff5bb59b97ce18a0308976256e10e6 Mon Sep 17 00:00:00 2001
From: Blazej Kustra <blazej.kustra@swmansion.com>
Date: Mon, 25 Nov 2024 17:34:21 +0100
Subject: [PATCH 11/75] Add FlightTripDetails component to display flight
 reservation information

---
 src/pages/Travel/FlightTripDetails.tsx | 132 +++++++++++++++++++++++++
 1 file changed, 132 insertions(+)
 create mode 100644 src/pages/Travel/FlightTripDetails.tsx

diff --git a/src/pages/Travel/FlightTripDetails.tsx b/src/pages/Travel/FlightTripDetails.tsx
new file mode 100644
index 000000000000..6f32aeed0b42
--- /dev/null
+++ b/src/pages/Travel/FlightTripDetails.tsx
@@ -0,0 +1,132 @@
+import React from 'react';
+import {View} from 'react-native';
+import type {OnyxEntry} from 'react-native-onyx';
+import * as Expensicons from '@components/Icon/Expensicons';
+import MenuItem from '@components/MenuItem';
+import MenuItemWithTopDescription from '@components/MenuItemWithTopDescription';
+import Text from '@components/Text';
+import useLocalize from '@hooks/useLocalize';
+import useStyleUtils from '@hooks/useStyleUtils';
+import useTheme from '@hooks/useTheme';
+import useThemeStyles from '@hooks/useThemeStyles';
+import DateUtils from '@libs/DateUtils';
+import * as TripReservationUtils from '@libs/TripReservationUtils';
+import CONST from '@src/CONST';
+import type {PersonalDetails, Transaction} from '@src/types/onyx';
+
+type FlightTripDetailsProps = {
+    transaction: OnyxEntry<Transaction>;
+    personalDetails: OnyxEntry<PersonalDetails>;
+};
+
+function FlightTripDetails({transaction, personalDetails}: FlightTripDetailsProps) {
+    const styles = useThemeStyles();
+    const theme = useTheme();
+    const StyleUtils = useStyleUtils();
+    const {translate} = useLocalize();
+
+    return (
+        <>
+            <MenuItem
+                description={`${transaction?.receipt?.reservationList?.at(0)?.start.longName} (${transaction?.receipt?.reservationList?.at(0)?.start.shortName})`}
+                // TODO: blazejkustra - Use the actual duration
+                title={`1h 43m ${translate('travel.flightDetails.layover')}`}
+                descriptionTextStyle={[styles.textLabelSupporting, styles.lh16]}
+                secondaryIcon={Expensicons.Chair}
+                wrapperStyle={[styles.taskDescriptionMenuItem]}
+                numberOfLinesDescription={2}
+                iconHeight={20}
+                iconWidth={20}
+                iconStyles={[StyleUtils.getTripReservationIconContainer(false), styles.mr3]}
+                secondaryIconFill={theme.icon}
+                interactive={false}
+            />
+            <View style={[styles.borderBottom, styles.mh5, styles.mt3, styles.mb6]} />
+
+            {transaction?.receipt?.reservationList?.map((reservation) => {
+                const reservationIcon = TripReservationUtils.getTripReservationIcon(reservation.type);
+                const startDate = DateUtils.getFormattedTransportDate(new Date(reservation.start.date), true);
+                const endDate = DateUtils.getFormattedTransportDate(new Date(reservation.end.date), true);
+
+                return (
+                    <>
+                        <Text style={[styles.textSupporting, styles.mh5, styles.mb2]}>{translate('travel.flight')}</Text>
+                        <Text style={[styles.textHeadlineH1, styles.mh5, styles.mb3]}>
+                            {reservation.start.cityName} ({reservation.start.shortName}) {translate('common.conjunctionTo')} {reservation.end.cityName} ({reservation.end.shortName})
+                        </Text>
+                        <MenuItem
+                            // TODO: blazejkustra - Use the actual duration
+                            description={`2h 15m ${CONST.DOT_SEPARATOR} ${reservation.end.longName}`}
+                            descriptionTextStyle={[styles.textLabelSupporting, styles.lh16]}
+                            title={`${reservation.company?.longName} ${CONST.DOT_SEPARATOR} ${reservation.route?.airlineCode}`}
+                            secondaryIcon={reservationIcon}
+                            wrapperStyle={[styles.taskDescriptionMenuItem]}
+                            numberOfLinesDescription={2}
+                            iconHeight={20}
+                            iconWidth={20}
+                            iconStyles={[StyleUtils.getTripReservationIconContainer(false), styles.mr3]}
+                            secondaryIconFill={theme.icon}
+                            interactive={false}
+                        />
+                        <MenuItemWithTopDescription
+                            description={translate('travel.flightDetails.takeOff')}
+                            title={startDate}
+                            helperText={`${reservation.start.longName} (${reservation.start.shortName})${reservation.arrivalGate?.terminal ? `, ${reservation.arrivalGate?.terminal}` : ''}`}
+                            helperTextStyle={styles.mtn2}
+                            interactive={false}
+                        />
+                        <MenuItemWithTopDescription
+                            description={translate('travel.flightDetails.landing')}
+                            title={endDate}
+                            helperText={`${reservation.end.longName} (${reservation.end.shortName})`}
+                            helperTextStyle={styles.mtn2}
+                            interactive={false}
+                        />
+                        <View style={[styles.borderBottom, styles.mh5, styles.mt1, styles.mb3]} />
+                        <MenuItem
+                            label={translate('travel.flightDetails.passenger')}
+                            title={personalDetails?.displayName}
+                            icon={personalDetails?.avatar ?? Expensicons.FallbackAvatar}
+                            iconType={CONST.ICON_TYPE_AVATAR}
+                            description={personalDetails?.login}
+                            interactive={false}
+                        />
+                        <View style={[styles.flexRow, styles.flexWrap, styles.mb6]}>
+                            {!!reservation.route?.number && (
+                                <View style={styles.w50}>
+                                    <MenuItemWithTopDescription
+                                        description={translate('travel.flightDetails.seat')}
+                                        title={reservation.route?.number}
+                                        interactive={false}
+                                    />
+                                </View>
+                            )}
+                            {!!reservation.route?.class && (
+                                <View style={styles.w50}>
+                                    <MenuItemWithTopDescription
+                                        description={translate('travel.flightDetails.class')}
+                                        title={reservation.route.class}
+                                        interactive={false}
+                                    />
+                                </View>
+                            )}
+                            {!!reservation.confirmations?.at(0)?.value && (
+                                <View style={styles.w50}>
+                                    <MenuItemWithTopDescription
+                                        description={translate('travel.flightDetails.recordLocator')}
+                                        title={reservation.confirmations?.at(0)?.value}
+                                        interactive={false}
+                                    />
+                                </View>
+                            )}
+                        </View>
+                    </>
+                );
+            })}
+        </>
+    );
+}
+
+FlightTripDetails.displayName = 'FlightTripDetails';
+
+export default FlightTripDetails;

From aeddf58eb767159b5184e6de188c4aefd9b3e152 Mon Sep 17 00:00:00 2001
From: Blazej Kustra <blazej.kustra@swmansion.com>
Date: Mon, 25 Nov 2024 17:34:29 +0100
Subject: [PATCH 12/75] Integrate FlightTripDetails component into TripDetails
 screen and wrap content in ScrollView

---
 src/pages/Travel/TripDetails.tsx | 60 ++++++++++++++++++--------------
 1 file changed, 34 insertions(+), 26 deletions(-)

diff --git a/src/pages/Travel/TripDetails.tsx b/src/pages/Travel/TripDetails.tsx
index dab130bde1aa..6c924d0957b6 100644
--- a/src/pages/Travel/TripDetails.tsx
+++ b/src/pages/Travel/TripDetails.tsx
@@ -7,21 +7,21 @@ import HeaderWithBackButton from '@components/HeaderWithBackButton';
 import * as Expensicons from '@components/Icon/Expensicons';
 import MenuItem from '@components/MenuItem';
 import ScreenWrapper from '@components/ScreenWrapper';
+import ScrollView from '@components/ScrollView';
 import useLocalize from '@hooks/useLocalize';
 import usePermissions from '@hooks/usePermissions';
 import useTheme from '@hooks/useTheme';
-import useThemeStyles from '@hooks/useThemeStyles';
 import type {TravelNavigatorParamList} from '@libs/Navigation/types';
 import * as ReportUtils from '@libs/ReportUtils';
 import * as Link from '@userActions/Link';
 import CONST from '@src/CONST';
 import ONYXKEYS from '@src/ONYXKEYS';
 import type SCREENS from '@src/SCREENS';
+import FlightTripDetails from './FlightTripDetails';
 
 type TripDetailsProps = StackScreenProps<TravelNavigatorParamList, typeof SCREENS.TRAVEL.TRIP_DETAILS>;
 
 function TripDetails({route}: TripDetailsProps) {
-    const styles = useThemeStyles();
     const theme = useTheme();
     const {translate} = useLocalize();
     const {canUseSpotnanaTravel} = usePermissions();
@@ -30,11 +30,11 @@ function TripDetails({route}: TripDetailsProps) {
     const [transaction] = useOnyx(`${ONYXKEYS.COLLECTION.TRANSACTION}${route.params.transactionID}`);
     const [report] = useOnyx(`${ONYXKEYS.COLLECTION.REPORT}${route.params.reportID}`);
     const [parentReport] = useOnyx(`${ONYXKEYS.COLLECTION.REPORT}${report?.parentReportID ?? '-1'}`);
-    const tripID = ReportUtils.getTripIDFromTransactionParentReportID(parentReport?.parentReportID);
 
-    console.log(`transaction = `, transaction);
-    console.log(`report = `, report);
-    console.log(`parentReport = `, parentReport);
+    const tripID = ReportUtils.getTripIDFromTransactionParentReportID(parentReport?.parentReportID);
+    const accountID = Object.keys(report?.participants ?? {}).at(0) ?? '-1';
+    const [personalDetails] = useOnyx(ONYXKEYS.PERSONAL_DETAILS_LIST, {selector: (data) => data?.[accountID]});
+    const reservationType = transaction?.receipt?.reservationList?.at(0)?.type;
 
     return (
         <ScreenWrapper
@@ -52,26 +52,34 @@ function TripDetails({route}: TripDetailsProps) {
                     title={translate('common.details')}
                     shouldShowBackButton
                 />
-                <MenuItem
-                    title={translate('travel.flightDetails.modifyTrip')}
-                    icon={Expensicons.Pencil}
-                    iconFill={theme.iconSuccessFill}
-                    iconRight={Expensicons.NewWindow}
-                    shouldShowRightIcon
-                    onPress={() => {
-                        Link.openTravelDotLink(activePolicyID, CONST.TRIP_ID_PATH(tripID));
-                    }}
-                />
-                <MenuItem
-                    title={translate('travel.tripSupport')}
-                    icon={Expensicons.Phone}
-                    iconFill={theme.iconSuccessFill}
-                    iconRight={Expensicons.NewWindow}
-                    shouldShowRightIcon
-                    onPress={() => {
-                        Link.openTravelDotLink(activePolicyID, CONST.TRIP_ID_PATH(tripID));
-                    }}
-                />
+                <ScrollView>
+                    {reservationType === 'flight' && (
+                        <FlightTripDetails
+                            transaction={transaction}
+                            personalDetails={personalDetails}
+                        />
+                    )}
+                    <MenuItem
+                        title={translate('travel.modifyTrip')}
+                        icon={Expensicons.Pencil}
+                        iconFill={theme.iconSuccessFill}
+                        iconRight={Expensicons.NewWindow}
+                        shouldShowRightIcon
+                        onPress={() => {
+                            Link.openTravelDotLink(activePolicyID, CONST.TRIP_ID_PATH(tripID));
+                        }}
+                    />
+                    <MenuItem
+                        title={translate('travel.tripSupport')}
+                        icon={Expensicons.Phone}
+                        iconFill={theme.iconSuccessFill}
+                        iconRight={Expensicons.NewWindow}
+                        shouldShowRightIcon
+                        onPress={() => {
+                            Link.openTravelDotLink(activePolicyID, CONST.TRIP_ID_PATH(tripID));
+                        }}
+                    />
+                </ScrollView>
             </FullPageNotFoundView>
         </ScreenWrapper>
     );

From ae395901e50f5bf0ba1564941d1aab95a4e4d9d5 Mon Sep 17 00:00:00 2001
From: Blazej Kustra <blazej.kustra@swmansion.com>
Date: Sun, 24 Nov 2024 20:39:28 +0100
Subject: [PATCH 13/75] Final touches

---
 src/components/ApprovalWorkflowSection.tsx | 34 +++++++++++++++++++---
 src/components/AttachmentModal.tsx         |  4 +--
 2 files changed, 31 insertions(+), 7 deletions(-)

diff --git a/src/components/ApprovalWorkflowSection.tsx b/src/components/ApprovalWorkflowSection.tsx
index fd28595e7436..de6626c5bd5f 100644
--- a/src/components/ApprovalWorkflowSection.tsx
+++ b/src/components/ApprovalWorkflowSection.tsx
@@ -1,4 +1,5 @@
-import React, {useCallback, useMemo} from 'react';
+/* eslint-disable react/function-component-definition */
+import React, {useCallback, useMemo, useRef} from 'react';
 import {View} from 'react-native';
 import useLocalize from '@hooks/useLocalize';
 import useResponsiveLayout from '@hooks/useResponsiveLayout';
@@ -20,11 +21,36 @@ type ApprovalWorkflowSectionProps = {
     onPress: () => void;
 };
 
-function ApprovalWorkflowSection({approvalWorkflow, onPress}: ApprovalWorkflowSectionProps) {
+const Test = () => {
     const styles = useThemeStyles();
     const theme = useTheme();
+    const {shouldUseNarrowLayout} = useResponsiveLayout();
     const {translate, toLocaleOrdinal} = useLocalize();
+
+    const approverTitle = useCallback(
+        (index: number) =>
+            approvalWorkflow.approvers.length > 1 ? `${toLocaleOrdinal(index + 1, true)} ${translate('workflowsPage.approver').toLowerCase()}` : `${translate('workflowsPage.approver')}`,
+        [approvalWorkflow.approvers.length, toLocaleOrdinal, translate],
+    );
+
+    const members = useMemo(() => {
+        if (approvalWorkflow.isDefault) {
+            return translate('workspace.common.everyone');
+        }
+
+        return OptionsListUtils.sortAlphabetically(approvalWorkflow.members, 'displayName')
+            .map((m) => m.displayName)
+            .join(', ');
+    }, [approvalWorkflow.isDefault, translate]);
+
+    return <View />;
+};
+
+function ApprovalWorkflowSection({approvalWorkflow, onPress}: ApprovalWorkflowSectionProps) {
+    const styles = useThemeStyles();
+    const theme = useTheme();
     const {shouldUseNarrowLayout} = useResponsiveLayout();
+    const {translate, toLocaleOrdinal} = useLocalize();
 
     const approverTitle = useCallback(
         (index: number) =>
@@ -40,7 +66,7 @@ function ApprovalWorkflowSection({approvalWorkflow, onPress}: ApprovalWorkflowSe
         return OptionsListUtils.sortAlphabetically(approvalWorkflow.members, 'displayName')
             .map((m) => m.displayName)
             .join(', ');
-    }, [approvalWorkflow.isDefault, approvalWorkflow.members, translate]);
+    }, [approvalWorkflow]);
 
     return (
         <PressableWithoutFeedback
@@ -110,4 +136,4 @@ function ApprovalWorkflowSection({approvalWorkflow, onPress}: ApprovalWorkflowSe
     );
 }
 
-export default ApprovalWorkflowSection;
+export {ApprovalWorkflowSection};
diff --git a/src/components/AttachmentModal.tsx b/src/components/AttachmentModal.tsx
index 207f3eed6f8c..75095c888407 100644
--- a/src/components/AttachmentModal.tsx
+++ b/src/components/AttachmentModal.tsx
@@ -275,7 +275,6 @@ function AttachmentModal({
         }
 
         setIsModalOpen(false);
-        // eslint-disable-next-line react-compiler/react-compiler, react-hooks/exhaustive-deps
     }, [isModalOpen, isConfirmButtonDisabled, onConfirm, file, sourceState]);
 
     /**
@@ -458,8 +457,7 @@ function AttachmentModal({
             });
         }
         return menuItems;
-        // eslint-disable-next-line react-compiler/react-compiler, react-hooks/exhaustive-deps
-    }, [isReceiptAttachment, transaction, file, sourceState, iouType]);
+    }, [isReceiptAttachment, canEditReceipt, isOffline, allowDownload, isLocalSource, transaction, translate, closeModal, iouType, report?.reportID, downloadAttachment]);
 
     // There are a few things that shouldn't be set until we absolutely know if the file is a receipt or an attachment.
     // props.isReceiptAttachment will be null until its certain what the file is, in which case it will then be true|false.

From 2954e6a2cbf512d428b6636eb07ddae1208874e4 Mon Sep 17 00:00:00 2001
From: Blazej Kustra <blazej.kustra@swmansion.com>
Date: Tue, 26 Nov 2024 09:31:52 +0100
Subject: [PATCH 14/75] Fix flight page after design changes

---
 src/libs/DateUtils.ts                  | 11 +++++
 src/pages/Travel/FlightTripDetails.tsx | 60 +++++++++++++++-----------
 src/pages/Travel/TripDetails.tsx       |  3 ++
 3 files changed, 48 insertions(+), 26 deletions(-)

diff --git a/src/libs/DateUtils.ts b/src/libs/DateUtils.ts
index 11482aec46b5..9bf707acdf46 100644
--- a/src/libs/DateUtils.ts
+++ b/src/libs/DateUtils.ts
@@ -13,6 +13,7 @@ import {
     formatDistance,
     getDate,
     getDay,
+    intervalToDuration,
     isAfter,
     isBefore,
     isSameDay,
@@ -813,6 +814,15 @@ function getFormattedTransportDate(date: Date, shorter = false): string {
         : `${translateLocal('travel.departs')} ${format(date, 'EEEE, MMM d, yyyy')} ${translateLocal('common.conjunctionAt')} ${format(date, 'HH:MM')}`;
 }
 
+/**
+ * Returns a formatted layover duration in format "2h 30m".
+ */
+function getFormattedDurationBetweenDates(start: Date, end: Date): string {
+    const {days, hours, minutes} = intervalToDuration({start, end});
+
+    return `${days ? `${days}d ` : ''}${hours ? `${hours}h ` : ''}${minutes}m`;
+}
+
 function doesDateBelongToAPastYear(date: string): boolean {
     const transactionYear = new Date(date).getFullYear();
     return transactionYear !== new Date().getFullYear();
@@ -897,6 +907,7 @@ const DateUtils = {
     isCardExpired,
     getDifferenceInDaysFromNow,
     isValidDateString,
+    getFormattedDurationBetweenDates,
 };
 
 export default DateUtils;
diff --git a/src/pages/Travel/FlightTripDetails.tsx b/src/pages/Travel/FlightTripDetails.tsx
index 6f32aeed0b42..b92c4ad57cce 100644
--- a/src/pages/Travel/FlightTripDetails.tsx
+++ b/src/pages/Travel/FlightTripDetails.tsx
@@ -28,29 +28,26 @@ function FlightTripDetails({transaction, personalDetails}: FlightTripDetailsProp
     return (
         <>
             <MenuItem
-                description={`${transaction?.receipt?.reservationList?.at(0)?.start.longName} (${transaction?.receipt?.reservationList?.at(0)?.start.shortName})`}
-                // TODO: blazejkustra - Use the actual duration
-                title={`1h 43m ${translate('travel.flightDetails.layover')}`}
-                descriptionTextStyle={[styles.textLabelSupporting, styles.lh16]}
-                secondaryIcon={Expensicons.Chair}
-                wrapperStyle={[styles.taskDescriptionMenuItem]}
-                numberOfLinesDescription={2}
-                iconHeight={20}
-                iconWidth={20}
-                iconStyles={[StyleUtils.getTripReservationIconContainer(false), styles.mr3]}
-                secondaryIconFill={theme.icon}
+                label={translate('travel.flightDetails.passenger')}
+                title={personalDetails?.displayName}
+                icon={personalDetails?.avatar ?? Expensicons.FallbackAvatar}
+                iconType={CONST.ICON_TYPE_AVATAR}
+                description={personalDetails?.login}
                 interactive={false}
+                wrapperStyle={styles.pb3}
             />
-            <View style={[styles.borderBottom, styles.mh5, styles.mt3, styles.mb6]} />
 
-            {transaction?.receipt?.reservationList?.map((reservation) => {
+            {transaction?.receipt?.reservationList?.map((reservation, index) => {
                 const reservationIcon = TripReservationUtils.getTripReservationIcon(reservation.type);
                 const startDate = DateUtils.getFormattedTransportDate(new Date(reservation.start.date), true);
                 const endDate = DateUtils.getFormattedTransportDate(new Date(reservation.end.date), true);
 
+                const nextFlightStartDate = transaction.receipt?.reservationList?.at(index + 1)?.start.date;
+                const layover = nextFlightStartDate && DateUtils.getFormattedDurationBetweenDates(new Date(reservation.end.date), new Date(nextFlightStartDate));
+
                 return (
                     <>
-                        <Text style={[styles.textSupporting, styles.mh5, styles.mb2]}>{translate('travel.flight')}</Text>
+                        <Text style={[styles.textSupporting, styles.mh5, styles.mt3, styles.mb2]}>{translate('travel.flight')}</Text>
                         <Text style={[styles.textHeadlineH1, styles.mh5, styles.mb3]}>
                             {reservation.start.cityName} ({reservation.start.shortName}) {translate('common.conjunctionTo')} {reservation.end.cityName} ({reservation.end.shortName})
                         </Text>
@@ -72,26 +69,18 @@ function FlightTripDetails({transaction, personalDetails}: FlightTripDetailsProp
                             description={translate('travel.flightDetails.takeOff')}
                             title={startDate}
                             helperText={`${reservation.start.longName} (${reservation.start.shortName})${reservation.arrivalGate?.terminal ? `, ${reservation.arrivalGate?.terminal}` : ''}`}
-                            helperTextStyle={styles.mtn2}
+                            helperTextStyle={[styles.pb3, styles.mtn2]}
                             interactive={false}
                         />
                         <MenuItemWithTopDescription
                             description={translate('travel.flightDetails.landing')}
                             title={endDate}
                             helperText={`${reservation.end.longName} (${reservation.end.shortName})`}
-                            helperTextStyle={styles.mtn2}
+                            helperTextStyle={[styles.pb3, styles.mtn2]}
                             interactive={false}
                         />
-                        <View style={[styles.borderBottom, styles.mh5, styles.mt1, styles.mb3]} />
-                        <MenuItem
-                            label={translate('travel.flightDetails.passenger')}
-                            title={personalDetails?.displayName}
-                            icon={personalDetails?.avatar ?? Expensicons.FallbackAvatar}
-                            iconType={CONST.ICON_TYPE_AVATAR}
-                            description={personalDetails?.login}
-                            interactive={false}
-                        />
-                        <View style={[styles.flexRow, styles.flexWrap, styles.mb6]}>
+
+                        <View style={[styles.flexRow, styles.flexWrap]}>
                             {!!reservation.route?.number && (
                                 <View style={styles.w50}>
                                     <MenuItemWithTopDescription
@@ -120,6 +109,25 @@ function FlightTripDetails({transaction, personalDetails}: FlightTripDetailsProp
                                 </View>
                             )}
                         </View>
+                        <View style={[styles.borderBottom, styles.mh5, styles.mv3]} />
+                        {!!layover && (
+                            <>
+                                <MenuItem
+                                    description={`${transaction?.receipt?.reservationList?.at(0)?.start.longName} (${transaction?.receipt?.reservationList?.at(0)?.start.shortName})`}
+                                    title={`${layover} ${translate('travel.flightDetails.layover')}`}
+                                    descriptionTextStyle={[styles.textLabelSupporting, styles.lh16]}
+                                    secondaryIcon={Expensicons.Chair}
+                                    wrapperStyle={[styles.taskDescriptionMenuItem]}
+                                    numberOfLinesDescription={2}
+                                    iconHeight={20}
+                                    iconWidth={20}
+                                    iconStyles={[StyleUtils.getTripReservationIconContainer(false), styles.mr3]}
+                                    secondaryIconFill={theme.icon}
+                                    interactive={false}
+                                />
+                                <View style={[styles.borderBottom, styles.mh5, styles.mv3]} />
+                            </>
+                        )}
                     </>
                 );
             })}
diff --git a/src/pages/Travel/TripDetails.tsx b/src/pages/Travel/TripDetails.tsx
index 6c924d0957b6..5eaee8d60dc4 100644
--- a/src/pages/Travel/TripDetails.tsx
+++ b/src/pages/Travel/TripDetails.tsx
@@ -11,6 +11,7 @@ import ScrollView from '@components/ScrollView';
 import useLocalize from '@hooks/useLocalize';
 import usePermissions from '@hooks/usePermissions';
 import useTheme from '@hooks/useTheme';
+import useThemeStyles from '@hooks/useThemeStyles';
 import type {TravelNavigatorParamList} from '@libs/Navigation/types';
 import * as ReportUtils from '@libs/ReportUtils';
 import * as Link from '@userActions/Link';
@@ -23,6 +24,7 @@ type TripDetailsProps = StackScreenProps<TravelNavigatorParamList, typeof SCREEN
 
 function TripDetails({route}: TripDetailsProps) {
     const theme = useTheme();
+    const styles = useThemeStyles();
     const {translate} = useLocalize();
     const {canUseSpotnanaTravel} = usePermissions();
 
@@ -68,6 +70,7 @@ function TripDetails({route}: TripDetailsProps) {
                         onPress={() => {
                             Link.openTravelDotLink(activePolicyID, CONST.TRIP_ID_PATH(tripID));
                         }}
+                        wrapperStyle={styles.mt3}
                     />
                     <MenuItem
                         title={translate('travel.tripSupport')}

From 08fd3fb4563ebd27e3f49abc37d9789518026c0c Mon Sep 17 00:00:00 2001
From: Blazej Kustra <blazej.kustra@swmansion.com>
Date: Tue, 26 Nov 2024 09:33:48 +0100
Subject: [PATCH 15/75] Change TripDetails into TripDetailsPage

---
 .../AppNavigator/ModalStackNavigators/index.tsx        |  2 +-
 .../Travel/{TripDetails.tsx => TripDetailsPage.tsx}    | 10 +++++-----
 2 files changed, 6 insertions(+), 6 deletions(-)
 rename src/pages/Travel/{TripDetails.tsx => TripDetailsPage.tsx} (92%)

diff --git a/src/libs/Navigation/AppNavigator/ModalStackNavigators/index.tsx b/src/libs/Navigation/AppNavigator/ModalStackNavigators/index.tsx
index beb030ccb09d..543b0b374b8d 100644
--- a/src/libs/Navigation/AppNavigator/ModalStackNavigators/index.tsx
+++ b/src/libs/Navigation/AppNavigator/ModalStackNavigators/index.tsx
@@ -105,7 +105,7 @@ const MoneyRequestModalStackNavigator = createModalStackNavigator<MoneyRequestNa
 const TravelModalStackNavigator = createModalStackNavigator<TravelNavigatorParamList>({
     [SCREENS.TRAVEL.MY_TRIPS]: () => require<ReactComponentModule>('../../../../pages/Travel/MyTripsPage').default,
     [SCREENS.TRAVEL.TCS]: () => require<ReactComponentModule>('../../../../pages/Travel/TravelTerms').default,
-    [SCREENS.TRAVEL.TRIP_DETAILS]: () => require<ReactComponentModule>('../../../../pages/Travel/TripDetails').default,
+    [SCREENS.TRAVEL.TRIP_DETAILS]: () => require<ReactComponentModule>('../../../../pages/Travel/TripDetailsPage').default,
 });
 
 const SplitDetailsModalStackNavigator = createModalStackNavigator<SplitDetailsNavigatorParamList>({
diff --git a/src/pages/Travel/TripDetails.tsx b/src/pages/Travel/TripDetailsPage.tsx
similarity index 92%
rename from src/pages/Travel/TripDetails.tsx
rename to src/pages/Travel/TripDetailsPage.tsx
index 5eaee8d60dc4..0f35bc0c36e1 100644
--- a/src/pages/Travel/TripDetails.tsx
+++ b/src/pages/Travel/TripDetailsPage.tsx
@@ -20,9 +20,9 @@ import ONYXKEYS from '@src/ONYXKEYS';
 import type SCREENS from '@src/SCREENS';
 import FlightTripDetails from './FlightTripDetails';
 
-type TripDetailsProps = StackScreenProps<TravelNavigatorParamList, typeof SCREENS.TRAVEL.TRIP_DETAILS>;
+type TripDetailsPageProps = StackScreenProps<TravelNavigatorParamList, typeof SCREENS.TRAVEL.TRIP_DETAILS>;
 
-function TripDetails({route}: TripDetailsProps) {
+function TripDetailsPage({route}: TripDetailsPageProps) {
     const theme = useTheme();
     const styles = useThemeStyles();
     const {translate} = useLocalize();
@@ -43,7 +43,7 @@ function TripDetails({route}: TripDetailsProps) {
             includeSafeAreaPaddingBottom={false}
             shouldEnablePickerAvoiding={false}
             shouldEnableMaxHeight
-            testID={TripDetails.displayName}
+            testID={TripDetailsPage.displayName}
             shouldShowOfflineIndicatorInWideScreen
         >
             <FullPageNotFoundView
@@ -88,6 +88,6 @@ function TripDetails({route}: TripDetailsProps) {
     );
 }
 
-TripDetails.displayName = 'TripDetails';
+TripDetailsPage.displayName = 'TripDetailsPage';
 
-export default TripDetails;
+export default TripDetailsPage;

From 6e71d437de401f60f56421ed2a757b2c6d546b17 Mon Sep 17 00:00:00 2001
From: Blazej Kustra <blazej.kustra@swmansion.com>
Date: Tue, 26 Nov 2024 10:16:35 +0100
Subject: [PATCH 16/75] Create HotelTripDetails

---
 src/pages/Travel/HotelTripDetails.tsx | 88 +++++++++++++++++++++++++++
 src/pages/Travel/TripDetailsPage.tsx  |  7 +++
 2 files changed, 95 insertions(+)
 create mode 100644 src/pages/Travel/HotelTripDetails.tsx

diff --git a/src/pages/Travel/HotelTripDetails.tsx b/src/pages/Travel/HotelTripDetails.tsx
new file mode 100644
index 000000000000..f0f8ec7398cc
--- /dev/null
+++ b/src/pages/Travel/HotelTripDetails.tsx
@@ -0,0 +1,88 @@
+import React from 'react';
+import {View} from 'react-native';
+import type {OnyxEntry} from 'react-native-onyx';
+import * as Expensicons from '@components/Icon/Expensicons';
+import MenuItem from '@components/MenuItem';
+import MenuItemWithTopDescription from '@components/MenuItemWithTopDescription';
+import Text from '@components/Text';
+import useLocalize from '@hooks/useLocalize';
+import useStyleUtils from '@hooks/useStyleUtils';
+import useTheme from '@hooks/useTheme';
+import useThemeStyles from '@hooks/useThemeStyles';
+import DateUtils from '@libs/DateUtils';
+import * as TripReservationUtils from '@libs/TripReservationUtils';
+import CONST from '@src/CONST';
+import type {PersonalDetails, Transaction} from '@src/types/onyx';
+
+type HotelTripDetailsProps = {
+    transaction: OnyxEntry<Transaction>;
+    personalDetails: OnyxEntry<PersonalDetails>;
+};
+
+function HotelTripDetails({transaction, personalDetails}: HotelTripDetailsProps) {
+    const styles = useThemeStyles();
+    const theme = useTheme();
+    const StyleUtils = useStyleUtils();
+    const {translate} = useLocalize();
+
+    const hotelReservation = transaction?.receipt?.reservationList?.at(0);
+
+    if (!transaction || !hotelReservation) {
+        return null;
+    }
+    const reservationIcon = TripReservationUtils.getTripReservationIcon(hotelReservation.type);
+    const checkInDate = DateUtils.getFormattedTransportDate(new Date(hotelReservation.start.date), true);
+    const checkOutDate = DateUtils.getFormattedTransportDate(new Date(hotelReservation.end.date), true);
+
+    return (
+        <>
+            <MenuItem
+                label={translate('travel.hotelDetails.guest')}
+                title={personalDetails?.displayName}
+                icon={personalDetails?.avatar ?? Expensicons.FallbackAvatar}
+                iconType={CONST.ICON_TYPE_AVATAR}
+                description={personalDetails?.login}
+                interactive={false}
+                wrapperStyle={styles.pb3}
+            />
+            <Text style={[styles.textSupporting, styles.mh5, styles.mt3, styles.mb2]}>{translate('travel.hotel')}</Text>
+            <Text style={[styles.textHeadlineH1, styles.mh5, styles.mb3]}>{hotelReservation.start.longName}</Text>
+            <MenuItem
+                description={hotelReservation.start.address}
+                descriptionTextStyle={[styles.textLabelSupporting, styles.lh16]}
+                title={hotelReservation.start.longName}
+                secondaryIcon={reservationIcon}
+                wrapperStyle={[styles.taskDescriptionMenuItem]}
+                numberOfLinesDescription={2}
+                iconHeight={20}
+                iconWidth={20}
+                iconStyles={[StyleUtils.getTripReservationIconContainer(false), styles.mr3]}
+                secondaryIconFill={theme.icon}
+                interactive={false}
+            />
+            <MenuItemWithTopDescription
+                description={translate('travel.hotelDetails.checkIn')}
+                title={checkInDate}
+                interactive={false}
+            />
+            <MenuItemWithTopDescription
+                description={translate('travel.hotelDetails.checkOut')}
+                title={checkOutDate}
+                interactive={false}
+            />
+            {!!hotelReservation.confirmations?.at(0)?.value && (
+                <View style={styles.w50}>
+                    <MenuItemWithTopDescription
+                        description={translate('travel.flightDetails.recordLocator')}
+                        title={hotelReservation.confirmations?.at(0)?.value}
+                        interactive={false}
+                    />
+                </View>
+            )}
+        </>
+    );
+}
+
+HotelTripDetails.displayName = 'FlightTripDetails';
+
+export default HotelTripDetails;
diff --git a/src/pages/Travel/TripDetailsPage.tsx b/src/pages/Travel/TripDetailsPage.tsx
index 0f35bc0c36e1..590ab2949ea5 100644
--- a/src/pages/Travel/TripDetailsPage.tsx
+++ b/src/pages/Travel/TripDetailsPage.tsx
@@ -19,6 +19,7 @@ import CONST from '@src/CONST';
 import ONYXKEYS from '@src/ONYXKEYS';
 import type SCREENS from '@src/SCREENS';
 import FlightTripDetails from './FlightTripDetails';
+import HotelTripDetails from './HotelTripDetails';
 
 type TripDetailsPageProps = StackScreenProps<TravelNavigatorParamList, typeof SCREENS.TRAVEL.TRIP_DETAILS>;
 
@@ -61,6 +62,12 @@ function TripDetailsPage({route}: TripDetailsPageProps) {
                             personalDetails={personalDetails}
                         />
                     )}
+                    {reservationType === 'hotel' && (
+                        <HotelTripDetails
+                            transaction={transaction}
+                            personalDetails={personalDetails}
+                        />
+                    )}
                     <MenuItem
                         title={translate('travel.modifyTrip')}
                         icon={Expensicons.Pencil}

From 4ff355f5898043e450eee9d5b293f77ac1d7e633 Mon Sep 17 00:00:00 2001
From: Blazej Kustra <blazej.kustra@swmansion.com>
Date: Tue, 26 Nov 2024 10:16:43 +0100
Subject: [PATCH 17/75] Add missing translation

---
 src/languages/en.ts | 1 +
 1 file changed, 1 insertion(+)

diff --git a/src/languages/en.ts b/src/languages/en.ts
index e525ac717729..81d2a9dfc5c9 100755
--- a/src/languages/en.ts
+++ b/src/languages/en.ts
@@ -2432,6 +2432,7 @@ const translations = {
         },
         hotel: 'Hotel',
         hotelDetails: {
+            guest: 'Guest',
             checkIn: 'Check-in',
             checkOut: 'Check-out',
             roomType: 'Room type',

From 2eb1bb96d8d633b605c75a0d9e059cac1ff4b4f8 Mon Sep 17 00:00:00 2001
From: Blazej Kustra <blazej.kustra@swmansion.com>
Date: Tue, 26 Nov 2024 11:48:40 +0100
Subject: [PATCH 18/75] Revert "Final touches"

This reverts commit 04d94db6fc38eb5cd30e85373c3ac58ca28ebc26.
---
 src/components/ApprovalWorkflowSection.tsx | 34 +++-------------------
 src/components/AttachmentModal.tsx         |  4 ++-
 2 files changed, 7 insertions(+), 31 deletions(-)

diff --git a/src/components/ApprovalWorkflowSection.tsx b/src/components/ApprovalWorkflowSection.tsx
index de6626c5bd5f..fd28595e7436 100644
--- a/src/components/ApprovalWorkflowSection.tsx
+++ b/src/components/ApprovalWorkflowSection.tsx
@@ -1,5 +1,4 @@
-/* eslint-disable react/function-component-definition */
-import React, {useCallback, useMemo, useRef} from 'react';
+import React, {useCallback, useMemo} from 'react';
 import {View} from 'react-native';
 import useLocalize from '@hooks/useLocalize';
 import useResponsiveLayout from '@hooks/useResponsiveLayout';
@@ -21,36 +20,11 @@ type ApprovalWorkflowSectionProps = {
     onPress: () => void;
 };
 
-const Test = () => {
-    const styles = useThemeStyles();
-    const theme = useTheme();
-    const {shouldUseNarrowLayout} = useResponsiveLayout();
-    const {translate, toLocaleOrdinal} = useLocalize();
-
-    const approverTitle = useCallback(
-        (index: number) =>
-            approvalWorkflow.approvers.length > 1 ? `${toLocaleOrdinal(index + 1, true)} ${translate('workflowsPage.approver').toLowerCase()}` : `${translate('workflowsPage.approver')}`,
-        [approvalWorkflow.approvers.length, toLocaleOrdinal, translate],
-    );
-
-    const members = useMemo(() => {
-        if (approvalWorkflow.isDefault) {
-            return translate('workspace.common.everyone');
-        }
-
-        return OptionsListUtils.sortAlphabetically(approvalWorkflow.members, 'displayName')
-            .map((m) => m.displayName)
-            .join(', ');
-    }, [approvalWorkflow.isDefault, translate]);
-
-    return <View />;
-};
-
 function ApprovalWorkflowSection({approvalWorkflow, onPress}: ApprovalWorkflowSectionProps) {
     const styles = useThemeStyles();
     const theme = useTheme();
-    const {shouldUseNarrowLayout} = useResponsiveLayout();
     const {translate, toLocaleOrdinal} = useLocalize();
+    const {shouldUseNarrowLayout} = useResponsiveLayout();
 
     const approverTitle = useCallback(
         (index: number) =>
@@ -66,7 +40,7 @@ function ApprovalWorkflowSection({approvalWorkflow, onPress}: ApprovalWorkflowSe
         return OptionsListUtils.sortAlphabetically(approvalWorkflow.members, 'displayName')
             .map((m) => m.displayName)
             .join(', ');
-    }, [approvalWorkflow]);
+    }, [approvalWorkflow.isDefault, approvalWorkflow.members, translate]);
 
     return (
         <PressableWithoutFeedback
@@ -136,4 +110,4 @@ function ApprovalWorkflowSection({approvalWorkflow, onPress}: ApprovalWorkflowSe
     );
 }
 
-export {ApprovalWorkflowSection};
+export default ApprovalWorkflowSection;
diff --git a/src/components/AttachmentModal.tsx b/src/components/AttachmentModal.tsx
index 75095c888407..207f3eed6f8c 100644
--- a/src/components/AttachmentModal.tsx
+++ b/src/components/AttachmentModal.tsx
@@ -275,6 +275,7 @@ function AttachmentModal({
         }
 
         setIsModalOpen(false);
+        // eslint-disable-next-line react-compiler/react-compiler, react-hooks/exhaustive-deps
     }, [isModalOpen, isConfirmButtonDisabled, onConfirm, file, sourceState]);
 
     /**
@@ -457,7 +458,8 @@ function AttachmentModal({
             });
         }
         return menuItems;
-    }, [isReceiptAttachment, canEditReceipt, isOffline, allowDownload, isLocalSource, transaction, translate, closeModal, iouType, report?.reportID, downloadAttachment]);
+        // eslint-disable-next-line react-compiler/react-compiler, react-hooks/exhaustive-deps
+    }, [isReceiptAttachment, transaction, file, sourceState, iouType]);
 
     // There are a few things that shouldn't be set until we absolutely know if the file is a receipt or an attachment.
     // props.isReceiptAttachment will be null until its certain what the file is, in which case it will then be true|false.

From 503cf60743346a6037956bbc2048db60f2ad8da9 Mon Sep 17 00:00:00 2001
From: Blazej Kustra <blazej.kustra@swmansion.com>
Date: Tue, 26 Nov 2024 11:52:58 +0100
Subject: [PATCH 19/75] Remove flight from hotel page

---
 src/pages/Travel/HotelTripDetails.tsx | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/src/pages/Travel/HotelTripDetails.tsx b/src/pages/Travel/HotelTripDetails.tsx
index f0f8ec7398cc..b77b3530fca9 100644
--- a/src/pages/Travel/HotelTripDetails.tsx
+++ b/src/pages/Travel/HotelTripDetails.tsx
@@ -73,7 +73,7 @@ function HotelTripDetails({transaction, personalDetails}: HotelTripDetailsProps)
             {!!hotelReservation.confirmations?.at(0)?.value && (
                 <View style={styles.w50}>
                     <MenuItemWithTopDescription
-                        description={translate('travel.flightDetails.recordLocator')}
+                        description={translate('travel.hotelDetails.confirmation')}
                         title={hotelReservation.confirmations?.at(0)?.value}
                         interactive={false}
                     />
@@ -83,6 +83,6 @@ function HotelTripDetails({transaction, personalDetails}: HotelTripDetailsProps)
     );
 }
 
-HotelTripDetails.displayName = 'FlightTripDetails';
+HotelTripDetails.displayName = 'HotelTripDetails';
 
 export default HotelTripDetails;

From a4a0cded4bec256a13dd85c03ffdbf176319e618 Mon Sep 17 00:00:00 2001
From: Blazej Kustra <blazej.kustra@swmansion.com>
Date: Tue, 26 Nov 2024 15:42:19 +0100
Subject: [PATCH 20/75] Add a blank line for improved readability in
 HotelTripDetails component

---
 src/pages/Travel/HotelTripDetails.tsx | 1 +
 1 file changed, 1 insertion(+)

diff --git a/src/pages/Travel/HotelTripDetails.tsx b/src/pages/Travel/HotelTripDetails.tsx
index b77b3530fca9..32f0a6836828 100644
--- a/src/pages/Travel/HotelTripDetails.tsx
+++ b/src/pages/Travel/HotelTripDetails.tsx
@@ -30,6 +30,7 @@ function HotelTripDetails({transaction, personalDetails}: HotelTripDetailsProps)
     if (!transaction || !hotelReservation) {
         return null;
     }
+
     const reservationIcon = TripReservationUtils.getTripReservationIcon(hotelReservation.type);
     const checkInDate = DateUtils.getFormattedTransportDate(new Date(hotelReservation.start.date), true);
     const checkOutDate = DateUtils.getFormattedTransportDate(new Date(hotelReservation.end.date), true);

From 30e27d1c2ba817f810c4f2e4a2b8c57a1346eb48 Mon Sep 17 00:00:00 2001
From: Blazej Kustra <blazej.kustra@swmansion.com>
Date: Tue, 26 Nov 2024 15:42:26 +0100
Subject: [PATCH 21/75] Add CarTripDetails component for displaying car rental
 information

---
 src/pages/Travel/CarTripDetails.tsx | 103 ++++++++++++++++++++++++++++
 1 file changed, 103 insertions(+)
 create mode 100644 src/pages/Travel/CarTripDetails.tsx

diff --git a/src/pages/Travel/CarTripDetails.tsx b/src/pages/Travel/CarTripDetails.tsx
new file mode 100644
index 000000000000..25c417425a9f
--- /dev/null
+++ b/src/pages/Travel/CarTripDetails.tsx
@@ -0,0 +1,103 @@
+import React from 'react';
+import {View} from 'react-native';
+import type {OnyxEntry} from 'react-native-onyx';
+import * as Expensicons from '@components/Icon/Expensicons';
+import MenuItem from '@components/MenuItem';
+import MenuItemWithTopDescription from '@components/MenuItemWithTopDescription';
+import Text from '@components/Text';
+import useLocalize from '@hooks/useLocalize';
+import useStyleUtils from '@hooks/useStyleUtils';
+import useTheme from '@hooks/useTheme';
+import useThemeStyles from '@hooks/useThemeStyles';
+import DateUtils from '@libs/DateUtils';
+import * as TripReservationUtils from '@libs/TripReservationUtils';
+import CONST from '@src/CONST';
+import type {PersonalDetails, Transaction} from '@src/types/onyx';
+
+type CarTripDetailsProps = {
+    transaction: OnyxEntry<Transaction>;
+    personalDetails: OnyxEntry<PersonalDetails>;
+};
+
+function CarTripDetails({transaction, personalDetails}: CarTripDetailsProps) {
+    const styles = useThemeStyles();
+    const theme = useTheme();
+    const StyleUtils = useStyleUtils();
+    const {translate} = useLocalize();
+
+    const carReservation = transaction?.receipt?.reservationList?.at(0);
+
+    if (!transaction || !carReservation) {
+        return null;
+    }
+
+    const reservationIcon = TripReservationUtils.getTripReservationIcon(carReservation.type);
+    const checkInDate = DateUtils.getFormattedTransportDate(new Date(carReservation.start.date), true);
+    const checkOutDate = DateUtils.getFormattedTransportDate(new Date(carReservation.end.date), true);
+
+    return (
+        <>
+            <MenuItem
+                label={translate('travel.carDetails.driver')}
+                title={personalDetails?.displayName}
+                icon={personalDetails?.avatar ?? Expensicons.FallbackAvatar}
+                iconType={CONST.ICON_TYPE_AVATAR}
+                description={personalDetails?.login}
+                interactive={false}
+                wrapperStyle={styles.pb3}
+            />
+            <Text style={[styles.textSupporting, styles.mh5, styles.mt3, styles.mb2]}>{translate('travel.carDetails.rentalCar')}</Text>
+            <Text style={[styles.textHeadlineH1, styles.mh5, styles.mb3]}>{carReservation.vendor}</Text>
+            <MenuItem
+                description={carReservation.start.location}
+                descriptionTextStyle={[styles.textLabelSupporting, styles.lh16]}
+                title={carReservation.vendor}
+                secondaryIcon={reservationIcon}
+                wrapperStyle={[styles.taskDescriptionMenuItem]}
+                numberOfLinesDescription={2}
+                iconHeight={20}
+                iconWidth={20}
+                iconStyles={[StyleUtils.getTripReservationIconContainer(false), styles.mr3]}
+                secondaryIconFill={theme.icon}
+                interactive={false}
+            />
+            <MenuItemWithTopDescription
+                description={translate('travel.carDetails.pickUp')}
+                title={checkInDate}
+                interactive={false}
+                helperText={carReservation.start.location}
+                helperTextStyle={[styles.pb3, styles.mtn2]}
+            />
+            <MenuItemWithTopDescription
+                description={translate('travel.carDetails.dropOff')}
+                title={checkOutDate}
+                interactive={false}
+                helperText={carReservation.end.location}
+                helperTextStyle={[styles.pb3, styles.mtn2]}
+            />
+
+            {!!carReservation.carInfo?.name && (
+                <View style={styles.w50}>
+                    <MenuItemWithTopDescription
+                        description={translate('travel.carDetails.carType')}
+                        title={carReservation.carInfo.name}
+                        interactive={false}
+                    />
+                </View>
+            )}
+            {!!carReservation.reservationID && (
+                <View style={styles.w50}>
+                    <MenuItemWithTopDescription
+                        description={translate('travel.carDetails.confirmation')}
+                        title={carReservation.reservationID}
+                        interactive={false}
+                    />
+                </View>
+            )}
+        </>
+    );
+}
+
+CarTripDetails.displayName = 'FlightTripDetails';
+
+export default CarTripDetails;

From a8b78f875075575e7400e32e8137c95bf5b1957b Mon Sep 17 00:00:00 2001
From: Blazej Kustra <blazej.kustra@swmansion.com>
Date: Tue, 26 Nov 2024 15:42:37 +0100
Subject: [PATCH 22/75] Refactor getReservationsFromTripTransactions to return
 structured reservation data and sort by start date

---
 src/libs/TripReservationUtils.ts | 17 +++++++++++++----
 1 file changed, 13 insertions(+), 4 deletions(-)

diff --git a/src/libs/TripReservationUtils.ts b/src/libs/TripReservationUtils.ts
index 9fd850ab161b..a8714122da97 100644
--- a/src/libs/TripReservationUtils.ts
+++ b/src/libs/TripReservationUtils.ts
@@ -63,11 +63,19 @@ function getTripReservationIcon(reservationType?: ReservationType): IconAsset {
     }
 }
 
-function getReservationsFromTripTransactions(transactions: Transaction[]): Reservation[] {
+type ReservationData = {reservation: Reservation; transactionID: string; reportID: string};
+
+function getReservationsFromTripTransactions(transactions: Transaction[]): ReservationData[] {
     return transactions
-        .map((item) => item?.receipt?.reservationList ?? [])
-        .filter((item) => item.length > 0)
-        .flat();
+        .flatMap(
+            (item) =>
+                item?.receipt?.reservationList?.map((reservation) => ({
+                    reservation,
+                    transactionID: item.transactionID,
+                    reportID: item.reportID,
+                })) ?? [],
+        )
+        .sort((a, b) => new Date(a.reservation.start.date).getTime() - new Date(b.reservation.start.date).getTime());
 }
 
 function getTripEReceiptIcon(transaction?: Transaction): IconAsset | undefined {
@@ -115,3 +123,4 @@ function bookATrip(translate: LocaleContextProps['translate'], setCtaErrorMessag
         });
 }
 export {getTripReservationIcon, getReservationsFromTripTransactions, getTripEReceiptIcon, bookATrip};
+export type {ReservationData};

From f4f5501fe0c7afb0d4ee4c819643c40e9ce2ae79 Mon Sep 17 00:00:00 2001
From: Blazej Kustra <blazej.kustra@swmansion.com>
Date: Tue, 26 Nov 2024 15:42:47 +0100
Subject: [PATCH 23/75] Add translation for rental car

---
 src/languages/en.ts | 1 +
 1 file changed, 1 insertion(+)

diff --git a/src/languages/en.ts b/src/languages/en.ts
index 81d2a9dfc5c9..e1b932a3852a 100755
--- a/src/languages/en.ts
+++ b/src/languages/en.ts
@@ -2441,6 +2441,7 @@ const translations = {
         },
         car: 'Car',
         carDetails: {
+            rentalCar: 'Rental car',
             pickUp: 'Pick-up',
             dropOff: 'Drop-off',
             driver: 'Driver',

From d49cdce25f3839547511714ccaf716499374616d Mon Sep 17 00:00:00 2001
From: Blazej Kustra <blazej.kustra@swmansion.com>
Date: Tue, 26 Nov 2024 15:43:01 +0100
Subject: [PATCH 24/75] Fix navigation route in MoneyRequestView to use
 parentReportID

---
 src/components/ReportActionItem/MoneyRequestView.tsx | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/src/components/ReportActionItem/MoneyRequestView.tsx b/src/components/ReportActionItem/MoneyRequestView.tsx
index 6bc356dd6f15..4fb50ad39cc1 100644
--- a/src/components/ReportActionItem/MoneyRequestView.tsx
+++ b/src/components/ReportActionItem/MoneyRequestView.tsx
@@ -695,7 +695,7 @@ function MoneyRequestView({report, shouldShowAnimatedBackground, readonly = fals
                         title={translate('travel.viewTripDetails')}
                         icon={Expensicons.Suitcase}
                         onPress={() =>
-                            Navigation.navigate(ROUTES.TRAVEL_TRIP_DETAILS.getRoute(report?.reportID ?? '-1', transaction?.transactionID ?? '-1', Navigation.getReportRHPActiveRoute()))
+                            Navigation.navigate(ROUTES.TRAVEL_TRIP_DETAILS.getRoute(report?.parentReportID ?? '-1', transaction?.transactionID ?? '-1', Navigation.getReportRHPActiveRoute()))
                         }
                     />
                 )}

From 092e430260226f367a28150edb89477e8cca435c Mon Sep 17 00:00:00 2001
From: Blazej Kustra <blazej.kustra@swmansion.com>
Date: Tue, 26 Nov 2024 15:43:29 +0100
Subject: [PATCH 25/75] Refactor TripDetailsView and TripRoomPreview to use
 structured reservation data and improve navigation handling

---
 .../ReportActionItem/TripDetailsView.tsx      | 25 +++++++++++----
 .../ReportActionItem/TripRoomPreview.tsx      | 32 +++++++------------
 src/libs/ReportUtils.ts                       |  6 ++--
 3 files changed, 33 insertions(+), 30 deletions(-)

diff --git a/src/components/ReportActionItem/TripDetailsView.tsx b/src/components/ReportActionItem/TripDetailsView.tsx
index 32cbc5dd853e..0043232d1119 100644
--- a/src/components/ReportActionItem/TripDetailsView.tsx
+++ b/src/components/ReportActionItem/TripDetailsView.tsx
@@ -11,11 +11,13 @@ import useStyleUtils from '@hooks/useStyleUtils';
 import useTheme from '@hooks/useTheme';
 import useThemeStyles from '@hooks/useThemeStyles';
 import DateUtils from '@libs/DateUtils';
+import Navigation from '@libs/Navigation/Navigation';
 import variables from '@styles/variables';
 import * as Expensicons from '@src/components/Icon/Expensicons';
 import CONST from '@src/CONST';
 import * as ReportUtils from '@src/libs/ReportUtils';
 import * as TripReservationUtils from '@src/libs/TripReservationUtils';
+import ROUTES from '@src/ROUTES';
 import type {Reservation, ReservationTimeDetails} from '@src/types/onyx/Transaction';
 
 type TripDetailsViewProps = {
@@ -28,9 +30,11 @@ type TripDetailsViewProps = {
 
 type ReservationViewProps = {
     reservation: Reservation;
+    transactionID: string;
+    reportID: string;
 };
 
-function ReservationView({reservation}: ReservationViewProps) {
+function ReservationView({reservation, transactionID, reportID}: ReservationViewProps) {
     const theme = useTheme();
     const styles = useThemeStyles();
     const StyleUtils = useStyleUtils();
@@ -129,6 +133,7 @@ function ReservationView({reservation}: ReservationViewProps) {
             iconWidth={20}
             iconStyles={[StyleUtils.getTripReservationIconContainer(false), styles.mr3]}
             secondaryIconFill={theme.icon}
+            onPress={() => Navigation.navigate(ROUTES.TRAVEL_TRIP_DETAILS.getRoute(reportID, transactionID, Navigation.getReportRHPActiveRoute()))}
         />
     );
 }
@@ -138,7 +143,7 @@ function TripDetailsView({tripRoomReportID, shouldShowHorizontalRule}: TripDetai
     const {translate} = useLocalize();
 
     const tripTransactions = ReportUtils.getTripTransactions(tripRoomReportID);
-    const reservations: Reservation[] = TripReservationUtils.getReservationsFromTripTransactions(tripTransactions);
+    const reservationsData: TripReservationUtils.ReservationData[] = TripReservationUtils.getReservationsFromTripTransactions(tripTransactions);
 
     return (
         <View>
@@ -153,11 +158,17 @@ function TripDetailsView({tripRoomReportID, shouldShowHorizontalRule}: TripDetai
                 </View>
             </View>
             <>
-                {reservations.map((reservation) => (
-                    <OfflineWithFeedback>
-                        <ReservationView reservation={reservation} />
-                    </OfflineWithFeedback>
-                ))}
+                {reservationsData.map(({reservation, transactionID, reportID}) => {
+                    return (
+                        <OfflineWithFeedback>
+                            <ReservationView
+                                reservation={reservation}
+                                transactionID={transactionID}
+                                reportID={reportID}
+                            />
+                        </OfflineWithFeedback>
+                    );
+                })}
                 <SpacerView
                     shouldShow={shouldShowHorizontalRule}
                     style={[shouldShowHorizontalRule && styles.reportHorizontalRule]}
diff --git a/src/components/ReportActionItem/TripRoomPreview.tsx b/src/components/ReportActionItem/TripRoomPreview.tsx
index d8d5f7d11aa4..0299486a22c6 100644
--- a/src/components/ReportActionItem/TripRoomPreview.tsx
+++ b/src/components/ReportActionItem/TripRoomPreview.tsx
@@ -18,7 +18,6 @@ import * as CurrencyUtils from '@libs/CurrencyUtils';
 import DateUtils from '@libs/DateUtils';
 import * as DeviceCapabilities from '@libs/DeviceCapabilities';
 import Navigation from '@libs/Navigation/Navigation';
-import {getReportActionText} from '@libs/ReportActionsUtils';
 import * as ReportUtils from '@libs/ReportUtils';
 import * as TripReservationUtils from '@libs/TripReservationUtils';
 import type {ContextMenuAnchor} from '@pages/home/report/ContextMenu/ReportActionContextMenu';
@@ -104,7 +103,7 @@ function ReservationView({reservation}: ReservationViewProps) {
     );
 }
 
-const renderItem = ({item}: {item: Reservation}) => <ReservationView reservation={item} />;
+const renderItem = ({item}: {item: TripReservationUtils.ReservationData}) => <ReservationView reservation={item.reservation} />;
 
 function TripRoomPreview({action, chatReportID, containerStyles, contextMenuAnchor, isHovered = false, checkIfContextMenuActive = () => {}}: TripRoomPreviewProps) {
     const styles = useThemeStyles();
@@ -112,31 +111,22 @@ function TripRoomPreview({action, chatReportID, containerStyles, contextMenuAnch
     const [chatReport] = useOnyx(`${ONYXKEYS.COLLECTION.REPORT}${chatReportID}`);
     const [iouReport] = useOnyx(`${ONYXKEYS.COLLECTION.REPORT}${chatReport?.iouReportID}`);
 
-    const tripTransactions = ReportUtils.getTripTransactions(chatReport?.iouReportID, 'reportID');
-    const reservations: Reservation[] = TripReservationUtils.getReservationsFromTripTransactions(tripTransactions);
+    const tripTransactions = ReportUtils.getTripTransactions(chatReport?.reportID);
+    const reservationsData: TripReservationUtils.ReservationData[] = TripReservationUtils.getReservationsFromTripTransactions(tripTransactions);
     const dateInfo = chatReport?.tripData ? DateUtils.getFormattedDateRange(new Date(chatReport.tripData.startDate), new Date(chatReport.tripData.endDate)) : '';
     const {totalDisplaySpend} = ReportUtils.getMoneyRequestSpendBreakdown(chatReport);
 
+    const currency = iouReport?.currency ?? chatReport?.currency;
     const displayAmount = useMemo(() => {
         if (totalDisplaySpend) {
-            return CurrencyUtils.convertToDisplayString(totalDisplaySpend, iouReport?.currency);
+            return CurrencyUtils.convertToDisplayString(totalDisplaySpend, currency);
         }
 
-        // If iouReport is not available, get amount from the action message (Ex: "Domain20821's Workspace owes $33.00" or "paid ₫60" or "paid -₫60 elsewhere")
-        let displayAmountValue = '';
-        const actionMessage = getReportActionText(action) ?? '';
-        const splits = actionMessage.split(' ');
-
-        splits.forEach((split) => {
-            if (!/\d/.test(split)) {
-                return;
-            }
-
-            displayAmountValue = split;
-        });
-
-        return displayAmountValue;
-    }, [action, iouReport?.currency, totalDisplaySpend]);
+        return CurrencyUtils.convertToDisplayString(
+            tripTransactions.reduce((acc, transaction) => acc + Math.abs(transaction.amount), 0),
+            currency,
+        );
+    }, [currency, totalDisplaySpend, tripTransactions]);
 
     return (
         <OfflineWithFeedback
@@ -179,7 +169,7 @@ function TripRoomPreview({action, chatReportID, containerStyles, contextMenuAnch
                             </View>
                         </View>
                         <FlatList
-                            data={reservations}
+                            data={reservationsData}
                             style={styles.gap3}
                             renderItem={renderItem}
                         />
diff --git a/src/libs/ReportUtils.ts b/src/libs/ReportUtils.ts
index 72f11f4a3150..534559dd8cb8 100644
--- a/src/libs/ReportUtils.ts
+++ b/src/libs/ReportUtils.ts
@@ -854,7 +854,7 @@ function isChatReport(report: OnyxEntry<Report>): boolean {
     return report?.type === CONST.REPORT.TYPE.CHAT;
 }
 
-function isInvoiceReport(report: OnyxInputOrEntry<Report> | SearchReport): boolean {
+function isInvoiceReport(report: OnyxInputOrEntry<Report> | SearchReport): report is Report {
     return report?.type === CONST.REPORT.TYPE.INVOICE;
 }
 
@@ -1659,6 +1659,8 @@ function isMoneyRequest(reportOrID: OnyxEntry<Report> | string): boolean {
 /**
  * Checks if a report is an IOU or expense report.
  */
+function isMoneyRequestReport(reportOrID: OnyxInputOrEntry<Report>): reportOrID is Report;
+function isMoneyRequestReport(reportOrID: SearchReport | string): boolean;
 function isMoneyRequestReport(reportOrID: OnyxInputOrEntry<Report> | SearchReport | string): boolean {
     const report = typeof reportOrID === 'string' ? ReportConnection.getAllReports()?.[`${ONYXKEYS.COLLECTION.REPORT}${reportOrID}`] ?? null : reportOrID;
     return isIOUReport(report) || isExpenseReport(report);
@@ -2837,7 +2839,7 @@ function hasNonReimbursableTransactions(iouReportID: string | undefined): boolea
 
 function getMoneyRequestSpendBreakdown(report: OnyxInputOrEntry<Report>, allReportsDict?: OnyxCollection<Report>): SpendBreakdown {
     const allAvailableReports = allReportsDict ?? ReportConnection.getAllReports();
-    let moneyRequestReport;
+    let moneyRequestReport: OnyxEntry<Report>;
     if (isMoneyRequestReport(report) || isInvoiceReport(report)) {
         moneyRequestReport = report;
     }

From 6c59ca4a4208e2d946c75be3357c551ecb4fe5a9 Mon Sep 17 00:00:00 2001
From: Blazej Kustra <blazej.kustra@swmansion.com>
Date: Tue, 26 Nov 2024 15:43:39 +0100
Subject: [PATCH 26/75] Add CarTripDetails component to TripDetailsPage for
 displaying car rental information

---
 src/pages/Travel/TripDetailsPage.tsx | 10 ++++++++--
 1 file changed, 8 insertions(+), 2 deletions(-)

diff --git a/src/pages/Travel/TripDetailsPage.tsx b/src/pages/Travel/TripDetailsPage.tsx
index 590ab2949ea5..971128101486 100644
--- a/src/pages/Travel/TripDetailsPage.tsx
+++ b/src/pages/Travel/TripDetailsPage.tsx
@@ -18,6 +18,7 @@ import * as Link from '@userActions/Link';
 import CONST from '@src/CONST';
 import ONYXKEYS from '@src/ONYXKEYS';
 import type SCREENS from '@src/SCREENS';
+import CarTripDetails from './CarTripDetails';
 import FlightTripDetails from './FlightTripDetails';
 import HotelTripDetails from './HotelTripDetails';
 
@@ -32,9 +33,8 @@ function TripDetailsPage({route}: TripDetailsPageProps) {
     const [activePolicyID] = useOnyx(ONYXKEYS.NVP_ACTIVE_POLICY_ID);
     const [transaction] = useOnyx(`${ONYXKEYS.COLLECTION.TRANSACTION}${route.params.transactionID}`);
     const [report] = useOnyx(`${ONYXKEYS.COLLECTION.REPORT}${route.params.reportID}`);
-    const [parentReport] = useOnyx(`${ONYXKEYS.COLLECTION.REPORT}${report?.parentReportID ?? '-1'}`);
 
-    const tripID = ReportUtils.getTripIDFromTransactionParentReportID(parentReport?.parentReportID);
+    const tripID = ReportUtils.getTripIDFromTransactionParentReportID(report?.parentReportID);
     const accountID = Object.keys(report?.participants ?? {}).at(0) ?? '-1';
     const [personalDetails] = useOnyx(ONYXKEYS.PERSONAL_DETAILS_LIST, {selector: (data) => data?.[accountID]});
     const reservationType = transaction?.receipt?.reservationList?.at(0)?.type;
@@ -68,6 +68,12 @@ function TripDetailsPage({route}: TripDetailsPageProps) {
                             personalDetails={personalDetails}
                         />
                     )}
+                    {reservationType === 'car' && (
+                        <CarTripDetails
+                            transaction={transaction}
+                            personalDetails={personalDetails}
+                        />
+                    )}
                     <MenuItem
                         title={translate('travel.modifyTrip')}
                         icon={Expensicons.Pencil}

From 49f946ff2b5538f4fcbd92c70ee55393a589f0bb Mon Sep 17 00:00:00 2001
From: Blazej Kustra <blazej.kustra@swmansion.com>
Date: Wed, 27 Nov 2024 18:29:42 +0100
Subject: [PATCH 27/75] Add Trip Summary screen

---
 src/ROUTES.ts                                 |  7 +-
 src/SCREENS.ts                                |  1 +
 .../ReportActionItem/TripDetailsView.tsx      |  9 ++-
 src/pages/Travel/TripSummary.tsx              | 65 +++++++++++++++++++
 4 files changed, 78 insertions(+), 4 deletions(-)
 create mode 100644 src/pages/Travel/TripSummary.tsx

diff --git a/src/ROUTES.ts b/src/ROUTES.ts
index 920e328ebfff..2be153e4dad3 100644
--- a/src/ROUTES.ts
+++ b/src/ROUTES.ts
@@ -1343,10 +1343,15 @@ const ROUTES = {
     TRAVEL_MY_TRIPS: 'travel',
     TRAVEL_TCS: 'travel/terms',
     TRACK_TRAINING_MODAL: 'track-training',
-    TRAVEL_TRIP_DETAILS: {
+    TRAVEL_TRIP_SUMMARY: {
         route: 'r/:reportID/trip/:transactionID',
         getRoute: (reportID: string, transactionID: string, backTo?: string) => getUrlWithBackToParam(`r/${reportID}/trip/${transactionID}`, backTo),
     },
+    TRAVEL_TRIP_DETAILS: {
+        route: 'r/:reportID/trip/:transactionID/:reservationIndex',
+        getRoute: (reportID: string, transactionID: string, reservationIndex: number, backTo?: string) =>
+            getUrlWithBackToParam(`r/${reportID}/trip/${transactionID}/${reservationIndex}`, backTo),
+    },
     ONBOARDING_ROOT: {
         route: 'onboarding',
         getRoute: (backTo?: string) => getUrlWithBackToParam(`onboarding`, backTo),
diff --git a/src/SCREENS.ts b/src/SCREENS.ts
index f6a53da3f199..eeb805d0ca36 100644
--- a/src/SCREENS.ts
+++ b/src/SCREENS.ts
@@ -27,6 +27,7 @@ const SCREENS = {
     TRAVEL: {
         MY_TRIPS: 'Travel_MyTrips',
         TCS: 'Travel_TCS',
+        TRIP_SUMMARY: 'Travel_TripSummary',
         TRIP_DETAILS: 'Trip_Details',
     },
     SEARCH: {
diff --git a/src/components/ReportActionItem/TripDetailsView.tsx b/src/components/ReportActionItem/TripDetailsView.tsx
index 0043232d1119..dfc282b230e4 100644
--- a/src/components/ReportActionItem/TripDetailsView.tsx
+++ b/src/components/ReportActionItem/TripDetailsView.tsx
@@ -32,9 +32,10 @@ type ReservationViewProps = {
     reservation: Reservation;
     transactionID: string;
     reportID: string;
+    reservationIndex: number;
 };
 
-function ReservationView({reservation, transactionID, reportID}: ReservationViewProps) {
+function ReservationView({reservation, transactionID, reportID, reservationIndex}: ReservationViewProps) {
     const theme = useTheme();
     const styles = useThemeStyles();
     const StyleUtils = useStyleUtils();
@@ -133,7 +134,7 @@ function ReservationView({reservation, transactionID, reportID}: ReservationView
             iconWidth={20}
             iconStyles={[StyleUtils.getTripReservationIconContainer(false), styles.mr3]}
             secondaryIconFill={theme.icon}
-            onPress={() => Navigation.navigate(ROUTES.TRAVEL_TRIP_DETAILS.getRoute(reportID, transactionID, Navigation.getReportRHPActiveRoute()))}
+            onPress={() => Navigation.navigate(ROUTES.TRAVEL_TRIP_DETAILS.getRoute(reportID, transactionID, reservationIndex, Navigation.getReportRHPActiveRoute()))}
         />
     );
 }
@@ -158,13 +159,14 @@ function TripDetailsView({tripRoomReportID, shouldShowHorizontalRule}: TripDetai
                 </View>
             </View>
             <>
-                {reservationsData.map(({reservation, transactionID, reportID}) => {
+                {reservationsData.map(({reservation, transactionID, reportID, reservationIndex}) => {
                     return (
                         <OfflineWithFeedback>
                             <ReservationView
                                 reservation={reservation}
                                 transactionID={transactionID}
                                 reportID={reportID}
+                                reservationIndex={reservationIndex}
                             />
                         </OfflineWithFeedback>
                     );
@@ -181,3 +183,4 @@ function TripDetailsView({tripRoomReportID, shouldShowHorizontalRule}: TripDetai
 TripDetailsView.displayName = 'TripDetailsView';
 
 export default TripDetailsView;
+export {ReservationView};
diff --git a/src/pages/Travel/TripSummary.tsx b/src/pages/Travel/TripSummary.tsx
new file mode 100644
index 000000000000..a024d28bd6db
--- /dev/null
+++ b/src/pages/Travel/TripSummary.tsx
@@ -0,0 +1,65 @@
+import type {StackScreenProps} from '@react-navigation/stack';
+import React from 'react';
+import {NativeModules} from 'react-native';
+import {useOnyx} from 'react-native-onyx';
+import FullPageNotFoundView from '@components/BlockingViews/FullPageNotFoundView';
+import HeaderWithBackButton from '@components/HeaderWithBackButton';
+import OfflineWithFeedback from '@components/OfflineWithFeedback';
+import {ReservationView} from '@components/ReportActionItem/TripDetailsView';
+import ScreenWrapper from '@components/ScreenWrapper';
+import ScrollView from '@components/ScrollView';
+import useLocalize from '@hooks/useLocalize';
+import usePermissions from '@hooks/usePermissions';
+import type {TravelNavigatorParamList} from '@libs/Navigation/types';
+import * as TripReservationUtils from '@src/libs/TripReservationUtils';
+import ONYXKEYS from '@src/ONYXKEYS';
+import type SCREENS from '@src/SCREENS';
+
+type TripDetailsPageProps = StackScreenProps<TravelNavigatorParamList, typeof SCREENS.TRAVEL.TRIP_DETAILS>;
+
+function TripDetailsPage({route}: TripDetailsPageProps) {
+    const {translate} = useLocalize();
+    const {canUseSpotnanaTravel} = usePermissions();
+
+    const [transaction] = useOnyx(`${ONYXKEYS.COLLECTION.TRANSACTION}${route.params.transactionID}`);
+    const reservationType = transaction?.receipt?.reservationList?.at(0)?.type;
+    const reservationsData: TripReservationUtils.ReservationData[] = TripReservationUtils.getReservationsFromTripTransactions(transaction ? [transaction] : []);
+
+    return (
+        <ScreenWrapper
+            includeSafeAreaPaddingBottom={false}
+            shouldEnablePickerAvoiding={false}
+            shouldEnableMaxHeight
+            testID={TripDetailsPage.displayName}
+            shouldShowOfflineIndicatorInWideScreen
+        >
+            <FullPageNotFoundView
+                shouldForceFullScreen
+                shouldShow={!canUseSpotnanaTravel && !NativeModules.HybridAppModule}
+            >
+                <HeaderWithBackButton
+                    title={reservationType ? `${translate(`travel.${reservationType}`)} ${translate('common.details').toLowerCase()}` : translate('common.details')}
+                    shouldShowBackButton
+                />
+                <ScrollView>
+                    {reservationsData.map(({reservation, transactionID, reportID, reservationIndex}) => {
+                        return (
+                            <OfflineWithFeedback>
+                                <ReservationView
+                                    reservation={reservation}
+                                    transactionID={transactionID}
+                                    reportID={reportID}
+                                    reservationIndex={reservationIndex}
+                                />
+                            </OfflineWithFeedback>
+                        );
+                    })}
+                </ScrollView>
+            </FullPageNotFoundView>
+        </ScreenWrapper>
+    );
+}
+
+TripDetailsPage.displayName = 'TripDetailsPage';
+
+export default TripDetailsPage;

From 9c5963e50f51d541e70f171454947e9e440c6d22 Mon Sep 17 00:00:00 2001
From: Blazej Kustra <blazej.kustra@swmansion.com>
Date: Wed, 27 Nov 2024 18:30:02 +0100
Subject: [PATCH 28/75] Add address translation to common

---
 src/languages/en.ts | 3 ++-
 src/languages/es.ts | 1 +
 2 files changed, 3 insertions(+), 1 deletion(-)

diff --git a/src/languages/en.ts b/src/languages/en.ts
index e1b932a3852a..f745d2d3f579 100755
--- a/src/languages/en.ts
+++ b/src/languages/en.ts
@@ -474,6 +474,7 @@ const translations = {
         links: 'Links',
         days: 'days',
         rename: 'Rename',
+        address: 'Address',
     },
     location: {
         useCurrent: 'Use current location',
@@ -2441,7 +2442,7 @@ const translations = {
         },
         car: 'Car',
         carDetails: {
-            rentalCar: 'Rental car',
+            rentalCar: 'Car rental',
             pickUp: 'Pick-up',
             dropOff: 'Drop-off',
             driver: 'Driver',
diff --git a/src/languages/es.ts b/src/languages/es.ts
index 623afb1ff16a..edcba33bd58a 100644
--- a/src/languages/es.ts
+++ b/src/languages/es.ts
@@ -465,6 +465,7 @@ const translations = {
         sent: 'Enviado',
         links: 'Enlaces',
         days: 'días',
+        address: 'Dirección',
     },
     connectionComplete: {
         title: 'Conexión completa',

From 34553ef3aeb1a09e42257e9703f15f1b463c2cf3 Mon Sep 17 00:00:00 2001
From: Blazej Kustra <blazej.kustra@swmansion.com>
Date: Wed, 27 Nov 2024 18:30:50 +0100
Subject: [PATCH 29/75] Add screen to navigator and fix types

---
 .../AppNavigator/ModalStackNavigators/index.tsx        |  1 +
 src/libs/Navigation/types.ts                           |  6 ++++++
 .../Travel/{TripSummary.tsx => TripSummaryPage.tsx}    | 10 +++++-----
 3 files changed, 12 insertions(+), 5 deletions(-)
 rename src/pages/Travel/{TripSummary.tsx => TripSummaryPage.tsx} (90%)

diff --git a/src/libs/Navigation/AppNavigator/ModalStackNavigators/index.tsx b/src/libs/Navigation/AppNavigator/ModalStackNavigators/index.tsx
index 543b0b374b8d..377013af0ada 100644
--- a/src/libs/Navigation/AppNavigator/ModalStackNavigators/index.tsx
+++ b/src/libs/Navigation/AppNavigator/ModalStackNavigators/index.tsx
@@ -105,6 +105,7 @@ const MoneyRequestModalStackNavigator = createModalStackNavigator<MoneyRequestNa
 const TravelModalStackNavigator = createModalStackNavigator<TravelNavigatorParamList>({
     [SCREENS.TRAVEL.MY_TRIPS]: () => require<ReactComponentModule>('../../../../pages/Travel/MyTripsPage').default,
     [SCREENS.TRAVEL.TCS]: () => require<ReactComponentModule>('../../../../pages/Travel/TravelTerms').default,
+    [SCREENS.TRAVEL.TRIP_SUMMARY]: () => require<ReactComponentModule>('../../../../pages/Travel/TripSummaryPage').default,
     [SCREENS.TRAVEL.TRIP_DETAILS]: () => require<ReactComponentModule>('../../../../pages/Travel/TripDetailsPage').default,
 });
 
diff --git a/src/libs/Navigation/types.ts b/src/libs/Navigation/types.ts
index 469d20d15bbc..750542a55172 100644
--- a/src/libs/Navigation/types.ts
+++ b/src/libs/Navigation/types.ts
@@ -1380,9 +1380,15 @@ type RightModalNavigatorParamList = {
 
 type TravelNavigatorParamList = {
     [SCREENS.TRAVEL.MY_TRIPS]: undefined;
+    [SCREENS.TRAVEL.TRIP_SUMMARY]: {
+        reportID: string;
+        transactionID: string;
+        backTo?: string;
+    };
     [SCREENS.TRAVEL.TRIP_DETAILS]: {
         reportID: string;
         transactionID: string;
+        reservationIndex: number;
         backTo?: string;
     };
 };
diff --git a/src/pages/Travel/TripSummary.tsx b/src/pages/Travel/TripSummaryPage.tsx
similarity index 90%
rename from src/pages/Travel/TripSummary.tsx
rename to src/pages/Travel/TripSummaryPage.tsx
index a024d28bd6db..92a9aab8e107 100644
--- a/src/pages/Travel/TripSummary.tsx
+++ b/src/pages/Travel/TripSummaryPage.tsx
@@ -15,9 +15,9 @@ import * as TripReservationUtils from '@src/libs/TripReservationUtils';
 import ONYXKEYS from '@src/ONYXKEYS';
 import type SCREENS from '@src/SCREENS';
 
-type TripDetailsPageProps = StackScreenProps<TravelNavigatorParamList, typeof SCREENS.TRAVEL.TRIP_DETAILS>;
+type TripSummaryPageProps = StackScreenProps<TravelNavigatorParamList, typeof SCREENS.TRAVEL.TRIP_SUMMARY>;
 
-function TripDetailsPage({route}: TripDetailsPageProps) {
+function TripSummaryPage({route}: TripSummaryPageProps) {
     const {translate} = useLocalize();
     const {canUseSpotnanaTravel} = usePermissions();
 
@@ -30,7 +30,7 @@ function TripDetailsPage({route}: TripDetailsPageProps) {
             includeSafeAreaPaddingBottom={false}
             shouldEnablePickerAvoiding={false}
             shouldEnableMaxHeight
-            testID={TripDetailsPage.displayName}
+            testID={TripSummaryPage.displayName}
             shouldShowOfflineIndicatorInWideScreen
         >
             <FullPageNotFoundView
@@ -60,6 +60,6 @@ function TripDetailsPage({route}: TripDetailsPageProps) {
     );
 }
 
-TripDetailsPage.displayName = 'TripDetailsPage';
+TripSummaryPage.displayName = 'TripSummaryPage';
 
-export default TripDetailsPage;
+export default TripSummaryPage;

From 4b3a15904f8a3997364ef234ad7bd5eeb9a45712 Mon Sep 17 00:00:00 2001
From: Blazej Kustra <blazej.kustra@swmansion.com>
Date: Wed, 27 Nov 2024 18:32:54 +0100
Subject: [PATCH 30/75] Navigate to summary conditionally

---
 .../ReportActionItem/MoneyRequestView.tsx          | 14 +++++++++++---
 1 file changed, 11 insertions(+), 3 deletions(-)

diff --git a/src/components/ReportActionItem/MoneyRequestView.tsx b/src/components/ReportActionItem/MoneyRequestView.tsx
index 4fb50ad39cc1..56fdf582f5b7 100644
--- a/src/components/ReportActionItem/MoneyRequestView.tsx
+++ b/src/components/ReportActionItem/MoneyRequestView.tsx
@@ -694,9 +694,17 @@ function MoneyRequestView({report, shouldShowAnimatedBackground, readonly = fals
                     <MenuItem
                         title={translate('travel.viewTripDetails')}
                         icon={Expensicons.Suitcase}
-                        onPress={() =>
-                            Navigation.navigate(ROUTES.TRAVEL_TRIP_DETAILS.getRoute(report?.parentReportID ?? '-1', transaction?.transactionID ?? '-1', Navigation.getReportRHPActiveRoute()))
-                        }
+                        onPress={() => {
+                            const reservations = transaction?.receipt?.reservationList?.length ?? 0;
+                            if (reservations > 1) {
+                                Navigation.navigate(
+                                    ROUTES.TRAVEL_TRIP_SUMMARY.getRoute(report?.parentReportID ?? '-1', transaction?.transactionID ?? '-1', Navigation.getReportRHPActiveRoute()),
+                                );
+                            }
+                            Navigation.navigate(
+                                ROUTES.TRAVEL_TRIP_DETAILS.getRoute(report?.parentReportID ?? '-1', transaction?.transactionID ?? '-1', 0, Navigation.getReportRHPActiveRoute()),
+                            );
+                        }}
                     />
                 )}
                 {shouldShowAttendees && (

From a1ebfe7db4c327d6d9d8ff755976fb526ab0ac1f Mon Sep 17 00:00:00 2001
From: Blazej Kustra <blazej.kustra@swmansion.com>
Date: Wed, 27 Nov 2024 18:33:13 +0100
Subject: [PATCH 31/75] Clean date utils around transport

---
 src/libs/DateUtils.ts | 34 +++++++++++++++++++++++++---------
 1 file changed, 25 insertions(+), 9 deletions(-)

diff --git a/src/libs/DateUtils.ts b/src/libs/DateUtils.ts
index 9bf707acdf46..21c0a2b7e375 100644
--- a/src/libs/DateUtils.ts
+++ b/src/libs/DateUtils.ts
@@ -799,19 +799,34 @@ function getFormattedReservationRangeDate(date1: Date, date2: Date): string {
 /**
  * Returns a formatted date of departure.
  * Dates are formatted as follows:
- * 1. When the date refers to the current year: Departs on Sunday, Mar 17 at 8:00. When shorter is true, the output is: Mar 17, 8:00 AM
- * 2. When the date refers not to the current year: Departs on Wednesday, Mar 17, 2023 at 8:00. When shorter is true, the output is: Mar 17, 2023 8:00 AM
+ * 1. When the date refers to the current year: Departs on Sunday, Mar 17 at 8:00.
+ * 2. When the date refers not to the current year: Departs on Wednesday, Mar 17, 2023 at 8:00.
  */
-function getFormattedTransportDate(date: Date, shorter = false): string {
+function getFormattedTransportDate(date: Date): string {
     const {translateLocal} = Localize;
     if (isThisYear(date)) {
-        return shorter
-            ? format(date, 'MMM d, h:mm a')
-            : `${translateLocal('travel.departs')} ${format(date, 'EEEE, MMM d')} ${translateLocal('common.conjunctionAt')} ${format(date, 'HH:MM')}`;
+        return `${translateLocal('travel.departs')} ${format(date, 'EEEE, MMM d')} ${translateLocal('common.conjunctionAt')} ${format(date, 'HH:MM')}`;
     }
-    return shorter
-        ? format(date, 'MMM d, yyyy, h:mm a')
-        : `${translateLocal('travel.departs')} ${format(date, 'EEEE, MMM d, yyyy')} ${translateLocal('common.conjunctionAt')} ${format(date, 'HH:MM')}`;
+    return `${translateLocal('travel.departs')} ${format(date, 'EEEE, MMM d, yyyy')} ${translateLocal('common.conjunctionAt')} ${format(date, 'HH:MM')}`;
+}
+
+/**
+ * Returns a formatted flight date and hour.
+ * Dates are formatted as follows:
+ * 1. When the date refers to the current year: Wednesday, Mar 17 8:00 AM
+ * 2. When the date refers not to the current year: Wednesday, Mar 17, 2023 8:00 AM
+ */
+function getFormattedTransportDateAndHour(date: Date): {date: string; hour: string} {
+    if (isThisYear(date)) {
+        return {
+            date: format(date, 'EEEE, MMM d'),
+            hour: format(date, 'h:mm a'),
+        };
+    }
+    return {
+        date: format(date, 'EEEE, MMM d, yyyy'),
+        hour: format(date, 'h:mm a'),
+    };
 }
 
 /**
@@ -903,6 +918,7 @@ const DateUtils = {
     getFormattedDateRange,
     getFormattedReservationRangeDate,
     getFormattedTransportDate,
+    getFormattedTransportDateAndHour,
     doesDateBelongToAPastYear,
     isCardExpired,
     getDifferenceInDaysFromNow,

From aa0fb9403d8c8d67ec0dc4800e859c6fe01f9610 Mon Sep 17 00:00:00 2001
From: Blazej Kustra <blazej.kustra@swmansion.com>
Date: Wed, 27 Nov 2024 18:33:36 +0100
Subject: [PATCH 32/75] Add reservation index to display just one flight

---
 src/libs/TripReservationUtils.ts | 5 +++--
 1 file changed, 3 insertions(+), 2 deletions(-)

diff --git a/src/libs/TripReservationUtils.ts b/src/libs/TripReservationUtils.ts
index a8714122da97..6ddf0dc30f57 100644
--- a/src/libs/TripReservationUtils.ts
+++ b/src/libs/TripReservationUtils.ts
@@ -63,16 +63,17 @@ function getTripReservationIcon(reservationType?: ReservationType): IconAsset {
     }
 }
 
-type ReservationData = {reservation: Reservation; transactionID: string; reportID: string};
+type ReservationData = {reservation: Reservation; transactionID: string; reportID: string; reservationIndex: number};
 
 function getReservationsFromTripTransactions(transactions: Transaction[]): ReservationData[] {
     return transactions
         .flatMap(
             (item) =>
-                item?.receipt?.reservationList?.map((reservation) => ({
+                item?.receipt?.reservationList?.map((reservation, reservationIndex) => ({
                     reservation,
                     transactionID: item.transactionID,
                     reportID: item.reportID,
+                    reservationIndex,
                 })) ?? [],
         )
         .sort((a, b) => new Date(a.reservation.start.date).getTime() - new Date(b.reservation.start.date).getTime());

From 1d541a1e95271c6682c74a7ad9f55c23363952f4 Mon Sep 17 00:00:00 2001
From: Blazej Kustra <blazej.kustra@swmansion.com>
Date: Wed, 27 Nov 2024 18:33:48 +0100
Subject: [PATCH 33/75] Update config configuration

---
 src/libs/Navigation/linkingConfig/config.ts | 8 +++++++-
 1 file changed, 7 insertions(+), 1 deletion(-)

diff --git a/src/libs/Navigation/linkingConfig/config.ts b/src/libs/Navigation/linkingConfig/config.ts
index 317c1e15e04f..2cf2f28a08e7 100644
--- a/src/libs/Navigation/linkingConfig/config.ts
+++ b/src/libs/Navigation/linkingConfig/config.ts
@@ -1320,7 +1320,13 @@ const config: LinkingOptions<RootStackParamList>['config'] = {
                     screens: {
                         [SCREENS.TRAVEL.MY_TRIPS]: ROUTES.TRAVEL_MY_TRIPS,
                         [SCREENS.TRAVEL.TCS]: ROUTES.TRAVEL_TCS,
-                        [SCREENS.TRAVEL.TRIP_DETAILS]: ROUTES.TRAVEL_TRIP_DETAILS.route,
+                        [SCREENS.TRAVEL.TRIP_SUMMARY]: ROUTES.TRAVEL_TRIP_SUMMARY.route,
+                        [SCREENS.TRAVEL.TRIP_DETAILS]: {
+                            path: ROUTES.TRAVEL_TRIP_DETAILS.route,
+                            parse: {
+                                reservationIndex: (reservationIndex: string) => parseInt(reservationIndex, 10),
+                            },
+                        },
                     },
                 },
                 [SCREENS.RIGHT_MODAL.SEARCH_REPORT]: {

From fe182384b590466d33be942542788135551a16d1 Mon Sep 17 00:00:00 2001
From: Blazej Kustra <blazej.kustra@swmansion.com>
Date: Wed, 27 Nov 2024 18:34:03 +0100
Subject: [PATCH 34/75] Update styles after design changes

---
 src/pages/Travel/CarTripDetails.tsx    |  19 ++-
 src/pages/Travel/FlightTripDetails.tsx | 171 ++++++++++++-------------
 src/pages/Travel/HotelTripDetails.tsx  |  24 ++--
 src/pages/Travel/TripDetailsPage.tsx   |   3 +-
 4 files changed, 108 insertions(+), 109 deletions(-)

diff --git a/src/pages/Travel/CarTripDetails.tsx b/src/pages/Travel/CarTripDetails.tsx
index 25c417425a9f..ceff885c349b 100644
--- a/src/pages/Travel/CarTripDetails.tsx
+++ b/src/pages/Travel/CarTripDetails.tsx
@@ -4,7 +4,6 @@ import type {OnyxEntry} from 'react-native-onyx';
 import * as Expensicons from '@components/Icon/Expensicons';
 import MenuItem from '@components/MenuItem';
 import MenuItemWithTopDescription from '@components/MenuItemWithTopDescription';
-import Text from '@components/Text';
 import useLocalize from '@hooks/useLocalize';
 import useStyleUtils from '@hooks/useStyleUtils';
 import useTheme from '@hooks/useTheme';
@@ -32,8 +31,8 @@ function CarTripDetails({transaction, personalDetails}: CarTripDetailsProps) {
     }
 
     const reservationIcon = TripReservationUtils.getTripReservationIcon(carReservation.type);
-    const checkInDate = DateUtils.getFormattedTransportDate(new Date(carReservation.start.date), true);
-    const checkOutDate = DateUtils.getFormattedTransportDate(new Date(carReservation.end.date), true);
+    const pickUpDate = DateUtils.getFormattedTransportDateAndHour(new Date(carReservation.start.date));
+    const dropOffDate = DateUtils.getFormattedTransportDateAndHour(new Date(carReservation.end.date));
 
     return (
         <>
@@ -46,12 +45,10 @@ function CarTripDetails({transaction, personalDetails}: CarTripDetailsProps) {
                 interactive={false}
                 wrapperStyle={styles.pb3}
             />
-            <Text style={[styles.textSupporting, styles.mh5, styles.mt3, styles.mb2]}>{translate('travel.carDetails.rentalCar')}</Text>
-            <Text style={[styles.textHeadlineH1, styles.mh5, styles.mb3]}>{carReservation.vendor}</Text>
             <MenuItem
-                description={carReservation.start.location}
-                descriptionTextStyle={[styles.textLabelSupporting, styles.lh16]}
                 title={carReservation.vendor}
+                description={translate('travel.carDetails.rentalCar')}
+                descriptionTextStyle={[styles.textLabelSupporting, styles.lh16]}
                 secondaryIcon={reservationIcon}
                 wrapperStyle={[styles.taskDescriptionMenuItem]}
                 numberOfLinesDescription={2}
@@ -62,15 +59,15 @@ function CarTripDetails({transaction, personalDetails}: CarTripDetailsProps) {
                 interactive={false}
             />
             <MenuItemWithTopDescription
-                description={translate('travel.carDetails.pickUp')}
-                title={checkInDate}
+                description={`${translate('travel.carDetails.pickUp')} ${CONST.DOT_SEPARATOR} ${pickUpDate.date}`}
+                title={pickUpDate.hour}
                 interactive={false}
                 helperText={carReservation.start.location}
                 helperTextStyle={[styles.pb3, styles.mtn2]}
             />
             <MenuItemWithTopDescription
-                description={translate('travel.carDetails.dropOff')}
-                title={checkOutDate}
+                description={`${translate('travel.carDetails.dropOff')} ${CONST.DOT_SEPARATOR} ${dropOffDate.date}`}
+                title={dropOffDate.hour}
                 interactive={false}
                 helperText={carReservation.end.location}
                 helperTextStyle={[styles.pb3, styles.mtn2]}
diff --git a/src/pages/Travel/FlightTripDetails.tsx b/src/pages/Travel/FlightTripDetails.tsx
index b92c4ad57cce..d407dfb72aa4 100644
--- a/src/pages/Travel/FlightTripDetails.tsx
+++ b/src/pages/Travel/FlightTripDetails.tsx
@@ -4,7 +4,6 @@ import type {OnyxEntry} from 'react-native-onyx';
 import * as Expensicons from '@components/Icon/Expensicons';
 import MenuItem from '@components/MenuItem';
 import MenuItemWithTopDescription from '@components/MenuItemWithTopDescription';
-import Text from '@components/Text';
 import useLocalize from '@hooks/useLocalize';
 import useStyleUtils from '@hooks/useStyleUtils';
 import useTheme from '@hooks/useTheme';
@@ -17,14 +16,28 @@ import type {PersonalDetails, Transaction} from '@src/types/onyx';
 type FlightTripDetailsProps = {
     transaction: OnyxEntry<Transaction>;
     personalDetails: OnyxEntry<PersonalDetails>;
+    reservationIndex: number;
 };
 
-function FlightTripDetails({transaction, personalDetails}: FlightTripDetailsProps) {
+function FlightTripDetails({transaction, personalDetails, reservationIndex}: FlightTripDetailsProps) {
     const styles = useThemeStyles();
     const theme = useTheme();
     const StyleUtils = useStyleUtils();
     const {translate} = useLocalize();
 
+    const flightReservation = transaction?.receipt?.reservationList?.at(reservationIndex);
+
+    if (!flightReservation) {
+        return null;
+    }
+
+    const reservationIcon = TripReservationUtils.getTripReservationIcon(flightReservation.type);
+    const startDate = DateUtils.getFormattedTransportDateAndHour(new Date(flightReservation.start.date));
+    const endDate = DateUtils.getFormattedTransportDateAndHour(new Date(flightReservation.end.date));
+
+    const prevFlightStartDate = reservationIndex > 0 && transaction?.receipt?.reservationList?.at(reservationIndex - 1)?.end.date;
+    const layover = prevFlightStartDate && DateUtils.getFormattedDurationBetweenDates(new Date(prevFlightStartDate), new Date(flightReservation.start.date));
+
     return (
         <>
             <MenuItem
@@ -37,100 +50,86 @@ function FlightTripDetails({transaction, personalDetails}: FlightTripDetailsProp
                 wrapperStyle={styles.pb3}
             />
 
-            {transaction?.receipt?.reservationList?.map((reservation, index) => {
-                const reservationIcon = TripReservationUtils.getTripReservationIcon(reservation.type);
-                const startDate = DateUtils.getFormattedTransportDate(new Date(reservation.start.date), true);
-                const endDate = DateUtils.getFormattedTransportDate(new Date(reservation.end.date), true);
+            {!!layover && (
+                <>
+                    <MenuItem
+                        description={`${transaction?.receipt?.reservationList?.at(0)?.start.longName} (${transaction?.receipt?.reservationList?.at(0)?.start.shortName})`}
+                        title={`${layover} ${translate('travel.flightDetails.layover')}`}
+                        descriptionTextStyle={[styles.textLabelSupporting, styles.lh16]}
+                        secondaryIcon={Expensicons.Chair}
+                        wrapperStyle={[styles.taskDescriptionMenuItem]}
+                        numberOfLinesDescription={2}
+                        iconHeight={20}
+                        iconWidth={20}
+                        iconStyles={[StyleUtils.getTripReservationIconContainer(false), styles.mr3]}
+                        secondaryIconFill={theme.icon}
+                        interactive={false}
+                    />
+                    <View style={[styles.borderBottom, styles.mh5, styles.mv3]} />
+                </>
+            )}
 
-                const nextFlightStartDate = transaction.receipt?.reservationList?.at(index + 1)?.start.date;
-                const layover = nextFlightStartDate && DateUtils.getFormattedDurationBetweenDates(new Date(reservation.end.date), new Date(nextFlightStartDate));
+            <MenuItem
+                title={`${flightReservation.start.cityName} (${flightReservation.start.shortName}) ${translate('common.conjunctionTo')} ${flightReservation.end.cityName} (${
+                    flightReservation.end.shortName
+                })`}
+                description={`${flightReservation.company?.longName} ${CONST.DOT_SEPARATOR} ${flightReservation.route?.airlineCode}`}
+                descriptionTextStyle={[styles.textLabelSupporting, styles.lh16]}
+                secondaryIcon={reservationIcon}
+                wrapperStyle={[styles.taskDescriptionMenuItem]}
+                numberOfLinesDescription={2}
+                iconHeight={20}
+                iconWidth={20}
+                iconStyles={[StyleUtils.getTripReservationIconContainer(false), styles.mr3]}
+                secondaryIconFill={theme.icon}
+                interactive={false}
+            />
+            <MenuItemWithTopDescription
+                description={`${translate('travel.flightDetails.takeOff')} ${CONST.DOT_SEPARATOR} ${startDate.date}`}
+                title={startDate.hour}
+                helperText={`${flightReservation.start.longName} (${flightReservation.start.shortName})${
+                    flightReservation.arrivalGate?.terminal ? `, ${flightReservation.arrivalGate?.terminal}` : ''
+                }`}
+                helperTextStyle={[styles.pb3, styles.mtn2]}
+                interactive={false}
+            />
+            <MenuItemWithTopDescription
+                description={`${translate('travel.flightDetails.landing')} ${CONST.DOT_SEPARATOR} ${endDate.date}`}
+                title={endDate.hour}
+                helperText={`${flightReservation.end.longName} (${flightReservation.end.shortName})`}
+                helperTextStyle={[styles.pb3, styles.mtn2]}
+                interactive={false}
+            />
 
-                return (
-                    <>
-                        <Text style={[styles.textSupporting, styles.mh5, styles.mt3, styles.mb2]}>{translate('travel.flight')}</Text>
-                        <Text style={[styles.textHeadlineH1, styles.mh5, styles.mb3]}>
-                            {reservation.start.cityName} ({reservation.start.shortName}) {translate('common.conjunctionTo')} {reservation.end.cityName} ({reservation.end.shortName})
-                        </Text>
-                        <MenuItem
-                            // TODO: blazejkustra - Use the actual duration
-                            description={`2h 15m ${CONST.DOT_SEPARATOR} ${reservation.end.longName}`}
-                            descriptionTextStyle={[styles.textLabelSupporting, styles.lh16]}
-                            title={`${reservation.company?.longName} ${CONST.DOT_SEPARATOR} ${reservation.route?.airlineCode}`}
-                            secondaryIcon={reservationIcon}
-                            wrapperStyle={[styles.taskDescriptionMenuItem]}
-                            numberOfLinesDescription={2}
-                            iconHeight={20}
-                            iconWidth={20}
-                            iconStyles={[StyleUtils.getTripReservationIconContainer(false), styles.mr3]}
-                            secondaryIconFill={theme.icon}
+            <View style={[styles.flexRow, styles.flexWrap]}>
+                {!!flightReservation.route?.number && (
+                    <View style={styles.w50}>
+                        <MenuItemWithTopDescription
+                            description={translate('travel.flightDetails.seat')}
+                            title={flightReservation.route?.number}
                             interactive={false}
                         />
+                    </View>
+                )}
+                {!!flightReservation.route?.class && (
+                    <View style={styles.w50}>
                         <MenuItemWithTopDescription
-                            description={translate('travel.flightDetails.takeOff')}
-                            title={startDate}
-                            helperText={`${reservation.start.longName} (${reservation.start.shortName})${reservation.arrivalGate?.terminal ? `, ${reservation.arrivalGate?.terminal}` : ''}`}
-                            helperTextStyle={[styles.pb3, styles.mtn2]}
+                            description={translate('travel.flightDetails.class')}
+                            title={flightReservation.route.class}
                             interactive={false}
                         />
+                    </View>
+                )}
+                {!!flightReservation.confirmations?.at(0)?.value && (
+                    <View style={styles.w50}>
                         <MenuItemWithTopDescription
-                            description={translate('travel.flightDetails.landing')}
-                            title={endDate}
-                            helperText={`${reservation.end.longName} (${reservation.end.shortName})`}
-                            helperTextStyle={[styles.pb3, styles.mtn2]}
+                            description={translate('travel.flightDetails.recordLocator')}
+                            title={flightReservation.confirmations?.at(0)?.value}
                             interactive={false}
                         />
-
-                        <View style={[styles.flexRow, styles.flexWrap]}>
-                            {!!reservation.route?.number && (
-                                <View style={styles.w50}>
-                                    <MenuItemWithTopDescription
-                                        description={translate('travel.flightDetails.seat')}
-                                        title={reservation.route?.number}
-                                        interactive={false}
-                                    />
-                                </View>
-                            )}
-                            {!!reservation.route?.class && (
-                                <View style={styles.w50}>
-                                    <MenuItemWithTopDescription
-                                        description={translate('travel.flightDetails.class')}
-                                        title={reservation.route.class}
-                                        interactive={false}
-                                    />
-                                </View>
-                            )}
-                            {!!reservation.confirmations?.at(0)?.value && (
-                                <View style={styles.w50}>
-                                    <MenuItemWithTopDescription
-                                        description={translate('travel.flightDetails.recordLocator')}
-                                        title={reservation.confirmations?.at(0)?.value}
-                                        interactive={false}
-                                    />
-                                </View>
-                            )}
-                        </View>
-                        <View style={[styles.borderBottom, styles.mh5, styles.mv3]} />
-                        {!!layover && (
-                            <>
-                                <MenuItem
-                                    description={`${transaction?.receipt?.reservationList?.at(0)?.start.longName} (${transaction?.receipt?.reservationList?.at(0)?.start.shortName})`}
-                                    title={`${layover} ${translate('travel.flightDetails.layover')}`}
-                                    descriptionTextStyle={[styles.textLabelSupporting, styles.lh16]}
-                                    secondaryIcon={Expensicons.Chair}
-                                    wrapperStyle={[styles.taskDescriptionMenuItem]}
-                                    numberOfLinesDescription={2}
-                                    iconHeight={20}
-                                    iconWidth={20}
-                                    iconStyles={[StyleUtils.getTripReservationIconContainer(false), styles.mr3]}
-                                    secondaryIconFill={theme.icon}
-                                    interactive={false}
-                                />
-                                <View style={[styles.borderBottom, styles.mh5, styles.mv3]} />
-                            </>
-                        )}
-                    </>
-                );
-            })}
+                    </View>
+                )}
+            </View>
         </>
     );
 }
diff --git a/src/pages/Travel/HotelTripDetails.tsx b/src/pages/Travel/HotelTripDetails.tsx
index 32f0a6836828..4ce3fbabb7ad 100644
--- a/src/pages/Travel/HotelTripDetails.tsx
+++ b/src/pages/Travel/HotelTripDetails.tsx
@@ -4,7 +4,6 @@ import type {OnyxEntry} from 'react-native-onyx';
 import * as Expensicons from '@components/Icon/Expensicons';
 import MenuItem from '@components/MenuItem';
 import MenuItemWithTopDescription from '@components/MenuItemWithTopDescription';
-import Text from '@components/Text';
 import useLocalize from '@hooks/useLocalize';
 import useStyleUtils from '@hooks/useStyleUtils';
 import useTheme from '@hooks/useTheme';
@@ -32,8 +31,8 @@ function HotelTripDetails({transaction, personalDetails}: HotelTripDetailsProps)
     }
 
     const reservationIcon = TripReservationUtils.getTripReservationIcon(hotelReservation.type);
-    const checkInDate = DateUtils.getFormattedTransportDate(new Date(hotelReservation.start.date), true);
-    const checkOutDate = DateUtils.getFormattedTransportDate(new Date(hotelReservation.end.date), true);
+    const checkInDate = DateUtils.getFormattedTransportDateAndHour(new Date(hotelReservation.start.date));
+    const checkOutDate = DateUtils.getFormattedTransportDateAndHour(new Date(hotelReservation.end.date));
 
     return (
         <>
@@ -46,12 +45,10 @@ function HotelTripDetails({transaction, personalDetails}: HotelTripDetailsProps)
                 interactive={false}
                 wrapperStyle={styles.pb3}
             />
-            <Text style={[styles.textSupporting, styles.mh5, styles.mt3, styles.mb2]}>{translate('travel.hotel')}</Text>
-            <Text style={[styles.textHeadlineH1, styles.mh5, styles.mb3]}>{hotelReservation.start.longName}</Text>
             <MenuItem
-                description={hotelReservation.start.address}
-                descriptionTextStyle={[styles.textLabelSupporting, styles.lh16]}
                 title={hotelReservation.start.longName}
+                description={translate('travel.hotel')}
+                descriptionTextStyle={[styles.textLabelSupporting, styles.lh16]}
                 secondaryIcon={reservationIcon}
                 wrapperStyle={[styles.taskDescriptionMenuItem]}
                 numberOfLinesDescription={2}
@@ -62,13 +59,18 @@ function HotelTripDetails({transaction, personalDetails}: HotelTripDetailsProps)
                 interactive={false}
             />
             <MenuItemWithTopDescription
-                description={translate('travel.hotelDetails.checkIn')}
-                title={checkInDate}
+                description={translate('common.address')}
+                title={hotelReservation.start.address}
+                interactive={false}
+            />
+            <MenuItemWithTopDescription
+                description={`${translate('travel.hotelDetails.checkIn')} ${CONST.DOT_SEPARATOR} ${checkInDate.date}`}
+                title={checkInDate.hour}
                 interactive={false}
             />
             <MenuItemWithTopDescription
-                description={translate('travel.hotelDetails.checkOut')}
-                title={checkOutDate}
+                description={`${translate('travel.hotelDetails.checkOut')} ${CONST.DOT_SEPARATOR} ${checkOutDate.date}`}
+                title={checkOutDate.hour}
                 interactive={false}
             />
             {!!hotelReservation.confirmations?.at(0)?.value && (
diff --git a/src/pages/Travel/TripDetailsPage.tsx b/src/pages/Travel/TripDetailsPage.tsx
index 971128101486..96d7ec2b56ba 100644
--- a/src/pages/Travel/TripDetailsPage.tsx
+++ b/src/pages/Travel/TripDetailsPage.tsx
@@ -52,7 +52,7 @@ function TripDetailsPage({route}: TripDetailsPageProps) {
                 shouldShow={!canUseSpotnanaTravel && !NativeModules.HybridAppModule}
             >
                 <HeaderWithBackButton
-                    title={translate('common.details')}
+                    title={reservationType ? `${translate(`travel.${reservationType}`)} ${translate('common.details').toLowerCase()}` : translate('common.details')}
                     shouldShowBackButton
                 />
                 <ScrollView>
@@ -60,6 +60,7 @@ function TripDetailsPage({route}: TripDetailsPageProps) {
                         <FlightTripDetails
                             transaction={transaction}
                             personalDetails={personalDetails}
+                            reservationIndex={route.params.reservationIndex}
                         />
                     )}
                     {reservationType === 'hotel' && (

From c882db81eb5712c02fb0b01a652163b651a87e2d Mon Sep 17 00:00:00 2001
From: Blazej Kustra <blazej.kustra@swmansion.com>
Date: Wed, 27 Nov 2024 18:52:46 +0100
Subject: [PATCH 35/75] Rename TRIP_DETAILS screen identifier to maintain
 consistent naming convention

---
 src/SCREENS.ts | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/src/SCREENS.ts b/src/SCREENS.ts
index 2efe8084b3bb..5b708e537147 100644
--- a/src/SCREENS.ts
+++ b/src/SCREENS.ts
@@ -28,7 +28,7 @@ const SCREENS = {
         MY_TRIPS: 'Travel_MyTrips',
         TCS: 'Travel_TCS',
         TRIP_SUMMARY: 'Travel_TripSummary',
-        TRIP_DETAILS: 'Trip_Details',
+        TRIP_DETAILS: 'Travel_TripDetails',
     },
     SEARCH: {
         CENTRAL_PANE: 'Search_Central_Pane',

From c20e09e6810ddc7f4979d5fc8e72d3116fdff964 Mon Sep 17 00:00:00 2001
From: Blazej Kustra <blazej.kustra@swmansion.com>
Date: Wed, 27 Nov 2024 18:54:41 +0100
Subject: [PATCH 36/75] Fix typecheck and lint

---
 src/libs/ReportUtils.ts | 6 ++----
 1 file changed, 2 insertions(+), 4 deletions(-)

diff --git a/src/libs/ReportUtils.ts b/src/libs/ReportUtils.ts
index 16d1d65d99f1..c647223a4715 100644
--- a/src/libs/ReportUtils.ts
+++ b/src/libs/ReportUtils.ts
@@ -860,7 +860,7 @@ function isChatReport(report: OnyxEntry<Report>): boolean {
     return report?.type === CONST.REPORT.TYPE.CHAT;
 }
 
-function isInvoiceReport(report: OnyxInputOrEntry<Report> | SearchReport): report is Report {
+function isInvoiceReport(report: OnyxInputOrEntry<Report> | SearchReport): boolean {
     return report?.type === CONST.REPORT.TYPE.INVOICE;
 }
 
@@ -1667,8 +1667,6 @@ function isMoneyRequest(reportOrID: OnyxEntry<Report> | string): boolean {
 /**
  * Checks if a report is an IOU or expense report.
  */
-function isMoneyRequestReport(reportOrID: OnyxInputOrEntry<Report>): reportOrID is Report;
-function isMoneyRequestReport(reportOrID: SearchReport | string): boolean;
 function isMoneyRequestReport(reportOrID: OnyxInputOrEntry<Report> | SearchReport | string): boolean {
     const report = typeof reportOrID === 'string' ? ReportConnection.getAllReports()?.[`${ONYXKEYS.COLLECTION.REPORT}${reportOrID}`] ?? null : reportOrID;
     return isIOUReport(report) || isExpenseReport(report);
@@ -2848,7 +2846,7 @@ function hasNonReimbursableTransactions(iouReportID: string | undefined): boolea
 function getMoneyRequestSpendBreakdown(report: OnyxInputOrEntry<Report>, allReportsDict?: OnyxCollection<Report>): SpendBreakdown {
     const allAvailableReports = allReportsDict ?? ReportConnection.getAllReports();
     let moneyRequestReport: OnyxEntry<Report>;
-    if (isMoneyRequestReport(report) || isInvoiceReport(report)) {
+    if (report && (isMoneyRequestReport(report) || isInvoiceReport(report))) {
         moneyRequestReport = report;
     }
     if (allAvailableReports && report?.iouReportID) {

From 7dcfbd0159a50dba5fd7a7a4f559f844a5d8bcb6 Mon Sep 17 00:00:00 2001
From: Blazej Kustra <blazej.kustra@swmansion.com>
Date: Wed, 27 Nov 2024 19:01:16 +0100
Subject: [PATCH 37/75] Add Spanish translations for flight, hotel, and car
 details

---
 src/languages/es.ts | 27 +++++++++++++++++++++++++++
 1 file changed, 27 insertions(+)

diff --git a/src/languages/es.ts b/src/languages/es.ts
index 1897e10ccaac..3710c3080c99 100644
--- a/src/languages/es.ts
+++ b/src/languages/es.ts
@@ -2449,9 +2449,36 @@ const translations = {
             error: 'Debes aceptar los Términos y condiciones para que el viaje continúe',
         },
         flight: 'Vuelo',
+        flightDetails: {
+            layover: 'Escala',
+            takeOff: 'Despegue',
+            landing: 'Aterrizaje',
+            passenger: 'Pasajero',
+            seat: 'Asiento',
+            class: 'Clase de cabina',
+            recordLocator: 'Localizador de la reserva',
+        },
         hotel: 'Hotel',
+        hotelDetails: {
+            guest: 'Cliente',
+            checkIn: 'Entrada',
+            checkOut: 'Salida',
+            roomType: 'Tipo de habitación',
+            cancellation: 'Política de cancelación',
+            confirmation: 'Número de confirmación',
+        },
         car: 'Auto',
+        carDetails: {
+            rentalCar: 'Coche de alquiler',
+            pickUp: 'Recogida',
+            dropOff: 'Devolución',
+            driver: 'Conductor',
+            carType: 'Tipo de coche',
+            cancellation: 'Política de cancelación',
+            confirmation: 'Número de confirmación',
+        },
         viewTrip: 'Ver viaje',
+        modifyTrip: 'Modificar viaje',
         tripSupport: 'Soporte de Viaje',
         viewTripDetails: 'Ver detalles del viaje',
         trip: 'Viaje',

From 5ba408aa59533d7f32c22e48d69bc1340b8cff2a Mon Sep 17 00:00:00 2001
From: Blazej Kustra <blazej.kustra@swmansion.com>
Date: Thu, 28 Nov 2024 14:52:46 +0100
Subject: [PATCH 38/75] Refactor reservation type checks to use constants

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

diff --git a/src/pages/Travel/TripDetailsPage.tsx b/src/pages/Travel/TripDetailsPage.tsx
index 96d7ec2b56ba..ee7328299219 100644
--- a/src/pages/Travel/TripDetailsPage.tsx
+++ b/src/pages/Travel/TripDetailsPage.tsx
@@ -56,20 +56,20 @@ function TripDetailsPage({route}: TripDetailsPageProps) {
                     shouldShowBackButton
                 />
                 <ScrollView>
-                    {reservationType === 'flight' && (
+                    {reservationType === CONST.RESERVATION_TYPE.FLIGHT && (
                         <FlightTripDetails
                             transaction={transaction}
                             personalDetails={personalDetails}
                             reservationIndex={route.params.reservationIndex}
                         />
                     )}
-                    {reservationType === 'hotel' && (
+                    {reservationType === CONST.RESERVATION_TYPE.HOTEL && (
                         <HotelTripDetails
                             transaction={transaction}
                             personalDetails={personalDetails}
                         />
                     )}
-                    {reservationType === 'car' && (
+                    {reservationType === CONST.RESERVATION_TYPE.CAR && (
                         <CarTripDetails
                             transaction={transaction}
                             personalDetails={personalDetails}

From 7c2d12d2635435503054d5ab9dec05e3aa0b2273 Mon Sep 17 00:00:00 2001
From: Blazej Kustra <blazej.kustra@swmansion.com>
Date: Thu, 28 Nov 2024 15:45:44 +0100
Subject: [PATCH 39/75] Add cancellation deadline and policy to car and hotel
 trip details

---
 src/languages/en.ts                   |  2 ++
 src/pages/Travel/CarTripDetails.tsx   | 16 ++++++++++++++--
 src/pages/Travel/HotelTripDetails.tsx | 14 +++++++++++++-
 src/types/onyx/Transaction.ts         |  6 ++++++
 4 files changed, 35 insertions(+), 3 deletions(-)

diff --git a/src/languages/en.ts b/src/languages/en.ts
index 148f3463495f..753b4600e78d 100755
--- a/src/languages/en.ts
+++ b/src/languages/en.ts
@@ -2441,6 +2441,7 @@ const translations = {
             checkOut: 'Check-out',
             roomType: 'Room type',
             cancellation: 'Cancellation policy',
+            cancellationUntil: 'Free cancellation until',
             confirmation: 'Confirmation number',
         },
         car: 'Car',
@@ -2451,6 +2452,7 @@ const translations = {
             driver: 'Driver',
             carType: 'Car type',
             cancellation: 'Cancellation policy',
+            cancellationUntil: 'Free cancellation until',
             confirmation: 'Confirmation number',
         },
         viewTrip: 'View trip',
diff --git a/src/pages/Travel/CarTripDetails.tsx b/src/pages/Travel/CarTripDetails.tsx
index ceff885c349b..5e87b0f5b79f 100644
--- a/src/pages/Travel/CarTripDetails.tsx
+++ b/src/pages/Travel/CarTripDetails.tsx
@@ -33,6 +33,9 @@ function CarTripDetails({transaction, personalDetails}: CarTripDetailsProps) {
     const reservationIcon = TripReservationUtils.getTripReservationIcon(carReservation.type);
     const pickUpDate = DateUtils.getFormattedTransportDateAndHour(new Date(carReservation.start.date));
     const dropOffDate = DateUtils.getFormattedTransportDateAndHour(new Date(carReservation.end.date));
+    const cancellationText = carReservation.deadline
+        ? `${translate('travel.carDetails.cancellationUntil')} ${DateUtils.getFormattedTransportDateAndHour(new Date(carReservation.deadline)).date}`
+        : carReservation.cancellationPolicy;
 
     return (
         <>
@@ -74,7 +77,7 @@ function CarTripDetails({transaction, personalDetails}: CarTripDetailsProps) {
             />
 
             {!!carReservation.carInfo?.name && (
-                <View style={styles.w50}>
+                <View>
                     <MenuItemWithTopDescription
                         description={translate('travel.carDetails.carType')}
                         title={carReservation.carInfo.name}
@@ -82,8 +85,17 @@ function CarTripDetails({transaction, personalDetails}: CarTripDetailsProps) {
                     />
                 </View>
             )}
+            {!!cancellationText && (
+                <View>
+                    <MenuItemWithTopDescription
+                        description={translate('travel.carDetails.cancellation')}
+                        title={cancellationText}
+                        interactive={false}
+                    />
+                </View>
+            )}
             {!!carReservation.reservationID && (
-                <View style={styles.w50}>
+                <View>
                     <MenuItemWithTopDescription
                         description={translate('travel.carDetails.confirmation')}
                         title={carReservation.reservationID}
diff --git a/src/pages/Travel/HotelTripDetails.tsx b/src/pages/Travel/HotelTripDetails.tsx
index 4ce3fbabb7ad..6e3e5e8c8bfb 100644
--- a/src/pages/Travel/HotelTripDetails.tsx
+++ b/src/pages/Travel/HotelTripDetails.tsx
@@ -33,6 +33,9 @@ function HotelTripDetails({transaction, personalDetails}: HotelTripDetailsProps)
     const reservationIcon = TripReservationUtils.getTripReservationIcon(hotelReservation.type);
     const checkInDate = DateUtils.getFormattedTransportDateAndHour(new Date(hotelReservation.start.date));
     const checkOutDate = DateUtils.getFormattedTransportDateAndHour(new Date(hotelReservation.end.date));
+    const cancellationText = hotelReservation.deadline
+        ? `${translate('travel.hotelDetails.cancellationUntil')} ${DateUtils.getFormattedTransportDateAndHour(new Date(hotelReservation.deadline)).date}`
+        : hotelReservation.cancellationPolicy;
 
     return (
         <>
@@ -73,8 +76,17 @@ function HotelTripDetails({transaction, personalDetails}: HotelTripDetailsProps)
                 title={checkOutDate.hour}
                 interactive={false}
             />
+            {!!cancellationText && (
+                <View>
+                    <MenuItemWithTopDescription
+                        description={translate('travel.carDetails.cancellation')}
+                        title={cancellationText}
+                        interactive={false}
+                    />
+                </View>
+            )}
             {!!hotelReservation.confirmations?.at(0)?.value && (
-                <View style={styles.w50}>
+                <View>
                     <MenuItemWithTopDescription
                         description={translate('travel.hotelDetails.confirmation')}
                         title={hotelReservation.confirmations?.at(0)?.value}
diff --git a/src/types/onyx/Transaction.ts b/src/types/onyx/Transaction.ts
index 0183286510f6..703769dfabf7 100644
--- a/src/types/onyx/Transaction.ts
+++ b/src/types/onyx/Transaction.ts
@@ -207,6 +207,12 @@ type Reservation = {
     /** In flight reservations, this represents the details of the airline company */
     company?: Company;
 
+    /** In car and hotel reservations, this represents the cancellation policy */
+    cancellationPolicy?: string;
+
+    /** In car and hotel reservations, this represents the cancellation deadline */
+    deadline?: string;
+
     /** Collection of passenger confirmations */
     confirmations?: ReservationConfirmation[];
 

From 0389b737e12da98f81af5b2fe4cc951c9bbb936d Mon Sep 17 00:00:00 2001
From: Blazej Kustra <blazej.kustra@swmansion.com>
Date: Fri, 29 Nov 2024 13:51:28 +0100
Subject: [PATCH 40/75] Rename reservation deadline property and update related
 components to use the new name

---
 src/libs/DateUtils.ts                 | 8 ++++++--
 src/pages/Travel/CarTripDetails.tsx   | 4 ++--
 src/pages/Travel/HotelTripDetails.tsx | 5 +++--
 src/types/onyx/Transaction.ts         | 2 +-
 4 files changed, 12 insertions(+), 7 deletions(-)

diff --git a/src/libs/DateUtils.ts b/src/libs/DateUtils.ts
index 21c0a2b7e375..8bdbdd2d21d0 100644
--- a/src/libs/DateUtils.ts
+++ b/src/libs/DateUtils.ts
@@ -832,10 +832,14 @@ function getFormattedTransportDateAndHour(date: Date): {date: string; hour: stri
 /**
  * Returns a formatted layover duration in format "2h 30m".
  */
-function getFormattedDurationBetweenDates(start: Date, end: Date): string {
+function getFormattedDurationBetweenDates(start: Date, end: Date): string | undefined {
     const {days, hours, minutes} = intervalToDuration({start, end});
 
-    return `${days ? `${days}d ` : ''}${hours ? `${hours}h ` : ''}${minutes}m`;
+    if (days && days > 0) {
+        return;
+    }
+
+    return `${hours ? `${hours}h ` : ''}${minutes}m`;
 }
 
 function doesDateBelongToAPastYear(date: string): boolean {
diff --git a/src/pages/Travel/CarTripDetails.tsx b/src/pages/Travel/CarTripDetails.tsx
index 5e87b0f5b79f..4ad406e9b868 100644
--- a/src/pages/Travel/CarTripDetails.tsx
+++ b/src/pages/Travel/CarTripDetails.tsx
@@ -33,8 +33,8 @@ function CarTripDetails({transaction, personalDetails}: CarTripDetailsProps) {
     const reservationIcon = TripReservationUtils.getTripReservationIcon(carReservation.type);
     const pickUpDate = DateUtils.getFormattedTransportDateAndHour(new Date(carReservation.start.date));
     const dropOffDate = DateUtils.getFormattedTransportDateAndHour(new Date(carReservation.end.date));
-    const cancellationText = carReservation.deadline
-        ? `${translate('travel.carDetails.cancellationUntil')} ${DateUtils.getFormattedTransportDateAndHour(new Date(carReservation.deadline)).date}`
+    const cancellationText = carReservation.cancellationDeadline
+        ? `${translate('travel.carDetails.cancellationUntil')} ${DateUtils.getFormattedTransportDateAndHour(new Date(carReservation.cancellationDeadline)).date}`
         : carReservation.cancellationPolicy;
 
     return (
diff --git a/src/pages/Travel/HotelTripDetails.tsx b/src/pages/Travel/HotelTripDetails.tsx
index 6e3e5e8c8bfb..f0fa279fbbe2 100644
--- a/src/pages/Travel/HotelTripDetails.tsx
+++ b/src/pages/Travel/HotelTripDetails.tsx
@@ -30,11 +30,12 @@ function HotelTripDetails({transaction, personalDetails}: HotelTripDetailsProps)
         return null;
     }
 
+
     const reservationIcon = TripReservationUtils.getTripReservationIcon(hotelReservation.type);
     const checkInDate = DateUtils.getFormattedTransportDateAndHour(new Date(hotelReservation.start.date));
     const checkOutDate = DateUtils.getFormattedTransportDateAndHour(new Date(hotelReservation.end.date));
-    const cancellationText = hotelReservation.deadline
-        ? `${translate('travel.hotelDetails.cancellationUntil')} ${DateUtils.getFormattedTransportDateAndHour(new Date(hotelReservation.deadline)).date}`
+    const cancellationText = hotelReservation.cancellationDeadline
+        ? `${translate('travel.hotelDetails.cancellationUntil')} ${DateUtils.getFormattedTransportDateAndHour(new Date(hotelReservation.cancellationDeadline)).date}`
         : hotelReservation.cancellationPolicy;
 
     return (
diff --git a/src/types/onyx/Transaction.ts b/src/types/onyx/Transaction.ts
index 703769dfabf7..991b5230440f 100644
--- a/src/types/onyx/Transaction.ts
+++ b/src/types/onyx/Transaction.ts
@@ -211,7 +211,7 @@ type Reservation = {
     cancellationPolicy?: string;
 
     /** In car and hotel reservations, this represents the cancellation deadline */
-    deadline?: string;
+    cancellationDeadline?: string;
 
     /** Collection of passenger confirmations */
     confirmations?: ReservationConfirmation[];

From f906103b84cadcd8612120cbe0fefb592af54afd Mon Sep 17 00:00:00 2001
From: Blazej Kustra <blazej.kustra@swmansion.com>
Date: Fri, 29 Nov 2024 14:30:47 +0100
Subject: [PATCH 41/75] Rename displayName for CarTripDetails component

---
 src/pages/Travel/CarTripDetails.tsx | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/src/pages/Travel/CarTripDetails.tsx b/src/pages/Travel/CarTripDetails.tsx
index 4ad406e9b868..711e2b07332c 100644
--- a/src/pages/Travel/CarTripDetails.tsx
+++ b/src/pages/Travel/CarTripDetails.tsx
@@ -107,6 +107,6 @@ function CarTripDetails({transaction, personalDetails}: CarTripDetailsProps) {
     );
 }
 
-CarTripDetails.displayName = 'FlightTripDetails';
+CarTripDetails.displayName = 'CarTripDetails';
 
 export default CarTripDetails;

From 79b0cbd84970de02ffeddc99d328729bd55fc81a Mon Sep 17 00:00:00 2001
From: Blazej Kustra <blazej.kustra@swmansion.com>
Date: Fri, 29 Nov 2024 14:35:31 +0100
Subject: [PATCH 42/75] Add Spanish translation for cancellationUntil in
 booking and car sections

---
 src/languages/es.ts | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/src/languages/es.ts b/src/languages/es.ts
index 9a8a6c69ebe3..c25a9a0f6027 100644
--- a/src/languages/es.ts
+++ b/src/languages/es.ts
@@ -2474,6 +2474,7 @@ const translations = {
             checkOut: 'Salida',
             roomType: 'Tipo de habitación',
             cancellation: 'Política de cancelación',
+            cancellationUntil: 'Cancelación gratuita hasta el',
             confirmation: 'Número de confirmación',
         },
         car: 'Auto',
@@ -2484,6 +2485,7 @@ const translations = {
             driver: 'Conductor',
             carType: 'Tipo de coche',
             cancellation: 'Política de cancelación',
+            cancellationUntil: 'Cancelación gratuita hasta el',
             confirmation: 'Número de confirmación',
         },
         viewTrip: 'Ver viaje',

From 7bdea21dc5f71150e9e4c16b916b571dd796b896 Mon Sep 17 00:00:00 2001
From: Blazej Kustra <blazej.kustra@swmansion.com>
Date: Fri, 29 Nov 2024 14:35:39 +0100
Subject: [PATCH 43/75] Remove unnecessary blank line in HotelTripDetails
 component

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

diff --git a/src/pages/Travel/HotelTripDetails.tsx b/src/pages/Travel/HotelTripDetails.tsx
index f0fa279fbbe2..f0b16b0cb142 100644
--- a/src/pages/Travel/HotelTripDetails.tsx
+++ b/src/pages/Travel/HotelTripDetails.tsx
@@ -30,7 +30,6 @@ function HotelTripDetails({transaction, personalDetails}: HotelTripDetailsProps)
         return null;
     }
 
-
     const reservationIcon = TripReservationUtils.getTripReservationIcon(hotelReservation.type);
     const checkInDate = DateUtils.getFormattedTransportDateAndHour(new Date(hotelReservation.start.date));
     const checkOutDate = DateUtils.getFormattedTransportDateAndHour(new Date(hotelReservation.end.date));

From 889416c1855f1bf2498daf7ea2d33effecda25fb Mon Sep 17 00:00:00 2001
From: Blazej Kustra <blazej.kustra@swmansion.com>
Date: Mon, 2 Dec 2024 11:37:56 +0100
Subject: [PATCH 44/75] Add optional fields for rail reservations in
 Transaction

---
 src/types/onyx/Transaction.ts | 9 +++++++++
 1 file changed, 9 insertions(+)

diff --git a/src/types/onyx/Transaction.ts b/src/types/onyx/Transaction.ts
index 33a9e2a71141..3130a9a76560 100644
--- a/src/types/onyx/Transaction.ts
+++ b/src/types/onyx/Transaction.ts
@@ -232,6 +232,9 @@ type Reservation = {
 
         /** Passenger seat number */
         number: string;
+
+        /** Rail route name */
+        name?: string;
     };
 
     /** In car reservations, this represents the car dealership name */
@@ -248,6 +251,12 @@ type Reservation = {
         /** Arrival terminal number */
         terminal: string;
     };
+
+    /** Coach number for rail */
+    coachNumber?: string;
+
+    /** Seat number for rail */
+    seatNumber?: string;
 };
 
 /** Model of trip reservation time details */

From c8557b09f092535edaf78b23b5f1a91fb2e232dc Mon Sep 17 00:00:00 2001
From: Blazej Kustra <blazej.kustra@swmansion.com>
Date: Mon, 2 Dec 2024 11:38:03 +0100
Subject: [PATCH 45/75] Add TRAIN constant to CONST for transportation options

---
 src/CONST.ts | 1 +
 1 file changed, 1 insertion(+)

diff --git a/src/CONST.ts b/src/CONST.ts
index 64040d8c775b..94e8f98816c9 100755
--- a/src/CONST.ts
+++ b/src/CONST.ts
@@ -5928,6 +5928,7 @@ const CONST = {
         CAR: 'car',
         HOTEL: 'hotel',
         FLIGHT: 'flight',
+        TRAIN: 'train',
     },
 
     DOT_SEPARATOR: '•',

From 9f7ca7e1dcad8d8b41668022b07f75aaa68f83e5 Mon Sep 17 00:00:00 2001
From: Blazej Kustra <blazej.kustra@swmansion.com>
Date: Mon, 2 Dec 2024 11:38:11 +0100
Subject: [PATCH 46/75] Add train translations and details to language file

---
 src/languages/en.ts | 12 +++++++++++-
 1 file changed, 11 insertions(+), 1 deletion(-)

diff --git a/src/languages/en.ts b/src/languages/en.ts
index e39a91709dc8..b2f2d064ee15 100755
--- a/src/languages/en.ts
+++ b/src/languages/en.ts
@@ -2435,10 +2435,10 @@ const translations = {
         },
         flight: 'Flight',
         flightDetails: {
+            passenger: 'Passenger',
             layover: 'layover',
             takeOff: 'Take-off',
             landing: 'Landing',
-            passenger: 'Passenger',
             seat: 'Seat',
             class: 'Cabin Class',
             recordLocator: 'Record locator',
@@ -2464,6 +2464,16 @@ const translations = {
             cancellationUntil: 'Free cancellation until',
             confirmation: 'Confirmation number',
         },
+        train: 'Train',
+        trainDetails: {
+            passenger: 'Passenger',
+            departs: 'Departs',
+            arrives: 'Arrives',
+            coachNumber: 'Coach number',
+            seat: 'Seat',
+            fareDetails: 'Fare details',
+            confirmation: 'Confirmation number',
+        },
         viewTrip: 'View trip',
         modifyTrip: 'Modify trip',
         tripSupport: 'Trip support',

From 347714992d9d4ec941f65823e1ac0abed8fe89e2 Mon Sep 17 00:00:00 2001
From: Blazej Kustra <blazej.kustra@swmansion.com>
Date: Mon, 2 Dec 2024 11:38:20 +0100
Subject: [PATCH 47/75] Add TrainTripDetails component to display train
 reservation details

---
 src/pages/Travel/TrainTripDetails.tsx | 114 ++++++++++++++++++++++++++
 src/pages/Travel/TripDetailsPage.tsx  |   8 ++
 2 files changed, 122 insertions(+)
 create mode 100644 src/pages/Travel/TrainTripDetails.tsx

diff --git a/src/pages/Travel/TrainTripDetails.tsx b/src/pages/Travel/TrainTripDetails.tsx
new file mode 100644
index 000000000000..afaac7fdbf8e
--- /dev/null
+++ b/src/pages/Travel/TrainTripDetails.tsx
@@ -0,0 +1,114 @@
+import React from 'react';
+import {View} from 'react-native';
+import type {OnyxEntry} from 'react-native-onyx';
+import * as Expensicons from '@components/Icon/Expensicons';
+import MenuItem from '@components/MenuItem';
+import MenuItemWithTopDescription from '@components/MenuItemWithTopDescription';
+import useLocalize from '@hooks/useLocalize';
+import useStyleUtils from '@hooks/useStyleUtils';
+import useTheme from '@hooks/useTheme';
+import useThemeStyles from '@hooks/useThemeStyles';
+import DateUtils from '@libs/DateUtils';
+import * as TripReservationUtils from '@libs/TripReservationUtils';
+import CONST from '@src/CONST';
+import type {PersonalDetails, Transaction} from '@src/types/onyx';
+
+type TrainTripDetailsProps = {
+    transaction: OnyxEntry<Transaction>;
+    personalDetails: OnyxEntry<PersonalDetails>;
+    reservationIndex: number;
+};
+
+function TrainTripDetails({transaction, personalDetails, reservationIndex}: TrainTripDetailsProps) {
+    const styles = useThemeStyles();
+    const theme = useTheme();
+    const StyleUtils = useStyleUtils();
+    const {translate} = useLocalize();
+
+    const trainReservation = transaction?.receipt?.reservationList?.at(reservationIndex);
+
+    if (!trainReservation) {
+        return null;
+    }
+
+    const reservationIcon = TripReservationUtils.getTripReservationIcon(trainReservation.type);
+    const startDate = DateUtils.getFormattedTransportDateAndHour(new Date(trainReservation.start.date));
+    const endDate = DateUtils.getFormattedTransportDateAndHour(new Date(trainReservation.end.date));
+
+    return (
+        <>
+            <MenuItem
+                label={translate('travel.trainDetails.passenger')}
+                title={personalDetails?.displayName}
+                icon={personalDetails?.avatar ?? Expensicons.FallbackAvatar}
+                iconType={CONST.ICON_TYPE_AVATAR}
+                description={personalDetails?.login}
+                interactive={false}
+                wrapperStyle={styles.pb3}
+            />
+
+            <MenuItem
+                title={`${trainReservation.start.longName} (${trainReservation.start.shortName}) ${translate('common.conjunctionTo')} ${trainReservation.end.longName} (${
+                    trainReservation.end.shortName
+                })`}
+                description={`${trainReservation.company?.longName} ${CONST.DOT_SEPARATOR} ${trainReservation.route?.name}`}
+                descriptionTextStyle={[styles.textLabelSupporting, styles.lh16]}
+                secondaryIcon={reservationIcon}
+                wrapperStyle={[styles.taskDescriptionMenuItem]}
+                numberOfLinesDescription={2}
+                iconHeight={20}
+                iconWidth={20}
+                iconStyles={[StyleUtils.getTripReservationIconContainer(false), styles.mr3]}
+                secondaryIconFill={theme.icon}
+                interactive={false}
+            />
+            <MenuItemWithTopDescription
+                description={`${translate('travel.trainDetails.departs')} ${CONST.DOT_SEPARATOR} ${startDate.date}`}
+                title={startDate.hour}
+                helperText={`${trainReservation.start.longName} (${trainReservation.start.shortName})`}
+                helperTextStyle={[styles.pb3, styles.mtn2]}
+                interactive={false}
+            />
+            <MenuItemWithTopDescription
+                description={`${translate('travel.trainDetails.arrives')} ${CONST.DOT_SEPARATOR} ${endDate.date}`}
+                title={endDate.hour}
+                helperText={`${trainReservation.end.longName} (${trainReservation.end.shortName})`}
+                helperTextStyle={[styles.pb3, styles.mtn2]}
+                interactive={false}
+            />
+
+            <View style={[styles.flexRow, styles.flexWrap]}>
+                {!!trainReservation.coachNumber && (
+                    <View style={styles.w50}>
+                        <MenuItemWithTopDescription
+                            description={translate('travel.trainDetails.coachNumber')}
+                            title={trainReservation.coachNumber}
+                            interactive={false}
+                        />
+                    </View>
+                )}
+                {!!trainReservation.seatNumber && (
+                    <View style={styles.w50}>
+                        <MenuItemWithTopDescription
+                            description={translate('travel.trainDetails.seat')}
+                            title={trainReservation.seatNumber}
+                            interactive={false}
+                        />
+                    </View>
+                )}
+            </View>
+
+            {!!trainReservation.confirmations?.at(0)?.value && (
+                <MenuItemWithTopDescription
+                    description={translate('travel.trainDetails.confirmation')}
+                    title={trainReservation.confirmations?.at(0)?.value}
+                    interactive={false}
+                />
+            )}
+        </>
+    );
+}
+
+TrainTripDetails.displayName = 'TrainTripDetails';
+
+export default TrainTripDetails;
diff --git a/src/pages/Travel/TripDetailsPage.tsx b/src/pages/Travel/TripDetailsPage.tsx
index ee7328299219..0b80f8b049d1 100644
--- a/src/pages/Travel/TripDetailsPage.tsx
+++ b/src/pages/Travel/TripDetailsPage.tsx
@@ -21,6 +21,7 @@ import type SCREENS from '@src/SCREENS';
 import CarTripDetails from './CarTripDetails';
 import FlightTripDetails from './FlightTripDetails';
 import HotelTripDetails from './HotelTripDetails';
+import TrainTripDetails from './TrainTripDetails';
 
 type TripDetailsPageProps = StackScreenProps<TravelNavigatorParamList, typeof SCREENS.TRAVEL.TRIP_DETAILS>;
 
@@ -75,6 +76,13 @@ function TripDetailsPage({route}: TripDetailsPageProps) {
                             personalDetails={personalDetails}
                         />
                     )}
+                    {reservationType === CONST.RESERVATION_TYPE.TRAIN && (
+                        <TrainTripDetails
+                            transaction={transaction}
+                            personalDetails={personalDetails}
+                            reservationIndex={route.params.reservationIndex}
+                        />
+                    )}
                     <MenuItem
                         title={translate('travel.modifyTrip')}
                         icon={Expensicons.Pencil}

From 3c720d152bc43d075b028815f343b8b8ac0158a5 Mon Sep 17 00:00:00 2001
From: Blazej Kustra <blazej.kustra@swmansion.com>
Date: Mon, 2 Dec 2024 12:01:58 +0100
Subject: [PATCH 48/75] Update Spanish translations for train terminology

---
 src/languages/en.ts |  2 +-
 src/languages/es.ts | 12 +++++++++++-
 2 files changed, 12 insertions(+), 2 deletions(-)

diff --git a/src/languages/en.ts b/src/languages/en.ts
index b2f2d064ee15..187bf58eaae3 100755
--- a/src/languages/en.ts
+++ b/src/languages/en.ts
@@ -2464,7 +2464,7 @@ const translations = {
             cancellationUntil: 'Free cancellation until',
             confirmation: 'Confirmation number',
         },
-        train: 'Train',
+        train: 'Rail',
         trainDetails: {
             passenger: 'Passenger',
             departs: 'Departs',
diff --git a/src/languages/es.ts b/src/languages/es.ts
index c25a9a0f6027..6669c54667ec 100644
--- a/src/languages/es.ts
+++ b/src/languages/es.ts
@@ -2459,10 +2459,10 @@ const translations = {
         },
         flight: 'Vuelo',
         flightDetails: {
+            passenger: 'Pasajero',
             layover: 'Escala',
             takeOff: 'Despegue',
             landing: 'Aterrizaje',
-            passenger: 'Pasajero',
             seat: 'Asiento',
             class: 'Clase de cabina',
             recordLocator: 'Localizador de la reserva',
@@ -2488,6 +2488,16 @@ const translations = {
             cancellationUntil: 'Cancelación gratuita hasta el',
             confirmation: 'Número de confirmación',
         },
+        train: 'Tren',
+        trainDetails: {
+            passenger: 'Pasajero',
+            departs: 'Sale',
+            arrives: 'Llega',
+            coachNumber: 'Número de vagón',
+            seat: 'Asiento',
+            fareDetails: 'Detalles de la tarifa',
+            confirmation: 'Número de confirmación',
+        },
         viewTrip: 'Ver viaje',
         modifyTrip: 'Modificar viaje',
         tripSupport: 'Soporte de Viaje',

From 575918c44f41866efaab33cb7e6c989fcc759671 Mon Sep 17 00:00:00 2001
From: Blazej Kustra <blazej.kustra@swmansion.com>
Date: Mon, 2 Dec 2024 12:07:09 +0100
Subject: [PATCH 49/75] Add train icon SVG and import it into Expensicons

---
 assets/images/train.svg            | 3 +++
 src/components/Icon/Expensicons.ts | 2 ++
 2 files changed, 5 insertions(+)
 create mode 100644 assets/images/train.svg

diff --git a/assets/images/train.svg b/assets/images/train.svg
new file mode 100644
index 000000000000..67f70e2964e3
--- /dev/null
+++ b/assets/images/train.svg
@@ -0,0 +1,3 @@
+<svg width="20" height="20" viewBox="0 0 20 20" fill="none" xmlns="http://www.w3.org/2000/svg">
+<path fill-rule="evenodd" clip-rule="evenodd" d="M3 3.40321C3 2.71453 3.44106 2.10651 4.11065 1.94544C5.33356 1.65128 7.46614 1.25 10 1.25C12.5339 1.25 14.6664 1.65128 15.8894 1.94544C16.5589 2.10651 17 2.71453 17 3.40321V14.05C17 14.7127 16.4627 15.25 15.8 15.25H14.9834L15.9141 17.3439C16.1384 17.8486 15.9111 18.4396 15.4064 18.6639C14.9017 18.8882 14.3107 18.6609 14.0864 18.1562L12.7948 15.25H7.2057L5.91406 18.1562C5.68976 18.6609 5.0988 18.8882 4.59411 18.6639C4.08943 18.4396 3.86213 17.8486 4.08644 17.3439L5.01707 15.25H4.2C3.53726 15.25 3 14.7127 3 14.05V3.40321ZM14.5999 9.25H10.7499V3.25924C12.5495 3.30418 13.7776 3.50346 14.4342 3.64289C14.7745 3.71516 14.9999 4.0194 14.9999 4.3673V8.85C14.9999 9.07091 14.8208 9.25 14.5999 9.25ZM5.56565 3.64289C6.22223 3.50346 7.45032 3.30418 9.2499 3.25924V9.25H5.3999C5.17899 9.25 4.9999 9.07091 4.9999 8.85V4.3673C4.9999 4.0194 5.22534 3.71516 5.56565 3.64289ZM5.4999 13.25C6.05219 13.25 6.4999 12.8023 6.4999 12.25C6.4999 11.6977 6.05219 11.25 5.4999 11.25C4.94762 11.25 4.4999 11.6977 4.4999 12.25C4.4999 12.8023 4.94762 13.25 5.4999 13.25ZM15.4999 12.25C15.4999 12.8023 15.0522 13.25 14.4999 13.25C13.9476 13.25 13.4999 12.8023 13.4999 12.25C13.4999 11.6977 13.9476 11.25 14.4999 11.25C15.0522 11.25 15.4999 11.6977 15.4999 12.25Z" fill="#A2A9A3"/>
+</svg>
diff --git a/src/components/Icon/Expensicons.ts b/src/components/Icon/Expensicons.ts
index bd4bb64da050..96f4f503f6b5 100644
--- a/src/components/Icon/Expensicons.ts
+++ b/src/components/Icon/Expensicons.ts
@@ -185,6 +185,7 @@ import Task from '@assets/images/task.svg';
 import Thread from '@assets/images/thread.svg';
 import ThreeDots from '@assets/images/three-dots.svg';
 import ThumbsUp from '@assets/images/thumbs-up.svg';
+import Train from '@assets/images/train.svg';
 import Transfer from '@assets/images/transfer.svg';
 import Trashcan from '@assets/images/trashcan.svg';
 import Unlock from '@assets/images/unlock.svg';
@@ -410,4 +411,5 @@ export {
     Star,
     QBDSquare,
     GalleryNotFound,
+    Train,
 };

From 542749b2817714fbed2b520a7297b8067df9a5cd Mon Sep 17 00:00:00 2001
From: Blazej Kustra <blazej.kustra@swmansion.com>
Date: Mon, 2 Dec 2024 12:18:09 +0100
Subject: [PATCH 50/75] Update train SVG to remove fixed width and height
 attributes

---
 assets/images/train.svg | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/assets/images/train.svg b/assets/images/train.svg
index 67f70e2964e3..40d8c9d1af8a 100644
--- a/assets/images/train.svg
+++ b/assets/images/train.svg
@@ -1,3 +1,3 @@
-<svg width="20" height="20" viewBox="0 0 20 20" fill="none" xmlns="http://www.w3.org/2000/svg">
-<path fill-rule="evenodd" clip-rule="evenodd" d="M3 3.40321C3 2.71453 3.44106 2.10651 4.11065 1.94544C5.33356 1.65128 7.46614 1.25 10 1.25C12.5339 1.25 14.6664 1.65128 15.8894 1.94544C16.5589 2.10651 17 2.71453 17 3.40321V14.05C17 14.7127 16.4627 15.25 15.8 15.25H14.9834L15.9141 17.3439C16.1384 17.8486 15.9111 18.4396 15.4064 18.6639C14.9017 18.8882 14.3107 18.6609 14.0864 18.1562L12.7948 15.25H7.2057L5.91406 18.1562C5.68976 18.6609 5.0988 18.8882 4.59411 18.6639C4.08943 18.4396 3.86213 17.8486 4.08644 17.3439L5.01707 15.25H4.2C3.53726 15.25 3 14.7127 3 14.05V3.40321ZM14.5999 9.25H10.7499V3.25924C12.5495 3.30418 13.7776 3.50346 14.4342 3.64289C14.7745 3.71516 14.9999 4.0194 14.9999 4.3673V8.85C14.9999 9.07091 14.8208 9.25 14.5999 9.25ZM5.56565 3.64289C6.22223 3.50346 7.45032 3.30418 9.2499 3.25924V9.25H5.3999C5.17899 9.25 4.9999 9.07091 4.9999 8.85V4.3673C4.9999 4.0194 5.22534 3.71516 5.56565 3.64289ZM5.4999 13.25C6.05219 13.25 6.4999 12.8023 6.4999 12.25C6.4999 11.6977 6.05219 11.25 5.4999 11.25C4.94762 11.25 4.4999 11.6977 4.4999 12.25C4.4999 12.8023 4.94762 13.25 5.4999 13.25ZM15.4999 12.25C15.4999 12.8023 15.0522 13.25 14.4999 13.25C13.9476 13.25 13.4999 12.8023 13.4999 12.25C13.4999 11.6977 13.9476 11.25 14.4999 11.25C15.0522 11.25 15.4999 11.6977 15.4999 12.25Z" fill="#A2A9A3"/>
+<svg viewBox="0 0 20 20" xmlns="http://www.w3.org/2000/svg">
+<path fill-rule="evenodd" d="M3 3.40321C3 2.71453 3.44106 2.10651 4.11065 1.94544C5.33356 1.65128 7.46614 1.25 10 1.25C12.5339 1.25 14.6664 1.65128 15.8894 1.94544C16.5589 2.10651 17 2.71453 17 3.40321V14.05C17 14.7127 16.4627 15.25 15.8 15.25H14.9834L15.9141 17.3439C16.1384 17.8486 15.9111 18.4396 15.4064 18.6639C14.9017 18.8882 14.3107 18.6609 14.0864 18.1562L12.7948 15.25H7.2057L5.91406 18.1562C5.68976 18.6609 5.0988 18.8882 4.59411 18.6639C4.08943 18.4396 3.86213 17.8486 4.08644 17.3439L5.01707 15.25H4.2C3.53726 15.25 3 14.7127 3 14.05V3.40321ZM14.5999 9.25H10.7499V3.25924C12.5495 3.30418 13.7776 3.50346 14.4342 3.64289C14.7745 3.71516 14.9999 4.0194 14.9999 4.3673V8.85C14.9999 9.07091 14.8208 9.25 14.5999 9.25ZM5.56565 3.64289C6.22223 3.50346 7.45032 3.30418 9.2499 3.25924V9.25H5.3999C5.17899 9.25 4.9999 9.07091 4.9999 8.85V4.3673C4.9999 4.0194 5.22534 3.71516 5.56565 3.64289ZM5.4999 13.25C6.05219 13.25 6.4999 12.8023 6.4999 12.25C6.4999 11.6977 6.05219 11.25 5.4999 11.25C4.94762 11.25 4.4999 11.6977 4.4999 12.25C4.4999 12.8023 4.94762 13.25 5.4999 13.25ZM15.4999 12.25C15.4999 12.8023 15.0522 13.25 14.4999 13.25C13.9476 13.25 13.4999 12.8023 13.4999 12.25C13.4999 11.6977 13.9476 11.25 14.4999 11.25C15.0522 11.25 15.4999 11.6977 15.4999 12.25Z" />
 </svg>

From f9b5bbc3b96e53b51d6c529a515093f6e74a4528 Mon Sep 17 00:00:00 2001
From: Blazej Kustra <blazej.kustra@swmansion.com>
Date: Mon, 2 Dec 2024 12:26:29 +0100
Subject: [PATCH 51/75] Add support for train in TripDetailsView and
 TripRoomPreview components

---
 .../ReportActionItem/TripDetailsView.tsx      |  5 +++-
 .../ReportActionItem/TripRoomPreview.tsx      | 28 +++++++++++--------
 src/libs/TripReservationUtils.ts              |  2 ++
 3 files changed, 23 insertions(+), 12 deletions(-)

diff --git a/src/components/ReportActionItem/TripDetailsView.tsx b/src/components/ReportActionItem/TripDetailsView.tsx
index dfc282b230e4..4fcd1906afc9 100644
--- a/src/components/ReportActionItem/TripDetailsView.tsx
+++ b/src/components/ReportActionItem/TripDetailsView.tsx
@@ -80,11 +80,14 @@ function ReservationView({reservation, transactionID, reportID, reservationIndex
             const vendor = reservation.vendor ? `${reservation.vendor} • ` : '';
             return `${vendor}${reservation.start.location}`;
         }
+        if (reservation.type === CONST.RESERVATION_TYPE.TRAIN) {
+            return reservation.route?.name;
+        }
         return reservation.start.address ?? reservation.start.location;
     }, [reservation]);
 
     const titleComponent = () => {
-        if (reservation.type === CONST.RESERVATION_TYPE.FLIGHT) {
+        if (reservation.type === CONST.RESERVATION_TYPE.FLIGHT || reservation.type === CONST.RESERVATION_TYPE.TRAIN) {
             return (
                 <View style={styles.gap1}>
                     <View style={[styles.flexRow, styles.alignItemsCenter, styles.gap2]}>
diff --git a/src/components/ReportActionItem/TripRoomPreview.tsx b/src/components/ReportActionItem/TripRoomPreview.tsx
index 0299486a22c6..f8537e4beacf 100644
--- a/src/components/ReportActionItem/TripRoomPreview.tsx
+++ b/src/components/ReportActionItem/TripRoomPreview.tsx
@@ -62,26 +62,32 @@ function ReservationView({reservation}: ReservationViewProps) {
     const reservationIcon = TripReservationUtils.getTripReservationIcon(reservation.type);
     const title = reservation.type === CONST.RESERVATION_TYPE.CAR ? reservation.carInfo?.name : reservation.start.longName;
 
-    const titleComponent =
-        reservation.type === CONST.RESERVATION_TYPE.FLIGHT ? (
+    let titleComponent = (
+        <Text
+            numberOfLines={1}
+            style={styles.labelStrong}
+        >
+            {title}
+        </Text>
+    );
+
+    if (reservation.type === CONST.RESERVATION_TYPE.FLIGHT || reservation.type === CONST.RESERVATION_TYPE.TRAIN) {
+        const startName = reservation.type === CONST.RESERVATION_TYPE.FLIGHT ? reservation.start.shortName : reservation.start.longName;
+        const endName = reservation.type === CONST.RESERVATION_TYPE.FLIGHT ? reservation.end.shortName : reservation.end.longName;
+
+        titleComponent = (
             <View style={[styles.flexRow, styles.alignItemsCenter, styles.gap2]}>
-                <Text style={styles.labelStrong}>{reservation.start.shortName}</Text>
+                <Text style={styles.labelStrong}>{startName}</Text>
                 <Icon
                     src={Expensicons.ArrowRightLong}
                     width={variables.iconSizeSmall}
                     height={variables.iconSizeSmall}
                     fill={theme.icon}
                 />
-                <Text style={styles.labelStrong}>{reservation.end.shortName}</Text>
+                <Text style={styles.labelStrong}>{endName}</Text>
             </View>
-        ) : (
-            <Text
-                numberOfLines={1}
-                style={styles.labelStrong}
-            >
-                {title}
-            </Text>
         );
+    }
 
     return (
         <MenuItemWithTopDescription
diff --git a/src/libs/TripReservationUtils.ts b/src/libs/TripReservationUtils.ts
index 6ddf0dc30f57..2c774637b4a0 100644
--- a/src/libs/TripReservationUtils.ts
+++ b/src/libs/TripReservationUtils.ts
@@ -58,6 +58,8 @@ function getTripReservationIcon(reservationType?: ReservationType): IconAsset {
             return Expensicons.Bed;
         case CONST.RESERVATION_TYPE.CAR:
             return Expensicons.CarWithKey;
+        case CONST.RESERVATION_TYPE.TRAIN:
+            return Expensicons.Train;
         default:
             return Expensicons.Luggage;
     }

From 575fa3899f692360b3a86581d4925b5b58ac3204 Mon Sep 17 00:00:00 2001
From: Blazej Kustra <blazej.kustra@swmansion.com>
Date: Tue, 3 Dec 2024 09:48:03 +0100
Subject: [PATCH 52/75] Add trip details translation for English and Spanish;
 update TripSummaryPage title

---
 src/languages/en.ts                  | 1 +
 src/languages/es.ts                  | 1 +
 src/pages/Travel/TripSummaryPage.tsx | 3 +--
 3 files changed, 3 insertions(+), 2 deletions(-)

diff --git a/src/languages/en.ts b/src/languages/en.ts
index 187bf58eaae3..a43e6ce694b9 100755
--- a/src/languages/en.ts
+++ b/src/languages/en.ts
@@ -2477,6 +2477,7 @@ const translations = {
         viewTrip: 'View trip',
         modifyTrip: 'Modify trip',
         tripSupport: 'Trip support',
+        tripDetails: 'Trip details',
         viewTripDetails: 'View trip details',
         trip: 'Trip',
         trips: 'Trips',
diff --git a/src/languages/es.ts b/src/languages/es.ts
index 6669c54667ec..c6c377bf8396 100644
--- a/src/languages/es.ts
+++ b/src/languages/es.ts
@@ -2501,6 +2501,7 @@ const translations = {
         viewTrip: 'Ver viaje',
         modifyTrip: 'Modificar viaje',
         tripSupport: 'Soporte de Viaje',
+        tripDetails: 'Detalles del viaje',
         viewTripDetails: 'Ver detalles del viaje',
         trip: 'Viaje',
         trips: 'Viajes',
diff --git a/src/pages/Travel/TripSummaryPage.tsx b/src/pages/Travel/TripSummaryPage.tsx
index 92a9aab8e107..caf5d471c84c 100644
--- a/src/pages/Travel/TripSummaryPage.tsx
+++ b/src/pages/Travel/TripSummaryPage.tsx
@@ -22,7 +22,6 @@ function TripSummaryPage({route}: TripSummaryPageProps) {
     const {canUseSpotnanaTravel} = usePermissions();
 
     const [transaction] = useOnyx(`${ONYXKEYS.COLLECTION.TRANSACTION}${route.params.transactionID}`);
-    const reservationType = transaction?.receipt?.reservationList?.at(0)?.type;
     const reservationsData: TripReservationUtils.ReservationData[] = TripReservationUtils.getReservationsFromTripTransactions(transaction ? [transaction] : []);
 
     return (
@@ -38,7 +37,7 @@ function TripSummaryPage({route}: TripSummaryPageProps) {
                 shouldShow={!canUseSpotnanaTravel && !NativeModules.HybridAppModule}
             >
                 <HeaderWithBackButton
-                    title={reservationType ? `${translate(`travel.${reservationType}`)} ${translate('common.details').toLowerCase()}` : translate('common.details')}
+                    title={translate(`travel.tripDetails`)}
                     shouldShowBackButton
                 />
                 <ScrollView>

From 0ab84cdfa30ebb568a5508c43c2a02769d88b1fb Mon Sep 17 00:00:00 2001
From: Blazej Kustra <blazej.kustra@swmansion.com>
Date: Tue, 3 Dec 2024 11:03:06 +0100
Subject: [PATCH 53/75] Add customizable icon dimensions and styles to
 HeaderWithBackButton component

---
 src/components/HeaderWithBackButton/index.tsx | 10 +++++++---
 src/components/HeaderWithBackButton/types.ts  |  9 +++++++++
 2 files changed, 16 insertions(+), 3 deletions(-)

diff --git a/src/components/HeaderWithBackButton/index.tsx b/src/components/HeaderWithBackButton/index.tsx
index 2c07c48d52b7..6c956891c86f 100755
--- a/src/components/HeaderWithBackButton/index.tsx
+++ b/src/components/HeaderWithBackButton/index.tsx
@@ -26,6 +26,9 @@ import type HeaderWithBackButtonProps from './types';
 function HeaderWithBackButton({
     icon,
     iconFill,
+    iconWidth,
+    iconHeight,
+    iconStyles,
     guidesCallTaskID = '',
     onBackButtonPress = () => Navigation.goBack(),
     onCloseButtonPress = () => Navigation.dismissModal(),
@@ -180,9 +183,10 @@ function HeaderWithBackButton({
                 {!!icon && (
                     <Icon
                         src={icon}
-                        width={variables.iconHeader}
-                        height={variables.iconHeader}
-                        additionalStyles={[styles.mr2]}
+                        width={iconWidth ?? variables.iconHeader}
+                        height={iconHeight ?? variables.iconHeader}
+                        additionalStyles={[styles.mr2, iconStyles]}
+                        fill={iconFill ?? theme.icon}
                     />
                 )}
                 {!!policyAvatar && (
diff --git a/src/components/HeaderWithBackButton/types.ts b/src/components/HeaderWithBackButton/types.ts
index 6eef2b072eee..68493ef7fa79 100644
--- a/src/components/HeaderWithBackButton/types.ts
+++ b/src/components/HeaderWithBackButton/types.ts
@@ -38,6 +38,15 @@ type HeaderWithBackButtonProps = Partial<ChildrenProps> & {
      * */
     icon?: IconAsset;
 
+    /** Icon Width */
+    iconWidth?: number;
+
+    /** Icon Height */
+    iconHeight?: number;
+
+    /** Any additional styles to pass to the icon container. */
+    iconStyles?: StyleProp<ViewStyle>;
+
     /** Method to trigger when pressing download button of the header */
     onDownloadButtonPress?: () => void;
 

From 13dd939a96440042d9724e5bda189fa602735ca3 Mon Sep 17 00:00:00 2001
From: Blazej Kustra <blazej.kustra@swmansion.com>
Date: Tue, 3 Dec 2024 11:03:17 +0100
Subject: [PATCH 54/75] Add dynamic reservation icon support in TripDetailsPage
 component

---
 src/pages/Travel/TripDetailsPage.tsx | 12 +++++++++++-
 1 file changed, 11 insertions(+), 1 deletion(-)

diff --git a/src/pages/Travel/TripDetailsPage.tsx b/src/pages/Travel/TripDetailsPage.tsx
index 0b80f8b049d1..c8172b6ace85 100644
--- a/src/pages/Travel/TripDetailsPage.tsx
+++ b/src/pages/Travel/TripDetailsPage.tsx
@@ -10,10 +10,12 @@ import ScreenWrapper from '@components/ScreenWrapper';
 import ScrollView from '@components/ScrollView';
 import useLocalize from '@hooks/useLocalize';
 import usePermissions from '@hooks/usePermissions';
+import useStyleUtils from '@hooks/useStyleUtils';
 import useTheme from '@hooks/useTheme';
 import useThemeStyles from '@hooks/useThemeStyles';
 import type {TravelNavigatorParamList} from '@libs/Navigation/types';
 import * as ReportUtils from '@libs/ReportUtils';
+import * as TripReservationUtils from '@libs/TripReservationUtils';
 import * as Link from '@userActions/Link';
 import CONST from '@src/CONST';
 import ONYXKEYS from '@src/ONYXKEYS';
@@ -28,6 +30,7 @@ type TripDetailsPageProps = StackScreenProps<TravelNavigatorParamList, typeof SC
 function TripDetailsPage({route}: TripDetailsPageProps) {
     const theme = useTheme();
     const styles = useThemeStyles();
+    const StyleUtils = useStyleUtils();
     const {translate} = useLocalize();
     const {canUseSpotnanaTravel} = usePermissions();
 
@@ -38,7 +41,9 @@ function TripDetailsPage({route}: TripDetailsPageProps) {
     const tripID = ReportUtils.getTripIDFromTransactionParentReportID(report?.parentReportID);
     const accountID = Object.keys(report?.participants ?? {}).at(0) ?? '-1';
     const [personalDetails] = useOnyx(ONYXKEYS.PERSONAL_DETAILS_LIST, {selector: (data) => data?.[accountID]});
-    const reservationType = transaction?.receipt?.reservationList?.at(0)?.type;
+    const reservationType = transaction?.receipt?.reservationList?.at(route.params.reservationIndex ?? 0)?.type;
+    const reservation = transaction?.receipt?.reservationList?.at(route.params.reservationIndex ?? 0);
+    const reservationIcon = TripReservationUtils.getTripReservationIcon(reservation?.type);
 
     return (
         <ScreenWrapper
@@ -55,6 +60,11 @@ function TripDetailsPage({route}: TripDetailsPageProps) {
                 <HeaderWithBackButton
                     title={reservationType ? `${translate(`travel.${reservationType}`)} ${translate('common.details').toLowerCase()}` : translate('common.details')}
                     shouldShowBackButton
+                    icon={reservationIcon}
+                    iconHeight={20}
+                    iconWidth={20}
+                    iconStyles={[StyleUtils.getTripReservationIconContainer(false), styles.mr3]}
+                    iconFill={theme.icon}
                 />
                 <ScrollView>
                     {reservationType === CONST.RESERVATION_TYPE.FLIGHT && (

From 0a33fd42f361c634ce71b6c218ebaee15077a72a Mon Sep 17 00:00:00 2001
From: Blazej Kustra <blazej.kustra@swmansion.com>
Date: Tue, 3 Dec 2024 11:11:08 +0100
Subject: [PATCH 55/75] Refactor TripDetailsPage to use reservation object for
 details rendering

---
 src/pages/Travel/TripDetailsPage.tsx | 18 ++++++++----------
 1 file changed, 8 insertions(+), 10 deletions(-)

diff --git a/src/pages/Travel/TripDetailsPage.tsx b/src/pages/Travel/TripDetailsPage.tsx
index c8172b6ace85..fd117ce8b790 100644
--- a/src/pages/Travel/TripDetailsPage.tsx
+++ b/src/pages/Travel/TripDetailsPage.tsx
@@ -67,30 +67,28 @@ function TripDetailsPage({route}: TripDetailsPageProps) {
                     iconFill={theme.icon}
                 />
                 <ScrollView>
-                    {reservationType === CONST.RESERVATION_TYPE.FLIGHT && (
+                    {!!reservation && reservationType === CONST.RESERVATION_TYPE.FLIGHT && (
                         <FlightTripDetails
-                            transaction={transaction}
+                            reservation={reservation}
                             personalDetails={personalDetails}
-                            reservationIndex={route.params.reservationIndex}
                         />
                     )}
-                    {reservationType === CONST.RESERVATION_TYPE.HOTEL && (
+                    {!!reservation && reservationType === CONST.RESERVATION_TYPE.HOTEL && (
                         <HotelTripDetails
-                            transaction={transaction}
+                            reservation={reservation}
                             personalDetails={personalDetails}
                         />
                     )}
-                    {reservationType === CONST.RESERVATION_TYPE.CAR && (
+                    {!!reservation && reservationType === CONST.RESERVATION_TYPE.CAR && (
                         <CarTripDetails
-                            transaction={transaction}
+                            reservation={reservation}
                             personalDetails={personalDetails}
                         />
                     )}
-                    {reservationType === CONST.RESERVATION_TYPE.TRAIN && (
+                    {!!reservation && reservationType === CONST.RESERVATION_TYPE.TRAIN && (
                         <TrainTripDetails
-                            transaction={transaction}
+                            reservation={reservation}
                             personalDetails={personalDetails}
-                            reservationIndex={route.params.reservationIndex}
                         />
                     )}
                     <MenuItem

From 7f7d5d40e7e3920bd2337705a8f9e277448ca998 Mon Sep 17 00:00:00 2001
From: Blazej Kustra <blazej.kustra@swmansion.com>
Date: Tue, 3 Dec 2024 11:11:16 +0100
Subject: [PATCH 56/75] Refactor CarTripDetails component to use reservation
 object for rendering details

---
 src/pages/Travel/CarTripDetails.tsx | 124 ++++++++++++----------------
 1 file changed, 51 insertions(+), 73 deletions(-)

diff --git a/src/pages/Travel/CarTripDetails.tsx b/src/pages/Travel/CarTripDetails.tsx
index 711e2b07332c..920fa73d6140 100644
--- a/src/pages/Travel/CarTripDetails.tsx
+++ b/src/pages/Travel/CarTripDetails.tsx
@@ -1,108 +1,86 @@
 import React from 'react';
-import {View} from 'react-native';
 import type {OnyxEntry} from 'react-native-onyx';
 import * as Expensicons from '@components/Icon/Expensicons';
 import MenuItem from '@components/MenuItem';
 import MenuItemWithTopDescription from '@components/MenuItemWithTopDescription';
+import Text from '@components/Text';
 import useLocalize from '@hooks/useLocalize';
-import useStyleUtils from '@hooks/useStyleUtils';
-import useTheme from '@hooks/useTheme';
 import useThemeStyles from '@hooks/useThemeStyles';
 import DateUtils from '@libs/DateUtils';
-import * as TripReservationUtils from '@libs/TripReservationUtils';
 import CONST from '@src/CONST';
-import type {PersonalDetails, Transaction} from '@src/types/onyx';
+import type {PersonalDetails} from '@src/types/onyx';
+import type {Reservation} from '@src/types/onyx/Transaction';
 
 type CarTripDetailsProps = {
-    transaction: OnyxEntry<Transaction>;
+    reservation: Reservation;
     personalDetails: OnyxEntry<PersonalDetails>;
 };
 
-function CarTripDetails({transaction, personalDetails}: CarTripDetailsProps) {
+function CarTripDetails({reservation, personalDetails}: CarTripDetailsProps) {
     const styles = useThemeStyles();
-    const theme = useTheme();
-    const StyleUtils = useStyleUtils();
     const {translate} = useLocalize();
 
-    const carReservation = transaction?.receipt?.reservationList?.at(0);
-
-    if (!transaction || !carReservation) {
-        return null;
-    }
-
-    const reservationIcon = TripReservationUtils.getTripReservationIcon(carReservation.type);
-    const pickUpDate = DateUtils.getFormattedTransportDateAndHour(new Date(carReservation.start.date));
-    const dropOffDate = DateUtils.getFormattedTransportDateAndHour(new Date(carReservation.end.date));
-    const cancellationText = carReservation.cancellationDeadline
-        ? `${translate('travel.carDetails.cancellationUntil')} ${DateUtils.getFormattedTransportDateAndHour(new Date(carReservation.cancellationDeadline)).date}`
-        : carReservation.cancellationPolicy;
+    const pickUpDate = DateUtils.getFormattedTransportDateAndHour(new Date(reservation.start.date));
+    const dropOffDate = DateUtils.getFormattedTransportDateAndHour(new Date(reservation.end.date));
+    const cancellationText = reservation.cancellationDeadline
+        ? `${translate('travel.carDetails.cancellationUntil')} ${DateUtils.getFormattedTransportDateAndHour(new Date(reservation.cancellationDeadline)).date}`
+        : reservation.cancellationPolicy;
 
     return (
         <>
-            <MenuItem
-                label={translate('travel.carDetails.driver')}
-                title={personalDetails?.displayName}
-                icon={personalDetails?.avatar ?? Expensicons.FallbackAvatar}
-                iconType={CONST.ICON_TYPE_AVATAR}
-                description={personalDetails?.login}
-                interactive={false}
-                wrapperStyle={styles.pb3}
-            />
-            <MenuItem
-                title={carReservation.vendor}
-                description={translate('travel.carDetails.rentalCar')}
-                descriptionTextStyle={[styles.textLabelSupporting, styles.lh16]}
-                secondaryIcon={reservationIcon}
-                wrapperStyle={[styles.taskDescriptionMenuItem]}
-                numberOfLinesDescription={2}
-                iconHeight={20}
-                iconWidth={20}
-                iconStyles={[StyleUtils.getTripReservationIconContainer(false), styles.mr3]}
-                secondaryIconFill={theme.icon}
-                interactive={false}
-            />
+            <Text style={[styles.textHeadlineH1, styles.mh5, styles.mv3]}>{reservation.vendor}</Text>
             <MenuItemWithTopDescription
-                description={`${translate('travel.carDetails.pickUp')} ${CONST.DOT_SEPARATOR} ${pickUpDate.date}`}
-                title={pickUpDate.hour}
+                description={translate('travel.carDetails.pickUp')}
+                titleComponent={
+                    <Text style={[styles.textLarge, styles.textHeadlineH2]}>
+                        {pickUpDate.date} {CONST.DOT_SEPARATOR} {pickUpDate.hour}
+                    </Text>
+                }
                 interactive={false}
-                helperText={carReservation.start.location}
+                helperText={reservation.start.location}
                 helperTextStyle={[styles.pb3, styles.mtn2]}
             />
             <MenuItemWithTopDescription
-                description={`${translate('travel.carDetails.dropOff')} ${CONST.DOT_SEPARATOR} ${dropOffDate.date}`}
-                title={dropOffDate.hour}
+                description={translate('travel.carDetails.dropOff')}
+                titleComponent={
+                    <Text style={[styles.textLarge, styles.textHeadlineH2]}>
+                        {dropOffDate.date} {CONST.DOT_SEPARATOR} {dropOffDate.hour}
+                    </Text>
+                }
                 interactive={false}
-                helperText={carReservation.end.location}
+                helperText={reservation.end.location}
                 helperTextStyle={[styles.pb3, styles.mtn2]}
             />
-
-            {!!carReservation.carInfo?.name && (
-                <View>
-                    <MenuItemWithTopDescription
-                        description={translate('travel.carDetails.carType')}
-                        title={carReservation.carInfo.name}
-                        interactive={false}
-                    />
-                </View>
+            {!!reservation.carInfo?.name && (
+                <MenuItemWithTopDescription
+                    description={translate('travel.carDetails.carType')}
+                    title={reservation.carInfo.name}
+                    interactive={false}
+                />
             )}
             {!!cancellationText && (
-                <View>
-                    <MenuItemWithTopDescription
-                        description={translate('travel.carDetails.cancellation')}
-                        title={cancellationText}
-                        interactive={false}
-                    />
-                </View>
+                <MenuItemWithTopDescription
+                    description={translate('travel.carDetails.cancellation')}
+                    title={cancellationText}
+                    interactive={false}
+                />
             )}
-            {!!carReservation.reservationID && (
-                <View>
-                    <MenuItemWithTopDescription
-                        description={translate('travel.carDetails.confirmation')}
-                        title={carReservation.reservationID}
-                        interactive={false}
-                    />
-                </View>
+            {!!reservation.reservationID && (
+                <MenuItemWithTopDescription
+                    description={translate('travel.carDetails.confirmation')}
+                    title={reservation.reservationID}
+                    interactive={false}
+                />
             )}
+            <MenuItem
+                label={translate('travel.carDetails.driver')}
+                title={personalDetails?.displayName}
+                icon={personalDetails?.avatar ?? Expensicons.FallbackAvatar}
+                iconType={CONST.ICON_TYPE_AVATAR}
+                description={personalDetails?.login}
+                interactive={false}
+                wrapperStyle={styles.pb3}
+            />
         </>
     );
 }

From 3de4fb934c4054424e30d2453abd71d8bf18f024 Mon Sep 17 00:00:00 2001
From: Blazej Kustra <blazej.kustra@swmansion.com>
Date: Tue, 3 Dec 2024 11:29:38 +0100
Subject: [PATCH 57/75] Add shouldUseHeadlineHeader prop to multiple pages for
 consistent header styling

---
 src/components/HeaderWithBackButton/index.tsx          | 10 ++++------
 src/components/HeaderWithBackButton/types.ts           |  3 +++
 src/pages/TeachersUnite/SaveTheWorldPage.tsx           |  1 +
 src/pages/settings/AboutPage/AboutPage.tsx             |  1 +
 src/pages/settings/Preferences/PreferencesPage.tsx     |  1 +
 src/pages/settings/Profile/ProfilePage.tsx             |  1 +
 src/pages/settings/Security/SecuritySettingsPage.tsx   |  1 +
 .../settings/Subscription/SubscriptionSettingsPage.tsx |  1 +
 src/pages/settings/Troubleshoot/TroubleshootPage.tsx   |  1 +
 src/pages/settings/Wallet/WalletPage/WalletPage.tsx    |  1 +
 src/pages/workspace/WorkspaceMoreFeaturesPage.tsx      |  1 +
 src/pages/workspace/WorkspacesListPage.tsx             |  2 ++
 .../workspace/accounting/PolicyAccountingPage.tsx      |  1 +
 .../workspace/categories/WorkspaceCategoriesPage.tsx   |  1 +
 .../distanceRates/PolicyDistanceRatesPage.tsx          |  1 +
 .../expensifyCard/WorkspaceExpensifyCardListPage.tsx   |  1 +
 src/pages/workspace/perDiem/WorkspacePerDiemPage.tsx   |  1 +
 .../reportFields/WorkspaceReportFieldsPage.tsx         |  1 +
 src/pages/workspace/tags/WorkspaceTagsPage.tsx         |  1 +
 src/pages/workspace/taxes/WorkspaceTaxesPage.tsx       |  1 +
 20 files changed, 26 insertions(+), 6 deletions(-)

diff --git a/src/components/HeaderWithBackButton/index.tsx b/src/components/HeaderWithBackButton/index.tsx
index 6c956891c86f..d0907b2ea678 100755
--- a/src/components/HeaderWithBackButton/index.tsx
+++ b/src/components/HeaderWithBackButton/index.tsx
@@ -49,6 +49,7 @@ function HeaderWithBackButton({
     shouldSetModalVisibility = true,
     shouldShowThreeDotsButton = false,
     shouldDisableThreeDotsButton = false,
+    shouldUseHeadlineHeader = false,
     stepCounter,
     subtitle = '',
     title = '',
@@ -77,9 +78,6 @@ function HeaderWithBackButton({
     const {translate} = useLocalize();
     const {isKeyboardShown} = useKeyboardState();
 
-    // If the icon is present, the header bar should be taller and use different font.
-    const isCentralPaneSettings = !!icon;
-
     const middleContent = useMemo(() => {
         if (progressBarPercentage) {
             return (
@@ -111,14 +109,14 @@ function HeaderWithBackButton({
             <Header
                 title={title}
                 subtitle={stepCounter ? translate('stepCounter', stepCounter) : subtitle}
-                textStyles={[titleColor ? StyleUtils.getTextColorStyle(titleColor) : {}, isCentralPaneSettings && styles.textHeadlineH2]}
+                textStyles={[titleColor ? StyleUtils.getTextColorStyle(titleColor) : {}, shouldUseHeadlineHeader && styles.textHeadlineH2]}
                 subTitleLink={subTitleLink}
             />
         );
     }, [
         StyleUtils,
         subTitleLink,
-        isCentralPaneSettings,
+        shouldUseHeadlineHeader,
         policy,
         progressBarPercentage,
         report,
@@ -143,7 +141,7 @@ function HeaderWithBackButton({
             dataSet={{dragArea: false}}
             style={[
                 styles.headerBar,
-                isCentralPaneSettings && styles.headerBarDesktopHeight,
+                shouldUseHeadlineHeader && styles.headerBarDesktopHeight,
                 shouldShowBorderBottom && styles.borderBottom,
                 // progressBarPercentage can be 0 which would
                 // be falsey, hence using !== undefined explicitly
diff --git a/src/components/HeaderWithBackButton/types.ts b/src/components/HeaderWithBackButton/types.ts
index 68493ef7fa79..d2d4ba9e4e0f 100644
--- a/src/components/HeaderWithBackButton/types.ts
+++ b/src/components/HeaderWithBackButton/types.ts
@@ -128,6 +128,9 @@ type HeaderWithBackButtonProps = Partial<ChildrenProps> & {
     /** Whether we should navigate to report page when the route have a topMostReport  */
     shouldNavigateToTopMostReport?: boolean;
 
+    /** Whether the header should use the headline header style */
+    shouldUseHeadlineHeader?: boolean;
+
     /** The fill color for the icon. Can be hex, rgb, rgba, or valid react-native named color such as 'red' or 'blue'. */
     iconFill?: string;
 
diff --git a/src/pages/TeachersUnite/SaveTheWorldPage.tsx b/src/pages/TeachersUnite/SaveTheWorldPage.tsx
index b30fedab530e..f52d20ad9014 100644
--- a/src/pages/TeachersUnite/SaveTheWorldPage.tsx
+++ b/src/pages/TeachersUnite/SaveTheWorldPage.tsx
@@ -59,6 +59,7 @@ function SaveTheWorldPage() {
                 shouldDisplaySearchRouter
                 onBackButtonPress={() => Navigation.goBack()}
                 icon={Illustrations.TeachersUnite}
+                shouldUseHeadlineHeader
             />
             <ScrollView contentContainerStyle={styles.pt3}>
                 <View style={[styles.flex1, shouldUseNarrowLayout ? styles.workspaceSectionMobile : styles.workspaceSection]}>
diff --git a/src/pages/settings/AboutPage/AboutPage.tsx b/src/pages/settings/AboutPage/AboutPage.tsx
index 4232e08f70f0..3ab54c9f763f 100644
--- a/src/pages/settings/AboutPage/AboutPage.tsx
+++ b/src/pages/settings/AboutPage/AboutPage.tsx
@@ -138,6 +138,7 @@ function AboutPage() {
                 shouldDisplaySearchRouter
                 onBackButtonPress={() => Navigation.goBack(ROUTES.SETTINGS)}
                 icon={Illustrations.PalmTree}
+                shouldUseHeadlineHeader
             />
             <ScrollView contentContainerStyle={styles.pt3}>
                 <View style={[styles.flex1, shouldUseNarrowLayout ? styles.workspaceSectionMobile : styles.workspaceSection]}>
diff --git a/src/pages/settings/Preferences/PreferencesPage.tsx b/src/pages/settings/Preferences/PreferencesPage.tsx
index 9a7f1872b79a..48cb8c99cf21 100755
--- a/src/pages/settings/Preferences/PreferencesPage.tsx
+++ b/src/pages/settings/Preferences/PreferencesPage.tsx
@@ -44,6 +44,7 @@ function PreferencesPage() {
             <HeaderWithBackButton
                 title={translate('common.preferences')}
                 icon={Illustrations.Gears}
+                shouldUseHeadlineHeader
                 shouldShowBackButton={shouldUseNarrowLayout}
                 shouldDisplaySearchRouter
                 onBackButtonPress={() => Navigation.goBack()}
diff --git a/src/pages/settings/Profile/ProfilePage.tsx b/src/pages/settings/Profile/ProfilePage.tsx
index 1ea20a448820..f12dacfea24a 100755
--- a/src/pages/settings/Profile/ProfilePage.tsx
+++ b/src/pages/settings/Profile/ProfilePage.tsx
@@ -123,6 +123,7 @@ function ProfilePage() {
                 shouldShowBackButton={shouldUseNarrowLayout}
                 shouldDisplaySearchRouter
                 icon={Illustrations.Profile}
+                shouldUseHeadlineHeader
             />
             <ScrollView
                 style={styles.pt3}
diff --git a/src/pages/settings/Security/SecuritySettingsPage.tsx b/src/pages/settings/Security/SecuritySettingsPage.tsx
index ac66c368f631..e725442834d7 100644
--- a/src/pages/settings/Security/SecuritySettingsPage.tsx
+++ b/src/pages/settings/Security/SecuritySettingsPage.tsx
@@ -216,6 +216,7 @@ function SecuritySettingsPage() {
                         shouldShowBackButton={shouldUseNarrowLayout}
                         onBackButtonPress={() => Navigation.goBack()}
                         icon={Illustrations.LockClosed}
+                        shouldUseHeadlineHeader
                         shouldDisplaySearchRouter
                     />
                     <ScrollView contentContainerStyle={styles.pt3}>
diff --git a/src/pages/settings/Subscription/SubscriptionSettingsPage.tsx b/src/pages/settings/Subscription/SubscriptionSettingsPage.tsx
index c34db3fa77a8..6e10d41af635 100644
--- a/src/pages/settings/Subscription/SubscriptionSettingsPage.tsx
+++ b/src/pages/settings/Subscription/SubscriptionSettingsPage.tsx
@@ -49,6 +49,7 @@ function SubscriptionSettingsPage() {
                 shouldShowBackButton={shouldUseNarrowLayout}
                 shouldDisplaySearchRouter
                 icon={Illustrations.CreditCardsNew}
+                shouldUseHeadlineHeader
             />
             <ScrollView style={styles.pt3}>
                 <View style={[styles.flex1, shouldUseNarrowLayout ? styles.workspaceSectionMobile : styles.workspaceSection]}>
diff --git a/src/pages/settings/Troubleshoot/TroubleshootPage.tsx b/src/pages/settings/Troubleshoot/TroubleshootPage.tsx
index bd0ce596c733..c9802cf17d18 100644
--- a/src/pages/settings/Troubleshoot/TroubleshootPage.tsx
+++ b/src/pages/settings/Troubleshoot/TroubleshootPage.tsx
@@ -108,6 +108,7 @@ function TroubleshootPage() {
                 shouldDisplaySearchRouter
                 onBackButtonPress={() => Navigation.goBack(ROUTES.SETTINGS)}
                 icon={Illustrations.Lightbulb}
+                shouldUseHeadlineHeader
             />
             {isLoading && <FullScreenLoadingIndicator />}
             <ScrollView contentContainerStyle={styles.pt3}>
diff --git a/src/pages/settings/Wallet/WalletPage/WalletPage.tsx b/src/pages/settings/Wallet/WalletPage/WalletPage.tsx
index 6b402e562d3a..1c2068592a86 100644
--- a/src/pages/settings/Wallet/WalletPage/WalletPage.tsx
+++ b/src/pages/settings/Wallet/WalletPage/WalletPage.tsx
@@ -349,6 +349,7 @@ function WalletPage({shouldListenForResize = false}: WalletPageProps) {
                         title={translate('common.wallet')}
                         onBackButtonPress={() => Navigation.goBack()}
                         icon={Illustrations.MoneyIntoWallet}
+                        shouldUseHeadlineHeader
                         shouldShowBackButton={shouldUseNarrowLayout}
                         shouldDisplaySearchRouter
                     />
diff --git a/src/pages/workspace/WorkspaceMoreFeaturesPage.tsx b/src/pages/workspace/WorkspaceMoreFeaturesPage.tsx
index aa540f63599e..ddcb89064c7e 100644
--- a/src/pages/workspace/WorkspaceMoreFeaturesPage.tsx
+++ b/src/pages/workspace/WorkspaceMoreFeaturesPage.tsx
@@ -420,6 +420,7 @@ function WorkspaceMoreFeaturesPage({policy, route}: WorkspaceMoreFeaturesPagePro
             >
                 <HeaderWithBackButton
                     icon={Illustrations.Gears}
+                    shouldUseHeadlineHeader
                     title={translate('workspace.common.moreFeatures')}
                     shouldShowBackButton={shouldUseNarrowLayout}
                 />
diff --git a/src/pages/workspace/WorkspacesListPage.tsx b/src/pages/workspace/WorkspacesListPage.tsx
index 46f83a49b9f0..a6d0861f7d0e 100755
--- a/src/pages/workspace/WorkspacesListPage.tsx
+++ b/src/pages/workspace/WorkspacesListPage.tsx
@@ -395,6 +395,7 @@ function WorkspacesListPage() {
                     shouldDisplaySearchRouter
                     onBackButtonPress={() => Navigation.goBack()}
                     icon={Illustrations.BigRocket}
+                    shouldUseHeadlineHeader
                 />
                 <ScrollView contentContainerStyle={styles.pt3}>
                     <View style={[styles.flex1, isLessThanMediumScreen ? styles.workspaceSectionMobile : styles.workspaceSection]}>
@@ -429,6 +430,7 @@ function WorkspacesListPage() {
                     shouldDisplaySearchRouter
                     onBackButtonPress={() => Navigation.goBack()}
                     icon={Illustrations.BigRocket}
+                    shouldUseHeadlineHeader
                 >
                     {!shouldUseNarrowLayout && getHeaderButton()}
                 </HeaderWithBackButton>
diff --git a/src/pages/workspace/accounting/PolicyAccountingPage.tsx b/src/pages/workspace/accounting/PolicyAccountingPage.tsx
index 7aef46167d5d..079f6019868c 100644
--- a/src/pages/workspace/accounting/PolicyAccountingPage.tsx
+++ b/src/pages/workspace/accounting/PolicyAccountingPage.tsx
@@ -474,6 +474,7 @@ function PolicyAccountingPage({policy}: PolicyAccountingPageProps) {
                     title={translate('workspace.common.accounting')}
                     shouldShowBackButton={shouldUseNarrowLayout}
                     icon={Illustrations.Accounting}
+                    shouldUseHeadlineHeader
                     threeDotsAnchorPosition={styles.threeDotsPopoverOffsetNoCloseButton(windowWidth)}
                 />
                 <ScrollView contentContainerStyle={styles.pt3}>
diff --git a/src/pages/workspace/categories/WorkspaceCategoriesPage.tsx b/src/pages/workspace/categories/WorkspaceCategoriesPage.tsx
index 56ba8a5440b8..8364427560eb 100644
--- a/src/pages/workspace/categories/WorkspaceCategoriesPage.tsx
+++ b/src/pages/workspace/categories/WorkspaceCategoriesPage.tsx
@@ -359,6 +359,7 @@ function WorkspaceCategoriesPage({route}: WorkspaceCategoriesPageProps) {
                     shouldShowBackButton={shouldUseNarrowLayout}
                     title={selectionModeHeader ? translate('common.selectMultiple') : translate('workspace.common.categories')}
                     icon={!selectionModeHeader ? Illustrations.FolderOpen : undefined}
+                    shouldUseHeadlineHeader={!selectionModeHeader}
                     onBackButtonPress={() => {
                         if (selectionMode?.isEnabled) {
                             setSelectedCategories({});
diff --git a/src/pages/workspace/distanceRates/PolicyDistanceRatesPage.tsx b/src/pages/workspace/distanceRates/PolicyDistanceRatesPage.tsx
index 8520fd641c50..19878036030b 100644
--- a/src/pages/workspace/distanceRates/PolicyDistanceRatesPage.tsx
+++ b/src/pages/workspace/distanceRates/PolicyDistanceRatesPage.tsx
@@ -295,6 +295,7 @@ function PolicyDistanceRatesPage({
             >
                 <HeaderWithBackButton
                     icon={!selectionModeHeader ? Illustrations.CarIce : undefined}
+                    shouldUseHeadlineHeader={!selectionModeHeader}
                     title={translate(!selectionModeHeader ? 'workspace.common.distanceRates' : 'common.selectMultiple')}
                     shouldShowBackButton={shouldUseNarrowLayout}
                     onBackButtonPress={() => {
diff --git a/src/pages/workspace/expensifyCard/WorkspaceExpensifyCardListPage.tsx b/src/pages/workspace/expensifyCard/WorkspaceExpensifyCardListPage.tsx
index 200d84724bae..44e00c05c5a8 100644
--- a/src/pages/workspace/expensifyCard/WorkspaceExpensifyCardListPage.tsx
+++ b/src/pages/workspace/expensifyCard/WorkspaceExpensifyCardListPage.tsx
@@ -119,6 +119,7 @@ function WorkspaceExpensifyCardListPage({route, cardsList}: WorkspaceExpensifyCa
         >
             <HeaderWithBackButton
                 icon={Illustrations.HandCard}
+                shouldUseHeadlineHeader
                 title={translate('workspace.common.expensifyCard')}
                 shouldShowBackButton={shouldUseNarrowLayout}
                 onBackButtonPress={() => Navigation.goBack()}
diff --git a/src/pages/workspace/perDiem/WorkspacePerDiemPage.tsx b/src/pages/workspace/perDiem/WorkspacePerDiemPage.tsx
index 33ef0109a7a7..0753ba4772f6 100644
--- a/src/pages/workspace/perDiem/WorkspacePerDiemPage.tsx
+++ b/src/pages/workspace/perDiem/WorkspacePerDiemPage.tsx
@@ -353,6 +353,7 @@ function WorkspacePerDiemPage({route}: WorkspacePerDiemPageProps) {
                     shouldShowBackButton={shouldUseNarrowLayout}
                     title={translate(selectionModeHeader ? 'common.selectMultiple' : 'workspace.common.perDiem')}
                     icon={!selectionModeHeader ? Illustrations.PerDiem : undefined}
+                    shouldUseHeadlineHeader={!selectionModeHeader}
                     onBackButtonPress={() => {
                         if (selectionMode?.isEnabled) {
                             setSelectedPerDiem([]);
diff --git a/src/pages/workspace/reportFields/WorkspaceReportFieldsPage.tsx b/src/pages/workspace/reportFields/WorkspaceReportFieldsPage.tsx
index f162f267a44b..ea29d41199ec 100644
--- a/src/pages/workspace/reportFields/WorkspaceReportFieldsPage.tsx
+++ b/src/pages/workspace/reportFields/WorkspaceReportFieldsPage.tsx
@@ -246,6 +246,7 @@ function WorkspaceReportFieldsPage({
             >
                 <HeaderWithBackButton
                     icon={!selectionModeHeader ? Illustrations.Pencil : undefined}
+                    shouldUseHeadlineHeader={!selectionModeHeader}
                     title={translate(selectionModeHeader ? 'common.selectMultiple' : 'workspace.common.reportFields')}
                     shouldShowBackButton={shouldUseNarrowLayout}
                     onBackButtonPress={() => {
diff --git a/src/pages/workspace/tags/WorkspaceTagsPage.tsx b/src/pages/workspace/tags/WorkspaceTagsPage.tsx
index d5c72048f8a4..61bd2e3aa42f 100644
--- a/src/pages/workspace/tags/WorkspaceTagsPage.tsx
+++ b/src/pages/workspace/tags/WorkspaceTagsPage.tsx
@@ -364,6 +364,7 @@ function WorkspaceTagsPage({route}: WorkspaceTagsPageProps) {
             >
                 <HeaderWithBackButton
                     icon={!selectionModeHeader ? Illustrations.Tag : undefined}
+                    shouldUseHeadlineHeader={!selectionModeHeader}
                     title={translate(selectionModeHeader ? 'common.selectMultiple' : 'workspace.common.tags')}
                     shouldShowBackButton={shouldUseNarrowLayout}
                     onBackButtonPress={() => {
diff --git a/src/pages/workspace/taxes/WorkspaceTaxesPage.tsx b/src/pages/workspace/taxes/WorkspaceTaxesPage.tsx
index 9dbe739ae1db..e064c04878a1 100644
--- a/src/pages/workspace/taxes/WorkspaceTaxesPage.tsx
+++ b/src/pages/workspace/taxes/WorkspaceTaxesPage.tsx
@@ -297,6 +297,7 @@ function WorkspaceTaxesPage({
             >
                 <HeaderWithBackButton
                     icon={!selectionModeHeader ? Illustrations.Coins : undefined}
+                    shouldUseHeadlineHeader={!selectionModeHeader}
                     title={translate(selectionModeHeader ? 'common.selectMultiple' : 'workspace.common.taxes')}
                     shouldShowBackButton={shouldUseNarrowLayout}
                     onBackButtonPress={() => {

From a3d68f4f7040ba386112869ef775cef6c71edbc5 Mon Sep 17 00:00:00 2001
From: Blazej Kustra <blazej.kustra@swmansion.com>
Date: Tue, 3 Dec 2024 11:42:58 +0100
Subject: [PATCH 58/75] Refactor HotelTripDetails component to use reservation
 object for rendering details

---
 src/pages/Travel/HotelTripDetails.tsx | 107 +++++++++++---------------
 src/types/onyx/Transaction.ts         |   3 +
 2 files changed, 47 insertions(+), 63 deletions(-)

diff --git a/src/pages/Travel/HotelTripDetails.tsx b/src/pages/Travel/HotelTripDetails.tsx
index f0b16b0cb142..2f65a4e4cd3b 100644
--- a/src/pages/Travel/HotelTripDetails.tsx
+++ b/src/pages/Travel/HotelTripDetails.tsx
@@ -1,99 +1,80 @@
 import React from 'react';
-import {View} from 'react-native';
 import type {OnyxEntry} from 'react-native-onyx';
 import * as Expensicons from '@components/Icon/Expensicons';
 import MenuItem from '@components/MenuItem';
 import MenuItemWithTopDescription from '@components/MenuItemWithTopDescription';
+import Text from '@components/Text';
 import useLocalize from '@hooks/useLocalize';
-import useStyleUtils from '@hooks/useStyleUtils';
-import useTheme from '@hooks/useTheme';
 import useThemeStyles from '@hooks/useThemeStyles';
 import DateUtils from '@libs/DateUtils';
-import * as TripReservationUtils from '@libs/TripReservationUtils';
 import CONST from '@src/CONST';
-import type {PersonalDetails, Transaction} from '@src/types/onyx';
+import type {PersonalDetails} from '@src/types/onyx';
+import type {Reservation} from '@src/types/onyx/Transaction';
 
 type HotelTripDetailsProps = {
-    transaction: OnyxEntry<Transaction>;
+    reservation: Reservation;
     personalDetails: OnyxEntry<PersonalDetails>;
 };
 
-function HotelTripDetails({transaction, personalDetails}: HotelTripDetailsProps) {
+function HotelTripDetails({reservation, personalDetails}: HotelTripDetailsProps) {
     const styles = useThemeStyles();
-    const theme = useTheme();
-    const StyleUtils = useStyleUtils();
     const {translate} = useLocalize();
 
-    const hotelReservation = transaction?.receipt?.reservationList?.at(0);
-
-    if (!transaction || !hotelReservation) {
-        return null;
-    }
-
-    const reservationIcon = TripReservationUtils.getTripReservationIcon(hotelReservation.type);
-    const checkInDate = DateUtils.getFormattedTransportDateAndHour(new Date(hotelReservation.start.date));
-    const checkOutDate = DateUtils.getFormattedTransportDateAndHour(new Date(hotelReservation.end.date));
-    const cancellationText = hotelReservation.cancellationDeadline
-        ? `${translate('travel.hotelDetails.cancellationUntil')} ${DateUtils.getFormattedTransportDateAndHour(new Date(hotelReservation.cancellationDeadline)).date}`
-        : hotelReservation.cancellationPolicy;
+    const checkInDate = DateUtils.getFormattedTransportDateAndHour(new Date(reservation.start.date));
+    const checkOutDate = DateUtils.getFormattedTransportDateAndHour(new Date(reservation.end.date));
+    const cancellationText = reservation.cancellationDeadline
+        ? `${translate('travel.hotelDetails.cancellationUntil')} ${DateUtils.getFormattedTransportDateAndHour(new Date(reservation.cancellationDeadline)).date}`
+        : reservation.cancellationPolicy;
 
     return (
         <>
-            <MenuItem
-                label={translate('travel.hotelDetails.guest')}
-                title={personalDetails?.displayName}
-                icon={personalDetails?.avatar ?? Expensicons.FallbackAvatar}
-                iconType={CONST.ICON_TYPE_AVATAR}
-                description={personalDetails?.login}
-                interactive={false}
-                wrapperStyle={styles.pb3}
-            />
-            <MenuItem
-                title={hotelReservation.start.longName}
-                description={translate('travel.hotel')}
-                descriptionTextStyle={[styles.textLabelSupporting, styles.lh16]}
-                secondaryIcon={reservationIcon}
-                wrapperStyle={[styles.taskDescriptionMenuItem]}
-                numberOfLinesDescription={2}
-                iconHeight={20}
-                iconWidth={20}
-                iconStyles={[StyleUtils.getTripReservationIconContainer(false), styles.mr3]}
-                secondaryIconFill={theme.icon}
-                interactive={false}
-            />
+            <Text style={[styles.textHeadlineH1, styles.mh5, styles.mv3]}>{reservation.start.longName}</Text>
             <MenuItemWithTopDescription
                 description={translate('common.address')}
-                title={hotelReservation.start.address}
+                title={reservation.start.address}
                 interactive={false}
             />
             <MenuItemWithTopDescription
-                description={`${translate('travel.hotelDetails.checkIn')} ${CONST.DOT_SEPARATOR} ${checkInDate.date}`}
-                title={checkInDate.hour}
+                description={translate('travel.hotelDetails.checkIn')}
+                titleComponent={<Text style={[styles.textLarge, styles.textHeadlineH2]}>{checkInDate.date}</Text>}
                 interactive={false}
             />
             <MenuItemWithTopDescription
-                description={`${translate('travel.hotelDetails.checkOut')} ${CONST.DOT_SEPARATOR} ${checkOutDate.date}`}
-                title={checkOutDate.hour}
+                description={translate('travel.hotelDetails.checkOut')}
+                titleComponent={<Text style={[styles.textLarge, styles.textHeadlineH2]}>{checkOutDate.date}</Text>}
                 interactive={false}
             />
+
+            {!!reservation.roomClass && (
+                <MenuItemWithTopDescription
+                    description={translate('travel.hotelDetails.roomType')}
+                    title={reservation.roomClass.trim()}
+                    interactive={false}
+                />
+            )}
             {!!cancellationText && (
-                <View>
-                    <MenuItemWithTopDescription
-                        description={translate('travel.carDetails.cancellation')}
-                        title={cancellationText}
-                        interactive={false}
-                    />
-                </View>
+                <MenuItemWithTopDescription
+                    description={translate('travel.hotelDetails.cancellation')}
+                    title={cancellationText}
+                    interactive={false}
+                />
             )}
-            {!!hotelReservation.confirmations?.at(0)?.value && (
-                <View>
-                    <MenuItemWithTopDescription
-                        description={translate('travel.hotelDetails.confirmation')}
-                        title={hotelReservation.confirmations?.at(0)?.value}
-                        interactive={false}
-                    />
-                </View>
+            {!!reservation.confirmations?.at(0)?.value && (
+                <MenuItemWithTopDescription
+                    description={translate('travel.hotelDetails.confirmation')}
+                    title={reservation.confirmations?.at(0)?.value}
+                    interactive={false}
+                />
             )}
+            <MenuItem
+                label={translate('travel.hotelDetails.guest')}
+                title={personalDetails?.displayName}
+                icon={personalDetails?.avatar ?? Expensicons.FallbackAvatar}
+                iconType={CONST.ICON_TYPE_AVATAR}
+                description={personalDetails?.login}
+                interactive={false}
+                wrapperStyle={styles.pb3}
+            />
         </>
     );
 }
diff --git a/src/types/onyx/Transaction.ts b/src/types/onyx/Transaction.ts
index 3130a9a76560..e3937fee3c33 100644
--- a/src/types/onyx/Transaction.ts
+++ b/src/types/onyx/Transaction.ts
@@ -222,6 +222,9 @@ type Reservation = {
     /** In hotel reservations, this represents the number of rooms reserved */
     numberOfRooms?: number;
 
+    /** In hotel reservations, this represents the room class */
+    roomClass?: string;
+
     /** In flight reservations, this represents the details of the route */
     route?: {
         /** Route airline code */

From b9d0da2e8504eb012e62be06df315acdfa0bb4a4 Mon Sep 17 00:00:00 2001
From: Blazej Kustra <blazej.kustra@swmansion.com>
Date: Tue, 3 Dec 2024 13:07:43 +0100
Subject: [PATCH 59/75] Add flight layover translation support and
 abbreviations in English and Spanish

---
 src/languages/en.ts | 5 ++++-
 src/languages/es.ts | 5 ++++-
 2 files changed, 8 insertions(+), 2 deletions(-)

diff --git a/src/languages/en.ts b/src/languages/en.ts
index a43e6ce694b9..c99a00465c73 100755
--- a/src/languages/en.ts
+++ b/src/languages/en.ts
@@ -68,6 +68,7 @@ import type {
     FeatureNameParams,
     FileLimitParams,
     FiltersAmountBetweenParams,
+    FlightLayoverParams,
     FormattedMaxLengthParams,
     ForwardedAmountParams,
     GoBackMessageParams,
@@ -477,6 +478,8 @@ const translations = {
         days: 'days',
         rename: 'Rename',
         address: 'Address',
+        hourAbbreviation: 'h',
+        minuteAbbreviation: 'm',
         chatWithAccountManager: ({accountManagerDisplayName}: ChatWithAccountManagerParams) => `Need something specific? Chat with your account manager, ${accountManagerDisplayName}.`,
         chatNow: 'Chat now',
     },
@@ -2436,7 +2439,7 @@ const translations = {
         flight: 'Flight',
         flightDetails: {
             passenger: 'Passenger',
-            layover: 'layover',
+            layover: ({layover}: FlightLayoverParams) => `<muted-text>You have a <strong>${layover} layover</strong> before this flight</muted-text>`,
             takeOff: 'Take-off',
             landing: 'Landing',
             seat: 'Seat',
diff --git a/src/languages/es.ts b/src/languages/es.ts
index c6c377bf8396..0f23940c1c8b 100644
--- a/src/languages/es.ts
+++ b/src/languages/es.ts
@@ -67,6 +67,7 @@ import type {
     FeatureNameParams,
     FileLimitParams,
     FiltersAmountBetweenParams,
+    FlightLayoverParams,
     FormattedMaxLengthParams,
     ForwardedAmountParams,
     GoBackMessageParams,
@@ -468,6 +469,8 @@ const translations = {
         links: 'Enlaces',
         days: 'días',
         address: 'Dirección',
+        hourAbbreviation: 'h',
+        minuteAbbreviation: 'm',
         chatWithAccountManager: ({accountManagerDisplayName}: ChatWithAccountManagerParams) => `¿Necesitas algo específico? Habla con tu gerente de cuenta, ${accountManagerDisplayName}.`,
         chatNow: 'Chatear ahora',
     },
@@ -2460,7 +2463,7 @@ const translations = {
         flight: 'Vuelo',
         flightDetails: {
             passenger: 'Pasajero',
-            layover: 'Escala',
+            layover: ({layover}: FlightLayoverParams) => `Tienes una <strong>escala de ${layover}</strong> antes de este vuelo`,
             takeOff: 'Despegue',
             landing: 'Aterrizaje',
             seat: 'Asiento',

From 977804917a0a1bb85ff022ca8e778afb2559ae50 Mon Sep 17 00:00:00 2001
From: Blazej Kustra <blazej.kustra@swmansion.com>
Date: Tue, 3 Dec 2024 13:07:49 +0100
Subject: [PATCH 60/75] Add FlightLayoverParams type for layover details

---
 src/languages/params.ts | 5 +++++
 1 file changed, 5 insertions(+)

diff --git a/src/languages/params.ts b/src/languages/params.ts
index 90b789efae58..8c62fcb81cfe 100644
--- a/src/languages/params.ts
+++ b/src/languages/params.ts
@@ -567,6 +567,10 @@ type ChatWithAccountManagerParams = {
     accountManagerDisplayName: string;
 };
 
+type FlightLayoverParams = {
+    layover: string;
+};
+
 export type {
     AuthenticationErrorParams,
     ImportMembersSuccessfullDescriptionParams,
@@ -771,4 +775,5 @@ export type {
     CurrencyCodeParams,
     CompanyNameParams,
     ChatWithAccountManagerParams,
+    FlightLayoverParams,
 };

From 5eac23a9e088f5cd0a00d8ab5939b6ab7dbd2aaf Mon Sep 17 00:00:00 2001
From: Blazej Kustra <blazej.kustra@swmansion.com>
Date: Tue, 3 Dec 2024 13:08:06 +0100
Subject: [PATCH 61/75] Enhance duration formatting functions to support
 translation for hours and minutes

---
 src/libs/DateUtils.ts | 13 +++++++++++--
 1 file changed, 11 insertions(+), 2 deletions(-)

diff --git a/src/libs/DateUtils.ts b/src/libs/DateUtils.ts
index 8bdbdd2d21d0..5ea3fd605d6f 100644
--- a/src/libs/DateUtils.ts
+++ b/src/libs/DateUtils.ts
@@ -37,6 +37,7 @@ import {es} from 'date-fns/locale/es';
 import throttle from 'lodash/throttle';
 import Onyx from 'react-native-onyx';
 import type {ValueOf} from 'type-fest';
+import type {LocaleContextProps} from '@components/LocaleContextProvider';
 import CONST from '@src/CONST';
 import ONYXKEYS from '@src/ONYXKEYS';
 import {timezoneBackwardMap} from '@src/TIMEZONES';
@@ -832,14 +833,21 @@ function getFormattedTransportDateAndHour(date: Date): {date: string; hour: stri
 /**
  * Returns a formatted layover duration in format "2h 30m".
  */
-function getFormattedDurationBetweenDates(start: Date, end: Date): string | undefined {
+function getFormattedDurationBetweenDates(translate: LocaleContextProps['translate'], start: Date, end: Date): string | undefined {
     const {days, hours, minutes} = intervalToDuration({start, end});
 
     if (days && days > 0) {
         return;
     }
 
-    return `${hours ? `${hours}h ` : ''}${minutes}m`;
+    return `${hours ? `${hours}${translate('common.hourAbbreviation')} ` : ''}${minutes}${translate('common.minuteAbbreviation')}`;
+}
+
+function getFormattedDuration(translate: LocaleContextProps['translate'], durationInSeconds: number): string {
+    const hours = Math.floor(durationInSeconds / 3600);
+    const minutes = Math.floor((durationInSeconds % 3600) / 60);
+
+    return `${hours ? `${hours}${translate('common.hourAbbreviation')} ` : ''}${minutes}${translate('common.minuteAbbreviation')}`;
 }
 
 function doesDateBelongToAPastYear(date: string): boolean {
@@ -928,6 +936,7 @@ const DateUtils = {
     getDifferenceInDaysFromNow,
     isValidDateString,
     getFormattedDurationBetweenDates,
+    getFormattedDuration,
 };
 
 export default DateUtils;

From 72b825e0e43d1bfad9389dc7ea98ac9ccb892ff3 Mon Sep 17 00:00:00 2001
From: Blazej Kustra <blazej.kustra@swmansion.com>
Date: Tue, 3 Dec 2024 13:09:36 +0100
Subject: [PATCH 62/75] Refactor FlightTripDetails component to use reservation
 object

---
 src/pages/Travel/FlightTripDetails.tsx | 129 +++++++++++--------------
 src/pages/Travel/TripDetailsPage.tsx   |   1 +
 src/types/onyx/Transaction.ts          |   3 +
 3 files changed, 63 insertions(+), 70 deletions(-)

diff --git a/src/pages/Travel/FlightTripDetails.tsx b/src/pages/Travel/FlightTripDetails.tsx
index d407dfb72aa4..43e8e3e5f227 100644
--- a/src/pages/Travel/FlightTripDetails.tsx
+++ b/src/pages/Travel/FlightTripDetails.tsx
@@ -1,135 +1,124 @@
 import React from 'react';
 import {View} from 'react-native';
 import type {OnyxEntry} from 'react-native-onyx';
+import Icon from '@components/Icon';
 import * as Expensicons from '@components/Icon/Expensicons';
 import MenuItem from '@components/MenuItem';
 import MenuItemWithTopDescription from '@components/MenuItemWithTopDescription';
+import RenderHTML from '@components/RenderHTML';
+import Text from '@components/Text';
 import useLocalize from '@hooks/useLocalize';
-import useStyleUtils from '@hooks/useStyleUtils';
 import useTheme from '@hooks/useTheme';
 import useThemeStyles from '@hooks/useThemeStyles';
 import DateUtils from '@libs/DateUtils';
-import * as TripReservationUtils from '@libs/TripReservationUtils';
+import variables from '@styles/variables';
 import CONST from '@src/CONST';
-import type {PersonalDetails, Transaction} from '@src/types/onyx';
+import type {PersonalDetails} from '@src/types/onyx';
+import type {Reservation} from '@src/types/onyx/Transaction';
 
 type FlightTripDetailsProps = {
-    transaction: OnyxEntry<Transaction>;
+    reservation: Reservation;
+    prevReservation: Reservation | undefined;
     personalDetails: OnyxEntry<PersonalDetails>;
-    reservationIndex: number;
 };
 
-function FlightTripDetails({transaction, personalDetails, reservationIndex}: FlightTripDetailsProps) {
+function FlightTripDetails({reservation, prevReservation, personalDetails}: FlightTripDetailsProps) {
     const styles = useThemeStyles();
     const theme = useTheme();
-    const StyleUtils = useStyleUtils();
     const {translate} = useLocalize();
 
-    const flightReservation = transaction?.receipt?.reservationList?.at(reservationIndex);
+    const startDate = DateUtils.getFormattedTransportDateAndHour(new Date(reservation.start.date));
+    const endDate = DateUtils.getFormattedTransportDateAndHour(new Date(reservation.end.date));
 
-    if (!flightReservation) {
-        return null;
-    }
-
-    const reservationIcon = TripReservationUtils.getTripReservationIcon(flightReservation.type);
-    const startDate = DateUtils.getFormattedTransportDateAndHour(new Date(flightReservation.start.date));
-    const endDate = DateUtils.getFormattedTransportDateAndHour(new Date(flightReservation.end.date));
-
-    const prevFlightStartDate = reservationIndex > 0 && transaction?.receipt?.reservationList?.at(reservationIndex - 1)?.end.date;
-    const layover = prevFlightStartDate && DateUtils.getFormattedDurationBetweenDates(new Date(prevFlightStartDate), new Date(flightReservation.start.date));
+    const prevFlightEndDate = prevReservation?.end.date;
+    const layover = prevFlightEndDate && DateUtils.getFormattedDurationBetweenDates(translate, new Date(prevFlightEndDate), new Date(reservation.start.date));
+    const flightDuration = DateUtils.getFormattedDuration(translate, reservation.duration);
+    const flightRouteDescription = `${reservation.start.cityName} (${reservation.start.shortName}) ${translate('common.conjunctionTo')} ${reservation.end.cityName} (${
+        reservation.end.shortName
+    })`;
 
     return (
         <>
-            <MenuItem
-                label={translate('travel.flightDetails.passenger')}
-                title={personalDetails?.displayName}
-                icon={personalDetails?.avatar ?? Expensicons.FallbackAvatar}
-                iconType={CONST.ICON_TYPE_AVATAR}
-                description={personalDetails?.login}
-                interactive={false}
-                wrapperStyle={styles.pb3}
-            />
+            <Text style={[styles.textHeadlineH1, styles.mh5, styles.mv3]}>{flightRouteDescription}</Text>
 
             {!!layover && (
-                <>
-                    <MenuItem
-                        description={`${transaction?.receipt?.reservationList?.at(0)?.start.longName} (${transaction?.receipt?.reservationList?.at(0)?.start.shortName})`}
-                        title={`${layover} ${translate('travel.flightDetails.layover')}`}
-                        descriptionTextStyle={[styles.textLabelSupporting, styles.lh16]}
-                        secondaryIcon={Expensicons.Chair}
-                        wrapperStyle={[styles.taskDescriptionMenuItem]}
-                        numberOfLinesDescription={2}
-                        iconHeight={20}
-                        iconWidth={20}
-                        iconStyles={[StyleUtils.getTripReservationIconContainer(false), styles.mr3]}
-                        secondaryIconFill={theme.icon}
-                        interactive={false}
+                <View style={[styles.flexRow, styles.alignItemsCenter, styles.mh5, styles.mv3, styles.gap2]}>
+                    <Icon
+                        src={Expensicons.Hourglass}
+                        height={variables.iconSizeNormal}
+                        width={variables.iconSizeNormal}
+                        fill={theme.icon}
                     />
-                    <View style={[styles.borderBottom, styles.mh5, styles.mv3]} />
-                </>
+                    <RenderHTML html={translate('travel.flightDetails.layover', {layover})} />
+                </View>
             )}
-
-            <MenuItem
-                title={`${flightReservation.start.cityName} (${flightReservation.start.shortName}) ${translate('common.conjunctionTo')} ${flightReservation.end.cityName} (${
-                    flightReservation.end.shortName
-                })`}
-                description={`${flightReservation.company?.longName} ${CONST.DOT_SEPARATOR} ${flightReservation.route?.airlineCode}`}
-                descriptionTextStyle={[styles.textLabelSupporting, styles.lh16]}
-                secondaryIcon={reservationIcon}
-                wrapperStyle={[styles.taskDescriptionMenuItem]}
-                numberOfLinesDescription={2}
-                iconHeight={20}
-                iconWidth={20}
-                iconStyles={[StyleUtils.getTripReservationIconContainer(false), styles.mr3]}
-                secondaryIconFill={theme.icon}
+            <MenuItemWithTopDescription
+                description={`${translate('travel.flight')} ${CONST.DOT_SEPARATOR} ${flightDuration}`}
+                title={`${reservation.company?.longName} ${CONST.DOT_SEPARATOR} ${reservation.route?.airlineCode}`}
                 interactive={false}
             />
             <MenuItemWithTopDescription
-                description={`${translate('travel.flightDetails.takeOff')} ${CONST.DOT_SEPARATOR} ${startDate.date}`}
-                title={startDate.hour}
-                helperText={`${flightReservation.start.longName} (${flightReservation.start.shortName})${
-                    flightReservation.arrivalGate?.terminal ? `, ${flightReservation.arrivalGate?.terminal}` : ''
-                }`}
+                description={translate('common.date')}
+                title={startDate.date}
+                interactive={false}
+            />
+
+            <MenuItemWithTopDescription
+                description={translate('travel.flightDetails.takeOff')}
+                descriptionTextStyle={[styles.textLabelSupporting, styles.mb1]}
+                titleComponent={<Text style={[styles.textLarge, styles.textHeadlineH2]}>{startDate.hour}</Text>}
+                helperText={`${reservation.start.longName} (${reservation.start.shortName})${reservation.arrivalGate?.terminal ? `, ${reservation.arrivalGate?.terminal}` : ''}`}
                 helperTextStyle={[styles.pb3, styles.mtn2]}
                 interactive={false}
             />
             <MenuItemWithTopDescription
-                description={`${translate('travel.flightDetails.landing')} ${CONST.DOT_SEPARATOR} ${endDate.date}`}
-                title={endDate.hour}
-                helperText={`${flightReservation.end.longName} (${flightReservation.end.shortName})`}
+                description={translate('travel.flightDetails.landing')}
+                descriptionTextStyle={[styles.textLabelSupporting, styles.mb1]}
+                titleComponent={<Text style={[styles.textLarge, styles.textHeadlineH2]}>{endDate.hour}</Text>}
+                helperText={`${reservation.end.longName} (${reservation.end.shortName})`}
                 helperTextStyle={[styles.pb3, styles.mtn2]}
                 interactive={false}
             />
 
             <View style={[styles.flexRow, styles.flexWrap]}>
-                {!!flightReservation.route?.number && (
+                {!!reservation.route?.number && (
                     <View style={styles.w50}>
                         <MenuItemWithTopDescription
                             description={translate('travel.flightDetails.seat')}
-                            title={flightReservation.route?.number}
+                            title={reservation.route?.number}
                             interactive={false}
                         />
                     </View>
                 )}
-                {!!flightReservation.route?.class && (
+                {!!reservation.route?.class && (
                     <View style={styles.w50}>
                         <MenuItemWithTopDescription
                             description={translate('travel.flightDetails.class')}
-                            title={flightReservation.route.class}
+                            title={reservation.route.class}
                             interactive={false}
                         />
                     </View>
                 )}
-                {!!flightReservation.confirmations?.at(0)?.value && (
+                {!!reservation.confirmations?.at(0)?.value && (
                     <View style={styles.w50}>
                         <MenuItemWithTopDescription
                             description={translate('travel.flightDetails.recordLocator')}
-                            title={flightReservation.confirmations?.at(0)?.value}
+                            title={reservation.confirmations?.at(0)?.value}
                             interactive={false}
                         />
                     </View>
                 )}
             </View>
+
+            <MenuItem
+                label={translate('travel.flightDetails.passenger')}
+                title={personalDetails?.displayName}
+                icon={personalDetails?.avatar ?? Expensicons.FallbackAvatar}
+                iconType={CONST.ICON_TYPE_AVATAR}
+                description={personalDetails?.login}
+                interactive={false}
+                wrapperStyle={styles.pb3}
+            />
         </>
     );
 }
diff --git a/src/pages/Travel/TripDetailsPage.tsx b/src/pages/Travel/TripDetailsPage.tsx
index fd117ce8b790..2907775109cc 100644
--- a/src/pages/Travel/TripDetailsPage.tsx
+++ b/src/pages/Travel/TripDetailsPage.tsx
@@ -69,6 +69,7 @@ function TripDetailsPage({route}: TripDetailsPageProps) {
                 <ScrollView>
                     {!!reservation && reservationType === CONST.RESERVATION_TYPE.FLIGHT && (
                         <FlightTripDetails
+                            prevReservation={route.params.reservationIndex > 0 ? transaction?.receipt?.reservationList?.at(route.params.reservationIndex - 1) : undefined}
                             reservation={reservation}
                             personalDetails={personalDetails}
                         />
diff --git a/src/types/onyx/Transaction.ts b/src/types/onyx/Transaction.ts
index e3937fee3c33..b5d7bbd8d348 100644
--- a/src/types/onyx/Transaction.ts
+++ b/src/types/onyx/Transaction.ts
@@ -219,6 +219,9 @@ type Reservation = {
     /** In flight and car reservations, this represents the number of passengers */
     numPassengers?: number;
 
+    /** In flight reservations, this represents the flight duration in seconds */
+    duration: number;
+
     /** In hotel reservations, this represents the number of rooms reserved */
     numberOfRooms?: number;
 

From 6466aec45a505d3b2a1a84a12a39a31d46bda151 Mon Sep 17 00:00:00 2001
From: Blazej Kustra <blazej.kustra@swmansion.com>
Date: Tue, 3 Dec 2024 13:24:26 +0100
Subject: [PATCH 63/75] Refactor TrainTripDetails component to use reservation
 object for rendering details

---
 src/pages/Travel/TrainTripDetails.tsx | 106 ++++++++++++--------------
 1 file changed, 50 insertions(+), 56 deletions(-)

diff --git a/src/pages/Travel/TrainTripDetails.tsx b/src/pages/Travel/TrainTripDetails.tsx
index afaac7fdbf8e..e1ba7aa9aacf 100644
--- a/src/pages/Travel/TrainTripDetails.tsx
+++ b/src/pages/Travel/TrainTripDetails.tsx
@@ -4,107 +4,101 @@ import type {OnyxEntry} from 'react-native-onyx';
 import * as Expensicons from '@components/Icon/Expensicons';
 import MenuItem from '@components/MenuItem';
 import MenuItemWithTopDescription from '@components/MenuItemWithTopDescription';
+import Text from '@components/Text';
 import useLocalize from '@hooks/useLocalize';
-import useStyleUtils from '@hooks/useStyleUtils';
-import useTheme from '@hooks/useTheme';
 import useThemeStyles from '@hooks/useThemeStyles';
 import DateUtils from '@libs/DateUtils';
-import * as TripReservationUtils from '@libs/TripReservationUtils';
 import CONST from '@src/CONST';
-import type {PersonalDetails, Transaction} from '@src/types/onyx';
+import type {PersonalDetails} from '@src/types/onyx';
+import type {Reservation} from '@src/types/onyx/Transaction';
 
 type TrainTripDetailsProps = {
-    transaction: OnyxEntry<Transaction>;
+    reservation: Reservation;
     personalDetails: OnyxEntry<PersonalDetails>;
-    reservationIndex: number;
 };
 
-function TrainTripDetails({transaction, personalDetails, reservationIndex}: TrainTripDetailsProps) {
+function TrainTripDetails({reservation, personalDetails}: TrainTripDetailsProps) {
     const styles = useThemeStyles();
-    const theme = useTheme();
-    const StyleUtils = useStyleUtils();
     const {translate} = useLocalize();
 
-    const trainReservation = transaction?.receipt?.reservationList?.at(reservationIndex);
-
-    if (!trainReservation) {
-        return null;
-    }
-
-    const reservationIcon = TripReservationUtils.getTripReservationIcon(trainReservation.type);
-    const startDate = DateUtils.getFormattedTransportDateAndHour(new Date(trainReservation.start.date));
-    const endDate = DateUtils.getFormattedTransportDateAndHour(new Date(trainReservation.end.date));
+    const startDate = DateUtils.getFormattedTransportDateAndHour(new Date(reservation.start.date));
+    const endDate = DateUtils.getFormattedTransportDateAndHour(new Date(reservation.end.date));
+    const trainRouteDescription = `${reservation.start.longName} (${reservation.start.shortName}) ${translate('common.conjunctionTo')} ${reservation.end.longName} (${
+        reservation.end.shortName
+    })`;
+    const trainDuration = reservation.duration && DateUtils.getFormattedDuration(translate, reservation.duration);
 
     return (
         <>
-            <MenuItem
-                label={translate('travel.trainDetails.passenger')}
-                title={personalDetails?.displayName}
-                icon={personalDetails?.avatar ?? Expensicons.FallbackAvatar}
-                iconType={CONST.ICON_TYPE_AVATAR}
-                description={personalDetails?.login}
+            <Text style={[styles.textHeadlineH1, styles.mh5, styles.mv3]}>{trainRouteDescription}</Text>
+
+            <MenuItemWithTopDescription
+                description={`${translate('travel.train')} ${trainDuration ? `${CONST.DOT_SEPARATOR} ${trainDuration}` : ''}`}
+                title={reservation.route?.name}
                 interactive={false}
-                wrapperStyle={styles.pb3}
             />
-
-            <MenuItem
-                title={`${trainReservation.start.longName} (${trainReservation.start.shortName}) ${translate('common.conjunctionTo')} ${trainReservation.end.longName} (${
-                    trainReservation.end.shortName
-                })`}
-                description={`${trainReservation.company?.longName} ${CONST.DOT_SEPARATOR} ${trainReservation.route?.name}`}
-                descriptionTextStyle={[styles.textLabelSupporting, styles.lh16]}
-                secondaryIcon={reservationIcon}
-                wrapperStyle={[styles.taskDescriptionMenuItem]}
-                numberOfLinesDescription={2}
-                iconHeight={20}
-                iconWidth={20}
-                iconStyles={[StyleUtils.getTripReservationIconContainer(false), styles.mr3]}
-                secondaryIconFill={theme.icon}
+            <MenuItemWithTopDescription
+                description={translate('common.date')}
+                title={startDate.date}
                 interactive={false}
             />
+
             <MenuItemWithTopDescription
-                description={`${translate('travel.trainDetails.departs')} ${CONST.DOT_SEPARATOR} ${startDate.date}`}
-                title={startDate.hour}
-                helperText={`${trainReservation.start.longName} (${trainReservation.start.shortName})`}
+                description={translate('travel.trainDetails.departs')}
+                descriptionTextStyle={[styles.textLabelSupporting, styles.mb1]}
+                titleComponent={<Text style={[styles.textLarge, styles.textHeadlineH2]}>{startDate.hour}</Text>}
+                helperText={`${reservation.start.longName} (${reservation.start.shortName})`}
                 helperTextStyle={[styles.pb3, styles.mtn2]}
                 interactive={false}
             />
             <MenuItemWithTopDescription
-                description={`${translate('travel.trainDetails.arrives')} ${CONST.DOT_SEPARATOR} ${endDate.date}`}
-                title={endDate.hour}
-                helperText={`${trainReservation.end.longName} (${trainReservation.end.shortName})`}
+                description={translate('travel.trainDetails.arrives')}
+                descriptionTextStyle={[styles.textLabelSupporting, styles.mb1]}
+                titleComponent={<Text style={[styles.textLarge, styles.textHeadlineH2]}>{endDate.hour}</Text>}
+                helperText={`${reservation.end.longName} (${reservation.end.shortName})`}
                 helperTextStyle={[styles.pb3, styles.mtn2]}
                 interactive={false}
             />
 
             <View style={[styles.flexRow, styles.flexWrap]}>
-                {!!trainReservation.coachNumber && (
+                {!!reservation.coachNumber && (
                     <View style={styles.w50}>
                         <MenuItemWithTopDescription
                             description={translate('travel.trainDetails.coachNumber')}
-                            title={trainReservation.coachNumber}
+                            title={reservation.coachNumber}
                             interactive={false}
                         />
                     </View>
                 )}
-                {!!trainReservation.seatNumber && (
+                {!!reservation.seatNumber && (
                     <View style={styles.w50}>
                         <MenuItemWithTopDescription
                             description={translate('travel.trainDetails.seat')}
-                            title={trainReservation.seatNumber}
+                            title={reservation.seatNumber}
+                            interactive={false}
+                        />
+                    </View>
+                )}
+                {!!reservation.confirmations?.at(0)?.value && (
+                    <View style={styles.w50}>
+                        <MenuItemWithTopDescription
+                            description={translate('travel.trainDetails.confirmation')}
+                            title={reservation.confirmations?.at(0)?.value}
                             interactive={false}
                         />
                     </View>
                 )}
             </View>
 
-            {!!trainReservation.confirmations?.at(0)?.value && (
-                <MenuItemWithTopDescription
-                    description={translate('travel.trainDetails.confirmation')}
-                    title={trainReservation.confirmations?.at(0)?.value}
-                    interactive={false}
-                />
-            )}
+            <MenuItem
+                label={translate('travel.trainDetails.passenger')}
+                title={personalDetails?.displayName}
+                icon={personalDetails?.avatar ?? Expensicons.FallbackAvatar}
+                iconType={CONST.ICON_TYPE_AVATAR}
+                description={personalDetails?.login}
+                interactive={false}
+                wrapperStyle={styles.pb3}
+            />
         </>
     );
 }

From 6dc72b3ba23091bb6fddff6b336000c4f98863ec Mon Sep 17 00:00:00 2001
From: Blazej Kustra <blazej.kustra@swmansion.com>
Date: Thu, 5 Dec 2024 11:48:25 +0100
Subject: [PATCH 64/75] Refactor trip details components to remove personal
 details prop and use traveler information from reservation object

---
 src/pages/Travel/CarTripDetails.tsx    | 11 ++++-------
 src/pages/Travel/FlightTripDetails.tsx | 11 ++++-------
 src/pages/Travel/HotelTripDetails.tsx  | 11 ++++-------
 src/pages/Travel/TrainTripDetails.tsx  | 11 ++++-------
 src/pages/Travel/TripDetailsPage.tsx   | 24 +++---------------------
 src/types/onyx/Transaction.ts          | 12 ++++++++++++
 6 files changed, 31 insertions(+), 49 deletions(-)

diff --git a/src/pages/Travel/CarTripDetails.tsx b/src/pages/Travel/CarTripDetails.tsx
index 920fa73d6140..3a5d64c26eb4 100644
--- a/src/pages/Travel/CarTripDetails.tsx
+++ b/src/pages/Travel/CarTripDetails.tsx
@@ -1,5 +1,4 @@
 import React from 'react';
-import type {OnyxEntry} from 'react-native-onyx';
 import * as Expensicons from '@components/Icon/Expensicons';
 import MenuItem from '@components/MenuItem';
 import MenuItemWithTopDescription from '@components/MenuItemWithTopDescription';
@@ -8,15 +7,13 @@ import useLocalize from '@hooks/useLocalize';
 import useThemeStyles from '@hooks/useThemeStyles';
 import DateUtils from '@libs/DateUtils';
 import CONST from '@src/CONST';
-import type {PersonalDetails} from '@src/types/onyx';
 import type {Reservation} from '@src/types/onyx/Transaction';
 
 type CarTripDetailsProps = {
     reservation: Reservation;
-    personalDetails: OnyxEntry<PersonalDetails>;
 };
 
-function CarTripDetails({reservation, personalDetails}: CarTripDetailsProps) {
+function CarTripDetails({reservation}: CarTripDetailsProps) {
     const styles = useThemeStyles();
     const {translate} = useLocalize();
 
@@ -74,10 +71,10 @@ function CarTripDetails({reservation, personalDetails}: CarTripDetailsProps) {
             )}
             <MenuItem
                 label={translate('travel.carDetails.driver')}
-                title={personalDetails?.displayName}
-                icon={personalDetails?.avatar ?? Expensicons.FallbackAvatar}
+                title={reservation.travelerPersonalInfo?.name}
+                icon={Expensicons.FallbackAvatar}
                 iconType={CONST.ICON_TYPE_AVATAR}
-                description={personalDetails?.login}
+                description={reservation.travelerPersonalInfo?.email}
                 interactive={false}
                 wrapperStyle={styles.pb3}
             />
diff --git a/src/pages/Travel/FlightTripDetails.tsx b/src/pages/Travel/FlightTripDetails.tsx
index 43e8e3e5f227..3b2a8605d575 100644
--- a/src/pages/Travel/FlightTripDetails.tsx
+++ b/src/pages/Travel/FlightTripDetails.tsx
@@ -1,6 +1,5 @@
 import React from 'react';
 import {View} from 'react-native';
-import type {OnyxEntry} from 'react-native-onyx';
 import Icon from '@components/Icon';
 import * as Expensicons from '@components/Icon/Expensicons';
 import MenuItem from '@components/MenuItem';
@@ -13,16 +12,14 @@ import useThemeStyles from '@hooks/useThemeStyles';
 import DateUtils from '@libs/DateUtils';
 import variables from '@styles/variables';
 import CONST from '@src/CONST';
-import type {PersonalDetails} from '@src/types/onyx';
 import type {Reservation} from '@src/types/onyx/Transaction';
 
 type FlightTripDetailsProps = {
     reservation: Reservation;
     prevReservation: Reservation | undefined;
-    personalDetails: OnyxEntry<PersonalDetails>;
 };
 
-function FlightTripDetails({reservation, prevReservation, personalDetails}: FlightTripDetailsProps) {
+function FlightTripDetails({reservation, prevReservation}: FlightTripDetailsProps) {
     const styles = useThemeStyles();
     const theme = useTheme();
     const {translate} = useLocalize();
@@ -112,10 +109,10 @@ function FlightTripDetails({reservation, prevReservation, personalDetails}: Flig
 
             <MenuItem
                 label={translate('travel.flightDetails.passenger')}
-                title={personalDetails?.displayName}
-                icon={personalDetails?.avatar ?? Expensicons.FallbackAvatar}
+                title={reservation.travelerPersonalInfo?.name}
+                icon={Expensicons.FallbackAvatar}
                 iconType={CONST.ICON_TYPE_AVATAR}
-                description={personalDetails?.login}
+                description={reservation.travelerPersonalInfo?.email}
                 interactive={false}
                 wrapperStyle={styles.pb3}
             />
diff --git a/src/pages/Travel/HotelTripDetails.tsx b/src/pages/Travel/HotelTripDetails.tsx
index 2f65a4e4cd3b..a83ba657daae 100644
--- a/src/pages/Travel/HotelTripDetails.tsx
+++ b/src/pages/Travel/HotelTripDetails.tsx
@@ -1,5 +1,4 @@
 import React from 'react';
-import type {OnyxEntry} from 'react-native-onyx';
 import * as Expensicons from '@components/Icon/Expensicons';
 import MenuItem from '@components/MenuItem';
 import MenuItemWithTopDescription from '@components/MenuItemWithTopDescription';
@@ -8,15 +7,13 @@ import useLocalize from '@hooks/useLocalize';
 import useThemeStyles from '@hooks/useThemeStyles';
 import DateUtils from '@libs/DateUtils';
 import CONST from '@src/CONST';
-import type {PersonalDetails} from '@src/types/onyx';
 import type {Reservation} from '@src/types/onyx/Transaction';
 
 type HotelTripDetailsProps = {
     reservation: Reservation;
-    personalDetails: OnyxEntry<PersonalDetails>;
 };
 
-function HotelTripDetails({reservation, personalDetails}: HotelTripDetailsProps) {
+function HotelTripDetails({reservation}: HotelTripDetailsProps) {
     const styles = useThemeStyles();
     const {translate} = useLocalize();
 
@@ -68,10 +65,10 @@ function HotelTripDetails({reservation, personalDetails}: HotelTripDetailsProps)
             )}
             <MenuItem
                 label={translate('travel.hotelDetails.guest')}
-                title={personalDetails?.displayName}
-                icon={personalDetails?.avatar ?? Expensicons.FallbackAvatar}
+                title={reservation.travelerPersonalInfo?.name}
+                icon={Expensicons.FallbackAvatar}
                 iconType={CONST.ICON_TYPE_AVATAR}
-                description={personalDetails?.login}
+                description={reservation.travelerPersonalInfo?.email}
                 interactive={false}
                 wrapperStyle={styles.pb3}
             />
diff --git a/src/pages/Travel/TrainTripDetails.tsx b/src/pages/Travel/TrainTripDetails.tsx
index e1ba7aa9aacf..8a258b1a2ca2 100644
--- a/src/pages/Travel/TrainTripDetails.tsx
+++ b/src/pages/Travel/TrainTripDetails.tsx
@@ -1,6 +1,5 @@
 import React from 'react';
 import {View} from 'react-native';
-import type {OnyxEntry} from 'react-native-onyx';
 import * as Expensicons from '@components/Icon/Expensicons';
 import MenuItem from '@components/MenuItem';
 import MenuItemWithTopDescription from '@components/MenuItemWithTopDescription';
@@ -9,15 +8,13 @@ import useLocalize from '@hooks/useLocalize';
 import useThemeStyles from '@hooks/useThemeStyles';
 import DateUtils from '@libs/DateUtils';
 import CONST from '@src/CONST';
-import type {PersonalDetails} from '@src/types/onyx';
 import type {Reservation} from '@src/types/onyx/Transaction';
 
 type TrainTripDetailsProps = {
     reservation: Reservation;
-    personalDetails: OnyxEntry<PersonalDetails>;
 };
 
-function TrainTripDetails({reservation, personalDetails}: TrainTripDetailsProps) {
+function TrainTripDetails({reservation}: TrainTripDetailsProps) {
     const styles = useThemeStyles();
     const {translate} = useLocalize();
 
@@ -92,10 +89,10 @@ function TrainTripDetails({reservation, personalDetails}: TrainTripDetailsProps)
 
             <MenuItem
                 label={translate('travel.trainDetails.passenger')}
-                title={personalDetails?.displayName}
-                icon={personalDetails?.avatar ?? Expensicons.FallbackAvatar}
+                title={reservation.travelerPersonalInfo?.name}
+                icon={Expensicons.FallbackAvatar}
                 iconType={CONST.ICON_TYPE_AVATAR}
-                description={personalDetails?.login}
+                description={reservation.travelerPersonalInfo?.email}
                 interactive={false}
                 wrapperStyle={styles.pb3}
             />
diff --git a/src/pages/Travel/TripDetailsPage.tsx b/src/pages/Travel/TripDetailsPage.tsx
index 2907775109cc..a905d8bb1939 100644
--- a/src/pages/Travel/TripDetailsPage.tsx
+++ b/src/pages/Travel/TripDetailsPage.tsx
@@ -39,8 +39,6 @@ function TripDetailsPage({route}: TripDetailsPageProps) {
     const [report] = useOnyx(`${ONYXKEYS.COLLECTION.REPORT}${route.params.reportID}`);
 
     const tripID = ReportUtils.getTripIDFromTransactionParentReportID(report?.parentReportID);
-    const accountID = Object.keys(report?.participants ?? {}).at(0) ?? '-1';
-    const [personalDetails] = useOnyx(ONYXKEYS.PERSONAL_DETAILS_LIST, {selector: (data) => data?.[accountID]});
     const reservationType = transaction?.receipt?.reservationList?.at(route.params.reservationIndex ?? 0)?.type;
     const reservation = transaction?.receipt?.reservationList?.at(route.params.reservationIndex ?? 0);
     const reservationIcon = TripReservationUtils.getTripReservationIcon(reservation?.type);
@@ -71,27 +69,11 @@ function TripDetailsPage({route}: TripDetailsPageProps) {
                         <FlightTripDetails
                             prevReservation={route.params.reservationIndex > 0 ? transaction?.receipt?.reservationList?.at(route.params.reservationIndex - 1) : undefined}
                             reservation={reservation}
-                            personalDetails={personalDetails}
-                        />
-                    )}
-                    {!!reservation && reservationType === CONST.RESERVATION_TYPE.HOTEL && (
-                        <HotelTripDetails
-                            reservation={reservation}
-                            personalDetails={personalDetails}
-                        />
-                    )}
-                    {!!reservation && reservationType === CONST.RESERVATION_TYPE.CAR && (
-                        <CarTripDetails
-                            reservation={reservation}
-                            personalDetails={personalDetails}
-                        />
-                    )}
-                    {!!reservation && reservationType === CONST.RESERVATION_TYPE.TRAIN && (
-                        <TrainTripDetails
-                            reservation={reservation}
-                            personalDetails={personalDetails}
                         />
                     )}
+                    {!!reservation && reservationType === CONST.RESERVATION_TYPE.HOTEL && <HotelTripDetails reservation={reservation} />}
+                    {!!reservation && reservationType === CONST.RESERVATION_TYPE.CAR && <CarTripDetails reservation={reservation} />}
+                    {!!reservation && reservationType === CONST.RESERVATION_TYPE.TRAIN && <TrainTripDetails reservation={reservation} />}
                     <MenuItem
                         title={translate('travel.modifyTrip')}
                         icon={Expensicons.Pencil}
diff --git a/src/types/onyx/Transaction.ts b/src/types/onyx/Transaction.ts
index b5d7bbd8d348..6765f53d9f0b 100644
--- a/src/types/onyx/Transaction.ts
+++ b/src/types/onyx/Transaction.ts
@@ -190,6 +190,15 @@ type TaxRate = {
     data?: TaxRateData;
 };
 
+/** This represents the details of the traveler */
+type TravelerPersonalDetails = {
+    /** Email of the traveler */
+    email: string;
+
+    /** Name of the traveler */
+    name: string;
+};
+
 /** Model of reservation */
 type Reservation = {
     /** ID of the reservation */
@@ -263,6 +272,9 @@ type Reservation = {
 
     /** Seat number for rail */
     seatNumber?: string;
+
+    /** This represents the details of the traveler */
+    travelerPersonalInfo?: TravelerPersonalDetails;
 };
 
 /** Model of trip reservation time details */

From b892fe0abecd4209ab44d7a6a8b57739e6b44c6b Mon Sep 17 00:00:00 2001
From: Blazej Kustra <blazej.kustra@swmansion.com>
Date: Thu, 5 Dec 2024 12:00:43 +0100
Subject: [PATCH 65/75] Revert "Refactor trip details components to remove
 personal details prop and use traveler information from reservation object"

This reverts commit 6dc72b3ba23091bb6fddff6b336000c4f98863ec.
---
 src/pages/Travel/CarTripDetails.tsx    | 11 +++++++----
 src/pages/Travel/FlightTripDetails.tsx | 11 +++++++----
 src/pages/Travel/HotelTripDetails.tsx  | 11 +++++++----
 src/pages/Travel/TrainTripDetails.tsx  | 11 +++++++----
 src/pages/Travel/TripDetailsPage.tsx   | 24 +++++++++++++++++++++---
 src/types/onyx/Transaction.ts          | 12 ------------
 6 files changed, 49 insertions(+), 31 deletions(-)

diff --git a/src/pages/Travel/CarTripDetails.tsx b/src/pages/Travel/CarTripDetails.tsx
index 3a5d64c26eb4..920fa73d6140 100644
--- a/src/pages/Travel/CarTripDetails.tsx
+++ b/src/pages/Travel/CarTripDetails.tsx
@@ -1,4 +1,5 @@
 import React from 'react';
+import type {OnyxEntry} from 'react-native-onyx';
 import * as Expensicons from '@components/Icon/Expensicons';
 import MenuItem from '@components/MenuItem';
 import MenuItemWithTopDescription from '@components/MenuItemWithTopDescription';
@@ -7,13 +8,15 @@ import useLocalize from '@hooks/useLocalize';
 import useThemeStyles from '@hooks/useThemeStyles';
 import DateUtils from '@libs/DateUtils';
 import CONST from '@src/CONST';
+import type {PersonalDetails} from '@src/types/onyx';
 import type {Reservation} from '@src/types/onyx/Transaction';
 
 type CarTripDetailsProps = {
     reservation: Reservation;
+    personalDetails: OnyxEntry<PersonalDetails>;
 };
 
-function CarTripDetails({reservation}: CarTripDetailsProps) {
+function CarTripDetails({reservation, personalDetails}: CarTripDetailsProps) {
     const styles = useThemeStyles();
     const {translate} = useLocalize();
 
@@ -71,10 +74,10 @@ function CarTripDetails({reservation}: CarTripDetailsProps) {
             )}
             <MenuItem
                 label={translate('travel.carDetails.driver')}
-                title={reservation.travelerPersonalInfo?.name}
-                icon={Expensicons.FallbackAvatar}
+                title={personalDetails?.displayName}
+                icon={personalDetails?.avatar ?? Expensicons.FallbackAvatar}
                 iconType={CONST.ICON_TYPE_AVATAR}
-                description={reservation.travelerPersonalInfo?.email}
+                description={personalDetails?.login}
                 interactive={false}
                 wrapperStyle={styles.pb3}
             />
diff --git a/src/pages/Travel/FlightTripDetails.tsx b/src/pages/Travel/FlightTripDetails.tsx
index 3b2a8605d575..43e8e3e5f227 100644
--- a/src/pages/Travel/FlightTripDetails.tsx
+++ b/src/pages/Travel/FlightTripDetails.tsx
@@ -1,5 +1,6 @@
 import React from 'react';
 import {View} from 'react-native';
+import type {OnyxEntry} from 'react-native-onyx';
 import Icon from '@components/Icon';
 import * as Expensicons from '@components/Icon/Expensicons';
 import MenuItem from '@components/MenuItem';
@@ -12,14 +13,16 @@ import useThemeStyles from '@hooks/useThemeStyles';
 import DateUtils from '@libs/DateUtils';
 import variables from '@styles/variables';
 import CONST from '@src/CONST';
+import type {PersonalDetails} from '@src/types/onyx';
 import type {Reservation} from '@src/types/onyx/Transaction';
 
 type FlightTripDetailsProps = {
     reservation: Reservation;
     prevReservation: Reservation | undefined;
+    personalDetails: OnyxEntry<PersonalDetails>;
 };
 
-function FlightTripDetails({reservation, prevReservation}: FlightTripDetailsProps) {
+function FlightTripDetails({reservation, prevReservation, personalDetails}: FlightTripDetailsProps) {
     const styles = useThemeStyles();
     const theme = useTheme();
     const {translate} = useLocalize();
@@ -109,10 +112,10 @@ function FlightTripDetails({reservation, prevReservation}: FlightTripDetailsProp
 
             <MenuItem
                 label={translate('travel.flightDetails.passenger')}
-                title={reservation.travelerPersonalInfo?.name}
-                icon={Expensicons.FallbackAvatar}
+                title={personalDetails?.displayName}
+                icon={personalDetails?.avatar ?? Expensicons.FallbackAvatar}
                 iconType={CONST.ICON_TYPE_AVATAR}
-                description={reservation.travelerPersonalInfo?.email}
+                description={personalDetails?.login}
                 interactive={false}
                 wrapperStyle={styles.pb3}
             />
diff --git a/src/pages/Travel/HotelTripDetails.tsx b/src/pages/Travel/HotelTripDetails.tsx
index a83ba657daae..2f65a4e4cd3b 100644
--- a/src/pages/Travel/HotelTripDetails.tsx
+++ b/src/pages/Travel/HotelTripDetails.tsx
@@ -1,4 +1,5 @@
 import React from 'react';
+import type {OnyxEntry} from 'react-native-onyx';
 import * as Expensicons from '@components/Icon/Expensicons';
 import MenuItem from '@components/MenuItem';
 import MenuItemWithTopDescription from '@components/MenuItemWithTopDescription';
@@ -7,13 +8,15 @@ import useLocalize from '@hooks/useLocalize';
 import useThemeStyles from '@hooks/useThemeStyles';
 import DateUtils from '@libs/DateUtils';
 import CONST from '@src/CONST';
+import type {PersonalDetails} from '@src/types/onyx';
 import type {Reservation} from '@src/types/onyx/Transaction';
 
 type HotelTripDetailsProps = {
     reservation: Reservation;
+    personalDetails: OnyxEntry<PersonalDetails>;
 };
 
-function HotelTripDetails({reservation}: HotelTripDetailsProps) {
+function HotelTripDetails({reservation, personalDetails}: HotelTripDetailsProps) {
     const styles = useThemeStyles();
     const {translate} = useLocalize();
 
@@ -65,10 +68,10 @@ function HotelTripDetails({reservation}: HotelTripDetailsProps) {
             )}
             <MenuItem
                 label={translate('travel.hotelDetails.guest')}
-                title={reservation.travelerPersonalInfo?.name}
-                icon={Expensicons.FallbackAvatar}
+                title={personalDetails?.displayName}
+                icon={personalDetails?.avatar ?? Expensicons.FallbackAvatar}
                 iconType={CONST.ICON_TYPE_AVATAR}
-                description={reservation.travelerPersonalInfo?.email}
+                description={personalDetails?.login}
                 interactive={false}
                 wrapperStyle={styles.pb3}
             />
diff --git a/src/pages/Travel/TrainTripDetails.tsx b/src/pages/Travel/TrainTripDetails.tsx
index 8a258b1a2ca2..e1ba7aa9aacf 100644
--- a/src/pages/Travel/TrainTripDetails.tsx
+++ b/src/pages/Travel/TrainTripDetails.tsx
@@ -1,5 +1,6 @@
 import React from 'react';
 import {View} from 'react-native';
+import type {OnyxEntry} from 'react-native-onyx';
 import * as Expensicons from '@components/Icon/Expensicons';
 import MenuItem from '@components/MenuItem';
 import MenuItemWithTopDescription from '@components/MenuItemWithTopDescription';
@@ -8,13 +9,15 @@ import useLocalize from '@hooks/useLocalize';
 import useThemeStyles from '@hooks/useThemeStyles';
 import DateUtils from '@libs/DateUtils';
 import CONST from '@src/CONST';
+import type {PersonalDetails} from '@src/types/onyx';
 import type {Reservation} from '@src/types/onyx/Transaction';
 
 type TrainTripDetailsProps = {
     reservation: Reservation;
+    personalDetails: OnyxEntry<PersonalDetails>;
 };
 
-function TrainTripDetails({reservation}: TrainTripDetailsProps) {
+function TrainTripDetails({reservation, personalDetails}: TrainTripDetailsProps) {
     const styles = useThemeStyles();
     const {translate} = useLocalize();
 
@@ -89,10 +92,10 @@ function TrainTripDetails({reservation}: TrainTripDetailsProps) {
 
             <MenuItem
                 label={translate('travel.trainDetails.passenger')}
-                title={reservation.travelerPersonalInfo?.name}
-                icon={Expensicons.FallbackAvatar}
+                title={personalDetails?.displayName}
+                icon={personalDetails?.avatar ?? Expensicons.FallbackAvatar}
                 iconType={CONST.ICON_TYPE_AVATAR}
-                description={reservation.travelerPersonalInfo?.email}
+                description={personalDetails?.login}
                 interactive={false}
                 wrapperStyle={styles.pb3}
             />
diff --git a/src/pages/Travel/TripDetailsPage.tsx b/src/pages/Travel/TripDetailsPage.tsx
index a905d8bb1939..2907775109cc 100644
--- a/src/pages/Travel/TripDetailsPage.tsx
+++ b/src/pages/Travel/TripDetailsPage.tsx
@@ -39,6 +39,8 @@ function TripDetailsPage({route}: TripDetailsPageProps) {
     const [report] = useOnyx(`${ONYXKEYS.COLLECTION.REPORT}${route.params.reportID}`);
 
     const tripID = ReportUtils.getTripIDFromTransactionParentReportID(report?.parentReportID);
+    const accountID = Object.keys(report?.participants ?? {}).at(0) ?? '-1';
+    const [personalDetails] = useOnyx(ONYXKEYS.PERSONAL_DETAILS_LIST, {selector: (data) => data?.[accountID]});
     const reservationType = transaction?.receipt?.reservationList?.at(route.params.reservationIndex ?? 0)?.type;
     const reservation = transaction?.receipt?.reservationList?.at(route.params.reservationIndex ?? 0);
     const reservationIcon = TripReservationUtils.getTripReservationIcon(reservation?.type);
@@ -69,11 +71,27 @@ function TripDetailsPage({route}: TripDetailsPageProps) {
                         <FlightTripDetails
                             prevReservation={route.params.reservationIndex > 0 ? transaction?.receipt?.reservationList?.at(route.params.reservationIndex - 1) : undefined}
                             reservation={reservation}
+                            personalDetails={personalDetails}
+                        />
+                    )}
+                    {!!reservation && reservationType === CONST.RESERVATION_TYPE.HOTEL && (
+                        <HotelTripDetails
+                            reservation={reservation}
+                            personalDetails={personalDetails}
+                        />
+                    )}
+                    {!!reservation && reservationType === CONST.RESERVATION_TYPE.CAR && (
+                        <CarTripDetails
+                            reservation={reservation}
+                            personalDetails={personalDetails}
+                        />
+                    )}
+                    {!!reservation && reservationType === CONST.RESERVATION_TYPE.TRAIN && (
+                        <TrainTripDetails
+                            reservation={reservation}
+                            personalDetails={personalDetails}
                         />
                     )}
-                    {!!reservation && reservationType === CONST.RESERVATION_TYPE.HOTEL && <HotelTripDetails reservation={reservation} />}
-                    {!!reservation && reservationType === CONST.RESERVATION_TYPE.CAR && <CarTripDetails reservation={reservation} />}
-                    {!!reservation && reservationType === CONST.RESERVATION_TYPE.TRAIN && <TrainTripDetails reservation={reservation} />}
                     <MenuItem
                         title={translate('travel.modifyTrip')}
                         icon={Expensicons.Pencil}
diff --git a/src/types/onyx/Transaction.ts b/src/types/onyx/Transaction.ts
index 6765f53d9f0b..b5d7bbd8d348 100644
--- a/src/types/onyx/Transaction.ts
+++ b/src/types/onyx/Transaction.ts
@@ -190,15 +190,6 @@ type TaxRate = {
     data?: TaxRateData;
 };
 
-/** This represents the details of the traveler */
-type TravelerPersonalDetails = {
-    /** Email of the traveler */
-    email: string;
-
-    /** Name of the traveler */
-    name: string;
-};
-
 /** Model of reservation */
 type Reservation = {
     /** ID of the reservation */
@@ -272,9 +263,6 @@ type Reservation = {
 
     /** Seat number for rail */
     seatNumber?: string;
-
-    /** This represents the details of the traveler */
-    travelerPersonalInfo?: TravelerPersonalDetails;
 };
 
 /** Model of trip reservation time details */

From 1457fda10ae577ff1a5a1cacf108ec023401e222 Mon Sep 17 00:00:00 2001
From: Blazej Kustra <blazej.kustra@swmansion.com>
Date: Thu, 5 Dec 2024 12:08:31 +0100
Subject: [PATCH 66/75] Update trip details components to use traveler
 information from reservation object (but also use avatars from personal
 details)

---
 src/pages/Travel/CarTripDetails.tsx    |  4 ++--
 src/pages/Travel/FlightTripDetails.tsx |  4 ++--
 src/pages/Travel/HotelTripDetails.tsx  |  4 ++--
 src/pages/Travel/TrainTripDetails.tsx  |  4 ++--
 src/pages/Travel/TripDetailsPage.tsx   | 18 ++++++++++++------
 src/types/onyx/Transaction.ts          | 12 ++++++++++++
 6 files changed, 32 insertions(+), 14 deletions(-)

diff --git a/src/pages/Travel/CarTripDetails.tsx b/src/pages/Travel/CarTripDetails.tsx
index 920fa73d6140..bc13f76a1855 100644
--- a/src/pages/Travel/CarTripDetails.tsx
+++ b/src/pages/Travel/CarTripDetails.tsx
@@ -74,10 +74,10 @@ function CarTripDetails({reservation, personalDetails}: CarTripDetailsProps) {
             )}
             <MenuItem
                 label={translate('travel.carDetails.driver')}
-                title={personalDetails?.displayName}
+                title={personalDetails?.displayName ?? reservation.travelerPersonalInfo?.name}
                 icon={personalDetails?.avatar ?? Expensicons.FallbackAvatar}
                 iconType={CONST.ICON_TYPE_AVATAR}
-                description={personalDetails?.login}
+                description={personalDetails?.login ?? reservation.travelerPersonalInfo?.email}
                 interactive={false}
                 wrapperStyle={styles.pb3}
             />
diff --git a/src/pages/Travel/FlightTripDetails.tsx b/src/pages/Travel/FlightTripDetails.tsx
index 43e8e3e5f227..58268c94dd1d 100644
--- a/src/pages/Travel/FlightTripDetails.tsx
+++ b/src/pages/Travel/FlightTripDetails.tsx
@@ -112,10 +112,10 @@ function FlightTripDetails({reservation, prevReservation, personalDetails}: Flig
 
             <MenuItem
                 label={translate('travel.flightDetails.passenger')}
-                title={personalDetails?.displayName}
+                title={personalDetails?.displayName ?? reservation.travelerPersonalInfo?.name}
                 icon={personalDetails?.avatar ?? Expensicons.FallbackAvatar}
                 iconType={CONST.ICON_TYPE_AVATAR}
-                description={personalDetails?.login}
+                description={personalDetails?.login ?? reservation.travelerPersonalInfo?.email}
                 interactive={false}
                 wrapperStyle={styles.pb3}
             />
diff --git a/src/pages/Travel/HotelTripDetails.tsx b/src/pages/Travel/HotelTripDetails.tsx
index 2f65a4e4cd3b..5ee7b228c14f 100644
--- a/src/pages/Travel/HotelTripDetails.tsx
+++ b/src/pages/Travel/HotelTripDetails.tsx
@@ -68,10 +68,10 @@ function HotelTripDetails({reservation, personalDetails}: HotelTripDetailsProps)
             )}
             <MenuItem
                 label={translate('travel.hotelDetails.guest')}
-                title={personalDetails?.displayName}
+                title={personalDetails?.displayName ?? reservation.travelerPersonalInfo?.name}
                 icon={personalDetails?.avatar ?? Expensicons.FallbackAvatar}
                 iconType={CONST.ICON_TYPE_AVATAR}
-                description={personalDetails?.login}
+                description={personalDetails?.login ?? reservation.travelerPersonalInfo?.email}
                 interactive={false}
                 wrapperStyle={styles.pb3}
             />
diff --git a/src/pages/Travel/TrainTripDetails.tsx b/src/pages/Travel/TrainTripDetails.tsx
index e1ba7aa9aacf..8fa7ff1bed01 100644
--- a/src/pages/Travel/TrainTripDetails.tsx
+++ b/src/pages/Travel/TrainTripDetails.tsx
@@ -92,10 +92,10 @@ function TrainTripDetails({reservation, personalDetails}: TrainTripDetailsProps)
 
             <MenuItem
                 label={translate('travel.trainDetails.passenger')}
-                title={personalDetails?.displayName}
+                title={personalDetails?.displayName ?? reservation.travelerPersonalInfo?.name}
                 icon={personalDetails?.avatar ?? Expensicons.FallbackAvatar}
                 iconType={CONST.ICON_TYPE_AVATAR}
-                description={personalDetails?.login}
+                description={personalDetails?.login ?? reservation.travelerPersonalInfo?.email}
                 interactive={false}
                 wrapperStyle={styles.pb3}
             />
diff --git a/src/pages/Travel/TripDetailsPage.tsx b/src/pages/Travel/TripDetailsPage.tsx
index 2907775109cc..4e12f79809aa 100644
--- a/src/pages/Travel/TripDetailsPage.tsx
+++ b/src/pages/Travel/TripDetailsPage.tsx
@@ -1,6 +1,7 @@
 import type {StackScreenProps} from '@react-navigation/stack';
 import React from 'react';
 import {NativeModules} from 'react-native';
+import type {OnyxEntry} from 'react-native-onyx';
 import {useOnyx} from 'react-native-onyx';
 import FullPageNotFoundView from '@components/BlockingViews/FullPageNotFoundView';
 import HeaderWithBackButton from '@components/HeaderWithBackButton';
@@ -20,11 +21,17 @@ import * as Link from '@userActions/Link';
 import CONST from '@src/CONST';
 import ONYXKEYS from '@src/ONYXKEYS';
 import type SCREENS from '@src/SCREENS';
+import type {PersonalDetailsList} from '@src/types/onyx';
+import type {Reservation} from '@src/types/onyx/Transaction';
 import CarTripDetails from './CarTripDetails';
 import FlightTripDetails from './FlightTripDetails';
 import HotelTripDetails from './HotelTripDetails';
 import TrainTripDetails from './TrainTripDetails';
 
+function pickTravelerPersonalDetails(personalDetails: OnyxEntry<PersonalDetailsList>, reservation: Reservation | undefined) {
+    return Object.values(personalDetails ?? {})?.find((personalDetail) => personalDetail?.login === reservation?.travelerPersonalInfo?.email);
+}
+
 type TripDetailsPageProps = StackScreenProps<TravelNavigatorParamList, typeof SCREENS.TRAVEL.TRIP_DETAILS>;
 
 function TripDetailsPage({route}: TripDetailsPageProps) {
@@ -39,11 +46,10 @@ function TripDetailsPage({route}: TripDetailsPageProps) {
     const [report] = useOnyx(`${ONYXKEYS.COLLECTION.REPORT}${route.params.reportID}`);
 
     const tripID = ReportUtils.getTripIDFromTransactionParentReportID(report?.parentReportID);
-    const accountID = Object.keys(report?.participants ?? {}).at(0) ?? '-1';
-    const [personalDetails] = useOnyx(ONYXKEYS.PERSONAL_DETAILS_LIST, {selector: (data) => data?.[accountID]});
     const reservationType = transaction?.receipt?.reservationList?.at(route.params.reservationIndex ?? 0)?.type;
     const reservation = transaction?.receipt?.reservationList?.at(route.params.reservationIndex ?? 0);
     const reservationIcon = TripReservationUtils.getTripReservationIcon(reservation?.type);
+    const [travelerPersonalDetails] = useOnyx(ONYXKEYS.PERSONAL_DETAILS_LIST, {selector: (personalDetails) => pickTravelerPersonalDetails(personalDetails, reservation)});
 
     return (
         <ScreenWrapper
@@ -71,25 +77,25 @@ function TripDetailsPage({route}: TripDetailsPageProps) {
                         <FlightTripDetails
                             prevReservation={route.params.reservationIndex > 0 ? transaction?.receipt?.reservationList?.at(route.params.reservationIndex - 1) : undefined}
                             reservation={reservation}
-                            personalDetails={personalDetails}
+                            personalDetails={travelerPersonalDetails}
                         />
                     )}
                     {!!reservation && reservationType === CONST.RESERVATION_TYPE.HOTEL && (
                         <HotelTripDetails
                             reservation={reservation}
-                            personalDetails={personalDetails}
+                            personalDetails={travelerPersonalDetails}
                         />
                     )}
                     {!!reservation && reservationType === CONST.RESERVATION_TYPE.CAR && (
                         <CarTripDetails
                             reservation={reservation}
-                            personalDetails={personalDetails}
+                            personalDetails={travelerPersonalDetails}
                         />
                     )}
                     {!!reservation && reservationType === CONST.RESERVATION_TYPE.TRAIN && (
                         <TrainTripDetails
                             reservation={reservation}
-                            personalDetails={personalDetails}
+                            personalDetails={travelerPersonalDetails}
                         />
                     )}
                     <MenuItem
diff --git a/src/types/onyx/Transaction.ts b/src/types/onyx/Transaction.ts
index b5d7bbd8d348..6765f53d9f0b 100644
--- a/src/types/onyx/Transaction.ts
+++ b/src/types/onyx/Transaction.ts
@@ -190,6 +190,15 @@ type TaxRate = {
     data?: TaxRateData;
 };
 
+/** This represents the details of the traveler */
+type TravelerPersonalDetails = {
+    /** Email of the traveler */
+    email: string;
+
+    /** Name of the traveler */
+    name: string;
+};
+
 /** Model of reservation */
 type Reservation = {
     /** ID of the reservation */
@@ -263,6 +272,9 @@ type Reservation = {
 
     /** Seat number for rail */
     seatNumber?: string;
+
+    /** This represents the details of the traveler */
+    travelerPersonalInfo?: TravelerPersonalDetails;
 };
 
 /** Model of trip reservation time details */

From 9a9eaf705d166f1441af0a853affee18a8bc48f3 Mon Sep 17 00:00:00 2001
From: Blazej Kustra <blazej.kustra@swmansion.com>
Date: Thu, 5 Dec 2024 14:33:41 +0100
Subject: [PATCH 67/75] Show duration for train, fix truncated confirmatiion
 number

---
 src/pages/Travel/TrainTripDetails.tsx | 18 ++++++++----------
 1 file changed, 8 insertions(+), 10 deletions(-)

diff --git a/src/pages/Travel/TrainTripDetails.tsx b/src/pages/Travel/TrainTripDetails.tsx
index 8fa7ff1bed01..a16ec20fd2a6 100644
--- a/src/pages/Travel/TrainTripDetails.tsx
+++ b/src/pages/Travel/TrainTripDetails.tsx
@@ -26,7 +26,7 @@ function TrainTripDetails({reservation, personalDetails}: TrainTripDetailsProps)
     const trainRouteDescription = `${reservation.start.longName} (${reservation.start.shortName}) ${translate('common.conjunctionTo')} ${reservation.end.longName} (${
         reservation.end.shortName
     })`;
-    const trainDuration = reservation.duration && DateUtils.getFormattedDuration(translate, reservation.duration);
+    const trainDuration = DateUtils.getFormattedDurationBetweenDates(translate, new Date(reservation.start.date), new Date(reservation.end.date));
 
     return (
         <>
@@ -79,16 +79,14 @@ function TrainTripDetails({reservation, personalDetails}: TrainTripDetailsProps)
                         />
                     </View>
                 )}
-                {!!reservation.confirmations?.at(0)?.value && (
-                    <View style={styles.w50}>
-                        <MenuItemWithTopDescription
-                            description={translate('travel.trainDetails.confirmation')}
-                            title={reservation.confirmations?.at(0)?.value}
-                            interactive={false}
-                        />
-                    </View>
-                )}
             </View>
+            {!!reservation.confirmations?.at(0)?.value && (
+                <MenuItemWithTopDescription
+                    description={translate('travel.trainDetails.confirmation')}
+                    title={reservation.confirmations?.at(0)?.value}
+                    interactive={false}
+                />
+            )}
 
             <MenuItem
                 label={translate('travel.trainDetails.passenger')}

From c7ebfb2de0e65fecc4de23140982daa08e2adbcb Mon Sep 17 00:00:00 2001
From: Blazej Kustra <blazej.kustra@swmansion.com>
Date: Thu, 5 Dec 2024 15:49:48 +0100
Subject: [PATCH 68/75] Display passenger/guest conditionally

---
 src/pages/Travel/CarTripDetails.tsx    | 22 +++++++++++++---------
 src/pages/Travel/FlightTripDetails.tsx | 23 +++++++++++++----------
 src/pages/Travel/HotelTripDetails.tsx  | 22 +++++++++++++---------
 src/pages/Travel/TrainTripDetails.tsx  | 22 +++++++++++++---------
 4 files changed, 52 insertions(+), 37 deletions(-)

diff --git a/src/pages/Travel/CarTripDetails.tsx b/src/pages/Travel/CarTripDetails.tsx
index bc13f76a1855..09ffd3d2cad1 100644
--- a/src/pages/Travel/CarTripDetails.tsx
+++ b/src/pages/Travel/CarTripDetails.tsx
@@ -26,6 +26,8 @@ function CarTripDetails({reservation, personalDetails}: CarTripDetailsProps) {
         ? `${translate('travel.carDetails.cancellationUntil')} ${DateUtils.getFormattedTransportDateAndHour(new Date(reservation.cancellationDeadline)).date}`
         : reservation.cancellationPolicy;
 
+    const displayName = personalDetails?.displayName ?? reservation.travelerPersonalInfo?.name;
+
     return (
         <>
             <Text style={[styles.textHeadlineH1, styles.mh5, styles.mv3]}>{reservation.vendor}</Text>
@@ -72,15 +74,17 @@ function CarTripDetails({reservation, personalDetails}: CarTripDetailsProps) {
                     interactive={false}
                 />
             )}
-            <MenuItem
-                label={translate('travel.carDetails.driver')}
-                title={personalDetails?.displayName ?? reservation.travelerPersonalInfo?.name}
-                icon={personalDetails?.avatar ?? Expensicons.FallbackAvatar}
-                iconType={CONST.ICON_TYPE_AVATAR}
-                description={personalDetails?.login ?? reservation.travelerPersonalInfo?.email}
-                interactive={false}
-                wrapperStyle={styles.pb3}
-            />
+            {!!displayName && (
+                <MenuItem
+                    label={translate('travel.carDetails.driver')}
+                    title={displayName}
+                    icon={personalDetails?.avatar ?? Expensicons.FallbackAvatar}
+                    iconType={CONST.ICON_TYPE_AVATAR}
+                    description={personalDetails?.login ?? reservation.travelerPersonalInfo?.email}
+                    interactive={false}
+                    wrapperStyle={styles.pb3}
+                />
+            )}
         </>
     );
 }
diff --git a/src/pages/Travel/FlightTripDetails.tsx b/src/pages/Travel/FlightTripDetails.tsx
index 58268c94dd1d..901286ef33b8 100644
--- a/src/pages/Travel/FlightTripDetails.tsx
+++ b/src/pages/Travel/FlightTripDetails.tsx
@@ -37,6 +37,8 @@ function FlightTripDetails({reservation, prevReservation, personalDetails}: Flig
         reservation.end.shortName
     })`;
 
+    const displayName = personalDetails?.displayName ?? reservation.travelerPersonalInfo?.name;
+
     return (
         <>
             <Text style={[styles.textHeadlineH1, styles.mh5, styles.mv3]}>{flightRouteDescription}</Text>
@@ -109,16 +111,17 @@ function FlightTripDetails({reservation, prevReservation, personalDetails}: Flig
                     </View>
                 )}
             </View>
-
-            <MenuItem
-                label={translate('travel.flightDetails.passenger')}
-                title={personalDetails?.displayName ?? reservation.travelerPersonalInfo?.name}
-                icon={personalDetails?.avatar ?? Expensicons.FallbackAvatar}
-                iconType={CONST.ICON_TYPE_AVATAR}
-                description={personalDetails?.login ?? reservation.travelerPersonalInfo?.email}
-                interactive={false}
-                wrapperStyle={styles.pb3}
-            />
+            {!!displayName && (
+                <MenuItem
+                    label={translate('travel.flightDetails.passenger')}
+                    title={displayName}
+                    icon={personalDetails?.avatar ?? Expensicons.FallbackAvatar}
+                    iconType={CONST.ICON_TYPE_AVATAR}
+                    description={personalDetails?.login ?? reservation.travelerPersonalInfo?.email}
+                    interactive={false}
+                    wrapperStyle={styles.pb3}
+                />
+            )}
         </>
     );
 }
diff --git a/src/pages/Travel/HotelTripDetails.tsx b/src/pages/Travel/HotelTripDetails.tsx
index 5ee7b228c14f..bb500fa673fa 100644
--- a/src/pages/Travel/HotelTripDetails.tsx
+++ b/src/pages/Travel/HotelTripDetails.tsx
@@ -26,6 +26,8 @@ function HotelTripDetails({reservation, personalDetails}: HotelTripDetailsProps)
         ? `${translate('travel.hotelDetails.cancellationUntil')} ${DateUtils.getFormattedTransportDateAndHour(new Date(reservation.cancellationDeadline)).date}`
         : reservation.cancellationPolicy;
 
+    const displayName = personalDetails?.displayName ?? reservation.travelerPersonalInfo?.name;
+
     return (
         <>
             <Text style={[styles.textHeadlineH1, styles.mh5, styles.mv3]}>{reservation.start.longName}</Text>
@@ -66,15 +68,17 @@ function HotelTripDetails({reservation, personalDetails}: HotelTripDetailsProps)
                     interactive={false}
                 />
             )}
-            <MenuItem
-                label={translate('travel.hotelDetails.guest')}
-                title={personalDetails?.displayName ?? reservation.travelerPersonalInfo?.name}
-                icon={personalDetails?.avatar ?? Expensicons.FallbackAvatar}
-                iconType={CONST.ICON_TYPE_AVATAR}
-                description={personalDetails?.login ?? reservation.travelerPersonalInfo?.email}
-                interactive={false}
-                wrapperStyle={styles.pb3}
-            />
+            {!!displayName && (
+                <MenuItem
+                    label={translate('travel.hotelDetails.guest')}
+                    title={displayName}
+                    icon={personalDetails?.avatar ?? Expensicons.FallbackAvatar}
+                    iconType={CONST.ICON_TYPE_AVATAR}
+                    description={personalDetails?.login ?? reservation.travelerPersonalInfo?.email}
+                    interactive={false}
+                    wrapperStyle={styles.pb3}
+                />
+            )}
         </>
     );
 }
diff --git a/src/pages/Travel/TrainTripDetails.tsx b/src/pages/Travel/TrainTripDetails.tsx
index a16ec20fd2a6..c83245981321 100644
--- a/src/pages/Travel/TrainTripDetails.tsx
+++ b/src/pages/Travel/TrainTripDetails.tsx
@@ -28,6 +28,8 @@ function TrainTripDetails({reservation, personalDetails}: TrainTripDetailsProps)
     })`;
     const trainDuration = DateUtils.getFormattedDurationBetweenDates(translate, new Date(reservation.start.date), new Date(reservation.end.date));
 
+    const displayName = personalDetails?.displayName ?? reservation.travelerPersonalInfo?.name;
+
     return (
         <>
             <Text style={[styles.textHeadlineH1, styles.mh5, styles.mv3]}>{trainRouteDescription}</Text>
@@ -88,15 +90,17 @@ function TrainTripDetails({reservation, personalDetails}: TrainTripDetailsProps)
                 />
             )}
 
-            <MenuItem
-                label={translate('travel.trainDetails.passenger')}
-                title={personalDetails?.displayName ?? reservation.travelerPersonalInfo?.name}
-                icon={personalDetails?.avatar ?? Expensicons.FallbackAvatar}
-                iconType={CONST.ICON_TYPE_AVATAR}
-                description={personalDetails?.login ?? reservation.travelerPersonalInfo?.email}
-                interactive={false}
-                wrapperStyle={styles.pb3}
-            />
+            {!!displayName && (
+                <MenuItem
+                    label={translate('travel.trainDetails.passenger')}
+                    title={displayName}
+                    icon={personalDetails?.avatar ?? Expensicons.FallbackAvatar}
+                    iconType={CONST.ICON_TYPE_AVATAR}
+                    description={personalDetails?.login ?? reservation.travelerPersonalInfo?.email}
+                    interactive={false}
+                    wrapperStyle={styles.pb3}
+                />
+            )}
         </>
     );
 }

From e09dc23aaf9a1546aa01d39342b07e1d9f7a3236 Mon Sep 17 00:00:00 2001
From: Blazej Kustra <blazej.kustra@swmansion.com>
Date: Fri, 6 Dec 2024 09:32:32 +0100
Subject: [PATCH 69/75] Use label size for layover

---
 src/languages/en.ts                    | 2 +-
 src/languages/es.ts                    | 2 +-
 src/pages/Travel/FlightTripDetails.tsx | 2 +-
 3 files changed, 3 insertions(+), 3 deletions(-)

diff --git a/src/languages/en.ts b/src/languages/en.ts
index 95ac762d0d2b..f37ed7a8ac29 100755
--- a/src/languages/en.ts
+++ b/src/languages/en.ts
@@ -2445,7 +2445,7 @@ const translations = {
         flight: 'Flight',
         flightDetails: {
             passenger: 'Passenger',
-            layover: ({layover}: FlightLayoverParams) => `<muted-text>You have a <strong>${layover} layover</strong> before this flight</muted-text>`,
+            layover: ({layover}: FlightLayoverParams) => `<muted-text-label>You have a <strong>${layover} layover</strong> before this flight</muted-text-label>`,
             takeOff: 'Take-off',
             landing: 'Landing',
             seat: 'Seat',
diff --git a/src/languages/es.ts b/src/languages/es.ts
index b327e73c3950..76b23e905514 100644
--- a/src/languages/es.ts
+++ b/src/languages/es.ts
@@ -2469,7 +2469,7 @@ const translations = {
         flight: 'Vuelo',
         flightDetails: {
             passenger: 'Pasajero',
-            layover: ({layover}: FlightLayoverParams) => `Tienes una <strong>escala de ${layover}</strong> antes de este vuelo`,
+            layover: ({layover}: FlightLayoverParams) => `<muted-text-label>Tienes una <strong>escala de ${layover}</strong> antes de este vuelo</muted-text-label>`,
             takeOff: 'Despegue',
             landing: 'Aterrizaje',
             seat: 'Asiento',
diff --git a/src/pages/Travel/FlightTripDetails.tsx b/src/pages/Travel/FlightTripDetails.tsx
index 901286ef33b8..2882527879d9 100644
--- a/src/pages/Travel/FlightTripDetails.tsx
+++ b/src/pages/Travel/FlightTripDetails.tsx
@@ -38,7 +38,7 @@ function FlightTripDetails({reservation, prevReservation, personalDetails}: Flig
     })`;
 
     const displayName = personalDetails?.displayName ?? reservation.travelerPersonalInfo?.name;
-
+    console.log(`%%% reservation`, reservation);
     return (
         <>
             <Text style={[styles.textHeadlineH1, styles.mh5, styles.mv3]}>{flightRouteDescription}</Text>

From e91d3a824d9c603b31f8472e99d90863caacccac Mon Sep 17 00:00:00 2001
From: Blazej Kustra <blazej.kustra@swmansion.com>
Date: Fri, 6 Dec 2024 09:32:44 +0100
Subject: [PATCH 70/75] Remove console log from FlightTripDetails component

---
 src/pages/Travel/FlightTripDetails.tsx | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/src/pages/Travel/FlightTripDetails.tsx b/src/pages/Travel/FlightTripDetails.tsx
index 2882527879d9..901286ef33b8 100644
--- a/src/pages/Travel/FlightTripDetails.tsx
+++ b/src/pages/Travel/FlightTripDetails.tsx
@@ -38,7 +38,7 @@ function FlightTripDetails({reservation, prevReservation, personalDetails}: Flig
     })`;
 
     const displayName = personalDetails?.displayName ?? reservation.travelerPersonalInfo?.name;
-    console.log(`%%% reservation`, reservation);
+
     return (
         <>
             <Text style={[styles.textHeadlineH1, styles.mh5, styles.mv3]}>{flightRouteDescription}</Text>

From 6b313498d810ae76b4b3d42a82e56277f1c1ec23 Mon Sep 17 00:00:00 2001
From: Blazej Kustra <blazej.kustra@swmansion.com>
Date: Fri, 6 Dec 2024 09:44:55 +0100
Subject: [PATCH 71/75] Refactor navigation parameters to use tripRoomReportID
 consistently across trip-related components

---
 src/components/ReportActionItem/MoneyRequestView.tsx |  8 ++------
 src/components/ReportActionItem/TripDetailsView.tsx  | 12 ++++++------
 src/pages/Travel/TripDetailsPage.tsx                 |  3 +--
 src/pages/Travel/TripSummaryPage.tsx                 |  4 ++--
 4 files changed, 11 insertions(+), 16 deletions(-)

diff --git a/src/components/ReportActionItem/MoneyRequestView.tsx b/src/components/ReportActionItem/MoneyRequestView.tsx
index 46ff97fcc6db..b48880c3ae76 100644
--- a/src/components/ReportActionItem/MoneyRequestView.tsx
+++ b/src/components/ReportActionItem/MoneyRequestView.tsx
@@ -702,13 +702,9 @@ function MoneyRequestView({report, shouldShowAnimatedBackground, readonly = fals
                         onPress={() => {
                             const reservations = transaction?.receipt?.reservationList?.length ?? 0;
                             if (reservations > 1) {
-                                Navigation.navigate(
-                                    ROUTES.TRAVEL_TRIP_SUMMARY.getRoute(report?.parentReportID ?? '-1', transaction?.transactionID ?? '-1', Navigation.getReportRHPActiveRoute()),
-                                );
+                                Navigation.navigate(ROUTES.TRAVEL_TRIP_SUMMARY.getRoute(report?.reportID ?? '-1', transaction?.transactionID ?? '-1', Navigation.getReportRHPActiveRoute()));
                             }
-                            Navigation.navigate(
-                                ROUTES.TRAVEL_TRIP_DETAILS.getRoute(report?.parentReportID ?? '-1', transaction?.transactionID ?? '-1', 0, Navigation.getReportRHPActiveRoute()),
-                            );
+                            Navigation.navigate(ROUTES.TRAVEL_TRIP_DETAILS.getRoute(report?.reportID ?? '-1', transaction?.transactionID ?? '-1', 0, Navigation.getReportRHPActiveRoute()));
                         }}
                     />
                 )}
diff --git a/src/components/ReportActionItem/TripDetailsView.tsx b/src/components/ReportActionItem/TripDetailsView.tsx
index 4fcd1906afc9..a7fdef547bf9 100644
--- a/src/components/ReportActionItem/TripDetailsView.tsx
+++ b/src/components/ReportActionItem/TripDetailsView.tsx
@@ -22,7 +22,7 @@ import type {Reservation, ReservationTimeDetails} from '@src/types/onyx/Transact
 
 type TripDetailsViewProps = {
     /** The active tripRoomReportID, used for Onyx subscription */
-    tripRoomReportID?: string;
+    tripRoomReportID: string;
 
     /** Whether we should display the horizontal rule below the component */
     shouldShowHorizontalRule: boolean;
@@ -31,11 +31,11 @@ type TripDetailsViewProps = {
 type ReservationViewProps = {
     reservation: Reservation;
     transactionID: string;
-    reportID: string;
+    tripRoomReportID: string;
     reservationIndex: number;
 };
 
-function ReservationView({reservation, transactionID, reportID, reservationIndex}: ReservationViewProps) {
+function ReservationView({reservation, transactionID, tripRoomReportID, reservationIndex}: ReservationViewProps) {
     const theme = useTheme();
     const styles = useThemeStyles();
     const StyleUtils = useStyleUtils();
@@ -137,7 +137,7 @@ function ReservationView({reservation, transactionID, reportID, reservationIndex
             iconWidth={20}
             iconStyles={[StyleUtils.getTripReservationIconContainer(false), styles.mr3]}
             secondaryIconFill={theme.icon}
-            onPress={() => Navigation.navigate(ROUTES.TRAVEL_TRIP_DETAILS.getRoute(reportID, transactionID, reservationIndex, Navigation.getReportRHPActiveRoute()))}
+            onPress={() => Navigation.navigate(ROUTES.TRAVEL_TRIP_DETAILS.getRoute(tripRoomReportID, transactionID, reservationIndex, Navigation.getReportRHPActiveRoute()))}
         />
     );
 }
@@ -162,13 +162,13 @@ function TripDetailsView({tripRoomReportID, shouldShowHorizontalRule}: TripDetai
                 </View>
             </View>
             <>
-                {reservationsData.map(({reservation, transactionID, reportID, reservationIndex}) => {
+                {reservationsData.map(({reservation, transactionID, reservationIndex}) => {
                     return (
                         <OfflineWithFeedback>
                             <ReservationView
                                 reservation={reservation}
                                 transactionID={transactionID}
-                                reportID={reportID}
+                                tripRoomReportID={tripRoomReportID}
                                 reservationIndex={reservationIndex}
                             />
                         </OfflineWithFeedback>
diff --git a/src/pages/Travel/TripDetailsPage.tsx b/src/pages/Travel/TripDetailsPage.tsx
index 4e12f79809aa..7b6d0cde85c2 100644
--- a/src/pages/Travel/TripDetailsPage.tsx
+++ b/src/pages/Travel/TripDetailsPage.tsx
@@ -43,9 +43,8 @@ function TripDetailsPage({route}: TripDetailsPageProps) {
 
     const [activePolicyID] = useOnyx(ONYXKEYS.NVP_ACTIVE_POLICY_ID);
     const [transaction] = useOnyx(`${ONYXKEYS.COLLECTION.TRANSACTION}${route.params.transactionID}`);
-    const [report] = useOnyx(`${ONYXKEYS.COLLECTION.REPORT}${route.params.reportID}`);
 
-    const tripID = ReportUtils.getTripIDFromTransactionParentReportID(report?.parentReportID);
+    const tripID = ReportUtils.getTripIDFromTransactionParentReportID(route.params.reportID);
     const reservationType = transaction?.receipt?.reservationList?.at(route.params.reservationIndex ?? 0)?.type;
     const reservation = transaction?.receipt?.reservationList?.at(route.params.reservationIndex ?? 0);
     const reservationIcon = TripReservationUtils.getTripReservationIcon(reservation?.type);
diff --git a/src/pages/Travel/TripSummaryPage.tsx b/src/pages/Travel/TripSummaryPage.tsx
index caf5d471c84c..8a0a4f9c38b7 100644
--- a/src/pages/Travel/TripSummaryPage.tsx
+++ b/src/pages/Travel/TripSummaryPage.tsx
@@ -41,13 +41,13 @@ function TripSummaryPage({route}: TripSummaryPageProps) {
                     shouldShowBackButton
                 />
                 <ScrollView>
-                    {reservationsData.map(({reservation, transactionID, reportID, reservationIndex}) => {
+                    {reservationsData.map(({reservation, transactionID, reservationIndex}) => {
                         return (
                             <OfflineWithFeedback>
                                 <ReservationView
                                     reservation={reservation}
                                     transactionID={transactionID}
-                                    reportID={reportID}
+                                    tripRoomReportID={route.params.reportID}
                                     reservationIndex={reservationIndex}
                                 />
                             </OfflineWithFeedback>

From 9c82c76e0ef228591383ab3aa1c917936d25ba73 Mon Sep 17 00:00:00 2001
From: Blazej Kustra <blazej.kustra@swmansion.com>
Date: Fri, 6 Dec 2024 11:05:56 +0100
Subject: [PATCH 72/75] Fix modify trip and trip support buttons for all cases

---
 src/pages/Travel/TripDetailsPage.tsx | 4 +++-
 1 file changed, 3 insertions(+), 1 deletion(-)

diff --git a/src/pages/Travel/TripDetailsPage.tsx b/src/pages/Travel/TripDetailsPage.tsx
index 7b6d0cde85c2..c6ff3c23990f 100644
--- a/src/pages/Travel/TripDetailsPage.tsx
+++ b/src/pages/Travel/TripDetailsPage.tsx
@@ -43,8 +43,10 @@ function TripDetailsPage({route}: TripDetailsPageProps) {
 
     const [activePolicyID] = useOnyx(ONYXKEYS.NVP_ACTIVE_POLICY_ID);
     const [transaction] = useOnyx(`${ONYXKEYS.COLLECTION.TRANSACTION}${route.params.transactionID}`);
+    const [report] = useOnyx(`${ONYXKEYS.COLLECTION.REPORT}${transaction?.reportID ?? '-1'}`);
+    const [parentReport] = useOnyx(`${ONYXKEYS.COLLECTION.REPORT}${report?.parentReportID ?? '-1'}`);
 
-    const tripID = ReportUtils.getTripIDFromTransactionParentReportID(route.params.reportID);
+    const tripID = ReportUtils.getTripIDFromTransactionParentReportID(parentReport?.reportID);
     const reservationType = transaction?.receipt?.reservationList?.at(route.params.reservationIndex ?? 0)?.type;
     const reservation = transaction?.receipt?.reservationList?.at(route.params.reservationIndex ?? 0);
     const reservationIcon = TripReservationUtils.getTripReservationIcon(reservation?.type);

From c69639a6ada393bab6714e1af4228880bcc5c043 Mon Sep 17 00:00:00 2001
From: Blazej Kustra <blazej.kustra@swmansion.com>
Date: Fri, 6 Dec 2024 11:15:48 +0100
Subject: [PATCH 73/75] Add network status handling to disable buttons when
 offline

---
 src/pages/Travel/TripDetailsPage.tsx | 4 ++++
 1 file changed, 4 insertions(+)

diff --git a/src/pages/Travel/TripDetailsPage.tsx b/src/pages/Travel/TripDetailsPage.tsx
index c6ff3c23990f..0ba086bff325 100644
--- a/src/pages/Travel/TripDetailsPage.tsx
+++ b/src/pages/Travel/TripDetailsPage.tsx
@@ -10,6 +10,7 @@ import MenuItem from '@components/MenuItem';
 import ScreenWrapper from '@components/ScreenWrapper';
 import ScrollView from '@components/ScrollView';
 import useLocalize from '@hooks/useLocalize';
+import useNetwork from '@hooks/useNetwork';
 import usePermissions from '@hooks/usePermissions';
 import useStyleUtils from '@hooks/useStyleUtils';
 import useTheme from '@hooks/useTheme';
@@ -40,6 +41,7 @@ function TripDetailsPage({route}: TripDetailsPageProps) {
     const StyleUtils = useStyleUtils();
     const {translate} = useLocalize();
     const {canUseSpotnanaTravel} = usePermissions();
+    const {isOffline} = useNetwork();
 
     const [activePolicyID] = useOnyx(ONYXKEYS.NVP_ACTIVE_POLICY_ID);
     const [transaction] = useOnyx(`${ONYXKEYS.COLLECTION.TRANSACTION}${route.params.transactionID}`);
@@ -109,6 +111,7 @@ function TripDetailsPage({route}: TripDetailsPageProps) {
                             Link.openTravelDotLink(activePolicyID, CONST.TRIP_ID_PATH(tripID));
                         }}
                         wrapperStyle={styles.mt3}
+                        disabled={isOffline}
                     />
                     <MenuItem
                         title={translate('travel.tripSupport')}
@@ -119,6 +122,7 @@ function TripDetailsPage({route}: TripDetailsPageProps) {
                         onPress={() => {
                             Link.openTravelDotLink(activePolicyID, CONST.TRIP_ID_PATH(tripID));
                         }}
+                        disabled={isOffline}
                     />
                 </ScrollView>
             </FullPageNotFoundView>

From 0b6030ff28924ce995bc70ee9099b614910284a9 Mon Sep 17 00:00:00 2001
From: Blazej Kustra <blazej.kustra@swmansion.com>
Date: Fri, 6 Dec 2024 15:38:55 +0100
Subject: [PATCH 74/75] Add loading state management for trip modification and
 support actions

---
 src/pages/Travel/TripDetailsPage.tsx | 21 ++++++++++++++++-----
 1 file changed, 16 insertions(+), 5 deletions(-)

diff --git a/src/pages/Travel/TripDetailsPage.tsx b/src/pages/Travel/TripDetailsPage.tsx
index 0ba086bff325..39094d1821e7 100644
--- a/src/pages/Travel/TripDetailsPage.tsx
+++ b/src/pages/Travel/TripDetailsPage.tsx
@@ -1,5 +1,5 @@
 import type {StackScreenProps} from '@react-navigation/stack';
-import React from 'react';
+import React, {useState} from 'react';
 import {NativeModules} from 'react-native';
 import type {OnyxEntry} from 'react-native-onyx';
 import {useOnyx} from 'react-native-onyx';
@@ -43,6 +43,9 @@ function TripDetailsPage({route}: TripDetailsPageProps) {
     const {canUseSpotnanaTravel} = usePermissions();
     const {isOffline} = useNetwork();
 
+    const [isModifyTripLoading, setIsModifyTripLoading] = useState(false);
+    const [isTripSupportLoading, setIsTripSupportLoading] = useState(false);
+
     const [activePolicyID] = useOnyx(ONYXKEYS.NVP_ACTIVE_POLICY_ID);
     const [transaction] = useOnyx(`${ONYXKEYS.COLLECTION.TRANSACTION}${route.params.transactionID}`);
     const [report] = useOnyx(`${ONYXKEYS.COLLECTION.REPORT}${transaction?.reportID ?? '-1'}`);
@@ -108,10 +111,14 @@ function TripDetailsPage({route}: TripDetailsPageProps) {
                         iconRight={Expensicons.NewWindow}
                         shouldShowRightIcon
                         onPress={() => {
-                            Link.openTravelDotLink(activePolicyID, CONST.TRIP_ID_PATH(tripID));
+                            setIsModifyTripLoading(true);
+                            Link.openTravelDotLink(activePolicyID, CONST.TRIP_ID_PATH(tripID))?.finally(() => {
+                                setIsModifyTripLoading(false);
+                            });
                         }}
                         wrapperStyle={styles.mt3}
-                        disabled={isOffline}
+                        shouldShowLoadingSpinnerIcon={isModifyTripLoading}
+                        disabled={isModifyTripLoading || isOffline}
                     />
                     <MenuItem
                         title={translate('travel.tripSupport')}
@@ -120,9 +127,13 @@ function TripDetailsPage({route}: TripDetailsPageProps) {
                         iconRight={Expensicons.NewWindow}
                         shouldShowRightIcon
                         onPress={() => {
-                            Link.openTravelDotLink(activePolicyID, CONST.TRIP_ID_PATH(tripID));
+                            setIsTripSupportLoading(true);
+                            Link.openTravelDotLink(activePolicyID, CONST.TRIP_ID_PATH(tripID))?.finally(() => {
+                                setIsTripSupportLoading(false);
+                            });
                         }}
-                        disabled={isOffline}
+                        shouldShowLoadingSpinnerIcon={isTripSupportLoading}
+                        disabled={isTripSupportLoading || isOffline}
                     />
                 </ScrollView>
             </FullPageNotFoundView>

From 8324be88317eac24e8a594a37d7b979b682fa330 Mon Sep 17 00:00:00 2001
From: Jakub Szymczak <szymczak.jakub12@gmail.com>
Date: Tue, 10 Dec 2024 13:19:33 +0100
Subject: [PATCH 75/75] fix PR comments

---
 src/components/ReportActionItem/TripRoomPreview.tsx | 4 ++--
 src/pages/Travel/HotelTripDetails.tsx               | 1 +
 src/pages/Travel/TripDetailsPage.tsx                | 2 +-
 3 files changed, 4 insertions(+), 3 deletions(-)

diff --git a/src/components/ReportActionItem/TripRoomPreview.tsx b/src/components/ReportActionItem/TripRoomPreview.tsx
index f8537e4beacf..764979651ee7 100644
--- a/src/components/ReportActionItem/TripRoomPreview.tsx
+++ b/src/components/ReportActionItem/TripRoomPreview.tsx
@@ -77,14 +77,14 @@ function ReservationView({reservation}: ReservationViewProps) {
 
         titleComponent = (
             <View style={[styles.flexRow, styles.alignItemsCenter, styles.gap2]}>
-                <Text style={styles.labelStrong}>{startName}</Text>
+                <Text style={[styles.labelStrong, styles.flexShrink1]}>{startName}</Text>
                 <Icon
                     src={Expensicons.ArrowRightLong}
                     width={variables.iconSizeSmall}
                     height={variables.iconSizeSmall}
                     fill={theme.icon}
                 />
-                <Text style={styles.labelStrong}>{endName}</Text>
+                <Text style={[styles.labelStrong, styles.flexShrink1]}>{endName}</Text>
             </View>
         );
     }
diff --git a/src/pages/Travel/HotelTripDetails.tsx b/src/pages/Travel/HotelTripDetails.tsx
index bb500fa673fa..747dc3ceca70 100644
--- a/src/pages/Travel/HotelTripDetails.tsx
+++ b/src/pages/Travel/HotelTripDetails.tsx
@@ -35,6 +35,7 @@ function HotelTripDetails({reservation, personalDetails}: HotelTripDetailsProps)
                 description={translate('common.address')}
                 title={reservation.start.address}
                 interactive={false}
+                numberOfLinesTitle={2}
             />
             <MenuItemWithTopDescription
                 description={translate('travel.hotelDetails.checkIn')}
diff --git a/src/pages/Travel/TripDetailsPage.tsx b/src/pages/Travel/TripDetailsPage.tsx
index 39094d1821e7..d7a93e7cdeba 100644
--- a/src/pages/Travel/TripDetailsPage.tsx
+++ b/src/pages/Travel/TripDetailsPage.tsx
@@ -59,7 +59,7 @@ function TripDetailsPage({route}: TripDetailsPageProps) {
 
     return (
         <ScreenWrapper
-            includeSafeAreaPaddingBottom={false}
+            includeSafeAreaPaddingBottom
             shouldEnablePickerAvoiding={false}
             shouldEnableMaxHeight
             testID={TripDetailsPage.displayName}
