├── .all-contributorsrc ├── .gitignore ├── CONTRIBUTING.md ├── LICENSE.md ├── README.md ├── package-lock.json ├── package.json ├── public ├── favicon.png ├── index.html ├── logo192.png ├── logo512.png ├── manifest.json └── robots.txt └── src ├── App.css ├── App.js ├── assets ├── FacebookIcon.js ├── LinkedinIcon.js ├── SvgWrapper.js ├── TwitterIcon.js └── svgs.js ├── components ├── ErrorMessage.js ├── HomeShocase.js ├── HomeShowcase.js ├── Profile.js ├── SearchForm.js └── SocialHandler.js ├── index.css ├── index.js ├── serviceWorker.js ├── services └── Github.js └── utils ├── Dimensions.js └── usePrevious.js /.all-contributorsrc: -------------------------------------------------------------------------------- 1 | { 2 | "files": [ 3 | "README.md" 4 | ], 5 | "imageSize": 100, 6 | "commit": false, 7 | "contributors": [ 8 | { 9 | "login": "NomanGul", 10 | "name": "Noman Gul", 11 | "avatar_url": "https://avatars1.githubusercontent.com/u/39244918?v=4", 12 | "profile": "https://dev.to/nomangul", 13 | "contributions": [ 14 | "infra", 15 | "code" 16 | ] 17 | }, 18 | { 19 | "login": "MuhaddiMu", 20 | "name": "Muhammad Muhaddis", 21 | "avatar_url": "https://avatars3.githubusercontent.com/u/26611847?v=4", 22 | "profile": "http://www.Muhaddis.Info", 23 | "contributions": [ 24 | "code" 25 | ] 26 | }, 27 | { 28 | "login": "ahmadawais", 29 | "name": "Ahmad Awais ⚡️", 30 | "avatar_url": "https://avatars1.githubusercontent.com/u/960133?v=4", 31 | "profile": "https://AhmadAwais.com/", 32 | "contributions": [ 33 | "bug" 34 | ] 35 | }, 36 | { 37 | "login": "Mohammad-Quanit", 38 | "name": "mquanit", 39 | "avatar_url": "https://avatars3.githubusercontent.com/u/32056694?v=4", 40 | "profile": "https://mohammad-quanit.github.io/", 41 | "contributions": [ 42 | "code" 43 | ] 44 | }, 45 | { 46 | "login": "abhisheksatre", 47 | "name": "Abhishek Satre", 48 | "avatar_url": "https://avatars2.githubusercontent.com/u/7577351?v=4", 49 | "profile": "https://abhisheksatre.com", 50 | "contributions": [ 51 | "code" 52 | ] 53 | }, 54 | { 55 | "login": "Sn0wB", 56 | "name": "Sn0wB", 57 | "avatar_url": "https://avatars0.githubusercontent.com/u/51188711?v=4", 58 | "profile": "https://github.com/Sn0wB", 59 | "contributions": [ 60 | "bug" 61 | ] 62 | }, 63 | { 64 | "login": "iadeelzafar", 65 | "name": "Adeel Zafar", 66 | "avatar_url": "https://avatars0.githubusercontent.com/u/36811908?v=4", 67 | "profile": "http://adeelzafar.dev", 68 | "contributions": [ 69 | "doc" 70 | ] 71 | }, 72 | { 73 | "login": "Mudassar045", 74 | "name": "Mudassar Ali", 75 | "avatar_url": "https://avatars0.githubusercontent.com/u/24487349?v=4", 76 | "profile": "http://thefactsbook.com", 77 | "contributions": [ 78 | "doc" 79 | ] 80 | }, 81 | { 82 | "login": "rehan-sattar", 83 | "name": "Rehan Sattar", 84 | "avatar_url": "https://avatars1.githubusercontent.com/u/26999472?v=4", 85 | "profile": "https://rehan-sattar.github.io", 86 | "contributions": [ 87 | "code", 88 | "review" 89 | ] 90 | }, 91 | { 92 | "login": "MOHAMMADArsalan", 93 | "name": "Mohammad Arsalan", 94 | "avatar_url": "https://avatars0.githubusercontent.com/u/14179110?v=4", 95 | "profile": "https://github.com/MOHAMMADArsalan", 96 | "contributions": [ 97 | "code" 98 | ] 99 | }, 100 | { 101 | "login": "viveksharmaui", 102 | "name": "Vivek Anand Sharma", 103 | "avatar_url": "https://avatars1.githubusercontent.com/u/28563357?v=4", 104 | "profile": "https://viveksharmaui.js.org", 105 | "contributions": [ 106 | "code" 107 | ] 108 | }, 109 | { 110 | "login": "smkamranqadri", 111 | "name": "Muhammad Kamran", 112 | "avatar_url": "https://avatars2.githubusercontent.com/u/13115396?v=4", 113 | "profile": "https://kamranqadri.me", 114 | "contributions": [ 115 | "infra" 116 | ] 117 | }, 118 | { 119 | "login": "umershaikh97", 120 | "name": "Umer Shaikh", 121 | "avatar_url": "https://avatars0.githubusercontent.com/u/26284894?v=4", 122 | "profile": "https://geeksofkolachi.com/", 123 | "contributions": [ 124 | "design", 125 | "code" 126 | ] 127 | } 128 | ], 129 | "contributorsPerLine": 7, 130 | "projectName": "octocat-day", 131 | "projectOwner": "NomanGul", 132 | "repoType": "github", 133 | "repoHost": "https://github.com" 134 | } 135 | -------------------------------------------------------------------------------- /.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 | .eslintcache 25 | -------------------------------------------------------------------------------- /CONTRIBUTING.md: -------------------------------------------------------------------------------- 1 | # Contributing 2 | 3 | When contributing to this repository, please first discuss the change you wish to make via issue, 4 | email, or any other method with the owner of this repository before making a change. 5 | 6 | Please note we have a code of conduct, please follow it in all your interactions with the project. 7 | 8 | ## Pull Request Process 9 | 10 | 1. The first time you work on the project, you need to clone it using the following command: 11 | ``` 12 | git clone https://github.com/NomanGul/octocat-day.git 13 | ``` 14 | 15 | 2. Never Push anything to master branch directly. So to avoid this you have to checkout to development branch by the following method: 16 | ```bash 17 | git checkout development 18 | git pull --rebase origin development # To make sure you have up-to-date development. Very important. 19 | ``` 20 | 21 | 3. From the `development` branch you have to create a new branch with proper specified names 22 | 23 | Example 24 | ```bash 25 | git checkout -b feat- 26 | 27 | # Now Start working on files and once done only submit your relative work files, not linter or something else. 28 | # This is very important for others to review. 29 | 30 | git add 31 | git commit -m "CLEAN and CONCISE message" 32 | git pull --rebase origin development # To make sure that you have the latest changes from "origin development" 33 | git push origin feat- 34 | ``` 35 | 36 | 4. Create Pull Request (PR) 37 | 38 | Once you have created the branch, did some coding, now submit a `Pull Request` back to `development` with the title starting as `WIP:` which means "Work In Progress". Some of the guidelines for submitting PRs are as below: 39 | * Always rebase with development before submitting a PR (check above examples). 40 | * Create short PRs that should be easy to review and make suggested changes. Shorter PRs have more chances to get approved quickly and it's also easy to make changes. 41 | * Try your best to get a PR approved and merged before making another PR. 42 | * Ideally there should be a PR per issue i.e. one PR should close one issue at a time. Create multiple PRs for multiple issues. 43 | * Put the following sentence in the PR description field: `PR for issue #issue_number` 44 | * Once you feel it's ready, remove the `WIP:` from the title and assign at least one reviewer. Later on, the reviewer will either request some changes or they will approve the PR if everything is perfect. 45 | 46 | **Example of Good PR:** 47 | * A PR with 1-5 modified files 48 | * A PR addressing and preferably closing a single issue 49 | * A PR with `WIP` in the title if it's not closing the issue 50 | 51 | **Example of Bad PR:** 52 | * A PR with 5+ files 53 | * A PR with 100+ lines of modified code 54 | * A PR addressing multiple issues 55 | * Multiple, very small & repetitive PRs of just a few lines of code changes 56 | 57 | Some of the guidelines for submitting PRs are as below: 58 | 59 | * Commits should be small. We don't encourage commits with hundreds of modified code lines or several modified files. 60 | * Ideally a commit should refer to a particular change/functionality/fix. 61 | * Commit message should be descriptive, small and clear. 62 | * Commit message completely should not be in uppercase. 63 | * Ensure there is NO semi-colon. 64 | * Code is properly indented with 2 space method. 65 | 66 | ## Code of Conduct 67 | 68 | ### Our Pledge 69 | 70 | In the interest of fostering an open and welcoming environment, we as 71 | contributors and maintainers pledge to making participation in our project and 72 | our community a harassment-free experience for everyone, regardless of age, body 73 | size, disability, ethnicity, gender identity and expression, level of experience, 74 | nationality, personal appearance, race, religion, or sexual identity and 75 | orientation. 76 | 77 | ### Our Standards 78 | 79 | Examples of behavior that contributes to creating a positive environment 80 | include: 81 | 82 | * Using welcoming and inclusive language 83 | * Being respectful of differing viewpoints and experiences 84 | * Gracefully accepting constructive criticism 85 | * Focusing on what is best for the community 86 | * Showing empathy towards other community members 87 | 88 | Examples of unacceptable behavior by participants include: 89 | 90 | * The use of sexualized language or imagery and unwelcome sexual attention or 91 | advances 92 | * Trolling, insulting/derogatory comments, and personal or political attacks 93 | * Public or private harassment 94 | * Publishing others' private information, such as a physical or electronic 95 | address, without explicit permission 96 | * Other conduct which could reasonably be considered inappropriate in a 97 | professional setting 98 | 99 | ### Our Responsibilities 100 | 101 | Project maintainers are responsible for clarifying the standards of acceptable 102 | behavior and are expected to take appropriate and fair corrective action in 103 | response to any instances of unacceptable behavior. 104 | 105 | Project maintainers have the right and responsibility to remove, edit, or 106 | reject comments, commits, code, wiki edits, issues, and other contributions 107 | that are not aligned to this Code of Conduct, or to ban temporarily or 108 | permanently any contributor for other behaviors that they deem inappropriate, 109 | threatening, offensive, or harmful. 110 | 111 | ### Scope 112 | 113 | This Code of Conduct applies both within project spaces and in public spaces 114 | when an individual is representing the project or its community. Examples of 115 | representing a project or community include using an official project e-mail 116 | address, posting via an official social media account, or acting as an appointed 117 | representative at an online or offline event. Representation of a project may be 118 | further defined and clarified by project maintainers. 119 | 120 | ### Enforcement 121 | 122 | Instances of abusive, harassing, or otherwise unacceptable behavior may be 123 | reported by contacting the project team at nomangul2001@gmail.com. All 124 | complaints will be reviewed and investigated and will result in a response that 125 | is deemed necessary and appropriate to the circumstances. The project team is 126 | obligated to maintain confidentiality with regard to the reporter of an incident. 127 | Further details of specific enforcement policies may be posted separately. 128 | 129 | Project maintainers who do not follow or enforce the Code of Conduct in good 130 | faith may face temporary or permanent repercussions as determined by other 131 | members of the project's leadership. 132 | -------------------------------------------------------------------------------- /LICENSE.md: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2019 Noman Gul 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 |

Octocat Day :octocat:

2 | 3 |

Believe me, It'll give you your open-source birthday date :grin:

4 | 5 |
6 | octocat day image 7 |
8 | 9 | --- 10 | 11 | ## Built With 12 | 13 | * [ReactJS](https://reactjs.org/) - The SPA library used 🔧 14 | * [Ant Design](https://ant.design/) - UI library 🌈 15 | * [GitHub API](https://developer.github.com/v3/) - :octocat: 16 | 17 | ## Contributors ✨ 18 | 19 | Thanks goes to these wonderful people ([emoji key](https://allcontributors.org/docs/en/emoji-key)): 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 |
Noman Gul
Noman Gul

🚇 💻
Muhammad Muhaddis
Muhammad Muhaddis

💻
Ahmad Awais ⚡️
Ahmad Awais ⚡️

🐛
mquanit
mquanit

💻
Abhishek Satre
Abhishek Satre

💻
Sn0wB
Sn0wB

🐛
Adeel Zafar
Adeel Zafar

📖
Mudassar Ali
Mudassar Ali

📖
Rehan Sattar
Rehan Sattar

💻 👀
Mohammad Arsalan
Mohammad Arsalan

💻
Vivek Anand Sharma
Vivek Anand Sharma

💻
Muhammad Kamran
Muhammad Kamran

🚇
Umer Shaikh
Umer Shaikh

🎨 💻
42 | 43 | 44 | 45 | Please don't hesitate to open an [issue](https://github.com/NomanGul/octocat-day/issues) or [pull request](https://github.com/NomanGul/octocat-day/pulls). You can also send me a message on [Twitter](https://twitter.com/NomanGulKhan). Contributions of any kind are welcomed! 46 | 47 | ## License 48 | 49 | This project is licensed under the MIT License - see the [LICENSE.md](LICENSE.md) file for details 50 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "octocat-day", 3 | "version": "0.1.0", 4 | "private": true, 5 | "homepage": "https://nomangul.github.io/octocat-day", 6 | "dependencies": { 7 | "antd": "^4.21.3", 8 | "moment": "^2.29.3", 9 | "react": "^18.2.0", 10 | "react-confetti": "^6.1.0", 11 | "react-dom": "^18.2.0", 12 | "react-scripts": "^5.0.1" 13 | }, 14 | "scripts": { 15 | "start": "react-scripts start", 16 | "build": "react-scripts build", 17 | "predeploy": "npm run build", 18 | "deploy": "gh-pages -d build", 19 | "test": "react-scripts test", 20 | "eject": "react-scripts eject" 21 | }, 22 | "eslintConfig": { 23 | "extends": "react-app" 24 | }, 25 | "browserslist": { 26 | "production": [ 27 | ">0.2%", 28 | "not dead", 29 | "not op_mini all" 30 | ], 31 | "development": [ 32 | "last 1 chrome version", 33 | "last 1 firefox version", 34 | "last 1 safari version" 35 | ] 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /public/favicon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/NomanGul/octocat-day/cf5a9c8023e4d0e1a8631c39198daf7258a14986/public/favicon.png -------------------------------------------------------------------------------- /public/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 12 | 13 | 17 | 18 | 27 | Octocat Day 28 | 29 | 30 | 31 |
32 | 42 | 43 | 44 | -------------------------------------------------------------------------------- /public/logo192.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/NomanGul/octocat-day/cf5a9c8023e4d0e1a8631c39198daf7258a14986/public/logo192.png -------------------------------------------------------------------------------- /public/logo512.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/NomanGul/octocat-day/cf5a9c8023e4d0e1a8631c39198daf7258a14986/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 | -------------------------------------------------------------------------------- /src/App.css: -------------------------------------------------------------------------------- 1 | @import url("https://fonts.googleapis.com/css?family=Fira+Code&display=swap"); 2 | 3 | .container { 4 | height: 100vh; 5 | background-color: #f0f2f5; 6 | display: flex; 7 | justify-content: center; 8 | align-items: center; 9 | flex-direction: column; 10 | } 11 | 12 | .header_container { 13 | margin-top: 20vh; 14 | text-align: center; 15 | } 16 | 17 | .header { 18 | font-weight: bold; 19 | font-family: "Fira Code", "Courier New", Courier, monospace; 20 | text-align: center; 21 | background: linear-gradient(to right, #485563, #29323c); 22 | background-clip: initial; 23 | -webkit-background-clip: text; 24 | -webkit-text-fill-color: transparent; 25 | } 26 | 27 | .sub_header { 28 | text-align: center; 29 | } 30 | 31 | .search_container { 32 | text-align: center; 33 | padding: 4vw; 34 | max-width: 30rem; 35 | margin: 0 auto; 36 | } 37 | 38 | .search { 39 | max-width: 800px; 40 | margin: 0px auto; 41 | } 42 | 43 | .row { 44 | display: flex; 45 | flex-direction: row; 46 | flex-wrap: wrap; 47 | width: 100%; 48 | } 49 | 50 | .column { 51 | display: flex; 52 | flex-direction: column; 53 | flex-basis: 100%; 54 | flex: 1; 55 | } 56 | 57 | .response__container { 58 | align-items: center; 59 | } 60 | 61 | .paragraph { 62 | display: flex; 63 | align-items: center; 64 | font-size: 2.6vh; 65 | } 66 | 67 | .paragraph a{ 68 | color: rgba(0,0,0,.45); 69 | margin-right: 1vh; 70 | } 71 | 72 | .date { 73 | font-size: 4vh; 74 | } 75 | 76 | .avatar-style { 77 | border-radius: 40px; 78 | width: 60px; 79 | height: 60px; 80 | margin-right: 10px 81 | } 82 | 83 | .facebookIcon { 84 | margin-top: 20px; 85 | } 86 | 87 | .twitterIcon { 88 | margin-top: 5px; 89 | } 90 | 91 | .linkedinIcon { 92 | margin-top:5px; 93 | background-color: #2867B2; 94 | border-radius: 20px; 95 | } 96 | -------------------------------------------------------------------------------- /src/App.js: -------------------------------------------------------------------------------- 1 | import React, { useState } from "react" 2 | import moment from "moment" 3 | import Confetti from "react-confetti" 4 | import { Spin } from "antd" 5 | import { width, height } from "./utils/Dimensions" 6 | import { usePrevious } from "./utils/usePrevious" 7 | import { FaceBookIcon, TwitterIcon, LinkedinIcon } from "./assets/svgs" 8 | import HomeShowcase from "./components/HomeShowcase" 9 | import SearchForm from "./components/SearchForm" 10 | import SocialHandler from "./components/SocialHandler" 11 | import ErrorMessage from "./components/ErrorMessage" 12 | import Profile from "./components/Profile" 13 | import GithubService from "./services/Github" 14 | import "./App.css" 15 | 16 | const ICON_WIDTH = 30, 17 | ICON_HEIGHT = 30 18 | 19 | const App = () => { 20 | const [{ name, date, login, avatar }, setData] = useState({ 21 | name: "", 22 | date: "", 23 | login: "", 24 | avatar: "" 25 | }) 26 | const [userName, setUserName] = useState("") 27 | const [loading, setLoading] = useState(false) 28 | const [error, setError] = useState("") 29 | 30 | const prevUsername = usePrevious(userName) 31 | 32 | // for github user data fetching via github api 33 | const getJoiningDate = async () => { 34 | if (!userName || prevUsername === userName) return false 35 | setLoading(true) 36 | setError("") 37 | try { 38 | const user = await GithubService.getJoiningDateOfUser(userName) 39 | setData({ 40 | name: user.name, 41 | date: moment(user.created_at).format("DD MMMM YYYY"), 42 | login: user.login, 43 | avatar: user.avatar_url 44 | }) 45 | setUserName("") 46 | } catch (err) { 47 | setData({ name: "", date: "", login: "" }) 48 | /** 49 | * @code err.message.split(":")[1] - Formatted message. 50 | * @description: Error constructor returns response of pattern Error: ERR_MESSAGE 51 | */ 52 | setError(err.message.split(":")[1]) 53 | } finally { 54 | setLoading(false) 55 | } 56 | } 57 | 58 | const renderProfileLink = () => { 59 | return ( 60 | 65 | {name || login} 66 | 67 | ) 68 | } 69 | 70 | return ( 71 |
72 | {!loading && date ? ( 73 | 79 | ) : null} 80 | 81 |
82 | 83 | setUserName(e.target.value)} 85 | value={userName} 86 | searchHandler={getJoiningDate} 87 | /> 88 |
89 | 90 |
91 | 92 | {!loading && date ? ( 93 | <> 94 | 99 |
100 | 103 | 108 | 109 | 112 | 117 | 118 | 121 | 126 | 127 |
128 | 129 | ) : error ? ( 130 | 131 | ) : null} 132 |
133 |
134 | ) 135 | } 136 | 137 | export default App 138 | -------------------------------------------------------------------------------- /src/assets/FacebookIcon.js: -------------------------------------------------------------------------------- 1 | import React from 'react' 2 | import SvgWrapper from './SvgWrapper' 3 | 4 | const FacebookIcon = ({ fill = '#3b5998', ...props }) => { 5 | return ( 6 | 7 | 11 | 12 | ); 13 | } 14 | 15 | export default FacebookIcon -------------------------------------------------------------------------------- /src/assets/LinkedinIcon.js: -------------------------------------------------------------------------------- 1 | import React from 'react' 2 | import SvgWrapper from './SvgWrapper' 3 | 4 | const LinkedinIcon = ({ fill = "#FFF", ...props }) => { 5 | delete props.viewBox 6 | props.viewBox = "0 0 512 512" 7 | return ( 8 | 9 | 13 | 14 | ); 15 | } 16 | 17 | export default LinkedinIcon -------------------------------------------------------------------------------- /src/assets/SvgWrapper.js: -------------------------------------------------------------------------------- 1 | import React from 'react' 2 | 3 | const SvgWrapper = ({ width = 24, height = 24, viewBox = '0 0 24 24', style = {}, children, ...props }) => { 4 | return ( 5 | {children} 13 | ); 14 | } 15 | 16 | export default SvgWrapper -------------------------------------------------------------------------------- /src/assets/TwitterIcon.js: -------------------------------------------------------------------------------- 1 | import React from 'react' 2 | import SvgWrapper from './SvgWrapper' 3 | 4 | const TwitterIcon = ({ fill = '#00acee', ...props }) => { 5 | return ( 6 | 7 | 11 | 12 | ); 13 | } 14 | 15 | export default TwitterIcon -------------------------------------------------------------------------------- /src/assets/svgs.js: -------------------------------------------------------------------------------- 1 | import FaceBookIcon from './FacebookIcon' 2 | import TwitterIcon from './TwitterIcon' 3 | import LinkedinIcon from "./LinkedinIcon" 4 | 5 | export { 6 | FaceBookIcon, 7 | TwitterIcon, 8 | LinkedinIcon 9 | } 10 | -------------------------------------------------------------------------------- /src/components/ErrorMessage.js: -------------------------------------------------------------------------------- 1 | import React from "react" 2 | import { Typography } from "antd" 3 | 4 | const { Paragraph } = Typography 5 | const ErrorMessage = ({ errMessage }) => ( 6 | 7 | {errMessage} 8 | 9 | ❌ 10 | 11 | 12 | ) 13 | export default ErrorMessage 14 | -------------------------------------------------------------------------------- /src/components/HomeShocase.js: -------------------------------------------------------------------------------- 1 | import React from "react" 2 | import { Typography } from "antd" 3 | 4 | const { Text, Title } = Typography 5 | 6 | const HomeShowcase = () => { 7 | return ( 8 | <> 9 | 10 | <span className="header">Octocat Day</span> 11 | <span role="img" aria-label="man_technologist"> 12 | 👨‍💻 13 | </span> 14 | 15 | 16 | GitHub user join date 17 | 18 | 😃 19 | 20 | 21 | 22 | ) 23 | } 24 | 25 | export default HomeShowcase 26 | -------------------------------------------------------------------------------- /src/components/HomeShowcase.js: -------------------------------------------------------------------------------- 1 | import React from "react" 2 | import { Typography } from "antd" 3 | 4 | const { Text, Title } = Typography 5 | 6 | const HomeShowcase = () => { 7 | return ( 8 | <> 9 | 10 | <span className="header">Octocat Day</span> 11 | <span role="img" aria-label="man_technologist"> 12 | 👨‍💻 13 | </span> 14 | 15 | 16 | GitHub user join date 17 | 18 | 😃 19 | 20 | 21 | 22 | ) 23 | } 24 | 25 | export default HomeShowcase 26 | -------------------------------------------------------------------------------- /src/components/Profile.js: -------------------------------------------------------------------------------- 1 | import React from "react" 2 | import { Typography } from "antd" 3 | 4 | const { Paragraph, Text } = Typography 5 | const Profile = ({ renderProfileLink, avatar, date }) => ( 6 | <> 7 | 8 | avatar 9 | {renderProfileLink()} joined GitHub on 10 | 11 | 12 | {date} 13 | 14 | 15 | ) 16 | 17 | export default Profile 18 | -------------------------------------------------------------------------------- /src/components/SearchForm.js: -------------------------------------------------------------------------------- 1 | import React from "react" 2 | import { Input } from "antd" 3 | 4 | const { Search } = Input 5 | const SearchForm = ({ handleChange, value, searchHandler }) => ( 6 |
7 | 16 |
17 | ) 18 | 19 | export default SearchForm 20 | -------------------------------------------------------------------------------- /src/components/SocialHandler.js: -------------------------------------------------------------------------------- 1 | import React from "react" 2 | 3 | const SocialHandler = ({ children, href }) => { 4 | return ( 5 | 11 | {children} 12 | 13 | ) 14 | } 15 | 16 | export default SocialHandler 17 | -------------------------------------------------------------------------------- /src/index.css: -------------------------------------------------------------------------------- 1 | @import '~antd/dist/antd.css'; 2 | 3 | body { 4 | margin: 0; 5 | font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", "Roboto", "Oxygen", 6 | "Ubuntu", "Cantarell", "Fira Sans", "Droid Sans", "Helvetica Neue", 7 | sans-serif; 8 | -webkit-font-smoothing: antialiased; 9 | -moz-osx-font-smoothing: grayscale; 10 | } 11 | 12 | code { 13 | font-family: source-code-pro, Menlo, Monaco, Consolas, "Courier New", 14 | monospace; 15 | } 16 | -------------------------------------------------------------------------------- /src/index.js: -------------------------------------------------------------------------------- 1 | import { StrictMode } from "react"; 2 | import { createRoot } from "react-dom/client"; 3 | import "./index.css"; 4 | import App from "./App"; 5 | import * as serviceWorker from "./serviceWorker"; 6 | 7 | const rootElement = document.getElementById("root"); 8 | const root = createRoot(rootElement); 9 | 10 | root.render( 11 | 12 | 13 | 14 | ); 15 | 16 | // If you want your app to work offline and load faster, you can change 17 | // unregister() to register() below. Note this comes with some pitfalls. 18 | // Learn more about service workers: https://bit.ly/CRA-PWA 19 | serviceWorker.unregister(); 20 | -------------------------------------------------------------------------------- /src/serviceWorker.js: -------------------------------------------------------------------------------- 1 | // This optional code is used to register a service worker. 2 | // register() is not called by default. 3 | 4 | // This lets the app load faster on subsequent visits in production, and gives 5 | // it offline capabilities. However, it also means that developers (and users) 6 | // will only see deployed updates on subsequent visits to a page, after all the 7 | // existing tabs open on the page have been closed, since previously cached 8 | // resources are updated in the background. 9 | 10 | // To learn more about the benefits of this model and instructions on how to 11 | // opt-in, read https://bit.ly/CRA-PWA 12 | 13 | const isLocalhost = Boolean( 14 | window.location.hostname === 'localhost' || 15 | // [::1] is the IPv6 localhost address. 16 | window.location.hostname === '[::1]' || 17 | // 127.0.0.1/8 is considered localhost for IPv4. 18 | window.location.hostname.match( 19 | /^127(?:\.(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)){3}$/ 20 | ) 21 | ); 22 | 23 | export function register(config) { 24 | if (process.env.NODE_ENV === 'production' && 'serviceWorker' in navigator) { 25 | // The URL constructor is available in all browsers that support SW. 26 | const publicUrl = new URL(process.env.PUBLIC_URL, window.location.href); 27 | if (publicUrl.origin !== window.location.origin) { 28 | // Our service worker won't work if PUBLIC_URL is on a different origin 29 | // from what our page is served on. This might happen if a CDN is used to 30 | // serve assets; see https://github.com/facebook/create-react-app/issues/2374 31 | return; 32 | } 33 | 34 | window.addEventListener('load', () => { 35 | const swUrl = `${process.env.PUBLIC_URL}/service-worker.js`; 36 | 37 | if (isLocalhost) { 38 | // This is running on localhost. Let's check if a service worker still exists or not. 39 | checkValidServiceWorker(swUrl, config); 40 | 41 | // Add some additional logging to localhost, pointing developers to the 42 | // service worker/PWA documentation. 43 | navigator.serviceWorker.ready.then(() => { 44 | console.log( 45 | 'This web app is being served cache-first by a service ' + 46 | 'worker. To learn more, visit https://bit.ly/CRA-PWA' 47 | ); 48 | }); 49 | } else { 50 | // Is not localhost. Just register service worker 51 | registerValidSW(swUrl, config); 52 | } 53 | }); 54 | } 55 | } 56 | 57 | function registerValidSW(swUrl, config) { 58 | navigator.serviceWorker 59 | .register(swUrl) 60 | .then(registration => { 61 | registration.onupdatefound = () => { 62 | const installingWorker = registration.installing; 63 | if (installingWorker == null) { 64 | return; 65 | } 66 | installingWorker.onstatechange = () => { 67 | if (installingWorker.state === 'installed') { 68 | if (navigator.serviceWorker.controller) { 69 | // At this point, the updated precached content has been fetched, 70 | // but the previous service worker will still serve the older 71 | // content until all client tabs are closed. 72 | console.log( 73 | 'New content is available and will be used when all ' + 74 | 'tabs for this page are closed. See https://bit.ly/CRA-PWA.' 75 | ); 76 | 77 | // Execute callback 78 | if (config && config.onUpdate) { 79 | config.onUpdate(registration); 80 | } 81 | } else { 82 | // At this point, everything has been precached. 83 | // It's the perfect time to display a 84 | // "Content is cached for offline use." message. 85 | console.log('Content is cached for offline use.'); 86 | 87 | // Execute callback 88 | if (config && config.onSuccess) { 89 | config.onSuccess(registration); 90 | } 91 | } 92 | } 93 | }; 94 | }; 95 | }) 96 | .catch(error => { 97 | console.error('Error during service worker registration:', error); 98 | }); 99 | } 100 | 101 | function checkValidServiceWorker(swUrl, config) { 102 | // Check if the service worker can be found. If it can't reload the page. 103 | fetch(swUrl) 104 | .then(response => { 105 | // Ensure service worker exists, and that we really are getting a JS file. 106 | const contentType = response.headers.get('content-type'); 107 | if ( 108 | response.status === 404 || 109 | (contentType != null && contentType.indexOf('javascript') === -1) 110 | ) { 111 | // No service worker found. Probably a different app. Reload the page. 112 | navigator.serviceWorker.ready.then(registration => { 113 | registration.unregister().then(() => { 114 | window.location.reload(); 115 | }); 116 | }); 117 | } else { 118 | // Service worker found. Proceed as normal. 119 | registerValidSW(swUrl, config); 120 | } 121 | }) 122 | .catch(() => { 123 | console.log( 124 | 'No internet connection found. App is running in offline mode.' 125 | ); 126 | }); 127 | } 128 | 129 | export function unregister() { 130 | if ('serviceWorker' in navigator) { 131 | navigator.serviceWorker.ready.then(registration => { 132 | registration.unregister(); 133 | }); 134 | } 135 | } 136 | -------------------------------------------------------------------------------- /src/services/Github.js: -------------------------------------------------------------------------------- 1 | /** 2 | * @class GithubService 3 | * @description A central service for all of the operations related to the Github Api. 4 | */ 5 | export default class GithubService { 6 | static getJoiningDateOfUser = async userName => { 7 | try { 8 | return await fetch(`https://api.github.com/users/${userName}`, { 9 | headers: { 10 | "User-Agent": "Octocat-Day" 11 | } 12 | }).then(res => { 13 | if (res.status === 404) throw new Error("User not found.") 14 | else if (res.status !== 200) throw new Error("Some Error Occurred.") 15 | else return res.json() 16 | }) 17 | } catch (err) { 18 | throw new Error(err) 19 | } 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /src/utils/Dimensions.js: -------------------------------------------------------------------------------- 1 | export const width = 2 | window.innerWidth || 3 | document.documentElement.clientWidth || 4 | document.body.clientWidth 5 | 6 | export const height = 7 | window.innerHeight || 8 | document.documentElement.clientHeight || 9 | document.body.clientHeight 10 | -------------------------------------------------------------------------------- /src/utils/usePrevious.js: -------------------------------------------------------------------------------- 1 | import React from "react" 2 | 3 | export const usePrevious = value => { 4 | const ref = React.useRef() 5 | React.useEffect(() => { 6 | ref.current = value 7 | }) 8 | return ref.current 9 | } 10 | --------------------------------------------------------------------------------