From 37f61c7ef8a9c4381bfd118e8078fc5a6aaa1ecd Mon Sep 17 00:00:00 2001 From: Pretty Taruvinga Date: Tue, 21 Apr 2026 18:45:04 +0200 Subject: [PATCH 01/24] Fix render loop syntax error and display books on load Fix submit function to add books correctly Fix author field bug and read status logic Fix delete button functionality Add form validation for missing author input --- debugging/book-library/script.js | 27 +++++++++++---------------- 1 file changed, 11 insertions(+), 16 deletions(-) diff --git a/debugging/book-library/script.js b/debugging/book-library/script.js index 75ce6c1d..018839be 100644 --- a/debugging/book-library/script.js +++ b/debugging/book-library/script.js @@ -28,17 +28,12 @@ const check = document.getElementById("check"); //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() { - if ( - title.value == null || - title.value == "" || - pages.value == null || - pages.value == "" - ) { + if (title.value == "" || author.value == "" || pages.value == "") { alert("Please fill all fields!"); return false; - } else { - let book = new Book(title.value, title.value, pages.value, check.checked); - library.push(book); + + let book = new Book(title.value, author.value, pages.value, check.checked); + myLibrary.push(book); render(); } } @@ -54,7 +49,7 @@ function render() { let table = document.getElementById("display"); let rowsNumber = table.rows.length; //delete old table - for (let n = rowsNumber - 1; n > 0; n-- { + for (let n = rowsNumber - 1; n > 0; n--) { table.deleteRow(n); } //insert updated row and cells @@ -76,7 +71,7 @@ function render() { changeBut.className = "btn btn-success"; wasReadCell.appendChild(changeBut); let readStatus = ""; - if (myLibrary[i].check == false) { + if (myLibrary[i].check == true) { readStatus = "Yes"; } else { readStatus = "No"; @@ -90,11 +85,11 @@ function 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 () { + delButton.id = i + 5; + deleteCell.appendChild(delButton); + delButton.className = "btn btn-warning"; + delButton.innerHTML = "Delete"; + delButton.addEventListener("click", function () { alert(`You've deleted title: ${myLibrary[i].title}`); myLibrary.splice(i, 1); render(); From 1279f891d31c8d63ad13879b71dcc16bc385d2d7 Mon Sep 17 00:00:00 2001 From: Pretty Taruvinga Date: Tue, 21 Apr 2026 19:00:55 +0200 Subject: [PATCH 02/24] Add object destructuring to introduceYourself function --- Sprint-1/destructuring/exercise-1/exercise.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Sprint-1/destructuring/exercise-1/exercise.js b/Sprint-1/destructuring/exercise-1/exercise.js index 1ff2ac5c..d86bc7bf 100644 --- a/Sprint-1/destructuring/exercise-1/exercise.js +++ b/Sprint-1/destructuring/exercise-1/exercise.js @@ -6,7 +6,7 @@ const personOne = { // Update the parameter to this function to make it work. // Don't change anything else. -function introduceYourself(___________________________) { +function introduceYourself({ name, age, favouriteFood }) { console.log( `Hello, my name is ${name}. I am ${age} years old and my favourite food is ${favouriteFood}.` ); From af758d37d9825e3e3c951bf5ed64e3c0eabfef35 Mon Sep 17 00:00:00 2001 From: Pretty Taruvinga Date: Tue, 21 Apr 2026 19:10:55 +0200 Subject: [PATCH 03/24] Filter Gryffindor members and teachers with pets using destructuring --- Sprint-1/destructuring/exercise-2/exercise.js | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/Sprint-1/destructuring/exercise-2/exercise.js b/Sprint-1/destructuring/exercise-2/exercise.js index e11b75eb..4c67324b 100644 --- a/Sprint-1/destructuring/exercise-2/exercise.js +++ b/Sprint-1/destructuring/exercise-2/exercise.js @@ -70,3 +70,16 @@ let hogwarts = [ occupation: "Teacher", }, ]; +// Task 1 +hogwarts.forEach(({ firstName, lastName, house }) => { + if (house === "Gryffindor") { + console.log(firstName, lastName); + } +}); + +// Task 2 +hogwarts.forEach(({ firstName, lastName, occupation, pet }) => { + if (occupation === "Teacher" && pet !== null) { + console.log(firstName, lastName); + } +}); From 70dad6b4e61e1ed3386a16c4adc6e3dc5d80d679 Mon Sep 17 00:00:00 2001 From: Pretty Taruvinga Date: Tue, 21 Apr 2026 19:13:57 +0200 Subject: [PATCH 04/24] Print takeout receipt using object destructuring --- Sprint-1/destructuring/exercise-3/exercise.js | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/Sprint-1/destructuring/exercise-3/exercise.js b/Sprint-1/destructuring/exercise-3/exercise.js index b3a36f4e..14328b99 100644 --- a/Sprint-1/destructuring/exercise-3/exercise.js +++ b/Sprint-1/destructuring/exercise-3/exercise.js @@ -6,3 +6,17 @@ let order = [ { itemName: "Hot Coffee", quantity: 2, unitPricePence: 100 }, { itemName: "Hash Brown", quantity: 4, unitPricePence: 40 }, ]; +let totalPence = 0; + +console.log("QTY ITEM TOTAL"); + +order.forEach(({ itemName, quantity, unitPricePence }) => { + let itemTotal = quantity * unitPricePence; + totalPence += itemTotal; + + console.log( + `${quantity} ${itemName} ${(itemTotal / 100).toFixed(2)}` + ); +}); + +console.log(`\nTotal: ${(totalPence / 100).toFixed(2)}`); From 1c1a717a6dbe912020e9304478485d3da5f67cb3 Mon Sep 17 00:00:00 2001 From: Pretty Taruvinga Date: Tue, 21 Apr 2026 19:29:34 +0200 Subject: [PATCH 05/24] Implement ASCII cowsay CLI with default fallback message --- challenges/challenge-cowsay-two/solution1.js | 29 ++++++++++---------- 1 file changed, 15 insertions(+), 14 deletions(-) diff --git a/challenges/challenge-cowsay-two/solution1.js b/challenges/challenge-cowsay-two/solution1.js index a7f2416b..863fa5bc 100644 --- a/challenges/challenge-cowsay-two/solution1.js +++ b/challenges/challenge-cowsay-two/solution1.js @@ -4,27 +4,28 @@ // https://nodejs.dev/learn/nodejs-accept-arguments-from-the-command-line // ================= -// 1. Accept arguments - -// how will you accept arguments? - -// 2. Make supplies for our speech bubble +let saying = process.argv[2]; || "Mooooo"; let topLine = '_'; let bottomLine = '-'; -let saying = ''; +let saying = '';"" // 3. Make a cow that takes a string function cowsay(saying) { -// how will you make the speech bubble contain the text? - -// where will the cow picture go? - -// how will you account for the parameter being empty? - + let line = "_".repeat(saying.length + 2); + let bottom = "-".repeat(saying.length + 2); + + + console.log(` ${line} `); + console.log(`< ${saying} >`); + console.log(` ${bottom} `); + console.log(` \\ ^__^`); + console.log(` \\ (oo)\\_______`); + console.log(` (__)\\ )\\/\\`); + console.log(` ||----w |`); + console.log(` || ||`); } -//4. Pipe argument into cowsay function and return a cow +cowsay(saying); -// how will you log this to the console? From 433d3bbc24a05f7f6ed64e0e4d7589df1af3e92e Mon Sep 17 00:00:00 2001 From: Pretty Taruvinga Date: Tue, 21 Apr 2026 19:42:06 +0200 Subject: [PATCH 06/24] Add readline prompt and default fallback to cowsay --- challenges/challenge-cowsay-two/solution2.js | 19 +++++++++++++++++-- 1 file changed, 17 insertions(+), 2 deletions(-) diff --git a/challenges/challenge-cowsay-two/solution2.js b/challenges/challenge-cowsay-two/solution2.js index 8aca8572..669c79ba 100644 --- a/challenges/challenge-cowsay-two/solution2.js +++ b/challenges/challenge-cowsay-two/solution2.js @@ -11,8 +11,23 @@ // 3. Make a cow that takes a string const cow = (saying) => { - // how did you make the cow before? -} + let line = "_".repeat(saying.length + 2); + let bottom = "-".repeat(saying.length + 2); + + console.log(` ${line} `); + console.log(`< ${saying} >`); + console.log(` ${bottom} `); + console.log(` \\ ^__^`); + console.log(` \\ (oo)\\_______`); + console.log(` (__)\\ )\\/\\`); + console.log(` ||----w |`); + console.log(` || ||`); + +}; +rl.question("What would you like the cow to say? ", function(answer) { + cow(answer || "Mooooo"); + rl.close(); +}); // 4. Use readline to get a string from the terminal // (with a prompt so it's clearer what we want) \ No newline at end of file From 6f81c61615cd59be8dc5905b1e495926e10190a9 Mon Sep 17 00:00:00 2001 From: Pretty Taruvinga Date: Tue, 21 Apr 2026 22:11:04 +0200 Subject: [PATCH 07/24] Fix cowsay CLI argument handling and syntax errors" --- challenges/challenge-cowsay-two/solution1.js | 32 +++++++++----------- 1 file changed, 14 insertions(+), 18 deletions(-) diff --git a/challenges/challenge-cowsay-two/solution1.js b/challenges/challenge-cowsay-two/solution1.js index 863fa5bc..fa799814 100644 --- a/challenges/challenge-cowsay-two/solution1.js +++ b/challenges/challenge-cowsay-two/solution1.js @@ -1,31 +1,27 @@ // ================= -// Stripped down cowsayer CLI, +// Stripped down cowsayer CLI, // no libraries // https://nodejs.dev/learn/nodejs-accept-arguments-from-the-command-line // ================= -let saying = process.argv[2]; || "Mooooo"; - -let topLine = '_'; -let bottomLine = '-'; -let saying = '';"" +let topLine = "_"; +let bottomLine = "-"; +let saying = process.argv[2] || "Mooooo"; // 3. Make a cow that takes a string function cowsay(saying) { - let line = "_".repeat(saying.length + 2); - let bottom = "-".repeat(saying.length + 2); + let line = "_".repeat(saying.length + 2); + let bottom = "-".repeat(saying.length + 2); - - console.log(` ${line} `); - console.log(`< ${saying} >`); - console.log(` ${bottom} `); - console.log(` \\ ^__^`); - console.log(` \\ (oo)\\_______`); - console.log(` (__)\\ )\\/\\`); - console.log(` ||----w |`); - console.log(` || ||`); + console.log(` ${line} `); + console.log(`< ${saying} >`); + console.log(` ${bottom} `); + console.log(` \\ ^__^`); + console.log(` \\ (oo)\\_______`); + console.log(` (__)\\ )\\/\\`); + console.log(` ||----w |`); + console.log(` || ||`); } cowsay(saying); - From 47f20949f8b9defca2bb01326f26672d7d52b3b6 Mon Sep 17 00:00:00 2001 From: Pretty Taruvinga Date: Tue, 21 Apr 2026 22:25:00 +0200 Subject: [PATCH 08/24] Add convertToNewRoman function for modern Roman numeral conversion --- .../roman-numerals/convert-to-new-roman.js | 28 ++++++++++++++++++- 1 file changed, 27 insertions(+), 1 deletion(-) diff --git a/challenges/unit-testing/katas-tdd/roman-numerals/convert-to-new-roman.js b/challenges/unit-testing/katas-tdd/roman-numerals/convert-to-new-roman.js index 0f2fe4b5..49dccbe0 100644 --- a/challenges/unit-testing/katas-tdd/roman-numerals/convert-to-new-roman.js +++ b/challenges/unit-testing/katas-tdd/roman-numerals/convert-to-new-roman.js @@ -1,3 +1,29 @@ -function convertToNewRoman(n) {} +function convertToNewRoman(n) { + const romanNumerals = [ + [1000, "M"], + [900, "CM"], + [500, "D"], + [400, "CD"], + [100, "C"], + [90, "XC"], + [50, "L"], + [40, "XL"], + [10, "X"], + [9, "IX"], + [5, "V"], + [4, "IV"], + [1, "I"], + ]; + let result = ""; + + for (let [value, symbol] of romanNumerals) { + while (n >= value) { + result += symbol; + n -= value; + } + } + + return result; +} module.exports = convertToNewRoman; From fb4cd7eb847276c97cab705136dbcb89619b183e Mon Sep 17 00:00:00 2001 From: Pretty Taruvinga Date: Tue, 21 Apr 2026 22:30:16 +0200 Subject: [PATCH 09/24] Add initial test for converting 1 to I --- .../katas-tdd/roman-numerals/convert-to-new-roman.test.js | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/challenges/unit-testing/katas-tdd/roman-numerals/convert-to-new-roman.test.js b/challenges/unit-testing/katas-tdd/roman-numerals/convert-to-new-roman.test.js index ae49f737..d7862a28 100644 --- a/challenges/unit-testing/katas-tdd/roman-numerals/convert-to-new-roman.test.js +++ b/challenges/unit-testing/katas-tdd/roman-numerals/convert-to-new-roman.test.js @@ -2,6 +2,11 @@ let convertToNewRoman = require("./convert-to-new-roman"); test("returns I if passed 1 as an argument", function () { // Arrange + const input = 1; + // Act + const result = convertToNewRoman(input); + // Assert + expect(result).toBe("I"); }); From 2689f1240634f74033cebd9c6370565d037f1c5a Mon Sep 17 00:00:00 2001 From: Pretty Taruvinga Date: Tue, 21 Apr 2026 22:32:33 +0200 Subject: [PATCH 10/24] Implement minimal convertToOldRoman function to pass first test --- .../katas-tdd/roman-numerals/convert-to-old-roman.js | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/challenges/unit-testing/katas-tdd/roman-numerals/convert-to-old-roman.js b/challenges/unit-testing/katas-tdd/roman-numerals/convert-to-old-roman.js index f7f0d06d..045e2f46 100644 --- a/challenges/unit-testing/katas-tdd/roman-numerals/convert-to-old-roman.js +++ b/challenges/unit-testing/katas-tdd/roman-numerals/convert-to-old-roman.js @@ -1,3 +1,5 @@ -function convertToOldRoman(n) {} +function convertToOldRoman(n) { + return "I"; +} module.exports = convertToOldRoman; From a2d2a049c463b66785161a6136d40d29caef96fe Mon Sep 17 00:00:00 2001 From: Pretty Taruvinga Date: Tue, 21 Apr 2026 22:34:40 +0200 Subject: [PATCH 11/24] Add initial test for converting 1 to old Roman numeral I --- .../katas-tdd/roman-numerals/convert-to-old-roman.test.js | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/challenges/unit-testing/katas-tdd/roman-numerals/convert-to-old-roman.test.js b/challenges/unit-testing/katas-tdd/roman-numerals/convert-to-old-roman.test.js index b9a43869..e7a02f34 100644 --- a/challenges/unit-testing/katas-tdd/roman-numerals/convert-to-old-roman.test.js +++ b/challenges/unit-testing/katas-tdd/roman-numerals/convert-to-old-roman.test.js @@ -2,6 +2,11 @@ let convertToOldRoman = require("./convert-to-old-roman"); test("returns I if passed 1 as an argument", function () { // Arrange + const input = 1; + // Act + const result = convertToOldRoman(input); + // Assert + expect(result).toBe("I"); }); From 003029fd3e2bb6ba67b6afcad0e860f4017dafe4 Mon Sep 17 00:00:00 2001 From: Pretty Taruvinga Date: Tue, 21 Apr 2026 22:38:23 +0200 Subject: [PATCH 12/24] Implement sales function to total car prices by make --- .../passing-tests/car-sales/car-sales.js | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) diff --git a/challenges/unit-testing/passing-tests/car-sales/car-sales.js b/challenges/unit-testing/passing-tests/car-sales/car-sales.js index e8bb8511..18d20e99 100644 --- a/challenges/unit-testing/passing-tests/car-sales/car-sales.js +++ b/challenges/unit-testing/passing-tests/car-sales/car-sales.js @@ -1,3 +1,15 @@ -function sales(carsSold) {} +function sales(carsSold) { + let totals = {}; + + for (let car of carsSold) { + if (totals[car.make]) { + totals[car.make] += car.price; + } else { + totals[car.make] = car.price; + } + } + + return totals; +} module.exports = sales; From 0b5add5f74528253e980087cdb5cbcc75cd6804c Mon Sep 17 00:00:00 2001 From: Pretty Taruvinga Date: Tue, 21 Apr 2026 22:40:08 +0200 Subject: [PATCH 13/24] Implement factorial function using loop --- .../unit-testing/passing-tests/factorial/factorial.js | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/challenges/unit-testing/passing-tests/factorial/factorial.js b/challenges/unit-testing/passing-tests/factorial/factorial.js index fefa4368..3e39dcfb 100644 --- a/challenges/unit-testing/passing-tests/factorial/factorial.js +++ b/challenges/unit-testing/passing-tests/factorial/factorial.js @@ -8,6 +8,14 @@ // calculate and return the factorial of int // note: factorial of 0 is 1 -function factorial(int) {} +function factorial(int) { + let result = 1; + + for (let i = 1; i <= int; i++) { + result *= i; + } + + return result; +} module.exports = factorial; From 9b628c525fcacd089455adac789a1accbbe18f44 Mon Sep 17 00:00:00 2001 From: Pretty Taruvinga Date: Tue, 21 Apr 2026 22:41:06 +0200 Subject: [PATCH 14/24] Implement factorial function using loop --- .../unit-testing/passing-tests/factorial/factorial.js | 10 ---------- 1 file changed, 10 deletions(-) diff --git a/challenges/unit-testing/passing-tests/factorial/factorial.js b/challenges/unit-testing/passing-tests/factorial/factorial.js index 3e39dcfb..c8e2ef59 100644 --- a/challenges/unit-testing/passing-tests/factorial/factorial.js +++ b/challenges/unit-testing/passing-tests/factorial/factorial.js @@ -1,13 +1,3 @@ -// int is an integer -// a factorial is the product of all non-negative integers -// less than or equal to the iniital number. - -// for example the factorial of 5 is 120 -// 120 = 1 * 2 * 3 * 4 * 5 - -// calculate and return the factorial of int -// note: factorial of 0 is 1 - function factorial(int) { let result = 1; From f902079af16a9ca52ea0cc4568e9d93e3d1fac81 Mon Sep 17 00:00:00 2001 From: Pretty Taruvinga Date: Tue, 21 Apr 2026 22:43:10 +0200 Subject: [PATCH 15/24] Implement average function excluding strings from calculation --- .../passing-tests/get-average/get-average.js | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) diff --git a/challenges/unit-testing/passing-tests/get-average/get-average.js b/challenges/unit-testing/passing-tests/get-average/get-average.js index b5588a57..ce20599e 100644 --- a/challenges/unit-testing/passing-tests/get-average/get-average.js +++ b/challenges/unit-testing/passing-tests/get-average/get-average.js @@ -2,6 +2,18 @@ // return the average of all the numbers // be sure to exclude the strings -function average(numbers) {} +function average(numbers) { + let sum = 0; + let count = 0; + + for (let item of numbers) { + if (typeof item === "number") { + sum += item; + count++; + } + } + + return sum / count; +} module.exports = average; From 4d7dceca38b0ebc39e28a321ab79eb6ec1469cf3 Mon Sep 17 00:00:00 2001 From: Pretty Taruvinga Date: Tue, 21 Apr 2026 22:45:40 +0200 Subject: [PATCH 16/24] Add test for largest number function and verify array is unchanged --- .../largest-number/largest-number.test.js | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/challenges/unit-testing/writing-tests/largest-number/largest-number.test.js b/challenges/unit-testing/writing-tests/largest-number/largest-number.test.js index ce674209..1768759a 100644 --- a/challenges/unit-testing/writing-tests/largest-number/largest-number.test.js +++ b/challenges/unit-testing/writing-tests/largest-number/largest-number.test.js @@ -2,12 +2,13 @@ let getLargestNumber = require("./largest-number"); test("returns largest number in array", function () { // Arrange + let input = [3, 21, 88, 4, 36]; + let original = [...input]; + // Act + let result = getLargestNumber(input); + // Assert + expect(result).toBe(88); + expect(input).toEqual(original); }); - -// example -// input: [3, 21, 88, 4, 36]; -// expected: 88; - -// also test that the original array hasn't changed From 09b94c5a30b14f52806888ee404bd990fb523395 Mon Sep 17 00:00:00 2001 From: Pretty Taruvinga Date: Tue, 21 Apr 2026 22:47:51 +0200 Subject: [PATCH 17/24] Add test for removing vowels from all words in array --- .../remove-vowels/remove-vowels-in-array.test.js | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/challenges/unit-testing/writing-tests/remove-vowels/remove-vowels-in-array.test.js b/challenges/unit-testing/writing-tests/remove-vowels/remove-vowels-in-array.test.js index ee739e22..3e59add8 100644 --- a/challenges/unit-testing/writing-tests/remove-vowels/remove-vowels-in-array.test.js +++ b/challenges/unit-testing/writing-tests/remove-vowels/remove-vowels-in-array.test.js @@ -2,10 +2,12 @@ let removeVowelsFromWords = require("./remove-vowels-in-array"); test("remove vowels from all words in array", function () { // Arrange + let input = ["Irina", "Etza", "Daniel"]; + let expected = ["rn", "tz", "Dnl"]; + // Act + let result = removeVowelsFromWords(input); + // Assert + expect(result).toEqual(expected); }); - -// example -// input: ["Irina", "Etza", "Daniel"] -// expected output: ["rn", "tz", "Dnl"] From 1ae0ec8c26349949cd416503677bb8e0f909711b Mon Sep 17 00:00:00 2001 From: Pretty Taruvinga Date: Tue, 21 Apr 2026 22:50:26 +0200 Subject: [PATCH 18/24] Implement removeVowels function to remove lowercase vowels from word --- .../writing-tests/remove-vowels/remove-vowels.js | 10 +--------- 1 file changed, 1 insertion(+), 9 deletions(-) diff --git a/challenges/unit-testing/writing-tests/remove-vowels/remove-vowels.js b/challenges/unit-testing/writing-tests/remove-vowels/remove-vowels.js index e5bb67ba..346ec953 100644 --- a/challenges/unit-testing/writing-tests/remove-vowels/remove-vowels.js +++ b/challenges/unit-testing/writing-tests/remove-vowels/remove-vowels.js @@ -18,12 +18,4 @@ function removeVowels(word) { return result.join(""); } -module.exports = removeVowels; - -/* - Let's trace this piece of code - what is the value of result with this input - - let result = removeVowels('samuel'); - - what is the value of result? -*/ +module.exports = removeVowels("samuel"); From c43aa614853dd7300cecedaace8d0eeddf50fca6 Mon Sep 17 00:00:00 2001 From: Pretty Taruvinga Date: Tue, 21 Apr 2026 23:51:25 +0200 Subject: [PATCH 19/24] Fix HTML validation errors and add language attribute" --- .../remove-vowels/remove-vowels-in-array.js | 5 ----- debugging/book-library/index.html | 11 ++++------- debugging/book-library/script.js | 8 ++++---- 3 files changed, 8 insertions(+), 16 deletions(-) diff --git a/challenges/unit-testing/writing-tests/remove-vowels/remove-vowels-in-array.js b/challenges/unit-testing/writing-tests/remove-vowels/remove-vowels-in-array.js index 6f4e06bf..f609e3d6 100644 --- a/challenges/unit-testing/writing-tests/remove-vowels/remove-vowels-in-array.js +++ b/challenges/unit-testing/writing-tests/remove-vowels/remove-vowels-in-array.js @@ -9,8 +9,3 @@ function removeVowelsFromWords(words) { } module.exports = removeVowelsFromWords; - -/* - input: ["Irina", "Etza", "Daniel"] - expected output: ["rn", "tz", "Dnl"] -*/ diff --git a/debugging/book-library/index.html b/debugging/book-library/index.html index 23acfa71..d7717eb3 100644 --- a/debugging/book-library/index.html +++ b/debugging/book-library/index.html @@ -1,12 +1,9 @@ - + - - + My Book Library + + diff --git a/debugging/book-library/script.js b/debugging/book-library/script.js index 018839be..c854eac4 100644 --- a/debugging/book-library/script.js +++ b/debugging/book-library/script.js @@ -31,11 +31,11 @@ function submit() { if (title.value == "" || author.value == "" || pages.value == "") { alert("Please fill all fields!"); return false; - - let book = new Book(title.value, author.value, pages.value, check.checked); - myLibrary.push(book); - render(); } + + let book = new Book(title.value, author.value, pages.value, check.checked); + myLibrary.push(book); + render(); } function Book(title, author, pages, check) { From 2c80a9bbfb49900e7084e2c84012df76e8c19dc1 Mon Sep 17 00:00:00 2001 From: Pretty Taruvinga Date: Wed, 22 Apr 2026 00:21:59 +0200 Subject: [PATCH 20/24] Clean up HTML validator issues" --- debugging/book-library/index.html | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/debugging/book-library/index.html b/debugging/book-library/index.html index d7717eb3..de831da7 100644 --- a/debugging/book-library/index.html +++ b/debugging/book-library/index.html @@ -28,7 +28,7 @@

Library

Library /> Date: Wed, 22 Apr 2026 00:33:37 +0200 Subject: [PATCH 21/24] Refactor book library code and address review feedback" --- debugging/book-library/script.js | 119 ++++++++++++++++--------------- 1 file changed, 60 insertions(+), 59 deletions(-) diff --git a/debugging/book-library/script.js b/debugging/book-library/script.js index c854eac4..c1a3cced 100644 --- a/debugging/book-library/script.js +++ b/debugging/book-library/script.js @@ -1,39 +1,43 @@ let myLibrary = []; -window.addEventListener("load", function (e) { +window.addEventListener("load", function () { populateStorage(); - render(); + render(); // only called once now }); function populateStorage() { - if (myLibrary.length == 0) { - let book1 = new Book("Robison Crusoe", "Daniel Defoe", "252", true); - let book2 = new Book( + if (myLibrary.length === 0) { + const book1 = new Book("Robison Crusoe", "Daniel Defoe", 252, true); + const book2 = new Book( "The Old Man and the Sea", "Ernest Hemingway", - "127", + 127, true ); - myLibrary.push(book1); - myLibrary.push(book2); - render(); + + myLibrary.push(book1, book2); + + // removed extra render() here } } -const title = document.getElementById("title"); -const author = document.getElementById("author"); -const pages = document.getElementById("pages"); -const check = document.getElementById("check"); +const titleInput = document.getElementById("title"); +const authorInput = document.getElementById("author"); +const pagesInput = document.getElementById("pages"); +const readCheckbox = document.getElementById("check"); -//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() { - if (title.value == "" || author.value == "" || pages.value == "") { - alert("Please fill all fields!"); - return false; + const title = titleInput.value.trim(); + const author = authorInput.value.trim(); + const pages = Number(pagesInput.value); + + if (!title || !author || !pages || pages <= 0) { + alert("Please fill all fields correctly!"); + return; } - let book = new Book(title.value, author.value, pages.value, check.checked); + const book = new Book(title, author, pages, readCheckbox.checked); + myLibrary.push(book); render(); } @@ -46,53 +50,50 @@ function Book(title, author, pages, check) { } 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"); + + // remove old rows (keep header row) + 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 == true) { - readStatus = "Yes"; - } else { - readStatus = "No"; - } - changeBut.innerText = readStatus; - - changeBut.addEventListener("click", function () { + + for (let i = 0; i < myLibrary.length; i++) { + const row = table.insertRow(1); + + const titleCell = row.insertCell(0); + const authorCell = row.insertCell(1); + const pagesCell = row.insertCell(2); + const wasReadCell = row.insertCell(3); + const deleteCell = row.insertCell(4); + + titleCell.textContent = myLibrary[i].title; + authorCell.textContent = myLibrary[i].author; + pagesCell.textContent = myLibrary[i].pages; + + const toggleButton = document.createElement("button"); + toggleButton.className = "btn btn-success"; + toggleButton.textContent = myLibrary[i].check ? "Yes" : "No"; + + toggleButton.addEventListener("click", function () { myLibrary[i].check = !myLibrary[i].check; render(); }); - //add delete button to every row and render again - let delButton = document.createElement("button"); - delButton.id = i + 5; - deleteCell.appendChild(delButton); - delButton.className = "btn btn-warning"; - delButton.innerHTML = "Delete"; - delButton.addEventListener("click", function () { - alert(`You've deleted title: ${myLibrary[i].title}`); + wasReadCell.appendChild(toggleButton); + + const deleteButton = document.createElement("button"); + deleteButton.className = "btn btn-warning"; + deleteButton.textContent = "Delete"; + + deleteButton.addEventListener("click", function () { + const deletedTitle = myLibrary[i].title; + myLibrary.splice(i, 1); render(); + + alert(`You've deleted title: ${deletedTitle}`); }); + + deleteCell.appendChild(deleteButton); } } From d0a6c0a68463b19a2d5b284a51b6c062ff69cb05 Mon Sep 17 00:00:00 2001 From: Pretty Taruvinga Date: Wed, 22 Apr 2026 00:46:53 +0200 Subject: [PATCH 22/24] Add readline prompt to interactive cowsay solution --- challenges/challenge-cowsay-two/solution2.js | 42 ++++++++------------ 1 file changed, 16 insertions(+), 26 deletions(-) diff --git a/challenges/challenge-cowsay-two/solution2.js b/challenges/challenge-cowsay-two/solution2.js index 669c79ba..6050f9e2 100644 --- a/challenges/challenge-cowsay-two/solution2.js +++ b/challenges/challenge-cowsay-two/solution2.js @@ -1,33 +1,23 @@ -// ================= -// Stripped down cowsayer CLI, -// no libraries or arguments -// https://nodejs.dev/learn/accept-input-from-the-command-line-in-nodejs -// ================= - -// 1. Make a command line interface. - -// 2. Make supplies for our speech bubble - -// 3. Make a cow that takes a string +const readline = require("readline"); +const rl = readline.createInterface({ + input: process.stdin, + output: process.stdout, +}); const cow = (saying) => { - let line = "_".repeat(saying.length + 2); - let bottom = "-".repeat(saying.length + 2); + let line = "_".repeat(saying.length + 2); + let bottom = "-".repeat(saying.length + 2); - console.log(` ${line} `); - console.log(`< ${saying} >`); - console.log(` ${bottom} `); - console.log(` \\ ^__^`); - console.log(` \\ (oo)\\_______`); - console.log(` (__)\\ )\\/\\`); - console.log(` ||----w |`); - console.log(` || ||`); - + console.log(` ${line} `); + console.log(`< ${saying} >`); + console.log(` ${bottom} `); + console.log(` \\ ^__^`); + console.log(` \\ (oo)\\_______`); + console.log(` (__)\\ )\\/\\`); + console.log(` ||----w |`); + console.log(` || ||`); }; -rl.question("What would you like the cow to say? ", function(answer) { +rl.question("What would you like the cow to say? ", function (answer) { cow(answer || "Mooooo"); rl.close(); }); - -// 4. Use readline to get a string from the terminal -// (with a prompt so it's clearer what we want) \ No newline at end of file From b67a1fe357f594fdcffadd3155b9eaf222f18da7 Mon Sep 17 00:00:00 2001 From: Pretty Taruvinga Date: Wed, 22 Apr 2026 00:56:02 +0200 Subject: [PATCH 23/24] Set up HTML structure for mini-weather app --- challenges/challenge-weather-app/index.html | 96 +++++++++++---------- 1 file changed, 50 insertions(+), 46 deletions(-) diff --git a/challenges/challenge-weather-app/index.html b/challenges/challenge-weather-app/index.html index b1add346..2815a717 100644 --- a/challenges/challenge-weather-app/index.html +++ b/challenges/challenge-weather-app/index.html @@ -1,49 +1,53 @@ - - - - - - - Meteoropolis - - - - - - -
-
-

- Meteor - opolis -

-
- -
- -
-

-

- - on - Unsplash -

-
- -
- -
- -
-
- - - - + + + + + + Meteoropolis + + + + + + +
+
+

+ Meteor + opolis +

+
+ +
+ +
+

+

+ + on + Unsplash +

+
+ +
+ +
+ +
+
+ + + From 4c83be7323cad1ca0ff1e76c26d39522476aeeac Mon Sep 17 00:00:00 2001 From: Pretty Taruvinga Date: Wed, 22 Apr 2026 00:58:03 +0200 Subject: [PATCH 24/24] Remove duplicate opacity declaration in thumbnail styles --- challenges/challenge-weather-app/assets/styles.css | 2 -- 1 file changed, 2 deletions(-) diff --git a/challenges/challenge-weather-app/assets/styles.css b/challenges/challenge-weather-app/assets/styles.css index 9046ba1b..14abf3d5 100644 --- a/challenges/challenge-weather-app/assets/styles.css +++ b/challenges/challenge-weather-app/assets/styles.css @@ -113,7 +113,6 @@ animation: 0.25s forwards fade-in; display: block; - opacity: 0; object-fit: cover; flex: 0 0 auto; @@ -125,7 +124,6 @@ background: rgba(0, 0, 0, 0.5); } - /* Credits ------------------------------------------------------------------------------*/ .info {