diff --git a/src/components/asignaturas/wizard/PasoBasicosForm.tsx b/src/components/asignaturas/wizard/PasoBasicosForm.tsx index dff2726..6c6c0d3 100644 --- a/src/components/asignaturas/wizard/PasoBasicosForm.tsx +++ b/src/components/asignaturas/wizard/PasoBasicosForm.tsx @@ -27,14 +27,25 @@ export function PasoBasicosForm({ const [creditosInput, setCreditosInput] = useState(() => { const c = Number(wizard.datosBasicos.creditos ?? 0) - return c > 0 ? c.toFixed(2) : '' + let newC = c + console.log('antes', newC) + + if (Number.isFinite(c) && c > 999) { + newC = 999 + } + console.log('desp', newC) + return newC > 0 ? newC.toFixed(2) : '' }) const [creditosFocused, setCreditosFocused] = useState(false) useEffect(() => { if (creditosFocused) return const c = Number(wizard.datosBasicos.creditos ?? 0) - setCreditosInput(c > 0 ? c.toFixed(2) : '') + let newC = c + if (Number.isFinite(c) && c > 999) { + newC = 999 + } + setCreditosInput(newC > 0 ? newC.toFixed(2) : '') }, [wizard.datosBasicos.creditos, creditosFocused]) return ( @@ -44,6 +55,7 @@ export function PasoBasicosForm({ onChange( @@ -67,6 +79,7 @@ export function PasoBasicosForm({ onChange( @@ -123,6 +136,7 @@ export function PasoBasicosForm({ id="creditos" type="text" inputMode="decimal" + maxLength={6} pattern="^\\d*(?:[.,]\\d{0,2})?$" value={creditosInput} onKeyDown={(e) => { @@ -144,7 +158,7 @@ export function PasoBasicosForm({ } const normalized = raw.replace(',', '.') - const asNumber = Number.parseFloat(normalized) + let asNumber = Number.parseFloat(normalized) if (!Number.isFinite(asNumber) || asNumber <= 0) { setCreditosInput('') onChange((w) => ({ @@ -154,6 +168,9 @@ export function PasoBasicosForm({ return } + // Cap to 999 + if (asNumber > 999) asNumber = 999 + const fixed = asNumber.toFixed(2) setCreditosInput(fixed) onChange((w) => ({ @@ -174,6 +191,22 @@ export function PasoBasicosForm({ if (!/^\d*(?:[.,]\d{0,2})?$/.test(nextRaw)) return + // If typed number exceeds 999, cap it immediately (prevents entering >999) + const asNumberRaw = Number.parseFloat(nextRaw.replace(',', '.')) + if (Number.isFinite(asNumberRaw) && asNumberRaw > 999) { + // show capped value to the user + const cappedStr = '999.00' + setCreditosInput(cappedStr) + onChange((w) => ({ + ...w, + datosBasicos: { + ...w.datosBasicos, + creditos: 999, + }, + })) + return + } + setCreditosInput(nextRaw) const asNumber = Number.parseFloat(nextRaw.replace(',', '.')) @@ -191,94 +224,6 @@ export function PasoBasicosForm({ /> -
- - { - if (['.', ',', '-', 'e', 'E', '+'].includes(e.key)) { - e.preventDefault() - } - }} - onChange={(e: React.ChangeEvent) => - onChange( - (w): NewSubjectWizardState => ({ - ...w, - datosBasicos: { - ...w.datosBasicos, - horasAcademicas: (() => { - const raw = e.target.value - if (raw === '') return null - const asNumber = Number(raw) - if (Number.isNaN(asNumber)) return null - // Coerce to positive integer (natural numbers without zero) - const n = Math.floor(Math.abs(asNumber)) - return n >= 1 ? n : 1 - })(), - }, - }), - ) - } - className="placeholder:text-muted-foreground/70 font-medium not-italic placeholder:font-normal placeholder:italic" - placeholder="Ej. 48" - /> -
- -
- - { - if (['.', ',', '-', 'e', 'E', '+'].includes(e.key)) { - e.preventDefault() - } - }} - onChange={(e: React.ChangeEvent) => - onChange( - (w): NewSubjectWizardState => ({ - ...w, - datosBasicos: { - ...w.datosBasicos, - horasIndependientes: (() => { - const raw = e.target.value - if (raw === '') return null - const asNumber = Number(raw) - if (Number.isNaN(asNumber)) return null - // Coerce to positive integer (natural numbers without zero) - const n = Math.floor(Math.abs(asNumber)) - return n >= 1 ? n : 1 - })(), - }, - }), - ) - } - className="placeholder:text-muted-foreground/70 font-medium not-italic placeholder:font-normal placeholder:italic" - placeholder="Ej. 24" - /> -
-
{ + if (['.', ',', '-', 'e', 'E', '+'].includes(e.key)) { + e.preventDefault() + } + }} + onChange={(e: React.ChangeEvent) => + onChange( + (w): NewSubjectWizardState => ({ + ...w, + datosBasicos: { + ...w.datosBasicos, + horasAcademicas: (() => { + const raw = e.target.value + if (raw === '') return null + const asNumber = Number(raw) + if (Number.isNaN(asNumber)) return null + // Coerce to positive integer (natural numbers without zero) + const n = Math.floor(Math.abs(asNumber)) + const capped = Math.min(n >= 1 ? n : 1, 999) + return capped + })(), + }, + }), + ) + } + className="placeholder:text-muted-foreground/70 font-medium not-italic placeholder:font-normal placeholder:italic" + placeholder="Ej. 48" + /> +
+ +
+ + { + if (['.', ',', '-', 'e', 'E', '+'].includes(e.key)) { + e.preventDefault() + } + }} + onChange={(e: React.ChangeEvent) => + onChange( + (w): NewSubjectWizardState => ({ + ...w, + datosBasicos: { + ...w.datosBasicos, + horasIndependientes: (() => { + const raw = e.target.value + if (raw === '') return null + const asNumber = Number(raw) + if (Number.isNaN(asNumber)) return null + // Coerce to positive integer (natural numbers without zero) + const n = Math.floor(Math.abs(asNumber)) + const capped = Math.min(n >= 1 ? n : 1, 999) + return capped + })(), + }, + }), + ) + } + className="placeholder:text-muted-foreground/70 font-medium not-italic placeholder:font-normal placeholder:italic" + placeholder="Ej. 24" + /> +
) } diff --git a/src/components/asignaturas/wizard/PasoDetallesPanel.tsx b/src/components/asignaturas/wizard/PasoDetallesPanel.tsx index 612d4fc..7b672f1 100644 --- a/src/components/asignaturas/wizard/PasoDetallesPanel.tsx +++ b/src/components/asignaturas/wizard/PasoDetallesPanel.tsx @@ -56,6 +56,7 @@ export function PasoDetallesPanel({