196 lines
10 KiB
HTML
196 lines
10 KiB
HTML
{% load static %}
|
|
<!DOCTYPE html>
|
|
<html lang="es">
|
|
<head>
|
|
<meta charset="UTF-8">
|
|
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
|
<title>EFINTEL | ERP Interno I+D+i</title>
|
|
<link rel="preconnect" href="https://fonts.googleapis.com">
|
|
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
|
|
<link href="https://fonts.googleapis.com/css2?family=Inter:wght@400;500;600;700;800&family=JetBrains+Mono:wght@500;700;800&display=swap" rel="stylesheet">
|
|
<script src="https://cdn.jsdelivr.net/npm/chart.js"></script>
|
|
<script src="https://unpkg.com/lucide@latest"></script>
|
|
<script defer src="https://cdn.jsdelivr.net/npm/alpinejs@3.x.x/dist/cdn.min.js"></script>
|
|
<!-- HTMX & WebSockets Extension -->
|
|
<script src="https://unpkg.com/htmx.org@2.0.2"></script>
|
|
<script src="https://unpkg.com/htmx-ext-ws@2.0.1/ws.js"></script>
|
|
<link rel="stylesheet" href="{% static 'css/style.css' %}?v=3.0">
|
|
<meta name="csrf-token" content="{{ csrf_token }}">
|
|
</head>
|
|
<body>
|
|
|
|
<!-- Top Corporate ERP Header -->
|
|
<header class="app-header">
|
|
<div class="brand-section">
|
|
<div class="brand-logo-container">
|
|
<img src="{% static 'img/efintel_logo.png' %}" alt="EFINTEL Logo" class="brand-logo-img" />
|
|
</div>
|
|
<div class="brand-title">
|
|
<h1>EFINTEL | ERP Interno I+D+i</h1>
|
|
<p>Sistema Integrado de Control Financiero, Operaciones, Talento y Proyectos</p>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- Normalized Action Bar for ERP -->
|
|
<div class="header-actions">
|
|
<div style="font-size:0.8rem; font-weight: 600; color: white; margin-right: 15px;">
|
|
Usuario: {{ request.user.username }} | Rol: {% if request.user.groups.all %}{{ request.user.groups.all.0.name }}{% else %}Usuario{% endif %}
|
|
</div>
|
|
<a href="{% url 'export_csv' %}" class="btn-primary" style="background:#107c41; text-decoration: none;">
|
|
<i data-lucide="file-spreadsheet" style="width:16px;"></i> Exportar CSV
|
|
</a>
|
|
<a href="{% url 'expense_create' %}" class="btn-primary" style="text-decoration: none;">
|
|
<i data-lucide="plus-circle" style="width:16px;"></i> + Registrar Erogación
|
|
</a>
|
|
<a href="{% url 'logout' %}" class="btn-danger" style="text-decoration: none;">
|
|
<i data-lucide="log-out" style="width:16px;"></i> Salir
|
|
</a>
|
|
</div>
|
|
</header>
|
|
|
|
<!-- Corporate Ecosystem Navigation Bar -->
|
|
<nav class="nav-bar">
|
|
<a href="{% url 'dashboard' %}" class="nav-tab {% if request.resolver_match.url_name == 'dashboard' %}active{% endif %}">
|
|
<i data-lucide="pie-chart" style="width:16px;"></i> Resumen Financiero
|
|
</a>
|
|
<a href="{% url 'expense_list' %}" class="nav-tab {% if request.resolver_match.url_name == 'expense_list' or request.resolver_match.url_name == 'expense_report_list' %}active{% endif %}">
|
|
<i data-lucide="truck" style="width:16px;"></i> Operaciones y Erogaciones
|
|
</a>
|
|
<a href="{% url 'project_list' %}" class="nav-tab {% if 'project' in request.resolver_match.url_name %}active{% endif %}">
|
|
<i data-lucide="folder-kanban" style="width:16px;"></i> Control de Proyectos
|
|
</a>
|
|
<a href="{% url 'procurement:catalog_list' %}" class="nav-tab {% if 'procurement' in request.resolver_match.namespace %}active{% endif %}">
|
|
<i data-lucide="shopping-cart" style="width:16px;"></i> Compras & OC
|
|
</a>
|
|
<a href="{% url 'payroll:employee_list' %}" class="nav-tab {% if 'payroll' in request.resolver_match.namespace %}active{% endif %}">
|
|
<i data-lucide="users" style="width:16px;"></i> Remuneraciones
|
|
</a>
|
|
<a href="{% url 'talent:candidate_list' %}" class="nav-tab {% if 'talent' in request.resolver_match.namespace %}active{% endif %}">
|
|
<i data-lucide="award" style="width:16px;"></i> Cartera Talento
|
|
</a>
|
|
{% if 'Administrador Finanzas' in request.user.groups.all.0.name or 'Administrador' in request.user.groups.all.0.name or request.user.is_superuser %}
|
|
<a href="{% url 'accounts_payable' %}" class="nav-tab {% if request.resolver_match.url_name == 'accounts_payable' %}active{% endif %}">
|
|
<i data-lucide="calculator" style="width:16px;"></i> Cuentas por Pagar (CXP)
|
|
</a>
|
|
{% endif %}
|
|
{% if 'Administrador' in request.user.groups.all.0.name or request.user.is_superuser %}
|
|
<a href="{% url 'gestion_panel' %}" class="nav-tab {% if request.resolver_match.url_name == 'gestion_panel' %}active{% endif %}" style="margin-left:auto; background:var(--efintel-petroleum); color:white;">
|
|
<i data-lucide="settings" style="width:16px;"></i> Gestión ERP
|
|
</a>
|
|
{% endif %}
|
|
</nav>
|
|
|
|
<main class="main-container">
|
|
{% if messages %}
|
|
<div class="messages-container" style="margin-bottom: 1rem;">
|
|
{% for message in messages %}
|
|
<div class="alert alert-{{ message.tags }}" style="padding: 10px; border-radius: 4px; background: var(--efintel-light); border-left: 4px solid var(--efintel-blue); font-weight: 600;">
|
|
{{ message }}
|
|
</div>
|
|
{% endfor %}
|
|
</div>
|
|
{% endif %}
|
|
|
|
{% block content %}{% endblock %}
|
|
</main>
|
|
|
|
<!-- Requerimiento 3: Modal Universal de Previsualización de Evidencias (JPG/PNG/PDF) -->
|
|
<div id="evidencePreviewModal" style="display:none; position:fixed; top:0; left:0; width:100%; height:100%; background:rgba(15,23,42,0.85); z-index:9999; backdrop-filter:blur(4px); align-items:center; justify-content:center;">
|
|
<div style="background:white; border-radius:12px; width:90%; max-width:900px; height:85vh; display:flex; flex-direction:column; overflow:hidden; box-shadow:0 25px 50px -12px rgba(0,0,0,0.5);">
|
|
<div style="padding:1rem 1.5rem; background:var(--efintel-dark, #1e293b); color:white; display:flex; justify-content:space-between; align-items:center;">
|
|
<h3 id="previewModalTitle" style="margin:0; font-size:1.1rem; font-weight:700; color:white;">Vista Previa de Evidencia</h3>
|
|
<div style="display:flex; gap:0.5rem; align-items:center;">
|
|
<a id="previewModalDownloadBtn" href="#" target="_blank" class="btn-primary" style="padding:0.3rem 0.8rem; font-size:0.8rem; text-decoration:none; background:#0284c7;">
|
|
<i data-lucide="download" style="width:14px;"></i> Descargar
|
|
</a>
|
|
<button onclick="closePreviewModal()" style="background:transparent; border:none; color:white; font-size:1.5rem; cursor:pointer; padding:0 0.5rem;">×</button>
|
|
</div>
|
|
</div>
|
|
<div id="previewModalContent" style="flex:1; background:#f8fafc; display:flex; align-items:center; justify-content:center; padding:1rem; overflow:auto;">
|
|
<!-- Contenido dinámico embebido (Image o PDF) -->
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<script>
|
|
if (window.lucide) {
|
|
lucide.createIcons();
|
|
}
|
|
|
|
function previewDocument(fileUrl, title, isPdf) {
|
|
const modal = document.getElementById('evidencePreviewModal');
|
|
const modalTitle = document.getElementById('previewModalTitle');
|
|
const downloadBtn = document.getElementById('previewModalDownloadBtn');
|
|
const content = document.getElementById('previewModalContent');
|
|
|
|
modalTitle.textContent = title || 'Vista Previa de Evidencia';
|
|
downloadBtn.href = fileUrl;
|
|
|
|
if (isPdf || fileUrl.toLowerCase().endsWith('.pdf')) {
|
|
content.innerHTML = `<object data="${fileUrl}" type="application/pdf" width="100%" height="100%" style="min-height:70vh; border:none;">
|
|
<iframe src="${fileUrl}" width="100%" height="100%" style="min-height:70vh; border:none;">
|
|
Tu navegador no soporta visualización directa de PDF. <a href="${fileUrl}" target="_blank">Haz clic aquí para descargar.</a>
|
|
</iframe>
|
|
</object>`;
|
|
} else {
|
|
content.innerHTML = `<img src="${fileUrl}" alt="Evidencia" style="max-width:100%; max-height:75vh; object-fit:contain; border-radius:8px; box-shadow:0 4px 6px -1px rgba(0,0,0,0.1);" />`;
|
|
}
|
|
|
|
modal.style.display = 'flex';
|
|
}
|
|
|
|
function closePreviewModal() {
|
|
const modal = document.getElementById('evidencePreviewModal');
|
|
const content = document.getElementById('previewModalContent');
|
|
modal.style.display = 'none';
|
|
content.innerHTML = '';
|
|
}
|
|
|
|
// Formateador automático global para cualquier formulario presente o futuro
|
|
function styleAllFormControls() {
|
|
document.querySelectorAll('form input:not([type="checkbox"]):not([type="radio"]):not([type="submit"]):not([type="button"]):not([type="hidden"]), form select, form textarea').forEach(function(el) {
|
|
if (!el.classList.contains('form-control') && !el.classList.contains('form-input')) {
|
|
el.classList.add('form-control');
|
|
}
|
|
});
|
|
}
|
|
|
|
document.addEventListener('DOMContentLoaded', styleAllFormControls);
|
|
const formObserver = new MutationObserver(styleAllFormControls);
|
|
if (document.body) {
|
|
formObserver.observe(document.body, { childList: true, subtree: true });
|
|
}
|
|
|
|
// Cerrar modal al presionar Escape
|
|
document.addEventListener('keydown', function(e) {
|
|
if (e.key === 'Escape') closePreviewModal();
|
|
});
|
|
</script>
|
|
{% block extra_js %}{% endblock %}
|
|
<!-- Modal Vista Previa -->
|
|
<div id="previewModal" style="display:none; position:fixed; z-index:9999; left:0; top:0; width:100%; height:100%; overflow:auto; background-color:rgba(0,0,0,0.8); align-items:center; justify-content:center;">
|
|
<div style="background:#fff; margin:auto; padding:20px; border-radius:8px; width:80%; max-width:800px; max-height:90vh; display:flex; flex-direction:column; position:relative;">
|
|
<span onclick="closePreview()" style="position:absolute; right:15px; top:10px; font-size:24px; cursor:pointer; font-weight:bold;">×</span>
|
|
<h3 id="previewTitle" style="margin-top:0;">Vista Previa</h3>
|
|
<div id="previewContent" style="flex:1; overflow:hidden; display:flex; justify-content:center; align-items:center; min-height:400px;"></div>
|
|
</div>
|
|
</div>
|
|
<script>
|
|
function openPreview(url, title) {
|
|
document.getElementById("previewTitle").innerText = "Evidencia: " + title;
|
|
let contentDiv = document.getElementById("previewContent");
|
|
if(url.toLowerCase().endsWith(".pdf")) {
|
|
contentDiv.innerHTML = "<iframe src=\"" + url + "\" style=\"width:100%; height:100%; min-height:600px; border:none;\"></iframe>";
|
|
} else {
|
|
contentDiv.innerHTML = "<img src=\"" + url + "\" style=\"max-width:100%; max-height:600px; object-fit:contain;\">";
|
|
}
|
|
document.getElementById("previewModal").style.display = "flex";
|
|
}
|
|
function closePreview() {
|
|
document.getElementById("previewModal").style.display = "none";
|
|
document.getElementById("previewContent").innerHTML = "";
|
|
}
|
|
</script>
|
|
</body>
|
|
</html>
|