diff --git a/.idea/.gitignore b/.idea/.gitignore new file mode 100644 index 0000000..13566b8 --- /dev/null +++ b/.idea/.gitignore @@ -0,0 +1,8 @@ +# Default ignored files +/shelf/ +/workspace.xml +# Editor-based HTTP Client requests +/httpRequests/ +# Datasource local storage ignored files +/dataSources/ +/dataSources.local.xml diff --git a/.idea/vcs.xml b/.idea/vcs.xml new file mode 100644 index 0000000..d843f34 --- /dev/null +++ b/.idea/vcs.xml @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/library-ui/src/components/libclient.tsx b/library-ui/src/components/libclient.tsx index 7a5702a..f203c71 100644 --- a/library-ui/src/components/libclient.tsx +++ b/library-ui/src/components/libclient.tsx @@ -37,10 +37,15 @@ export default function LibClient() { showDtls = true; } if (contentType === 'book_dtls') { - const copies = res.data.copies; - res.data = copies.map((copy: { imprint: string, status: string }) => { - return copy.imprint + ' | ' + copy.status; + const { title, author, bookInstances } = res.data; + // Display book title and author at the top + const headerInfo = [`Title: ${title}`, `Author: ${author}`]; + // Map book instances to display format + const instancesInfo = bookInstances.map((instance: { imprint: string, status: string }) => { + return `Copy: ${instance.imprint} | Status: ${instance.status}`; }); + // Combine header and instances information + res.data = [...headerInfo, ...instancesInfo]; } setContent({ data: res.data, dtls: showDtls }); }); diff --git a/models/book.ts b/models/book.ts index 408a1e9..4e13e08 100644 --- a/models/book.ts +++ b/models/book.ts @@ -32,10 +32,12 @@ export interface IBook extends Document { * @extends Model * @property {Function} getAllBooksWithAuthors - A function to get all books with authors. * @property {Function} getBookCount - A function to get the count of books. + * @property {Function} getBookDetails - A function to get the details of a specific book. */ interface IBookModel extends Model { getAllBooksWithAuthors(projectionOpts: string, sortOpts?: { [key: string]: 1 | -1 }): Promise; getBookCount(fitler?: FilterQuery): Promise; + getBookDetails(bookId: string): Promise; } /** @@ -83,6 +85,40 @@ BookSchema.statics.getBookCount = async function (filter?: FilterQuery): return this.countDocuments(filter || {}); } +/** + * retrieves the details of a specific book including its author information and book instances + * @param bookId the ID of the book to retrieve details for + * @returns a promise that resolves to the book details or null if not found + */ +BookSchema.statics.getBookDetails = async function(bookId: string): Promise { + try { + const BookInstance = mongoose.model('BookInstance'); + + // Find book by ID and populate author information + const book = await this.findById(bookId).populate('author'); + + if (!book) { + return null; + } + + // Get all book instances for this book + const bookInstances = await BookInstance.find({ book: bookId }); + + // Format response with required fields + return { + title: book.title, + author: book.author.name, + bookInstances: bookInstances.map(instance => ({ + imprint: instance.imprint, + status: instance.status + })) + }; + } catch (error) { + console.error('Error getting book details:', error); + return null; + } +} + /** * retrieves an existing author by name and an existing genre by name, * and saves a new book in this collection with the provided title, summary, and ISBN. diff --git a/pages/book_dtls.ts b/pages/book_dtls.ts new file mode 100644 index 0000000..42a4699 --- /dev/null +++ b/pages/book_dtls.ts @@ -0,0 +1,33 @@ +import express from 'express'; +import Book from '../models/book'; + +const router = express.Router(); + +/** + * @route GET /book_dtls + * @query id - The ID of the book to retrieve details for + * @returns An object containing the book title, author name, and book instances with imprint and status + * @description Retrieves detailed information about a specific book by its ID + */ +router.get('/', async (req, res) => { + try { + const bookId = req.query.id as string; + + if (!bookId) { + return res.status(400).send({ error: 'Book ID is required' }); + } + + const bookDetails = await Book.getBookDetails(bookId); + + if (!bookDetails) { + return res.status(404).send({ error: 'Book not found' }); + } + + res.status(200).send(bookDetails); + } catch (error) { + console.error('Error in book details route:', error); + res.status(500).send({ error: 'Internal server error' }); + } +}); + +export default router; \ No newline at end of file diff --git a/server.ts b/server.ts index 3e7a62a..4f048d3 100644 --- a/server.ts +++ b/server.ts @@ -6,6 +6,7 @@ import availableRouter from './pages/books_status'; import bookRouter from './pages/books'; import authorRouter from './pages/authors'; import createBookRouter from './pages/create_book'; +import bookDetailsRouter from './pages/book_dtls'; // Create express app const app = express(); @@ -45,3 +46,5 @@ app.use('/books', bookRouter); app.use('/authors', authorRouter); app.use('/newbook', createBookRouter); + +app.use('/book_dtls', bookDetailsRouter);