Implandação da customização das permissões dos usuarios e das notificaçoes

This commit is contained in:
2026-08-26 17:24:25 -03:00
parent 808c2c7545
commit 5bb5d74e22
71 changed files with 2487 additions and 269 deletions

View File

@@ -40,16 +40,46 @@
placeholder: 'João da Silva' %>
</div>
<%# Perfil %>
<div>
<%= f.label :role, 'Perfil de acesso', class: 'block text-sm font-medium text-gray-300 mb-1.5' %>
<%= f.select :role,
options_for_select(role_options_for_select, usuario.role),
{},
class: 'w-full px-4 py-3 bg-[#0a0a0a] border border-white/10 rounded-xl text-white
focus:outline-none focus:border-[#f97316] focus:ring-1 focus:ring-[#f97316]
transition-colors cursor-pointer' %>
</div>
<%# TIPO DE CONTA x PERFIL DE ACESSO — são coisas diferentes:
• tipo de conta define COMO a pessoa entra e onde ela vive (motorista
entra por PIN e tem painel próprio);
• perfil de acesso define O QUE ela enxerga (Permissao::TODAS).
Antes este select se chamava "Perfil de acesso" e editava `role`.
Os dois só aparecem para quem pode alterar acesso — e nunca na própria
ficha, senão qualquer usuário se promoveria editando o próprio cadastro
(o controller também filtra os campos, não só a tela). %>
<% if pode_alterar_acesso? %>
<div>
<%= f.label :role, 'Tipo de conta', class: 'block text-sm font-medium text-gray-300 mb-1.5' %>
<%= f.select :role,
options_for_select(role_options_for_select, usuario.role),
{},
class: 'w-full px-4 py-3 bg-[#0a0a0a] border border-white/10 rounded-xl text-white
focus:outline-none focus:border-[#f97316] focus:ring-1 focus:ring-[#f97316]
transition-colors cursor-pointer' %>
</div>
<div id="campo-perfil-acesso">
<%= f.label :perfil_acesso_id, 'Perfil de acesso', class: 'block text-sm font-medium text-gray-300 mb-1.5' %>
<%= f.select :perfil_acesso_id,
options_from_collection_for_select(PerfilAcesso.ativos.ordenados, :id, :nome, usuario.perfil_acesso_id),
{ include_blank: 'Sem perfil (usa o padrão do tipo de conta)' },
class: 'w-full px-4 py-3 bg-[#0a0a0a] border border-white/10 rounded-xl text-white
focus:outline-none focus:border-[#f97316] focus:ring-1 focus:ring-[#f97316]
transition-colors cursor-pointer' %>
<p class="text-gray-500 text-xs mt-1.5">
Define o que a pessoa enxerga.
<%= link_to 'Gerenciar perfis', admin_perfis_path, class: 'text-orange-500 hover:underline' %>
</p>
</div>
<% else %>
<div class="bg-[#0a0a0a] border border-white/10 rounded-xl px-4 py-3">
<p class="text-sm text-gray-400">Tipo de conta</p>
<p class="text-white font-semibold"><%= usuario.role_label %></p>
<p class="text-gray-500 text-xs mt-1">Só quem administra usuários altera tipo de conta e perfil de acesso.</p>
</div>
<% end %>
<%# Ativo toggle %>
<div class="flex items-center">
@@ -142,10 +172,16 @@
const fieldsPin = document.getElementById('fields-pin');
if (!roleSelect || !fieldsEmail || !fieldsPin) return;
// Motorista não usa perfil de acesso: o que ele enxerga é o painel próprio,
// governado pelo tipo de conta. Deixar o select à mostra sugeriria que dá
// para liberar telas administrativas para ele.
const campoPerfil = document.getElementById('campo-perfil-acesso');
function toggleFields() {
const motorista = roleSelect.value === 'motorista';
fieldsEmail.classList.toggle('hidden', motorista);
fieldsPin.classList.toggle('hidden', !motorista);
if (campoPerfil) campoPerfil.classList.toggle('hidden', motorista);
}
roleSelect.addEventListener('change', toggleFields);

View File

@@ -29,7 +29,8 @@
<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">Nome</th>
<th class="px-6 py-4 text-left text-xs font-semibold text-gray-400 uppercase tracking-wider">E-mail / PIN</th>
<th class="px-6 py-4 text-left text-xs font-semibold text-gray-400 uppercase tracking-wider">Perfil</th>
<th class="px-6 py-4 text-left text-xs font-semibold text-gray-400 uppercase tracking-wider">Tipo de conta</th>
<th class="px-6 py-4 text-left text-xs font-semibold text-gray-400 uppercase tracking-wider">Perfil de acesso</th>
<th class="px-6 py-4 text-left text-xs font-semibold text-gray-400 uppercase tracking-wider">Status</th>
<th class="px-6 py-4 text-right text-xs font-semibold text-gray-400 uppercase tracking-wider">Ações</th>
</tr>
@@ -56,6 +57,22 @@
<td class="px-6 py-4">
<%= badge_role(usuario.role) %>
</td>
<%# Tipo de conta x perfil são coisas diferentes: o primeiro diz como
a pessoa entra, o segundo o que ela enxerga. Sem perfil, vale o
padrão do tipo de conta — a tela precisa dizer isso, senão parece
que a pessoa está sem acesso nenhum. %>
<td class="px-6 py-4">
<% if usuario.motorista? %>
<span class="text-gray-500 text-sm">—</span>
<% elsif usuario.perfil_acesso %>
<span class="text-white text-sm font-semibold"><%= usuario.perfil_acesso.nome %></span>
<% unless usuario.perfil_acesso.ativo? %>
<span class="block text-red-400 text-xs">perfil desativado</span>
<% end %>
<% else %>
<span class="text-gray-400 text-sm">Padrão do tipo de conta</span>
<% end %>
</td>
<td class="px-6 py-4">
<%= badge_status_usuario(usuario.ativo?) %>
</td>