feat(discord): add DiscordRescheduleVotingRenderer and replace inline helper
This commit is contained in:
@@ -0,0 +1,67 @@
|
||||
namespace GmRelay.DiscordBot.Rendering;
|
||||
|
||||
using GmRelay.Shared.Domain;
|
||||
using GmRelay.Shared.Features.Sessions.RescheduleSession;
|
||||
using NetCord;
|
||||
using NetCord.Rest;
|
||||
|
||||
public static class DiscordRescheduleVotingRenderer
|
||||
{
|
||||
public static (EmbedProperties Embed, ActionRowProperties ActionRow) Render(
|
||||
string title,
|
||||
DateTime currentTime,
|
||||
DateTimeOffset deadline,
|
||||
IReadOnlyList<RescheduleOptionDto> options,
|
||||
IReadOnlyList<VoteParticipantDto> participants,
|
||||
IReadOnlyList<RescheduleOptionVoteDto> votes)
|
||||
{
|
||||
var votesByOption = votes.GroupBy(v => v.OptionId).ToDictionary(g => g.Key, g => g.ToList());
|
||||
var votedPlayerIds = votes.Select(v => v.PlayerId).ToHashSet();
|
||||
var pending = participants.Where(p => !votedPlayerIds.Contains(p.PlayerId)).Select(p => p.DisplayName).ToList();
|
||||
|
||||
var sb = new System.Text.StringBuilder();
|
||||
sb.AppendLine($"📅 Текущее время: {currentTime.FormatMoscow()} (МСК)");
|
||||
sb.AppendLine($"⏳ Дедлайн: {deadline.FormatMoscow()} (МСК)");
|
||||
sb.AppendLine();
|
||||
sb.AppendLine("Выберите один из вариантов:");
|
||||
|
||||
foreach (var option in options.OrderBy(o => o.DisplayOrder))
|
||||
{
|
||||
var optionVotes = votesByOption.GetValueOrDefault(option.OptionId, []);
|
||||
sb.AppendLine($"{option.DisplayOrder}. **{option.ProposedAt.FormatMoscow()}** (МСК) — {optionVotes.Count} голосов");
|
||||
if (optionVotes.Count > 0)
|
||||
{
|
||||
sb.AppendLine($" {string.Join(", ", optionVotes.Select(v => v.DisplayName))}");
|
||||
}
|
||||
}
|
||||
|
||||
if (pending.Count > 0)
|
||||
{
|
||||
sb.AppendLine();
|
||||
sb.AppendLine($"Не проголосовали: {string.Join(", ", pending)}");
|
||||
}
|
||||
|
||||
sb.AppendLine();
|
||||
sb.AppendLine($"Голосов: {votedPlayerIds.Count}/{participants.Count}");
|
||||
sb.AppendLine("Правило: побеждает вариант с большинством голосов к дедлайну; при ничьей перенос не применяется.");
|
||||
|
||||
var embed = new EmbedProperties()
|
||||
.WithTitle($"🔄 Перенос сессии «{title}»")
|
||||
.WithDescription(sb.ToString())
|
||||
.WithColor(new Color(0xFEE75C));
|
||||
|
||||
var actionRow = new ActionRowProperties();
|
||||
foreach (var option in options.OrderBy(o => o.DisplayOrder))
|
||||
{
|
||||
actionRow.Add(new ButtonProperties(
|
||||
$"reschedule_vote:{option.OptionId}",
|
||||
$"{option.DisplayOrder}. {FormatButtonTime(option.ProposedAt)}",
|
||||
ButtonStyle.Primary));
|
||||
}
|
||||
|
||||
return (embed, actionRow);
|
||||
}
|
||||
|
||||
private static string FormatButtonTime(DateTimeOffset utc)
|
||||
=> utc.ToOffset(TimeSpan.FromHours(3)).ToString("dd.MM HH:mm", System.Globalization.CultureInfo.InvariantCulture);
|
||||
}
|
||||
Reference in New Issue
Block a user