* feat: initial commit

* feat: initial javascript complete

* feat: modal added

* feat: logic completed.

* feat: modal base styling complete

* feat: more styling

* feat: styling complete
This commit is contained in:
Mike 2023-11-22 11:32:12 -05:00 committed by GitHub
parent d667833847
commit 7a40d907d9
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
3 changed files with 336 additions and 0 deletions

161
library/css/style.css Normal file
View file

@ -0,0 +1,161 @@
:root {
--background-color: #DBDADD;
--card-color: #EFEEF0;
--btn-red-color: #e15252;
--btn-green-color: #7ed7a9;
--spacing-sm: 16px;
--spacing-md: 20px;
}
body, html {
font-size: 16px;
margin: 0;
padding: 0;
font-family: 'Roboto', sans-serif;
min-height: 100vh;
background-color: var(--background-color);
}
button {
font-size: 1.3rem;
font-family: inherit;
cursor: pointer;
border: none;
border-radius: 5px;
}
dialog {
box-shadow: 0 0 #0000, 0 0 #0000, 0 25px 50px -12px rgba(0, 0, 0, 0.25);
}
.container {
display: flex;
flex-direction: column;
justify-content: center;
align-items: center;
}
.navbar {
margin-top: 20px;
margin-bottom: 100px;
display: flex;
flex-direction: column;
justify-content: space-between;
align-content: center;
align-items: center;
}
.navbar .header {
font-size: 2.6rem;
font-weight: 900;
}
.content {
min-width: 1200px;
margin-left: 30px;
}
.book-cards {
display: grid;
grid-template-columns: repeat(auto-fit, minmax(300px, 370px));
gap: 10px;
}
.card {
display: flex;
flex-direction: column;
justify-content: center;
gap: 20px;
width: 300px;
min-height: 250px;
text-align: center;
box-shadow: 0 4px 8px 0 rgba(0,0,0,0.2);
transition: 0.3s;
padding: 20px;
margin: 20px;
background-color: var(--card-color);
}
.card:hover {
box-shadow: 0 8px 16px 0 rgba(0,0,0,0.2);
}
.card p {
font-size: 1.5rem;
padding: 0;
margin: 0;
}
.card>.card-title {
font-weight: 700;
}
.card>.card-author {
font-weight: 300;
}
.modal {
/* display: flex; */
flex-direction: column;
min-height: 43vh;
min-width: 20vw;
border: none;
padding: 20px 40px;
}
.form {
display: flex;
flex-direction: column;
gap: 10px;
}
.form input {
min-height: 2.2rem;
font-size: 1.2rem;
}
.form-header {
display: flex;
justify-content: space-between;
}
.form-header h1 {
font-size: 1.7rem;
align-self: center;
}
.form-item {
display: flex;
justify-content: center;
align-items: center;
gap: 20px;
}
.form-item input {
transform: scale(1.5);
}
.form-item label {
font-weight: 500;
font-size: 1.3rem;
}
.close-btn {
height: 30px;
align-self: center;
padding: 4px;
}
.btn {
padding: var(--spacing-sm) var(--spacing-md);
}
.red-btn-color {
background-color: var(--btn-red-color);
}
.green-btn-color {
background-color: var(--btn-green-color);
}

53
library/index.html Normal file
View file

@ -0,0 +1,53 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<link rel="stylesheet"
href="https://fonts.googleapis.com/css2?family=Material+Symbols+Outlined:opsz,wght,FILL,GRAD@20..48,100..700,0..1,-50..200" />
<link rel="preconnect" href="https://fonts.googleapis.com">
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
<link href="https://fonts.googleapis.com/css2?family=Roboto:ital,wght@0,500;0,700;0,900;1,500;1,700;1,900&display=swap" rel="stylesheet">
<link rel="stylesheet" href="css/style.css">
<title>Anonymous Library</title>
</head>
<body>
<div class="container">
<nav class="navbar">
<h1 class="header">Anonymous Library</h1>
<button class="show-modal btn">Add Book</button>
</nav>
<div class="content">
<div class="book-cards">
</div>
</div>
<footer>
<div class="contact"></div>
<div class="icons"></div>
</footer>
</div>
<dialog class="modal">
<div class="form-header">
<h1 class="form-header">Add New Book</h1>
<button class="close-btn">
<span class="material-symbols-outlined">close</span>
</button>
</div>
<form action="dialog" class="form">
<input type="text" name="title" id="title" placeholder="Book title"
required>
<input type="text" name="author" id="author" placeholder="Author"
required>
<div class="form-item">
<label for="checkbox">Have you read the book?</label>
<input type="checkbox" id="read-button">
</div>
<button type="submit" id="submit-btn" class="btn">Submit</button>
</form>
</dialog>
<script src="js/script.js"></script>
</body>
</html>

122
library/js/script.js Normal file
View file

@ -0,0 +1,122 @@
const myLibrary = [];
const submitButton = document.querySelector('#submit-btn');
const booksDiv = document.querySelector('.book-cards');
const dialog = document.querySelector("dialog");
const addBookButton = document.querySelector(".show-modal");
const closeDialogButton = document.querySelector(".close-btn");
const defaultData = new Book('Atomic Habits', 'James Clear', false);
function Book(title, author, read) {
this.title = title;
this.author = author;
this.read = read;
this.info = function() {
let haveRead = this.read ? "have read" : "have not read";
return `${this.title}, by ${this.author}, ${this.pages} pages, ${haveRead}`;
};
}
Book.prototype.toggleBookReadStatus = function(){
this.read = !this.read;
}
function addBookToLibrary(book) {
let newBook = new Book(book.title, book.author, book.read);
myLibrary.push(newBook);
}
function displayBooks(books) {
// Clear the screen before looping
booksDiv.innerHTML = "";
books.forEach((element, i) => {
const card = document.createElement('div');
card.classList.add('card');
card.setAttribute("data-card", i);
const title = document.createElement('p');
title.classList.add('card-title');
const author = document.createElement('p');
author.classList.add('card-author');
const readBtn = document.createElement('button');
const readBtnFlag = element.read ? "read" : "not read";
const readBtnColor = element.read ? "green-btn-color" : "red-btn-color";
console.log(readBtnColor, element.read, readBtnFlag);
readBtn.classList.add('btn','read-btn',readBtnColor);
readBtn.textContent = readBtnFlag;
const deleteBtn = document.createElement('button');
deleteBtn.classList.add('btn', 'delete-btn')
deleteBtn.textContent = 'delete book';
title.textContent = `"${element.title}"`;
author.textContent = element.author;
card.appendChild(title);
card.appendChild(author);
card.appendChild(readBtn);
card.appendChild(deleteBtn);
booksDiv.appendChild(card);
});
}
booksDiv.addEventListener('click', event => {
let target = event.target.className;
if (target.includes('read-btn')){
let cardIndex = event.target.parentElement.dataset.card;
myLibrary[cardIndex].toggleBookReadStatus();
displayBooks(myLibrary);
};
});
booksDiv.addEventListener('click', event => {
let target = event.target.className;
if (target.includes('delete-btn')){
let cardIndex = event.target.parentElement.dataset.card;
myLibrary.splice(cardIndex, 1);
displayBooks(myLibrary);
};
});
submitButton.addEventListener('click', event => {
const author = document.querySelector('#author').value;
const title = document.querySelector('#title').value;
const readBtn = document.querySelector('#read-button').value;
const bookIsRead = readBtn === 'on' ? true : false;
if (author === "" || title === "") {
return
}
// create book object
const newBook = new Book(title, author, bookIsRead);
addBookToLibrary(newBook);
displayBooks(myLibrary);
event.preventDefault();
dialog.close();
});
addBookButton.addEventListener('click', () => {
dialog.showModal();
});
closeDialogButton.addEventListener('click', () => {
dialog.close();
});
// default data
myLibrary.push(defaultData)
// Load books on page load
displayBooks(myLibrary);