diff --git a/reading-list-manager/.gitignore b/reading-list-manager/.gitignore new file mode 100644 index 0000000..40b878d --- /dev/null +++ b/reading-list-manager/.gitignore @@ -0,0 +1 @@ +node_modules/ \ No newline at end of file diff --git a/reading-list-manager/.prettierrc b/reading-list-manager/.prettierrc new file mode 100644 index 0000000..ef485de --- /dev/null +++ b/reading-list-manager/.prettierrc @@ -0,0 +1,4 @@ +{ + "semi": true, + "singleQuote": false +} diff --git a/reading-list-manager/app.js b/reading-list-manager/app.js index b0365ef..0610ba3 100644 --- a/reading-list-manager/app.js +++ b/reading-list-manager/app.js @@ -1,13 +1,26 @@ -// This is the entrypoint for your application. -// node app.js +import { + loadBooks, + saveBooks, + addBook, + getUnreadBooks, + getBooksByGenre, + markAsRead, + getTotalBooks, + hasUnreadBooks, + printAllBooks, + printSummary, +} from "./readingList.js"; -// 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 +const newBook = { + id: 6, + title: "Clean Code", + author: "Robert C. Martin", + genre: "Software Development", + read: false, +}; -console.log('📚 MY READING LIST 📚\n'); +addBook(newBook); -// Your implementation here +printAllBooks(); +console.log("\n"); +printSummary(); diff --git a/reading-list-manager/books.json b/reading-list-manager/books.json index 0637a08..b4006dd 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": "Dystopian Fiction", + "read": false + }, + { + "id": 2, + "title": "The Diary of a Young Girl", + "author": "Anne Frank", + "genre": "Autobiography", + "read": true + }, + { + "id": 3, + "title": "The Great Gatsby", + "author": "F. Scott Fitzgerald", + "genre": "Classic Literature", + "read": false + }, + { + "id": 4, + "title": "Atomic Habits", + "author": "James Clear", + "genre": "Self-Help", + "read": true + }, + { + "id": 5, + "title": "The Hitchhiker's Guide to the Galaxy", + "author": "Douglas Adams", + "genre": "Science Fiction", + "read": false + } +] diff --git a/reading-list-manager/package-lock.json b/reading-list-manager/package-lock.json new file mode 100644 index 0000000..2e6e410 --- /dev/null +++ b/reading-list-manager/package-lock.json @@ -0,0 +1,28 @@ +{ + "name": "reading-list-manager", + "version": "1.0.0", + "lockfileVersion": 3, + "requires": true, + "packages": { + "": { + "name": "reading-list-manager", + "version": "1.0.0", + "license": "ISC", + "dependencies": { + "chalk": "^5.6.2" + } + }, + "node_modules/chalk": { + "version": "5.6.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-5.6.2.tgz", + "integrity": "sha512-7NzBL0rN6fMUW+f7A6Io4h40qQlG+xGmtMxfbnH/K7TAtt8JQWVQK+6g0UXKMeVJoyV5EkkNsErQ8pVD3bLHbA==", + "license": "MIT", + "engines": { + "node": "^12.17.0 || ^14.13 || >=16.0.0" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" + } + } + } +} diff --git a/reading-list-manager/package.json b/reading-list-manager/package.json new file mode 100644 index 0000000..66d4359 --- /dev/null +++ b/reading-list-manager/package.json @@ -0,0 +1,17 @@ +{ + "name": "reading-list-manager", + "version": "1.0.0", + "description": "", + "main": "app.js", + "scripts": { + "start": "node ./app.js", + "test": "echo \"Error: no test specified\" && exit 1" + }, + "keywords": [], + "author": "", + "license": "ISC", + "type": "module", + "dependencies": { + "chalk": "^5.6.2" + } +} diff --git a/reading-list-manager/readingList.js b/reading-list-manager/readingList.js index 84febab..f09cec2 100644 --- a/reading-list-manager/readingList.js +++ b/reading-list-manager/readingList.js @@ -1,53 +1,122 @@ +import chalk from "chalk"; +import fs from "node:fs"; + // Place here the file operation functions for loading and saving books -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 +export function loadBooks() { + try { + const jsonString = fs.readFileSync("books.json", "utf8"); + const books = JSON.parse(jsonString); + return books; + } catch (error) { + if (error.code === "ENOENT") { + const books = []; + return books; + } else if (error.name === "SyntaxError") { + console.log("invalid JSON"); + const books = []; + return books; + } + } } -function saveBooks(books) { - // TODO: Implement this function - // Write books array to books.json - // Use try-catch for error handling +export function saveBooks(books) { + try { + fs.writeFileSync("books.json", JSON.stringify(books, null, 2)); + } catch (error) { + if (error.code === "ENOENT") { + console.log("File not exist"); + } else if (error.name === "SyntaxError") { + console.log("invalid JSON"); + } + } + return true; } -function addBook(book) { - // TODO: Implement this function +export function addBook(book) { + const books = loadBooks(); + if (!book.id) { + book.id = books.length + 1; + } + books.push(book); + + if (saveBooks(books)) { + return true; + } + return false; } -function getUnreadBooks() { - // TODO: Implement this function using filter() +export function getUnreadBooks() { + const books = loadBooks(); + const unreadBooks = books.filter((book) => book.read === false); + + return unreadBooks; } -function getBooksByGenre(genre) { - // TODO: Implement this function using filter() +export function getReadBooks() { + const books = loadBooks(); + const readBooks = books.filter((book) => book.read === true); + + return readBooks; } -function markAsRead(id) { - // TODO: Implement this function using map() +export function getBooksByGenre(genre) { + const books = loadBooks(); + const booksByGenre = books.filter((book) => book.genre === genre); + + return booksByGenre; } -function getTotalBooks() { - // TODO: Implement this function using length +export function markAsRead(id) { + const books = loadBooks(); + const updateBooks = books.map(function (book) { + if (book.id === id) { + book.read = true; + } + return { ...book }; + }); + + if (saveBooks(updateBooks)) { + return true; + } + return false; } -function hasUnreadBooks() { - // TODO: Implement this function using some() +export function getTotalBooks() { + const books = loadBooks(); + return books.length; } -function printAllBooks() { - // TODO: Implement this function - // Loop through and display with chalk - // Use green for read books, yellow for unread - // Use cyan for titles +export function hasUnreadBooks() { + const Books = loadBooks(); + const unreadBooks = Books.some((book) => book.read === false); + + return unreadBooks; } -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 +export function printAllBooks() { + console.log(chalk.bold("📚 MY READING LIST 📚")); + const books = loadBooks(); + for (const book of books) { + const { id, title, author, genre, read } = book; + + let readStatus = null; + if (read === true) { + readStatus = chalk.green(`✓ Read`); + } else { + readStatus = chalk.yellow(`⚠ Unread`); + } + + console.log( + `${id}. ${chalk.cyan(title)} by ${author} (${genre}) ${readStatus}`, + ); + } +} + +export function printSummary() { + console.log(chalk.bold("📊 SUMMARY 📊")); + + console.log(chalk.bold(`Total Books: ${loadBooks().length}`)); + console.log(chalk.green.bold(`Read: ${getReadBooks().length}`)); + console.log(chalk.yellow.bold(`Unread: ${getUnreadBooks().length}`)); +}