21 changed files with 963 additions and 57 deletions
@ -0,0 +1,64 @@
|
||||
import { RSAA } from 'redux-api-middleware' |
||||
|
||||
import * as types from '../constants/ActionTypes' |
||||
import { RSAAHeaders } from '../utils/ApiClient' |
||||
import { API_URL } from '../constants/Api' |
||||
|
||||
|
||||
export const getTrip = (query) => ({ |
||||
[RSAA]: { |
||||
endpoint: `${API_URL}/trip/?${query || ''}`, |
||||
method: 'GET', |
||||
headers: RSAAHeaders, |
||||
bailout: (state) => state.trip.fetching, |
||||
types: [ |
||||
types.TRIP_REQUEST, |
||||
types.TRIP_SUCCESS, |
||||
types.TRIP_FAILURE, |
||||
] |
||||
} |
||||
}) |
||||
|
||||
export const updateTrip = (id, body) => ({ |
||||
[RSAA]: { |
||||
endpoint: `${API_URL}/trip/${id}/`, |
||||
body: JSON.stringify(body), |
||||
method: 'PATCH', |
||||
headers: RSAAHeaders, |
||||
types: [ |
||||
types.TRIP_REQUEST, |
||||
types.TRIP_UPDATE, |
||||
types.TRIP_FAILURE, |
||||
] |
||||
} |
||||
}) |
||||
|
||||
export const createTrip = (body) => ({ |
||||
[RSAA]: { |
||||
endpoint: `${API_URL}/trip/`, |
||||
body: JSON.stringify(body), |
||||
method: 'POST', |
||||
headers: RSAAHeaders, |
||||
types: [ |
||||
types.TRIP_REQUEST, |
||||
types.TRIP_CREATE, |
||||
types.TRIP_FAILURE, |
||||
] |
||||
} |
||||
}) |
||||
|
||||
export const deleteTrip = (id) => ({ |
||||
[RSAA]: { |
||||
endpoint: `${API_URL}/trip/${id}/`, |
||||
method: 'DELETE', |
||||
headers: RSAAHeaders, |
||||
types: [ |
||||
types.TRIP_REQUEST, |
||||
{ |
||||
type: types.TRIP_DELETE, |
||||
meta: { id } |
||||
}, |
||||
types.TRIP_FAILURE, |
||||
] |
||||
} |
||||
}) |
@ -0,0 +1,186 @@
|
||||
import React, { Component } from 'react' |
||||
import styled from 'styled-components' |
||||
import Select from 'react-select' |
||||
|
||||
import Input from './parts/Input' |
||||
import OurSelect from './parts/Select' |
||||
import { |
||||
updateStopTime, createStopTime, deleteStopTime |
||||
} from '../actions/stoptime' |
||||
import store from '../store' |
||||
import { API_URL } from '../constants/Api' |
||||
|
||||
const StyleBox = styled.div` |
||||
padding: 5px; |
||||
background: white; |
||||
margin-bottom: 1rem; |
||||
` |
||||
|
||||
class StopTimeForm extends Component { |
||||
|
||||
state = { |
||||
editMode: false, |
||||
trip: null, |
||||
id: null, |
||||
} |
||||
|
||||
constructor(props) { |
||||
super(props) |
||||
this.handleChange = this.handleChange.bind(this) |
||||
this.handleSubmit = this.handleSubmit.bind(this) |
||||
this.handleDelete = this.handleDelete.bind(this) |
||||
} |
||||
|
||||
handleChange(evt) { |
||||
let updated = {} |
||||
updated[evt.target.name] = evt.target.value |
||||
this.setState(updated) |
||||
} |
||||
|
||||
handleSubmit() { |
||||
const { id } = this.state |
||||
let body = {...this.state } |
||||
delete body.id |
||||
if (id !== null) { |
||||
store.dispatch(updateStopTime(id, body)) |
||||
} else { |
||||
store.dispatch(createStopTime(body)) |
||||
} |
||||
this.props.toggleEditMode() |
||||
} |
||||
|
||||
handleDelete() { |
||||
const { id } = this.state |
||||
store.dispatch(deleteStopTime(id)) |
||||
this.props.toggleEditMode() |
||||
} |
||||
|
||||
static getDerivedStateFromProps(props, state) { |
||||
if (props.item && props.item.id !== null && state.id === null) { |
||||
return props.item |
||||
} else if (props.trip !== undefined) { |
||||
return { trip: props.trip } |
||||
} |
||||
return null |
||||
} |
||||
|
||||
getStops = (inputValue) => { |
||||
if (!inputValue) { |
||||
return Promise.resolve({ options: [] }); |
||||
} |
||||
return fetch(`${API_URL}/stop/?search=${inputValue}`) |
||||
.then((response) => response.json()) |
||||
.then((json) => ({ options: json.results })) |
||||
} |
||||
|
||||
render() { |
||||
const item = this.state |
||||
return ( |
||||
<StyleBox> |
||||
<Input |
||||
label="Sequence" |
||||
type="text" |
||||
fieldName="sequence" |
||||
value={item.sequence || ''} |
||||
handleChange={this.handleChange} /> |
||||
|
||||
<div className="field"> |
||||
<label className="label">Stop</label> |
||||
<Select.Async |
||||
value={this.state.stop} |
||||
labelKey="stop_id" |
||||
valueKey="id" |
||||
filterOptionunion={false} |
||||
loadOptions={this.getStops} |
||||
onChange={(data) => { |
||||
let evt = { |
||||
target: { |
||||
name: 'stop', |
||||
value: data, |
||||
}} |
||||
return this.handleChange(evt) |
||||
}} |
||||
/> |
||||
</div> |
||||
|
||||
<Input |
||||
label="Arrival" |
||||
type="text" |
||||
fieldName="arrival" |
||||
value={item.arrival || ''} |
||||
handleChange={this.handleChange} /> |
||||
<Input |
||||
label="Departure" |
||||
type="text" |
||||
fieldName="departure" |
||||
value={item.departure || ''} |
||||
handleChange={this.handleChange} /> |
||||
<Input |
||||
label="Stop Headsign" |
||||
type="text" |
||||
fieldName="stop_headsign" |
||||
value={item.stop_headsign || ''} |
||||
handleChange={this.handleChange} /> |
||||
|
||||
<OurSelect |
||||
label="Pickup Type" |
||||
type="text" |
||||
fieldName="pickup_type" |
||||
value={item.pickup_type || '0'} |
||||
handleChange={this.handleChange} |
||||
choices={[ |
||||
{ value: '0', label: 'Regularly scheduled pickup' }, |
||||
{ value: '1', label: 'No pickup' }, |
||||
{ value: '2', label: 'Arrange pickup' }, |
||||
{ value: '3', label: 'Contact driver' }, |
||||
]} /> |
||||
|
||||
<OurSelect |
||||
label="Drop off Type" |
||||
type="text" |
||||
fieldName="pickup_type" |
||||
value={item.pickup_type || '0'} |
||||
handleChange={this.handleChange} |
||||
choices={[ |
||||
{ value: '0', label: 'Regularly scheduled dropoff' }, |
||||
{ value: '1', label: 'No drop off' }, |
||||
{ value: '2', label: 'Arrange drop off' }, |
||||
{ value: '3', label: 'Contact driver' }, |
||||
]} /> |
||||
|
||||
<OurSelect |
||||
label="Timepoint" |
||||
type="text" |
||||
fieldName="timepoint" |
||||
value={item.timepoint || '1'} |
||||
handleChange={this.handleChange} |
||||
choices={[ |
||||
{ value: '0', label: 'times are considered approximate.' }, |
||||
{ value: '1', label: 'times are considered exact.' }, |
||||
]} /> |
||||
|
||||
<div className="field is-grouped"> |
||||
<div className="control"> |
||||
<button className="button is-link" |
||||
onClick={this.handleSubmit} |
||||
disabled={false}> |
||||
Save</button> |
||||
</div> |
||||
{item.id !== null && <div className="control"> |
||||
<button className="button is-danger" |
||||
onClick={this.handleDelete} |
||||
disabled={false}> |
||||
DELETE</button> |
||||
</div>} |
||||
{this.props.toggleEditMode && |
||||
<div className="control"> |
||||
<a onClick={() => this.props.toggleEditMode()} className="button is-text">Cancel</a> |
||||
</div>} |
||||
</div> |
||||
</StyleBox> |
||||
) |
||||
} |
||||
|
||||
} |
||||
|
||||
export default StopTimeForm |
@ -0,0 +1,69 @@
|
||||
import React, { Component } from 'react' |
||||
import styled from 'styled-components' |
||||
|
||||
import StopTimeForm from './StopTimeForm' |
||||
|
||||
const StyledRow = styled.div` |
||||
padding-top: 5px; |
||||
padding-bottom: 5px; |
||||
background: white; |
||||
margin-bottom: 1rem; |
||||
` |
||||
|
||||
class StopTimeOne extends Component { |
||||
|
||||
state = { |
||||
editMode: false |
||||
} |
||||
|
||||
constructor(props) { |
||||
super(props) |
||||
this.toggleEditMode = this.toggleEditMode.bind(this) |
||||
} |
||||
|
||||
toggleEditMode() { |
||||
this.setState({editMode: !this.state.editMode}) |
||||
} |
||||
|
||||
renderReadOnly = (item) => ( |
||||
<StyledRow className="level panel" key={`st-item-${item.id}`}> |
||||
<div className="level-item has-text-centered"> |
||||
<div> |
||||
<p className="heading"> |
||||
Stop <a onClick={() => this.toggleEditMode()}>EDIT</a> |
||||
</p> |
||||
<p className="title">{item.sequence}. {item.stop.stop_id}</p> |
||||
</div> |
||||
</div> |
||||
<div className="level-item has-text-centered"> |
||||
<div> |
||||
<p className="heading">Arrival</p> |
||||
<p className="title">{item.arrival}</p> |
||||
</div> |
||||
</div> |
||||
<div className="level-item has-text-centered"> |
||||
<div> |
||||
<p className="heading">Departure</p> |
||||
<p className="title">{item.departure}</p> |
||||
</div> |
||||
</div> |
||||
<div className="level-item has-text-centered"> |
||||
<div> |
||||
<p className="heading">Stop headsign</p> |
||||
<p className="title">{item.stop_headsign || '-'}</p> |
||||
</div> |
||||
</div> |
||||
</StyledRow> |
||||
) |
||||
|
||||
render() { |
||||
const { item } = this.props |
||||
if (this.state.editMode) |
||||
return <StopTimeForm item={item} |
||||
toggleEditMode={this.toggleEditMode} /> |
||||
return this.renderReadOnly(item) |
||||
} |
||||
|
||||
} |
||||
|
||||
export default StopTimeOne |
@ -0,0 +1,251 @@
|
||||
import React, { Component } from 'react' |
||||
import styled from 'styled-components' |
||||
import { connect } from 'react-redux' |
||||
import { Redirect, Link } from 'react-router-dom' |
||||
|
||||
import StopTimeOne from './StopTimeOne' |
||||
import StopTimeForm from './StopTimeForm' |
||||
import HorizontalInput from './parts/HorizontalInput' |
||||
import HorizontalSelect from './parts/HorizontalSelect' |
||||
import { updateTrip, createTrip, deleteTrip } from '../actions/trip' |
||||
import { getCalendar } from '../actions/calendar' |
||||
import { getRoute } from '../actions' |
||||
import { getStopTime } from '../actions/stoptime' |
||||
import store from '../store' |
||||
|
||||
const StyledTripForm = styled.div` |
||||
padding: 1rem; |
||||
background: #fafafa; |
||||
` |
||||
const StyleBox = styled.div` |
||||
padding: 5px; |
||||
background: white; |
||||
margin-bottom: 1rem; |
||||
` |
||||
|
||||
class TripForm extends Component { |
||||
|
||||
state = { |
||||
id: null, |
||||
trip_id: "", |
||||
email: "", |
||||
fare_url: "", |
||||
lang: "", |
||||
name: "", |
||||
phone: "", |
||||
timezone: "", |
||||
url: "", |
||||
newStopTime: false, |
||||
} |
||||
|
||||
constructor() { |
||||
super() |
||||
this.handleChange = this.handleChange.bind(this) |
||||
this.handleSubmit = this.handleSubmit.bind(this) |
||||
this.handleDelete = this.handleDelete.bind(this) |
||||
this.renderForm = this.renderForm.bind(this) |
||||
} |
||||
|
||||
toggleNewStopTime = () => { |
||||
this.setState({ newStopTime: !this.state.newStopTime }) |
||||
} |
||||
|
||||
handleChange(evt) { |
||||
let updated = {} |
||||
updated[evt.target.name] = evt.target.value |
||||
this.setState(updated) |
||||
} |
||||
|
||||
handleSubmit() { |
||||
const { id } = this.state |
||||
let body = {...this.state } |
||||
delete body.id |
||||
delete body.newStopTime |
||||
if (id !== null) { |
||||
store.dispatch(updateTrip(id, body)) |
||||
} else { |
||||
store.dispatch(createTrip(body)) |
||||
} |
||||
this.setState({justSubmit: true}) |
||||
} |
||||
|
||||
handleDelete() { |
||||
const { id } = this.state |
||||
store.dispatch(deleteTrip(id)) |
||||
this.setState({justSubmit: true}) |
||||
} |
||||
|
||||
static getDerivedStateFromProps(props, state) { |
||||
const { agencyId, routeId, tripId } = props.match.params |
||||
if (!props.calendar.fetching && props.calendar.count === 0) |
||||
store.dispatch(getCalendar()) |
||||
if (tripId !== undefined && state.id === null) { |
||||
const { route } = props |
||||
const tRoute = route.results.filter(ele => ele.route_id === routeId) |
||||
if (tRoute.length > 0) { |
||||
const trips = tRoute[0].trip_set.filter(ele => ele.trip_id === tripId) |
||||
if (trips.length > 0) { |
||||
store.dispatch(getStopTime(`trip=${trips[0].id}&limit=100`)) |
||||
return trips[0] |
||||
} |
||||
} else { |
||||
store.dispatch(getRoute(`agency=${agencyId}`)) |
||||
} |
||||
} |
||||
return null |
||||
} |
||||
|
||||
renderForm() { |
||||
const one = this.state |
||||
const { agencyId, routeId } = this.props.match.params |
||||
const { fetching } = this.props.route |
||||
const { calendar } = this.props |
||||
|
||||
return ( |
||||
<StyledTripForm> |
||||
<h1 className="title">{one.name} </h1> |
||||
<div className="content"> |
||||
<HorizontalInput |
||||
label="Trip ID" |
||||
type="text" |
||||
fieldName="trip_id" |
||||
value={one.trip_id || ''} |
||||
handleChange={this.handleChange} /> |
||||
|
||||
<HorizontalInput |
||||
label="Headsign" |
||||
type="text" |
||||
fieldName="trip_headsign" |
||||
value={one.trip_headsign || ''} |
||||
handleChange={this.handleChange} /> |
||||
|
||||
<HorizontalInput |
||||
label="Name" |
||||
type="text" |
||||
fieldName="short_name" |
||||
value={one.short_name || ''} |
||||
handleChange={this.handleChange} /> |
||||
|
||||
{!calendar.fetching && <HorizontalSelect |
||||
label="Service" |
||||
type="text" |
||||
fieldName="service" |
||||
value={one.service ? one.service.id : ''} |
||||
handleChange={this.handleChange} |
||||
choices={calendar.results.map(ele => ({ value: ele.id, label: ele.service_id }))} />} |
||||
|
||||
<HorizontalSelect |
||||
label="Direction ID" |
||||
type="text" |
||||
fieldName="direction_id" |
||||
value={one.direction_id || ''} |
||||
handleChange={this.handleChange} |
||||
choices={[ |
||||
{ value: '0', label: 'outbound' }, |
||||
{ value: '1', label: 'inbound' }, |
||||
]} /> |
||||
|
||||
<HorizontalInput |
||||
label="Block ID" |
||||
type="text" |
||||
fieldName="block_id" |
||||
value={one.block_id || ''} |
||||
handleChange={this.handleChange} /> |
||||
|
||||
<HorizontalSelect |
||||
label="Wheelchair Accessible" |
||||
type="text" |
||||
fieldName="wheelchair_accessible" |
||||
value={one.wheelchair_accessible || '0'} |
||||
handleChange={this.handleChange} |
||||
choices={[ |
||||
{ value: '0', label: 'No information' }, |
||||
{ value: '1', label: 'Yes' }, |
||||
{ value: '2', label: 'Not possible' }, |
||||
]} /> |
||||
|
||||
<HorizontalSelect |
||||
label="Bike Allowance" |
||||
type="text" |
||||
fieldName="bike_allowed" |
||||
value={one.bike_allowed || '0'} |
||||
handleChange={this.handleChange} |
||||
choices={[ |
||||
{ value: '0', label: 'No information' }, |
||||
{ value: '1', label: 'Yes' }, |
||||
{ value: '2', label: 'Not possible' }, |
||||
]} /> |
||||
</div> |
||||
<div className="field is-grouped"> |
||||
<div className="control"> |
||||
<button className="button is-link" |
||||
onClick={this.handleSubmit} |
||||
disabled={fetching}> |
||||
Save</button> |
||||
</div> |
||||
{one.id !== null && <div className="control"> |
||||
<button className="button is-danger" |
||||
onClick={this.handleDelete} |
||||
disabled={fetching}> |
||||
DELETE</button> |
||||
</div>} |
||||
<div className="control"> |
||||
<Link to={`/map/${agencyId}/route/${routeId}/trip`} className="button is-text">Cancel</Link> |
||||
</div> |
||||
</div> |
||||
</StyledTripForm> |
||||
) |
||||
} |
||||
|
||||
render () { |
||||
const one = this.state |
||||
const { fetching } = this.props.trip |
||||
// redirect to view page if no data
|
||||
const { agencyId, routeId, tripId } = this.props.match.params |
||||
// this is a create form
|
||||
// if (tripId === undefined) {
|
||||
// if (one.justSubmit === true && !fetching) {
|
||||
// return <Redirect to={`/trip/`} />
|
||||
// }
|
||||
// return this.renderForm()
|
||||
// }
|
||||
|
||||
// if (one.id === null && tripId.length > 0)
|
||||
// return <Redirect to={`/trip/`} />
|
||||
|
||||
// redirect to trip list if submitted
|
||||
if (one.justSubmit === true && !fetching) { |
||||
return <Redirect to={`/map/${agencyId}/route/${routeId}/trip`} /> |
||||
} |
||||
return ( |
||||
<div className="columns"> |
||||
<div className="column is-half"> |
||||
{this.renderForm()} |
||||
</div> |
||||
<div className="column is-half"> |
||||
<StyleBox> |
||||
{!this.state.newStopTime && <button className="button is-outlined" onClick={this.toggleNewStopTime}>new StopTime</button>} |
||||
{this.state.newStopTime && <StopTimeForm {...this.props} |
||||
trip={this.state.id} |
||||
toggleEditMode={this.toggleNewStopTime} /> } |
||||
</StyleBox> |
||||
{this.props.stoptime.results.map( |
||||
ele => <StopTimeOne key={`stb-${ele.id}`} item={ele} />)} |
||||
</div> |
||||
</div> |
||||
) |
||||
} |
||||
|
||||
} |
||||
|
||||
const mapStateToProps = state => ({ |
||||
route: state.route, |
||||
trip: state.trip, |
||||
calendar: state.calendar, |
||||
stoptime: state.stoptime, |
||||
}) |
||||
|
||||
const connectTripForm = connect( |
||||
mapStateToProps, |
||||
)(TripForm) |
||||
export default connectTripForm |
@ -0,0 +1,24 @@
|
||||
import React from 'react' |
||||
import Flatpickr from 'react-flatpickr' |
||||
import 'flatpickr/dist/themes/airbnb.css' |
||||
|
||||
|
||||
const Date = (props) => ( |
||||
<div className="field"> |
||||
<label className="label">{props.label}</label> |
||||
<p className="control"> |
||||
<Flatpickr |
||||
className="input" |
||||
defaultValue={props.value} |
||||
onChange={(date) => { |
||||
let evt = { |
||||
target: { |
||||
name: props.fieldName, |
||||
value: date[0].toISOString('YYYY-MM-DD').slice(0, 10) |
||||
}} |
||||
return props.handleChange(evt)}} /> |
||||
</p> |
||||
</div> |
||||
) |
||||
|
||||
export default Date |
@ -0,0 +1,36 @@
|
||||
import React from 'react' |
||||
import Select from 'react-select' |
||||
import 'react-select/dist/react-select.css' |
||||
|
||||
|
||||
const HorizontalInput = (props) => ( |
||||
<div className="field is-horizontal"> |
||||
<div className="field-label is-normal"> |
||||
<label className="label">{props.label}</label> |
||||
</div> |
||||
<div className="field-body"> |
||||
<div className="field"> |
||||
<Select |
||||
className="control" |
||||
name={props.fieldName} |
||||
value={props.value} |
||||
onChange={(data) => { |
||||
console.log('change', data) |
||||
let evt = { |
||||
target: { |
||||
name: props.fieldName, |
||||
value: data ? data.value : '', |
||||
}} |
||||
return props.handleChange(evt) |
||||
}} |
||||
options={props.choices || [ |
||||
{ value: 'one', label: 'change choices with' }, |
||||
{ value: 'two', label: 'props.choices' }, |
||||
]} |
||||
/> |
||||
</div> |
||||
</div> |
||||
</div> |
||||
) |
||||
|
||||
export default HorizontalInput |
@ -0,0 +1,15 @@
|
||||
import React from 'react' |
||||
|
||||
const Input = (props) => ( |
||||
<div className="field"> |
||||
<label className="label">{props.label}</label> |
||||
<p className="control"> |
||||
<input className="input" type={props.type || 'text'} |
||||
name={props.fieldName} |
||||
onChange={props.handleChange} |
||||
defaultValue={props.value} /> |
||||
</p> |
||||
</div> |
||||
) |
||||
|
||||
export default Input |
@ -0,0 +1,29 @@
|
||||
import React from 'react' |
||||
import Select from 'react-select' |
||||
import 'react-select/dist/react-select.css' |
||||
|
||||
|
||||
const NormalSelect = (props) => ( |
||||
<div className="field"> |
||||
<label className="label">{props.label}</label> |
||||
<Select |
||||
className="control" |
||||
name={props.fieldName} |
||||
value={props.value} |
||||
onChange={(data) => { |
||||
let evt = { |
||||
target: { |
||||
name: props.fieldName, |
||||
value: data ? data.value : '', |
||||
}} |
||||
return props.handleChange(evt) |
||||
}} |
||||
options={props.choices || [ |
||||
{ value: 'one', label: 'change choices with' }, |
||||
{ value: 'two', label: 'props.choices' }, |
||||
]} |
||||
/> |
||||
</div> |
||||
) |
||||
|
||||
export default NormalSelect |
@ -0,0 +1,76 @@
|
||||
import { |
||||
TRIP_CREATE, TRIP_DELETE, TRIP_UPDATE, |
||||
TRIP_REQUEST, TRIP_SUCCESS, TRIP_FAILURE, |
||||
} from '../constants/ActionTypes' |
||||
|
||||
|
||||
const tripInitState = { |
||||
results: [], |
||||
next: null, |
||||
count: 0, |
||||
fetching: false, |
||||
} |
||||
const trip = (state = tripInitState, action) => { |
||||
switch(action.type) { |
||||
case TRIP_REQUEST: |
||||
return { |
||||
...state, |
||||
fetching: true, |
||||
} |
||||
case TRIP_SUCCESS: |
||||
const { count, next, prev, results } = action.payload |
||||
return { |
||||
...state, |
||||
fetching: false, |
||||
count, |
||||
next, |
||||
results: [ |
||||
...(prev ? state.results : []), |
||||
...results, |
||||
] |
||||
} |
||||
case TRIP_UPDATE: |
||||
const { id } = action.payload |
||||
const oldResults = state.results |
||||
const targetInd = oldResults.findIndex(ele => ele.id === id) |
||||
return { |
||||
...state, |
||||
fetching: false, |
||||
results: [ |
||||
...oldResults.slice(0, targetInd), |
||||
action.payload, |
||||
...oldResults.slice(targetInd + 1) |
||||
] |
||||
} |
||||
case TRIP_CREATE: |
||||
return { |
||||
...state, |
||||
fetching: false, |
||||
count: state.count + 1, |
||||
results: [ |
||||
...state.results, |
||||
action.payload, |
||||
] |
||||
} |
||||
case TRIP_DELETE: |
||||
const deleteInd = state.results.findIndex(ele => ele.id === action.meta.id) |
||||
return { |
||||
...state, |
||||
count: state.count - 1, |
||||
fetching: false, |
||||
results: [ |
||||
...state.results.slice(0, deleteInd), |
||||
...state.results.slice(deleteInd + 1) |
||||
] |
||||
} |
||||
case TRIP_FAILURE: |
||||
return { |
||||
...state, |
||||
fetching: false, |
||||
} |
||||
default: |
||||
return state; |
||||
} |
||||
} |
||||
|
||||
export default trip |
Loading…
Reference in new issue