Browse Source

Partial Bike table and edit modal.

feature/bike-tracking
Drew Larson 7 years ago
parent
commit
ea0b2b1052
  1. 110
      bikeshop_project/assets/js/bikes/components/BikeModal/index.jsx
  2. 104
      bikeshop_project/assets/js/bikes/components/BikeTable/index.jsx
  3. 47
      bikeshop_project/assets/js/bikes/components/Size/index.jsx
  4. 44
      bikeshop_project/assets/js/bikes/components/Source/index.jsx
  5. 11
      bikeshop_project/assets/js/bikes/index.jsx

110
bikeshop_project/assets/js/bikes/components/BikeModal/index.jsx

@ -0,0 +1,110 @@
import React from 'react';
import Dialog from 'material-ui/Dialog';
import FlatButton from 'material-ui/FlatButton';
import TextField from 'material-ui/TextField';
import DatePicker from 'material-ui/DatePicker';
import RaisedButton from 'material-ui/RaisedButton';
import moment from 'moment-timezone';
import Size from '../Size';
import Source from '../Source';
import Checkbox from 'material-ui/Checkbox';
/**
* A modal dialog can only be closed by selecting one of the actions.
*/
export default class BikeModal extends React.Component {
constructor(props) {
super(props);
this.state = {
open: props.open,
bike: undefined,
};
}
componentWillReceiveProps(newProps) {
this.setState({ open: newProps.open || false, bike: newProps.bike || false });
}
handleClose = () => {
this.setState({ open: false });
};
render() {
const styles = {
block: {
maxWidth: 250,
},
checkbox: {
marginBottom: 16,
},
};
const actions = [
<FlatButton
label="Cancel"
primary
onTouchTap={this.handleClose}
/>,
<FlatButton
label="Submit"
primary
disabled
onTouchTap={this.handleClose}
/>,
];
let form;
if (this.state.bike !== undefined) {
const timezone = moment.tz.guess();
const {
make,
price,
claimed_at,
claimed_by,
colour,
cpic_searched_at,
created_at,
size,
serial_number,
source,
stripped } = this.state.bike;
const createdAtFormatted = moment(created_at).tz(timezone).fromNow();
form = (
<div>
<TextField label={'Blah'} value={make} /><TextField label="Price" value={price} /><br />
<TextField label="Claimed on" value={claimed_at} /><TextField label="Claimed by" value={claimed_by} /><br />
<TextField label="Colour" value={colour} /><br />
<TextField label="CPIC Searched on" value={cpic_searched_at} /><br />
<TextField label="Created at" value={createdAtFormatted} readOnly disabled /><br />
<Size size={size} />
<TextField label="Serial number" value={serial_number} />
<Source source={source} />
<div style={styles.block}>
<Checkbox
label="Stripped"
labelPosition="left"
style={styles.checkbox}
value={stripped}
/>
</div>
</div>
);
}
return (
<div>
<Dialog
title="Edit Bike"
actions={actions}
modal={true}
open={this.state.open}
>
{(form) ? form : <div>Unable to edit bike.</div>}
</Dialog>
</div>
);
}
}

104
bikeshop_project/assets/js/bikes/components/BikeTable/index.jsx

@ -0,0 +1,104 @@
import React from 'react';
import { polyFill } from 'es6-promise';
import moment from 'moment-timezone';
import fetch from 'isomorphic-fetch';
import { Table, TableBody, TableHeader, TableHeaderColumn, TableRow, TableRowColumn } from 'material-ui/Table';
import FlatButton from 'material-ui/FlatButton';
import { friendlySize } from '../Size';
import BikeModal from '../BikeModal';
function checkStatus(response) {
if (response.status >= 200 && response.status < 300) {
return response;
}
const error = new Error(response.statusText);
error.response = response;
throw error;
}
function parseJSON(response) {
return response.json();
}
export default class BikeTable extends React.Component {
constructor(props) {
super(props);
this.state = {
bikes: [],
bikeModal: {
open: false,
bike: undefined,
},
};
this.handleEditBike = this.handleEditBike.bind(this);
}
componentDidMount() {
fetch('/api/v1/bikes/')
.then(checkStatus)
.then(parseJSON)
.then((data) => {
this.setState({ bikes: data });
console.log('request succeeded with JSON response', data);
})
.catch((error) => {
console.log('request failed', error);
});
}
handleEditBike(bike) {
console.log('Bike edit!');
this.setState({
bikeModal: {
open: true,
bike,
},
});
}
render() {
const bikeRows = this.state.bikes.map(bike => (
<TableRow selectable={false} key={bike.id}>
<TableRowColumn>{friendlySize(bike.size)}</TableRowColumn>
<TableRowColumn>{bike.colour}</TableRowColumn>
<TableRowColumn>{bike.make}</TableRowColumn>
<TableRowColumn>{bike.serial_number}</TableRowColumn>
<TableRowColumn>{bike.state}</TableRowColumn>
<TableRowColumn>{bike.claimed_by}</TableRowColumn>
<TableRowColumn><FlatButton label="Edit" primary onTouchTap={this.handleEditBike.bind(null, bike)} /></TableRowColumn>
</TableRow>
));
return (
<div className="mdl-grid">
<div className="mdl-cell mdl-cell--12-col">
<h3>Bikes</h3>
<Table selectable={false}>
<TableHeader adjustForCheckbox={false} displaySelectAll={false}>
<TableRow>
<TableHeaderColumn>Size</TableHeaderColumn>
<TableHeaderColumn>Colour</TableHeaderColumn>
<TableHeaderColumn>Make</TableHeaderColumn>
<TableHeaderColumn>Serial number</TableHeaderColumn>
<TableHeaderColumn>State</TableHeaderColumn>
<TableHeaderColumn>Claimed by</TableHeaderColumn>
<TableRowColumn />
</TableRow>
</TableHeader>
<TableBody displayRowCheckbox={false}>
{bikeRows.length ?
bikeRows :
<TableRow>
<TableRowColumn>{'No members currently signed in.'}</TableRowColumn>
</TableRow>
}
</TableBody>
</Table>
<BikeModal bike={this.state.bikeModal.bike} open={this.state.bikeModal.open} />
</div>
</div>
);
}
}

47
bikeshop_project/assets/js/bikes/components/Size/index.jsx

@ -0,0 +1,47 @@
import React, { PropTypes } from 'react';
import SelectField from 'material-ui/SelectField';
import MenuItem from 'material-ui/MenuItem';
const sizes = ['C', 'S', 'M', 'L', 'XL'];
export const friendlySize = (size) => {
switch (size) {
case 'C':
return 'child';
case 'S':
return 'small';
case 'M':
return 'medium';
case 'L':
return 'large';
case 'XL':
return 'extra large';
default:
return 'unknown';
}
};
const Size = ({ size }) => {
const items = sizes.map(s =>
<MenuItem value={s} primaryText={friendlySize(s)} />,
);
return (
<div>
<SelectField
floatingLabelText="Size"
value={size}
onChange={undefined}
>
<MenuItem value={null} primaryText="" />
{items}
</SelectField>
</div>
);
};
Size.propTypes = {
size: PropTypes.string,
};
export default Size;

44
bikeshop_project/assets/js/bikes/components/Source/index.jsx

@ -0,0 +1,44 @@
import React, { PropTypes } from 'react';
import SelectField from 'material-ui/SelectField';
import MenuItem from 'material-ui/MenuItem';
const sources = ['COS_BIKE_DIVERSION_PILOT', 'UOFS', 'DROP_OFF'];
export const friendly = (s) => {
switch (s) {
case 'COS_BIKE_DIVERSION_PILOT':
return 'City of Saskatoon Bike Diversion Pilot';
case 'UOFS':
return 'University of Saskatchewan';
case 'DROP_OFF':
return 'Drop Off';
default:
return undefined;
};
};
const Source = ({ source }) => {
const items = sources.map(s =>
<MenuItem value={s} primaryText={friendly(s)} />,
);
return (
<div>
<SelectField
floatingLabelText="Source"
value={source}
onChange={undefined}
autoWidth={true}
>
<MenuItem value={null} primaryText="" />
{items}
</SelectField>
</div>
);
};
Source.propTypes = {
source: PropTypes.string,
};
export default Source;

11
bikeshop_project/assets/js/bikes/index.jsx

@ -1,6 +1,9 @@
import React from 'react';
import ReactDOM from 'react-dom';
import injectTapEventPlugin from 'react-tap-event-plugin';
import getMuiTheme from 'material-ui/styles/getMuiTheme';
import MuiThemeProvider from 'material-ui/styles/MuiThemeProvider';
import BikeTable from './components/BikeTable';
// Needed for onTouchTap
// http://stackoverflow.com/a/34015469/988941
@ -10,11 +13,9 @@ injectTapEventPlugin();
class App extends React.Component {
render() {
return (
<div className="mdl-grid">
<div className="mdl-cell mdl-cell--12-col">
<h1>Bikes</h1>
</div>
</div>
<MuiThemeProvider muiTheme={getMuiTheme()}>
<BikeTable/>
</MuiThemeProvider>
);
}
}

Loading…
Cancel
Save