Compare commits

..

2 Commits
main ... pages

View File

@ -14,11 +14,12 @@
@media (max-width: 900px) { .kpi-strip { grid-template-columns: repeat(2, 1fr); } }
.charts-row { display: grid; grid-template-columns: repeat(2, 1fr); gap: 24px; padding: 0 32px 24px; }
@media (max-width: 900px) { .charts-row { grid-template-columns: 1fr; } }
.chart-wrap { height: 220px; position: relative; display: flex; align-items: flex-end; gap: 4px; padding-top: 28px; overflow-x: auto; }
.chart-wrap { height: 280px; position: relative; display: flex; align-items: flex-end; gap: 4px; padding-top: 28px; padding-bottom: 60px; padding-left: 24px; overflow-x: auto; }
.bar { flex: 1; min-width: 20px; max-width: 28px; border-radius: 2px 2px 0 0; position: relative; cursor: pointer; }
.bar[data-kt-tip]::after { content: attr(data-kt-tip); position: absolute; bottom: calc(100% + 4px); left: 50%; transform: translateX(-50%); background: var(--kt-ai-overlay); color: var(--kt-ai-fg-on-fill); padding: 4px 8px; border-radius: 4px; font-size: 11px; white-space: nowrap; opacity: 0; pointer-events: none; transition: opacity 0.15s; }
.bar:hover::after { opacity: 1; }
.bar-value { position: absolute; bottom: calc(100% + 4px); left: 50%; transform: translateX(-50%); font-size: 11px; font-family: var(--kt-ai-font-mono); color: var(--kt-ai-fg-muted); }
.bar-value { position: absolute; bottom: calc(100% + 4px); left: 50%; transform: translateX(-50%); font-size: 11px; font-family: var(--kt-ai-font-mono); color: var(--kt-ai-fg-muted); white-space: nowrap; }
.bar-label { position: absolute; bottom: -56px; left: 50%; transform: translateX(-50%) rotate(-35deg); transform-origin: center top; font-size: 10px; color: var(--kt-ai-fg-muted); white-space: nowrap; }
.table-section { padding: 0 32px 32px; }
.table-controls { display: flex; gap: 12px; margin-bottom: 16px; flex-wrap: wrap; }
.chip-row { display: flex; gap: 8px; flex-wrap: wrap; margin-bottom: 16px; }
@ -157,21 +158,25 @@
document.getElementById('kpi-service').title = topService[0];
document.getElementById('kpi-region').textContent = topRegion[0];
function renderChart(containerId, data, colorVar) {
function renderChart(containerId, data, colorVar, isService) {
const container = document.getElementById(containerId);
const maxVal = Math.max(...data.map(d => d.value));
container.innerHTML = data.map((d, i) => {
const h = (d.value / maxVal) * 170;
return `<div class="bar" data-kt-tip="${d.label}: ${fmtNum(d.value)}" style="height:${h}px;background:var(${colorVar});">
<span class="bar-value">${fmtNum(d.value)}</span>
const shortLabel = isService ? (d.label.length > 14 ? d.label.slice(0, 14) + '…' : d.label) : d.label;
const tipLabel = isService ? d.label : shortLabel;
const showValue = i < 3 ? `<span class="bar-value">${fmtNum(d.value)}</span>` : '';
return `<div class="bar" data-kt-tip="${tipLabel}: ${fmtNum(d.value)}" style="height:${h}px;background:var(${colorVar});">
${showValue}
<span class="bar-label">${shortLabel}</span>
</div>`;
}).join('');
}
const regionData = Object.entries(byRegion).sort((a, b) => b[1] - a[1]).slice(0, 12).map(([label, value]) => ({ label, value }));
const serviceData = Object.entries(byService).sort((a, b) => b[1] - a[1]).slice(0, 12).map(([label, value]) => ({ label, value: value }));
renderChart('chart-regions', regionData, '--kt-ai-chart-blue');
renderChart('chart-services', serviceData, '--kt-ai-chart-green');
renderChart('chart-regions', regionData, '--kt-ai-chart-blue', false);
renderChart('chart-services', serviceData, '--kt-ai-chart-green', true);
const regionFilter = document.getElementById('region-filter');
const chipRow = document.getElementById('chip-row');