Add joker support during voting

This commit is contained in:
2026-02-05 13:09:45 +01:00
parent 434a0f05fc
commit 41d88016ea
16 changed files with 407 additions and 7 deletions

View File

@@ -44,7 +44,7 @@ public static class AdminEndpoints
.AsNoTracking()
.Where(p => p.CurrentPhase == Phase.Vote || p.Suggestions.Any())
.OrderBy(p => p.DisplayName ?? p.Username)
.Select(p => new VoteStatusDto(p.Id, p.DisplayName ?? p.Username, p.VotesFinal))
.Select(p => new VoteStatusDto(p.Id, p.DisplayName ?? p.Username, p.VotesFinal, p.HasJoker))
.ToListAsync();
var waiting = voters.Where(v => !v.Finalized).Select(v => v.Name).ToList();
@@ -52,6 +52,23 @@ public static class AdminEndpoints
return Results.Ok(new { voters, ready, waiting });
});
admin.MapPost("/joker", async ([FromBody] GrantJokerRequest request, HttpContext ctx, AppDbContext db, IConfiguration config) =>
{
if (!await EndpointHelpers.IsAdmin(ctx, db, config)) return Results.Unauthorized();
var player = await db.Players.FirstOrDefaultAsync(p => p.Id == request.PlayerId);
if (player is null) return Results.NotFound(new { error = "Player not found." });
var phase = await EndpointHelpers.GetPhase(db, player.Id);
if (phase != Phase.Vote)
return Results.BadRequest(new { error = "Player must be in the Vote phase to receive a joker." });
player.HasJoker = true;
player.VotesFinal = false;
await db.SaveChangesAsync();
return Results.Ok(new { player.Id, player.HasJoker });
});
admin.MapPost("/link-suggestions", async ([FromBody] LinkSuggestionsRequest request, HttpContext ctx, AppDbContext db, IConfiguration config) =>
{
var player = await EndpointHelpers.GetAuthenticatedPlayer(ctx, db);
@@ -187,7 +204,8 @@ public static class AdminEndpoints
await db.Suggestions.ExecuteDeleteAsync();
await db.Players.ExecuteUpdateAsync(p => p.SetProperty(x => x.CurrentPhase, Phase.Suggest)
.SetProperty(x => x.VotesFinal, false));
.SetProperty(x => x.VotesFinal, false)
.SetProperty(x => x.HasJoker, false));
var state = await db.AppState.FirstAsync();
state.ResultsOpen = false;
state.UpdatedAt = DateTimeOffset.UtcNow;

View File

@@ -21,6 +21,7 @@ public static class StateEndpoints
{
CurrentPhase = phase,
player.VotesFinal,
player.HasJoker,
state.ResultsOpen,
state.UpdatedAt,
Players = await db.Players.CountAsync(),
@@ -35,7 +36,7 @@ public static class StateEndpoints
var player = await EndpointHelpers.GetAuthenticatedPlayer(ctx, db);
if (player is null) return Results.Unauthorized();
var phase = await EndpointHelpers.GetPhase(db, player.Id);
return Results.Ok(new { player.Id, player.DisplayName, player.Username, player.IsAdmin, CurrentPhase = phase, player.VotesFinal });
return Results.Ok(new { player.Id, player.DisplayName, player.Username, player.IsAdmin, CurrentPhase = phase, player.VotesFinal, player.HasJoker });
});
app.MapPost("/api/me/phase/next", async (HttpContext ctx, AppDbContext db, IConfiguration config) =>

View File

@@ -62,7 +62,8 @@ public static class SuggestEndpoints
var player = await EndpointHelpers.GetAuthenticatedPlayer(ctx, db);
if (player is null) return Results.Unauthorized();
var phase = await EndpointHelpers.GetPhase(db, player.Id);
if (phase != Phase.Suggest)
var usingJoker = phase == Phase.Vote && player.HasJoker;
if (phase != Phase.Suggest && !usingJoker)
return EndpointHelpers.PhaseMismatch(Phase.Suggest, phase);
if (string.IsNullOrWhiteSpace(player.DisplayName))
@@ -90,6 +91,13 @@ public static class SuggestEndpoints
};
db.Suggestions.Add(suggestion);
if (usingJoker)
{
player.HasJoker = false;
await db.Players.ExecuteUpdateAsync(p => p.SetProperty(x => x.VotesFinal, false));
}
await db.SaveChangesAsync();
return Results.Created($"/api/suggestions/{suggestion.Id}", new { suggestion.Id });