├── .gitignore
├── modules
├── currentDate.js
├── dateTime.js
└── books.js
├── .stylelintrc.json
├── .hintrc
├── .eslintrc.json
├── package.json
├── index.js
├── README.md
├── .github
└── workflows
│ └── linters.yml
├── index.html
└── index.css
/.gitignore:
--------------------------------------------------------------------------------
1 | node_modules/
--------------------------------------------------------------------------------
/modules/currentDate.js:
--------------------------------------------------------------------------------
1 | import { DateTime } from './luxon.js';
2 |
3 | const currentDate = DateTime.now().toLocaleString(DateTime.DATETIME_MED);
4 |
5 | export default currentDate;
--------------------------------------------------------------------------------
/.stylelintrc.json:
--------------------------------------------------------------------------------
1 | {
2 | "extends": ["stylelint-config-standard"],
3 | "plugins": ["stylelint-scss", "stylelint-csstree-validator"],
4 | "rules": {
5 | "at-rule-no-unknown": null,
6 | "scss/at-rule-no-unknown": true,
7 | "csstree/validator": true
8 | },
9 | "ignoreFiles": ["build/**", "dist/**", "**/reset*.css", "**/bootstrap*.css"]
10 | }
11 |
--------------------------------------------------------------------------------
/.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 |
--------------------------------------------------------------------------------
/.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 | "no-use-before-define": "off",
17 | "eol-last": "off",
18 | "import/extensions": [ 1, {
19 | "js": "always", "json": "always"
20 | }]
21 | },
22 | "ignorePatterns": [
23 | "dist/",
24 | "build/"
25 | ]
26 | }
--------------------------------------------------------------------------------
/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "awesome-books-with-es6",
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/divinecharlotte/Awesome-books-with-ES6.git"
12 | },
13 | "keywords": [],
14 | "author": "",
15 | "license": "ISC",
16 | "bugs": {
17 | "url": "https://github.com/divinecharlotte/Awesome-books-with-ES6/issues"
18 | },
19 | "homepage": "https://github.com/divinecharlotte/Awesome-books-with-ES6#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 | "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 | }
31 |
--------------------------------------------------------------------------------
/modules/dateTime.js:
--------------------------------------------------------------------------------
1 | const handleTime = () => {
2 | const dateContainer = document.querySelector('.date-container');
3 | const dateFunc = new Date();
4 | const months = ['January', 'February', 'March', 'April', 'May', 'June', 'July', 'August', 'September', 'October', 'November', 'December'];
5 | const year = dateFunc.getFullYear();
6 | const month = months[dateFunc.getMonth()];
7 | let currentDate = dateFunc.getDate();
8 | const hour = dateFunc.getHours();
9 | const minutes = dateFunc.getMinutes();
10 | const second = dateFunc.getSeconds();
11 | if (currentDate === 1) currentDate = 'first';
12 | else if (currentDate === 2) currentDate = 'second';
13 | else if (currentDate === 3) currentDate = 'third';
14 | else currentDate += 'th';
15 |
16 | const time = (hour < 12) ? `${month} ${currentDate} ${year}, ${hour} ${minutes} ${second} AM`
17 | : `${month} ${currentDate} ${year}, ${hour}: ${minutes}: ${second} PM`;
18 | dateContainer.innerHTML = time;
19 | };
20 | export default handleTime;
21 |
--------------------------------------------------------------------------------
/modules/books.js:
--------------------------------------------------------------------------------
1 | class Book {
2 | constructor() {
3 | this.books = JSON.parse(localStorage.getItem('Bookstore')) || [];
4 | }
5 |
6 | addBook(title, author) {
7 | this.books.push({ title, author });
8 | this.storeBookData();
9 | this.addBookToList();
10 | }
11 |
12 | addBookToList() {
13 | const table = document.querySelector('#book-list');
14 | let listOfBooks = '';
15 | this.books.forEach((book, index) => {
16 | listOfBooks += `
17 |
18 | | "${book.title}" by ${book.author} |
19 | |
20 |
`;
21 | });
22 | table.innerHTML = listOfBooks;
23 | if (this.books.length > 0) {
24 | const deleteButtons = document.querySelectorAll('.delete');
25 | deleteButtons.forEach((btn) => { btn.addEventListener('click', this.deleteBook.bind(this)); });
26 | }
27 | }
28 |
29 | deleteBook(click) {
30 | const bookId = click.target.id;
31 | this.books.splice(bookId, 1);
32 | this.storeBookData();
33 | this.addBookToList();
34 | }
35 |
36 | storeBookData() {
37 | const bookdata = JSON.stringify(this.books);
38 | localStorage.setItem('Bookstore', bookdata);
39 | }
40 | }
41 |
42 | export default Book;
--------------------------------------------------------------------------------
/index.js:
--------------------------------------------------------------------------------
1 | import Book from './modules/books.js';
2 | import handleTime from './modules/dateTime.js';
3 |
4 | window.addEventListener('load', () => {
5 | handleTime();
6 | });
7 |
8 | const Bookstore = new Book();
9 |
10 | window.onload = () => { Bookstore.addBookToList(); };
11 |
12 | document.querySelector('#book-form').addEventListener('submit', (e) => {
13 | e.preventDefault();
14 | const title = document.querySelector('#title');
15 | const author = document.querySelector('#tuthor');
16 | Bookstore.addBook(title.value, author.value);
17 | title.value = '';
18 | author.value = '';
19 | });
20 |
21 | const list = document.querySelector('#n1');
22 | const addBook = document.querySelector('#n2');
23 | const contactUs = document.querySelector('#n3');
24 |
25 | list.addEventListener('click', () => {
26 | document.getElementById('show-book').style.cssText = 'display: flex;';
27 | document.getElementById('book-form').style.cssText = 'display: none;';
28 | document.getElementById('show-contact').style.cssText = 'display: none;';
29 | });
30 |
31 | addBook.addEventListener('click', () => {
32 | document.getElementById('show-book').style.cssText = 'display: none;';
33 | document.getElementById('book-form').style.cssText = 'display: flex;';
34 | document.getElementById('show-contact').style.cssText = 'display: none;';
35 | });
36 |
37 | contactUs.addEventListener('click', () => {
38 | document.getElementById('show-book').style.cssText = 'display: none;';
39 | document.getElementById('book-form').style.cssText = 'display: none;';
40 | document.getElementById('show-contact').style.cssText = 'display: flex;';
41 | });
42 |
43 | export default { list, addBook, contactUs };
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # Awesome-books-with-ES6
2 |
3 | > This project is about building a book keeping website. Where folks can store their favortie book names. And can also delete those, whenever, needed.
4 | 
5 |
6 | ## Live demo
7 | [Live Demo]( https://divinecharlotte.github.io/Awesome-books-with-ES6/)
8 |
9 |
10 | ## Built With
11 |
12 | - Lighthouse (An open-source, automated tool for improving the quality of web pages. It has audits for performance, accessibility, progressive web apps, SEO and more).
13 |
14 | - Webhint (A customizable linting tool that helps you improve your site's accessibility, speed, cross-browser compatibility, and more by checking your code for best practices and common errors).
15 |
16 | - Stylelint (A mighty, modern linter that helps you avoid errors and enforce conventions in your styles).
17 |
18 | ### Prerequisites
19 |
20 | ## VScode or other editor
21 |
22 | ### Install
23 |
24 | #### Cloning the project
25 |
26 |
27 | ``` bash
28 | git clone https://github.com/iambenkis/Awesome-books-with-ES6.git
29 | ```
30 |
31 |
32 | ##### For validation detection using Stylelint Run
33 | ``` bash
34 | npx stylelint "**/*.{css,scss}"
35 | ```
36 |
37 | ## Getting packages and debuging with Webhint
38 |
39 | npm init -y
40 | npm install --save-dev hint@6.x
41 |
42 | ##### For validation detection using Webhint Run
43 |
44 | npx hint .
45 |
46 | ## Author
47 |
48 | 👤 **Divine Charlotte**
49 |
50 | - GitHub: [@Divine](https://github.com/divinecharlotte)
51 | - LinkedIn: [Divine Charlotte](https://www.linkedin.com/in/safar-ali999/)
52 |
53 | ## 🤝 Contributing
54 |
55 | Contributions, issues, and feature requests are welcome!
56 |
57 | Feel free to check the [issues page](https://github.com/divinecharlotte/Awesome-books-with-ES6/issues).
58 |
59 | ## Show your support
60 |
61 | Give a ⭐️ if you like this project!
62 |
63 | ## Acknowledgments
64 |
65 | - This project was inspired by [Microverse](https://www.microverse.org)
66 |
67 |
68 |
--------------------------------------------------------------------------------
/.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 .
--------------------------------------------------------------------------------
/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 | Book Keeping Website
9 |
10 |
11 |
27 |
28 |
29 |
30 |
31 |
All Awesome books
32 |
37 |
38 |
39 |
40 |
48 |
49 |
62 |
63 |
67 |
68 |
69 |
70 |
71 |
72 |
--------------------------------------------------------------------------------
/index.css:
--------------------------------------------------------------------------------
1 | #bookss {
2 | display: flex;
3 | width: 70%;
4 | align-items: center;
5 | flex-direction: column;
6 | justify-content: center;
7 | align-content: center;
8 | margin: 0 auto;
9 | }
10 |
11 | #dynamic {
12 | border: black 2px solid;
13 | }
14 |
15 | hr {
16 | width: 40%;
17 | height: 2px;
18 | background-color: black;
19 | }
20 |
21 | .table {
22 | width: 100%;
23 | }
24 |
25 | .delete {
26 | margin-left: 260px;
27 | }
28 |
29 | #book-list tr:nth-child(odd) {
30 | background-color: #e4e4e4;
31 | }
32 |
33 | #book-list td,
34 | #book-list th {
35 | padding: 4px;
36 | }
37 |
38 | table {
39 | border-collapse: collapse;
40 | }
41 |
42 | button {
43 | background-color: white;
44 | border-right: 4px solid black;
45 | border-bottom: 4px solid black;
46 | }
47 |
48 | form button {
49 | float: right;
50 | width: 100px;
51 | height: 40px;
52 | font-size: 25px;
53 | }
54 |
55 | section h1 {
56 | display: flex;
57 | justify-content: center;
58 | align-items: center;
59 | align-content: center;
60 | }
61 |
62 | nav #navigation {
63 | border: 3px black solid;
64 | display: flex;
65 | justify-content: space-between;
66 | align-content: center;
67 | align-items: center;
68 | padding-left: 3%;
69 | padding-right: 3%;
70 | height: 50px;
71 | margin-bottom: 150px;
72 | }
73 |
74 | nav ul {
75 | display: flex;
76 | gap: 30px;
77 | align-items: center;
78 | justify-content: center;
79 | align-content: center;
80 | }
81 |
82 | nav ul li a {
83 | text-decoration: none;
84 | color: black;
85 | }
86 |
87 | nav ul li {
88 | list-style-type: none;
89 | font-size: 20px;
90 | }
91 |
92 | nav ul hr {
93 | height: 30px;
94 | }
95 |
96 | nav ul li a:hover {
97 | color: blue;
98 | }
99 |
100 | #show-contact {
101 | align-items: center;
102 | flex-direction: column;
103 | display: none;
104 | }
105 |
106 | footer {
107 | border: 3px black solid;
108 | display: flex;
109 | align-items: center;
110 | justify-content: flex-start;
111 | gap: 43px;
112 | padding-left: 3%;
113 | height: 50px;
114 | width: 96%;
115 | margin: 0 auto;
116 | position: fixed;
117 | bottom: 0;
118 | left: 0;
119 | right: 0;
120 | }
121 |
122 | #book-form {
123 | font-size: 25px;
124 | display: none;
125 | align-items: center;
126 | justify-content: center;
127 | align-content: center;
128 | flex-direction: column;
129 | }
130 |
131 | #book-form input {
132 | width: 500px;
133 | height: 25px;
134 | border: 2px black solid;
135 | }
136 |
137 | section #show-book {
138 | justify-content: center;
139 | align-items: center;
140 | flex-direction: column;
141 | align-content: center;
142 | }
143 |
144 | .remove-page {
145 | display: flex;
146 | }
147 |
148 | .date-section {
149 | float: right;
150 | margin-top: -140px;
151 | }
152 |
--------------------------------------------------------------------------------