├── .gitignore ├── .vscode └── settings.json ├── .hintrc ├── .eslintrc.json ├── .stylelintrc.json ├── package.json ├── README.md ├── index.html ├── .github └── workflows │ └── linters.yml ├── style.css └── script.js /.gitignore: -------------------------------------------------------------------------------- 1 | node_modules -------------------------------------------------------------------------------- /.vscode/settings.json: -------------------------------------------------------------------------------- 1 | { 2 | "liveServer.settings.port": 5501 3 | } -------------------------------------------------------------------------------- /.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": "awsome-books", 3 | "version": "1.0.0", 4 | "description": "", 5 | "main": "index.js", 6 | "scripts": { 7 | "test": "echo \"Error: no test specified\" && exit 1" 8 | }, 9 | "repository": { 10 | "type": "git", 11 | "url": "git+https://github.com/nedjwab/Awsome-Books.git" 12 | }, 13 | "keywords": [], 14 | "author": "", 15 | "license": "ISC", 16 | "bugs": { 17 | "url": "https://github.com/nedjwab/Awsome-Books/issues" 18 | }, 19 | "homepage": "https://github.com/nedjwab/Awsome-Books#readme", 20 | "devDependencies": { 21 | "babel-eslint": "^10.1.0", 22 | "eslint": "^7.32.0", 23 | "eslint-config-airbnb-base": "^14.2.1", 24 | "eslint-plugin-import": "^2.26.0", 25 | "hint": "^6.1.11", 26 | "stylelint": "^13.13.1", 27 | "stylelint-config-standard": "^21.0.0", 28 | "stylelint-csstree-validator": "^1.9.0", 29 | "stylelint-scss": "^3.21.0" 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | 2 | 3 | # Awsome Books 4 | 5 | In this Project, we have built A Books websites. 6 | 7 | 8 | 9 | ## Built With 🔨 10 | 11 | - HTML 12 | - CSS 13 | - javascript 14 | - Git & Github 15 | 16 | ## Live Demo 17 | [Here](https://nedjwab.github.io/Awsome-Books/) you can find the live Demo of the website 18 | 19 | ### Install 20 | Download the zip file. 21 | extract the folder. 22 | go to the index.html file. 23 | 24 | 25 | ### Prerequisites 26 | 27 | - IDE ( VCode For me 🔥). 28 | - Git. 29 | - Npm and node.js installed. 30 | 31 | 32 | ### Usage 33 | 34 | - For anyone who wants to practice html5 or/and css3 35 | - For anyone who wants to create a CRUD website. 36 | 37 | ## Authors 38 | 39 | 👤 **Nedjwa Bouraiou** 40 | 👤 **Shaquille Ndunda** 41 | 👤 **Sonia Karungi** 42 | 43 | 44 | 45 | 46 | - GitHub: [@Nedjwab](https://github.com/nedjwab) 47 | - LinkedIn: [@Bouraiounedjwa](https://www.linkedin.com/feed/) 48 | 49 | - GitHub:[@shaqdeff](https://github.com/shaqdeff) 50 | - LinkedIn:[Shaquille Ndunda](https://www.linkedin.com/in/shaquille-ndunda-b13a95107/) 51 | 52 | - GitHub: [@SoniaKarungi](https://github.com/SoniaKarungi) 53 | - LinkedIn:[Sonia Karungi](https://www.linkedin.com/in/soniarmkarungi/) 54 | 55 | 56 | ## 🤝 Contributing 57 | 58 | Contributions, issues, and feature requests are welcome! 59 | 60 | ## Show your support 61 | 62 | Give a ⭐️ if you like this project! 63 | 64 | 65 | 66 | -------------------------------------------------------------------------------- /index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | Awesome Books 10 | 11 | 12 |
13 |

Awesome Books

14 | 21 |
22 |

23 |
24 |

All Awesome Books

25 |
26 |
27 |
28 | 29 |
30 | 31 |
32 |

Add a new book

33 |
34 |
35 |
36 |
37 | 38 |
39 |
40 |
41 |
42 |

Contact Information

43 |
44 |

Do you have any questions or do you just want to say "Hello"?

45 |

You can reach out to us!

46 |
    47 |
  • Our e-mail: awesomebooks@awesomebooks.com
  • 48 |
  • Our phone number: 09876542657
  • 49 |
  • Our address: Awesome Street, 22 North, Awesome City, Earth
  • 50 |
51 |
52 |
53 |
54 | 57 | 58 | 59 | 60 | 61 | -------------------------------------------------------------------------------- /.github/workflows/linters.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-18.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-18.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@6.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-18.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-18.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 . -------------------------------------------------------------------------------- /style.css: -------------------------------------------------------------------------------- 1 | 2 | @import url('https://fonts.googleapis.com/css2?family=Anek+Telugu&display=swap'); 3 | 4 | body { 5 | margin: 0; 6 | font-family: 'Anek Telugu', sans-serif; 7 | } 8 | 9 | header { 10 | display: flex; 11 | justify-content: space-between; 12 | align-items: center; 13 | border: 2px solid black; 14 | width: 90%; 15 | margin: 15px auto 0 auto; 16 | } 17 | 18 | nav ul { 19 | display: flex; 20 | list-style: none; 21 | gap: 20px; 22 | padding-right: 10px; 23 | } 24 | 25 | nav ul li { 26 | border-right: 1px solid black; 27 | padding-right: 15px; 28 | cursor: pointer; 29 | } 30 | 31 | nav ul li:hover { 32 | color: purple; 33 | } 34 | 35 | #nav-contact { 36 | border: none; 37 | } 38 | 39 | .heading-title { 40 | font-size: 24px; 41 | padding-left: 15px; 42 | } 43 | 44 | #date { 45 | position: absolute; 46 | text-align: right; 47 | right: 5%; 48 | } 49 | 50 | .heading h1 { 51 | margin-top: 70px; 52 | text-align: center; 53 | font-size: 30px; 54 | font-family: 'Anek Telugu', sans-serif; 55 | } 56 | 57 | hr { 58 | width: 30%; 59 | margin-inline: auto; 60 | border: none; 61 | height: 3px; 62 | background: black; 63 | } 64 | 65 | .tinyhr { 66 | width: 20%; 67 | margin-inline: auto; 68 | border: none; 69 | height: 2px; 70 | background: black; 71 | } 72 | 73 | h2 { 74 | text-align: center; 75 | font-size: 30px; 76 | font-family: 'Anek Telugu', sans-serif; 77 | } 78 | 79 | .bookscontainer { 80 | width: 89%; 81 | display: flex; 82 | flex-direction: column; 83 | justify-content: space-evenly; 84 | border: solid 4px black; 85 | margin-left: auto; 86 | margin-right: auto; 87 | padding: 0; 88 | } 89 | 90 | .book-details { 91 | list-style: none; 92 | } 93 | 94 | .book { 95 | width: 99%; 96 | display: flex; 97 | flex-direction: row; 98 | font-size: 28px; 99 | font-family: 'Anek Telugu', sans-serif; 100 | font-weight: 600; 101 | padding: 5px; 102 | overflow-x: hidden; 103 | overflow-y: hidden; 104 | } 105 | 106 | .book:nth-child(odd) { 107 | background-color: #dfdfde; 108 | } 109 | 110 | .remove-btn { 111 | background-color: white; 112 | border: solid 2px black; 113 | font-size: 17px; 114 | font-weight: 600; 115 | font-family: 'Anek Telugu', sans-serif; 116 | box-shadow: 3px 3px; 117 | margin-left: auto; 118 | text-align: center; 119 | } 120 | 121 | .remove-btn:hover { 122 | cursor: pointer; 123 | } 124 | 125 | .form { 126 | display: flex; 127 | flex-direction: column; 128 | align-items: center; 129 | padding: 20px; 130 | } 131 | 132 | input { 133 | width: 30%; 134 | border: solid 2px black; 135 | padding: 17px; 136 | font-size: 19px; 137 | } 138 | 139 | #add-button { 140 | background-color: white; 141 | border: solid 2px black; 142 | font-size: 17px; 143 | font-weight: 600; 144 | font-family: 'Anek Telugu', sans-serif; 145 | box-shadow: 3px 3px; 146 | padding: 10px; 147 | } 148 | 149 | #add-button:hover { 150 | cursor: pointer; 151 | } 152 | 153 | .contact-info { 154 | display: flex; 155 | justify-content: center; 156 | flex-direction: column; 157 | align-items: center; 158 | font-size: 19px; 159 | } 160 | 161 | footer { 162 | border: solid 2px black; 163 | width: 88%; 164 | margin: 15px auto 0 auto; 165 | padding: 9px; 166 | font-weight: 600; 167 | } 168 | -------------------------------------------------------------------------------- /script.js: -------------------------------------------------------------------------------- 1 | // Select the Elements 2 | const container = document.querySelector('.bookscontainer'); 3 | const addBtn = document.querySelector('form'); 4 | const titleI = document.querySelector('.title'); 5 | const authorI = document.querySelector('.author'); 6 | 7 | // Class of Books 8 | class Books { 9 | static books = []; 10 | 11 | id = `${Date.now()}`.slice(-10); 12 | 13 | constructor(id, title, author) { 14 | this.id = id; 15 | this.title = title; 16 | this.author = author; 17 | } 18 | 19 | // Data Storage 20 | static storage(books) { 21 | localStorage.setItem('books', JSON.stringify(books)); 22 | } 23 | 24 | addBook() { 25 | Books.books.push(this); 26 | Books.storage(Books.books); 27 | Books.displayBook(); 28 | titleI.value = ''; 29 | authorI.value = ''; 30 | } 31 | 32 | // Display Book 33 | static displayBook() { 34 | if (JSON.parse(localStorage.getItem('books'))) { 35 | Books.books = JSON.parse(localStorage.getItem('books')); 36 | } 37 | 38 | let list = ''; 39 | Books.books.forEach((book) => { 40 | list += ` 41 |
  • 42 |
    "${book.title}" by ${book.author}
    43 | 44 |
  • 45 | `; 46 | }); 47 | 48 | const addNewSection = document.getElementById('add-new'); 49 | const contactSection = document.getElementById('contact'); 50 | const dateSection = document.getElementById('date'); 51 | addNewSection.style.display = 'none'; 52 | contactSection.style.display = 'none'; 53 | dateSection.innerText = new Date().toLocaleString('en-US', { 54 | day: 'numeric', 55 | year: 'numeric', 56 | month: 'long', 57 | hour: 'numeric', 58 | minute: 'numeric', 59 | second: 'numeric', 60 | }); 61 | 62 | container.innerHTML = list; 63 | 64 | // Remove Book eventlistner 65 | document.querySelectorAll('.remove-btn').forEach((btn) => { 66 | btn.addEventListener('click', (e) => { 67 | const targetId = e.target.parentElement.id; 68 | Books.books = Books.books.filter((book) => book.id !== targetId); 69 | Books.storage(Books.books); 70 | e.target.parentElement.remove(); 71 | }); 72 | }); 73 | } 74 | } 75 | 76 | let id; 77 | // Add Book eventlistner 78 | addBtn.addEventListener('submit', (e) => { 79 | e.preventDefault(); 80 | id = `${Date.now()}`.slice(-10); 81 | const title = titleI.value; 82 | const author = authorI.value; 83 | const newBook = new Books(id, title, author); 84 | newBook.addBook(); 85 | // eslint-disable-next-line no-restricted-globals 86 | location.reload(); 87 | }); 88 | 89 | const addNewSection = document.getElementById('add-new'); 90 | const contactSection = document.getElementById('contact'); 91 | const ListSection = document.getElementById('list'); 92 | 93 | document.querySelector('#nav-add-new').addEventListener('click', () => { 94 | addNewSection.style.display = 'block'; 95 | contactSection.style.display = 'none'; 96 | ListSection.style.display = 'none'; 97 | }); 98 | 99 | document.querySelector('#nav-list').addEventListener('click', () => { 100 | addNewSection.style.display = 'none'; 101 | contactSection.style.display = 'none'; 102 | ListSection.style.display = 'block'; 103 | }); 104 | 105 | document.querySelector('#nav-contact').addEventListener('click', () => { 106 | addNewSection.style.display = 'none'; 107 | contactSection.style.display = 'block'; 108 | ListSection.style.display = 'none'; 109 | }); 110 | 111 | // Reload function 112 | window.onload = () => { 113 | Books.displayBook(); 114 | }; 115 | --------------------------------------------------------------------------------