Mudança dos cardes das operaçoes no formato vertical e adição do logo na tela inicial

This commit is contained in:
2026-07-03 14:31:07 -03:00
parent 069301bc2e
commit e6e8ddc8d1
5 changed files with 79 additions and 32 deletions

View File

@@ -4,12 +4,8 @@
<%# Logo / Header %>
<div class="text-center mb-10">
<div class="inline-flex items-center justify-center w-16 h-16 rounded-2xl bg-[#f97316] mb-4">
<svg class="w-8 h-8 text-white" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2"
d="M13 16V6a1 1 0 00-1-1H4a1 1 0 00-1 1v10a1 1 0 001 1h1m8-1a1 1 0 01-1 1H9m4-1V8a1 1 0 011-1h2.586a1 1 0 01.707.293l3.414 3.414a1 1 0 01.293.707V16a1 1 0 01-1 1h-1m-6-1a1 1 0 001 1h1M5 17a2 2 0 104 0m-4 0a2 2 0 114 0m6 0a2 2 0 104 0m-4 0a2 2 0 114 0"/>
</svg>
</div>
<%= image_tag '/logo-reem.png', alt: 'Reem Transporte',
class: 'h-20 w-auto mx-auto mb-4 object-contain' %>
<h1 class="text-3xl font-bold text-white">Reem Logística</h1>
<p class="text-gray-400 mt-1 text-sm">Sistema de Controle de Custos</p>
</div>

View File

@@ -17,34 +17,27 @@
<%# ── KPIs ─────────────────────────────────────────────── %>
<% pct_total = ->(parte) { metricas.total.zero? ? 0 : (parte * 100.0 / metricas.total).round(1) } %>
<div class="grid grid-cols-2 xl:grid-cols-4 gap-4">
<div class="group bg-[#1a1a1a] rounded-2xl border border-white/5 p-6 transition-all duration-200 hover:border-white/20 hover:bg-[#202020] hover:-translate-y-0.5 hover:shadow-lg hover:shadow-black/40">
<p class="text-gray-400 text-sm font-medium mb-2">📦 Total de Entregas</p>
<p class="text-4xl font-black text-white inline-block origin-left transition-transform duration-200 group-hover:scale-110"><%= metricas.total %></p>
<p class="text-xs text-gray-500 mt-2 h-0 overflow-hidden opacity-0 transition-all duration-200 group-hover:h-4 group-hover:opacity-100">
✅ <%= metricas.sucesso %> · <span class="text-blue-500">●</span> <%= metricas.recusas %> · ⏳ <%= metricas.pendentes %>
</p>
<%# Cards de status empilhados na vertical (orientação da img 13): título discreto
em cima, número grande colorido embaixo. %>
<div class="space-y-3">
<div class="bg-[#1a1a1a] rounded-2xl border border-white/5 p-6">
<p class="text-gray-400 text-sm font-medium mb-1">Total de Entregas</p>
<p class="text-5xl font-black text-white leading-none"><%= metricas.total %></p>
</div>
<div class="group bg-[#1a1a1a] rounded-2xl border border-white/5 p-6 transition-all duration-200 hover:border-green-500/40 hover:bg-[#202020] hover:-translate-y-0.5 hover:shadow-lg hover:shadow-black/40">
<p class="text-gray-400 text-sm font-medium mb-2">Total de Sucesso</p>
<p class="text-4xl font-black text-green-400 inline-block origin-left transition-transform duration-200 group-hover:scale-110"><%= metricas.sucesso %></p>
<p class="text-xs text-gray-500 mt-2 h-0 overflow-hidden opacity-0 transition-all duration-200 group-hover:h-4 group-hover:opacity-100">
<%= pct_total.(metricas.sucesso) %>% do total
</p>
<div class="bg-[#1a1a1a] rounded-2xl border border-white/5 p-6">
<p class="text-gray-400 text-sm font-medium mb-1">Total de Sucesso</p>
<p class="text-5xl font-black text-green-400 leading-none"><%= metricas.sucesso %></p>
<p class="text-xs text-gray-500 mt-2"><%= pct_total.(metricas.sucesso) %>% do total</p>
</div>
<div class="group bg-[#1a1a1a] rounded-2xl border border-white/5 p-6 transition-all duration-200 hover:border-blue-500/40 hover:bg-[#202020] hover:-translate-y-0.5 hover:shadow-lg hover:shadow-black/40">
<p class="text-gray-400 text-sm font-medium mb-2">Total de Recusas</p>
<p class="text-4xl font-black text-blue-500 inline-block origin-left transition-transform duration-200 group-hover:scale-110"><%= metricas.recusas %></p>
<p class="text-xs text-gray-500 mt-2 h-0 overflow-hidden opacity-0 transition-all duration-200 group-hover:h-4 group-hover:opacity-100">
<%= pct_total.(metricas.recusas) %>% do total
</p>
<div class="bg-[#1a1a1a] rounded-2xl border border-white/5 p-6">
<p class="text-gray-400 text-sm font-medium mb-1">Total de Recusas</p>
<p class="text-5xl font-black text-blue-500 leading-none"><%= metricas.recusas %></p>
<p class="text-xs text-gray-500 mt-2"><%= pct_total.(metricas.recusas) %>% do total</p>
</div>
<div class="group bg-[#1a1a1a] rounded-2xl border border-white/5 p-6 transition-all duration-200 hover:border-yellow-500/40 hover:bg-[#202020] hover:-translate-y-0.5 hover:shadow-lg hover:shadow-black/40">
<p class="text-gray-400 text-sm font-medium mb-2">Entregas Pendentes</p>
<p class="text-4xl font-black text-yellow-400 inline-block origin-left transition-transform duration-200 group-hover:scale-110"><%= metricas.pendentes %></p>
<p class="text-xs text-gray-500 mt-2 h-0 overflow-hidden opacity-0 transition-all duration-200 group-hover:h-4 group-hover:opacity-100">
<%= pct_total.(metricas.pendentes) %>% do total
</p>
<div class="bg-[#1a1a1a] rounded-2xl border border-white/5 p-6">
<p class="text-gray-400 text-sm font-medium mb-1">Entregas Pendentes</p>
<p class="text-5xl font-black text-yellow-400 leading-none"><%= metricas.pendentes %></p>
<p class="text-xs text-gray-500 mt-2"><%= pct_total.(metricas.pendentes) %>% do total</p>
</div>
</div>

View File

@@ -310,6 +310,37 @@
});
});
// Plugin: desenha o valor centralizado DENTRO de cada segmento da barra
// (pula segmentos baixos demais e valores zero).
const barValueLabels = {
id: 'barValueLabels',
afterDatasetsDraw: function (chart) {
const g = chart.ctx;
g.save();
g.font = '600 11px system-ui, -apple-system, sans-serif';
g.fillStyle = '#ffffff';
g.textAlign = 'center';
g.textBaseline = 'middle';
chart.data.datasets.forEach(function (ds, i) {
const meta = chart.getDatasetMeta(i);
if (meta.hidden) return;
meta.data.forEach(function (bar, idx) {
const v = Number(ds.data[idx]) || 0;
if (!v) return;
const p = bar.getProps(['x', 'y', 'base'], true);
if (Math.abs(p.base - p.y) < 16) return; // segmento pequeno demais
g.fillText(String(v), p.x, (p.y + p.base) / 2);
});
});
g.restore();
}
};
// Total do dia (soma das séries) para o % no tooltip.
const totalDoDia = function (datasets, idx) {
return datasets.reduce(function (s, d) { return s + (Number(d.data[idx]) || 0); }, 0);
};
document.querySelectorAll('canvas.dash-bars').forEach(function (ctx) {
Chart.getChart(ctx)?.destroy();
new Chart(ctx, {
@@ -321,8 +352,10 @@
{ label: 'Falhas', data: JSON.parse(ctx.dataset.failed), backgroundColor: COR_FAIL }
]
},
plugins: [barValueLabels],
options: {
responsive: true, maintainAspectRatio: false,
interaction: { mode: 'index', intersect: false },
onHover: cursorPonteiro,
onClick: function (e, els) {
if (!els.length) return;
@@ -334,7 +367,32 @@
x: { stacked: true, ticks: { color: '#6b7280', maxTicksLimit: 12 }, grid: { color: 'rgba(255,255,255,0.04)' } },
y: { stacked: true, beginAtZero: true, ticks: { color: '#6b7280' }, grid: { color: 'rgba(255,255,255,0.04)' } }
},
plugins: { legend: { labels: { color: '#9ca3af' } } }
plugins: {
legend: { labels: { color: '#9ca3af' } },
// Card de hover no tema escuro do app: data + Completas/Falhas (n e %) + Total.
tooltip: {
mode: 'index', intersect: false,
backgroundColor: '#1f1f1f',
borderColor: 'rgba(255,255,255,0.1)', borderWidth: 1,
titleColor: '#ffffff', bodyColor: '#d1d5db', footerColor: '#9ca3af',
padding: 12, cornerRadius: 12, boxPadding: 4, usePointStyle: true,
titleFont: { weight: '700' }, footerFont: { weight: '600' },
callbacks: {
title: function (items) { return items.length ? items[0].label : ''; },
label: function (item) {
const total = totalDoDia(item.chart.data.datasets, item.dataIndex);
const v = Number(item.raw) || 0;
const pct = total ? (v * 100 / total).toFixed(2) : '0.00';
return ' ' + item.dataset.label + ': ' + v + ' (' + pct + '%)';
},
footer: function (items) {
if (!items.length) return '';
const total = totalDoDia(items[0].chart.data.datasets, items[0].dataIndex);
return 'Total: ' + total + ' (100%)';
}
}
}
}
}
});
});