diff --git a/api/prisma/schema.prisma b/api/prisma/schema.prisma index d7a77b8..7ecca71 100644 --- a/api/prisma/schema.prisma +++ b/api/prisma/schema.prisma @@ -32,6 +32,8 @@ model Game { coverImage String? tags String[] links Link[] + series String? + seriesOrder Int? @db.Int createdAt DateTime @default(now()) updatedAt DateTime @updatedAt comments Comment[] @@ -58,6 +60,8 @@ model Book { coverImage String? tags String[] links Link[] + series String? + seriesOrder Int? @db.Int createdAt DateTime @default(now()) updatedAt DateTime @updatedAt comments Comment[] diff --git a/api/src/app/routes/books/index.ts b/api/src/app/routes/books/index.ts index 2aea0fe..f6991d3 100644 --- a/api/src/app/routes/books/index.ts +++ b/api/src/app/routes/books/index.ts @@ -24,6 +24,17 @@ const booksRoutes: FastifyPluginAsync = async (app) => { return bookService.getAllBooks(); }); + /** + * Get all books in a series (public route). + */ + app.get<{ Params: { seriesName: string }; Reply: Book[] }>( + "/series/:seriesName", + async (request) => { + const { seriesName } = request.params; + return bookService.getBooksBySeries(seriesName); + } + ); + /** * Get single book by ID (public route). */ diff --git a/api/src/app/routes/games/index.ts b/api/src/app/routes/games/index.ts index 2d00886..eef98a0 100644 --- a/api/src/app/routes/games/index.ts +++ b/api/src/app/routes/games/index.ts @@ -22,6 +22,15 @@ const gamesRoutes: FastifyPluginAsync = async (app) => { return gameService.getAllGames(); }); + // Get all games in a series (public route) + app.get<{ Params: { seriesName: string }; Reply: Game[] }>( + "/series/:seriesName", + async (request) => { + const { seriesName } = request.params; + return gameService.getGamesBySeries(seriesName); + } + ); + // Get single game (public route) app.get<{ Params: { id: string }; Reply: Game | null }>( "/:id", diff --git a/api/src/app/services/book.service.ts b/api/src/app/services/book.service.ts index afb97bc..1e396af 100644 --- a/api/src/app/services/book.service.ts +++ b/api/src/app/services/book.service.ts @@ -56,6 +56,28 @@ export class BookService { }; } + /** + * Get all books in a series, ordered by seriesOrder. + */ + async getBooksBySeries(seriesName: string): Promise { + const books = await this.prisma.book.findMany({ + where: { series: seriesName }, + orderBy: { seriesOrder: "asc" }, + }); + + return books.map((book) => ({ + ...book, + status: book.status as unknown as BookStatus, + dateAdded: book.dateAdded, + dateStarted: book.dateStarted || undefined, + dateFinished: book.dateFinished || undefined, + tags: book.tags ?? [], + links: book.links ?? [], + createdAt: book.createdAt, + updatedAt: book.updatedAt, + })); + } + /** * Create new book. */ diff --git a/api/src/app/services/game.service.ts b/api/src/app/services/game.service.ts index d748c22..66a9cdf 100644 --- a/api/src/app/services/game.service.ts +++ b/api/src/app/services/game.service.ts @@ -58,6 +58,29 @@ export class GameService { }; } + /** + * Get all games in a series, ordered by seriesOrder. + */ + async getGamesBySeries(seriesName: string): Promise { + const games = await this.prisma.game.findMany({ + where: { series: seriesName }, + orderBy: { seriesOrder: "asc" }, + }); + + return games.map((game) => ({ + ...game, + status: game.status as unknown as GameStatus, + dateAdded: game.dateAdded, + dateStarted: game.dateStarted || undefined, + dateCompleted: game.dateCompleted || undefined, + dateFinished: game.dateFinished || undefined, + tags: game.tags ?? [], + links: game.links ?? [], + createdAt: game.createdAt, + updatedAt: game.updatedAt, + })); + } + /** * Create new game. */ diff --git a/apps/frontend/src/app/components/books/books-list.component.ts b/apps/frontend/src/app/components/books/books-list.component.ts index bcdbb50..ceda6ed 100644 --- a/apps/frontend/src/app/components/books/books-list.component.ts +++ b/apps/frontend/src/app/components/books/books-list.component.ts @@ -127,6 +127,29 @@ import { Book, BookStatus, CreateBookDto, UpdateBookDto, Comment, SuggestionEnti > +
+ + +
+ +
+ + +
+
+
+ + +
+ +
+ + +
+
+
+ + +
+ +
+ + +
+
+
+ + +
+ +
+ + +
+
; links: Array; + series?: string; + seriesOrder?: number; createdAt: Date; updatedAt: Date; } @@ -43,6 +45,8 @@ interface CreateBookDto { coverImage?: string; tags?: Array; links?: Array; + series?: string; + seriesOrder?: number; } interface UpdateBookDto extends Partial { diff --git a/shared-types/src/lib/game.types.ts b/shared-types/src/lib/game.types.ts index 38949ac..4689816 100644 --- a/shared-types/src/lib/game.types.ts +++ b/shared-types/src/lib/game.types.ts @@ -27,6 +27,8 @@ interface Game { coverImage?: string; tags: Array; links: Array; + series?: string; + seriesOrder?: number; createdAt: Date; updatedAt: Date; } @@ -42,6 +44,8 @@ interface CreateGameDto { coverImage?: string; tags?: Array; links?: Array; + series?: string; + seriesOrder?: number; } interface UpdateGameDto extends Partial {