diff --git a/src/components/asignaturas/wizard/WizardControls.tsx b/src/components/asignaturas/wizard/WizardControls.tsx index fd26612..1b6cd8e 100644 --- a/src/components/asignaturas/wizard/WizardControls.tsx +++ b/src/components/asignaturas/wizard/WizardControls.tsx @@ -1,10 +1,6 @@ -import { useNavigate } from '@tanstack/react-router' - -import type { AIGenerateSubjectInput } from '@/data' import type { NewSubjectWizardState } from '@/features/asignaturas/nueva/types' import { Button } from '@/components/ui/button' -import { useGenerateSubjectAI } from '@/data' export function WizardControls({ wizard, @@ -16,6 +12,7 @@ export function WizardControls({ disableNext, disableCreate, isLastStep, + onCreate, }: { wizard: NewSubjectWizardState setWizard: React.Dispatch> @@ -26,9 +23,8 @@ export function WizardControls({ disableNext: boolean disableCreate: boolean isLastStep: boolean + onCreate: () => Promise | void }) { - const navigate = useNavigate() - const generateSubjectAI = useGenerateSubjectAI() const handleCreate = async () => { setWizard((w) => ({ ...w, @@ -37,46 +33,7 @@ export function WizardControls({ })) try { - if (wizard.tipoOrigen === 'IA') { - const aiInput: AIGenerateSubjectInput = { - plan_estudio_id: wizard.plan_estudio_id, - datosBasicos: { - nombre: wizard.datosBasicos.nombre, - codigo: wizard.datosBasicos.codigo, - tipo: wizard.datosBasicos.tipo!, - creditos: wizard.datosBasicos.creditos!, - horasIndependientes: wizard.datosBasicos.horasIndependientes, - horasAcademicas: wizard.datosBasicos.horasAcademicas, - estructuraId: wizard.datosBasicos.estructuraId!, - }, - iaConfig: { - descripcionEnfoqueAcademico: - wizard.iaConfig!.descripcionEnfoqueAcademico, - instruccionesAdicionalesIA: - wizard.iaConfig!.instruccionesAdicionalesIA, - archivosReferencia: wizard.iaConfig!.archivosReferencia, - repositoriosReferencia: - wizard.iaConfig!.repositoriosReferencia || [], - archivosAdjuntos: wizard.iaConfig!.archivosAdjuntos || [], - }, - } - - console.log( - `${new Date().toISOString()} - Enviando a generar asignatura con IA`, - ) - - const asignatura = await generateSubjectAI.mutateAsync(aiInput) - console.log( - `${new Date().toISOString()} - Asignatura IA generada`, - asignatura, - ) - - navigate({ - to: `/planes/${wizard.plan_estudio_id}/asignaturas/${asignatura.id}`, - state: { showConfetti: true }, - }) - return - } + await onCreate() } catch (err: any) { setWizard((w) => ({ ...w, diff --git a/src/components/planes/wizard/WizardControls.tsx b/src/components/planes/wizard/WizardControls.tsx index 446fd53..24ea695 100644 --- a/src/components/planes/wizard/WizardControls.tsx +++ b/src/components/planes/wizard/WizardControls.tsx @@ -1,6 +1,5 @@ import { useNavigate } from '@tanstack/react-router' -import type { AIGeneratePlanInput } from '@/data' import type { NivelPlanEstudio, TipoCiclo } from '@/data/types/domain' import type { NewPlanWizardState } from '@/features/planes/nuevo/types' // import type { Database } from '@/types/supabase' @@ -55,11 +54,11 @@ export function WizardControls({ ? wizard.datosBasicos.numCiclos : 1 - const aiInput: AIGeneratePlanInput = { + const aiInput = { datosBasicos: { nombrePlan: wizard.datosBasicos.nombrePlan, - carreraId: wizard.datosBasicos.carrera.id, - facultadId: wizard.datosBasicos.facultad.id, + carreraId: wizard.datosBasicos.carrera.id || undefined, + facultadId: wizard.datosBasicos.facultad.id || undefined, nivel: wizard.datosBasicos.nivel as string, tipoCiclo: tipoCicloSafe, numCiclos: numCiclosSafe, diff --git a/src/data/api/subjects.api.ts b/src/data/api/subjects.api.ts index 7488aab..b0b5f2a 100644 --- a/src/data/api/subjects.api.ts +++ b/src/data/api/subjects.api.ts @@ -11,12 +11,11 @@ import type { TipoAsignatura, UUID, } from '../types/domain' -import type { UploadedFile } from '@/components/planes/wizard/PasoDetallesPanel/FileDropZone' import type { Database } from '@/types/supabase' const EDGE = { subjects_create_manual: 'subjects_create_manual', - ai_generate_subject: 'ai-generate-subject', + ai_generate_subject: 'ai_generate_subject', subjects_persist_from_ai: 'subjects_persist_from_ai', subjects_clone_from_existing: 'subjects_clone_from_existing', subjects_import_from_file: 'subjects_import_from_file', @@ -103,58 +102,26 @@ export async function subjects_create_manual( return invokeEdge(EDGE.subjects_create_manual, payload) } -export type AIGenerateSubjectInput = { - plan_estudio_id: Asignatura['plan_estudio_id'] +export async function ai_generate_subject(payload: { + planId: UUID datosBasicos: { - nombre: Asignatura['nombre'] - codigo?: Asignatura['codigo'] - tipo: Asignatura['tipo'] | null - creditos: Asignatura['creditos'] | null - horasAcademicas?: Asignatura['horas_academicas'] | null - horasIndependientes?: Asignatura['horas_independientes'] | null - estructuraId: Asignatura['estructura_id'] | null + nombre: string + clave?: string + tipo: TipoAsignatura + creditos: number + horasSemana?: number + estructuraId: UUID } - // clonInterno?: { - // facultadId?: string - // carreraId?: string - // planOrigenId?: string - // asignaturaOrigenId?: string | null - // } - // clonTradicional?: { - // archivoWordAsignaturaId: string | null - // archivosAdicionalesIds: Array - // } - iaConfig?: { - descripcionEnfoqueAcademico: string - instruccionesAdicionalesIA: string - archivosReferencia: Array - repositoriosReferencia?: Array - archivosAdjuntos?: Array + iaConfig: { + descripcionEnfoque: string + notasAdicionales?: string + archivosExistentesIds?: Array + repositoriosIds?: Array + archivosAdhocIds?: Array + usarMCP?: boolean } -} - -export async function ai_generate_subject( - input: AIGenerateSubjectInput, -): Promise { - const edgeFunctionBody = new FormData() - edgeFunctionBody.append('plan_estudio_id', input.plan_estudio_id) - edgeFunctionBody.append('datosBasicos', JSON.stringify(input.datosBasicos)) - edgeFunctionBody.append( - 'iaConfig', - JSON.stringify({ - ...input.iaConfig, - archivosAdjuntos: undefined, // los manejamos aparte - }), - ) - input.iaConfig?.archivosAdjuntos?.forEach((file, index) => { - edgeFunctionBody.append(`archivosAdjuntos`, file.file) - }) - return invokeEdge( - EDGE.ai_generate_subject, - edgeFunctionBody, - undefined, - supabaseBrowser(), - ) +}): Promise { + return invokeEdge(EDGE.ai_generate_subject, payload) } export async function subjects_persist_from_ai(payload: { diff --git a/src/data/hooks/useSubjects.ts b/src/data/hooks/useSubjects.ts index a5870d4..c52f15b 100644 --- a/src/data/hooks/useSubjects.ts +++ b/src/data/hooks/useSubjects.ts @@ -94,10 +94,7 @@ export function useCreateSubjectManual() { } export function useGenerateSubjectAI() { - const qc = useQueryClient() - return useMutation({ - mutationFn: ai_generate_subject, - }) + return useMutation({ mutationFn: ai_generate_subject }) } export function usePersistSubjectFromAI() { diff --git a/src/features/asignaturas/nueva/NuevaAsignaturaModalContainer.tsx b/src/features/asignaturas/nueva/NuevaAsignaturaModalContainer.tsx index 9308fe2..0ac8e81 100644 --- a/src/features/asignaturas/nueva/NuevaAsignaturaModalContainer.tsx +++ b/src/features/asignaturas/nueva/NuevaAsignaturaModalContainer.tsx @@ -118,6 +118,10 @@ export function NuevaAsignaturaModalContainer({ planId }: { planId: string }) { isLastStep={idx >= Wizard.steps.length - 1} wizard={wizard} setWizard={setWizard} + onCreate={async () => { + await crearAsignatura() + handleClose() + }} /> } diff --git a/src/routes/planes/$planId/asignaturas/$asignaturaId.tsx b/src/routes/planes/$planId/asignaturas/$asignaturaId.tsx index e227155..bfa039d 100644 --- a/src/routes/planes/$planId/asignaturas/$asignaturaId.tsx +++ b/src/routes/planes/$planId/asignaturas/$asignaturaId.tsx @@ -1,8 +1,6 @@ -import { createFileRoute, notFound, useLocation } from '@tanstack/react-router' -import { useEffect } from 'react' +import { createFileRoute, notFound } from '@tanstack/react-router' import AsignaturaDetailPage from '@/components/asignaturas/detalle/AsignaturaDetailPage' -import { lateralConfetti } from '@/components/ui/lateral-confetti' import { NotFoundPage } from '@/components/ui/NotFoundPage' import { subjects_get } from '@/data/api/subjects.api' import { qk } from '@/data/query/keys' @@ -37,15 +35,6 @@ export const Route = createFileRoute( function RouteComponent() { // const { planId, asignaturaId } = Route.useParams() - const location = useLocation() - - // Confetti al llegar desde creación - useEffect(() => { - if ((location.state as any)?.showConfetti) { - lateralConfetti() - window.history.replaceState({}, document.title) // Limpiar el estado para que no se repita - } - }, [location.state]) return (