Add inline timer form validation
All checks were successful
Deploy Sokko G / deploy (push) Successful in 7s

This commit is contained in:
Shinuwa 2026-08-03 16:20:05 +02:00
parent 3e16ea278d
commit d54a93e1f4
6 changed files with 80 additions and 4 deletions

View file

@ -94,6 +94,27 @@ function hasTimePartValue(parts) {
return Boolean(String(parts?.hours || "").trim() || String(parts?.minutes || "").trim() || String(parts?.seconds || "").trim());
}
function getCountdownValidationError(type, draft, textContent) {
const requiredError = textContent.requiredError || "Valeur requise.";
const invalidError = textContent.invalidError || "Valeur invalide.";
if (type === "duration" && timePartsToDurationMs(draft.duration) <= 0) {
return requiredError;
}
if (type === "daily_time" && !timePartsToString(draft.time)) {
return invalidError;
}
if (type === "time_pattern") {
if (!hasTimePartValue(draft.pattern)) return requiredError;
if (!timePartsToString(draft.pattern, { allowWildcard: true })) return invalidError;
}
if (type === "interval") {
const startTimeHasValue = hasTimePartValue(draft.intervalStartTime);
if (timePartsToDurationMs(draft.interval) <= 0) return requiredError;
if (startTimeHasValue && !timePartsToString(draft.intervalStartTime)) return invalidError;
}
return "";
}
export function TimerModule({ toolboxId, moduleId, context }) {
const data = context.normalizeTimerData(context.getModuleData(toolboxId, moduleId, { activeTab: "stopwatch" }));
const textContent = context.moduleText?.timer || {};
@ -194,6 +215,8 @@ export function TimerModule({ toolboxId, moduleId, context }) {
function createCountdown(event) {
countdownDraft.handleSubmit(event, (draft, { updateValues }) => {
const type = COUNTDOWN_TYPES.includes(draft.type) ? draft.type : "duration";
const validationError = getCountdownValidationError(type, draft, textContent);
if (validationError) return validationError;
const label = draft.label.trim() || textContent.defaultCountdownLabel || "Timer";
const now = getNowMs();
let countdown = null;
@ -335,6 +358,7 @@ export function TimerModule({ toolboxId, moduleId, context }) {
<CountdownControls
textContent={textContent}
form={countdownDraft.values}
error={countdownDraft.error}
onChange={countdownDraft.updateValues}
onSubmit={createCountdown}
/>
@ -441,9 +465,9 @@ function StopwatchControls({ textContent, elapsedMs, running, onStart, onPause,
);
}
function CountdownControls({ textContent, form, onChange, onSubmit }) {
function CountdownControls({ textContent, form, error, onChange, onSubmit }) {
return (
<form className="timer-control-panel timer-countdown-form" role="tabpanel" onSubmit={onSubmit}>
<form className="timer-control-panel timer-countdown-form" role="tabpanel" onSubmit={onSubmit} aria-describedby={error ? "timer-countdown-error" : undefined}>
<label>
<span>{textContent.countdownLabel || "Libellé"}</span>
<input value={form.label} onChange={(event) => onChange({ label: event.target.value })} placeholder={textContent.countdownLabelPlaceholder || "Boss, event, craft..."} />
@ -490,6 +514,12 @@ function CountdownControls({ textContent, form, onChange, onSubmit }) {
</label>
</div>
)}
{error && (
<p id="timer-countdown-error" className="timer-form-error" role="alert">
<Icon name="close" />
<span>{error}</span>
</p>
)}
<button className="primary" type="submit">{textContent.addCountdownButton || "Ajouter"}</button>
</form>
);