@page "/gm/{Slug}" @layout PublicLayout @inject ISessionStore SessionStore @inject IPortfolioStore PortfolioStore @inject NavigationManager Navigation @inject IHttpContextAccessor HttpContextAccessor @using GmRelay.Web.Components.Portfolio @using GmRelay.Web.Services.Portfolio @PageTitleText @if (loaded && profile is null) {
Недоступно

Профиль мастера не найден

Мастер скрыл профиль или этот короткий адрес больше не используется.

} else if (!loaded) {
} else if (profile is not null) {
Мастер

@profile.DisplayName

@if (!string.IsNullOrWhiteSpace(profile.Bio)) {

@profile.Bio

}
Ссылка профиля @PublicMasterProfileUrl
@if (profile.Clubs.Count > 0) {

Клубы

@foreach (var club in profile.Clubs) { @club.Name }
} @if (profile.Sessions.Count == 0) {

Опубликованных игр пока нет

Когда мастер откроет игры для каталога, они появятся здесь.

} else {
@foreach (var session in profile.Sessions) {
@TranslateStatus(session.Status)

@session.Title

@session.GroupName @session.ScheduledAt.FormatMoscow() @FormatSeats(session)
Открыть
}
} @if (portfolioGames.Count > 0) {

Портфолио

Завершённые игры мастера, открытые для публичного просмотра.

} } @code { [Parameter] public string? Slug { get; set; } private GmRelay.Web.Services.PublicMasterProfile? profile; private IReadOnlyList portfolioGames = []; private bool loaded; private string PageTitleText => profile is null ? "Профиль мастера — GM-Relay" : $"{profile.DisplayName} — GM-Relay"; private string PublicMasterProfileUrl => profile is null ? Navigation.ToAbsoluteUri($"/gm/{Slug}").ToString() : Navigation.ToAbsoluteUri($"/gm/{profile.Slug}").ToString(); protected override async Task OnParametersSetAsync() { loaded = false; var trimmedSlug = string.IsNullOrWhiteSpace(Slug) ? null : Slug.Trim(); Guid? viewerPlayerId = null; var user = HttpContextAccessor.HttpContext?.User; if (user?.Identity?.IsAuthenticated == true && user.TryGetPlatformIdentity(out _, out var externalUserId)) { var platform = user.FindFirst("Platform")?.Value; viewerPlayerId = !string.IsNullOrWhiteSpace(platform) ? await SessionStore.GetPlayerIdByPlatformIdentityAsync(platform, externalUserId) : null; } profile = trimmedSlug is null ? null : await SessionStore.GetPublicMasterProfileBySlugAsync(trimmedSlug, viewerPlayerId); portfolioGames = trimmedSlug is null ? [] : await PortfolioStore.GetPublicPortfolioGamesForMasterAsync(trimmedSlug); loaded = true; } private static string FormatSeats(WebPublicSession session) { var seats = session.MaxPlayers.HasValue ? $"{session.ActivePlayerCount}/{session.MaxPlayers.Value}" : $"{session.ActivePlayerCount} игроков"; return session.WaitlistedPlayerCount > 0 ? $"{seats}, ожидание {session.WaitlistedPlayerCount}" : seats; } private static string GetStatusClass(string status) => status switch { SessionStatus.Confirmed => "status-success", SessionStatus.ConfirmationSent => "status-warning", SessionStatus.Planned => "status-info", _ => "status-neutral" }; private static string TranslateStatus(string status) => status switch { SessionStatus.Planned => "Запланировано", SessionStatus.ConfirmationSent => "Ждем подтверждения", SessionStatus.Confirmed => "Подтверждено", _ => status }; }