Initial commit: FL-Akademie LMS mit Docker, Admin, Portal und Dokumentation.
Made-with: Cursor
This commit is contained in:
203
prisma/seed.ts
Normal file
203
prisma/seed.ts
Normal file
@@ -0,0 +1,203 @@
|
||||
import { PrismaClient, BillingInterval, Role } from "@prisma/client";
|
||||
import bcrypt from "bcryptjs";
|
||||
import { defaultLandingContent } from "../lib/landing";
|
||||
|
||||
const prisma = new PrismaClient();
|
||||
|
||||
async function main() {
|
||||
const passwordHash = await bcrypt.hash("devpassword", 10);
|
||||
|
||||
const admin = await prisma.user.upsert({
|
||||
where: { email: "admin@akademie.local" },
|
||||
update: {},
|
||||
create: {
|
||||
email: "admin@akademie.local",
|
||||
name: "MatzeFix",
|
||||
passwordHash,
|
||||
role: Role.ADMIN,
|
||||
},
|
||||
});
|
||||
|
||||
const instructor = await prisma.user.upsert({
|
||||
where: { email: "matze@akademie.local" },
|
||||
update: {},
|
||||
create: {
|
||||
email: "matze@akademie.local",
|
||||
name: "MatzeFix",
|
||||
passwordHash,
|
||||
role: Role.INSTRUCTOR,
|
||||
},
|
||||
});
|
||||
|
||||
const learner = await prisma.user.upsert({
|
||||
where: { email: "lernender@akademie.local" },
|
||||
update: {},
|
||||
create: {
|
||||
email: "lernender@akademie.local",
|
||||
name: "Demo Lernender",
|
||||
passwordHash,
|
||||
role: Role.LEARNER,
|
||||
},
|
||||
});
|
||||
|
||||
const catKostenlos = await prisma.category.upsert({
|
||||
where: { slug: "kostenlos" },
|
||||
update: {},
|
||||
create: { slug: "kostenlos", name: "kostenlos" },
|
||||
});
|
||||
const catModul1 = await prisma.category.upsert({
|
||||
where: { slug: "modul-1" },
|
||||
update: {},
|
||||
create: { slug: "modul-1", name: "Modul 1" },
|
||||
});
|
||||
const catUebung = await prisma.category.upsert({
|
||||
where: { slug: "uebung-der-woche" },
|
||||
update: {},
|
||||
create: { slug: "uebung-der-woche", name: "Übung der Woche" },
|
||||
});
|
||||
|
||||
const courseSlug = "modul-1-die-fahrschule";
|
||||
let course = await prisma.course.findUnique({ where: { slug: courseSlug } });
|
||||
|
||||
if (!course) {
|
||||
course = await prisma.course.create({
|
||||
data: {
|
||||
slug: courseSlug,
|
||||
title: "Modul 1 – Die Fahrschule",
|
||||
description:
|
||||
"Von der Fahrschulauswahl bis zu den ersten Übungen – strukturiert und praxisnah.",
|
||||
published: true,
|
||||
priceCents: 0,
|
||||
billingInterval: BillingInterval.NONE,
|
||||
ratingAverage: 4.8,
|
||||
ratingCount: 12,
|
||||
authorId: instructor.id,
|
||||
authorName: "MatzeFix",
|
||||
categories: {
|
||||
create: [
|
||||
{ categoryId: catKostenlos.id },
|
||||
{ categoryId: catModul1.id },
|
||||
],
|
||||
},
|
||||
modules: {
|
||||
create: [
|
||||
{
|
||||
title: "Einstieg",
|
||||
sortOrder: 0,
|
||||
lessons: {
|
||||
create: [
|
||||
{
|
||||
slug: "wie-waehle-ich-die-richtige-fahrschule-aus",
|
||||
title: "Wie wähle ich die richtige Fahrschule aus?",
|
||||
sortOrder: 0,
|
||||
contentHtml: `
|
||||
<p>Die Wahl der Fahrschule prägt deinen gesamten Lernweg. Achte auf:</p>
|
||||
<ul>
|
||||
<li>Kommunikation und Transparenz bei Kosten</li>
|
||||
<li>Motorrad-spezifische Erfahrung der Trainer</li>
|
||||
<li>Übungsflächen und realistische Sonderfahrten</li>
|
||||
</ul>
|
||||
`,
|
||||
},
|
||||
{
|
||||
slug: "ausruestung-und-erste-schritte",
|
||||
title: "Ausrüstung und erste Schritte",
|
||||
sortOrder: 1,
|
||||
contentHtml:
|
||||
"<p>Helm, Handschuhe, Protektoren – passend zur Jahreszeit und zum Übungsplatz.</p>",
|
||||
},
|
||||
],
|
||||
},
|
||||
},
|
||||
{
|
||||
title: "Grundlagen auf dem Platz",
|
||||
sortOrder: 1,
|
||||
lessons: {
|
||||
create: [
|
||||
{
|
||||
slug: "langsames-fahren-und-balance",
|
||||
title: "Langsames Fahren und Balance",
|
||||
sortOrder: 0,
|
||||
contentHtml:
|
||||
"<p>Übe Schrittgeschwindigkeit, Kupplungsfeinfühlen und Blickführung.</p>",
|
||||
},
|
||||
],
|
||||
},
|
||||
},
|
||||
],
|
||||
},
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
const demoPaidSlug = "demo-ubung-der-woche";
|
||||
let paid = await prisma.course.findUnique({ where: { slug: demoPaidSlug } });
|
||||
if (!paid) {
|
||||
paid = await prisma.course.create({
|
||||
data: {
|
||||
slug: demoPaidSlug,
|
||||
title: "Demo – Übung der Woche",
|
||||
description: "Beispiel für wiederkehrende Inhalte (Preisfeld für späteres Abo).",
|
||||
published: true,
|
||||
priceCents: 2396,
|
||||
billingInterval: BillingInterval.QUARTER,
|
||||
ratingAverage: 4,
|
||||
ratingCount: 1,
|
||||
authorId: instructor.id,
|
||||
authorName: "MatzeFix",
|
||||
categories: {
|
||||
create: [
|
||||
{ categoryId: catKostenlos.id },
|
||||
{ categoryId: catUebung.id },
|
||||
],
|
||||
},
|
||||
modules: {
|
||||
create: [
|
||||
{
|
||||
title: "Woche 1",
|
||||
sortOrder: 0,
|
||||
lessons: {
|
||||
create: [
|
||||
{
|
||||
slug: "uebung-saubere-blickfuehrung",
|
||||
title: "Übung: Saubere Blickführung",
|
||||
sortOrder: 0,
|
||||
contentHtml:
|
||||
"<p>Blick früh in die Kurve, Kurveneinlage planen, ruhige Handgelenke.</p>",
|
||||
},
|
||||
],
|
||||
},
|
||||
},
|
||||
],
|
||||
},
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
await prisma.enrollment.upsert({
|
||||
where: {
|
||||
userId_courseId: { userId: learner.id, courseId: course.id },
|
||||
},
|
||||
update: {},
|
||||
create: { userId: learner.id, courseId: course.id },
|
||||
});
|
||||
|
||||
await prisma.landingPage.upsert({
|
||||
where: { id: "default" },
|
||||
update: {},
|
||||
create: {
|
||||
id: "default",
|
||||
content: defaultLandingContent() as object,
|
||||
},
|
||||
});
|
||||
|
||||
console.log("Seed OK:", { admin: admin.email, learner: learner.email });
|
||||
}
|
||||
|
||||
main()
|
||||
.then(() => prisma.$disconnect())
|
||||
.catch(async (e) => {
|
||||
console.error(e);
|
||||
await prisma.$disconnect();
|
||||
process.exit(1);
|
||||
});
|
||||
Reference in New Issue
Block a user