├── .gitignore
├── LICENSE
├── README.md
├── package-lock.json
├── package.json
├── public
├── _redirects
├── favicon.ico
├── index.html
├── logo192.png
├── logo512.png
├── manifest.json
└── robots.txt
├── screenshots
├── countdown.png
├── duma.png
├── generate.png
└── wishPage.png
└── src
├── App.css
├── App.js
├── Birthday.jsx
├── Countdown.jsx
├── Generate.jsx
├── RouterBirthday.jsx
├── Wish.jsx
├── githubLogo.svg
├── index.css
└── index.js
/.gitignore:
--------------------------------------------------------------------------------
1 | # See https://help.github.com/articles/ignoring-files/ for more about ignoring files.
2 |
3 | # dependencies
4 | /node_modules
5 | /.pnp
6 | .pnp.js
7 |
8 | # testing
9 | /coverage
10 |
11 | # production
12 | /build
13 |
14 | # misc
15 | .DS_Store
16 | .env.local
17 | .env.development.local
18 | .env.test.local
19 | .env.production.local
20 |
21 | npm-debug.log*
22 | yarn-debug.log*
23 | yarn-error.log*
24 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | MIT License
2 |
3 | Copyright (c) 2020 Deepankar Bhade
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
22 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # 🎉Birthday Wisher with Countdown!🎉
2 |
3 | Made with React with Hooks.
4 |
5 | ## Getting started
6 |
7 | You can view a live demo over at https://birthday-wisher.netlify.app/
8 |
9 | To get It running locally:
10 |
11 | - Clone this repo
12 | - `npm install` to install all req'd dependencies
13 | - `npm start` to start the local server (this project uses create-react-app)
14 |
15 | ## Usage:
16 |
17 | Visit [https://birthday-wisher.netlify.app/]()
18 |
19 | Click on Generate Link
20 | or Head to [https://birthday-wisher.netlify.app/generate]()
21 |
22 | Enter the `name , day , month of birthday`
23 |
24 | 
25 |
26 | Click on Generate Link
27 |
28 | You Can see a Link being generated Copy or Visit the link by Clicking on the Button
29 |
30 | And There You Go ! 🎉
31 |
32 | 
33 |
34 | ## ScreenShot of Coutdown Timer⏲️
35 |
36 | 
37 |
38 | ## Birthday Wisher🎂
39 |
40 | Loads this Page Instead of Coutdown on the Birthday
41 | 
42 |
43 | It's Fully Responsive and you change styles in the `app.css`
44 |
45 | Wishing Component Page : `Wish.jsx`
46 | Countdown Compenent Page : `Countdown.jsx`
47 |
--------------------------------------------------------------------------------
/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "birthday-wisher",
3 | "version": "0.1.0",
4 | "private": true,
5 | "dependencies": {
6 | "@testing-library/jest-dom": "^4.2.4",
7 | "@testing-library/react": "^9.5.0",
8 | "@testing-library/user-event": "^7.2.1",
9 | "react": "^16.13.1",
10 | "react-dom": "^16.13.1",
11 | "react-router-dom": "^5.2.0",
12 | "react-scripts": "3.4.3"
13 | },
14 | "scripts": {
15 | "start": "react-scripts start",
16 | "build": "react-scripts build",
17 | "test": "react-scripts test",
18 | "eject": "react-scripts eject"
19 | },
20 | "eslintConfig": {
21 | "extends": "react-app"
22 | },
23 | "browserslist": {
24 | "production": [
25 | ">0.2%",
26 | "not dead",
27 | "not op_mini all"
28 | ],
29 | "development": [
30 | "last 1 chrome version",
31 | "last 1 firefox version",
32 | "last 1 safari version"
33 | ]
34 | }
35 | }
36 |
--------------------------------------------------------------------------------
/public/_redirects:
--------------------------------------------------------------------------------
1 | /* /index.html 200
--------------------------------------------------------------------------------
/public/favicon.ico:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Deep-Codes/Birthday-Wisher/e8d36ce44bb80c532ac33cf8b03dcc929d6587be/public/favicon.ico
--------------------------------------------------------------------------------
/public/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
14 |
15 |
24 | Birthday Coutdown & Wisher
25 |
26 |
27 |
28 |
29 |
39 |
40 |
41 |
--------------------------------------------------------------------------------
/public/logo192.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Deep-Codes/Birthday-Wisher/e8d36ce44bb80c532ac33cf8b03dcc929d6587be/public/logo192.png
--------------------------------------------------------------------------------
/public/logo512.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Deep-Codes/Birthday-Wisher/e8d36ce44bb80c532ac33cf8b03dcc929d6587be/public/logo512.png
--------------------------------------------------------------------------------
/public/manifest.json:
--------------------------------------------------------------------------------
1 | {
2 | "short_name": "React App",
3 | "name": "Create React App Sample",
4 | "icons": [
5 | {
6 | "src": "favicon.ico",
7 | "sizes": "64x64 32x32 24x24 16x16",
8 | "type": "image/x-icon"
9 | },
10 | {
11 | "src": "logo192.png",
12 | "type": "image/png",
13 | "sizes": "192x192"
14 | },
15 | {
16 | "src": "logo512.png",
17 | "type": "image/png",
18 | "sizes": "512x512"
19 | }
20 | ],
21 | "start_url": ".",
22 | "display": "standalone",
23 | "theme_color": "#000000",
24 | "background_color": "#ffffff"
25 | }
26 |
--------------------------------------------------------------------------------
/public/robots.txt:
--------------------------------------------------------------------------------
1 | # https://www.robotstxt.org/robotstxt.html
2 | User-agent: *
3 | Disallow:
4 |
--------------------------------------------------------------------------------
/screenshots/countdown.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Deep-Codes/Birthday-Wisher/e8d36ce44bb80c532ac33cf8b03dcc929d6587be/screenshots/countdown.png
--------------------------------------------------------------------------------
/screenshots/duma.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Deep-Codes/Birthday-Wisher/e8d36ce44bb80c532ac33cf8b03dcc929d6587be/screenshots/duma.png
--------------------------------------------------------------------------------
/screenshots/generate.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Deep-Codes/Birthday-Wisher/e8d36ce44bb80c532ac33cf8b03dcc929d6587be/screenshots/generate.png
--------------------------------------------------------------------------------
/screenshots/wishPage.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Deep-Codes/Birthday-Wisher/e8d36ce44bb80c532ac33cf8b03dcc929d6587be/screenshots/wishPage.png
--------------------------------------------------------------------------------
/src/App.css:
--------------------------------------------------------------------------------
1 | @import url('https://fonts.googleapis.com/css2?family=Montserrat:ital,wght@0,100;0,200;0,300;0,400;0,500;0,600;0,700;0,800;1,100;1,200&display=swap');
2 |
3 | /* VARIABLES */
4 | :root {
5 | --main-bg-color-dark: #212529;
6 | --main-text-color-dark: #e8e8e8;
7 | }
8 |
9 | * {
10 | box-sizing: border-box;
11 | margin: 0;
12 | padding: 0;
13 | }
14 | body {
15 | font-family: 'Montserrat', sans-serif;
16 | background-color: var(--main-bg-color-dark);
17 | color: var(--main-text-color-dark);
18 | background-color: #1d1d1d;
19 | }
20 | .page {
21 | width: 100%;
22 | height: 100vh;
23 | display: flex;
24 | flex-direction: column;
25 | justify-content: center;
26 | align-items: center;
27 | text-align: center;
28 | }
29 | .heading {
30 | font-size: 45px;
31 | }
32 | .highlight {
33 | color: #7f78d2;
34 | }
35 | .countdown-wrapper {
36 | max-width: 800px;
37 | display: flex;
38 | flex-direction: row;
39 | flex-wrap: wrap;
40 | justify-content: space-around;
41 | margin: 40px 0;
42 | }
43 | .countdown-box {
44 | background-color: #413c69;
45 | font-size: 50px;
46 | font-weight: 700;
47 | color: #dcd6f7;
48 | border-radius: 15px;
49 | width: 160px;
50 | height: 160px;
51 | margin: 10px;
52 | display: flex;
53 | flex-direction: column;
54 | justify-content: center;
55 | align-items: center;
56 | text-align: center;
57 | }
58 | .legend {
59 | font-size: 30px;
60 | color: #a6b1e1;
61 | }
62 | .wish-message {
63 | font-size: 45px;
64 | font-weight: 700;
65 | }
66 | .birthdate {
67 | font-size: 25px;
68 | font-weight: 600;
69 | color: #7f78d2;
70 | }
71 | .credits {
72 | margin-top: 15px;
73 | }
74 | .github-logo {
75 | opacity: 0.5;
76 | width: 50px;
77 | }
78 | .github-logo:hover {
79 | opacity: 1;
80 | }
81 | .form {
82 | display: flex;
83 | flex-direction: column;
84 | justify-content: center;
85 | align-items: center;
86 | text-align: center;
87 | margin-top: 20px;
88 | }
89 | .form input {
90 | margin: 10px;
91 | }
92 | input {
93 | color: var(--main-text-color-dark);
94 | outline: none;
95 | width: 300px;
96 | height: 40px;
97 | background-color: transparent;
98 | border: 1px rgba(255, 255, 255, 0.2) solid;
99 | border-radius: 5px;
100 | padding-left: 10px;
101 | padding-right: 10px;
102 | font-size: 18px;
103 | }
104 | select {
105 | width: 300px;
106 | height: 40px;
107 | background-color: transparent;
108 | color: rgba(255, 255, 255, 0.527);
109 | font-family: Montserrat, sans-serif;
110 | border: 1px rgba(255, 255, 255, 0.164) solid;
111 | padding-left: 20px;
112 | -webkit-appearance: none;
113 | -moz-appearance: none;
114 | border-radius: 5px;
115 | font-size: 18px;
116 | margin-top: 10px;
117 | outline: none;
118 | }
119 | input:focus,
120 | select:focus,
121 | .btn:focus {
122 | border: 1px rgba(255, 255, 255, 1) solid;
123 | transition: all 0.5s;
124 | }
125 | .btn {
126 | width: 300px;
127 | height: 40px;
128 | margin-top: 20px;
129 | outline: none;
130 | border: 1px rgba(255, 255, 255, 0.2) solid;
131 | background-color: transparent;
132 | border-radius: 5px;
133 | color: rgba(255, 255, 255, 0.719);
134 | font-size: 18px;
135 | font-weight: 700;
136 | }
137 | .btn:hover {
138 | color: white;
139 | }
140 | a {
141 | color: #7f78d2;
142 | font-weight: bold;
143 | margin-top: 20px;
144 | }
145 | .gen-link {
146 | margin-top: 20px;
147 | font-size: 400;
148 | }
149 |
--------------------------------------------------------------------------------
/src/App.js:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 | import './App.css';
3 | import Birthday from './Birthday';
4 | import { Route, Switch } from 'react-router-dom';
5 | import RouterBirthday from './RouterBirthday';
6 | import Generate from './Generate';
7 |
8 | function App() {
9 | return (
10 |
11 |
12 |
13 |
18 |
19 |
20 |
21 | );
22 | }
23 |
24 | export default App;
25 |
--------------------------------------------------------------------------------
/src/Birthday.jsx:
--------------------------------------------------------------------------------
1 | import React, { useState, useEffect } from 'react';
2 | import Countdown from './Countdown';
3 | import githubLogo from './githubLogo.svg';
4 | import { Link } from 'react-router-dom';
5 |
6 | const Birthday = ({ name, day, month }) => {
7 | // useState Hooks
8 | const [state, setState] = useState({
9 | seconds: 0,
10 | hours: 0,
11 | minutes: 0,
12 | days: 0,
13 | isItBday: false,
14 | });
15 |
16 | if (name === undefined || day === undefined || month === undefined) {
17 | // This is if not enough params are provided
18 | name = 'Deepankar'; // Name of the Person
19 | month = 6; // Month of the Birthday
20 | day = 14; // Day of the Birthday
21 | }
22 |
23 | // get current time
24 | const currentTime = new Date();
25 | // get current year
26 | const currentYear = currentTime.getFullYear();
27 |
28 | // Getting the Birthday in Data Object
29 | // WE subtract 1 from momnth ; Months start from 0 in Date Object
30 | // Bithday Boolean
31 | const isItBday =
32 | currentTime.getDate() === day && currentTime.getMonth() === month - 1;
33 |
34 | useEffect(() => {
35 | setInterval(() => {
36 | const countdown = () => {
37 | // Getting the Current Date
38 | const dateAtm = new Date();
39 |
40 | // if the Birthday has passed
41 | // then set the Birthday countdown for next year
42 | let birthdayDay = new Date(currentYear, month - 1, day);
43 | if (dateAtm > birthdayDay) {
44 | birthdayDay = new Date(currentYear + 1, month - 1, day);
45 | } else if (dateAtm.getFullYear() === birthdayDay.getFullYear() + 1) {
46 | birthdayDay = new Date(currentYear, month - 1, day);
47 | }
48 |
49 | // Getitng Current Time
50 | const currentTime = dateAtm.getTime();
51 | // Getting Birthdays Time
52 | const birthdayTime = birthdayDay.getTime();
53 |
54 | // Time remaining for the Birthday
55 | const timeRemaining = birthdayTime - currentTime;
56 |
57 | let seconds = Math.floor(timeRemaining / 1000);
58 | let minutes = Math.floor(seconds / 60);
59 | let hours = Math.floor(minutes / 60);
60 | let days = Math.floor(hours / 24);
61 |
62 | seconds %= 60;
63 | minutes %= 60;
64 | hours %= 24;
65 |
66 | // Setting States
67 | setState((prevState) => ({
68 | ...prevState,
69 | seconds,
70 | minutes,
71 | hours,
72 | days,
73 | isItBday,
74 | }));
75 | // console.log(`${days}:${hours}:${minutes}:${seconds} , ${isItBday}`);
76 | };
77 | if (!isItBday) {
78 | countdown();
79 | } else {
80 | setState((prevState) => ({
81 | ...prevState,
82 | isItBday: true,
83 | }));
84 | }
85 | }, 1000);
86 | }, [currentYear, day, isItBday, month]);
87 |
88 | let birth = new Date(currentYear, month - 1, day);
89 | const monthNames = [
90 | 'January',
91 | 'February',
92 | 'March',
93 | 'April',
94 | 'May',
95 | 'June',
96 | 'July',
97 | 'August',
98 | 'September',
99 | 'October',
100 | 'November',
101 | 'December',
102 | ];
103 | let monthBday = monthNames[birth.getMonth()];
104 |
105 | return (
106 |
107 |
108 | {!isItBday && (
109 | <>
110 |
111 | Birth-Date: {day} {monthBday} {currentYear}
112 |
113 |
118 |
Generate Here
119 | >
120 | )}
121 |
122 | );
123 | };
124 |
125 | export default Birthday;
126 |
--------------------------------------------------------------------------------
/src/Countdown.jsx:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 | import Wish from './Wish';
3 |
4 | const Countdown = ({ countdownData, name }) => {
5 | if (!countdownData.isItBday) {
6 | return (
7 |
8 |
9 | Countdown to {name}'s Birthday
10 |
11 |
12 |
13 | {countdownData.days}
14 | Days
15 |
16 |
17 | {countdownData.hours}
18 | Hours
19 |
20 |
21 | {countdownData.minutes}
22 | Minutes
23 |
24 |
25 | {countdownData.seconds}
26 | Seconds
27 |
28 |
29 |
30 | );
31 | } else {
32 | return ;
33 | }
34 | };
35 |
36 | export default Countdown;
37 |
--------------------------------------------------------------------------------
/src/Generate.jsx:
--------------------------------------------------------------------------------
1 | import React, { useState } from 'react';
2 | import { Link } from 'react-router-dom';
3 |
4 | const Generate = () => {
5 | const [name, setName] = useState('');
6 | const [day, setDay] = useState(1);
7 | const [month, setMonth] = useState(1);
8 | const [link, setLink] = useState('');
9 | const generateLink = () => {
10 | setLink(
11 | `https://birthday-wisher.netlify.app/birthday/${name}/${day}/${month}`
12 | );
13 | };
14 | return (
15 |
16 |
Generate Here
17 |
18 | setName(e.target.value)}
23 | />
24 | setDay(e.target.value)}
29 | max={31}
30 | min={1}
31 | />
32 |
49 |
50 |
53 |
54 | {link !== '' ? (
55 | <>
56 |
{link}
57 |
58 |
59 |
60 | >
61 | ) : (
62 | ''
63 | )}
64 |
65 | );
66 | };
67 |
68 | export default Generate;
69 |
--------------------------------------------------------------------------------
/src/RouterBirthday.jsx:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 | import Birthday from './Birthday';
3 |
4 | const RouterBirthday = (props) => {
5 | const { params } = props.match;
6 | const { name, day, month } = params;
7 | return (
8 | <>
9 |
10 | >
11 | );
12 | };
13 |
14 | export default RouterBirthday;
15 |
--------------------------------------------------------------------------------
/src/Wish.jsx:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 |
3 | const Wish = ({ name }) => {
4 | return (
5 |
6 | HAPPY BIRTHDAY {name.toUpperCase()} !!!
7 |
8 | );
9 | };
10 |
11 | export default Wish;
12 |
--------------------------------------------------------------------------------
/src/githubLogo.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/src/index.css:
--------------------------------------------------------------------------------
1 | body {
2 | margin: 0;
3 | font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', 'Roboto', 'Oxygen',
4 | 'Ubuntu', 'Cantarell', 'Fira Sans', 'Droid Sans', 'Helvetica Neue',
5 | sans-serif;
6 | -webkit-font-smoothing: antialiased;
7 | -moz-osx-font-smoothing: grayscale;
8 | }
9 |
10 | code {
11 | font-family: source-code-pro, Menlo, Monaco, Consolas, 'Courier New',
12 | monospace;
13 | }
14 |
--------------------------------------------------------------------------------
/src/index.js:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 | import ReactDOM from 'react-dom';
3 | import './index.css';
4 | import App from './App';
5 | import { BrowserRouter } from 'react-router-dom';
6 |
7 | ReactDOM.render(
8 |
9 |
10 |
11 |
12 | ,
13 | document.getElementById('root')
14 | );
15 |
--------------------------------------------------------------------------------