Browse Source

Add Fare (WIP)

dev
sipp11 6 years ago
parent
commit
4d38652eb4
  1. 2
      package.json
  2. 194
      src/components/FareAttributesForm.js
  3. 112
      src/components/FareList.js
  4. 169
      src/components/FareRulesForm.js
  5. 16
      src/components/Nav.js
  6. 9
      src/container/Main.js

2
package.json

@ -1,6 +1,6 @@
{
"name": "grunt-front",
"version": "0.1.0",
"version": "0.2.0",
"private": true,
"dependencies": {
"ajv": "^6.5.1",

194
src/components/FareAttributesForm.js

@ -0,0 +1,194 @@
import React, { Component } from 'react'
import styled from 'styled-components'
import { connect } from 'react-redux'
import { Redirect, Link } from 'react-router-dom'
import { updateCalendar, createCalendar, deleteCalendar } from '../actions/calendar'
import store from '../store'
import HorizontalInput from './parts/HorizontalInput'
import HorizontalDate from './parts/HorizontalDate'
import HorizontalCheckbox from './parts/HorizontalCheckbox'
const StyledFareAttributesForm = styled.div`
padding: 1rem;
background: #fafafa;
`;
class FareAttributesForm extends Component {
state = {
id: null,
fare_id: "",
price: 0,
currency_type: "THB", // ISO 4217
payment_method: "", // 0 - paid on board or 1 - paid before boarding
transfer: "0", // 0 no transfer, 1 - transfer once, 2 tranfer twice,
// '' - unlimited transfer
agency_id: false, // optional
transfer_duration: "0", // optional 0 - no transfer allowed,
// otherwise it's length of time in seconds before
// transfer expires
}
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)
}
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(updateCalendar(id, body))
} else {
store.dispatch(createCalendar(body))
}
this.setState({justSubmit: true})
}
handleDelete() {
const { id } = this.state
store.dispatch(deleteCalendar(id))
this.setState({justSubmit: true})
}
componentWillMount() {
const { props } = this
const { serviceId } = props.match.params
const { results } = props.calendar
const ones = results.filter(ele => ele.service_id === serviceId)
if (ones.length > 0) {
this.setState(ones[0])
}
}
renderForm() {
const one = this.state
const { fetching } = this.props.calendar
return (
<StyledFareAttributesForm>
<h1 className="title">{one.name}&nbsp;&nbsp;</h1>
<div className="content">
<HorizontalInput
label="Fare ID"
type="text"
fieldName="fare_id"
value={one.fare_id || ''}
handleChange={this.handleChange} />
<HorizontalInput
label="Price"
type="text"
fieldName="price"
value={one.price || ''}
handleChange={this.handleChange} />
<HorizontalInput
key="currency_type"
label="Currency"
type="text"
fieldName="currency_type"
value={one.currency_type || 'THB'}
handleChange={this.handleChange} />
<HorizontalInput
key="payment_method"
label="Payment method"
type="text"
fieldName="payment_method"
value={one.payment_method || '0'}
handleChange={this.handleChange} />
<HorizontalInput
key="transfer"
label="Transfer"
type="text"
fieldName="transfer"
value={one.transfer || '0'}
handleChange={this.handleChange} />
{/* TODO: probably need HorizontalSelect */}
<HorizontalInput
key="agency_id"
label="Agency ID"
type="text"
fieldName="agency_id"
value={one.agency_id || ''}
handleChange={this.handleChange} />
<HorizontalInput
key="transfer_duration"
label="Transfer Duration"
type="text"
fieldName="transfer_duration"
value={one.transfer_duration || '0'}
handleChange={this.handleChange} />
</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={`/calendar`} className="button is-text">Cancel</Link>
</div>
</div>
</StyledFareAttributesForm>
)
}
render () {
const one = this.state
const { fetching } = this.props.calendar
// redirect to view page if no data
const { serviceId } = this.props.match.params
// this is a create form
if (serviceId === undefined) {
if (one.justSubmit === true && !fetching) {
return <Redirect to={`/calendar`} />
}
return this.renderForm()
}
if (one.id === null && serviceId.length > 0)
return <Redirect to={`/calendar`} />
// redirect to calendar list if submitted
if (one.justSubmit === true && !fetching) {
return <Redirect to={`/calendar`} />
}
return this.renderForm()
}
}
const mapStateToProps = state => ({
calendar: state.calendar
})
const connectCalendarFom = connect(
mapStateToProps,
)(FareAttributesForm)
export default connectCalendarFom

112
src/components/FareList.js

@ -0,0 +1,112 @@
import React, { Component } from 'react'
import styled from 'styled-components'
import { connect } from 'react-redux'
import { Link } from 'react-router-dom'
import { getCalendar } from '../actions/calendar'
import store from '../store'
const StyledBox = styled.div`
padding: 1rem;
background: #fafafa;
`
const GapBox = styled.span`
margin-right: 5px;
color: ${props => props.checked ? 'green' : 'gray'};;
`
const FakeRow = styled.nav`
padding-top: 5px;
padding-bottom: 5px;
background: white;
margin-bottom: 1rem;
`
const CheckboxIcon = (props) => (
<GapBox checked={props.checked}>
{props.checked === true && <span><i className="fas fa-check-square"></i></span>}
{props.checked !== true && <span><i className="fas fa-square"></i></span>}
</GapBox>
)
class FareList extends Component {
componentWillMount() {
const { count } = this.props.calendar
if (count === 0)
store.dispatch(getCalendar())
}
render() {
const { results } = this.props.calendar
const { match } = this.props
return (
<StyledBox>
<h1 className="title">Service</h1>
<div className="columns">
<div className="column is-12">
<nav className="level is-mobile">
<p className="level-item has-text-centered">
<Link className="link is-info" to={`${match.url}/new`}>
<i className="fas fa-plus" /> New service
</Link>
</p>
</nav>
{results && Object.keys(results).map(i => (
<FakeRow className="level panel" key={results[i].service_id}>
<div className="level-item has-text-centered">
<div>
<p className="heading">Service ID</p>
<p className="title"><Link to={`${match.url}/${results[i].service_id}`}>{results[i].service_id}</Link></p>
</div>
</div>
<div className="level-item has-text-centered">
<div>
<p className="heading">Start</p>
<p className="title">{results[i].start_date}</p>
</div>
</div>
<div className="level-item has-text-centered">
<div>
<p className="heading">End</p>
<p className="title">{results[i].end_date}</p>
</div>
</div>
<div className="level-item has-text-centered">
<div>
<p className="heading">M T W Th F Sa Su</p>
<p className="title">
<CheckboxIcon disabled={true} checked={results[i].monday} />
<CheckboxIcon disabled={true} checked={results[i].tuesday} />
<CheckboxIcon disabled={true} checked={results[i].wednesday} />
<CheckboxIcon disabled={true} checked={results[i].thursday} />
<CheckboxIcon disabled={true} checked={results[i].friday} />
<CheckboxIcon disabled={true} checked={results[i].saturday} />
<CheckboxIcon disabled={true} checked={results[i].sunday} />
</p>
</div>
</div>
</FakeRow>
))}
</div>
</div>
</StyledBox>
)
}
}
const mapStateToProps = state => ({
calendar: state.calendar
})
const connectFareList = connect(
mapStateToProps,
{},
)(FareList)
export default styled(connectFareList)`
color: palevioletred;
font-weight: bold;
`

169
src/components/FareRulesForm.js

@ -0,0 +1,169 @@
import React, { Component } from 'react'
import styled from 'styled-components'
import { connect } from 'react-redux'
import { Redirect, Link } from 'react-router-dom'
import { updateCalendar, createCalendar, deleteCalendar } from '../actions/calendar'
import store from '../store'
import HorizontalInput from './parts/HorizontalInput'
import HorizontalDate from './parts/HorizontalDate'
import HorizontalCheckbox from './parts/HorizontalCheckbox'
const StyledFareRulesForm = styled.div`
padding: 1rem;
background: #fafafa;
`;
class FareRulesForm extends Component {
state = {
id: null,
fare_id: "",
route_id: "", // optinal
origin_id: "",
destination_id: "",
contains_id: "",
}
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)
}
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(updateCalendar(id, body))
} else {
store.dispatch(createCalendar(body))
}
this.setState({justSubmit: true})
}
handleDelete() {
const { id } = this.state
store.dispatch(deleteCalendar(id))
this.setState({justSubmit: true})
}
componentWillMount() {
const { props } = this
const { serviceId } = props.match.params
const { results } = props.calendar
const ones = results.filter(ele => ele.service_id === serviceId)
if (ones.length > 0) {
this.setState(ones[0])
}
}
renderForm() {
const one = this.state
const { fetching } = this.props.calendar
return (
<StyledFareRulesForm>
<h1 className="title">{one.name}&nbsp;&nbsp;</h1>
<div className="content">
<HorizontalInput
label="Fare ID"
type="text"
fieldName="fare_id"
value={one.fare_id || ''}
handleChange={this.handleChange} />
<HorizontalInput
label="Route ID"
type="text"
fieldName="route_id"
value={one.route_id || ''}
handleChange={this.handleChange} />
<HorizontalInput
label="Origin ID"
type="text"
fieldName="origin_id"
value={one.origin_id || ''}
handleChange={this.handleChange} />
<HorizontalInput
label="Destination ID"
type="text"
fieldName="destination_id"
value={one.destination_id || ''}
handleChange={this.handleChange} />
<HorizontalInput
label="Contains ID"
type="text"
fieldName="contains_id"
value={one.contains_id || ''}
handleChange={this.handleChange} />
</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={`/calendar`} className="button is-text">Cancel</Link>
</div>
</div>
</StyledFareRulesForm>
)
}
render () {
const one = this.state
const { fetching } = this.props.calendar
// redirect to view page if no data
const { serviceId } = this.props.match.params
// this is a create form
if (serviceId === undefined) {
if (one.justSubmit === true && !fetching) {
return <Redirect to={`/calendar`} />
}
return this.renderForm()
}
if (one.id === null && serviceId.length > 0)
return <Redirect to={`/calendar`} />
// redirect to calendar list if submitted
if (one.justSubmit === true && !fetching) {
return <Redirect to={`/calendar`} />
}
return this.renderForm()
}
}
const mapStateToProps = state => ({
calendar: state.calendar
})
const connectCalendarFom = connect(
mapStateToProps,
)(FareRulesForm)
export default connectCalendarFom

16
src/components/Nav.js

@ -20,9 +20,21 @@ class Nav extends Component {
const { props } = this
return (
<div className="navbar-start">
<StyledLink to="/" className="navbar-item">
Home
<div className="navbar-item has-dropdown is-hoverable">
<StyledLink to="/fare" className="navbar-link">
Fare
</StyledLink>
<div className="navbar-dropdown is-boxed">
<StyledLink to={`/fare/rules/new`} className="navbar-item">
<i className="fas fa-plus" />
&nbsp; new fare rule
</StyledLink>
<StyledLink to={`/fare/attributes/new`} className="navbar-item">
<i className="fas fa-plus" />
&nbsp; new fare attributes
</StyledLink>
</div>
</div>
<div className="navbar-item has-dropdown is-hoverable">
<StyledLink to="/calendar" className="navbar-link">
Service

9
src/container/Main.js

@ -13,6 +13,11 @@ import AgencyList from '../components/AgencyList'
import AgencyItem from '../components/AgencyItem'
import AgencyForm from '../components/AgencyForm'
import TripForm from '../components/TripForm'
import FareList from '../components/FareList'
import FareRulesForm from '../components/FareRulesForm'
import FareAttributesForm from '../components/FareAttributesForm'
import { LOGIN_PATH } from '../constants/path'
import store from '../store'
@ -48,6 +53,10 @@ class Main extends Component {
<Route path={`${match.url}agency/:agencyId/:agencyChild`} component={AgencyItem} />
<Route exact path={`${match.url}agency`} component={AgencyList} />
<Route exact path={`${match.url}fare`} component={FareList} />
<Route exact path={`${match.url}fare/rules/new`} component={FareRulesForm} />
<Route exact path={`${match.url}fare/attributes/new`} component={FareAttributesForm} />
<Route exact path={`${match.url}calendar/new`} component={CalendarForm} />
<Route exact path={`${match.url}calendar/:serviceId`} component={CalendarForm} />
<Route exact path={`${match.url}calendar`} component={CalendarList} />

Loading…
Cancel
Save