diff --git a/src/components/asignaturas/detalle/MateriaDetailPage.tsx b/src/components/asignaturas/detalle/MateriaDetailPage.tsx index a7c4883..1922bb5 100644 --- a/src/components/asignaturas/detalle/MateriaDetailPage.tsx +++ b/src/components/asignaturas/detalle/MateriaDetailPage.tsx @@ -73,15 +73,13 @@ function EditableHeaderField({ } return ( - - {value} - + onSave(e.target.value)} + onBlur={(e) => onSave(e.target.value)} + className={`border-none bg-transparent outline-none focus:ring-2 focus:ring-blue-400 ${className}`} + /> ) } @@ -97,6 +95,9 @@ export default function MateriaDetailPage() { const { asignaturaId } = useParams({ from: '/planes/$planId/asignaturas/$asignaturaId', }) + const { planId } = useParams({ + from: '/planes/$planId/asignaturas/$asignaturaId', + }) const { data: asignaturasApi, isLoading: loadingAsig } = useSubject(asignaturaId) // 1. Asegúrate de tener estos estados en tu componente principal @@ -116,10 +117,10 @@ export default function MateriaDetailPage() { useEffect(() => { if (asignaturasApi) { setHeaderData({ - codigo: asignaturasApi?.codigo ?? '', - nombre: asignaturasApi?.nombre ?? '', - creditos: asignaturasApi?.creditos ?? '', - ciclo: asignaturasApi?.numero_ciclo ?? 0, + codigo: asignaturasApi.codigo ?? '', + nombre: asignaturasApi.nombre, + creditos: asignaturasApi.creditos, + ciclo: asignaturasApi.numero_ciclo ?? 0, }) } }, [asignaturasApi]) @@ -194,6 +195,7 @@ export default function MateriaDetailPage() {
Volver al plan diff --git a/src/routes/planes/$planId/_detalle/mapa.tsx b/src/routes/planes/$planId/_detalle/mapa.tsx index 985604e..218b4ec 100644 --- a/src/routes/planes/$planId/_detalle/mapa.tsx +++ b/src/routes/planes/$planId/_detalle/mapa.tsx @@ -177,7 +177,29 @@ function MapaCurricularPage() { const manejarAgregarLinea = (nombre: string) => { const nombreNormalizado = nombre.trim() - // Validar si es Área Común (insensible a mayúsculas/minúsculas) + // 1. Validar que no esté vacío + if (!nombreNormalizado) return + + // 2. Validar duplicados (Insensible a mayúsculas/minúsculas y acentos) + const nombreParaComparar = nombreNormalizado + .toLowerCase() + .normalize('NFD') + .replace(/[\u0300-\u036f]/g, '') + + const yaExiste = lineas.some((l) => { + const lineaNombreBase = l.nombre + .toLowerCase() + .normalize('NFD') + .replace(/[\u0300-\u036f]/g, '') + return lineaNombreBase === nombreParaComparar + }) + + if (yaExiste) { + alert(`La línea "${nombreNormalizado}" ya existe.`) + return + } + + // 3. Validar Área Común (usando tu lógica previa) const esAreaComun = nombreNormalizado.toLowerCase() === 'área común' || nombreNormalizado.toLowerCase() === 'area comun' @@ -187,10 +209,12 @@ function MapaCurricularPage() { return } + // 4. Agregar la línea si todo está bien const nueva = { id: crypto.randomUUID(), nombre: nombreNormalizado, orden: lineas.length + 1, + color: '#1976d2', } setLineas([...lineas, nueva]) @@ -198,6 +222,7 @@ function MapaCurricularPage() { if (esAreaComun) { setHasAreaComun(true) } + setNombreNuevaLinea('') // Limpiar input } @@ -599,19 +624,46 @@ function MapaCurricularPage() { - + + setEditingData({ + ...editingData, + creditos: Number(e.target.value), + }) + } + />
- + + setEditingData({ + ...editingData, + hd: Number(e.target.value), + }) + } + />
- + + setEditingData({ + ...editingData, + hi: Number(e.target.value), + }) + } + />
@@ -621,11 +673,22 @@ function MapaCurricularPage() { - + setEditingData({ + ...editingData, + ciclo: val === 'unassigned' ? null : Number(val), + }) + } + > + + -- Sin Asignar -- + {ciclosArray.map((n) => ( Ciclo {n} @@ -634,15 +697,27 @@ function MapaCurricularPage() { +
- + setEditingData({ + ...editingData, + lineaCurricularId: val === 'unassigned' ? null : val, + }) + } + > + + -- Sin Asignar -- + {lineas.map((l) => ( {l.nombre} @@ -689,7 +764,12 @@ function MapaCurricularPage() { - + setEditingData({ ...editingData, tipo: val }) + } + >