Files
fuz-site/src/islands/modals/sections/TvAddonsSection.jsx

180 lines
5.6 KiB
JavaScript
Raw 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.
import SectionAccordion from "./SectionAccordion.jsx";
import { money } from "../../../lib/money.js";
import { hasTvTermPricing, getAddonUnitPrice } from "../../../lib/offer-pricing.js";
export default function TvAddonsSection({
open,
onToggle,
cenaOpis,
pkg,
tvAddonsVisible = [],
selectedQty,
setSelectedQty,
tvTerm,
setTvTerm,
tvAddonsPrice,
}) {
const toggleCheckboxAddon = (addon) => {
setSelectedQty((prev) => {
const next = { ...prev };
const isOn = (next[addon.id] || 0) > 0;
const willTurnOn = !isOn;
// ✅ jeśli grupa "single" i włączamy -> wyłącz inne z tej grupy
if (willTurnOn && addon.group && addon.group_mode === "single") {
for (const a of tvAddonsVisible) {
if (a.id !== addon.id && a.group === addon.group) {
next[a.id] = 0;
}
}
}
// toggle bieżącego
next[addon.id] = willTurnOn ? 1 : 0;
return next;
});
};
const setQtyAddon = (id, qty, min, max) => {
const safe = Math.max(min, Math.min(max, qty));
setSelectedQty((prev) => ({ ...prev, [id]: safe }));
};
const renderRow = (a) => {
const qty = Number(selectedQty[a.id] || 0);
const isQty = a.typ === "quantity" || a.ilosc === true;
const termPricing = hasTvTermPricing(a, pkg);
const term = tvTerm[a.id] || "12m";
const unit = getAddonUnitPrice(a, pkg, termPricing ? term : null);
if (!isQty) {
return (
<label class="f-addon-item f-addon-item--tv" key={"tv-" + a.id}>
<div class="f-addon-checkbox">
<input
type="checkbox"
checked={qty > 0}
onChange={() => toggleCheckboxAddon(a)}
/>
</div>
<div class="f-addon-main">
<div class="f-addon-name">{a.nazwa}</div>
{termPricing && (
<div class="mt-2 flex flex-wrap gap-3 text-sm" onClick={(e) => e.stopPropagation()}>
<label class="inline-flex items-center gap-2">
<input
type="radio"
name={`term-${a.id}`}
checked={(tvTerm[a.id] || "12m") === "12m"}
onChange={() => setTvTerm((p) => ({ ...p, [a.id]: "12m" }))}
/>
<span>12 miesięcy</span>
</label>
<label class="inline-flex items-center gap-2">
<input
type="radio"
name={`term-${a.id}`}
checked={(tvTerm[a.id] || "12m") === "bezterminowo"}
onChange={() => setTvTerm((p) => ({ ...p, [a.id]: "bezterminowo" }))}
/>
<span>Bezterminowo</span>
</label>
</div>
)}
</div>
<div class="f-addon-price">{money(unit)} {cenaOpis}</div>
{/* ✅ osobny wiersz na pełną szerokość */}
{(a.tid || a.opis) && (
<div class="f-addon-below" onClick={(e) => e.stopPropagation()}>
{a.tid ? (
<a
class="f-addon-more"
href={`/internet-telewizja/pakiety-tematyczne#tid-${encodeURIComponent(a.tid)}`}
target="_blank"
rel="noopener noreferrer"
aria-label={`Więcej informacji o pakiecie ${a.nazwa ?? ""} (otwiera się w nowej karcie)`}
title={`Więcej o pakiecie ${a.nazwa ?? ""}`}
>
Przejdź do szczegółowych informacji pakietu {a.nazwa ?? ""}
</a>
) : (
a.opis ? <div class="f-addon-desc">{a.opis}</div> : null
)}
</div>
)}
</label>
);
}
const min = Number.isFinite(a.min) ? a.min : 0;
const max = Number.isFinite(a.max) ? a.max : 10;
const step = Number.isFinite(a.krok) ? a.krok : 1;
const lineTotal = qty * unit;
return (
<div class="f-addon-item f-addon-item--qty f-addon-item--tv" key={"tvq-" + a.id}>
<div class="f-addon-checkbox" aria-hidden="true"></div>
<div class="f-addon-main">
<div class="f-addon-name">{a.nazwa}</div>
{a.opis && <div class="f-addon-desc">{a.opis}</div>}
</div>
<div class="f-addon-qty" onClick={(e) => e.stopPropagation()}>
<button
type="button"
class="btn btn-outline"
onClick={() => setQtyAddon(a.id, qty - step, min, max)}
disabled={qty <= min}
>
</button>
<span class="f-addon-qty-value">{qty}</span>
<button
type="button"
class="btn btn-outline"
onClick={() => setQtyAddon(a.id, qty + step, min, max)}
disabled={qty >= max}
>
+
</button>
</div>
<div class="f-addon-price">
<div>{money(unit)} {cenaOpis}</div>
<div class="f-addon-price-total">{qty > 0 ? `${money(lineTotal)} ${cenaOpis}` : "—"}</div>
</div>
</div>
);
};
return (
<div class="f-modal-section">
<SectionAccordion
title="Pakiety dodatkowe TV"
right={<span class="f-modal-phone-price">{tvAddonsPrice ? `${money(tvAddonsPrice)} ${cenaOpis}` : "—"}</span>}
open={open}
onToggle={onToggle}
>
{tvAddonsVisible.length === 0 ? (
<p>Brak pakietów dodatkowych TV.</p>
) : (
<div class="f-addon-list">{tvAddonsVisible.map(renderRow)}</div>
)}
</SectionAccordion>
</div>
);
}