React Weather Practice

by YangHax

HTML

<script src="https://cdnjs.cloudflare.com/ajax/libs/redux/4.0.5/redux.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-redux/7.2.0/react-redux.min.js"></script>
<div id="app"></div>

<!--
•	Build form control with the following. Label : “Enter City”, Input form field, Submit Button. Button should be custom built and re-usable.
•	Build weather details component. It should show the current Date, City Name, Current time & temperature details. “Begin with Static Data and later bind with JSON dynamic data”
•	Retrieve weather data from JSON service (API). Use Redux Store for the Data management. Parse the content to respective UI components.
•	Weather Details should be updated based on the City name entered in the form control.
•	Build “5 Day Weather” Button by re-using the button component which was created earlier.
•	Implement new page which shows 5 day weather Details. Create an event to “5 Day Weather” button to take to 5 Day weather details page.
•	Enhance Weather details UI component. Component should be divided into 3 small re-usable components. Date Display, City & current time, Temperature. Show the Visual screen to the candidate 
•	5 Day Weather details page should contain a data grid which shows the 5 day weather info. Temperature component should be reused and rendered in each cell. Show the visual design to the candidate.
-->

<script type="text/javascript">
	const data = {
	"States": {
		"IL": {
			"currentdate": "04/05/2019",
			"time": "02:59 PM",
			"cities": [{
					"name": "Chicago",
					"forecast": [{
							"Date": "04/05/2019",
							"Time": "2.59pm",
							"temprature": 47,
							"feels": 40
						},
						{
							"Date": "04/06/2019",
							"Time": "2.59pm",
							"temprature": 57,
							"feels": 55
						},
						{
							"Date": "04/07/2019",
							"Time": "2.59pm",
							"temprature": 45,
							"feels": 44
						},
						{
							"Date": "04/08/2019",
							"Time": "2.59pm",
							"temprature":...

CSS

body {
  background: #20262E;
  padding: 20px;
  font-family: Helvetica;
}

#app {
  background: #fff;
  border-radius: 4px;
  padding: 20px;
  transition: all 0.2s;
}

li {
  margin: 8px 0;
}

h2 {
  font-weight: bold;
  margin-bottom: 15px;
}

.done {
  color: rgba(0, 0, 0, 0.3);
  text-decoration: line-through;
}

input {
  margin-right: 5px;
}

.date-card {
  display: inline-block;
  background: #4caf50;
  margin: 5px;
  padding: 5px;
  box-shadow: gray 1px 2px 4px;
}

React

class WeatherApp extends React.Component {
  constructor(props) {
    super(props)
    this.state = {
    	city: undefined,
      hasSearched: false
    }
  }
  
  render() {
    return (
      <div>
        <h2>Weather App</h2>
        <input 
          ref="cityInput" 
          placeholder="Enter City"
          onKeyDown={e => e.key === 'Enter' && this.onSubmit()}
        />
        <WeatherButton onSubmit={_ => this.onSubmit()} />
        {this.state.hasSearched && !this.state.city ? <div>City not found</div> : null}
        {this.state.city ? <WeatherDetails city={this.state.city} /> : null}
      </div>
    )
  }
  
  onSubmit() {
    this.setState({ hasSearched: true });
  	const cityName = this.refs.cityInput.value;
    if (cityName) this.setState({ city: this.findCity(cityName) });
  }
  
  findCity(name) {
  	const mathcRegExp = new RegExp(`^${name}$`,'i');
    let foundCity = null;
    for (let iState in data.States ) {
      data.States[iState].cities.forEach(city => {
        if (city.name.match(mathcRegExp)) {
          foundCity = city;
          return false;
        }
      });
    }
    return foundCity;
  }
}

const WeatherButton = props => (
	<input type="submit" 
    onClick={_ => props.onSubmit()}
  />);

class WeatherDetails extends React.Component {

	render() {    
  	return (
    	<div>
        Weather data for <b>{this.props.city.name}</b>:
        {this.props.city.forecast.map((forecast,i) => 
          <WeatherDayCard
            key={i}
            Date={forecast.Date}
            Time={forecast.Time}
            temprature={forecast.temprature}
            feels={forecast.feels}
            />)}
      </div>
    );
  }

}

const WeatherDayCard = props => (
  <div className="date-card">
    <div>Date: {props.Date}</div>
    <div>Current Time: {props.Time}</div>
    <div>Currently {props.temprature} F / Feels {props.feels} F </div>
  </div>
);

ReactDOM.render(<WeatherApp />, document.querySelector("#app"))