├── .gitignore ├── .hintrc ├── .eslintrc.json ├── .stylelintrc.json ├── package.json ├── LICENSE ├── .github └── workflows │ └── blank.yml ├── index.js ├── index.html ├── README.md └── style.css /.gitignore: -------------------------------------------------------------------------------- 1 | node_modules -------------------------------------------------------------------------------- /.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 | } -------------------------------------------------------------------------------- /.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": [ 1, { 18 | "js": "always", "json": "always" 19 | }] 20 | }, 21 | "ignorePatterns": [ 22 | "dist/", 23 | "build/" 24 | ] 25 | } -------------------------------------------------------------------------------- /.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": ["tailwind", "apply", "variants", "responsive", "screen"] 9 | } 10 | ], 11 | "scss/at-rule-no-unknown": [ 12 | true, 13 | { 14 | "ignoreAtRules": ["tailwind", "apply", "variants", "responsive", "screen"] 15 | } 16 | ], 17 | "csstree/validator": true 18 | }, 19 | "ignoreFiles": ["build/**", "dist/**", "**/reset*.css", "**/bootstrap*.css", "**/*.js", "**/*.jsx"] 20 | } -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "awesome_book", 3 | "version": "1.0.0", 4 | "description": "", 5 | "main": "index.js", 6 | "scripts": { 7 | "test": "echo \"Error: no test specified\" && exit 1" 8 | }, 9 | "keywords": [], 10 | "author": "", 11 | "license": "ISC", 12 | "devDependencies": { 13 | "babel-eslint": "^10.1.0", 14 | "eslint": "^7.32.0", 15 | "eslint-config-airbnb-base": "^14.2.1", 16 | "eslint-plugin-import": "^2.27.5", 17 | "hint": "^7.1.10", 18 | "stylelint": "^13.13.1", 19 | "stylelint-config-standard": "^21.0.0", 20 | "stylelint-csstree-validator": "^1.9.0", 21 | "stylelint-scss": "^3.21.0" 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2023 MIKE 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 | -------------------------------------------------------------------------------- /.github/workflows/blank.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@v3 14 | - uses: actions/setup-node@v3 15 | with: 16 | node-version: "18.x" 17 | - name: Setup Lighthouse 18 | run: npm install -g @lhci/cli@0.11.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@v3 26 | - uses: actions/setup-node@v3 27 | with: 28 | node-version: "18.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@v3 40 | - uses: actions/setup-node@v3 41 | with: 42 | node-version: "18.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@v3 54 | - uses: actions/setup-node@v3 55 | with: 56 | node-version: "18.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@v3 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 | -------------------------------------------------------------------------------- /index.js: -------------------------------------------------------------------------------- 1 | class BookCollection { 2 | constructor() { 3 | this.books = JSON.parse(localStorage.getItem('bookCollection')) || []; 4 | } 5 | 6 | displayBooks() { 7 | const bookListDiv = document.getElementById('bookList'); 8 | bookListDiv.innerHTML = ''; 9 | 10 | this.books.forEach((book, index) => { 11 | const bookDiv = document.createElement('div'); 12 | bookDiv.classList.add('book-details'); 13 | bookDiv.innerHTML = ` 14 |
15 | ${book.title} By: ${book.author} 16 |
17 | `; 18 | 19 | const removeBtn = document.createElement('button'); 20 | removeBtn.classList.add('remove-btn'); 21 | removeBtn.textContent = 'Remove'; 22 | removeBtn.addEventListener('click', () => this.removeBook(index)); 23 | 24 | bookDiv.appendChild(removeBtn); 25 | bookListDiv.appendChild(bookDiv); 26 | }); 27 | } 28 | 29 | addBook(event) { 30 | event.preventDefault(); 31 | 32 | const titleInput = document.getElementById('title'); 33 | const authorInput = document.getElementById('author'); 34 | 35 | const title = titleInput.value; 36 | const author = authorInput.value; 37 | 38 | if (title && author) { 39 | const newBook = { 40 | title, 41 | author, 42 | }; 43 | 44 | this.books.push(newBook); 45 | 46 | localStorage.setItem('bookCollection', JSON.stringify(this.books)); 47 | 48 | titleInput.value = ''; 49 | authorInput.value = ''; 50 | 51 | this.displayBooks(); 52 | } 53 | } 54 | 55 | removeBook(index) { 56 | this.books.splice(index, 1); 57 | 58 | localStorage.setItem('bookCollection', JSON.stringify(this.books)); 59 | 60 | this.displayBooks(); 61 | } 62 | } 63 | 64 | const bookCollection = new BookCollection(); 65 | 66 | const addBookForm = document.getElementById('addBookForm'); 67 | addBookForm.addEventListener('submit', (event) => bookCollection.addBook(event)); 68 | 69 | bookCollection.displayBooks(); 70 | 71 | // Displaying the navitems individually 72 | 73 | const mainLink = document.getElementById('Main-Link'); 74 | const addLink = document.getElementById('Add-Page-Link'); 75 | const contactLink = document.getElementById('Contact_Link'); 76 | 77 | const awesomeBooks = document.querySelector('.books-content-top'); 78 | const contactPage = document.querySelector('.contact-container'); 79 | const formPage = document.querySelector('.form-container'); 80 | 81 | mainLink.addEventListener('click', () => { 82 | mainLink.classList.toggle('clicked'); 83 | contactLink.classList.remove('clicked3'); 84 | addLink.classList.remove('clicked2'); 85 | formPage.classList.add('less'); 86 | formPage.classList.remove('remove'); 87 | 88 | contactPage.classList.remove('add'); 89 | awesomeBooks.classList.add('more'); 90 | }); 91 | 92 | addLink.addEventListener('click', () => { 93 | addLink.classList.toggle('clicked2'); 94 | mainLink.classList.remove('clicked'); 95 | contactLink.classList.remove('clicked3'); 96 | awesomeBooks.classList.remove('more'); 97 | contactPage.classList.remove('add'); 98 | formPage.classList.remove('less', 'remove'); 99 | }); 100 | 101 | contactLink.addEventListener('click', () => { 102 | addLink.classList.remove('clicked2'); 103 | contactLink.classList.toggle('clicked3'); 104 | mainLink.classList.remove('clicked'); 105 | awesomeBooks.classList.remove('more'); 106 | contactPage.classList.add('add'); 107 | formPage.classList.add('remove'); 108 | }); 109 | 110 | const dateTime = document.querySelector('.date-time'); 111 | dateTime.innerHTML = new Date().toString().slice(0, 34); -------------------------------------------------------------------------------- /index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | Awesome Book 7 | 8 | 9 | 10 |
11 |
12 | 22 |
23 | July 12th 2023 10:43AM 24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |

Awesome Books

32 |
33 | 34 |
35 | 36 |
37 |
38 | 39 |
40 |

Add new Book

41 |
42 | 43 | 44 | 45 | 46 |
47 | 48 |
49 | 50 |
51 |
52 | 53 |
54 | 55 |
56 |
57 | 58 | 59 | 60 |
61 |
62 |

Contact Information

63 |
64 |
65 |

66 | Do you have any questions or you just want to say "hello"
67 | You can reach out to us!! 68 |

69 |
    70 |
  • 71 |

    Our email @webstorebooks.com

    72 |
  • 73 |
  • 74 |

    Our phone : 115167999

    75 |
  • 76 |
  • 77 |

    Our adress, street name: Ghosttown 84502 city London

    78 |
  • 79 |
80 |
81 |
82 | 88 | 89 |
90 | 91 | 92 | 93 | 94 | 95 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | 2 | 3 |
4 | 5 |

Awesome Book

6 | 7 |
8 | 9 | 10 | 11 | # 📗 Table of Contents 12 | 13 | - [📗 Table of Contents](#-table-of-contents) 14 | - [📖 \[Awesome Book\] ](#-awesome-book-) 15 | - [🛠 Built With ](#-built-with-) 16 | - [Tech Stack ](#tech-stack-) 17 | - [Key Features ](#key-features-) 18 | - [💻 Getting Started ](#-getting-started-) 19 | - [Prerequisites](#prerequisites) 20 | - [Setup](#setup) 21 | - [Usage](#usage) 22 | - [👥 Authors ](#-authors-) 23 | - [🔭 Future Features ](#-future-features-) 24 | - [🤝 Contributing ](#-contributing-) 25 | - [⭐️ Show your support ](#️-show-your-support-) 26 | - [🙏 Acknowledgments ](#-acknowledgments-) 27 | - [📝 License ](#-license-) 28 | 29 | 30 | 31 | # 📖 [Awesome Book] 32 | 33 | > Describe your project in 1 or 2 sentences. 34 | 35 | **[Awesome Book]** is a webpage for storing and displying books from the localStorage of the browser 36 | 37 | ## 🛠 Built With 38 | 39 | ### Tech Stack 40 | 41 | > Describe the tech stack and include only the relevant sections that apply to your project. 42 | 43 |
44 | HTML 45 | 48 |
49 | 50 |
51 | JavaScript 52 | 55 |
56 | 57 | 58 | 59 | ### Key Features 60 | 61 | > Describe between 1-3 key features of the application. 62 | 63 | - **[local storage]** 64 | - **[dynamic pages]** 65 | - **[navigation]** 66 | 67 |

(back to top)

68 | 69 | - [Awesome Book](https://github.com/Mike47ip/Awesome_Book/) 70 | 71 | 72 | 73 | ## 💻 Getting Started 74 | 75 | To get a local copy up and running, follow these steps. 76 | 77 | ### Prerequisites 78 | 79 | In order to run this project you need: 80 | 81 | ```sh 82 | sudo apt install git-all 83 | or 84 | npm install 85 | ``` 86 | 87 | ### Setup 88 | 89 | Clone this repository to your desired folder: 90 | 91 | ```sh 92 | cd my-folder 93 | git clone https://github.com/Mike47ip/Awesome_Book.git 94 | ``` 95 | 96 | ### Usage 97 | 98 | To run the project, execute the following command: 99 | 100 | ```sh 101 | Open index.html in browser 102 | or 103 | open with Live server in Vscode 104 | ``` 105 | 106 |

(back to top)

107 | 108 | 109 | 110 | ## 👥 Authors 111 | 112 | > Mention all of the collaborators of this project. 113 | 114 | 👤 **Michael Darkwah** 115 | 👤 **Enoch Bett** 116 | 👤 **Uzair Manzoor** 117 | 118 | - GitHub: [@Mike47ip](https://github.com/Mike47ip) 119 | - GitHub: [@bettenoch](https://github.com/Bettenoch) 120 | - GitHub: [@Uzair-Manzoor](https://github.com/Uzair-Manzoor) 121 | 122 | 123 | 124 | ## 🔭 Future Features 125 | 126 | > Describe 1 - 3 features you will add to the project. 127 | 128 | - [ ] **[Add more pages]** 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](https://github.com/Yacoubou-seidou/awesome_book/issues). 139 | 140 | 141 | 142 | ## ⭐️ Show your support 143 | 144 | > Write a message to encourage readers to support your project 145 | 146 | If you like this project show some love by commenting 147 | 148 | 149 | 150 | ## 🙏 Acknowledgments 151 | 152 | > Give credit to everyone who inspired your codebase. 153 | 154 | I would like to thank Microverse staff for their support 155 | 156 | 157 | 158 | ## 📝 License 159 | 160 | This project is [MIT](https://github.com/Mike47ip/Awesome_Book/blob/main/LICENSE) licensed. 161 | 162 |

(back to top)

163 | -------------------------------------------------------------------------------- /style.css: -------------------------------------------------------------------------------- 1 | * { 2 | margin: 0; 3 | padding: 0; 4 | list-style: none; 5 | text-decoration: none; 6 | box-sizing: border-box; 7 | } 8 | 9 | .main-container { 10 | position: relative; 11 | min-height: 100vh; 12 | } 13 | 14 | /* <==========Header Section ===========> */ 15 | 16 | header { 17 | display: flex; 18 | flex-direction: column; 19 | width: 100vw; 20 | padding: 2rem; 21 | gap: 1rem; 22 | position: fixed; 23 | } 24 | 25 | .header-container { 26 | width: 100%; 27 | display: flex; 28 | align-items: center; 29 | justify-content: space-between; 30 | padding: 0.5rem 2rem; 31 | border: 2px solid rgb(67, 64, 64); 32 | border-radius: 5px; 33 | } 34 | 35 | .logo a { 36 | color: rgb(11, 11, 11); 37 | font-size: 1.3rem; 38 | font-weight: 600; 39 | } 40 | 41 | .navLinks li a { 42 | color: rgb(11, 11, 11); 43 | } 44 | 45 | .logo a:hover { 46 | color: blue; 47 | } 48 | 49 | .navLinks { 50 | text-decoration: none; 51 | list-style: none; 52 | display: flex; 53 | gap: 1rem; 54 | } 55 | 56 | .navLinks li { 57 | padding: 0.5rem; 58 | } 59 | 60 | .contact-details li { 61 | list-style: circle; 62 | } 63 | 64 | .navLinks li:nth-child(1), 65 | .navLinks li:nth-child(2) { 66 | border-right: 1px solid rgb(121, 118, 118); 67 | } 68 | 69 | .date-time { 70 | display: flex; 71 | justify-content: flex-end; 72 | } 73 | 74 | /* <==========Header End ===========> */ 75 | 76 | .books-container { 77 | display: flex; 78 | align-items: center; 79 | justify-content: center; 80 | padding-top: 6rem; 81 | } 82 | 83 | .book-collections { 84 | display: flex; 85 | flex-direction: column; 86 | gap: 1.5rem; 87 | align-items: flex-start; 88 | justify-content: center; 89 | width: 100%; 90 | padding: 2rem; 91 | } 92 | 93 | .book-collections h1 { 94 | font-weight: 600; 95 | font-size: 2.2rem; 96 | } 97 | 98 | .book-collections .heading { 99 | text-align: center; 100 | } 101 | 102 | .books-content { 103 | display: flex; 104 | width: 100%; 105 | justify-content: center; 106 | align-items: center; 107 | flex-direction: column; 108 | } 109 | 110 | .books-content-top { 111 | width: 100%; 112 | display: none; 113 | flex-direction: column; 114 | gap: 2rem; 115 | padding-bottom: 4rem; 116 | } 117 | 118 | #bookList { 119 | border: 2px solid black; 120 | border-radius: 5px; 121 | display: flex; 122 | flex-direction: column; 123 | width: 100%; 124 | height: auto; 125 | } 126 | 127 | .book-details { 128 | display: flex; 129 | justify-content: space-between; 130 | gap: 1rem; 131 | padding: 0.5rem 1rem; 132 | } 133 | 134 | .form-container { 135 | display: flex; 136 | flex-direction: column; 137 | justify-content: center; 138 | align-items: center; 139 | padding-top: 3rem; 140 | } 141 | 142 | form { 143 | display: flex; 144 | flex-direction: column; 145 | gap: 0.5rem; 146 | } 147 | 148 | #addBookForm { 149 | width: 360px; 150 | } 151 | 152 | #title { 153 | height: 35px; 154 | } 155 | 156 | #author { 157 | height: 35px; 158 | } 159 | 160 | .btn-holder { 161 | display: flex; 162 | align-items: flex-end; 163 | justify-content: flex-end; 164 | } 165 | 166 | .remove-btn { 167 | width: 70px; 168 | padding: 5px; 169 | box-shadow: 0 5px 10px 0 rgba(0, 0, 0, 0.5); 170 | } 171 | 172 | .form-btn { 173 | width: 70px; 174 | padding: 5px; 175 | box-shadow: 10px 10px 8px #888; 176 | } 177 | 178 | #bookList .book-details:nth-child(odd) { 179 | background: rgb(170, 165, 165); 180 | } 181 | 182 | /* <==========Contact Section ===========> */ 183 | .contact-container { 184 | display: none; 185 | flex-direction: column; 186 | gap: 3rem; 187 | align-items: center; 188 | } 189 | 190 | .contact-info { 191 | display: flex; 192 | flex-direction: column; 193 | gap: 1rem; 194 | } 195 | 196 | .contact-details { 197 | padding-left: 3rem; 198 | } 199 | 200 | /* <==========Footer Section ===========> */ 201 | .footer-container { 202 | display: flex; 203 | flex-direction: column; 204 | width: 100vw; 205 | padding: 2rem; 206 | position: absolute; 207 | bottom: 0; 208 | } 209 | 210 | footer { 211 | width: 100%; 212 | display: flex; 213 | align-items: center; 214 | justify-content: space-between; 215 | padding: 0.5rem 2rem; 216 | border: 2px solid rgb(67, 64, 64); 217 | border-radius: 5px; 218 | } 219 | 220 | .clicked { 221 | color: blue !important; 222 | } 223 | 224 | .clicked2 { 225 | color: blue !important; 226 | } 227 | 228 | .clicked3 { 229 | color: blue !important; 230 | } 231 | 232 | .more { 233 | display: flex; 234 | } 235 | 236 | .less { 237 | display: none; 238 | } 239 | 240 | .remove { 241 | display: none; 242 | } 243 | 244 | .add { 245 | display: flex; 246 | } 247 | --------------------------------------------------------------------------------