431 lines
20 KiB
HTML
431 lines
20 KiB
HTML
{% extends 'base.html' %}
|
|
{% load static %}
|
|
|
|
{% block title %}Assign Department Head - {{ department.name }}{% endblock %}
|
|
|
|
{% block content %}
|
|
<div class="content">
|
|
<div class="container-fluid">
|
|
<!-- Page Header -->
|
|
<div class="row">
|
|
<div class="col-12">
|
|
<div class="page-header">
|
|
<div class="page-title">
|
|
<h4>Assign Department Head</h4>
|
|
<h6>{{ department.code }} - {{ department.name }}</h6>
|
|
</div>
|
|
<div class="page-btn">
|
|
<a href="{% url 'core:department_detail' department.pk %}" class="btn btn-secondary">
|
|
<i class="fas fa-arrow-left me-1"></i>Back to Department
|
|
</a>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<div class="row justify-content-center">
|
|
<div class="col-lg-8 col-md-10 col-12">
|
|
<!-- Department Information -->
|
|
<div class="card">
|
|
<div class="card-header">
|
|
<h5 class="card-title mb-0">
|
|
<i class="fas fa-building me-2"></i>
|
|
Department Information
|
|
</h5>
|
|
</div>
|
|
<div class="card-body">
|
|
<div class="row">
|
|
<div class="col-md-6">
|
|
<table class="table table-borderless">
|
|
<tr>
|
|
<td><strong>Department Code:</strong></td>
|
|
<td>{{ department.code }}</td>
|
|
</tr>
|
|
<tr>
|
|
<td><strong>Department Name:</strong></td>
|
|
<td>{{ department.name }}</td>
|
|
</tr>
|
|
<tr>
|
|
<td><strong>Type:</strong></td>
|
|
<td>
|
|
<span class="badge bg-primary">{{ department.get_department_type_display }}</span>
|
|
</td>
|
|
</tr>
|
|
</table>
|
|
</div>
|
|
<div class="col-md-6">
|
|
<table class="table table-borderless">
|
|
<tr>
|
|
<td><strong>Current Head:</strong></td>
|
|
<td>
|
|
{% if current_head %}
|
|
<div class="d-flex align-items-center">
|
|
<div class="avatar-sm me-2">
|
|
<span class="avatar-title rounded-circle bg-success text-white">
|
|
{{ current_head.first_name|first|upper }}{{ current_head.last_name|first|upper }}
|
|
</span>
|
|
</div>
|
|
<div>
|
|
<strong>{{ current_head.get_full_name }}</strong>
|
|
<br><small class="text-muted">{{ current_head.email }}</small>
|
|
</div>
|
|
</div>
|
|
{% else %}
|
|
<span class="text-muted">No department head assigned</span>
|
|
{% endif %}
|
|
</td>
|
|
</tr>
|
|
<tr>
|
|
<td><strong>Status:</strong></td>
|
|
<td>
|
|
{% if department.is_active %}
|
|
<span class="badge bg-success">Active</span>
|
|
{% else %}
|
|
<span class="badge bg-danger">Inactive</span>
|
|
{% endif %}
|
|
</td>
|
|
</tr>
|
|
</table>
|
|
</div>
|
|
</div>
|
|
|
|
{% if department.description %}
|
|
<div class="row">
|
|
<div class="col-12">
|
|
<hr>
|
|
<p><strong>Description:</strong></p>
|
|
<p class="text-muted">{{ department.description }}</p>
|
|
</div>
|
|
</div>
|
|
{% endif %}
|
|
</div>
|
|
</div>
|
|
|
|
<!-- Assignment Form -->
|
|
<div class="card">
|
|
<div class="card-header">
|
|
<h5 class="card-title mb-0">
|
|
<i class="fas fa-user-tie me-2"></i>
|
|
Department Head Assignment
|
|
</h5>
|
|
</div>
|
|
<div class="card-body">
|
|
<form method="post" id="assignmentForm">
|
|
{% csrf_token %}
|
|
|
|
<div class="row">
|
|
<div class="col-12">
|
|
<div class="form-group">
|
|
<label for="user_id" class="form-label">
|
|
Select Department Head <span class="text-danger">*</span>
|
|
</label>
|
|
<select name="user_id" id="user_id" class="form-select" required>
|
|
<option value="">Choose a staff member...</option>
|
|
{% for user in eligible_users %}
|
|
<option value="{{ user.id }}"
|
|
data-email="{{ user.email }}"
|
|
data-phone="{{ user.phone|default:'' }}"
|
|
data-department="{{ user.department|default:'' }}">
|
|
{{ user.get_full_name }} - {{ user.email }}
|
|
</option>
|
|
{% endfor %}
|
|
</select>
|
|
<small class="form-text text-muted">
|
|
Only active staff members are eligible to be department heads.
|
|
</small>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- Selected User Preview -->
|
|
<div class="row" id="userPreview" style="display: none;">
|
|
<div class="col-12">
|
|
<div class="alert alert-info">
|
|
<h6><i class="fas fa-info-circle me-2"></i>Selected User Information</h6>
|
|
<div class="row">
|
|
<div class="col-md-6">
|
|
<p><strong>Name:</strong> <span id="previewName"></span></p>
|
|
<p><strong>Email:</strong> <span id="previewEmail"></span></p>
|
|
</div>
|
|
<div class="col-md-6">
|
|
<p><strong>Phone:</strong> <span id="previewPhone"></span></p>
|
|
<p><strong>Current Department:</strong> <span id="previewDepartment"></span></p>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- Warning for Current Head -->
|
|
{% if current_head %}
|
|
<div class="row">
|
|
<div class="col-12">
|
|
<div class="alert alert-warning">
|
|
<h6><i class="fas fa-exclamation-triangle me-2"></i>Current Department Head</h6>
|
|
<p class="mb-0">
|
|
<strong>{{ current_head.get_full_name }}</strong> is currently the head of this department.
|
|
Assigning a new head will automatically remove the current assignment.
|
|
</p>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
{% endif %}
|
|
|
|
<!-- Action Buttons -->
|
|
<div class="row">
|
|
<div class="col-12">
|
|
<div class="form-group text-end">
|
|
<a href="{% url 'core:department_detail' department.pk %}" class="btn btn-secondary me-2">
|
|
<i class="fas fa-times me-1"></i>Cancel
|
|
</a>
|
|
|
|
{% if current_head %}
|
|
<button type="button" class="btn btn-warning me-2" onclick="removeDepartmentHead()">
|
|
<i class="fas fa-user-minus me-1"></i>Remove Current Head
|
|
</button>
|
|
{% endif %}
|
|
|
|
<button type="submit" class="btn btn-primary" id="assignButton">
|
|
<i class="fas fa-user-plus me-1"></i>Assign Department Head
|
|
</button>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</form>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- Eligible Users List -->
|
|
{% if eligible_users %}
|
|
<div class="card">
|
|
<div class="card-header">
|
|
<h5 class="card-title mb-0">
|
|
<i class="fas fa-users me-2"></i>
|
|
Eligible Staff Members ({{ eligible_users.count }})
|
|
</h5>
|
|
</div>
|
|
<div class="card-body">
|
|
<div class="table-responsive">
|
|
<table class="table table-hover">
|
|
<thead>
|
|
<tr>
|
|
<th>Name</th>
|
|
<th>Email</th>
|
|
<th>Phone</th>
|
|
<th>Current Department</th>
|
|
<th>Action</th>
|
|
</tr>
|
|
</thead>
|
|
<tbody>
|
|
{% for user in eligible_users %}
|
|
<tr>
|
|
<td>
|
|
<div class="d-flex align-items-center">
|
|
<div class="avatar-sm me-2">
|
|
<span class="avatar-title rounded-circle bg-primary text-white">
|
|
{{ user.first_name|first|upper }}{{ user.last_name|first|upper }}
|
|
</span>
|
|
</div>
|
|
<div>
|
|
<strong>{{ user.get_full_name }}</strong>
|
|
{% if user.is_superuser %}
|
|
<span class="badge bg-danger ms-1">Admin</span>
|
|
{% elif user.is_staff %}
|
|
<span class="badge bg-info ms-1">Staff</span>
|
|
{% endif %}
|
|
</div>
|
|
</div>
|
|
</td>
|
|
<td>{{ user.email }}</td>
|
|
<td>{{ user.phone|default:"-" }}</td>
|
|
<td>{{ user.department|default:"-" }}</td>
|
|
<td>
|
|
<button type="button" class="btn btn-sm btn-outline-primary"
|
|
onclick="selectUser('{{ user.id }}', '{{ user.get_full_name }}')">
|
|
<i class="fas fa-hand-pointer me-1"></i>Select
|
|
</button>
|
|
</td>
|
|
</tr>
|
|
{% endfor %}
|
|
</tbody>
|
|
</table>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
{% else %}
|
|
<div class="card">
|
|
<div class="card-body text-center">
|
|
<i class="fas fa-users-slash fa-3x text-muted mb-3"></i>
|
|
<h5>No Eligible Staff Members</h5>
|
|
<p class="text-muted">
|
|
There are no active staff members available to assign as department head.
|
|
</p>
|
|
<a href="{% url 'core:department_detail' department.pk %}" class="btn btn-secondary">
|
|
<i class="fas fa-arrow-left me-1"></i>Back to Department
|
|
</a>
|
|
</div>
|
|
</div>
|
|
{% endif %}
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<script>
|
|
document.addEventListener('DOMContentLoaded', function() {
|
|
const userSelect = document.getElementById('user_id');
|
|
const userPreview = document.getElementById('userPreview');
|
|
const assignButton = document.getElementById('assignButton');
|
|
const assignmentForm = document.getElementById('assignmentForm');
|
|
|
|
// Handle user selection change
|
|
userSelect.addEventListener('change', function() {
|
|
const selectedOption = this.options[this.selectedIndex];
|
|
|
|
if (this.value) {
|
|
// Show user preview
|
|
document.getElementById('previewName').textContent = selectedOption.text.split(' - ')[0];
|
|
document.getElementById('previewEmail').textContent = selectedOption.dataset.email;
|
|
document.getElementById('previewPhone').textContent = selectedOption.dataset.phone || 'Not provided';
|
|
document.getElementById('previewDepartment').textContent = selectedOption.dataset.department || 'None';
|
|
|
|
userPreview.style.display = 'block';
|
|
assignButton.disabled = false;
|
|
} else {
|
|
userPreview.style.display = 'none';
|
|
assignButton.disabled = true;
|
|
}
|
|
});
|
|
|
|
// Form submission confirmation
|
|
assignmentForm.addEventListener('submit', function(e) {
|
|
const selectedOption = userSelect.options[userSelect.selectedIndex];
|
|
const userName = selectedOption.text.split(' - ')[0];
|
|
|
|
const confirmed = confirm(
|
|
`Are you sure you want to assign ${userName} as the head of {{ department.name }}?`
|
|
);
|
|
|
|
if (!confirmed) {
|
|
e.preventDefault();
|
|
} else {
|
|
// Show loading state
|
|
assignButton.disabled = true;
|
|
assignButton.innerHTML = '<i class="fas fa-spinner fa-spin me-1"></i>Assigning...';
|
|
}
|
|
});
|
|
});
|
|
|
|
function selectUser(userId, userName) {
|
|
const userSelect = document.getElementById('user_id');
|
|
userSelect.value = userId;
|
|
|
|
// Trigger change event to update preview
|
|
const event = new Event('change');
|
|
userSelect.dispatchEvent(event);
|
|
|
|
// Scroll to form
|
|
document.getElementById('assignmentForm').scrollIntoView({
|
|
behavior: 'smooth',
|
|
block: 'start'
|
|
});
|
|
|
|
// Highlight the form briefly
|
|
const card = document.getElementById('assignmentForm').closest('.card');
|
|
card.style.border = '2px solid #007bff';
|
|
setTimeout(() => {
|
|
card.style.border = '';
|
|
}, 2000);
|
|
}
|
|
|
|
function removeDepartmentHead() {
|
|
const confirmed = confirm(
|
|
'Are you sure you want to remove the current department head?\n\n' +
|
|
'This will leave the department without a head until a new one is assigned.'
|
|
);
|
|
|
|
if (confirmed) {
|
|
// Create a form to submit the removal
|
|
const form = document.createElement('form');
|
|
form.method = 'POST';
|
|
form.action = '';
|
|
|
|
// Add CSRF token
|
|
const csrfToken = document.querySelector('[name=csrfmiddlewaretoken]').value;
|
|
const csrfInput = document.createElement('input');
|
|
csrfInput.type = 'hidden';
|
|
csrfInput.name = 'csrfmiddlewaretoken';
|
|
csrfInput.value = csrfToken;
|
|
form.appendChild(csrfInput);
|
|
|
|
// Add empty user_id to indicate removal
|
|
const userIdInput = document.createElement('input');
|
|
userIdInput.type = 'hidden';
|
|
userIdInput.name = 'user_id';
|
|
userIdInput.value = '';
|
|
form.appendChild(userIdInput);
|
|
|
|
document.body.appendChild(form);
|
|
form.submit();
|
|
}
|
|
}
|
|
</script>
|
|
|
|
<style>
|
|
.avatar-sm {
|
|
width: 40px;
|
|
height: 40px;
|
|
}
|
|
|
|
.avatar-title {
|
|
width: 100%;
|
|
height: 100%;
|
|
display: flex;
|
|
align-items: center;
|
|
justify-content: center;
|
|
font-size: 14px;
|
|
font-weight: 600;
|
|
}
|
|
|
|
.table-hover tbody tr:hover {
|
|
background-color: rgba(0, 123, 255, 0.1);
|
|
}
|
|
|
|
#userPreview {
|
|
animation: fadeIn 0.3s ease-in;
|
|
}
|
|
|
|
@keyframes fadeIn {
|
|
from { opacity: 0; transform: translateY(-10px); }
|
|
to { opacity: 1; transform: translateY(0); }
|
|
}
|
|
|
|
.card {
|
|
box-shadow: 0 0.125rem 0.25rem rgba(0, 0, 0, 0.075);
|
|
border: 1px solid rgba(0, 0, 0, 0.125);
|
|
margin-bottom: 1.5rem;
|
|
}
|
|
|
|
.card-header {
|
|
background-color: rgba(0, 123, 255, 0.1);
|
|
border-bottom: 1px solid rgba(0, 0, 0, 0.125);
|
|
}
|
|
|
|
@media (max-width: 768px) {
|
|
.table-responsive {
|
|
font-size: 0.875rem;
|
|
}
|
|
|
|
.avatar-sm {
|
|
width: 32px;
|
|
height: 32px;
|
|
}
|
|
|
|
.avatar-title {
|
|
font-size: 12px;
|
|
}
|
|
}
|
|
</style>
|
|
{% endblock %}
|
|
|