├── .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 | ![ScreenShot of Form](screenshots/generate.png) 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 | ![ScreenShot of Form](screenshots/duma.png) 33 | 34 | ## ScreenShot of Coutdown Timer⏲️ 35 | 36 | ![ScreenShot of Countdown](screenshots/countdown.png) 37 | 38 | ## Birthday Wisher🎂 39 | 40 | Loads this Page Instead of Coutdown on the Birthday 41 | ![ScreenShot of Countdown](screenshots/wishPage.png) 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 |
114 | 115 | Github-Logo 116 | 117 |
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 | --------------------------------------------------------------------------------