Skip to content

Commit

Permalink
feat(saved trip): Add route and basic structure for saving trips.
Browse files Browse the repository at this point in the history
  • Loading branch information
binh-dam-ibigroup committed Jun 2, 2020
1 parent effc7f9 commit 9e9b7ce
Show file tree
Hide file tree
Showing 9 changed files with 248 additions and 1 deletion.
8 changes: 8 additions & 0 deletions lib/components/app/responsive-webapp.js
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import { Route, Switch, withRouter } from 'react-router'

import PrintLayout from './print-layout'
import AfterSignInScreen from '../user/after-signin-screen'
import SaveTripScreen from '../user/save-trip-screen'
import UserAccountScreen from '../user/user-account-screen'
import withLoggedInUser from '../user/with-logged-in-user'
import { setMapCenter, setMapZoom } from '../../actions/config'
Expand Down Expand Up @@ -220,6 +221,13 @@ class RouterWrapper extends Component {
return withLoggedInUser(<UserAccountScreen {...props} />)
}}
/>
<Route
path={'/savetrip'}
component={(routerProps) => {
const props = this._combineProps(routerProps)
return withLoggedInUser(<SaveTripScreen wizard {...props} />)
}}
/>
<Route
path={'/signedin'}
component={AfterSignInScreen}
Expand Down
1 change: 1 addition & 0 deletions lib/components/user/new-account-wizard.js
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,7 @@ const NewAccountWizard = ({ onComplete, panes, userData }) => {

return (
<SequentialPaneDisplay
initialPaneId='terms'
onComplete={onComplete}
paneSequence={paneSequence}
/>
Expand Down
156 changes: 156 additions & 0 deletions lib/components/user/save-trip-screen.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,156 @@
import PropTypes from 'prop-types'
import React, { Component } from 'react'
import { connect } from 'react-redux'
import { withLoginRequired } from 'use-auth0-hooks'

import { addTrip, updateTrip } from '../../util/middleware'
import { routeTo } from '../../actions/ui'
import AppNav from '../app/app-nav'

import SavedTripEditor from './saved-trip-editor'
import SavedTripWizard from './saved-trip-wizard'
import TripBasicsPane from './trip-basics-pane'
import TripNotificationsPane from './trip-notifications-pane'
import TripSummaryPane from './trip-summary-pane'

/**
* This screen handles saving a trip from an OTP query for the logged-in user.
*/
class SaveTripScreen extends Component {
static propTypes = {
originalUrl: PropTypes.string
}

static defaultProps = {
originalUrl: '/'
}

constructor (props) {
super(props)

this.state = {
// New trip: deep clone active trip to make edits.
monitoredTrip: {}
}
}

_updateMonitoredTripState = newMonitoredTrip => {
const { monitoredTrip } = this.state
this.setState({
monitoredTrip: {
...monitoredTrip,
...newMonitoredTrip
}
})
}

_updateMonitoredTrip = async () => {
const { auth, loggedInUser, persistence, wizard } = this.props

if (persistence && persistence.otp_middleware) {
const { accessToken } = auth
const { id } = loggedInUser
const { monitoredTrip } = this.state

// TODO: Change state of Save button.

let result
if (wizard) {
result = await addTrip(persistence.otp_middleware, accessToken, monitoredTrip)
} else {
result = await updateTrip(persistence.otp_middleware, accessToken, monitoredTrip)
}

// TODO: improve this.
if (result.status === 'success') {
alert('Your preferences have been saved.')
} else {
alert(`An error was encountered:\n${JSON.stringify(result)}`)
}
}
}

_handleExit = () => {
const { originalUrl } = this.props
this.props.routeTo(originalUrl)
}

_handleExitAndSave = async () => {
await this._updateMonitoredTrip()
this._handleExit()
}

/**
* Hook monitoredTrip, onMonitoredTripChange on some panes upon rendering.
* This returns a new render function for the passed component
* that allows passing other props to it later if needed.
*/
_hookMonitoredTrip = Pane => props => {
const { monitoredTrip } = this.state
return (
<Pane
onMonitoredTripChange={this._updateMonitoredTripState}
monitoredTrip={monitoredTrip}
{...props}
/>
)
}

// Make an index of pane components, so we don't render all panes at once on every render.
// Hook some panes to the monitoredTrip and onMonitoredTripChange props.
_panes = {
basics: this._hookMonitoredTrip(TripBasicsPane),
notifications: this._hookMonitoredTrip(TripNotificationsPane),
summary: this._hookMonitoredTrip(TripSummaryPane)
}

// TODO: Update title bar during componentDidMount.

render () {
const { monitoredTrip, wizard } = this.props

let content
if (wizard) {
content = (
<SavedTripWizard
onComplete={this._handleExitAndSave}
panes={this._panes}
/>
)
} else {
content = (
<SavedTripEditor
onCancel={this._handleExit}
onComplete={this._handleExitAndSave}
monitoredTrip={monitoredTrip}
panes={this._panes}
/>
)
}

return (
<div className='otp'>
{/* TODO: Do mobile view. */}
<AppNav />
<form className='container'>
{content}
</form>
</div>
)
}
}

// connect to the redux store

const mapStateToProps = (state, ownProps) => {
return {
loggedInUser: state.otp.user.loggedInUser,
persistence: state.otp.config.persistence
}
}

const mapDispatchToProps = {
routeTo
}

export default withLoginRequired(connect(mapStateToProps, mapDispatchToProps)(SaveTripScreen))
29 changes: 29 additions & 0 deletions lib/components/user/saved-trip-editor.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
import React from 'react'

import StackedPaneDisplay from './stacked-pane-display'

/**
* This component handles the existing account display.
*/
const SavedTripEditor = ({ onCancel, onComplete, panes }) => {
const paneSequence = [
{
pane: panes.basics,
title: 'Trip information'
},
{
pane: panes.notifications,
title: 'Trip notifications'
}
]

return (
<StackedPaneDisplay
onCancel={onCancel}
onComplete={onComplete}
paneSequence={paneSequence}
/>
)
}

export default SavedTripEditor
37 changes: 37 additions & 0 deletions lib/components/user/saved-trip-wizard.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
import React from 'react'

import SequentialPaneDisplay from './sequential-pane-display'

/**
* This component is the new account wizard.
*/
const SavedTripWizard = ({ onComplete, panes }) => {
const paneSequence = {
basics: {
nextId: 'notifications',
pane: panes.basics,
title: 'Trip information'
},
notifications: {
nextId: 'summary',
pane: panes.notifications,
prevId: 'basics',
title: 'Trip notification preferences'
},
summary: {
pane: panes.summary,
prevId: 'notifications',
title: 'Trip summary'
}
}

return (
<SequentialPaneDisplay
initialPaneId='basics'
onComplete={onComplete}
paneSequence={paneSequence}
/>
)
}

export default SavedTripWizard
3 changes: 2 additions & 1 deletion lib/components/user/sequential-pane-display.js
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ const PaneContainer = styled.div`
*/
class SequentialPaneDisplay extends Component {
static propTypes = {
initialPaneId: PropTypes.string.isRequired,
onComplete: PropTypes.func.isRequired,
paneSequence: PropTypes.object.isRequired
}
Expand All @@ -23,7 +24,7 @@ class SequentialPaneDisplay extends Component {
super(props)

this.state = {
activePaneId: 'terms'
activePaneId: props.initialPaneId
}
}

Expand Down
5 changes: 5 additions & 0 deletions lib/components/user/trip-basics-pane.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
import React from 'react'

const TripBasicsPane = () => <div>Trip basics!</div>

export default TripBasicsPane
5 changes: 5 additions & 0 deletions lib/components/user/trip-notifications-pane.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
import React from 'react'

const TripNotificationsPane = () => <div>Trip notifications!</div>

export default TripNotificationsPane
5 changes: 5 additions & 0 deletions lib/components/user/trip-summary-pane.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
import React from 'react'

const TripSummaryPane = () => <div>Trip summary!</div>

export default TripSummaryPane

0 comments on commit 9e9b7ce

Please sign in to comment.