Files
Reem-Notas/app/views/consolidacoes/wizard.html.erb

297 lines
18 KiB
Plaintext
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
<%# app/views/consolidacoes/wizard.html.erb — PASSO 1: Selecionar motorista %>
<% content_for :title, "Wizard — #{@consolidacao.nome}" %>
<div class="max-w-3xl mx-auto">
<%# Header do wizard %>
<div class="mb-6">
<%= link_to '← Voltar para o resumo', consolidacao_path(@consolidacao), class: 'text-gray-500 hover:text-orange-500 text-sm' %>
<h1 class="text-2xl font-bold text-white mt-2"><%= @consolidacao.nome %></h1>
<p class="text-gray-400 text-sm">
📅 <%= l @consolidacao.data_inicio, format: :short %> → <%= l @consolidacao.data_fim, format: :short %>
· <%= badge_status(@consolidacao.status) %>
</p>
</div>
<%# Indicador de passos %>
<div class="flex items-center gap-2 mb-8">
<div class="flex items-center gap-2 text-orange-500 font-bold">
<span class="w-8 h-8 bg-orange-500 text-black rounded-full flex items-center justify-center">1</span>
Selecionar motorista
</div>
<div class="flex-1 h-px bg-[#2a2a2a]"></div>
<div class="flex items-center gap-2 text-gray-600">
<span class="w-8 h-8 bg-[#1a1a1a] border border-[#2a2a2a] rounded-full flex items-center justify-center">2</span>
Validar entregas
</div>
<div class="flex-1 h-px bg-[#2a2a2a]"></div>
<div class="flex items-center gap-2 text-gray-600">
<span class="w-8 h-8 bg-[#1a1a1a] border border-[#2a2a2a] rounded-full flex items-center justify-center">3</span>
Revisar
</div>
</div>
<%# Caixa de ferramentas do Passo 1 — concentra "Apontamento manual" (busca pela
NF) e "Adicionar motorista" num único botão com menu suspenso. %>
<% unless @consolidacao.finalizada? && current_user.operador? %>
<div class="relative mb-4"
data-controller="ferramentas apontamento adicionar-motorista"
data-apontamento-buscar-url-value="<%= buscar_nf_consolidacao_consolidacao_entregas_path(@consolidacao) %>"
data-apontamento-apontar-url-value="<%= apontar_consolidacao_consolidacao_entregas_path(@consolidacao) %>">
<%# Botão único + menu suspenso %>
<button type="button" data-action="ferramentas#toggle"
class="w-full md:w-auto inline-flex items-center justify-center gap-2 bg-[#1a1a1a] hover:bg-[#2a2a2a] text-white border border-dashed border-[#3a3a3a] hover:border-orange-500 font-semibold px-4 py-3 rounded-lg min-h-[48px]">
Adicionar / Ferramentas
<span class="text-gray-500">▾</span>
</button>
<div data-ferramentas-target="menu"
class="hidden absolute z-40 mt-2 w-72 bg-[#1a1a1a] border border-[#2a2a2a] rounded-xl shadow-xl overflow-hidden">
<button type="button" data-action="apontamento#abrir ferramentas#fechar"
class="w-full text-left px-4 py-3 hover:bg-[#2a2a2a] border-l-2 border-transparent hover:border-orange-500">
<span class="block text-white font-semibold">📝 Apontamento manual</span>
<span class="block text-gray-500 text-xs">nota que chegou por fora (busca pela NF)</span>
</button>
<button type="button" data-action="adicionar-motorista#abrir ferramentas#fechar"
class="w-full text-left px-4 py-3 hover:bg-[#2a2a2a] border-t border-[#2a2a2a] border-l-2 border-l-transparent hover:border-l-green-500">
<span class="block text-white font-semibold">🧑‍✈️ Adicionar motorista</span>
<span class="block text-gray-500 text-xs">incluir/restaurar um motorista nesta consolidação</span>
</button>
</div>
<%# Modal — apontamento manual (busca NF) %>
<div data-apontamento-target="modal" data-action="click->apontamento#fundo"
class="hidden fixed inset-0 z-50 bg-black/70 flex items-center justify-center p-4">
<div class="bg-[#1a1a1a] border border-[#2a2a2a] rounded-2xl w-full max-w-lg p-6 max-h-[90vh] overflow-y-auto">
<div class="flex items-center justify-between mb-1">
<h2 class="text-xl font-bold text-white">Apontamento manual</h2>
<button type="button" data-action="apontamento#fechar"
class="text-gray-500 hover:text-white text-2xl leading-none">✕</button>
</div>
<p class="text-gray-400 text-sm mb-4">Busque a nota pela base de rastreio e adicione ao fechamento do motorista correspondente.</p>
<p data-apontamento-target="erro" class="hidden bg-red-500/10 text-red-400 border border-red-500/30 rounded-lg px-3 py-2 text-sm mb-3"></p>
<%# Busca da NF %>
<form data-action="submit->apontamento#buscar" class="flex gap-2 mb-4">
<input data-apontamento-target="nf" type="text" inputmode="numeric"
placeholder="Número da nota (NF)"
class="flex-1 bg-[#0a0a0a] border border-[#2a2a2a] text-white rounded-lg px-3 py-3 text-base focus:border-orange-500 focus:outline-none">
<button type="submit"
class="bg-orange-500 hover:bg-orange-600 text-black font-bold px-5 rounded-lg min-h-[48px]">Buscar</button>
</form>
<%# Resultados (preenchidos via JS) %>
<div data-apontamento-target="resultados" class="space-y-2 mb-4"></div>
<%# Confirmação — pilares (múltiplos) + adicionar (oculto até a busca retornar) %>
<div data-apontamento-target="confirmar" class="hidden border-t border-[#2a2a2a] pt-4">
<label class="block text-gray-400 text-sm mb-2">Classificar como <span class="text-gray-600">(pode marcar mais de uma)</span></label>
<div class="grid grid-cols-2 gap-2 mb-4">
<% [['entrega_normal', '🚚 Entrega Normal', Configuracao.preco_entrega],
['retirada', '📦 Retirada', Configuracao.preco_retirada],
['bonus', '⭐ Bônus', Configuracao.preco_bonus],
['desconto', '⚠️ Desconto', Configuracao.preco_desconto],
['extraordinaria', '✨ Entrega Extraordinária', Configuracao.preco_extraordinaria]].each do |tipo, label, preco| %>
<label class="flex items-center gap-2 bg-[#0a0a0a] border border-[#2a2a2a] rounded-lg px-3 py-3 cursor-pointer hover:border-orange-500 text-sm text-white">
<input type="checkbox" value="<%= tipo %>" data-apontamento-target="tipoCheck"
<%= 'checked' if tipo == 'entrega_normal' %>
class="accent-orange-500">
<span><%= label %><br><span class="text-gray-500 text-xs"><%= moeda(preco) %></span></span>
</label>
<% end %>
</div>
<button type="button" data-action="apontamento#apontar"
class="w-full bg-green-600 hover:bg-green-500 text-white font-bold py-3.5 rounded-lg min-h-[48px]">
Adicionar apontamento ✓
</button>
</div>
</div>
</div>
<%# Modal — adicionar motorista %>
<div data-adicionar-motorista-target="modal" data-action="click->adicionar-motorista#fundo"
class="hidden fixed inset-0 z-50 bg-black/70 flex items-center justify-center p-4">
<div class="bg-[#1a1a1a] border border-[#2a2a2a] rounded-2xl w-full max-w-md p-6">
<div class="flex items-center justify-between mb-1">
<h2 class="text-xl font-bold text-white">🧑‍✈️ Adicionar motorista</h2>
<button type="button" data-action="adicionar-motorista#fechar"
class="text-gray-500 hover:text-white text-2xl leading-none">✕</button>
</div>
<p class="text-gray-400 text-sm mb-4">Inclua um motorista nesta consolidação. Se ele estava arquivado, será restaurado.</p>
<%= form_with url: adicionar_motorista_consolidacao_path(@consolidacao), method: :post do |f| %>
<label class="block text-gray-400 text-sm mb-1">Motorista <span class="text-gray-600">(previstos no período)</span></label>
<input data-adicionar-motorista-target="input" type="text" name="motorista_nome"
list="motoristas-disponiveis" placeholder="Nome do motorista" autocomplete="off"
class="w-full bg-[#0a0a0a] border border-[#2a2a2a] text-white rounded-lg px-3 py-3 text-base focus:border-orange-500 focus:outline-none mb-4">
<datalist id="motoristas-disponiveis">
<% Array(@motoristas_periodo).each do |m| %>
<option value="<%= m[:nome] %>" label="<%= '🚚 ' + m[:veiculos].join(', ') if m[:veiculos].any? %>"></option>
<% end %>
</datalist>
<%# Lista de previstos no período (nome + veículos usados) — clique para preencher %>
<% if Array(@motoristas_periodo).any? %>
<p class="text-gray-500 text-xs mb-1">Previstos neste período (clique para escolher):</p>
<div class="max-h-48 overflow-y-auto space-y-1 mb-4 pr-1">
<% @motoristas_periodo.each do |m| %>
<button type="button" data-action="adicionar-motorista#selecionar" data-nome="<%= m[:nome] %>"
class="w-full text-left px-3 py-2 bg-[#0a0a0a] border border-[#2a2a2a] hover:border-orange-500 rounded-lg">
<span class="block text-white text-sm font-semibold"><%= m[:nome] %></span>
<% if m[:veiculos].any? %>
<span class="block text-gray-500 text-xs">🚚 <%= m[:veiculos].join(', ') %></span>
<% end %>
</button>
<% end %>
</div>
<% else %>
<p class="text-gray-500 text-xs mb-4">Nenhum motorista previsto no período — você ainda pode digitar um nome manualmente.</p>
<% end %>
<button type="submit"
class="w-full bg-green-600 hover:bg-green-500 text-white font-bold py-3.5 rounded-lg min-h-[48px]">
Adicionar ✓
</button>
<% end %>
</div>
</div>
</div>
<% end %>
<%# Lista de motoristas %>
<% pode_arquivar_motorista = !(@consolidacao.finalizada? && current_user.operador?) %>
<div class="space-y-3">
<% @motoristas.each do |m| %>
<%# Container relativo: o card é um link; o botão de arquivar fica FORA da
âncora (não se pode aninhar <form>/<button_to> dentro de <a>). %>
<div class="relative">
<%= link_to validar_consolidacao_consolidacao_entregas_path(@consolidacao, motorista: m[:registro].motorista_nome),
class: "block bg-[#1a1a1a] border rounded-xl p-5 transition-colors
#{m[:completo] ? 'border-green-600 hover:border-green-500' : 'border-[#2a2a2a] hover:border-orange-500'}" do %>
<div class="flex items-center justify-between">
<div class="flex items-center gap-4">
<div class="w-12 h-12 rounded-full flex items-center justify-center text-xl font-black
<%= m[:completo] ? 'bg-green-600 text-white' : 'bg-orange-500 text-black' %>">
<%= m[:completo] ? '✓' : m[:registro].motorista_nome.first.upcase %>
</div>
<div>
<p class="text-white font-bold text-lg"><%= m[:registro].motorista_nome %></p>
<p class="text-gray-400 text-sm">
<%= m[:total] %> entregas pagas no período
· <span class="<%= m[:completo] ? 'text-green-400' : 'text-orange-400' %>">
<%= m[:classificadas] %>/<%= m[:total] %> classificadas
</span>
<% if m[:apontamentos].positive? %>
· <span class="text-orange-400"> <%= m[:apontamentos] %> apontamento<%= 's' if m[:apontamentos] > 1 %></span>
<% end %>
</p>
<% if m[:veiculos_total] > 0 %>
<p class="text-xs mt-0.5">
<span class="<%= m[:veiculos_fechados] == m[:veiculos_total] ? 'text-green-400' : 'text-gray-400' %>">
🚗 <%= m[:veiculos_fechados] %>/<%= m[:veiculos_total] %> veículo<%= 's' if m[:veiculos_total] > 1 %> consolidado<%= 's' if m[:veiculos_fechados] != 1 %>
</span>
<% if m[:veiculos_pendentes].any? %>
<span class="text-orange-400">· pendente<%= 's' if m[:veiculos_pendentes].size > 1 %>: <%= m[:veiculos_pendentes].join(', ') %></span>
<% end %>
</p>
<% end %>
</div>
</div>
<div class="text-right <%= 'pr-10' if pode_arquivar_motorista %>">
<p class="text-orange-500 font-bold"><%= moeda(m[:registro].valor_total) %></p>
<span class="text-gray-600 text-2xl">→</span>
</div>
</div>
<div class="mt-3">
<% pct = m[:total].zero? ? 0 : (m[:classificadas] * 100 / m[:total]) %>
<div class="w-full bg-[#0a0a0a] rounded-full h-2">
<div class="h-2 rounded-full <%= m[:completo] ? 'bg-green-500' : 'bg-orange-500' %> transition-all"
style="width: <%= pct %>%"></div>
</div>
</div>
<% end %>
<% if pode_arquivar_motorista %>
<%= button_to '🗄️',
arquivar_motorista_consolidacao_path(@consolidacao, consolidacao_motorista_id: m[:registro].id),
method: :post,
form: { data: { turbo_confirm: "Arquivar #{m[:registro].motorista_nome} desta consolidação? Você poderá restaurar depois." },
class: 'absolute top-3 right-3' },
class: 'text-gray-500 hover:text-red-400 border border-[#2a2a2a] hover:border-red-500/50 rounded-lg w-9 h-9 flex items-center justify-center',
title: "Arquivar #{m[:registro].motorista_nome}" %>
<% end %>
</div>
<% end %>
</div>
<%# Motoristas arquivados — restauráveis %>
<% if @arquivados.present? %>
<div class="mt-6">
<h2 class="text-gray-400 font-semibold text-sm mb-2">🗄️ Motoristas arquivados (<%= @arquivados.size %>)</h2>
<div class="space-y-2">
<% @arquivados.each do |cm| %>
<div class="flex items-center justify-between bg-[#141414] border border-[#2a2a2a] border-dashed rounded-xl px-4 py-3">
<div>
<p class="text-gray-300 font-semibold"><%= cm.motorista_nome %></p>
<p class="text-gray-600 text-xs">Arquivado · não conta no total</p>
</div>
<div class="flex items-center gap-2">
<% if pode_arquivar_motorista %>
<%= button_to '♻️ Restaurar',
desarquivar_motorista_consolidacao_path(@consolidacao, consolidacao_motorista_id: cm.id),
method: :post,
class: 'text-green-400 hover:text-green-300 border border-[#2a2a2a] hover:border-green-500/50 px-3 py-2 rounded-lg text-xs min-h-[40px]' %>
<% end %>
<% if policy(@consolidacao).destroy? %>
<%= button_to '🗑️ Excluir',
excluir_motorista_consolidacao_path(@consolidacao, consolidacao_motorista_id: cm.id),
method: :delete,
form: { data: { turbo_confirm: "Excluir DEFINITIVAMENTE #{cm.motorista_nome} desta consolidação? Os lançamentos dele serão apagados e isso não pode ser desfeito." } },
class: 'text-red-400 hover:text-red-300 border border-[#2a2a2a] hover:border-red-500/50 px-3 py-2 rounded-lg text-xs min-h-[40px]' %>
<% end %>
</div>
</div>
<% end %>
</div>
</div>
<% end %>
<%# Finalizar — habilita quando tudo classificado. Se sobram veículos pendentes
mas já há veículos consolidados, oferece "arquivar pendentes e finalizar". %>
<% tudo_completo = @motoristas.all? { |m| m[:completo] } && @motoristas.any? %>
<% tem_consolidados = @motoristas.any? { |m| m[:veiculos_fechados] > 0 || m[:veiculos_prontos] > 0 } %>
<% tem_pendentes = @motoristas.any? { |m| m[:veiculos_pendentes].any? } %>
<div class="mt-8 bg-[#1a1a1a] border border-[#2a2a2a] rounded-xl p-5">
<div class="flex items-center justify-between gap-3 flex-wrap">
<div>
<p class="text-white font-bold">Total da consolidação</p>
<p class="text-orange-500 font-black text-3xl"><%= moeda(@consolidacao.valor_total) %></p>
</div>
<% if @consolidacao.rascunho? %>
<div class="flex flex-col sm:flex-row gap-2">
<% if !tudo_completo && tem_consolidados && tem_pendentes %>
<%= button_to '🔒 Arquivar pendentes e finalizar',
finalizar_parcial_consolidacao_path(@consolidacao),
method: :post,
data: { turbo_confirm: 'Arquivar TODOS os veículos ainda não classificados 100% e finalizar? Eles ficam de fora desta consolidação (você resolve depois). Os veículos consolidados são pagos normalmente.' },
class: 'bg-orange-500 hover:bg-orange-600 text-black font-bold px-5 py-3.5 rounded-lg min-h-[48px] flex items-center justify-center text-center' %>
<% end %>
<%= button_to 'Finalizar consolidação ✓', finalizar_consolidacao_path(@consolidacao),
method: :post,
disabled: !tudo_completo,
data: { turbo_confirm: 'Finalizar? Após finalizada, a consolidação não poderá ser editada por operadores.' },
class: "font-bold px-6 py-3.5 rounded-lg min-h-[48px] transition-colors
#{tudo_completo ? 'bg-green-600 hover:bg-green-500 text-white cursor-pointer' : 'bg-[#2a2a2a] text-gray-600 cursor-not-allowed'}" %>
</div>
<% end %>
</div>
</div>
<% unless tudo_completo %>
<p class="text-gray-500 text-sm mt-2 text-center">
⚠️ Classifique todas as entregas de todos os motoristas para finalizar tudo<% if tem_consolidados && tem_pendentes %> — ou use <strong>“Arquivar pendentes e finalizar”</strong> para fechar só os veículos já consolidados.<% end %>
</p>
<% end %>
</div>