Files
ACVE/resumen_cambios.md
2026-03-15 13:52:11 +00:00

11 KiB

Resumen de Cambios (25/02/26)

Marcelo

Fecha de trabajo: 2026-02-25
Proyecto: /opt/ACVE

1) Objetivo de la sesion

Implementar el backlog solicitado:

  • Mas mini-games con calificacion ligada al perfil.
  • Recomendaciones de estudio por perfil/progreso.
  • Certificados al completar curso.
  • Ver cursos inscritos (enrolled).
  • Cambiar Start Course por Continue cuando ya esta inscrito.
  • Actualizar Case Studies con contenido de Andres.

Tambien se resolvio operativa de entorno para Prisma/Node y baseline de migraciones sobre Supabase.


2) Features implementadas

2.1 Mini-games (3 interactivos) + persistencia + perfil

  • Se expandieron los mini-games a 3 modulos interactivos:
    • translation
    • term-matching
    • contract-clauses
  • Se paso de historial localStorage a acciones server-side con persistencia DB (si tablas ya migradas).
  • Se agrego calculo de calificacion global de mini-games para perfil (promedio de ultimo intento por juego).

Archivos:

  • lib/data/mockPractice.ts
  • types/practice.ts
  • app/(protected)/practice/[slug]/actions.ts
  • app/(protected)/practice/[slug]/page.tsx
  • lib/recommendations.ts
  • app/(protected)/profile/page.tsx

2.2 Recomendaciones de estudio (deterministicas)

  • Se implemento motor de recomendaciones por reglas:
    • basado en score de mini-games y progreso/cursos.
    • prioriza cursos ya inscritos e incompletos.
    • fallback por nivel objetivo (beginner/intermediate/advanced).
  • Se muestra bloque “Recommended next” en perfil.

Archivos:

  • lib/recommendations.ts
  • app/(protected)/profile/page.tsx
  • app/(protected)/courses/[slug]/learn/actions.ts (refresh de recomendaciones al completar leccion)

2.3 Certificados automáticos + descarga PDF

  • Emision automatica al llegar a 100% de lecciones completadas (idempotente por curso/usuario).
  • Endpoint de descarga PDF:
    • /api/certificates/[id]/pdf
  • Integracion en:
    • Profile (listado de certificados)
    • My Courses (download cuando existe certificado)

Archivos:

  • lib/certificates.ts
  • app/api/certificates/[id]/pdf/route.ts
  • app/(protected)/courses/[slug]/learn/actions.ts
  • app/(protected)/profile/page.tsx
  • app/(protected)/my-courses/page.tsx

2.4 UX: completion modal + confetti + CTA de certificado

  • Al completar curso por primera vez (cuando se emite certificado nuevo):
    • aparece modal de “Course completed”
    • animacion de confetti
    • boton Download PDF
    • boton Open Profile

Archivo:

  • components/courses/StudentClassroomClient.tsx

2.5 Vista de cursos inscritos

  • Nueva ruta protegida:
    • /my-courses
  • Muestra progreso por curso, CTA Continue/Review, y descarga de certificado si aplica.

Archivo:

  • app/(protected)/my-courses/page.tsx

2.6 Cambio Start -> Continue

  • En detalle de curso (/courses/[slug]):
    • si usuario inscrito: Continue
    • si no inscrito: Start Course
    • no autenticado: Login to start

Archivo:

  • app/(public)/courses/[slug]/page.tsx

2.7 Profile del alumno

  • Nueva ruta protegida:
    • /profile
  • Incluye:
    • score mini-games
    • desglose latest/best por mini-game
    • recomendaciones
    • certificados + descarga

Archivo:

  • app/(protected)/profile/page.tsx

2.8 Navbar

  • Se agregaron enlaces para usuario autenticado:
    • My Courses
    • Profile

Archivo:

  • components/Navbar.tsx

2.9 Case Studies actualizados con Andres

  • Se reemplazo contenido mock por:
    • Marbury v. Madison
    • Miranda v. Arizona
    • Brown v. Board of Education
  • Se modelaron campos nuevos:
    • summaryEs
    • legalOutcomeEs
    • category
    • difficulty
    • keyTerms estructurado (termino + definicion)
    • quizPrompt
  • Se actualizaron lista y detalle para mostrar contenido legal en espanol.

Archivos:

  • types/caseStudy.ts
  • lib/data/mockCaseStudies.ts
  • app/(public)/case-studies/page.tsx
  • app/(public)/case-studies/[slug]/page.tsx

3) Cambios de datos (Prisma schema)

Se actualizaron modelos en prisma/schema.prisma:

  • Nuevos:

    • MiniGame
    • MiniGameQuestion
    • MiniGameAttempt
    • StudyRecommendation
    • enum MiniGameDifficulty
  • Ajustes:

    • Certificate:
      • certificateNumber (unique)
      • pdfVersion
      • @@unique([userId, courseId])
    • Profile:
      • relaciones a mini-games/recomendaciones
    • Course:
      • relacion inversa recommendations StudyRecommendation[] (se corrigio tras error P1012)

Seed actualizado:

  • prisma/seed.ts para sembrar 3 mini-games y preguntas.

4) Node 24+ / Prisma / Supabase (incidentes y fix)

4.1 Problema detectado

  • En Node 18.19.1, Prisma CLI (v7.3.0) fallaba con:
    • ERR_REQUIRE_ESM (zeptomatch / @prisma/dev)
  • Resultado:
    • no funcionaba correctamente prisma generate/migrate.

4.2 Fix aplicado

  • Se trabajo con Node 24.14.0.
  • Se agrego .nvmrc con 24.
  • Se reinstalaron dependencias (npm ci).
  • Se agregaron scripts Prisma en package.json:
    • prisma:generate
    • prisma:status
    • prisma:migrate:dev
    • prisma:migrate:deploy
    • prisma:seed
  • Se corrigio prisma.config.ts seed command:
    • npx ts-node prisma/seed.ts

4.3 Baseline y drift en Supabase

  • No existia prisma/migrations historico en repo.
  • Se intento baseline inicial con comando viejo (--to-url) y genero SQL vacio.
  • Se corrigio usando Prisma 7:
    • --to-config-datasource
  • Se genero baseline real (~8148 bytes) y se marco aplicado.
  • Estado final reportado:
    • Database schema is up to date!

Nota:

  • Hubo dos carpetas baseline:
    • 20260225_baseline (invalida / vacia)
    • 20260225_baseline_v2 (valida)

5) Archivos nuevos creados

  • task_implementation.md
  • resumen_cambios.md
  • app/(protected)/my-courses/page.tsx
  • app/(protected)/profile/page.tsx
  • app/(protected)/practice/[slug]/actions.ts
  • app/api/certificates/[id]/pdf/route.ts
  • lib/certificates.ts
  • lib/recommendations.ts

6) Validaciones ejecutadas

Se ejecutaron en distintos momentos:

  • npm run lint -> OK
  • npx tsc --noEmit -> OK
  • npm run build -> compilacion/lint/types OK en varios intentos; hubo un fallo intermitente de worker de Next durante static generation sin stack especifico en esta sesion.
  • npm run prisma:generate -> OK (Node 24)
  • npm run prisma:status -> OK tras baseline correcto

7) Estado funcional actual

  • Certificado automatico: funcionando.
  • Descarga PDF: funcionando.
  • Modal de finalizacion + confetti: funcionando.
  • Profile muestra certificados/recomendaciones: implementado.
  • My Courses: implementado.
  • Case Studies actualizados: implementado.

Observacion de UX:

  • El diseno del certificado actual es basico/tecnico (no final de branding visual).

8) Implicaciones y pendientes recomendados

  1. Limpiar migracion baseline invalida:

    • revisar si se debe eliminar prisma/migrations/20260225_baseline del historial.
  2. Confirmar estrategia de migraciones por entorno:

    • migrate dev solo en DB de desarrollo.
    • migrate deploy en staging/prod.
  3. Mejorar UI de certificado/modal:

    • plantilla de certificado con branding final.
    • polish de animacion/confetti.
  4. QA end-to-end:

    • flujo completo desde completar curso hasta ver certificado en Profile y My Courses.
  5. Verificar consistencia en Supabase:

    • mantener DATABASE_URL (pooler) para runtime app.
    • mantener DIRECT_URL (5432) para Prisma migrate.

9) Resumen ejecutivo

  • Se implementaron todos los ejes funcionales del backlog.
  • Se desbloqueo el problema estructural de Prisma (Node 18 -> Node 24).
  • Se normalizo flujo de migraciones con baseline real en Supabase.
  • Ya existe flujo real de completion + certificado + descarga + visibilidad en perfil/cursos.

Daniel

Resumen de cambios (sesión 25/02/26)

1) Catálogo y publicación de cursos

  • Problema: Los cursos publicados no aparecían de inmediato en el catálogo y hacía falta refrescar la página a mano.
  • Causa: No se revalidaba la ruta pública /courses al guardar un curso.
  • Solución: En la acción updateCourse se agregó revalidatePath("/courses") y revalidación con "page" y "layout" para la página de edición del curso, para que el catálogo y el formulario de edición muestren datos actualizados sin refrescar.

2) Estado y nivel del curso que volvían a valores anteriores al guardar

  • Problema: Al cambiar Estado (Borrador → Publicado) o Nivel (p. ej. Intermedio → Principiante) y dar "Guardar Cambios", el formulario seguía mostrando el valor anterior hasta hacer un refresco manual.
  • Causas: (1) Los inputs de nivel y estado son no controlados (defaultValue); React no actualiza el valor en re-renders. (2) router.refresh() a veces seguía sirviendo una versión en caché del RSC.
  • Soluciones:
    • En la página de edición del curso se puso export const dynamic = "force-dynamic" para no cachear la ruta.
    • Al componente TeacherEditCourseForm se le pasó un key que incluye course.updatedAt para forzar un nuevo montaje cuando cambian los datos del curso y así aplicar los nuevos defaultValue.
    • Tras guardar con éxito se reemplazó router.refresh() por router.push(\/teacher/courses/${course.slug}/edit`)` para forzar una navegación y cargar datos frescos.
  • Archivos: app/(protected)/teacher/actions.ts, app/(protected)/teacher/courses/[slug]/edit/page.tsx, components/teacher/TeacherEditCourseForm.tsx.

3) Vista previa gratuita para usuarios sin sesión

  • Objetivo: Que los usuarios no autenticados puedan ver lecciones marcadas como "free preview" y que en la ficha del curso se indique cuáles son y se ofrezca un CTA para verlas.
  • Cambios:
    • Se movió la ruta de aprendizaje de app/(protected)/courses/[slug]/learn a app/(public)/courses/[slug]/learn (page + actions) para que no quede detrás de un layout que exija autenticación.
    • Se actualizó el import en StudentClassroomClient para usar las acciones en la nueva ruta pública.
    • En la página de detalle del curso (landing):
      • Se incluyó isFreePreview en la consulta de lecciones.
      • En "Course structure preview" se muestra un indicador "Free preview" (pill amarillo) en las lecciones que lo son.
      • Para invitados: si hay al menos una lección en free preview, se muestra el botón principal "Watch free preview" con enlace a /courses/[slug]/learn?lesson=[id], y como secundario "Login to unlock all lessons" con redirectTo=/courses/[slug] para que tras iniciar sesión vuelvan a la ficha y puedan inscribirse/comprar.
  • Archivos: app/(public)/courses/[slug]/learn/page.tsx, app/(public)/courses/[slug]/learn/actions.ts, app/(public)/courses/[slug]/page.tsx, components/courses/StudentClassroomClient.tsx. Eliminados los archivos bajo app/(protected)/courses/[slug]/learn/.

4) Botón "Editar Título" en módulos

  • Problema: El botón "Editar Título" en cada módulo del plan de estudios no hacía nada.
  • Solución:
    • Nueva acción de servidor updateModuleTitle(moduleId, title) en teacher actions: valida que el módulo sea del profesor, actualiza el título en BD y revalida las rutas correspondientes.
    • En el formulario de edición del curso: al hacer clic en "Editar Título" se muestra un campo de texto inline con el título actual y botones "Guardar" y "Cancelar"; Enter guarda, Escape cancela. Tras guardar se navega a la misma página de edición para ver el título actualizado.
  • Archivos: app/(protected)/teacher/actions.ts, components/teacher/TeacherEditCourseForm.tsx.