Add client-side player count validation

This commit is contained in:
2026-02-06 22:42:54 +01:00
parent dffeec85f3
commit c64ac7480d
3 changed files with 40 additions and 0 deletions

View File

@@ -33,3 +33,13 @@ input[readonly].readonly {
color: #6f6353;
cursor: not-allowed;
}
.form-error {
color: #b23b3b;
font-weight: 600;
}
.input-error {
border-color: #b23b3b;
box-shadow: 0 0 0 2px rgba(178, 59, 59, 0.1);
}

View File

@@ -62,6 +62,7 @@ const translations = {
"form.placeholder.screenshot": "Screenshot URL",
"form.placeholder.youtube": "YouTube URL",
"form.placeholder.gameUrl": "Game website URL",
"form.playersInvalid": "Players must be between 1 and 32, and min cannot exceed max.",
"section.mySuggestions": "Your suggestions",
"section.allSuggestions": "All suggestions",
@@ -227,6 +228,7 @@ const translations = {
"form.placeholder.screenshot": "Screenshot-URL",
"form.placeholder.youtube": "YouTube-URL",
"form.placeholder.gameUrl": "Spiel-Webseite",
"form.playersInvalid": "Spielerzahl muss zwischen 1 und 32 liegen, und Min darf Max nicht überschreiten.",
"section.mySuggestions": "Deine Vorschläge",
"section.allSuggestions": "Alle Vorschläge",

View File

@@ -512,6 +512,7 @@ function buildSuggestionForm(initial = {}, lockTitle = false) {
<input name="maxPlayers" type="number" min="1" max="32" inputmode="numeric" />
</label>
</div>
<div class="form-error hidden" data-error="players"></div>
</div>
<label class="stack">
<span class="label-row">
@@ -614,6 +615,33 @@ function openSuggestionModal({ title, submitLabel, initial = {}, onSubmit, lockT
form.addEventListener("submit", async (e) => {
e.preventDefault();
const data = normalizeSuggestionForm(new FormData(form));
const errorBox = form.querySelector('[data-error="players"]');
const minInput = form.querySelector('input[name="minPlayers"]');
const maxInput = form.querySelector('input[name="maxPlayers"]');
const markError = (msg) => {
if (errorBox) {
errorBox.textContent = msg;
errorBox.classList.remove("hidden");
}
};
const clearError = () => {
if (errorBox) errorBox.classList.add("hidden");
};
clearError();
const min = data.minPlayers;
const max = data.maxPlayers;
const inRange = (v) => v == null || (Number.isInteger(v) && v >= 1 && v <= 32);
const valid =
inRange(min) &&
inRange(max) &&
(min == null || max == null || min <= max);
[minInput, maxInput].forEach((el) =>
el?.classList.toggle("input-error", !valid),
);
if (!valid) {
markError(t("form.playersInvalid"));
return;
}
if (data.screenshotUrl && !isValidImageUrl(data.screenshotUrl)) {
return toast(t("toast.invalidImageUrl"), true);
}