Add CookieConsentBanner component and integrate cookie consent functionality
This commit is contained in:
@@ -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>
|
||||||
|
|||||||
128
lawfirm-demos/demo-1/components/CookieConsentBanner.tsx
Normal file
128
lawfirm-demos/demo-1/components/CookieConsentBanner.tsx
Normal 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;
|
||||||
|
}
|
||||||
@@ -1,21 +1,27 @@
|
|||||||
|
'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>© {new Date().getFullYear()} Kanzlei Mustermann. Alle Rechte vorbehalten.</p>
|
<p>© {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>
|
<button onClick={openCookieSettings} className="hover:underline">
|
||||||
</div>
|
Cookie-Einstellungen
|
||||||
|
</button>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</footer>
|
</footer>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user