-
Notifications
You must be signed in to change notification settings - Fork 19
Hannah N #13
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Hannah N #13
Changes from all commits
7ba04fe
64a56f3
da0a961
a685ad7
561ac1c
fcc16ea
5c966d6
66392ed
1788255
82c6adf
b331165
373c6ab
f354c3d
2a28d43
eaf9663
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -156,3 +156,7 @@ dist | |
| vite.config.js.timestamp-* | ||
| vite.config.ts.timestamp-* | ||
|
|
||
| node_modules/ | ||
| package-lock.json | ||
| .env | ||
| .DS_store | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,7 @@ | ||
| { | ||
| "semi": true, | ||
| "singleQuote": true, | ||
| "tabWidth": 2, | ||
| "trailingComma": "es5", | ||
| "printWidth": 80 | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,24 @@ | ||
| { | ||
| "name": "c55-core-week-6", | ||
| "version": "1.0.0", | ||
| "description": "The week 6 assignment for the HackYourFuture Core program can be found at the following link: https://hub.hackyourfuture.nl/core-program-week-6-assignment", | ||
| "main": "index.js", | ||
| "scripts": { | ||
| "test": "echo \"Error: no test specified\" && exit 1" | ||
| }, | ||
| "repository": { | ||
| "type": "git", | ||
| "url": "git+https://github.com/hannahwn/c55-core-week-6.git" | ||
| }, | ||
| "keywords": [], | ||
| "author": "", | ||
| "license": "ISC", | ||
| "type": "commonjs", | ||
| "bugs": { | ||
| "url": "https://github.com/hannahwn/c55-core-week-6/issues" | ||
| }, | ||
| "homepage": "https://github.com/hannahwn/c55-core-week-6#readme", | ||
| "dependencies": { | ||
| "chalk": "^4.1.2" | ||
| } | ||
| } | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1 +1,51 @@ | ||
| [] | ||
| [ | ||
| { | ||
| "id": 1, | ||
| "title": "1984", | ||
| "author": "George Orwell", | ||
| "genre": "Fiction", | ||
| "read": false | ||
| }, | ||
| { | ||
| "id": 2, | ||
| "title": "The Havoc of Choice", | ||
| "author": "Wanjiru Koinange", | ||
| "genre": "African Literature", | ||
| "read": true | ||
| }, | ||
| { | ||
| "id": 3, | ||
| "title": "CreepShow", | ||
| "author": "Stephen King", | ||
| "genre": "Comic", | ||
| "read": false | ||
| }, | ||
| { | ||
| "id": 4, | ||
| "title": "Fire and Ice", | ||
| "author": "Erin Hunter", | ||
| "genre": "Fiction", | ||
| "read": true | ||
| }, | ||
| { | ||
| "id": 5, | ||
| "title": "Toxic Bachelors", | ||
| "author": "Daniella Steel", | ||
| "genre": "Adult", | ||
| "read": false | ||
| }, | ||
| { | ||
| "id": 6, | ||
| "title": "Foxes in a fix", | ||
| "author": "Bruce Cameron", | ||
| "genre": "Animals", | ||
| "read": true | ||
| }, | ||
| { | ||
| "id": 7, | ||
| "title": "The Luzhin Defense", | ||
| "author": "Vladimir Nabokov", | ||
| "genre": "Chess", | ||
| "read": true | ||
| } | ||
| ] |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,53 +1,241 @@ | ||
| // Place here the file operation functions for loading and saving books | ||
| const fs = require('fs'); | ||
| const chalk = require('chalk'); | ||
|
|
||
| const FILE_NAME = '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 content = fs.readFileSync('./books.json', 'utf8'); | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Better to check first if file exsts - If yes: then read file. Then check if read content is an array. If yes: continue. Else return empty array There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. fs.readFileSync('./books.json', 'utf8'); can use FILE_NAME too |
||
| const books = JSON.parse(content); | ||
|
|
||
| if (!Array.isArray(books)) { | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. good check... |
||
| console.log(chalk.yellow('Books data was not an array – starting fresh')); | ||
| return []; | ||
| } | ||
|
|
||
| return books; | ||
| } catch (error) { | ||
| if (error.code === 'ENOENT') { | ||
| console.log( | ||
| chalk.yellow('No books.json found. Starting with empty list.') | ||
| ); | ||
| return []; | ||
| } | ||
| if (error instanceof SyntaxError) { | ||
| console.log( | ||
| chalk.red( | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Nice to check for specific errors and inform the user |
||
| 'Invalid JSON in books.json – file is broken. Starting fresh!' | ||
| ) | ||
| ); | ||
| return []; | ||
| } | ||
| console.log(chalk.red('Error loading books:'), error.message); | ||
| return []; | ||
| } | ||
| } | ||
|
|
||
| function saveBooks(books) { | ||
| // TODO: Implement this function | ||
| // Write books array to books.json | ||
| // Use try-catch for error handling | ||
| try { | ||
| const data = JSON.stringify(books, null, 2); | ||
| fs.writeFileSync(FILE_NAME, data); | ||
| console.log(chalk.green('Saved :')); | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. console.log(chalk.green('Books saved')); With 'Saved :' it looks like something is missing |
||
| } catch (error) { | ||
| console.log(chalk.red('Save failed'), error.message); | ||
| } | ||
| } | ||
|
|
||
| function addBook(book) { | ||
| function addBook(books, titles, author, genre) { | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Typo: addBook(books, titles, author, genre) titles = title |
||
| // TODO: Implement this function | ||
| //Create new book | ||
| const newBook = { | ||
| id: books.length + 1, | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. this works if the id's reflect the book's index. If the id's don't match the index you may add a book with a duplicate ID: [{id:22}, {id:2}, {id: 1}] |
||
| title: title, | ||
| author: author, | ||
| genre: genre, | ||
| read: false, | ||
| }; | ||
|
|
||
| books.push(newBook); | ||
|
|
||
| saveBooks(books); | ||
|
|
||
| console.log(chalk.green(`✓ Added "${title}"`)); | ||
|
|
||
| return books; | ||
| } | ||
|
|
||
| function getUnreadBooks() { | ||
| function getUnreadBooks(books) { | ||
| // TODO: Implement this function using filter() | ||
| const unreadBooks = books.filter(function (book) { | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. don't use function expression here but anonymous function: books.filter(() => book.read === false) |
||
| return book.read === false; | ||
| }); | ||
|
|
||
| console.log(chalk.blue('\n--- UNREAD BOOKS ---')); | ||
| if (unreadBooks.length === 0) { | ||
| console.log(chalk.yellow('No unread books!')); | ||
| } else { | ||
| for (let i = 0; i < unreadBooks.length; i++) { | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. books.forEach(book => console.log( |
||
| const book = unreadBooks[i]; | ||
| console.log(`${book.id}. ${book.title} by ${book.author}`); | ||
| } | ||
| } | ||
|
|
||
| return unreadBooks; | ||
| } | ||
|
|
||
| function getBooksByGenre(genre) { | ||
| function getBooksByGenre(books, genre) { | ||
| // TODO: Implement this function using filter() | ||
|
|
||
| console.log('DEBUG → books type:', typeof books); | ||
| console.log('DEBUG → is array?:', Array.isArray(books)); | ||
| console.log( | ||
| 'DEBUG → books length:', | ||
| books?.length ?? 'N/A (books not array)' | ||
| ); | ||
|
|
||
| // Safe filter – prevents crash even if array has holes, undefined items, null, etc. | ||
| const genreBooks = books.filter( | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This is very elaborate and fits 'production code' but for a small app these checks are overkill. Anyway, if you want to do this it can be done easier like this: const genreBooks = books.filter( ? (optional chaining operator) does the same as book && |
||
| (book) => | ||
| book && | ||
| typeof book === 'object' && // exists & is object (not null/undefined) | ||
| typeof book.genre === 'string' && // genre exists and is actually a string | ||
| book.genre.toLowerCase() === genre.toLowerCase() | ||
| ); | ||
|
|
||
| console.log(chalk.blue(`\n--- ${genre} BOOKS ---`)); | ||
|
|
||
| if (genreBooks.length === 0) { | ||
| console.log(chalk.yellow(`No ${genre} books!`)); | ||
| } else { | ||
| for (let i = 0; i < genreBooks.length; i++) { | ||
| const book = genreBooks[i]; | ||
| const readStatus = book.read ? '✓' : '○'; | ||
| console.log(`${readStatus} ${book.id}. ${book.title} by ${book.author}`); | ||
| } | ||
| } | ||
|
|
||
| return genreBooks; | ||
| } | ||
|
|
||
| function markAsRead(id) { | ||
| function markAsRead(books, id) { | ||
| // TODO: Implement this function using map() | ||
| const updatedBooks = books.map(function (book) { | ||
| if (book.id === id) { | ||
| return { | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I saw this elsewhere: |
||
| id: book.id, | ||
| title: book.title, | ||
| author: book.author, | ||
| genre: book.genre, | ||
| read: true, | ||
| }; | ||
| } | ||
|
|
||
| return book; | ||
| }); | ||
|
|
||
| //Does book exist? | ||
|
|
||
| const oldBook = books.find(function (book) { | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. books.find(book => book.id === id) does the same because you don't use a function expression (function(book)...). Devs don't use function expressions in array methods |
||
| return book.id === id; | ||
| }); | ||
|
|
||
| if (!oldBook) { | ||
| console.log(chalk.red(`✗ Book #${id} not found!`)); | ||
| return books; | ||
| } | ||
|
|
||
| // Save changes | ||
| saveBooks(updatedBooks); | ||
| console.log(chalk.green(`✓ Marked "${oldBook.title}" as read!`)); | ||
|
|
||
| return updatedBooks; | ||
| } | ||
|
|
||
| function getTotalBooks() { | ||
| function getTotalBooks(books) { | ||
| // TODO: Implement this function using length | ||
| const total = books.length; | ||
| console.log(chalk.blue(`\nTotal books: ${total}`)); | ||
| return total; | ||
| } | ||
|
|
||
| function hasUnreadBooks() { | ||
| function hasUnreadBooks(books) { | ||
| // TODO: Implement this function using some() | ||
| const hasUnread = books.some(function (book) { | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. no function(book)... but (book) => |
||
| return book.read === false; | ||
| }); | ||
|
|
||
| if (hasUnread) { | ||
| console.log(chalk.yellow('You have books to read!')); | ||
| } else { | ||
| console.log(chalk.green('All books are read!')); | ||
| } | ||
|
|
||
| return hasUnread; | ||
| } | ||
|
|
||
| function printAllBooks() { | ||
| function printAllBooks(books) { | ||
| // TODO: Implement this function | ||
| // Loop through and display with chalk | ||
| // Use green for read books, yellow for unread | ||
| // Use cyan for titles | ||
| console.log(chalk.blue('\n--- ALL BOOKS ---')); | ||
|
|
||
| if (books.length === 0) { | ||
| console.log(chalk.yellow('No books yet!')); | ||
| return; | ||
| } | ||
|
|
||
| for (let i = 0; i < books.length; i++) { | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. books.forEach(book => {const status = book.read ? chalk.green('✓ Read') : chalk.red('○ Unread')) |
||
| const book = books[i]; | ||
| let status; | ||
| if (book.read) { | ||
| status = chalk.green('✓ Read'); | ||
| } else { | ||
| status = chalk.red('○ Unread'); | ||
| } | ||
| console.log( | ||
| `${book.id}.${chalk.cyan(book.title)} by ${book.author} - ${status}` | ||
| ); | ||
| } | ||
| } | ||
|
|
||
| function printSummary() { | ||
| function printSummary(books) { | ||
| // TODO: Implement this function | ||
| // Show statistics with chalk | ||
| // Display total books, read count, unread count | ||
| // Use bold for stats | ||
| } | ||
| console.log(chalk.blue('\n--- READING SUMMARY ---')); | ||
|
|
||
| // Total books | ||
| const total = books.length; | ||
| console.log(`Total: ${total}`); | ||
|
|
||
| // Count read books | ||
| let readCount = 0; | ||
| for (let i = 0; i < books.length; i++) { | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. const readCount = books.reduce((acc,book) => acc += book.read ? 1 : 0). |
||
| if (books[i].read) { | ||
| readCount++; | ||
| } | ||
| } | ||
| const unreadCount = total - readCount; | ||
|
|
||
| console.log(chalk.green(`Read: ${readCount}`)); | ||
| console.log(chalk.red(`Unread: ${unreadCount}`)); | ||
| } | ||
|
|
||
| module.exports = { | ||
| loadBooks, | ||
| saveBooks, | ||
| addBook, | ||
| getUnreadBooks, | ||
| getBooksByGenre, | ||
| markAsRead, | ||
| getTotalBooks, | ||
| hasUnreadBooks, | ||
| printAllBooks, | ||
| printSummary, | ||
| }; | ||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Very elaborate package,json file. Good attention to detail!