Przebudowa stron na indywidualne karty , pobierane z bazy danych
This commit is contained in:
@@ -1,19 +1,141 @@
|
||||
import { useEffect, useState } from "preact/hooks";
|
||||
// import "../../styles/offers/offers-switches.css";
|
||||
|
||||
export default function OffersSwitches({ switches, selected, onSwitch }) {
|
||||
if (!switches.length) return null;
|
||||
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">
|
||||
{switches.map((sw) => (
|
||||
{effectiveSwitches.map((sw) => (
|
||||
<div class="f-switch-box">
|
||||
<div class="f-switch-group">
|
||||
{sw.opcje.map((op) => (
|
||||
<button
|
||||
type="button"
|
||||
class={`f-switch ${selected[sw.id] === op.id ? "active" : ""
|
||||
}`}
|
||||
onClick={() => onSwitch(sw.id, op.id)}
|
||||
class={`f-switch ${
|
||||
String(effectiveSelected[sw.id]) === String(op.id)
|
||||
? "active"
|
||||
: ""
|
||||
}`}
|
||||
onClick={() => handleClick(sw.id, op.id)}
|
||||
title={sw.title}
|
||||
>
|
||||
{op.nazwa}
|
||||
|
||||
Reference in New Issue
Block a user