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)
This commit is contained in:
@@ -11,6 +11,9 @@ import { Product } from '@/content/products';
|
||||
import { useCartStore } from '@/lib/cart-store';
|
||||
import { useCompareStore } from '@/lib/compare-store';
|
||||
import { getProductVariants } from '@/content/product-variants';
|
||||
import { useRecentlyViewedStore } from '@/lib/recently-viewed-store';
|
||||
import { RecentlyViewedProducts } from './RecentlyViewedProducts';
|
||||
import { useEffect } from 'react';
|
||||
|
||||
const brandLogos: Record<string, string> = {
|
||||
'Gree': '/brands/gree.webp',
|
||||
@@ -34,7 +37,6 @@ interface Props {
|
||||
companyPhoneRaw: string;
|
||||
}
|
||||
|
||||
// Szacowany SEER na podstawie klasy energetycznej
|
||||
function estimateSEER(klasa: string): number {
|
||||
if (!klasa) return 5.0;
|
||||
const k = klasa.toUpperCase();
|
||||
@@ -45,7 +47,6 @@ function estimateSEER(klasa: string): number {
|
||||
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);
|
||||
@@ -81,6 +82,11 @@ export function ProductPageClient({ product, seriesProducts, companyPhone, compa
|
||||
const { addItem: addCompare, removeItem: removeCompare, isAdded } = useCompareStore();
|
||||
const inCompare = isAdded(currentProduct.slug);
|
||||
|
||||
const addRecentlyViewed = useRecentlyViewedStore((s) => s.addItem);
|
||||
useEffect(() => {
|
||||
addRecentlyViewed(currentProduct);
|
||||
}, [currentProduct, addRecentlyViewed]);
|
||||
|
||||
const handleAddToCart = () => {
|
||||
if (!currentProduct.price) return;
|
||||
addToCart({
|
||||
@@ -99,14 +105,12 @@ export function ProductPageClient({ product, seriesProducts, companyPhone, compa
|
||||
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' },
|
||||
@@ -120,7 +124,6 @@ export function ProductPageClient({ product, seriesProducts, companyPhone, compa
|
||||
<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>
|
||||
@@ -133,7 +136,6 @@ export function ProductPageClient({ product, seriesProducts, companyPhone, compa
|
||||
|
||||
<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
|
||||
@@ -144,7 +146,6 @@ export function ProductPageClient({ product, seriesProducts, companyPhone, compa
|
||||
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]}
|
||||
@@ -158,9 +159,7 @@ export function ProductPageClient({ product, seriesProducts, companyPhone, compa
|
||||
</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] ? (
|
||||
@@ -195,7 +194,6 @@ export function ProductPageClient({ product, seriesProducts, companyPhone, compa
|
||||
<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">
|
||||
@@ -235,7 +233,6 @@ export function ProductPageClient({ product, seriesProducts, companyPhone, compa
|
||||
</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">
|
||||
@@ -265,7 +262,6 @@ export function ProductPageClient({ product, seriesProducts, companyPhone, compa
|
||||
</div>
|
||||
)}
|
||||
|
||||
{/* Ikony parametrów */}
|
||||
{params.length > 0 && (
|
||||
<div className="flex flex-wrap gap-2">
|
||||
{params.map((p, i) => {
|
||||
@@ -283,7 +279,6 @@ export function ProductPageClient({ product, seriesProducts, companyPhone, compa
|
||||
</div>
|
||||
)}
|
||||
|
||||
{/* Cena i CTA */}
|
||||
<div className="bg-white rounded-2xl border border-border p-4">
|
||||
{currentProduct.price !== null ? (
|
||||
<>
|
||||
@@ -347,7 +342,6 @@ export function ProductPageClient({ product, seriesProducts, companyPhone, compa
|
||||
)}
|
||||
</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"
|
||||
@@ -358,7 +352,6 @@ export function ProductPageClient({ product, seriesProducts, companyPhone, compa
|
||||
</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">
|
||||
@@ -408,7 +401,6 @@ export function ProductPageClient({ product, seriesProducts, companyPhone, compa
|
||||
</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 => (
|
||||
@@ -426,7 +418,6 @@ export function ProductPageClient({ product, seriesProducts, companyPhone, compa
|
||||
))}
|
||||
</div>
|
||||
|
||||
{/* Tab: Opis */}
|
||||
{activeTab === 'Opis' && (
|
||||
<div className="max-w-3xl">
|
||||
{currentProduct.shortDescription ? (
|
||||
@@ -437,7 +428,6 @@ export function ProductPageClient({ product, seriesProducts, companyPhone, compa
|
||||
</div>
|
||||
)}
|
||||
|
||||
{/* Tab: Specyfikacja */}
|
||||
{activeTab === 'Specyfikacja' && (
|
||||
<div className="max-w-2xl">
|
||||
{Object.keys(currentProduct.specs).length > 0 ? (
|
||||
@@ -459,7 +449,6 @@ export function ProductPageClient({ product, seriesProducts, companyPhone, compa
|
||||
</div>
|
||||
)}
|
||||
|
||||
{/* Tab: Montaż */}
|
||||
{activeTab === 'Montaż' && (
|
||||
<div className="max-w-2xl space-y-4">
|
||||
<div className="bg-white rounded-xl border border-border p-5">
|
||||
@@ -483,7 +472,6 @@ export function ProductPageClient({ product, seriesProducts, companyPhone, compa
|
||||
</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">
|
||||
@@ -512,7 +500,7 @@ export function ProductPageClient({ product, seriesProducts, companyPhone, compa
|
||||
</div>
|
||||
)}
|
||||
|
||||
|
||||
<RecentlyViewedProducts currentSlug={currentProduct.slug} />
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
Reference in New Issue
Block a user