Imṕlantação do dash board de acompanhamento diario das entregas
This commit is contained in:
110
app/views/operacoes_dashboard/_painel.html.erb
Normal file
110
app/views/operacoes_dashboard/_painel.html.erb
Normal file
@@ -0,0 +1,110 @@
|
||||
<%# locals: metricas (Analytics::OperacaoMetricas), titulo (opcional) %>
|
||||
<% titulo = local_assigns[:titulo] %>
|
||||
<% ins = metricas.insucessos_pct %>
|
||||
<% pd = metricas.por_dia %>
|
||||
|
||||
<div class="space-y-4">
|
||||
<% if titulo.present? %>
|
||||
<div class="flex items-center justify-between">
|
||||
<h2 class="text-lg font-bold text-white"><%= titulo %></h2>
|
||||
<span class="text-xs text-gray-500"><%= metricas.total %> entregas</span>
|
||||
</div>
|
||||
<% end %>
|
||||
|
||||
<%# ── KPIs ─────────────────────────────────────────────── %>
|
||||
<div class="grid grid-cols-2 xl:grid-cols-4 gap-4">
|
||||
<div class="bg-[#1a1a1a] rounded-2xl border border-white/5 p-6">
|
||||
<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>
|
||||
</div>
|
||||
<div class="bg-[#1a1a1a] rounded-2xl border border-white/5 p-6">
|
||||
<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>
|
||||
</div>
|
||||
<div class="bg-[#1a1a1a] rounded-2xl border border-white/5 p-6">
|
||||
<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>
|
||||
</div>
|
||||
<div class="bg-[#1a1a1a] rounded-2xl border border-white/5 p-6">
|
||||
<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>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<%# ── Insucessos % + Índices de falha + Status ─────────── %>
|
||||
<div class="grid grid-cols-1 lg:grid-cols-3 gap-4">
|
||||
<div class="bg-[#1a1a1a] rounded-2xl border border-white/5 p-6">
|
||||
<p class="text-gray-400 text-sm font-medium mb-4">Insucessos %</p>
|
||||
<% if metricas.total.zero? %>
|
||||
<p class="text-center py-8 text-gray-500 text-sm">Sem dados no período.</p>
|
||||
<% else %>
|
||||
<div class="relative h-56">
|
||||
<canvas class="dash-donut"
|
||||
data-completed="<%= ins[:completed] %>"
|
||||
data-failed="<%= ins[:failed] %>"></canvas>
|
||||
</div>
|
||||
<div class="flex justify-center gap-4 mt-3 text-xs">
|
||||
<span class="text-cyan-400">● Completas <%= ins[:pct_completed] %>%</span>
|
||||
<span class="text-indigo-400">● Falhas <%= ins[:pct_failed] %>%</span>
|
||||
</div>
|
||||
<% end %>
|
||||
</div>
|
||||
|
||||
<div class="bg-[#1a1a1a] rounded-2xl border border-white/5 p-6">
|
||||
<p class="text-gray-400 text-sm font-medium mb-4">Índices de Falha</p>
|
||||
<%= render 'tabela_simples',
|
||||
cabecalhos: ['Observação', 'Total', '%'],
|
||||
linhas: metricas.indices_falha.map { |h| [h[:observation], h[:total], "#{h[:pct]}%"] },
|
||||
vazio: 'Nenhuma falha no período.' %>
|
||||
</div>
|
||||
|
||||
<div class="bg-[#1a1a1a] rounded-2xl border border-white/5 p-6">
|
||||
<p class="text-gray-400 text-sm font-medium mb-4">Por Status</p>
|
||||
<%= render 'tabela_simples',
|
||||
cabecalhos: ['Status', 'Quantidade'],
|
||||
linhas: metricas.por_status_gade.map { |h| [h[:status], h[:total]] },
|
||||
vazio: 'Sem dados.',
|
||||
total: metricas.total %>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<%# ── Motoristas + STS ─────────────────────────────────── %>
|
||||
<div class="grid grid-cols-1 lg:grid-cols-2 gap-4">
|
||||
<div class="bg-[#1a1a1a] rounded-2xl border border-white/5 p-6">
|
||||
<p class="text-gray-400 text-sm font-medium mb-4">Notas fiscais por Motorista</p>
|
||||
<div class="max-h-80 overflow-y-auto">
|
||||
<%= render 'tabela_simples',
|
||||
cabecalhos: ['Motorista', 'Notas fiscais'],
|
||||
linhas: metricas.por_motorista.map { |h| [h[:nome], h[:total]] },
|
||||
vazio: 'Sem dados.',
|
||||
total: metricas.total %>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="bg-[#1a1a1a] rounded-2xl border border-white/5 p-6">
|
||||
<p class="text-gray-400 text-sm font-medium mb-4">Entregas por STS (Unidade)</p>
|
||||
<div class="max-h-80 overflow-y-auto">
|
||||
<%= render 'tabela_simples',
|
||||
cabecalhos: ['Unidade', 'NFs entregues'],
|
||||
linhas: metricas.por_sts.map { |h| [h[:nome], h[:total]] },
|
||||
vazio: 'Sem dados.',
|
||||
total: metricas.sucesso %>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<%# ── Entregas por dia ─────────────────────────────────── %>
|
||||
<div class="bg-[#1a1a1a] rounded-2xl border border-white/5 p-6">
|
||||
<p class="text-gray-400 text-sm font-medium mb-4">Entregas por Dia</p>
|
||||
<% if pd[:labels].empty? %>
|
||||
<p class="text-center py-8 text-gray-500 text-sm">Sem dados no período.</p>
|
||||
<% else %>
|
||||
<div class="relative h-72">
|
||||
<canvas class="dash-bars"
|
||||
data-labels="<%= pd[:labels].to_json %>"
|
||||
data-completed="<%= pd[:completed].to_json %>"
|
||||
data-failed="<%= pd[:failed].to_json %>"></canvas>
|
||||
</div>
|
||||
<% end %>
|
||||
</div>
|
||||
</div>
|
||||
Reference in New Issue
Block a user