Some checks failed
🚀 Build & Deploy / 🔍 Prepare (push) Successful in 4s
🚀 Build & Deploy / 🧪 QA (push) Successful in 2m15s
🚀 Build & Deploy / 🏗️ Build (push) Failing after 12m23s
🚀 Build & Deploy / 🚀 Deploy (push) Has been skipped
🚀 Build & Deploy / 🧪 Post-Deploy Verification (push) Has been skipped
🚀 Build & Deploy / 🔔 Notify (push) Successful in 1s
110 lines
4.1 KiB
TypeScript
110 lines
4.1 KiB
TypeScript
import { Download } from "lucide-react";
|
|
import fs from "fs";
|
|
import path from "path";
|
|
|
|
export default function AVB() {
|
|
const filePath = path.join(process.cwd(), "context/avbs.md");
|
|
const fileContent = fs.readFileSync(filePath, "utf8");
|
|
|
|
// Split by double newlines to get major blocks
|
|
const rawBlocks = fileContent
|
|
.split(/\n\s*\n/)
|
|
.map((b) => b.trim())
|
|
.filter((b) => b !== "");
|
|
|
|
// Extract title and stand more robustly
|
|
const title = rawBlocks.find(b => b.startsWith("# "))?.replace(/^#\s+/, "") || "Allgemeine Verkaufsbedingungen";
|
|
const stand = rawBlocks.find(b => b.toLowerCase().startsWith("stand:")) || "Stand: April 2026";
|
|
|
|
const sections: { title: string; content: string[] }[] = [];
|
|
let currentSection: { title: string; content: string[] } | null = null;
|
|
|
|
// Process sections, skipping title and stand blocks
|
|
rawBlocks.forEach((block) => {
|
|
if (block.startsWith("# ") || block.toLowerCase().startsWith("stand:")) return;
|
|
|
|
if (block.startsWith("##")) {
|
|
// New section header: e.g. "## 1. Geltungsbereich"
|
|
if (currentSection) sections.push(currentSection);
|
|
currentSection = {
|
|
title: block.replace(/^##\s+/, "").trim(),
|
|
content: []
|
|
};
|
|
} else if (currentSection) {
|
|
// Clean up bold markers for better display
|
|
const cleanedBlock = block.replace(/\*\*(.*?)\*\*/g, "$1");
|
|
currentSection.content.push(cleanedBlock);
|
|
}
|
|
});
|
|
if (currentSection) sections.push(currentSection);
|
|
|
|
// The very last block might be a footer/schlussbestimmung if it's not in a section
|
|
// In our MD, everything is in a section, so we just use the last block of the last section as potential footer if we want,
|
|
// but the current UI expects a separate 'footer' variable.
|
|
const footer = "MB Grid Solutions & Services";
|
|
|
|
return (
|
|
<div className="bg-slate-50 min-h-screen pt-40 pb-20">
|
|
<div className="container-custom">
|
|
<div className="max-w-4xl mx-auto bg-white p-8 md:p-12 rounded-[2.5rem] shadow-sm border border-slate-100">
|
|
<div className="flex flex-col md:flex-row md:items-center justify-between gap-6 mb-8">
|
|
<div>
|
|
<h1 className="text-4xl font-extrabold text-primary mb-2">
|
|
{title}
|
|
</h1>
|
|
<p className="text-slate-500 font-medium">{stand}</p>
|
|
</div>
|
|
<a
|
|
href="/assets/AVB MB Grid 4-2026.pdf"
|
|
download
|
|
className="btn-primary !py-3 !px-6 flex items-center gap-2"
|
|
>
|
|
<Download size={18} />
|
|
Als PDF herunterladen
|
|
</a>
|
|
</div>
|
|
|
|
<div className="space-y-8 text-slate-600 leading-relaxed">
|
|
<div className="pb-4 border-b border-slate-50">
|
|
<p className="text-slate-400 italic">{stand}</p>
|
|
</div>
|
|
{sections.map((section, index) => (
|
|
<div key={index}>
|
|
<h2 className="text-2xl font-bold text-primary mb-4">
|
|
{section.title}
|
|
</h2>
|
|
<div className="space-y-4">
|
|
{section.content.map((paragraph, pIndex) => (
|
|
<p key={pIndex}>
|
|
{paragraph.split(/(\[.*?\]\(.*?\))/g).map((part, i) => {
|
|
const match = part.match(/\[(.*?)\]\((.*?)\)/);
|
|
if (match) {
|
|
return (
|
|
<a
|
|
key={i}
|
|
href={match[2]}
|
|
className="text-primary hover:underline font-medium"
|
|
download={match[2].endsWith(".pdf")}
|
|
>
|
|
{match[1]}
|
|
</a>
|
|
);
|
|
}
|
|
return part;
|
|
})}
|
|
</p>
|
|
))}
|
|
</div>
|
|
</div>
|
|
))}
|
|
|
|
<div className="pt-8 border-t border-slate-100">
|
|
<p className="font-bold text-primary">{footer}</p>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
);
|
|
}
|