sgmp/templates/dashboard.html

455 lines
46 KiB
HTML
Raw Permalink Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

{% extends "base.html" %}
{% block title %}Dashboard - SGMP{% endblock %}
{% block css %}
<style>
.tab-pane { display: none; }
.tab-pane.active { display: block; }
.tab-btn.active { color: #2563eb; border-bottom-color: #2563eb; font-weight: 600; }
.details-row td { padding: 0 !important; border-bottom: none; }
.request-row.expanded .chevron-icon { transform: rotate(180deg); }
.metric-card.active { background-color: #f8fafc; border-color: #cbd5e1; transform: scale(1.02); box-shadow: 0 4px 6px -1px rgba(0,0,0,0.1); }
.status-RASCUNHO { background: #fffbeb; color: #b45309; border: 1px solid #fcd34d; }
.status-AGUARDANDO_HEAD { background: #fef3c7; color: #b45309; border: 1px solid #fcd34d; }
.status-ENVIADA { background: #eff6ff; color: #1d4ed8; border: 1px solid #bfdbfe; }
.status-APROVADA_GG, .status-APROVADA_CONTROLADORIA, .status-APROVADA_DIRETORIA { background: #ecfdf5; color: #047857; border: 1px solid #6ee7b7; }
.status-FINALIZADA { background: #f3f4f6; color: #374151; border: 1px solid #d1d5db; }
.status-REPROVADA { background: #fef2f2; color: #b91c1c; border: 1px solid #fecaca; }
</style>
{% endblock %}
{% block content %}
<div class="dashboard-header mb-8 flex flex-col gap-2">
<h1 class="text-2xl md:text-3xl font-bold text-slate-800 m-0 tracking-tight">SGMP - Movimentação de Pessoas</h1>
<p class="text-slate-500 text-sm md:text-base leading-relaxed m-0">
Olá, <strong>{{ usuario_sistema.nome }}</strong>!
<span class="inline-block bg-slate-200 py-0.5 px-2 rounded text-xs ml-2 text-slate-600">{{ usuario_sistema.get_perfil_display }}</span>
<br>
<small class="text-slate-400">Matrícula: {{ usuario_sistema.matricula }}</small>
</p>
</div>
{% if messages %}
<ul class="list-none p-0 m-0 mb-5">
{% for message in messages %}
<li class="py-3.5 px-4 mb-3 rounded-lg border text-sm flex items-center
{% if message.tags == 'error' %}bg-red-50 text-red-800 border-red-200
{% elif message.tags == 'success' %}bg-green-50 text-green-800 border-green-200
{% else %}bg-blue-50 text-blue-800 border-blue-200{% endif %}">
{% if message.tags == 'error' %}⚠️{% elif message.tags == 'success' %}✅{% else %}{% endif %}
&nbsp;{{ message }}
</li>
{% endfor %}
</ul>
{% endif %}
{% if usuario_sistema.perfil == 'GESTOR' %}
<div class="mb-8">
<div class="bg-amber-50 border border-amber-300 rounded-xl p-4 mb-6 flex gap-3 items-start">
<span class="text-2xl">💡</span>
<div>
<h4 class="m-0 mb-1 text-amber-800 font-semibold">Lembrete Rápido</h4>
<p class="m-0 text-amber-700 text-sm">
Solicitações em <strong>Rascunho</strong> só são visíveis para você.
Lembre-se de clicar em <strong>"Enviar para Aprovação"</strong> na página de detalhes para iniciar o fluxo.
</p>
</div>
</div>
</div>
{% endif %}
<div class="metrics-grid grid grid-cols-2 md:grid-cols-[repeat(auto-fit,minmax(220px,1fr))] gap-4 md:gap-6 mb-10">
<div class="metric-card bg-white p-6 rounded-xl border border-slate-200 shadow-sm border-l-4 border-l-blue-500 cursor-pointer transition-all hover:-translate-y-1 hover:shadow-md active" onclick="filtrarTabela('todos', this)">
<div class="metric-label text-xs uppercase tracking-wider text-slate-500 font-bold mb-2">Total</div>
<div class="metric-value text-3xl font-extrabold leading-none text-blue-500">{{ total }}</div>
</div>
<div class="metric-card bg-white p-6 rounded-xl border border-slate-200 shadow-sm border-l-4 border-l-amber-500 cursor-pointer transition-all hover:-translate-y-1 hover:shadow-md" onclick="filtrarTabela('pendente', this)">
<div class="metric-label text-xs uppercase tracking-wider text-slate-500 font-bold mb-2">Pendentes</div>
<div class="metric-value text-3xl font-extrabold leading-none text-amber-600">{{ pendentes }}</div>
</div>
</div>
<div class="section mb-8">
<h3 class="text-slate-800 text-xl font-semibold mb-4 flex items-center gap-2">
{% if usuario_sistema.perfil == 'GESTOR' %}📋 Minhas Solicitações{% else %}⏳ Pendentes de Aprovação{% endif %}
</h3>
{% if usuario_sistema.perfil != 'GESTOR' %}
<div class="bg-blue-50 border border-blue-200 rounded-lg py-3 px-4 mb-5 text-blue-800 text-sm flex items-center gap-2">
Você está vendo solicitações com status <strong>Enviada</strong> aguardando sua análise.
</div>
{% endif %}
{% if solicitacoes %}
<div class="table-responsive w-full overflow-x-auto bg-white rounded-xl shadow border border-slate-200">
<table id="tabela-solicitacoes" class="w-full border-collapse whitespace-nowrap">
<thead>
<tr>
<th class="p-4 text-left border-b border-slate-200 bg-slate-50 font-semibold text-slate-600 text-xs uppercase tracking-wide">Tipo</th>
<th class="p-4 text-left border-b border-slate-200 bg-slate-50 font-semibold text-slate-600 text-xs uppercase tracking-wide">Colaborador</th>
<th class="p-4 text-left border-b border-slate-200 bg-slate-50 font-semibold text-slate-600 text-xs uppercase tracking-wide">Status</th>
<th class="p-4 text-left border-b border-slate-200 bg-slate-50 font-semibold text-slate-600 text-xs uppercase tracking-wide">Data</th>
<th class="p-4 text-left border-b border-slate-200 bg-slate-50 font-semibold text-slate-600 text-xs uppercase tracking-wide">Ações</th>
</tr>
</thead>
<tbody>
{% for item in solicitacoes_com_acao %}
{% with solicitacao=item.solicitacao %}
<tr class="request-row border-b border-slate-200 hover:bg-slate-50 cursor-pointer"
data-id="{{ solicitacao.id }}"
data-status="{% if solicitacao.status == 'FINALIZADA' %}aprovado{% elif solicitacao.status == 'REPROVADA' %}reprovado{% else %}pendente{% endif %}"
onclick="toggleDetails('{{ solicitacao.id }}', this)">
<td class="p-4"><strong>{{ solicitacao.get_tipo_display }}</strong></td>
<td class="p-4">
{% if solicitacao.funcionario %}{{ solicitacao.funcionario.nome }}{% else %}<span class="text-slate-400">N/A</span>{% endif %}
</td>
<td class="p-4">
<span class="status-badge inline-flex items-center py-1 px-2.5 rounded-full text-xs font-bold status-{{ solicitacao.status }}">{{ solicitacao.get_status_display }}</span>
</td>
<td class="p-4 text-slate-500">{{ solicitacao.criado_em|date:"d/m/Y H:i" }}</td>
<td class="p-4">
<div class="flex gap-3 items-center">
<span class="expand-btn text-blue-600 font-semibold text-sm">Detalhes <span class="chevron-icon inline-block text-xs transition-transform"></span></span>
{% if item.pode_dar_parecer %}
<a href="{% url 'solicitacoes:solicitacao_detalhe' solicitacao.id %}" class="btn-action btn-action-primary inline-flex items-center gap-1.5 py-2.5 px-4 rounded-md text-sm font-semibold bg-primary text-white border border-primary-hover hover:bg-primary-hover no-underline" title="Fornecer parecer técnico">📝 Parecer</a>
{% endif %}
{% if item.pode_aprovar %}
<div class="flex gap-1">
<button type="button" class="btn-action btn-action-success py-1 px-2 text-sm bg-emerald-500 text-white border border-emerald-600 rounded hover:bg-emerald-600" onclick="event.stopPropagation(); abrirModalAprovacao('{{ solicitacao.id }}', 'APROVADO')" title="Aprovar"></button>
<button type="button" class="btn-action btn-action-danger py-1 px-2 text-sm bg-white text-red-500 border border-red-500 rounded hover:bg-red-50" onclick="event.stopPropagation(); abrirModalAprovacao('{{ solicitacao.id }}', 'REPROVADO')" title="Reprovar"></button>
</div>
{% endif %}
</div>
</td>
</tr>
<tr id="details-{{ solicitacao.id }}" class="details-row bg-slate-50" style="display:none;">
<td colspan="5">
<div class="details-wrapper p-8" id="wrapper-{{ solicitacao.id }}">
<div class="tab-nav flex border-b border-slate-200 mb-6 gap-8 overflow-x-auto">
<button type="button" class="tab-btn active pb-3 border-b-2 border-transparent text-slate-500 text-sm font-medium whitespace-nowrap hover:text-primary border-b-primary text-primary font-semibold" onclick="switchTab(event, 'solicitacao', '{{ solicitacao.id }}')">📄 Solicitação</button>
{% if solicitacao.funcionario %}
<button type="button" class="tab-btn pb-3 border-b-2 border-transparent text-slate-500 text-sm font-medium whitespace-nowrap hover:text-primary" onclick="switchTab(event, 'rm', '{{ solicitacao.id }}')">🏢 RM (Totvs)</button>
{% endif %}
{% for item_acao in solicitacoes_com_acao %}
{% if item_acao.solicitacao.id == solicitacao.id and item_acao.dados_winthor_organizados %}
<button type="button" class="tab-btn pb-3 border-b-2 border-transparent text-slate-500 text-sm font-medium whitespace-nowrap hover:text-primary" onclick="switchTab(event, 'winthor', '{{ solicitacao.id }}')">💼 Winthor</button>
{% endif %}
{% endfor %}
<button type="button" class="tab-btn pb-3 border-b-2 border-transparent text-slate-500 text-sm font-medium whitespace-nowrap hover:text-primary" onclick="switchTab(event, 'auditoria', '{{ solicitacao.id }}')">📝 Histórico & Auditoria</button>
</div>
<div class="tab-pane active" data-tab="solicitacao">
<div class="details-section mb-6 bg-white p-6 rounded-xl border border-slate-200">
<h5 class="text-slate-400 text-xs uppercase mt-6 mb-4 font-bold tracking-wider border-b border-slate-100 pb-2 first:mt-0">Dados Gerais</h5>
<div class="info-grid grid grid-cols-1 md:grid-cols-[repeat(auto-fill,minmax(200px,1fr))] gap-6 mb-6">
<div class="info-item flex flex-col"><label class="text-xs text-slate-500 mb-1 font-semibold uppercase">Solicitante</label><span class="text-slate-900 font-medium">{{ solicitacao.solicitante.nome }} <small class="text-slate-500">({{ solicitacao.solicitante.matricula }})</small></span></div>
<div class="info-item flex flex-col"><label class="text-xs text-slate-500 mb-1 font-semibold uppercase">Tipo</label><span class="font-bold text-primary">{{ solicitacao.get_tipo_display }}</span></div>
<div class="info-item flex flex-col"><label class="text-xs text-slate-500 mb-1 font-semibold uppercase">Data Criação</label><span class="text-slate-900 font-medium">{{ solicitacao.criado_em|date:"d/m/Y H:i" }}</span></div>
{% if solicitacao.enviada_em %}<div class="info-item flex flex-col"><label class="text-xs text-slate-500 mb-1 font-semibold uppercase">Enviada em</label><span class="text-slate-900 font-medium">{{ solicitacao.enviada_em|date:"d/m/Y H:i" }}</span></div>{% endif %}
{% if solicitacao.finalizada_em %}<div class="info-item flex flex-col"><label class="text-xs text-slate-500 mb-1 font-semibold uppercase">Finalizada em</label><span class="text-slate-900 font-medium">{{ solicitacao.finalizada_em|date:"d/m/Y H:i" }}</span></div>{% endif %}
</div>
{% if solicitacao.tipo == 'DESLIGAMENTO' and solicitacao.desligamento %}
<h5 class="text-slate-400 text-xs uppercase mt-6 mb-4 font-bold tracking-wider border-b border-slate-100 pb-2">Detalhes do Desligamento</h5>
<div class="info-grid grid grid-cols-1 md:grid-cols-[repeat(auto-fill,minmax(200px,1fr))] gap-6 mb-6">
{% if solicitacao.desligamento.tipo_desligamento %}
<div class="info-item flex flex-col"><label class="text-xs text-slate-500 mb-1 font-semibold uppercase">Tipo de Desligamento</label><span>{% if solicitacao.desligamento.tipo_desligamento == 'PEDIDO_DEMISSAO' %}📝 Pedido de Demissão{% elif solicitacao.desligamento.tipo_desligamento == 'SEM_JUSTA_CAUSA' %}🚪 Sem Justa Causa{% elif solicitacao.desligamento.tipo_desligamento == 'COM_JUSTA_CAUSA' %}⚠️ Por Justa Causa{% elif solicitacao.desligamento.tipo_desligamento == 'TERMINO_CONTRATO' %}📅 Término de Contrato{% elif solicitacao.desligamento.tipo_desligamento == 'OUTROS' %}📋 Outros{% else %}{{ solicitacao.desligamento.get_tipo_desligamento_display|default:"—" }}{% endif %}</span></div>
{% endif %}
{% if solicitacao.desligamento.aviso_previo %}
<div class="info-item flex flex-col"><label class="text-xs text-slate-500 mb-1 font-semibold uppercase">Aviso Prévio</label><span>{% if solicitacao.desligamento.aviso_previo == 'TRABALHADO' %}✅ Trabalhado{% elif solicitacao.desligamento.aviso_previo == 'INDENIZADO' %}💰 Indenizado{% elif solicitacao.desligamento.aviso_previo == 'DISPENSADO' %}📤 Dispensado{% else %}{{ solicitacao.desligamento.get_aviso_previo_display|default:"—" }}{% endif %}</span></div>
{% endif %}
<div class="info-item flex flex-col"><label class="text-xs text-slate-500 mb-1 font-semibold uppercase">Data Prevista de Saída</label><span>{{ solicitacao.desligamento.data_prevista_desligamento|date:"d/m/Y"|default:"—" }}</span></div>
<div class="info-item flex flex-col md:col-span-full"><label class="text-xs text-slate-500 mb-1 font-semibold uppercase">Detalhamento / Justificativa</label><span class="whitespace-pre-wrap">{{ solicitacao.desligamento.motivo|default:"—" }}</span></div>
{% if solicitacao.desligamento.arquivo_pedido %}<div class="info-item flex flex-col md:col-span-full"><label class="text-xs text-slate-500 mb-1 font-semibold uppercase">Carta de Pedido</label><span><a href="{{ solicitacao.desligamento.arquivo_pedido.url }}" target="_blank" class="text-primary no-underline">📎 Ver arquivo</a></span></div>{% endif %}
{% if solicitacao.desligamento.observacoes %}<div class="info-item flex flex-col md:col-span-full"><label class="text-xs text-slate-500 mb-1 font-semibold uppercase">Observações Adicionais</label><span class="whitespace-pre-wrap">{{ solicitacao.desligamento.observacoes }}</span></div>{% endif %}
</div>
{% elif solicitacao.tipo == 'MOVIMENTACAO' and solicitacao.movimentacao %}
<h5 class="text-slate-400 text-xs uppercase mt-6 mb-4 font-bold tracking-wider border-b border-slate-100 pb-2">Detalhes da Movimentação</h5>
<div class="info-grid grid grid-cols-1 md:grid-cols-[repeat(auto-fill,minmax(200px,1fr))] gap-6 mb-6">
<div class="info-item flex flex-col"><label class="text-xs text-slate-500 mb-1 font-semibold uppercase">Data de Efetivação</label><span>{{ solicitacao.movimentacao.data_efetivacao|date:"d/m/Y"|default:"—" }}</span></div>
{% if solicitacao.movimentacao.altera_funcao %}<div class="info-item flex flex-col"><label class="text-xs text-slate-500 mb-1 font-semibold uppercase">Nova Função</label><span>{{ solicitacao.movimentacao.novo_cod_funcao|default:"—" }}</span></div>{% endif %}
{% if solicitacao.movimentacao.altera_centro_custo %}<div class="info-item flex flex-col"><label class="text-xs text-slate-500 mb-1 font-semibold uppercase">Nova Seção</label><span>{{ solicitacao.movimentacao.novo_cod_secao|default:"—" }}</span></div>{% endif %}
{% if solicitacao.movimentacao.novo_salario %}<div class="info-item flex flex-col"><label class="text-xs text-slate-500 mb-1 font-semibold uppercase">Novo Salário</label><span>R$ {{ solicitacao.movimentacao.novo_salario }}</span></div>{% endif %}
<div class="info-item flex flex-col md:col-span-full"><label class="text-xs text-slate-500 mb-1 font-semibold uppercase">Justificativa</label><span>{{ solicitacao.movimentacao.justificativa|default:"—" }}</span></div>
</div>
{% elif solicitacao.tipo == 'ADM_SUBSTITUICAO' and solicitacao.admissao_substituicao %}
<h5 class="text-slate-400 text-xs uppercase mt-6 mb-4 font-bold tracking-wider border-b border-slate-100 pb-2">Detalhes da Admissão por Substituição</h5>
<div class="info-grid grid grid-cols-1 md:grid-cols-[repeat(auto-fill,minmax(200px,1fr))] gap-6 mb-6">
<div class="info-item flex flex-col"><label class="text-xs text-slate-500 mb-1 font-semibold uppercase">Data Prevista</label><span>{{ solicitacao.admissao_substituicao.data_previsao_contratacao|date:"d/m/Y"|default:"—" }}</span></div>
<div class="info-item flex flex-col"><label class="text-xs text-slate-500 mb-1 font-semibold uppercase">Coligada Destino</label><span>{{ solicitacao.admissao_substituicao.cod_coligada_destino|default:"—" }}</span></div>
<div class="info-item flex flex-col"><label class="text-xs text-slate-500 mb-1 font-semibold uppercase">Filial Destino</label><span>{{ solicitacao.admissao_substituicao.cod_filial_destino|default:"—" }}</span></div>
<div class="info-item flex flex-col"><label class="text-xs text-slate-500 mb-1 font-semibold uppercase">Seção Destino</label><span>{{ solicitacao.admissao_substituicao.cod_secao_destino|default:"—" }}</span></div>
<div class="info-item flex flex-col"><label class="text-xs text-slate-500 mb-1 font-semibold uppercase">Função Destino</label><span>{{ solicitacao.admissao_substituicao.cod_funcao_destino|default:"—" }}</span></div>
<div class="info-item flex flex-col md:col-span-full"><label class="text-xs text-slate-500 mb-1 font-semibold uppercase">Justificativa</label><span>{{ solicitacao.admissao_substituicao.justificativa|default:"—" }}</span></div>
</div>
{% elif solicitacao.tipo == 'ADM_AUMENTO' and solicitacao.admissao_aumento %}
<h5 class="text-slate-400 text-xs uppercase mt-6 mb-4 font-bold tracking-wider border-b border-slate-100 pb-2">Detalhes da Admissão por Aumento de Quadro</h5>
<div class="info-grid grid grid-cols-1 md:grid-cols-[repeat(auto-fill,minmax(200px,1fr))] gap-6 mb-6">
<div class="info-item flex flex-col"><label class="text-xs text-slate-500 mb-1 font-semibold uppercase">Data Prevista</label><span>{{ solicitacao.admissao_aumento.data_previsao_contratacao|date:"d/m/Y"|default:"—" }}</span></div>
<div class="info-item flex flex-col"><label class="text-xs text-slate-500 mb-1 font-semibold uppercase">Coligada Destino</label><span>{{ solicitacao.admissao_aumento.cod_coligada_destino|default:"—" }}</span></div>
<div class="info-item flex flex-col"><label class="text-xs text-slate-500 mb-1 font-semibold uppercase">Filial Destino</label><span>{{ solicitacao.admissao_aumento.cod_filial_destino|default:"—" }}</span></div>
<div class="info-item flex flex-col"><label class="text-xs text-slate-500 mb-1 font-semibold uppercase">Seção Destino</label><span>{{ solicitacao.admissao_aumento.cod_secao_destino|default:"—" }}</span></div>
<div class="info-item flex flex-col"><label class="text-xs text-slate-500 mb-1 font-semibold uppercase">Função Destino</label><span>{{ solicitacao.admissao_aumento.cod_funcao_destino|default:"—" }}</span></div>
<div class="info-item flex flex-col md:col-span-full"><label class="text-xs text-slate-500 mb-1 font-semibold uppercase">Justificativa Estratégica</label><span>{{ solicitacao.admissao_aumento.justificativa_estrategica|default:"—" }}</span></div>
</div>
{% endif %}
<div class="mt-8 pt-6 border-t border-slate-200">
{% if solicitacao.pode_enviar and solicitacao.solicitante.id == usuario_sistema.id %}
<a href="{% url 'solicitacoes:enviar_solicitacao' solicitacao.id %}" class="btn-action btn-action-primary inline-flex items-center gap-1.5 py-2.5 px-4 rounded-md text-sm font-semibold bg-primary text-white border border-primary-hover hover:bg-primary-hover no-underline">🚀 Enviar para Aprovação</a>
{% endif %}
</div>
</div>
</div>
{% if solicitacao.funcionario %}
<div class="tab-pane" data-tab="rm">
<div class="details-section mb-6 bg-white p-6 rounded-xl border-2 border-primary">
<div class="inline-flex items-center gap-2 -mt-4 mb-6 text-primary bg-blue-100 py-2 px-3 rounded-md text-sm font-semibold">💾 Snapshot TOTVS RM</div>
<h5 class="text-slate-400 text-xs uppercase mt-6 mb-4 font-bold tracking-wider border-b border-slate-100 pb-2 first:mt-0">Dados Básicos</h5>
<div class="info-grid grid grid-cols-1 md:grid-cols-[repeat(auto-fill,minmax(200px,1fr))] gap-6 mb-6">
<div class="info-item flex flex-col"><label class="text-xs text-slate-500 mb-1 font-semibold uppercase">Matrícula</label><span><strong>{{ solicitacao.funcionario.matricula }}</strong></span></div>
<div class="info-item flex flex-col"><label class="text-xs text-slate-500 mb-1 font-semibold uppercase">Nome Completo</label><span><strong>{{ solicitacao.funcionario.nome }}</strong></span></div>
{% if solicitacao.funcionario.cpf %}<div class="info-item flex flex-col"><label class="text-xs text-slate-500 mb-1 font-semibold uppercase">CPF</label><span>{{ solicitacao.funcionario.cpf }}</span></div>{% endif %}
{% if solicitacao.funcionario.data_admissao %}<div class="info-item flex flex-col"><label class="text-xs text-slate-500 mb-1 font-semibold uppercase">Data de Admissão</label><span>{{ solicitacao.funcionario.data_admissao|date:"d/m/Y" }}</span></div>{% endif %}
{% if solicitacao.funcionario.situacao %}<div class="info-item flex flex-col"><label class="text-xs text-slate-500 mb-1 font-semibold uppercase">Situação</label><span>{{ solicitacao.funcionario.situacao }}</span></div>{% endif %}
</div>
<h5 class="text-slate-400 text-xs uppercase mt-6 mb-4 font-bold tracking-wider border-b border-slate-100 pb-2">Dados Profissionais</h5>
<div class="info-grid grid grid-cols-1 md:grid-cols-[repeat(auto-fill,minmax(200px,1fr))] gap-6 mb-6">
<div class="info-item flex flex-col"><label class="text-xs text-slate-500 mb-1 font-semibold uppercase">Cargo/Função</label><span>{{ solicitacao.funcionario.cargo }}</span></div>
<div class="info-item flex flex-col"><label class="text-xs text-slate-500 mb-1 font-semibold uppercase">Código da Função</label><span>{{ solicitacao.funcionario.cod_funcao|default:"N/A" }}</span></div>
<div class="info-item flex flex-col"><label class="text-xs text-slate-500 mb-1 font-semibold uppercase">Setor/Seção</label><span>{{ solicitacao.funcionario.setor }}</span></div>
<div class="info-item flex flex-col"><label class="text-xs text-slate-500 mb-1 font-semibold uppercase">Centro de Custo</label><span>{{ solicitacao.funcionario.centro_custo }}</span></div>
{% if solicitacao.funcionario.salario %}<div class="info-item flex flex-col"><label class="text-xs text-slate-500 mb-1 font-semibold uppercase">Salário Atual</label><span><strong class="text-emerald-600 text-lg">R$ {{ solicitacao.funcionario.salario|floatformat:2 }}</strong></span></div>{% endif %}
</div>
{% if solicitacao.funcionario.saldo_banco_horas_minutos is not None %}
<h5 class="text-slate-400 text-xs uppercase mt-6 mb-4 font-bold tracking-wider border-b border-slate-100 pb-2">Banco de Horas</h5>
<div class="info-grid grid grid-cols-1 md:grid-cols-[repeat(auto-fill,minmax(200px,1fr))] gap-6 mb-6">
<div class="info-item flex flex-col"><label class="text-xs text-slate-500 mb-1 font-semibold uppercase">Saldo Atual</label><span>{% if solicitacao.funcionario.saldo_banco_horas_minutos >= 0 %}<strong class="text-emerald-600 text-lg">+{{ solicitacao.funcionario.saldo_banco_horas_minutos }} min</strong>{% else %}<strong class="text-red-500 text-lg">{{ solicitacao.funcionario.saldo_banco_horas_minutos }} min</strong>{% endif %}</span></div>
</div>
{% endif %}
</div>
</div>
{% endif %}
{% for item_acao in solicitacoes_com_acao %}
{% if item_acao.solicitacao.id == solicitacao.id and item_acao.dados_winthor_organizados %}
{% with win=item_acao.dados_winthor_organizados %}
<div class="tab-pane" data-tab="winthor">
<div class="details-section mb-6 bg-white p-6 rounded-xl border-2 border-emerald-500">
<div class="inline-flex items-center gap-2 -mt-4 mb-6 text-emerald-700 bg-emerald-100 py-2 px-3 rounded-md text-sm font-semibold">💼 Sistema Winthor</div>
{% if win.basicos %}
<h5 class="text-slate-400 text-xs uppercase mt-6 mb-4 font-bold tracking-wider border-b border-slate-100 pb-2 first:mt-0">Dados Básicos</h5>
<div class="info-grid grid grid-cols-1 md:grid-cols-[repeat(auto-fill,minmax(200px,1fr))] gap-6 mb-6">
{% if win.basicos.matricula %}<div class="info-item flex flex-col"><label class="text-xs text-slate-500 mb-1 font-semibold uppercase">Matrícula</label><span><strong>{{ win.basicos.matricula }}</strong></span></div>{% endif %}
{% if win.basicos.nome %}<div class="info-item flex flex-col"><label class="text-xs text-slate-500 mb-1 font-semibold uppercase">Nome</label><span><strong>{{ win.basicos.nome }}</strong></span></div>{% endif %}
{% if win.basicos.cpf %}<div class="info-item flex flex-col"><label class="text-xs text-slate-500 mb-1 font-semibold uppercase">CPF</label><span>{{ win.basicos.cpf }}</span></div>{% endif %}
</div>
{% endif %}
{% if win.admissao %}
<h5 class="text-slate-400 text-xs uppercase mt-6 mb-4 font-bold tracking-wider border-b border-slate-100 pb-2">Admissão e Situação</h5>
<div class="info-grid grid grid-cols-1 md:grid-cols-[repeat(auto-fill,minmax(200px,1fr))] gap-6 mb-6">
{% if win.admissao.admissao %}<div class="info-item flex flex-col"><label class="text-xs text-slate-500 mb-1 font-semibold uppercase">Data de Admissão</label><span>{% if win.admissao.admissao|date:"d/m/Y" %}{{ win.admissao.admissao|date:"d/m/Y" }}{% else %}{{ win.admissao.admissao }}{% endif %}</span></div>{% endif %}
{% if win.admissao.situacao %}<div class="info-item flex flex-col"><label class="text-xs text-slate-500 mb-1 font-semibold uppercase">Situação</label><span>{{ win.admissao.situacao }}</span></div>{% endif %}
{% if win.admissao.dt_exclusao %}<div class="info-item flex flex-col"><label class="text-xs text-slate-500 mb-1 font-semibold uppercase">Data de Exclusão</label><span>{% if win.admissao.dt_exclusao|date:"d/m/Y" %}{{ win.admissao.dt_exclusao|date:"d/m/Y" }}{% else %}{{ win.admissao.dt_exclusao }}{% endif %}</span></div>{% endif %}
</div>
{% endif %}
{% if win.endereco %}
<h5 class="text-slate-400 text-xs uppercase mt-6 mb-4 font-bold tracking-wider border-b border-slate-100 pb-2">Endereço</h5>
<div class="info-grid grid grid-cols-1 md:grid-cols-[repeat(auto-fill,minmax(200px,1fr))] gap-6 mb-6">
{% if win.endereco.endereco %}<div class="info-item flex flex-col md:col-span-full"><label class="text-xs text-slate-500 mb-1 font-semibold uppercase">Endereço</label><span>{{ win.endereco.endereco }}</span></div>{% endif %}
{% if win.endereco.bairro %}<div class="info-item flex flex-col"><label class="text-xs text-slate-500 mb-1 font-semibold uppercase">Bairro</label><span>{{ win.endereco.bairro }}</span></div>{% endif %}
{% if win.endereco.cidade %}<div class="info-item flex flex-col"><label class="text-xs text-slate-500 mb-1 font-semibold uppercase">Cidade</label><span>{{ win.endereco.cidade }}</span></div>{% endif %}
{% if win.endereco.estado %}<div class="info-item flex flex-col"><label class="text-xs text-slate-500 mb-1 font-semibold uppercase">Estado</label><span>{{ win.endereco.estado }}</span></div>{% endif %}
</div>
{% endif %}
</div>
</div>
{% endwith %}
{% endif %}
{% endfor %}
<div class="tab-pane" data-tab="auditoria">
<div class="details-section mb-6 bg-white p-6 rounded-xl border border-slate-200">
<h5 class="text-slate-400 text-xs uppercase mt-6 mb-4 font-bold tracking-wider border-b border-slate-100 pb-2 first:mt-0">Status Atual</h5>
<div class="info-grid grid grid-cols-1 md:grid-cols-[repeat(auto-fill,minmax(200px,1fr))] gap-6 mb-6">
<div class="info-item flex flex-col"><label class="text-xs text-slate-500 mb-1 font-semibold uppercase">Status</label><span class="status-badge status-{{ solicitacao.status }}">{{ solicitacao.get_status_display }}</span></div>
<div class="info-item flex flex-col"><label class="text-xs text-slate-500 mb-1 font-semibold uppercase">Última Modificação</label><span>{{ solicitacao.atualizado_em|date:"d/m/Y H:i" }}</span></div>
</div>
<h5 class="text-slate-400 text-xs uppercase mt-6 mb-4 font-bold tracking-wider border-b border-slate-100 pb-2">Histórico de Aprovações</h5>
{% if solicitacao.aprovacoes.all %}
<div class="timeline pl-8 border-l-2 border-slate-200 ml-2">
{% for aprovacao in solicitacao.aprovacoes.all %}
<div class="timeline-item relative pb-8 pl-6 last:pb-0 before:content-[''] before:absolute before:-left-[2.4rem] before:top-1 before:w-3.5 before:h-3.5 before:rounded-full before:bg-slate-300 before:border-[3px] before:border-white before:shadow-[0_0_0_1px_#e2e8f0]">
<div class="timeline-header flex flex-wrap gap-2 mb-1 text-sm items-baseline">
<span class="timeline-user font-semibold text-slate-800">{{ aprovacao.usuario.nome }}</span>
<span class="timeline-action text-slate-500">{% if aprovacao.decisao == 'APROVADO' %}<span class="text-emerald-500">aprovou</span>{% else %}<span class="text-red-500">reprovou</span>{% endif %} em {{ aprovacao.get_etapa_display }}</span>
<span class="timeline-date text-xs text-slate-400 ml-auto">{{ aprovacao.decidido_em|date:"d/m/Y H:i" }}</span>
</div>
{% if aprovacao.justificativa %}<div class="timeline-justificativa mt-3 p-4 bg-slate-50 rounded-lg text-sm text-slate-700 border border-slate-200 italic">"{{ aprovacao.justificativa }}"</div>{% endif %}
</div>
{% endfor %}
</div>
{% else %}
<p class="text-slate-500 italic bg-slate-50 p-2.5 rounded-md">⏳ Nenhuma aprovação registrada ainda.</p>
{% endif %}
{% if solicitacao.pareceres.all %}
<h5 class="text-slate-400 text-xs uppercase mt-6 mb-4 font-bold tracking-wider border-b border-slate-100 pb-2">Pareceres Técnicos</h5>
<div class="mb-6">
{% for parecer in solicitacao.pareceres.all %}
<div class="bg-white p-4 rounded-lg mb-3 border border-slate-200 shadow-sm">
<div class="flex justify-between mb-2"><strong class="text-slate-800">{{ parecer.get_etapa_display }}</strong><small class="text-slate-500">{{ parecer.criado_em|date:"d/m/Y H:i" }}</small></div>
<small class="text-slate-500 block mb-2">Autor: {{ parecer.usuario.nome }}</small>
<p class="m-0 text-slate-700 leading-relaxed">{{ parecer.texto }}</p>
{% if parecer.anexo %}<div class="mt-3 pt-3 border-t border-dashed border-slate-200"><a href="{{ parecer.anexo.url }}" target="_blank" class="text-primary no-underline text-sm font-medium">📎 Visualizar Anexo ({{ parecer.anexo.name|slice:"20:" }})</a></div>{% endif %}
</div>
{% endfor %}
</div>
{% endif %}
{% if solicitacao.solicitante.id == usuario_sistema.id and solicitacao.status != 'RASCUNHO' %}
<div class="bg-slate-100 rounded-lg py-4 px-4 mt-6 text-slate-500 text-center text-sm">👁️ Você é o solicitante. Acompanhe o status acima.</div>
{% endif %}
</div>
</div>
</div>
</td>
</tr>
{% endwith %}
{% endfor %}
</tbody>
</table>
</div>
<div id="no-results" class="empty-state text-center py-16 px-5 text-slate-500 bg-white rounded-xl border-2 border-dashed border-slate-300 hidden">
<p class="m-0 text-lg">🔍 Nenhuma solicitação encontrada com este filtro.</p>
</div>
{% if solicitacoes.has_other_pages %}
<div class="pagination mt-6 flex items-center justify-center gap-1.5 flex-wrap">
{% if solicitacoes.has_previous %}<a href="?page=1" class="py-2 px-3.5 no-underline border border-slate-200 rounded-md text-slate-600 bg-white text-sm transition-all hover:bg-slate-50 hover:border-slate-300 hover:text-slate-800">« Primeira</a><a href="?page={{ solicitacoes.previous_page_number }}" class="py-2 px-3.5 no-underline border border-slate-200 rounded-md text-slate-600 bg-white text-sm transition-all hover:bg-slate-50 hover:border-slate-300 hover:text-slate-800"> Anterior</a>{% endif %}
<span class="current py-2 px-3.5 bg-primary text-white rounded-md font-medium border border-primary">{{ solicitacoes.number }} / {{ solicitacoes.paginator.num_pages }}</span>
{% if solicitacoes.has_next %}<a href="?page={{ solicitacoes.next_page_number }}" class="py-2 px-3.5 no-underline border border-slate-200 rounded-md text-slate-600 bg-white text-sm transition-all hover:bg-slate-50 hover:border-slate-300 hover:text-slate-800">Próxima </a><a href="?page={{ solicitacoes.paginator.num_pages }}" class="py-2 px-3.5 no-underline border border-slate-200 rounded-md text-slate-600 bg-white text-sm transition-all hover:bg-slate-50 hover:border-slate-300 hover:text-slate-800">Última »</a>{% endif %}
</div>
{% endif %}
{% else %}
<div class="empty-state text-center py-16 px-5 text-slate-500 bg-white rounded-xl border-2 border-dashed border-slate-300">
<p class="m-0 text-lg">🎉 Nenhuma solicitação encontrada.</p>
{% if usuario_sistema.perfil == 'GESTOR' %}<p class="text-sm mt-2">Use o botão "Nova Solicitação" para começar.</p>{% endif %}
</div>
{% endif %}
</div>
{% endblock %}
{% block scripts %}
<script>
function filtrarTabela(status, cardElement) {
document.querySelectorAll('.metric-card').forEach(c => c.classList.remove('active'));
if (cardElement) cardElement.classList.add('active');
const rows = document.querySelectorAll('.request-row');
let visibleCount = 0;
rows.forEach(row => {
const categoria = row.getAttribute('data-status');
let show = (status === 'todos') || (status === 'pendente' && categoria === 'pendente');
if (show) { row.style.display = ''; visibleCount++; } else {
row.style.display = 'none';
const solicitacaoId = row.getAttribute('data-id');
const detailsRow = document.getElementById('details-' + solicitacaoId);
if (detailsRow && detailsRow.style.display !== 'none') { detailsRow.style.display = 'none'; row.classList.remove('expanded'); }
}
});
const noResults = document.getElementById('no-results');
const tableContainer = document.querySelector('.table-responsive');
if (noResults && tableContainer) { noResults.style.display = visibleCount === 0 ? 'block' : 'none'; tableContainer.style.display = visibleCount === 0 ? 'none' : 'block'; }
}
function toggleDetails(solicitacaoId, rowElement) {
const detailsRow = document.getElementById('details-' + solicitacaoId);
if (!detailsRow) return;
if (detailsRow.style.display === 'none' || detailsRow.style.display === '') {
document.querySelectorAll('.details-row').forEach(row => { row.style.display = 'none'; });
document.querySelectorAll('.request-row').forEach(row => { row.classList.remove('expanded'); });
detailsRow.style.display = 'table-row';
if (rowElement) rowElement.classList.add('expanded');
} else {
detailsRow.style.display = 'none';
if (rowElement) rowElement.classList.remove('expanded');
}
}
function switchTab(event, tabName, solicitacaoId) {
event.preventDefault(); event.stopPropagation();
const wrapper = document.getElementById('wrapper-' + solicitacaoId);
if (!wrapper) return;
wrapper.querySelectorAll('.tab-btn').forEach(btn => btn.classList.remove('active'));
wrapper.querySelectorAll('.tab-pane').forEach(pane => pane.classList.remove('active'));
event.currentTarget.classList.add('active');
const targetPane = wrapper.querySelector('.tab-pane[data-tab="' + tabName + '"]');
if (targetPane) targetPane.classList.add('active');
}
document.addEventListener('DOMContentLoaded', function() {
const cardTotal = document.querySelector('.card-total');
if (cardTotal) filtrarTabela('todos', cardTotal);
});
function abrirModalAprovacao(solicitacaoId, decisao) {
const modal = document.getElementById('modal-aprovacao');
const form = document.getElementById('form-aprovacao');
const decisaoInput = document.getElementById('decisao-input');
const justificativaDiv = document.getElementById('justificativa-div');
const justificativaInput = document.getElementById('justificativa-input');
const tituloModal = document.getElementById('titulo-modal');
decisaoInput.value = decisao;
justificativaInput.value = '';
justificativaInput.removeAttribute('required');
if (decisao === 'REPROVADO') {
tituloModal.textContent = 'Reprovar Solicitação';
tituloModal.style.color = '#ef4444';
justificativaDiv.style.display = 'block';
justificativaInput.setAttribute('required', 'required');
justificativaInput.placeholder = 'Descreva o motivo da reprovação...';
} else {
tituloModal.textContent = 'Aprovar Solicitação';
tituloModal.style.color = '#10b981';
justificativaDiv.style.display = 'none';
}
form.action = '/solicitacao/' + solicitacaoId + '/decidir/';
modal.style.display = 'flex';
}
function fecharModalAprovacao() { document.getElementById('modal-aprovacao').style.display = 'none'; }
window.onclick = function(event) { if (event.target === document.getElementById('modal-aprovacao')) fecharModalAprovacao(); };
document.querySelectorAll('.decisao-select').forEach(function(select) {
select.addEventListener('change', function() {
var form = this.closest('form');
var justificativa = form.querySelector('.justificativa-input');
var requiredMarker = form.querySelector('.justificativa-required');
if (this.value === 'REPROVADO') { justificativa.setAttribute('required', 'required'); if (requiredMarker) requiredMarker.style.display = 'inline'; justificativa.placeholder = 'Descreva o motivo da reprovação...'; }
else { justificativa.removeAttribute('required'); if (requiredMarker) requiredMarker.style.display = 'none'; justificativa.placeholder = 'Opcional para aprovação...'; }
});
});
document.querySelectorAll('.form-decisao-dashboard').forEach(function(form) {
form.addEventListener('submit', function(e) {
var decisao = form.querySelector('.decisao-select').value;
var justificativa = form.querySelector('.justificativa-input').value.trim();
if (decisao === 'REPROVADO' && !justificativa) { e.preventDefault(); alert('A justificativa é obrigatória para reprovações.'); form.querySelector('.justificativa-input').focus(); }
});
});
</script>
<div id="modal-aprovacao" class="hidden fixed inset-0 z-[1000] bg-black/50 items-center justify-center" style="display: none;">
<div class="modal-content bg-white p-8 rounded-xl max-w-md w-[90%] shadow-xl border border-slate-200">
<h3 id="titulo-modal" class="mt-0 mb-5 text-xl font-semibold">Aprovar Solicitação</h3>
<form id="form-aprovacao" method="post" action="">
{% csrf_token %}
<input type="hidden" id="decisao-input" name="decisao" value="">
<div id="justificativa-div" class="hidden mb-5">
<label for="justificativa-input" class="block mb-2 font-semibold text-slate-700">Justificativa Obrigatória <span class="text-red-500">*</span></label>
<textarea id="justificativa-input" name="justificativa" rows="4" class="w-full p-2.5 border border-slate-300 rounded-md font-sans text-sm focus:outline-none focus:border-primary focus:ring-2 focus:ring-primary/20" placeholder="Descreva o motivo..."></textarea>
</div>
<div class="flex gap-2.5 justify-end mt-6">
<button type="button" onclick="fecharModalAprovacao()" class="py-2.5 px-5 bg-white text-slate-500 border border-slate-300 rounded-md cursor-pointer font-semibold hover:bg-slate-50">Cancelar</button>
<button type="submit" class="py-2.5 px-6 bg-primary text-white border-none rounded-md cursor-pointer font-semibold shadow-sm">Confirmar</button>
</div>
</form>
</div>
</div>
{% endblock %}