import { useEffect, useMemo, useState } from "preact/hooks"; import "../../styles/modal.css"; import "../../styles/offers/offers-table.css"; export default function JamboxAddonsModal({ isOpen, onClose, pkg }) { const [phonePlans, setPhonePlans] = useState([]); const [addons, setAddons] = useState([]); const [tvAddons, setTvAddons] = useState([]); const [selectedTvAddonTids, setSelectedTvAddonTids] = useState([]); const [loading, setLoading] = useState(false); const [error, setError] = useState(""); const [selectedPhoneId, setSelectedPhoneId] = useState(null); const [selectedAddonIds, setSelectedAddonIds] = useState([]); // akordeony const [openPhoneId, setOpenPhoneId] = useState(null); const [baseOpen, setBaseOpen] = useState(true); const formatFeatureValue = (val) => { if (val === true || val === "true") return "✓"; if (val === false || val === "false" || val == null) return "✕"; return val; }; const handlePhoneSelect = (id) => { if (id === null) { setSelectedPhoneId(null); setOpenPhoneId(null); return; } setSelectedPhoneId(id); setOpenPhoneId((prev) => (prev === id ? null : id)); }; const toggleAddon = (addonId) => { setSelectedAddonIds((prev) => prev.includes(addonId) ? prev.filter((x) => x !== addonId) : [...prev, addonId] ); }; // reset po otwarciu / zmianie pakietu useEffect(() => { if (!isOpen) return; setSelectedPhoneId(null); setSelectedAddonIds([]); setOpenPhoneId(null); setBaseOpen(true); setError(""); setSelectedTvAddonTids([]); }, [isOpen, pkg?.id]); // load danych useEffect(() => { if (!isOpen || !pkg?.id) return; let cancelled = false; async function loadData() { setLoading(true); setError(""); try { // telefon const phoneRes = await fetch("/api/phone/plans"); if (!phoneRes.ok) throw new Error(`HTTP ${phoneRes.status} (phone)`); const phoneJson = await phoneRes.json(); const phoneData = Array.isArray(phoneJson.data) ? phoneJson.data : []; // dodatki JAMBOX (dla pakietu) const addonsRes = await fetch(`/api/jambox/addons?packageId=${pkg.id}`); if (!addonsRes.ok) throw new Error(`HTTP ${addonsRes.status} (addons)`); const addonsJson = await addonsRes.json(); const addonsData = Array.isArray(addonsJson.data) ? addonsJson.data : []; // pakiety TV const tvRes = await fetch(`/api/jambox/tv-addons?packageId=${pkg.id}`); if (!tvRes.ok) throw new Error(`HTTP ${tvRes.status} (tv-addons)`); const tvJson = await tvRes.json(); const tvData = Array.isArray(tvJson.data) ? tvJson.data : []; if (!cancelled) { setPhonePlans(phoneData); setAddons(addonsData); setTvAddons(tvData); } } catch (err) { console.error("❌ Błąd ładowania danych do JamboxAddonsModal:", err); if (!cancelled) setError("Nie udało się załadować danych dodatkowych usług."); } finally { if (!cancelled) setLoading(false); } } loadData(); return () => { cancelled = true; }; }, [isOpen, pkg?.id]); if (!isOpen || !pkg) return null; const basePrice = Number(pkg.price_monthly || 0); const phonePrice = useMemo(() => { if (!selectedPhoneId) return 0; const p = phonePlans.find((x) => x.id === selectedPhoneId); return Number(p?.price_monthly || 0); }, [selectedPhoneId, phonePlans]); // backend może zwrócić { id, price } albo { addon_id, price } const addonsPrice = useMemo(() => { return selectedAddonIds.reduce((sum, addonId) => { const a = addons.find((x) => (x.id ?? x.addon_id) === addonId); return sum + Number(a?.price || 0); }, 0); }, [selectedAddonIds, addons]); const tvAddonsPrice = useMemo(() => { return selectedTvAddonTids.reduce((sum, tid) => { const a = tvAddons.find((x) => Number(x.tid) === Number(tid)); return sum + Number(a?.price || 0); }, 0); }, [selectedTvAddonTids, tvAddons]); const totalMonthly = basePrice + phonePrice + addonsPrice + tvAddonsPrice; const toggleTvAddon = (tid) => { const t = Number(tid); setSelectedTvAddonTids((prev) => prev.includes(t) ? prev.filter((x) => x !== t) : [...prev, t] ); }; return (
e.stopPropagation()}>

Konfiguracja usług dodatkowych

{/* PAKIET JAMBOX jako akordeon */}
{baseOpen && pkg.features && pkg.features.length > 0 && (
    {pkg.features.map((f, idx) => (
  • {f.label} {formatFeatureValue(f.value)}
  • ))}
)}
{loading &&

Ładowanie danych...

} {error &&

{error}

} {!loading && !error && ( <> {/* TV ADDONS */}

Pakiety dodatkowe TV

{tvAddons.length === 0 ? (

Brak pakietów dodatkowych TV dla tego pakietu.

) : (
{tvAddons.map((a) => { const tid = Number(a.tid); const checked = selectedTvAddonTids.includes(tid); const priceNum = Number(a.price || 0); return ( ); })}
)}
{/* TELEFON */}

Usługa telefoniczna

{phonePlans.length === 0 ? (

Brak dostępnych pakietów telefonicznych.

) : (
{/* brak telefonu */}
{/* pakiety telefonu */} {phonePlans.map((p) => { const isSelected = selectedPhoneId === p.id; const isOpen = openPhoneId === p.id; return (
{isOpen && (
{p.features && p.features.length > 0 && (
    {p.features .filter( (f) => !String(f.label || "").toLowerCase().includes("aktyw") ) .map((f, idx) => (
  • {f.label} {f.value}
  • ))}
)}
)}
); })}
)}
{/* DODATKI JAMBOX */}

Dodatkowe usługi

{addons.length === 0 ? (

Brak usług dodatkowych dla tego pakietu.

) : (
{addons.map((a) => { const addonId = a.id ?? a.addon_id; const checked = selectedAddonIds.includes(addonId); const priceNum = Number(a.price || 0); return ( ); })}
)}
{/* PODSUMOWANIE */}

Podsumowanie miesięczne

Pakiet {basePrice ? `${basePrice.toFixed(2)} zł/mies.` : "—"}
Pakiety TV {tvAddonsPrice ? `${tvAddonsPrice.toFixed(2)} zł/mies.` : "—"}
Telefon {phonePrice ? `${phonePrice.toFixed(2)} zł/mies.` : "—"}
Dodatki {addonsPrice ? `${addonsPrice.toFixed(2)} zł/mies.` : "—"}
Łącznie {totalMonthly.toFixed(2)} zł/mies.
{/* FLOATING TOTAL (dymek jak czat) */}
e.stopPropagation()}>
Suma {totalMonthly.toFixed(2)} zł/mies.
)}
); }