kaauh_ats/templates/recruitment/applicant_application_detail.html
2025-12-10 13:56:51 +03:00

702 lines
33 KiB
HTML

{% extends 'portal_base.html' %}
{% load static i18n %}
{% block title %}{% trans "Application Details" %} - ATS{% endblock %}
{% block customCSS %}
<style>
/* Kaauh Theme Variables - Assuming these are defined in portal_base */
:root {
/* Assuming these are carried from your global CSS/base template */
--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-secondary: #6c757d; /* Added secondary color for general use */
}
/* Theme Utilities */
.bg-primary-theme {
background-color: var(--kaauh-teal) !important;
}
.text-primary-theme {
color: var(--kaauh-teal) !important;
}
/* 1. Application Progress Timeline (Improved Spacing) */
.application-progress {
position: relative;
/* Use flexbox for layout */
display: flex;
/* Use gap for consistent space between elements */
gap: 1.5rem;
/* Center the timeline content */
justify-content: center;
margin: 2rem 0 3rem; /* Extra spacing below timeline */
padding: 0 1rem;
overflow-x: auto; /* Allow horizontal scroll for small screens */
}
.progress-step {
/* Use fixed width or rely on content width for cleaner flow */
position: relative;
text-align: center;
/* Prevent shrinking */
flex-shrink: 0;
/* Added min-width for label spacing */
min-width: 100px;
}
/* Timeline Connector Line */
.progress-step::before {
content: '';
position: absolute;
top: 20px;
/* Adjust position to connect centered steps */
left: calc(-50% + 20px);
width: calc(100% - 40px);
height: 2px;
background: var(--kaauh-border);
z-index: -1;
}
/* Hide line for the first step */
.progress-step:first-child::before {
display: none;
}
.progress-step.completed::before {
background: var(--kaauh-success);
}
.progress-step.active::before {
/* Line leading up to the active step should be completed/success color */
background: var(--kaauh-success);
}
.progress-icon {
width: 40px;
height: 40px;
border-radius: 50%;
background: var(--kaauh-border);
display: flex;
align-items: center;
justify-content: center;
margin: 0 auto 0.5rem;
font-weight: bold;
color: #6c757d;
position: relative;
z-index: 2; /* Ensure icon covers the line */
}
.progress-step.completed .progress-icon {
background: var(--kaauh-success);
color: white;
}
.progress-step.active .progress-icon {
background: var(--kaauh-teal);
color: white;
/* Add a subtle shadow for focus */
box-shadow: 0 0 0 4px rgba(0, 99, 110, 0.2);
}
.progress-label {
font-size: 0.875rem;
color: #6c757d;
margin-top: 0.5rem;
line-height: 1.2;
}
.progress-step.completed .progress-label,
.progress-step.active .progress-label {
color: var(--kaauh-primary-text);
font-weight: 600;
}
/* Status Badges - Using Kaauh Theme */
.status-badge {
font-size: 0.875rem;
padding: 0.5rem 1rem;
border-radius: 20px;
font-weight: 600;
}
/* Card Header Consistency */
.card-header{
padding: 1rem 1.5rem; /* Increased padding */
border-top-left-radius: 0.75rem;
border-top-right-radius: 0.75rem;
border-bottom: none;
}
/* Table Actions Theme */
.table .btn-primary {
background-color: var(--kaauh-teal);
border-color: var(--kaauh-teal);
}
.table .btn-primary:hover {
background-color: var(--kaauh-teal-dark);
border-color: var(--kaauh-teal-dark);
}
.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);
}
/* Style for action cards to make text smaller */
.action-card .card-body h6 {
font-size: 1rem;
}
.action-card .card-body p {
font-size: 0.75rem;
margin-bottom: 0.75rem;
}
.action-card .card-body {
padding: 1.5rem 1rem;
}
/* Custom Alert for Document Review */
.alert-purple {
background-color: #e5e0ff;
border-color: #c9c0ff;
color: #5d49a3;
}
</style>
{% endblock %}
{% block content %}
<div class="container-fluid">
<!-- Breadcrumb Navigation -->
{% if not application.hiring_agency %}
<nav aria-label="breadcrumb" class="mb-4">
<ol class="breadcrumb">
<li class="breadcrumb-item">
<a href="{% url 'applicant_portal_dashboard' %}" class=" text-decoration-none text-secondary">{% trans "Dashboard" %}</a>
</li>
<li class="breadcrumb-item">
<a href="{% url 'applicant_portal_dashboard' %}#applications" class="text-secondary text-decoration-none">{% trans "My Applications" %}</a>
</li>
<li class="breadcrumb-item active" aria-current="page" style="
color: #F43B5E; /* Rosy Accent Color */
font-weight: 600;
">
{% trans "Application Details" %}
</li>
</ol>
</nav>
{% endif %}
<div class="row mb-4">
<div class="col-12">
<div class="kaauh-card">
<div class="card-header bg-primary-theme text-white">
<div class="row align-items-center">
<div class="col-md-8">
<h4 class="mb-1">
<i class="fas fa-briefcase me-2"></i>
{{ application.job.title }}
</h4>
<p class="mb-0 opacity-75">
<small>{% trans "Application ID:" %} {{ application.slug }}</small>
</p>
</div>
<div class="col-md-4 text-end">
<div class="d-inline-block p-1 rounded-pill" style="background-color: rgba(255, 255, 255, 0.2);">
<span class="status-badge status-{{ application.stage }}">
{{ application.get_stage_display }}
</span>
</div>
</div>
</div>
</div>
<div class="card-body pt-5">
<div class="application-progress">
<div class="progress-step {% if application.stage != 'Applied' and application.stage != 'Rejected' %}completed{% else %}active{% endif %}" style="flex: 0 0 auto;">
<div class="progress-icon">
<i class="fas fa-paper-plane"></i>
</div>
<div class="progress-label">{% trans "Applied" %}</div>
</div>
{% if application.stage in 'Exam,Interview,Document Review,Offer,Hired,Rejected' %}
<div class="progress-step {% if application.stage not in 'Applied,Exam' and application.stage != 'Rejected' %}completed{% elif application.stage == 'Exam' %}active{% endif %}" style="flex: 0 0 auto;">
<div class="progress-icon">
<i class="fas fa-clipboard-check"></i>
</div>
<div class="progress-label">{% trans "Exam" %}</div>
</div>
{% endif %}
{% if application.stage in 'Interview,Document Review,Offer,Hired,Rejected' %}
<div class="progress-step {% if application.stage not in 'Applied,Exam,Interview' and application.stage != 'Rejected' %}completed{% elif application.stage == 'Interview' %}active{% endif %}" style="flex: 0 0 auto;">
<div class="progress-icon">
<i class="fas fa-video"></i>
</div>
<div class="progress-label">{% trans "Interview" %}</div>
</div>
{% endif %}
{% if application.stage in 'Document Review,Offer,Hired,Rejected' %}
<div class="progress-step {% if application.stage not in 'Applied,Exam,Interview,Document Review' and application.stage != 'Rejected' %}completed{% elif application.stage == 'Document Review' %}active{% endif %}" style="flex: 0 0 auto;">
<div class="progress-icon">
<i class="fas fa-file-alt"></i>
</div>
<div class="progress-label">{% trans "Document Review" %}</div>
</div>
{% endif %}
{% if application.stage in 'Offer,Hired,Rejected' %}
<div class="progress-step {% if application.stage not in 'Applied,Exam,Interview,Document Review,Offer' and application.stage != 'Rejected' %}completed{% elif application.stage == 'Offer' %}active{% endif %}" style="flex: 0 0 auto;">
<div class="progress-icon">
<i class="fas fa-handshake"></i>
</div>
<div class="progress-label">{% trans "Offer" %}</div>
</div>
{% endif %}
{% if application.stage in 'Hired,Rejected' %}
<div class="progress-step {% if application.stage == 'Hired' %}completed{% elif application.stage == 'Rejected' %}active{% endif %}" style="flex: 0 0 auto;">
<div class="progress-icon">
<i class="fas {% if application.stage == 'Hired' %}fa-trophy{% else %}fa-times-circle{% endif %}"></i>
</div>
<div class="progress-label">{% trans "Final Status" %}</div>
</div>
{% endif %}
</div>
<div class="row mt-4 g-4">
<div class="col-md-3">
<div class="text-center p-3 bg-light rounded h-100 shadow-sm">
<i class="fas fa-calendar-alt text-primary-theme fa-2x mb-2"></i>
<h6 class="text-muted small">{% trans "Applied Date" %}</h6>
<p class="mb-0 fw-bold">{{ application.created_at|date:"M d, Y" }}</p>
</div>
</div>
<div class="col-md-3">
<div class="text-center p-3 bg-light rounded h-100 shadow-sm">
<i class="fas fa-building text-primary-theme fa-2x mb-2"></i>
<h6 class="text-muted small">{% trans "Department" %}</h6>
<p class="mb-0 fw-bold">{{ application.job.department|default:"" }}</p>
</div>
</div>
<div class="col-md-3">
<div class="text-center p-3 bg-light rounded h-100 shadow-sm">
<i class="fas fa-briefcase text-primary-theme fa-2x mb-2"></i>
<h6 class="text-muted small">{% trans "Job Type" %}</h6>
<p class="mb-0 fw-bold">{{ application.get_job_type_display }}</p>
</div>
</div>
<div class="col-md-3">
<div class="text-center p-3 bg-light rounded h-100 shadow-sm">
<i class="fas fa-map-marker-alt text-primary-theme fa-2x mb-2"></i>
<h6 class="text-muted small">{% trans "Location" %}</h6>
<p class="mb-0 fw-bold">{{ application.get_workplace_type_display }}</p>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
<div class="row mb-5">
<div class="col-md-6 col-6">
<a href="{% url 'applicant_portal_dashboard' %}" class="text-decoration-none text-dark">
<div class="kaauh-card h-50 shadow-sm action-card">
<div class="card-body text-center mb-4">
<i class="fas fa-arrow-left fa-2x text-primary-theme mb-3"></i>
<h6>{% trans "Go to Dashboard" %}</h6>
<p class="text-muted small">{% trans "View all applications" %}</p>
<a href="{% url 'applicant_portal_dashboard' %}" class="btn btn-main-action btn-sm w-100">
{% trans "Dashboard" %}
</a>
</div>
</div>
</a>
</div>
{% if application.resume %}
<div class="col-md-6 col-6">
<a href="{{ application.resume.url }}"
target="_blank" class="text-decoration-none text-dark">
<div class="kaauh-card h-50 shadow-sm action-card">
<div class="card-body text-center mb-4">
<i class="fas fa-file-download fa-2x text-primary-theme mb-3"></i>
<h6>{% trans "Download Resume" %}</h6>
<p class="text-muted small">{% trans "Get your submitted file" %}</p>
<a href="{{ application.resume.url }}"
target="_blank"
class="btn btn-main-action btn-sm w-100">
<i class="fas fa-download me-2"></i>
{% trans "Download" %}
</a>
</div>
</div>
</a>
</div>
{% endif %}
</div>
{% if interviews %}
<div class="row mb-5">
<div class="col-12">
<div class="kaauh-card">
<div class="card-header bg-primary-theme text-white">
<h5 class="mb-0">
<i class="fas fa-video me-2"></i>
{% trans "Interview Schedule" %}
</h5>
</div>
<div class="card-body p-4">
{% if interviews %}
<div class="table-responsive">
<table class="table table-hover align-middle">
<thead class="table-light">
<tr>
<th>{% trans "Topic" %}</th>
<th>{% trans "Date" %}</th>
<th>{% trans "Time" %}</th>
<th>{% trans "Type" %}</th>
<th>{% trans "Status" %}</th>
<th>{% trans "Meeting Link" %}</th>
<th>{% trans "Physical Location" %}</th>
</tr>
</thead>
<tbody>
{% for interview in interviews %}
<tr>
<td>{{ interview.interview.topic }}</td>
<td>{{ interview.interview_date|date:"M d, Y" }}</td>
<td>{{ interview.interview_time|time:"H:i" }}</td>
<td>
{% if interview.interview.location_type == 'Remote' %}
<span class="badge bg-primary-theme">
<i class="fas fa-laptop me-1"></i>
{% trans "Remote" %}
</span>
{% else %}
<span class="badge bg-primary-theme">
<i class="fas fa-building me-1"></i>
{% trans "On-site" %}
</span>
{% endif %}
</td>
<td>
{% if interview.interview.status %}
<span class="badge bg-primary-theme">
{{ interview.interview.status|capfirst }}
</span>
{% endif %}
</td>
<td>
{% if interview.interview and interview.interview.location_type == 'Remote' %}
<a href="{{ interview.interview.details_url }}"
target="_blank"
class="btn btn-sm bg-primary-theme text-white">
<i class="fas fa-video me-1"></i>
{% trans "Join" %}
</a>
{% else %}
<span class="text-muted">-</span>
{% endif %}
</td>
<td>
{% if interview.interview.physical_address %}
<span class="badge bg-primary-theme">{{interview.interview.physical_address}}</span>
{% endif %}
</td>
</tr>
{% endfor %}
</tbody>
</table>
</div>
{% else %}
<div class="text-center py-4">
<i class="fas fa-calendar-times fa-3x text-muted mb-3"></i>
<p class="text-muted">{% trans "No interviews scheduled yet." %}</p>
</div>
{% endif %}
</div>
</div>
</div>
</div>
{% endif %}
{% if application.stage == "Document Review" %}
<div class="row mb-5">
<div class="col-12">
<div class="kaauh-card">
<div class="card-header bg-primary-theme text-white">
<div class="row align-items-center">
<div class="col">
<h5 class="mb-0">
<i class="fas fa-file-alt me-2"></i>
{% trans "Documents" %}
</h5>
</div>
<div class="col-auto">
<button class="btn btn-outline-secondary text-white" data-bs-toggle="modal" data-bs-target="#uploadDocumentModal">
<i class="fas fa-plus me-1"></i>
{% trans "Upload Document" %}
</button>
</div>
</div>
</div>
<div class="card-body p-4">
{% if documents %}
<div class="table-responsive">
<table class="table table-hover align-middle">
<thead class="table-light">
<tr>
<th>{% trans "Document Name" %}</th>
<th>{% trans "Type" %}</th>
<th>{% trans "Upload Date" %}</th>
<th>{% trans "File Size" %}</th>
<th>{% trans "Actions" %}</th>
</tr>
</thead>
<tbody>
{% for document in documents %}
<tr>
<td>
{% if document.file %}
<a href="{{ document.file.url }}"
target="_blank"
class="text-decoration-none text-primary-theme">
<i class="fas fa-file-pdf text-danger me-2"></i>
{{ document.get_document_type_display }}
</a>
{% else %}
{{ document.get_document_type_display }}
{% endif %}
</td>
<td>
<span class="badge bg-light text-dark">
{{ document.get_document_type_display }}
</span>
</td>
<td>{{ document.created_at|date:"M d, Y" }}</td>
<td>
{% if document.file %}
{% with file_size=document.file.size|filesizeformat %}
{{ file_size }}
{% endwith %}
{% else %}
-
{% endif %}
</td>
<td>
{% if document.file %}
<a href="{{ document.file.url }}"
class="btn btn-sm btn-outline-primary me-1"
target="_blank">
<i class="fas fa-download"></i>
{% trans "Download" %}
</a>
<button class="btn btn-sm btn-outline-danger" onclick="deleteDocument({{ document.id }})">
<i class="fas fa-trash"></i>
</button>
{% endif %}
</td>
</tr>
{% endfor %}
</tbody>
</table>
</div>
{% else %}
<div class="text-center py-4">
<i class="fas fa-file-upload fa-3x text-muted mb-3"></i>
<p class="text-muted">{% trans "No documents uploaded." %}</p>
<button class="btn btn-main-action" data-bs-toggle="modal" data-bs-target="#uploadDocumentModal">
<i class="fas fa-plus me-2"></i>
{% trans "Upload Your First Document" %}
</button>
</div>
{% endif %}
</div>
</div>
</div>
</div>
{% endif %}
<!-- Next Steps Section -->
<div class="row">
<div class="col-12">
<div class="kaauh-card">
<div class="card-header bg-primary-theme text-white">
<h5 class="mb-0">
<i class="fas fa-info-circle me-2"></i>
{% trans "Next Steps" %}
</h5>
</div>
<div class="card-body p-4">
{% if application.stage == 'Applied' %}
<div class="alert bg-primary-theme text-white">
<i class="fas fa-clock me-2"></i>
{% trans "Your application is being reviewed by our recruitment team. You will receive an update within 3-5 business days." %}
</div>
{% elif application.stage == 'Screening' %}
<div class="alert bg-primary-theme text-white">
<i class="fas fa-search me-2"></i>
{% trans "Your application is currently under screening. We are evaluating your qualifications against the job requirements." %}
</div>
{% elif application.stage == 'Document Review' %}
<div class="alert bg-primary-theme text-white">
<i class="fas fa-file-alt me-2"></i>
{% trans "Please upload the required documents for review. Our team will evaluate your submitted materials." %}
</div>
{% elif application.stage == 'Exam' %}
<div class="alert bg-primary-theme text-white">
<i class="fas fa-clipboard-check me-2"></i>
{% trans "You have been shortlisted for an assessment. Please check your email for exam details and preparation materials." %}
</div>
{% elif application.stage == 'Interview' %}
<div class="alert bg-primary-theme text-white">
<i class="fas fa-video me-2"></i>
{% trans "Congratulations! You have been selected for an interview. Please check the interview schedule above and prepare accordingly." %}
</div>
{% elif application.stage == 'Offer' %}
<div class="alert bg-primary-theme text-white">
<i class="fas fa-handshake me-2"></i>
{% trans "You have received a job offer! Please check your email for the detailed offer letter and next steps." %}
</div>
{% elif application.stage == 'Hired' %}
<div class="alert bg-primary-theme text-white">
<i class="fas fa-trophy me-2"></i>
{% trans "Welcome to the team! You will receive onboarding information shortly." %}
</div>
{% elif application.stage == 'Rejected' %}
<div class="alert bg-primary-theme text-white">
<i class="fas fa-times-circle me-2"></i>
{% trans "Thank you for your interest. Unfortunately, your application was not selected at this time. We encourage you to apply for other positions." %}
</div>
{% endif %}
</div>
</div>
</div>
</div>
</div>
<div class="modal fade" id="uploadDocumentModal" tabindex="-1">
<div class="modal-dialog">
<div class="modal-content">
<div class="modal-header">
<h5 class="modal-title">{% trans "Upload Document" %}</h5>
<button type="button" class="btn-close" data-bs-dismiss="modal"></button>
</div>
{% include "forms/document_form.html" with slug=application.slug %}
{% comment %} <form action="{% url 'document_upload' application.slug %}" method="POST" enctype="multipart/form-data">
{% csrf_token %}
<div class="modal-body">
<div class="mb-3">
<label for="documentType" class="form-label">{% trans "Document Type" %}</label>
<select class="form-select" id="documentType" name="document_type" required>
<option value="">{% trans "Select document type" %}</option>
<option value="resume">{% trans "Resume" %}</option>
<option value="cover_letter">{% trans "Cover Letter" %}</option>
<option value="transcript">{% trans "Academic Transcript" %}</option>
<option value="certificate">{% trans "Certificate" %}</option>
<option value="portfolio">{% trans "Portfolio" %}</option>
<option value="other">{% trans "Other" %}</option>
</select>
</div>
<div class="mb-3">
<label for="documentDescription" class="form-label">{% trans "Description" %}</label>
<textarea class="form-control" id="documentDescription" name="description" rows="3"></textarea>
</div>
<div class="mb-3">
<label for="documentFile" class="form-label">{% trans "Choose File" %}</label>
<input type="file" class="form-control" id="documentFile" name="file" accept=".pdf,.doc,.docx,.jpg,.png" required>
<div class="form-text">{% trans "Accepted formats: PDF, DOC, DOCX, JPG, PNG (Max 5MB)" %}</div>
</div>
<input type="hidden" name="application_slug" value="{{ application.slug }}">
</div>
<div class="modal-footer">
<button type="button" class="btn btn-outline-secondary btn-lg" data-bs-dismiss="modal">{% trans "Cancel" %}</button>
<button type="submit" class="btn btn-main-action">
<i class="fas fa-upload me-2"></i>
{% trans "Upload" %}
</button>
</div>
</form> {% endcomment %}
</div>
</div>
</div>
<script>
function addToCalendar(year, month, day, time, title) {
// Create Google Calendar URL
const startDate = new Date(year, month - 1, day, time.split(':')[0], time.split(':')[1]);
const endDate = new Date(startDate.getTime() + 60 * 60 * 1000); // Add 1 hour
const formatDate = (date) => {
return date.toISOString().replace(/-|:|\.\d\d\d/g, '');
};
const googleCalendarUrl = `https://calendar.google.com/calendar/render?action=TEMPLATE&text=${encodeURIComponent(title)}&dates=${formatDate(startDate)}/${formatDate(endDate)}&details=${encodeURIComponent('Interview scheduled via ATS')}`;
window.open(googleCalendarUrl, '_blank');
}
function deleteDocument(documentId) {
if (confirm('{% trans "Are you sure you want to delete this document?" %}')) {
fetch(`/documents/${documentId}/delete/`, {
method: 'POST',
headers: {
'X-CSRFToken': getCookie('csrftoken'),
'Content-Type': 'application/json',
},
})
.then(response => response.json())
.then(data => {
if (data.success) {
location.reload();
} else {
alert('{% trans "Error deleting document. Please try again." %}');
}
})
.catch(error => {
console.error('Error:', error);
alert('{% trans "Error deleting document. Please try again." %}');
});
}
}
// Helper function to get CSRF token
function getCookie(name) {
let cookieValue = null;
if (document.cookie && document.cookie !== '') {
const cookies = document.cookie.split(';');
for (let i = 0; i < cookies.length; i++) {
const cookie = cookies[i].trim();
if (cookie.substring(0, name.length + 1) === (name + '=')) {
cookieValue = decodeURIComponent(cookie.substring(name.length + 1));
break;
}
}
}
return cookieValue;
}
</script>
{% endblock %}