feat: implement entity detail pages with full navigation

Implements issue #56 (activity feed) followup - adds complete detail pages for all entity types so activity feed and homepage links work properly.

Created Detail Components:
- game-detail.component.ts - Shows full game details with platform, series, time played
- book-detail.component.ts - Shows book details with author, ISBN, series, reading time
- music-detail.component.ts - Shows music details with artist, type (album/single), listening time
- art-detail.component.ts - Shows art details with artist, description, large image display
- show-detail.component.ts - Shows show details with type (TV/anime/film), watch time
- manga-detail.component.ts - Shows manga details with author, reading time

Features per Detail Page:
- Read-only display of full entity information
- Cover/poster/art image display (when available)
- Rating display with 10-star system (when applicable)
- Time spent formatting (hours and minutes)
- Date formatting (British English locale)
- Tags display with entity-specific colour schemes
- External links with hover effects
- Comments section with add/edit/delete functionality
- Like button integration
- Breadcrumb navigation back to list page
- Loading states with spinner
- Error handling for not found cases
- Responsive design for all screen sizes

Routing Updates:
- Added 6 new routes: /games/:id, /books/:id, /music/:id, /art/:id, /shows/:id, /manga/:id
- All routes use lazy loading with loadComponent

Navigation Fixes:
- Fixed activity feed like links to point to entity detail pages (was pointing to list)
- Updated homepage recent items to link directly to entity detail pages (was pointing to list)

Technical Fixes:
- Corrected Art component to only use existing fields (removed non-existent medium, rating, notes)
- Fixed Show component to use coverImage instead of non-existent posterImage
- Added proper null checks for optional fields (timeSpent, dateStarted, dateFinished)
- Added non-null assertions where values are guaranteed to exist within conditionals

Each detail component follows the established pattern from the list components whilst adapting for single-item display. All components use Angular signals for reactive state management and integrate with existing services.

 This issue was created with help from Hikari~ 🌸
This commit is contained in:
2026-02-20 00:33:28 -08:00
committed by Naomi Carrigan
parent b8d3365158
commit 7606a18e38
9 changed files with 3836 additions and 7 deletions
@@ -92,7 +92,7 @@ import { Game, GameStatus, Book, BookStatus, Music, MusicType, Manga, MangaStatu
<ul class="recent-list">
@for (game of recentGames(); track game.id) {
<li>
<a routerLink="/games">{{ game.title }}</a>
<a [routerLink]="['/games', game.id]">{{ game.title }}</a>
@if (game.platform) {
<span class="platform">({{ game.platform }})</span>
}
@@ -108,7 +108,7 @@ import { Game, GameStatus, Book, BookStatus, Music, MusicType, Manga, MangaStatu
<ul class="recent-list">
@for (book of recentBooks(); track book.id) {
<li>
<a routerLink="/books">{{ book.title }}</a>
<a [routerLink]="['/books', book.id]">{{ book.title }}</a>
<span class="author">by {{ book.author }}</span>
</li>
}
@@ -122,7 +122,7 @@ import { Game, GameStatus, Book, BookStatus, Music, MusicType, Manga, MangaStatu
<ul class="recent-list">
@for (music of recentMusic(); track music.id) {
<li>
<a routerLink="/music">{{ music.title }}</a>
<a [routerLink]="['/music', music.id]">{{ music.title }}</a>
<span class="artist">by {{ music.artist }}</span>
</li>
}
@@ -136,7 +136,7 @@ import { Game, GameStatus, Book, BookStatus, Music, MusicType, Manga, MangaStatu
<ul class="recent-list">
@for (manga of recentManga(); track manga.id) {
<li>
<a routerLink="/manga">{{ manga.title }}</a>
<a [routerLink]="['/manga', manga.id]">{{ manga.title }}</a>
<span class="author">by {{ manga.author }}</span>
</li>
}
@@ -150,7 +150,7 @@ import { Game, GameStatus, Book, BookStatus, Music, MusicType, Manga, MangaStatu
<ul class="recent-list">
@for (show of recentShows(); track show.id) {
<li>
<a routerLink="/shows">{{ show.title }}</a>
<a [routerLink]="['/shows', show.id]">{{ show.title }}</a>
<span class="show-type">{{ formatShowType(show.type) }}</span>
</li>
}
@@ -164,7 +164,7 @@ import { Game, GameStatus, Book, BookStatus, Music, MusicType, Manga, MangaStatu
<ul class="recent-list">
@for (art of recentArt(); track art.id) {
<li>
<a routerLink="/art">{{ art.title }}</a>
<a [routerLink]="['/art', art.id]">{{ art.title }}</a>
<span class="artist">by {{ art.artist }}</span>
</li>
}