// components/teacher/TeacherEditCourseForm.tsx "use client"; import { updateCourse, createModule, createLesson, reorderModules, reorderLessons, } from "@/app/(protected)/teacher/actions"; import { useState, useEffect } from "react"; import { useRouter } from "next/navigation"; import Link from "next/link"; import { toast } from "sonner"; import { Prisma } from "@prisma/client"; type CourseData = { id: string; slug: string; title: Prisma.JsonValue; description: Prisma.JsonValue; level: string; status: string; price: number; modules: { id: string; title: Prisma.JsonValue; lessons: { id: string; title: Prisma.JsonValue }[]; }[]; }; export default function TeacherEditCourseForm({ course }: { course: CourseData }) { const router = useRouter(); const [loading, setLoading] = useState(false); const [optimisticModules, setOptimisticModules] = useState(course.modules); useEffect(() => { setOptimisticModules(course.modules); }, [course.modules]); // Helper for JSON/String fields const getStr = (val: Prisma.JsonValue) => { if (typeof val === "string") return val; if (val && typeof val === "object" && !Array.isArray(val)) { const v = val as Record; if (typeof v.en === "string") return v.en; if (typeof v.es === "string") return v.es; return ""; } return ""; }; // 1. SAVE COURSE SETTINGS async function handleSubmit(formData: FormData) { setLoading(true); const res = await updateCourse(course.id, course.slug, formData); if (res.success) { toast.success("Curso actualizado"); router.refresh(); } else { toast.error("Error al guardar"); } setLoading(false); } // 2. CREATE NEW MODULE const handleAddModule = async () => { setLoading(true); // Block UI while working const res = await createModule(course.id); if (res.success) { toast.success("Módulo agregado"); router.refresh(); } else { toast.error("Error al crear módulo"); } setLoading(false); }; // 3. CREATE NEW LESSON const handleAddLesson = async (moduleId: string) => { setLoading(true); const res = await createLesson(moduleId); if (res.success && res.lessonId) { toast.success("Lección creada"); // Redirect immediately to the video upload page router.push(`/teacher/courses/${course.slug}/lessons/${res.lessonId}`); } else { toast.error("Error al crear lección"); setLoading(false); // Only stop loading if we failed (otherwise we are redirecting) } }; // 4. REORDER MODULES (optimistic) const handleReorderModule = async (moduleIndex: number, direction: "up" | "down") => { const swapWith = direction === "up" ? moduleIndex - 1 : moduleIndex + 1; if (swapWith < 0 || swapWith >= optimisticModules.length) return; const next = [...optimisticModules]; [next[moduleIndex], next[swapWith]] = [next[swapWith], next[moduleIndex]]; setOptimisticModules(next); const res = await reorderModules(optimisticModules[moduleIndex].id, direction); if (res.success) { router.refresh(); } else { setOptimisticModules(course.modules); toast.error(res.error ?? "Error al reordenar"); } }; // 5. REORDER LESSONS (optimistic) const handleReorderLesson = async ( moduleIndex: number, lessonIndex: number, direction: "up" | "down" ) => { const lessons = optimisticModules[moduleIndex].lessons; const swapWith = direction === "up" ? lessonIndex - 1 : lessonIndex + 1; if (swapWith < 0 || swapWith >= lessons.length) return; const nextModules = [...optimisticModules]; const nextLessons = [...lessons]; [nextLessons[lessonIndex], nextLessons[swapWith]] = [ nextLessons[swapWith], nextLessons[lessonIndex], ]; nextModules[moduleIndex] = { ...nextModules[moduleIndex], lessons: nextLessons }; setOptimisticModules(nextModules); const res = await reorderLessons(lessons[lessonIndex].id, direction); if (res.success) { router.refresh(); } else { setOptimisticModules(course.modules); toast.error(res.error ?? "Error al reordenar"); } }; return (
{/* Header */}

Editar Curso

👁️ Ver Vista Previa
{/* LEFT COLUMN: Main Info */}
{/* Title */}
{/* Description */}