diff --git a/src/App.js b/src/App.js
index cce40ce..c349f4b 100644
--- a/src/App.js
+++ b/src/App.js
@@ -1,26 +1,38 @@
-import React, { Component } from 'react';
-import Countdown from './Countdown.js';
-import logo from './logo.svg';
-import github from './github.png';
+import React, { Component } from "react";
+import Countdown from "./Countdown.js";
+import logo from "./logo.svg";
+import github from "./github.png";
class App extends Component {
render() {
const currentDate = new Date();
- const year = (currentDate.getMonth() === 11 && currentDate.getDate() > 23) ? currentDate.getFullYear() + 1 : currentDate.getFullYear();
+ const year =
+ currentDate.getMonth() === 11 && currentDate.getDate() > 23
+ ? currentDate.getFullYear() + 1
+ : currentDate.getFullYear();
return (
-
Christmas Eve is coming soon (Midnight of 23rd to 24th Dec, UTC time):
-
+
+ Christmas Eve is coming soon (Midnight of 23rd to 24th Dec, UTC time):
+
+
);
}
diff --git a/src/Countdown.js b/src/Countdown.js
index b101841..439a517 100644
--- a/src/Countdown.js
+++ b/src/Countdown.js
@@ -1,10 +1,11 @@
-import React, { Component } from 'react';
-import PropTypes from 'prop-types'
+import React, { Component } from "react";
+import PropTypes from "prop-types";
+import FlipUnitContainer from "./FlipUnitContainer.js";
/**
- * Note :
+ * Note :
* If you're using react v 15.4 or less
- * You can directly import PropTypes from react instead.
+ * You can directly import PropTypes from react instead.
* Refer to this : https://reactjs.org/warnings/dont-call-proptypes.html
*/
@@ -17,14 +18,27 @@ class Countdown extends Component {
hours: 0,
min: 0,
sec: 0,
- }
+
+ daysShuffle: true,
+ hoursShuffle: true,
+ minutesShuffle: true,
+ secondsShuffle: true,
+
+ isExpired: false
+ };
+
+ this.addLeadingZeros = this.addLeadingZeros.bind(this);
}
componentDidMount() {
// update every second
this.interval = setInterval(() => {
const date = this.calculateCountdown(this.props.date);
- date ? this.setState(date) : this.stop();
+ date
+ ? this.props.useFlipView
+ ? this.updateFlippers(date)
+ : this.setState(date)
+ : this.expired();
}, 1000);
}
@@ -32,6 +46,47 @@ class Countdown extends Component {
this.stop();
}
+ updateFlippers(date) {
+ // set time units
+ const days = date.days;
+ const hours = date.hours;
+ const min = date.min;
+ const sec = date.sec;
+
+ // on hour chanage, update hours and shuffle state
+ if (days !== this.state.days) {
+ const daysShuffle = !this.state.daysShuffle;
+ this.setState({
+ days,
+ daysShuffle
+ });
+ }
+ // on hour chanage, update hours and shuffle state
+ if (hours !== this.state.hours) {
+ const hoursShuffle = !this.state.hoursShuffle;
+ this.setState({
+ hours,
+ hoursShuffle
+ });
+ }
+ // on minute chanage, update minutes and shuffle state
+ if (min !== this.state.min) {
+ const minutesShuffle = !this.state.minutesShuffle;
+ this.setState({
+ min,
+ minutesShuffle
+ });
+ }
+ // on second chanage, update seconds and shuffle state
+ if (sec !== this.state.sec) {
+ const secondsShuffle = !this.state.secondsShuffle;
+ this.setState({
+ sec,
+ secondsShuffle
+ });
+ }
+ }
+
calculateCountdown(endDate) {
let diff = (Date.parse(new Date(endDate)) - Date.parse(new Date())) / 1000;
@@ -47,15 +102,18 @@ class Countdown extends Component {
};
// calculate time difference between now and expected date
- if (diff >= (365.25 * 86400)) { // 365.25 * 24 * 60 * 60
+ if (diff >= 365.25 * 86400) {
+ // 365.25 * 24 * 60 * 60
timeLeft.years = Math.floor(diff / (365.25 * 86400));
diff -= timeLeft.years * 365.25 * 86400;
}
- if (diff >= 86400) { // 24 * 60 * 60
+ if (diff >= 86400) {
+ // 24 * 60 * 60
timeLeft.days = Math.floor(diff / 86400);
diff -= timeLeft.days * 86400;
}
- if (diff >= 3600) { // 60 * 60
+ if (diff >= 3600) {
+ // 60 * 60
timeLeft.hours = Math.floor(diff / 3600);
diff -= timeLeft.hours * 3600;
}
@@ -68,6 +126,11 @@ class Countdown extends Component {
return timeLeft;
}
+ expired() {
+ this.setState({ isExpired: true });
+ this.stop();
+ }
+
stop() {
clearInterval(this.interval);
}
@@ -75,47 +138,122 @@ class Countdown extends Component {
addLeadingZeros(value) {
value = String(value);
while (value.length < 2) {
- value = '0' + value;
+ value = "0" + value;
}
return value;
}
render() {
const countDown = this.state;
+ const {
+ isExpired,
+ daysShuffle,
+ hoursShuffle,
+ minutesShuffle,
+ secondsShuffle
+ } = this.state;
return (
-
-
- {this.addLeadingZeros(countDown.days)}
- {countDown.days === 1 ? 'Day' : 'Days'}
-
-
+ {isExpired ? (
+
+ ) : this.props.useFlipView ? (
+
+ ) : (
+
+ )}
+
+ );
+ }
+}
+
+function ExpiryView(props) {
+ return {props.expiryMsg}
;
+}
+
+function DefaultPlainView(props) {
+ const { countDown, addLeadingZeros } = props;
-
-
- {this.addLeadingZeros(countDown.hours)}
- Hours
-
+ return (
+
+
+
+ {addLeadingZeros(countDown.days)}
+ {countDown.days === 1 ? "Day" : "Days"}
+
+
+
+ {addLeadingZeros(countDown.hours)}
+ Hours
+
+
-
-
- {this.addLeadingZeros(countDown.min)}
- Min
-
+
+
+ {addLeadingZeros(countDown.min)}
+ Min
+
-
-
- {this.addLeadingZeros(countDown.sec)}
- Sec
-
+
+
+ {addLeadingZeros(countDown.sec)}
+ Sec
-
- );
- }
+
+
+ );
+}
+
+function FlipView(props) {
+ const { countDown, addLeadingZeros, shuffle } = props;
+
+ return (
+
+
+
+
+
+
+ );
}
Countdown.propTypes = {
diff --git a/src/FlipStyles.css b/src/FlipStyles.css
new file mode 100644
index 0000000..0201164
--- /dev/null
+++ b/src/FlipStyles.css
@@ -0,0 +1,192 @@
+@import url("https://fonts.googleapis.com/css?family=Droid+Sans+Mono");
+* {
+ box-sizing: border-box;
+}
+
+body {
+ margin: 0;
+}
+
+header {
+ display: flex;
+ position: relative;
+}
+header h1 {
+ font-family: "Droid Sans Mono", monospace;
+ font-weight: lighter;
+ text-transform: uppercase;
+ letter-spacing: 0.1em;
+ color: white;
+}
+
+.flipClock {
+ display: flex;
+ justify-content: space-between;
+ width: 500px;
+}
+
+.flipUnitContainer {
+ display: block;
+ position: relative;
+ width: 140px;
+ height: 120px;
+ -webkit-perspective-origin: 50% 50%;
+ perspective-origin: 50% 50%;
+ -webkit-perspective: 300px;
+ perspective: 300px;
+ background-color: white;
+ border-radius: 3px;
+ box-shadow: 0px 10px 10px -10px grey;
+}
+
+.upperCard,
+.lowerCard {
+ display: flex;
+ position: relative;
+ justify-content: center;
+ width: 100%;
+ height: 50%;
+ overflow: hidden;
+ border: 1px solid whitesmoke;
+}
+.upperCard span,
+.lowerCard span {
+ font-size: 5em;
+ font-family: "Droid Sans Mono", monospace;
+ font-weight: lighter;
+ color: #333333;
+}
+
+.upperCard {
+ align-items: flex-end;
+ border-bottom: 0.5px solid whitesmoke;
+ border-top-left-radius: 3px;
+ border-top-right-radius: 3px;
+}
+.upperCard span {
+ -webkit-transform: translateY(50%);
+ transform: translateY(50%);
+}
+
+.lowerCard {
+ align-items: flex-start;
+ border-top: 0.5px solid whitesmoke;
+ border-bottom-left-radius: 3px;
+ border-bottom-right-radius: 3px;
+}
+.lowerCard span {
+ -webkit-transform: translateY(-50%);
+ transform: translateY(-50%);
+}
+
+.flipCard {
+ display: flex;
+ justify-content: center;
+ position: absolute;
+ left: 0;
+ width: 100%;
+ height: 50%;
+ overflow: hidden;
+ -webkit-backface-visibility: hidden;
+ backface-visibility: hidden;
+}
+.flipCard span {
+ font-family: "Droid Sans Mono", monospace;
+ font-size: 5em;
+ font-weight: lighter;
+ color: #333333;
+}
+.flipCard.unfold {
+ top: 50%;
+ align-items: flex-start;
+ -webkit-transform-origin: 50% 0%;
+ transform-origin: 50% 0%;
+ -webkit-transform: rotateX(180deg);
+ transform: rotateX(180deg);
+ background-color: white;
+ border-bottom-left-radius: 3px;
+ border-bottom-right-radius: 3px;
+ border: 0.5px solid whitesmoke;
+ border-top: 0.5px solid whitesmoke;
+}
+.flipCard.unfold span {
+ -webkit-transform: translateY(-50%);
+ transform: translateY(-50%);
+}
+.flipCard.fold {
+ top: 0%;
+ align-items: flex-end;
+ -webkit-transform-origin: 50% 100%;
+ transform-origin: 50% 100%;
+ -webkit-transform: rotateX(0deg);
+ transform: rotateX(0deg);
+ background-color: white;
+ border-top-left-radius: 3px;
+ border-top-right-radius: 3px;
+ border: 0.5px solid whitesmoke;
+ border-bottom: 0.5px solid whitesmoke;
+}
+.flipCard.fold span {
+ -webkit-transform: translateY(50%);
+ transform: translateY(50%);
+}
+
+.fold {
+ -webkit-animation: fold 0.6s cubic-bezier(0.455, 0.03, 0.515, 0.955) 0s 1
+ normal forwards;
+ animation: fold 0.6s cubic-bezier(0.455, 0.03, 0.515, 0.955) 0s 1 normal
+ forwards;
+ -webkit-transform-style: preserve-3d;
+ transform-style: preserve-3d;
+}
+
+.unfold {
+ -webkit-animation: unfold 0.6s cubic-bezier(0.455, 0.03, 0.515, 0.955) 0s 1
+ normal forwards;
+ animation: unfold 0.6s cubic-bezier(0.455, 0.03, 0.515, 0.955) 0s 1 normal
+ forwards;
+ -webkit-transform-style: preserve-3d;
+ transform-style: preserve-3d;
+}
+
+@-webkit-keyframes fold {
+ 0% {
+ -webkit-transform: rotateX(0deg);
+ transform: rotateX(0deg);
+ }
+ 100% {
+ -webkit-transform: rotateX(-180deg);
+ transform: rotateX(-180deg);
+ }
+}
+
+@keyframes fold {
+ 0% {
+ -webkit-transform: rotateX(0deg);
+ transform: rotateX(0deg);
+ }
+ 100% {
+ -webkit-transform: rotateX(-180deg);
+ transform: rotateX(-180deg);
+ }
+}
+@-webkit-keyframes unfold {
+ 0% {
+ -webkit-transform: rotateX(180deg);
+ transform: rotateX(180deg);
+ }
+ 100% {
+ -webkit-transform: rotateX(0deg);
+ transform: rotateX(0deg);
+ }
+}
+@keyframes unfold {
+ 0% {
+ -webkit-transform: rotateX(180deg);
+ transform: rotateX(180deg);
+ }
+ 100% {
+ -webkit-transform: rotateX(0deg);
+ transform: rotateX(0deg);
+ }
+}
diff --git a/src/FlipUnitContainer.js b/src/FlipUnitContainer.js
new file mode 100644
index 0000000..1cc9420
--- /dev/null
+++ b/src/FlipUnitContainer.js
@@ -0,0 +1,69 @@
+import React from "react";
+import "./FlipStyles.css";
+
+// function component
+const AnimatedCard = ({ animation, digit }) => {
+ return (
+
+ {digit}
+
+ );
+};
+
+// function component
+const StaticCard = ({ position, digit }) => {
+ return (
+
+ {digit}
+
+ );
+};
+
+// function component
+const FlipUnitContainer = ({
+ digit,
+ currentDigit,
+ previousDigit,
+ shuffle,
+ unit
+}) => {
+ // assign digit values
+ // let currentDigit = digit;
+ // let previousDigit = digit + 1;
+
+ // to prevent a negative value
+ // if (unit !== "hours") {
+ // previousDigit = previousDigit === -1 ? 59 : previousDigit;
+ // } else {
+ // previousDigit = previousDigit === -1 ? 23 : previousDigit;
+ // }
+
+ // // add zero
+ // if (currentDigit < 10) {
+ // currentDigit = `0${currentDigit}`;
+ // }
+ // if (previousDigit < 10) {
+ // previousDigit = `0${previousDigit}`;
+ // }
+
+ // shuffle digits
+ const digit1 = shuffle ? previousDigit : currentDigit;
+ const digit2 = !shuffle ? previousDigit : currentDigit;
+
+ // shuffle animations
+ const animation1 = shuffle ? "fold" : "unfold";
+ const animation2 = !shuffle ? "fold" : "unfold";
+
+ return (
+
+ );
+};
+
+export default FlipUnitContainer;