'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(key: string, initialValue: T) { const [state, setState] = useState(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 (

Dobierz urządzenie

Odpowiedz na {STEPS.length} krótkich pytań — pokażemy Ci najlepsze opcje z naszej oferty

{STEPS.map((s, i) => (
{i < step ? : i + 1}
{i < STEPS.length - 1 && (
)}
))}
{step === 0 && (

Pomieszczenie

Metraż i warunki

{pomieszczenia.map((p, i) => (
{p.nazwa} {pomieszczenia.length > 1 && ( )}
Powierzchnia {p.m2} m²
updateRoom(i, Number(e.target.value))} className="range range-xs range-accent w-full" />
5 m² 100 m²
{(() => { 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 (
Zalecana moc jednostki {zalecana} kW
); })()}
))}
{pomieszczenia.length < 5 && ( )}

Ograniczenie szerokości jednostki?

Np. wąska ściana, wnęka, szafa

{showWidthWarning && (
Maksymalna szerokość jednostki {maxWidth} cm
setMaxWidth(Number(e.target.value))} className="absolute w-full h-1.5 opacity-0 cursor-pointer z-10" />
40 cm 120 cm
⚠️

Standardowe jednostki split mają 70–110 cm szerokości. {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. Zapytaj nas →

)}

Łączna wymagana moc: ok. {requiredPowerRounded} kW ({pomieszczenia.length === 1 ? 'klimatyzator split' : `multisplit ${pomieszczenia.length}+1`}, łącznie {totalM2} m²)

{[ { value: 'apartment', label: '🏢 Mieszkanie w bloku', sub: 'Kamienica, wieżowiec, blok' }, { value: 'house', label: '🏠 Dom jednorodzinny', sub: 'Wolnostojący, szeregowiec, bliźniak' }, ].map(o => ( ))}
{building === 'house' && (
{[ { value: 'ground', label: '🏠 Parter' }, { value: 'top', label: '🏠 Piętro / poddasze' }, ].map(o => ( ))}
)} {building === 'apartment' && (
{[ { 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 => ( ))}
)}
{[ { 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 => ( ))}
)} {step === 1 && (

Długość instalacji

Rury i kable między jednostkami

{[ { 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 => ( ))}
{[ { 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 => ( ))}
Szacowany koszt montażu dla Twojej konfiguracji: {installCost.min.toLocaleString('pl-PL')}–{installCost.max.toLocaleString('pl-PL')} zł

📐 Chcesz dokładną wycenę?

Skontaktuj się z nami — wycena jest bezpłatna i niezobowiązująca. Aby przyspieszyć wycenę, wyślij nam zdjęcia:

    {[ '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) => (
  • → {item}
  • ))}
Wyślij zdjęcia i zapytaj o wycenę →
)} {step === 2 && (

Całkowity budżet

Urządzenie + montaż łącznie

Budżet {budget.toLocaleString('pl-PL')} zł
setBudget(Number(e.target.value))} className="range range-xs range-accent w-full" />
3 000 zł 25 000 zł

Na urządzenie zostaje

ok. {(budget * 0.75).toLocaleString('pl-PL')} zł

Szac. koszt montażu

{installCost.min.toLocaleString('pl-PL')}–{installCost.max.toLocaleString('pl-PL')} zł

💡 Podsumowanie: szukamy klimatyzatora {category === 'scienne' ? 'split ściennego' : 'multisplit'} o mocy ok. {requiredPowerRounded} kW w cenie do {(budget * 0.75).toLocaleString('pl-PL')} zł
{['Bez preferencji', 'Gree', 'Rotenso', 'Daikin', 'Haier', 'LG', 'Samsung', 'Mitsubishi Electric', 'Toshiba', 'Fuji Electric'].map(b => ( ))}
{['Bez preferencji', 'A+++', 'A++', 'A+'].map(c => ( ))}
)} {step === 2 && (

Dopasowane klimatyzatory

{[ { 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) => (

{s.label}

{s.value}

))}

⚠️ Ceny mają charakter orientacyjny

Podane ceny urządzeń są cenami brutto (23% VAT). Koszt montażu jest szacunkowy. Zachęcamy do darmowej wyceny.

Prześlij zdjęcia
)}
{step > 0 ? ( ) :
} {step < STEPS.length - 1 ? ( ) : ( Przejdź do sklepu )}
); }