Zmiany w modalach
This commit is contained in:
@@ -124,14 +124,12 @@ export default function InternetAddonsModal({ isOpen, onClose, plan }) {
|
|||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
const togglePhoneOpen = (id) => {
|
|
||||||
setOpenPhoneId((prev) => (prev === id ? null : id));
|
|
||||||
};
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div class="fuz-modal-overlay" onClick={onClose}>
|
<div class="f-modal-overlay" onClick={onClose}>
|
||||||
<button
|
<button
|
||||||
class="fuz-modal-close"
|
class="f-modal-close"
|
||||||
|
type="button"
|
||||||
|
aria-label="Zamknij"
|
||||||
onClick={(e) => {
|
onClick={(e) => {
|
||||||
e.stopPropagation();
|
e.stopPropagation();
|
||||||
onClose();
|
onClose();
|
||||||
@@ -141,33 +139,35 @@ export default function InternetAddonsModal({ isOpen, onClose, plan }) {
|
|||||||
</button>
|
</button>
|
||||||
|
|
||||||
<div
|
<div
|
||||||
class="fuz-modal-panel fuz-modal-panel--compact"
|
class="f-modal-panel f-modal-panel--compact"
|
||||||
onClick={(e) => e.stopPropagation()}
|
onClick={(e) => e.stopPropagation()}
|
||||||
>
|
>
|
||||||
<div class="fuz-modal-inner">
|
<div class="f-modal-inner">
|
||||||
<h2 class="fuz-modal-title">Konfiguracja usług dodatkowych</h2>
|
<h2 class="f-modal-title">Konfiguracja usług dodatkowych</h2>
|
||||||
|
|
||||||
{/* INTERNET (fiber) jako akordeon */}
|
{/* INTERNET (fiber) jako akordeon */}
|
||||||
<div class="fuz-modal-section">
|
<div class="f-modal-section">
|
||||||
<div class={`fuz-accordion-item ${baseOpen ? "is-open" : ""}`}>
|
<div class={`f-accordion-item ${baseOpen ? "is-open" : ""}`}>
|
||||||
<button
|
<button
|
||||||
type="button"
|
type="button"
|
||||||
class="fuz-accordion-header"
|
class="f-accordion-header"
|
||||||
onClick={() => setBaseOpen((prev) => !prev)}
|
onClick={() => setBaseOpen((prev) => !prev)}
|
||||||
>
|
>
|
||||||
<span class="fuz-modal-phone-name">{plan.name}</span>
|
<span class="f-modal-phone-name">{plan.name}</span>
|
||||||
<span class="fuz-modal-phone-price">
|
<span class="f-modal-phone-price">
|
||||||
{basePrice.toFixed(2)} zł/mies.
|
{basePrice.toFixed(2)} zł/mies.
|
||||||
</span>
|
</span>
|
||||||
</button>
|
</button>
|
||||||
|
|
||||||
{baseOpen && plan.features && plan.features.length > 0 && (
|
{baseOpen && plan.features && plan.features.length > 0 && (
|
||||||
<div class="fuz-accordion-body">
|
<div class="f-accordion-body">
|
||||||
<ul class="f-card-features">
|
<ul class="f-card-features">
|
||||||
{plan.features.map((f, idx) => (
|
{plan.features.map((f, idx) => (
|
||||||
<li class="f-card-row" key={idx}>
|
<li class="f-card-row" key={idx}>
|
||||||
<span class="f-card-label">{f.label}</span>
|
<span class="f-card-label">{f.label}</span>
|
||||||
<span class="f-card-value">{formatFeatureValue(f.value)}</span>
|
<span class="f-card-value">
|
||||||
|
{formatFeatureValue(f.value)}
|
||||||
|
</span>
|
||||||
</li>
|
</li>
|
||||||
))}
|
))}
|
||||||
</ul>
|
</ul>
|
||||||
@@ -181,21 +181,22 @@ export default function InternetAddonsModal({ isOpen, onClose, plan }) {
|
|||||||
|
|
||||||
{!loading && !error && (
|
{!loading && !error && (
|
||||||
<>
|
<>
|
||||||
{/* Sekcja: wybór telefonu (akordeon + opcja bez telefonu) */}
|
{/* Telefon */}
|
||||||
<div class="fuz-modal-section">
|
<div class="f-modal-section">
|
||||||
<h3>Usługa telefoniczna</h3>
|
<h3>Usługa telefoniczna</h3>
|
||||||
|
|
||||||
{phonePlans.length === 0 ? (
|
{phonePlans.length === 0 ? (
|
||||||
<p>Brak dostępnych pakietów telefonicznych.</p>
|
<p>Brak dostępnych pakietów telefonicznych.</p>
|
||||||
) : (
|
) : (
|
||||||
<div class="fuz-modal-phone-list fuz-accordion">
|
<div class="f-modal-phone-list f-accordion">
|
||||||
{/* OPCJA: brak telefonu */}
|
{/* brak telefonu */}
|
||||||
<div class="fuz-accordion-item fuz-accordion-item--no-phone">
|
<div class="f-accordion-item f-accordion-item--no-phone">
|
||||||
<button
|
<button
|
||||||
type="button"
|
type="button"
|
||||||
class="fuz-accordion-header"
|
class="f-accordion-header"
|
||||||
onClick={() => handlePhoneSelect(null)}
|
onClick={() => handlePhoneSelect(null)}
|
||||||
>
|
>
|
||||||
<span class="fuz-accordion-header-left">
|
<span class="f-accordion-header-left">
|
||||||
<input
|
<input
|
||||||
type="radio"
|
type="radio"
|
||||||
name="phone-plan"
|
name="phone-plan"
|
||||||
@@ -206,32 +207,30 @@ export default function InternetAddonsModal({ isOpen, onClose, plan }) {
|
|||||||
}}
|
}}
|
||||||
onClick={(e) => e.stopPropagation()}
|
onClick={(e) => e.stopPropagation()}
|
||||||
/>
|
/>
|
||||||
<span class="fuz-modal-phone-name">
|
<span class="f-modal-phone-name">
|
||||||
Nie potrzebuję telefonu
|
Nie potrzebuję telefonu
|
||||||
</span>
|
</span>
|
||||||
</span>
|
</span>
|
||||||
<span class="fuz-modal-phone-price">0,00 zł/mies.</span>
|
<span class="f-modal-phone-price">0,00 zł/mies.</span>
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
{/* lista pakietów telefonu */}
|
||||||
{/* LISTA PAKIETÓW TELEFONICZNYCH */}
|
|
||||||
{phonePlans.map((p) => {
|
{phonePlans.map((p) => {
|
||||||
const isSelected = selectedPhoneId === p.id;
|
const isSelected = selectedPhoneId === p.id;
|
||||||
const isOpen = openPhoneId === p.id;
|
const isOpen = openPhoneId === p.id;
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div
|
<div
|
||||||
class={`fuz-accordion-item ${isOpen ? "is-open" : ""
|
class={`f-accordion-item ${isOpen ? "is-open" : ""}`}
|
||||||
}`}
|
|
||||||
key={p.id}
|
key={p.id}
|
||||||
>
|
>
|
||||||
<button
|
<button
|
||||||
type="button"
|
type="button"
|
||||||
class="fuz-accordion-header"
|
class="f-accordion-header"
|
||||||
onClick={() => handlePhoneSelect(p.id)}
|
onClick={() => handlePhoneSelect(p.id)}
|
||||||
>
|
>
|
||||||
<span class="fuz-accordion-header-left">
|
<span class="f-accordion-header-left">
|
||||||
<input
|
<input
|
||||||
type="radio"
|
type="radio"
|
||||||
name="phone-plan"
|
name="phone-plan"
|
||||||
@@ -242,36 +241,29 @@ export default function InternetAddonsModal({ isOpen, onClose, plan }) {
|
|||||||
}}
|
}}
|
||||||
onClick={(e) => e.stopPropagation()}
|
onClick={(e) => e.stopPropagation()}
|
||||||
/>
|
/>
|
||||||
<span class="fuz-modal-phone-name">
|
<span class="f-modal-phone-name">{p.name}</span>
|
||||||
{p.name}
|
|
||||||
</span>
|
</span>
|
||||||
</span>
|
|
||||||
<span class="fuz-modal-phone-price">
|
<span class="f-modal-phone-price">
|
||||||
{p.price_monthly.toFixed(2)} zł/mies.
|
{p.price_monthly.toFixed(2)} zł/mies.
|
||||||
</span>
|
</span>
|
||||||
</button>
|
</button>
|
||||||
|
|
||||||
{isOpen && (
|
{isOpen && (
|
||||||
<div class="fuz-accordion-body">
|
<div class="f-accordion-body">
|
||||||
{p.features && p.features.length > 0 && (
|
{p.features && p.features.length > 0 && (
|
||||||
<ul class="f-card-features">
|
<ul class="f-card-features">
|
||||||
{p.features
|
{p.features
|
||||||
.filter(
|
.filter(
|
||||||
(f) =>
|
(f) =>
|
||||||
!String(
|
!String(f.label || "")
|
||||||
f.label || ""
|
|
||||||
)
|
|
||||||
.toLowerCase()
|
.toLowerCase()
|
||||||
.includes("aktyw")
|
.includes("aktyw")
|
||||||
)
|
)
|
||||||
.map((f, idx) => (
|
.map((f, idx) => (
|
||||||
<li class="f-card-row" key={idx}>
|
<li class="f-card-row" key={idx}>
|
||||||
<span class="f-card-label">
|
<span class="f-card-label">{f.label}</span>
|
||||||
{f.label}
|
<span class="f-card-value">{f.value}</span>
|
||||||
</span>
|
|
||||||
<span class="f-card-value">
|
|
||||||
{f.value}
|
|
||||||
</span>
|
|
||||||
</li>
|
</li>
|
||||||
))}
|
))}
|
||||||
</ul>
|
</ul>
|
||||||
@@ -285,47 +277,39 @@ export default function InternetAddonsModal({ isOpen, onClose, plan }) {
|
|||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
{/* Sekcja: dodatki internetowe */}
|
{/* Dodatki internetowe */}
|
||||||
<div class="fuz-modal-section">
|
<div class="f-modal-section">
|
||||||
<h3>Dodatkowe usługi</h3>
|
<h3>Dodatkowe usługi</h3>
|
||||||
|
|
||||||
{addons.length === 0 ? (
|
{addons.length === 0 ? (
|
||||||
<p>Brak dodatkowych usług.</p>
|
<p>Brak dodatkowych usług.</p>
|
||||||
) : (
|
) : (
|
||||||
<div class="fuz-addon-list">
|
<div class="f-addon-list">
|
||||||
{addons.map((addon) =>
|
{addons.map((addon) =>
|
||||||
addon.options.map((opt) => {
|
addon.options.map((opt) => {
|
||||||
const checked = selectedAddons.some(
|
const checked = selectedAddons.some(
|
||||||
(x) =>
|
(x) => x.addonId === addon.id && x.optionId === opt.id
|
||||||
x.addonId === addon.id &&
|
|
||||||
x.optionId === opt.id
|
|
||||||
);
|
);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<label
|
<label class="f-addon-item" key={`${addon.id}-${opt.id}`}>
|
||||||
class="fuz-addon-item"
|
<div class="f-addon-checkbox">
|
||||||
key={`${addon.id}-${opt.id}`}
|
|
||||||
>
|
|
||||||
<div class="fuz-addon-checkbox">
|
|
||||||
<input
|
<input
|
||||||
type="checkbox"
|
type="checkbox"
|
||||||
checked={checked}
|
checked={checked}
|
||||||
onChange={() =>
|
onChange={() => handleAddonToggle(addon.id, opt.id)}
|
||||||
handleAddonToggle(addon.id, opt.id)
|
|
||||||
}
|
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="fuz-addon-main">
|
<div class="f-addon-main">
|
||||||
<div class="fuz-addon-name">{addon.name}</div>
|
<div class="f-addon-name">{addon.name}</div>
|
||||||
{addon.description && (
|
{addon.description && (
|
||||||
<div class="fuz-addon-desc">
|
<div class="f-addon-desc">{addon.description}</div>
|
||||||
{addon.description}
|
|
||||||
</div>
|
|
||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="fuz-addon-price">
|
<div class="f-addon-price">
|
||||||
{opt.price.toFixed(2)} zł/mies.
|
{opt.price.toFixed(2)} {opt.currency}
|
||||||
</div>
|
</div>
|
||||||
</label>
|
</label>
|
||||||
);
|
);
|
||||||
@@ -336,34 +320,30 @@ export default function InternetAddonsModal({ isOpen, onClose, plan }) {
|
|||||||
</div>
|
</div>
|
||||||
|
|
||||||
{/* Podsumowanie */}
|
{/* Podsumowanie */}
|
||||||
<div class="fuz-modal-section fuz-summary">
|
<div class="f-modal-section f-summary">
|
||||||
<h3>Podsumowanie miesięczne</h3>
|
<h3>Podsumowanie miesięczne</h3>
|
||||||
|
|
||||||
<div class="fuz-summary-list">
|
<div class="f-summary-list">
|
||||||
<div class="fuz-summary-row">
|
<div class="f-summary-row">
|
||||||
<span>Internet</span>
|
<span>Internet</span>
|
||||||
<span>{basePrice.toFixed(2)} zł/mies.</span>
|
<span>{basePrice.toFixed(2)} zł/mies.</span>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="fuz-summary-row">
|
<div class="f-summary-row">
|
||||||
<span>Telefon</span>
|
<span>Telefon</span>
|
||||||
<span>
|
<span>
|
||||||
{phonePrice
|
{phonePrice ? `${phonePrice.toFixed(2)} zł/mies.` : "—"}
|
||||||
? `${phonePrice.toFixed(2)} zł/mies.`
|
|
||||||
: "—"}
|
|
||||||
</span>
|
</span>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="fuz-summary-row">
|
<div class="f-summary-row">
|
||||||
<span>Dodatki</span>
|
<span>Dodatki</span>
|
||||||
<span>
|
<span>
|
||||||
{addonsPrice
|
{addonsPrice ? `${addonsPrice.toFixed(2)} zł/mies.` : "—"}
|
||||||
? `${addonsPrice.toFixed(2)} zł/mies.`
|
|
||||||
: "—"}
|
|
||||||
</span>
|
</span>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="fuz-summary-total">
|
<div class="f-summary-total">
|
||||||
<span>Łącznie</span>
|
<span>Łącznie</span>
|
||||||
<span>{totalMonthly.toFixed(2)} zł/mies.</span>
|
<span>{totalMonthly.toFixed(2)} zł/mies.</span>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -37,9 +37,7 @@ export default function JamboxAddonsModal({ isOpen, onClose, pkg }) {
|
|||||||
|
|
||||||
const toggleAddon = (addonId) => {
|
const toggleAddon = (addonId) => {
|
||||||
setSelectedAddonIds((prev) =>
|
setSelectedAddonIds((prev) =>
|
||||||
prev.includes(addonId)
|
prev.includes(addonId) ? prev.filter((x) => x !== addonId) : [...prev, addonId]
|
||||||
? prev.filter((x) => x !== addonId)
|
|
||||||
: [...prev, addonId]
|
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -77,9 +75,9 @@ export default function JamboxAddonsModal({ isOpen, onClose, pkg }) {
|
|||||||
const addonsJson = await addonsRes.json();
|
const addonsJson = await addonsRes.json();
|
||||||
const addonsData = Array.isArray(addonsJson.data) ? addonsJson.data : [];
|
const addonsData = Array.isArray(addonsJson.data) ? addonsJson.data : [];
|
||||||
|
|
||||||
|
// pakiety TV
|
||||||
const tvRes = await fetch(`/api/jambox/tv-addons?packageId=${pkg.id}`);
|
const tvRes = await fetch(`/api/jambox/tv-addons?packageId=${pkg.id}`);
|
||||||
if (!tvRes.ok) throw new Error(`HTTP ${tvRes.status} (tv-addons)`);
|
if (!tvRes.ok) throw new Error(`HTTP ${tvRes.status} (tv-addons)`);
|
||||||
|
|
||||||
const tvJson = await tvRes.json();
|
const tvJson = await tvRes.json();
|
||||||
const tvData = Array.isArray(tvJson.data) ? tvJson.data : [];
|
const tvData = Array.isArray(tvJson.data) ? tvJson.data : [];
|
||||||
|
|
||||||
@@ -112,7 +110,7 @@ export default function JamboxAddonsModal({ isOpen, onClose, pkg }) {
|
|||||||
return Number(p?.price_monthly || 0);
|
return Number(p?.price_monthly || 0);
|
||||||
}, [selectedPhoneId, phonePlans]);
|
}, [selectedPhoneId, phonePlans]);
|
||||||
|
|
||||||
// UWAGA: backend może zwrócić { id, price } albo { addon_id, price }
|
// backend może zwrócić { id, price } albo { addon_id, price }
|
||||||
const addonsPrice = useMemo(() => {
|
const addonsPrice = useMemo(() => {
|
||||||
return selectedAddonIds.reduce((sum, addonId) => {
|
return selectedAddonIds.reduce((sum, addonId) => {
|
||||||
const a = addons.find((x) => (x.id ?? x.addon_id) === addonId);
|
const a = addons.find((x) => (x.id ?? x.addon_id) === addonId);
|
||||||
@@ -120,8 +118,6 @@ export default function JamboxAddonsModal({ isOpen, onClose, pkg }) {
|
|||||||
}, 0);
|
}, 0);
|
||||||
}, [selectedAddonIds, addons]);
|
}, [selectedAddonIds, addons]);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
const tvAddonsPrice = useMemo(() => {
|
const tvAddonsPrice = useMemo(() => {
|
||||||
return selectedTvAddonTids.reduce((sum, tid) => {
|
return selectedTvAddonTids.reduce((sum, tid) => {
|
||||||
const a = tvAddons.find((x) => Number(x.tid) === Number(tid));
|
const a = tvAddons.find((x) => Number(x.tid) === Number(tid));
|
||||||
@@ -139,9 +135,11 @@ export default function JamboxAddonsModal({ isOpen, onClose, pkg }) {
|
|||||||
};
|
};
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div class="fuz-modal-overlay" onClick={onClose}>
|
<div class="f-modal-overlay" onClick={onClose}>
|
||||||
<button
|
<button
|
||||||
class="fuz-modal-close"
|
class="f-modal-close"
|
||||||
|
type="button"
|
||||||
|
aria-label="Zamknij"
|
||||||
onClick={(e) => {
|
onClick={(e) => {
|
||||||
e.stopPropagation();
|
e.stopPropagation();
|
||||||
onClose();
|
onClose();
|
||||||
@@ -150,36 +148,31 @@ export default function JamboxAddonsModal({ isOpen, onClose, pkg }) {
|
|||||||
✕
|
✕
|
||||||
</button>
|
</button>
|
||||||
|
|
||||||
<div
|
<div class="f-modal-panel f-modal-panel--compact" onClick={(e) => e.stopPropagation()}>
|
||||||
class="fuz-modal-panel fuz-modal-panel--compact"
|
<div class="f-modal-inner">
|
||||||
onClick={(e) => e.stopPropagation()}
|
<h2 class="f-modal-title">Konfiguracja usług dodatkowych</h2>
|
||||||
>
|
|
||||||
<div class="fuz-modal-inner">
|
|
||||||
<h2 class="fuz-modal-title">Konfiguracja usług dodatkowych</h2>
|
|
||||||
|
|
||||||
{/* PAKIET JAMBOX jako akordeon (jak internet w Twoim modalu) */}
|
{/* PAKIET JAMBOX jako akordeon */}
|
||||||
<div class="fuz-modal-section">
|
<div class="f-modal-section">
|
||||||
<div class={`fuz-accordion-item ${baseOpen ? "is-open" : ""}`}>
|
<div class={`f-accordion-item ${baseOpen ? "is-open" : ""}`}>
|
||||||
<button
|
<button
|
||||||
type="button"
|
type="button"
|
||||||
class="fuz-accordion-header"
|
class="f-accordion-header"
|
||||||
onClick={() => setBaseOpen((prev) => !prev)}
|
onClick={() => setBaseOpen((prev) => !prev)}
|
||||||
>
|
>
|
||||||
<span class="fuz-modal-phone-name">{pkg.name}</span>
|
<span class="f-modal-phone-name">{pkg.name}</span>
|
||||||
<span class="fuz-modal-phone-price">
|
<span class="f-modal-phone-price">
|
||||||
{basePrice ? `${basePrice.toFixed(2)} zł/mies.` : "—"}
|
{basePrice ? `${basePrice.toFixed(2)} zł/mies.` : "—"}
|
||||||
</span>
|
</span>
|
||||||
</button>
|
</button>
|
||||||
|
|
||||||
{baseOpen && pkg.features && pkg.features.length > 0 && (
|
{baseOpen && pkg.features && pkg.features.length > 0 && (
|
||||||
<div class="fuz-accordion-body">
|
<div class="f-accordion-body">
|
||||||
<ul class="f-card-features">
|
<ul class="f-card-features">
|
||||||
{pkg.features.map((f, idx) => (
|
{pkg.features.map((f, idx) => (
|
||||||
<li class="f-card-row" key={idx}>
|
<li class="f-card-row" key={idx}>
|
||||||
<span class="f-card-label">{f.label}</span>
|
<span class="f-card-label">{f.label}</span>
|
||||||
<span class="f-card-value">
|
<span class="f-card-value">{formatFeatureValue(f.value)}</span>
|
||||||
{formatFeatureValue(f.value)}
|
|
||||||
</span>
|
|
||||||
</li>
|
</li>
|
||||||
))}
|
))}
|
||||||
</ul>
|
</ul>
|
||||||
@@ -193,22 +186,22 @@ export default function JamboxAddonsModal({ isOpen, onClose, pkg }) {
|
|||||||
|
|
||||||
{!loading && !error && (
|
{!loading && !error && (
|
||||||
<>
|
<>
|
||||||
|
{/* TV ADDONS */}
|
||||||
<div class="fuz-modal-section">
|
<div class="f-modal-section">
|
||||||
<h3>Pakiety dodatkowe TV</h3>
|
<h3>Pakiety dodatkowe TV</h3>
|
||||||
|
|
||||||
{tvAddons.length === 0 ? (
|
{tvAddons.length === 0 ? (
|
||||||
<p>Brak pakietów dodatkowych TV dla tego pakietu.</p>
|
<p>Brak pakietów dodatkowych TV dla tego pakietu.</p>
|
||||||
) : (
|
) : (
|
||||||
<div class="fuz-addon-list">
|
<div class="f-addon-list">
|
||||||
{tvAddons.map((a) => {
|
{tvAddons.map((a) => {
|
||||||
const tid = Number(a.tid);
|
const tid = Number(a.tid);
|
||||||
const checked = selectedTvAddonTids.includes(tid);
|
const checked = selectedTvAddonTids.includes(tid);
|
||||||
const priceNum = Number(a.price || 0);
|
const priceNum = Number(a.price || 0);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<label class="fuz-addon-item" key={`tv-${tid}`}>
|
<label class="f-addon-item" key={`tv-${tid}`}>
|
||||||
<div class="fuz-addon-checkbox">
|
<div class="f-addon-checkbox">
|
||||||
<input
|
<input
|
||||||
type="checkbox"
|
type="checkbox"
|
||||||
checked={checked}
|
checked={checked}
|
||||||
@@ -216,13 +209,12 @@ export default function JamboxAddonsModal({ isOpen, onClose, pkg }) {
|
|||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="fuz-addon-main">
|
<div class="f-addon-main">
|
||||||
<div class="fuz-addon-name">{a.name}</div>
|
<div class="f-addon-name">{a.name}</div>
|
||||||
{/* jeśli chcesz pokazać typ/kind */}
|
<div class="f-addon-desc">{a.description}</div>
|
||||||
<div class="fuz-addon-desc">{a.description}</div>
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="fuz-addon-price">
|
<div class="f-addon-price">
|
||||||
{Number.isFinite(priceNum) ? `${priceNum.toFixed(2)} zł/mies.` : "—"}
|
{Number.isFinite(priceNum) ? `${priceNum.toFixed(2)} zł/mies.` : "—"}
|
||||||
</div>
|
</div>
|
||||||
</label>
|
</label>
|
||||||
@@ -232,22 +224,22 @@ export default function JamboxAddonsModal({ isOpen, onClose, pkg }) {
|
|||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
{/* TELEFON (identycznie jak w InternetAddonsModal) */}
|
{/* TELEFON */}
|
||||||
<div class="fuz-modal-section">
|
<div class="f-modal-section">
|
||||||
<h3>Usługa telefoniczna</h3>
|
<h3>Usługa telefoniczna</h3>
|
||||||
|
|
||||||
{phonePlans.length === 0 ? (
|
{phonePlans.length === 0 ? (
|
||||||
<p>Brak dostępnych pakietów telefonicznych.</p>
|
<p>Brak dostępnych pakietów telefonicznych.</p>
|
||||||
) : (
|
) : (
|
||||||
<div class="fuz-modal-phone-list fuz-accordion">
|
<div class="f-modal-phone-list f-accordion">
|
||||||
{/* OPCJA: brak telefonu */}
|
{/* brak telefonu */}
|
||||||
<div class="fuz-accordion-item fuz-accordion-item--no-phone">
|
<div class="f-accordion-item f-accordion-item--no-phone">
|
||||||
<button
|
<button
|
||||||
type="button"
|
type="button"
|
||||||
class="fuz-accordion-header"
|
class="f-accordion-header"
|
||||||
onClick={() => handlePhoneSelect(null)}
|
onClick={() => handlePhoneSelect(null)}
|
||||||
>
|
>
|
||||||
<span class="fuz-accordion-header-left">
|
<span class="f-accordion-header-left">
|
||||||
<input
|
<input
|
||||||
type="radio"
|
type="radio"
|
||||||
name="phone-plan"
|
name="phone-plan"
|
||||||
@@ -258,30 +250,25 @@ export default function JamboxAddonsModal({ isOpen, onClose, pkg }) {
|
|||||||
}}
|
}}
|
||||||
onClick={(e) => e.stopPropagation()}
|
onClick={(e) => e.stopPropagation()}
|
||||||
/>
|
/>
|
||||||
<span class="fuz-modal-phone-name">
|
<span class="f-modal-phone-name">Nie potrzebuję telefonu</span>
|
||||||
Nie potrzebuję telefonu
|
|
||||||
</span>
|
</span>
|
||||||
</span>
|
<span class="f-modal-phone-price">0,00 zł/mies.</span>
|
||||||
<span class="fuz-modal-phone-price">0,00 zł/mies.</span>
|
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
{/* PAKIETY TELEFONU */}
|
{/* pakiety telefonu */}
|
||||||
{phonePlans.map((p) => {
|
{phonePlans.map((p) => {
|
||||||
const isSelected = selectedPhoneId === p.id;
|
const isSelected = selectedPhoneId === p.id;
|
||||||
const isOpen = openPhoneId === p.id;
|
const isOpen = openPhoneId === p.id;
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div
|
<div class={`f-accordion-item ${isOpen ? "is-open" : ""}`} key={p.id}>
|
||||||
class={`fuz-accordion-item ${isOpen ? "is-open" : ""}`}
|
|
||||||
key={p.id}
|
|
||||||
>
|
|
||||||
<button
|
<button
|
||||||
type="button"
|
type="button"
|
||||||
class="fuz-accordion-header"
|
class="f-accordion-header"
|
||||||
onClick={() => handlePhoneSelect(p.id)}
|
onClick={() => handlePhoneSelect(p.id)}
|
||||||
>
|
>
|
||||||
<span class="fuz-accordion-header-left">
|
<span class="f-accordion-header-left">
|
||||||
<input
|
<input
|
||||||
type="radio"
|
type="radio"
|
||||||
name="phone-plan"
|
name="phone-plan"
|
||||||
@@ -292,23 +279,21 @@ export default function JamboxAddonsModal({ isOpen, onClose, pkg }) {
|
|||||||
}}
|
}}
|
||||||
onClick={(e) => e.stopPropagation()}
|
onClick={(e) => e.stopPropagation()}
|
||||||
/>
|
/>
|
||||||
<span class="fuz-modal-phone-name">{p.name}</span>
|
<span class="f-modal-phone-name">{p.name}</span>
|
||||||
</span>
|
</span>
|
||||||
<span class="fuz-modal-phone-price">
|
<span class="f-modal-phone-price">
|
||||||
{Number(p.price_monthly || 0).toFixed(2)} zł/mies.
|
{Number(p.price_monthly || 0).toFixed(2)} zł/mies.
|
||||||
</span>
|
</span>
|
||||||
</button>
|
</button>
|
||||||
|
|
||||||
{isOpen && (
|
{isOpen && (
|
||||||
<div class="fuz-accordion-body">
|
<div class="f-accordion-body">
|
||||||
{p.features && p.features.length > 0 && (
|
{p.features && p.features.length > 0 && (
|
||||||
<ul class="f-card-features">
|
<ul class="f-card-features">
|
||||||
{p.features
|
{p.features
|
||||||
.filter(
|
.filter(
|
||||||
(f) =>
|
(f) =>
|
||||||
!String(f.label || "")
|
!String(f.label || "").toLowerCase().includes("aktyw")
|
||||||
.toLowerCase()
|
|
||||||
.includes("aktyw")
|
|
||||||
)
|
)
|
||||||
.map((f, idx) => (
|
.map((f, idx) => (
|
||||||
<li class="f-card-row" key={idx}>
|
<li class="f-card-row" key={idx}>
|
||||||
@@ -327,21 +312,22 @@ export default function JamboxAddonsModal({ isOpen, onClose, pkg }) {
|
|||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
{/* DODATKI JAMBOX (checkbox, cena z jambox_package_addon_options.price) */}
|
{/* DODATKI JAMBOX */}
|
||||||
<div class="fuz-modal-section">
|
<div class="f-modal-section">
|
||||||
<h3>Dodatkowe usługi</h3>
|
<h3>Dodatkowe usługi</h3>
|
||||||
|
|
||||||
{addons.length === 0 ? (
|
{addons.length === 0 ? (
|
||||||
<p>Brak usług dodatkowych dla tego pakietu.</p>
|
<p>Brak usług dodatkowych dla tego pakietu.</p>
|
||||||
) : (
|
) : (
|
||||||
<div class="fuz-addon-list">
|
<div class="f-addon-list">
|
||||||
{addons.map((a) => {
|
{addons.map((a) => {
|
||||||
const addonId = a.id ?? a.addon_id; // defensywnie
|
const addonId = a.id ?? a.addon_id;
|
||||||
const checked = selectedAddonIds.includes(addonId);
|
const checked = selectedAddonIds.includes(addonId);
|
||||||
|
const priceNum = Number(a.price || 0);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<label class="fuz-addon-item" key={addonId}>
|
<label class="f-addon-item" key={addonId}>
|
||||||
<div class="fuz-addon-checkbox">
|
<div class="f-addon-checkbox">
|
||||||
<input
|
<input
|
||||||
type="checkbox"
|
type="checkbox"
|
||||||
checked={checked}
|
checked={checked}
|
||||||
@@ -349,16 +335,12 @@ export default function JamboxAddonsModal({ isOpen, onClose, pkg }) {
|
|||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="fuz-addon-main">
|
<div class="f-addon-main">
|
||||||
<div class="fuz-addon-name">{a.name}</div>
|
<div class="f-addon-name">{a.name}</div>
|
||||||
{a.description && (
|
{a.description && <div class="f-addon-desc">{a.description}</div>}
|
||||||
<div class="fuz-addon-desc">{a.description}</div>
|
|
||||||
)}
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="fuz-addon-price">
|
<div class="f-addon-price">{priceNum.toFixed(2)} zł/mies.</div>
|
||||||
{Number(a.price || 0).toFixed(2)} zł/mies.
|
|
||||||
</div>
|
|
||||||
</label>
|
</label>
|
||||||
);
|
);
|
||||||
})}
|
})}
|
||||||
@@ -367,35 +349,31 @@ export default function JamboxAddonsModal({ isOpen, onClose, pkg }) {
|
|||||||
</div>
|
</div>
|
||||||
|
|
||||||
{/* PODSUMOWANIE */}
|
{/* PODSUMOWANIE */}
|
||||||
<div class="fuz-modal-section fuz-summary">
|
<div class="f-modal-section f-summary">
|
||||||
<h3>Podsumowanie miesięczne</h3>
|
<h3>Podsumowanie miesięczne</h3>
|
||||||
|
|
||||||
<div class="fuz-summary-list">
|
<div class="f-summary-list">
|
||||||
<div class="fuz-summary-row">
|
<div class="f-summary-row">
|
||||||
<span>Pakiet</span>
|
<span>Pakiet</span>
|
||||||
<span>
|
<span>{basePrice ? `${basePrice.toFixed(2)} zł/mies.` : "—"}</span>
|
||||||
{basePrice ? `${basePrice.toFixed(2)} zł/mies.` : "—"}
|
|
||||||
</span>
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="fuz-summary-row">
|
<div class="f-summary-row">
|
||||||
<span>Pakiety TV</span>
|
<span>Pakiety TV</span>
|
||||||
<span>
|
<span>{tvAddonsPrice ? `${tvAddonsPrice.toFixed(2)} zł/mies.` : "—"}</span>
|
||||||
{tvAddonsPrice ? `${tvAddonsPrice.toFixed(2)} zł/mies.` : "—"}
|
|
||||||
</span>
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="fuz-summary-row">
|
<div class="f-summary-row">
|
||||||
<span>Telefon</span>
|
<span>Telefon</span>
|
||||||
<span>{phonePrice ? `${phonePrice.toFixed(2)} zł/mies.` : "—"}</span>
|
<span>{phonePrice ? `${phonePrice.toFixed(2)} zł/mies.` : "—"}</span>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="fuz-summary-row">
|
<div class="f-summary-row">
|
||||||
<span>Dodatki</span>
|
<span>Dodatki</span>
|
||||||
<span>{addonsPrice ? `${addonsPrice.toFixed(2)} zł/mies.` : "—"}</span>
|
<span>{addonsPrice ? `${addonsPrice.toFixed(2)} zł/mies.` : "—"}</span>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="fuz-summary-total">
|
<div class="f-summary-total">
|
||||||
<span>Łącznie</span>
|
<span>Łącznie</span>
|
||||||
<span>{totalMonthly.toFixed(2)} zł/mies.</span>
|
<span>{totalMonthly.toFixed(2)} zł/mies.</span>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -1,23 +1,26 @@
|
|||||||
// src/islands/JamboxChannelsModal.jsx
|
import { useEffect, useMemo, useState } from "preact/hooks";
|
||||||
import { useEffect, useState } from "preact/hooks";
|
|
||||||
import "../../styles/modal.css";
|
import "../../styles/modal.css";
|
||||||
import "../../styles/offers/offers-table.css";
|
import "../../styles/offers/offers-table.css";
|
||||||
|
import "../../styles/channels-search.css"; // żeby input miał identyczny styl
|
||||||
|
|
||||||
export default function JamboxChannelsModal({ isOpen, onClose, pkg }) {
|
export default function JamboxChannelsModal({ isOpen, onClose, pkg }) {
|
||||||
const [channels, setChannels] = useState([]);
|
const [channels, setChannels] = useState([]);
|
||||||
const [loading, setLoading] = useState(false);
|
const [loading, setLoading] = useState(false);
|
||||||
const [error, setError] = useState("");
|
const [error, setError] = useState("");
|
||||||
|
|
||||||
const [query, setQuery] = useState("");
|
const [query, setQuery] = useState("");
|
||||||
|
|
||||||
const q = query.trim().toLowerCase();
|
const q = query.trim().toLowerCase();
|
||||||
|
|
||||||
const filtered = !q
|
const filtered = !q
|
||||||
? channels
|
? channels
|
||||||
: channels.filter((ch) =>
|
: channels.filter((ch) => (ch.name || "").toLowerCase().includes(q));
|
||||||
(ch.name || "").toLowerCase().includes(q)
|
|
||||||
);
|
|
||||||
|
|
||||||
|
const meta = useMemo(() => {
|
||||||
|
if (loading) return "Ładowanie…";
|
||||||
|
if (error) return error;
|
||||||
|
if (!query.trim()) return `Wyniki: ${filtered.length} / ${channels.length}`;
|
||||||
|
return `Wyniki: ${filtered.length} / ${channels.length}`;
|
||||||
|
}, [loading, error, query, filtered.length, channels.length]);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (!isOpen || !pkg?.id) return;
|
if (!isOpen || !pkg?.id) return;
|
||||||
@@ -34,19 +37,13 @@ export default function JamboxChannelsModal({ isOpen, onClose, pkg }) {
|
|||||||
const params = new URLSearchParams({ packageId: String(pkg.id) });
|
const params = new URLSearchParams({ packageId: String(pkg.id) });
|
||||||
const res = await fetch(`/api/jambox/channels?${params.toString()}`);
|
const res = await fetch(`/api/jambox/channels?${params.toString()}`);
|
||||||
|
|
||||||
if (!res.ok) {
|
if (!res.ok) throw new Error(`HTTP ${res.status}`);
|
||||||
throw new Error(`HTTP ${res.status}`);
|
|
||||||
}
|
|
||||||
|
|
||||||
const json = await res.json();
|
const json = await res.json();
|
||||||
if (!cancelled) {
|
if (!cancelled) setChannels(Array.isArray(json.data) ? json.data : []);
|
||||||
setChannels(Array.isArray(json.data) ? json.data : []);
|
|
||||||
}
|
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
console.error("❌ Błąd pobierania listy kanałów:", err);
|
console.error("❌ Błąd pobierania listy kanałów:", err);
|
||||||
if (!cancelled) {
|
if (!cancelled) setError("Nie udało się załadować listy kanałów.");
|
||||||
setError("Nie udało się załadować listy kanałów.");
|
|
||||||
}
|
|
||||||
} finally {
|
} finally {
|
||||||
if (!cancelled) setLoading(false);
|
if (!cancelled) setLoading(false);
|
||||||
}
|
}
|
||||||
@@ -61,81 +58,105 @@ export default function JamboxChannelsModal({ isOpen, onClose, pkg }) {
|
|||||||
if (!isOpen || !pkg) return null;
|
if (!isOpen || !pkg) return null;
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div class="fuz-modal-overlay" onClick={onClose}>
|
<div class="f-modal-overlay" onClick={onClose}>
|
||||||
<button
|
<button
|
||||||
class="fuz-modal-close"
|
class="f-modal-close"
|
||||||
onClick={(e) => {
|
onClick={(e) => {
|
||||||
e.stopPropagation();
|
e.stopPropagation();
|
||||||
onClose();
|
onClose();
|
||||||
}}
|
}}
|
||||||
|
aria-label="Zamknij"
|
||||||
|
type="button"
|
||||||
>
|
>
|
||||||
✕
|
✕
|
||||||
</button>
|
</button>
|
||||||
|
|
||||||
<div
|
<div
|
||||||
class="fuz-modal-panel fuz-modal-panel--channels"
|
class="f-modal-panel f-modal-panel--channels"
|
||||||
onClick={(e) => e.stopPropagation()}
|
onClick={(e) => e.stopPropagation()}
|
||||||
|
role="dialog"
|
||||||
|
aria-modal="true"
|
||||||
|
aria-label={`Kanały w pakiecie ${pkg.name}`}
|
||||||
>
|
>
|
||||||
<div class="max-w-8xl mx-auto px-3 md:px-6">
|
<div class="max-w-8xl mx-auto px-3 md:px-6">
|
||||||
<h2 class="fuz-modal-title">Kanały w pakiecie {pkg.name}</h2>
|
<h2 class="f-modal-title">Kanały w pakiecie {pkg.name}</h2>
|
||||||
|
|
||||||
<div class="fuz-chsearch__top">
|
{/* INPUT jak w wyszukiwarce (z własnym X) */}
|
||||||
|
<div class="f-chsearch__top">
|
||||||
|
<div class="f-chsearch__inputwrap">
|
||||||
<input
|
<input
|
||||||
class="fuz-chsearch__input"
|
class="f-chsearch__input"
|
||||||
type="search"
|
type="search"
|
||||||
value={query}
|
value={query}
|
||||||
onInput={(e) => setQuery(e.currentTarget.value)}
|
onInput={(e) => setQuery(e.currentTarget.value)}
|
||||||
placeholder="Szukaj kanału po nazwie…"
|
placeholder="Szukaj kanału po nazwie…"
|
||||||
aria-label="Szukaj kanału po nazwie"
|
aria-label="Szukaj kanału po nazwie"
|
||||||
/>
|
/>
|
||||||
|
|
||||||
|
{query && (
|
||||||
|
<button
|
||||||
|
type="button"
|
||||||
|
class="f-chsearch__clear"
|
||||||
|
aria-label="Wyczyść wyszukiwanie"
|
||||||
|
onClick={() => setQuery("")}
|
||||||
|
onMouseDown={(e) => e.preventDefault()} // nie zabieraj focusa inputowi
|
||||||
|
>
|
||||||
|
✕
|
||||||
|
</button>
|
||||||
|
)}
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
{!loading && !error && (
|
<div class="f-chsearch__meta">{meta}</div>
|
||||||
<div class="jmb-search-meta">
|
|
||||||
Wyniki: <strong>{filtered.length}</strong> / {channels.length}
|
|
||||||
</div>
|
</div>
|
||||||
)}
|
|
||||||
|
|
||||||
{loading && <p>Ładowanie kanałów...</p>}
|
{loading && <p>Ładowanie kanałów...</p>}
|
||||||
{error && <p class="text-red-600">{error}</p>}
|
{error && !loading && <p class="text-red-600">{error}</p>}
|
||||||
|
|
||||||
{!loading && !error && (
|
{!loading && !error && (
|
||||||
<>
|
<>
|
||||||
{filtered.length === 0 ? (
|
{filtered.length === 0 ? (
|
||||||
<p>Brak kanałów spełniających kryteria.</p>
|
<p>Brak kanałów spełniających kryteria.</p>
|
||||||
) : (
|
) : (
|
||||||
<div class="">
|
|
||||||
<div class="f-section-channel">
|
<div class="f-section-channel">
|
||||||
{filtered.map((ch) => (
|
{filtered.map((ch) => (
|
||||||
<div
|
<div
|
||||||
class="jmb-channel-card"
|
class="jmb-channel-card"
|
||||||
key={ch.number}
|
key={ch.number}
|
||||||
onClick={(e) => {
|
onClick={(e) => {
|
||||||
|
// żeby klik w link w opisie nie flipował
|
||||||
if (e.target.closest("a, button")) return;
|
if (e.target.closest("a, button")) return;
|
||||||
e.currentTarget.classList.toggle("is-flipped");
|
e.currentTarget.classList.toggle("is-flipped");
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
<div class="jmb-channel-inner">
|
<div class="jmb-channel-inner">
|
||||||
|
{/* FRONT */}
|
||||||
<div class="jmb-channel-face jmb-channel-front">
|
<div class="jmb-channel-face jmb-channel-front">
|
||||||
{ch.logo_url && (
|
{ch.logo_url && (
|
||||||
<img src={ch.logo_url} alt={ch.name} class="jmb-channel-logo" loading="lazy" />
|
<img
|
||||||
|
src={ch.logo_url}
|
||||||
|
alt={ch.name}
|
||||||
|
class="jmb-channel-logo"
|
||||||
|
loading="lazy"
|
||||||
|
/>
|
||||||
)}
|
)}
|
||||||
<div class="jmb-channel-name">{ch.name}</div>
|
<div class="jmb-channel-name">{ch.name}</div>
|
||||||
<div class="jmb-channel-number">kanał {ch.number}</div>
|
<div class="jmb-channel-number">kanał {ch.number}</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
{/* BACK */}
|
||||||
<div class="jmb-channel-face jmb-channel-back">
|
<div class="jmb-channel-face jmb-channel-back">
|
||||||
<div class="jmb-channel-back-title">{ch.name}</div>
|
<div class="jmb-channel-back-title">{ch.name}</div>
|
||||||
<div
|
<div
|
||||||
class="jmb-channel-desc"
|
class="jmb-channel-desc"
|
||||||
dangerouslySetInnerHTML={{ __html: ch.description || "<em>Brak opisu kanału.</em>" }}
|
dangerouslySetInnerHTML={{
|
||||||
|
__html: ch.description || "<em>Brak opisu kanału.</em>",
|
||||||
|
}}
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
))}
|
))}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
|
||||||
)}
|
)}
|
||||||
</>
|
</>
|
||||||
)}
|
)}
|
||||||
|
|||||||
@@ -31,10 +31,13 @@ export default function JamboxChannelsSearch() {
|
|||||||
params.set("q", qq);
|
params.set("q", qq);
|
||||||
params.set("limit", "80");
|
params.set("limit", "80");
|
||||||
|
|
||||||
const res = await fetch(`/api/jambox/channels-search?${params.toString()}`, {
|
const res = await fetch(
|
||||||
|
`/api/jambox/channels-search?${params.toString()}`,
|
||||||
|
{
|
||||||
signal: ac.signal,
|
signal: ac.signal,
|
||||||
headers: { Accept: "application/json" },
|
headers: { Accept: "application/json" },
|
||||||
});
|
}
|
||||||
|
);
|
||||||
|
|
||||||
const json = await res.json();
|
const json = await res.json();
|
||||||
if (!res.ok || !json.ok) throw new Error(json?.error || "API_ERROR");
|
if (!res.ok || !json.ok) throw new Error(json?.error || "API_ERROR");
|
||||||
@@ -68,16 +71,17 @@ export default function JamboxChannelsSearch() {
|
|||||||
el.scrollIntoView({ behavior: "smooth", block: "start" });
|
el.scrollIntoView({ behavior: "smooth", block: "start" });
|
||||||
|
|
||||||
el.classList.add("is-target");
|
el.classList.add("is-target");
|
||||||
setTimeout(() => el.classList.remove("is-target"), 1200);
|
window.setTimeout(() => el.classList.remove("is-target"), 1200);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div class="fuz-chsearch">
|
<div class="f-chsearch">
|
||||||
<h1 class="f-section-title">Wyszukiwanie kanałów w pakietach telewizji</h1>
|
<h1 class="f-section-title">Wyszukiwanie kanałów w pakietach telewizji</h1>
|
||||||
<div class="fuz-chsearch__top">
|
|
||||||
|
<div class="f-chsearch__top">
|
||||||
|
<div class="f-chsearch__inputwrap">
|
||||||
<input
|
<input
|
||||||
class="fuz-chsearch__input"
|
class="f-chsearch__input"
|
||||||
type="search"
|
type="search"
|
||||||
value={q}
|
value={q}
|
||||||
onInput={(e) => setQ(e.currentTarget.value)}
|
onInput={(e) => setQ(e.currentTarget.value)}
|
||||||
@@ -85,59 +89,63 @@ export default function JamboxChannelsSearch() {
|
|||||||
aria-label="Szukaj kanału po nazwie"
|
aria-label="Szukaj kanału po nazwie"
|
||||||
/>
|
/>
|
||||||
|
|
||||||
<div class="fuz-chsearch__meta">
|
{q && (
|
||||||
{meta}
|
<button
|
||||||
</div>
|
type="button"
|
||||||
|
class="f-chsearch__clear"
|
||||||
|
aria-label="Wyczyść wyszukiwanie"
|
||||||
|
onClick={() => setQ("")}
|
||||||
|
>
|
||||||
|
✕
|
||||||
|
</button>
|
||||||
|
)}
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="fuz-chsearch__list" role="list">
|
<div class="f-chsearch__meta">{meta}</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="f-chsearch__list" role="list">
|
||||||
{items.map((c) => (
|
{items.map((c) => (
|
||||||
<div class="fuz-chsearch__row" role="listitem" key={`${c.name}-${c.logo_url || ""}`}>
|
<div
|
||||||
|
class="f-chsearch__row"
|
||||||
|
role="listitem"
|
||||||
|
key={`${c.name}-${c.logo_url || ""}`}
|
||||||
|
>
|
||||||
{/* kolumna 1 */}
|
{/* kolumna 1 */}
|
||||||
<div class="fuz-chsearch__left">
|
<div class="f-chsearch__left">
|
||||||
{c.logo_url && (
|
{c.logo_url && (
|
||||||
<img
|
<img
|
||||||
src={c.logo_url}
|
src={c.logo_url}
|
||||||
alt={c.name}
|
alt={c.name}
|
||||||
class="fuz-chsearch__logo"
|
class="f-chsearch__logo"
|
||||||
loading="lazy"
|
loading="lazy"
|
||||||
/>
|
/>
|
||||||
)}
|
)}
|
||||||
|
|
||||||
<div class="fuz-chsearch__channel-name">
|
<div class="f-chsearch__channel-name">{c.name}</div>
|
||||||
{c.name}
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
{/* <div class="fuz-chsearch__channel-number">
|
|
||||||
kanał {c.min_number || "—"}
|
|
||||||
</div> */}
|
|
||||||
</div>
|
|
||||||
|
|
||||||
|
|
||||||
{/* kolumna 2 */}
|
{/* kolumna 2 */}
|
||||||
<div class="fuz-chsearch__right">
|
<div class="f-chsearch__right">
|
||||||
<div
|
<div
|
||||||
class="fuz-chsearch__desc fuz-chsearch__desc--html"
|
class="f-chsearch__desc f-chsearch__desc--html"
|
||||||
dangerouslySetInnerHTML={{ __html: c.description || "<em>—</em>" }}
|
dangerouslySetInnerHTML={{
|
||||||
|
__html: c.description || "<em>—</em>",
|
||||||
|
}}
|
||||||
/>
|
/>
|
||||||
|
|
||||||
{Array.isArray(c.packages) && c.packages.length > 0 && (
|
{Array.isArray(c.packages) && c.packages.length > 0 && (
|
||||||
<div class="fuz-chsearch__packages">
|
<div class="f-chsearch__packages">
|
||||||
Dostępny w:
|
Dostępny w:
|
||||||
{c.packages.map((p, i) => (
|
{c.packages.map((p, i) => (
|
||||||
// <span class="fuz-chsearch__pkg" key={p.id}>
|
|
||||||
// {p.name}{" "}
|
|
||||||
// <span class="fuz-chsearch__pkgnum">(kanał {p.number})</span>
|
|
||||||
// {i < c.packages.length - 1 ? ", " : ""}
|
|
||||||
// </span>
|
|
||||||
<button
|
<button
|
||||||
type="button"
|
type="button"
|
||||||
class="fuz-chsearch__pkg"
|
class="f-chsearch__pkg"
|
||||||
key={p.id}
|
key={p.id}
|
||||||
onClick={() => scrollToPackage(p.id)}
|
onClick={() => scrollToPackage(p.id)}
|
||||||
>
|
>
|
||||||
{p.name}{" "}
|
{p.name}{" "}
|
||||||
<span class="fuz-chsearch__pkgnum">(kanał {p.number})</span>
|
<span class="f-chsearch__pkgnum">(kanał {p.number})</span>
|
||||||
{i < c.packages.length - 1 ? ", " : ""}
|
{i < c.packages.length - 1 ? ", " : ""}
|
||||||
</button>
|
</button>
|
||||||
))}
|
))}
|
||||||
@@ -148,7 +156,7 @@ export default function JamboxChannelsSearch() {
|
|||||||
))}
|
))}
|
||||||
|
|
||||||
{q.trim().length >= 2 && !loading && items.length === 0 && (
|
{q.trim().length >= 2 && !loading && items.length === 0 && (
|
||||||
<div class="fuz-chsearch__empty">
|
<div class="f-chsearch__empty">
|
||||||
Brak wyników dla: <strong>{q}</strong>
|
Brak wyników dla: <strong>{q}</strong>
|
||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
|
|||||||
@@ -1,94 +1,127 @@
|
|||||||
.fuz-chsearch {
|
.f-chsearch {
|
||||||
@apply mt-6;
|
@apply mt-6;
|
||||||
}
|
}
|
||||||
|
|
||||||
.fuz-chsearch__top {
|
.f-chsearch__top {
|
||||||
@apply flex flex-col gap-1 mb-4;
|
@apply flex flex-col gap-1 mb-4;
|
||||||
}
|
}
|
||||||
|
|
||||||
.fuz-chsearch__input {
|
/* wrapper dla X w środku inputa */
|
||||||
@apply w-full md:flex-1 px-4 py-3 rounded-xl border border-[--f-input-border] bg-[--f-background] text-[--f-text] outline-none focus:ring-2 focus:ring-[--btn-background];
|
.f-chsearch__inputwrap {
|
||||||
|
@apply relative;
|
||||||
}
|
}
|
||||||
|
|
||||||
.fuz-chsearch__meta {
|
.f-chsearch__input {
|
||||||
|
@apply w-full md:flex-1 px-4 py-3 rounded-xl border border-[--f-input-border] bg-[--f-background] text-[--f-text] outline-none focus:ring-2 focus:ring-[--btn-background];
|
||||||
|
padding-right: 2.75rem; /* miejsce na X */
|
||||||
|
}
|
||||||
|
|
||||||
|
.f-chsearch__clear {
|
||||||
|
@apply absolute right-2 top-1/2 -translate-y-1/2 grid place-items-center rounded-full border-0 bg-transparent text-[--f-text] opacity-70;
|
||||||
|
width: 2rem;
|
||||||
|
height: 2rem;
|
||||||
|
cursor: pointer;
|
||||||
|
}
|
||||||
|
|
||||||
|
.f-chsearch__clear:hover {
|
||||||
|
@apply opacity-100;
|
||||||
|
}
|
||||||
|
|
||||||
|
.f-chsearch__meta {
|
||||||
@apply text-sm opacity-70 pl-1;
|
@apply text-sm opacity-70 pl-1;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* =========================
|
/* =========================
|
||||||
List + Row layout
|
List + Row layout
|
||||||
========================== */
|
========================== */
|
||||||
.fuz-chsearch__list {
|
.f-chsearch__list {
|
||||||
@apply flex flex-col gap-2;
|
@apply flex flex-col gap-2;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* ✅ węższa pierwsza kolumna */
|
.f-chsearch__row {
|
||||||
.fuz-chsearch__row {
|
|
||||||
@apply grid grid-cols-1 md:grid-cols-[220px_1fr] gap-6 rounded-2xl border border-[--f-input-border] bg-[--f-background] p-4;
|
@apply grid grid-cols-1 md:grid-cols-[220px_1fr] gap-6 rounded-2xl border border-[--f-input-border] bg-[--f-background] p-4;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* =========================
|
/* =========================
|
||||||
Column 1: Channel card
|
Column 1: Channel card
|
||||||
========================== */
|
========================== */
|
||||||
.fuz-chsearch__left {
|
.f-chsearch__left {
|
||||||
@apply flex flex-col items-center text-center gap-1 px-2;
|
@apply flex flex-col items-center text-center gap-1 px-2;
|
||||||
}
|
}
|
||||||
|
|
||||||
.fuz-chsearch__logo {
|
.f-chsearch__logo {
|
||||||
@apply w-14 h-14 object-contain bg-white dark:bg-slate-900 border border-slate-200 dark:border-slate-700 rounded-xl p-1 mb-1;
|
@apply w-14 h-14 object-contain bg-white dark:bg-slate-900 border border-slate-200 dark:border-slate-700 rounded-xl p-1 mb-1;
|
||||||
}
|
}
|
||||||
|
|
||||||
.fuz-chsearch__channel-name {
|
.f-chsearch__channel-name {
|
||||||
@apply font-semibold text-[--fuz-header] leading-tight;
|
@apply font-semibold text-[--fuz-header] leading-tight;
|
||||||
}
|
}
|
||||||
|
|
||||||
.fuz-chsearch__channel-number {
|
|
||||||
@apply text-sm opacity-70;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* =========================
|
/* =========================
|
||||||
Column 2: Description + Packages
|
Column 2: Description + Packages
|
||||||
========================== */
|
========================== */
|
||||||
.fuz-chsearch__right {
|
.f-chsearch__right {
|
||||||
@apply flex flex-col gap-2;
|
@apply flex flex-col gap-2;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* opis NIE ucinany */
|
.f-chsearch__desc {
|
||||||
.fuz-chsearch__desc {
|
|
||||||
@apply text-sm md:text-base opacity-90;
|
@apply text-sm md:text-base opacity-90;
|
||||||
overflow-wrap: anywhere;
|
overflow-wrap: anywhere;
|
||||||
word-break: break-word;
|
word-break: break-word;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* HTML jak w modalu */
|
.f-chsearch__desc--html :global(p) {
|
||||||
.fuz-chsearch__desc--html :global(p) {
|
|
||||||
@apply mb-2;
|
@apply mb-2;
|
||||||
}
|
}
|
||||||
|
|
||||||
.fuz-chsearch__desc--html :global(ol),
|
.f-chsearch__desc--html :global(ol),
|
||||||
.fuz-chsearch__desc--html :global(ul) {
|
.f-chsearch__desc--html :global(ul) {
|
||||||
@apply pl-6 mb-2;
|
@apply pl-6 mb-2;
|
||||||
}
|
}
|
||||||
|
|
||||||
.fuz-chsearch__desc--html :global(li) {
|
.f-chsearch__desc--html :global(li) {
|
||||||
@apply mb-1;
|
@apply mb-1;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* pakiety (bez gwarantowanych) */
|
.f-chsearch__packages {
|
||||||
.fuz-chsearch__packages {
|
|
||||||
@apply text-sm opacity-80;
|
@apply text-sm opacity-80;
|
||||||
}
|
}
|
||||||
|
|
||||||
.fuz-chsearch__pkg {
|
/* klikalny pakiet jak link */
|
||||||
@apply inline text-[--btn-background];
|
.f-chsearch__pkg {
|
||||||
|
@apply inline;
|
||||||
|
background: transparent;
|
||||||
|
border: 0;
|
||||||
|
padding: 0;
|
||||||
|
cursor: pointer;
|
||||||
|
font: inherit;
|
||||||
|
color: var(--f-link, var(--btn-background));
|
||||||
|
text-decoration: underline;
|
||||||
}
|
}
|
||||||
|
|
||||||
.fuz-chsearch__pkgnum {
|
.f-chsearch__pkg:hover {
|
||||||
|
text-decoration-thickness: 2px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.f-chsearch__pkgnum {
|
||||||
@apply opacity-70;
|
@apply opacity-70;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* =========================
|
/* =========================
|
||||||
Empty state
|
Empty state
|
||||||
========================== */
|
========================== */
|
||||||
.fuz-chsearch__empty {
|
.f-chsearch__empty {
|
||||||
@apply mt-2 p-4 rounded-2xl border border-slate-200 dark:border-slate-700 opacity-80;
|
@apply mt-2 p-4 rounded-2xl border border-slate-200 dark:border-slate-700 opacity-80;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.f-chsearch__input::-webkit-search-cancel-button {
|
||||||
|
-webkit-appearance: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
.f-chsearch__input::-ms-clear {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
.f-chsearch__input[type="search"] {
|
||||||
|
appearance: none;
|
||||||
|
}
|
||||||
@@ -2,98 +2,93 @@
|
|||||||
MODAL — FULLSCREEN OVERLAY
|
MODAL — FULLSCREEN OVERLAY
|
||||||
=========================== */
|
=========================== */
|
||||||
|
|
||||||
.fuz-modal-overlay {
|
.f-modal-overlay {
|
||||||
@apply fixed inset-0 z-[9999] flex flex-col;
|
@apply fixed inset-0 z-[9999] flex flex-col;
|
||||||
background: rgba(0, 0, 0, 0.65);
|
background: rgba(0, 0, 0, 0.65);
|
||||||
backdrop-filter: blur(6px);
|
backdrop-filter: blur(6px);
|
||||||
animation: fadeIn 0.25s ease-out forwards;
|
animation: fadeIn 0.25s ease-out forwards;
|
||||||
}
|
}
|
||||||
|
|
||||||
.fuz-modal-close {
|
.f-modal-close {
|
||||||
@apply absolute top-4 right-6 text-3xl font-bold cursor-pointer transition-opacity;
|
@apply absolute top-4 right-6 text-3xl font-bold cursor-pointer transition-opacity;
|
||||||
@apply text-[--f-text] opacity-70;
|
@apply text-[--f-text] opacity-70;
|
||||||
}
|
}
|
||||||
|
|
||||||
.fuz-modal-close:hover {
|
.f-modal-close:hover {
|
||||||
@apply opacity-100;
|
@apply opacity-100;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* panel – pełny ekran, ale treść centrowana max-w */
|
/* panel – pełny ekran, ale treść centrowana max-w */
|
||||||
.fuz-modal-panel {
|
.f-modal-panel {
|
||||||
@apply w-full h-full overflow-y-auto bg-[--f-background] text-[--f-text];
|
@apply w-full h-full overflow-y-auto bg-[--f-background] text-[--f-text];
|
||||||
@apply px-6 py-8 md:px-12 md:py-12;
|
@apply px-6 py-8 md:px-12 md:py-12;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* wersja "kompaktowa" z mniejszym max-width (używana w dodatkach) */
|
/* wersja "kompaktowa" z mniejszym max-width (używana w dodatkach) */
|
||||||
.fuz-modal-panel.fuz-modal-panel--compact {
|
.f-modal-panel.f-modal-panel--compact {
|
||||||
@apply flex justify-center items-start;
|
@apply flex justify-center items-start;
|
||||||
}
|
}
|
||||||
|
|
||||||
.fuz-modal-inner {
|
.f-modal-inner {
|
||||||
@apply w-full max-w-4xl mx-auto;
|
@apply w-full max-w-4xl mx-auto;
|
||||||
}
|
}
|
||||||
|
|
||||||
.fuz-modal-title {
|
.f-modal-title {
|
||||||
@apply text-3xl md:text-4xl font-bold mb-8 text-center text-[--f-text];
|
@apply text-3xl md:text-4xl font-bold mb-8 text-center text-[--f-text];
|
||||||
}
|
}
|
||||||
|
|
||||||
.fuz-modal-content p {
|
.f-modal-content p {
|
||||||
@apply leading-relaxed text-2xl text-center;
|
@apply leading-relaxed text-2xl text-center;
|
||||||
}
|
}
|
||||||
|
|
||||||
.fuz-modal-content p img {
|
.f-modal-content p img {
|
||||||
@apply mt-2;
|
@apply mt-2;
|
||||||
}
|
}
|
||||||
|
|
||||||
@keyframes fadeIn {
|
@keyframes fadeIn {
|
||||||
from {
|
from { opacity: 0; }
|
||||||
opacity: 0;
|
to { opacity: 1; }
|
||||||
}
|
|
||||||
|
|
||||||
to {
|
|
||||||
opacity: 1;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* ===========================
|
/* ===========================
|
||||||
TELEFON — AKORDEON
|
TELEFON — AKORDEON
|
||||||
=========================== */
|
=========================== */
|
||||||
|
|
||||||
.fuz-modal-phone-list.fuz-accordion {
|
.f-modal-phone-list.f-accordion {
|
||||||
@apply flex flex-col gap-2;
|
@apply flex flex-col gap-2;
|
||||||
}
|
}
|
||||||
|
|
||||||
.fuz-accordion-item {
|
.f-accordion-item {
|
||||||
@apply rounded-xl border overflow-hidden bg-[--f-background];
|
@apply rounded-xl border overflow-hidden bg-[--f-background];
|
||||||
border-color: rgba(148, 163, 184, 0.6); /* neutralna szarość — ok w obu motywach */
|
border-color: rgba(148, 163, 184, 0.6);
|
||||||
}
|
}
|
||||||
|
|
||||||
.fuz-accordion-header {
|
.f-accordion-header {
|
||||||
@apply w-full flex items-center justify-between gap-4 px-4 py-2 cursor-pointer;
|
@apply w-full flex items-center justify-between gap-4 px-4 py-2 cursor-pointer;
|
||||||
background: rgba(148, 163, 184, 0.06);
|
background: rgba(148, 163, 184, 0.06);
|
||||||
border: none;
|
border: none;
|
||||||
outline: none;
|
outline: none;
|
||||||
}
|
}
|
||||||
|
|
||||||
.fuz-accordion-header-left {
|
.f-accordion-header-left {
|
||||||
@apply flex items-center gap-1;
|
@apply flex items-center gap-1;
|
||||||
}
|
}
|
||||||
|
|
||||||
.fuz-modal-phone-name {
|
.f-modal-phone-name {
|
||||||
@apply font-medium ml-2;
|
@apply font-medium ml-2;
|
||||||
}
|
}
|
||||||
|
|
||||||
.fuz-modal-phone-price {
|
.f-modal-phone-price {
|
||||||
@apply font-semibold whitespace-nowrap;
|
@apply font-semibold whitespace-nowrap;
|
||||||
}
|
}
|
||||||
|
|
||||||
.fuz-accordion-body {
|
.f-accordion-body {
|
||||||
@apply px-4 pt-2 pb-3;
|
@apply px-4 pt-2 pb-3;
|
||||||
border-top: 1px solid rgba(148, 163, 184, 0.4);
|
border-top: 1px solid rgba(148, 163, 184, 0.4);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* wyróżnienie otwartego pakietu – lekki „accent wash” na tle */
|
/* wyróżnienie otwartego pakietu */
|
||||||
.fuz-accordion-item.is-open .fuz-accordion-header {
|
.f-accordion-item.is-open .f-accordion-header {
|
||||||
background: color-mix(in srgb, var(--fuz-accent, #2563eb) 8%, transparent);
|
background: color-mix(in srgb, var(--fuz-accent, #2563eb) 8%, transparent);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -101,94 +96,96 @@
|
|||||||
DODATKI — KOLUMNOWA LISTA
|
DODATKI — KOLUMNOWA LISTA
|
||||||
=========================== */
|
=========================== */
|
||||||
|
|
||||||
.fuz-addon-list {
|
.f-addon-list {
|
||||||
@apply flex flex-col gap-2;
|
@apply flex flex-col gap-2;
|
||||||
}
|
}
|
||||||
|
|
||||||
.fuz-addon-item {
|
.f-addon-item {
|
||||||
@apply grid items-center gap-3 px-3 py-2 rounded-xl border cursor-pointer;
|
@apply grid items-center gap-3 px-3 py-2 rounded-xl border cursor-pointer;
|
||||||
grid-template-columns: auto 1fr auto; /* [checkbox] [opis] [cena] */
|
grid-template-columns: auto 1fr auto;
|
||||||
border-color: rgba(148, 163, 184, 0.5);
|
border-color: rgba(148, 163, 184, 0.5);
|
||||||
background: var(--f-background);
|
background: var(--f-background);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* kliknięcie w środek też zaznacza checkboxa */
|
.f-addon-item input[type="checkbox"] {
|
||||||
.fuz-addon-item input[type="checkbox"] {
|
|
||||||
@apply cursor-pointer;
|
@apply cursor-pointer;
|
||||||
}
|
}
|
||||||
|
|
||||||
.fuz-addon-checkbox {
|
.f-addon-checkbox {
|
||||||
@apply flex items-center justify-center;
|
@apply flex items-center justify-center;
|
||||||
}
|
}
|
||||||
|
|
||||||
.fuz-addon-main {
|
.f-addon-main {
|
||||||
@apply flex flex-col gap-0.5;
|
@apply flex flex-col gap-0.5;
|
||||||
}
|
}
|
||||||
|
|
||||||
.fuz-addon-name {
|
.f-addon-name {
|
||||||
@apply font-medium;
|
@apply font-medium;
|
||||||
}
|
}
|
||||||
|
|
||||||
.fuz-addon-desc {
|
.f-addon-desc {
|
||||||
@apply text-sm opacity-85;
|
@apply text-sm opacity-85;
|
||||||
}
|
}
|
||||||
|
|
||||||
.fuz-addon-price {
|
.f-addon-price {
|
||||||
@apply font-semibold whitespace-nowrap;
|
@apply font-semibold whitespace-nowrap;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* lekkie podświetlenie przy hover */
|
.f-addon-item:hover {
|
||||||
.fuz-addon-item:hover {
|
border-color: color-mix(
|
||||||
border-color: color-mix(in srgb, var(--fuz-accent, #2563eb) 70%, rgba(148, 163, 184, 0.5) 30%);
|
in srgb,
|
||||||
|
var(--fuz-accent, #2563eb) 70%,
|
||||||
|
rgba(148, 163, 184, 0.5) 30%
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* ===========================
|
/* ===========================
|
||||||
PODSUMOWANIE MIESIĘCZNE
|
PODSUMOWANIE MIESIĘCZNE
|
||||||
=========================== */
|
=========================== */
|
||||||
|
|
||||||
.fuz-summary {
|
.f-summary {
|
||||||
@apply pt-2;
|
@apply pt-2;
|
||||||
}
|
}
|
||||||
|
|
||||||
.fuz-summary-list {
|
.f-summary-list {
|
||||||
@apply flex flex-col gap-1 mt-2 p-4 rounded-xl;
|
@apply flex flex-col gap-1 mt-2 p-4 rounded-xl;
|
||||||
background: rgba(148, 163, 184, 0.07);
|
background: rgba(148, 163, 184, 0.07);
|
||||||
}
|
}
|
||||||
|
|
||||||
.fuz-summary-row,
|
.f-summary-row,
|
||||||
.fuz-summary-total {
|
.f-summary-total {
|
||||||
@apply flex items-center justify-between;
|
@apply flex items-center justify-between;
|
||||||
}
|
}
|
||||||
|
|
||||||
.fuz-summary-row span:last-child {
|
.f-summary-row span:last-child {
|
||||||
@apply font-medium whitespace-nowrap;
|
@apply font-medium whitespace-nowrap;
|
||||||
}
|
}
|
||||||
|
|
||||||
.fuz-summary-total {
|
.f-summary-total {
|
||||||
@apply mt-1 pt-2;
|
@apply mt-1 pt-2;
|
||||||
border-top: 1px solid rgba(148, 163, 184, 0.4);
|
border-top: 1px solid rgba(148, 163, 184, 0.4);
|
||||||
}
|
}
|
||||||
|
|
||||||
.fuz-summary-total span:last-child {
|
.f-summary-total span:last-child {
|
||||||
@apply font-bold;
|
@apply font-bold;
|
||||||
font-size: 1.25rem;
|
font-size: 1.25rem;
|
||||||
color: var(--fuz-accent, #2563eb);
|
color: var(--fuz-accent, #2563eb);
|
||||||
}
|
}
|
||||||
|
|
||||||
.fuz-modal-section {
|
.f-modal-section {
|
||||||
@apply mb-6;
|
@apply mb-6;
|
||||||
}
|
}
|
||||||
|
|
||||||
.fuz-modal-section h3 {
|
.f-modal-section h3 {
|
||||||
@apply text-xl md:text-2xl font-semibold mb-3;
|
@apply text-xl md:text-2xl font-semibold mb-3;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* opcja "bez telefonu" — trochę lżejsze tło */
|
/* opcja "bez telefonu" */
|
||||||
.fuz-accordion-item--no-phone .fuz-accordion-header {
|
.f-accordion-item--no-phone .f-accordion-header {
|
||||||
background: rgba(148, 163, 184, 0.03);
|
background: rgba(148, 163, 184, 0.03);
|
||||||
}
|
}
|
||||||
|
|
||||||
.fuz-accordion-header-left input[type="radio"] {
|
.f-accordion-header-left input[type="radio"] {
|
||||||
width: 1.05rem;
|
width: 1.05rem;
|
||||||
height: 1.05rem;
|
height: 1.05rem;
|
||||||
transform: scale(1.05);
|
transform: scale(1.05);
|
||||||
@@ -196,7 +193,7 @@
|
|||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
}
|
}
|
||||||
|
|
||||||
.fuz-addon-checkbox input[type="checkbox"] {
|
.f-addon-checkbox input[type="checkbox"] {
|
||||||
width: 1.05rem;
|
width: 1.05rem;
|
||||||
height: 1.05rem;
|
height: 1.05rem;
|
||||||
transform: scale(1.05);
|
transform: scale(1.05);
|
||||||
@@ -204,10 +201,7 @@
|
|||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
}
|
}
|
||||||
|
|
||||||
.fuz-accordion-header-left {
|
.f-accordion-header-left,
|
||||||
align-items: center;
|
.f-addon-checkbox {
|
||||||
}
|
|
||||||
|
|
||||||
.fuz-addon-checkbox {
|
|
||||||
align-items: center;
|
align-items: center;
|
||||||
}
|
}
|
||||||
@@ -331,16 +331,3 @@ obszar ze scrollem wewnątrz modala
|
|||||||
outline-offset: 4px;
|
outline-offset: 4px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.fuz-chsearch__pkg {
|
|
||||||
background: transparent;
|
|
||||||
border: 0;
|
|
||||||
padding: 0;
|
|
||||||
cursor: pointer;
|
|
||||||
font: inherit;
|
|
||||||
color: var(--f-link, var(--f-link));
|
|
||||||
text-decoration: underline;
|
|
||||||
}
|
|
||||||
|
|
||||||
.fuz-chsearch__pkg:hover {
|
|
||||||
text-decoration-thickness: 2px;
|
|
||||||
}
|
|
||||||
Reference in New Issue
Block a user