Romaneio: lista de veículos visível, busca com contador e logo escolhível

Traz para a tela as funções do programa original (Romaneiro PDF), na linha de
design do projeto:
- Veículos deixam de ser um <select> e viram lista visível com a contagem de
  paradas de cada carro — que é a conferência feita antes de imprimir e ficava
  invisível mostrando um veículo por vez. Cada item é link (?veiculo=), então
  sobrevive ao 'voltar' e ao F5. No celular vira faixa horizontal.
- Na mesma coluna: motorista do veículo, 'PDF deste veículo' e 'PDF de TODOS'.
- Busca ganha 'Limpar busca' e contador vivo ('4 de 31 paradas'). A contagem
  saiu do cabeçalho da tabela: dois números para a mesma coisa, um atualizando e
  o outro não, é a divergência que a diretriz 1 proíbe.
- Logo do cabeçalho escolhível (Configuracao 'romaneio_logo', separado do
  empresa_logo — o romaneio é documento do cliente). PNG/JPG até 2MB, gravado em
  storage/logos/ e não em public/, com nome gerado pelo sistema.
This commit is contained in:
2026-08-27 19:20:49 -03:00
parent 7fa2336b35
commit b3464e3acd
11 changed files with 274 additions and 65 deletions

View File

@@ -0,0 +1,78 @@
<%# Coluna "Veículos" — a lista INTEIRA visível, como no programa original.
Antes era um <select> com : resolvia o scroll de 72 carros, mas o operador
não conseguia VER o plano — via um carro por vez e perdia a noção de quantas
paradas cada um tem, que é justamente a conferência que ele faz antes de
mandar imprimir.
Adapta ao dispositivo (diretriz 3): no celular vira faixa horizontal, porque
72 itens empilhados empurrariam a tabela para fora da primeira tela; no
desktop é coluna com rolagem própria, do lado da tabela. %>
<div class="bg-[#111] border border-white/5 rounded-2xl p-4 space-y-3">
<div class="flex items-center justify-between">
<h2 class="text-white font-semibold text-sm">Veículos</h2>
<span class="text-xs text-gray-500"><%= @veiculos.size %> no plano</span>
</div>
<div class="flex lg:flex-col gap-2 overflow-x-auto lg:overflow-x-visible
lg:overflow-y-auto lg:max-h-[46vh] pb-1 lg:pb-0
lg:pr-1 [scrollbar-width:thin]">
<% @veiculos.each do |v| %>
<% atual = v.veiculo == @veiculo %>
<%# Link de verdade (não botão com JS): o veículo vive na query string, então
ele é endereçável, volta com o "voltar" do navegador e sobrevive a um F5. %>
<a href="<%= admin_romaneio_path(@romaneio, veiculo: v.veiculo) %>"
data-romaneio-target="itemVeiculo" data-veiculo="<%= v.veiculo %>"
<%= 'data-atual="1"'.html_safe if atual %>
class="shrink-0 lg:shrink flex items-center justify-between gap-3 min-h-[48px]
px-3 rounded-xl border transition-colors
<%= atual ? 'bg-[#f97316] border-orange-400 text-white font-semibold'
: 'bg-[#1a1a1a] border-white/10 text-gray-300 hover:border-orange-500 hover:text-white' %>">
<span class="whitespace-nowrap"><%= v.veiculo %></span>
<%# A contagem é o que o operador confere: carro sem parada ou com parada
demais é erro de plano, e some quando só um veículo aparece por vez. %>
<span class="text-xs px-2 py-0.5 rounded-lg
<%= atual ? 'bg-black/25' : 'bg-white/5 text-gray-400' %>">
<%= @romaneio.contagem_por_veiculo[v.veiculo].to_i %>
</span>
</a>
<% end %>
</div>
<div class="flex gap-2">
<button type="button" data-action="romaneio#anterior" aria-label="Veículo anterior"
class="flex-1 min-h-[48px] bg-[#1a1a1a] border border-white/10 rounded-xl
text-white hover:bg-[#242424]"></button>
<button type="button" data-action="romaneio#proximo" aria-label="Próximo veículo"
class="flex-1 min-h-[48px] bg-[#1a1a1a] border border-white/10 rounded-xl
text-white hover:bg-[#242424]"></button>
</div>
<div class="pt-1 border-t border-white/5">
<label class="block text-sm font-medium text-gray-300 mb-1.5 mt-3">
Motorista deste veículo
<span class="text-gray-500 font-normal">— só na tela</span>
</label>
<% atual = @veiculos.find { |v| v.veiculo == @veiculo } %>
<input type="text" value="<%= atual&.motorista %>" placeholder="Quem leva este carro"
data-romaneio-target="motorista" data-action="change->romaneio#salvarMotorista"
class="w-full bg-[#1a1a1a] border border-white/10 rounded-xl px-3 py-3 text-white
placeholder-gray-600 focus:outline-none focus:border-orange-500 min-h-[48px]">
<p class="text-xs text-gray-500 mt-1.5">
Não sai impresso — a linha do rodapé é assinada à mão na retirada.
</p>
</div>
<div class="space-y-2 pt-1">
<%= link_to pdf_admin_romaneio_path(@romaneio, veiculo: @veiculo),
target: '_blank', rel: 'noopener',
class: 'w-full min-h-[48px] flex items-center justify-center gap-2 bg-[#1a1a1a]
hover:bg-[#242424] text-white border border-white/10 rounded-xl' do %>
<%= icone :visualizar, cor: nil %> PDF deste veículo
<% end %>
<%= link_to pdf_admin_romaneio_path(@romaneio),
class: 'w-full min-h-[48px] flex items-center justify-center gap-2 bg-[#f97316]
hover:bg-orange-500 text-white font-semibold rounded-xl' do %>
<%= icone :baixar, cor: nil %> PDF de TODOS os veículos
<% end %>
</div>
</div>