Poprawki w switcherach i internet Card
This commit is contained in:
Binary file not shown.
@@ -1,9 +1,8 @@
|
|||||||
import { useEffect, useState } from "preact/hooks";
|
import { useEffect, useState } from "preact/hooks";
|
||||||
|
import InternetAddonsModal from "./InternetAddonsModal.jsx";
|
||||||
import "../../styles/offers/offers-table.css";
|
import "../../styles/offers/offers-table.css";
|
||||||
import InternetAddonsModal from "./InternetAddonsModal.jsx"; // 🔹 dostosuj ścieżkę, jeśli inna
|
|
||||||
|
|
||||||
export default function InternetDbOffersCards({
|
export default function InternetDbOffersCards({
|
||||||
title = "Oferty Internetu FUZ",
|
|
||||||
}) {
|
}) {
|
||||||
const [selected, setSelected] = useState({});
|
const [selected, setSelected] = useState({});
|
||||||
const [labels, setLabels] = useState({});
|
const [labels, setLabels] = useState({});
|
||||||
@@ -11,12 +10,16 @@ export default function InternetDbOffersCards({
|
|||||||
const [loading, setLoading] = useState(false);
|
const [loading, setLoading] = useState(false);
|
||||||
const [error, setError] = useState("");
|
const [error, setError] = useState("");
|
||||||
|
|
||||||
// 🔹 stan modala z dodatkami
|
|
||||||
const [addonsModalOpen, setAddonsModalOpen] = useState(false);
|
const [addonsModalOpen, setAddonsModalOpen] = useState(false);
|
||||||
const [activePlan, setActivePlan] = useState(null);
|
const [activePlan, setActivePlan] = useState(null);
|
||||||
|
|
||||||
// nasłuchuj globalnego eventu z OffersSwitches
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
|
if (typeof window !== "undefined" && window.fuzSwitchState) {
|
||||||
|
const { selected: sel, labels: labs } = window.fuzSwitchState;
|
||||||
|
if (sel) setSelected(sel);
|
||||||
|
if (labs) setLabels(labs);
|
||||||
|
}
|
||||||
|
|
||||||
function handler(e) {
|
function handler(e) {
|
||||||
const detail = e.detail || {};
|
const detail = e.detail || {};
|
||||||
if (detail.selected) {
|
if (detail.selected) {
|
||||||
@@ -31,6 +34,7 @@ export default function InternetDbOffersCards({
|
|||||||
return () => window.removeEventListener("fuz:switch-change", handler);
|
return () => window.removeEventListener("fuz:switch-change", handler);
|
||||||
}, []);
|
}, []);
|
||||||
|
|
||||||
|
|
||||||
const buildingCode = Number(selected.budynek) || 1;
|
const buildingCode = Number(selected.budynek) || 1;
|
||||||
const contractCode = Number(selected.umowa) || 1;
|
const contractCode = Number(selected.umowa) || 1;
|
||||||
|
|
||||||
@@ -94,7 +98,6 @@ export default function InternetDbOffersCards({
|
|||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
|
|
||||||
{/* 🔹 Modal z usługami dodatkowymi (internet + telefon + addon’y) */}
|
|
||||||
<InternetAddonsModal
|
<InternetAddonsModal
|
||||||
isOpen={addonsModalOpen}
|
isOpen={addonsModalOpen}
|
||||||
onClose={() => setAddonsModalOpen(false)}
|
onClose={() => setAddonsModalOpen(false)}
|
||||||
@@ -108,32 +111,24 @@ function OfferCard({ plan, contractLabel, onConfigureAddons }) {
|
|||||||
const basePrice = plan.price_monthly;
|
const basePrice = plan.price_monthly;
|
||||||
const installPrice = plan.price_installation;
|
const installPrice = plan.price_installation;
|
||||||
|
|
||||||
const allFeatures = plan.features || [];
|
const featureRows = plan.features || [];
|
||||||
|
|
||||||
// 🔹 to są inne cechy (bez umowy i instalacji)
|
const effectiveContract = contractLabel || "—";
|
||||||
const featureRows = allFeatures.filter(
|
|
||||||
(f) => f.id !== "umowa_info" && f.id !== "instalacja"
|
|
||||||
);
|
|
||||||
|
|
||||||
// 🔹 cecha opisująca umowę (z backendu)
|
|
||||||
const contractFeature = allFeatures.find((f) => f.id === "umowa_info");
|
|
||||||
|
|
||||||
// 🔹 tekst, który faktycznie pokażemy w wierszu "Umowa"
|
|
||||||
const effectiveContract =
|
|
||||||
contractLabel || contractFeature?.value || contractFeature?.label || "—";
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div class={`f-card ${plan.popular ? "f-card-popular" : ""}`}>
|
<div class={`f-card ${plan.popular ? "f-card-popular" : ""}`}>
|
||||||
<div class="f-card-header">
|
<div class="f-card-header">
|
||||||
<div class="f-card-name">{plan.name}</div>
|
<div class="f-card-name">{plan.name}</div>
|
||||||
<div class="f-card-price">{basePrice} zł/mies.</div>
|
<div class="f-card-price">
|
||||||
|
{basePrice != null ? `${basePrice} zł/mies.` : "—"}
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<ul class="f-card-features">
|
<ul class="f-card-features">
|
||||||
{featureRows.map((f) => {
|
{featureRows.map((f) => {
|
||||||
let val = f.value;
|
let val = f.value;
|
||||||
|
|
||||||
let display;
|
let display;
|
||||||
|
|
||||||
if (val === true || val === "true") display = "✓";
|
if (val === true || val === "true") display = "✓";
|
||||||
else if (val === false || val === "false" || val == null) display = "✕";
|
else if (val === false || val === "false" || val == null) display = "✕";
|
||||||
else display = val;
|
else display = val;
|
||||||
@@ -146,11 +141,13 @@ function OfferCard({ plan, contractLabel, onConfigureAddons }) {
|
|||||||
);
|
);
|
||||||
})}
|
})}
|
||||||
|
|
||||||
|
{/* Umowa – już tylko z przełącznika */}
|
||||||
<li class="f-card-row">
|
<li class="f-card-row">
|
||||||
<span class="f-card-label">Umowa</span>
|
<span class="f-card-label">Umowa</span>
|
||||||
<span class="f-card-value">{effectiveContract}</span>
|
<span class="f-card-value">{effectiveContract}</span>
|
||||||
</li>
|
</li>
|
||||||
|
|
||||||
|
{/* Aktywacja – z pola plan.price_installation */}
|
||||||
<li class="f-card-row">
|
<li class="f-card-row">
|
||||||
<span class="f-card-label">Aktywacja</span>
|
<span class="f-card-label">Aktywacja</span>
|
||||||
<span class="f-card-value">
|
<span class="f-card-value">
|
||||||
|
|||||||
@@ -1,5 +1,4 @@
|
|||||||
import { useEffect, useState } from "preact/hooks";
|
import { useEffect, useState } from "preact/hooks";
|
||||||
// import "../../styles/offers/offers-switches.css";
|
|
||||||
|
|
||||||
function buildLabels(switches, selected) {
|
function buildLabels(switches, selected) {
|
||||||
const out = {};
|
const out = {};
|
||||||
@@ -24,7 +23,7 @@ export default function OffersSwitches(props) {
|
|||||||
const [loading, setLoading] = useState(false);
|
const [loading, setLoading] = useState(false);
|
||||||
const [error, setError] = useState("");
|
const [error, setError] = useState("");
|
||||||
|
|
||||||
// AUTO: pobieramy konfigurację z API
|
// 🔹 AUTO mode – sam pobieram /api/switches + wysyłam event
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (isControlled) return;
|
if (isControlled) return;
|
||||||
|
|
||||||
@@ -35,7 +34,7 @@ export default function OffersSwitches(props) {
|
|||||||
setError("");
|
setError("");
|
||||||
|
|
||||||
try {
|
try {
|
||||||
const res = await fetch("/api/internet");
|
const res = await fetch("/api/switches");
|
||||||
if (!res.ok) throw new Error(`HTTP ${res.status}`);
|
if (!res.ok) throw new Error(`HTTP ${res.status}`);
|
||||||
|
|
||||||
const json = await res.json();
|
const json = await res.json();
|
||||||
@@ -53,18 +52,24 @@ export default function OffersSwitches(props) {
|
|||||||
setAutoSwitches(sws);
|
setAutoSwitches(sws);
|
||||||
setAutoSelected(initial);
|
setAutoSelected(initial);
|
||||||
|
|
||||||
|
// 🔥 zapisz globalny stan
|
||||||
|
window.fuzSwitchState = {
|
||||||
|
selected: initial,
|
||||||
|
labels,
|
||||||
|
};
|
||||||
|
|
||||||
window.dispatchEvent(
|
window.dispatchEvent(
|
||||||
new CustomEvent("fuz:switch-change", {
|
new CustomEvent("fuz:switch-change", {
|
||||||
detail: {
|
detail: {
|
||||||
id: null,
|
id: null,
|
||||||
value: null,
|
value: null,
|
||||||
selected: initial,
|
selected: initial,
|
||||||
labels, // tu lecą etykiety z DB
|
labels,
|
||||||
},
|
},
|
||||||
}),
|
}),
|
||||||
);
|
);
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
console.error("❌ Błąd pobierania switchy:", err);
|
console.error("Błąd pobierania switchy:", err);
|
||||||
if (!cancelled) setError("Nie udało się załadować przełączników.");
|
if (!cancelled) setError("Nie udało się załadować przełączników.");
|
||||||
} finally {
|
} finally {
|
||||||
if (!cancelled) setLoading(false);
|
if (!cancelled) setLoading(false);
|
||||||
@@ -88,13 +93,19 @@ export default function OffersSwitches(props) {
|
|||||||
const next = { ...prev, [id]: value };
|
const next = { ...prev, [id]: value };
|
||||||
const labels = buildLabels(autoSwitches, next);
|
const labels = buildLabels(autoSwitches, next);
|
||||||
|
|
||||||
|
// 🔥 aktualizuj globalny stan
|
||||||
|
window.fuzSwitchState = {
|
||||||
|
selected: next,
|
||||||
|
labels,
|
||||||
|
};
|
||||||
|
|
||||||
window.dispatchEvent(
|
window.dispatchEvent(
|
||||||
new CustomEvent("fuz:switch-change", {
|
new CustomEvent("fuz:switch-change", {
|
||||||
detail: {
|
detail: {
|
||||||
id,
|
id,
|
||||||
value,
|
value,
|
||||||
selected: next,
|
selected: next,
|
||||||
labels, // etykiety po kliknięciu
|
labels,
|
||||||
},
|
},
|
||||||
}),
|
}),
|
||||||
);
|
);
|
||||||
@@ -104,6 +115,32 @@ export default function OffersSwitches(props) {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// 🔥 CONTROLLED: zsynchronizuj globalny stan + event
|
||||||
|
useEffect(() => {
|
||||||
|
if (!isControlled) return;
|
||||||
|
if (!Array.isArray(switches) || !switches.length) return;
|
||||||
|
|
||||||
|
const safeSelected = selected || {};
|
||||||
|
const labels = buildLabels(switches, safeSelected);
|
||||||
|
|
||||||
|
// 🔥 globalny stan
|
||||||
|
window.fuzSwitchState = {
|
||||||
|
selected: safeSelected,
|
||||||
|
labels,
|
||||||
|
};
|
||||||
|
|
||||||
|
window.dispatchEvent(
|
||||||
|
new CustomEvent("fuz:switch-change", {
|
||||||
|
detail: {
|
||||||
|
id: null,
|
||||||
|
value: null,
|
||||||
|
selected: safeSelected,
|
||||||
|
labels,
|
||||||
|
},
|
||||||
|
}),
|
||||||
|
);
|
||||||
|
}, [isControlled, switches, selected]);
|
||||||
|
|
||||||
if (!isControlled && loading) {
|
if (!isControlled && loading) {
|
||||||
return (
|
return (
|
||||||
<div class="f-switches-wrapper">
|
<div class="f-switches-wrapper">
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
// src/pages/api/switches/internet.js
|
// src/pages/api/switches.js
|
||||||
import Database from "better-sqlite3";
|
import Database from "better-sqlite3";
|
||||||
|
|
||||||
const DB_PATH =
|
const DB_PATH =
|
||||||
@@ -13,13 +13,11 @@ export function GET() {
|
|||||||
|
|
||||||
try {
|
try {
|
||||||
const buildingTypes = db
|
const buildingTypes = db
|
||||||
.prepare("SELECT code, label FROM jambox_building_types ORDER BY code")
|
.prepare("SELECT code, label FROM jambox_building_types ORDER BY is_default DESC, code")
|
||||||
.all();
|
.all();
|
||||||
|
|
||||||
const contractTypes = db
|
const contractTypes = db
|
||||||
.prepare(
|
.prepare("SELECT code, label FROM jambox_contract_types ORDER BY is_default DESC, code")
|
||||||
"SELECT code, label FROM jambox_contract_types ORDER BY code"
|
|
||||||
)
|
|
||||||
.all();
|
.all();
|
||||||
|
|
||||||
const switches = [
|
const switches = [
|
||||||
@@ -29,7 +27,7 @@ export function GET() {
|
|||||||
domyslny: buildingTypes[0]?.code ?? 1,
|
domyslny: buildingTypes[0]?.code ?? 1,
|
||||||
title: "Zmień rodzaj budynku by zobaczyć odpowiednie ceny",
|
title: "Zmień rodzaj budynku by zobaczyć odpowiednie ceny",
|
||||||
opcje: buildingTypes.map((b) => ({
|
opcje: buildingTypes.map((b) => ({
|
||||||
id: b.code, // 1,2,...
|
id: b.code,
|
||||||
nazwa: b.label,
|
nazwa: b.label,
|
||||||
})),
|
})),
|
||||||
},
|
},
|
||||||
@@ -39,7 +37,7 @@ export function GET() {
|
|||||||
domyslny: contractTypes[0]?.code ?? 1,
|
domyslny: contractTypes[0]?.code ?? 1,
|
||||||
title: "Wybierz okres umowy by zobaczyć odpowiednie ceny",
|
title: "Wybierz okres umowy by zobaczyć odpowiednie ceny",
|
||||||
opcje: contractTypes.map((c) => ({
|
opcje: contractTypes.map((c) => ({
|
||||||
id: c.code, // 1,2,...
|
id: c.code,
|
||||||
nazwa: c.label,
|
nazwa: c.label,
|
||||||
})),
|
})),
|
||||||
},
|
},
|
||||||
@@ -56,7 +54,7 @@ export function GET() {
|
|||||||
}
|
}
|
||||||
);
|
);
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
console.error("❌ Błąd w /api/switches/internet:", err);
|
console.error("Błąd w /api/switches:", err);
|
||||||
return new Response(
|
return new Response(
|
||||||
JSON.stringify({ ok: false, error: err.message || "DB_ERROR" }),
|
JSON.stringify({ ok: false, error: err.message || "DB_ERROR" }),
|
||||||
{
|
{
|
||||||
Reference in New Issue
Block a user