mirror of
https://github.com/reiyua/TombayRetirementTimerV2.git
synced 2026-01-20 16:37:48 +00:00
Basic countdown setup, time to make it look good!
This commit is contained in:
parent
31018deee8
commit
2cf59226aa
2 changed files with 141 additions and 31 deletions
93
src/App.jsx
93
src/App.jsx
|
|
@ -1,35 +1,66 @@
|
|||
import { useState } from 'react'
|
||||
import reactLogo from './assets/react.svg'
|
||||
import viteLogo from '/vite.svg'
|
||||
import './App.css'
|
||||
import React, { useState, useEffect } from 'react';
|
||||
import './Countdown.css';
|
||||
|
||||
function App() {
|
||||
const [count, setCount] = useState(0)
|
||||
const RetirementCountdown = () => {
|
||||
const [timeLeft, setTimeLeft] = useState({});
|
||||
const [prevTimeLeft, setPrevTimeLeft] = useState({});
|
||||
|
||||
return (
|
||||
<>
|
||||
<div>
|
||||
<a href="https://vitejs.dev" target="_blank">
|
||||
<img src={viteLogo} className="logo" alt="Vite logo" />
|
||||
</a>
|
||||
<a href="https://react.dev" target="_blank">
|
||||
<img src={reactLogo} className="logo react" alt="React logo" />
|
||||
</a>
|
||||
</div>
|
||||
<h1>Vite + React</h1>
|
||||
<div className="card">
|
||||
<button onClick={() => setCount((count) => count + 1)}>
|
||||
count is {count}
|
||||
</button>
|
||||
<p>
|
||||
Edit <code>src/App.jsx</code> and save to test HMR
|
||||
</p>
|
||||
</div>
|
||||
<p className="read-the-docs">
|
||||
Click on the Vite and React logos to learn more
|
||||
</p>
|
||||
</>
|
||||
)
|
||||
const calculateTimeLeft = () => {
|
||||
const retirementDate = new Date('2025-09-02'); // Replace with your retirement date
|
||||
const now = new Date();
|
||||
const difference = retirementDate - now;
|
||||
|
||||
let timeLeft = {};
|
||||
|
||||
if (difference > 0) {
|
||||
timeLeft = {
|
||||
days: Math.floor(difference / (1000 * 60 * 60 * 24)),
|
||||
hours: Math.floor((difference / (1000 * 60 * 60)) % 24),
|
||||
minutes: Math.floor((difference / 1000 / 60) % 60),
|
||||
seconds: Math.floor((difference / 1000) % 60),
|
||||
};
|
||||
}
|
||||
|
||||
export default App
|
||||
return timeLeft;
|
||||
};
|
||||
|
||||
useEffect(() => {
|
||||
const timer = setInterval(() => {
|
||||
const newTimeLeft = calculateTimeLeft();
|
||||
setPrevTimeLeft(timeLeft); // Store the previous time
|
||||
setTimeLeft(newTimeLeft);
|
||||
}, 1000);
|
||||
|
||||
return () => clearInterval(timer);
|
||||
}, [timeLeft]);
|
||||
|
||||
return (
|
||||
<div className="countdown-container">
|
||||
<h1 className="countdown-title">Tombay retires in:</h1>
|
||||
{Object.keys(timeLeft).length > 0 ? (
|
||||
<div className="countdown">
|
||||
<FlipUnit number={timeLeft.days} prevNumber={prevTimeLeft.days} label="Days" />
|
||||
<FlipUnit number={timeLeft.hours} prevNumber={prevTimeLeft.hours} label="Hours" />
|
||||
<FlipUnit number={timeLeft.minutes} prevNumber={prevTimeLeft.minutes} label="Minutes" />
|
||||
<FlipUnit number={timeLeft.seconds} prevNumber={prevTimeLeft.seconds} label="Seconds" />
|
||||
</div>
|
||||
) : (
|
||||
<p>Congratulations! You're retired!</p>
|
||||
)}
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
// FlipUnit component handles the animation for each unit
|
||||
const FlipUnit = ({ number, prevNumber, label }) => {
|
||||
return (
|
||||
<div className="countdown-section">
|
||||
<div className={`flip-card ${number !== prevNumber ? 'animate' : ''}`}>
|
||||
<span className="countdown-number">{number}</span>
|
||||
</div>
|
||||
<span className="countdown-label">{label}</span>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
export default RetirementCountdown;
|
||||
|
|
|
|||
79
src/Countdown.css
Normal file
79
src/Countdown.css
Normal file
|
|
@ -0,0 +1,79 @@
|
|||
/* Countdown Container */
|
||||
.countdown-container {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
min-height: 100vh; /* Full viewport height */
|
||||
width: 100vw; /* Full viewport width */
|
||||
background-color: #282c34;
|
||||
color: white;
|
||||
font-family: 'Roboto', sans-serif;
|
||||
text-align: center;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
/* Countdown Title */
|
||||
.countdown-title {
|
||||
font-size: 4em; /* Make the title larger */
|
||||
margin-bottom: 40px; /* Add more space below the title */
|
||||
color: #ffffff;
|
||||
}
|
||||
|
||||
/* Countdown */
|
||||
.countdown {
|
||||
display: flex;
|
||||
gap: 40px; /* Increase space between countdown sections */
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
flex-wrap: wrap; /* Ensure it wraps on smaller screens */
|
||||
width: 100%;
|
||||
max-width: 1200px; /* Maximum width to avoid overcrowding */
|
||||
}
|
||||
|
||||
/* Countdown Section (Days, Hours, Minutes, Seconds) */
|
||||
.countdown-section {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
/* Flip Animation */
|
||||
.flip-card {
|
||||
perspective: 1000px;
|
||||
}
|
||||
|
||||
.flip-card.animate .countdown-number {
|
||||
animation: flip 0.6s ease-in-out;
|
||||
}
|
||||
|
||||
@keyframes flip {
|
||||
0% {
|
||||
transform: rotateX(0deg);
|
||||
}
|
||||
50% {
|
||||
transform: rotateX(-90deg);
|
||||
}
|
||||
100% {
|
||||
transform: rotateX(0deg);
|
||||
}
|
||||
}
|
||||
|
||||
/* Countdown Number (Big Digital Style Numbers) */
|
||||
.countdown-number {
|
||||
font-size: 8em; /* Larger numbers */
|
||||
background-color: #ffffff;
|
||||
color: #000000;
|
||||
padding: 30px; /* More padding around the numbers */
|
||||
border-radius: 10px;
|
||||
box-shadow: 0px 4px 10px rgba(0, 0, 0, 0.4);
|
||||
transform-style: preserve-3d;
|
||||
backface-visibility: hidden;
|
||||
}
|
||||
|
||||
/* Countdown Label (Small Text under Numbers) */
|
||||
.countdown-label {
|
||||
font-size: 2em; /* Larger labels */
|
||||
margin-top: 20px;
|
||||
}
|
||||
|
||||
Loading…
Reference in a new issue