Feat: dashboard con gráficos, estructura CBS/Portafolios, semáforo de proyectos y cartera de especialistas

This commit is contained in:
Nachou-u
2026-08-20 18:54:58 -04:00
parent 8c0b435555
commit b692614857
25 changed files with 1717 additions and 159 deletions
+81 -44
View File
@@ -1,71 +1,108 @@
{% extends 'base.html' %}
{% block content %}
<div class="form-container">
<div class="glass-card" style="padding: 2.5rem;">
<h1 style="margin-bottom: 2rem;">
<div class="form-container" style="max-width: 800px; margin: 0 auto;">
<div class="data-card" style="padding: 2.5rem; background: white; border-radius: 8px; box-shadow: 0 4px 6px -1px rgba(0,0,0,0.05);">
<h2 style="color: var(--efintel-petroleum); margin-bottom: 2rem; border-bottom: 2px solid var(--efintel-light); padding-bottom: 1rem; display: flex; align-items: center; gap: 0.5rem;">
<i data-lucide="{% if edit_mode %}edit-3{% else %}plus-circle{% endif %}"></i>
{% if edit_mode %}Editar Colaborador (Responsable): {{ target_user.username }}{% else %}Nuevo Colaborador (Responsable){% endif %}
</h1>
</h2>
<form method="post">
{% csrf_token %}
<div class="form-group">
<label for="{{ form.username.id_for_label }}">Nombre de Usuario</label>
{{ form.username }}
{% if form.username.errors %}
<div style="color: var(--danger); font-size: 0.8rem; margin-top: 0.25rem;">{{ form.username.errors }}</div>
{% endif %}
</div>
<div class="form-group">
<label for="{{ form.email.id_for_label }}">Correo Electrónico</label>
{{ form.email }}
{% if form.email.errors %}
<div style="color: var(--danger); font-size: 0.8rem; margin-top: 0.25rem;">{{ form.email.errors }}</div>
{% endif %}
</div>
<div class="form-group">
<label for="{{ form.password.id_for_label }}">
Contraseña
{% if edit_mode %}
<span style="font-size: 0.8rem; color: var(--text-secondary);">(Opcional: Dejar en blanco para no cambiarla)</span>
<div style="display: grid; grid-template-columns: 1fr 1fr; gap: 1.5rem; margin-bottom: 1.5rem;">
<div class="form-group">
<label for="{{ form.username.id_for_label }}" style="font-weight: 600; font-size: 0.85rem; color: var(--efintel-dark);">Nombre de Usuario</label>
{{ form.username }}
{% if form.username.errors %}
<div style="color: var(--efintel-danger); font-size: 0.75rem; margin-top: 4px;">{{ form.username.errors }}</div>
{% endif %}
</label>
{{ form.password }}
{% if form.password.errors %}
<div style="color: var(--danger); font-size: 0.8rem; margin-top: 0.25rem;">{{ form.password.errors }}</div>
{% endif %}
</div>
<div class="form-group">
<label for="{{ form.email.id_for_label }}" style="font-weight: 600; font-size: 0.85rem; color: var(--efintel-dark);">Correo Electrónico</label>
{{ form.email }}
{% if form.email.errors %}
<div style="color: var(--efintel-danger); font-size: 0.75rem; margin-top: 4px;">{{ form.email.errors }}</div>
{% endif %}
</div>
</div>
<div class="form-group">
<label for="{{ form.role.id_for_label }}">Rol / Grupo del Sistema</label>
{{ form.role }}
{% if form.role.errors %}
<div style="color: var(--danger); font-size: 0.8rem; margin-top: 0.25rem;">{{ form.role.errors }}</div>
{% endif %}
<div style="display: grid; grid-template-columns: 1fr 1fr; gap: 1.5rem; margin-bottom: 1.5rem;">
<div class="form-group">
<label for="{{ form.password.id_for_label }}" style="font-weight: 600; font-size: 0.85rem; color: var(--efintel-dark);">
Contraseña
{% if edit_mode %}
<span style="font-size: 0.75rem; color: var(--efintel-gray); font-weight: 400;">(Opcional)</span>
{% endif %}
</label>
{{ form.password }}
{% if form.password.errors %}
<div style="color: var(--efintel-danger); font-size: 0.75rem; margin-top: 4px;">{{ form.password.errors }}</div>
{% endif %}
</div>
<div class="form-group">
<label for="{{ form.role.id_for_label }}" style="font-weight: 600; font-size: 0.85rem; color: var(--efintel-dark);">Rol / Grupo del Sistema</label>
{{ form.role }}
{% if form.role.errors %}
<div style="color: var(--efintel-danger); font-size: 0.75rem; margin-top: 4px;">{{ form.role.errors }}</div>
{% endif %}
</div>
</div>
<div class="form-group">
<label for="{{ form.description.id_for_label }}">Descripción / Bio del Responsable</label>
<div class="form-group" style="margin-bottom: 2rem;">
<label for="{{ form.description.id_for_label }}" style="font-weight: 600; font-size: 0.85rem; color: var(--efintel-dark);">Descripción / Bio del Responsable</label>
{{ form.description }}
{% if form.description.errors %}
<div style="color: var(--danger); font-size: 0.8rem; margin-top: 0.25rem;">{{ form.description.errors }}</div>
<div style="color: var(--efintel-danger); font-size: 0.75rem; margin-top: 4px;">{{ form.description.errors }}</div>
{% endif %}
</div>
<div style="display: flex; gap: 1rem; margin-top: 2rem;">
<button type="submit" class="btn btn-primary">Guardar</button>
<a href="{% url 'gestion_panel' %}" class="btn btn-outline">Cancelar</a>
<div class="form-group" style="margin-bottom: 2rem;">
<label style="font-weight: 600; font-size: 0.85rem; color: var(--efintel-dark);">Especialidades Técnicas (Categorías Asociadas)</label>
<p style="font-size: 0.75rem; color: var(--efintel-gray); margin-bottom: 0.75rem;">Selecciona las áreas de especialidad de este colaborador en la cartera técnica.</p>
<div class="specialties-container" style="max-height: 220px; overflow-y: auto; padding: 1rem; border: 1px solid var(--efintel-border); border-radius: 4px; background: #f8fafc;">
<style>
.specialties-container ul {
list-style: none;
padding: 0;
margin: 0;
display: grid;
grid-template-columns: repeat(auto-fill, minmax(230px, 1fr));
gap: 0.75rem;
}
.specialties-container li {
display: flex;
align-items: flex-start;
gap: 0.4rem;
font-size: 0.8rem;
color: var(--efintel-dark);
}
.specialties-container input[type="checkbox"] {
margin-top: 0.2rem;
cursor: pointer;
}
</style>
{{ form.specialties }}
</div>
{% if form.specialties.errors %}
<div style="color: var(--efintel-danger); font-size: 0.75rem; margin-top: 4px;">{{ form.specialties.errors }}</div>
{% endif %}
</div>
<div style="display: flex; gap: 1rem; padding-top: 1.5rem; border-top: 1px solid var(--efintel-light);">
<button type="submit" class="btn-primary" style="padding: 0.6rem 2rem; font-size: 0.9rem;">Guardar Responsable</button>
<a href="{% url 'gestion_panel' %}" class="btn-secondary" style="padding: 0.6rem 2rem; font-size: 0.9rem; text-decoration: none;">Cancelar</a>
</div>
</form>
</div>
</div>
<script>
// Apply form-control class to all inputs
document.querySelectorAll('input, select, textarea').forEach(el => {
// Apply form-control class to all inputs except checkboxes
document.querySelectorAll('input:not([type="checkbox"]), select, textarea').forEach(el => {
el.classList.add('form-control');
});
</script>