diff --git a/src/App.css b/src/App.css new file mode 100644 index 0000000..e3ed9ef --- /dev/null +++ b/src/App.css @@ -0,0 +1,34 @@ +.countdown-container { + display: flex; + justify-content: center; + align-items: center; + height: 100vh; + background: linear-gradient(to bottom, #ff9966, #ff5e62); + font-family: 'Roboto', sans-serif; + color: white; + } + + .title { + font-family: 'Pacifico', cursive; + font-size: 3em; + text-align: center; + margin-bottom: 2em; + } + + .time-remaining { + font-size: 3em; + letter-spacing: 2px; + } + + .time-remaining span { + margin: 0 10px; + } + + .retirement-message { + position: absolute; + top: 50%; + left: 50%; + transform: translate(-50%, -50%); + font-size: 2em; + text-align: center; + } \ No newline at end of file diff --git a/src/App.js b/src/App.js index 9363608..2bebbf4 100644 --- a/src/App.js +++ b/src/App.js @@ -1,11 +1,20 @@ -import { Countdown } from "./Countdown"; +import React from 'react'; +import CountdownTimer from './CountdownTimer'; +import 'bootstrap/dist/css/bootstrap.min.css'; +import './App.css'; + +// Set your target date here function App() { - return ( -
- -
- ); + const targetDate = new Date("2025-09-02T00:00:00"); // Current target date is specifed here in US date format (YYYY-MM-DD) + + return ( +
+
+ +
+
+ ); } -export default App; \ No newline at end of file +export default App; diff --git a/src/App.test.js b/src/App.test.js new file mode 100644 index 0000000..1f03afe --- /dev/null +++ b/src/App.test.js @@ -0,0 +1,8 @@ +import { render, screen } from '@testing-library/react'; +import App from './App'; + +test('renders learn react link', () => { + render(); + const linkElement = screen.getByText(/learn react/i); + expect(linkElement).toBeInTheDocument(); +}); diff --git a/src/CountdownTimer.js b/src/CountdownTimer.js new file mode 100644 index 0000000..9139e14 --- /dev/null +++ b/src/CountdownTimer.js @@ -0,0 +1,41 @@ +// Import react and the custom hooks +import React from 'react'; +import ExpiredNotice from './ExpiredNotice'; +import ShowCounter from './ShowCounter'; +import { useCountdown } from './hooks/useCountdown'; +import Container from 'react-bootstrap/Container'; +import Row from 'react-bootstrap/Row'; +import Col from 'react-bootstrap/Col'; +import Card from 'react-bootstrap/Card'; +import Button from 'react-bootstrap/Button'; + +// Create a CountdownTimer component and add variables to hold the days, hours, minutes, and seconds values returned from the useCountdown hook +const CountdownTimer = ({ targetDate }) => { + const [days, hours, minutes, seconds] = useCountdown(targetDate); + +// Return the JSX to display the countdown timer + + return ( + + + +

Countdown to Retirement

+ + {days + hours + minutes + seconds <= 0 ? ( + + + + + ) : ( + + + + )} + + +
+
+ ); +}; + +export default CountdownTimer; diff --git a/src/ExpiredNotice.js b/src/ExpiredNotice.js new file mode 100644 index 0000000..9c156f1 --- /dev/null +++ b/src/ExpiredNotice.js @@ -0,0 +1,6 @@ +import React from 'react'; + +// ExpiredNotice component +const ExpiredNotice = () =>
Time's up!
; + +export default ExpiredNotice; \ No newline at end of file diff --git a/src/ShowCounter.js b/src/ShowCounter.js new file mode 100644 index 0000000..d7c3c38 --- /dev/null +++ b/src/ShowCounter.js @@ -0,0 +1,11 @@ +// This file contains the ShowCounter component which is used to display the countdown timer. + +import React from 'react'; + +const ShowCounter = ({ days, hours, minutes, seconds }) => ( +
+ {days} days, {hours} hours, {minutes} minutes, {seconds} seconds +
+); + +export default ShowCounter; \ No newline at end of file diff --git a/src/hooks/useCountdown.js b/src/hooks/useCountdown.js new file mode 100644 index 0000000..f0a1c0d --- /dev/null +++ b/src/hooks/useCountdown.js @@ -0,0 +1,33 @@ +import { useEffect, useState } from 'react'; + +const useCountdown = (targetDate) => { + const countDownDate = new Date(targetDate).getTime(); + + const [countDown, setCountDown] = useState( + countDownDate - new Date().getTime() + ); + + useEffect(() => { + const interval = setInterval(() => { + setCountDown(countDownDate - new Date().getTime()); + }, 1000); + + return () => clearInterval(interval); + }, [countDownDate]); + + return getReturnValues(countDown); +}; + +const getReturnValues = (countDown) => { + // calculate time left + const days = Math.floor(countDown / (1000 * 60 * 60 * 24)); + const hours = Math.floor( + (countDown % (1000 * 60 * 60 * 24)) / (1000 * 60 * 60) + ); + const minutes = Math.floor((countDown % (1000 * 60 * 60)) / (1000 * 60)); + const seconds = Math.floor((countDown % (1000 * 60)) / 1000); + + return [days, hours, minutes, seconds]; +}; + +export { useCountdown }; \ No newline at end of file diff --git a/src/index.css b/src/index.css index 3e3b6a1..ec2585e 100644 --- a/src/index.css +++ b/src/index.css @@ -10,4 +10,4 @@ body { code { font-family: source-code-pro, Menlo, Monaco, Consolas, 'Courier New', monospace; -} \ No newline at end of file +} diff --git a/src/index.js b/src/index.js index f84af50..d563c0f 100644 --- a/src/index.js +++ b/src/index.js @@ -1,11 +1,17 @@ -import React from "react"; -import ReactDOM from "react-dom/client"; -import "./index.css"; -import App from "./App"; +import React from 'react'; +import ReactDOM from 'react-dom/client'; +import './index.css'; +import App from './App'; +import reportWebVitals from './reportWebVitals'; -const root = ReactDOM.createRoot(document.getElementById("root")); +const root = ReactDOM.createRoot(document.getElementById('root')); root.render( -); \ No newline at end of file +); + +// If you want to start measuring performance in your app, pass a function +// to log results (for example: reportWebVitals(console.log)) +// or send to an analytics endpoint. Learn more: https://bit.ly/CRA-vitals +reportWebVitals(); diff --git a/src/logo.svg b/src/logo.svg new file mode 100644 index 0000000..9dfc1c0 --- /dev/null +++ b/src/logo.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/setupTests.js b/src/setupTests.js new file mode 100644 index 0000000..8f2609b --- /dev/null +++ b/src/setupTests.js @@ -0,0 +1,5 @@ +// jest-dom adds custom jest matchers for asserting on DOM nodes. +// allows you to do things like: +// expect(element).toHaveTextContent(/react/i) +// learn more: https://github.com/testing-library/jest-dom +import '@testing-library/jest-dom';