110 lines
4.9 KiB
TypeScript
110 lines
4.9 KiB
TypeScript
import Link from "next/link";
|
|
import { ArrowLeft, BookOpenCheck, Clock3, GraduationCap, UsersRound } from "lucide-react";
|
|
import { cn } from "@/lib/utils";
|
|
|
|
type CourseDetailHeaderProps = {
|
|
title: string;
|
|
stageLabel: string;
|
|
proficiencyLabel: string;
|
|
availabilityLabel: string;
|
|
availabilityState: "published" | "upcoming" | "draft";
|
|
description: string;
|
|
thumbnailUrl: string | null;
|
|
instructor: string;
|
|
durationLabel: string;
|
|
lessonCount: number;
|
|
studentsCount: number;
|
|
};
|
|
|
|
const availabilityClass: Record<CourseDetailHeaderProps["availabilityState"], string> = {
|
|
published: "border-emerald-300/70 bg-emerald-50 text-emerald-800 dark:border-emerald-700/40 dark:bg-emerald-900/30 dark:text-emerald-200",
|
|
upcoming: "border-amber-300/70 bg-amber-50 text-amber-800 dark:border-amber-700/50 dark:bg-amber-900/30 dark:text-amber-200",
|
|
draft: "border-slate-300/70 bg-slate-100 text-slate-700 dark:border-slate-700/60 dark:bg-slate-800/70 dark:text-slate-200",
|
|
};
|
|
|
|
function initials(text: string): string {
|
|
return text
|
|
.split(" ")
|
|
.filter(Boolean)
|
|
.slice(0, 2)
|
|
.map((chunk) => chunk[0]?.toUpperCase() ?? "")
|
|
.join("");
|
|
}
|
|
|
|
export default function CourseDetailHeader({
|
|
title,
|
|
stageLabel,
|
|
proficiencyLabel,
|
|
availabilityLabel,
|
|
availabilityState,
|
|
description,
|
|
thumbnailUrl,
|
|
instructor,
|
|
durationLabel,
|
|
lessonCount,
|
|
studentsCount,
|
|
}: CourseDetailHeaderProps) {
|
|
return (
|
|
<section className="acve-panel acve-section-base">
|
|
<Link className="inline-flex items-center gap-2 text-sm font-medium text-muted-foreground hover:text-foreground" href="/courses">
|
|
<ArrowLeft className="h-4 w-4" />
|
|
Volver a Formación Académica
|
|
</Link>
|
|
|
|
<div className="mt-4 grid gap-4 lg:grid-cols-[1.45fr_0.95fr]">
|
|
<div>
|
|
<div className="flex flex-wrap items-center gap-2 text-xs font-semibold">
|
|
<span className="rounded-full border border-primary/30 bg-primary/10 px-3 py-1 text-primary">{stageLabel}</span>
|
|
<span className="rounded-full border border-border/80 bg-card/80 px-3 py-1 text-muted-foreground">{proficiencyLabel}</span>
|
|
<span className={cn("rounded-full border px-3 py-1", availabilityClass[availabilityState])}>{availabilityLabel}</span>
|
|
</div>
|
|
|
|
<h1 className="acve-heading mt-4 text-3xl leading-tight md:text-4xl">{title}</h1>
|
|
<p className="mt-3 text-sm leading-relaxed text-muted-foreground md:text-base">{description}</p>
|
|
|
|
<div className="mt-5 grid gap-3 sm:grid-cols-2 lg:grid-cols-4">
|
|
<article className="rounded-xl border border-border/80 bg-card/70 px-3 py-2">
|
|
<p className="text-[11px] font-semibold uppercase tracking-wide text-muted-foreground">Duración</p>
|
|
<p className="mt-1 inline-flex items-center gap-1.5 text-sm font-semibold text-foreground">
|
|
<Clock3 className="h-3.5 w-3.5 text-primary/80" />
|
|
{durationLabel}
|
|
</p>
|
|
</article>
|
|
<article className="rounded-xl border border-border/80 bg-card/70 px-3 py-2">
|
|
<p className="text-[11px] font-semibold uppercase tracking-wide text-muted-foreground">Lecciones</p>
|
|
<p className="mt-1 inline-flex items-center gap-1.5 text-sm font-semibold text-foreground">
|
|
<BookOpenCheck className="h-3.5 w-3.5 text-primary/80" />
|
|
{lessonCount}
|
|
</p>
|
|
</article>
|
|
<article className="rounded-xl border border-border/80 bg-card/70 px-3 py-2">
|
|
<p className="text-[11px] font-semibold uppercase tracking-wide text-muted-foreground">Instructor</p>
|
|
<p className="mt-1 inline-flex items-center gap-1.5 text-sm font-semibold text-foreground">
|
|
<GraduationCap className="h-3.5 w-3.5 text-primary/80" />
|
|
{instructor}
|
|
</p>
|
|
</article>
|
|
<article className="rounded-xl border border-border/80 bg-card/70 px-3 py-2">
|
|
<p className="text-[11px] font-semibold uppercase tracking-wide text-muted-foreground">Comunidad</p>
|
|
<p className="mt-1 inline-flex items-center gap-1.5 text-sm font-semibold text-foreground">
|
|
<UsersRound className="h-3.5 w-3.5 text-primary/80" />
|
|
{studentsCount.toLocaleString()} inscritos
|
|
</p>
|
|
</article>
|
|
</div>
|
|
</div>
|
|
|
|
<div className="overflow-hidden rounded-2xl border border-border/70 bg-card/70">
|
|
{thumbnailUrl ? (
|
|
<img alt={`Portada del programa ${title}`} className="h-full min-h-56 w-full object-cover lg:min-h-full" src={thumbnailUrl} />
|
|
) : (
|
|
<div className="flex h-full min-h-56 items-end bg-gradient-to-br from-[#eadbc9] via-[#f4e9dc] to-[#fdf8f2] p-5 text-5xl font-semibold text-primary/75">
|
|
{initials(title)}
|
|
</div>
|
|
)}
|
|
</div>
|
|
</div>
|
|
</section>
|
|
);
|
|
}
|