Skip to content

Instantly share code, notes, and snippets.

@raininglemons
Created July 26, 2018 10:52
Show Gist options
  • Save raininglemons/f655cf3eb048be707aaefaad1d119b36 to your computer and use it in GitHub Desktop.
Save raininglemons/f655cf3eb048be707aaefaad1d119b36 to your computer and use it in GitHub Desktop.
World Clock v2
<div id="app"></div>
class WeatherApp extends React.Component {
constructor() {
super();
this.state = {
currentTime: moment(),
cities: {
'London': {
weatherId: 2643743,
timeZone: 'America/London'
},
'Gibraltar' : {
weatherId: 2411585,
timeZone: 'Europe/Gibraltar'
},
'Hyderabad': {
weatherId: 1269843,
timeZone: 'Asia/Kolkata'
},
'Vienna': {
weatherId: 2761369,
timeZone: 'Europe/Vienna'
}
}
}
}
componentDidMount() {
window.setInterval(() => this.setState({ currentTime: moment() }), 5000)
}
render() {
const { cities, currentTime } = this.state;
return (
<div className="panels">
{
Object
.keys(cities)
.map(cityName =>
<City name={cityName}
weatherId = {cities[cityName].weatherId}
timeZone = {cities[cityName].timeZone}
bgImg = {cities[cityName].bgImg}
currentTime = {currentTime}
key={cityName}
/>)
}
</div>
)
}
}
class City extends React.Component {
constructor(props) {
super(props);
const { timeZone, currentTime } = this.props;
this.state = {
weatherData: {},
localTime: currentTime.tz(timeZone).format('HH:mm dddd'),
currentHour: currentTime.tz(timeZone).format('HH'),
open: false,
bgGradient: ''
}
this.getWeatherInfo = this.getWeatherInfo.bind(this);
this.updateCurrentTime = this.updateCurrentTime.bind(this);
this.toggleOpen = this.toggleOpen.bind(this);
};
async getWeatherInfo(id) {
const res = await fetch(`https://api.openweathermap.org/data/2.5/weather?id=${id}&units=metric&appid=c5baa00af2bfbc51b5a8bff68a069bb0`).then(res => res.json());
const weatherInfo = {
temp: res.main.temp,
desc: res.weather[0].main,
icon: `icon-${res.weather[0].icon}`
};
this.setState({
weatherData: weatherInfo
})
}
setGradient(currentHour) {
if (currentHour < 3) {
this.setState({ bgGradient : 'night-2'});
} else if (currentHour < 6) {
this.setState({ bgGradient : 'dawn'});
} else if (currentHour < 9) {
this.setState({ bgGradient : 'morning'});
} else if (currentHour < 12) {
this.setState({ bgGradient : 'afternoon-1'});
} else if (currentHour < 15) {
this.setState({ bgGradient : 'afternoon-2'});
} else if (currentHour < 18) {
this.setState({ bgGradient : 'evening-1'});
} else if (currentHour < 21) {
this.setState({ bgGradient : 'evening-2'});
} else if (currentHour < 24) {
this.setState({ bgGradient : 'night-1'});
}
}
updateCurrentTime() {
const { timeZone, currentTime } = this.props;
this.setState({ localTime: currentTime.tz(timeZone).format('dddd HH:mm') });
this.setGradient(this.state.currentHour);
}
componentDidMount() {
const { weatherId } = this.props;
this.getWeatherInfo(weatherId);
window.setInterval(() => this.updateCurrentTime(), 5000);
this.setGradient(this.state.currentHour);
}
toggleOpen() {
const currentState = this.state.open;
this.setState({ open: !currentState });
}
render() {
const { name, bgImg } = this.props;
const { localTime } = this.state;
const { desc, temp, icon } = this.state.weatherData;
const activeClass = this.state.open ? 'open': '';
const gradientClass = this.state.bgGradient;
return (
<div className={`panel ${activeClass} ${gradientClass}`}
onClick={this.toggleOpen}
>
<div>
<h2>{ name }</h2>
<p>{ localTime }</p>
</div>
<div className="weather-icon">
<i className={icon}></i>
{temp ?
<span> { desc } { temp }°C </span>
: ''
}
</div>
</div>
)
}
}
ReactDOM.render(<WeatherApp />, document.querySelector('#app'));
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.4.2/react.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.6.1/react-dom.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/moment.js/2.18.0/moment.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/moment-timezone/0.5.9/moment-timezone-with-data-2010-2020.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/babel-core/6.1.19/browser.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/babel-core/5.8.29/browser-polyfill.min.js"></script>
@import url('https://fonts.googleapis.com/css?family=Open+Sans+Condensed:300');
$txtGrey: #CDD5C1;
$dawn-1: #123352;
$dawn-2: #1d5372;
$dawn-3: #3885a2;
$morning-1: #8dcdba;
$morning-2: #eee07a;
$morning-3: #f0eebc;
$afternoon-1: #e6756f;
$afternoon-2: #ee8049;
$afternoon-3: #facf62;
$evening-1: #291c6b;
$evening-2: #4a257d;
$evening-3: #884186;
$night-1: #111642;
$night-2: #011548;
*, *:before, *:after {
box-sizing: inherit;
}
html {
font-family: 'Open Sans Condensed', sans-serif;
color: $txtGrey;
}
body {
margin: 0;
}
h2 {
text-transform: uppercase;
font-weight: lighter;
font-size: 40px;
margin: 0;
}
p {
margin: 0;
}
.panels {
min-height: 100vh;
overflow: hidden;
display: flex;
font-size: 20px;
}
.panel {
flex: 1;
text-align: center;
display: flex;
flex-direction: column;
justify-content: center;
align-items: center;
background: linear-gradient($dawn-1, $dawn-2, $dawn-3);
border-right: 1px solid rgba($txtGrey, .3);
cursor: pointer;
transition:
font-size 0.7s cubic-bezier(0.61,-0.19, 0.7,-0.11),
flex 0.7s cubic-bezier(0.61,-0.19, 0.7,-0.11),
background 0.3s;
&.open {
flex: 4;
font-size: 30px;
}
}
.panel > * {
flex: 1 0 auto;
margin: 0;
width: 100%;
display: flex;
flex-direction: column;
justify-content: center;
align-items: center;
transition: transform 0.5s;
}
.panel > *:first-child {
justify-content: flex-end;
}
.panel > *:last-child {
justify-content: flex-start;
}
.dawn {
background: linear-gradient($dawn-1, $dawn-2, $dawn-3);
}
.morning {
background: linear-gradient($morning-1, $morning-2, $morning-3);
color: #363c80;
}
.afternoon-1 {
background: linear-gradient($morning-3, $afternoon-1, $afternoon-2);
color: #fff;
}
.afternoon-2 {
background: linear-gradient($afternoon-2, $afternoon-3, $afternoon-1);
color: #fff;
}
.evening-1 {
background: linear-gradient($afternoon-3, $afternoon-1, $evening-3);
color: #fff;
}
.evening-2 {
background: linear-gradient($evening-1, $evening-2, $evening-3);
color: #9eaf81;
}
.night-1 {
background: linear-gradient($evening-3, $night-1, $night-2);
}
.night-2 {
background: linear-gradient($night-1, $dawn-2, $dawn-1);
}
.weather-icon i {
font-family: 'weathericons';
font-style: normal;
font-weight: normal;
line-height: 1;
font-size: 40px;
padding: 20px 0;
&.icon-01d:before {
content: '\f00d';
}
&.icon-01n:before {
content: '\f02e';
}
&.icon-02d:before {
content: '\f002';
}
&.icon-02n:before {
content: '\f086';
}
&.icon-03d:before,
&.icon-03n:before {
content: '\f041';
}
&.icon-04d:before,
&.icon-04n:before {
content: '\f013';
}
&.icon-09d:before,
&.icon-09n:before {
content: '\f017';
}
&.icon-10d:before {
content: '\f009';
}
&.icon-10n:before {
content: '\f029';
}
&.icon-11d:before,
&.icon-11n:before {
content: '\f01d';
}
&.icon-13d:before,
&.icon-13n:before {
content: '\f01d';
}
&.icon-50d:before,
&.icon-50n:before {
content: '\f01b';
}
}
<link href="https://cdnjs.cloudflare.com/ajax/libs/weather-icons/2.0.9/css/weather-icons.min.css" rel="stylesheet" />

World Clock v2

My siblings, my folks and I are all living continents apart! Thus it was high time I redesigned my world clock to include the day of the week and the weather* where we all live! The weather data was fetched with the help of an async function to cut down on promise chaining. Design inspired by [Figure It Out dribbble] (https://dribbble.com/shots/1128554-Figure-it-Out).

*weather data will appear permitting I haven't maxed out the requests on my free API key 🙈

A Pen by Dom England on CodePen.

License.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment