feat: implement identity authentication, authorization policies, and MAUI platform support with Docker orchestration

This commit is contained in:
2026-04-29 20:37:41 +02:00
parent 10efed0369
commit 0210611edf
55 changed files with 2359 additions and 949 deletions
@@ -1,54 +1,101 @@
@page "/account/profile"
@using Microsoft.AspNetCore.Authorization
@using NexusReader.UI.Shared.Services
@using NexusReader.UI.Shared.Components.Atoms
@attribute [Authorize]
@inject IIdentityService IdentityService
@inject NavigationManager NavigationManager
<div class="profile-container">
<div class="profile-card">
@if (_profile == null)
{
<div class="loading-state">
<div class="spinner"></div>
<p>Fetching your Nexus profile...</p>
</div>
}
else
{
<div class="profile-header">
<div class="user-avatar">
@(string.IsNullOrEmpty(_profile.Email) ? "?" : _profile.Email[0].ToString().ToUpper())
<div class="profile-dashboard">
<div class="mesh-overlay"></div>
@if (_profile == null)
{
<div class="loading-overlay">
<div class="nexus-loader"></div>
<p>Ładowanie Twojego profilu...</p>
</div>
}
else
{
<div class="dashboard-content">
<header class="dashboard-header">
<div class="user-meta">
<div class="user-avatar">
@(_profile.Email[0].ToString().ToUpper())
</div>
<div class="user-info">
<h1>@_profile.Email</h1>
<div class="plan-info">
<span class="badge @(_profile.CurrentPlan.ToLower())">@_profile.CurrentPlan Plan</span>
<span class="tenant-id">ID: @_profile.TenantId.ToString()[..8]...</span>
</div>
</div>
</div>
<h2>@_profile.Email</h2>
<div class="plan-badge @(_profile.CurrentPlan.ToLower())">
@_profile.CurrentPlan Plan
<div class="header-actions">
<button class="btn-logout" @onclick="HandleLogout">
<NexusIcon Name="lock" Size="16" />
Wyloguj się
</button>
</div>
</header>
<div class="stats-grid">
<!-- AI Token Card -->
<div class="stat-card usage-card">
<div class="card-icon">
<NexusIcon Name="robot" Size="24" />
</div>
<div class="card-info">
<h3>Wykorzystanie AI</h3>
<div class="token-numbers">
<span class="tokens-used">@_profile.AITokensUsed</span>
<span class="tokens-limit">/ @_profile.AITokenLimit tokenów</span>
</div>
<div class="usage-bar">
<div class="usage-fill" style="width: @(CalculateProgress())%"></div>
</div>
<p class="usage-desc">Limit odnawia się w następnym cyklu rozliczeniowym.</p>
</div>
</div>
<!-- Learning Progress Card -->
<div class="stat-card learning-card">
<div class="card-icon">
<NexusIcon Name="mail" Size="24" />
</div>
<div class="card-info">
<h3>Aktywna Nauka</h3>
<div class="learning-metrics">
<div class="metric">
<span class="label">Średni wynik quizów</span>
<span class="value">@_profile.AverageQuizScore%</span>
</div>
<div class="metric">
<span class="label">Ostatnio czytane</span>
<span class="value truncate">@_profile.LastReadBookTitle</span>
</div>
</div>
</div>
</div>
</div>
<div class="profile-stats">
<div class="stat-group">
<div class="stat-header">
<span>AI Token Usage</span>
<span class="usage-count">@_profile.AITokensUsed / @_profile.AITokenLimit</span>
<section class="subscription-section">
<div class="section-card">
<div class="section-info">
<h2>Zarządzaj subskrypcją</h2>
<p>Zmień swój plan, aby zwiększyć limit tokenów AI i odblokować funkcje premium.</p>
</div>
<div class="progress-bar">
<div class="progress-fill" style="width: @(CalculateProgress())%"></div>
</div>
<p class="stat-footer">Resetting on your next billing date.</p>
<button class="btn-upgrade" @onclick="HandleUpgrade">
Przejdź do panelu płatności
</button>
</div>
</div>
</section>
</div>
}
<div class="profile-actions">
<button class="btn-primary" @onclick="HandleUpgrade">
Manage Subscription
</button>
<button class="btn-outline" @onclick="HandleLogout">
Sign Out
</button>
</div>
}
</div>
<div class="decoration-star top-left">✦</div>
<div class="decoration-star bottom-right">✦</div>
</div>
@code {