From 11e30f5fccbd7900ee868dc9fadf058fa334db78 Mon Sep 17 00:00:00 2001 From: Baba05206 Date: Thu, 6 Nov 2025 18:05:48 +0000 Subject: [PATCH 1/8] Add initial implementation of mean calculation and tests --- prep/mean.js | 37 +++++++++++++++++++++++++++++++++++++ prep/mean.test.js | 12 ++++++++++++ prep/package.json | 16 ++++++++++++++++ 3 files changed, 65 insertions(+) create mode 100644 prep/mean.js create mode 100644 prep/mean.test.js create mode 100644 prep/package.json diff --git a/prep/mean.js b/prep/mean.js new file mode 100644 index 000000000..c378b7b73 --- /dev/null +++ b/prep/mean.js @@ -0,0 +1,37 @@ +/* +Let’s consider a list of prices in a bill: +4.6, 5.03, 7.99, 8.01 +instead of writing the like below +const price0 = 4.6; +const price1 = 5.03; +const price2 = 7.99; +const price3 = 8.01; +We can write it as an array literal +const items = [4.6, 5.03, 7.99, 8.01]; + +The Array object, as with arrays in other programming languages, enables storing a collection +of multiple items under a single variable name, and has members for performing common array operations. +Arrays can store items of any type & multiple pieces of information. + +In JavaScript, we can use [] notation to access specific elements in the array using index numbers. +The index numbers start from 0. + + +const items = [4.6, 5.03, 7.99, 8.01]; +console.log(items[0]); // 4.6 +console.log(items[1]); // 5.03 +console.log(items[2]); // 7.99 +console.log(items[3]); // 8.01 +// Accessing elements using index numbers +*/ +const items = [4.6, 5.03, 7.99, 8.01]; +function calculateMean(list) { + // Calculate the sum of all elements in the array + const sum = list.reduce( + (accumulator, currentValue) => accumulator + currentValue, + 0 + ); + // Calculate the mean by dividing the sum by the number of elements + const mean = sum / list.length; + return mean; +} diff --git a/prep/mean.test.js b/prep/mean.test.js new file mode 100644 index 000000000..22b24b55c --- /dev/null +++ b/prep/mean.test.js @@ -0,0 +1,12 @@ +/* +test("does something as described below", () => { + // test implementation goes here +}); +*/ +test("calculates the mean of a list of numbers", () => { + const list = [3, 50, 7]; + const currentOutput = calculateMean(list); + const targetOutput = 20; + + expect(currentOutput).toEqual(targetOutput); // 20 is (3 + 50 + 7) / 3 +}); diff --git a/prep/package.json b/prep/package.json new file mode 100644 index 000000000..663b964da --- /dev/null +++ b/prep/package.json @@ -0,0 +1,16 @@ +{ + "name": "prep", + "version": "1.0.0", + "description": "", + "main": "index.js", + "scripts": { + "test": "jest" + }, + "keywords": [], + "author": "", + "license": "ISC", + "type": "commonjs", + "devDependencies": { + "jest": "^30.2.0" + } +} From 3cb29a05ca2867b60c8dd968537c74fe3abee781 Mon Sep 17 00:00:00 2001 From: Baba05206 Date: Fri, 7 Nov 2025 17:03:55 +0000 Subject: [PATCH 2/8] Refactor mean calculation and tests for clarity and functionality --- prep/mean.js | 24 +++++++++++++++++++++++- prep/mean.test.js | 14 ++++++++++++++ 2 files changed, 37 insertions(+), 1 deletion(-) diff --git a/prep/mean.js b/prep/mean.js index c378b7b73..2aec83fb7 100644 --- a/prep/mean.js +++ b/prep/mean.js @@ -23,7 +23,7 @@ console.log(items[1]); // 5.03 console.log(items[2]); // 7.99 console.log(items[3]); // 8.01 // Accessing elements using index numbers -*/ + const items = [4.6, 5.03, 7.99, 8.01]; function calculateMean(list) { // Calculate the sum of all elements in the array @@ -35,3 +35,25 @@ function calculateMean(list) { const mean = sum / list.length; return mean; } + */ +//const list = [4.6, 5.03, 7.99, 8.01]; +function calculateMean(list) { + //1. sum the elements of the array + let sum = 0; + for (let i = 0; i < list.length; i++) { + const arrayInValue = Number(list); + if (typeof list[i] === "number" && !isNaN(list[i])) { + sum += list[i]; + } + } + //2. determine the length of the array + let count = list.length; + //3. divide #1 by #2 + const mean = sum / count; + //4. return #3 + return mean; +} +console.log(calculateMean([4.6, 5.03, 7.99, 8.01])); +console.log(calculateMean([3, "50", 7])); + +//module.exports = calculateMean; diff --git a/prep/mean.test.js b/prep/mean.test.js index 22b24b55c..8b893a0b9 100644 --- a/prep/mean.test.js +++ b/prep/mean.test.js @@ -2,7 +2,19 @@ test("does something as described below", () => { // test implementation goes here }); + + */ +//mean.test.js +const mean = require("./mean"); // Import the mean function from mean.js +test("calculates the mean of a list of numbers", () => { + expect(mean([3, 50, 7])).toBe(20); // 20 is (3 + 50 + 7) / 3 + expect(mean([4.6, 5.03, 7.99, 8.01])).toBeCloseTo(6.4075); // 6.4075 is (4.6 + 5.03 + 7.99 + 8.01) / 4 + expect(mean([10, 20, 30, 40, 50])).toBe(30); // 30 is (10 + 20 + 30 + 40 + 50) / 5 + expect(mean([1, 2, 3, 4, 5, 6])).toBe(3.5); // 3.5 is (1 + 2 + 3 + 4 + 5 + 6) / 6 +}); +/* +The expect statement is used to create an assertion that checks if the output of the mean function matches the expected value. test("calculates the mean of a list of numbers", () => { const list = [3, 50, 7]; const currentOutput = calculateMean(list); @@ -10,3 +22,5 @@ test("calculates the mean of a list of numbers", () => { expect(currentOutput).toEqual(targetOutput); // 20 is (3 + 50 + 7) / 3 }); + +*/ From 3d4c4072900c18bbd170d1fa462ad408f75156dc Mon Sep 17 00:00:00 2001 From: Baba05206 Date: Tue, 18 Nov 2025 20:16:10 +0000 Subject: [PATCH 3/8] Update mean.js --- prep/mean.js | 21 +++++++++++++++++++++ 1 file changed, 21 insertions(+) diff --git a/prep/mean.js b/prep/mean.js index 2aec83fb7..f30eafb97 100644 --- a/prep/mean.js +++ b/prep/mean.js @@ -36,6 +36,7 @@ function calculateMean(list) { return mean; } */ +/* //const list = [4.6, 5.03, 7.99, 8.01]; function calculateMean(list) { //1. sum the elements of the array @@ -57,3 +58,23 @@ console.log(calculateMean([4.6, 5.03, 7.99, 8.01])); console.log(calculateMean([3, "50", 7])); //module.exports = calculateMean; +*/ +function calculateMean(list) { + //1. sum the elements of the array + let sum = 0; + for (const item of list) { + const value = Number(item); + if (!isNaN(value)) { + sum += value; + } + } + + //2. determine the length of the array + let count = list.length; + //3. divide #1 by #2 + const mean = sum / count; + //4. return #3 + return mean; +} +console.log(calculateMean([4.6, 5.03, 7.99, 8.01])); +console.log(calculateMean([3, "50", 7])); From 17dea8ed3d092b071473cbfa43917d52c59e4b2f Mon Sep 17 00:00:00 2001 From: Baba05206 Date: Sat, 29 Nov 2025 14:50:23 +0000 Subject: [PATCH 4/8] deleted prep --- prep/mean.js | 80 ----------------------------------------------- prep/mean.test.js | 26 --------------- prep/package.json | 16 ---------- 3 files changed, 122 deletions(-) delete mode 100644 prep/mean.js delete mode 100644 prep/mean.test.js delete mode 100644 prep/package.json diff --git a/prep/mean.js b/prep/mean.js deleted file mode 100644 index f30eafb97..000000000 --- a/prep/mean.js +++ /dev/null @@ -1,80 +0,0 @@ -/* -Let’s consider a list of prices in a bill: -4.6, 5.03, 7.99, 8.01 -instead of writing the like below -const price0 = 4.6; -const price1 = 5.03; -const price2 = 7.99; -const price3 = 8.01; -We can write it as an array literal -const items = [4.6, 5.03, 7.99, 8.01]; - -The Array object, as with arrays in other programming languages, enables storing a collection -of multiple items under a single variable name, and has members for performing common array operations. -Arrays can store items of any type & multiple pieces of information. - -In JavaScript, we can use [] notation to access specific elements in the array using index numbers. -The index numbers start from 0. - - -const items = [4.6, 5.03, 7.99, 8.01]; -console.log(items[0]); // 4.6 -console.log(items[1]); // 5.03 -console.log(items[2]); // 7.99 -console.log(items[3]); // 8.01 -// Accessing elements using index numbers - -const items = [4.6, 5.03, 7.99, 8.01]; -function calculateMean(list) { - // Calculate the sum of all elements in the array - const sum = list.reduce( - (accumulator, currentValue) => accumulator + currentValue, - 0 - ); - // Calculate the mean by dividing the sum by the number of elements - const mean = sum / list.length; - return mean; -} - */ -/* -//const list = [4.6, 5.03, 7.99, 8.01]; -function calculateMean(list) { - //1. sum the elements of the array - let sum = 0; - for (let i = 0; i < list.length; i++) { - const arrayInValue = Number(list); - if (typeof list[i] === "number" && !isNaN(list[i])) { - sum += list[i]; - } - } - //2. determine the length of the array - let count = list.length; - //3. divide #1 by #2 - const mean = sum / count; - //4. return #3 - return mean; -} -console.log(calculateMean([4.6, 5.03, 7.99, 8.01])); -console.log(calculateMean([3, "50", 7])); - -//module.exports = calculateMean; -*/ -function calculateMean(list) { - //1. sum the elements of the array - let sum = 0; - for (const item of list) { - const value = Number(item); - if (!isNaN(value)) { - sum += value; - } - } - - //2. determine the length of the array - let count = list.length; - //3. divide #1 by #2 - const mean = sum / count; - //4. return #3 - return mean; -} -console.log(calculateMean([4.6, 5.03, 7.99, 8.01])); -console.log(calculateMean([3, "50", 7])); diff --git a/prep/mean.test.js b/prep/mean.test.js deleted file mode 100644 index 8b893a0b9..000000000 --- a/prep/mean.test.js +++ /dev/null @@ -1,26 +0,0 @@ -/* -test("does something as described below", () => { - // test implementation goes here -}); - - -*/ -//mean.test.js -const mean = require("./mean"); // Import the mean function from mean.js -test("calculates the mean of a list of numbers", () => { - expect(mean([3, 50, 7])).toBe(20); // 20 is (3 + 50 + 7) / 3 - expect(mean([4.6, 5.03, 7.99, 8.01])).toBeCloseTo(6.4075); // 6.4075 is (4.6 + 5.03 + 7.99 + 8.01) / 4 - expect(mean([10, 20, 30, 40, 50])).toBe(30); // 30 is (10 + 20 + 30 + 40 + 50) / 5 - expect(mean([1, 2, 3, 4, 5, 6])).toBe(3.5); // 3.5 is (1 + 2 + 3 + 4 + 5 + 6) / 6 -}); -/* -The expect statement is used to create an assertion that checks if the output of the mean function matches the expected value. -test("calculates the mean of a list of numbers", () => { - const list = [3, 50, 7]; - const currentOutput = calculateMean(list); - const targetOutput = 20; - - expect(currentOutput).toEqual(targetOutput); // 20 is (3 + 50 + 7) / 3 -}); - -*/ diff --git a/prep/package.json b/prep/package.json deleted file mode 100644 index 663b964da..000000000 --- a/prep/package.json +++ /dev/null @@ -1,16 +0,0 @@ -{ - "name": "prep", - "version": "1.0.0", - "description": "", - "main": "index.js", - "scripts": { - "test": "jest" - }, - "keywords": [], - "author": "", - "license": "ISC", - "type": "commonjs", - "devDependencies": { - "jest": "^30.2.0" - } -} From d71a8424a685d061245d22900514fabb77cdc5d9 Mon Sep 17 00:00:00 2001 From: Baba05206 Date: Sun, 30 Nov 2025 21:10:52 +0000 Subject: [PATCH 5/8] Refactor reading list functionality and update styles for read/unread books --- Sprint-3/package.json | 4 ++-- Sprint-3/reading-list/index.html | 4 ++-- Sprint-3/reading-list/package.json | 7 +++++-- Sprint-3/reading-list/script.js | 25 +++++++++++++++++++++++++ Sprint-3/reading-list/script.test.js | 7 ++++--- Sprint-3/reading-list/style.css | 9 +++++++++ 6 files changed, 47 insertions(+), 9 deletions(-) diff --git a/Sprint-3/package.json b/Sprint-3/package.json index 711a5390f..722b1d55d 100644 --- a/Sprint-3/package.json +++ b/Sprint-3/package.json @@ -4,7 +4,7 @@ "license": "CC-BY-SA-4.0", "description": "", "scripts": { - "test": "jest", + "test": "jest --config=../jest.config.js reading-list", "format": "prettier --write ." }, "workspaces": [ @@ -26,7 +26,7 @@ "@testing-library/dom": "^10.4.0", "@testing-library/jest-dom": "^6.6.3", "@testing-library/user-event": "^14.6.1", - "jest": "^30.0.4", + "jest": "^30.2.0", "jest-environment-jsdom": "^30.0.4" } } diff --git a/Sprint-3/reading-list/index.html b/Sprint-3/reading-list/index.html index dbdb0f471..dc501edef 100644 --- a/Sprint-3/reading-list/index.html +++ b/Sprint-3/reading-list/index.html @@ -1,10 +1,10 @@ - + - Title here + Reading list app
diff --git a/Sprint-3/reading-list/package.json b/Sprint-3/reading-list/package.json index 96f540518..827682171 100644 --- a/Sprint-3/reading-list/package.json +++ b/Sprint-3/reading-list/package.json @@ -4,7 +4,7 @@ "license": "CC-BY-SA-4.0", "description": "You must update this package", "scripts": { - "test": "jest --config=../jest.config.js reading-list" + "test": "jest" }, "repository": { "type": "git", @@ -13,5 +13,8 @@ "bugs": { "url": "https://github.com/CodeYourFuture/CYF-Coursework-Template/issues" }, - "homepage": "https://github.com/CodeYourFuture/CYF-Coursework-Template#readme" + "homepage": "https://github.com/CodeYourFuture/CYF-Coursework-Template#readme", + "devDependencies": { + "@testing-library/jest-dom": "^6.9.1" + } } diff --git a/Sprint-3/reading-list/script.js b/Sprint-3/reading-list/script.js index 6024d73a0..d5ee33f8f 100644 --- a/Sprint-3/reading-list/script.js +++ b/Sprint-3/reading-list/script.js @@ -20,4 +20,29 @@ const books = [ bookCoverImage: "https://blackwells.co.uk/jacket/l/9780135957059.jpg", }, ]; +function readingList() { + const unorderedList = document.querySelector("#reading-list"); + for (const book of books) { + const newList = document.createElement("li"); + + const newImage = document.createElement("img"); + newImage.src = book.bookCoverImage; + + const paragraph = document.createElement("p"); + paragraph.textContent = `${book.title} by ${book.author}`; + + newList.append(paragraph, newImage); + + // Apply classes expected by the test + if (book.alreadyRead) { + newList.classList.add("read"); + } else { + newList.classList.add("notRead"); + } + + unorderedList.appendChild(newList); + } +} + +readingList(); diff --git a/Sprint-3/reading-list/script.test.js b/Sprint-3/reading-list/script.test.js index 39bdd921d..11e4d0503 100644 --- a/Sprint-3/reading-list/script.test.js +++ b/Sprint-3/reading-list/script.test.js @@ -1,3 +1,4 @@ +require("@testing-library/jest-dom"); const path = require("path"); const { JSDOM } = require("jsdom"); @@ -67,16 +68,16 @@ describe("Reading list", () => { const firstLi = page.window.document.querySelector( "#reading-list > :first-child" ); - expect(firstLi).toHaveStyle({ backgroundColor: "red" }); + expect(firstLi).toHaveClass("notRead"); const secondLi = page.window.document.querySelector( "#reading-list > :nth-child(2)" ); - expect(secondLi).toHaveStyle({ backgroundColor: "green" }); + expect(secondLi).toHaveClass("read"); const thirdLi = page.window.document.querySelector( "#reading-list > :nth-child(3)" ); - expect(thirdLi).toHaveStyle({ backgroundColor: "green" }); + expect(thirdLi).toHaveClass("read"); }); }); diff --git a/Sprint-3/reading-list/style.css b/Sprint-3/reading-list/style.css index 74406e64f..0aa4fc0d1 100644 --- a/Sprint-3/reading-list/style.css +++ b/Sprint-3/reading-list/style.css @@ -157,3 +157,12 @@ body { max-height: 80px; } } +.red { + background-color: red; +} +.read { + background-color: green; +} +.notRead { + background-color: red; +} From 2bbaaf3d70d0839f5d0af5d82472c49a5de026f1 Mon Sep 17 00:00:00 2001 From: Baba05206 Date: Sun, 30 Nov 2025 21:12:49 +0000 Subject: [PATCH 6/8] Remove unnecessary comment in readingList function --- Sprint-3/reading-list/script.js | 1 - 1 file changed, 1 deletion(-) diff --git a/Sprint-3/reading-list/script.js b/Sprint-3/reading-list/script.js index d5ee33f8f..eb5c0fa48 100644 --- a/Sprint-3/reading-list/script.js +++ b/Sprint-3/reading-list/script.js @@ -34,7 +34,6 @@ function readingList() { newList.append(paragraph, newImage); - // Apply classes expected by the test if (book.alreadyRead) { newList.classList.add("read"); } else { From e813e11d67e4c444aac679ea934389aa901f5ff0 Mon Sep 17 00:00:00 2001 From: Baba05206 Date: Mon, 8 Dec 2025 07:52:18 +0000 Subject: [PATCH 7/8] handled null or undefined book variable. returns helpful message --- Sprint-3/reading-list/script.js | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/Sprint-3/reading-list/script.js b/Sprint-3/reading-list/script.js index eb5c0fa48..5d11c2e15 100644 --- a/Sprint-3/reading-list/script.js +++ b/Sprint-3/reading-list/script.js @@ -23,6 +23,19 @@ const books = [ function readingList() { const unorderedList = document.querySelector("#reading-list"); + // Base condition: check if books array is empty + if (!books || books.length === 0) { + const emptyMessage = document.createElement("li"); + emptyMessage.textContent = + "No books in your reading list yet. Add some books to get started!"; + emptyMessage.style.listStyle = "none"; + emptyMessage.style.padding = "20px"; + emptyMessage.style.textAlign = "center"; + emptyMessage.style.color = "#666"; + unorderedList.appendChild(emptyMessage); + return; // Exit the function early + } + for (const book of books) { const newList = document.createElement("li"); From 038c26a741f8364cb8c8a400ee983e0de2cd00a3 Mon Sep 17 00:00:00 2001 From: Baba05206 Date: Mon, 8 Dec 2025 17:05:43 +0000 Subject: [PATCH 8/8] improved the look and feel of the reading-list page. modified contrast and color scheme. --- Sprint-3/reading-list/index.html | 11 +- Sprint-3/reading-list/script.js | 38 ++-- Sprint-3/reading-list/script.test.js | 142 +++++++-------- Sprint-3/reading-list/style.css | 253 ++++++++++++++------------- 4 files changed, 224 insertions(+), 220 deletions(-) diff --git a/Sprint-3/reading-list/index.html b/Sprint-3/reading-list/index.html index dc501edef..d1d016f3b 100644 --- a/Sprint-3/reading-list/index.html +++ b/Sprint-3/reading-list/index.html @@ -8,7 +8,16 @@
-
    +

    My Reading List

    +
    + + Already Read + + + To Read + +
    +
      diff --git a/Sprint-3/reading-list/script.js b/Sprint-3/reading-list/script.js index 5d11c2e15..7d201c3f5 100644 --- a/Sprint-3/reading-list/script.js +++ b/Sprint-3/reading-list/script.js @@ -20,40 +20,46 @@ const books = [ bookCoverImage: "https://blackwells.co.uk/jacket/l/9780135957059.jpg", }, ]; + function readingList() { - const unorderedList = document.querySelector("#reading-list"); + const orderedList = document.querySelector("#reading-list"); // Base condition: check if books array is empty if (!books || books.length === 0) { const emptyMessage = document.createElement("li"); + emptyMessage.className = "empty-message"; emptyMessage.textContent = "No books in your reading list yet. Add some books to get started!"; - emptyMessage.style.listStyle = "none"; - emptyMessage.style.padding = "20px"; - emptyMessage.style.textAlign = "center"; - emptyMessage.style.color = "#666"; - unorderedList.appendChild(emptyMessage); - return; // Exit the function early + orderedList.appendChild(emptyMessage); + return; } for (const book of books) { - const newList = document.createElement("li"); + const listItem = document.createElement("li"); - const newImage = document.createElement("img"); - newImage.src = book.bookCoverImage; + const bookImage = document.createElement("img"); + bookImage.src = book.bookCoverImage; + bookImage.alt = "Book cover for " + book.title; - const paragraph = document.createElement("p"); - paragraph.textContent = `${book.title} by ${book.author}`; + const bookInfo = document.createElement("p"); + bookInfo.textContent = book.title + " by " + book.author; - newList.append(paragraph, newImage); + const statusBadge = document.createElement("span"); + statusBadge.className = "status-badge"; if (book.alreadyRead) { - newList.classList.add("read"); + listItem.classList.add("read"); + statusBadge.textContent = "✓"; } else { - newList.classList.add("notRead"); + listItem.classList.add("notRead"); + statusBadge.textContent = "○"; } - unorderedList.appendChild(newList); + listItem.appendChild(bookImage); + listItem.appendChild(bookInfo); + listItem.appendChild(statusBadge); + + orderedList.appendChild(listItem); } } diff --git a/Sprint-3/reading-list/script.test.js b/Sprint-3/reading-list/script.test.js index 11e4d0503..cb2bb3357 100644 --- a/Sprint-3/reading-list/script.test.js +++ b/Sprint-3/reading-list/script.test.js @@ -1,83 +1,59 @@ -require("@testing-library/jest-dom"); -const path = require("path"); -const { JSDOM } = require("jsdom"); - -let page = null; - -beforeEach(async () => { - page = await JSDOM.fromFile(path.join(__dirname, "index.html"), { - resources: "usable", - runScripts: "dangerously", - }); - - // do this so students can use element.innerText which jsdom does not implement - Object.defineProperty(page.window.HTMLElement.prototype, "innerText", { - get() { - return this.textContent; - }, - set(value) { - this.textContent = value; - }, - }); - - return new Promise((res) => { - page.window.document.addEventListener("load", res); - }); -}); - -afterEach(() => { - page = null; -}); - -describe("Reading list", () => { - test("renders a list of books with author and title", () => { - const readingList = page.window.document.querySelector("#reading-list"); - - expect(readingList).toHaveTextContent("The Design of Everyday Things"); - expect(readingList).toHaveTextContent("Don Norman"); - - expect(readingList).toHaveTextContent("The Most Human Human"); - expect(readingList).toHaveTextContent("Brian Christian"); - - expect(readingList).toHaveTextContent("The Pragmatic Programmer"); - expect(readingList).toHaveTextContent("Andrew Hunt"); - }); - test("each book in the list has an image", () => { - const firstLi = page.window.document.querySelector( - "#reading-list > :first-child" - ); - expect(firstLi).toContainHTML( - `` - ); - - const secondLi = page.window.document.querySelector( - "#reading-list > :nth-child(2)" - ); - expect(secondLi).toContainHTML( - `` - ); - - const thirdLi = page.window.document.querySelector( - "#reading-list > :nth-child(3)" - ); - expect(thirdLi).toContainHTML( - `` - ); - }); - test("background color changes depending on whether book has been read", () => { - const firstLi = page.window.document.querySelector( - "#reading-list > :first-child" - ); - expect(firstLi).toHaveClass("notRead"); - - const secondLi = page.window.document.querySelector( - "#reading-list > :nth-child(2)" - ); - expect(secondLi).toHaveClass("read"); - - const thirdLi = page.window.document.querySelector( - "#reading-list > :nth-child(3)" - ); - expect(thirdLi).toHaveClass("read"); - }); -}); +// for the tests, do not modify this array of books +const books = [ + { + title: "The Design of Everyday Things", + author: "Don Norman", + alreadyRead: false, + bookCoverImage: "https://blackwells.co.uk/jacket/l/9780465050659.jpg", + }, + { + title: "The Most Human Human", + author: "Brian Christian", + alreadyRead: true, + bookCoverImage: + "https://images-na.ssl-images-amazon.com/images/I/41m1rQjm5tL._SX322_BO1,204,203,200_.jpg", + }, + { + title: "The Pragmatic Programmer", + author: "Andrew Hunt", + alreadyRead: true, + bookCoverImage: "https://blackwells.co.uk/jacket/l/9780135957059.jpg", + }, +]; + +function readingList() { + const orderedList = document.querySelector("#reading-list"); + + // Base condition: check if books array is empty + if (!books || books.length === 0) { + const emptyMessage = document.createElement("li"); + emptyMessage.className = "empty-message"; + emptyMessage.textContent = + "No books in your reading list yet. Add some books to get started!"; + orderedList.appendChild(emptyMessage); + return; + } + + for (const book of books) { + const listItem = document.createElement("li"); + + const bookImage = document.createElement("img"); + bookImage.src = book.bookCoverImage; + bookImage.alt = `Cover of ${book.title}`; + + const bookInfo = document.createElement("p"); + bookInfo.textContent = `${book.title} by ${book.author}`; + + listItem.append(bookImage, bookInfo); + + if (book.alreadyRead) { + listItem.classList.add("read"); + } else { + listItem.classList.add("notRead"); + } + + orderedList.appendChild(listItem); + } +} + +readingList(); diff --git a/Sprint-3/reading-list/style.css b/Sprint-3/reading-list/style.css index 0aa4fc0d1..ff0f344cc 100644 --- a/Sprint-3/reading-list/style.css +++ b/Sprint-3/reading-list/style.css @@ -1,168 +1,181 @@ /** - * Base styles to use at the start of the class - * - * Module: HTML/CSS - * Lesson: 1,2 - * Class: Scotland 2017 + * Reading List App Styles - Intermediate Level */ -html, -body { - font-family: "Source Sans Pro", -apple-system, system-ui, BlinkMacSystemFont, - "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif; +/* Reset default browser styles */ +* { + margin: 0; + padding: 0; + box-sizing: border-box; } -.site-footer { - margin-top: 4em; +body { + font-family: Arial, sans-serif; + background-color: #f0f0f0; + padding: 20px; } -.site-footer p { - border-top: 1px solid #dccdc6; - padding-top: 2em; - padding-bottom: 2em; +/* Main container */ +#content { + max-width: 800px; + margin: 0 auto; + background-color: white; + border-radius: 8px; + padding: 30px; + box-shadow: 0 2px 10px rgba(0, 0, 0, 0.1); } -.navbar-brand > img { - max-height: 40px; - width: auto; +/* Page heading */ +h1 { + text-align: center; + color: #333; + margin-bottom: 20px; + font-size: 28px; } -.navbar-light .navbar-nav .nav-link { - color: #292b2c; - font-weight: 600; - text-transform: uppercase; +/* Legend section */ +.legend { + text-align: center; + margin-bottom: 25px; + padding-bottom: 15px; + border-bottom: 2px solid #ddd; } -/* Buttons */ -.btn { - border-radius: 0.15em; +.legend-item { + display: inline-block; + margin: 0 15px; + font-size: 14px; + color: #666; } -/* Alert */ -.alert { - position: relative; - margin-top: 2em; - margin-bottom: 3em; - padding-top: 1.5em; - padding-bottom: 1.5em; - border: 1px solid #dccdc6; - border-radius: 0; - font-size: 0.85rem; - line-height: 1.3em; - background: transparent; - color: #292b2c; +.legend-badge { + display: inline-block; + width: 22px; + height: 22px; + border-radius: 50%; + text-align: center; + line-height: 20px; + font-weight: bold; + margin-right: 5px; } -.alert:before { - content: ""; - position: absolute; - left: -1px; - top: 0; - height: 100%; - width: 1px; - background: #ce5f31; +.read-badge { + background-color: #d4edda; + color: #155724; + border: 2px solid #28a745; } -/* Jumbotron */ -.jumbotron { - border-radius: 0; +.unread-badge { + background-color: #fff3cd; + color: #856404; + border: 2px solid #ffc107; } -/* Headings */ -.heading-underline { - position: relative; - margin-bottom: 2em; - padding-bottom: 0.5em; - border-bottom: 1px solid #dccdc6; - font-size: 1rem; - font-weight: 600; - text-transform: uppercase; +/* Ordered list */ +#reading-list { + list-style: decimal; + padding-left: 0; } -.heading-underline:before { - content: ""; - position: absolute; - bottom: -1px; - left: 0; - width: 25%; - height: 1px; - max-width: 100px; - background: #ce5f31; +#reading-list li { + display: flex; + align-items: center; + padding: 15px; + margin-bottom: 15px; + border-radius: 6px; + background-color: #f8f9fa; + border-left: 4px solid #ddd; } -/* Article */ -.article { - margin-bottom: 2em; +/* Book cover image */ +#reading-list li img { + width: 60px; + height: 90px; + border-radius: 4px; + margin-right: 15px; + box-shadow: 0 2px 5px rgba(0, 0, 0, 0.1); } -.article-title { - margin-bottom: 0.5em; - font-weight: 700; +/* Book information text */ +#reading-list li p { + flex: 1; + font-size: 16px; + color: #333; + margin: 0; } -.article-read-more a { - font-size: 0.85em; - font-weight: 700; - text-decoration: uppercase; +/* Status indicator */ +.status-badge { + width: 28px; + height: 28px; + border-radius: 50%; + text-align: center; + line-height: 24px; + font-weight: bold; + font-size: 16px; + margin-left: 15px; } -.article-read-more a:hover, -.article-read-more a:focus { - text-decoration: none; +/* Read books styling */ +#reading-list li.read { + background-color: #e8f5e9; + border-left-color: #28a745; } -.article-read-more .fa { - margin-right: 0.5em; - color: #ce5f31; +#reading-list li.read .status-badge { + background-color: #d4edda; + color: #155724; + border: 2px solid #28a745; } -.article-read-more:last-child { - margin-bottom: 0; +/* Unread books styling */ +#reading-list li.notRead { + background-color: #fff8e1; + border-left-color: #ffc107; } -.red { - background-color: red; +#reading-list li.notRead .status-badge { + background-color: #fff3cd; + color: #856404; + border: 2px solid #ffc107; } -.addArticle { - margin-bottom: 10px; +/* Empty state message */ +.empty-message { + text-align: center; + padding: 40px 20px; + background-color: #f8f9fa; + border: 2px dashed #ccc; + color: #666; + font-style: italic; + list-style: none; } -#addArticleBtn { - margin-left: 20px; - height: 37px; -} +/* Mobile responsive */ +@media screen and (max-width: 600px) { + body { + padding: 10px; + } -.colorButton { - margin-bottom: 20px; - margin-right: 20px; - width: 100px; - height: 50px; -} + #content { + padding: 20px; + } -#blueBtn { - background: #588fbd; -} + h1 { + font-size: 24px; + } -#orangeBtn { - background: #f0ad4e; -} + .legend-item { + display: block; + margin: 5px 0; + } -#greenBtn { - background: #87ca8a; -} + #reading-list li img { + width: 50px; + height: 75px; + } -@media screen and (min-width: 992px) { - .navbar-brand > img { - max-height: 80px; + #reading-list li p { + font-size: 14px; } } -.red { - background-color: red; -} -.read { - background-color: green; -} -.notRead { - background-color: red; -}