diff --git a/package.json b/package.json
index 7b8c2e6..5f0a6d8 100644
--- a/package.json
+++ b/package.json
@@ -1,6 +1,6 @@
{
"name": "grunt-front",
- "version": "0.1.0",
+ "version": "0.2.0",
"private": true,
"dependencies": {
"ajv": "^6.5.1",
diff --git a/src/components/FareAttributesForm.js b/src/components/FareAttributesForm.js
new file mode 100644
index 0000000..816cfda
--- /dev/null
+++ b/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 (
+
+ {one.name}
+
+
+
+
+
+
+
+
+
+
+
+ {/* TODO: probably need HorizontalSelect */}
+
+
+
+
+
+
+
+
+
+ Save
+
+ {one.id !== null &&
+
+ DELETE
+
}
+
+ Cancel
+
+
+
+ )
+ }
+
+ 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
+ }
+ return this.renderForm()
+ }
+
+ if (one.id === null && serviceId.length > 0)
+ return
+
+ // redirect to calendar list if submitted
+ if (one.justSubmit === true && !fetching) {
+ return
+ }
+ return this.renderForm()
+ }
+
+}
+
+
+const mapStateToProps = state => ({
+ calendar: state.calendar
+})
+
+const connectCalendarFom = connect(
+ mapStateToProps,
+)(FareAttributesForm)
+export default connectCalendarFom
diff --git a/src/components/FareList.js b/src/components/FareList.js
new file mode 100644
index 0000000..b5f5d7b
--- /dev/null
+++ b/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) => (
+
+ {props.checked === true && }
+ {props.checked !== true && }
+
+)
+
+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 (
+
+ Service
+
+
+
+
+
+ New service
+
+
+
+ {results && Object.keys(results).map(i => (
+
+
+
+
Service ID
+
{results[i].service_id}
+
+
+
+
+
Start
+
{results[i].start_date}
+
+
+
+
+
End
+
{results[i].end_date}
+
+
+
+
+
M T W Th F Sa Su
+
+
+
+
+
+
+
+
+
+
+
+
+ ))}
+
+
+
+ )
+ }
+}
+
+const mapStateToProps = state => ({
+ calendar: state.calendar
+})
+const connectFareList = connect(
+ mapStateToProps,
+ {},
+)(FareList)
+
+export default styled(connectFareList)`
+ color: palevioletred;
+ font-weight: bold;
+`
diff --git a/src/components/FareRulesForm.js b/src/components/FareRulesForm.js
new file mode 100644
index 0000000..d738366
--- /dev/null
+++ b/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 (
+
+ {one.name}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Save
+
+ {one.id !== null &&
+
+ DELETE
+
}
+
+ Cancel
+
+
+
+ )
+ }
+
+ 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
+ }
+ return this.renderForm()
+ }
+
+ if (one.id === null && serviceId.length > 0)
+ return
+
+ // redirect to calendar list if submitted
+ if (one.justSubmit === true && !fetching) {
+ return
+ }
+ return this.renderForm()
+ }
+
+}
+
+
+const mapStateToProps = state => ({
+ calendar: state.calendar
+})
+
+const connectCalendarFom = connect(
+ mapStateToProps,
+)(FareRulesForm)
+export default connectCalendarFom
diff --git a/src/components/Nav.js b/src/components/Nav.js
index 44cbff0..f54fcb4 100644
--- a/src/components/Nav.js
+++ b/src/components/Nav.js
@@ -20,9 +20,21 @@ class Nav extends Component {
const { props } = this
return (
-
- Home
-
+
+
+ Fare
+
+
+
+
+ new fare rule
+
+
+
+ new fare attributes
+
+
+
Service
diff --git a/src/container/Main.js b/src/container/Main.js
index 9a23134..3b9cd2f 100644
--- a/src/container/Main.js
+++ b/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 {
+
+
+
+