React

by mpetrovich

HTML

<div id="app"></div>

SCSS

body {
  background: #f0f0f0;
  padding: 40px 50px;
  font-family: Arial, sans-serif;
  font-size: 16px;
}

.bc-weather {
	box-sizing: border-box;
	display: inline-block;
	position: relative;
	padding: 0 0.5em;
	color: #333;
	background: #fff;
	border-radius: 0.3em;
	box-shadow: 0 15px 30px rgba(0, 0, 0, 0.25);
	
	&.-loading {
		padding: 20px 40px;
		color: #888;
	}
	
	& .summary {
		float: left;
		padding: 1.1em 1em;
		text-align: center;
	}
	
	& .location {
		font-weight: bold;
	}
	
	& .icon {
		margin-bottom: -2em;
		height: 3em;
	}
	
	& .forecast {
		float: left;
		margin: 0 0.2em;
		padding: 1.2em 0.3em 1em;
		text-align: center;
		
		&.-today {
			padding-left: 0.7em;
			padding-right: 0.7em;
			background: #f8f8f8;
		}
	}
	
	& .forecast-day {
		font-size: 0.8em;
		text-transform: uppercase;
		color: #888;
		
		&.-today {
			font-weight: bold;
			color: inherit;
		}
	}
	
	& .forecast-temp {
		padding-top: 0.2em;
		font-size: 2em;
	}
}

React

class Weather extends React.Component {
	constructor(props) {
		super(props);
		
		const FORECAST_API = `https://api.openweathermap.org/data/2.5/forecast?zip=${this.props.zip}&units=imperial&appid=b08abc60f5222977c05dc54b137b2d17`;
		
		this.state = {};
		
		fetch(FORECAST_API)
			.then(res => res.json())
			.then(res => {
				const forecast = res.list
					.filter((item, index) => index % 8 === 0)  // Because forecast is in 3-hour increments
					.map(item => {
						const date = new Date(item.dt * 1000);
						return {
							weekday: date.toLocaleDateString('en-US', { weekday: 'short' }),
							temp: Math.round(item.main.temp),
						}
					});
				
				this.setState({
					location: res.city.name,
					icon: `http://openweathermap.org/img/w/${res.list[0].weather[0].icon}.png`,
					forecast,
				});
			});
	}

	render() {
		const { location, icon, forecast } = this.state;
		
		if (!forecast) {
			return (
				<div className="bc-weather -loading">Loading…</div>
			);
		}
		
		return (		
			<div className="bc-weather">
				<div className="summary">
					<div className="location">{location}</div>
					<img className="icon" src={icon} />
				</div>
				{forecast.map((day, index) => index === 0
					? (
						<div className="forecast -today" key={day.weekday}>
							<div className="forecast-day -today">Today</div>
							<div className="forecast-temp -today">{day.temp}</div>
						</div>
					)
					: (
						<div className="forecast" key={day.weekday}>
							<div className="forecast-day">{day.weekday}</div>
							<div className="forecast-temp">{day.temp}</div>
						</div>
					)
				)}
			</div>
		);
	}
}

class App extends React.Component {
	render() {
		return (
			<Weather zip="32801" />
		);
	}
}

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