From dc07fa083e52651e385ee9ab672368584de75d77 Mon Sep 17 00:00:00 2001 From: dm Date: Mon, 15 Dec 2025 12:32:21 +0100 Subject: [PATCH] =?UTF-8?q?Przej=C5=9Bcie=20w=20internecie=20na=20addons?= =?UTF-8?q?=20kompaktowe?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../Internet/InternetAddonsModalCompact.jsx | 237 ++++++++++++------ src/islands/Internet/InternetCards.jsx | 2 +- 2 files changed, 164 insertions(+), 75 deletions(-) diff --git a/src/islands/Internet/InternetAddonsModalCompact.jsx b/src/islands/Internet/InternetAddonsModalCompact.jsx index bbefe30..6c508dc 100644 --- a/src/islands/Internet/InternetAddonsModalCompact.jsx +++ b/src/islands/Internet/InternetAddonsModalCompact.jsx @@ -43,7 +43,7 @@ function normalizeAddons(addons) { .map((a) => ({ id: String(a.id), nazwa: String(a.nazwa), - typ: String(a.typ || "checkbox"), + typ: String(a.typ ?? a.type ?? "checkbox"), ilosc: !!a.ilosc, min: a.min != null ? Number(a.min) : 0, max: a.max != null ? Number(a.max) : 10, @@ -53,6 +53,7 @@ function normalizeAddons(addons) { })); } +/** ✅ Sekcja-akordeon (jak w internet modal) */ function SectionAccordion({ title, right, open, onToggle, children }) { return (
@@ -78,8 +79,8 @@ export default function InternetAddonsModal({ onClose, plan, - phoneCards = [], // telefon/cards.yaml -> cards[] - addons = [], // internet-swiatlowodowy/addons.yaml -> dodatki[] + phoneCards = [], + addons = [], cenaOpis = "zł/mies.", }) { const phonePlans = useMemo(() => mapPhoneYamlToPlans(phoneCards), [phoneCards]); @@ -118,22 +119,24 @@ export default function InternetAddonsModal({ setSelectedPhoneId(null); setSelectedQty({}); setOpenSections({ internet: true, phone: false, addons: false, summary: false }); - }, [isOpen, plan]); + }, [isOpen, plan?.id]); if (!isOpen || !plan) return null; const basePrice = Number(plan.price_monthly || 0); - const phonePrice = (() => { + const phonePrice = useMemo(() => { if (!selectedPhoneId) return 0; - const p = phonePlans.find((p) => String(p.id) === String(selectedPhoneId)); + const p = phonePlans.find((x) => String(x.id) === String(selectedPhoneId)); return Number(p?.price_monthly || 0); - })(); + }, [selectedPhoneId, phonePlans]); - const addonsPrice = addonsList.reduce((sum, a) => { - const qty = Number(selectedQty[a.id] || 0); - return sum + qty * Number(a.cena || 0); - }, 0); + const addonsPrice = useMemo(() => { + return addonsList.reduce((sum, a) => { + const qty = Number(selectedQty[a.id] || 0); + return sum + qty * Number(a.cena || 0); + }, 0); + }, [selectedQty, addonsList]); const totalMonthly = basePrice + phonePrice + addonsPrice; @@ -158,6 +161,91 @@ export default function InternetAddonsModal({ setSelectedQty((prev) => ({ ...prev, [id]: safe })); }; + // ====================== + // ✅ zapis do localStorage (jak w Jambox) + // ====================== + const LS_KEY = "fuz_offer_config_v1"; + + function buildOfferPayload() { + const phone = selectedPhoneId + ? phonePlans.find((p) => String(p.id) === String(selectedPhoneId)) + : null; + + const addonsChosen = addonsList + .map((a) => { + const qty = Number(selectedQty[a.id] || 0); + if (qty <= 0) return null; + return { id: a.id, nazwa: a.nazwa, qty, unit: Number(a.cena || 0) }; + }) + .filter(Boolean); + + return { + createdAt: new Date().toISOString(), + // ważne: plan internetowy jako "pkg" żeby kontakt miał wspólny format + pkg: { id: plan?.id ?? null, name: plan?.name ?? "", price: basePrice }, + + phone: phone ? { id: phone.id, name: phone.name, price: phone.price_monthly } : null, + + // tu nie ma dekodera i tv-addons + decoder: null, + tvAddons: [], + addons: addonsChosen, + + totals: { + base: basePrice, + phone: phonePrice, + decoder: 0, + tv: 0, + addons: addonsPrice, + total: totalMonthly, + currencyLabel: cenaOpis, + }, + }; + } + + function moneyWithLabel(v) { + return `${money(v)} ${cenaOpis}`; + } + + function buildOfferMessage(payload) { + const lines = []; + + lines.push(`Wybrana oferta: ${payload?.pkg?.name || "—"}`); + lines.push(""); + + // ✅ WSZYSTKIE linie jak w podsumowaniu (wspólny standard) + lines.push(`Pakiet: ${moneyWithLabel(payload?.totals?.base ?? 0)}`); + lines.push(`Telefon: ${payload?.phone ? moneyWithLabel(payload.totals.phone) : "—"}`); + lines.push(`Dekoder: —`); + lines.push(`Dodatki TV: —`); + lines.push(`Dodatkowe usługi: ${payload?.addons?.length ? moneyWithLabel(payload.totals.addons) : "—"}`); + lines.push(`Łącznie: ${moneyWithLabel(payload?.totals?.total ?? 0)}`); + + if (payload?.phone) { + lines.push(""); + lines.push(`Telefon: ${payload.phone.name} (${moneyWithLabel(payload.phone.price)})`); + } + + if (Array.isArray(payload?.addons) && payload.addons.length) { + lines.push(""); + lines.push("Dodatkowe usługi:"); + for (const it of payload.addons) { + lines.push(`- ${it.nazwa} x${it.qty} @ ${moneyWithLabel(it.unit)}`); + } + } + + return lines.join("\n"); + } + + function saveOfferToLocalStorage() { + try { + const payload = buildOfferPayload(); + payload.message = buildOfferMessage(payload); + localStorage.setItem(LS_KEY, JSON.stringify(payload)); + } catch {} + } + // ====================== + return (
-
+ + + {/* pakiety */} {phonePlans.map((p) => { const isSelected = String(selectedPhoneId) === String(p.id); + return ( -
- +
+ - {/* pokazuj parametry tylko dla wybranego (czytelniej) */} - {isSelected && p.features?.length > 0 && ( -
+ {/* ✅ detale ZAWSZE widoczne (jak w TV) */} + {p.features?.length > 0 && ( +
    {p.features .filter( - (f) => - !String(f.label || "") - .toLowerCase() - .includes("aktyw"), + (f) => !String(f.label || "").toLowerCase().includes("aktyw"), ) .map((f, idx) => (
  • {f.label} - - {formatFeatureValue(f.value)} - + {formatFeatureValue(f.value)}
  • ))}
@@ -409,8 +480,9 @@ export default function InternetAddonsModal({ >
+ {/* ✅ WSZYSTKIE linie jak w Jambox (standard) */}
- Internet + Pakiet {money(basePrice)} {cenaOpis}
@@ -420,7 +492,17 @@ export default function InternetAddonsModal({
- Dodatki + Dekoder + +
+ +
+ Dodatki TV + +
+ +
+ Dodatkowe usługi {addonsPrice ? `${money(addonsPrice)} ${cenaOpis}` : "—"}
@@ -428,18 +510,25 @@ export default function InternetAddonsModal({ Łącznie {money(totalMonthly)} {cenaOpis}
+ + saveOfferToLocalStorage()} + > + Wyślij zapytanie z tym wyborem +
- {/* ✅ zawsze widoczne w rogu */} + {/* ✅ pływająca suma (ten sam styl co w Jambox, jeśli już masz CSS) */}
e.stopPropagation()}> -
- Suma - - {money(totalMonthly)} {cenaOpis} - +
+ Razem + {money(totalMonthly)} + {cenaOpis}
diff --git a/src/islands/Internet/InternetCards.jsx b/src/islands/Internet/InternetCards.jsx index c6852da..4cf6698 100644 --- a/src/islands/Internet/InternetCards.jsx +++ b/src/islands/Internet/InternetCards.jsx @@ -1,7 +1,7 @@ import { useEffect, useState } from "preact/hooks"; import Markdown from "../Markdown.jsx"; import OffersSwitches from "../OffersSwitches.jsx"; -import InternetAddonsModal from "./InternetAddonsModal.jsx"; +import InternetAddonsModal from "./InternetAddonsModalCompact.jsx"; import "../../styles/offers/offers-table.css"; function formatMoney(amount, currency = "PLN") {