feat: implement Blazor web interface for GM session management
Deploy Telegram Bot / deploy (push) Has been cancelled

- Created GmRelay.Web project (Blazor Server)
- Created GmRelay.Shared library for domain models and rendering
- Refactored GmRelay.Bot to use the Shared library
- Integrated Telegram Login widget with server-side HMAC verification
- Added Dashboard, Group Details, and Edit Session pages
- Enabled bot notifications and in-place message updates from web actions
- Updated .NET Aspire orchestration and Docker Compose configuration
This commit is contained in:
2026-04-17 11:06:59 +03:00
parent c27456e726
commit 988133e389
93 changed files with 61016 additions and 34 deletions
@@ -0,0 +1,64 @@
@page "/"
@using Microsoft.AspNetCore.Authorization
@using Microsoft.AspNetCore.Components.Authorization
@using GmRelay.Web.Services
@attribute [Authorize]
@inject SessionService SessionService
@inject AuthenticationStateProvider AuthStateProvider
<PageTitle>Dashboard - GM-Relay</PageTitle>
<div class="container mt-4">
<h2>Welcome, @userName!</h2>
<p class="text-muted">Select a group to manage your game sessions.</p>
<div class="row mt-4">
@if (groups == null)
{
<p>Loading groups...</p>
}
else if (groups.Count == 0)
{
<div class="col-12">
<div class="card bg-light">
<div class="card-body text-center">
<p class="mb-0">You don't have any groups registered yet. Use the bot in a Telegram group first!</p>
</div>
</div>
</div>
}
else
{
@foreach (var group in groups)
{
<div class="col-md-4 mb-3">
<div class="card h-100 shadow-sm">
<div class="card-body">
<h5 class="card-title">@group.Name</h5>
<p class="card-text text-muted">ID: @group.TelegramChatId</p>
<a href="/group/@group.Id" class="btn btn-primary">View Sessions</a>
</div>
</div>
</div>
}
}
</div>
</div>
@code {
private List<WebGameGroup>? groups;
private string userName = "";
protected override async Task OnInitializedAsync()
{
var authState = await AuthStateProvider.GetAuthenticationStateAsync();
var user = authState.User;
userName = user.Identity?.Name ?? "Game Master";
var telegramIdClaim = user.FindFirst("TelegramId")?.Value;
if (long.TryParse(telegramIdClaim, out var telegramId))
{
groups = await SessionService.GetGroupsForGmAsync(telegramId);
}
}
}