a391c51761
For non-managers /listsessions now shows player-friendly actions: - ✅ Записаться <date> when not registered - ✖️ Выйти <date> when already active - ✖️ Выйти из ожидания <date> when waitlisted Extend SessionListItemDto and the shared SQL query with IsUserActive and IsUserWaitlisted flags so the renderer can choose the right button. Update tests to cover all three player states.
98 lines
3.6 KiB
C#
98 lines
3.6 KiB
C#
using GmRelay.Shared.Domain;
|
||
using GmRelay.Shared.Platform;
|
||
using GmRelay.Shared.Features.Sessions.ListSessions;
|
||
|
||
namespace GmRelay.Bot.Features.Sessions.ListSessions;
|
||
|
||
internal static class SessionListMessageRenderer
|
||
{
|
||
public static string RenderText(IReadOnlyList<SessionListItemDto> sessions)
|
||
{
|
||
var text = "📅 <b>Ближайшие игры:</b>\n\n";
|
||
foreach (var session in sessions)
|
||
{
|
||
var seats = session.MaxPlayers.HasValue
|
||
? $"{session.PlayerCount}/{session.MaxPlayers.Value}"
|
||
: session.PlayerCount.ToString(System.Globalization.CultureInfo.InvariantCulture);
|
||
var waitlist = session.WaitlistCount > 0 ? $", ожидание: {session.WaitlistCount}" : string.Empty;
|
||
text += $"🔹 <b>{session.ScheduledAt.FormatMoscow()}</b> — {System.Net.WebUtility.HtmlEncode(session.Title)} (Места: {seats}{waitlist})\n";
|
||
}
|
||
|
||
return text;
|
||
}
|
||
|
||
public static IReadOnlyList<PlatformMessageAction> RenderActions(IReadOnlyList<SessionListItemDto> sessions)
|
||
{
|
||
if (sessions.Count == 0)
|
||
{
|
||
return [];
|
||
}
|
||
|
||
return sessions.First().CanManage
|
||
? RenderManagerActions(sessions)
|
||
: RenderPlayerActions(sessions);
|
||
}
|
||
|
||
private static IReadOnlyList<PlatformMessageAction> RenderManagerActions(IReadOnlyList<SessionListItemDto> sessions)
|
||
{
|
||
var actions = new List<PlatformMessageAction>();
|
||
|
||
foreach (var session in sessions)
|
||
{
|
||
var dateTitle = session.ScheduledAt.FormatMoscowShort();
|
||
|
||
actions.Add(new PlatformMessageAction(
|
||
$"cancel_session:{session.Id}",
|
||
$"❌ Отменить {dateTitle}",
|
||
$"cancel_session:{session.Id}"));
|
||
|
||
actions.Add(new PlatformMessageAction(
|
||
$"reschedule_session:{session.Id}",
|
||
$"⏰ Перенести {dateTitle}",
|
||
$"reschedule_session:{session.Id}"));
|
||
|
||
if (SessionCapacityRules.CanPromoteWaitlistedPlayer(session.MaxPlayers, session.PlayerCount, session.WaitlistCount))
|
||
{
|
||
actions.Add(new PlatformMessageAction(
|
||
$"promote_waitlist:{session.Id}",
|
||
$"⬆️ С ожидания {dateTitle}",
|
||
$"promote_waitlist:{session.Id}"));
|
||
}
|
||
|
||
actions.Add(new PlatformMessageAction(
|
||
$"delete_session:{session.Id}",
|
||
$"🗑 Удалить {dateTitle}",
|
||
$"delete_session:{session.Id}"));
|
||
}
|
||
|
||
return actions;
|
||
}
|
||
|
||
private static IReadOnlyList<PlatformMessageAction> RenderPlayerActions(IReadOnlyList<SessionListItemDto> sessions)
|
||
{
|
||
var actions = new List<PlatformMessageAction>();
|
||
|
||
foreach (var session in sessions)
|
||
{
|
||
var dateTitle = session.ScheduledAt.FormatMoscowShort();
|
||
|
||
if (session.IsUserActive || session.IsUserWaitlisted)
|
||
{
|
||
actions.Add(new PlatformMessageAction(
|
||
$"leave_session:{session.Id}",
|
||
session.IsUserWaitlisted ? $"✖️ Выйти из ожидания {dateTitle}" : $"✖️ Выйти {dateTitle}",
|
||
$"leave_session:{session.Id}"));
|
||
}
|
||
else
|
||
{
|
||
actions.Add(new PlatformMessageAction(
|
||
$"join_session:{session.Id}",
|
||
$"✅ Записаться {dateTitle}",
|
||
$"join_session:{session.Id}"));
|
||
}
|
||
}
|
||
|
||
return actions;
|
||
}
|
||
}
|