Atualização dos icones para um modelo chapado
This commit is contained in:
@@ -2,19 +2,105 @@
|
||||
module ApplicationHelper
|
||||
include Pagy::Frontend
|
||||
|
||||
# ---------------------------------------------------------------------------
|
||||
# Ícones
|
||||
#
|
||||
# Substituem os emojis antigos (que davam aparência "genérica de IA" e variavam
|
||||
# de forma/cor conforme o sistema operacional). Agora são SVG chapados vindos do
|
||||
# sprite em public/icons.svg (subset do Bootstrap Icons, licença MIT).
|
||||
#
|
||||
# O SVG usa `currentColor`, então a cor vem da classe CSS:
|
||||
# - padrão → laranja da marca (#f97316)
|
||||
# - ícones de status → passe `cor:` para preservar a leitura semântica
|
||||
# (ex.: icone(:sucesso, cor: "text-green-400"))
|
||||
# ---------------------------------------------------------------------------
|
||||
|
||||
# Nome semântico (pt-BR) → id do símbolo no sprite.
|
||||
ICONES = {
|
||||
# Navegação
|
||||
dashboard: "bar-chart-fill", operacoes: "graph-up-arrow", consolidacoes: "box-seam-fill",
|
||||
arquivadas: "folder-fill", painel: "house-fill", usuarios: "people-fill",
|
||||
configuracoes: "gear-fill", auditoria: "search", planilha: "box-arrow-in-down",
|
||||
editar_lancamento: "pencil-fill", sair: "box-arrow-right", menu: "list",
|
||||
# Domínio
|
||||
caminhao: "truck", veiculo: "car-front-fill", motorista: "person-badge-fill",
|
||||
dinheiro: "cash-coin", pagamento: "cash-stack", custo: "cash",
|
||||
consolidado_pago: "briefcase-fill", calendario: "calendar-event", nota_fiscal: "receipt",
|
||||
documento: "file-earmark-text-fill", termo_especial: "clipboard-data-fill",
|
||||
apontamento: "pencil-square", local: "geo-alt-fill", operacao: "hospital-fill",
|
||||
retirada: "box-seam-fill", desconto: "exclamation-triangle-fill",
|
||||
global: "globe2", comparar: "arrow-left-right", pessoa: "person-fill",
|
||||
ticket: "ticket-perforated-fill", tag: "tag-fill", composicao: "puzzle-fill",
|
||||
ranking: "trophy-fill", historico: "clock-history", relogio: "clock-fill",
|
||||
parcial: "hourglass-split", diario: "journal-text", vazio: "inbox",
|
||||
dica: "lightbulb-fill", bonus: "star-fill", extraordinaria: "stars",
|
||||
calor: "fire", foto: "camera-fill", mapa: "map-fill",
|
||||
satelite: "broadcast-pin", escuro: "moon-fill", tela_cheia: "arrows-fullscreen",
|
||||
email: "envelope-fill", telefone: "telephone-fill", chave: "key-fill",
|
||||
# Ações
|
||||
adicionar: "plus-lg", fechar: "x-lg", confirmar: "check-lg",
|
||||
buscar: "search", editar: "pencil-fill", excluir: "trash-fill",
|
||||
arquivar: "archive-fill", restaurar: "arrow-clockwise", salvar: "floppy-fill",
|
||||
imprimir: "printer-fill", visualizar: "eye-fill", baixar: "download",
|
||||
pasta: "folder2-open", travado: "lock-fill", destravado: "unlock-fill",
|
||||
expandir: "chevron-down", recolher: "chevron-left",
|
||||
voltar: "arrow-left", avancar: "arrow-right", estornar: "arrow-counterclockwise",
|
||||
# Status (use sempre com `cor:` semântica)
|
||||
sucesso: "check-circle-fill", alerta: "exclamation-triangle-fill",
|
||||
erro: "x-circle-fill", desconhecido: "question-circle",
|
||||
cancelado: "slash-circle", ponto: "circle-fill", ponto_vazio: "circle"
|
||||
}.freeze
|
||||
|
||||
# Renderiza um ícone do sprite.
|
||||
#
|
||||
# icone(:caminhao) # laranja da marca
|
||||
# icone(:sucesso, cor: "text-green-400") # status verde
|
||||
# icone(:fechar, cor: nil) # herda a cor do elemento pai
|
||||
# icone(:dashboard, titulo: "Painel") # acessível (vira role="img")
|
||||
def icone(nome, cor: "text-brand-laranja", tamanho: "w-[1.05em] h-[1.05em]", classe: nil, titulo: nil)
|
||||
simbolo = ICONES.fetch(nome.to_sym) { nome.to_s }
|
||||
css = ["inline-block align-[-0.125em] shrink-0", tamanho, cor, classe].compact.join(" ")
|
||||
|
||||
tag.svg(class: css, fill: "currentColor", role: (titulo ? "img" : nil),
|
||||
aria: { hidden: (titulo ? nil : true), label: titulo }) do
|
||||
tag.use(href: "/icons.svg##{simbolo}")
|
||||
end
|
||||
end
|
||||
|
||||
# Rótulo "ícone + texto" para link_to / button_to (que recebem o label como
|
||||
# argumento, onde não dá para escrever ERB).
|
||||
#
|
||||
# link_to rotulo(:salvar, 'Salvar rascunho'), caminho, class: '...'
|
||||
#
|
||||
# Atenção: NÃO serve para `f.submit` nem `button_to` sem bloco — ambos geram
|
||||
# <input type="submit">, que não aceita HTML dentro. Nesses casos use
|
||||
# `button_tag`/`button_to ... do`.
|
||||
def rotulo(nome, texto, cor: "text-brand-laranja", tamanho: "w-4 h-4")
|
||||
safe_join([icone(nome, cor: cor, tamanho: tamanho), texto], " ")
|
||||
end
|
||||
|
||||
# Opções [label, valor] para o select de perfil de usuário (form de usuário)
|
||||
def role_options_for_select
|
||||
User::ROLES_LABEL.map { |value, label| [label, value] }
|
||||
end
|
||||
|
||||
# Link de navegação com estado ativo
|
||||
def nav_link_to(label, path, **opts)
|
||||
# Link de navegação com estado ativo.
|
||||
# `icon:` aceita um nome semântico de ICONES; no estado ativo o ícone herda o
|
||||
# preto do fundo laranja, fora dele fica laranja da marca.
|
||||
def nav_link_to(label, path, icon: nil, **opts)
|
||||
active = current_page?(path)
|
||||
css = [
|
||||
"flex items-center gap-3 px-3 py-2.5 rounded-lg text-sm font-medium transition-all min-h-[44px]",
|
||||
"flex items-center gap-2.5 px-3 py-2.5 rounded-lg text-sm font-medium transition-all min-h-[44px]",
|
||||
active ? "bg-orange-500 text-black" : "text-gray-400 hover:bg-[#1a1a1a] hover:text-white"
|
||||
].join(" ")
|
||||
link_to label, path, class: css
|
||||
|
||||
conteudo = if icon
|
||||
safe_join([icone(icon, cor: (active ? "text-black" : "text-brand-laranja"),
|
||||
tamanho: "w-4 h-4"), label])
|
||||
else
|
||||
label
|
||||
end
|
||||
link_to conteudo, path, class: css
|
||||
end
|
||||
|
||||
# Formata moeda BR (milhar com ".", decimais com ","): R$ 1.234,56
|
||||
@@ -22,31 +108,34 @@ module ApplicationHelper
|
||||
number_to_currency(valor.to_f, unit: 'R$ ', separator: ',', delimiter: '.', precision: 2)
|
||||
end
|
||||
|
||||
# Badge de status de consolidação
|
||||
# Badge de status de consolidação.
|
||||
# O ícone herda a cor do texto do badge (cor: nil) para não brigar com o fundo.
|
||||
def badge_status(status)
|
||||
cfg = case status.to_s
|
||||
when 'rascunho' then { cor: 'bg-yellow-500 text-black', icone: '📝', label: 'Rascunho' }
|
||||
when 'finalizada' then { cor: 'bg-green-600 text-white', icone: '✅', label: 'Finalizada' }
|
||||
when 'arquivada' then { cor: 'bg-gray-700 text-gray-300', icone: '📁', label: 'Arquivada' }
|
||||
else { cor: 'bg-gray-800 text-gray-400', icone: '❓', label: status.humanize }
|
||||
when 'rascunho' then { cor: 'bg-yellow-500 text-black', icone: :apontamento, label: 'Rascunho' }
|
||||
when 'finalizada' then { cor: 'bg-green-600 text-white', icone: :sucesso, label: 'Finalizada' }
|
||||
when 'arquivada' then { cor: 'bg-gray-700 text-gray-300', icone: :arquivar, label: 'Arquivada' }
|
||||
else { cor: 'bg-gray-800 text-gray-400', icone: :desconhecido, label: status.humanize }
|
||||
end
|
||||
|
||||
tag.span class: "inline-flex items-center gap-1 px-2.5 py-1 rounded-full text-xs font-bold #{cfg[:cor]}" do
|
||||
"#{cfg[:icone]} #{cfg[:label]}"
|
||||
end
|
||||
badge_com_icone(cfg)
|
||||
end
|
||||
|
||||
# Badge de status de pagamento de uma consolidação (derivado dos motoristas)
|
||||
def badge_pagamento(status)
|
||||
cfg = case status.to_s
|
||||
when 'pago' then { cor: 'bg-green-600 text-white', icone: '💰', label: 'Pago' }
|
||||
when 'parcial' then { cor: 'bg-yellow-500 text-black', icone: '⏳', label: 'Parcial' }
|
||||
when 'pendente' then { cor: 'bg-gray-700 text-gray-300', icone: '🕗', label: 'Pendente' }
|
||||
else { cor: 'bg-gray-800 text-gray-400', icone: '❓', label: status.to_s.humanize }
|
||||
when 'pago' then { cor: 'bg-green-600 text-white', icone: :dinheiro, label: 'Pago' }
|
||||
when 'parcial' then { cor: 'bg-yellow-500 text-black', icone: :parcial, label: 'Parcial' }
|
||||
when 'pendente' then { cor: 'bg-gray-700 text-gray-300', icone: :relogio, label: 'Pendente' }
|
||||
else { cor: 'bg-gray-800 text-gray-400', icone: :desconhecido, label: status.to_s.humanize }
|
||||
end
|
||||
|
||||
tag.span class: "inline-flex items-center gap-1 px-2.5 py-1 rounded-full text-xs font-bold #{cfg[:cor]}" do
|
||||
"#{cfg[:icone]} #{cfg[:label]}"
|
||||
badge_com_icone(cfg)
|
||||
end
|
||||
|
||||
def badge_com_icone(cfg)
|
||||
tag.span class: "inline-flex items-center gap-1.5 px-2.5 py-1 rounded-full text-xs font-bold #{cfg[:cor]}" do
|
||||
safe_join([icone(cfg[:icone], cor: nil, tamanho: "w-3.5 h-3.5"), cfg[:label]])
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
Reference in New Issue
Block a user