Pending course, rest ready for launch
This commit is contained in:
297
resumen_cambios.md
Normal file
297
resumen_cambios.md
Normal file
@@ -0,0 +1,297 @@
|
||||
# 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`.
|
||||
Reference in New Issue
Block a user