fix(onboarding): require fields before advancing steps

- Validate each step before allowing goNext
- Show required error message on name step if empty
- Clear error on input change

💘 Generated with Crush

Assisted-by: MiniMax-M2.7 via Crush <crush@charm.land>
This commit is contained in:
Augustin
2026-04-22 20:58:36 +02:00
parent 275a9a4cc7
commit b6147ddb12

View File

@@ -25,14 +25,31 @@ export default function OnboardingWizard({ api, onComplete }) {
}) })
const [saving, setSaving] = useState(false) const [saving, setSaving] = useState(false)
const [error, setError] = useState(null) const [error, setError] = useState(null)
const [requiredError, setRequiredError] = useState(false)
const current = STEPS[step] const current = STEPS[step]
const layouts = getLayoutList() const layouts = getLayoutList()
const goNext = () => { const goNext = () => {
if (step < STEPS.length - 1) setStep(step + 1) if (step < STEPS.length - 1) {
if (!canProceed) { setRequiredError(true); return }
setRequiredError(false)
setStep(step + 1)
}
} }
const canProceed = (() => {
switch (current.key) {
case 'welcome': return true
case 'name': return answers.name.trim().length > 0
case 'language': return !!answers.language
case 'keyboard': return !!answers.keyboard
case 'editor': return true
case 'done': return true
default: return true
}
})()
const goPrev = () => { const goPrev = () => {
if (step > 0) setStep(step - 1) if (step > 0) setStep(step - 1)
} }
@@ -103,9 +120,10 @@ export default function OnboardingWizard({ api, onComplete }) {
className="onboarding-input" className="onboarding-input"
placeholder="Votre nom..." placeholder="Votre nom..."
value={answers.name} value={answers.name}
onChange={e => setAnswers(a => ({ ...a, name: e.target.value }))} onChange={e => { setAnswers(a => ({ ...a, name: e.target.value })); setRequiredError(false) }}
autoFocus autoFocus
/> />
{requiredError && <div className="onboarding-required">Veuillez entrer votre nom</div>}
</div> </div>
)} )}
@@ -205,6 +223,11 @@ export default function OnboardingWizard({ api, onComplete }) {
Suivant <ArrowRight size={14} /> Suivant <ArrowRight size={14} />
</button> </button>
)} )}
{step === STEPS.length - 1 && !saving && !error && (
<button className="primary" onClick={handleSave}>
Commencer
</button>
)}
</div> </div>
</div> </div>
@@ -256,6 +279,9 @@ export default function OnboardingWizard({ api, onComplete }) {
padding: 16px 20px; border-top: 1px solid var(--border); padding: 16px 20px; border-top: 1px solid var(--border);
background: var(--bg-surface); background: var(--bg-surface);
} }
.onboarding-required {
font-size: 12px; color: var(--error); margin-top: 4px;
}
`}</style> `}</style>
</div> </div>
) )