sipp11
6 years ago
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