Files
ACVE/components/courses/ProgramContentList.tsx
2026-03-15 13:52:11 +00:00

113 lines
6.0 KiB
TypeScript

import { LockKeyhole, PlayCircle } from "lucide-react";
import { cn } from "@/lib/utils";
import type { CourseProgramModuleView } from "@/lib/courses/publicCourses";
type ProgramContentListProps = {
modules: CourseProgramModuleView[];
};
const badgeClass: Record<string, string> = {
Video: "border-sky-300/70 bg-sky-50 text-sky-800 dark:border-sky-700/50 dark:bg-sky-900/30 dark:text-sky-200",
Lectura: "border-indigo-300/70 bg-indigo-50 text-indigo-800 dark:border-indigo-700/50 dark:bg-indigo-900/30 dark:text-indigo-200",
Actividad: "border-rose-300/70 bg-rose-50 text-rose-800 dark:border-rose-700/50 dark:bg-rose-900/30 dark:text-rose-200",
"Evaluación":
"border-amber-300/70 bg-amber-50 text-amber-800 dark:border-amber-700/50 dark:bg-amber-900/30 dark:text-amber-200",
};
export default function ProgramContentList({ modules }: ProgramContentListProps) {
return (
<section className="acve-panel acve-section-base">
<div className="mb-5">
<p className="text-xs font-semibold uppercase tracking-[0.14em] text-muted-foreground">Plan de estudios</p>
<h2 className="acve-heading mt-2 text-2xl md:text-3xl">Contenido del Programa</h2>
</div>
{modules.length === 0 ? (
<div className="rounded-2xl border border-dashed border-border bg-muted/35 px-6 py-9 text-center">
<p className="text-lg font-semibold text-foreground">Contenido en preparación</p>
<p className="mt-2 text-sm text-muted-foreground">
El equipo académico está publicando módulos y lecciones para este programa.
</p>
</div>
) : (
<div className="space-y-5">
{modules.map((module) => (
<article key={module.id} className="overflow-hidden rounded-2xl border border-border/80 bg-card/65">
<header className="flex flex-wrap items-center justify-between gap-3 border-b border-border/70 bg-muted/30 px-4 py-3">
<h3 className="text-lg font-semibold text-foreground">
Módulo {module.order}. {module.title}
</h3>
<p className="text-xs font-semibold uppercase tracking-wide text-muted-foreground">{module.items.length} lecciones</p>
</header>
<ol className="divide-y divide-border/60">
{module.items.map((item) => (
<li key={item.id} className="px-4 py-3">
<div className="flex flex-wrap items-start justify-between gap-3">
<div className="min-w-0 flex-1">
<div className="flex flex-wrap items-center gap-2">
<span className="inline-flex min-w-8 items-center justify-center rounded-full border border-border bg-card px-2 py-0.5 text-xs font-semibold text-muted-foreground">
{String(item.order).padStart(2, "0")}
</span>
{item.badges.map((badge) => (
<span
key={`${item.id}-${badge}`}
className={cn("rounded-full border px-2 py-0.5 text-[11px] font-semibold", badgeClass[badge])}
>
{badge}
</span>
))}
{item.isPreview ? (
<span className="rounded-full border border-primary/35 bg-primary/10 px-2 py-0.5 text-[11px] font-semibold text-primary">
Vista previa
</span>
) : null}
{item.isFinalExam ? (
<span className="rounded-full border border-amber-300/70 bg-amber-50 px-2 py-0.5 text-[11px] font-semibold text-amber-800 dark:border-amber-700/50 dark:bg-amber-900/30 dark:text-amber-200">
Evaluación final obligatoria
</span>
) : null}
{item.isCompleted ? (
<span className="rounded-full border border-emerald-300/70 bg-emerald-50 px-2 py-0.5 text-[11px] font-semibold text-emerald-800 dark:border-emerald-700/50 dark:bg-emerald-900/30 dark:text-emerald-200">
Completada
</span>
) : null}
</div>
<p className="mt-2 text-sm font-semibold text-foreground md:text-base">{item.title}</p>
{item.subtitle ? <p className="mt-1 text-sm text-muted-foreground">{item.subtitle}</p> : null}
</div>
<div className="flex shrink-0 items-center gap-2 text-xs font-medium text-muted-foreground">
{item.durationLabel ? <span>{item.durationLabel}</span> : null}
{item.isUpcoming ? (
<span className="rounded-full border border-amber-300/70 bg-amber-50 px-2 py-0.5 text-amber-800 dark:border-amber-700/50 dark:bg-amber-900/30 dark:text-amber-200">
Próximamente
</span>
) : item.isLocked ? (
<span className="inline-flex items-center gap-1 rounded-full border border-border bg-muted/35 px-2 py-0.5">
<LockKeyhole className="h-3 w-3" />
Bloqueada
</span>
) : (
<span className="inline-flex items-center gap-1 rounded-full border border-primary/30 bg-primary/10 px-2 py-0.5 text-primary">
<PlayCircle className="h-3 w-3" />
Disponible
</span>
)}
</div>
</div>
</li>
))}
</ol>
</article>
))}
</div>
)}
</section>
);
}