Atualização dos icones para um modelo chapado

This commit is contained in:
2026-07-20 15:08:09 -03:00
parent 7d3753f9c5
commit 42d06c50a7
34 changed files with 550 additions and 337 deletions

View File

@@ -1,7 +1,7 @@
<%# app/views/admin/auditoria_logs/index.html.erb %>
<% content_for :title, 'Auditoria' %>
<h1 class="text-2xl font-bold text-white mb-6">🔍 Auditoria</h1>
<h1 class="text-2xl font-bold text-white mb-6 flex items-center gap-2"><%= icone :auditoria %> Auditoria</h1>
<%= form_with url: admin_auditoria_logs_path, method: :get,
class: 'bg-[#1a1a1a] border border-[#2a2a2a] rounded-xl p-4 mb-6 flex flex-wrap gap-3' do %>

View File

@@ -10,7 +10,7 @@
<%# Pilares de preço %>
<div>
<h2 class="text-lg font-semibold text-white mb-4">💰 Pilares de Preço</h2>
<h2 class="text-lg font-semibold text-white mb-4 flex items-center gap-2"><%= icone :dinheiro %> Pilares de Preço</h2>
<div class="grid grid-cols-1 sm:grid-cols-2 lg:grid-cols-4 gap-4">
<% @configuracoes.each do |cfg| %>
<div class="bg-[#1a1a1a] rounded-2xl border border-white/5 p-6 group relative">
@@ -39,7 +39,7 @@
<%# Informações do banco externo %>
<div class="bg-[#1a1a1a] rounded-2xl border border-white/5 p-6">
<h2 class="text-lg font-semibold text-white mb-4">🗄️ Banco de Dados Externo</h2>
<h2 class="text-lg font-semibold text-white mb-4 flex items-center gap-2"><%= icone :arquivar %> Banco de Dados Externo</h2>
<div class="grid grid-cols-1 sm:grid-cols-3 gap-4">
<div class="p-4 bg-[#0a0a0a] rounded-xl border border-white/5">
<p class="text-gray-400 text-xs mb-1">Tabela monitorada</p>

View File

@@ -20,8 +20,8 @@
<%# Aviso de sincronização %>
<div class="p-4 bg-amber-900/20 border border-amber-500/40 rounded-xl text-amber-200/90 text-sm flex items-start gap-2">
<span class="text-base leading-none">⚠️</span>
<p>As alterações são gravadas no <strong>SimpliRoute na hora</strong> (cada campo salva ao confirmar ),
<%= icone :alerta, cor: nil, tamanho: 'w-4 h-4 mt-0.5' %>
<p>As alterações são gravadas no <strong>SimpliRoute na hora</strong> (cada campo salva ao confirmar <%= icone :confirmar, cor: nil, tamanho: 'w-3 h-3' %>),
mas o painel e as consolidações só refletem <strong>após a próxima sincronização</strong> da base de
rastreio. Toda alteração fica registrada na auditoria.</p>
</div>
@@ -57,15 +57,15 @@
<div class="flex flex-wrap gap-2 mt-2 text-xs text-gray-500">
<span class="px-2 py-0.5 rounded-full bg-white/5">NF <span id="c-nf">—</span></span>
<span class="px-2 py-0.5 rounded-full bg-white/5">Visita <span id="c-id">—</span></span>
<span class="px-2 py-0.5 rounded-full bg-white/5">🚚 <span id="c-motorista">—</span></span>
<span class="px-2 py-0.5 rounded-full bg-white/5">🚗 <span id="c-veiculo">—</span></span>
<span class="px-2 py-0.5 rounded-full bg-white/5">📞 <span id="c-telefone">—</span></span>
<span class="px-2 py-0.5 rounded-full bg-white/5"><%= icone :caminhao %> <span id="c-motorista">—</span></span>
<span class="px-2 py-0.5 rounded-full bg-white/5"><%= icone :veiculo %> <span id="c-veiculo">—</span></span>
<span class="px-2 py-0.5 rounded-full bg-white/5"><%= icone :telefone %> <span id="c-telefone">—</span></span>
</div>
</div>
<button id="btn-historico" type="button"
class="px-4 py-2.5 bg-[#1a1a1a] hover:bg-[#252525] border border-white/10 text-gray-200
text-sm font-semibold rounded-xl transition-colors whitespace-nowrap">
🕑 Histórico
<%= icone :historico %> Histórico
</button>
</div>
@@ -96,9 +96,9 @@
<div id="modal-hist-overlay" class="absolute inset-0 bg-black/70"></div>
<div class="relative bg-[#151515] border border-white/10 rounded-2xl w-full max-w-2xl max-h-[85vh] flex flex-col">
<div class="flex items-center justify-between p-4 border-b border-white/5">
<h3 class="text-white font-bold">🕑 Histórico de alterações</h3>
<h3 class="text-white font-bold flex items-center gap-2"><%= icone :historico %> Histórico de alterações</h3>
<button id="modal-hist-fechar" type="button"
class="w-9 h-9 rounded-lg bg-white/5 hover:bg-white/10 text-gray-300"></button>
class="w-9 h-9 rounded-lg bg-white/5 hover:bg-white/10 text-gray-300" aria-label="Fechar"><%= icone :fechar, cor: nil, tamanho: 'w-4 h-4' %></button>
</div>
<div id="modal-hist-corpo" class="p-4 overflow-y-auto space-y-5 text-sm">
<p class="text-gray-400">Carregando…</p>
@@ -121,12 +121,18 @@
let visita = null; // estado atual do lançamento carregado
// ── Config dos campos editáveis ─────────────────────────────
// Ícone do sprite (public/icons.svg). fill=currentColor -> herda a cor do badge.
function ico(id, cls) {
return '<svg class="' + (cls || 'w-3.5 h-3.5') + '" fill="currentColor" ' +
'style="display:inline-block;vertical-align:-2px"><use href="/icons.svg#' + id + '"></use></svg>';
}
const STATUS = {
completed: { label: 'Completa', cls: 'bg-green-600 text-white', icone: '' },
failed: { label: 'Falha', cls: 'bg-red-600 text-white', icone: '' },
pending: { label: 'Pendente', cls: 'bg-yellow-500 text-black', icone: '🕗' },
partial: { label: 'Parcial', cls: 'bg-blue-600 text-white', icone: '◐' },
canceled: { label: 'Cancelada', cls: 'bg-gray-700 text-gray-300', icone: '🚫' }
completed: { label: 'Completa', cls: 'bg-green-600 text-white', icone: 'check-circle-fill' },
failed: { label: 'Falha', cls: 'bg-red-600 text-white', icone: 'x-circle-fill' },
pending: { label: 'Pendente', cls: 'bg-yellow-500 text-black', icone: 'clock-fill' },
partial: { label: 'Parcial', cls: 'bg-blue-600 text-white', icone: 'hourglass-split' },
canceled: { label: 'Cancelada', cls: 'bg-gray-700 text-gray-300', icone: 'slash-circle' }
};
const CAMPOS = [
{ campo: 'status', label: 'Status', tipo: 'status' },
@@ -190,10 +196,10 @@
}
function renderBadge() {
const cfg = STATUS[visita.status] || { label: visita.status || '—', cls: 'bg-gray-800 text-gray-400', icone: '' };
const cfg = STATUS[visita.status] || { label: visita.status || '—', cls: 'bg-gray-800 text-gray-400', icone: 'question-circle' };
const b = document.getElementById('c-badge');
b.className = 'inline-flex items-center gap-1 px-2.5 py-1 rounded-full text-xs font-bold ' + cfg.cls;
b.textContent = cfg.icone + ' ' + cfg.label;
b.innerHTML = ico(cfg.icone) + ' ' + esc(cfg.label);
}
function renderFotos() {
@@ -207,7 +213,7 @@
} else {
wrap.innerHTML =
'<div class="w-full h-52 rounded-xl border border-dashed border-white/10 flex items-center justify-center ' +
'text-gray-600 text-sm">📷 Sem foto da fachada para esta entrega</div>';
'text-gray-600 text-sm">' + ico('camera-fill') + ' Sem foto da fachada para esta entrega</div>';
}
const extras = [...(visita.pictures || [])];
@@ -257,7 +263,7 @@
'<p class="text-xs text-gray-500 mb-0.5">' + esc(def.label) + '</p>' +
'<div class="flex items-start justify-between gap-2">' +
'<p class="texto-valor text-sm text-white break-words min-h-[20px]">' + esc(valorExibicao(def)) + '</p>' +
'<span class="text-gray-600 group-hover:text-orange-400 text-sm" title="Editar">✏️</span>' +
'<span class="text-gray-600 group-hover:text-orange-400" title="Editar">' + ico('pencil-fill') + '</span>' +
'</div>';
div.onclick = () => abrirEdicao(div, def);
if (flash) {
@@ -297,8 +303,8 @@
'<p class="text-xs text-orange-400 mb-1">' + esc(def.label) + '</p>' +
editorHtml +
'<div class="flex items-center gap-2 mt-2">' +
'<button type="button" class="btn-ok px-3 py-1.5 bg-green-600 hover:bg-green-500 text-white text-xs font-bold rounded-lg"> Salvar</button>' +
'<button type="button" class="btn-cancelar px-3 py-1.5 bg-white/5 hover:bg-white/10 text-gray-300 text-xs rounded-lg"> Cancelar</button>' +
'<button type="button" class="btn-ok px-3 py-1.5 bg-green-600 hover:bg-green-500 text-white text-xs font-bold rounded-lg">' + ico('check-lg', 'w-3 h-3') + ' Salvar</button>' +
'<button type="button" class="btn-cancelar px-3 py-1.5 bg-white/5 hover:bg-white/10 text-gray-300 text-xs rounded-lg">' + ico('x-lg', 'w-3 h-3') + ' Cancelar</button>' +
'<span class="msg-salvando hidden text-xs text-gray-400">Salvando…</span>' +
'</div>' +
'<p class="msg-erro hidden mt-1.5 text-xs text-red-400"></p>';
@@ -388,7 +394,7 @@
function htmlHistorico(data) {
let html = '<div>' +
'<p class="text-xs font-semibold text-gray-500 uppercase tracking-wider mb-2">📒 Nosso sistema (auditoria)</p>';
'<p class="text-xs font-semibold text-gray-500 uppercase tracking-wider mb-2">' + ico('journal-text') + ' Nosso sistema (auditoria)</p>';
const interno = (data.interno || []);
if (!interno.length) {
html += '<p class="text-gray-500">Nenhuma alteração registrada pelo sistema.</p>';
@@ -400,14 +406,14 @@
' → <span class="text-green-300">' + esc(fmtValor(campo, l.para[campo])) + '</span></li>').join('');
return '<div class="bg-[#1a1a1a] border border-white/5 rounded-xl p-3 mb-2">' +
'<div class="flex items-center justify-between text-xs text-gray-500 mb-1.5">' +
'<span>👤 ' + esc(l.usuario) + '</span><span>' + esc(l.quando) + '</span>' +
'<span>' + ico('person-fill') + ' ' + esc(l.usuario) + '</span><span>' + esc(l.quando) + '</span>' +
'</div>' +
'<ul class="space-y-0.5 text-xs">' + (mudancas || '<li class="text-gray-500">—</li>') + '</ul>' +
'</div>';
}).join('');
}
html += '</div><div>' +
'<p class="text-xs font-semibold text-gray-500 uppercase tracking-wider mb-2">🌐 SimpliRoute (API)</p>';
'<p class="text-xs font-semibold text-gray-500 uppercase tracking-wider mb-2">' + ico('globe2') + ' SimpliRoute (API)</p>';
const api = (data.api || []);
if (!api.length) {
html += '<p class="text-gray-500">Sem registros de histórico na API do SimpliRoute.</p>';

View File

@@ -43,7 +43,7 @@
<button type="submit"
class="px-6 py-3 bg-[#f97316] hover:bg-orange-500 text-white font-semibold rounded-xl
transition-colors min-h-[48px] whitespace-nowrap">
📥 Baixar planilha
<%= icone :baixar, cor: nil %> Baixar planilha
</button>
<% end %>
<% end %>

View File

@@ -103,7 +103,7 @@
<% if @usuarios.empty? %>
<tr>
<td colspan="5" class="px-6 py-16 text-center text-gray-500">
<div class="text-4xl mb-3">👥</div>
<div class="mb-3"><%= icone :usuarios, tamanho: 'w-10 h-10', cor: 'text-gray-600' %></div>
<p>Nenhum usuário encontrado.</p>
</td>
</tr>