Correçoes do campo de busca no mapa e ajustes de interface no dash
This commit is contained in:
@@ -16,22 +16,35 @@
|
||||
<% end %>
|
||||
|
||||
<%# ── 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="bg-[#1a1a1a] rounded-2xl border border-white/5 p-6">
|
||||
<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"><%= metricas.total %></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>
|
||||
</div>
|
||||
<div class="bg-[#1a1a1a] rounded-2xl border border-white/5 p-6">
|
||||
<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"><%= metricas.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>
|
||||
<div class="bg-[#1a1a1a] rounded-2xl border border-white/5 p-6">
|
||||
<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-red-400"><%= metricas.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>
|
||||
<div class="bg-[#1a1a1a] rounded-2xl border border-white/5 p-6">
|
||||
<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"><%= metricas.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>
|
||||
</div>
|
||||
|
||||
@@ -49,7 +62,7 @@
|
||||
</div>
|
||||
<div class="flex justify-center gap-4 mt-3 text-xs">
|
||||
<span class="text-orange-400">● Completas <%= ins[:pct_completed] %>%</span>
|
||||
<span class="text-red-400">● Falhas <%= ins[:pct_failed] %>%</span>
|
||||
<span class="text-blue-500">● Falhas <%= ins[:pct_failed] %>%</span>
|
||||
</div>
|
||||
<% end %>
|
||||
</div>
|
||||
|
||||
@@ -24,8 +24,9 @@
|
||||
.flatpickr-months .flatpickr-prev-month svg, .flatpickr-months .flatpickr-next-month svg { fill: #f97316; }
|
||||
/* O mapa do Leaflet usa fundo claro — moldura escura ao redor */
|
||||
.leaflet-container { background: #1a1a1a; }
|
||||
/* Realça ruas e nomes no tile escuro (CARTO dark_all tem baixo contraste) */
|
||||
.tiles-escuro-contraste { filter: brightness(1.45) contrast(1.2) saturate(0.9); }
|
||||
/* Modo escuro = OpenStreetMap completo (detalhe igual ao claro) invertido,
|
||||
para ruas e nomes ficarem bem visíveis sobre fundo escuro. */
|
||||
.tiles-escuro-contraste { filter: invert(1) hue-rotate(180deg) brightness(0.95) contrast(1.05); }
|
||||
</style>
|
||||
<% end %>
|
||||
|
||||
@@ -262,9 +263,9 @@
|
||||
});
|
||||
}
|
||||
|
||||
// ── Cores da marca (laranja + vermelho p/ falha) ──
|
||||
// ── Cores da marca (laranja + azul p/ falha) ──
|
||||
const COR_OK = '#f97316'; // laranja Reem (completas)
|
||||
const COR_FAIL = '#ef4444'; // vermelho (falhas), igual ao card de Recusas
|
||||
const COR_FAIL = '#3b82f6'; // azul (falhas), igual ao card de Recusas
|
||||
const COR_A = '#f97316'; // comparativo: A = laranja da marca
|
||||
const COR_B = '#3b82f6'; // comparativo: B = azul (contraste)
|
||||
|
||||
@@ -350,11 +351,15 @@
|
||||
'style="margin-top:8px;width:100%;max-height:160px;object-fit:cover;border-radius:6px;display:block"></a>' +
|
||||
'<div style="display:none;margin-top:6px;color:#9ca3af;font-size:11px">📷 Foto indisponível (link expirado/sem acesso)</div>'
|
||||
: '<div style="margin-top:6px;color:#6b7280;font-size:11px">📷 Sem foto da fachada para esta entrega</div>';
|
||||
const statusLinha = p.sucesso
|
||||
? '<div style="color:#16a34a;font-size:11px;margin-bottom:6px">✔ Entrega realizada</div>'
|
||||
: '<div style="color:#3b82f6;font-size:11px;margin-bottom:6px">✖ Insucesso' +
|
||||
(p.motivo ? ' — ' + escapeHtml(p.motivo) : '') + '</div>';
|
||||
return '' +
|
||||
'<div style="min-width:210px;max-width:240px">' +
|
||||
'<div style="font-weight:700;color:#f97316">NF ' + escapeHtml(p.nf) + '</div>' +
|
||||
'<div style="font-weight:600;margin-bottom:4px">' + escapeHtml(p.nome) + '</div>' +
|
||||
'<div style="color:#16a34a;font-size:11px;margin-bottom:6px">✔ Entrega realizada</div>' +
|
||||
statusLinha +
|
||||
linha('📍', p.endereco) +
|
||||
linha('🏥', p.unidade) +
|
||||
linha('🚚', p.motorista) +
|
||||
@@ -364,13 +369,14 @@
|
||||
'</div>';
|
||||
}
|
||||
|
||||
// Ícone de localização (balão) — laranja da marca, sem depender de imagem externa.
|
||||
function pinIcon() {
|
||||
// Ícone de localização (balão) — sem depender de imagem externa.
|
||||
// Cor por resultado: laranja = sucesso, azul = insucesso (falha/óbito).
|
||||
function pinIcon(cor) {
|
||||
return L.divIcon({
|
||||
className: 'pin-entrega',
|
||||
html: '<svg width="28" height="40" viewBox="0 0 28 40" xmlns="http://www.w3.org/2000/svg">' +
|
||||
'<path d="M14 0C6.8 0 1 5.8 1 13c0 9.7 13 27 13 27s13-17.3 13-27C27 5.8 21.2 0 14 0z" ' +
|
||||
'fill="#f97316" stroke="#0a0a0a" stroke-width="1.5"/>' +
|
||||
'fill="' + cor + '" stroke="#0a0a0a" stroke-width="1.5"/>' +
|
||||
'<circle cx="14" cy="13" r="5" fill="#0a0a0a"/></svg>',
|
||||
iconSize: [28, 40],
|
||||
iconAnchor: [14, 40],
|
||||
@@ -380,7 +386,8 @@
|
||||
|
||||
function initMapas() {
|
||||
if (typeof L === 'undefined') return;
|
||||
const ICONE = pinIcon();
|
||||
const ICONE_OK = pinIcon('#f97316'); // sucesso — laranja
|
||||
const ICONE_FALHA = pinIcon('#3b82f6'); // insucesso — azul
|
||||
document.querySelectorAll('.mapa-box').forEach(function (box) {
|
||||
const el = box.querySelector('.mapa-calor');
|
||||
if (!el || el._leaflet_id) return;
|
||||
@@ -390,9 +397,11 @@
|
||||
const centro = JSON.parse(el.dataset.centro || '[-23.55,-46.63]');
|
||||
|
||||
// Camadas base (todas grátis, sem chave): escuro (padrão, combina com o
|
||||
// tema), claro e satélite.
|
||||
const escuro = L.tileLayer('https://{s}.basemaps.cartocdn.com/dark_all/{z}/{x}/{y}{r}.png', {
|
||||
attribution: '© OpenStreetMap © CARTO', subdomains: 'abcd', maxZoom: 20,
|
||||
// tema), claro e satélite. O escuro usa o OpenStreetMap COMPLETO (mesmo
|
||||
// detalhe do claro: ruas, nomes, POIs) e é escurecido por filtro CSS de
|
||||
// inversão (.tiles-escuro-contraste).
|
||||
const escuro = L.tileLayer('https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png', {
|
||||
attribution: '© OpenStreetMap', maxZoom: 19,
|
||||
className: 'tiles-escuro-contraste'
|
||||
});
|
||||
const claro = L.tileLayer('https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png', {
|
||||
@@ -422,7 +431,7 @@
|
||||
if (marcadores) return marcadores;
|
||||
marcadores = L.layerGroup();
|
||||
pontos.forEach(function (p) {
|
||||
const marker = L.marker([p.lat, p.lng], { icon: ICONE })
|
||||
const marker = L.marker([p.lat, p.lng], { icon: p.sucesso ? ICONE_OK : ICONE_FALHA })
|
||||
.bindPopup(function () { return popupHtml(p); }, { maxWidth: 260 });
|
||||
marker.addTo(marcadores);
|
||||
entradas.push({ marker: marker, p: p });
|
||||
|
||||
Reference in New Issue
Block a user