feat(web): add portfolio management UI

This commit is contained in:
2026-06-02 15:21:51 +03:00
parent 242ff99a83
commit e970e94e00
6 changed files with 1026 additions and 1 deletions
@@ -1,9 +1,11 @@
@page "/session/{SessionId:guid}/history"
@using GmRelay.Web.Services
@using GmRelay.Web.Services.Portfolio
@using Microsoft.AspNetCore.Authorization
@using Microsoft.AspNetCore.Components.Authorization
@attribute [Authorize]
@inject AuthorizedSessionService SessionService
@inject AuthorizedPortfolioService PortfolioService
@inject AuthenticationStateProvider AuthStateProvider
@inject NavigationManager Navigation
@@ -22,6 +24,14 @@
{
<p style="color: var(--text-muted); margin-top: 0.25rem;">@sessionTitle</p>
}
@if (groupId is not null && session is not null && session.ScheduledAt < DateTime.UtcNow)
{
<div style="margin-top: 0.75rem;">
<button type="button" class="btn-gm btn-gm-primary" disabled="@isCreatingDraft" @onclick="AddToPortfolio">
@(isCreatingDraft ? "⏳ Создаём..." : "➕ Добавить в портфолио")
</button>
</div>
}
</div>
@if (entries is null)
@@ -78,6 +88,8 @@
private List<SessionAuditLogEntry>? entries;
private string? sessionTitle;
private Guid? groupId;
private WebSession? session;
private bool isCreatingDraft;
protected override async Task OnInitializedAsync()
{
@@ -88,7 +100,7 @@
return;
}
var session = await SessionService.GetSessionForCurrentUserAsync(SessionId);
session = await SessionService.GetSessionForCurrentUserAsync(SessionId);
if (session is null)
{
Navigation.NavigateTo("/access-denied");
@@ -100,6 +112,30 @@
entries = await SessionService.GetSessionHistoryForCurrentUserAsync(SessionId);
}
private async Task AddToPortfolio()
{
if (groupId is null)
{
return;
}
isCreatingDraft = true;
try
{
var portfolioId = await PortfolioService.CreateDraftForCurrentUserAsync(groupId.Value, SessionId);
Navigation.NavigateTo($"/portfolio/manage/{portfolioId}");
}
catch (SessionAccessDeniedException)
{
Navigation.NavigateTo("/access-denied");
}
catch
{
isCreatingDraft = false;
}
}
private string GetChangeTypeLabel(string changeType) => changeType switch
{
"Title" => "Название",