Initial commit: FL-Akademie LMS mit Docker, Admin, Portal und Dokumentation.
Made-with: Cursor
This commit is contained in:
95
lib/landing.ts
Normal file
95
lib/landing.ts
Normal file
@@ -0,0 +1,95 @@
|
||||
import type { Prisma } from "@prisma/client";
|
||||
import { prisma } from "@/lib/prisma";
|
||||
|
||||
export type LandingContentV1 = {
|
||||
version: 1;
|
||||
heroTitle: string;
|
||||
heroLead: string;
|
||||
primaryCta: { label: string; href: string };
|
||||
secondaryCta?: { label: string; href: string };
|
||||
benefitSectionTitle: string;
|
||||
benefits: { title: string; body: string }[];
|
||||
};
|
||||
|
||||
export const defaultLandingContent = (): LandingContentV1 => ({
|
||||
version: 1,
|
||||
heroTitle: "Motorrad fahren von A–Z",
|
||||
heroLead:
|
||||
"Von der Fahrschule zur ersten Serpentine. Tipps, Übungen und Kurse – strukturiert auf einer Plattform.",
|
||||
primaryCta: { label: "Zu den Kursen", href: "/kurse" },
|
||||
secondaryCta: { label: "Mitgliederbereich", href: "/portal" },
|
||||
benefitSectionTitle: "Deine Vorteile",
|
||||
benefits: [
|
||||
{
|
||||
title: "Praxisorientiert",
|
||||
body: "Inhalte, die du auf den Platz und in den Alltag übernehmen kannst – Schritt für Schritt.",
|
||||
},
|
||||
{
|
||||
title: "Von A bis Z",
|
||||
body: "Klare Module statt Wildwuchs: vom ersten Gedanken ans Motorradfahren bis zu gezielten Übungen.",
|
||||
},
|
||||
{
|
||||
title: "Fortschritt & Zertifikat",
|
||||
body: "Behalte deinen Lernstand im Blick und sichere dir nach Abschluss eine Teilnahmebestätigung.",
|
||||
},
|
||||
],
|
||||
});
|
||||
|
||||
function isRecord(v: unknown): v is Record<string, unknown> {
|
||||
return typeof v === "object" && v !== null;
|
||||
}
|
||||
|
||||
export function parseLandingContent(raw: unknown): LandingContentV1 {
|
||||
if (!isRecord(raw) || raw.version !== 1) return defaultLandingContent();
|
||||
const heroTitle = typeof raw.heroTitle === "string" ? raw.heroTitle : "";
|
||||
const heroLead = typeof raw.heroLead === "string" ? raw.heroLead : "";
|
||||
const benefitSectionTitle =
|
||||
typeof raw.benefitSectionTitle === "string" ? raw.benefitSectionTitle : "Deine Vorteile";
|
||||
const primaryCta = isRecord(raw.primaryCta)
|
||||
? {
|
||||
label: typeof raw.primaryCta.label === "string" ? raw.primaryCta.label : "Mehr",
|
||||
href: typeof raw.primaryCta.href === "string" ? raw.primaryCta.href : "/kurse",
|
||||
}
|
||||
: { label: "Zu den Kursen", href: "/kurse" };
|
||||
let secondaryCta: LandingContentV1["secondaryCta"];
|
||||
if (isRecord(raw.secondaryCta)) {
|
||||
const l = typeof raw.secondaryCta.label === "string" ? raw.secondaryCta.label : "";
|
||||
const h = typeof raw.secondaryCta.href === "string" ? raw.secondaryCta.href : "";
|
||||
if (l && h) secondaryCta = { label: l, href: h };
|
||||
}
|
||||
const benefitsRaw = Array.isArray(raw.benefits) ? raw.benefits : [];
|
||||
const benefits = benefitsRaw
|
||||
.map((b) => {
|
||||
if (!isRecord(b)) return null;
|
||||
const title = typeof b.title === "string" ? b.title : "";
|
||||
const body = typeof b.body === "string" ? b.body : "";
|
||||
if (!title && !body) return null;
|
||||
return { title, body };
|
||||
})
|
||||
.filter(Boolean) as { title: string; body: string }[];
|
||||
|
||||
return {
|
||||
version: 1,
|
||||
heroTitle: heroTitle || defaultLandingContent().heroTitle,
|
||||
heroLead: heroLead || defaultLandingContent().heroLead,
|
||||
primaryCta,
|
||||
secondaryCta,
|
||||
benefitSectionTitle,
|
||||
benefits: benefits.length ? benefits : defaultLandingContent().benefits,
|
||||
};
|
||||
}
|
||||
|
||||
export async function getLandingContent(): Promise<LandingContentV1> {
|
||||
const row = await prisma.landingPage.findUnique({ where: { id: "default" } });
|
||||
if (!row) return defaultLandingContent();
|
||||
return parseLandingContent(row.content);
|
||||
}
|
||||
|
||||
export async function saveLandingContent(content: LandingContentV1) {
|
||||
const json = content as unknown as Prisma.InputJsonValue;
|
||||
await prisma.landingPage.upsert({
|
||||
where: { id: "default" },
|
||||
create: { id: "default", content: json },
|
||||
update: { content: json },
|
||||
});
|
||||
}
|
||||
Reference in New Issue
Block a user