-
Notifications
You must be signed in to change notification settings - Fork 4k
Add alternate route for map-based mileage expenses #96169
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Open
GCyganek
wants to merge
35
commits into
Expensify:main
Choose a base branch
from
software-mansion-labs:@GCyganek/alternate-routes
base: main
Could not load branches
Branch not found: {{ refName }}
Loading
Could not load tags
Nothing to show
Loading
Are you sure you want to change the base?
Some commits from the old base branch may be removed from the timeline,
and old review comments may become outdated.
Open
Changes from all commits
Commits
Show all changes
35 commits
Select commit
Hold shift + click to select a range
bd123ec
Init add alternate route for map-based mileage expenses
GCyganek 4bef03f
Fix lint and ts
GCyganek d02b07d
Code cleanup, adjust styles to Figma
GCyganek 0223d92
Fix directions layers order when switching between directions
GCyganek 72942c4
Revert changes in Direction.tsx
GCyganek 8319296
Add missing geojson types
GCyganek 8676bcc
Merge branch 'main' into @GCyganek/alternate-routes
GCyganek f1aa5fc
Use selectedRouteDistance prop, add tests
GCyganek 99ed0b9
Fix getSelectedRouteDistance
GCyganek 9ed553f
Fix transactionState
GCyganek ed1f20d
Clear selectedRouteKey when invalidating routes
GCyganek 1d602e2
Add web alternate routes components
GCyganek 1eed358
Fix expense updates, add tests
GCyganek 63d2059
Always send selectedRouteDistance
GCyganek 6a31934
Fix problems with map expense updates
GCyganek 2866450
Include legacy distance requests when resolving route choice
GCyganek d8f6942
Use transaction currency for route-change
GCyganek 4073305
Change distance unit for all distance symbols
GCyganek c6c8b65
Fix eslint in test
GCyganek 6a94d7f
Udpate route selection with the route distance fix
GCyganek 7646a49
Fix preserving manual overwrite for split expense
GCyganek ad0e44d
Fix showing discard modal
GCyganek a07a7eb
Fix retry params
GCyganek b7f31a8
read troutes from updatedTransaction
GCyganek 9466cf5
Recompute violations when selected route key changes
GCyganek 1191b8e
Fix case where re-fetched route slightly differs
GCyganek ebc582d
getHasUnsavedChanges guard
GCyganek 39450b8
Merge branch 'main' into @GCyganek/alternate-routes
GCyganek ffa6548
Merge branch 'main' into @GCyganek/alternate-routes
GCyganek bff3375
Fix getCurrencySymbol
GCyganek 76b40d0
Fix tests
GCyganek 949f623
Fix comment styles
GCyganek 19ed063
Merge branch 'main' into @GCyganek/alternate-routes
GCyganek 242822f
Use pointer cursor over routes
GCyganek 793a7a8
Pass selectedRouteDistance to categorize/share/submit paths
GCyganek File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Oops, something went wrong.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,51 @@ | ||
| import useThemeStyles from '@hooks/useThemeStyles'; | ||
|
|
||
| import Mapbox from '@rnmapbox/maps'; | ||
|
|
||
| import type {AlternateDirectionsProps} from './MapViewTypes'; | ||
|
|
||
| import {getAlternateDirectionsShape, SELECTED_BORDER_ID, SELECTED_FILL_ID, SOURCE_ID, UNSELECTED_BORDER_ID, UNSELECTED_FILL_ID} from './alternateDirectionsUtils'; | ||
|
|
||
| function AlternateDirections({directionCoordinates, alternateDirection, setIsAlternateDirectionSelected}: AlternateDirectionsProps) { | ||
| const styles = useThemeStyles(); | ||
| const directionShape = getAlternateDirectionsShape(directionCoordinates, alternateDirection); | ||
|
|
||
| return ( | ||
| <Mapbox.ShapeSource | ||
| id={SOURCE_ID} | ||
| shape={directionShape} | ||
| onPress={({features}) => { | ||
| const properties = features.at(0)?.properties; | ||
| if (typeof properties?.isAlternate !== 'boolean') { | ||
| return; | ||
| } | ||
| setIsAlternateDirectionSelected?.(properties.isAlternate); | ||
| }} | ||
| > | ||
| <Mapbox.LineLayer | ||
| id={UNSELECTED_FILL_ID} | ||
| filter={['==', ['get', 'isSelected'], false]} | ||
| style={styles.alternativeMapDirection} | ||
| /> | ||
| <Mapbox.LineLayer | ||
| id={UNSELECTED_BORDER_ID} | ||
| belowLayerID={UNSELECTED_FILL_ID} | ||
| filter={['==', ['get', 'isSelected'], false]} | ||
| style={styles.mapDirectionBorder} | ||
| /> | ||
| <Mapbox.LineLayer | ||
| id={SELECTED_FILL_ID} | ||
| filter={['==', ['get', 'isSelected'], true]} | ||
| style={styles.mapDirection} | ||
| /> | ||
| <Mapbox.LineLayer | ||
| id={SELECTED_BORDER_ID} | ||
| belowLayerID={SELECTED_FILL_ID} | ||
| filter={['==', ['get', 'isSelected'], true]} | ||
| style={styles.mapDirectionBorder} | ||
| /> | ||
| </Mapbox.ShapeSource> | ||
| ); | ||
| } | ||
|
|
||
| export default AlternateDirections; |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,72 @@ | ||
| import useThemeStyles from '@hooks/useThemeStyles'; | ||
|
|
||
| import type {FilterSpecification} from 'mapbox-gl'; | ||
|
|
||
| import React from 'react'; | ||
| import {Layer, Source} from 'react-map-gl/mapbox'; | ||
|
|
||
| import type {AlternateDirectionsProps} from './MapViewTypes'; | ||
|
|
||
| import {getAlternateDirectionsShape, SELECTED_BORDER_ID, SELECTED_FILL_ID, SOURCE_ID, UNSELECTED_BORDER_ID, UNSELECTED_FILL_ID} from './alternateDirectionsUtils'; | ||
|
|
||
| /** Layers that must be interactive on the map so that tapping a route selects it. */ | ||
| const ALTERNATE_DIRECTIONS_LAYER_IDS = [UNSELECTED_BORDER_ID, UNSELECTED_FILL_ID, SELECTED_BORDER_ID, SELECTED_FILL_ID]; | ||
|
|
||
| const UNSELECTED_FILTER: FilterSpecification = ['==', ['get', 'isSelected'], false]; | ||
| const SELECTED_FILTER: FilterSpecification = ['==', ['get', 'isSelected'], true]; | ||
|
|
||
| function AlternateDirections({directionCoordinates, alternateDirection}: AlternateDirectionsProps) { | ||
| const styles = useThemeStyles(); | ||
| const layerLayoutStyle: Record<string, string> = styles.mapDirectionLayer.layout; | ||
| const layerPaintStyle: Record<string, string | number> = styles.mapDirectionLayer.paint; | ||
| const alternativeLayerLayoutStyle: Record<string, string> = styles.alternativeMapDirectionLayer.layout; | ||
| const alternativeLayerPaintStyle: Record<string, string | number> = styles.alternativeMapDirectionLayer.paint; | ||
| const layerBorderLayoutStyle: Record<string, string> = styles.mapDirectionLayerBorder.layout; | ||
| const layerBorderPaintStyle: Record<string, string | number> = styles.mapDirectionLayerBorder.paint; | ||
|
|
||
| const directionShape = getAlternateDirectionsShape(directionCoordinates, alternateDirection); | ||
|
|
||
| return ( | ||
| <Source | ||
| id={SOURCE_ID} | ||
| type="geojson" | ||
| data={directionShape} | ||
| > | ||
| <Layer | ||
| id={UNSELECTED_BORDER_ID} | ||
| type="line" | ||
| source={SOURCE_ID} | ||
| filter={UNSELECTED_FILTER} | ||
| paint={layerBorderPaintStyle} | ||
| layout={layerBorderLayoutStyle} | ||
| /> | ||
| <Layer | ||
| id={UNSELECTED_FILL_ID} | ||
| type="line" | ||
| source={SOURCE_ID} | ||
| filter={UNSELECTED_FILTER} | ||
| paint={alternativeLayerPaintStyle} | ||
| layout={alternativeLayerLayoutStyle} | ||
| /> | ||
| <Layer | ||
| id={SELECTED_BORDER_ID} | ||
| type="line" | ||
| source={SOURCE_ID} | ||
| filter={SELECTED_FILTER} | ||
| paint={layerBorderPaintStyle} | ||
| layout={layerBorderLayoutStyle} | ||
| /> | ||
| <Layer | ||
| id={SELECTED_FILL_ID} | ||
| type="line" | ||
| source={SOURCE_ID} | ||
| filter={SELECTED_FILTER} | ||
| paint={layerPaintStyle} | ||
| layout={layerLayoutStyle} | ||
| /> | ||
| </Source> | ||
| ); | ||
| } | ||
|
|
||
| export default AlternateDirections; | ||
| export {ALTERNATE_DIRECTIONS_LAYER_IDS}; |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,54 @@ | ||
| import type {DirectionsProps} from './MapViewTypes'; | ||
|
|
||
| import AlternateDirections from './AlternateDirections'; | ||
| import Direction from './Direction'; | ||
| import DistanceSymbol from './DistanceSymbol'; | ||
| import useDistanceUnit from './useDistanceUnit'; | ||
| import utils from './utils'; | ||
|
|
||
| function Directions({directionCoordinates, alternateDirection, setIsAlternateDirectionSelected, distanceInMeters, unit, waypoints}: DirectionsProps) { | ||
| // Held here rather than in each DistanceSymbol so that toggling one label switches the unit for every label on the map. | ||
| const {distanceUnit, toggleDistanceUnit} = useDistanceUnit(unit); | ||
|
|
||
| if (!directionCoordinates) { | ||
| return null; | ||
| } | ||
|
|
||
| const alternateDirectionCoordinates = alternateDirection?.coordinates; | ||
| const hasAlternateDirection = !!alternateDirection && !!alternateDirectionCoordinates?.length; | ||
| const isAlternateDirectionSelected = !!alternateDirection?.isSelected; | ||
|
|
||
| return ( | ||
| <> | ||
| {hasAlternateDirection ? ( | ||
| <> | ||
| <AlternateDirections | ||
| directionCoordinates={directionCoordinates} | ||
| alternateDirection={alternateDirection} | ||
| setIsAlternateDirectionSelected={setIsAlternateDirectionSelected} | ||
| /> | ||
| <DistanceSymbol | ||
| distanceInMeters={alternateDirection.distanceInMeters} | ||
| distanceUnit={distanceUnit} | ||
| toggleDistanceUnit={toggleDistanceUnit} | ||
| directionCoordinates={utils.convertSegmentedRouteToSingleSegmentRoute(alternateDirectionCoordinates)} | ||
| waypoints={waypoints} | ||
| isSelected={isAlternateDirectionSelected} | ||
| /> | ||
| </> | ||
| ) : ( | ||
| <Direction coordinates={directionCoordinates} /> | ||
| )} | ||
| <DistanceSymbol | ||
| distanceInMeters={distanceInMeters} | ||
| distanceUnit={distanceUnit} | ||
| toggleDistanceUnit={toggleDistanceUnit} | ||
| directionCoordinates={utils.convertSegmentedRouteToSingleSegmentRoute(directionCoordinates)} | ||
| waypoints={waypoints} | ||
| isSelected={!isAlternateDirectionSelected} | ||
| /> | ||
| </> | ||
| ); | ||
| } | ||
|
|
||
| export default Directions; |
Oops, something went wrong.
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.