Initial commit: FL-Akademie LMS mit Docker, Admin, Portal und Dokumentation.
Made-with: Cursor
This commit is contained in:
90
app/kurse/[slug]/page.tsx
Normal file
90
app/kurse/[slug]/page.tsx
Normal file
@@ -0,0 +1,90 @@
|
||||
import Link from "next/link";
|
||||
import { notFound } from "next/navigation";
|
||||
import { getServerSession } from "next-auth";
|
||||
import { authOptions } from "@/lib/auth-options";
|
||||
import { getCourseBySlug, firstLessonPath } from "@/lib/course-queries";
|
||||
import { formatMoney, billingLabel } from "@/lib/format";
|
||||
import { prisma } from "@/lib/prisma";
|
||||
import { EnrollButton } from "@/components/enroll-button";
|
||||
|
||||
type Props = { params: Promise<{ slug: string }> };
|
||||
|
||||
export default async function CoursePage({ params }: Props) {
|
||||
const { slug } = await params;
|
||||
const course = await getCourseBySlug(slug);
|
||||
if (!course) notFound();
|
||||
|
||||
const session = await getServerSession(authOptions);
|
||||
const enrollment =
|
||||
session?.user?.id &&
|
||||
(await prisma.enrollment.findUnique({
|
||||
where: { userId_courseId: { userId: session.user.id, courseId: course.id } },
|
||||
}));
|
||||
|
||||
const startPath = firstLessonPath(course);
|
||||
const cats = course.categories.map((c) => c.category.name).join(", ");
|
||||
const priceSuffix = billingLabel(course.billingInterval);
|
||||
const isFree = course.priceCents === 0;
|
||||
|
||||
return (
|
||||
<section className="section">
|
||||
<div className="container">
|
||||
<p className="muted">
|
||||
<Link href="/kurse">← Alle Kurse</Link>
|
||||
</p>
|
||||
<h1>{course.title}</h1>
|
||||
<p className="course-meta">
|
||||
Von <strong>{course.authorName}</strong>
|
||||
{cats ? <> · {cats}</> : null}
|
||||
</p>
|
||||
{!isFree && (
|
||||
<p className="course-price">
|
||||
{formatMoney(course.priceCents, course.currency)}
|
||||
{priceSuffix ? ` ${priceSuffix}` : ""}{" "}
|
||||
<span className="muted">(Zahlungsanbindung in Arbeit – aktuell nicht kaufbar)</span>
|
||||
</p>
|
||||
)}
|
||||
|
||||
<div style={{ margin: "1.5rem 0" }}>
|
||||
{!session ? (
|
||||
<Link href={`/login?callbackUrl=/kurse/${course.slug}`} className="btn btn-primary">
|
||||
Anmelden, um fortzufahren
|
||||
</Link>
|
||||
) : enrollment && startPath ? (
|
||||
<Link href={startPath} className="btn btn-primary">
|
||||
Mit dem Lernen beginnen
|
||||
</Link>
|
||||
) : enrollment ? (
|
||||
<span className="muted">Noch keine Lektionen.</span>
|
||||
) : isFree ? (
|
||||
<EnrollButton courseSlug={course.slug} />
|
||||
) : (
|
||||
<p className="muted">Kostenpflichtige Kurse werden über Stripe angebunden.</p>
|
||||
)}
|
||||
</div>
|
||||
|
||||
<div className="panel">
|
||||
<h2>Kurrikulum</h2>
|
||||
{course.description ? <p>{course.description}</p> : null}
|
||||
<ul className="curriculum">
|
||||
{course.modules.map((m) => (
|
||||
<li key={m.id}>
|
||||
<div className="module-title">{m.title}</div>
|
||||
<ul className="curriculum">
|
||||
{m.lessons.map((lesson) => {
|
||||
const href = `/kurse/${course.slug}/lektionen/${lesson.slug}`;
|
||||
return (
|
||||
<li key={lesson.id}>
|
||||
<Link href={href}>{lesson.title}</Link>
|
||||
</li>
|
||||
);
|
||||
})}
|
||||
</ul>
|
||||
</li>
|
||||
))}
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
);
|
||||
}
|
||||
Reference in New Issue
Block a user