sipp11
7 years ago
31 changed files with 1434 additions and 76 deletions
@ -0,0 +1,67 @@ |
|||||||
|
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 getCalendar = (query) => ({ |
||||||
|
[RSAA]: { |
||||||
|
endpoint: `${API_URL}/calendar/?${query || ''}`, |
||||||
|
method: 'GET', |
||||||
|
headers: RSAAHeaders, |
||||||
|
bailout: (state) => state.calendar.fetching || state.calendar.query === query, |
||||||
|
types: [ |
||||||
|
{ |
||||||
|
type: types.CALENDAR_REQUEST, |
||||||
|
meta: { query: query }, |
||||||
|
}, |
||||||
|
types.CALENDAR_SUCCESS, |
||||||
|
types.CALENDAR_FAILURE, |
||||||
|
] |
||||||
|
} |
||||||
|
}) |
||||||
|
|
||||||
|
export const updateCalendar = (id, body) => ({ |
||||||
|
[RSAA]: { |
||||||
|
endpoint: `${API_URL}/calendar/${id}/`, |
||||||
|
body: JSON.stringify(body), |
||||||
|
method: 'PATCH', |
||||||
|
headers: RSAAHeaders, |
||||||
|
types: [ |
||||||
|
types.CALENDAR_REQUEST, |
||||||
|
types.CALENDAR_UPDATE, |
||||||
|
types.CALENDAR_FAILURE, |
||||||
|
] |
||||||
|
} |
||||||
|
}) |
||||||
|
|
||||||
|
export const createCalendar = (body) => ({ |
||||||
|
[RSAA]: { |
||||||
|
endpoint: `${API_URL}/calendar/`, |
||||||
|
body: JSON.stringify(body), |
||||||
|
method: 'POST', |
||||||
|
headers: RSAAHeaders, |
||||||
|
types: [ |
||||||
|
types.CALENDAR_REQUEST, |
||||||
|
types.CALENDAR_CREATE, |
||||||
|
types.CALENDAR_FAILURE, |
||||||
|
] |
||||||
|
} |
||||||
|
}) |
||||||
|
|
||||||
|
export const deleteCalendar = (id) => ({ |
||||||
|
[RSAA]: { |
||||||
|
endpoint: `${API_URL}/calendar/${id}/`, |
||||||
|
method: 'DELETE', |
||||||
|
headers: RSAAHeaders, |
||||||
|
types: [ |
||||||
|
types.CALENDAR_REQUEST, |
||||||
|
{ |
||||||
|
type: types.CALENDAR_DELETE, |
||||||
|
meta: { id } |
||||||
|
}, |
||||||
|
types.CALENDAR_FAILURE, |
||||||
|
] |
||||||
|
} |
||||||
|
}) |
@ -0,0 +1,67 @@ |
|||||||
|
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 getFareAttr = (query) => ({ |
||||||
|
[RSAA]: { |
||||||
|
endpoint: `${API_URL}/fare-attribute/?${query || ''}`, |
||||||
|
method: 'GET', |
||||||
|
headers: RSAAHeaders, |
||||||
|
bailout: (state) => state.fareattr.fetching || state.fareattr.query === query, |
||||||
|
types: [ |
||||||
|
{ |
||||||
|
type: types.FAREATTR_REQUEST, |
||||||
|
meta: { query: query }, |
||||||
|
}, |
||||||
|
types.FAREATTR_SUCCESS, |
||||||
|
types.FAREATTR_FAILURE, |
||||||
|
] |
||||||
|
} |
||||||
|
}) |
||||||
|
|
||||||
|
export const updateFareAttr = (id, body) => ({ |
||||||
|
[RSAA]: { |
||||||
|
endpoint: `${API_URL}/fare-attribute/${id}/`, |
||||||
|
body: JSON.stringify(body), |
||||||
|
method: 'PATCH', |
||||||
|
headers: RSAAHeaders, |
||||||
|
types: [ |
||||||
|
types.FAREATTR_REQUEST, |
||||||
|
types.FAREATTR_UPDATE, |
||||||
|
types.FAREATTR_FAILURE, |
||||||
|
] |
||||||
|
} |
||||||
|
}) |
||||||
|
|
||||||
|
export const createFareAttr = (body) => ({ |
||||||
|
[RSAA]: { |
||||||
|
endpoint: `${API_URL}/fare-attribute/`, |
||||||
|
body: JSON.stringify(body), |
||||||
|
method: 'POST', |
||||||
|
headers: RSAAHeaders, |
||||||
|
types: [ |
||||||
|
types.FAREATTR_REQUEST, |
||||||
|
types.FAREATTR_CREATE, |
||||||
|
types.FAREATTR_FAILURE, |
||||||
|
] |
||||||
|
} |
||||||
|
}) |
||||||
|
|
||||||
|
export const deleteFareAttr = (id) => ({ |
||||||
|
[RSAA]: { |
||||||
|
endpoint: `${API_URL}/fare-attribute/${id}/`, |
||||||
|
method: 'DELETE', |
||||||
|
headers: RSAAHeaders, |
||||||
|
types: [ |
||||||
|
types.FAREATTR_REQUEST, |
||||||
|
{ |
||||||
|
type: types.FAREATTR_DELETE, |
||||||
|
meta: { id } |
||||||
|
}, |
||||||
|
types.FAREATTR_FAILURE, |
||||||
|
] |
||||||
|
} |
||||||
|
}) |
@ -0,0 +1,207 @@ |
|||||||
|
import React, { Component } from 'react' |
||||||
|
import styled from 'styled-components' |
||||||
|
import { connect } from 'react-redux' |
||||||
|
import { Redirect, Link } from 'react-router-dom' |
||||||
|
|
||||||
|
import { updateAgency, createAgency, deleteAgency } from '../actions'; |
||||||
|
import store from '../store' |
||||||
|
|
||||||
|
const StyledAgencyForm = styled.div` |
||||||
|
padding: 1rem; |
||||||
|
background: #fafafa; |
||||||
|
`;
|
||||||
|
|
||||||
|
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"> |
||||||
|
<p className="control"> |
||||||
|
<input className="input" type={props.type || 'text'} |
||||||
|
name={props.fieldName} |
||||||
|
onChange={props.handleChange} |
||||||
|
defaultValue={props.value} /> |
||||||
|
</p> |
||||||
|
</div> |
||||||
|
</div> |
||||||
|
</div> |
||||||
|
) |
||||||
|
|
||||||
|
|
||||||
|
class AgencyForm extends Component { |
||||||
|
|
||||||
|
state = { |
||||||
|
id: null, |
||||||
|
agency_id: "", |
||||||
|
email: "", |
||||||
|
fare_url: "", |
||||||
|
lang: "", |
||||||
|
name: "", |
||||||
|
phone: "", |
||||||
|
timezone: "", |
||||||
|
url: "", |
||||||
|
} |
||||||
|
|
||||||
|
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(updateAgency(id, body)) |
||||||
|
} else { |
||||||
|
store.dispatch(createAgency(body)) |
||||||
|
} |
||||||
|
this.setState({justSubmit: true}) |
||||||
|
} |
||||||
|
|
||||||
|
handleDelete() { |
||||||
|
const { id } = this.state |
||||||
|
store.dispatch(deleteAgency(id)) |
||||||
|
this.setState({justSubmit: true}) |
||||||
|
} |
||||||
|
|
||||||
|
componentWillMount() { |
||||||
|
const { props } = this |
||||||
|
const { agencyId } = props.match.params |
||||||
|
const { results } = props.agency |
||||||
|
const ones = results.filter(ele => ele.agency_id === agencyId) |
||||||
|
if (ones.length > 0) { |
||||||
|
this.setState(ones[0]) |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
renderForm() { |
||||||
|
const one = this.state |
||||||
|
const { fetching } = this.props.agency |
||||||
|
return ( |
||||||
|
<StyledAgencyForm> |
||||||
|
<h1 className="title">{one.name} </h1> |
||||||
|
<div className="content"> |
||||||
|
<HorizontalInput |
||||||
|
label="Agency ID" |
||||||
|
type="text" |
||||||
|
fieldName="agency_id" |
||||||
|
value={one.agency_id || ''} |
||||||
|
handleChange={this.handleChange} /> |
||||||
|
|
||||||
|
<HorizontalInput |
||||||
|
label="Name" |
||||||
|
type="text" |
||||||
|
fieldName="name" |
||||||
|
value={one.name || ''} |
||||||
|
handleChange={this.handleChange} /> |
||||||
|
|
||||||
|
<HorizontalInput |
||||||
|
label="URL" |
||||||
|
type="text" |
||||||
|
fieldName="url" |
||||||
|
value={one.url || ''} |
||||||
|
handleChange={this.handleChange} /> |
||||||
|
|
||||||
|
<HorizontalInput |
||||||
|
label="Timezone" |
||||||
|
type="text" |
||||||
|
fieldName="timezone" |
||||||
|
value={one.timezone || ''} |
||||||
|
handleChange={this.handleChange} /> |
||||||
|
|
||||||
|
<HorizontalInput |
||||||
|
label="Phone" |
||||||
|
type="text" |
||||||
|
fieldName="phone" |
||||||
|
value={one.phone || ''} |
||||||
|
handleChange={this.handleChange} /> |
||||||
|
|
||||||
|
<HorizontalInput |
||||||
|
label="Language" |
||||||
|
type="text" |
||||||
|
fieldName="lang" |
||||||
|
value={one.lang || ''} |
||||||
|
handleChange={this.handleChange} /> |
||||||
|
|
||||||
|
<HorizontalInput |
||||||
|
label="Fare URL" |
||||||
|
type="text" |
||||||
|
fieldName="fare_url" |
||||||
|
value={one.fare_url || ''} |
||||||
|
handleChange={this.handleChange} /> |
||||||
|
|
||||||
|
<HorizontalInput |
||||||
|
label="Email" |
||||||
|
type="email" |
||||||
|
fieldName="email" |
||||||
|
value={one.email || ''} |
||||||
|
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={`/agency/${one.agency_id}`} className="button is-text">Cancel</Link> |
||||||
|
</div> |
||||||
|
</div> |
||||||
|
</StyledAgencyForm> |
||||||
|
) |
||||||
|
} |
||||||
|
|
||||||
|
render () { |
||||||
|
const one = this.state |
||||||
|
const { fetching } = this.props.agency |
||||||
|
// redirect to view page if no data
|
||||||
|
const { agencyId } = this.props.match.params |
||||||
|
// this is a create form
|
||||||
|
if (agencyId === undefined) { |
||||||
|
if (one.justSubmit === true && !fetching) { |
||||||
|
return <Redirect to={`/agency/`} /> |
||||||
|
} |
||||||
|
return this.renderForm() |
||||||
|
} |
||||||
|
|
||||||
|
if (one.id === null && agencyId.length > 0) |
||||||
|
return <Redirect to={`/agency/`} /> |
||||||
|
|
||||||
|
// redirect to agency list if submitted
|
||||||
|
if (one.justSubmit === true && !fetching) { |
||||||
|
return <Redirect to={`/agency/${one.agency_id || ''}`} /> |
||||||
|
} |
||||||
|
return this.renderForm() |
||||||
|
} |
||||||
|
|
||||||
|
} |
||||||
|
|
||||||
|
|
||||||
|
const mapStateToProps = state => ({ |
||||||
|
agency: state.agency |
||||||
|
}) |
||||||
|
|
||||||
|
const connectAgencyList = connect( |
||||||
|
mapStateToProps, |
||||||
|
)(AgencyForm) |
||||||
|
export default connectAgencyList |
@ -0,0 +1,87 @@ |
|||||||
|
import React, { Component } from 'react' |
||||||
|
import styled from 'styled-components' |
||||||
|
import { connect } from 'react-redux' |
||||||
|
import { Link, Redirect, Route } from 'react-router-dom' |
||||||
|
|
||||||
|
// import { getRoute } from '../actions'
|
||||||
|
// import store from '../store'
|
||||||
|
|
||||||
|
import Spinner from './Spinner' |
||||||
|
import RouteList from './RouteList' |
||||||
|
import FareAttrList from './FareAttrList' |
||||||
|
|
||||||
|
const StyledAgencyItem = styled.div` |
||||||
|
padding: 1rem; |
||||||
|
background: #fafafa; |
||||||
|
` |
||||||
|
|
||||||
|
class AgencyItem extends Component { |
||||||
|
|
||||||
|
render() { |
||||||
|
const { props } = this |
||||||
|
const { agencyId, agencyChild } = props.match.params |
||||||
|
const { results, fetching } = props.agency |
||||||
|
const one = results.filter(ele => ele.agency_id === agencyId)[0] |
||||||
|
|
||||||
|
if (!fetching && one === undefined) |
||||||
|
return <Redirect to='/agency' /> |
||||||
|
|
||||||
|
if (fetching) |
||||||
|
return <Spinner show={true} /> |
||||||
|
|
||||||
|
return ( |
||||||
|
<StyledAgencyItem> |
||||||
|
<h1 className="title"> |
||||||
|
{one.name} |
||||||
|
<Link to={`/agency/${one.agency_id}/edit`} className="button">Edit</Link></h1> |
||||||
|
<div className="columns"> |
||||||
|
<div className="column is-3 is-hidden-mobile"> |
||||||
|
<div className="content"> |
||||||
|
<dl> |
||||||
|
<dt>agency_id</dt> |
||||||
|
<dd>{one.agency_id}</dd> |
||||||
|
<dt>URL</dt> |
||||||
|
<dd>{one.url}</dd> |
||||||
|
<dt>Timezone</dt> |
||||||
|
<dd>{one.timezone || '-'}</dd> |
||||||
|
<dt>Phone</dt> |
||||||
|
<dd>{one.phone || '-'}</dd> |
||||||
|
<dt>Language</dt> |
||||||
|
<dd>{one.lang || '-'}</dd> |
||||||
|
<dt>Fare URL</dt> |
||||||
|
<dd>{one.fare_url || '-'}</dd> |
||||||
|
<dt>Email</dt> |
||||||
|
<dd>{one.email || '-'}</dd> |
||||||
|
</dl> |
||||||
|
</div> |
||||||
|
</div> |
||||||
|
<div className="column is-9"> |
||||||
|
<div className="tabs"> |
||||||
|
<ul> |
||||||
|
<li className={`${agencyChild === undefined && "is-active"}`}><Link to={`/agency/${one.agency_id}`}>Overview</Link></li> |
||||||
|
<li className={`${agencyChild === 'route' && "is-active"}`}><Link to={`/agency/${one.agency_id}/route`}>Route</Link></li> |
||||||
|
<li className={`${agencyChild === 'fare-attr' && "is-active"}`}><Link to={`/agency/${one.agency_id}/fare-attr`}>Fare Attributes</Link></li> |
||||||
|
</ul> |
||||||
|
</div> |
||||||
|
<Route path={`/agency/:agencyId/route/:routeId`} component={RouteList} /> |
||||||
|
<Route path={`/agency/:agencyId/route`} component={RouteList} /> |
||||||
|
<Route path={`/agency/:agencyId/fare-attr/:fareAttrId`} component={FareAttrList} /> |
||||||
|
<Route path={`/agency/:agencyId/fare-attr`} component={FareAttrList} /> |
||||||
|
{agencyChild === undefined && <p>Pick options on the tab</p>} |
||||||
|
</div> |
||||||
|
</div> |
||||||
|
{props.children} |
||||||
|
</StyledAgencyItem> |
||||||
|
) |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
const mapStateToProps = state => ({ |
||||||
|
agency: state.agency, |
||||||
|
route: state.route, |
||||||
|
}) |
||||||
|
|
||||||
|
const connectAgencyList = connect( |
||||||
|
mapStateToProps, |
||||||
|
)(AgencyItem) |
||||||
|
export default connectAgencyList |
@ -0,0 +1,47 @@ |
|||||||
|
import React, { Component } from 'react' |
||||||
|
import styled from 'styled-components' |
||||||
|
import { connect } from 'react-redux' |
||||||
|
import { Link } from 'react-router-dom' |
||||||
|
|
||||||
|
import { getAgency } from '../actions' |
||||||
|
import store from '../store' |
||||||
|
|
||||||
|
// const StyledAgencyList = styled.section`
|
||||||
|
// padding: 1em;
|
||||||
|
// background: papayawhip;
|
||||||
|
// `;
|
||||||
|
|
||||||
|
class AgencyList extends Component { |
||||||
|
|
||||||
|
componentWillMount() { |
||||||
|
const { count } = this.props.agency |
||||||
|
if (count === 0) |
||||||
|
store.dispatch(getAgency()) |
||||||
|
} |
||||||
|
|
||||||
|
render() { |
||||||
|
const { results } = this.props.agency |
||||||
|
return ( |
||||||
|
<ul> |
||||||
|
{results && Object.keys(results).map(i => ( |
||||||
|
<li key={i}> |
||||||
|
<Link to={`/agency/${results[i].agency_id}`}>{results[i].agency_id}</Link> |
||||||
|
</li> |
||||||
|
))} |
||||||
|
</ul> |
||||||
|
) |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
const mapStateToProps = state => ({ |
||||||
|
agency: state.agency |
||||||
|
}) |
||||||
|
const connectAgencyList = connect( |
||||||
|
mapStateToProps, |
||||||
|
{}, |
||||||
|
)(AgencyList) |
||||||
|
|
||||||
|
export default styled(connectAgencyList)` |
||||||
|
color: palevioletred; |
||||||
|
font-weight: bold; |
||||||
|
` |
@ -0,0 +1,50 @@ |
|||||||
|
import React, { Component } from 'react' |
||||||
|
import { connect } from 'react-redux' |
||||||
|
|
||||||
|
import Spinner from './Spinner' |
||||||
|
import { getFareAttr } from '../actions/fareattr' |
||||||
|
import store from '../store' |
||||||
|
|
||||||
|
|
||||||
|
class FareAttrList extends Component { |
||||||
|
|
||||||
|
|
||||||
|
componentDidMount() { |
||||||
|
const { agencyId } = this.props.match.params |
||||||
|
store.dispatch(getFareAttr(`agency=${agencyId}`)) |
||||||
|
} |
||||||
|
|
||||||
|
componentWillReceiveProps(newProps) { |
||||||
|
const { agencyId } = newProps.match.params |
||||||
|
if (agencyId !== this.props.match.params.agencyId) |
||||||
|
store.dispatch(getFareAttr(`agency=${agencyId}`)) |
||||||
|
} |
||||||
|
|
||||||
|
render() { |
||||||
|
const { fareattr } = this.props |
||||||
|
|
||||||
|
return ( |
||||||
|
<div> |
||||||
|
<h3 className="title">Fare Attributes</h3> |
||||||
|
<Spinner show={fareattr.fetching} /> |
||||||
|
<ul> |
||||||
|
{fareattr.count === 0 && <li>No fare attribute</li>} |
||||||
|
{fareattr.count > 0 |
||||||
|
&& fareattr.results.map(ele => ( |
||||||
|
<li key={ele.fare_id}>{ ele.fare_id }</li>) |
||||||
|
)} |
||||||
|
</ul> |
||||||
|
</div> |
||||||
|
) |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
const mapStateToProps = state => ({ |
||||||
|
fareattr: state.fareattr, |
||||||
|
}) |
||||||
|
|
||||||
|
const connectFareAttrList = connect( |
||||||
|
mapStateToProps, |
||||||
|
)(FareAttrList) |
||||||
|
|
||||||
|
export default connectFareAttrList |
@ -0,0 +1,13 @@ |
|||||||
|
import React from 'react' |
||||||
|
|
||||||
|
const Footer = () => |
||||||
|
<footer className="footer"> |
||||||
|
<div className="content has-text-centered"> |
||||||
|
<p> |
||||||
|
<strong>Go</strong><sup>TH</sup> |
||||||
|
</p> |
||||||
|
</div> |
||||||
|
</footer> |
||||||
|
|
||||||
|
|
||||||
|
export default Footer |
@ -0,0 +1,62 @@ |
|||||||
|
import React from 'react' |
||||||
|
|
||||||
|
let invalidEmail = false |
||||||
|
let goodPassword = null |
||||||
|
|
||||||
|
const Login = (props) => ( |
||||||
|
<div> |
||||||
|
<h1 className="title">Login</h1> |
||||||
|
<div className="field"> |
||||||
|
<label className="label">Email</label> |
||||||
|
<div className="control has-icons-left has-icons-right"> |
||||||
|
<input className={`input ${invalidEmail && 'is-danger'}`} |
||||||
|
type="email" |
||||||
|
name="email" |
||||||
|
onChange={props.updateField} |
||||||
|
placeholder="yourname@example.com" /> |
||||||
|
<span className="icon is-small is-left"> |
||||||
|
<i className="fas fa-envelope"></i> |
||||||
|
</span> |
||||||
|
{ invalidEmail && |
||||||
|
<span className="icon is-small is-right"> |
||||||
|
<i className="fas fa-exclamation-triangle"></i> |
||||||
|
</span>} |
||||||
|
</div> |
||||||
|
{ invalidEmail && |
||||||
|
<p className="help is-danger">This email is invalid</p> } |
||||||
|
</div> |
||||||
|
<div className="field"> |
||||||
|
<label className="label">Password</label> |
||||||
|
<div className="control has-icons-left has-icons-right"> |
||||||
|
<input type="password" |
||||||
|
name="password" |
||||||
|
className={`input ${goodPassword === true && 'is-success'}`} |
||||||
|
onChange={props.updateField} |
||||||
|
onKeyPress={(e) => {(e.key === 'Enter') && props.fetchAuth()}} |
||||||
|
placeholder="Password" /> |
||||||
|
<span className="icon is-small is-left"> |
||||||
|
<i className="fas fa-key"></i> |
||||||
|
</span> |
||||||
|
{ goodPassword === true && |
||||||
|
<span className="icon is-small is-right"> |
||||||
|
<i className="fas fa-check"></i> |
||||||
|
</span> } |
||||||
|
</div> |
||||||
|
{ goodPassword === true && |
||||||
|
<p className="help is-success">This password is great</p>} |
||||||
|
</div> |
||||||
|
|
||||||
|
<div className="field is-grouped"> |
||||||
|
<div className="control"> |
||||||
|
<button className="button is-link" |
||||||
|
onClick={props.fetchAuth}> |
||||||
|
Submit</button> |
||||||
|
</div> |
||||||
|
{/* <div className="control"> |
||||||
|
<button className="button is-text">Cancel</button> |
||||||
|
</div> */} |
||||||
|
</div> |
||||||
|
</div> |
||||||
|
) |
||||||
|
|
||||||
|
export default Login |
@ -0,0 +1,96 @@ |
|||||||
|
import React, { Component } from 'react' |
||||||
|
import { connect } from 'react-redux' |
||||||
|
import styled from 'styled-components' |
||||||
|
import { Link } from 'react-router-dom' |
||||||
|
|
||||||
|
import { logout } from '../utils/Auth' |
||||||
|
|
||||||
|
const StyledLink = styled(Link)` |
||||||
|
&[data-active] { |
||||||
|
color: red; |
||||||
|
} |
||||||
|
`;
|
||||||
|
|
||||||
|
class Nav extends Component { |
||||||
|
|
||||||
|
state = { expandNavbar: false } |
||||||
|
|
||||||
|
render() { |
||||||
|
const { props } = this |
||||||
|
return ( |
||||||
|
<nav className="navbar"> |
||||||
|
<div className="navbar-brand"> |
||||||
|
<StyledLink to="/" className="navbar-item"> |
||||||
|
<img src="https://static.10ninox.com/goth-rect-640x160.svg" alt="GoTH" width="112" height="28" /> |
||||||
|
</StyledLink> |
||||||
|
<div className="navbar-burger burger" onClick={() => { this.setState({expandNavbar: !this.state.expandNavbar}) }}> |
||||||
|
<span></span> |
||||||
|
<span></span> |
||||||
|
<span></span> |
||||||
|
</div> |
||||||
|
</div> |
||||||
|
|
||||||
|
<div className={`navbar-menu ${(this.state.expandNavbar ? 'is-active' : '')}`}> |
||||||
|
<div className="navbar-start"> |
||||||
|
<StyledLink to="/" className="navbar-item"> |
||||||
|
Home |
||||||
|
</StyledLink> |
||||||
|
<div className="navbar-item has-dropdown is-hoverable"> |
||||||
|
<StyledLink to="/calendar" className="navbar-link"> |
||||||
|
Service |
||||||
|
</StyledLink> |
||||||
|
<div className="navbar-dropdown is-boxed"> |
||||||
|
<StyledLink to={`/calendar/new`} className="navbar-item"> |
||||||
|
<i className="fas fa-plus" /> |
||||||
|
new service calendar |
||||||
|
</StyledLink> |
||||||
|
</div> |
||||||
|
</div> |
||||||
|
<div className="navbar-item has-dropdown is-hoverable"> |
||||||
|
<StyledLink to="/agency" className="navbar-link"> |
||||||
|
Agency |
||||||
|
</StyledLink> |
||||||
|
<div className="navbar-dropdown is-boxed"> |
||||||
|
{props.agency.count > 0 |
||||||
|
&& props.agency.results.map(ele => ( |
||||||
|
<StyledLink key={`nav$a${ele.agency_id}`} to={`/agency/${ele.agency_id}`} className="navbar-item"> |
||||||
|
{ele.name || ele.agency_id} |
||||||
|
</StyledLink> |
||||||
|
))} |
||||||
|
<StyledLink to={`/agency/new`} className="navbar-item"> |
||||||
|
<i className="fas fa-plus" /> |
||||||
|
Add new agency |
||||||
|
</StyledLink> |
||||||
|
</div> |
||||||
|
</div> |
||||||
|
</div> |
||||||
|
|
||||||
|
<div className="navbar-end"> |
||||||
|
<div className="navbar-item"> |
||||||
|
<div className="field is-grouped"> |
||||||
|
<p className="control"> |
||||||
|
<a className="button is-primary" |
||||||
|
onClick={() => logout()}> |
||||||
|
<span className="icon"> |
||||||
|
<i className="fas fa-sign-out-alt"></i> |
||||||
|
</span> |
||||||
|
<span>Logout</span> |
||||||
|
</a> |
||||||
|
</p> |
||||||
|
</div> |
||||||
|
</div> |
||||||
|
</div> |
||||||
|
</div> |
||||||
|
</nav> |
||||||
|
) |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
|
||||||
|
const mapStateToProps = state => ({ |
||||||
|
agency: state.agency, |
||||||
|
expandNavbar: false, |
||||||
|
}) |
||||||
|
export default connect( |
||||||
|
mapStateToProps, |
||||||
|
)(Nav) |
@ -0,0 +1,49 @@ |
|||||||
|
import React, { Component } from 'react' |
||||||
|
import { connect } from 'react-redux' |
||||||
|
|
||||||
|
import Spinner from './Spinner' |
||||||
|
import { getRoute } from '../actions' |
||||||
|
import store from '../store' |
||||||
|
|
||||||
|
|
||||||
|
class RouteList extends Component { |
||||||
|
|
||||||
|
componentDidMount() { |
||||||
|
const { agencyId } = this.props.match.params |
||||||
|
store.dispatch(getRoute(`agency=${agencyId}`)) |
||||||
|
} |
||||||
|
|
||||||
|
componentWillReceiveProps(newProps) { |
||||||
|
const { agencyId } = newProps.match.params |
||||||
|
if (agencyId !== this.props.match.params.agencyId) |
||||||
|
store.dispatch(getRoute(`agency=${agencyId}`)) |
||||||
|
} |
||||||
|
|
||||||
|
render() { |
||||||
|
const { route } = this.props |
||||||
|
|
||||||
|
return ( |
||||||
|
<div> |
||||||
|
<h3 className="title">Routes</h3> |
||||||
|
<Spinner show={route.fetching} /> |
||||||
|
<ul> |
||||||
|
{route.count === 0 && <li>No route</li>} |
||||||
|
{route.count > 0 |
||||||
|
&& route.results.map(ele => ( |
||||||
|
<li key={ele.route_id}>{ ele.route_id }</li>) |
||||||
|
)} |
||||||
|
</ul> |
||||||
|
</div> |
||||||
|
) |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
const mapStateToProps = state => ({ |
||||||
|
route: state.route, |
||||||
|
}) |
||||||
|
|
||||||
|
const connectRouteList = connect( |
||||||
|
mapStateToProps, |
||||||
|
)(RouteList) |
||||||
|
|
||||||
|
export default connectRouteList |
@ -0,0 +1,9 @@ |
|||||||
|
import React from 'react' |
||||||
|
|
||||||
|
const Spinner = (props) => ( |
||||||
|
<span> |
||||||
|
{props.show && <span><i className="fas fa-spinner" /></span>} |
||||||
|
</span> |
||||||
|
) |
||||||
|
|
||||||
|
export default Spinner |
@ -1,9 +1,45 @@ |
|||||||
|
|
||||||
export const FIRST_INCREMENT_COUNTER = 'FIRST_INCREMENT_COUNTER' |
export const FIRST_INCREMENT_COUNTER = 'FIRST_INCREMENT_COUNTER' |
||||||
export const FIRST_ASSIGN_ID = 'FIRST_ASSIGN_ID' |
export const FIRST_ASSIGN_ID = 'FIRST_ASSIGN_ID' |
||||||
export const SET_TOKEN = 'SET_TOKEN' |
// export const SET_TOKEN = 'SET_TOKEN'
|
||||||
|
|
||||||
|
|
||||||
export const REQUEST_LOGIN = 'REQUEST_LOGIN' |
export const REQUEST_LOGIN = 'REQUEST_LOGIN' |
||||||
export const SUCCESS_LOGIN = 'SUCCESS_LOGIN' |
export const SUCCESS_LOGIN = 'SUCCESS_LOGIN' |
||||||
export const FAILED_LOGIN = 'FAILED_LOGIN' |
export const FAILED_LOGIN = 'FAILED_LOGIN' |
||||||
|
export const SUCCESS_LOGOUT = 'SUCCESS_LOGOUT' |
||||||
|
|
||||||
|
|
||||||
|
export const AGENCY_REQUEST = 'AGENCY_REQUEST' |
||||||
|
export const AGENCY_FAILURE = 'AGENCY_FAILURE' |
||||||
|
export const AGENCY_SUCCESS = 'AGENCY_SUCCESS' |
||||||
|
// below items are SUCCESS for other tasks
|
||||||
|
export const AGENCY_CREATE = 'AGENCY_CREATE' |
||||||
|
export const AGENCY_DELETE = 'AGENCY_DELETE' |
||||||
|
export const AGENCY_UPDATE = 'AGENCY_UPDATE' |
||||||
|
|
||||||
|
|
||||||
|
export const ROUTE_REQUEST = 'ROUTE_REQUEST' |
||||||
|
export const ROUTE_FAILURE = 'ROUTE_FAILURE' |
||||||
|
export const ROUTE_SUCCESS = 'ROUTE_SUCCESS' |
||||||
|
// below items are SUCCESS for other tasks
|
||||||
|
export const ROUTE_CREATE = 'ROUTE_CREATE' |
||||||
|
export const ROUTE_DELETE = 'ROUTE_DELETE' |
||||||
|
export const ROUTE_UPDATE = 'ROUTE_UPDATE' |
||||||
|
|
||||||
|
|
||||||
|
export const CALENDAR_REQUEST = 'CALENDAR_REQUEST' |
||||||
|
export const CALENDAR_FAILURE = 'CALENDAR_FAILURE' |
||||||
|
export const CALENDAR_SUCCESS = 'CALENDAR_SUCCESS' |
||||||
|
// below items are SUCCESS for other tasks
|
||||||
|
export const CALENDAR_CREATE = 'CALENDAR_CREATE' |
||||||
|
export const CALENDAR_DELETE = 'CALENDAR_DELETE' |
||||||
|
export const CALENDAR_UPDATE = 'CALENDAR_UPDATE' |
||||||
|
|
||||||
|
|
||||||
|
export const FAREATTR_REQUEST = 'FAREATTR_REQUEST' |
||||||
|
export const FAREATTR_FAILURE = 'FAREATTR_FAILURE' |
||||||
|
export const FAREATTR_SUCCESS = 'FAREATTR_SUCCESS' |
||||||
|
// below items are SUCCESS for other tasks
|
||||||
|
export const FAREATTR_CREATE = 'FAREATTR_CREATE' |
||||||
|
export const FAREATTR_DELETE = 'FAREATTR_DELETE' |
||||||
|
export const FAREATTR_UPDATE = 'FAREATTR_UPDATE' |
||||||
|
@ -1,3 +1,5 @@ |
|||||||
|
|
||||||
export const URL = process.env.API_URL || 'https://showtimes.everyday.in.th' |
export const URL = process.env.API_URL || '//localhost:8000' |
||||||
|
export const API_PREFIX = process.env.API_PREFIX || '/v1' |
||||||
|
export const API_URL = `${URL}${API_PREFIX}` |
||||||
export const LOGIN = '/api-token-auth/' |
export const LOGIN = '/api-token-auth/' |
||||||
|
@ -1,30 +0,0 @@ |
|||||||
import React from 'react' |
|
||||||
import { Link } from 'react-router-dom' |
|
||||||
import { connect } from 'react-redux' |
|
||||||
import { getToken, loggedIn } from '../reducers/auth' |
|
||||||
import { fetchAuth } from '../actions' |
|
||||||
|
|
||||||
const Gone = (props) => ( |
|
||||||
<div> |
|
||||||
Gone { props.match.params.id } |
|
||||||
|
|
||||||
<hr /> |
|
||||||
<Link to={`/`}>Main</Link> |
|
||||||
|
|
||||||
<hr /> |
|
||||||
{props.loggedIn ? 'Logged in': 'Nah anonymous'} |
|
||||||
<hr /> |
|
||||||
|
|
||||||
<button onClick={_ => props.fetchAuth("sipp11", "gi23ft")}>Login</button> |
|
||||||
</div> |
|
||||||
) |
|
||||||
|
|
||||||
|
|
||||||
const mapStateToProps = state => ({ |
|
||||||
token: getToken(state.auth), |
|
||||||
auth: state.auth, |
|
||||||
}) |
|
||||||
export default connect( |
|
||||||
mapStateToProps, |
|
||||||
{ loggedIn, fetchAuth } |
|
||||||
)(Gone) |
|
@ -1,25 +1,64 @@ |
|||||||
import React from 'react' |
import React, { Component } from 'react' |
||||||
import { connect } from 'react-redux' |
import { connect } from 'react-redux' |
||||||
import { Link } from 'react-router-dom' |
import { Redirect, Route, Switch } from 'react-router-dom' |
||||||
|
|
||||||
import { getCounter } from '../reducers/first' |
import { loggedIn } from '../reducers/auth' |
||||||
import { incFirstCounter } from '../actions' |
import { getAgency } from '../actions' |
||||||
|
|
||||||
const Main = (props) => ( |
import Nav from '../components/Nav' |
||||||
<div> |
import AgencyList from '../components/AgencyList' |
||||||
Main |
import AgencyItem from '../components/AgencyItem' |
||||||
|
import AgencyForm from '../components/AgencyForm' |
||||||
|
import { LOGIN_PATH } from '../constants/path' |
||||||
|
import store from '../store' |
||||||
|
|
||||||
<Link to={`/roster/12`}>12</Link> |
class Main extends Component { |
||||||
<p>Counter: { props.counter }</p> |
|
||||||
<p><button onClick={() => props.incFirstCounter() }>Increment</button></p> |
componentWillMount() { |
||||||
</div> |
const { count } = this.props.agency |
||||||
) |
if (count === 0) |
||||||
|
store.dispatch(getAgency()) |
||||||
|
} |
||||||
|
|
||||||
|
// componentWillReceiveProps(nextProps) {
|
||||||
|
// const oldPathname = this.props.location.pathname
|
||||||
|
// const { pathname } = nextProps.location
|
||||||
|
// console.log(oldPathname, pathname)
|
||||||
|
// }
|
||||||
|
|
||||||
|
render() { |
||||||
|
const { match, loggedIn } = this.props |
||||||
|
if (loggedIn !== true) { |
||||||
|
return <Redirect to={LOGIN_PATH} /> |
||||||
|
} |
||||||
|
return ( |
||||||
|
<div> |
||||||
|
<Nav /> |
||||||
|
<div className="container is-widescreen"> |
||||||
|
<Switch> |
||||||
|
<Route exact path={`${match.url}agency/new`} component={AgencyForm} /> |
||||||
|
<Route exact path={`${match.url}agency/:agencyId`} component={AgencyItem} /> |
||||||
|
<Route path={`${match.url}agency/:agencyId/edit`} component={AgencyForm} /> |
||||||
|
<Route path={`${match.url}agency/:agencyId/:agencyChild`} component={AgencyItem} /> |
||||||
|
<Route exact path={`${match.url}agency`} component={AgencyList} /> |
||||||
|
|
||||||
|
<Route exact path={`${match.url}calendar/new`} component={AgencyForm} /> |
||||||
|
<Route exact path={`${match.url}calendar/:serviceId`} component={AgencyForm} /> |
||||||
|
<Route path={`${match.url}calendar/:serviceId/edit`} component={AgencyForm} /> |
||||||
|
<Route exact path={`${match.url}calendar`} component={AgencyList} /> |
||||||
|
</Switch> |
||||||
|
</div> |
||||||
|
</div> |
||||||
|
) |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
|
||||||
const mapStateToProps = state => ({ |
const mapStateToProps = state => ({ |
||||||
counter: getCounter(state.first) |
loggedIn: loggedIn(state.auth), |
||||||
|
agency: state.agency, |
||||||
}) |
}) |
||||||
export default connect( |
export default connect( |
||||||
mapStateToProps, |
mapStateToProps, |
||||||
{ incFirstCounter } |
{ } |
||||||
)(Main) |
)(Main) |
||||||
|
@ -0,0 +1,81 @@ |
|||||||
|
import React, { Component } from 'react' |
||||||
|
import { Redirect } from 'react-router-dom' |
||||||
|
import { connect } from 'react-redux' |
||||||
|
|
||||||
|
import { getToken, loggedIn } from '../reducers/auth' |
||||||
|
import { fetchAuth } from '../actions' |
||||||
|
|
||||||
|
import Login from '../components/Login' |
||||||
|
|
||||||
|
class Public extends Component { |
||||||
|
state = { |
||||||
|
email: null, password: null |
||||||
|
} |
||||||
|
constructor() { |
||||||
|
super() |
||||||
|
this.updateField = this.updateField.bind(this) |
||||||
|
this.handleFetchAuth = this.handleFetchAuth.bind(this) |
||||||
|
} |
||||||
|
|
||||||
|
updateField(evt) { |
||||||
|
const { name, value } = evt.target |
||||||
|
let newState = {} |
||||||
|
newState[name] = value |
||||||
|
this.setState(newState) |
||||||
|
} |
||||||
|
|
||||||
|
handleFetchAuth() { |
||||||
|
const { dispatch } = this.props |
||||||
|
const { email, password } = this.state |
||||||
|
dispatch(fetchAuth(email, password)) |
||||||
|
} |
||||||
|
|
||||||
|
render() { |
||||||
|
const { loggedIn } = this.props |
||||||
|
return ( |
||||||
|
<div style={{minHeight: '100vh'}} |
||||||
|
className="columns is-mobile is-centered is-desktop is-vcentered"> |
||||||
|
<div className="column is-centered is-12-mobile is-two-thirds-tablet |
||||||
|
is-half-desktop is-one-third-widescreen is-one-quarter-fullhd"> |
||||||
|
<div className="card"> |
||||||
|
<div className="card-content"> |
||||||
|
{/* {<h1 className="title">Public</h1> { props.match.params.id } |
||||||
|
<Link to={`/`}>Main</Link> |
||||||
|
<hr />} */} |
||||||
|
{loggedIn === true |
||||||
|
? <Redirect to={'/'} /> |
||||||
|
: <Login |
||||||
|
fetchAuth={this.handleFetchAuth} |
||||||
|
updateField={this.updateField} /> } |
||||||
|
{/* <hr /> */} |
||||||
|
</div> |
||||||
|
{/* <footer className="card-footer"> |
||||||
|
<p className="card-footer-item"> |
||||||
|
<span> |
||||||
|
<button className="button is-info" |
||||||
|
onClick={_ => props.fetchAuth("sipp11", "gi23ft")}> |
||||||
|
Login</button> |
||||||
|
</span> |
||||||
|
</p> |
||||||
|
</footer> */} |
||||||
|
</div> |
||||||
|
</div> |
||||||
|
</div> |
||||||
|
) |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
const mapStateToProps = state => ({ |
||||||
|
token: getToken(state.auth), |
||||||
|
loggedIn: loggedIn(state.auth), |
||||||
|
}) |
||||||
|
const mapDispatchToProps = (dispatch) => { |
||||||
|
return { |
||||||
|
dispatch, |
||||||
|
fetchAuth, |
||||||
|
} |
||||||
|
} |
||||||
|
export default connect( |
||||||
|
mapStateToProps, |
||||||
|
mapDispatchToProps, |
||||||
|
)(Public) |
@ -0,0 +1,76 @@ |
|||||||
|
import { |
||||||
|
AGENCY_CREATE, AGENCY_DELETE, AGENCY_UPDATE, |
||||||
|
AGENCY_REQUEST, AGENCY_SUCCESS, AGENCY_FAILURE, |
||||||
|
} from '../constants/ActionTypes' |
||||||
|
|
||||||
|
|
||||||
|
const agencyInitState = { |
||||||
|
results: [], |
||||||
|
next: null, |
||||||
|
count: 0, |
||||||
|
fetching: false, |
||||||
|
} |
||||||
|
const agency = (state = agencyInitState, action) => { |
||||||
|
switch(action.type) { |
||||||
|
case AGENCY_REQUEST: |
||||||
|
return { |
||||||
|
...state, |
||||||
|
fetching: true, |
||||||
|
} |
||||||
|
case AGENCY_SUCCESS: |
||||||
|
const { count, next, prev, results } = action.payload |
||||||
|
return { |
||||||
|
...state, |
||||||
|
fetching: false, |
||||||
|
count, |
||||||
|
next, |
||||||
|
results: [ |
||||||
|
...(prev ? state.results : []), |
||||||
|
...results, |
||||||
|
] |
||||||
|
} |
||||||
|
case AGENCY_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 AGENCY_CREATE: |
||||||
|
return { |
||||||
|
...state, |
||||||
|
fetching: false, |
||||||
|
count: state.count + 1, |
||||||
|
results: [ |
||||||
|
...state.results, |
||||||
|
action.payload, |
||||||
|
] |
||||||
|
} |
||||||
|
case AGENCY_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 AGENCY_FAILURE: |
||||||
|
return { |
||||||
|
...state, |
||||||
|
fetching: false, |
||||||
|
} |
||||||
|
default: |
||||||
|
return state; |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
export default agency |
@ -0,0 +1,79 @@ |
|||||||
|
import { |
||||||
|
CALENDAR_CREATE, CALENDAR_DELETE, CALENDAR_UPDATE, |
||||||
|
CALENDAR_REQUEST, CALENDAR_SUCCESS, CALENDAR_FAILURE, |
||||||
|
} from '../constants/ActionTypes' |
||||||
|
|
||||||
|
|
||||||
|
const calendarInitState = { |
||||||
|
results: [], |
||||||
|
next: null, |
||||||
|
count: 0, |
||||||
|
fetching: false, |
||||||
|
query: '', |
||||||
|
} |
||||||
|
const calendar = (state = calendarInitState, action) => { |
||||||
|
switch(action.type) { |
||||||
|
case CALENDAR_REQUEST: |
||||||
|
const { query } = action.meta |
||||||
|
return { |
||||||
|
...state, |
||||||
|
fetching: true, |
||||||
|
query, |
||||||
|
} |
||||||
|
case CALENDAR_SUCCESS: |
||||||
|
const { count, next, prev, results } = action.payload |
||||||
|
return { |
||||||
|
...state, |
||||||
|
fetching: false, |
||||||
|
count, |
||||||
|
next, |
||||||
|
results: [ |
||||||
|
...( (prev) ? state.results : [] ), |
||||||
|
...results, |
||||||
|
] |
||||||
|
} |
||||||
|
case CALENDAR_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 CALENDAR_CREATE: |
||||||
|
return { |
||||||
|
...state, |
||||||
|
fetching: false, |
||||||
|
count: state.count + 1, |
||||||
|
results: [ |
||||||
|
...state.results, |
||||||
|
action.payload, |
||||||
|
] |
||||||
|
} |
||||||
|
case CALENDAR_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 CALENDAR_FAILURE: |
||||||
|
return { |
||||||
|
...state, |
||||||
|
fetching: false, |
||||||
|
} |
||||||
|
default: |
||||||
|
return state; |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
export default calendar |
@ -0,0 +1,79 @@ |
|||||||
|
import { |
||||||
|
CALENDAR_CREATE, CALENDAR_DELETE, CALENDAR_UPDATE, |
||||||
|
CALENDAR_REQUEST, CALENDAR_SUCCESS, CALENDAR_FAILURE, |
||||||
|
} from '../constants/ActionTypes' |
||||||
|
|
||||||
|
|
||||||
|
const calendarInitState = { |
||||||
|
results: [], |
||||||
|
next: null, |
||||||
|
count: 0, |
||||||
|
fetching: false, |
||||||
|
query: '', |
||||||
|
} |
||||||
|
const calendar = (state = calendarInitState, action) => { |
||||||
|
switch(action.type) { |
||||||
|
case CALENDAR_REQUEST: |
||||||
|
const { query } = action.meta |
||||||
|
return { |
||||||
|
...state, |
||||||
|
fetching: true, |
||||||
|
query, |
||||||
|
} |
||||||
|
case CALENDAR_SUCCESS: |
||||||
|
const { count, next, prev, results } = action.payload |
||||||
|
return { |
||||||
|
...state, |
||||||
|
fetching: false, |
||||||
|
count, |
||||||
|
next, |
||||||
|
results: [ |
||||||
|
...( (prev) ? state.results : [] ), |
||||||
|
...results, |
||||||
|
] |
||||||
|
} |
||||||
|
case CALENDAR_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 CALENDAR_CREATE: |
||||||
|
return { |
||||||
|
...state, |
||||||
|
fetching: false, |
||||||
|
count: state.count + 1, |
||||||
|
results: [ |
||||||
|
...state.results, |
||||||
|
action.payload, |
||||||
|
] |
||||||
|
} |
||||||
|
case CALENDAR_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 CALENDAR_FAILURE: |
||||||
|
return { |
||||||
|
...state, |
||||||
|
fetching: false, |
||||||
|
} |
||||||
|
default: |
||||||
|
return state; |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
export default calendar |
@ -1,8 +1,14 @@ |
|||||||
import { combineReducers } from 'redux' |
import { combineReducers } from 'redux' |
||||||
import first from './first' |
import first from './first' |
||||||
import auth from './auth' |
import auth from './auth' |
||||||
|
import agency from './agency' |
||||||
|
import route from './route' |
||||||
|
import fareattr from './fareattr' |
||||||
|
|
||||||
export default combineReducers({ |
export default combineReducers({ |
||||||
auth, |
auth, |
||||||
first, |
first, |
||||||
|
agency, |
||||||
|
route, |
||||||
|
fareattr, |
||||||
}) |
}) |
||||||
|
@ -0,0 +1,79 @@ |
|||||||
|
import { |
||||||
|
ROUTE_CREATE, ROUTE_DELETE, ROUTE_UPDATE, |
||||||
|
ROUTE_REQUEST, ROUTE_SUCCESS, ROUTE_FAILURE, |
||||||
|
} from '../constants/ActionTypes' |
||||||
|
|
||||||
|
|
||||||
|
const routeInitState = { |
||||||
|
results: [], |
||||||
|
next: null, |
||||||
|
count: 0, |
||||||
|
fetching: false, |
||||||
|
query: '', |
||||||
|
} |
||||||
|
const route = (state = routeInitState, action) => { |
||||||
|
switch(action.type) { |
||||||
|
case ROUTE_REQUEST: |
||||||
|
const { query } = action.meta |
||||||
|
return { |
||||||
|
...state, |
||||||
|
fetching: true, |
||||||
|
query, |
||||||
|
} |
||||||
|
case ROUTE_SUCCESS: |
||||||
|
const { count, next, prev, results } = action.payload |
||||||
|
return { |
||||||
|
...state, |
||||||
|
fetching: false, |
||||||
|
count, |
||||||
|
next, |
||||||
|
results: [ |
||||||
|
...( (prev) ? state.results : [] ), |
||||||
|
...results, |
||||||
|
] |
||||||
|
} |
||||||
|
case ROUTE_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 ROUTE_CREATE: |
||||||
|
return { |
||||||
|
...state, |
||||||
|
fetching: false, |
||||||
|
count: state.count + 1, |
||||||
|
results: [ |
||||||
|
...state.results, |
||||||
|
action.payload, |
||||||
|
] |
||||||
|
} |
||||||
|
case ROUTE_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 ROUTE_FAILURE: |
||||||
|
return { |
||||||
|
...state, |
||||||
|
fetching: false, |
||||||
|
} |
||||||
|
default: |
||||||
|
return state; |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
export default route |
@ -1,12 +1,20 @@ |
|||||||
import axios from 'axios' |
import axios from 'axios' |
||||||
import store from '../store' |
import store from '../store' |
||||||
import { URL } from '../config/Api' |
import { URL, API_PREFIX } from '../constants/Api' |
||||||
|
|
||||||
export const apiClient = function() { |
export const apiClient = function(url) { |
||||||
const token = store.getState().token |
const token = store.getState().auth.token |
||||||
const params = { |
const params = { |
||||||
baseURL: URL, |
baseURL: `${URL}${API_PREFIX}${url}`, |
||||||
headers: {'Authorization': 'Token ' + token} |
headers: {'Authorization': 'Bearer ' + token} |
||||||
} |
} |
||||||
return axios.create(params) |
return axios.get(params) |
||||||
} |
} |
||||||
|
|
||||||
|
export const RSAAHeaders = () => { |
||||||
|
const token = store.getState().auth.token |
||||||
|
return { |
||||||
|
'Content-Type': 'application/json', |
||||||
|
'Authorization': 'Bearer ' + token, |
||||||
|
} |
||||||
|
} |
||||||
|
Loading…
Reference in new issue