151 lines
9.7 KiB
HTML
151 lines
9.7 KiB
HTML
|
|
{% extends "base.html" %}
|
||
|
|
|
||
|
|
{% block title %}Todas as Solicitações - SGMP{% endblock %}
|
||
|
|
|
||
|
|
{% block css %}
|
||
|
|
<style>
|
||
|
|
.filter-pill.active { background-color: #2563eb; color: white; border-color: #2563eb; font-weight: 600; }
|
||
|
|
.custom-table { table-layout: fixed; }
|
||
|
|
.custom-table th:nth-child(1) { width: 18%; } .custom-table th:nth-child(2), .custom-table th:nth-child(3) { width: 18%; }
|
||
|
|
.custom-table th:nth-child(4), .custom-table th:nth-child(5) { width: 12%; } .custom-table th:nth-child(6) { width: 22%; }
|
||
|
|
.status-RASCUNHO { background: #f3f4f6; color: #4b5563; }
|
||
|
|
.status-AGUARDANDO_HEAD { background: #fefce8; color: #a16207; }
|
||
|
|
.status-ENVIADA { background: #eff6ff; color: #1d4ed8; }
|
||
|
|
.status-APROVADA_GG, .status-APROVADA_CONTROLADORIA { background: #f0fdf4; color: #15803d; }
|
||
|
|
.status-AGUARDANDO_DIRETORIA { background: #fefce8; color: #a16207; }
|
||
|
|
.status-FINALIZADA, .status-APROVADA_DIRETORIA { background: #ecfdf5; color: #047857; }
|
||
|
|
.status-REPROVADA { background: #fef2f2; color: #b91c1c; }
|
||
|
|
#no-results-message { display: none; }
|
||
|
|
</style>
|
||
|
|
{% endblock %}
|
||
|
|
|
||
|
|
{% block content %}
|
||
|
|
<div class="page-header mb-6">
|
||
|
|
<h1 class="text-2xl font-bold text-slate-800 mb-1">Todas as Solicitações</h1>
|
||
|
|
<p class="text-slate-500 text-base max-w-xl">Acompanhe, filtre e analise todas as solicitações do sistema de forma rápida e centralizada.</p>
|
||
|
|
</div>
|
||
|
|
|
||
|
|
<div class="control-panel bg-white p-4 md:p-6 rounded-lg shadow border border-slate-200 mb-8">
|
||
|
|
<div class="filters-header flex flex-wrap justify-between items-center gap-4 mb-4">
|
||
|
|
<h2 class="text-base font-semibold text-slate-800 m-0">Filtros</h2>
|
||
|
|
<div class="search-box relative min-w-[280px]">
|
||
|
|
<svg class="absolute left-3 top-1/2 -translate-y-1/2 w-[18px] h-[18px] text-slate-500" xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor"><path stroke-linecap="round" stroke-linejoin="round" d="M21 21l-5.197-5.197m0 0A7.5 7.5 0 105.196 5.196a7.5 7.5 0 0010.607 10.607z" /></svg>
|
||
|
|
<input type="text" id="searchInput" class="search-input w-full py-2.5 pl-10 pr-3 border border-slate-200 rounded-md text-sm focus:outline-none focus:border-primary focus:ring-2 focus:ring-primary/20" placeholder="Pesquisar por nome, tipo ou ID...">
|
||
|
|
</div>
|
||
|
|
</div>
|
||
|
|
<div class="filter-pills flex flex-wrap gap-2 border-t border-slate-200 pt-4">
|
||
|
|
<button type="button" class="filter-pill active px-3 py-1.5 rounded-full text-xs font-medium border border-slate-200 text-slate-500 hover:bg-slate-100 hover:border-slate-300 hover:text-slate-800 transition-colors cursor-pointer" data-status="todos">Todos</button>
|
||
|
|
{% for valor, label in status_choices %}
|
||
|
|
<button type="button" class="filter-pill px-3 py-1.5 rounded-full text-xs font-medium border border-slate-200 text-slate-500 hover:bg-slate-100 hover:border-slate-300 hover:text-slate-800 transition-colors cursor-pointer" data-status="{{ valor }}">{{ label }}</button>
|
||
|
|
{% endfor %}
|
||
|
|
<button type="button" id="clearFilters" class="clear-filters bg-transparent border-none text-primary font-medium cursor-pointer text-sm py-1 px-1 hover:underline">Limpar Filtros</button>
|
||
|
|
</div>
|
||
|
|
</div>
|
||
|
|
|
||
|
|
{% if solicitacoes %}
|
||
|
|
<div class="table-container bg-white rounded-lg shadow border border-slate-200 overflow-x-auto max-w-full">
|
||
|
|
<table class="custom-table w-full min-w-0 border-collapse">
|
||
|
|
<thead>
|
||
|
|
<tr>
|
||
|
|
<th class="p-3 md:p-3.5 text-left border-b border-slate-200 bg-slate-50 font-semibold text-slate-600 text-xs uppercase tracking-wider">Tipo da Solicitação</th>
|
||
|
|
<th class="p-3 md:p-3.5 text-left border-b border-slate-200 bg-slate-50 font-semibold text-slate-600 text-xs uppercase tracking-wider">Colaborador</th>
|
||
|
|
<th class="p-3 md:p-3.5 text-left border-b border-slate-200 bg-slate-50 font-semibold text-slate-600 text-xs uppercase tracking-wider">Solicitante</th>
|
||
|
|
<th class="p-3 md:p-3.5 text-left border-b border-slate-200 bg-slate-50 font-semibold text-slate-600 text-xs uppercase tracking-wider">Status</th>
|
||
|
|
<th class="p-3 md:p-3.5 text-left border-b border-slate-200 bg-slate-50 font-semibold text-slate-600 text-xs uppercase tracking-wider">Data</th>
|
||
|
|
<th class="p-3 md:p-3.5 text-left border-b border-slate-200 bg-slate-50"></th>
|
||
|
|
</tr>
|
||
|
|
</thead>
|
||
|
|
<tbody id="solicitacoesTbody">
|
||
|
|
{% for item in solicitacoes_com_acao %}
|
||
|
|
{% with solicitacao=item.solicitacao %}
|
||
|
|
<tr class="solicitacao-row border-b border-slate-200 hover:bg-slate-50/50 align-middle"
|
||
|
|
data-status="{{ solicitacao.status }}"
|
||
|
|
data-search-term="{{ solicitacao.get_tipo_display|lower }} {{ solicitacao.funcionario.nome|default:''|lower }} {{ solicitacao.solicitante.nome|lower }} #{{ solicitacao.id }}">
|
||
|
|
<td class="p-3 md:p-3.5 text-left align-middle break-words">
|
||
|
|
<div class="flex items-center gap-2 min-w-0">
|
||
|
|
<div class="flex-1 min-w-0">
|
||
|
|
<strong class="text-slate-800">{{ solicitacao.get_tipo_display }}</strong>
|
||
|
|
<span class="meta-info block text-xs text-slate-500 mt-0.5">#{{ solicitacao.id }}</span>
|
||
|
|
</div>
|
||
|
|
</div>
|
||
|
|
</td>
|
||
|
|
<td class="p-3 md:p-3.5 text-left align-middle break-words">
|
||
|
|
<strong>{% if solicitacao.funcionario %}{{ solicitacao.funcionario.nome }}{% else %}<span class="text-slate-400">N/A</span>{% endif %}</strong>
|
||
|
|
{% if solicitacao.funcionario and solicitacao.funcionario.chapa %}<span class="meta-info block text-xs text-slate-500">Chapa: {{ solicitacao.funcionario.chapa }}</span>{% endif %}
|
||
|
|
</td>
|
||
|
|
<td class="p-3 md:p-3.5 text-left align-middle break-words">
|
||
|
|
<strong class="text-slate-800">{{ solicitacao.solicitante.nome }}</strong>
|
||
|
|
<span class="meta-info block text-xs text-slate-500">{{ solicitacao.solicitante.setor|default:"Sem setor" }}</span>
|
||
|
|
</td>
|
||
|
|
<td class="p-3 md:p-3.5 text-left align-middle">
|
||
|
|
<span class="status-badge inline-flex items-center gap-1 py-1 px-2.5 rounded-full text-xs font-semibold status-{{ solicitacao.status }}">{{ solicitacao.get_status_display }}</span>
|
||
|
|
</td>
|
||
|
|
<td class="p-3 md:p-3.5 text-left align-middle text-xs text-slate-500"><span class="meta-info">{{ solicitacao.criado_em|timesince }} atrás</span></td>
|
||
|
|
<td class="p-3 md:p-3.5 text-left align-middle">
|
||
|
|
<a href="{% url 'solicitacoes:solicitacao_detalhe' solicitacao.id %}" class="btn-action inline-flex items-center gap-1 py-2 px-4 rounded-md text-sm font-semibold no-underline bg-primary text-white border border-primary hover:bg-primary-hover transition-colors whitespace-nowrap">Analisar ◹</a>
|
||
|
|
</td>
|
||
|
|
</tr>
|
||
|
|
{% endwith %}
|
||
|
|
{% endfor %}
|
||
|
|
</tbody>
|
||
|
|
</table>
|
||
|
|
<div id="no-results-message" class="empty-state text-center py-12 px-6 text-slate-500 bg-white border-2 border-dashed border-slate-200 rounded-lg m-4">
|
||
|
|
Nenhuma solicitação encontrada com os filtros aplicados.
|
||
|
|
</div>
|
||
|
|
</div>
|
||
|
|
{% if solicitacoes.has_other_pages %}
|
||
|
|
<div class="pagination mt-6 flex justify-center gap-2"></div>
|
||
|
|
{% endif %}
|
||
|
|
{% else %}
|
||
|
|
<div class="empty-state text-center py-12 px-6 text-slate-500 bg-white rounded-xl border-2 border-dashed border-slate-200">
|
||
|
|
Nenhuma solicitação encontrada no sistema.
|
||
|
|
</div>
|
||
|
|
{% endif %}
|
||
|
|
{% endblock %}
|
||
|
|
|
||
|
|
{% block scripts %}
|
||
|
|
{{ block.super }}
|
||
|
|
<script>
|
||
|
|
document.addEventListener('DOMContentLoaded', function() {
|
||
|
|
const searchInput = document.getElementById('searchInput');
|
||
|
|
const filterPills = document.querySelectorAll('.filter-pill');
|
||
|
|
const clearButton = document.getElementById('clearFilters');
|
||
|
|
const tableBody = document.getElementById('solicitacoesTbody');
|
||
|
|
if (!tableBody) return;
|
||
|
|
const rows = tableBody.getElementsByClassName('solicitacao-row');
|
||
|
|
const noResultsMessage = document.getElementById('no-results-message');
|
||
|
|
let currentStatusFilter = 'todos';
|
||
|
|
let currentSearchTerm = '';
|
||
|
|
function applyFilters() {
|
||
|
|
let visibleRows = 0;
|
||
|
|
for (let i = 0; i < rows.length; i++) {
|
||
|
|
const row = rows[i];
|
||
|
|
const statusMatch = (currentStatusFilter === 'todos' || row.dataset.status === currentStatusFilter);
|
||
|
|
const searchMatch = (row.dataset.searchTerm || '').toLowerCase().includes(currentSearchTerm);
|
||
|
|
if (statusMatch && searchMatch) { row.style.display = ''; visibleRows++; } else { row.style.display = 'none'; }
|
||
|
|
}
|
||
|
|
if (noResultsMessage) noResultsMessage.style.display = visibleRows === 0 ? 'block' : 'none';
|
||
|
|
}
|
||
|
|
if (searchInput) searchInput.addEventListener('input', function() { currentSearchTerm = searchInput.value.toLowerCase().trim(); applyFilters(); });
|
||
|
|
filterPills.forEach(pill => {
|
||
|
|
pill.addEventListener('click', function() {
|
||
|
|
if (!this.classList.contains('filter-pill')) return;
|
||
|
|
filterPills.forEach(p => p.classList.remove('active'));
|
||
|
|
this.classList.add('active');
|
||
|
|
currentStatusFilter = this.dataset.status || 'todos';
|
||
|
|
applyFilters();
|
||
|
|
});
|
||
|
|
});
|
||
|
|
if (clearButton) clearButton.addEventListener('click', function() {
|
||
|
|
if (searchInput) searchInput.value = '';
|
||
|
|
currentSearchTerm = '';
|
||
|
|
filterPills.forEach(p => p.classList.remove('active'));
|
||
|
|
const todosBtn = document.querySelector('.filter-pill[data-status="todos"]');
|
||
|
|
if (todosBtn) todosBtn.classList.add('active');
|
||
|
|
currentStatusFilter = 'todos';
|
||
|
|
applyFilters();
|
||
|
|
});
|
||
|
|
});
|
||
|
|
</script>
|
||
|
|
{% endblock %}
|