diff --git a/src/components/ReportActionItem/TripDetailsView.tsx b/src/components/ReportActionItem/TripDetailsView.tsx index 999ef4345e5b..fe6831f72512 100644 --- a/src/components/ReportActionItem/TripDetailsView.tsx +++ b/src/components/ReportActionItem/TripDetailsView.tsx @@ -7,6 +7,7 @@ import SpacerView from '@components/SpacerView'; import Text from '@components/Text'; import useLocalize from '@hooks/useLocalize'; import useResponsiveLayout from '@hooks/useResponsiveLayout'; +import useStyleUtils from '@hooks/useStyleUtils'; import useTheme from '@hooks/useTheme'; import useThemeStyles from '@hooks/useThemeStyles'; import DateUtils from '@libs/DateUtils'; @@ -32,6 +33,7 @@ type ReservationViewProps = { function ReservationView({reservation}: ReservationViewProps) { const theme = useTheme(); const styles = useThemeStyles(); + const StyleUtils = useStyleUtils(); const {shouldUseNarrowLayout} = useResponsiveLayout(); const reservationIcon = TripReservationUtils.getTripReservationIcon(reservation.type); @@ -125,7 +127,7 @@ function ReservationView({reservation}: ReservationViewProps) { onSecondaryInteraction={() => {}} iconHeight={20} iconWidth={20} - iconStyles={[styles.tripReservationIconContainer, styles.mr3]} + iconStyles={[StyleUtils.getTripReservationIconContainer(false), styles.mr3]} secondaryIconFill={theme.icon} hoverAndPressStyle={styles.hoveredComponentBG} /> diff --git a/src/components/ReportActionItem/TripRoomPreview.tsx b/src/components/ReportActionItem/TripRoomPreview.tsx new file mode 100644 index 000000000000..3711965305a9 --- /dev/null +++ b/src/components/ReportActionItem/TripRoomPreview.tsx @@ -0,0 +1,200 @@ +import React, {useMemo} from 'react'; +import type {StyleProp, ViewStyle} from 'react-native'; +import {FlatList, View} from 'react-native'; +import {useOnyx} from 'react-native-onyx'; +import Button from '@components/Button'; +import Icon from '@components/Icon'; +import MenuItemWithTopDescription from '@components/MenuItemWithTopDescription'; +import OfflineWithFeedback from '@components/OfflineWithFeedback'; +import {PressableWithoutFeedback} from '@components/Pressable'; +import {showContextMenuForReport} from '@components/ShowContextMenuContext'; +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 ControlSelection from '@libs/ControlSelection'; +import * as CurrencyUtils from '@libs/CurrencyUtils'; +import DateUtils from '@libs/DateUtils'; +import * as DeviceCapabilities from '@libs/DeviceCapabilities'; +import Navigation from '@libs/Navigation/Navigation'; +import * as ReportUtils from '@libs/ReportUtils'; +import * as TripReservationUtils from '@libs/TripReservationUtils'; +import type {ContextMenuAnchor} from '@pages/home/report/ContextMenu/ReportActionContextMenu'; +import variables from '@styles/variables'; +import * as Expensicons from '@src/components/Icon/Expensicons'; +import CONST from '@src/CONST'; +import ONYXKEYS from '@src/ONYXKEYS'; +import ROUTES from '@src/ROUTES'; +import type {ReportAction} from '@src/types/onyx'; +import type {Reservation} from '@src/types/onyx/Transaction'; + +type TripRoomPreviewProps = { + /** All the data of the action */ + action: ReportAction; + + /** The associated chatReport */ + chatReportID: string; + + /** Extra styles to pass to View wrapper */ + containerStyles?: StyleProp; + + /** Popover context menu anchor, used for showing context menu */ + contextMenuAnchor?: ContextMenuAnchor; + + /** Callback for updating context menu active state, used for showing context menu */ + checkIfContextMenuActive?: () => void; + + /** Whether the corresponding report action item is hovered */ + isHovered?: boolean; +}; + +type ReservationViewProps = { + reservation: Reservation; +}; + +function ReservationView({reservation}: ReservationViewProps) { + const theme = useTheme(); + const styles = useThemeStyles(); + const StyleUtils = useStyleUtils(); + const {translate} = useLocalize(); + + 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 ? ( + + {reservation.start.shortName} + + {reservation.end.shortName} + + ) : ( + + {title} + + ); + + return ( + + ); +} + +const renderItem = ({item}: {item: Reservation}) => ; + +function TripRoomPreview({action, chatReportID, containerStyles, contextMenuAnchor, isHovered = false, checkIfContextMenuActive = () => {}}: TripRoomPreviewProps) { + const styles = useThemeStyles(); + const {translate} = useLocalize(); + 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 dateInfo = chatReport?.tripData ? DateUtils.getFormattedDateRange(new Date(chatReport.tripData.startDate), new Date(chatReport.tripData.endDate)) : ''; + const {totalDisplaySpend} = ReportUtils.getMoneyRequestSpendBreakdown(chatReport); + + const displayAmount = useMemo(() => { + if (totalDisplaySpend) { + return CurrencyUtils.convertToDisplayString(totalDisplaySpend, iouReport?.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 = action.message?.[0]?.text ?? ''; + const splits = actionMessage.split(' '); + + splits.forEach((split) => { + if (!/\d/.test(split)) { + return; + } + + displayAmountValue = split; + }); + + return displayAmountValue; + }, [action.message, iouReport?.currency, totalDisplaySpend]); + + return ( + + + DeviceCapabilities.canUseTouchScreen() && ControlSelection.block()} + onPressOut={() => ControlSelection.unblock()} + onLongPress={(event) => showContextMenuForReport(event, contextMenuAnchor, chatReportID, action, checkIfContextMenuActive)} + shouldUseHapticsOnLongPress + style={[styles.flexRow, styles.justifyContentBetween, styles.reportPreviewBox, styles.cursorDefault]} + role={CONST.ROLE.BUTTON} + accessibilityLabel={translate('iou.viewDetails')} + > + + + + + + + {translate('travel.trip')} • {dateInfo} + + + + + + + + {displayAmount} + + + + + {chatReport?.reportName} + + + + + +