├── .hintrc ├── webpack.config.js ├── .eslintrc.json ├── .stylelintrc.json ├── LICENSE ├── package.json ├── src ├── index.html ├── index.js └── style.css ├── .gitignore ├── .github └── workflows │ └── linter.yml └── README.md /.hintrc: -------------------------------------------------------------------------------- 1 | { 2 | "connector": { 3 | "name": "local", 4 | "options": { 5 | "pattern": ["**", "!.git/**", "!node_modules/**"] 6 | } 7 | }, 8 | "extends": ["development"], 9 | "formatters": ["stylish"], 10 | "hints": [ 11 | "button-type", 12 | "disown-opener", 13 | "html-checker", 14 | "meta-charset-utf-8", 15 | "meta-viewport", 16 | "no-inline-styles:error" 17 | ] 18 | } 19 | -------------------------------------------------------------------------------- /webpack.config.js: -------------------------------------------------------------------------------- 1 | /* eslint import/no-unresolved:0 */ 2 | const path = require('path'); 3 | const HtmlWebpackPlugin = require('html-webpack-plugin'); 4 | 5 | module.exports = { 6 | module: { 7 | rules: [ 8 | { 9 | test: /\.css$/, 10 | use: ['style-loader', 'css-loader'], 11 | }, 12 | ], 13 | }, 14 | plugins: [ 15 | new HtmlWebpackPlugin({ 16 | template: path.resolve(__dirname, 'src', 'index.html'), 17 | }), 18 | ], 19 | }; -------------------------------------------------------------------------------- /.eslintrc.json: -------------------------------------------------------------------------------- 1 | { 2 | "env": { 3 | "browser": true, 4 | "es6": true, 5 | "jest": true 6 | }, 7 | "parser": "babel-eslint", 8 | "parserOptions": { 9 | "ecmaVersion": 2018, 10 | "sourceType": "module" 11 | }, 12 | "extends": ["airbnb-base"], 13 | "rules": { 14 | "no-shadow": "off", 15 | "no-param-reassign": "off", 16 | "eol-last": "off", 17 | "import/extensions": [ 18 | 1, 19 | { 20 | "js": "always", 21 | "json": "always" 22 | } 23 | ] 24 | }, 25 | "ignorePatterns": ["dist/", "build/"] 26 | } 27 | -------------------------------------------------------------------------------- /.stylelintrc.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": ["stylelint-config-standard"], 3 | "plugins": ["stylelint-scss", "stylelint-csstree-validator"], 4 | "rules": { 5 | "at-rule-no-unknown": [ 6 | true, 7 | { 8 | "ignoreAtRules": [ 9 | "tailwind", 10 | "apply", 11 | "variants", 12 | "responsive", 13 | "screen" 14 | ] 15 | } 16 | ], 17 | "scss/at-rule-no-unknown": [ 18 | true, 19 | { 20 | "ignoreAtRules": [ 21 | "tailwind", 22 | "apply", 23 | "variants", 24 | "responsive", 25 | "screen" 26 | ] 27 | } 28 | ], 29 | "csstree/validator": true 30 | }, 31 | "ignoreFiles": [ 32 | "build/**", 33 | "dist/**", 34 | "**/reset*.css", 35 | "**/bootstrap*.css", 36 | "**/*.js", 37 | "**/*.jsx" 38 | ] 39 | } 40 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2023 Nahom_zd 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 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "leaderboard", 3 | "version": "1.0.0", 4 | "description": "", 5 | "main": "index.js", 6 | "scripts": { 7 | "test": "echo \"Error: no test specified\" && exit 1", 8 | "build": "webpack --mode development", 9 | "start": "webpack serve --mode development --open" 10 | }, 11 | "repository": { 12 | "type": "git", 13 | "url": "git+https://github.com/zdnahom/leaderboard.git" 14 | }, 15 | "keywords": [], 16 | "author": "", 17 | "license": "ISC", 18 | "bugs": { 19 | "url": "https://github.com/zdnahom/leaderboard/issues" 20 | }, 21 | "homepage": "https://github.com/zdnahom/leaderboard#readme", 22 | "devDependencies": { 23 | "babel-eslint": "^10.1.0", 24 | "css-loader": "^6.7.3", 25 | "eslint": "^7.32.0", 26 | "eslint-config-airbnb-base": "^14.2.1", 27 | "eslint-plugin-import": "^2.27.5", 28 | "html-webpack-plugin": "^5.5.0", 29 | "style-loader": "^3.3.1", 30 | "stylelint": "^13.13.1", 31 | "stylelint-config-standard": "^21.0.0", 32 | "stylelint-csstree-validator": "^1.9.0", 33 | "stylelint-scss": "^3.21.0", 34 | "webpack": "^5.75.0", 35 | "webpack-cli": "^5.0.1", 36 | "webpack-dev-server": "^4.11.1" 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /src/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 11 | 12 | 13 | Leaderboard Homepage 14 | 15 | 16 |
17 |

Leaderboard

18 |
19 |
20 |
21 |
22 |

Recent scores

23 | 24 |
25 |
26 |
27 | User 28 | Score 29 |
30 |
31 |
32 | 41 |
42 | 43 | 44 | 45 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Logs 2 | logs 3 | *.log 4 | npm-debug.log* 5 | yarn-debug.log* 6 | yarn-error.log* 7 | lerna-debug.log* 8 | 9 | # Diagnostic reports (https://nodejs.org/api/report.html) 10 | report.[0-9]*.[0-9]*.[0-9]*.[0-9]*.json 11 | 12 | # Runtime data 13 | pids 14 | *.pid 15 | *.seed 16 | *.pid.lock 17 | 18 | # Directory for instrumented libs generated by jscoverage/JSCover 19 | lib-cov 20 | 21 | # Coverage directory used by tools like istanbul 22 | coverage 23 | *.lcov 24 | 25 | # nyc test coverage 26 | .nyc_output 27 | 28 | # Grunt intermediate storage (https://gruntjs.com/creating-plugins#storing-task-files) 29 | .grunt 30 | 31 | # Bower dependency directory (https://bower.io/) 32 | bower_components 33 | 34 | # node-waf configuration 35 | .lock-wscript 36 | 37 | # Compiled binary addons (https://nodejs.org/api/addons.html) 38 | build/Release 39 | 40 | # Dependency directories 41 | node_modules/ 42 | jspm_packages/ 43 | 44 | # TypeScript v1 declaration files 45 | typings/ 46 | 47 | # TypeScript cache 48 | *.tsbuildinfo 49 | 50 | # Optional npm cache directory 51 | .npm 52 | 53 | # Optional eslint cache 54 | .eslintcache 55 | 56 | # Microbundle cache 57 | .rpt2_cache/ 58 | .rts2_cache_cjs/ 59 | .rts2_cache_es/ 60 | .rts2_cache_umd/ 61 | 62 | # Optional REPL history 63 | .node_repl_history 64 | 65 | # Output of 'npm pack' 66 | *.tgz 67 | 68 | # Yarn Integrity file 69 | .yarn-integrity 70 | 71 | # dotenv environment variables file 72 | .env 73 | .env.test 74 | 75 | # parcel-bundler cache (https://parceljs.org/) 76 | .cache 77 | 78 | # Next.js build output 79 | .next 80 | 81 | # Nuxt.js build / generate output 82 | .nuxt 83 | dist 84 | 85 | # Gatsby files 86 | .cache/ 87 | # Comment in the public line in if your project uses Gatsby and *not* Next.js 88 | # https://nextjs.org/blog/next-9-1#public-directory-support 89 | # public 90 | 91 | # vuepress build output 92 | .vuepress/dist 93 | 94 | # Serverless directories 95 | .serverless/ 96 | 97 | # FuseBox cache 98 | .fusebox/ 99 | 100 | # DynamoDB Local files 101 | .dynamodb/ 102 | 103 | # TernJS port file 104 | .tern-port 105 | -------------------------------------------------------------------------------- /src/index.js: -------------------------------------------------------------------------------- 1 | /* eslint no-unused-vars: 0 */ 2 | import './style.css'; 3 | 4 | const refreshButton = document.querySelector('.recent-scores button'); 5 | const leaders = document.querySelector('.leaders'); 6 | const form = document.querySelector('form'); 7 | const successElement = document.querySelector('form span'); 8 | 9 | const { name, score } = form.elements; 10 | 11 | const generateScores = (data) => { 12 | data.forEach((item) => { 13 | const player = document.createElement('div'); 14 | player.innerHTML = ` 15 | ${item.user} ${item.score} 16 | `; 17 | leaders.appendChild(player); 18 | }); 19 | }; 20 | 21 | const createNewGame = async () => { 22 | await fetch( 23 | 'https://us-central1-js-capstone-backend.cloudfunctions.net/api/games/', 24 | { 25 | method: 'POST', 26 | body: JSON.stringify({ 27 | name: "Beat Nahom's score", 28 | }), 29 | headers: { 30 | 'Content-type': 'application/json; charset=UTF-8', 31 | }, 32 | }, 33 | ); 34 | }; 35 | 36 | const refreshBoard = async () => { 37 | const res = await fetch('https://us-central1-js-capstone-backend.cloudfunctions.net/api/games/BwlgxYvt8p5JJSu0N3Ht/scores'); 38 | const data = await res.json(); 39 | const { result } = data; 40 | 41 | result.sort((a, b) => { 42 | if (Number(a.score) > Number(b.score)) { 43 | return -1; 44 | } 45 | if (Number(a.score) > Number(b.score)) { 46 | return 1; 47 | } 48 | return 0; 49 | }); 50 | 51 | generateScores(result); 52 | }; 53 | 54 | const addScore = async (userName, score) => { 55 | await fetch( 56 | 'https://us-central1-js-capstone-backend.cloudfunctions.net/api/games/BwlgxYvt8p5JJSu0N3Ht/scores', 57 | { 58 | method: 'POST', 59 | body: JSON.stringify({ 60 | user: userName, 61 | score, 62 | }), 63 | headers: { 64 | 'Content-type': 'application/json; charset=UTF-8', 65 | }, 66 | }, 67 | ); 68 | }; 69 | refreshButton.addEventListener('click', () => { 70 | leaders.innerHTML = ''; 71 | refreshBoard(); 72 | }); 73 | 74 | form.addEventListener('submit', (event) => { 75 | event.preventDefault(); 76 | addScore(name.value, score.value); 77 | name.value = ''; 78 | score.value = ''; 79 | successElement.textContent = 'Successfully added score to the game!'; 80 | }); 81 | window.addEventListener('DOMContentLoaded', () => { 82 | refreshBoard(); 83 | }); 84 | -------------------------------------------------------------------------------- /.github/workflows/linter.yml: -------------------------------------------------------------------------------- 1 | name: Linters 2 | 3 | on: pull_request 4 | 5 | env: 6 | FORCE_COLOR: 1 7 | 8 | jobs: 9 | lighthouse: 10 | name: Lighthouse 11 | runs-on: ubuntu-22.04 12 | steps: 13 | - uses: actions/checkout@v2 14 | - uses: actions/setup-node@v1 15 | with: 16 | node-version: "12.x" 17 | - name: Setup Lighthouse 18 | run: npm install -g @lhci/cli@0.7.x 19 | - name: Lighthouse Report 20 | run: lhci autorun --upload.target=temporary-public-storage --collect.staticDistDir=. 21 | webhint: 22 | name: Webhint 23 | runs-on: ubuntu-22.04 24 | steps: 25 | - uses: actions/checkout@v2 26 | - uses: actions/setup-node@v1 27 | with: 28 | node-version: "12.x" 29 | - name: Setup Webhint 30 | run: | 31 | npm install --save-dev hint@7.x 32 | [ -f .hintrc ] || wget https://raw.githubusercontent.com/microverseinc/linters-config/master/html-css-js/.hintrc 33 | - name: Webhint Report 34 | run: npx hint . 35 | stylelint: 36 | name: Stylelint 37 | runs-on: ubuntu-22.04 38 | steps: 39 | - uses: actions/checkout@v2 40 | - uses: actions/setup-node@v1 41 | with: 42 | node-version: "12.x" 43 | - name: Setup Stylelint 44 | run: | 45 | npm install --save-dev stylelint@13.x stylelint-scss@3.x stylelint-config-standard@21.x stylelint-csstree-validator@1.x 46 | [ -f .stylelintrc.json ] || wget https://raw.githubusercontent.com/microverseinc/linters-config/master/html-css-js/.stylelintrc.json 47 | - name: Stylelint Report 48 | run: npx stylelint "**/*.{css,scss}" 49 | eslint: 50 | name: ESLint 51 | runs-on: ubuntu-22.04 52 | steps: 53 | - uses: actions/checkout@v2 54 | - uses: actions/setup-node@v1 55 | with: 56 | node-version: "12.x" 57 | - name: Setup ESLint 58 | run: | 59 | npm install --save-dev eslint@7.x eslint-config-airbnb-base@14.x eslint-plugin-import@2.x babel-eslint@10.x 60 | [ -f .eslintrc.json ] || wget https://raw.githubusercontent.com/microverseinc/linters-config/master/html-css-js/.eslintrc.json 61 | - name: ESLint Report 62 | run: npx eslint . 63 | nodechecker: 64 | name: node_modules checker 65 | runs-on: ubuntu-22.04 66 | steps: 67 | - uses: actions/checkout@v2 68 | - name: Check node_modules existence 69 | run: | 70 | if [ -d "node_modules/" ]; then echo -e "\e[1;31mThe node_modules/ folder was pushed to the repo. Please remove it from the GitHub repository and try again."; echo -e "\e[1;32mYou can set up a .gitignore file with this folder included on it to prevent this from happening in the future." && exit 1; fi 71 | -------------------------------------------------------------------------------- /src/style.css: -------------------------------------------------------------------------------- 1 | @import url("https://fonts.googleapis.com/css2?family=Lato:wght@300;400;700;900&display=swap"); 2 | @import url('https://fonts.googleapis.com/css2?family=Press+Start+2P&display=swap'); 3 | 4 | * { 5 | margin: 0; 6 | padding: 0; 7 | box-sizing: border-box; 8 | font-family: 'Press Start 2P', cursive; 9 | } 10 | 11 | body { 12 | background-image: url('https://cdna.artstation.com/p/assets/images/images/047/517/388/original/inkpendude-portal-storm.gif?1647794887'); 13 | background-size: cover; 14 | height: 100vh; 15 | padding: 0; 16 | margin: 0; 17 | } 18 | 19 | .btn { 20 | background-color: #f8cb01; 21 | border-radius: 0.5rem; 22 | border: 1px solid #ffe260; 23 | color: #fff; 24 | line-height: 1.5em; 25 | letter-spacing: 0.03em; 26 | transition-duration: 0.4s; 27 | padding: 5px 10px; 28 | cursor: pointer; 29 | } 30 | 31 | .btn:hover { 32 | transform: scale(1.2); 33 | } 34 | 35 | header { 36 | padding-top: 50px; 37 | padding-left: 2%; 38 | } 39 | 40 | header h1 { 41 | font-size: 4em; 42 | color: #fff; 43 | } 44 | 45 | main { 46 | padding: 35px 10%; 47 | display: flex; 48 | flex-direction: column; 49 | gap: 50px; 50 | } 51 | 52 | .leaderboard-section { 53 | width: 100%; 54 | } 55 | 56 | .recent-scores { 57 | display: flex; 58 | justify-content: space-between; 59 | } 60 | 61 | .recent-scores h2 { 62 | font-size: 1.5em; 63 | color: #fff; 64 | } 65 | 66 | .recent-scores button { 67 | align-self: center; 68 | } 69 | 70 | .leaders { 71 | display: flex; 72 | flex-direction: column; 73 | gap: 5px; 74 | border: 2px solid #f5e9b4; 75 | margin-top: 30px; 76 | max-height: 500px; 77 | overflow-y: scroll; 78 | -ms-overflow-style: none; 79 | scrollbar-width: none; 80 | } 81 | 82 | /* Hide scrollbar for Chrome, Safari and Opera */ 83 | .leaders::-webkit-scrollbar { 84 | display: none; 85 | } 86 | 87 | .leaders div { 88 | display: flex; 89 | justify-content: space-between; 90 | padding: 10px; 91 | align-items: center; 92 | width: 100%; 93 | } 94 | 95 | .leaders div:nth-child(odd) { 96 | background-color: #f5e9b4; 97 | } 98 | 99 | .leaders div:nth-child(even) { 100 | background-color: white; 101 | } 102 | 103 | .leaders div:nth-child(1) { 104 | background-color: rgb(108, 247, 108); 105 | } 106 | 107 | .add-score { 108 | width: 80%; 109 | } 110 | 111 | .add-score h2 { 112 | font-size: 1.5em; 113 | color: #fff; 114 | } 115 | 116 | .add-score form { 117 | margin-top: 30px; 118 | display: flex; 119 | flex-direction: column; 120 | width: 100%; 121 | row-gap: 20px; 122 | } 123 | 124 | .add-score button { 125 | align-self: flex-end; 126 | } 127 | 128 | .add-score span { 129 | color: rgb(108, 247, 108); 130 | font-size: 1em; 131 | } 132 | 133 | .add-score input { 134 | padding: 8px; 135 | outline: none; 136 | } 137 | 138 | @media screen and (min-width: 768px) { 139 | main { 140 | display: flex; 141 | flex-direction: row; 142 | gap: 10%; 143 | } 144 | 145 | .leaderboard-section { 146 | width: 50%; 147 | } 148 | 149 | .add-score { 150 | width: 30%; 151 | } 152 | } 153 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | 2 | 3 | # 📗 Table of Contents 4 | 5 | - [📗 Table of Contents](#-table-of-contents) 6 | - [📖 Leaderboard](#-leaderboard) 7 | - [🛠 Built With ](#-built-with-) 8 | - [Tech Stack ](#tech-stack-) 9 | - [Key Features ](#key-features-) 10 | - [🚀 Live Demo ](#-live-demo-) 11 | - [💻 Getting Started ](#-getting-started-) 12 | - [Prerequisites](#prerequisites) 13 | - [Setup](#setup) 14 | - [Install](#install) 15 | - [Usage](#usage) 16 | - [Run tests](#run-tests) 17 | - [👥 Authors ](#-authors-) 18 | - [🔭 Future Features ](#-future-features-) 19 | - [🤝 Contributing ](#-contributing-) 20 | - [⭐️ Show your support ](#️-show-your-support-) 21 | - [🙏 Acknowledgments ](#-acknowledgments-) 22 | - [❓ FAQ (OPTIONAL) ](#-faq-optional-) 23 | - [📝 License ](#-license-) 24 | 25 | 26 | 27 | # 📖 Leaderboard 28 | > 29 | Leaderboard is website which displays scores submitted by different players. It also allows you to submit your score. All data is preserved thanks to the external Leaderboard API service. It is built using pure javascript(ES6) , HTML, CSS, and Webpack. 30 | 31 | ## 🛠 Built With 32 | 33 | ### Tech Stack 34 | 35 |
36 | Client 37 | 42 |
43 |
44 | Server 45 | 49 |
50 | 51 | 52 | 53 | 54 | ### Key Features 55 | 56 | - **Display raw leaderboard data** 57 | 58 | 59 | 60 | 61 |

(back to top)

62 | 63 | 64 | 65 | ## 🚀 Live Demo 66 | 67 | No live demo for now.But it will be added in the near future. 68 | 69 |

(back to top)

70 | 71 | 72 | ## 💻 Getting Started 73 | 74 | 75 | ### Prerequisites 76 | 77 | In order to run this project you need: Configure your code editor with HTML , CSS & JS and some other important extensions 78 | 79 | 80 | 81 | ### Setup 82 | 83 | git clone git@github.com:zdnahom/leaderboard.git 84 | 85 | 86 | 87 | ### Install 88 | 89 | Install this project with: 90 | 91 | git clone git@github.com:zdnahom/leaderboard.git 92 | 93 | 94 | ### Usage 95 | 96 | To run the project, execute the following command: 97 | - cd leaderboard 98 | - npm install 99 | - npm run build 100 | - npm start 101 | 102 | ### Run tests 103 | 104 | No test module for now.But it will be added in the near future. 105 | 106 | 107 | 108 | 109 | ## 👥 Authors 110 | 111 | 👤 **Nahom Zerihun Demissie 💻** 112 | - GitHub: [@zdnahom](https://github.com/zdnahom/) 113 | 114 | 115 |

(back to top)

116 | 117 | 118 | 119 | ## 🔭 Future Features 120 | 121 | - **Fetch data from Leaderboard API** 122 | - **Display players scores dynamically** 123 | - **Add player name and score** 124 | - **Sort players scores** 125 | 126 | 127 | 128 | 129 | 130 |

(back to top)

131 | 132 | 133 | 134 | ## 🤝 Contributing 135 | 136 | Contributions, issues, and feature requests are welcome! 137 | 138 | Feel free to check the [issues page](../../issues/). 139 | 140 |

(back to top)

141 | 142 | 143 | 144 | ## ⭐️ Show your support 145 | 146 | If you like this project , please clone it and try it . I know you're going to love it 147 | 148 |

(back to top)

149 | 150 | 151 | 152 | ## 🙏 Acknowledgments 153 | I would like to thank Microverse(staffs , mentors , reviewers) giving me the knowledge to build an amazing project like this. 154 | 155 |

(back to top)

156 | 157 | 158 | 159 | ## ❓ FAQ (OPTIONAL) 160 | 161 | - **Can I fork the project and make a contribution?** 162 | 163 | Of course you can! First fork it and contribute to it. 164 | 165 | - **How should I ask a pull request** 166 | 167 | - Step 1 : Click on the pull request button 168 | - Step 2 : create pull request 169 | 170 |

(back to top)

171 | 172 | 173 | 174 | ## 📝 License 175 | 176 | This project is [MIT](./LICENSE) licensed. 177 | 178 | _NOTE: we recommend using the [MIT license](https://choosealicense.com/licenses/mit/) - you can set it up quickly by [using templates available on GitHub](https://docs.github.com/en/communities/setting-up-your-project-for-healthy-contributions/adding-a-license-to-a-repository). You can also use [any other license](https://choosealicense.com/licenses/) if you wish._ 179 | 180 |

(back to top)

181 | --------------------------------------------------------------------------------