diff --git a/Program.cs b/Program.cs index 8956825..d427b18 100644 --- a/Program.cs +++ b/Program.cs @@ -178,6 +178,11 @@ api.MapPost("/suggestions", async ([FromBody] SuggestionRequest request, HttpCon var player = await GetOrCreatePlayer(ctx, db); + if (string.IsNullOrWhiteSpace(player.DisplayName)) + { + return Results.BadRequest(new { error = "Set a display name before submitting suggestions." }); + } + var existingCount = await db.Suggestions.CountAsync(s => s.PlayerId == player.Id); if (existingCount >= 3) { @@ -263,6 +268,9 @@ api.MapPost("/votes", async ([FromBody] VoteRequest request, HttpContext ctx, Ap var player = await GetOrCreatePlayer(ctx, db); + if (string.IsNullOrWhiteSpace(player.DisplayName)) + return Results.BadRequest(new { error = "Set a display name before voting." }); + var suggestionExists = await db.Suggestions.AnyAsync(s => s.Id == request.SuggestionId); if (!suggestionExists) return Results.BadRequest(new { error = "Suggestion not found." }); diff --git a/wwwroot/app.js b/wwwroot/app.js index 7a9a1a9..c1add84 100644 --- a/wwwroot/app.js +++ b/wwwroot/app.js @@ -55,6 +55,7 @@ async function loadState() { if ($("player-id")) { $("player-id").textContent = `Player ID: ${me.id}`; } + applyNameRequirementUI(); } async function loadSuggestData() { @@ -97,6 +98,7 @@ function renderPhasePill() { if (phaseSelect && !phaseSelect.dataset.userEditing) { phaseSelect.value = state.phase || "Suggest"; } + applyNameRequirementUI(); } function renderCounts() { @@ -216,6 +218,7 @@ function setupHandlers() { state.me = me; nameInput.dataset.userEditing = ""; toast("Saved name"); + applyNameRequirementUI(); } catch (err) { toast(err.message, true); } @@ -335,6 +338,31 @@ function openLightbox(url, title) { document.body.appendChild(overlay); } +function applyNameRequirementUI() { + const requiresName = !state.me?.displayName?.trim(); + const warning = $("name-warning"); + if (warning) warning.classList.toggle("hidden", !requiresName); + + const suggestForm = $("suggest-form"); + if (suggestForm) { + suggestForm.querySelectorAll("input,textarea,button").forEach(el => { + if (el.id === "save-name") return; + el.disabled = requiresName; + }); + suggestForm.classList.toggle("disabled-form", requiresName); + } + + const voteList = $("vote-list"); + if (voteList) { + voteList.querySelectorAll("input[type=range]").forEach(el => el.disabled = requiresName); + voteList.classList.toggle("disabled-form", requiresName); + } + + if (requiresName && state.phase !== "Suggest") { + toast("Enter a name to continue.", true); + } +} + async function main() { setupHandlers(); try { diff --git a/wwwroot/styles.css b/wwwroot/styles.css index 3034d1c..83306d8 100644 --- a/wwwroot/styles.css +++ b/wwwroot/styles.css @@ -106,6 +106,8 @@ button.ghost { .label { color: #9ca3af; font-size: 12px; } .hint { color: #9ca3af; font-size: 12px; margin: 8px 0 0; } +.hint.warning { color: #f59e0b; } +.disabled-form { opacity: 0.5; pointer-events: none; } .card-grid { display: grid;