diff --git a/reading-list-manager/app.js b/reading-list-manager/app.js index b0365ef..2fb225b 100644 --- a/reading-list-manager/app.js +++ b/reading-list-manager/app.js @@ -1,13 +1,42 @@ -// This is the entrypoint for your application. -// node app.js +const chalk = require("chalk"); +const { + printAllBooks, + printSummary, + getUnreadBooks, + getBooksByGenre, + addBook, + markAsRead, +} = require("./readingList"); +const command = process.argv[2]; -// TODO: Implement the main application logic here -// 1. Load books on startup -// 2. Display all books -// 3. Show summary statistics -// 4. Add example of filtering by genre or read/unread status -// 5. Add example of marking a book as read +printAllBooks(); +printSummary(); -console.log('šŸ“š MY READING LIST šŸ“š\n'); +// Example: filter unread +const unread = getUnreadBooks(); +console.log("\nUnread Books:"); +unread.forEach((book) => console.log(`${book.id}. ${book.title}`)); -// Your implementation here +// Example: filter by genre +const fiction = getBooksByGenre("Fiction"); +console.log("\nFiction Books:"); +fiction.forEach((book) => console.log(`${book.id}. ${book.title}`)); + +// Example: add new book +if (command === "add") { + const title = process.argv[3]; + const author = process.argv[4]; + const genre = process.argv[5]; + addBook({ + title: "Nudge", + author: "Richard Thaler", + genre: "Pyschology", + }); +} + +// Example: mark a book as read +markAsRead(2); + +console.log("\nRead books:"); +printAllBooks(); +printSummary(); diff --git a/reading-list-manager/books.json b/reading-list-manager/books.json index 0637a08..0e922df 100644 --- a/reading-list-manager/books.json +++ b/reading-list-manager/books.json @@ -1 +1,37 @@ -[] \ No newline at end of file +[ + { + "id": 1, + "title": "1984", + "author": "George Orwell", + "genre": "Fiction", + "read": true + }, + { + "id": 2, + "title": "Dune", + "author": "Frank Herbert", + "genre": "Sci-Fi", + "read": true + }, + { + "id": 3, + "title": "The Hobbit", + "author": "J.R.R. Tolkien", + "genre": "Fantasy", + "read": false + }, + { + "id": 4, + "title": "Think Like a Programmer", + "author": "V. Anton Spraul", + "genre": "Programming", + "read": true + }, + { + "id": 5, + "title": "Animal Farm", + "author": "George Orwell", + "genre": "Fiction", + "read": true + } +] diff --git a/reading-list-manager/readingList.js b/reading-list-manager/readingList.js index 84febab..c39b87d 100644 --- a/reading-list-manager/readingList.js +++ b/reading-list-manager/readingList.js @@ -1,53 +1,167 @@ -// Place here the file operation functions for loading and saving books +const fs = require("fs"); +const chalk = require("chalk"); + +const FILE = "books.json"; function loadBooks() { - // TODO: Implement this function - // Read from books.json - // Handle missing file (create empty array) - // Handle invalid JSON (notify user, use empty array) - // Use try-catch for error handling + try { + const text = fs.readFileSync(FILE, "utf8"); + const books = JSON.parse(text); + if (!Array.isArray(books)) { + console.log(chalk.yellow("Error: books.json is not an array.")); + return []; + } + return books; + } catch (error) { + if (error.code === "ENOENT") { + fs.writeFileSync(FILE, "[]\n", "utf8"); + return []; + } + if (error.name === "SyntaxError") { + console.log(chalk.yellow("Invalid books.json.")); + return []; + } + throw error; + } } function saveBooks(books) { - // TODO: Implement this function - // Write books array to books.json - // Use try-catch for error handling + try { + fs.writeFileSync(FILE, JSON.stringify(books, null, 2) + "\n", "utf8"); + } catch (error) { + console.log(chalk.red("Error: Could not save books.json")); + throw error; + } } function addBook(book) { - // TODO: Implement this function + const books = loadBooks(); + let maxId = 0; + books.forEach((book) => { + if (typeof book.id === "number" && book.id > maxId) maxId = book.id; + }); + const newBook = { + id: maxId + 1, + title: book.title, + author: book.author, + genre: book.genre, + read: false, + }; + books.push(newBook); + saveBooks(books); + return newBook; } function getUnreadBooks() { - // TODO: Implement this function using filter() + const books = loadBooks(); + return books.filter((book) => book.read === false); } function getBooksByGenre(genre) { - // TODO: Implement this function using filter() + const books = loadBooks(); + const genreLowCase = String(genre).toLowerCase(); + return books.filter( + (book) => String(book.genre).toLowerCase() === genreLowCase, + ); } function markAsRead(id) { - // TODO: Implement this function using map() + const books = loadBooks(); + const targetId = Number(id); + let found = false; + const updated = books.map((book) => { + if (Number(book.id) === targetId) { + found = true; + return { ...book, read: true }; + } + return book; + }); + if (found) saveBooks(updated); + return found; } function getTotalBooks() { - // TODO: Implement this function using length + return loadBooks().length; } function hasUnreadBooks() { - // TODO: Implement this function using some() + return loadBooks().some((book) => book.read === false); +} + +function printAllBooks() { + const books = loadBooks(); + console.log("\nAll Books:"); + books.forEach((book) => { + const color = book.read ? chalk.green : chalk.yellow; + const status = book.read ? "READ" : "UNREAD"; + console.log( + color(`${book.id}. `) + + chalk.cyan(book.title) + + color(` by ${book.author} (${book.genre}) ${status}`), + ); + }); +} + +function printSummary() { + const books = loadBooks(); + const total = books.length; + const readCount = books.filter((book) => book.read === true).length; + const unreadCount = total - readCount; + console.log(chalk.bold("\nšŸ“Š SUMMARY šŸ“Š")); + console.log(chalk.bold(`Total Books: ${total}`)); + console.log(chalk.bold(`Read: ${readCount}`)); + console.log(chalk.bold(`Unread: ${unreadCount}`)); } +module.exports = { + loadBooks, + saveBooks, + addBook, + getUnreadBooks, + getBooksByGenre, + markAsRead, + getTotalBooks, + hasUnreadBooks, + printAllBooks, + printSummary, +}; function printAllBooks() { - // TODO: Implement this function - // Loop through and display with chalk - // Use green for read books, yellow for unread - // Use cyan for titles + const books = loadBooks(); + + console.log("\nAll Books:"); + books.forEach((b) => { + const color = b.read ? chalk.green : chalk.yellow; + const status = b.read ? "āœ“ Read" : "⚠ Unread"; + + console.log( + color(`${b.id}. `) + + chalk.cyan(b.title) + + color(` by ${b.author} (${b.genre}) ${status}`), + ); + }); } function printSummary() { - // TODO: Implement this function - // Show statistics with chalk - // Display total books, read count, unread count - // Use bold for stats -} \ No newline at end of file + const books = loadBooks(); + const total = books.length; + const readCount = books.filter((b) => b.read === true).length; + const unreadCount = total - readCount; + + console.log(chalk.bold("\nšŸ“Š SUMMARY šŸ“Š")); + console.log(chalk.bold(`Total Books: ${total}`)); + console.log(chalk.bold(`Read: ${readCount}`)); + console.log(chalk.bold(`Unread: ${unreadCount}`)); +} + +module.exports = { + loadBooks, + saveBooks, + addBook, + getUnreadBooks, + getBooksByGenre, + markAsRead, + getTotalBooks, + hasUnreadBooks, + printAllBooks, + printSummary, +};