180 lines
5.6 KiB
JavaScript
180 lines
5.6 KiB
JavaScript
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>
|
||
);
|
||
}
|