Przebudowa stron na indywidualne karty , pobierane z bazy danych

This commit is contained in:
dm
2025-12-11 15:25:00 +01:00
parent 49c5beb362
commit 0cf7c45131
27 changed files with 1133 additions and 420 deletions

View File

@@ -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}