correção de bugs na area de Dashbord
This commit is contained in:
42
app/views/dashboard/_ranking_motoristas.html.erb
Normal file
42
app/views/dashboard/_ranking_motoristas.html.erb
Normal file
@@ -0,0 +1,42 @@
|
||||
<%# Lista do ranking de motoristas — markup COMPARTILHADO pelas abas "Estimado" e
|
||||
"Consolidado" do dashboard. Os dois conjuntos têm a mesma forma
|
||||
(:nome, :valor, :entregas); só muda a origem dos números, então duplicar o
|
||||
markup faria as duas abas divergirem visualmente na primeira alteração.
|
||||
|
||||
Locais: itens (array de hashes), vazio (texto do estado sem dados). %>
|
||||
<% if itens.any? %>
|
||||
<div class="space-y-3">
|
||||
<%# Base da barra: o MAIOR nº de entregas da aba, não o primeiro item — a aba
|
||||
consolidada é ordenada por VALOR, então o primeiro pode não ser o maior em
|
||||
quantidade e a barra passaria de 100%. Sem entregas (só bônus/desconto,
|
||||
por exemplo) a barra fica vazia em vez de dividir por zero. %>
|
||||
<% max = itens.map { |x| x[:entregas].to_i }.max.to_f %>
|
||||
<% itens.each_with_index do |m, i| %>
|
||||
<div class="flex items-center gap-3">
|
||||
<span class="text-xs font-bold w-5 text-center
|
||||
<%= i == 0 ? 'text-yellow-400' : i == 1 ? 'text-gray-300' : i == 2 ? 'text-orange-600' : 'text-gray-400' %>">
|
||||
<%= i + 1 %>
|
||||
</span>
|
||||
<div class="flex-1 min-w-0">
|
||||
<div class="flex items-center justify-between mb-1">
|
||||
<span class="text-white text-sm font-medium truncate"><%= m[:nome] %></span>
|
||||
<span class="text-[#f97316] text-sm font-semibold ml-2 flex-shrink-0">
|
||||
<%= moeda(m[:valor]) %>
|
||||
</span>
|
||||
</div>
|
||||
<%# Barra de progresso %>
|
||||
<div class="w-full bg-white/5 rounded-full h-1.5">
|
||||
<div class="h-1.5 rounded-full bg-[#f97316]"
|
||||
style="width: <%= max.zero? ? 0 : [(m[:entregas] / max * 100).round, 100].min %>%"></div>
|
||||
</div>
|
||||
<span class="text-gray-400 text-xs"><%= m[:entregas] %> entregas</span>
|
||||
</div>
|
||||
</div>
|
||||
<% end %>
|
||||
</div>
|
||||
<% else %>
|
||||
<div class="text-center py-8 text-gray-400">
|
||||
<div class="mb-2"><%= icone :caminhao, tamanho: 'w-8 h-8', cor: 'text-gray-600', espaco: false %></div>
|
||||
<p class="text-sm"><%= vazio %></p>
|
||||
</div>
|
||||
<% end %>
|
||||
@@ -262,42 +262,48 @@
|
||||
<% end %>
|
||||
</div>
|
||||
|
||||
<%# Top motoristas %>
|
||||
<%# Top motoristas — DUAS ABAS sobre o mesmo ranking:
|
||||
• Estimado = entregas atendidas × preço da entrega (mesma base do card
|
||||
laranja do topo).
|
||||
• Consolidado = o que foi REALMENTE fechado nas consolidações do período,
|
||||
já com bônus/desconto/retirada aplicados, e a quantidade
|
||||
exata de entregas que entrou no fechamento.
|
||||
Os dois números divergem DE PROPÓSITO: o estimado cobre tudo que foi
|
||||
atendido no período; o consolidado, só o que já entrou em consolidação
|
||||
finalizada. Por isso cada aba diz de onde vem o seu número. %>
|
||||
<div class="bg-[#1a1a1a] rounded-2xl border border-white/5 p-6">
|
||||
<h2 class="text-lg font-semibold text-white mb-4 flex items-center gap-2"><%= icone :ranking, espaco: false %> Motoristas</h2>
|
||||
<div class="flex flex-wrap items-center justify-between gap-2 mb-4">
|
||||
<h2 class="text-lg font-semibold text-white flex items-center gap-2"><%= icone :ranking, espaco: false %> Motoristas</h2>
|
||||
|
||||
<% if @motoristas.any? %>
|
||||
<div class="space-y-3">
|
||||
<% @motoristas.each_with_index do |m, i| %>
|
||||
<div class="flex items-center gap-3">
|
||||
<span class="text-xs font-bold w-5 text-center
|
||||
<%= i == 0 ? 'text-yellow-400' : i == 1 ? 'text-gray-300' : i == 2 ? 'text-orange-600' : 'text-gray-400' %>">
|
||||
<%= i + 1 %>
|
||||
</span>
|
||||
<div class="flex-1 min-w-0">
|
||||
<div class="flex items-center justify-between mb-1">
|
||||
<span class="text-white text-sm font-medium truncate"><%= m[:nome] %></span>
|
||||
<span class="text-[#f97316] text-sm font-semibold ml-2 flex-shrink-0">
|
||||
<%= moeda(m[:valor]) %>
|
||||
</span>
|
||||
</div>
|
||||
<%# Barra de progresso %>
|
||||
<div class="w-full bg-white/5 rounded-full h-1.5">
|
||||
<% max = @motoristas.first[:entregas].to_f %>
|
||||
<div class="h-1.5 rounded-full bg-[#f97316]"
|
||||
style="width: <%= [(m[:entregas] / max * 100).round, 100].min %>%"></div>
|
||||
</div>
|
||||
<span class="text-gray-400 text-xs"><%= m[:entregas] %> entregas</span>
|
||||
</div>
|
||||
</div>
|
||||
<% end %>
|
||||
<%# Mesmas pílulas da paginação de pagamentos (as classes estão duplicadas
|
||||
no JS que troca a aba — mexeu aqui, mexa lá). %>
|
||||
<div id="ranking-abas" class="flex gap-1.5">
|
||||
<button type="button" data-aba="estimado"
|
||||
class="px-3 py-1.5 rounded-lg text-xs font-semibold transition-colors bg-[#f97316] text-white">
|
||||
Estimado
|
||||
</button>
|
||||
<button type="button" data-aba="consolidado"
|
||||
class="px-3 py-1.5 rounded-lg text-xs font-semibold transition-colors bg-[#0a0a0a] text-gray-400 border border-white/5 hover:text-white">
|
||||
Consolidado
|
||||
</button>
|
||||
</div>
|
||||
<% else %>
|
||||
<div class="text-center py-8 text-gray-400">
|
||||
<div class="mb-2"><%= icone :caminhao, tamanho: 'w-8 h-8', cor: 'text-gray-600', espaco: false %></div>
|
||||
<p class="text-sm">Nenhuma entrega concluída neste período</p>
|
||||
</div>
|
||||
<% end %>
|
||||
</div>
|
||||
|
||||
<div id="ranking-painel-estimado">
|
||||
<p class="text-gray-400 text-xs mb-3">Entregas atendidas × preço da entrega</p>
|
||||
<%= render 'ranking_motoristas',
|
||||
itens: @motoristas,
|
||||
vazio: 'Nenhuma entrega atendida neste período' %>
|
||||
</div>
|
||||
|
||||
<%# Sem JS a aba fica escondida — aceitável: o mesmo dado consolidado
|
||||
também aparece no gráfico "Custo por motorista" logo abaixo. %>
|
||||
<div id="ranking-painel-consolidado" class="hidden">
|
||||
<p class="text-gray-400 text-xs mb-3">Valor fechado nas consolidações do período</p>
|
||||
<%= render 'ranking_motoristas',
|
||||
itens: @ranking_consolidado,
|
||||
vazio: 'Nenhuma consolidação finalizada neste período' %>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -577,6 +583,38 @@
|
||||
})();
|
||||
</script>
|
||||
|
||||
<%# Abas do ranking de motoristas (Estimado × Consolidado) %>
|
||||
<script>
|
||||
(function () {
|
||||
// As classes repetem as do ERB porque a troca de aba reescreve o className
|
||||
// inteiro — mesmo padrão da paginação de pagamentos acima.
|
||||
const ATIVA = 'px-3 py-1.5 rounded-lg text-xs font-semibold transition-colors bg-[#f97316] text-white';
|
||||
const INATIVA = 'px-3 py-1.5 rounded-lg text-xs font-semibold transition-colors bg-[#0a0a0a] text-gray-400 border border-white/5 hover:text-white';
|
||||
|
||||
function initAbasRanking() {
|
||||
const abas = document.getElementById('ranking-abas');
|
||||
if (!abas || abas.dataset.iniciado) return;
|
||||
abas.dataset.iniciado = '1';
|
||||
|
||||
const botoes = Array.from(abas.querySelectorAll('button'));
|
||||
|
||||
botoes.forEach(function (btn) {
|
||||
btn.addEventListener('click', function () {
|
||||
botoes.forEach(function (b) {
|
||||
const ativa = (b === btn);
|
||||
const painel = document.getElementById('ranking-painel-' + b.dataset.aba);
|
||||
b.className = ativa ? ATIVA : INATIVA;
|
||||
if (painel) painel.classList.toggle('hidden', !ativa);
|
||||
});
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
initAbasRanking();
|
||||
document.addEventListener('turbo:load', initAbasRanking);
|
||||
})();
|
||||
</script>
|
||||
|
||||
<%# Filtro de operação — submete o form ao marcar/desmarcar %>
|
||||
<script>
|
||||
(function () {
|
||||
|
||||
Reference in New Issue
Block a user