Skip to content

Commit

Permalink
refactor(actions/user): Move itinerary check to actions/reducer.
Browse files Browse the repository at this point in the history
  • Loading branch information
binh-dam-ibigroup committed Oct 30, 2020
1 parent 1cbc87a commit ea97ce6
Show file tree
Hide file tree
Showing 3 changed files with 82 additions and 51 deletions.
50 changes: 33 additions & 17 deletions lib/actions/user.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,14 +5,17 @@ import { secureFetch } from '../util/middleware'
import { isNewUser } from '../util/user'

// Middleware API paths.
const API_MONITORTRIP_PATH = '/api/secure/monitoredtrip'
const API_ITINERARY_CHECK_PATH = '/api/secure/itinerarycheck'
const API_MONITORED_TRIP_PATH = '/api/secure/monitoredtrip'
const API_OTPUSER_PATH = '/api/secure/user'
const API_OTPUSER_VERIFYSMS_PATH = '/verify_sms'
const API_OTPUSER_VERIFY_SMS_PATH = '/verify_sms'

const setCurrentUser = createAction('SET_CURRENT_USER')
const setCurrentUserMonitoredTrips = createAction('SET_CURRENT_USER_MONITORED_TRIPS')
const setLastPhoneSmsRequest = createAction('SET_LAST_PHONE_SMS_REQUEST')
export const setPathBeforeSignIn = createAction('SET_PATH_BEFORE_SIGNIN')
export const clearItineraryAvailability = createAction('CLEAR_ITINERARY_AVAILABILITY')
const setItineraryAvailability = createAction('SET_ITINERARY_AVAILABILITY')

function createNewUser (auth0User) {
return {
Expand Down Expand Up @@ -160,7 +163,7 @@ export function createOrUpdateUser (userData, silentOnSuccess = false) {
export function fetchUserMonitoredTrips () {
return async function (dispatch, getState) {
const { accessToken, apiBaseUrl, apiKey } = getMiddlewareVariables(getState())
const requestUrl = `${apiBaseUrl}${API_MONITORTRIP_PATH}`
const requestUrl = `${apiBaseUrl}${API_MONITORED_TRIP_PATH}`

const { data: trips, status } = await secureFetch(requestUrl, accessToken, apiKey, 'GET')
if (status === 'success') {
Expand All @@ -182,10 +185,10 @@ export function createOrUpdateUserMonitoredTrip (tripData, isNew, silentOnSucces

// Determine URL and method to use.
if (isNew) {
requestUrl = `${apiBaseUrl}${API_MONITORTRIP_PATH}`
requestUrl = `${apiBaseUrl}${API_MONITORED_TRIP_PATH}`
method = 'POST'
} else {
requestUrl = `${apiBaseUrl}${API_MONITORTRIP_PATH}/${id}`
requestUrl = `${apiBaseUrl}${API_MONITORED_TRIP_PATH}/${id}`
method = 'PUT'
}

Expand Down Expand Up @@ -217,7 +220,7 @@ export function createOrUpdateUserMonitoredTrip (tripData, isNew, silentOnSucces
export function deleteUserMonitoredTrip (tripId) {
return async function (dispatch, getState) {
const { accessToken, apiBaseUrl, apiKey } = getMiddlewareVariables(getState())
const requestUrl = `${apiBaseUrl}${API_MONITORTRIP_PATH}/${tripId}`
const requestUrl = `${apiBaseUrl}${API_MONITORED_TRIP_PATH}/${tripId}`

const { message, status } = await secureFetch(requestUrl, accessToken, apiKey, 'DELETE')
if (status === 'success') {
Expand All @@ -243,7 +246,7 @@ export function requestPhoneVerificationSms (newPhoneNumber) {
// TODO: Should throttling be handled in the middleware?
if (number !== newPhoneNumber || (now - timestamp) >= 60000) {
const { accessToken, apiBaseUrl, apiKey, loggedInUser } = getMiddlewareVariables(state)
const requestUrl = `${apiBaseUrl}${API_OTPUSER_PATH}/${loggedInUser.id}${API_OTPUSER_VERIFYSMS_PATH}/${encodeURIComponent(newPhoneNumber)}`
const requestUrl = `${apiBaseUrl}${API_OTPUSER_PATH}/${loggedInUser.id}${API_OTPUSER_VERIFY_SMS_PATH}/${encodeURIComponent(newPhoneNumber)}`

const { message, status } = await secureFetch(requestUrl, accessToken, apiKey, 'GET')

Expand Down Expand Up @@ -273,7 +276,7 @@ export function requestPhoneVerificationSms (newPhoneNumber) {
export function verifyPhoneNumber (code) {
return async function (dispatch, getState) {
const { accessToken, apiBaseUrl, apiKey, loggedInUser } = getMiddlewareVariables(getState())
const requestUrl = `${apiBaseUrl}${API_OTPUSER_PATH}/${loggedInUser.id}${API_OTPUSER_VERIFYSMS_PATH}/${code}`
const requestUrl = `${apiBaseUrl}${API_OTPUSER_PATH}/${loggedInUser.id}${API_OTPUSER_VERIFY_SMS_PATH}/${code}`

const { data, status } = await secureFetch(requestUrl, accessToken, apiKey, 'POST')

Expand All @@ -293,13 +296,26 @@ export function verifyPhoneNumber (code) {
}
}
}
/*
export async function checkItinerary (middlewareConfig, token, monitoredTrip) {
const { apiBaseUrl, apiKey } = middlewareConfig
const requestUrl = `${apiBaseUrl}${API_ITINERARYCHECK_PATH}`
return secureFetch(requestUrl, token, apiKey, 'POST', {
body: JSON.stringify(monitoredTrip)
})

/**
* Check itinerary availability (existence) for the given monitored trip.
*/
export function checkItineraryAvailability (trip) {
return async function (dispatch, getState) {
const { accessToken, apiBaseUrl, apiKey } = getMiddlewareVariables(getState())
const requestUrl = `${apiBaseUrl}${API_ITINERARY_CHECK_PATH}`

// Empty state before performing the checks.
dispatch(clearItineraryAvailability())

const { data, status } = await secureFetch(requestUrl, accessToken, apiKey, 'POST', {
body: JSON.stringify(trip)
})

if (status === 'success' && data) {
dispatch(setItineraryAvailability(data))
} else {
alert('Error checking the availability of your selected trip.')
}
}
}
*/
70 changes: 36 additions & 34 deletions lib/components/user/trip-basics-pane.js
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ import {
import { connect } from 'react-redux'
import styled from 'styled-components'

import { checkItinerary } from '../../util/middleware'
import * as userActions from '../../actions/user'
import { ALL_DAYS } from '../../util/monitored-trip'
import TripSummary from './trip-summary'

Expand Down Expand Up @@ -46,45 +46,47 @@ const allDays = [
{ name: 'sunday', text: 'Sun.', fullText: 'Sundays' }
]

/**
* @returns true if there is a trip matching for the specified availability/existence check.
*/
function isDayAvailable (dayAvailability) {
return dayAvailability && dayAvailability.isValid
}

/**
* This component shows summary information for a trip
* and lets the user edit the trip name and day.
*/
class TripBasicsPane extends Component {
constructor () {
super()

this.state = {}
componentDidMount () {
// Check itinerary availability (existence) for all days.
const { checkItineraryAvailability, values: monitoredTrip } = this.props
checkItineraryAvailability(monitoredTrip)
}

async componentDidMount () {
// Check itinerary existence for all days.
const { accessToken, config, isCreating, setFieldValue, values } = this.props

const itineraryCheckResult = await checkItinerary(
config.persistence.otp_middleware,
accessToken,
values
)
componentDidUpdate (prevProps) {
const { isCreating, itineraryAvailability, setFieldValue } = this.props

this.setState({ itineraryCheckResult })

// For new trips only,
// update the Formik state to uncheck days for which the itinerary is not available.
if (isCreating && itineraryCheckResult && itineraryCheckResult.status === 'success') {
ALL_DAYS.forEach(day => {
const dayAvailability = itineraryCheckResult.data[day]
if (!dayAvailability || !dayAvailability.isValid) {
setFieldValue(day, false)
}
})
if (itineraryAvailability !== prevProps.itineraryAvailability) {
// For new trips only,
// update the Formik state to uncheck days for which the itinerary is not available.
if (isCreating && itineraryAvailability) {
ALL_DAYS.forEach(day => {
if (!isDayAvailable(itineraryAvailability[day])) {
setFieldValue(day, false)
}
})
}
}
}

componentWillUnmount () {
this.props.clearItineraryAvailability()
}

render () {
const { errors, isCreating, touched, values: monitoredTrip } = this.props
const { errors, isCreating, itineraryAvailability, touched, values: monitoredTrip } = this.props
const { itinerary } = monitoredTrip
const { itineraryCheckResult } = this.state

if (!itinerary) {
return <div>No itinerary to display.</div>
Expand Down Expand Up @@ -123,11 +125,7 @@ class TripBasicsPane extends Component {
<ControlLabel>What days do you take this trip?</ControlLabel>
<div>
{allDays.map(({ name, fullText, text }, index) => {
const isDayDisabled =
itineraryCheckResult &&
itineraryCheckResult.status === 'success' &&
(!itineraryCheckResult.data[name] || !itineraryCheckResult.data[name].isValid)

const isDayDisabled = itineraryAvailability && !isDayAvailable(itineraryAvailability[name])
const boxClass = isDayDisabled ? 'alert-danger' : (monitoredTrip[name] ? 'bg-primary' : '')
const notAvailableText = isDayDisabled ? `Trip not available on ${fullText}` : null

Expand All @@ -146,7 +144,7 @@ class TripBasicsPane extends Component {
<div style={{clear: 'both'}} />
</div>
<HelpBlock>
{itineraryCheckResult
{itineraryAvailability
? (
<>Your trip is available on the days of the week as indicated above.</>
) : (
Expand All @@ -164,13 +162,17 @@ class TripBasicsPane extends Component {

// Connect to redux store
const mapStateToProps = (state, ownProps) => {
const { accessToken, itineraryAvailability } = state.user
return {
accessToken,
config: state.otp.config,
accessToken: state.user.accessToken
itineraryAvailability
}
}

const mapDispatchToProps = {
checkItineraryAvailability: userActions.checkItineraryAvailability,
clearItineraryAvailability: userActions.clearItineraryAvailability
}

export default connect(mapStateToProps, mapDispatchToProps)(TripBasicsPane)
13 changes: 13 additions & 0 deletions lib/reducers/create-user-reducer.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import update from 'immutability-helper'
function createUserReducer () {
const initialState = {
accessToken: null,
itineraryAvailability: null,
lastPhoneSmsRequest: {
number: null,
status: null,
Expand Down Expand Up @@ -41,6 +42,18 @@ function createUserReducer () {
})
}

case 'SET_ITINERARY_AVAILABILITY': {
return update(state, {
itineraryAvailability: { $set: action.payload }
})
}

case 'CLEAR_ITINERARY_AVAILABILITY': {
return update(state, {
itineraryAvailability: { $set: null }
})
}

default:
return state
}
Expand Down

0 comments on commit ea97ce6

Please sign in to comment.