- DSB Portal, Industry Templates, Multi-Tenant, SSO frontend pages - All SDK API proxy routes (academy, crawler, incidents, vendors, whistleblower, etc.) - Blog section with compliance articles - BYOEH system documentation Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
269 lines
8.2 KiB
TypeScript
269 lines
8.2 KiB
TypeScript
'use client'
|
|
|
|
import { useState } from 'react'
|
|
import Link from 'next/link'
|
|
|
|
// ---------------------------------------------------------------------------
|
|
// Types
|
|
// ---------------------------------------------------------------------------
|
|
|
|
interface Article {
|
|
slug: string
|
|
title: string
|
|
excerpt: string
|
|
category: Category
|
|
readingTime: string
|
|
date: string
|
|
}
|
|
|
|
type Category = 'DSGVO' | 'AI Act' | 'NIS2' | 'Glossar'
|
|
|
|
type FilterOption = 'Alle' | Category
|
|
|
|
// ---------------------------------------------------------------------------
|
|
// Data
|
|
// ---------------------------------------------------------------------------
|
|
|
|
const ARTICLES: Article[] = [
|
|
{
|
|
slug: 'dsgvo-vvt-erstellen',
|
|
title: 'Verzeichnis von Verarbeitungstaetigkeiten (VVT) erstellen',
|
|
excerpt:
|
|
'Schritt-fuer-Schritt Anleitung zur Erstellung eines DSGVO-konformen VVT nach Art. 30.',
|
|
category: 'DSGVO',
|
|
readingTime: '8 Min.',
|
|
date: '2026-02-10',
|
|
},
|
|
{
|
|
slug: 'ai-act-ueberblick',
|
|
title: 'EU AI Act: Was Unternehmen jetzt wissen muessen',
|
|
excerpt:
|
|
'Der EU AI Act tritt stufenweise in Kraft. Welche Pflichten gelten fuer Ihr Unternehmen?',
|
|
category: 'AI Act',
|
|
readingTime: '10 Min.',
|
|
date: '2026-02-08',
|
|
},
|
|
{
|
|
slug: 'nis2-checkliste',
|
|
title: 'NIS2-Richtlinie: Checkliste fuer betroffene Unternehmen',
|
|
excerpt:
|
|
'Pruefen Sie mit unserer Checkliste, ob Ihr Unternehmen unter die NIS2-Richtlinie faellt.',
|
|
category: 'NIS2',
|
|
readingTime: '6 Min.',
|
|
date: '2026-02-05',
|
|
},
|
|
{
|
|
slug: 'tom-massnahmen-uebersicht',
|
|
title: 'Technische und Organisatorische Massnahmen (TOM)',
|
|
excerpt:
|
|
'Welche TOMs verlangt die DSGVO? Eine praxisnahe Uebersicht mit Beispielen.',
|
|
category: 'DSGVO',
|
|
readingTime: '7 Min.',
|
|
date: '2026-01-28',
|
|
},
|
|
{
|
|
slug: 'auftragsverarbeitung-avv',
|
|
title: 'Auftragsverarbeitung und AVV nach Art. 28 DSGVO',
|
|
excerpt:
|
|
'Wann brauchen Sie einen AVV? Was muss drin stehen? Praxisleitfaden.',
|
|
category: 'DSGVO',
|
|
readingTime: '9 Min.',
|
|
date: '2026-01-20',
|
|
},
|
|
{
|
|
slug: 'glossar',
|
|
title: 'Compliance-Glossar: Die wichtigsten Begriffe',
|
|
excerpt:
|
|
'Von AVV bis ZAB — alle Compliance-Fachbegriffe verstaendlich erklaert.',
|
|
category: 'Glossar',
|
|
readingTime: '15 Min.',
|
|
date: '2026-02-12',
|
|
},
|
|
]
|
|
|
|
const FILTER_OPTIONS: FilterOption[] = [
|
|
'Alle',
|
|
'DSGVO',
|
|
'AI Act',
|
|
'NIS2',
|
|
'Glossar',
|
|
]
|
|
|
|
// ---------------------------------------------------------------------------
|
|
// Helpers
|
|
// ---------------------------------------------------------------------------
|
|
|
|
const CATEGORY_STYLES: Record<Category, string> = {
|
|
DSGVO: 'bg-blue-50 text-blue-700 ring-blue-600/10',
|
|
'AI Act': 'bg-purple-50 text-purple-700 ring-purple-600/10',
|
|
NIS2: 'bg-orange-50 text-orange-700 ring-orange-600/10',
|
|
Glossar: 'bg-green-50 text-green-700 ring-green-600/10',
|
|
}
|
|
|
|
function formatDate(dateStr: string): string {
|
|
return new Date(dateStr).toLocaleDateString('de-DE', {
|
|
day: '2-digit',
|
|
month: 'long',
|
|
year: 'numeric',
|
|
})
|
|
}
|
|
|
|
// ---------------------------------------------------------------------------
|
|
// Components
|
|
// ---------------------------------------------------------------------------
|
|
|
|
function CategoryBadge({ category }: { category: Category }) {
|
|
return (
|
|
<span
|
|
className={`inline-flex items-center rounded-full px-2.5 py-0.5 text-xs font-medium ring-1 ring-inset ${CATEGORY_STYLES[category]}`}
|
|
>
|
|
{category}
|
|
</span>
|
|
)
|
|
}
|
|
|
|
function ArticleCard({ article }: { article: Article }) {
|
|
return (
|
|
<Link
|
|
href={`/blog/${article.slug}`}
|
|
className="group flex flex-col bg-white rounded-xl border border-slate-200 overflow-hidden card-hover"
|
|
>
|
|
{/* Card Body */}
|
|
<div className="flex-1 p-6">
|
|
<div className="flex items-center justify-between mb-3">
|
|
<CategoryBadge category={article.category} />
|
|
<span className="text-xs text-slate-400">{article.readingTime}</span>
|
|
</div>
|
|
|
|
<h3 className="text-lg font-semibold text-slate-900 group-hover:text-primary-600 transition-colors leading-snug mb-2">
|
|
{article.title}
|
|
</h3>
|
|
|
|
<p className="text-sm text-slate-500 leading-relaxed">
|
|
{article.excerpt}
|
|
</p>
|
|
</div>
|
|
|
|
{/* Card Footer */}
|
|
<div className="px-6 pb-5 pt-0 flex items-center justify-between">
|
|
<time className="text-xs text-slate-400" dateTime={article.date}>
|
|
{formatDate(article.date)}
|
|
</time>
|
|
|
|
<span className="inline-flex items-center text-sm font-medium text-primary-600 group-hover:translate-x-1 transition-transform">
|
|
Lesen
|
|
<svg
|
|
className="ml-1 w-4 h-4"
|
|
fill="none"
|
|
viewBox="0 0 24 24"
|
|
stroke="currentColor"
|
|
strokeWidth={2}
|
|
>
|
|
<path
|
|
strokeLinecap="round"
|
|
strokeLinejoin="round"
|
|
d="M17 8l4 4m0 0l-4 4m4-4H3"
|
|
/>
|
|
</svg>
|
|
</span>
|
|
</div>
|
|
</Link>
|
|
)
|
|
}
|
|
|
|
// ---------------------------------------------------------------------------
|
|
// Page
|
|
// ---------------------------------------------------------------------------
|
|
|
|
export default function BlogPage() {
|
|
const [activeFilter, setActiveFilter] = useState<FilterOption>('Alle')
|
|
|
|
const filteredArticles =
|
|
activeFilter === 'Alle'
|
|
? ARTICLES
|
|
: ARTICLES.filter((a) => a.category === activeFilter)
|
|
|
|
return (
|
|
<div className="pb-20 max-w-7xl mx-auto px-4 sm:px-6 lg:px-8">
|
|
{/* Hero */}
|
|
<section className="pt-16 pb-12 text-center">
|
|
<h1 className="text-4xl sm:text-5xl font-bold text-slate-900 tracking-tight">
|
|
Compliance{' '}
|
|
<span className="gradient-text">Ressourcen-Hub</span>
|
|
</h1>
|
|
<p className="mt-4 max-w-2xl mx-auto text-lg text-slate-500">
|
|
Praxisleitfaeden, Checklisten und Glossar zu DSGVO, AI Act und NIS2
|
|
— damit Sie jederzeit compliant bleiben.
|
|
</p>
|
|
</section>
|
|
|
|
{/* Category Filters */}
|
|
<section className="mb-10">
|
|
<div className="flex flex-wrap items-center justify-center gap-2">
|
|
{FILTER_OPTIONS.map((option) => {
|
|
const isActive = activeFilter === option
|
|
return (
|
|
<button
|
|
key={option}
|
|
onClick={() => setActiveFilter(option)}
|
|
className={`px-4 py-2 rounded-full text-sm font-medium transition-colors ${
|
|
isActive
|
|
? 'bg-primary-600 text-white shadow-sm'
|
|
: 'bg-slate-100 text-slate-600 hover:bg-slate-200'
|
|
}`}
|
|
>
|
|
{option}
|
|
</button>
|
|
)
|
|
})}
|
|
</div>
|
|
</section>
|
|
|
|
{/* Articles Grid */}
|
|
<section>
|
|
{filteredArticles.length > 0 ? (
|
|
<div className="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-6">
|
|
{filteredArticles.map((article) => (
|
|
<ArticleCard key={article.slug} article={article} />
|
|
))}
|
|
</div>
|
|
) : (
|
|
<p className="text-center text-slate-400 py-16">
|
|
Keine Artikel in dieser Kategorie.
|
|
</p>
|
|
)}
|
|
</section>
|
|
|
|
{/* CTA */}
|
|
<section className="mt-20 text-center bg-gradient-to-br from-primary-50 to-accent-50 rounded-2xl py-14 px-6">
|
|
<h2 className="text-2xl sm:text-3xl font-bold text-slate-900">
|
|
Compliance automatisieren?
|
|
</h2>
|
|
<p className="mt-3 text-slate-600 max-w-xl mx-auto">
|
|
BreakPilot Comply hilft Ihnen, DSGVO, AI Act und NIS2 Anforderungen
|
|
effizient umzusetzen — mit KI-gestuetzten Tools.
|
|
</p>
|
|
<Link
|
|
href="/"
|
|
className="mt-6 inline-flex items-center px-6 py-3 bg-primary-600 text-white rounded-lg font-medium hover:bg-primary-700 transition-colors btn-press"
|
|
>
|
|
Kostenlos testen
|
|
<svg
|
|
className="ml-2 w-4 h-4"
|
|
fill="none"
|
|
viewBox="0 0 24 24"
|
|
stroke="currentColor"
|
|
strokeWidth={2}
|
|
>
|
|
<path
|
|
strokeLinecap="round"
|
|
strokeLinejoin="round"
|
|
d="M17 8l4 4m0 0l-4 4m4-4H3"
|
|
/>
|
|
</svg>
|
|
</Link>
|
|
</section>
|
|
</div>
|
|
)
|
|
}
|