Files
FL-Akademie/app/admin/courses/[id]/edit/page.tsx

149 lines
5.0 KiB
TypeScript

import Link from "next/link";
import { notFound } from "next/navigation";
import { prisma } from "@/lib/prisma";
import {
createLessonAction,
createModuleAction,
updateCourseAction,
} from "@/app/admin/courses/actions";
type Props = { params: Promise<{ id: string }> };
export default async function AdminEditCoursePage({ params }: Props) {
const { id } = await params;
const course = await prisma.course.findUnique({
where: { id },
include: {
modules: {
orderBy: { sortOrder: "asc" },
include: { lessons: { orderBy: { sortOrder: "asc" } } },
},
},
});
if (!course) notFound();
const priceEuros = (course.priceCents / 100).toFixed(2);
return (
<div>
<p className="muted">
<Link href="/admin/courses"> Alle Kurse</Link> ·{" "}
<Link href={`/kurse/${course.slug}`}>Öffentliche Kursseite</Link>
</p>
<h1 className="page-title">Kurs bearbeiten</h1>
<p className="muted subtitle">{course.title}</p>
<form action={updateCourseAction.bind(null, course.id)} className="panel form" style={{ maxWidth: 820 }}>
<h2 style={{ marginTop: 0 }}>Stammdaten</h2>
<label>
Titel
<input name="title" defaultValue={course.title} required />
</label>
<label>
Slug
<input name="slug" defaultValue={course.slug} required />
</label>
<label>
Beschreibung
<textarea name="description" defaultValue={course.description} />
</label>
<label>
Anzeige-Autor
<input name="authorName" defaultValue={course.authorName} required />
</label>
<label>
Preis (EUR)
<input name="priceEuros" type="number" step="0.01" min="0" defaultValue={priceEuros} />
</label>
<label>
Abrechnungsintervall
<select name="billingInterval" defaultValue={course.billingInterval}>
<option value="NONE">Einmal / kein Abo</option>
<option value="MONTH">Monatlich</option>
<option value="QUARTER">Vierteljährlich</option>
<option value="YEAR">Jährlich</option>
</select>
</label>
<label className="stack" style={{ alignItems: "center" }}>
<span style={{ display: "flex", gap: "0.5rem", alignItems: "center" }}>
<input type="checkbox" name="published" defaultChecked={course.published} /> Veröffentlicht
</span>
</label>
<button type="submit" className="btn btn-primary">
Speichern
</button>
</form>
<div className="panel" style={{ marginTop: "1.25rem" }}>
<h2 style={{ marginTop: 0 }}>Neues Modul</h2>
<form action={createModuleAction.bind(null, course.id)} className="form" style={{ maxWidth: 720 }}>
<label>
Modultitel
<input name="title" required />
</label>
<button type="submit" className="btn btn-ghost">
Modul hinzufügen
</button>
</form>
</div>
<div className="panel" style={{ marginTop: "1.25rem" }}>
<h2 style={{ marginTop: 0 }}>Neue Lektion</h2>
<form action={createLessonAction.bind(null, course.id)} className="form" style={{ maxWidth: 720 }}>
<label>
Modul
<select name="moduleId" required defaultValue={course.modules[0]?.id ?? ""}>
<option value="" disabled>
Modul wählen
</option>
{course.modules.map((m) => (
<option key={m.id} value={m.id}>
{m.title}
</option>
))}
</select>
</label>
<label>
Lektionstitel
<input name="lessonTitle" required />
</label>
<label>
Slug (optional)
<input name="lessonSlug" placeholder="wird sonst aus dem Titel erzeugt" />
</label>
<label>
Inhalt (HTML)
<textarea name="contentHtml" placeholder="<p>…</p>" />
</label>
<button type="submit" className="btn btn-ghost">
Lektion hinzufügen
</button>
</form>
</div>
<div className="panel" style={{ marginTop: "1.25rem" }}>
<h2 style={{ marginTop: 0 }}>Kurrikulum</h2>
{course.modules.length === 0 ? (
<p className="muted">Noch keine Module.</p>
) : (
<ul className="curriculum">
{course.modules.map((m) => (
<li key={m.id}>
<div className="module-title">{m.title}</div>
<ul className="curriculum">
{m.lessons.map((l) => (
<li key={l.id}>
<Link href={`/kurse/${course.slug}/lektionen/${l.slug}`}>{l.title}</Link>{" "}
<span className="muted">({l.slug})</span>
</li>
))}
</ul>
</li>
))}
</ul>
)}
</div>
</div>
);
}