iteracion 2
This commit is contained in:
+81
-4
@@ -10,7 +10,8 @@
|
||||
<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>
|
||||
<link rel="stylesheet" href="{% static 'css/style.css' %}">
|
||||
<script defer src="https://cdn.jsdelivr.net/npm/alpinejs@3.x.x/dist/cdn.min.js"></script>
|
||||
<link rel="stylesheet" href="{% static 'css/style.css' %}?v=2.1">
|
||||
<meta name="csrf-token" content="{{ csrf_token }}">
|
||||
</head>
|
||||
<body>
|
||||
@@ -49,12 +50,21 @@
|
||||
<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' %}active{% endif %}">
|
||||
<i data-lucide="truck" style="width:16px;"></i> Operaciones y Gastos
|
||||
<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 request.resolver_match.url_name == 'project_list' %}active{% endif %}">
|
||||
<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)
|
||||
@@ -81,10 +91,77 @@
|
||||
{% 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 %}
|
||||
</body>
|
||||
|
||||
Reference in New Issue
Block a user