Feat: generación IA de asignaturas, navegación con confetti y ajustes de API
closes #63: - Añadido AIGenerateSubjectInput y nueva implementación ai_generate_subject que envía FormData (soporta archivosAdjuntos) al Edge Function. - Creado hook useGenerateSubjectAI (mutation) y usado en WizardControls de asignaturas para generar la asignatura vía IA. - WizardControls (asignaturas) construye el payload IA, invoca la mutación y navega al detalle de la asignatura creada pasando state.showConfetti para lanzar confetti. - Ajustes en subjects.api.ts (nombres de endpoint, tipos y envío de datos) y sincronización de tipos en WizardControls (plan y campos básicos). - Ruta de detalle de asignatura ($asignaturaId) ahora lee location.state.showConfetti y dispara lateralConfetti al entrar. - Eliminado el prop onCreate del modal de nueva asignatura (la creación IA se gestiona internamente).
This commit was merged in pull request #76.
This commit is contained in:
@@ -1,6 +1,10 @@
|
||||
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,
|
||||
@@ -12,7 +16,6 @@ export function WizardControls({
|
||||
disableNext,
|
||||
disableCreate,
|
||||
isLastStep,
|
||||
onCreate,
|
||||
}: {
|
||||
wizard: NewSubjectWizardState
|
||||
setWizard: React.Dispatch<React.SetStateAction<NewSubjectWizardState>>
|
||||
@@ -23,8 +26,9 @@ export function WizardControls({
|
||||
disableNext: boolean
|
||||
disableCreate: boolean
|
||||
isLastStep: boolean
|
||||
onCreate: () => Promise<void> | void
|
||||
}) {
|
||||
const navigate = useNavigate()
|
||||
const generateSubjectAI = useGenerateSubjectAI()
|
||||
const handleCreate = async () => {
|
||||
setWizard((w) => ({
|
||||
...w,
|
||||
@@ -33,7 +37,46 @@ export function WizardControls({
|
||||
}))
|
||||
|
||||
try {
|
||||
await onCreate()
|
||||
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
|
||||
}
|
||||
} catch (err: any) {
|
||||
setWizard((w) => ({
|
||||
...w,
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
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'
|
||||
@@ -54,11 +55,11 @@ export function WizardControls({
|
||||
? wizard.datosBasicos.numCiclos
|
||||
: 1
|
||||
|
||||
const aiInput = {
|
||||
const aiInput: AIGeneratePlanInput = {
|
||||
datosBasicos: {
|
||||
nombrePlan: wizard.datosBasicos.nombrePlan,
|
||||
carreraId: wizard.datosBasicos.carrera.id || undefined,
|
||||
facultadId: wizard.datosBasicos.facultad.id || undefined,
|
||||
carreraId: wizard.datosBasicos.carrera.id,
|
||||
facultadId: wizard.datosBasicos.facultad.id,
|
||||
nivel: wizard.datosBasicos.nivel as string,
|
||||
tipoCiclo: tipoCicloSafe,
|
||||
numCiclos: numCiclosSafe,
|
||||
|
||||
Reference in New Issue
Block a user