iteracion 2

This commit is contained in:
Nachou-u
2026-09-07 18:44:32 -03:00
parent a103a47ae6
commit 09a3f6fb37
93 changed files with 7394 additions and 349 deletions
+81 -4
View File
@@ -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;">&times;</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>