diff --git a/src/GmRelay.Web/Components/Pages/GroupStats.razor b/src/GmRelay.Web/Components/Pages/GroupStats.razor
new file mode 100644
index 0000000..c8d386b
--- /dev/null
+++ b/src/GmRelay.Web/Components/Pages/GroupStats.razor
@@ -0,0 +1,234 @@
+@page "/group/{GroupId:guid}/stats"
+@using GmRelay.Web.Services
+@using GmRelay.Shared.Domain
+@using Microsoft.AspNetCore.Authorization
+@using Microsoft.AspNetCore.Components.Authorization
+@attribute [Authorize]
+@inject ISessionStore SessionStore
+@inject AuthenticationStateProvider AuthStateProvider
+@inject NavigationManager Navigation
+
+Статистика — GM-Relay
+
+
+
+
+
+
+ @if (!string.IsNullOrEmpty(errorMessage))
+ {
+
+ ⚠️ @errorMessage
+
+ }
+
+ @if (stats is null)
+ {
+
⏳ Загружаем статистику…
+ }
+ else if (stats.Count == 0)
+ {
+
+
📈
+
Пока нет данных
+
После первых сессий здесь появится аналитика.
+
+ }
+ else
+ {
+
+
+
+
@stats.Count
+
Игроков
+
+
+
@TotalSessions
+
Сессий
+
+
+
@AvgAttendanceRate%
+
Средняя посещаемость
+
+
+
@topPlayer?.DisplayName
+
Самый стабильный
+
+
+
+
+
+
+
+ | SortBy("player")" style="cursor:pointer;">Игрок @(SortIndicator("player")) |
+ SortBy("total")" style="cursor:pointer;text-align:center;">Всего @(SortIndicator("total")) |
+ SortBy("confirmed")" style="cursor:pointer;text-align:center;">✅ @(SortIndicator("confirmed")) |
+ SortBy("declined")" style="cursor:pointer;text-align:center;">❌ @(SortIndicator("declined")) |
+ SortBy("noresponse")" style="cursor:pointer;text-align:center;">💤 @(SortIndicator("noresponse")) |
+ SortBy("waitlist")" style="cursor:pointer;text-align:center;">⏳ @(SortIndicator("waitlist")) |
+ SortBy("rate")" style="cursor:pointer;text-align:center;">% @(SortIndicator("rate")) |
+ SortBy("cancelled")" style="cursor:pointer;text-align:center;">🚫 @(SortIndicator("cancelled")) |
+
+
+
+ @foreach (var s in sortedStats)
+ {
+
+ |
+
+ @s.DisplayName
+ @if (!string.IsNullOrEmpty(s.TelegramUsername))
+ {
+ @@@s.TelegramUsername
+ }
+
+ |
+ @s.TotalSessions |
+ @s.ConfirmedCount |
+ @s.DeclinedCount |
+ @s.NoResponseCount |
+ @s.WaitlistedCount |
+
+
+ @s.AttendanceRate%
+
+ |
+ @s.CancellationAffectedCount |
+
+ }
+
+
+
+
+ }
+
+
+
+
+@code {
+ [Parameter] public Guid GroupId { get; set; }
+ private List