kaauh_ats/templates/recruitment/agency_portal_assignment_detail.html

697 lines
30 KiB
HTML

{% extends 'portal_base.html' %}
{% load static i18n %}
{% block title %}{{ assignment.job.title }} - {{ assignment.agency.name }} - Agency Portal{% endblock %}
{% block customCSS %}
<style>
/* KAAT-S UI Variables */
:root {
--kaauh-teal: #00636e;
--kaauh-teal-dark: #004a53;
--kaauh-border: #eaeff3;
--kaauh-primary-text: #343a40;
--kaauh-success: #28a745;
--kaauh-info: #17a2b8;
--kaauh-danger: #dc3545;
--kaauh-warning: #ffc107;
}
.kaauh-card {
border: 1px solid var(--kaauh-border);
border-radius: 0.75rem;
box-shadow: 0 4px 12px rgba(0,0,0,0.06);
background-color: white;
}
.btn-main-action {
background-color: var(--kaauh-teal);
border-color: var(--kaauh-teal);
color: white;
font-weight: 600;
transition: all 0.2s ease;
}
.btn-main-action:hover {
background-color: var(--kaauh-teal-dark);
border-color: var(--kaauh-teal-dark);
box-shadow: 0 4px 8px rgba(0,0,0,0.15);
}
.status-badge {
font-size: 0.75rem;
padding: 0.3em 0.7em;
border-radius: 0.35rem;
font-weight: 700;
}
.status-ACTIVE { background-color: var(--kaauh-teal-dark); color: white; }
.status-EXPIRED { background-color: var(--kaauh-teal-dark); color: white; }
.status-COMPLETED { background-color: var(--kaauh-teal-dark); color: white; }
.status-CANCELLED { background-color: var(--kaauh-teal-dark); color: white; }
.progress-ring {
width: 120px;
height: 120px;
position: relative;
}
.progress-ring-circle {
transition: stroke-dashoffset 0.35s;
transform: rotate(-90deg);
transform-origin: 50% 50%;
}
.progress-ring-text {
position: absolute;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
font-size: 1.5rem;
font-weight: 700;
color: var(--kaauh-teal-dark);
}
.candidate-item {
border-left: 4px solid var(--kaauh-teal);
background-color: #f8f9fa;
padding: 1rem;
margin-bottom: 1rem;
border-radius: 0 0.5rem 0.5rem 0;
transition: all 0.2s ease;
}
.candidate-item:hover {
background-color: #e9ecef;
transform: translateX(2px);
}
.message-item {
border-left: 4px solid var(--kaauh-teal);
background-color: #f8f9fa;
padding: 1rem;
margin-bottom: 1rem;
border-radius: 0 0.5rem 0.5rem 0;
}
.message-item.unread {
border-left-color: var(--kaauh-info);
background-color: #e7f3ff;
}
</style>
{% endblock %}
{% block content %}
<div class="container-fluid py-4">
<!-- Header -->
<div class="d-flex justify-content-between align-items-center mb-4">
<div>
<h1 class="h3 mb-1" style="color: var(--kaauh-teal-dark); font-weight: 700;">
<i class="fas fa-briefcase me-2"></i>
{{ assignment.job.title }}
</h1>
<p class="text-muted mb-0">
{% trans "Assignment Details" %} - {{ assignment.agency.name }}
</p>
</div>
<div>
<a href="{% url 'agency_portal_dashboard' %}" class="btn btn-outline-secondary btn-sm me-2">
<i class="fas fa-arrow-left me-1"></i> {% trans "Back to Dashboard" %}
</a>
<a href="{% url 'agency_portal_submit_application_page' assignment.slug %}" class="btn btn-sm btn-main-action {% if assignment.is_full %}disabled{% endif %}" >
<i class="fas fa-user-plus me-1"></i> {% trans "Submit New application" %}
</a>
{% comment %} <a href="#" class="btn btn-outline-info">
<i class="fas fa-envelope me-1"></i> {% trans "Messages" %}
{% if total_unread_messages > 0 %}
<span class="badge bg-danger ms-1">{{ total_unread_messages }}</span>
{% endif %}
</a> {% endcomment %}
</div>
</div>
<div class="row">
<!-- Assignment Overview -->
<div class="col-lg-8">
<!-- Assignment Details Card -->
<div class="kaauh-card p-4 mb-4">
<h5 class="mb-4" style="color: var(--kaauh-teal-dark);">
<i class="fas fa-info-circle me-2"></i>
{% trans "Assignment Details" %}
</h5>
<div class="row">
<div class="col-md-6">
<div class="mb-3">
<label class="text-muted small">{% trans "Job Title" %}</label>
<div class="fw-bold">{{ assignment.job.title }}</div>
<div class="text-muted small">{{ assignment.job.department }}</div>
</div>
<div class="mb-3">
<label class="text-muted small">{% trans "Status" %}</label>
<div>
<span class="status-badge status-{{ assignment.status }}" >
{{ assignment.get_status_display }}
</span>
</div>
</div>
</div>
<div class="col-md-6">
<div class="mb-3">
<label class="text-muted small">{% trans "Deadline" %}</label>
<div class="{% if assignment.is_expired %}text-danger{% else %}text-muted{% endif %}">
<i class="fas fa-calendar-alt me-1"></i>
{{ assignment.deadline_date|date:"Y-m-d H:i" }}
</div>
{% if assignment.is_expired %}
<small class="text-danger">
<i class="fas fa-exclamation-triangle me-1"></i>{% trans "Expired" %}
</small>
{% else %}
<small class="text-primary-theme">
<i class="fas fa-clock me-1"></i>{{ assignment.days_remaining }} {% trans "days remaining" %}
</small>
{% endif %}
</div>
<div class="mb-3">
<label class="text-muted small">{% trans "Maximum applications" %}</label>
<div class="fw-bold">{{max_applications }} {% trans "applications" %}</div>
</div>
</div>
</div>
{% if assignment.job.description %}
<div class="mt-3 pt-3 border-top">
<label class="text-muted small">{% trans "Job Description " %}</label>
<div class="text-muted">
{{ assignment.job.description|safe|truncatewords:50 }}</div>
</div>
{% endif %}
</div>
<!-- Quick Actions Card -->
{% comment %} <div class="kaauh-card p-4 mb-4">
<h5 class="mb-4" style="color: var(--kaauh-teal-dark);">
<i class="fas fa-bolt me-2"></i>
{% trans "Quick Actions" %}
</h5>
<div class="d-grid gap-2">
{% if assignment.can_submit %}
<a href="{% url 'agency_portal_submit_application_page' assignment.slug %}" class="btn btn-main-action">
<i class="fas fa-user-plus me-1"></i> {% trans "Submit New application" %}
</a>
{% else %}
<button class="btn btn-outline-secondary" disabled>
<i class="fas fa-user-plus me-1"></i> {% trans "Cannot Submit applications" %}
</button>
<div class="alert alert-warning mt-2">
<i class="fas fa-exclamation-triangle me-2"></i>
{% if assignment.is_expired %}
{% trans "This assignment has expired. Submissions are no longer accepted." %}
{% elif assignment.is_full %}
{% trans "Maximum application limit reached for this assignment." %}
{% else %}
{% trans "This assignment is not currently active." %}
{% endif %}
</div>
{% endif %}
<a href="{% url 'agency_portal_dashboard' %}" class="btn btn-outline-secondary">
<i class="fas fa-dashboard me-1"></i> {% trans "Dashboard" %}
</a>
<a href="#" class="btn btn-outline-info">
<i class="fas fa-comments me-1"></i> {% trans "All Messages" %}
</a>
</div>
</div>
<!-- Submitted applications --> {% endcomment %}
<div class="kaauh-card p-4">
<div class="d-flex justify-content-between align-items-center mb-4">
<h5 class="mb-0" style="color: var(--kaauh-teal-dark);">
<i class="fas fa-users me-2"></i>
{% trans "Submitted applications" %} ({{ total_applications }})
</h5>
<span class="badge bg-primary-theme">{{ total_applications }}/{{ max_applications }}</span>
</div>
{% if page_obj %}
<div class="table-responsive">
<table class="table table-hover">
<thead>
<tr>
<th>{% trans "Name" %}</th>
<th>{% trans "Contact" %}</th>
<th>{% trans "Stage" %}</th>
<th>{% trans "Submitted" %}</th>
<th>{% trans "Actions" %}</th>
</tr>
</thead>
<tbody>
{% for application in page_obj %}
<tr>
<td>
<div class="fw-bold">{{ application.name }}</div>
</td>
<td>
<div class="small">
<div><i class="fas fa-envelope me-1"></i> {{ application.email }}</div>
<div><i class="fas fa-phone me-1"></i> {{ application.phone }}</div>
</div>
</td>
<td>
<span class="badge bg-primary-theme">{{ application.get_stage_display }}</span>
</td>
<td>
<div class="small text-muted">
{{ application.created_at|date:"Y-m-d H:i" }}
</div>
</td>
<td>
<a href="{% url 'applicant_application_detail' application.slug %}" class="btn btn-sm btn-outline-primary" title="{% trans 'View Profile' %}">
<i class="fas fa-eye"></i>
</a>
</td>
</tr>
{% endfor %}
</tbody>
</table>
</div>
<!-- Pagination -->
{% if page_obj.has_other_pages %}
<nav aria-label="Candidate pagination">
<ul class="pagination justify-content-center">
{% if page_obj.has_previous %}
<li class="page-item">
<a class="page-link" href="?page={{ page_obj.previous_page_number }}">
<i class="fas fa-chevron-left"></i>
</a>
</li>
{% endif %}
{% for num in page_obj.paginator.page_range %}
{% if page_obj.number == num %}
<li class="page-item active">
<span class="page-link">{{ num }}</span>
</li>
{% elif num > page_obj.number|add:'-3' and num < page_obj.number|add:'3' %}
<li class="page-item">
<a class="page-link" href="?page={{ num }}">{{ num }}</a>
</li>
{% endif %}
{% endfor %}
{% if page_obj.has_next %}
<li class="page-item">
<a class="page-link" href="?page={{ page_obj.next_page_number }}">
<i class="fas fa-chevron-right"></i>
</a>
</li>
{% endif %}
</ul>
</nav>
{% endif %}
{% else %}
<div class="text-center py-4">
<i class="fas fa-users fa-2x text-muted mb-3"></i>
<h6 class="text-muted">{% trans "No applications submitted yet" %}</h6>
<p class="text-muted small">
{% trans "Submit applications using the form above to get started." %}
</p>
</div>
{% endif %}
</div>
</div>
<!-- Sidebar -->
</div>
<div class="col-lg-4 col-md-12">
<!-- Progress Card -->
<div class="col kaauh-card p-4 mb-4">
<h5 class="mb-4 text-center" style="color: var(--kaauh-teal-dark);">
{% trans "Submission Progress" %}
</h5>
<div class="text-center mb-3">
<div class="progress-ring">
<svg width="120" height="120">
<circle class="progress-ring-circle"
stroke="#e9ecef"
stroke-width="8"
fill="transparent"
r="52"
cx="60"
cy="60"/>
<circle class="progress-ring-circle"
stroke="var(--kaauh-teal)"
stroke-width="8"
fill="transparent"
r="52"
cx="60"
cy="60"
style="stroke-dasharray: 326.73; stroke-dashoffset: {{ stroke_dashoffset }};"/>
</svg>
<div class="progress-ring-text">
{% widthratio total_applications assignment.max_candidates 100 as progress %}
{{ progress|floatformat:0 }}%
</div>
</div>
</div>
<div class="text-center">
<div class="h4 mb-1">{{ total_applications }}</div>
<div class="text-muted">/ {{ assignment.max_candidates }} {% trans "applications" %}</div>
</div>
<div class="progress mt-3" style="height: 8px;">
{% widthratio total_applications assignment.max_candidates 100 as progress %}
<div class="progress-bar bg-primary-theme" style="width: {{ progress }}%"></div>
</div>
<div class="mt-3 text-center">
{% if assignment.can_submit %}
<span class="badge bg-primary-theme">{% trans "Can Submit" %}</span>
{% else %}
<span class="badge bg-danger">{% trans "Cannot Submit" %}</span>
{% endif %}
</div>
</div>
<!-- Assignment Info Card -->
<div class="col kaauh-card p-4">
<h5 class="mb-4" style="color: var(--kaauh-teal-dark);">
<i class="fas fa-info me-2"></i>
{% trans "Assignment Info" %}
</h5>
<div class="mb-3">
<label class="text-muted small">{% trans "Assigned Date" %}</label>
<div class="fw-bold">{{ assignment.assigned_date|date:"Y-m-d" }}</div>
</div>
<div class="mb-3">
<label class="text-muted small">{% trans "Days Remaining" %}</label>
<div class="fw-bold {% if assignment.days_remaining <= 3 %}text-danger{% endif %}">
{{ assignment.days_remaining }} {% trans "days" %}
</div>
</div>
<div class="mb-3">
<label class="text-muted small">{% trans "Submission Rate" %}</label>
<div class="fw-bold">
{% widthratio total_applications assignment.max_candidates 100 as progress %}
{{ progress|floatformat:1 }}%
</div>
</div>
</div>
</div>
<!-- Recent Messages Section -->
{% if message_page_obj %}
<div class="kaauh-card p-4 mt-4">
<h5 class="mb-4" style="color: var(--kaauh-teal-dark);">
<i class="fas fa-comments me-2"></i>
{% trans "Recent Messages" %}
</h5>
<div class="row">
{% for message in message_page_obj|slice:":6" %}
<div class="col-lg-6 mb-3">
<div class="message-item {% if not message.is_read %}unread{% endif %}">
<div class="d-flex justify-content-between align-items-start mb-2">
<div class="fw-bold">{{ message.subject }}</div>
<small class="text-muted">{{ message.created_at|date:"Y-m-d H:i" }}</small>
</div>
<div class="small text-muted mb-2">
{% trans "From" %}: {{ message.sender.get_full_name }}
</div>
<div class="small">{{ message.message|truncatewords:30 }}</div>
{% if not message.is_read %}
<span class="badge bg-info mt-2">{% trans "New" %}</span>
{% endif %}
</div>
</div>
{% endfor %}
</div>
{% if message_page_obj.count > 6 %}
<div class="text-center mt-3">
<a href="#" class="btn btn-outline-primary btn-sm">
{% trans "View All Messages" %}
</a>
</div>
{% endif %}
</div>
{% endif %}
</div>
<!-- Message Modal -->
<div class="modal fade" id="messageModal" tabindex="-1">
<div class="modal-dialog">
<div class="modal-content">
<div class="modal-header">
<h5 class="modal-title">
<i class="fas fa-envelope me-2"></i>
{% trans "Send Message to Admin" %}
</h5>
<button type="button" class="btn-close" data-bs-dismiss="modal"></button>
</div>
<form method="post" action="#">
{% csrf_token %}
<input type="hidden" name="assignment_id" value="{{ assignment.id }}">
<div class="modal-body">
<div class="mb-3">
<label for="subject" class="form-label">
{% trans "Subject" %} <span class="text-danger">*</span>
</label>
<input type="text" class="form-control" id="subject" name="subject" required>
</div>
<div class="mb-3">
<label for="priority" class="form-label">{% trans "Priority" %}</label>
<select class="form-select" id="priority" name="priority">
<option value="low">{% trans "Low" %}</option>
<option value="medium" selected>{% trans "Medium" %}</option>
<option value="high">{% trans "High" %}</option>
<option value="urgent">{% trans "Urgent" %}</option>
</select>
</div>
<div class="mb-3">
<label for="content" class="form-label">
{% trans "Message" %} <span class="text-danger">*</span>
</label>
<textarea class="form-control" id="content" name="content" rows="5" required></textarea>
</div>
</div>
<div class="modal-footer">
<button type="button" class="btn btn-outline-primary" data-bs-dismiss="modal">
{% trans "Cancel" %}
</button>
<button type="submit" class="btn btn-main-action">
<i class="fas fa-paper-plane me-1"></i> {% trans "Send Message" %}
</button>
</div>
</form>
</div>
</div>
</div>
<!-- Edit application Modal -->
<div class="modal fade" id="editCandidateModal" tabindex="-1">
<div class="modal-dialog">
<div class="modal-content">
<div class="modal-header">
<h5 class="modal-title">
<i class="fas fa-edit me-2"></i>
{% trans "Edit application" %}
</h5>
<button type="button" class="btn-close" data-bs-dismiss="modal"></button>
</div>
<form id="editCandidateForm" method="post" action="{% url 'agency_portal_edit_application' 0 %}">
{% csrf_token %}
<input type="hidden" id="edit_candidate_id" name="candidate_id">
<div class="modal-body">
<div class="row">
<div class="col-md-6 mb-3">
<label for="edit_first_name" class="form-label">
{% trans "First Name" %} <span class="text-danger">*</span>
</label>
<input type="text" class="form-control" id="edit_first_name" name="first_name" required>
</div>
<div class="col-md-6 mb-3">
<label for="edit_last_name" class="form-label">
{% trans "Last Name" %} <span class="text-danger">*</span>
</label>
<input type="text" class="form-control" id="edit_last_name" name="last_name" required>
</div>
</div>
<div class="row">
<div class="col-md-6 mb-3">
<label for="edit_email" class="form-label">
{% trans "Email" %} <span class="text-danger">*</span>
</label>
<input type="email" class="form-control" id="edit_email" name="email" required>
</div>
<div class="col-md-6 mb-3">
<label for="edit_phone" class="form-label">
{% trans "Phone" %} <span class="text-danger">*</span>
</label>
<input type="tel" class="form-control" id="edit_phone" name="phone" required>
</div>
</div>
<div class="mb-3">
<label for="edit_address" class="form-label">
{% trans "Address" %} <span class="text-danger">*</span>
</label>
<textarea class="form-control" id="edit_address" name="address" rows="3" required></textarea>
</div>
</div>
<div class="modal-footer">
<button type="button" class="btn btn-secondary" data-bs-dismiss="modal">
{% trans "Cancel" %}
</button>
<button type="submit" class="btn btn-main-action">
<i class="fas fa-save me-1"></i> {% trans "Save Changes" %}
</button>
</div>
</form>
</div>
</div>
</div>
<!-- Delete Confirmation Modal -->
<div class="modal fade" id="deleteCandidateModal" tabindex="-1">
<div class="modal-dialog">
<div class="modal-content">
<div class="modal-header">
<h5 class="modal-title">
<i class="fas fa-trash me-2"></i>
{% trans "Remove application" %}
</h5>
<button type="button" class="btn-close" data-bs-dismiss="modal"></button>
</div>
<form id="deleteCandidateForm" method="post" action="{% url 'agency_portal_delete_application' 0 %}">
{% csrf_token %}
<input type="hidden" id="delete_candidate_id" name="candidate_id">
<div class="modal-body">
<div class="alert alert-warning">
<i class="fas fa-exclamation-triangle me-2"></i>
{% trans "Are you sure you want to remove this application? This action cannot be undone." %}
</div>
<p><strong>{% trans "Application:" %}</strong> <span id="delete_candidate_name"></span></p>
</div>
<div class="modal-footer">
<button type="button" class="btn btn-secondary" data-bs-dismiss="modal">
{% trans "Cancel" %}
</button>
<button type="submit" class="btn btn-danger">
<i class="fas fa-trash me-1"></i> {% trans "Remove Application" %}
</button>
</div>
</form>
</div>
</div>
</div>
{% endblock %}
{% block customJS %}
<script>
// Edit Candidate
function editCandidate(candidateId) {
// Update form action URL with candidate ID
const editForm = document.getElementById('editCandidateForm');
editForm.action = editForm.action.replace('/0/', `/${candidateId}/`);
// Fetch candidate data and populate modal
fetch(`/api/candidate/${candidateId}/`)
.then(response => response.json())
.then(data => {
document.getElementById('edit_candidate_id').value = data.id;
document.getElementById('edit_first_name').value = data.first_name;
document.getElementById('edit_last_name').value = data.last_name;
document.getElementById('edit_email').value = data.email;
document.getElementById('edit_phone').value = data.phone;
document.getElementById('edit_address').value = data.address;
new bootstrap.Modal(document.getElementById('editCandidateModal')).show();
})
.catch(error => {
console.error('Error fetching Application:', error);
alert('{% trans "Error loading Application data. Please try again." %}');
});
}
// Delete Application
function deleteCandidate(candidateId, candidateName) {
// Update form action URL with candidate ID
const deleteForm = document.getElementById('deleteCandidateForm');
deleteForm.action = deleteForm.action.replace('/0/', `/${candidateId}/`);
document.getElementById('delete_candidate_id').value = candidateId;
document.getElementById('delete_candidate_name').textContent = candidateName;
new bootstrap.Modal(document.getElementById('deleteCandidateModal')).show();
}
// Handle form submissions
document.getElementById('editCandidateForm').addEventListener('submit', function(e) {
e.preventDefault();
const formData = new FormData(this);
fetch(this.action, {
method: 'POST',
body: formData,
headers: {
'X-Requested-With': 'XMLHttpRequest'
}
})
.then(response => response.json())
.then(data => {
if (data.success) {
bootstrap.Modal.getInstance(document.getElementById('editCandidateModal')).hide();
location.reload();
} else {
alert(data.message || '{% trans "Error updating Application. Please try again." %}');
}
})
.catch(error => {
console.error('Error:', error);
alert('{% trans "Error updating Application. Please try again." %}');
});
});
document.getElementById('deleteCandidateForm').addEventListener('submit', function(e) {
e.preventDefault();
const formData = new FormData(this);
fetch(this.action, {
method: 'POST',
body: formData,
headers: {
'X-Requested-With': 'XMLHttpRequest'
}
})
.then(response => response.json())
.then(data => {
if (data.success) {
bootstrap.Modal.getInstance(document.getElementById('deleteCandidateModal')).hide();
location.reload();
} else {
alert(data.message || '{% trans "Error removing Application. Please try again." %}');
}
})
.catch(error => {
console.error('Error:', error);
alert('{% trans "Error removing Application. Please try again." %}');
});
});
// Auto-focus on first input in submission form
document.addEventListener('DOMContentLoaded', function() {
const firstNameField = document.getElementById('first_name');
if (firstNameField) {
firstNameField.focus();
}
});
</script>
{% endblock %}