183 lines
10 KiB
Plaintext
183 lines
10 KiB
Plaintext
<%# app/views/consolidacao_entregas/validar.html.erb — PASSO 2: Validar entregas %>
|
|
<% content_for :title, "Validar — #{@motorista}" %>
|
|
|
|
<div class="max-w-6xl mx-auto" data-controller="validacao"
|
|
data-validacao-url-value="<%= classificar_consolidacao_consolidacao_entregas_path(@consolidacao) %>"
|
|
data-validacao-massa-url-value="<%= classificar_em_massa_consolidacao_consolidacao_entregas_path(@consolidacao) %>"
|
|
data-validacao-motorista-value="<%= @motorista %>"
|
|
data-validacao-total-value="<%= @total_entregas %>">
|
|
|
|
<%# Header %>
|
|
<div class="mb-6">
|
|
<%= link_to '← Voltar (Passo 1)', wizard_consolidacao_path(@consolidacao),
|
|
class: 'inline-flex items-center gap-1 bg-[#1a1a1a] hover:bg-[#2a2a2a] text-white border border-[#2a2a2a] hover:border-orange-500 font-semibold px-4 py-2.5 rounded-lg text-sm min-h-[44px]' %>
|
|
<div class="flex items-center justify-between mt-2">
|
|
<div>
|
|
<h1 class="text-2xl font-bold text-white">🚚 <%= @motorista %></h1>
|
|
<p class="text-gray-400 text-sm"><%= @consolidacao.nome %> · <%= l @consolidacao.data_inicio, format: :short %> → <%= l @consolidacao.data_fim, format: :short %></p>
|
|
</div>
|
|
<%= link_to 'Revisar (Passo 3) →',
|
|
revisar_consolidacao_consolidacao_entregas_path(@consolidacao, motorista: @motorista),
|
|
class: 'bg-orange-500 hover:bg-orange-600 text-black font-bold px-5 py-3 rounded-lg min-h-[48px] flex items-center' %>
|
|
</div>
|
|
</div>
|
|
|
|
<%# Barra de progresso %>
|
|
<div class="bg-[#1a1a1a] border border-[#2a2a2a] rounded-xl p-4 mb-4">
|
|
<div class="flex justify-between text-sm mb-2">
|
|
<span class="text-white font-semibold">
|
|
<span data-validacao-target="contadorClassificadas"><%= @classificadas %></span>
|
|
de <span data-validacao-target="contadorTotal"><%= @total_entregas %></span> entregas classificadas
|
|
</span>
|
|
<span class="text-orange-500 font-bold" data-validacao-target="percentual"></span>
|
|
</div>
|
|
<div class="w-full bg-[#0a0a0a] rounded-full h-3">
|
|
<div data-validacao-target="barra" class="h-3 rounded-full bg-orange-500 transition-all duration-300" style="width: 0%"></div>
|
|
</div>
|
|
</div>
|
|
|
|
<%# Ações em massa + filtro %>
|
|
<div class="bg-[#1a1a1a] border border-[#2a2a2a] rounded-xl p-4 mb-4 flex flex-wrap items-center gap-3">
|
|
<span class="text-gray-400 text-sm font-semibold">Ações em massa:</span>
|
|
|
|
<button data-action="click->validacao#marcarTodos" data-tipo="entrega_normal"
|
|
class="bg-orange-500 hover:bg-orange-600 text-black font-bold px-4 py-2.5 rounded-lg text-sm min-h-[44px]">
|
|
✓ Marcar todos como Normal
|
|
</button>
|
|
|
|
<label class="flex items-center gap-2 text-gray-300 text-sm cursor-pointer select-none border-l border-[#2a2a2a] pl-3">
|
|
<input type="checkbox" data-validacao-target="selecionarTodos"
|
|
data-action="change->validacao#selecionarTodos"
|
|
class="rounded text-orange-500 bg-[#0a0a0a] border-[#2a2a2a] w-5 h-5">
|
|
Selecionar todos
|
|
</label>
|
|
|
|
<label class="flex items-center gap-2 text-sm cursor-pointer select-none border-l border-[#2a2a2a] pl-3">
|
|
<input type="checkbox" data-validacao-target="modoRemover" data-action="change->validacao#alternarModo"
|
|
class="rounded text-red-500 bg-[#0a0a0a] border-[#2a2a2a] w-5 h-5">
|
|
<span class="text-gray-300">Modo remover (desmarcar)</span>
|
|
</label>
|
|
|
|
<div class="flex items-center gap-2">
|
|
<span class="text-gray-500 text-sm" data-validacao-target="rotuloAcao">Selecionados como:</span>
|
|
<button data-action="click->validacao#marcarSelecionados" data-tipo="entrega_normal"
|
|
class="bg-orange-500 text-black font-bold px-3 py-2 rounded-lg text-xs min-h-[44px]">Normal</button>
|
|
<button data-action="click->validacao#marcarSelecionados" data-tipo="retirada"
|
|
class="bg-orange-800 text-white font-bold px-3 py-2 rounded-lg text-xs min-h-[44px]">Retirada</button>
|
|
<button data-action="click->validacao#marcarSelecionados" data-tipo="bonus"
|
|
class="bg-white text-black font-bold px-3 py-2 rounded-lg text-xs border border-orange-500 min-h-[44px]">Bônus</button>
|
|
<button data-action="click->validacao#marcarSelecionados" data-tipo="desconto"
|
|
class="bg-black text-white font-bold px-3 py-2 rounded-lg text-xs border border-gray-700 min-h-[44px]">Desconto</button>
|
|
</div>
|
|
|
|
<div class="ml-auto">
|
|
<%= link_to params[:apenas_pendentes] == '1' ? 'Mostrar todas' : 'Apenas não classificadas',
|
|
validar_consolidacao_consolidacao_entregas_path(@consolidacao, motorista: @motorista,
|
|
apenas_pendentes: params[:apenas_pendentes] == '1' ? nil : '1'),
|
|
class: 'text-orange-400 hover:text-orange-300 text-sm border border-orange-500/40 px-3 py-2 rounded-lg' %>
|
|
</div>
|
|
</div>
|
|
|
|
<div class="grid grid-cols-1 lg:grid-cols-4 gap-4">
|
|
|
|
<%# ── Lista de entregas (3 colunas) ─────────────────── %>
|
|
<div class="lg:col-span-3 space-y-2">
|
|
<% if @entregas.any? %>
|
|
<% @entregas.each do |e| %>
|
|
<% tipos_ativos = (@classificacoes[e.tracking_id] || []).map(&:tipo) %>
|
|
<div class="bg-[#1a1a1a] border border-[#2a2a2a] rounded-xl p-4 flex flex-col md:flex-row md:items-center gap-3"
|
|
data-validacao-target="linha" data-tracking="<%= e.tracking_id %>"
|
|
data-classificada="<%= tipos_ativos.any? ? '1' : '0' %>">
|
|
|
|
<%# Checkbox seleção em massa %>
|
|
<input type="checkbox" data-validacao-target="checkbox" value="<%= e.tracking_id %>"
|
|
class="rounded text-orange-500 bg-[#0a0a0a] border-[#2a2a2a] w-5 h-5">
|
|
|
|
<%# Dados da entrega %>
|
|
<div class="flex-1 min-w-0">
|
|
<p class="text-white font-semibold truncate">
|
|
NF <%= e.numero_nf %> · <%= e.local %>
|
|
</p>
|
|
<p class="text-gray-400 text-xs truncate">📍 <%= e.address.presence || 'sem endereço' %></p>
|
|
<p class="text-gray-500 text-xs">
|
|
📅 <%= e.planned_date %> · 🚚 <%= e.vehicle.presence || 'sem veículo' %>
|
|
<% if e.atraso_minutos > 0 %> · ⏱️ atraso <%= e.atraso_minutos %>min<% end %>
|
|
</p>
|
|
</div>
|
|
|
|
<%# Toggles coloridos — laranja=normal, laranja escuro=retirada, branco=bônus, preto=desconto %>
|
|
<div class="flex gap-1.5" data-validacao-target="toggles" data-tracking="<%= e.tracking_id %>">
|
|
<% [
|
|
['entrega_normal', 'Normal', 'bg-orange-500 text-black'],
|
|
['retirada', 'Retirada', 'bg-orange-800 text-white'],
|
|
['bonus', 'Bônus', 'bg-white text-black border border-orange-500'],
|
|
['desconto', 'Desc.', 'bg-black text-white border border-gray-700']
|
|
].each do |tipo, label, cores| %>
|
|
<button data-action="click->validacao#classificar"
|
|
data-tracking="<%= e.tracking_id %>" data-tipo="<%= tipo %>"
|
|
class="toggle-btn <%= cores %> font-bold px-3 py-2.5 rounded-lg text-xs min-h-[44px] transition-all
|
|
<%= tipos_ativos.include?(tipo) ? 'ring-2 ring-green-400 scale-105' : 'opacity-50 hover:opacity-100' %>">
|
|
<%= label %>
|
|
</button>
|
|
<% end %>
|
|
</div>
|
|
</div>
|
|
<% end %>
|
|
<% else %>
|
|
<div class="bg-[#1a1a1a] border border-[#2a2a2a] rounded-xl p-10 text-center">
|
|
<p class="text-4xl mb-3">🎉</p>
|
|
<p class="text-gray-400">Nenhuma entrega pendente neste filtro.</p>
|
|
</div>
|
|
<% end %>
|
|
</div>
|
|
|
|
<%# ── Resumo lateral (1 coluna, sticky) ─────────────── %>
|
|
<div class="lg:col-span-1">
|
|
<div class="bg-[#1a1a1a] border border-[#2a2a2a] rounded-xl p-5 sticky top-4 space-y-4">
|
|
<h3 class="text-white font-bold">📊 Resumo</h3>
|
|
|
|
<div class="space-y-2 text-sm">
|
|
<div class="flex justify-between items-center">
|
|
<span class="flex items-center gap-2"><span class="w-3 h-3 bg-orange-500 rounded-full"></span> Normal</span>
|
|
<span class="text-white font-bold" data-validacao-target="qtdNormal">0</span>
|
|
</div>
|
|
<div class="flex justify-between items-center">
|
|
<span class="flex items-center gap-2"><span class="w-3 h-3 bg-orange-800 rounded-full"></span> Retirada</span>
|
|
<span class="text-white font-bold" data-validacao-target="qtdRetirada">0</span>
|
|
</div>
|
|
<div class="flex justify-between items-center">
|
|
<span class="flex items-center gap-2"><span class="w-3 h-3 bg-white rounded-full border border-orange-500"></span> Bônus</span>
|
|
<span class="text-white font-bold" data-validacao-target="qtdBonus">0</span>
|
|
</div>
|
|
<div class="flex justify-between items-center">
|
|
<span class="flex items-center gap-2"><span class="w-3 h-3 bg-black border border-gray-600 rounded-full"></span> Desconto</span>
|
|
<span class="text-white font-bold" data-validacao-target="qtdDesconto">0</span>
|
|
</div>
|
|
</div>
|
|
|
|
<div class="border-t border-[#2a2a2a] pt-4">
|
|
<p class="text-gray-500 text-xs mb-1">Total do motorista</p>
|
|
<p class="text-orange-500 font-black text-2xl" data-validacao-target="valorTotal">R$ 0,00</p>
|
|
</div>
|
|
|
|
<div class="border-t border-[#2a2a2a] pt-4 text-xs text-gray-500 space-y-1">
|
|
<p>💰 Normal: <%= moeda(@precos[:entrega_normal]) %></p>
|
|
<p>📦 Retirada: <%= moeda(@precos[:retirada]) %></p>
|
|
<p>⭐ Bônus: <%= moeda(@precos[:bonus]) %></p>
|
|
<p>⚠️ Desconto: -<%= moeda(@precos[:desconto]) %></p>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<%# Estado inicial para o Stimulus %>
|
|
<script type="application/json" id="validacao-estado-inicial">
|
|
<% _todas = @classificacoes.values.flatten %>
|
|
<%= raw({
|
|
classificadas: @classificadas,
|
|
por_tipo: _todas.group_by(&:tipo).transform_values(&:size),
|
|
valor_total: _todas.sum { |c| c.tipo == 'desconto' ? -c.valor_aplicado : c.valor_aplicado }.to_f
|
|
}.to_json) %>
|
|
</script>
|