using GmRelay.Bot.Domain; using Telegram.Bot.Types.ReplyMarkups; namespace GmRelay.Bot.Features.Sessions.CreateSession; internal sealed record SessionBatchDto(Guid SessionId, DateTime ScheduledAt, string Status); internal sealed record ParticipantBatchDto(Guid SessionId, string DisplayName, string? TelegramUsername); internal static class SessionBatchRenderer { public static (string Text, InlineKeyboardMarkup Markup) Render( string title, IReadOnlyList sessions, IReadOnlyList participants) { var activeSessions = sessions.OrderBy(s => s.ScheduledAt).ToList(); var messageText = $"🎲 Новые игры: {System.Net.WebUtility.HtmlEncode(title)}\n\n" + $"Расписание:\n\n"; var buttons = new List(); foreach (var session in activeSessions) { var sessionPlayers = participants.Where(p => p.SessionId == session.SessionId).ToList(); messageText += $"📅 {session.ScheduledAt.FormatMoscow()}\n"; messageText += $"👥 Игроки ({sessionPlayers.Count}):\n"; if (sessionPlayers.Count > 0) { messageText += string.Join("\n", sessionPlayers.Select(p => $" 👤 {(p.TelegramUsername != null ? "@" + p.TelegramUsername : p.DisplayName)}")) + "\n"; } else { messageText += " Пока никто не записался\n"; } if (session.Status == "Cancelled") { messageText += "❌ Сессия отменена\n\n"; } else if (session.Status == "RecruitmentClosed") // custom state we can derive or use { messageText += "🔒 Набор завершен\n\n"; } else { messageText += "\n"; // Add buttons for this specific session var dateTitle = session.ScheduledAt.FormatMoscowShort(); buttons.Add(new[] { InlineKeyboardButton.WithCallbackData($"✋ На {dateTitle}", $"join_session:{session.SessionId}"), InlineKeyboardButton.WithCallbackData($"❌ Отменить {dateTitle} (ГМ)", $"cancel_session:{session.SessionId}"), InlineKeyboardButton.WithCallbackData($"⏰ (ГМ)", $"reschedule_session:{session.SessionId}") }); } } return (messageText, new InlineKeyboardMarkup(buttons)); } }