feat(ui): Hub Navigation, Profile Dashboard and Auth Stability Fixes #31
Reference in New Issue
Block a user
Delete Branch "feat/hub-navigation-profile-dashboard"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
This PR implements the Hub Navigation system and the Profile Dashboard, while resolving critical session synchronization issues.
Key Changes
MainHubLayoutwith a premium glassmorphism sidebar, providing access to Dashboard, Library, Concepts Map, and Profile./profilepage by implementing request deduplication and in-memory caching inIdentityService.401 Unauthorizedresponses to handle stale authentication states gracefully.Closes #26
Closes #27
Code Review Summary
Scope of PR #31
MainHubLayout+ sidebar)ReaderLayout,Routes.razor) and updated several UI pages (Login,Home,NotFound)IdentityService(cookie‑aware login, profile caching, graceful logout)AuthenticationStateProvider(caching, cookie‑fallback handling)Architectural & Clean‑Architecture Checklist
async voidTaskPerformance & Scalability
backdrop-filter; consider fallback for low‑end devices (optional).Nexus‑Specific Guidelines
Result<T>.Specific Observations & Recommendations
IdentityService.cs– caching (_cachedProfile) and_profileTaskguard are solid. Document cookie‑flow handling.NexusAuthenticationStateProvider.cs– added_cachedStateimproves performance; consider invalidating on token refresh.Profile.razor– redesigned UI looks great;CalculateProgress()safely guards division.Dashboard.razor– robust null checks; UI looks premium.MainHubLayout(hub sidebar).dotnet buildsucceeds; only warnings (unused package, known CVE) – acceptable.Action Items (optional)
Result<T>for richer error info.backdrop-filteron low‑performance browsers.IdentityService).If the optional items are out of scope, the PR meets the NexusReader quality gates and is ready for merge.
Action Items Resolved
I have addressed the recommendations from the code review:
IIdentityServiceand its implementations (IdentityService,ServerIdentityService) to returnResultandResult<T>for consistent error handling.OnStateInvalidatedevent andClearCache()inNexusAuthenticationStateProviderto handle token refreshes and logouts gracefully.@supportsfallbacks forbackdrop-filterinapp.css,Dashboard.razor.css, andProfile.razor.cssusing more opaque backgrounds.The build is successful with 0 errors. Ready for final review.
Improve table normalization and avoid magic strings
@@ -22,4 +23,8 @@ public record LastReadBookDto{public Guid Id { get; init; }public string Title { get; init; } = string.Empty;public string Author { get; init; } = string.Empty;From a data normalization perspective,
Authorshould be a dedicated object, not astringtype. The current configuration will cause issues with searching and potential sorting and grouping of e-books.These changes must be implemented in the DTO and in the model
@@ -126,4 +235,0 @@var profile = await GetProfileAsync();if (profile != null){await _storageService.SaveSecureString("nexus_user_email", profile.Email);Use const variables instead of magic strings
@@ -23,0 +25,4 @@LastReadBookDto? LastReadBook){// Helper properties for UI compatibilitypublic string CurrentPlan => Plan?.Name ?? "Standard";Use
SubscriptionPlanDtoand theSubscriptionPlanmodel instead ofstringvalues@@ -99,0 +80,4 @@{result = await response.Content.ReadFromJsonAsync<LoginResponse>();}catch (System.Text.Json.JsonException) { }Do not eat exceptions
@@ -99,0 +126,4 @@{await _storageService.SaveSecureString(TokenKey, "");await _storageService.SaveSecureString(RefreshTokenKey, "");await _storageService.SaveSecureString("nexus_user_email", "");Use const variables instead of magic strings
@@ -99,0 +127,4 @@await _storageService.SaveSecureString(TokenKey, "");await _storageService.SaveSecureString(RefreshTokenKey, "");await _storageService.SaveSecureString("nexus_user_email", "");await _storageService.SaveSecureString("nexus_user_tenant", "");Use const variables instead of magic strings
@@ -99,0 +191,4 @@if (profile != null){_cachedProfile = profile;await _storageService.SaveSecureString("nexus_user_email", profile.Email);Use const variables instead of magic strings
@@ -135,0 +241,4 @@{var profile = profileResult.Value;await _storageService.SaveSecureString("nexus_user_email", profile.Email);await _storageService.SaveSecureString("nexus_user_tenant", profile.TenantId.ToString());Use const variables instead of magic strings
@@ -26,2 +37,3 @@{return new AuthenticationState(new ClaimsPrincipal(new ClaimsIdentity()));var emailResult = await _storageService.GetSecureString("nexus_user_email");var tenantIdResult = await _storageService.GetSecureString("nexus_user_tenant");Use const variables instead of magic strings
Code Review #1 (issuecomment-89) Resolved
I have implemented the following improvements:
Authorentity andAuthorDto.Ebookmodel to useAuthorIdand navigation property.ServerIdentityServiceandProgram.csprojections to use structuredAuthorDto.Dashboard.razorto displayAuthor.Name.StorageKeysandPlanConstantsinUI.Shared/Constants.IdentityServiceandNexusAuthenticationStateProvider.IdentityService.LoginAsyncrelated to JSON deserialization.AuthorinAppDbContextwith proper relationship configuration.The solution builds successfully (0 errors). Ready for further verification.
🚀 Pull Request Update Summary
I have completed the technical refactoring and feature implementation for this PR. Key updates include:
🏗️ Architecture & CQRS
ServerIdentityServiceto a structuredGetUserProfileQuery(MediatR)./settingsand/profilesby properly utilizingIDbContextFactory<AppDbContext>within the query handlers.📊 Real-Time Reading Progress
ProgressandLastChapterfields to theEbookentity.EpubServiceandSyncHubto ensure reading activity is correctly mapped to the authenticated user.📝 Documentation & Standards
All builds are passing, and the database schema is updated. Ready for final review.