Formatowanie cen

This commit is contained in:
dm
2025-12-19 08:13:59 +01:00
parent 2920dc7c08
commit 97668743b2
6 changed files with 47 additions and 64 deletions

View File

@@ -3,8 +3,6 @@ opis: |
Wybierz rodzaj budynku i czas trwania umowy
cena_opis: "zł/mies."
grupy:
- id: "EVIO"
nazwa: "Evio"

View File

@@ -16,7 +16,12 @@ grupy:
canal_plus:
tytul: CANAL+
rejestracja:
opis: Aby skorzystać z Platformy należy się zarejestrować
opis: |
Platforma CANAL+ jest dostępna za pośrednictwem strony internetowej, podłączonych telewizorów, aplikacji na smartfony i tablety, konsol do gier i urządzeń takich jak Apple TV i Google Chromecast.
Wszystkie obsługiwane urządzenia opisane są na stronie: canalplus.com
Aby skorzystać z Platformy należy się zarejestrować
label: Rejestracja CANAL+
href: "https://jambox.pl/cplus-rejestracja"
title: "Rejestracja w usłudze streamingowej"
@@ -63,9 +68,6 @@ dodatki:
opis: |
Pakiet sportowy Canal+ oraz dostęp do platformy streamingowej Canal+
Platforma CANAL+ jest dostępna za pośrednictwem strony internetowej, podłączonych telewizorów, aplikacji na smartfony i tablety, konsol do gier i urządzeń takich jak Apple TV i Google Chromecast.
Wszystkie obsługiwane urządzenia opisane są na stronie: canalplus.com
cena:
- pakiety:
- Smart

View File

@@ -4,21 +4,10 @@ import OffersSwitches from "../Switches.jsx";
import InternetAddonsModal from "./InternetAddonsModal.jsx";
import "../../styles/cards.css";
function formatMoney(amount, currency = "PLN") {
if (typeof amount !== "number" || Number.isNaN(amount)) return "";
try {
return new Intl.NumberFormat("pl-PL", {
style: "",
currency,
maximumFractionDigits: 0,
}).format(amount);
} catch {
return String(amount);
}
}
import { moneyWithLabel, money } from "../../lib/money.js";
// ✅ mapper: InternetCard(YAML) + match + labels -> plan (dla modala)
function mapCardToPlan(card, match, labels, waluta) {
function mapCardToPlan(card, match, labels, cenaOpis) {
const baseParams = Array.isArray(card?.parametry) ? card.parametry : [];
const features = baseParams.map((p) => ({
@@ -30,8 +19,7 @@ function mapCardToPlan(card, match, labels, waluta) {
features.push({ label: "Umowa", value: labels?.umowa || "—" });
features.push({
label: "Aktywacja",
value:
typeof match?.aktywacja === "number" ? formatMoney(match.aktywacja, waluta) : "—",
value: typeof match?.aktywacja === "number" ? `${money(match.aktywacja)}` : "—",
});
return {
@@ -39,6 +27,7 @@ function mapCardToPlan(card, match, labels, waluta) {
price_monthly: typeof match?.miesiecznie === "number" ? match.miesiecznie : 0,
price_installation: typeof match?.aktywacja === "number" ? match.aktywacja : 0,
features,
cenaOpis,
};
}
@@ -52,23 +41,23 @@ function mapCardToPlan(card, match, labels, waluta) {
* phoneCards?: any[],
* addons?: any[],
* addonsCenaOpis?: string,
* switches?: any[] // ✅ NOWE: przełączniki z YAML
* switches?: any[]
* }} props
*/
export default function InternetCards({
title = "",
description = "",
cards = [],
waluta = "PLN",
waluta = "PLN", // zostawiamy, bo może się przydać dalej (np. w modalu), ale tu nie jest używana
cenaOpis = "zł/mies.",
phoneCards = [],
addons = [],
addonsCenaOpis = "zł/mies.",
switches = [], // ✅ NOWE
switches = [],
}) {
const visibleCards = Array.isArray(cards) ? cards : [];
// switch state (teraz idzie z OffersSwitches na podstawie YAML)
// switch state (idzie z OffersSwitches na podstawie YAML)
const [selected, setSelected] = useState({});
const [labels, setLabels] = useState({});
@@ -103,7 +92,6 @@ export default function InternetCards({
</div>
)}
{/* ✅ TERAZ switcher dostaje dane z YAML */}
<OffersSwitches switches={switches} />
{visibleCards.length === 0 ? (
@@ -116,7 +104,6 @@ export default function InternetCards({
card={card}
selected={selected}
labels={labels}
waluta={waluta}
cenaOpis={cenaOpis}
onConfigureAddons={(plan) => {
setActivePlan(plan);
@@ -139,7 +126,7 @@ export default function InternetCards({
);
}
function OfferCard({ card, selected, labels, waluta, cenaOpis, onConfigureAddons }) {
function OfferCard({ card, selected, labels, cenaOpis, onConfigureAddons }) {
const baseParams = Array.isArray(card?.parametry) ? card.parametry : [];
const ceny = Array.isArray(card?.ceny) ? card.ceny : [];
@@ -160,7 +147,7 @@ function OfferCard({ card, selected, labels, waluta, cenaOpis, onConfigureAddons
{
klucz: "aktywacja",
label: "Aktywacja",
value: typeof akt === "number" ? formatMoney(akt, waluta) : "—",
value: typeof akt === "number" ? `${money(akt)}` : "—",
},
];
@@ -175,9 +162,7 @@ function OfferCard({ card, selected, labels, waluta, cenaOpis, onConfigureAddons
<div class="f-card-price">
{typeof mies === "number" ? (
<>
{formatMoney(mies, waluta)} <span class="opacity-80">{cenaOpis}</span>
</>
<>{moneyWithLabel(mies, cenaOpis, false)}</>
) : (
<span class="opacity-70">Wybierz opcje</span>
)}
@@ -198,7 +183,7 @@ function OfferCard({ card, selected, labels, waluta, cenaOpis, onConfigureAddons
class="btn btn-primary mt-4"
disabled={!canConfigureAddons}
onClick={() => {
const plan = mapCardToPlan(card, match, labels, waluta);
const plan = mapCardToPlan(card, match, labels, cenaOpis);
onConfigureAddons(plan);
}}
title={!canConfigureAddons ? "Wybierz typ budynku i umowę" : ""}

View File

@@ -6,18 +6,7 @@ import JamboxChannelsModal from "./JamboxChannelsModal.jsx";
import JamboxAddonsModal from "./JamboxAddonsModal.jsx";
import Markdown from "../Markdown.jsx";
function formatMoney(amount, currency = "PLN") {
if (typeof amount !== "number" || Number.isNaN(amount)) return "";
try {
return new Intl.NumberFormat("pl-PL", {
style: "currency",
currency,
maximumFractionDigits: 0,
}).format(amount);
} catch {
return String(amount);
}
}
import { moneyWithLabel, money } from "../../lib/money.js";
function toFeatureRows(params) {
const list = Array.isArray(params) ? params : [];
@@ -52,7 +41,6 @@ function toFeatureRows(params) {
* decoders?: Decoder[],
* addonsCenaOpis?: string,
* channels?: ChannelYaml[],
* channels?: ChannelYaml[]
* }} props
*/
export default function JamboxCards({
@@ -60,7 +48,7 @@ export default function JamboxCards({
description = "",
cards = [],
internetWspolne = [],
waluta = "PLN",
waluta = "PLN", // zostawiamy (może być potrzebne w modalach), ale tu nie jest używane do formatowania
cenaOpis = "zł/mies.",
phoneCards = [],
@@ -122,7 +110,6 @@ export default function JamboxCards({
wsp={wsp}
selected={selected}
labels={labels}
waluta={waluta}
cenaOpis={cenaOpis}
onShowChannels={(pkg) => {
setActivePkg(pkg);
@@ -163,7 +150,6 @@ function JamboxPackageCard({
wsp,
selected,
labels,
waluta,
cenaOpis,
onShowChannels,
onConfigureAddons,
@@ -186,7 +172,7 @@ function JamboxPackageCard({
{
klucz: "aktywacja",
label: "Aktywacja",
value: typeof installPrice === "number" ? formatMoney(installPrice, waluta) : "—",
value: typeof installPrice === "number" ? `${money(installPrice)}` : "—",
},
];
@@ -206,15 +192,13 @@ function JamboxPackageCard({
const hasPrice = typeof basePrice === "number";
return (
<div class="f-card" id={`pkg-${card?.nazwa}`} data-pkg={card?.nazwa} >
<div class="f-card" id={`pkg-${card?.nazwa}`} data-pkg={card?.nazwa}>
<div class="f-card-header">
<div class="f-card-name">{card.nazwa}</div>
<div class="f-card-price">
{hasPrice ? (
<>
{formatMoney(basePrice, waluta)} <span class="opacity-80">{cenaOpis}</span>
</>
<>{moneyWithLabel(basePrice, cenaOpis, false)}</>
) : (
<span class="opacity-70">Wybierz opcje</span>
)}

View File

@@ -1,4 +1,5 @@
import Markdown from "../../islands/Markdown.jsx";
import { moneyWithLabel } from "../../lib/money.js";
import "../../styles/cards.css";
/**
@@ -25,9 +26,13 @@ export default function PhoneDbOffersCards({
return (
<section class="f-offers">
{title && <h2 class="f-section-header">{title}</h2>}
<div>
<Markdown text={description} />
</div>
{description && (
<div class="mb-4">
<Markdown text={description} />
</div>
)}
{visibleCards.length === 0 ? (
<p class="opacity-80">Brak dostępnych pakietów.</p>
) : (
@@ -42,8 +47,8 @@ export default function PhoneDbOffersCards({
}
function PhoneOfferCard({ card }) {
const price = card?.cena?.wartosc ?? "";
const priceDesc = card?.cena?.opis ?? "zł/mies.";
const priceValue = card?.cena?.wartosc;
const priceLabel = card?.cena?.opis || "zł/mies.";
const params = Array.isArray(card?.parametry) ? card.parametry : [];
@@ -53,8 +58,11 @@ function PhoneOfferCard({ card }) {
<div class="f-card-header">
<div class="f-card-name">{card.nazwa}</div>
<div class="f-card-price">
{price} {priceDesc}
{typeof priceValue === "number"
? moneyWithLabel(priceValue, priceLabel, false)
: "—"}
</div>
</div>

View File

@@ -1,8 +1,14 @@
export function money(amount) {
export function money(amount, decimals = true) {
const n = Number(amount || 0);
return n.toFixed(2).replace(".", ",");
if (decimals)
return n.toFixed(2).replace(".", ",");
return n;
}
export function moneyWithLabel(v, cenaOpis) {
return `${money(v)} ${cenaOpis}`;
export function moneyWithLabel(v, cenaOpis, decimals = true) {
return `${money(v, decimals)} ${cenaOpis}`;
}
export function moneyPLN(v, decimals = true) {
return `${money(v, decimals)}`;
}