Files
thermcool/components/CookieBanner.tsx
T
MichalC c9e4283789 feat: filtr jednostek multisplit, ostatnio oglądane, sklep pompy ciepła, czyszczenie komentarzy, checkbox zgody
- Filtr 'Ilość jednostek wewn.' w sklepie (1–9 jednostek, checkboxy, liczniki)
- Komponent RecentlyViewedProducts + Zustand store (recently-viewed-store.ts)
- Pompy ciepła dodane do sklepu i nawigacji (Header + MobileMenu)
- Logotypy marek zaktualizowane (Daikin, Panasonic + odświeżone istniejące)
- Checkbox zgody RODO w /zamowienie powiększony (w-5 h-5)
- Usunięcie ~65 zbędnych komentarzy WHAT z 12 plików (build: 0 errors)
- Plik analyze_products.ts (pomocniczy skrypt diagnostyczny)
2026-08-02 20:31:55 +02:00

182 lines
7.6 KiB
TypeScript

'use client';
import { useState, useEffect } from 'react';
import Link from 'next/link';
import { useConsentStore } from '@/lib/consent-store';
interface CookiePreferences {
necessary: boolean;
analytics: boolean;
marketing: boolean;
advertising: boolean;
}
export default function CookieBanner() {
const {
isInitialized,
isOpen,
analytics,
marketing,
advertising,
setConsent,
acceptAll: storeAcceptAll,
rejectOptional: storeRejectOptional
} = useConsentStore();
const [showDetails, setShowDetails] = useState(false);
const [prefs, setPrefs] = useState<CookiePreferences>({
necessary: true,
analytics: true,
marketing: true,
advertising: true,
});
useEffect(() => {
useConsentStore.getState().initialize();
}, []);
useEffect(() => {
if (isOpen) {
const timer = setTimeout(() => {
setPrefs({
necessary: true,
analytics: analytics,
marketing: marketing,
advertising: advertising,
});
setShowDetails(false);
}, 0);
return () => clearTimeout(timer);
}
}, [isOpen, analytics, marketing, advertising]);
const saveSelected = () => {
setConsent(prefs.analytics, prefs.marketing, prefs.advertising);
};
if (!isInitialized || !isOpen) return null;
return (
<div className="fixed bottom-0 left-0 right-0 z-[100] p-0 sm:p-6">
<div className="max-w-4xl mx-auto bg-white sm:rounded-2xl shadow-[0_-4px_20px_rgba(0,0,0,0.1)] sm:shadow-2xl border-t sm:border border-border overflow-hidden pb-safe sm:pb-0">
<div className="p-4 sm:p-6">
<div className="flex items-start gap-3 mb-3 sm:mb-4">
<span className="hidden sm:block text-2xl shrink-0">🍪</span>
<div>
<h2 className="text-sm sm:text-base font-extrabold text-primary font-heading mb-1">
Ta strona używa plików cookie
</h2>
<p className="text-xs sm:text-sm text-text-muted leading-relaxed">
Używamy plików cookie, aby zapewnić prawidłowe działanie strony, analizować ruch
i dostosowywać treści. Możesz wybrać które kategorie akceptujesz.{' '}
<Link href="/polityka-prywatnosci" className="text-accent underline hover:no-underline">
Polityka prywatności
</Link>
</p>
</div>
</div>
{showDetails && (
<div className="flex flex-col gap-3 mb-5 p-4 bg-slate-50 rounded-xl">
<div className="flex items-start justify-between gap-4">
<div>
<p className="text-sm font-semibold text-primary">Niezbędne</p>
<p className="text-xs text-text-muted mt-0.5">
Wymagane do prawidłowego działania strony. Nie można wyłączyć.
</p>
</div>
<div className="shrink-0">
<div className="w-11 h-6 bg-accent rounded-full relative cursor-not-allowed opacity-60">
<div className="absolute right-1 top-1 size-4 bg-white rounded-full" />
</div>
</div>
</div>
<div className="flex items-start justify-between gap-4 border-t border-border pt-3">
<div>
<p className="text-sm font-semibold text-primary">Analityczne</p>
<p className="text-xs text-text-muted mt-0.5">
Google Analytics — pomagają nam zrozumieć jak użytkownicy korzystają ze strony. Dane są anonimowe.
</p>
</div>
<button
onClick={() => setPrefs(p => ({ ...p, analytics: !p.analytics }))}
className="shrink-0"
>
<div className={`w-11 h-6 rounded-full relative transition-colors ${prefs.analytics ? 'bg-accent' : 'bg-slate-300'}`}>
<div className={`absolute top-1 size-4 bg-white rounded-full transition-all ${prefs.analytics ? 'right-1' : 'left-1'}`} />
</div>
</button>
</div>
<div className="flex items-start justify-between gap-4 border-t border-border pt-3">
<div>
<p className="text-sm font-semibold text-primary">Marketingowe</p>
<p className="text-xs text-text-muted mt-0.5">
Google Ads, Facebook Ads — pozwalają mierzyć skuteczność kampanii i docierać do odpowiednich odbiorców.
</p>
</div>
<button
onClick={() => setPrefs(p => ({ ...p, marketing: !p.marketing }))}
className="shrink-0"
>
<div className={`w-11 h-6 rounded-full relative transition-colors ${prefs.marketing ? 'bg-accent' : 'bg-slate-300'}`}>
<div className={`absolute top-1 size-4 bg-white rounded-full transition-all ${prefs.marketing ? 'right-1' : 'left-1'}`} />
</div>
</button>
</div>
<div className="flex items-start justify-between gap-4 border-t border-border pt-3">
<div>
<p className="text-sm font-semibold text-primary">Reklamowe</p>
<p className="text-xs text-text-muted mt-0.5">
Meta Pixel, Google Ads — umożliwiają wyświetlanie spersonalizowanych reklam na platformach takich jak Facebook, Instagram i Google.
</p>
</div>
<button
onClick={() => setPrefs(p => ({ ...p, advertising: !p.advertising }))}
className="shrink-0"
>
<div className={`w-11 h-6 rounded-full relative transition-colors ${prefs.advertising ? 'bg-accent' : 'bg-slate-300'}`}>
<div className={`absolute top-1 size-4 bg-white rounded-full transition-all ${prefs.advertising ? 'right-1' : 'left-1'}`} />
</div>
</button>
</div>
</div>
)}
<div className="grid grid-cols-2 sm:flex sm:flex-row items-stretch sm:items-center gap-2">
<button
onClick={storeAcceptAll}
className="col-span-2 sm:col-span-1 flex-1 sm:flex-none px-4 py-2 sm:px-5 sm:py-2.5 bg-accent text-white font-bold rounded-xl text-xs sm:text-sm hover:bg-accent/90 transition-colors min-h-[44px]"
>
Akceptuj wszystkie
</button>
<button
onClick={storeRejectOptional}
className="col-span-1 flex-1 sm:flex-none px-4 py-2 sm:px-5 sm:py-2.5 bg-slate-100 text-primary font-bold rounded-xl text-xs sm:text-sm hover:bg-slate-200 transition-colors min-h-[44px]"
>
Odrzuć
</button>
{showDetails ? (
<button
onClick={saveSelected}
className="col-span-1 flex-1 sm:flex-none px-4 py-2 sm:px-5 sm:py-2.5 bg-white border border-border text-primary font-bold rounded-xl text-xs sm:text-sm hover:border-accent transition-colors min-h-[44px]"
>
Zapisz
</button>
) : (
<button
onClick={() => setShowDetails(true)}
className="col-span-1 flex-1 sm:flex-none px-4 py-2 sm:px-5 sm:py-2.5 bg-white border border-border text-primary font-bold rounded-xl text-xs sm:text-sm hover:border-accent transition-colors min-h-[44px]"
>
Dostosuj
</button>
)}
</div>
</div>
</div>
</div>
);
}