forked from Expensify/App
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathConfirmedRoute.tsx
136 lines (118 loc) · 5.27 KB
/
ConfirmedRoute.tsx
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
import React, {useCallback, useEffect} from 'react';
import type {ReactNode} from 'react';
import {withOnyx} from 'react-native-onyx';
import type {OnyxEntry} from 'react-native-onyx';
import useNetwork from '@hooks/useNetwork';
import useStyleUtils from '@hooks/useStyleUtils';
import useTheme from '@hooks/useTheme';
import useThemeStyles from '@hooks/useThemeStyles';
import * as TransactionUtils from '@libs/TransactionUtils';
import * as MapboxToken from '@userActions/MapboxToken';
import CONST from '@src/CONST';
import ONYXKEYS from '@src/ONYXKEYS';
import type {MapboxAccessToken, Transaction} from '@src/types/onyx';
import type {WaypointCollection} from '@src/types/onyx/Transaction';
import type IconAsset from '@src/types/utils/IconAsset';
import DistanceMapView from './DistanceMapView';
import * as Expensicons from './Icon/Expensicons';
import ImageSVG from './ImageSVG';
import type {WayPoint} from './MapView/MapViewTypes';
import PendingMapView from './MapView/PendingMapView';
type ConfirmedRoutePropsOnyxProps = {
/** Data about Mapbox token for calling Mapbox API */
mapboxAccessToken: OnyxEntry<MapboxAccessToken>;
};
type ConfirmedRouteProps = ConfirmedRoutePropsOnyxProps & {
/** Transaction that stores the distance expense data */
transaction: OnyxEntry<Transaction>;
/** Whether the size of the route pending icon is smaller. */
isSmallerIcon?: boolean;
/** Whether it should have border radius */
shouldHaveBorderRadius?: boolean;
/** Whether it should display the Mapbox map only when the route/coordinates exist otherwise
* it will display pending map icon */
shouldDisplayMapOnlyIfCoordinatesExist?: boolean;
/** Whether the map is interactable or not */
interactive?: boolean;
};
function ConfirmedRoute({mapboxAccessToken, transaction, isSmallerIcon, shouldHaveBorderRadius = true, shouldDisplayMapOnlyIfCoordinatesExist = false, interactive}: ConfirmedRouteProps) {
const {isOffline} = useNetwork();
const {route0: route} = transaction?.routes ?? {};
const waypoints = transaction?.comment?.waypoints ?? {};
const coordinates = route?.geometry?.coordinates ?? [];
const theme = useTheme();
const styles = useThemeStyles();
const StyleUtils = useStyleUtils();
const getMarkerComponent = useCallback(
(icon: IconAsset): ReactNode => (
<ImageSVG
src={icon}
width={CONST.MAP_MARKER_SIZE}
height={CONST.MAP_MARKER_SIZE}
fill={theme.icon}
/>
),
[theme],
);
const getWaypointMarkers = useCallback(
(waypointsData: WaypointCollection): WayPoint[] => {
const numberOfWaypoints = Object.keys(waypointsData).length;
const lastWaypointIndex = numberOfWaypoints - 1;
return Object.entries(waypointsData)
.map(([key, waypoint]) => {
if (!waypoint?.lat || !waypoint?.lng) {
return;
}
const index = TransactionUtils.getWaypointIndex(key);
let MarkerComponent: IconAsset;
if (index === 0) {
MarkerComponent = Expensicons.DotIndicatorUnfilled;
} else if (index === lastWaypointIndex) {
MarkerComponent = Expensicons.Location;
} else {
MarkerComponent = Expensicons.DotIndicator;
}
return {
id: `${waypoint.lng},${waypoint.lat},${index}`,
coordinate: [waypoint.lng, waypoint.lat] as const,
markerComponent: (): ReactNode => getMarkerComponent(MarkerComponent),
};
})
.filter((waypoint): waypoint is WayPoint => !!waypoint);
},
[getMarkerComponent],
);
const waypointMarkers = getWaypointMarkers(waypoints);
useEffect(() => {
MapboxToken.init();
return MapboxToken.stop;
}, []);
const shouldDisplayMap = !shouldDisplayMapOnlyIfCoordinatesExist || (shouldDisplayMapOnlyIfCoordinatesExist && !!coordinates.length);
return !isOffline && Boolean(mapboxAccessToken?.token) && shouldDisplayMap ? (
<DistanceMapView
interactive={interactive}
accessToken={mapboxAccessToken?.token ?? ''}
mapPadding={CONST.MAP_PADDING}
pitchEnabled={false}
initialState={{
zoom: CONST.MAPBOX.DEFAULT_ZOOM,
location: waypointMarkers?.[0]?.coordinate ?? (CONST.MAPBOX.DEFAULT_COORDINATE as [number, number]),
}}
directionCoordinates={coordinates as Array<[number, number]>}
style={[styles.mapView, shouldHaveBorderRadius && styles.br4]}
waypoints={waypointMarkers}
styleURL={CONST.MAPBOX.STYLE_URL}
/>
) : (
<PendingMapView
isSmallerIcon={isSmallerIcon}
style={!shouldHaveBorderRadius && StyleUtils.getBorderRadiusStyle(0)}
/>
);
}
export default withOnyx<ConfirmedRouteProps, ConfirmedRoutePropsOnyxProps>({
mapboxAccessToken: {
key: ONYXKEYS.MAPBOX_ACCESS_TOKEN,
},
})(ConfirmedRoute);
ConfirmedRoute.displayName = 'ConfirmedRoute';