, Teste e correçoes

This commit is contained in:
2026-08-28 13:13:10 -03:00
parent 1143ed373b
commit 19a0c7a302
6 changed files with 157 additions and 76 deletions

View File

@@ -1,40 +1,44 @@
<%# Prévia do PDF em POP-UP, com navegação de veículo igual à do carrossel do
motorista (setas grandes + contador "3 de 72").
<%# Prévia do PDF em POP-UP, com navegação entre as folhas no mesmo desenho do
carrossel do motorista (setas grandes + contador "3 de 72").
── POR QUE É CSS PURO E NÃO JAVASCRIPT ────────────────────────────────────
Abrir/fechar sai do `:target`: o botão é um link para `#previa` e o pop-up só
aparece quando ele é o alvo da URL. As setas são links de verdade para
`?veiculo=X#previa`, então trocar de folha mantém o pop-up aberto.
── O ESTADO "ABERTA" MORA NA URL (?previa=1) ──────────────────────────────
Foram três tentativas até aqui, e cada uma quebrou de um jeito:
Isso não é preciosismo: a prévia é a ÚNICA conferência antes de imprimir e
já morreu três vezes junto com o JavaScript (assets 404 no servidor, com a
tela abrindo normal e o botão sem reação). Do jeito atual ela funciona com o
JS quebrado, sem JS, no celular, e continua endereçável — dá para mandar o
link já com a prévia aberta.
1. modal por JavaScript → morreu junto com os assets 404 no servidor: o
botão não fazia NADA e a tela abria normal, sem erro visível;
2. <details> nativo → funcionava, mas não é pop-up e não dava para
navegar entre as folhas sem fechar;
3. :target (#previa) → abria com o JS fora do ar e parava de abrir
quando ele voltava: o Turbo intercepta o clique, revisita a página e o
hash se perde no caminho. Pior dos mundos — funcionava no ambiente
quebrado e falhava no ambiente são.
`loading="lazy"` no iframe: fechado, o pop-up é `display:none` e o navegador
NÃO busca o PDF. É o que preserva a economia de não gerar um documento a cada
carregamento da tela.
Com a prévia na query string nada disso se aplica: é uma página como outra
qualquer, o Turbo trata como navegação normal, funciona sem JavaScript,
sobrevive ao F5 e ao "voltar", e o link pode ser enviado para outra pessoa
já com a folha aberta.
Fechado, este partial não renderiza NADA: o iframe nem existe, então o
servidor não monta um PDF que ninguém pediu (era o custo do desenho
original, que montava o iframe a cada carregamento da tela).
<iframe> e não <embed>/<object>: o CSP está enforcing com `object_src :none`
e sem `frame_src`, então cai em `default_src :self` — o iframe de mesma
origem passa, os outros dois não.
Fechar leva para `#sem-previa`, um id que não existe em lugar nenhum: o
`:target` deixa de casar e o pop-up some sem o salto ao topo que um `href="#"`
causaria. %>
origem passa, os outros dois não. %>
<% nomes = @veiculos.map(&:veiculo) %>
<% posicao = nomes.index(@veiculo) %>
<% anterior = posicao&.positive? ? nomes[posicao - 1] : nil %>
<% proximo = posicao && posicao < nomes.size - 1 ? nomes[posicao + 1] : nil %>
<% fechar = admin_romaneio_path(@romaneio, veiculo: @veiculo) %>
<div id="previa" data-romaneio-target="overlay"
class="hidden target:flex fixed inset-0 z-50 items-center justify-center p-3 sm:p-6
<div data-romaneio-target="overlay"
class="fixed inset-0 z-50 flex items-center justify-center p-3 sm:p-6
bg-black/80 backdrop-blur-sm">
<%# O fundo escuro fecha ao ser clicado — um link cobrindo a área, atrás da
caixa (que é `relative`). Sem isso, só o ✕ fecharia. %>
<a href="#sem-previa" tabindex="-1" aria-label="Fechar prévia" class="absolute inset-0"></a>
<%= link_to '', fechar, tabindex: -1, 'aria-label': 'Fechar prévia',
class: 'absolute inset-0' %>
<div class="relative w-full max-w-6xl h-[92vh] flex flex-col gap-3">
<div class="flex items-center justify-between gap-3">
@@ -46,24 +50,44 @@
pdf_admin_romaneio_path(@romaneio, veiculo: @veiculo),
target: '_blank', rel: 'noopener',
class: 'text-sm text-gray-300 hover:text-white px-3 py-2 rounded-lg hover:bg-white/10' %>
<a href="#sem-previa" aria-label="Fechar prévia"
class="min-w-[48px] min-h-[48px] flex items-center justify-center rounded-xl
bg-[#1a1a1a] border border-white/10 text-white hover:bg-[#242424]">✕</a>
<%= link_to fechar, 'aria-label': 'Fechar prévia',
class: 'min-w-[48px] min-h-[48px] flex items-center justify-center rounded-xl
bg-[#1a1a1a] border border-white/10 text-white hover:bg-[#242424]' do %>
<% end %>
</div>
</div>
<iframe data-romaneio-target="preview" loading="lazy"
<iframe data-romaneio-target="preview"
src="<%= pdf_admin_romaneio_path(@romaneio, veiculo: @veiculo) %>"
class="flex-1 w-full rounded-xl border border-white/10 bg-white"
title="Pré-visualização do romaneio"></iframe>
<%# AVISO SEMPRE VISÍVEL, não um alerta que aparece só no erro: quando o
navegador se recusa a desenhar o PDF, ele não avisa ninguém — o quadro
fica branco e a leitura natural é "o sistema está quebrado". O navegador
tem uma opção, ligada por padrão em algumas instalações, de BAIXAR PDF em
vez de exibir; bloqueador de conteúdo (Brave Shields, uBlock) e bloqueio
de pop-up derrubam o mesmo quadro. Como não dá para detectar isso de
dentro da página (o iframe é opaco por segurança), a saída honesta é
dizer onde fica a alternativa. %>
<p class="text-xs text-gray-400 text-center">
Quadro em branco? O navegador pode estar configurado para <strong>baixar</strong> PDF
em vez de exibir, ou um bloqueador está barrando —
<%= link_to 'abra em outra aba',
pdf_admin_romaneio_path(@romaneio, veiculo: @veiculo),
target: '_blank', rel: 'noopener',
class: 'underline text-gray-300 hover:text-white' %>
ou libere PDF para este site nas permissões (cadeado da barra de endereço).
</p>
<%# Controles no mesmo desenho do carrossel do motorista (redondos, 56px,
próximo em laranja), mas como LINKS: cada folha é uma URL. Na ponta vira
<span> apagado em vez de sumir — botão que some muda o layout no meio da
conferência e o operador perde o alvo do clique. %>
<div class="flex items-center justify-center gap-3">
<% if anterior %>
<%= link_to admin_romaneio_path(@romaneio, veiculo: anterior, anchor: 'previa'),
<%= link_to admin_romaneio_path(@romaneio, veiculo: anterior, previa: 1),
'aria-label': "Folha anterior (#{anterior})",
class: 'w-14 h-14 rounded-full flex items-center justify-center
bg-[#1a1a1a]/90 backdrop-blur border border-white/15 text-white
@@ -83,7 +107,7 @@
</span>
<% if proximo %>
<%= link_to admin_romaneio_path(@romaneio, veiculo: proximo, anchor: 'previa'),
<%= link_to admin_romaneio_path(@romaneio, veiculo: proximo, previa: 1),
'aria-label': "Próxima folha (#{proximo})",
class: 'w-14 h-14 rounded-full flex items-center justify-center
bg-orange-500/90 backdrop-blur border border-orange-400 text-black

View File

@@ -20,7 +20,7 @@
<% 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) %>"
<a href="<%= admin_romaneio_path(@romaneio, veiculo: v.veiculo, previa: (1 if @previa)) %>"
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]
@@ -47,13 +47,13 @@
<% prox_v = pos_v && pos_v < nomes_v.size - 1 ? nomes_v[pos_v + 1] : nil %>
<% base_v = 'flex-1 min-h-[48px] flex items-center justify-center rounded-xl border' %>
<% if ant_v %>
<a href="<%= admin_romaneio_path(@romaneio, veiculo: ant_v) %>" aria-label="Veículo anterior"
<a href="<%= admin_romaneio_path(@romaneio, veiculo: ant_v, previa: (1 if @previa)) %>" aria-label="Veículo anterior"
class="<%= base_v %> bg-[#1a1a1a] border-white/10 text-white hover:bg-[#242424]"></a>
<% else %>
<span class="<%= base_v %> bg-[#1a1a1a]/50 border-white/5 text-gray-600"></span>
<% end %>
<% if prox_v %>
<a href="<%= admin_romaneio_path(@romaneio, veiculo: prox_v) %>" aria-label="Próximo veículo"
<a href="<%= admin_romaneio_path(@romaneio, veiculo: prox_v, previa: (1 if @previa)) %>" aria-label="Próximo veículo"
class="<%= base_v %> bg-[#1a1a1a] border-white/10 text-white hover:bg-[#242424]"></a>
<% else %>
<span class="<%= base_v %> bg-[#1a1a1a]/50 border-white/5 text-gray-600"></span>
@@ -61,9 +61,12 @@
</div>
<div class="pt-4 mt-1 border-t border-white/5">
<%# "Motorista deste veículo — só na tela" não cabe numa linha na coluna
estreita; o complemento vai embaixo, como legenda, em vez de quebrar no
meio do travessão. %>
<label class="block text-sm font-medium text-gray-300 mb-1.5">
Motorista deste veículo
<span class="text-gray-500 font-normal">só na tela</span>
<span class="block text-xs text-gray-500 font-normal">só na tela, não sai impresso</span>
</label>
<% atual = @veiculos.find { |v| v.veiculo == @veiculo } %>
<input type="text" value="<%= atual&.motorista %>" placeholder="Quem leva este carro"
@@ -71,29 +74,38 @@
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.
A linha do rodapé é assinada à mão na retirada.
</p>
</div>
<div class="space-y-3 pt-4 mt-4 border-t border-white/5">
<%# Link, não botão: abre o pop-up da prévia pelo `:target` do CSS (ver
`_previa`), então continua funcionando com o JavaScript fora do ar — foi
o botão daqui que ficou morto três vezes seguidas. %>
<a href="#previa"
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">
<%# Link, não botão: a prévia aberta é a URL `?previa=1` (ver `_previa`),
então isto funciona com o JavaScript fora do ar — foi o botão daqui que
ficou morto três vezes seguidas. %>
<%= link_to admin_romaneio_path(@romaneio, veiculo: @veiculo, previa: 1),
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, espaco: false %> Ver prévia do PDF
</a>
<% end %>
<%= 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 :baixar, cor: nil, espaco: false %> PDF deste veículo
<% end %>
<%# Rótulo em DUAS linhas de propósito. "PDF de TODOS os veículos" numa linha
só não cabe nos 260px da coluna: quebrava sozinho e deixava o ícone
pendurado num degrau ao lado do texto. Aqui a quebra é intencional — o
ícone fica centrado na altura e a contagem vira a segunda linha, que
ainda informa quantas folhas saem. %>
<%= 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, espaco: false %> PDF de TODOS os veículos
class: 'w-full min-h-[56px] flex items-center justify-center gap-2.5 px-3 py-2
bg-[#f97316] hover:bg-orange-500 text-white rounded-xl text-left' do %>
<%= icone :baixar, cor: nil, espaco: false, classe: 'shrink-0' %>
<span class="leading-tight">
<span class="block font-semibold">PDF de todos</span>
<span class="block text-xs text-white/80"><%= @veiculos.size %> veículos, uma folha cada</span>
</span>
<% end %>
</div>
</div>

View File

@@ -1,10 +1,9 @@
<%# app/views/admin/romaneios/show.html.erb
Editor do romaneio: veículos à esquerda, tabela editável à direita, e o PDF
REAL num pop-up com navegação entre as folhas (partial `_previa`, que explica
por que abrir/fechar/trocar de folha é CSS puro e não JavaScript). %>
por que a prévia aberta é estado na URL e não estado de JavaScript). %>
<div class="space-y-5"
data-controller="romaneio"
data-action="hashchange@window->romaneio#aoTrocarHash"
data-romaneio-url-value="<%= admin_romaneio_path(@romaneio) %>"
data-romaneio-pdf-url-value="<%= pdf_admin_romaneio_path(@romaneio) %>"
data-romaneio-veiculo-value="<%= @veiculo %>">
@@ -81,8 +80,9 @@
</div>
</div>
<%# Pop-up da prévia: FORA da grade porque cobre a tela inteira quando
aberto (`:target`). Fechado não ocupa espaço nem busca o PDF. %>
<%= render 'previa' %>
<%# Pop-up da prévia: FORA da grade porque cobre a tela inteira. Só existe no
HTML quando ?previa=1 — fechado, nem o iframe é criado, então o servidor
não monta um PDF que ninguém pediu (ver `_previa`). %>
<%= render 'previa' if @previa %>
<% end %>
</div>