-
Notifications
You must be signed in to change notification settings - Fork 0
# Step 08 — AddReading component
Gerald Goh edited this page Aug 11, 2020
·
1 revision
app/javascript/components/Head.jsx
import React from 'react';
const Head = () => (
<div>
<nav className="navbar navbar-inverse bg-blue fixed-top">
<h1 className="navbar-brand abs">Add Reading</h1>
</nav>
</div>
);
export default Head;
app/javascript/components/ReadingForm.jsx
/* eslint-disable react/destructuring-assignment, react/no-unused-state */
import React from 'react';
import axios from 'axios';
import { withRouter } from 'react-router-dom';
import PropTypes from 'prop-types';
import {
Bedroom,
Study,
Garage,
Living,
Kitchen,
Guest,
} from './Rooms';
class ReadingForm extends React.Component {
constructor(props) {
super(props);
const defaultState = {
currentStep: 1,
bedroom: '',
study: '',
garage: '',
living: '',
kitchen: '',
guest: '',
units: '',
quota: '',
};
this.state = defaultState;
this.handleChange = this.handleChange.bind(this);
this.handleSubmit = this.handleSubmit.bind(this);
this.prev = this.prev.bind(this);
this.next = this.next.bind(this);
}
componentDidMount() {
const userID = JSON.parse(localStorage.getItem('redux')).id;
const { units } = this.state;
axios.get(`/api/v1/users/${userID}`, { units })
.then((response) => response.data)
.then((response) => {
if (response.code === 200) {
this.setState({
units: response.data.units,
quota: (Number(response.data.units) / 30) / 6,
});
} else if (response.code === 401) {
this.setState({
errors: response.errors,
});
}
});
}
handleChange(event) {
const { name, value } = event.target;
this.setState({
[name]: value,
});
}
handleSubmit(event) {
event.preventDefault();
const {
bedroom, study, garage, living, kitchen, guest, units,
} = this.state;
const consumption = Number(bedroom)
+ Number(study)
+ Number(garage)
+ Number(living)
+ Number(kitchen)
+ Number(guest);
const available = (units / 30) - consumption;
const saved = Math.floor(100 - (100 * (consumption / (units / 30))));
axios.post('/api/v1/readings', {
bedroom, study, garage, living, kitchen, guest, consumption, available, saved,
})
.then((response) => response.data)
.then((response) => {
if (response.code === 400) {
this.setState({
errors: response.errors,
});
} else if (response.code === 200) {
this.setState({
bedroom: '',
study: '',
garage: '',
living: '',
kitchen: '',
consumption: '',
available: '',
saved: '',
});
this.props.history.push('/readings');
}
});
}
next() {
let { currentStep } = this.state;
currentStep = currentStep === 6 ? 6 : currentStep + 1;
this.setState({
currentStep,
});
}
prev() {
let { currentStep } = this.state;
currentStep = currentStep === 1 ? 1 : currentStep - 1;
this.setState({
currentStep,
});
}
previousButton() {
const { currentStep } = this.state;
if (currentStep !== 1) {
return (
<button
type="button"
id="prevBtn"
onClick={this.prev}
>
Previous
</button>
);
}
return null;
}
nextButton() {
const { currentStep } = this.state;
if (currentStep < 6) {
return (
<button
type="button"
id="nextBtn"
onClick={this.next}
>
Next
</button>
);
}
return null;
}
render() {
return (
<>
<form id="regForm" onSubmit={this.handleSubmit}>
<Bedroom
currentStep={this.state.currentStep}
quota={this.state.quota}
handleChange={this.handleChange}
bedroom={this.state.bedroom}
/>
<Study
currentStep={this.state.currentStep}
quota={this.state.quota}
handleChange={this.handleChange}
study={this.state.study}
/>
<Garage
currentStep={this.state.currentStep}
quota={this.state.quota}
handleChange={this.handleChange}
garage={this.state.garage}
/>
<Living
currentStep={this.state.currentStep}
quota={this.state.quota}
handleChange={this.handleChange}
living={this.state.living}
/>
<Kitchen
currentStep={this.state.currentStep}
quota={this.state.quota}
handleChange={this.handleChange}
kitchen={this.state.kitchen}
/>
<Guest
currentStep={this.state.currentStep}
quota={this.state.quota}
handleChange={this.handleChange}
guest={this.state.guest}
/>
<div className="row justify-content-center btn-box">
{this.previousButton()}
{this.nextButton()}
</div>
</form>
</>
);
}
}
ReadingForm.propTypes = {
// eslint-disable-next-line react/forbid-prop-types
history: PropTypes.object.isRequired,
};
export default withRouter(ReadingForm);
app/javascript/components/Rooms.jsx
import React from 'react';
import InputGraph from '../graph/InputGraph'
export function Bedroom(props) {
if (props.currentStep !== 1) {
return null
}
return(
<React.Fragment>
<div className="row justify-content-center">
<div className="row justify-content-center reading-header">
<h4>Take your Bedroom Reading</h4>
</div>
<div className="graph-content">
<InputGraph strokeWidth={2} percentage={props.bedroom} />
</div>
</div>
<div className="row justify-content-center reading-input">
<input
className="form-control"
id="bedroom"
name="bedroom"
type="number"
placeholder="Enter bedroom reading"
value={props.bedroom}
onChange={props.handleChange}
/>
</div>
</React.Fragment>
);
}
export function Study(props) {
if (props.currentStep !== 2) {
return null
}
return(
<React.Fragment>
<div className="row justify-content-center">
<div className="row justify-content-center reading-header">
<h4>Take your Study room Reading</h4>
</div>
<div className="graph-content">
<InputGraph strokeWidth={2} percentage={props.study} />
</div>
</div>
<div className="row justify-content-center reading-input">
<input
className="form-control"
id="study"
name="study"
type="number"
placeholder="Enter study reading"
value={props.study}
onChange={props.handleChange}
/>
</div>
</React.Fragment>
);
}
export function Garage(props) {
if (props.currentStep !== 3) {
return null
}
return(
<React.Fragment>
<div className="row justify-content-center">
<div className="row justify-content-center reading-header">
<h4>Take your Garage Reading</h4>
</div>
<div className="graph-content">
<InputGraph strokeWidth={2} percentage={props.garage} />
</div>
</div>
<div className="row justify-content-center reading-input">
<input
className="form-control"
id="garage"
name="garage"
type="number"
placeholder="Enter garage reading"
value={props.garage}
onChange={props.handleChange}
/>
</div>
</React.Fragment>
);
}
export function Living(props) {
if (props.currentStep !== 4) {
return null
}
return(
<React.Fragment>
<div className="row justify-content-center">
<div className="row justify-content-center reading-header">
<h4>Take your Living Room Reading</h4>
</div>
<div className="graph-content">
<InputGraph strokeWidth={2} percentage={props.living} />
</div>
</div>
<div className="row justify-content-center reading-input">
<input
className="form-control"
id="living"
name="living"
type="number"
placeholder="Enter living reading"
value={props.living}
onChange={props.handleChange}
/>
</div>
</React.Fragment>
);
}
export function Kitchen(props) {
if (props.currentStep !== 5) {
return null
}
return(
<React.Fragment>
<div className="row justify-content-center">
<div className="row justify-content-center reading-header">
<h4>Take your Kitchen Reading</h4>
</div>
<div className="graph-content">
<InputGraph strokeWidth={2} percentage={props.kitchen} />
</div>
</div>
<div className="row justify-content-center reading-input">
<input
className="form-control"
id="kitchen"
name="kitchen"
type="number"
placeholder="Enter kitchen reading"
value={props.kitchen}
onChange={props.handleChange}
/>
</div>
</React.Fragment>
);
}
export function Guest(props) {
if (props.currentStep !== 6) {
return null
}
return(
<React.Fragment>
<div className="row justify-content-center">
<div className="row justify-content-center reading-header">
<h4>Take your Guest Room Reading</h4>
</div>
<div className="graph-content">
<InputGraph strokeWidth={2} percentage={props.guest} />
</div>
</div>
<div className="row justify-content-center reading-input">
<input
className="form-control"
id="guest"
name="guest"
type="number"
placeholder="Enter guest reading"
value={props.guest}
onChange={props.handleChange}
/>
</div>
<button className="btn btn-success btn-block">Submit</button>
</React.Fragment>
);
}
app/javascript/components/graph/InputGraph.jsx
import React from 'react';
const InputGraph = ({ strokeWidth, percentage }) => {
const radius = (50 - strokeWidth / 2);
const pathDescription = `
M 50,50 m 0,-${radius}
a ${radius},${radius} 0 1 1 0,${2 * radius}
a ${radius},${radius} 0 1 1 0,-${2 * radius}
`;
const diameter = Math.PI * 2 * radius;
const progressStyle = {
stroke: '#42B5E8',
strokeLinecap: 'round',
strokeDasharray: `${diameter}px ${diameter}px`,
strokeDashoffset: `${((100 - percentage) / 100 * diameter)}px`,
};
return (
<svg
className={'CircularProgressbar'}
viewBox="0 0 100 100"
width={300}
height={300}
>
<path
className="CircularProgressbar-trail"
d={pathDescription}
strokeWidth={strokeWidth}
fillOpacity={0}
style={{
stroke: '#FFFFFF',
}}
/>
<path
className="CircularProgressbar-path"
d={pathDescription}
strokeWidth={strokeWidth}
fillOpacity={0}
style={progressStyle}
/>
<text
className="CircularProgressbar-text"
x={50}
y={50}
style={{
fill: '#007dbc',
fontSize: '14px',
dominantBaseline: 'central',
textAnchor: 'middle',
}}
>
{`${percentage} Units`}
</text>
</svg>
);
};
export default InputGraph;
app/javascript/containers/AddReading.jsx
import React from 'react';
import Head from '../components/addReading/Head';
import ReadingForm from '../components/addReading/ReadingForm';
import Navbar from '../components/Navbar';
export default () => (
<div>
<Head />
<ReadingForm />
<Navbar />
</div>
);
app/javascript/routes/index.jsx
import React from 'react';
import { BrowserRouter as Router, Route, Switch } from 'react-router-dom';
import Home from '../containers/Home';
import Readings from '../containers/Readings';
import AddReading from '../containers/AddReading';
import reducer from "../reducer/sessions"
import { Provider } from "react-redux"
import { compose, createStore } from 'redux';
import persistState from 'redux-localstorage'
import PrivateRoute from "./privateRoute"
const store = createStore(
reducer, compose(persistState())
)
export default (
<Provider store={store}>
<Router>
<Switch>
<Route path="/" exact component={Home} />
<Route path="/addreading" component={AddReading} />
<PrivateRoute path="/readings" component={Readings} />
</Switch>
</Router>
</Provider>
);
export {store};
app/assets/stylesheets/custom.css.scss
.
.
.graph-content {
margin: 10% 0 10% 0;
}
.reading-input {
margin: 5% 0 5% 0;
}
.
.