Skip to content

Commit

Permalink
Merge pull request #5 from MahdiSohaily/create-SPA
Browse files Browse the repository at this point in the history
Create Single Page Application
  • Loading branch information
MahdiSohaily committed Sep 21, 2022
2 parents ff63fb3 + b27f66a commit 77467da
Show file tree
Hide file tree
Showing 9 changed files with 249 additions and 50 deletions.
3 changes: 2 additions & 1 deletion .eslintignore
@@ -1 +1,2 @@
src/js/modules/*.js
src/js/modules/*.js
src/js/components/*.js
32 changes: 15 additions & 17 deletions index.html
Expand Up @@ -14,7 +14,18 @@
</head>

<body>
<main class="full-height">
<header>
<nav class="main-header">
<a class="logo" href="javascript:void(0)">Awesome Book</a>
<ul class="nav-menu">
<li><a class="list-item" href="javascript:void(0)" data-display="list">List</a></li>
<li><a class="list-item" href="javascript:void(0)" data-display="form">Add New</a></li>
<li><a class="list-item" href="javascript:void(0)" data-display="contact">Contact</a></li>

</ul>
</nav>
</header>
<main id="app" class="full-height">
<section class="card" aria-labelledby="project-name">
<h1 id="project-name" class="text-center primary-heading">All Awesome Books</h1>
<table class="table my-3 px-3 py-3 border">
Expand All @@ -30,24 +41,11 @@ <h1 id="project-name" class="text-center primary-heading">All Awesome Books</h1>
<!-- Books list will be appended here -->
</tbody>
</table>
<div class="data-form">
<h2 class="text-center secondary-header">Add a new book</h2>
<form action="javascript:void(0)" method="post" class="form">
<div class="form-control my-3">
<input class="input-form border" type="text" required minlength="3" name="title" id="book-title" aria-label="book-title" placeholder="Title">
</div>
<div class="form-control my-3">
<input class="input-form border" type="text" required minlength="3" name="author" id="book-Author" aria-label="book-Author" placeholder="Author">
</div>
<div class="form-control my-3">
<button type="submit" class="btn border">Add
<img width="20" height="20" class="icon" src="./src/icon/submit-icon.svg" alt="submit-icon">
</button>
</div>
</form>
</div>
</section>
</main>
<footer>
<p>Copy Right are reserved</p>
</footer>
<script type="module" src="./src/js/main.js"></script>
</body>

Expand Down
68 changes: 59 additions & 9 deletions src/css/styles.css
@@ -1,10 +1,10 @@
:root {
--clr-primary-400: 263 55% 52%;
--clr-secondary-400: 217 19% 35%;
--clr-secondary-500: 219 29% 14%;
--clr-neutral-100: 0 0% 100%;
--clr-neutral-200: 210 46% 95%;
--clr-neutral-300: 0 0% 81%;
--clr-primary-400: hsl(263 55% 52%);
--clr-secondary-400: hsl(217 19% 35%);
--clr-secondary-500: hsl(219 29% 14%);
--clr-neutral-100: hsl(0 0% 100%);
--clr-neutral-200: hsl(210 46% 95%);
--clr-neutral-300: hsl(0 0% 81%);
}

/* Box sizing rules */
Expand All @@ -18,7 +18,7 @@
* {
margin: 0;
padding: 0;
font-family: "Barlow Semi Condensed", sans-serif;
font-family: 'Barlow Semi Condensed', sans-serif;
}

/* Remove list styles on ul, ol elements with a list role, which suggests default styling will be removed */
Expand All @@ -41,7 +41,7 @@ body {

/* A elements that don't have a class get default styles */
a:not([class]) {
text-decoration-skip-ink: auto;
text-decoration: auto;
}

/* Inherit fonts for inputs and buttons */
Expand Down Expand Up @@ -102,6 +102,43 @@ select {
border: 2px solid gray;
}

/* Main header section styles */
header {
position: fixed;
top: 0;
width: 100%;
box-shadow: 2px 2px 5px var(--clr-neutral-300);
background-color: white;
}

.main-header {
max-width: 90%;
margin-inline: auto;
display: flex;
justify-content: space-between;
align-items: center;
padding: 1.5rem 1rem;
}

.logo {
color: var(--clr-primary-400);
text-decoration: none;
font-size: 24px;
font-weight: bold;
}

.nav-menu {
list-style-type: none;
display: flex;
gap: 1rem;
}

.nav-menu li a {
color: var(--clr-secondary-500);
font-weight: bold;
text-decoration: none;
}

/* General styling */
.full-height {
height: 100vh;
Expand All @@ -110,7 +147,7 @@ select {
main {
display: flex;
justify-content: center;
align-items: center;
padding-top: 7rem;
}

.card {
Expand Down Expand Up @@ -166,3 +203,16 @@ td {
margin-inline: auto;
padding: 0.25rem 2rem;
}

/* footer styles */
footer {
position: fixed;
bottom: 0;
width: 100%;
padding: 1.5rem 1rem;
background-color: var(--clr-secondary-400);
}

footer p {
color: var(--clr-neutral-300);
}
21 changes: 21 additions & 0 deletions src/js/components/Contact.js
@@ -0,0 +1,21 @@
export default class Contact {
constructor() {
this._content = `
<section class="card" aria-labelledby="project-name">
<h1 id="project-name" class="text-center primary-heading">Contact Information</h1>
<div className="into">
<h2 class="secondary-heading">Find the best answer to your technical question, Reach out to us through the following contacts:</h2>
<ul class="my-3">
<li>Our email: Mahdi@gmail.af</li>
<li>Our phone number: +2349182566</li>
<li>Our Address: Lorem ipsum dolor sit amet.</li>
</ul>
</div>
</section>
`;
}

get content() {
return this._content;
}
}
46 changes: 46 additions & 0 deletions src/js/components/Form.js
@@ -0,0 +1,46 @@
import Book from '../modules/Books.js';

export default class Form {
constructor() {
this._content = `
<section class="card" aria-labelledby="project-name">
<div class="data-form">
<h2 class="text-center secondary-header">Add a new book</h2>
<form action="javascript:void(0)" method="post" class="form">
<div class="form-control my-3">
<input class="input-form border" type="text" required minlength="3" name="title" id="book-title" aria-label="book-title" placeholder="Title">
</div>
<div class="form-control my-3">
<input class="input-form border" type="text" required minlength="3" name="author" id="book-Author" aria-label="book-Author" placeholder="Author">
</div>
<div class="form-control my-3">
<button type="submit" class="btn border">Add
<img width="20" height="20" class="icon" src="./src/icon/submit-icon.svg" alt="submit-icon">
</button>
</div>
</form>
</div>
</section>
`;
}

get content() {
return this._content;
}

active() {
const form = document.querySelector('form');
const title = document.getElementById('book-title');
const author = document.getElementById('book-Author');

form.addEventListener('submit', () => {
const bookTitle = title.value;
const bookAuthor = author.value;
const newBook = new Book(bookTitle, bookAuthor);
newBook.addBook();
console.log(newBook);
title.value = '';
author.value = '';
});
}
}
54 changes: 54 additions & 0 deletions src/js/components/List.js
@@ -0,0 +1,54 @@
import BooktoDom from '../modules/BookController.js';

export default class List {
constructor() {
this._content = `
<section class="card" aria-labelledby="project-name">
<h1 id="project-name" class="text-center primary-heading">All Awesome Books</h1>
<table class="table my-3 px-3 py-3 border">
<thead>
<tr>
<th>NO</th>
<th>Title</th>
<th>Author</th>
<th>Actions</th>
</tr>
</thead>
<tbody class="books-list">
<!-- Books list will be appended here -->
</tbody>
</table>
</section>
`;
}

get content() {
return this._content;
}

active() {
const dataStored = localStorage.getItem('books');
const books = JSON.parse(dataStored);
const listContainer = document.querySelector('.books-list');
if (books) {
for (const item in books) {
listContainer.innerHTML += BooktoDom.append(item, books[item]);
}
} else {
listContainer.innerHTML =
'<tr> <td colspan="4">Nothing to show </td> <tr>';
}
}
deleteBook() {
const delBtn = document.querySelectorAll('.delete-btn');
delBtn.forEach((element, index) => {
element.addEventListener('click', () => {
element.parentNode.parentNode.remove();
const books = JSON.parse(localStorage.getItem('books'));
books.splice(index, 1);
localStorage.setItem('books', JSON.stringify(books));
});
});
}
}
63 changes: 45 additions & 18 deletions src/js/main.js
@@ -1,21 +1,48 @@
import Book from './modules/Books.js';
import BooktoDom from './modules/BookController.js';
// DOM Address to run handel events
const form = document.querySelector('form');
const title = document.getElementById('book-title');
const author = document.getElementById('book-Author');
const listContainer = document.querySelector('.books-list');
// Page components
import List from './components/List.js';
import Contact from './components/Contact.js';
import Form from './components/Form.js';

window.addEventListener('load', () => {
BooktoDom.checkStorage(listContainer);
});
// new DOM Elements
const pages = document.querySelectorAll('.list-item');
const container = document.getElementById('app');
const myList = new List();
container.innerHTML = myList.content;
myList.active();
myList.deleteBook();

pages.forEach((item) => {
item.addEventListener('click', (e) => {
const page = e.target.getAttribute('data-display');
switch (page) {
case 'list':
{
const myList = new List();
container.innerHTML = myList.content;
myList.active();
myList.deleteBook();
}
break;
case 'form':
{
const myForm = new Form();
container.innerHTML = myForm.content;
myForm.active();
}

form.addEventListener('submit', () => {
const bookTitle = title.value;
const bookAuthor = author.value;
const newBook = new Book(bookTitle, bookAuthor);
newBook.addBook();
BooktoDom.checkStorage(listContainer);
title.value = '';
author.value = '';
break;
case 'contact':
{
const myContact = new Contact();
container.innerHTML = myContact.content;
}
break;
default: {
const defaultPage = new List();
container.innerHTML = defaultPage.content;
defaultPage.active();
defaultPage.deleteBook();
}
}
});
});
9 changes: 4 additions & 5 deletions src/js/modules/BookController.js
@@ -1,5 +1,6 @@
import Book from './Books.js';
class BooktoDom {

export default class BooktoDom {
static append(index, { _title: title, _author: author }) {
return `
<tr >
Expand Down Expand Up @@ -30,9 +31,8 @@ class BooktoDom {
target.innerHTML = `<tr> <td colspan="4">Nothing to show </td> <tr>`;
}
}

static deleteBook() {
let delBtn = document.querySelectorAll('.delete-btn');
deleteBook() {
const delBtn = document.querySelectorAll('.delete-btn');
delBtn.forEach((element, index) => {
element.addEventListener('click', () => {
element.parentNode.parentNode.remove();
Expand All @@ -43,4 +43,3 @@ class BooktoDom {
});
}
}
export default BooktoDom;
3 changes: 3 additions & 0 deletions src/js/modules/Books.js
Expand Up @@ -7,6 +7,7 @@ export default class Book {
get title() {
return this._title;
}

get author() {
return this._author;
}
Expand All @@ -21,4 +22,6 @@ export default class Book {
books.push(this);
localStorage.setItem('books', JSON.stringify(books));
}


}

0 comments on commit 77467da

Please sign in to comment.