-
Notifications
You must be signed in to change notification settings - Fork 3k
/
Copy pathDistanceRequest.js
155 lines (138 loc) · 6.29 KB
/
DistanceRequest.js
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
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
import React, {useEffect, useState} from 'react';
import {ScrollView, View} from 'react-native';
import lodashGet from 'lodash/get';
import _ from 'underscore';
import PropTypes from 'prop-types';
import {withOnyx} from 'react-native-onyx';
import ONYXKEYS from '../ONYXKEYS';
import * as Transaction from '../libs/actions/Transaction';
import MenuItemWithTopDescription from './MenuItemWithTopDescription';
import withLocalize, {withLocalizePropTypes} from './withLocalize';
import compose from '../libs/compose';
import * as Expensicons from './Icon/Expensicons';
import theme from '../styles/themes/default';
import Button from './Button';
import styles from '../styles/styles';
import variables from '../styles/variables';
import LinearGradient from './LinearGradient';
const MAX_WAYPOINTS = 25;
const MAX_WAYPOINTS_TO_DISPLAY = 4;
const propTypes = {
/** The transactionID of this request */
transactionID: PropTypes.string,
/** The optimistic transaction for this request */
transaction: PropTypes.shape({
/** The transactionID of this request */
transactionID: PropTypes.string,
/** The comment object on the transaction */
comment: PropTypes.shape({
/** The waypoints defining the distance request */
waypoints: PropTypes.shape({
/** The latitude of the waypoint */
lat: PropTypes.number,
/** The longitude of the waypoint */
lng: PropTypes.number,
/** The address of the waypoint */
address: PropTypes.string,
}),
}),
}),
...withLocalizePropTypes,
};
const defaultProps = {
transactionID: '',
transaction: {},
};
function DistanceRequest({transactionID, transaction, translate}) {
const [shouldShowGradient, setShouldShowGradient] = useState(false);
const [scrollContainerHeight, setScrollContainerHeight] = useState(0);
const [scrollContentHeight, setScrollContentHeight] = useState(0);
const waypoints = lodashGet(transaction, 'comment.waypoints', {});
const numberOfWaypoints = _.size(waypoints);
const lastWaypointIndex = numberOfWaypoints - 1;
// Show up to the max number of waypoints plus 1/2 of one to hint at scrolling
const halfMenuItemHeight = Math.floor(variables.baseMenuItemHeight / 2);
const scrollContainerMaxHeight = variables.baseMenuItemHeight * MAX_WAYPOINTS_TO_DISPLAY + halfMenuItemHeight;
useEffect(() => {
if (!transaction.transactionID || !_.isEmpty(waypoints)) {
return;
}
// Create the initial start and stop waypoints
Transaction.createInitialWaypoints(transaction.transactionID);
}, [transaction.transactionID, waypoints]);
const updateGradientVisibility = (event = {}) => {
// If a waypoint extends past the bottom of the visible area show the gradient, else hide it.
const visibleAreaEnd = lodashGet(event, 'nativeEvent.contentOffset.y', 0) + scrollContainerHeight;
setShouldShowGradient(visibleAreaEnd < scrollContentHeight);
};
useEffect(updateGradientVisibility, [scrollContainerHeight, scrollContentHeight]);
return (
<>
<View
style={{maxHeight: scrollContainerMaxHeight}}
onLayout={(event = {}) => setScrollContainerHeight(lodashGet(event, 'nativeEvent.layout.height', 0))}
>
<ScrollView
onContentSizeChange={(width, height) => setScrollContentHeight(height)}
onScroll={updateGradientVisibility}
scrollEventThrottle={16}
>
{_.map(waypoints, (waypoint, key) => {
// key is of the form waypoint0, waypoint1, ...
const index = Number(key.replace('waypoint', ''));
let descriptionKey = 'distance.waypointDescription.';
let waypointIcon;
if (index === 0) {
descriptionKey += 'start';
waypointIcon = Expensicons.DotIndicatorUnfilled;
} else if (index === lastWaypointIndex) {
descriptionKey += 'finish';
waypointIcon = Expensicons.Location;
} else {
descriptionKey += 'stop';
waypointIcon = Expensicons.DotIndicator;
}
return (
<MenuItemWithTopDescription
description={translate(descriptionKey)}
icon={Expensicons.DragHandles}
secondaryIcon={waypointIcon}
secondaryIconFill={theme.icon}
shouldShowRightIcon
key={key}
/>
);
})}
</ScrollView>
{shouldShowGradient && (
<LinearGradient
style={[styles.pAbsolute, styles.b0, styles.l0, styles.r0, {height: halfMenuItemHeight}]}
colors={[theme.transparent, theme.modalBackground]}
/>
)}
</View>
<View style={[styles.flexRow, styles.justifyContentCenter, styles.pt1]}>
<Button
small
icon={Expensicons.Plus}
onPress={() => Transaction.addStop(transactionID, lastWaypointIndex + 1)}
text={translate('distance.addStop')}
isDisabled={numberOfWaypoints === MAX_WAYPOINTS}
innerStyles={[styles.ph10]}
/>
</View>
</>
);
}
DistanceRequest.displayName = 'DistanceRequest';
DistanceRequest.propTypes = propTypes;
DistanceRequest.defaultProps = defaultProps;
export default compose(
withLocalize,
withOnyx({
transaction: {
key: (props) => `${ONYXKEYS.COLLECTION.TRANSACTION}${props.transactionID}`,
selector: (transaction) => (transaction ? {transactionID: transaction.transactionID, comment: {waypoints: lodashGet(transaction, 'comment.waypoints')}} : null),
},
}),
)(DistanceRequest);