Zastosowanie wszystkich poprawek UI i logiki kalkulatora

This commit is contained in:
AI Assistant
2026-08-10 23:26:52 +02:00
commit 7324a6f800
218 changed files with 33628 additions and 0 deletions
+145
View File
@@ -0,0 +1,145 @@
import { Metadata } from 'next';
import { notFound } from 'next/navigation';
import { getProductBySlug, getProducts } from '@/content/products';
import { companyDetails } from '@/content/company';
import Image from 'next/image';
import Link from 'next/link';
import { ArrowLeft, Phone, Zap, Wind, Volume2, Thermometer } from 'lucide-react';
import MultisplitContactForm from '@/components/shop/MultisplitContactForm';
interface Props {
params: Promise<{ slug: string }>;
}
export async function generateStaticParams() {
return getProducts()
.filter(p => p.category === 'multisplit')
.map(p => ({ slug: p.slug }));
}
export async function generateMetadata({ params }: Props): Promise<Metadata> {
const { slug } = await params;
const product = getProductBySlug(slug);
if (!product) return { title: 'Produkt nie znaleziony' };
return {
title: `Zapytaj o ${product.name}`,
description: `Zapytaj o wycenę systemu multisplit ${product.name}. Bezpłatna konsultacja i wycena montażu.`,
};
}
export default async function MultisplitInquiryPage({ params }: Props) {
const { slug } = await params;
const product = getProductBySlug(slug);
if (!product || product.category !== 'multisplit') notFound();
const specIcons: Record<string, React.ElementType> = {
'Moc chłodnicza': Zap,
'Moc grzewcza': Thermometer,
'Głośność wewnętrzna (dB)': Volume2,
'Klasa energetyczna': Wind,
};
const keySpecs = ['Moc chłodnicza', 'Moc grzewcza', 'Klasa energetyczna', 'Głośność wewnętrzna (dB)'];
return (
<main className="bg-slate-50 min-h-screen">
{/* Breadcrumb */}
<div className="bg-white border-b border-border">
<div className="max-w-5xl mx-auto px-4 py-3">
<nav className="flex items-center gap-1.5 text-xs text-text-muted">
<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?category=multisplit" className="hover:text-accent transition-colors">Multisplit</Link>
<span>/</span>
<span className="text-primary font-medium truncate max-w-[200px]">{product.name}</span>
</nav>
</div>
</div>
<div className="max-w-5xl mx-auto px-4 py-10">
<Link href="/sklep?category=multisplit" className="inline-flex items-center gap-1.5 text-sm text-text-muted hover:text-accent transition-colors mb-6">
<ArrowLeft className="size-4" /> Wróć do multisplitów
</Link>
<div className="grid grid-cols-1 lg:grid-cols-2 gap-8 mb-10">
{/* Lewa — zdjęcie + specyfikacja */}
<div className="flex flex-col gap-4">
<div className="bg-white rounded-2xl border border-border p-6">
<div className="flex items-center justify-between mb-4">
<span className="text-xs font-bold text-white bg-accent px-2.5 py-1 rounded-full">Multisplit</span>
<span className="text-xs text-text-muted">{product.brand}</span>
</div>
<div className="relative w-full h-56 mb-4 bg-slate-100 rounded-xl flex items-center justify-center">
{product.image && !product.image.includes('placeholder') ? (
<Image
src={product.image}
alt={product.name}
fill
className="object-contain"
/>
) : (
<div className="flex flex-col items-center gap-2 text-text-muted">
<Wind className="size-12 text-slate-300" />
<span className="text-xs">Zdjęcie wkrótce</span>
</div>
)}
</div>
<h1 className="text-lg font-extrabold text-primary font-heading mb-1">{product.name}</h1>
{product.shortDescription && (
<p className="text-sm text-text-muted">{product.shortDescription}</p>
)}
</div>
{/* Kluczowe parametry */}
<div className="bg-white rounded-2xl border border-border p-5">
<h2 className="text-sm font-bold text-primary mb-3">Kluczowe parametry</h2>
<div className="grid grid-cols-2 gap-3">
{keySpecs.map(key => {
const val = product.specs?.[key];
if (!val) return null;
const Icon = specIcons[key] || Zap;
return (
<div key={key} className="flex items-start gap-2 p-3 bg-slate-50 rounded-xl">
<Icon className="size-4 text-accent shrink-0 mt-0.5" />
<div>
<p className="text-xs text-text-muted">{key}</p>
<p className="text-sm font-bold text-primary">{val}</p>
</div>
</div>
);
})}
</div>
</div>
{/* Wycena indywidualna info */}
<div className="bg-accent/10 border border-accent/20 rounded-2xl p-5">
<p className="text-sm font-bold text-accent mb-1">Wycena indywidualna</p>
<p className="text-xs text-text-muted leading-relaxed">
Cena systemu multisplit zależy od liczby pomieszczeń, długości instalacji i warunków montażu.
Wypełnij formularz — oddzwonimy z bezpłatną wyceną w ciągu 24 godzin.
</p>
<a href={`tel:${companyDetails.phoneRaw}`} className="inline-flex items-center gap-1.5 mt-3 text-sm font-bold text-accent hover:underline">
<Phone className="size-4" /> {companyDetails.phone}
</a>
</div>
</div>
{/* Prawa — formularz */}
<div>
<div className="bg-white rounded-2xl border border-border p-6">
<h2 className="text-base font-extrabold text-primary font-heading mb-1">
Zapytaj o wycenę
</h2>
<p className="text-sm text-text-muted mb-6">
Wypełnij formularz — skontaktujemy się w ciągu 24 godzin z bezpłatną wyceną montażu.
</p>
<MultisplitContactForm productName={product.name} productSku={product.sku} />
</div>
</div>
</div>
</div>
</main>
);
}