Iceshrimp.NET/Iceshrimp.Frontend/Components/Note/NotePoll.razor

89 lines
No EOL
3.2 KiB
Text

@using Iceshrimp.Frontend.Core.Services.NoteStore
@using Iceshrimp.Frontend.Localization
@using Iceshrimp.Shared.Schemas.Web
@using Microsoft.Extensions.Localization
@inject NoteActions NoteActions;
@inject IStringLocalizer<Localization> Loc;
<div class="poll">
@if (CanVote())
{
<div class="poll-options">
@foreach (var (choice, i) in Poll.Choices.Select((c, i) => (c, i)))
{
<span class="poll-option">
@if (Poll.Multiple)
{
<input type="checkbox" @onchange="() => SelectMultiple(i)" id="option-@i" name="poll" checked="@choice.Voted" disabled="@choice.Voted"/>
}
else
{
<input type="radio" @onchange="() => SelectSingle(i)" id="option-@i" name="poll"/>
}
<label for="option-@i">
<MfmText Text="@choice.Value" Emoji="@Emoji" Simple="true"/>
</label>
</span>
}
<button class="button" @onclick="Vote" disabled="@(Choices.Count == 0)">@Loc["Vote"]</button>
</div>
}
else
{
<div class="poll-results">
@{ var total = Poll.Choices.Sum(p => p.Votes); }
@foreach (var choice in Poll.Choices)
{
var percentage = total == 0 ? 0 : Math.Floor(choice.Votes / (double)total * 100);
<span class="poll-result @(choice.Voted ? "voted" : "")" style="--percentage: @percentage%;">
<span class="poll-value">
<MfmText Text="@choice.Value" Emoji="@Emoji" Simple="true"/>
</span>
<span class="poll-info"><span class="vote-count">@Loc["{0} votes", choice.Votes]</span><span class="vote-percentage">@percentage%</span></span>
</span>
}
</div>
}
@{
List<string> footerText = [];
@if (Poll.Multiple)
footerText.Add(Loc["Multiple choice"]);
@if (Poll.VotersCount != null)
footerText.Add(Loc["{0} users voted", Poll.VotersCount]);
@if (Poll.ExpiresAt != null)
footerText.Add(Poll.ExpiresAt <= DateTime.UtcNow ? Loc["Ended"] : Loc["Ends at {0}", Poll.ExpiresAt.Value.ToLocalTime().ToString("G")]);
}
<span class="poll-footer">@string.Join(" - ", footerText)</span>
</div>
@code {
[Parameter, EditorRequired] public required NotePollSchema Poll { get; set; }
[Parameter, EditorRequired] public required List<EmojiResponse> Emoji { get; set; }
private List<int> Choices { get; set; } = [];
private bool CanVote()
{
return !Poll.Choices.Any(p => p.Voted) && (Poll.ExpiresAt == null || Poll.ExpiresAt > DateTime.UtcNow);
}
private void SelectMultiple(int choice)
{
if (Choices.Contains(choice))
Choices.RemoveAll(p => p == choice);
else
Choices.Add(choice);
}
private void SelectSingle(int choice)
{
Choices = [choice];
}
private async Task Vote()
{
if (!CanVote()) return;
await NoteActions.AddPollVoteAsync(Poll, Choices);
}
}