Files
simple-cost-dashboard/frontend/static/common.js
T
2026-08-07 17:19:49 +02:00

97 lines
2.7 KiB
JavaScript

// common.js — petits utilitaires partagés entre app.js (page globale)
// et tenant.js (page détail tenant).
const eurFormatter = new Intl.NumberFormat("fr-FR", {
style: "currency",
currency: "EUR",
maximumFractionDigits: 2,
});
function formatEUR(amount) {
if (amount === null || amount === undefined) return "—";
return eurFormatter.format(amount);
}
function formatPct(value) {
if (value === null || value === undefined) return null;
const sign = value > 0 ? "+" : "";
return `${sign}${value.toFixed(1)} %`;
}
function deltaClass(value) {
if (value === null || value === undefined) return "flat";
if (value > 0.5) return "up";
if (value < -0.5) return "down";
return "flat";
}
function deltaArrow(value) {
if (value === null || value === undefined) return "";
if (value > 0.5) return "↑";
if (value < -0.5) return "↓";
return "→";
}
function monthLabel(monthKey) {
const [y, m] = monthKey.split("-").map(Number);
const d = new Date(Date.UTC(y, m - 1, 1));
return new Intl.DateTimeFormat("fr-FR", { month: "short", year: "2-digit", timeZone: "UTC" }).format(d);
}
function dayLabel(isoDate) {
const d = new Date(`${isoDate}T00:00:00Z`);
return new Intl.DateTimeFormat("fr-FR", { day: "2-digit", month: "short", timeZone: "UTC" }).format(d);
}
function providerLabel(provider) {
return provider === "aws" ? "AWS" : provider === "azure" ? "Azure" : provider;
}
function escapeHtml(str) {
return String(str)
.replace(/&/g, "&amp;")
.replace(/</g, "&lt;")
.replace(/>/g, "&gt;")
.replace(/"/g, "&quot;");
}
function cssVar(name) {
return getComputedStyle(document.documentElement).getPropertyValue(name).trim();
}
// Config partagée des axes/grilles Chart.js (gridlines discrètes, pas de
// deuxième axe, tooltip alignée sur le design system).
function chartBaseOptions() {
return {
responsive: true,
maintainAspectRatio: false,
interaction: { mode: "index", intersect: false },
plugins: {
legend: { display: false },
tooltip: {
backgroundColor: cssVar("--surface-1"),
titleColor: cssVar("--text-primary"),
bodyColor: cssVar("--text-secondary"),
borderColor: cssVar("--border"),
borderWidth: 1,
padding: 10,
displayColors: true,
boxPadding: 4,
},
},
scales: {
x: {
grid: { display: false },
border: { color: cssVar("--axis") },
ticks: { color: cssVar("--text-muted"), font: { size: 11 } },
},
y: {
beginAtZero: true,
grid: { color: cssVar("--gridline") },
border: { display: false },
ticks: { color: cssVar("--text-muted"), font: { size: 11 } },
},
},
};
}