150 lines
3.8 KiB
JavaScript
150 lines
3.8 KiB
JavaScript
import { useEffect, useState } from "preact/hooks";
|
|
// import "../../styles/offers/offers-switches.css";
|
|
|
|
function buildLabels(switches, selected) {
|
|
const out = {};
|
|
for (const sw of switches || []) {
|
|
const currentId = selected[sw.id];
|
|
const opt = sw.opcje?.find((op) => String(op.id) === String(currentId));
|
|
if (opt) out[sw.id] = opt.nazwa;
|
|
}
|
|
return out;
|
|
}
|
|
|
|
export default function OffersSwitches(props) {
|
|
const { switches, selected, onSwitch } = props || {};
|
|
|
|
const isControlled =
|
|
Array.isArray(switches) &&
|
|
switches.length > 0 &&
|
|
typeof onSwitch === "function";
|
|
|
|
const [autoSwitches, setAutoSwitches] = useState([]);
|
|
const [autoSelected, setAutoSelected] = useState({});
|
|
const [loading, setLoading] = useState(false);
|
|
const [error, setError] = useState("");
|
|
|
|
// AUTO: pobieramy konfigurację z API
|
|
useEffect(() => {
|
|
if (isControlled) return;
|
|
|
|
let cancelled = false;
|
|
|
|
async function load() {
|
|
setLoading(true);
|
|
setError("");
|
|
|
|
try {
|
|
const res = await fetch("/api/internet");
|
|
if (!res.ok) throw new Error(`HTTP ${res.status}`);
|
|
|
|
const json = await res.json();
|
|
const sws = Array.isArray(json.data) ? json.data : [];
|
|
if (cancelled) return;
|
|
|
|
const initial = {};
|
|
for (const sw of sws) {
|
|
if (sw.domyslny != null) initial[sw.id] = sw.domyslny;
|
|
else if (sw.opcje?.length) initial[sw.id] = sw.opcje[0].id;
|
|
}
|
|
|
|
const labels = buildLabels(sws, initial);
|
|
|
|
setAutoSwitches(sws);
|
|
setAutoSelected(initial);
|
|
|
|
window.dispatchEvent(
|
|
new CustomEvent("fuz:switch-change", {
|
|
detail: {
|
|
id: null,
|
|
value: null,
|
|
selected: initial,
|
|
labels, // tu lecą etykiety z DB
|
|
},
|
|
}),
|
|
);
|
|
} catch (err) {
|
|
console.error("❌ Błąd pobierania switchy:", err);
|
|
if (!cancelled) setError("Nie udało się załadować przełączników.");
|
|
} finally {
|
|
if (!cancelled) setLoading(false);
|
|
}
|
|
}
|
|
|
|
load();
|
|
return () => {
|
|
cancelled = true;
|
|
};
|
|
}, [isControlled]);
|
|
|
|
const effectiveSwitches = isControlled ? switches : autoSwitches;
|
|
const effectiveSelected = isControlled ? selected || {} : autoSelected;
|
|
|
|
const handleClick = (id, value) => {
|
|
if (isControlled) {
|
|
onSwitch(id, value);
|
|
} else {
|
|
setAutoSelected((prev) => {
|
|
const next = { ...prev, [id]: value };
|
|
const labels = buildLabels(autoSwitches, next);
|
|
|
|
window.dispatchEvent(
|
|
new CustomEvent("fuz:switch-change", {
|
|
detail: {
|
|
id,
|
|
value,
|
|
selected: next,
|
|
labels, // etykiety po kliknięciu
|
|
},
|
|
}),
|
|
);
|
|
|
|
return next;
|
|
});
|
|
}
|
|
};
|
|
|
|
if (!isControlled && loading) {
|
|
return (
|
|
<div class="f-switches-wrapper">
|
|
<p>Ładowanie opcji przełączników...</p>
|
|
</div>
|
|
);
|
|
}
|
|
|
|
if (!isControlled && error) {
|
|
return (
|
|
<div class="f-switches-wrapper">
|
|
<p class="text-red-600">{error}</p>
|
|
</div>
|
|
);
|
|
}
|
|
|
|
if (!effectiveSwitches.length) return null;
|
|
|
|
return (
|
|
<div class="f-switches-wrapper">
|
|
{effectiveSwitches.map((sw) => (
|
|
<div class="f-switch-box">
|
|
<div class="f-switch-group">
|
|
{sw.opcje.map((op) => (
|
|
<button
|
|
type="button"
|
|
class={`f-switch ${
|
|
String(effectiveSelected[sw.id]) === String(op.id)
|
|
? "active"
|
|
: ""
|
|
}`}
|
|
onClick={() => handleClick(sw.id, op.id)}
|
|
title={sw.title}
|
|
>
|
|
{op.nazwa}
|
|
</button>
|
|
))}
|
|
</div>
|
|
</div>
|
|
))}
|
|
</div>
|
|
);
|
|
}
|