style: update Ads tab number formatting to match Weekly Sales

- Use de-DE locale (dots for thousands, commas for decimals)
- Round Sales and Spend to integers
- Fix growth calculation to handle locale-specific formatting
This commit is contained in:
Christian Vidal Wolf
2026-01-22 14:21:14 +01:00
parent f774bb47a7
commit 3ffcd9be44
+16 -8
View File
@@ -157,13 +157,13 @@ const AdsPerformance: React.FC<AdsPerformanceProps> = ({ data, filters }) => {
};
const formatCurrency = (val: number) =>
new Intl.NumberFormat('en-US', { style: 'currency', currency: 'USD', maximumFractionDigits: 0 }).format(val);
`$${Math.round(val).toLocaleString('de-DE')}`;
const formatNumber = (val: number) =>
new Intl.NumberFormat('en-US').format(val);
Math.round(val).toLocaleString('de-DE');
const formatPercent = (val: number) =>
`${val.toFixed(2)}%`;
`${val.toLocaleString('de-DE', { minimumFractionDigits: 2, maximumFractionDigits: 2 })}%`;
return (
<div className="flex flex-col gap-6 animate-fade-in p-6 bg-[#0B0E14] min-h-screen text-slate-300">
@@ -190,7 +190,7 @@ const AdsPerformance: React.FC<AdsPerformanceProps> = ({ data, filters }) => {
<SummaryCard label="IMPR." value={formatNumber(totals.curr.impressions)} prevValue={totals.prev?.impressions} />
<SummaryCard label="CLICKS" value={formatNumber(totals.curr.clicks)} prevValue={totals.prev?.clicks} />
<SummaryCard label="ADS ORDERS" value={formatNumber(totals.curr.conversions)} prevValue={totals.prev?.conversions} />
<SummaryCard label="CPC" value={`$${currMetrics.cpc.toFixed(2)}`} prevValue={prevMetrics?.cpc} inverse />
<SummaryCard label="CPC" value={`$${currMetrics.cpc.toLocaleString('de-DE', { minimumFractionDigits: 2, maximumFractionDigits: 2 })}`} prevValue={prevMetrics?.cpc} inverse />
<SummaryCard label="CTR" value={formatPercent(currMetrics.ctr)} prevValue={prevMetrics?.ctr} />
<SummaryCard label="CVR" value={formatPercent(currMetrics.cvr)} prevValue={prevMetrics?.cvr} />
<SummaryCard label="ACOS" value={formatPercent(currMetrics.acos)} prevValue={prevMetrics?.acos} inverse />
@@ -272,8 +272,10 @@ const AdsPerformance: React.FC<AdsPerformanceProps> = ({ data, filters }) => {
};
const SummaryCard = ({ label, value, prevValue, color = "text-white", inverse = false }: { label: string; value: string; prevValue?: number; color?: string; inverse?: boolean }) => {
// Correctly parse value regardless of locale formatting (handles dots as thousands and commas as decimals)
const numericValue = parseFloat(value.replace(/[^\d,]/g, '').replace(',', '.'));
const growth = prevValue !== undefined && prevValue > 0
? ((parseFloat(value.replace(/[^0-9.-]+/g, "")) - prevValue) / prevValue) * 100
? ((numericValue - prevValue) / prevValue) * 100
: null;
return (
@@ -295,9 +297,15 @@ const TableCell = ({ value, prevValue, format, prefix = "", inverse = false, hig
const growth = prevValue !== undefined && prevValue > 0 ? ((value - prevValue) / prevValue) * 100 : null;
let displayValue = "";
if (format === 'currency') displayValue = new Intl.NumberFormat('en-US').format(value);
else if (format === 'number') displayValue = prefix + value.toFixed(format === 'number' && prefix === "$" ? 2 : 0);
else if (format === 'percent') displayValue = value.toFixed(2) + "%";
if (format === 'currency') displayValue = Math.round(value).toLocaleString('de-DE');
else if (format === 'number') {
if (prefix === "$") {
displayValue = "$" + value.toLocaleString('de-DE', { minimumFractionDigits: 2, maximumFractionDigits: 2 });
} else {
displayValue = prefix + Math.round(value).toLocaleString('de-DE');
}
}
else if (format === 'percent') displayValue = value.toLocaleString('de-DE', { minimumFractionDigits: 2, maximumFractionDigits: 2 }) + "%";
return (
<td className="p-4 text-right">