diff --git a/app/api/pages/[slug]/pdf/route.tsx b/app/api/pages/[slug]/pdf/route.tsx
index ff304d06..944628dd 100644
--- a/app/api/pages/[slug]/pdf/route.tsx
+++ b/app/api/pages/[slug]/pdf/route.tsx
@@ -11,8 +11,38 @@ export async function GET(req: NextRequest, { params }: { params: Promise<{ slug
try {
const { slug } = await params;
- // Hardcoded bypass for AGBs to use the original uploaded PDF.
+ // Handle AGBs specifically - either fetch from collection or use fallback file
if (slug === 'agbs') {
+ const payload = await getPayload({ config: configPromise });
+ const currentAgbs = await payload.find({
+ collection: 'agbs-collection',
+ where: {
+ isCurrent: { equals: true },
+ },
+ limit: 1,
+ });
+
+ if (currentAgbs.totalDocs > 0) {
+ const agb = currentAgbs.docs[0];
+ const media = agb.file as any;
+ if (media && media.url) {
+ // If it's a remote URL or absolute path, we might need to fetch it
+ // For now assume it's a local file in public/media
+ const filePath = path.join(process.cwd(), 'public', media.url);
+ if (fs.existsSync(filePath)) {
+ const fileBuffer = fs.readFileSync(filePath);
+ return new NextResponse(fileBuffer, {
+ status: 200,
+ headers: {
+ 'Content-Type': 'application/pdf',
+ 'Content-Disposition': `attachment; filename="${media.filename}"`,
+ },
+ });
+ }
+ }
+ }
+
+ // Fallback for hardcoded legacy AGB
const filePath = path.join(process.cwd(), 'public', 'AVB-KLZ-4-2026.pdf');
if (fs.existsSync(filePath)) {
const fileBuffer = fs.readFileSync(filePath);
diff --git a/components/AgbHistoryBlock.tsx b/components/AgbHistoryBlock.tsx
new file mode 100644
index 00000000..f11e82a6
--- /dev/null
+++ b/components/AgbHistoryBlock.tsx
@@ -0,0 +1,76 @@
+import React from 'react';
+import { getPayload } from 'payload';
+import configPromise from '@payload-config';
+import { Container, Card, Heading } from '@/components/ui';
+
+export const AgbHistoryBlock: React.FC<{ title: string }> = async ({ title }) => {
+ const payload = await getPayload({ config: configPromise });
+
+ const agbs = await payload.find({
+ collection: 'agbs-collection',
+ sort: '-versionDate',
+ limit: 100,
+ });
+
+ if (agbs.totalDocs === 0) {
+ return null;
+ }
+
+ return (
+
+
+ {title || 'Vorherige Versionen'}
+
+
+ {agbs.docs.map((agb: any) => {
+ const date = new Date(agb.versionDate).toLocaleDateString('de-DE', {
+ year: 'numeric',
+ month: 'long',
+ day: 'numeric',
+ });
+
+ const fileUrl = typeof agb.file === 'object' ? agb.file.url : '';
+ const filename = typeof agb.file === 'object' ? agb.file.filename : 'agb.pdf';
+
+ return (
+
+
+
+ {agb.title}
+
+
Gültig ab {date}
+
+ {fileUrl && (
+
+
+
+ )}
+
+ );
+ })}
+
+
+ );
+};
diff --git a/components/PayloadRichText.tsx b/components/PayloadRichText.tsx
index 83b44670..3497b2aa 100644
--- a/components/PayloadRichText.tsx
+++ b/components/PayloadRichText.tsx
@@ -38,6 +38,7 @@ import GallerySection from '@/components/home/GallerySection';
import VideoSection from '@/components/home/VideoSection';
import CTA from '@/components/home/CTA';
import { PDFDownloadBlock } from '@/components/PDFDownloadBlock';
+import { AgbHistoryBlock } from '@/components/AgbHistoryBlock';
/**
* Splits a text string on \n and intersperses
elements.
@@ -436,6 +437,8 @@ const jsxConverters: JSXConverters = {
'block-pdfDownload': ({ node }: any) => (
),
+ agbHistory: ({ node }: any) => ,
+ 'block-agbHistory': ({ node }: any) => ,
// ─── New Page Blocks ───────────────────────────────────────────
heroSection: ({ node }: any) => {
const f = node.fields;
diff --git a/payload.config.ts b/payload.config.ts
index f0acfcc8..be4f545e 100644
--- a/payload.config.ts
+++ b/payload.config.ts
@@ -21,6 +21,7 @@ import { Posts } from './src/payload/collections/Posts';
import { FormSubmissions } from './src/payload/collections/FormSubmissions';
import { Products } from './src/payload/collections/Products';
import { Pages } from './src/payload/collections/Pages';
+import { Agbs } from './src/payload/collections/Agbs';
import { seedDatabase } from './src/payload/seed';
const filename = fileURLToPath(import.meta.url);
@@ -56,7 +57,7 @@ export default buildConfig({
defaultLocale: 'de',
fallback: true,
},
- collections: [Users, Media, Posts, FormSubmissions, Products, Pages],
+ collections: [Users, Media, Posts, FormSubmissions, Products, Pages, Agbs],
editor: lexicalEditor({
features: ({ defaultFeatures }) => [
...defaultFeatures,
diff --git a/src/payload/blocks/AgbHistory.ts b/src/payload/blocks/AgbHistory.ts
new file mode 100644
index 00000000..b1eb9577
--- /dev/null
+++ b/src/payload/blocks/AgbHistory.ts
@@ -0,0 +1,18 @@
+import { Block } from 'payload';
+
+export const AgbHistory: Block = {
+ slug: 'agbHistory',
+ labels: {
+ singular: 'AGB Historie',
+ plural: 'AGB Historien',
+ },
+ fields: [
+ {
+ name: 'title',
+ type: 'text',
+ label: 'Titel',
+ localized: true,
+ defaultValue: 'Vorherige Versionen',
+ },
+ ],
+};
diff --git a/src/payload/blocks/allBlocks.ts b/src/payload/blocks/allBlocks.ts
index ffcbc51e..f34ff28e 100644
--- a/src/payload/blocks/allBlocks.ts
+++ b/src/payload/blocks/allBlocks.ts
@@ -17,6 +17,7 @@ import { TeamProfile } from './TeamProfile';
import { TechnicalGrid } from './TechnicalGrid';
import { VisualLinkPreview } from './VisualLinkPreview';
import { PDFDownload } from './PDFDownload';
+import { AgbHistory } from './AgbHistory';
import { homeBlocksArray } from './HomeBlocks';
export const payloadBlocks = [
@@ -40,4 +41,5 @@ export const payloadBlocks = [
TechnicalGrid,
VisualLinkPreview,
PDFDownload,
+ AgbHistory,
];
diff --git a/src/payload/collections/Agbs.ts b/src/payload/collections/Agbs.ts
new file mode 100644
index 00000000..78d14a2a
--- /dev/null
+++ b/src/payload/collections/Agbs.ts
@@ -0,0 +1,49 @@
+import { CollectionConfig } from 'payload';
+
+export const Agbs: CollectionConfig = {
+ slug: 'agbs-collection',
+ admin: {
+ useAsTitle: 'title',
+ defaultColumns: ['title', 'versionDate', 'updatedAt'],
+ group: 'Rechtliches',
+ },
+ access: {
+ read: () => true,
+ },
+ fields: [
+ {
+ name: 'title',
+ type: 'text',
+ required: true,
+ localized: true,
+ label: 'Titel (z.B. AGB April 2026)',
+ },
+ {
+ name: 'versionDate',
+ type: 'date',
+ required: true,
+ label: 'Gültig ab',
+ admin: {
+ date: {
+ pickerAppearance: 'dayOnly',
+ },
+ },
+ },
+ {
+ name: 'file',
+ type: 'upload',
+ relationTo: 'media',
+ required: true,
+ label: 'PDF Datei',
+ },
+ {
+ name: 'isCurrent',
+ type: 'checkbox',
+ label: 'Aktuelle Version',
+ defaultValue: false,
+ admin: {
+ position: 'sidebar',
+ },
+ },
+ ],
+};