mirror of
https://github.com/fspc/workstand.git
synced 2025-02-23 17:23:24 -05:00
Display available states.
This commit is contained in:
parent
a28fe8bb2d
commit
4af8c055e3
@ -4,7 +4,7 @@ import { connect } from 'react-redux';
|
|||||||
import FlatButton from 'material-ui/FlatButton';
|
import FlatButton from 'material-ui/FlatButton';
|
||||||
import RaisedButton from 'material-ui/RaisedButton';
|
import RaisedButton from 'material-ui/RaisedButton';
|
||||||
import Size from '../Size';
|
import Size from '../Size';
|
||||||
import { renderCheckbox, renderSelectField, renderTextField, sourceMenuItems } from './utils';
|
import { renderCheckbox, renderSelectField, renderTextField, sourceMenuItems, stateMenuItems, getRequiredFields } from './utils';
|
||||||
import { updateBike, saveBike, checkCpic } from '../../actions';
|
import { updateBike, saveBike, checkCpic } from '../../actions';
|
||||||
|
|
||||||
const styles = {
|
const styles = {
|
||||||
@ -19,15 +19,20 @@ const styles = {
|
|||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
const validate = (values) => {
|
const validate = (values, props) => {
|
||||||
const errors = {};
|
const errors = {};
|
||||||
const requiredFields = ['make', 'colour', 'size', 'serial_number', 'donation_source'];
|
console.log(values);
|
||||||
|
const requiredFields = getRequiredFields(values.new_state);
|
||||||
|
|
||||||
requiredFields.forEach((field) => {
|
requiredFields.forEach((field) => {
|
||||||
if (!values[field]) {
|
if (!values[field]) {
|
||||||
errors[field] = 'Required';
|
errors[field] = 'Required';
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
if (!props.availableStates.includes(values.new_state)) {
|
||||||
|
errors['new_state'] = `${values.new_state} is not allowed.`;
|
||||||
|
}
|
||||||
return errors;
|
return errors;
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -43,11 +48,22 @@ const handleSubmit = (data, dispatch, props) => {
|
|||||||
|
|
||||||
class BikeForm extends React.Component {
|
class BikeForm extends React.Component {
|
||||||
render() {
|
render() {
|
||||||
const { create } = this.props;
|
const { create, cpicSearched, id, availableStates, currentState } = this.props;
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div>
|
<div>
|
||||||
<form onSubmit={this.props.handleSubmit}>
|
<form onSubmit={this.props.handleSubmit}>
|
||||||
|
<div className="mdl-grid">
|
||||||
|
<div className="mdl-cell mdl-cell--3-col">
|
||||||
|
<Field
|
||||||
|
name="new_state"
|
||||||
|
component={renderSelectField}
|
||||||
|
floatingLabelText="State"
|
||||||
|
fullWidth
|
||||||
|
>
|
||||||
|
{stateMenuItems([currentState].concat(availableStates))}
|
||||||
|
</Field>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
<div className="mdl-grid">
|
<div className="mdl-grid">
|
||||||
<div className="mdl-cell mdl-cell--3-col">
|
<div className="mdl-cell mdl-cell--3-col">
|
||||||
<Field
|
<Field
|
||||||
@ -98,7 +114,6 @@ class BikeForm extends React.Component {
|
|||||||
floatingLabelText="Created at"
|
floatingLabelText="Created at"
|
||||||
fullWidth
|
fullWidth
|
||||||
readOnly
|
readOnly
|
||||||
disabled
|
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
}
|
}
|
||||||
@ -126,7 +141,6 @@ class BikeForm extends React.Component {
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
}
|
}
|
||||||
|
|
||||||
{!create &&
|
{!create &&
|
||||||
<div className="content-grid mdl-grid" style={styles.bottom}>
|
<div className="content-grid mdl-grid" style={styles.bottom}>
|
||||||
<div className="mdl-cell mdl-cell--6-col">
|
<div className="mdl-cell mdl-cell--6-col">
|
||||||
@ -134,7 +148,7 @@ class BikeForm extends React.Component {
|
|||||||
name="cpic_searched_at"
|
name="cpic_searched_at"
|
||||||
component={renderTextField}
|
component={renderTextField}
|
||||||
floatingLabelText="CPIC searched"
|
floatingLabelText="CPIC searched"
|
||||||
disabled
|
readOnly
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
<div className="mdl-cell mdl-cell--4-col">
|
<div className="mdl-cell mdl-cell--4-col">
|
||||||
@ -149,7 +163,7 @@ class BikeForm extends React.Component {
|
|||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
<div className="mdl-cell mdl-cell--2-col">
|
<div className="mdl-cell mdl-cell--2-col">
|
||||||
<FlatButton label="Check" onTouchTap={() => this.props.checkCpic(this.props.id)} disabled={!!this.props.cpic_searched} primary />
|
<FlatButton label="Check" onTouchTap={() => this.props.checkCpic(id)} disabled={cpicSearched} primary />
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
}
|
}
|
||||||
@ -196,15 +210,17 @@ BikeForm = reduxForm({
|
|||||||
onSubmit: handleSubmit,
|
onSubmit: handleSubmit,
|
||||||
})(BikeForm);
|
})(BikeForm);
|
||||||
|
|
||||||
const selector = formValueSelector('BikeForm')
|
|
||||||
|
|
||||||
BikeForm = connect(
|
BikeForm = connect(
|
||||||
state => ({
|
state => {
|
||||||
initialValues: state.bikes.form.bike, // pull initial values from account reducer
|
return {
|
||||||
create: state.bikes.form.create,
|
initialValues: {...state.bikes.form.bike, new_state: state.bikes.form.bike.state.toLowerCase()}, // pull initial values from account reducer
|
||||||
cpic_searched: selector(state, 'cpic_searched_at'),
|
create: state.bikes.form.create,
|
||||||
id: selector(state, 'id'),
|
cpicSearched: !!state.bikes.form.bike.cpic_searched_at,
|
||||||
}),
|
id: state.bikes.form.bike.id,
|
||||||
|
availableStates: state.bikes.form.bike.available_states,
|
||||||
|
currentState: state.bikes.form.bike.state.toLowerCase(),
|
||||||
|
};
|
||||||
|
},
|
||||||
dispatch => ({
|
dispatch => ({
|
||||||
checkCpic: id => dispatch(checkCpic(id)),
|
checkCpic: id => dispatch(checkCpic(id)),
|
||||||
}),
|
}),
|
||||||
|
@ -1,3 +1,4 @@
|
|||||||
|
import moment from 'moment';
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
import Checkbox from 'material-ui/Checkbox';
|
import Checkbox from 'material-ui/Checkbox';
|
||||||
import MenuItem from 'material-ui/MenuItem';
|
import MenuItem from 'material-ui/MenuItem';
|
||||||
@ -6,7 +7,7 @@ import TextField from 'material-ui/TextField';
|
|||||||
|
|
||||||
const sources = ['COS_BIKE_DIVERSION_PILOT', 'UOFS', 'DROP_OFF'];
|
const sources = ['COS_BIKE_DIVERSION_PILOT', 'UOFS', 'DROP_OFF'];
|
||||||
|
|
||||||
const friendly = (s) => {
|
const friendlySources = (s) => {
|
||||||
switch (s) {
|
switch (s) {
|
||||||
case 'COS_BIKE_DIVERSION_PILOT':
|
case 'COS_BIKE_DIVERSION_PILOT':
|
||||||
return 'City of Saskatoon Bike Diversion Pilot';
|
return 'City of Saskatoon Bike Diversion Pilot';
|
||||||
@ -19,8 +20,61 @@ const friendly = (s) => {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const states = ['received', 'assessed', 'available', 'claimed', 'purchased', 'scrapped', 'transferred_to_police'];
|
||||||
|
const friendlStates = (s) => {
|
||||||
|
switch (s) {
|
||||||
|
case 'received':
|
||||||
|
return 'Received';
|
||||||
|
case 'assessed':
|
||||||
|
return 'Assessed';
|
||||||
|
case 'available':
|
||||||
|
return 'Available';
|
||||||
|
case 'claimed':
|
||||||
|
return 'Claimed';
|
||||||
|
case 'purchased':
|
||||||
|
return 'Purchased';
|
||||||
|
case 'scrapped':
|
||||||
|
return 'Scrapped';
|
||||||
|
case 'transferred_to_police':
|
||||||
|
return 'Transferred to police';
|
||||||
|
default:
|
||||||
|
throw Error(`${s} is not an allowed state.`)
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
export const getRequiredFields = (bikeState) => {
|
||||||
|
switch (bikeState) {
|
||||||
|
case 'received':
|
||||||
|
return ['make', 'colour', 'size', 'serial_number', 'donation_source'];
|
||||||
|
case 'assessed':
|
||||||
|
return ['make', 'colour', 'size', 'serial_number', 'donation_source', 'price'];
|
||||||
|
case 'available':
|
||||||
|
return ['make', 'colour', 'size', 'serial_number', 'donation_source', 'price', 'stolen', 'cpic_searched'];
|
||||||
|
case 'claimed':
|
||||||
|
return ['make', 'colour', 'size', 'serial_number', 'donation_source', 'price', 'stolen', 'cpic_searched'];
|
||||||
|
case 'purchased':
|
||||||
|
return ['make', 'colour', 'size', 'serial_number', 'donation_source', 'price', 'stolen', 'cpic_searched'];
|
||||||
|
case 'scrapped':
|
||||||
|
return ['make', 'colour', 'size', 'serial_number', 'donation_source', 'cpic_searched'];
|
||||||
|
case 'transferred_to_police':
|
||||||
|
return ['make', 'colour', 'size', 'serial_number', 'donation_source', 'cpic_searched'];
|
||||||
|
default:
|
||||||
|
throw new Error(`${bikeState} is an invalid state.`);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const canAvailable = (stolen, cpicSearched) => !stolen && cpicSearched;
|
||||||
|
const canClaim = (claimedBy, lastWorkedOn) => !claimedBy || lastWorkedOn.isAfter(moment().add(4, 'weeks'));
|
||||||
|
const canPurchase = canClaim;
|
||||||
|
const canScrap = (stripped, claim) => stripped && claim;
|
||||||
|
const canTransferToPolice = stolen => stolen;
|
||||||
|
|
||||||
|
export const stateMenuItems = availableStates => states
|
||||||
|
.filter(s => availableStates.includes(s))
|
||||||
|
.map(s => <MenuItem key={s} value={s} primaryText={friendlStates(s)} />);
|
||||||
|
|
||||||
export const sourceMenuItems = sources.map(s =>
|
export const sourceMenuItems = sources.map(s =>
|
||||||
<MenuItem key={s} value={s} primaryText={friendly(s)} />,
|
<MenuItem key={s} value={s} primaryText={friendlySources(s)} />,
|
||||||
);
|
);
|
||||||
|
|
||||||
export const renderTextField = ({ input, meta: { touched, error }, ...custom }) => (
|
export const renderTextField = ({ input, meta: { touched, error }, ...custom }) => (
|
||||||
|
@ -22,7 +22,6 @@ class BikeModal extends React.Component {
|
|||||||
>
|
>
|
||||||
<BikeForm
|
<BikeForm
|
||||||
handleModalClose={this.props.handleClose}
|
handleModalClose={this.props.handleClose}
|
||||||
enableReinitialize
|
|
||||||
/>
|
/>
|
||||||
</Dialog>
|
</Dialog>
|
||||||
)
|
)
|
||||||
|
@ -104,7 +104,6 @@ class SignedInList extends React.Component {
|
|||||||
}
|
}
|
||||||
</TableBody>
|
</TableBody>
|
||||||
</Table>
|
</Table>
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user