Skip to content

Commit

Permalink
🚉 - Edit the current route from the routes list (#283)
Browse files Browse the repository at this point in the history
Closes #248 

Change origin and destination stations, and swap the direction directly
from the route list:

<img width="368" alt="image"
src="https://github.com/better-rail/app/assets/12946462/f4c5f1cf-310f-4502-b182-7d675cfe6b5c">

---------

Co-authored-by: Guy Tepper <[email protected]>
  • Loading branch information
planecore and guytepper authored Aug 5, 2023
1 parent fad9bd0 commit db398b4
Show file tree
Hide file tree
Showing 4 changed files with 80 additions and 12 deletions.
87 changes: 77 additions & 10 deletions app/components/route-details-header/route-details-header.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
/* eslint-disable react/display-name */
import React, { useMemo, useLayoutEffect } from "react"
import { Image, ImageBackground, View, ViewStyle, TextStyle, ImageStyle, Alert, Linking } from "react-native"
import React, { useMemo, useLayoutEffect, useRef, useEffect } from "react"
import { Image, ImageBackground, View, ViewStyle, TextStyle, ImageStyle, Alert, Linking, Animated } from "react-native"
import TouchableScale from "react-native-touchable-scale"
import analytics from "@react-native-firebase/analytics"
import { useNavigation } from "@react-navigation/native"
import { observer } from "mobx-react-lite"
Expand All @@ -15,6 +16,9 @@ import * as Burnt from "burnt"
import * as AddCalendarEvent from "react-native-add-calendar-event"
import { CalendarIcon } from "../calendar-icon/calendar-icon"
import { RouteItem } from "../../services/api"
import { TouchableOpacity } from "react-native-gesture-handler"

const AnimatedTouchable = Animated.createAnimatedComponent(TouchableScale)

const arrowIcon = require("../../../assets/arrow-left.png")

Expand Down Expand Up @@ -91,16 +95,19 @@ export interface RouteDetailsHeaderProps {
/**
* The screen name we're displaying the header inside
*/
screenName?: "routeDetails" | "activeRide"
screenName?: "routeList" | "routeDetails" | "activeRide"
style?: ViewStyle
eventConfig?: AddCalendarEvent.CreateOptions
}

export const RouteDetailsHeader = observer(function RouteDetailsHeader(props: RouteDetailsHeaderProps) {
const { routeItem, originId, destinationId, screenName, style } = props
const { favoriteRoutes } = useStores()
const { favoriteRoutes, routePlan } = useStores()
const navigation = useNavigation()

const routeEditDisabled = props.screenName !== "routeList"
const stationCardScale = useRef(new Animated.Value(1)).current

const addToCalendar = () => {
analytics().logEvent("add_route_to_calendar")
const eventConfig = createEventConfig(routeItem)
Expand All @@ -125,6 +132,48 @@ export const RouteDetailsHeader = observer(function RouteDetailsHeader(props: Ro

const routeId = `${originId}${destinationId}`

const swapDirection = () => {
scaleStationCards()
HapticFeedback.trigger("impactMedium")

// Delay the actual switch so it'll be synced with the animation
setTimeout(() => {
routePlan.switchDirection()
}, 50)
}

const changeOriginStation = () => {
navigation.navigate("selectStation", { selectionType: "origin" })
}

const changeDestinationStation = () => {
navigation.navigate("selectStation", { selectionType: "destination" })
}

useEffect(() => {
if (routePlan.origin.id !== routePlan.destination.id) {
navigation.setParams({
originId: routePlan.origin.id,
destinationId: routePlan.destination.id,
} as any)
}
}, [routePlan.origin.id, routePlan.destination.id])

const scaleStationCards = () => {
Animated.sequence([
Animated.timing(stationCardScale, {
toValue: 0.94,
duration: 175,
useNativeDriver: true,
}),
Animated.timing(stationCardScale, {
toValue: 1,
duration: 175,
useNativeDriver: true,
}),
]).start()
}

const isFavorite: boolean = useMemo(
() => !!favoriteRoutes.routes.find((favorite) => favorite.id === routeId),
[favoriteRoutes.routes.length],
Expand Down Expand Up @@ -171,19 +220,37 @@ export const RouteDetailsHeader = observer(function RouteDetailsHeader(props: Ro

<View style={{ top: -20, marginBottom: -30, zIndex: 5 }}>
<View style={[ROUTE_DETAILS_WRAPPER, style]}>
<View style={[ROUTE_DETAILS_STATION, { marginEnd: spacing[5] }]}>
<AnimatedTouchable
friction={9}
activeScale={0.95}
disabled={routeEditDisabled}
onPress={changeOriginStation}
style={[ROUTE_DETAILS_STATION, { marginEnd: spacing[5] }, { transform: [{ scale: stationCardScale }] }]}
>
<Text style={ROUTE_DETAILS_STATION_TEXT} maxFontSizeMultiplier={1.1}>
{originName}
</Text>
</View>
<View style={ROUTE_INFO_CIRCLE}>
</AnimatedTouchable>
<TouchableOpacity
activeOpacity={0.8}
hitSlop={spacing[2]}
onPress={swapDirection}
style={ROUTE_INFO_CIRCLE}
disabled={routeEditDisabled}
>
<Image source={arrowIcon} style={ARROW_ICON} />
</View>
<View style={ROUTE_DETAILS_STATION}>
</TouchableOpacity>
<AnimatedTouchable
friction={9}
activeScale={0.95}
disabled={routeEditDisabled}
style={[ROUTE_DETAILS_STATION, { transform: [{ scale: stationCardScale }] }]}
onPress={changeDestinationStation}
>
<Text style={ROUTE_DETAILS_STATION_TEXT} maxFontSizeMultiplier={1.1}>
{destinationName}
</Text>
</View>
</AnimatedTouchable>
</View>
</View>
</View>
Expand Down
2 changes: 1 addition & 1 deletion app/navigators/main-navigator.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -60,7 +60,7 @@ export function MainNavigator() {
<Stack.Screen
name="selectStation"
component={SelectStationScreen}
options={{ headerShown: false, ...TransitionPresets.ModalSlideFromBottomIOS }}
options={{ headerShown: false, ...TransitionPresets.ModalSlideFromBottomIOS, presentation: "modal" }}
/>
<Stack.Screen
name="routeList"
Expand Down
1 change: 1 addition & 0 deletions app/screens/route-list/route-list-screen.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -124,6 +124,7 @@ export const RouteListScreen = observer(function RouteListScreen({ navigation, r
>
<SharedElement id="route-header">
<RouteDetailsHeader
screenName="routeList"
originId={route.params.originId}
destinationId={route.params.destinationId}
style={{ paddingHorizontal: spacing[3], marginBottom: spacing[3] }}
Expand Down
2 changes: 1 addition & 1 deletion app/screens/select-station/select-station-screen.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -88,7 +88,7 @@ export const SelectStationScreen = observer(function SelectStationScreen({ navig
style={[SEARCH_BAR_WRAPPER, { paddingTop: insets.top > 20 ? insets.top : Platform.select({ ios: 27.5, android: 5 }) }]}
>
<SearchInput searchTerm={searchTerm} setSearchTerm={setSearchTerm} autoFocus={favoriteRoutes.routes.length < 2} />
<Pressable onPress={() => navigation.navigate("planner")}>
<Pressable onPress={navigation.goBack}>
<Text style={CANCEL_LINK} tx="common.cancel" />
</Pressable>
</View>
Expand Down

0 comments on commit db398b4

Please sign in to comment.