feat(ui): Hub Navigation, Profile Dashboard and Auth Stability Fixes (#31)

This PR implements the Hub Navigation system and the Profile Dashboard, while resolving critical session synchronization issues.

### Key Changes
- **Hub Navigation**: Introduced `MainHubLayout` with a premium glassmorphism sidebar, providing access to Dashboard, Library, Concepts Map, and Profile.
- **Profile Dashboard**: Implemented a high-fidelity Profile page (#27) with learning metrics, AI token usage tracking, and system rank visualization.
- **Stability Fixes**:
    - Resolved an infinite network loop on the `/profile` page by implementing request deduplication and in-memory caching in `IdentityService`.
    - Added environment-aware guards to prevent illegal JavaScript interop calls during server-side prerendering.
    - Implemented automatic session invalidation on `401 Unauthorized` responses to handle stale authentication states gracefully.
- **Reader Integration**: Added a "Return to Dashboard" option in the reader toolbar (#26).

Closes #26
Closes #27

Reviewed-on: #31
Co-authored-by: Marek Jasiński <jasins.marek@gmail.com>
Co-committed-by: Marek Jasiński <jasins.marek@gmail.com>
This commit was merged in pull request #31.
This commit is contained in:
2026-05-10 17:36:35 +00:00
committed by Marek Jaisński
parent 34794db209
commit 2e23a032d3
56 changed files with 4292 additions and 481 deletions
+12 -2
View File
@@ -15,8 +15,11 @@ public class Ebook
[MaxLength(255)]
public string Title { get; set; } = string.Empty;
[MaxLength(255)]
public string Author { get; set; } = "Unknown";
[Required]
public int AuthorId { get; set; }
[ForeignKey(nameof(AuthorId))]
public virtual Author Author { get; set; } = null!;
[Required]
public string FilePath { get; set; } = string.Empty;
@@ -30,6 +33,13 @@ public class Ebook
public DateTime AddedDate { get; set; } = DateTime.UtcNow;
public DateTime? LastReadDate { get; set; }
public double Progress { get; set; } = 0;
[MaxLength(255)]
public string? LastChapter { get; set; }
public int LastChapterIndex { get; set; } = 0;
// Relationship to NexusUser
[Required]