├── .gitignore ├── modules ├── currentDate.js └── booksclass.js ├── .stylelintrc.js ├── .hintrc ├── .eslintrc.json ├── .stylelintrc.json ├── package.json ├── LICENSE ├── index.js ├── index.html ├── .github └── workflows │ └── linters.yml ├── index.css └── README.md /.gitignore: -------------------------------------------------------------------------------- 1 | # .gitignore 2 | node_modules/ -------------------------------------------------------------------------------- /modules/currentDate.js: -------------------------------------------------------------------------------- 1 | import { DateTime } from './luxon.js'; 2 | 3 | const currentDate = () => { 4 | const date = DateTime.now().toLocaleString(DateTime.DATETIME_MED); 5 | document.getElementById('datetime').innerHTML = date; 6 | }; 7 | 8 | export default currentDate; -------------------------------------------------------------------------------- /.stylelintrc.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | "extends": "stylelint-config-standard", 3 | "plugins": ["stylelint-scss"], 4 | "rules": { 5 | "at-rule-no-unknown": null, 6 | "scss/at-rule-no-unknown": true, 7 | "no-descending-specificity": null 8 | }, 9 | } -------------------------------------------------------------------------------- /.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 | } 26 | -------------------------------------------------------------------------------- /.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 | "version": "1.0.0", 3 | "description": "Week 2 Day 1 ES6 activity", 4 | "main": "index.js", 5 | "scripts": { 6 | "test": "echo \"Error: no test specified\" && exit 1" 7 | }, 8 | "repository": { 9 | "type": "git", 10 | "url": "git+https://github.com/Maedea9/awesome-books-ES6.git" 11 | }, 12 | "keywords": [], 13 | "author": "", 14 | "license": "ISC", 15 | "bugs": { 16 | "url": "https://github.com/Maedea9/awesome-books-ES6/issues" 17 | }, 18 | "homepage": "https://github.com/Maedea9/awesome-books-ES6#readme", 19 | "devDependencies": { 20 | "babel-eslint": "^10.1.0", 21 | "eslint": "^7.32.0", 22 | "eslint-config-airbnb-base": "^14.2.1", 23 | "eslint-plugin-import": "^2.27.5", 24 | "hint": "^7.1.8", 25 | "stylelint": "^13.13.1", 26 | "stylelint-config-standard": "^21.0.0", 27 | "stylelint-csstree-validator": "^1.9.0", 28 | "stylelint-scss": "^3.21.0" 29 | }, 30 | "dependencies": { 31 | "luxon": "^3.3.0" 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2023 Maedea9 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 | -------------------------------------------------------------------------------- /index.js: -------------------------------------------------------------------------------- 1 | import Books from './modules/booksclass.js'; 2 | import currentDate from './modules/currentDate.js'; 3 | 4 | // navbar functionality 5 | const navlist = document.querySelector('.navList'); 6 | const navadd = document.querySelector('.navAdd'); 7 | const navcont = document.querySelector('.navCont'); 8 | const listPage = document.querySelector('.list'); 9 | const newBookPage = document.querySelector('.form-container'); 10 | const contactPage = document.querySelector('.contact-info'); 11 | 12 | navlist.addEventListener('click', () => { 13 | listPage.classList.remove('hide'); 14 | newBookPage.classList.add('hide'); 15 | contactPage.classList.add('hide'); 16 | }); 17 | 18 | navadd.addEventListener('click', () => { 19 | listPage.classList.add('hide'); 20 | newBookPage.classList.remove('hide'); 21 | contactPage.classList.add('hide'); 22 | }); 23 | 24 | navcont.addEventListener('click', () => { 25 | listPage.classList.add('hide'); 26 | newBookPage.classList.add('hide'); 27 | contactPage.classList.remove('hide'); 28 | }); 29 | // Creating a instance of Books 30 | const awesomeBooks = new Books(); 31 | 32 | // Checking Local Storage 33 | if (localStorage.getItem('createdBooks')) { 34 | awesomeBooks.books = JSON.parse(localStorage.getItem('createdBooks')); 35 | awesomeBooks.displayBooks(); 36 | } 37 | document.addEventListener('DOMContentLoaded', currentDate()); -------------------------------------------------------------------------------- /modules/booksclass.js: -------------------------------------------------------------------------------- 1 | // Create a book Class 2 | class Books { 3 | constructor() { 4 | this.books = []; 5 | // Call the HTML elements 6 | this.title = document.getElementById('title'); 7 | this.author = document.getElementById('author'); 8 | this.addButton = document.getElementById('submit'); 9 | this.bookList = document.getElementById('bookList'); 10 | 11 | this.displayBooks(); 12 | 13 | /* add an event listener to call the addbutton function and display the list of books */ 14 | this.addButton.addEventListener('click', (e) => { 15 | e.preventDefault(); 16 | this.addBooks(); 17 | this.displayBooks(); 18 | }); 19 | 20 | /* add an event listener to call the removebutton function and remove the list of books */ 21 | this.bookList.addEventListener('click', (event) => { 22 | if (event.target.classList.contains('removeBtn')) { 23 | const { bookIndex } = event.target.dataset; 24 | this.removeBook(bookIndex); 25 | } 26 | }); 27 | } 28 | 29 | /* Create Methods for the Book Class */ 30 | // display books. Create li and remove button elements 31 | displayBooks() { 32 | this.bookList.innerHTML = ''; 33 | this.books.forEach((book, index) => { 34 | const li = document.createElement('li'); 35 | li.classList.add('book-infocss'); 36 | li.innerHTML = `

"${book.title}" by ${book.author}

`; 37 | const removeBtn = document.createElement('button'); 38 | removeBtn.textContent = 'Remove'; 39 | removeBtn.classList.add('removeBtn'); 40 | removeBtn.setAttribute('book-index', index); 41 | li.appendChild(removeBtn); 42 | this.bookList.appendChild(li); 43 | }); 44 | } 45 | 46 | // add book 47 | addBooks() { 48 | if (this.title.value !== '' && this.author.value !== '') { 49 | const title = this.title.value; 50 | const author = this.author.value; 51 | 52 | this.books.push({ title, author }); 53 | // save book to localstorage separatedly 54 | localStorage.setItem('createdBooks', JSON.stringify(this.books)); 55 | this.title.value = ' '; 56 | this.author.value = ' '; 57 | } 58 | } 59 | 60 | // remove book method 61 | removeBook(bookIndex) { 62 | this.books.splice(bookIndex, 1); 63 | localStorage.setItem('createdBooks', JSON.stringify(this.books)); 64 | this.displayBooks(); 65 | } 66 | } 67 | 68 | export default Books; -------------------------------------------------------------------------------- /index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | AwesomeBooks 12 | 13 | 14 | 28 |

29 | 30 | 31 |
32 |
33 |

Awesome Books

34 |
35 |

All Awesome Books

36 | 37 |
    38 |
    39 |
    40 |
    41 | 42 |
    43 |

    Add a Book

    44 |
    45 | 46 | 47 | 48 |
    49 |
    50 | 51 |
    52 |

    Contact Information

    53 |

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

    54 |

    You can reach out us!

    55 | 60 |
    61 | 62 | 63 | 67 | 68 | 69 | 70 | -------------------------------------------------------------------------------- /.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-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: "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@v2 40 | - uses: actions/setup-node@v1 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@v2 54 | - uses: actions/setup-node@v1 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@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 -------------------------------------------------------------------------------- /index.css: -------------------------------------------------------------------------------- 1 | * { 2 | font-family: 'Comic Neue', cursive; 3 | margin: 2% 2%; 4 | } 5 | 6 | html { 7 | margin: 0; 8 | } 9 | 10 | body { 11 | margin: 0; 12 | height: 100%; 13 | } 14 | 15 | header { 16 | margin: 0; 17 | } 18 | 19 | .navBar { 20 | display: flex; 21 | border: #000 3px solid; 22 | align-items: center; 23 | margin: 0.5% 1%; 24 | width: 98%; 25 | justify-content: space-between; 26 | justify-self: center; 27 | } 28 | 29 | .nbTitle { 30 | padding-left: 4%; 31 | } 32 | 33 | nav { 34 | display: flex; 35 | width: 50%; 36 | margin: 0; 37 | padding-right: 1%; 38 | } 39 | 40 | .list { 41 | width: 90%; 42 | align-self: center; 43 | justify-content: center; 44 | } 45 | 46 | .bookList-add-contact { 47 | display: flex; 48 | width: 90%; 49 | list-style: none; 50 | padding: 0; 51 | justify-content: end; 52 | gap: 3px; 53 | } 54 | 55 | .bookList-add-contact li { 56 | cursor: pointer; 57 | } 58 | 59 | .navAdd { 60 | display: flex; 61 | } 62 | 63 | span { 64 | margin: 0; 65 | background-color: #000; 66 | height: 90%; 67 | width: 1px; 68 | align-self: center; 69 | } 70 | 71 | #datetime { 72 | display: flex; 73 | flex-direction: row; 74 | align-items: center; 75 | justify-content: end; 76 | } 77 | 78 | main { 79 | display: flex; 80 | flex-direction: column; 81 | align-content: center; 82 | justify-content: center; 83 | margin: 0; 84 | width: 100%; 85 | } 86 | 87 | h1 { 88 | display: flex; 89 | justify-content: center; 90 | margin: 0 2%; 91 | } 92 | 93 | .book-list-conatiner { 94 | display: flex; 95 | flex-direction: column; 96 | align-content: center; 97 | } 98 | 99 | .subtitle { 100 | display: flex; 101 | justify-content: center; 102 | } 103 | 104 | #bookList { 105 | display: flex; 106 | flex-direction: column; 107 | border: #000 3px solid; 108 | list-style: none; 109 | padding: 0; 110 | } 111 | 112 | .book-infocss { 113 | display: flex; 114 | width: 100%; 115 | justify-content: space-between; 116 | background-color: lightgray; 117 | margin: 0; 118 | align-self: center; 119 | } 120 | 121 | li p { 122 | font-size: 14px; 123 | } 124 | 125 | li:nth-child(even) { 126 | background-color: #fff; 127 | } 128 | 129 | button { 130 | border: #000 2.5px solid; 131 | background-color: #fff; 132 | box-shadow: 1.5px 2px #000; 133 | } 134 | 135 | .form-container { 136 | display: flex; 137 | flex-direction: column; 138 | align-content: center; 139 | } 140 | 141 | form { 142 | display: flex; 143 | flex-direction: column; 144 | align-self: center; 145 | width: 50%; 146 | padding: 0 3%; 147 | } 148 | 149 | input { 150 | border: #000 2.5px solid; 151 | } 152 | 153 | #submit { 154 | border: #000 2.5px solid; 155 | background-color: #fff; 156 | font-family: 'Comic Neue', cursive; 157 | width: 25%; 158 | align-self: flex-end; 159 | padding: 0 3%; 160 | } 161 | 162 | .contact-info { 163 | display: flex; 164 | flex-direction: column; 165 | margin: 2% 10%; 166 | } 167 | 168 | .contact-info h2 { 169 | display: flex; 170 | align-items: center; 171 | justify-content: center; 172 | } 173 | 174 | .contact-ul { 175 | display: flex; 176 | flex-direction: column; 177 | } 178 | 179 | .contact-ul li { 180 | font-weight: bold; 181 | } 182 | 183 | footer { 184 | display: flex; 185 | flex-direction: row; 186 | align-items: center; 187 | margin: 1% 3%; 188 | border: #000 3px solid; 189 | gap: 20px; 190 | } 191 | 192 | footer h6 { 193 | font-size: 12px; 194 | } 195 | 196 | .hide { 197 | display: none; 198 | } 199 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # awesome-books-ES6 2 | Week 2 Day 1 ES6 activity 3 | 4 | 5 |
    6 | 7 |

    Awesome Books ES6

    8 | 9 |
    10 | 11 | # 📗 Table of Contents 12 | 13 | - [📖 About the Project](#about-project) 14 | - [🛠 Built With](#built-with) 15 | - [Tech Stack](#tech-stack) 16 | - [Key Features](#key-features) 17 | - [🚀 Live Demo](#live-demo) 18 | - [💻 Getting Started](#getting-started) 19 | - [Prerequisites](#prerequisites) 20 | - [Setup](#setup) 21 | - [Usage](#usage) 22 | - [Run tests](#run-tests) 23 | - [Deployment](#deployment) 24 | - [👥 Authors](#authors) 25 | - [🔭 Future Features](#future-features) 26 | - [🤝 Contributing](#contributing) 27 | - [⭐️ Show your support](#support) 28 | - [🙏 Acknowledgements](#acknowledgements) 29 | - [📝 License](#license) 30 | 31 | # 📖 Awesome Books ES6 32 | 33 | **[Awesome Books with ES6]** is a project for the full time program in Microverse in which HTML, CSS and JavaScript technologies are applied. 34 | 35 | ## 🛠 Built With 36 | 37 | ### Tech Stack 38 | + HTML 39 | + CSS 40 | + JavaScript 41 | 42 | > Used HTML, CSS, JavaScript to work on this project and Linters configuration provided by Microverse. 43 | 44 |
    45 | Capstone project 46 | 49 |
    50 | 51 | ### Key Features 52 | 53 | > An exercise to create an SPA website using ES6 syntax. 54 | 55 | - **[Use of Linters]** 56 | - **[Responsive design]** 57 | - **[Single Page Application approach]** 58 | - **[Navigation bar]** 59 | - **[Main Section]** 60 | - **[Contact Section]** 61 | - **[Deploy using Github Pages]** 62 | - **[Functionality implemented with JavaScript]** 63 | - **[Import/export modules with JavaScript]** 64 | - **[User can add a book]** 65 | - **[User can see collection of boks]** 66 | - **[User can remove a book]** 67 | 68 |

    (back to top)

    69 | 70 | ## 🚀 Live Demo 71 | 72 | - [Live Demo Link](https://enchanting-centaur-6b4d71.netlify.app) 73 | 74 |

    (back to top)

    75 | 76 | ## 💻Getting Started 77 | To get a local copy up and running, follow these steps. 78 | ### Prerequisites 79 | In order to run this project you need: 80 | + Basic HTML, CSS and JavaScript knowledge 81 | + A computer with an internet connection 82 | + A web browser 83 | 84 | ### Setup 85 | Clone this repository to your computer 86 | 87 | ### Usage 88 | To run the project, execute the "index.html" file in your browser 89 |

    (back to top)

    90 | 91 | ### Run tests 92 | 93 | To run tests, run the following command: 94 | 95 | ```sh 96 | To check the HTML functionality use: 'npx hint .' 97 | ``` 98 | 99 | ```sh 100 | To check the CSS functionality use: 'npx stylelint "**/*.{css,scss}"' 101 | ``` 102 | 103 | ```sh 104 | To check the JavaScript functionality use: 'npx eslint."' 105 | ``` 106 | 107 | ### Deployment 108 | 109 | You can deploy this project using: 110 | 111 | ```sh 112 | GitHub pages. 113 | ``` 114 | 115 |

    (back to top)

    116 | 117 | ## 👥 Authors 118 | 119 | 👤 **Maedea9** 120 | 121 | - GitHub: [@maedea9](https://github.com/Maedea9) 122 | - Twitter: [@MelanieCascant6](https://twitter.com/MelanieCascant6) 123 | - LinkedIn: [LinkedIn](https://www.linkedin.com/in/melanie-cascante-938a93228/) 124 | 125 | ## 🔭 Future Features 126 | 127 | - **-Making the page more responsive** : Adding more than 1 breaking point. 128 | 129 |

    (back to top)

    130 | 131 | ## 🤝 Contributing 132 | Contributions, issues, and feature requests are welcome! 133 | 134 |

    (back to top)

    135 | 136 | ## ⭐️ Show your support 137 | If you like this project you can follow my work through my social networks. 138 | 139 |

    (back to top)

    140 | 141 | ## 🙏 Acknowledgments 142 | 143 | I would like to thank Microverse, my Coding partners, Standup Team and Morning Sessions Team for supporting me. 144 | 145 | 146 |

    (back to top)

    147 | 148 | ## 📝 License 149 | 150 | This project is [MIT](./LICENSE) licensed. 151 | 152 |

    (back to top)

    153 | --------------------------------------------------------------------------------