diff --git a/README.md b/README.md new file mode 100644 index 0000000..fce66d3 --- /dev/null +++ b/README.md @@ -0,0 +1,15 @@ +# odin-library + +A simple book tracking site using vanilla HTML CSS JS + +boocks - book/tracks + +### todo: + +* save library to cookies / localstorage +* edit existing books + +## pics + +![Alt text](image.png) +![Alt text](image-1.png) \ No newline at end of file diff --git a/image-1.png b/image-1.png new file mode 100644 index 0000000..c599340 Binary files /dev/null and b/image-1.png differ diff --git a/image.png b/image.png new file mode 100644 index 0000000..f130d87 Binary files /dev/null and b/image.png differ diff --git a/index.html b/index.html index 87d1530..14ae915 100644 --- a/index.html +++ b/index.html @@ -10,8 +10,28 @@ + +
+
+
+
+
+ + + + + +
+
+ +
+
+

boocks

+
diff --git a/script.js b/script.js index 5ac5bee..d5472a1 100644 --- a/script.js +++ b/script.js @@ -9,92 +9,128 @@ function Book(title, author, pages, read) { this.read = read; } -function addBookToLibrary(book) { - library.push(book); +function addBookToLibrary(title, author, pages, read) { + let bookObject = new Book(title, author, pages, read); + library.push(bookObject); + displayBooks(); +} + + +function removeBookFromLibrary(dataId) { + library.splice(dataId, 1); + displayBooks(); } let books = [ - ["book", "author", 1, true], - ["book", "author", 1, true], - ["book", "author", 1, true], - ["book", "author", 1, true], - ["book", "author", 1, true], - ["book", "author", 1, true], - ["book", "author", 1, true], - ["book", "author", 1, true], - ["book", "author", 1, true], - ["book", "author", 1, true], - ["book", "author", 1, true], + ["The Hobbit", "J.R.R. Tolkien", 295, false], + ["Jessica's Guide to Dating on the Dark Side", "Natalie M. Pete-Clarkson Jr.", 295, false], + ] -books.forEach(book => { - let aBook = new Book(book[0], book[1], book[2], book[3]); - addBookToLibrary(aBook); +if (books.length) { + books.forEach(book => { + addBookToLibrary(book[0], book[1], book[2], book[3]); + }) +} else { displayBooks(); -}) +} + function displayBooks() { bookGrid.querySelectorAll("& > *").forEach(book => { book.remove(); }) - let pos = 0; - library.forEach(book => { - bookDiv = document.createElement("div"); - bookDiv.classList.add("book"); - bookDiv.setAttribute("arrayPos", pos) + let dataId = 0; + if (library.length) { + library.forEach(book => { + let bookDiv = document.createElement("div"); + bookDiv.classList.add("book"); + bookDiv.setAttribute("data-id", dataId) - bookDetails = document.createElement("div"); - bookDetails.classList.add("book-details"); - bookDetails.innerText = `${book.title}\n${book.author}\n${book.pages} pages\n${book.read ? "read" : "not read yet"}`; - bookDiv.append(bookDetails); + let bookDetails = document.createElement("div"); + bookDetails.classList.add("book-details"); - bookActions = document.createElement("div"); - bookActions.classList.add("book-actions"); - - toggleRead = document.createElement("i"); - toggleRead.classList.add("fa-solid", "fa-book"); - toggleRead.addEventListener("click", function() { - library[this.parentNode.parentNode.getAttribute("arrayPos")].read = !library[this.parentNode.parentNode.getAttribute("arrayPos")].read; - displayBooks(); - }); - bookActions.append(toggleRead); + let allDetails = { + "title": `${book.title}`, + "author": `${book.author}`, + "pages": `${book.pages}`, + "status": `${book.read ? "read" : "not read yet"}`, + }; - edit = document.createElement("i"); - edit.classList.add("fa-solid", "fa-edit"); - edit.addEventListener("click", function() { - library.splice(this.parentNode.parentNode.getAttribute("arrayPos"), 1); - displayBooks(); - }); - bookActions.append(edit); + for (detail in allDetails) { + let detailNameContain = document.createElement("div"); + detailNameContain.classList.add("detail-name"); - removeBtn = document.createElement("i"); - removeBtn.classList.add("fa-solid", "fa-trash"); - removeBtn.addEventListener("click", function() { - library.splice(this.parentNode.parentNode.getAttribute("arrayPos"), 1); - displayBooks(); - }); - bookActions.append(removeBtn); + let detailName = document.createElement("span"); + detailName.textContent = `${detail}: `; + detailNameContain.append(detailName); - bookDiv.append(bookActions); + let detailContent = document.createElement("span"); + detailContent.textContent = allDetails[detail]; + detailContent.classList.add("detail-content"); - bookGrid.append(bookDiv); - pos++; - }) + bookDetails.append(detailNameContain, detailContent); + }; + + bookDiv.append(bookDetails); + + let bookActions = document.createElement("div"); + bookActions.classList.add("book-actions"); + + let toggleRead = document.createElement("i"); + toggleRead.classList.add("fa-solid", "fa-book"); + toggleRead.addEventListener("click", function() { + library[this.parentNode.parentNode.getAttribute("data-id")].read = !library[this.parentNode.parentNode.getAttribute("data-id")].read; + displayBooks(); + }); + bookActions.append(toggleRead); + + // let edit = document.createElement("i"); + // edit.classList.add("fa-solid", "fa-edit"); + // edit.addEventListener("click", function() { + // removeBookFromLibrary(this.parentNode.parentNode.getAttribute("data-id")); + // }); + // bookActions.append(edit); + + let removeBtn = document.createElement("i"); + removeBtn.classList.add("fa-solid", "fa-trash"); + removeBtn.addEventListener("click", function() { + removeBookFromLibrary(this.parentNode.parentNode.getAttribute("data-id")); + }); + bookActions.append(removeBtn); + + bookDiv.append(bookActions); + + bookGrid.append(bookDiv); + + dataId++; + }) + } else { + let info = document.createElement("span"); + info.classList.add("no-books"); + info.textContent = "No books to list. Add some!"; + bookGrid.append(info); + } } -// const newBookBtn = document.querySelector("button#new-book"); -// const newBookDialog = document.querySelector("dialog#new-book"); -// newBookBtn.addEventListener("click", () => { -// newBookDialog.showModal(); -// }) -// newBookDialog.querySelector("button[type='submit']").addEventListener("click", () => { -// let names = []; -// newBookDialog.querySelectorAll("form > input").forEach(input => { -// if (!names.includes(input.name)) { -// names.push(input.name); -// } -// }); -// names.forEach(one => { -// document.getElementsByName(one).value = ""; -// }) -// }) \ No newline at end of file +const newBookBtn = document.querySelector("button#new-book"); +const newBookDialog = document.querySelector("dialog"); +newBookBtn.addEventListener("click", () => { + newBookDialog.showModal(); +}) + +newBookDialog.querySelector("form").addEventListener("submit", (event) => { + let formData = new FormData(document.querySelector("form")); + let bookVals = [] + for (let [key, value] of formData.entries()) { + bookVals.push(value); + } + addBookToLibrary(bookVals[0], bookVals[1], bookVals[2], bookVals[3]); +}); + +newBookDialog.addEventListener("close", (event) => { + newBookDialog.querySelectorAll("input").forEach(input => { + input.value = null; + }) + newBookDialog.querySelector("input[type='radio']").checked = true; +}); \ No newline at end of file diff --git a/style.css b/style.css index 7ce19f1..1f89bfb 100644 --- a/style.css +++ b/style.css @@ -1,7 +1,7 @@ @import url('https://fonts.googleapis.com/css2?family=Roboto:ital,wght@0,400;0,700;1,400;1,700&display=swap'); :root { - font-family: 'Roboto', sans-serif; + font-family: "Roboto", system-ui, -apple-system, BlinkMacSystemFont, 'Segoe UI', Oxygen, Ubuntu, Cantarell, 'Open Sans', 'Helvetica Neue', sans-serif; } html, body { @@ -18,35 +18,73 @@ header { padding: 20px 40px; box-sizing: border-box; text-align: center; + display: flex; + justify-content: space-between; h1 { font-size: 2.5rem; font-weight: bold; } + button#new-book { + font-size: 1rem; + font-weight: bold; + border: 2px solid #444; + color: #fff; + background-color: #232323; + cursor: pointer; + outline: none; + border-radius: 15px; + padding: 5px 10px; + } } #books { display: grid; - grid-template-columns: repeat(auto-fit, minmax(max(20%, 270px), 1fr)); + grid-template-columns: repeat(auto-fill, minmax(max(20%, 270px), 1fr)); gap: 20px; padding: 20px; + .no-books { + font-size: 2rem; + text-shadow: 1px 1px 1px #2222dddd; + } + .book { background-color: #1d1d1dcc; - padding: 30px; + padding: 20px; border-radius: 20px; font-size: 1.3rem; text-align: center; display: flex; flex-direction: row; - + justify-content: space-between; + align-items: center; + gap: 10px; .book-details { - margin: auto; + flex: 1; + display: grid; + align-items: stretch; + grid-template-columns: 50px 1fr; + & > span { + display: block; + padding: 4px; + word-break: break-word; + } + span ~ span, .detail-name ~ .detail-name { + border-top: 1px solid #aaaaaaaa; + } + .detail-name { + color: #aaa; + display: flex; + align-items: center; + justify-content: center; + font-size: 0.9rem; + } } .book-actions { display: flex; flex-direction: column; gap: 8px; - justify-content: flex-end; + justify-content: center; i { display: block; font-size: 1.2rem; @@ -79,12 +117,12 @@ header { .fa-book::after { content: "toggle read"; } - .fa-edit:hover { + /* .fa-edit:hover { color: rgb(219, 175, 30); } .fa-edit::after { content: "edit"; - } + } */ .fa-trash:hover { color: rgb(220, 85, 85); } @@ -93,4 +131,40 @@ header { } } } -} \ No newline at end of file +} + +dialog { + background-color: #000000aa; + padding: 50px 40px; + color: #fff; + &[open] ~ * { + filter: blur(6px); + } + section { + display: flex; + justify-content: space-between; + gap: 5px; + padding: 5px; + align-items: center; + input[type="text"], input[type="number"] { + padding: 5px; + border-radius: 10px; + background-color: #121212aa; + outline: none; + border: 1px solid #aaaaaaaa; + color: #fff; + } + button[type="submit"] { + padding: 5px; + border-radius: 10px; + background-color: #121212aa; + outline: none; + border: 1px solid #aaaaaaaa; + color: #fff; + font-size: 1rem; + cursor: pointer; + margin: auto; + } + } +} +