From 09d8392a287345c5e5dc7e8198cee7188ace1fcd Mon Sep 17 00:00:00 2001 From: "Roberto.silva" Date: Fri, 6 Feb 2026 10:29:08 -0600 Subject: [PATCH] Deshacerse de todos estos query params de la URL fix #80 --- src/routes/planes/$planId/_detalle.tsx | 22 +-- .../planes/$planId/_detalle/historial.tsx | 22 +-- src/routes/planes/$planId/_detalle/index.tsx | 7 +- src/routes/planes/$planId/_detalle/mapa.tsx | 132 +++++++++--------- 4 files changed, 81 insertions(+), 102 deletions(-) diff --git a/src/routes/planes/$planId/_detalle.tsx b/src/routes/planes/$planId/_detalle.tsx index 94f1c29..0dcf508 100644 --- a/src/routes/planes/$planId/_detalle.tsx +++ b/src/routes/planes/$planId/_detalle.tsx @@ -26,8 +26,6 @@ import { qk } from '@/data/query/keys' export const Route = createFileRoute('/planes/$planId/_detalle')({ loader: async ({ context: { queryClient }, params: { planId } }) => { try { - console.log('loader') - await queryClient.ensureQueryData({ queryKey: qk.plan(planId), queryFn: () => plans_get(planId), @@ -35,8 +33,6 @@ export const Route = createFileRoute('/planes/$planId/_detalle')({ } catch (e: any) { // PGRST116: The result contains 0 rows if (e?.code === 'PGRST116') { - console.log('not found on', Route.path) - throw notFound() } throw e @@ -85,7 +81,6 @@ function RouteComponent() { } const handleSave = () => { - console.log('Guardando en DB...', { nombrePlan, nivelPlan }) // Aquí iría tu mutation setIsDirty(false) } @@ -221,11 +216,7 @@ function RouteComponent() { Datos Generales - + Mapa Curricular @@ -240,13 +231,7 @@ function RouteComponent() { Documento - + Historial @@ -300,7 +285,6 @@ const InfoCard = forwardRef< function Tab({ to, params, - search, children, }: { to: string @@ -308,12 +292,10 @@ function Tab({ search?: any children: React.ReactNode }) { - console.log(search) return ( ({ - structure: search.structure ?? null, - }), }) const getEventConfig = (tipo: string, campo: string) => { @@ -61,14 +58,23 @@ const getEventConfig = (tipo: string, campo: string) => { function RouteComponent() { const { planId } = Route.useParams() const { data: rawData, isLoading } = usePlanHistorial(planId) - const { structure } = Route.useSearch() - console.log(structure?.vigencia?.title) - console.log(structure) + const [structure, setStructure] = useState(null) + const { data } = usePlan(planId) + console.log('analizando estructura') + + console.log(data?.estructuras_plan?.definicion?.properties) + // console.log(structure) // ESTADOS PARA EL MODAL const [selectedEvent, setSelectedEvent] = useState(null) const [isModalOpen, setIsModalOpen] = useState(false) + useEffect(() => { + if (data?.estructuras_plan?.definicion?.properties) { + setStructure(data.estructuras_plan.definicion.properties) + } + }, [data]) + const historyEvents = useMemo(() => { if (!rawData) return [] return rawData.map((item: any) => { diff --git a/src/routes/planes/$planId/_detalle/index.tsx b/src/routes/planes/$planId/_detalle/index.tsx index d4582e4..86587ae 100644 --- a/src/routes/planes/$planId/_detalle/index.tsx +++ b/src/routes/planes/$planId/_detalle/index.tsx @@ -107,8 +107,6 @@ function DatosGeneralesPage() { setCampos(datosTransformados) } - - console.log(properties) }, [data]) // 3. Manejadores de acciones (Ahora como funciones locales) @@ -166,8 +164,6 @@ function DatosGeneralesPage() { } const handleIARequest = (clave: string) => { - console.log(clave) - navigate({ to: '/planes/$planId/iaplan', params: { @@ -190,9 +186,8 @@ function DatosGeneralesPage() {
- {campos.map((campo, key) => { + {campos.map((campo) => { const isEditing = editingId === campo.id - console.log(campo) return (
({ - ciclo: search.ciclo ?? null, - }), }) function MapaCurricularPage() { const { planId } = Route.useParams() // Idealmente usa el ID de la ruta - const { ciclo } = Route.useSearch() + const { data } = usePlan(planId) + const [ciclo, setCiclo] = useState(0) const [editingLineaId, setEditingLineaId] = useState(null) const [tempNombreLinea, setTempNombreLinea] = useState('') const { mutate: createLinea } = useCreateLinea() const { mutate: updateLineaApi } = useUpdateLinea() const { mutate: deleteLineaApi } = useDeleteLinea() - // 1. Fetch de Datos const { data: asignaturasApi, isLoading: loadingAsig } = usePlanAsignaturas(planId) const { data: lineasApi, isLoading: loadingLineas } = usePlanLineas(planId) - - // 2. Estado Local (Para interactividad) const [asignaturas, setAsignaturas] = useState>([]) const [lineas, setLineas] = useState>([]) const [draggedAsignatura, setDraggedAsignatura] = useState( null, ) const [isEditModalOpen, setIsEditModalOpen] = useState(false) - const [selectedAsignatura, setSelectedAsignatura] = - useState(null) - const [hasAreaComun, setHasAreaComun] = useState(false) const [nombreNuevaLinea, setNombreNuevaLinea] = useState('') // Para el input de nombre personalizado - const { mutate: updateAsignatura, isPending } = useUpdateAsignatura() + const { mutate: updateAsignatura } = useUpdateAsignatura() + const [seriacionValue, setSeriacionValue] = useState('unassigned') + + useEffect(() => { + if (data?.numero_ciclos) { + setCiclo(data.numero_ciclos) + } + }, [data]) const manejarAgregarLinea = (nombre: string) => { const nombreNormalizado = nombre.trim() - - // 1. Validar vacío if (!nombreNormalizado) return - - // 2. Validar duplicados en el estado local (Insensible a mayúsculas/acentos) const nombreBusqueda = nombreNormalizado .toLowerCase() .normalize('NFD') @@ -219,12 +215,9 @@ function MapaCurricularPage() { if (yaExiste) { alert(`La línea "${nombreNormalizado}" ya existe en este plan.`) - return // DETIENE la ejecución aquí, no llega a la mutación + return } - - // 3. Si pasa las validaciones, procedemos con la persistencia const maxOrden = lineas.reduce((max, l) => Math.max(max, l.orden || 0), 0) - createLinea( { nombre: nombreNormalizado, @@ -234,7 +227,6 @@ function MapaCurricularPage() { }, { onSuccess: (nueva) => { - // Sincronización local que ya teníamos const mapeada = { id: nueva.id, nombre: nueva.nombre, @@ -280,7 +272,6 @@ function MapaCurricularPage() { ) }, [lineas]) - // 3. Sincronizar API -> Estado Local useEffect(() => { if (asignaturasApi) setAsignaturas(mapAsignaturasToAsignaturas(asignaturasApi)) @@ -292,20 +283,27 @@ function MapaCurricularPage() { const ciclosTotales = Number(ciclo) const ciclosArray = Array.from({ length: ciclosTotales }, (_, i) => i + 1) - - // Nuevo estado para controlar los datos temporales del modal de edición const [editingData, setEditingData] = useState(null) + const handleDecimalChange = (value: string, max?: number): string | null => { + if (value === '') return '' - // 1. FUNCION DE GUARDAR MODAL + const val = value.replace(',', '.') + const regex = /^\d*\.?\d{0,2}$/ + if (!regex.test(val)) return null + if (max !== undefined) { + const num = Number(val) + if (!isNaN(num) && num > max) { + return max.toFixed(2) + } + } + + return val + } const handleSaveChanges = () => { if (!editingData) return - console.log(asignaturas) - setAsignaturas((prev) => prev.map((m) => (m.id === editingData.id ? { ...editingData } : m)), ) - // setIsEditModalOpen(false) - // Preparamos el patch con la estructura de tu tabla const patch = { nombre: editingData.nombre, codigo: editingData.clave, @@ -332,22 +330,11 @@ function MapaCurricularPage() { }, ) } - - // 2. MODIFICACIÓN: Zona de soltado siempre visible - // Cambiamos la condición: Mostramos la sección si hay asignaturas sin asignar - // O si simplemente queremos tener el "depósito" disponible. const unassignedAsignaturas = asignaturas.filter( (m) => m.ciclo === null || m.lineaCurricularId === null, ) - // --- Lógica de Gestión --- - const agregarLinea = (nombre: string) => { - const nueva = { id: crypto.randomUUID(), nombre, orden: lineas.length + 1 } - setLineas([...lineas, nueva]) - } - const borrarLinea = (id: string) => { - // 1. Opcional: Confirmación de seguridad if ( !confirm( '¿Estás seguro de eliminar esta línea? Las materias asignadas volverán a la bandeja de entrada.', @@ -356,11 +343,8 @@ function MapaCurricularPage() { return } - // 2. Llamada a la API deleteLineaApi(id, { onSuccess: () => { - // 3. Actualización instantánea del estado local - // Primero: Las materias que estaban en esa línea pasan a ser "huérfanas" setAsignaturas((prev) => prev.map((asig) => @@ -369,8 +353,6 @@ function MapaCurricularPage() { : asig, ), ) - - // Segundo: Quitamos la línea del estado setLineas((prev) => prev.filter((l) => l.id !== id)) }, onError: (error) => { @@ -427,8 +409,6 @@ function MapaCurricularPage() { : m, ), ) - - // 2. Persistir en la API const patch = { numero_ciclo: ciclo, linea_plan_id: lineaId, @@ -774,13 +754,17 @@ function MapaCurricularPage() { - setEditingData({ - ...editingData, - creditos: Number(e.target.value), - }) - } + onChange={(e) => { + const val = handleDecimalChange(e.target.value, 10) + if (val !== null) { + setEditingData({ + ...editingData, + creditos: val === '' ? 0 : Number(val), + }) + } + }} />
@@ -790,12 +774,15 @@ function MapaCurricularPage() { - setEditingData({ - ...editingData, - hd: Number(e.target.value), - }) - } + onChange={(e) => { + const val = handleDecimalChange(e.target.value, 10) + if (val !== null) { + setEditingData({ + ...editingData, + hd: Number(e.target.value), + }) + } + }} />
@@ -805,12 +792,15 @@ function MapaCurricularPage() { - setEditingData({ - ...editingData, - hi: Number(e.target.value), - }) - } + onChange={(e) => { + const val = handleDecimalChange(e.target.value, 10) + if (val !== null) { + setEditingData({ + ...editingData, + hi: Number(e.target.value), + }) + } + }} />
@@ -882,23 +872,29 @@ function MapaCurricularPage() { Seriación (Prerrequisitos)