541 lines
26 KiB
TypeScript
541 lines
26 KiB
TypeScript
'use client';
|
|
|
|
import { useState } from 'react';
|
|
import Image from 'next/image';
|
|
import Link from 'next/link';
|
|
import {
|
|
ArrowLeft, Phone, ShoppingCart, GitCompare, Check,
|
|
Thermometer, Volume2, Zap, Wind, Star, Info, Eye, X
|
|
} from 'lucide-react';
|
|
import { Product } from '@/content/products';
|
|
import { useCartStore } from '@/lib/cart-store';
|
|
import { useCompareStore } from '@/lib/compare-store';
|
|
import { getProductVariants } from '@/content/product-variants';
|
|
|
|
const brandLogos: Record<string, string> = {
|
|
'Gree': '/brands/gree.webp',
|
|
'Rotenso': '/brands/rotenso.webp',
|
|
'Toshiba': '/brands/toshiba.webp',
|
|
'Daikin': '/brands/daikin.webp',
|
|
'CHV': '/brands/chv.webp',
|
|
'Haier': '/brands/haier.webp',
|
|
'LG': '/brands/lg.webp',
|
|
'Samsung': '/brands/samsung.webp',
|
|
'Mitsubishi Electric': '/brands/mitsubishi.webp',
|
|
'Fuji Electric': '/brands/fuji.webp',
|
|
};
|
|
|
|
interface Props {
|
|
product: Product;
|
|
seriesProducts: Product[];
|
|
companyPhone: string;
|
|
companyPhoneRaw: string;
|
|
}
|
|
|
|
// Szacowany SEER na podstawie klasy energetycznej
|
|
function estimateSEER(klasa: string): number {
|
|
if (!klasa) return 5.0;
|
|
const k = klasa.toUpperCase();
|
|
if (k.includes('A+++')) return 8.5;
|
|
if (k.includes('A++')) return 6.1;
|
|
if (k.includes('A+')) return 4.6;
|
|
if (k.includes('A')) return 3.6;
|
|
return 5.0;
|
|
}
|
|
|
|
// Parsuj moc — bierz wartość nominalną (środkową lub pierwszą)
|
|
function parseMoc(val: string): number {
|
|
if (!val) return 0;
|
|
const nums = val.replace(',', '.').match(/[\d.]+/g);
|
|
if (!nums) return 0;
|
|
if (nums.length === 1) return parseFloat(nums[0]);
|
|
// zakres: bierz środkową
|
|
const floats = nums.map(parseFloat);
|
|
return floats[Math.floor(floats.length / 2)];
|
|
}
|
|
|
|
const TABS = ['Opis', 'Specyfikacja', 'Montaż', 'Opinie'] as const;
|
|
type Tab = typeof TABS[number];
|
|
|
|
function seededViews(slug: string): number {
|
|
let hash = 0;
|
|
for (let i = 0; i < slug.length; i++) {
|
|
hash = (hash * 31 + slug.charCodeAt(i)) >>> 0;
|
|
}
|
|
return 18 + (hash % 50);
|
|
}
|
|
|
|
export function ProductPageClient({ product, seriesProducts, companyPhone, companyPhoneRaw }: Props) {
|
|
const [currentProduct, setCurrentProduct] = useState(product);
|
|
const [activeTab, setActiveTab] = useState<Tab>('Opis');
|
|
const [godziny, setGodziny] = useState(8);
|
|
const [cartState, setCartState] = useState<'idle' | 'added' | 'cart'>('idle');
|
|
const [showViewsBanner, setShowViewsBanner] = useState(true);
|
|
const viewsCount = seededViews(currentProduct.slug);
|
|
|
|
const variants = getProductVariants(currentProduct.slug);
|
|
|
|
const addToCart = useCartStore(s => s.addItem);
|
|
const { addItem: addCompare, removeItem: removeCompare, isAdded } = useCompareStore();
|
|
const inCompare = isAdded(currentProduct.slug);
|
|
|
|
const handleAddToCart = () => {
|
|
if (!currentProduct.price) return;
|
|
addToCart({
|
|
slug: currentProduct.slug,
|
|
name: currentProduct.name,
|
|
brand: currentProduct.brand,
|
|
image: currentProduct.image,
|
|
price: currentProduct.price,
|
|
});
|
|
setCartState('added');
|
|
setTimeout(() => setCartState('cart'), 1500);
|
|
};
|
|
|
|
const handleCompare = () => {
|
|
if (inCompare) removeCompare(currentProduct.slug);
|
|
else addCompare({ slug: currentProduct.slug, name: currentProduct.name, brand: currentProduct.brand, price: currentProduct.price, image: currentProduct.image, specs: currentProduct.specs });
|
|
};
|
|
|
|
// Kalkulator
|
|
const mocChlodnicza = parseMoc(currentProduct.specs['Moc chłodnicza'] || '');
|
|
const pobórMocy = parseMoc(currentProduct.specs['Pobór mocy chłodzenie (kW)'] || '') || (mocChlodnicza / estimateSEER(currentProduct.specs['Klasa energetyczna'] || ''));
|
|
const cenaKwh = 0.75;
|
|
const kosztGodzina = pobórMocy * cenaKwh;
|
|
const kosztMiesiac = kosztGodzina * godziny * 30;
|
|
|
|
// Kluczowe parametry do ikon
|
|
const params = [
|
|
currentProduct.specs['Klasa energetyczna'] && { icon: Star, label: 'Klasa energetyczna', value: currentProduct.specs['Klasa energetyczna'], color: 'text-green-600 bg-green-50' },
|
|
currentProduct.specs['Moc chłodnicza'] && { icon: Thermometer, label: 'Moc chłodnicza', value: `${currentProduct.specs['Moc chłodnicza']} kW`, color: 'text-blue-600 bg-blue-50' },
|
|
currentProduct.specs['Moc grzewcza (kW)'] && { icon: Thermometer, label: 'Moc grzewcza', value: `${currentProduct.specs['Moc grzewcza (kW)']} kW`, color: 'text-orange-600 bg-orange-50' },
|
|
currentProduct.specs['Hałas wewnątrz (dB)'] && { icon: Volume2, label: 'Hałas wewnątrz', value: `${currentProduct.specs['Hałas wewnątrz (dB)']} dB`, color: 'text-purple-600 bg-purple-50' },
|
|
currentProduct.specs['Czynnik chłodniczy'] && { icon: Wind, label: 'Czynnik', value: currentProduct.specs['Czynnik chłodniczy'], color: 'text-teal-600 bg-teal-50' },
|
|
currentProduct.specs['Grzanie do'] && { icon: Zap, label: 'Grzanie do', value: `-${currentProduct.specs['Grzanie do']}°C`, color: 'text-accent bg-accent-light' },
|
|
].filter(Boolean) as { icon: any; label: string; value: string; color: string }[];
|
|
|
|
return (
|
|
<main className="bg-slate-50 min-h-screen pb-16">
|
|
<div className="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8 py-6">
|
|
|
|
{/* Breadcrumb */}
|
|
<nav className="flex items-center gap-1.5 text-xs text-text-muted mb-6">
|
|
<Link href="/" className="hover:text-accent transition-colors">Strona główna</Link>
|
|
<span>/</span>
|
|
<Link href="/sklep" className="hover:text-accent transition-colors">Sklep</Link>
|
|
<span>/</span>
|
|
<Link href={`/sklep?brand=${currentProduct.brand}`} className="hover:text-accent transition-colors">{currentProduct.brand}</Link>
|
|
<span>/</span>
|
|
<span className="text-primary font-medium truncate max-w-[200px]">{currentProduct.name}</span>
|
|
</nav>
|
|
|
|
<div className="grid grid-cols-1 lg:grid-cols-2 gap-8 xl:gap-12">
|
|
|
|
{/* LEWA: Zdjęcie */}
|
|
<div>
|
|
<div className="relative aspect-[4/3] lg:aspect-auto lg:h-[420px] lg:max-h-[420px] bg-white rounded-2xl border border-border overflow-hidden">
|
|
<Image
|
|
src={currentProduct.image}
|
|
alt={currentProduct.name}
|
|
fill
|
|
className="object-contain p-6"
|
|
priority
|
|
unoptimized={currentProduct.image.startsWith('http')}
|
|
/>
|
|
{/* Badges */}
|
|
{currentProduct.specs['Klasa energetyczna'] && (
|
|
<div className="absolute top-4 left-4 px-2.5 py-1 bg-green-500 text-white text-xs font-bold rounded-lg shadow">
|
|
{currentProduct.specs['Klasa energetyczna'].split('/')[0]}
|
|
</div>
|
|
)}
|
|
{currentProduct.category === 'multisplit' && (
|
|
<div className="absolute top-4 right-4 px-2.5 py-1 bg-accent text-white text-xs font-bold rounded-lg shadow">
|
|
MULTISPLIT
|
|
</div>
|
|
)}
|
|
</div>
|
|
</div>
|
|
|
|
{/* PRAWA: Info */}
|
|
<div className="flex flex-col gap-3">
|
|
{/* Nagłówek */}
|
|
<div>
|
|
<div className="mb-2 flex items-center gap-3 flex-wrap">
|
|
{brandLogos[currentProduct.brand] ? (
|
|
<div className="bg-white rounded-lg p-1.5 inline-block border border-border">
|
|
<Image
|
|
src={brandLogos[currentProduct.brand]}
|
|
alt={currentProduct.brand}
|
|
width={80}
|
|
height={28}
|
|
className="object-contain object-left"
|
|
unoptimized
|
|
/>
|
|
</div>
|
|
) : (
|
|
<span className="text-xs font-bold text-accent uppercase tracking-widest">
|
|
{currentProduct.brand}
|
|
</span>
|
|
)}
|
|
|
|
{currentProduct.brand === 'LG' && (
|
|
<Link href="/serwis-lg">
|
|
<div className="inline-flex items-center gap-1.5 px-3 py-1 bg-green-50 border border-green-200 rounded-full text-xs font-semibold text-green-700 hover:bg-green-100 transition-colors cursor-pointer">
|
|
<Check className="size-3.5" />
|
|
Serwisujemy urządzenia LG ✓
|
|
</div>
|
|
</Link>
|
|
)}
|
|
</div>
|
|
<h1 className="text-2xl md:text-3xl font-extrabold text-primary font-heading leading-tight">
|
|
{currentProduct.name}
|
|
</h1>
|
|
<p className="text-xs text-text-muted mt-1.5 mb-4">SKU: {currentProduct.sku}</p>
|
|
</div>
|
|
|
|
{/* Warianty mocy */}
|
|
{variants && variants.moce.length > 0 && (
|
|
<div className="mb-3">
|
|
<p className="text-xs font-semibold text-text-muted uppercase tracking-wider mb-2">
|
|
Dostępne moce (kW):
|
|
</p>
|
|
<div className="flex flex-wrap gap-2">
|
|
{variants.moce.map((v) => (
|
|
<button
|
|
key={v.slug}
|
|
onClick={() => {
|
|
const p = seriesProducts.find(sp => sp.slug === v.slug);
|
|
if (p) {
|
|
setCurrentProduct(p);
|
|
window.history.pushState(null, '', `/sklep/${v.slug}`);
|
|
}
|
|
}}
|
|
className={`px-3 py-1.5 rounded-xl text-xs font-bold border-2 transition-all ${
|
|
v.slug === currentProduct.slug
|
|
? 'border-accent bg-accent text-white shadow-sm'
|
|
: 'border-border bg-white text-primary hover:border-accent hover:text-accent'
|
|
}`}
|
|
>
|
|
{v.moc} kW
|
|
{v.slug !== currentProduct.slug && (
|
|
<span className="block text-[10px] font-normal opacity-70 mt-0.5">
|
|
{v.cena.toLocaleString('pl-PL')} zł
|
|
</span>
|
|
)}
|
|
{v.slug === currentProduct.slug && (
|
|
<span className="block text-[10px] font-normal opacity-80 mt-0.5">
|
|
{v.cena.toLocaleString('pl-PL')} zł
|
|
</span>
|
|
)}
|
|
</button>
|
|
))}
|
|
</div>
|
|
</div>
|
|
)}
|
|
|
|
{/* Warianty wykończenia */}
|
|
{variants && variants.wykończenia.length > 0 && (
|
|
<div className="mb-3">
|
|
<p className="text-xs font-semibold text-text-muted uppercase tracking-wider mb-2">
|
|
Wykończenie:
|
|
</p>
|
|
<div className="flex flex-wrap gap-2">
|
|
{variants.wykończenia.map((v) => (
|
|
<button
|
|
key={v.slug}
|
|
onClick={() => {
|
|
const p = seriesProducts.find(sp => sp.slug === v.slug);
|
|
if (p) {
|
|
setCurrentProduct(p);
|
|
window.history.pushState(null, '', `/sklep/${v.slug}`);
|
|
}
|
|
}}
|
|
className={`px-3 py-1.5 rounded-xl text-xs font-bold border-2 transition-all ${
|
|
v.slug === currentProduct.slug
|
|
? 'border-accent bg-accent text-white shadow-sm'
|
|
: 'border-border bg-white text-primary hover:border-accent hover:text-accent'
|
|
}`}
|
|
>
|
|
{v.wykończenie}
|
|
</button>
|
|
))}
|
|
</div>
|
|
</div>
|
|
)}
|
|
|
|
{/* Ikony parametrów */}
|
|
{params.length > 0 && (
|
|
<div className="flex flex-wrap gap-2">
|
|
{params.map((p, i) => {
|
|
const Icon = p.icon;
|
|
return (
|
|
<div key={i} className={`flex items-center gap-1.5 px-2.5 py-1.5 rounded-lg ${p.color} border border-current/10`}>
|
|
<Icon className="size-3.5 shrink-0" />
|
|
<div className="min-w-0">
|
|
<p className="text-[9px] font-medium opacity-70 leading-none mb-0.5">{p.label}</p>
|
|
<p className="text-[11px] font-bold truncate">{p.value}</p>
|
|
</div>
|
|
</div>
|
|
);
|
|
})}
|
|
</div>
|
|
)}
|
|
|
|
{/* Cena i CTA */}
|
|
<div className="bg-white rounded-2xl border border-border p-4">
|
|
{currentProduct.price !== null ? (
|
|
<>
|
|
<div className="flex items-end gap-3 mb-1">
|
|
<span className="text-2xl font-extrabold text-primary font-heading">
|
|
{currentProduct.price.toLocaleString('pl-PL')} zł
|
|
</span>
|
|
</div>
|
|
<p className="text-xs text-text-muted mb-1">cena urządzenia brutto (23% VAT)</p>
|
|
<p className="text-xs text-text-muted mb-4">Montaż wyceniamy indywidualnie — zadzwoń lub napisz</p>
|
|
|
|
<div className="flex flex-col sm:flex-row gap-3">
|
|
{cartState === 'idle' && (
|
|
<button
|
|
onClick={handleAddToCart}
|
|
className="flex-1 flex items-center justify-center gap-2 py-2.5 px-4 rounded-xl font-bold text-sm bg-accent text-white hover:bg-accent/90 transition-all"
|
|
>
|
|
<ShoppingCart className="size-4" /> Do koszyka
|
|
</button>
|
|
)}
|
|
{cartState === 'added' && (
|
|
<button
|
|
disabled
|
|
className="flex-1 flex items-center justify-center gap-2 py-2.5 px-4 rounded-xl font-bold text-sm bg-green-500 text-white"
|
|
>
|
|
<Check className="size-4" /> Dodano do koszyka
|
|
</button>
|
|
)}
|
|
{cartState === 'cart' && (
|
|
<Link href="/koszyk" className="flex-1 w-full flex items-center justify-center gap-2 py-2.5 px-4 rounded-xl font-bold text-sm bg-green-500 text-white hover:bg-green-600 transition-colors">
|
|
|
|
<ShoppingCart className="size-4" /> Zobacz koszyk
|
|
|
|
</Link>
|
|
)}
|
|
<Link href="/kontakt" className="flex-1 w-full flex items-center justify-center gap-2 py-2.5 px-4 rounded-xl font-bold text-sm border-2 border-primary text-primary hover:bg-primary hover:text-white transition-all">
|
|
|
|
Zapytaj o montaż
|
|
|
|
</Link>
|
|
</div>
|
|
|
|
<button
|
|
onClick={handleCompare}
|
|
className={`w-full mt-2 flex items-center justify-center gap-2 py-2 px-4 rounded-xl text-xs font-medium transition-colors ${
|
|
inCompare ? 'bg-accent/10 text-accent border border-accent' : 'bg-slate-50 text-text-muted border border-border hover:border-accent hover:text-accent'
|
|
}`}
|
|
>
|
|
<GitCompare className="size-3.5" />
|
|
{inCompare ? 'Usuń z porównania' : 'Dodaj do porównania'}
|
|
</button>
|
|
</>
|
|
) : (
|
|
<>
|
|
<p className="text-lg font-bold text-primary font-heading mb-1">Cena na zapytanie</p>
|
|
<p className="text-sm text-text-muted mb-4">Multisplit — cena zależy od konfiguracji jednostek wewnętrznych.</p>
|
|
<a href={`tel:${companyPhoneRaw}`} className="flex items-center justify-center gap-2 py-3 px-4 rounded-xl bg-accent text-white font-bold text-sm hover:bg-accent/90 transition-colors">
|
|
<Phone className="size-4" /> Zadzwoń: {companyPhone}
|
|
</a>
|
|
</>
|
|
)}
|
|
</div>
|
|
|
|
{/* Profesjonalna porada */}
|
|
<a
|
|
href={`tel:${companyPhoneRaw}`}
|
|
className="flex items-center justify-between px-5 py-2.5 bg-primary rounded-xl text-white hover:bg-primary/90 transition-colors"
|
|
>
|
|
<span className="text-xs font-semibold">Profesjonalna porada</span>
|
|
<span className="flex items-center gap-2 font-bold">
|
|
<Phone className="size-4" /> {companyPhone}
|
|
</span>
|
|
</a>
|
|
|
|
{/* Kalkulator kosztów energii */}
|
|
{mocChlodnicza > 0 && (
|
|
<div className="bg-white rounded-2xl border border-border p-4">
|
|
<div className="flex items-center gap-2 mb-4">
|
|
<Zap className="size-4 text-accent" />
|
|
<h2 className="text-sm font-bold text-primary font-heading">Kalkulator kosztów energii</h2>
|
|
<div className="group relative ml-auto">
|
|
<Info className="size-4 text-text-muted cursor-help" />
|
|
<div className="absolute right-0 bottom-6 w-56 bg-primary text-white text-xs rounded-lg p-2.5 hidden group-hover:block z-10">
|
|
Szacunek przy cenie prądu {cenaKwh} zł/kWh. Rzeczywiste koszty mogą się różnić.
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<div className="flex items-center gap-4 mb-4">
|
|
<label className="text-xs text-text-muted shrink-0">Godziny użycia dziennie:</label>
|
|
<input
|
|
type="range"
|
|
min={1}
|
|
max={24}
|
|
value={godziny}
|
|
onChange={e => setGodziny(Number(e.target.value))}
|
|
className="range range-xs range-accent flex-1"
|
|
/>
|
|
<span className="text-sm font-bold text-primary w-8 text-right">{godziny}h</span>
|
|
</div>
|
|
|
|
<div className="grid grid-cols-2 gap-3">
|
|
<div className="bg-slate-50 rounded-xl p-3 text-center">
|
|
<p className="text-xs text-text-muted mb-1">Koszt / godzinę</p>
|
|
<p className="text-lg font-bold text-primary font-heading">
|
|
{kosztGodzina.toFixed(2)} zł
|
|
</p>
|
|
</div>
|
|
<div className="bg-accent-light rounded-xl p-3 text-center border border-accent/20">
|
|
<p className="text-xs text-accent mb-1">Koszt miesięczny</p>
|
|
<p className="text-lg font-bold text-accent font-heading">
|
|
{kosztMiesiac.toFixed(2)} zł
|
|
</p>
|
|
</div>
|
|
</div>
|
|
<p className="text-[10px] text-text-muted mt-2 text-center">
|
|
Szacunek przy {cenaKwh} zł/kWh · {godziny}h/dzień · 30 dni
|
|
{!currentProduct.specs['Pobór mocy chłodzenie (kW)'] && ' · pobór szacowany z klasy energetycznej'}
|
|
</p>
|
|
</div>
|
|
)}
|
|
</div>
|
|
</div>
|
|
|
|
{/* TABS */}
|
|
<div className="mt-10">
|
|
<div className="flex gap-1 border-b border-border mb-6 overflow-x-auto [&::-webkit-scrollbar]:hidden [-ms-overflow-style:none] [scrollbar-width:none]">
|
|
{TABS.map(tab => (
|
|
<button
|
|
key={tab}
|
|
onClick={() => setActiveTab(tab)}
|
|
className={`px-5 py-3 text-sm font-semibold whitespace-nowrap transition-colors border-b-2 -mb-px ${
|
|
activeTab === tab
|
|
? 'border-accent text-accent'
|
|
: 'border-transparent text-text-muted hover:text-primary'
|
|
}`}
|
|
>
|
|
{tab}
|
|
</button>
|
|
))}
|
|
</div>
|
|
|
|
{/* Tab: Opis */}
|
|
{activeTab === 'Opis' && (
|
|
<div className="max-w-3xl">
|
|
{currentProduct.shortDescription ? (
|
|
<p className="text-text-muted leading-relaxed text-base">{currentProduct.shortDescription}</p>
|
|
) : (
|
|
<p className="text-text-muted">Brak opisu produktu.</p>
|
|
)}
|
|
</div>
|
|
)}
|
|
|
|
{/* Tab: Specyfikacja */}
|
|
{activeTab === 'Specyfikacja' && (
|
|
<div className="max-w-2xl">
|
|
{Object.keys(currentProduct.specs).length > 0 ? (
|
|
<div className="rounded-xl border border-border overflow-hidden">
|
|
<table className="w-full text-sm">
|
|
<tbody>
|
|
{Object.entries(currentProduct.specs).map(([key, val], idx) => (
|
|
<tr key={key} className={idx % 2 === 0 ? 'bg-white' : 'bg-slate-50'}>
|
|
<td className="px-5 py-3 text-text-muted font-medium w-1/2 border-r border-border">{key}</td>
|
|
<td className="px-5 py-3 text-primary font-semibold">{val}</td>
|
|
</tr>
|
|
))}
|
|
</tbody>
|
|
</table>
|
|
</div>
|
|
) : (
|
|
<p className="text-text-muted">Brak specyfikacji.</p>
|
|
)}
|
|
</div>
|
|
)}
|
|
|
|
{/* Tab: Montaż */}
|
|
{activeTab === 'Montaż' && (
|
|
<div className="max-w-2xl space-y-4">
|
|
<div className="bg-white rounded-xl border border-border p-5">
|
|
<h3 className="font-bold text-primary font-heading mb-3">Montaż klimatyzacji</h3>
|
|
<p className="text-sm text-text-muted leading-relaxed mb-4">
|
|
Oferujemy profesjonalny montaż wszystkich klimatyzatorów z naszego sklepu na terenie Dolnego Śląska.
|
|
Montaż wykonujemy z uprawnieniami F-Gaz, estetycznie i terminowo.
|
|
</p>
|
|
<ul className="space-y-2 text-sm text-text-muted">
|
|
{['Bezpłatna wycena montażu przed realizacją', 'Uprawnienia F-Gaz — wymóg prawny', 'Próba szczelności i próżnia po montażu', 'Szkolenie z obsługi urządzenia', 'Gwarancja na wykonaną instalację'].map(item => (
|
|
<li key={item} className="flex items-center gap-2">
|
|
<Check className="size-4 text-green-500 shrink-0" />
|
|
{item}
|
|
</li>
|
|
))}
|
|
</ul>
|
|
<a href={`tel:${companyPhoneRaw}`} className="mt-4 inline-flex items-center gap-2 btn btn-primary text-white font-bold text-sm">
|
|
<Phone className="size-4" /> Zapytaj o montaż
|
|
</a>
|
|
</div>
|
|
</div>
|
|
)}
|
|
|
|
{/* Tab: Opinie */}
|
|
{activeTab === 'Opinie' && (
|
|
<div className="max-w-3xl space-y-8">
|
|
<div className="bg-slate-50 p-6 rounded-2xl border border-border">
|
|
<h3 className="font-bold text-primary font-heading mb-4">Dodaj opinię</h3>
|
|
<form className="space-y-4" onSubmit={(e) => { e.preventDefault(); alert('Opinia została wysłana i oczekuje na moderację.'); e.currentTarget.reset(); }}>
|
|
<div className="flex gap-1 mb-2">
|
|
{[1,2,3,4,5].map(star => (
|
|
<Star key={star} className="size-6 text-amber-400 cursor-pointer fill-amber-400 hover:scale-110 transition-transform" />
|
|
))}
|
|
</div>
|
|
<div className="grid grid-cols-1 sm:grid-cols-2 gap-4">
|
|
<div className="space-y-1.5">
|
|
<label className="text-sm font-semibold text-primary">Imię</label>
|
|
<input type="text" required className="w-full px-4 py-2.5 rounded-xl border border-border bg-white text-sm focus:outline-none focus:ring-2 focus:ring-accent/50" placeholder="Twoje imię" />
|
|
</div>
|
|
<div className="space-y-1.5">
|
|
<label className="text-sm font-semibold text-primary">Email</label>
|
|
<input type="email" required className="w-full px-4 py-2.5 rounded-xl border border-border bg-white text-sm focus:outline-none focus:ring-2 focus:ring-accent/50" placeholder="twó[email protected]" />
|
|
</div>
|
|
</div>
|
|
<div className="space-y-1.5">
|
|
<label className="text-sm font-semibold text-primary">Treść opinii</label>
|
|
<textarea required rows={4} className="w-full px-4 py-2.5 rounded-xl border border-border bg-white text-sm focus:outline-none focus:ring-2 focus:ring-accent/50" placeholder="Podziel się swoimi wrażeniami..."></textarea>
|
|
</div>
|
|
<button type="submit" className="btn btn-primary font-bold text-white w-full sm:w-auto">Wyślij opinię</button>
|
|
</form>
|
|
</div>
|
|
<div className="space-y-4">
|
|
<h3 className="font-bold text-primary font-heading">Opinie klientów (0)</h3>
|
|
<p className="text-sm text-text-muted">Bądź pierwszą osobą, która oceni ten produkt!</p>
|
|
</div>
|
|
</div>
|
|
)}
|
|
|
|
|
|
</div>
|
|
</div>
|
|
|
|
{showViewsBanner && (
|
|
<div className="fixed bottom-24 left-6 z-50 flex items-center gap-3 bg-white border border-amber-200 shadow-lg rounded-xl px-4 py-3 max-w-xs animate-in slide-in-from-left-4 duration-300">
|
|
<Eye className="size-4 text-amber-500 shrink-0" />
|
|
<p className="text-sm text-gray-800">
|
|
W ostatnich 30 dniach interesuje się tym produktem <span className="font-bold">{viewsCount}</span> osób.
|
|
</p>
|
|
<button
|
|
onClick={() => setShowViewsBanner(false)}
|
|
className="text-gray-400 hover:text-gray-600 transition-colors shrink-0 ml-1"
|
|
aria-label="Zamknij"
|
|
>
|
|
<X className="size-4" />
|
|
</button>
|
|
</div>
|
|
)}
|
|
</main>
|
|
);
|
|
}
|