Files
2026-08-25 23:51:18 +02:00

623 lines
31 KiB
TypeScript
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
'use client';
import { useState, useEffect, useMemo } from 'react';
import Link from 'next/link';
import { ArrowRight, ArrowLeft, Check, Home, Zap, ShoppingCart, Phone } from 'lucide-react';
import { Product } from '@/content/products';
import { companyDetails } from '@/content/company';
import { Button, buttonClasses } from '@/components/ui/Button';
interface Props {
products: Product[];
}
// Hook do zapisywania stanu w sessionStorage
function useSessionState<T>(key: string, initialValue: T) {
const [state, setState] = useState<T>(initialValue);
useEffect(() => {
try {
const item = window.sessionStorage.getItem(key);
if (item) {
const timer = setTimeout(() => setState(JSON.parse(item)), 0);
return () => clearTimeout(timer);
}
} catch {}
}, [key]);
const setValue = (value: T | ((val: T) => T)) => {
try {
const valueToStore = value instanceof Function ? value(state) : value;
setState(valueToStore);
if (typeof window !== 'undefined') {
window.sessionStorage.setItem(key, JSON.stringify(valueToStore));
}
} catch {}
};
return [state, setValue] as const;
}
// Oblicz wymaganą moc chłodniczą w kW
function calculatePower(m2: number, floor: string, sun: string, building: string): number {
let power = m2 * 0.1; // baza: 1 kW na 10 m²
// Korekta typu budynku i piętra
if (building === 'apartment') {
if (floor === 'top') power *= 1.2; // ostatnie piętro - więcej ciepła z dachu
if (floor === 'ground') power *= 0.95;
} else if (building === 'house') {
if (floor === 'top') power *= 1.1; // poddasze - dodatkowe nagrzewanie
}
// Korekta nasłonecznienia
if (sun === 'south') power *= 1.15; // południe - duże nasłonecznienie
if (sun === 'west') power *= 1.1;
if (sun === 'north') power *= 0.9;
return Math.round(power * 10) / 10;
}
// Szacunkowy koszt montażu
function estimateInstall(pipes: string, rooms: number, installMethod: string): { min: number; max: number } {
const base = rooms === 1 ? 1400 : rooms === 2 ? 2400 : rooms === 3 ? 3200 : 3800;
// Przybliżona liczba dodatkowych metrów (powyżej 3m)
const extraMeters = pipes === 'short' ? 0 : pipes === 'medium' ? 3 : pipes === 'long' ? 7 : 15;
const methodPrice = installMethod === 'bruzda' ? 90 : 80; // zł za metr
// Zostawmy bazowe koszty rur miedzianych (np. miedź, kable) i dodajmy koszt bruzdy/korytka
const pipeBaseCost = pipes === 'short' ? 0 : pipes === 'medium' ? 200 : pipes === 'long' ? 500 : 1000;
const pipeExtra = pipeBaseCost + (extraMeters * methodPrice);
return { min: base + pipeExtra, max: base + pipeExtra + 600 };
}
const STEPS = ['Pomieszczenie', 'Instalacja', 'Budżet'] as const;
export function KalkulatorClient({ products }: Props) {
const [showWidthWarning, setShowWidthWarning] = useState(false);
const [maxWidth, setMaxWidth] = useState(80);
const [step, setStep] = useSessionState('calc_step', 0);
const [building, setBuilding] = useSessionState('calc_building', 'apartment');
const [pomieszczenia, setPomieszczenia] = useSessionState<{ nazwa: string; m2: number }[]>('calc_pomieszczenia', [
{ nazwa: 'Pokój 1', m2: 20 }
]);
const [floor, setFloor] = useSessionState('calc_floor', 'middle'); // ground | middle | top
const [sun, setSun] = useSessionState('calc_sun', 'south'); // north | east | south | west
const addRoom = () => {
if (pomieszczenia.length < 5) {
setPomieszczenia(prev => [...prev, { nazwa: `Pokój ${prev.length + 1}`, m2: 15 }]);
}
};
const removeRoom = (i: number) => {
if (pomieszczenia.length > 1) {
setPomieszczenia(prev => prev.filter((_, idx) => idx !== i));
}
};
const updateRoom = (i: number, m2: number) => {
setPomieszczenia(prev => prev.map((r, idx) => idx === i ? { ...r, m2 } : r));
};
const [pipes, setPipes] = useSessionState('calc_pipes', 'medium'); // short(<3m) | medium(3-6m) | long(6-10m) | verylong(>10m)
const [installMethod, setInstallMethod] = useSessionState<'korytko' | 'bruzda'>('calc_installMethod', 'korytko');
const [budget, setBudget] = useSessionState('calc_budget', 8000);
const [preferredBrand, setPreferredBrand] = useSessionState('calc_brand', '');
const [energyClass, setEnergyClass] = useSessionState('calc_energy', '');
const [page, setPage] = useSessionState('calc_page', 1);
const totalM2 = pomieszczenia.reduce((sum, p) => sum + p.m2, 0);
const rooms = pomieszczenia.length;
const requiredPower = useMemo(() =>
pomieszczenia.reduce((sum, p) => sum + calculatePower(p.m2, floor, sun, building), 0),
[pomieszczenia, floor, sun, building]
);
const requiredPowerRounded = Math.round(requiredPower * 10) / 10;
const installCost = useMemo(() => estimateInstall(pipes, rooms, installMethod), [pipes, rooms, installMethod]);
const category = rooms === 1 ? 'scienne' : 'multisplit';
const handleNext = () => {
setStep(s => s + 1);
setPage(1);
window.scrollTo({ top: 0, behavior: 'smooth' });
};
const getShopUrl = () => {
const params = new URLSearchParams();
if (category) params.set('category', category);
if (preferredBrand) params.set('brand', preferredBrand);
const avgInstallCost = (installCost.min + installCost.max) / 2;
const deviceBudget = Math.max(0, budget - avgInstallCost);
if (deviceBudget > 0) params.set('priceMax', Math.round(deviceBudget).toString());
if (category === 'scienne') {
if (requiredPowerRounded <= 2.5) params.set('room', 'Do 25 m²');
else if (requiredPowerRounded <= 3.5) params.set('room', '25-35 m²');
else if (requiredPowerRounded <= 5.0) params.set('room', '35-50 m²');
else params.set('room', 'Powyżej 50 m²');
} else if (category === 'multisplit') {
params.set('units', rooms.toString());
}
return `/sklep?${params.toString()}`;
};
return (
<main className="bg-slate-50 min-h-screen py-12">
<div className={`mx-auto px-4 sm:px-6 transition-all duration-500 ${step === 3 ? 'max-w-5xl' : 'max-w-2xl'}`}>
<div className="text-center mb-8">
<h1 className="text-3xl font-extrabold text-primary font-heading mb-2">
Dobierz urządzenie
</h1>
<p className="text-text-muted">Odpowiedz na {STEPS.length} krótkich pytań — pokażemy Ci najlepsze opcje z naszej oferty</p>
</div>
<div className="flex items-center mb-8">
{STEPS.map((s, i) => (
<div key={s} className="flex items-start flex-1 last:flex-none">
<div className="flex flex-col items-center gap-1">
<div className={`size-7 rounded-full flex items-center justify-center text-xs font-bold shrink-0 transition-all ${
i < step ? 'bg-green-500 text-white' : i === step ? 'bg-accent text-white' : 'bg-slate-200 text-text-muted'
}`}>
{i < step ? <Check className="size-3.5" /> : i + 1}
</div>
<span className={`text-xs font-medium hidden sm:block whitespace-nowrap ${i === step ? 'text-accent' : 'text-text-muted'}`}>{s}</span>
</div>
{i < STEPS.length - 1 && (
<div className={`flex-1 h-0.5 mx-2 mt-[13px] ${i < step ? 'bg-green-500' : 'bg-slate-200'}`} />
)}
</div>
))}
</div>
<div className="bg-white rounded-2xl border border-border p-6 md:p-8">
{step === 0 && (
<div className="flex flex-col gap-6">
<div className="flex items-center gap-3 mb-2">
<div className="size-10 rounded-xl bg-blue-50 flex items-center justify-center">
<Home className="size-5 text-blue-600" />
</div>
<div>
<h2 className="text-lg font-bold text-primary font-heading">Pomieszczenie</h2>
<p className="text-xs text-text-muted">Metraż i warunki</p>
</div>
</div>
<div className="flex flex-col gap-3">
{pomieszczenia.map((p, i) => (
<div key={i} className="bg-slate-50 rounded-xl border border-border p-4">
<div className="flex items-center justify-between mb-3">
<span className="text-sm font-semibold text-primary">{p.nazwa}</span>
{pomieszczenia.length > 1 && (
<button
onClick={() => removeRoom(i)}
className="text-xs text-red-400 hover:text-red-600 transition-colors"
>
Usuń
</button>
)}
</div>
<div className="flex flex-col gap-1.5">
<div className="flex items-center justify-between">
<span className="text-xs text-text-muted">Powierzchnia</span>
<span className="text-xs font-bold text-primary bg-accent/10 px-2 py-0.5 rounded-md">{p.m2} m²</span>
</div>
<input
type="range" min={5} max={100} step={5} value={p.m2}
onChange={e => updateRoom(i, Number(e.target.value))}
className="range range-xs range-accent w-full"
/>
<div className="flex justify-between text-xs text-text-muted">
<span>5 m²</span>
<span>100 m²</span>
</div>
{(() => {
const mocPokoju = Math.round(calculatePower(p.m2, floor, sun, building) * 10) / 10;
const dostepneMoce = [2.5, 3.5, 5.0, 7.0];
const zalecana = dostepneMoce.reduce((prev, curr) =>
Math.abs(curr - mocPokoju) < Math.abs(prev - mocPokoju) ? curr : prev
);
return (
<div className="mt-2 flex items-center justify-between bg-white border border-border rounded-lg px-3 py-2">
<span className="text-xs text-text-muted">Zalecana moc jednostki</span>
<span className="text-sm font-bold text-accent">{zalecana} kW</span>
</div>
);
})()}
</div>
</div>
))}
</div>
{pomieszczenia.length < 5 && (
<button
onClick={addRoom}
className="flex items-center gap-2 text-sm text-accent font-semibold hover:text-accent/80 transition-colors border border-dashed border-accent/40 rounded-xl px-4 py-3 w-full justify-center"
>
+ Dodaj kolejne pomieszczenie
</button>
)}
<div className="bg-slate-50 border border-border rounded-xl p-4">
<div className="flex items-start justify-between gap-3 mb-2">
<div>
<p className="text-sm font-semibold text-primary">Ograniczenie szerokości jednostki?</p>
<p className="text-xs text-text-muted mt-0.5">Np. wąska ściana, wnęka, szafa</p>
</div>
<button
onClick={() => setShowWidthWarning(prev => !prev)}
className={`shrink-0 text-xs font-bold px-3 py-1.5 rounded-lg transition-colors ${
showWidthWarning ? 'bg-amber-100 text-amber-700' : 'bg-slate-200 text-slate-600 hover:bg-slate-300'
}`}
>
{showWidthWarning ? 'Tak, mam ograniczenie' : 'Nie dotyczy'}
</button>
</div>
{showWidthWarning && (
<div className="mt-3">
<div className="flex items-center justify-between mb-1.5">
<span className="text-xs text-text-muted">Maksymalna szerokość jednostki</span>
<span className="text-xs font-bold text-amber-700 bg-amber-100 px-2 py-0.5 rounded-md">{maxWidth} cm</span>
</div>
<div className="relative h-5 flex items-center">
<div className="absolute w-full h-1.5 bg-slate-200 rounded-full" />
<div
className="absolute h-1.5 bg-amber-400 rounded-full"
style={{ width: `${((maxWidth - 40) / 80) * 100}%` }}
/>
<input
type="range" min={40} max={120} step={5} value={maxWidth}
onChange={e => setMaxWidth(Number(e.target.value))}
className="absolute w-full h-1.5 opacity-0 cursor-pointer z-10"
/>
<div
className="absolute size-4 bg-white border-2 border-amber-400 rounded-full shadow-md pointer-events-none"
style={{ left: `calc(${((maxWidth - 40) / 80) * 100}% - 8px)` }}
/>
</div>
<div className="flex justify-between text-xs text-text-muted mt-1">
<span>40 cm</span>
<span>120 cm</span>
</div>
<div className="mt-3 flex items-start gap-2 p-3 bg-amber-50 border border-amber-200 rounded-xl">
<span className="text-amber-500 text-base shrink-0">⚠️</span>
<p className="text-xs text-amber-800 leading-relaxed">
Standardowe jednostki split mają <strong>70–110 cm szerokości</strong>.
{maxWidth < 70 && ' Przy tak małej przestrzeni wybór jest bardzo ograniczony — '}
{maxWidth >= 70 && maxWidth < 85 && ' Przy tej szerokości dostępne są kompaktowe modele — '}
{maxWidth >= 85 && ' Większość modeli powinna się zmieścić — '}
skonsultuj wymiary konkretnego modelu przed zakupem.
<a href="/kontakt" className="ml-1 font-bold text-amber-700 underline">Zapytaj nas →</a>
</p>
</div>
</div>
)}
</div>
<div className="p-3 bg-accent/10 rounded-xl">
<p className="text-sm text-accent font-semibold">
Łączna wymagana moc: ok. <strong>{requiredPowerRounded} kW</strong>
<span className="text-xs font-normal text-text-muted ml-2">
({pomieszczenia.length === 1 ? 'klimatyzator split' : `multisplit ${pomieszczenia.length}+1`}, łącznie {totalM2} m²)
</span>
</p>
</div>
<div>
<label className="text-sm font-semibold text-primary mb-3 block">Typ budynku</label>
<div className="grid grid-cols-2 gap-2">
{[
{ value: 'apartment', label: '🏢 Mieszkanie w bloku', sub: 'Kamienica, wieżowiec, blok' },
{ value: 'house', label: '🏠 Dom jednorodzinny', sub: 'Wolnostojący, szeregowiec, bliźniak' },
].map(o => (
<button key={o.value} onClick={() => setBuilding(o.value)}
className={`p-4 rounded-xl border-2 text-left transition-all ${building === o.value ? 'border-accent bg-accent/5' : 'border-border hover:border-accent'}`}>
<p className="text-sm font-bold text-primary">{o.label}</p>
<p className="text-xs text-text-muted">{o.sub}</p>
</button>
))}
</div>
</div>
{building === 'house' && (
<div>
<label className="text-sm font-semibold text-primary mb-3 block">Typ przestrzeni</label>
<div className="grid grid-cols-2 gap-2">
{[
{ value: 'ground', label: '🏠 Parter' },
{ value: 'top', label: '🏠 Piętro / poddasze' },
].map(o => (
<button key={o.value} onClick={() => setFloor(o.value)}
className={`py-2.5 px-3 rounded-xl text-sm font-semibold border-2 transition-all ${floor === o.value ? 'border-accent bg-accent text-white' : 'border-border bg-white text-primary hover:border-accent'}`}>
{o.label}
</button>
))}
</div>
</div>
)}
{building === 'apartment' && (
<div>
<label className="text-sm font-semibold text-primary mb-3 block">Piętro</label>
<div className="flex flex-wrap gap-2">
{[
{ value: 'ground', label: 'Parter' },
{ value: 'low', label: '1-3 piętro' },
{ value: 'middle', label: '4-8 piętro' },
{ value: 'high', label: '9+ piętro' },
{ value: 'top', label: 'Ostatnie' },
].map(o => (
<button key={o.value} onClick={() => setFloor(o.value)}
className={`py-2 px-4 rounded-xl text-sm font-semibold border-2 transition-all ${floor === o.value ? 'border-accent bg-accent text-white' : 'border-border bg-white text-primary hover:border-accent'}`}>
{o.label}
</button>
))}
</div>
</div>
)}
<div>
<label className="text-sm font-semibold text-primary mb-3 block">Ekspozycja okien</label>
<div className="grid grid-cols-2 gap-2">
{[
{ value: 'north', label: '🧭 Północ (chłodna)' },
{ value: 'east', label: '🧭 Wschód' },
{ value: 'west', label: '🧭 Zachód' },
{ value: 'south', label: '🧭 Południe (mocne słońce)' },
].map(o => (
<button key={o.value} onClick={() => setSun(o.value)}
className={`py-2.5 px-3 rounded-xl text-sm font-semibold border-2 transition-all ${sun === o.value ? 'border-accent bg-accent text-white' : 'border-border bg-white text-primary hover:border-accent'}`}>
{o.label}
</button>
))}
</div>
</div>
</div>
)}
{step === 1 && (
<div className="flex flex-col gap-6">
<div className="flex items-center gap-3 mb-2">
<div className="size-10 rounded-xl bg-orange-50 flex items-center justify-center">
<Zap className="size-5 text-orange-600" />
</div>
<div>
<h2 className="text-lg font-bold text-primary font-heading">Długość instalacji</h2>
<p className="text-xs text-text-muted">Rury i kable między jednostkami</p>
</div>
</div>
<div className="flex flex-col gap-3">
{[
{ value: 'short', label: 'Do 3 metrów', sub: 'Jednostka zewnętrzna tuż obok (balkon, taras)' },
{ value: 'medium', label: '3–6 metrów', sub: 'Typowa instalacja w bloku lub domu' },
{ value: 'long', label: '6–10 metrów', sub: 'Dłuższa trasa, np. przez kilka pomieszczeń' },
{ value: 'verylong', label: 'Powyżej 10 metrów', sub: 'Bardzo długa trasa, wymaga dodatkowych materiałów' },
].map(o => (
<button key={o.value} onClick={() => setPipes(o.value)}
className={`p-4 rounded-xl border-2 text-left transition-all ${pipes === o.value ? 'border-accent bg-accent/5' : 'border-border hover:border-accent'}`}>
<p className="text-sm font-bold text-primary">{o.label}</p>
<p className="text-xs text-text-muted">{o.sub}</p>
</button>
))}
</div>
<div>
<label className="text-sm font-semibold text-primary mb-3 block">Sposób prowadzenia instalacji (powyżej 3m)</label>
<div className="flex flex-col gap-3">
{[
{ value: 'korytko', label: 'Korytko PCV', sub: 'Rury schowane w białym korytku (80 zł/mb)' },
{ value: 'bruzda', label: 'Bruzda w ścianie', sub: 'Rury ukryte w wykutej bruzdzie (90 zł/mb)' },
].map(o => (
<button key={o.value} onClick={() => setInstallMethod(o.value as 'korytko' | 'bruzda')}
className={`p-4 rounded-xl border-2 text-left transition-all ${installMethod === o.value ? 'border-accent bg-accent/5' : 'border-border hover:border-accent'}`}>
<p className="text-sm font-bold text-primary">{o.label}</p>
<p className="text-xs text-text-muted">{o.sub}</p>
</button>
))}
</div>
</div>
<div className="p-3 bg-orange-50 rounded-xl text-xs text-orange-700">
Szacowany koszt montażu dla Twojej konfiguracji:
<strong className="ml-1">{installCost.min.toLocaleString('pl-PL')}–{installCost.max.toLocaleString('pl-PL')} zł</strong>
</div>
<div className="mt-3 p-4 bg-blue-50 border border-blue-200 rounded-xl">
<p className="text-sm font-semibold text-blue-900 mb-1">📐 Chcesz dokładną wycenę?</p>
<p className="text-xs text-blue-800 leading-relaxed">
Skontaktuj się z nami — wycena jest <strong>bezpłatna i niezobowiązująca</strong>.
Aby przyspieszyć wycenę, wyślij nam zdjęcia:
</p>
<ul className="mt-2 flex flex-col gap-1">
{[
'Miejsca gdzie ma wisieć jednostka wewnętrzna',
'Ściany przez które przejdzie instalacja',
'Miejsca gdzie stanie jednostka zewnętrzna',
'Skrzynki elektrycznej (bezpieczniki)',
].map((item, i) => (
<li key={i} className="flex items-start gap-2 text-xs text-blue-800">
<span className="text-blue-500 shrink-0">→</span>
{item}
</li>
))}
</ul>
<a href="/kontakt" className="mt-3 inline-flex items-center gap-1.5 text-xs font-bold text-white bg-accent px-3 py-1.5 rounded-lg hover:bg-accent/90 transition-colors">
Wyślij zdjęcia i zapytaj o wycenę →
</a>
</div>
</div>
)}
{step === 2 && (
<div className="flex flex-col gap-6">
<div className="flex items-center gap-3 mb-2">
<div className="size-10 rounded-xl bg-green-50 flex items-center justify-center">
<ShoppingCart className="size-5 text-green-600" />
</div>
<div>
<h2 className="text-lg font-bold text-primary font-heading">Całkowity budżet</h2>
<p className="text-xs text-text-muted">Urządzenie + montaż łącznie</p>
</div>
</div>
<div className="flex flex-col gap-1.5">
<div className="flex items-center justify-between">
<span className="text-xs text-text-muted">Budżet</span>
<span className="text-xs font-bold text-primary bg-accent/10 px-2 py-0.5 rounded-md">{budget.toLocaleString('pl-PL')} zł</span>
</div>
<input
type="range" min={3000} max={25000} step={500} value={budget}
onChange={e => setBudget(Number(e.target.value))}
className="range range-xs range-accent w-full"
/>
<div className="flex justify-between text-xs text-text-muted">
<span>3 000 zł</span>
<span>25 000 zł</span>
</div>
</div>
<div className="grid grid-cols-2 gap-3">
<div className="bg-slate-50 rounded-xl p-3">
<p className="text-xs text-text-muted mb-1">Na urządzenie zostaje</p>
<p className="text-base font-bold text-primary font-heading">
ok. {(budget * 0.75).toLocaleString('pl-PL')} zł
</p>
</div>
<div className="bg-orange-50 rounded-xl p-3">
<p className="text-xs text-orange-700 mb-1">Szac. koszt montażu</p>
<p className="text-base font-bold text-orange-700 font-heading">
{installCost.min.toLocaleString('pl-PL')}–{installCost.max.toLocaleString('pl-PL')} zł
</p>
</div>
</div>
<div className="p-3 bg-blue-50 rounded-xl text-xs text-blue-700">
💡 Podsumowanie: szukamy klimatyzatora <strong>{category === 'scienne' ? 'split ściennego' : 'multisplit'}</strong> o mocy ok. <strong>{requiredPowerRounded} kW</strong> w cenie do <strong>{(budget * 0.75).toLocaleString('pl-PL')} zł</strong>
</div>
<div>
<label className="text-sm font-semibold text-primary mb-3 block">
Preferowana marka (opcjonalnie)
</label>
<div className="flex flex-wrap gap-2">
{['Bez preferencji', 'Gree', 'Rotenso', 'Daikin', 'Haier', 'LG', 'Samsung', 'Mitsubishi Electric', 'Toshiba', 'Fuji Electric'].map(b => (
<button
key={b}
onClick={() => setPreferredBrand(b === 'Bez preferencji' ? '' : b)}
className={`px-3 py-1.5 rounded-xl text-xs font-semibold border-2 transition-all ${
(b === 'Bez preferencji' && preferredBrand === '') || preferredBrand === b
? 'border-accent bg-accent text-white'
: 'border-border bg-white text-primary hover:border-accent'
}`}
>
{b}
</button>
))}
</div>
</div>
<div>
<label className="text-sm font-semibold text-primary mb-3 block">
Klasa energetyczna (opcjonalnie)
</label>
<div className="flex flex-wrap gap-2">
{['Bez preferencji', 'A+++', 'A++', 'A+'].map(c => (
<button
key={c}
onClick={() => setEnergyClass(c === 'Bez preferencji' ? '' : c)}
className={`px-3 py-1.5 rounded-xl text-xs font-semibold border-2 transition-all ${
(c === 'Bez preferencji' && energyClass === '') || energyClass === c
? 'border-accent bg-accent text-white'
: 'border-border bg-white text-primary hover:border-accent'
}`}
>
{c}
</button>
))}
</div>
</div>
</div>
)}
{step === 2 && (
<div className="flex flex-col gap-6">
<div className="bg-slate-50 rounded-2xl border border-border p-5">
<h2 className="text-lg font-bold text-primary font-heading mb-4">
Dopasowane klimatyzatory
</h2>
<div className="grid grid-cols-2 md:grid-cols-3 gap-3">
{[
{ label: 'Wymagana moc', value: `${requiredPowerRounded} kW` },
{ label: 'Powierzchnia', value: `${totalM2} m²` },
{ label: 'Typ instalacji', value: category === 'scienne' ? 'Split (1 pokój)' : `Multisplit (${rooms} pokoje)` },
{ label: 'Szac. montaż', value: `${installCost.min.toLocaleString('pl-PL')}–${installCost.max.toLocaleString('pl-PL')} zł` },
...(energyClass ? [{ label: 'Klasa energetyczna', value: energyClass }] : []),
].map((s, i) => (
<div key={i} className="bg-white rounded-xl p-3 border border-border">
<p className="text-xs text-text-muted mb-1">{s.label}</p>
<p className="text-sm font-bold text-primary font-heading">{s.value}</p>
</div>
))}
</div>
</div>
<div className="p-4 bg-amber-50 border border-amber-200 rounded-xl mt-2">
<p className="text-xs font-bold text-amber-800 mb-1">⚠️ Ceny mają charakter orientacyjny</p>
<p className="text-xs text-amber-700 mb-3">
Podane ceny urządzeń są cenami brutto (23% VAT). Koszt montażu jest szacunkowy. Zachęcamy do darmowej wyceny.
</p>
<div className="flex flex-col sm:flex-row gap-2">
<a href={`tel:${companyDetails.phoneRaw}`}>
<Button variant="primary" size="sm" className="w-full sm:w-auto">
<Phone className="size-3.5" /> Bezpłatna wycena
</Button>
</a>
<Link href="/kontakt" className="flex items-center gap-2 px-4 py-2 bg-amber-100 text-amber-800 rounded-xl text-xs font-bold hover:bg-amber-200 transition-colors border border-amber-300">
Prześlij zdjęcia
</Link>
</div>
</div>
</div>
)}
<div className="flex justify-between mt-8 pt-6 border-t border-border">
{step > 0 ? (
<Button
onClick={() => setStep(s => s - 1)}
variant="outline"
size="md"
>
<ArrowLeft className="size-4" /> Wstecz
</Button>
) : <div />}
{step < STEPS.length - 1 ? (
<Button
onClick={handleNext}
variant="primary"
size="md"
>
Dalej <ArrowRight className="size-4" />
</Button>
) : (
<Link href={getShopUrl()} className={buttonClasses({ variant: "primary", size: "md" })}>
Przejdź do sklepu <ArrowRight className="size-4" />
</Link>
)}
</div>
</div>
</div>
</main>
);
}