diff --git a/.github/pull_request_template.md b/.github/pull_request_template.md index ae4e1977..108898f0 100644 --- a/.github/pull_request_template.md +++ b/.github/pull_request_template.md @@ -2,11 +2,11 @@ You must title your PR like this: -COHORT_NAME | FIRST_NAME LAST_NAME | REPO_NAME | WEEK +REGION | COHORT_NAME | FIRST_NAME LAST_NAME | PROJ_NAME For example, -NW4 | Carol Owen | HTML-CSS-Module | Week1 +London | May-2025 | Carol Owen | Sprint-1 Complete the task list below this message. If your PR is rejected, check the task list. @@ -18,7 +18,7 @@ If your PR is rejected, check the task list. Self checklist - [ ] I have committed my files one by one, on purpose, and for a reason -- [ ] I have titled my PR with COHORT_NAME | FIRST_NAME LAST_NAME | REPO_NAME | WEEK +- [ ] I have titled my PR with REGION | COHORT_NAME | FIRST_NAME LAST_NAME | PROJ_NAME - [ ] I have tested my changes - [ ] My changes follow the [style guide](https://curriculum.codeyourfuture.io/guides/contributing/) - [ ] My changes meet the [requirements](./README.md) of this task diff --git a/.vscode/settings.json b/.vscode/settings.json new file mode 100644 index 00000000..6f3a2913 --- /dev/null +++ b/.vscode/settings.json @@ -0,0 +1,3 @@ +{ + "liveServer.settings.port": 5501 +} \ No newline at end of file diff --git a/debugging/book-library/index.html b/debugging/book-library/index.html index 23acfa71..9610077b 100644 --- a/debugging/book-library/index.html +++ b/debugging/book-library/index.html @@ -1,96 +1,109 @@ - + - - - - - + + + Book Library + - + + + + + + +
-

Library

-

Add books to your virtual library

+

📚 Book Library

+

Add books to your personal library

- +
+ + +
+
+
+ + -
-
- - - - - - - - + + + + + + +
+ + +
+ + + +
+
+ +
- - - - - - - - - - - - - - - - - - - -
TitleAuthorNumber of PagesRead
+
+ + + + + + + + + + + + + +
TitleAuthorPagesReadActions
+
- diff --git a/debugging/book-library/script.js b/debugging/book-library/script.js index 75ce6c1d..5fd2f376 100644 --- a/debugging/book-library/script.js +++ b/debugging/book-library/script.js @@ -1,103 +1,122 @@ let myLibrary = []; -window.addEventListener("load", function (e) { - populateStorage(); +window.addEventListener("load", () => { + loadFromStorage(); render(); }); -function populateStorage() { - if (myLibrary.length == 0) { - let book1 = new Book("Robison Crusoe", "Daniel Defoe", "252", true); - let book2 = new Book( - "The Old Man and the Sea", - "Ernest Hemingway", - "127", - true +function saveToStorage() { + localStorage.setItem("myLibrary", JSON.stringify(myLibrary)); +} + +function loadFromStorage() { + const stored = localStorage.getItem("myLibrary"); + if (stored) { + myLibrary = JSON.parse(stored).map( + (b) => new Book(b.title, b.author, b.pages, b.check) ); - myLibrary.push(book1); - myLibrary.push(book2); - render(); + } else { + populateStorage(); } } +function populateStorage() { + myLibrary.push( + new Book("Robinson Crusoe", "Daniel Defoe", "252", true), + new Book("The Old Man and the Sea", "Ernest Hemingway", "127", false) + ); + saveToStorage(); +} + +function Book(title, author, pages, check) { + this.title = title; + this.author = author; + this.pages = pages; + this.check = check; +} + const title = document.getElementById("title"); const author = document.getElementById("author"); const pages = document.getElementById("pages"); const check = document.getElementById("check"); +const message = document.getElementById("message"); +const search = document.getElementById("search"); -//check the right input from forms and if its ok -> add the new book (object in array) -//via Book function and start render function function submit() { + message.innerText = ""; + if ( - title.value == null || - title.value == "" || - pages.value == null || - pages.value == "" + title.value.trim() === "" || + author.value.trim() === "" || + pages.value.trim() === "" ) { - alert("Please fill all fields!"); - return false; - } else { - let book = new Book(title.value, title.value, pages.value, check.checked); - library.push(book); - render(); + message.innerText = " Please fill all fields."; + return; } -} -function Book(title, author, pages, check) { - this.title = title; - this.author = author; - this.pages = pages; - this.check = check; + const duplicate = myLibrary.some( + (book) => book.title.toLowerCase() === title.value.trim().toLowerCase() + ); + if (duplicate) { + message.innerText = " A book with this title already exists."; + return; + } + + const newBook = new Book(title.value, author.value, pages.value, check.checked); + myLibrary.push(newBook); + saveToStorage(); + render(); + + title.value = ""; + author.value = ""; + pages.value = ""; + check.checked = false; } function render() { - let table = document.getElementById("display"); - let rowsNumber = table.rows.length; - //delete old table - for (let n = rowsNumber - 1; n > 0; n-- { - table.deleteRow(n); + const table = document.getElementById("display"); + while (table.rows.length > 1) { + table.deleteRow(1); } - //insert updated row and cells - let length = myLibrary.length; - for (let i = 0; i < length; i++) { - let row = table.insertRow(1); - let titleCell = row.insertCell(0); - let authorCell = row.insertCell(1); - let pagesCell = row.insertCell(2); - let wasReadCell = row.insertCell(3); - let deleteCell = row.insertCell(4); - titleCell.innerHTML = myLibrary[i].title; - authorCell.innerHTML = myLibrary[i].author; - pagesCell.innerHTML = myLibrary[i].pages; - - //add and wait for action for read/unread button - let changeBut = document.createElement("button"); - changeBut.id = i; - changeBut.className = "btn btn-success"; - wasReadCell.appendChild(changeBut); - let readStatus = ""; - if (myLibrary[i].check == false) { - readStatus = "Yes"; - } else { - readStatus = "No"; + + const term = search?.value.toLowerCase() || ""; + + myLibrary.forEach((book, i) => { + + if ( + !book.title.toLowerCase().includes(term) && + !book.author.toLowerCase().includes(term) + ) { + return; } - changeBut.innerText = readStatus; - changeBut.addEventListener("click", function () { - myLibrary[i].check = !myLibrary[i].check; - render(); - }); - - //add delete button to every row and render again - let delButton = document.createElement("button"); - delBut.id = i + 5; - deleteCell.appendChild(delBut); - delBut.className = "btn btn-warning"; - delBut.innerHTML = "Delete"; - delBut.addEventListener("clicks", function () { - alert(`You've deleted title: ${myLibrary[i].title}`); - myLibrary.splice(i, 1); + const row = table.insertRow(1); + row.insertCell(0).innerText = book.title; + row.insertCell(1).innerText = book.author; + row.insertCell(2).innerText = book.pages; + + const readCell = row.insertCell(3); + const readBtn = document.createElement("button"); + readBtn.className = "btn btn-success btn-sm"; + readBtn.innerText = book.check ? "Yes" : "No"; + readBtn.onclick = () => { + book.check = !book.check; + saveToStorage(); render(); - }); - } + }; + readCell.appendChild(readBtn); + + const deleteCell = row.insertCell(4); + const delBtn = document.createElement("button"); + delBtn.className = "btn btn-danger btn-sm"; + delBtn.innerText = "Delete"; + delBtn.onclick = () => { + if (confirm(`Delete: "${book.title}"?`)) { + myLibrary.splice(i, 1); + saveToStorage(); + render(); + } + }; + deleteCell.appendChild(delBtn); + }); } diff --git a/debugging/book-library/style.css b/debugging/book-library/style.css index 302950cb..fe57b9e6 100644 --- a/debugging/book-library/style.css +++ b/debugging/book-library/style.css @@ -1,19 +1,40 @@ -.form-group { - width: 400px; - height: 300px; - align-self: left; - padding-left: 20px; +body { + background-color: #f8f9fa; + font-family: 'Segoe UI', sans-serif; } -.btn { - display: block; +.jumbotron { + background-color: #343a40; + color: white; + padding: 2rem 1rem; } -.form-check-label { - padding-left: 20px; - margin: 5px 0px 5px 0px; +#addBookForm { + border: 1px solid #dee2e6; + border-radius: 8px; + background-color: #ffffff; } -button.btn-info { - margin: 20px; +input[type="text"], +input[type="number"] { + margin-bottom: 10px; +} + +button, +input[type="submit"] { + margin-top: 10px; +} + +table th, +table td { + text-align: center; + vertical-align: middle; +} + +.btn-success { + background-color: #218838 !important; +} + +.btn-info { + background-color: #117a8b !important; }