Atualização para que possa mandar mesagens do Zap para grupos
This commit is contained in:
@@ -1,95 +1,142 @@
|
||||
<% ctx = { status: params[:status], canal: params[:canal] }.compact_blank %>
|
||||
<%
|
||||
# Pílula de filtro: uma só definição para os dois grupos (situação e canal),
|
||||
# senão o estilo do "ativo" fatalmente diverge entre eles com o tempo.
|
||||
pilula = lambda do |ativo|
|
||||
base = 'px-4 py-2 rounded-xl text-sm border transition-colors'
|
||||
ativo ? "#{base} bg-[#f97316] text-white border-[#f97316] font-semibold"
|
||||
: "#{base} bg-[#0a0a0a] text-gray-400 border-white/10 hover:border-white/20 hover:text-white"
|
||||
end
|
||||
%>
|
||||
<div class="space-y-6">
|
||||
|
||||
<div>
|
||||
<h1 class="text-2xl font-bold text-white">Envios</h1>
|
||||
<h1 class="text-2xl font-bold text-white flex items-center gap-2">
|
||||
<%= icone :historico, espaco: false %> Envios
|
||||
</h1>
|
||||
<p class="text-gray-400 text-sm mt-0.5">
|
||||
O que saiu, para quem e se chegou. Uma falha de envio nunca trava o fechamento —
|
||||
então é aqui que ela aparece.
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<div class="flex flex-wrap items-center gap-2">
|
||||
<% [['', 'Todos'], ['enviado', 'Enviados'], ['falhou', 'Falhados'], ['pendente', 'Pendentes']].each do |valor, rotulo| %>
|
||||
<% ativo = params[:status].to_s == valor %>
|
||||
<%= link_to rotulo, admin_envios_path(ctx.merge(status: valor.presence).compact), data: { turbo: false },
|
||||
class: "px-3 py-2 rounded-xl text-sm border #{ativo ? 'bg-orange-500 text-black border-orange-500 font-bold' : 'bg-[#1a1a1a] text-gray-300 border-white/10 hover:border-orange-500'}" %>
|
||||
<% end %>
|
||||
<span class="text-gray-600">|</span>
|
||||
<% [['', 'Todos os canais'], ['whatsapp', 'WhatsApp'], ['email', 'E-mail']].each do |valor, rotulo| %>
|
||||
<% ativo = params[:canal].to_s == valor %>
|
||||
<%= link_to rotulo, admin_envios_path(ctx.merge(canal: valor.presence).compact), data: { turbo: false },
|
||||
class: "px-3 py-2 rounded-xl text-sm border #{ativo ? 'bg-orange-500 text-black border-orange-500 font-bold' : 'bg-[#1a1a1a] text-gray-300 border-white/10 hover:border-orange-500'}" %>
|
||||
<% end %>
|
||||
<%= render 'shared/flash' %>
|
||||
|
||||
<%# Filtros %>
|
||||
<div class="bg-[#1a1a1a] rounded-2xl border border-white/5 p-4 flex flex-wrap items-center gap-4">
|
||||
<div class="flex flex-wrap items-center gap-2">
|
||||
<span class="text-xs font-semibold text-gray-500 uppercase tracking-wider mr-1">Situação</span>
|
||||
<% [['', 'Todos'], ['enviado', 'Enviados'], ['falhou', 'Falhados'], ['pendente', 'Pendentes']].each do |valor, rotulo| %>
|
||||
<%= link_to rotulo, admin_envios_path(ctx.merge(status: valor.presence).compact),
|
||||
data: { turbo: false }, class: pilula.call(params[:status].to_s == valor) %>
|
||||
<% end %>
|
||||
</div>
|
||||
|
||||
<span class="hidden sm:block w-px h-6 bg-white/10"></span>
|
||||
|
||||
<div class="flex flex-wrap items-center gap-2">
|
||||
<span class="text-xs font-semibold text-gray-500 uppercase tracking-wider mr-1">Canal</span>
|
||||
<% [['', 'Todos'], ['whatsapp', 'WhatsApp'], ['email', 'E-mail']].each do |valor, rotulo| %>
|
||||
<%= link_to rotulo, admin_envios_path(ctx.merge(canal: valor.presence).compact),
|
||||
data: { turbo: false }, class: pilula.call(params[:canal].to_s == valor) %>
|
||||
<% end %>
|
||||
</div>
|
||||
|
||||
<% if @total_falhas.positive? %>
|
||||
<span class="ml-auto text-sm text-red-400"><%= @total_falhas %> falha(s) neste filtro</span>
|
||||
<span class="ml-auto inline-flex items-center gap-1.5 px-2.5 py-1 rounded-full text-xs font-bold
|
||||
bg-red-500/15 border border-red-500/30 text-red-300">
|
||||
<%= icone :erro, cor: nil, tamanho: 'w-3.5 h-3.5', espaco: false %>
|
||||
<%= @total_falhas %> falha(s) neste filtro
|
||||
</span>
|
||||
<% end %>
|
||||
</div>
|
||||
|
||||
<%# Tabela %>
|
||||
<div class="bg-[#1a1a1a] rounded-2xl border border-white/5 overflow-hidden">
|
||||
<% if @envios.empty? %>
|
||||
<p class="px-6 py-10 text-center text-gray-500 text-sm">Nenhum envio registrado ainda.</p>
|
||||
<% else %>
|
||||
<div class="overflow-x-auto">
|
||||
<table class="w-full text-sm">
|
||||
<thead class="bg-white/5 text-gray-400 text-xs uppercase tracking-wider">
|
||||
<tr>
|
||||
<th class="text-left px-6 py-3 font-medium">Quando</th>
|
||||
<th class="text-left px-4 py-3 font-medium">Evento</th>
|
||||
<th class="text-left px-4 py-3 font-medium">Destinatário</th>
|
||||
<th class="text-left px-4 py-3 font-medium">Canal</th>
|
||||
<th class="text-left px-4 py-3 font-medium">Situação</th>
|
||||
<th class="text-left px-4 py-3 font-medium">Mensagem</th>
|
||||
<div class="overflow-x-auto">
|
||||
<table class="w-full">
|
||||
<thead>
|
||||
<tr class="border-b border-white/10">
|
||||
<th class="px-6 py-4 text-left text-xs font-semibold text-gray-400 uppercase tracking-wider">Quando</th>
|
||||
<th class="px-6 py-4 text-left text-xs font-semibold text-gray-400 uppercase tracking-wider">Evento</th>
|
||||
<th class="px-6 py-4 text-left text-xs font-semibold text-gray-400 uppercase tracking-wider">Destinatário</th>
|
||||
<th class="px-6 py-4 text-left text-xs font-semibold text-gray-400 uppercase tracking-wider">Canal</th>
|
||||
<th class="px-6 py-4 text-left text-xs font-semibold text-gray-400 uppercase tracking-wider">Situação</th>
|
||||
<th class="px-6 py-4 text-left text-xs font-semibold text-gray-400 uppercase tracking-wider">Mensagem</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody class="divide-y divide-white/5">
|
||||
<% @envios.each do |envio| %>
|
||||
<tr class="hover:bg-white/5 transition-colors align-top">
|
||||
<td class="px-6 py-4 text-gray-400 text-sm whitespace-nowrap">
|
||||
<%= envio.created_at.strftime('%d/%m/%Y') %>
|
||||
<span class="block text-xs text-gray-600"><%= envio.created_at.strftime('%H:%M') %></span>
|
||||
</td>
|
||||
<td class="px-6 py-4 text-gray-300 text-sm"><%= envio.evento_notificacao&.nome || '—' %></td>
|
||||
<td class="px-6 py-4">
|
||||
<span class="text-white text-sm"><%= envio.contato&.nome || envio.user&.nome || '—' %></span>
|
||||
<span class="block text-xs text-gray-500 font-mono mt-0.5"><%= envio.destino %></span>
|
||||
</td>
|
||||
<td class="px-6 py-4">
|
||||
<% wpp = envio.canal == 'whatsapp' %>
|
||||
<span class="inline-flex items-center gap-1.5 px-2.5 py-1 rounded-full text-xs font-bold
|
||||
<%= wpp ? 'bg-green-500/15 border border-green-500/30 text-green-300'
|
||||
: 'bg-blue-500/15 border border-blue-500/30 text-blue-300' %>">
|
||||
<%= icone(wpp ? :telefone : :email, cor: nil, tamanho: 'w-3.5 h-3.5', espaco: false) %>
|
||||
<%= wpp ? 'WhatsApp' : 'E-mail' %>
|
||||
</span>
|
||||
</td>
|
||||
<td class="px-6 py-4">
|
||||
<% cfg = case envio.status
|
||||
when 'enviado' then { cor: 'bg-green-600 text-white', icone: :sucesso, label: 'Enviado' }
|
||||
when 'falhou' then { cor: 'bg-red-600 text-white', icone: :erro, label: 'Falhou' }
|
||||
else { cor: 'bg-yellow-500 text-black', icone: :relogio, label: envio.status.to_s.capitalize }
|
||||
end %>
|
||||
<%= badge_com_icone(cfg) %>
|
||||
<% if envio.falhou? && envio.erro.present? %>
|
||||
<span class="block text-xs text-red-300/80 max-w-[22rem] mt-1.5"><%= envio.erro.truncate(160) %></span>
|
||||
<% end %>
|
||||
</td>
|
||||
<td class="px-6 py-4 text-gray-400 text-sm max-w-[24rem]">
|
||||
<span class="block truncate" title="<%= envio.corpo %>"><%= envio.corpo.to_s.truncate(90) %></span>
|
||||
</td>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody class="divide-y divide-white/5">
|
||||
<% @envios.each do |envio| %>
|
||||
<tr class="hover:bg-white/5 align-top">
|
||||
<td class="px-6 py-2.5 text-gray-400 whitespace-nowrap"><%= envio.created_at.strftime('%d/%m/%Y %H:%M') %></td>
|
||||
<td class="px-4 py-2.5 text-gray-300"><%= envio.evento_notificacao&.nome || '—' %></td>
|
||||
<td class="px-4 py-2.5">
|
||||
<span class="text-white"><%= envio.contato&.nome || envio.user&.nome || '—' %></span>
|
||||
<span class="block text-xs text-gray-500 font-mono"><%= envio.destino %></span>
|
||||
</td>
|
||||
<td class="px-4 py-2.5 text-gray-300"><%= envio.canal == 'whatsapp' ? 'WhatsApp' : 'E-mail' %></td>
|
||||
<td class="px-4 py-2.5">
|
||||
<% cor = { 'enviado' => 'text-green-400', 'falhou' => 'text-red-400' }.fetch(envio.status, 'text-yellow-400') %>
|
||||
<span class="<%= cor %>"><%= envio.status.capitalize %></span>
|
||||
<% if envio.falhou? && envio.erro.present? %>
|
||||
<span class="block text-xs text-red-300/80 max-w-[22rem]"><%= envio.erro.truncate(160) %></span>
|
||||
<% end %>
|
||||
</td>
|
||||
<td class="px-4 py-2.5 text-gray-400 max-w-[24rem]">
|
||||
<span class="block truncate" title="<%= envio.corpo %>"><%= envio.corpo.to_s.truncate(90) %></span>
|
||||
</td>
|
||||
</tr>
|
||||
<% end %>
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
<% end %>
|
||||
|
||||
<% if @pagy.pages > 1 %>
|
||||
<% pag = ->(p) { admin_envios_path(ctx.merge(page: p)) } %>
|
||||
<nav class="flex items-center justify-center gap-1.5 py-4 flex-wrap border-t border-white/5">
|
||||
<% if @pagy.prev %>
|
||||
<%= link_to '‹', pag.call(@pagy.prev), data: { turbo: false },
|
||||
class: 'min-w-[40px] min-h-[40px] flex items-center justify-center rounded-lg border border-[#2a2a2a] text-white hover:border-orange-500' %>
|
||||
<% if @envios.empty? %>
|
||||
<tr>
|
||||
<td colspan="6" class="px-6 py-16 text-center text-gray-500">
|
||||
<div class="mb-3"><%= icone :vazio, tamanho: 'w-10 h-10', cor: 'text-gray-600', espaco: false %></div>
|
||||
<p>Nenhum envio registrado ainda.</p>
|
||||
</td>
|
||||
</tr>
|
||||
<% end %>
|
||||
<% @pagy.series.each do |item| %>
|
||||
<% if item == :gap %>
|
||||
<span class="px-2 text-gray-500">…</span>
|
||||
<% elsif item.is_a?(String) %>
|
||||
<span class="min-w-[40px] min-h-[40px] flex items-center justify-center rounded-lg bg-orange-500 text-black font-bold"><%= item %></span>
|
||||
<% else %>
|
||||
<%= link_to item, pag.call(item), data: { turbo: false },
|
||||
class: 'min-w-[40px] min-h-[40px] flex items-center justify-center rounded-lg border border-[#2a2a2a] text-white hover:border-orange-500' %>
|
||||
<% end %>
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
|
||||
<% if @envios.any? && @pagy.pages > 1 %>
|
||||
<% pag = ->(p) { admin_envios_path(ctx.merge(page: p)) } %>
|
||||
<nav class="flex items-center justify-center gap-1.5 px-6 py-4 flex-wrap border-t border-white/10">
|
||||
<% if @pagy.prev %>
|
||||
<%= link_to '‹', pag.call(@pagy.prev), data: { turbo: false },
|
||||
class: 'min-w-[40px] min-h-[40px] flex items-center justify-center rounded-lg border border-white/10 text-white hover:border-[#f97316] transition-colors' %>
|
||||
<% end %>
|
||||
<% @pagy.series.each do |item| %>
|
||||
<% if item == :gap %>
|
||||
<span class="px-2 text-gray-500">…</span>
|
||||
<% elsif item.is_a?(String) %>
|
||||
<span class="min-w-[40px] min-h-[40px] flex items-center justify-center rounded-lg bg-[#f97316] text-white font-bold"><%= item %></span>
|
||||
<% else %>
|
||||
<%= link_to item, pag.call(item), data: { turbo: false },
|
||||
class: 'min-w-[40px] min-h-[40px] flex items-center justify-center rounded-lg border border-white/10 text-white hover:border-[#f97316] transition-colors' %>
|
||||
<% end %>
|
||||
<% if @pagy.next %>
|
||||
<%= link_to '›', pag.call(@pagy.next), data: { turbo: false },
|
||||
class: 'min-w-[40px] min-h-[40px] flex items-center justify-center rounded-lg border border-[#2a2a2a] text-white hover:border-orange-500' %>
|
||||
<% end %>
|
||||
</nav>
|
||||
<% end %>
|
||||
<% end %>
|
||||
<% if @pagy.next %>
|
||||
<%= link_to '›', pag.call(@pagy.next), data: { turbo: false },
|
||||
class: 'min-w-[40px] min-h-[40px] flex items-center justify-center rounded-lg border border-white/10 text-white hover:border-[#f97316] transition-colors' %>
|
||||
<% end %>
|
||||
</nav>
|
||||
<% end %>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
Reference in New Issue
Block a user