Refine CMS i18n fallback, refresh UI, add consent minimize, seed i18n content
Co-authored-by: dennis <dennis@konkol.net>
This commit is contained in:
@@ -6,6 +6,7 @@ import { useConsent, type ConsentState } from "./ConsentProvider";
|
||||
export default function ConsentBanner() {
|
||||
const { consent, setConsent } = useConsent();
|
||||
const [draft, setDraft] = useState<ConsentState>({ analytics: false, chat: false });
|
||||
const [minimized, setMinimized] = useState(false);
|
||||
|
||||
const locale = useMemo(() => {
|
||||
if (typeof document === "undefined") return "en";
|
||||
@@ -44,62 +45,86 @@ export default function ConsentBanner() {
|
||||
rejectAll: "Reject all",
|
||||
};
|
||||
|
||||
if (minimized) {
|
||||
return (
|
||||
<div className="fixed bottom-4 right-4 z-[60]">
|
||||
<button
|
||||
type="button"
|
||||
onClick={() => setMinimized(false)}
|
||||
className="px-4 py-2 rounded-full bg-white/80 backdrop-blur-xl border border-white/60 shadow-lg text-stone-800 font-semibold hover:bg-white transition-colors"
|
||||
aria-label="Open privacy settings"
|
||||
>
|
||||
{s.title}
|
||||
</button>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
return (
|
||||
<div className="fixed bottom-4 left-4 right-4 z-[60]">
|
||||
<div className="max-w-3xl mx-auto bg-white/95 backdrop-blur-xl border border-stone-200 rounded-2xl shadow-[0_12px_40px_rgba(41,37,36,0.18)] p-5">
|
||||
<div className="flex flex-col md:flex-row md:items-start md:justify-between gap-4">
|
||||
<div className="fixed bottom-4 right-4 z-[60] max-w-[calc(100vw-2rem)]">
|
||||
<div className="w-[360px] max-w-full bg-white/85 backdrop-blur-xl border border-white/60 rounded-2xl shadow-[0_12px_40px_rgba(41,37,36,0.14)] p-4">
|
||||
<div className="flex items-start justify-between gap-3">
|
||||
<div className="min-w-0">
|
||||
<div className="text-lg font-bold text-stone-900">{s.title}</div>
|
||||
<p className="text-sm text-stone-600 mt-1">{s.description}</p>
|
||||
<div className="text-base font-bold text-stone-900">{s.title}</div>
|
||||
<p className="text-xs text-stone-600 mt-1 leading-snug">{s.description}</p>
|
||||
</div>
|
||||
<button
|
||||
type="button"
|
||||
onClick={() => setMinimized(true)}
|
||||
className="shrink-0 text-xs text-stone-500 hover:text-stone-900 transition-colors"
|
||||
aria-label="Minimize privacy banner"
|
||||
title="Minimize"
|
||||
>
|
||||
Hide
|
||||
</button>
|
||||
</div>
|
||||
|
||||
<div className="mt-4 space-y-2">
|
||||
<div className="flex items-center justify-between gap-3">
|
||||
<div className="text-sm font-medium text-stone-800">{s.essential}</div>
|
||||
<div className="text-xs text-stone-500">Always on</div>
|
||||
</div>
|
||||
|
||||
<label className="flex items-center justify-between gap-3 py-1">
|
||||
<span className="text-sm font-medium text-stone-800">{s.analytics}</span>
|
||||
<input
|
||||
type="checkbox"
|
||||
checked={draft.analytics}
|
||||
onChange={(e) => setDraft((p) => ({ ...p, analytics: e.target.checked }))}
|
||||
className="w-4 h-4 accent-stone-900"
|
||||
/>
|
||||
</label>
|
||||
|
||||
<label className="flex items-center justify-between gap-3 py-1">
|
||||
<span className="text-sm font-medium text-stone-800">{s.chat}</span>
|
||||
<input
|
||||
type="checkbox"
|
||||
checked={draft.chat}
|
||||
onChange={(e) => setDraft((p) => ({ ...p, chat: e.target.checked }))}
|
||||
className="w-4 h-4 accent-stone-900"
|
||||
/>
|
||||
</label>
|
||||
</div>
|
||||
<div className="mt-3 space-y-2">
|
||||
<div className="flex items-center justify-between gap-3">
|
||||
<div className="text-xs font-semibold text-stone-800">{s.essential}</div>
|
||||
<div className="text-[11px] text-stone-500">Always on</div>
|
||||
</div>
|
||||
|
||||
<div className="flex flex-col gap-2 shrink-0">
|
||||
<button
|
||||
onClick={() => setConsent({ analytics: true, chat: true })}
|
||||
className="px-4 py-2 rounded-xl bg-stone-900 text-stone-50 font-semibold hover:bg-stone-800 transition-colors"
|
||||
>
|
||||
{s.acceptAll}
|
||||
</button>
|
||||
<button
|
||||
onClick={() => setConsent(draft)}
|
||||
className="px-4 py-2 rounded-xl bg-white border border-stone-200 text-stone-800 font-semibold hover:bg-stone-50 transition-colors"
|
||||
>
|
||||
{s.acceptSelected}
|
||||
</button>
|
||||
<button
|
||||
onClick={() => setConsent({ analytics: false, chat: false })}
|
||||
className="px-4 py-2 rounded-xl bg-transparent text-stone-600 font-semibold hover:text-stone-900 transition-colors"
|
||||
>
|
||||
{s.rejectAll}
|
||||
</button>
|
||||
</div>
|
||||
<label className="flex items-center justify-between gap-3 py-1">
|
||||
<span className="text-sm font-semibold text-stone-800">{s.analytics}</span>
|
||||
<input
|
||||
type="checkbox"
|
||||
checked={draft.analytics}
|
||||
onChange={(e) => setDraft((p) => ({ ...p, analytics: e.target.checked }))}
|
||||
className="w-4 h-4 accent-stone-900"
|
||||
/>
|
||||
</label>
|
||||
|
||||
<label className="flex items-center justify-between gap-3 py-1">
|
||||
<span className="text-sm font-semibold text-stone-800">{s.chat}</span>
|
||||
<input
|
||||
type="checkbox"
|
||||
checked={draft.chat}
|
||||
onChange={(e) => setDraft((p) => ({ ...p, chat: e.target.checked }))}
|
||||
className="w-4 h-4 accent-stone-900"
|
||||
/>
|
||||
</label>
|
||||
</div>
|
||||
|
||||
<div className="mt-3 flex flex-col gap-2">
|
||||
<button
|
||||
onClick={() => setConsent({ analytics: true, chat: true })}
|
||||
className="px-4 py-2 rounded-xl bg-stone-900 text-stone-50 font-semibold hover:bg-stone-800 transition-colors"
|
||||
>
|
||||
{s.acceptAll}
|
||||
</button>
|
||||
<button
|
||||
onClick={() => setConsent(draft)}
|
||||
className="px-4 py-2 rounded-xl bg-white border border-stone-200 text-stone-800 font-semibold hover:bg-stone-50 transition-colors"
|
||||
>
|
||||
{s.acceptSelected}
|
||||
</button>
|
||||
<button
|
||||
onClick={() => setConsent({ analytics: false, chat: false })}
|
||||
className="px-4 py-2 rounded-xl bg-transparent text-stone-600 font-semibold hover:text-stone-900 transition-colors"
|
||||
>
|
||||
{s.rejectAll}
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
Reference in New Issue
Block a user