├── .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 |
15 |
16 | Awesome Books
17 |
18 |
25 |
26 |
27 |
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 |
49 |
50 |
51 |
61 |
62 |
63 |
64 | Copyright
65 | ...
66 |
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 |
--------------------------------------------------------------------------------