Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions src/languages/en.js
Original file line number Diff line number Diff line change
Expand Up @@ -1612,6 +1612,8 @@ export default {
},
distance: {
addStop: 'Add stop',
deleteWaypoint: 'Delete waypoint',
deleteWaypointConfirmation: 'Are you sure you want to delete this waypoint?',
address: 'Address',
waypointEditor: 'Waypoint Editor',
waypointDescription: {
Expand Down
2 changes: 2 additions & 0 deletions src/languages/es.js
Original file line number Diff line number Diff line change
Expand Up @@ -2099,6 +2099,8 @@ export default {
},
distance: {
addStop: 'Agregar parada',
deleteWaypoint: 'Eliminar punto de ruta',
deleteWaypointConfirmation: '¿Estás seguro de que quieres eliminar este punto de ruta?',
address: 'Dirección',
waypointEditor: 'Editor de puntos de ruta',
waypointDescription: {
Expand Down
105 changes: 64 additions & 41 deletions src/pages/iou/WaypointEditor.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import React, {useRef} from 'react';
import _ from 'underscore';
import React, {useRef, useState} from 'react';
import lodashGet from 'lodash/get';
import {View} from 'react-native';
import PropTypes from 'prop-types';
Expand All @@ -11,14 +11,15 @@ import Navigation from '../../libs/Navigation/Navigation';
import ONYXKEYS from '../../ONYXKEYS';
import Form from '../../components/Form';
import styles from '../../styles/styles';
import compose from '../../libs/compose';
import useWindowDimensions from '../../hooks/useWindowDimensions';
import useLocalize from '../../hooks/useLocalize';
import useNetwork from '../../hooks/useNetwork';
import CONST from '../../CONST';
import withLocalize, {withLocalizePropTypes} from '../../components/withLocalize';
import * as Expensicons from '../../components/Icon/Expensicons';
import ConfirmModal from '../../components/ConfirmModal';
import * as Transaction from '../../libs/actions/Transaction';
import * as ValidationUtils from '../../libs/ValidationUtils';
import ROUTES from '../../ROUTES';
import {withNetwork} from '../../components/OnyxProvider';
import networkPropTypes from '../../components/networkPropTypes';
import transactionPropTypes from '../../components/transactionPropTypes';

const propTypes = {
Expand All @@ -38,11 +39,6 @@ const propTypes = {

/** The optimistic transaction for this request */
transaction: transactionPropTypes,

/** Information about the network */
network: networkPropTypes.isRequired,

...withLocalizePropTypes,
};

const defaultProps = {
Expand All @@ -54,21 +50,28 @@ const defaultProps = {
transaction: {},
};

function WaypointEditor({transactionID, route: {params: {iouType = '', waypointIndex = ''} = {}} = {}, network, translate, transaction, recentWaypoints}) {
function WaypointEditor({transactionID, route: {params: {iouType = '', waypointIndex = ''} = {}} = {}, transaction, recentWaypoints}) {
const {windowWidth} = useWindowDimensions();
const {translate} = useLocalize();
const {isOffline} = useNetwork();
const textInput = useRef(null);
const [isDeleteStopModalOpen, setIsDeleteStopModalOpen] = useState(false);
const currentWaypoint = lodashGet(transaction, `comment.waypoints.waypoint${waypointIndex}`, {});
const waypointAddress = lodashGet(currentWaypoint, 'address', '');
const totalWaypoints = _.size(lodashGet(transaction, 'comment.waypoints', {}));
// Hide the menu when there is only start and finish waypoint
const shouldShowThreeDotsButton = totalWaypoints > 2;

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

This caused a regression in #35644 , The delete option should not be displayed for empty waypoints.


const validate = (values) => {
const errors = {};
const waypointValue = values[`waypoint${waypointIndex}`] || '';
if (network.isOffline && waypointValue !== '' && !ValidationUtils.isValidAddress(waypointValue)) {
if (isOffline && waypointValue !== '' && !ValidationUtils.isValidAddress(waypointValue)) {
errors[`waypoint${waypointIndex}`] = 'bankAccount.error.address';
}

// If the user is online and they are trying to save a value without using the autocomplete, show an error message instructing them to use a selected address instead.
// That enables us to save the address with coordinates when it is selected
if (!network.isOffline && waypointValue !== '') {
if (!isOffline && waypointValue !== '') {
errors[`waypoint${waypointIndex}`] = 'distance.errors.selectSuggestedAddress';
}

Expand All @@ -85,7 +88,7 @@ function WaypointEditor({transactionID, route: {params: {iouType = '', waypointI

// While the user is offline, the auto-complete address search will not work
// Therefore, we're going to save the waypoint as just the address, and the lat/long will be filled in on the backend
if (network.isOffline && waypointValue) {
if (isOffline && waypointValue) {
const waypoint = {
address: waypointValue,
};
Expand All @@ -97,6 +100,12 @@ function WaypointEditor({transactionID, route: {params: {iouType = '', waypointI
Navigation.goBack(ROUTES.getMoneyRequestDistanceTabRoute(iouType));
};

const deleteStopAndHideModal = () => {
Transaction.removeWaypoint(transactionID, waypointIndex);
setIsDeleteStopModalOpen(false);
Navigation.goBack(ROUTES.getMoneyRequestDistanceTabRoute(iouType));
};

const selectWaypoint = (values) => {
const waypoint = {
lat: values.lat,
Expand All @@ -120,6 +129,25 @@ function WaypointEditor({transactionID, route: {params: {iouType = '', waypointI
onBackButtonPress={() => {
Navigation.goBack(ROUTES.getMoneyRequestDistanceTabRoute(iouType));
}}
shouldShowThreeDotsButton={shouldShowThreeDotsButton}
threeDotsAnchorPosition={styles.threeDotsPopoverOffset(windowWidth)}
Comment thread
hayata-suenaga marked this conversation as resolved.
threeDotsMenuItems={[
{
icon: Expensicons.Trashcan,
text: translate('distance.deleteWaypoint'),
onSelected: () => setIsDeleteStopModalOpen(true),
},
]}
/>
<ConfirmModal
title={translate('distance.deleteWaypoint')}
isVisible={isDeleteStopModalOpen}
onConfirm={deleteStopAndHideModal}
onCancel={() => setIsDeleteStopModalOpen(false)}
prompt={translate('distance.deleteWaypointConfirmation')}
confirmText={translate('common.delete')}
cancelText={translate('common.cancel')}
danger
/>
<Form
style={[styles.flexGrow1, styles.mh5]}
Expand All @@ -135,7 +163,7 @@ function WaypointEditor({transactionID, route: {params: {iouType = '', waypointI
<AddressSearch
inputID={`waypoint${waypointIndex}`}
ref={(e) => (textInput.current = e)}
hint={!network.isOffline ? translate('distance.errors.selectSuggestedAddress') : ''}
hint={!isOffline ? translate('distance.errors.selectSuggestedAddress') : ''}
containerStyles={[styles.mt4]}
label={translate('distance.address')}
defaultValue={waypointAddress}
Expand Down Expand Up @@ -163,30 +191,25 @@ function WaypointEditor({transactionID, route: {params: {iouType = '', waypointI
WaypointEditor.displayName = 'WaypointEditor';
WaypointEditor.propTypes = propTypes;
WaypointEditor.defaultProps = defaultProps;
export default compose(
withLocalize,
withNetwork(),
withOnyx({
transaction: {
key: (props) => `${ONYXKEYS.COLLECTION.TRANSACTION}${props.transactionID}`,
selector: (transaction) => (transaction ? {transactionID: transaction.transactionID, comment: {waypoints: lodashGet(transaction, 'comment.waypoints')}} : null),
},

recentWaypoints: {
key: ONYXKEYS.NVP_RECENT_WAYPOINTS,

// Only grab the most recent 5 waypoints because that's all that is shown in the UI. This also puts them into the format of data
// that the google autocomplete component expects for it's "predefined places" feature.
selector: (waypoints) =>
_.map(waypoints ? waypoints.slice(0, 5) : [], (waypoint) => ({
description: waypoint.address,
geometry: {
location: {
lat: waypoint.lat,
lng: waypoint.lng,
},
export default withOnyx({
transaction: {
key: ({transactionID}) => `${ONYXKEYS.COLLECTION.TRANSACTION}${transactionID}`,
selector: (transaction) => (transaction ? {transactionID: transaction.transactionID, comment: {waypoints: lodashGet(transaction, 'comment.waypoints')}} : null),
},
recentWaypoints: {
key: ONYXKEYS.NVP_RECENT_WAYPOINTS,

// Only grab the most recent 5 waypoints because that's all that is shown in the UI. This also puts them into the format of data
// that the google autocomplete component expects for it's "predefined places" feature.
selector: (waypoints) =>
_.map(waypoints ? waypoints.slice(0, 5) : [], (waypoint) => ({
description: waypoint.address,
geometry: {
location: {
lat: waypoint.lat,
lng: waypoint.lng,
},
})),
},
}),
)(WaypointEditor);
},
})),
},
})(WaypointEditor);