Add CookieConsentBanner component and integrate cookie consent functionality

This commit is contained in:
2025-06-25 09:37:07 +09:00
parent 2403dd72e9
commit f55ca657e8
3 changed files with 144 additions and 8 deletions

View File

@@ -3,6 +3,7 @@ import {Inter} from "next/font/google";
import Navbar from "@/components/Navbar"; import Navbar from "@/components/Navbar";
import Footer from "@/components/Footer"; import Footer from "@/components/Footer";
import React from "react"; import React from "react";
import CookieConsentBanner from "@/components/CookieConsentBanner";
const inter = Inter({subsets: ["latin"]}); const inter = Inter({subsets: ["latin"]});
@@ -18,6 +19,7 @@ export default function RootLayout(
<body className={inter.className}> <body className={inter.className}>
<Navbar/> <Navbar/>
{children} {children}
<CookieConsentBanner/>
<Footer/> <Footer/>
</body> </body>
</html> </html>

View File

@@ -0,0 +1,128 @@
// CookieConsentBanner.tsx
'use client';
import {useEffect, useState} from 'react';
export default function CookieConsentBanner() {
const [visible, setVisible] = useState(false);
const [loading, setLoading] = useState(false);
const [stats, setStats] = useState(false);
const [personalization, setPersonalization] = useState(false);
useEffect(() => {
const consent = localStorage.getItem('cookie_consent');
if (!consent) setVisible(true);
const show = () => {
setVisible(true);
};
window.addEventListener('show-cookie-banner', show);
return () => window.removeEventListener('show-cookie-banner', show);
}, []);
const handleAccept = () => {
setLoading(true);
setTimeout(() => {
localStorage.setItem('cookie_consent', 'true');
localStorage.setItem('cookie_stats', stats.toString());
localStorage.setItem('cookie_personalization', personalization.toString());
setVisible(false);
setLoading(false);
}, 1000);
};
const handleAcceptAll = () => {
setLoading(true);
setStats(true);
setPersonalization(true);
setTimeout(() => {
localStorage.setItem('cookie_consent', 'true');
localStorage.setItem('cookie_stats', 'true');
localStorage.setItem('cookie_personalization', 'true');
setVisible(false);
setLoading(false);
}, 1000);
};
const handleDecline = () => {
localStorage.setItem('cookie_consent', 'false');
localStorage.setItem('cookie_stats', 'false');
localStorage.setItem('cookie_personalization', 'false');
setVisible(false);
};
return visible ? (
<div className="fixed inset-0 z-50 bg-black/50 flex items-center justify-center px-4">
<div className="bg-white max-w-2xl w-full rounded-xl shadow-lg overflow-hidden text-sm text-gray-800">
<div className="px-6 py-4 border-b border-gray-200">
<h2 className="text-lg font-semibold">Wir nutzen Cookies und andere Technologien.</h2>
</div>
<div className="px-6 py-4 space-y-4 max-h-[60vh] overflow-y-auto">
<p>
Diese Website nutzt Cookies und vergleichbare Funktionen zur Verarbeitung von
Endgeräteinformationen und personenbezogenen Daten. Die Verarbeitung dient der Einbindung von
Inhalten, externen Diensten und Elementen Dritter, der statistischen Analyse/Messung, der
personalisierten Werbung sowie der Einbindung sozialer Medien.
</p>
<p>
Je nach Funktion werden dabei Daten an Dritte weitergegeben und in Länder außerhalb der EU
übertragen, in denen kein angemessenes Datenschutzniveau besteht z. B. die USA. Ihre
Einwilligung ist freiwillig und kann jederzeit über das Symbol unten links widerrufen werden.
</p>
<div className="space-y-2">
<label className="block">
<input type="checkbox" defaultChecked disabled className="mr-2"/>
Notwendige Cookies (immer aktiv)
</label>
<label className="block">
<input
type="checkbox"
checked={stats}
onChange={(e) => setStats(e.target.checked)}
className="mr-2"
/>
Statistiken (z. B. Besuchertracking)
</label>
<label className="block">
<input
type="checkbox"
checked={personalization}
onChange={(e) => setPersonalization(e.target.checked)}
className="mr-2"
/>
Personalisierung (z. B. eingebettete Medien, Google Maps)
</label>
</div>
</div>
<div className="px-6 py-4 border-t border-gray-200 flex flex-col sm:flex-row sm:justify-end gap-2">
<div className="flex flex-wrap gap-2">
<button
onClick={handleDecline}
className="px-4 py-2 border rounded text-gray-600 hover:bg-gray-100"
>
Ablehnen
</button>
<button
onClick={handleAccept}
className="px-4 py-2 border rounded text-gray-700 hover:bg-gray-100 disabled:opacity-60"
disabled={loading}
>
{loading ? 'Speichere ...' : 'Akzeptieren'}
</button>
<button
onClick={handleAcceptAll}
className="px-4 py-2 bg-red-700 text-white rounded hover:bg-red-800 disabled:opacity-60"
disabled={loading}
>
{loading ? 'Speichere ...' : 'Alles akzeptieren'}
</button>
</div>
</div>
<div className="px-6 py-3 border-t border-gray-100 text-xs text-gray-500 flex justify-start gap-4">
<a href="/impressum" className="hover:underline">Impressum</a>
<a href="/datenschutz" className="hover:underline">Datenschutzerklärung</a>
</div>
</div>
</div>
) : null;
}

View File

@@ -1,19 +1,25 @@
'use client';
import Link from 'next/link'; import Link from 'next/link';
import Links from "@/data/Links"; import Links from '@/data/Links';
export default function Footer() { export default function Footer() {
const openCookieSettings = () => {
window.dispatchEvent(new Event('show-cookie-banner'));
};
return ( return (
<footer <footer className="bg-white mt-auto py-10 px-6 md:px-12 lg:px-24 text-sm text-gray-600 border-t border-gray-200">
className="bg-white mt-auto py-10 px-6 md:px-12 lg:px-24 text-sm text-gray-600 border-t border-gray-200">
<div className="flex flex-col md:flex-row justify-between items-center gap-4"> <div className="flex flex-col md:flex-row justify-between items-center gap-4">
<div> <div>
<p>&copy; {new Date().getFullYear()} Kanzlei Mustermann. Alle Rechte vorbehalten.</p> <p>&copy; {new Date().getFullYear()} Kanzlei Mustermann. Alle Rechte vorbehalten.</p>
</div> </div>
<div className="space-x-4">
<div className="space-x-4"> <div className="space-x-4">
<Link href={Links.imprint} className="hover:underline">Impressum</Link> <Link href={Links.imprint} className="hover:underline">Impressum</Link>
<Link href={Links.privacy} className="hover:underline">Datenschutz</Link> <Link href={Links.privacy} className="hover:underline">Datenschutz</Link>
</div> <button onClick={openCookieSettings} className="hover:underline">
Cookie-Einstellungen
</button>
</div> </div>
</div> </div>
</footer> </footer>