2017-08-19 01:25:18 +00:00
|
|
|
import React from 'react';
|
2017-08-19 02:13:04 +00:00
|
|
|
import moment from 'moment-timezone';
|
2017-08-19 01:25:18 +00:00
|
|
|
import PropTypes from 'prop-types';
|
|
|
|
|
import DigitBlock from './DigitBlock';
|
|
|
|
|
import ProgressCircle from './ProgressCircle';
|
|
|
|
|
|
|
|
|
|
import style from './Countdown.sass';
|
|
|
|
|
|
|
|
|
|
export default class Countdown extends React.Component {
|
|
|
|
|
static propTypes = {
|
2017-08-19 21:18:04 +00:00
|
|
|
date: PropTypes.instanceOf(moment).isRequired,
|
2017-08-19 01:25:18 +00:00
|
|
|
locale: PropTypes.string,
|
|
|
|
|
minimumIntegerDigits: PropTypes.number,
|
|
|
|
|
useGrouping: PropTypes.bool,
|
|
|
|
|
getNow: PropTypes.func,
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
static defaultProps = {
|
|
|
|
|
locale: undefined,
|
|
|
|
|
minimumIntegerDigits: 2,
|
|
|
|
|
useGrouping: false,
|
|
|
|
|
getNow: () => moment(),
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
componentDidMount() {
|
|
|
|
|
this.tick();
|
2017-08-19 21:39:33 +00:00
|
|
|
this.interval = setInterval(this.tick.bind(this), 100);
|
2017-08-19 01:25:18 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
componentWillUnmount() {
|
|
|
|
|
clearInterval(this.interval);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
calculateDiff() {
|
|
|
|
|
const { getNow, date } = this.props;
|
|
|
|
|
return date.diff(getNow());
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
tick() {
|
|
|
|
|
this.setState({ duration: this.calculateDiff() });
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
render() {
|
|
|
|
|
if (!this.state) {
|
|
|
|
|
return null;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
const { duration } = this.state;
|
|
|
|
|
|
|
|
|
|
const durationMoment = moment.duration(duration);
|
|
|
|
|
|
2017-08-19 21:39:33 +00:00
|
|
|
const milliseconds = durationMoment.asMilliseconds();
|
|
|
|
|
const seconds = (milliseconds / 1000) % 60;
|
|
|
|
|
const minutes = (milliseconds / (60 * 1000)) % 60;
|
|
|
|
|
const hours = (milliseconds / (60 * 60 * 1000)) % 24;
|
|
|
|
|
const days = (milliseconds / (24 * 60 * 60 * 1000));
|
|
|
|
|
|
2017-08-19 01:25:18 +00:00
|
|
|
const size = 160; // @HACK
|
|
|
|
|
|
|
|
|
|
const { locale, minimumIntegerDigits, useGrouping } = this.props;
|
|
|
|
|
return (
|
|
|
|
|
<div className={style.countdown}>
|
2017-08-19 21:18:04 +00:00
|
|
|
<ProgressCircle size={size} max={3} progress={days} stroke="rgb(76,114,163)">
|
2017-08-19 01:25:18 +00:00
|
|
|
<DigitBlock suffix="d">
|
2017-08-19 21:39:33 +00:00
|
|
|
{Math.floor(days).toLocaleString(locale, {
|
2017-08-19 01:25:18 +00:00
|
|
|
minimumIntegerDigits,
|
|
|
|
|
useGrouping,
|
|
|
|
|
})}
|
|
|
|
|
</DigitBlock>
|
|
|
|
|
</ProgressCircle>
|
|
|
|
|
<ProgressCircle size={size} max={24} progress={hours} stroke="rgb(60, 144, 60)">
|
|
|
|
|
<DigitBlock suffix="h">
|
2017-08-19 21:39:33 +00:00
|
|
|
{Math.floor(hours).toLocaleString(locale, {
|
2017-08-19 01:25:18 +00:00
|
|
|
minimumIntegerDigits,
|
|
|
|
|
useGrouping,
|
|
|
|
|
})}
|
|
|
|
|
</DigitBlock>
|
|
|
|
|
</ProgressCircle>
|
|
|
|
|
<ProgressCircle size={size} max={60} progress={minutes} stroke="rgb(160, 154, 40)">
|
|
|
|
|
<DigitBlock suffix="m">
|
2017-08-19 21:39:33 +00:00
|
|
|
{Math.floor(minutes).toLocaleString(locale, {
|
2017-08-19 01:25:18 +00:00
|
|
|
minimumIntegerDigits,
|
|
|
|
|
useGrouping,
|
|
|
|
|
})}
|
|
|
|
|
</DigitBlock>
|
|
|
|
|
</ProgressCircle>
|
2017-08-19 21:18:04 +00:00
|
|
|
<ProgressCircle size={size} max={60} progress={seconds} stroke="rgb(193,63,88)">
|
2017-08-19 01:25:18 +00:00
|
|
|
<DigitBlock suffix="s">
|
2017-08-19 21:39:33 +00:00
|
|
|
{Math.floor(seconds).toLocaleString(locale, {
|
2017-08-19 01:25:18 +00:00
|
|
|
minimumIntegerDigits,
|
|
|
|
|
useGrouping,
|
|
|
|
|
})}
|
|
|
|
|
</DigitBlock>
|
|
|
|
|
</ProgressCircle>
|
|
|
|
|
</div>
|
|
|
|
|
);
|
|
|
|
|
}
|
|
|
|
|
}
|