kaauh_ats/templates/recruitment/candidate_application_detail.html

671 lines
32 KiB
HTML

{% extends 'portal_base.html' %}
{% load static i18n %}
{% block title %}{% trans "Application Details" %} - ATS{% endblock %}
{% block customCSS %}
<style>
/* Application Progress Timeline - Using Kaauh Theme Colors */
.application-progress {
position: relative;
display: flex;
justify-content: space-between;
margin: 2rem 0;
}
.progress-step {
flex: 1;
text-align: center;
position: relative;
}
.progress-step::before {
content: '';
position: absolute;
top: 20px;
left: 50%;
width: 100%;
height: 2px;
background: var(--kaauh-border);
z-index: -1;
}
.progress-step:first-child::before {
display: none;
}
.progress-step.completed::before {
background: var(--kaauh-success);
}
.progress-step.active::before {
background: var(--kaauh-teal);
}
.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: 1;
}
.progress-step.completed .progress-icon {
background: var(--kaauh-success);
color: white;
}
.progress-step.active .progress-icon {
background: var(--kaauh-teal);
color: white;
}
.progress-label {
font-size: 0.875rem;
color: #6c757d;
margin-top: 0.5rem;
}
.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;
}
.status-applied { background: #e3f2fd; color: #1976d2; }
.status-screening { background: #fff3e0; color: #f57c00; }
.status-document_review { background: #f3e5f5; color: #7b1fa2; }
.status-exam { background: #f3e5f5; color: #7b1fa2; }
.status-interview { background: #e8f5e8; color: #388e3c; }
.status-offer { background: #fff8e1; color: #f9a825; }
.status-hired { background: #e8f5e8; color: #2e7d32; }
.status-rejected { background: #ffebee; color: #c62828; }
/* AI Score Circle - Using Theme Colors */
.ai-score-circle {
width: 80px;
height: 80px;
border-radius: 50%;
display: flex;
align-items: center;
justify-content: center;
font-size: 1.5rem;
font-weight: bold;
color: white;
margin: 0 auto 1rem;
}
.ai-score-high { background: linear-gradient(135deg, var(--kaauh-success), #20c997); }
.ai-score-medium { background: linear-gradient(135deg, var(--kaauh-warning), #fd7e14); }
.ai-score-low { background: linear-gradient(135deg, var(--kaauh-danger), #e83e8c); }
/* Alert Purple - Using Theme Colors */
.alert-purple {
color: #4a148c;
background-color: #f3e5f5;
border-color: #ce93d8;
}
.card-header{
padding: 0.75rem 1.25rem;
}
</style>
{% endblock %}
{% block content %}
<div class="container-fluid">
<!-- Breadcrumb Navigation -->
<nav aria-label="breadcrumb" class="mb-4">
<ol class="breadcrumb">
<li class="breadcrumb-item">
<a href="{% url 'candidate_portal_dashboard' %}">{% trans "Dashboard" %}</a>
</li>
<li class="breadcrumb-item">
<a href="{% url 'candidate_portal_dashboard' %}#applications">{% trans "My Applications" %}</a>
</li>
<li class="breadcrumb-item active" aria-current="page">
{% trans "Application Details" %}
</li>
</ol>
</nav>
<!-- Application Header with Progress -->
<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-2">
<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">
<span class="status-badge status-{{ application.stage }}">
{{ application.get_stage_display }}
</span>
</div>
</div>
</div>
<div class="card-body">
<!-- Application Progress Timeline -->
<div class="application-progress">
<!-- Applied Stage - Always shown -->
<div class="progress-step {% if application.stage != 'Applied' %}completed{% else %}active{% endif %}">
<div class="progress-icon">
<i class="fas fa-paper-plane"></i>
</div>
<div class="progress-label">{% trans "Applied" %}</div>
</div>
<!-- Exam Stage - Show if current stage is Exam or beyond -->
{% if application.stage in 'Exam,Interview,Document Review,Offer,Hired,Rejected' %}
<div class="progress-step {% if application.stage not in 'Applied,Exam' %}completed{% elif application.stage == 'Exam' %}active{% endif %}">
<div class="progress-icon">
<i class="fas fa-clipboard-check"></i>
</div>
<div class="progress-label">{% trans "Exam" %}</div>
</div>
{% endif %}
<!-- Interview Stage - Show if current stage is Interview or beyond -->
{% if application.stage in 'Interview,Document Review,Offer,Hired,Rejected' %}
<div class="progress-step {% if application.stage not in 'Applied,Exam,Interview' %}completed{% elif application.stage == 'Interview' %}active{% endif %}">
<div class="progress-icon">
<i class="fas fa-video"></i>
</div>
<div class="progress-label">{% trans "Interview" %}</div>
</div>
{% endif %}
<!-- Document Review Stage - Show if current stage is Document Review or beyond -->
{% if application.stage in 'Document Review,Offer,Hired,Rejected' %}
<div class="progress-step {% if application.stage not in 'Applied,Exam,Interview,Document Review' %}completed{% elif application.stage == 'Document Review' %}active{% endif %}">
<div class="progress-icon">
<i class="fas fa-file-alt"></i>
</div>
<div class="progress-label">{% trans "Document Review" %}</div>
</div>
{% endif %}
<!-- Offer Stage - Show if current stage is Offer or beyond -->
{% if application.stage in 'Offer,Hired,Rejected' %}
<div class="progress-step {% if application.stage not in 'Applied,Exam,Interview,Document Review,Offer' %}completed{% elif application.stage == 'Offer' %}active{% endif %}">
<div class="progress-icon">
<i class="fas fa-handshake"></i>
</div>
<div class="progress-label">{% trans "Offer" %}</div>
</div>
{% endif %}
<!-- Hired Stage - Show only if current stage is Hired or Rejected -->
{% if application.stage in 'Hired,Rejected' %}
<div class="progress-step {% if application.stage == 'Hired' %}completed{% elif application.stage == 'Rejected' %}active{% endif %}">
<div class="progress-icon">
<i class="fas fa-trophy"></i>
</div>
<div class="progress-label">{% trans "Hired" %}</div>
</div>
{% endif %}
</div>
<!-- Application Details Grid -->
<div class="row mt-4">
<div class="col-md-3">
<div class="text-center p-3 bg-light rounded">
<i class="fas fa-calendar-alt text-primary-theme fa-2x mb-2"></i>
<h6 class="text-muted">{% 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">
<i class="fas fa-building text-info fa-2x mb-2"></i>
<h6 class="text-muted">{% 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">
<i class="fas fa-briefcase text-success fa-2x mb-2"></i>
<h6 class="text-muted">{% 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">
<i class="fas fa-map-marker-alt text-warning fa-2x mb-2"></i>
<h6 class="text-muted">{% trans "Location" %}</h6>
<p class="mb-0 fw-bold">{{ application.get_workplace_type_display }}</p>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
<!-- Interview Details -->
{% if interviews %}
<div class="row mb-4">
<div class="col-12">
<div class="kaauh-card">
<div class="card-header bg-success text-white">
<h5 class="mb-0">
<i class="fas fa-video me-2"></i>
{% trans "Interview Schedule" %}
</h5>
</div>
<div class="card-body">
{% if interviews %}
<div class="table-responsive">
<table class="table table-hover">
<thead>
<tr>
<th>{% trans "Date" %}</th>
<th>{% trans "Time" %}</th>
<th>{% trans "Type" %}</th>
<th>{% trans "Status" %}</th>
<th>{% trans "Meeting Link" %}</th>
<th>{% trans "Actions" %}</th>
</tr>
</thead>
<tbody>
{% for interview in interviews %}
<tr>
<td>{{ interview.interview_date|date:"M d, Y" }}</td>
<td>{{ interview.interview_time|time:"H:i" }}</td>
<td>
{% if interview.zoom_meeting %}
<span class="badge bg-primary">
<i class="fas fa-laptop me-1"></i>
{% trans "Remote" %}
</span>
{% else %}
<span class="badge bg-secondary">
<i class="fas fa-building me-1"></i>
{% trans "On-site" %}
</span>
{% endif %}
</td>
<td>
<span class="badge bg-{{ interview.status|lower }} text-white">
{{ interview.get_status_display }}
</span>
</td>
<td>
{% if interview.zoom_meeting and interview.zoom_meeting.join_url %}
<a href="{{ interview.zoom_meeting.join_url }}"
target="_blank"
class="btn btn-sm btn-primary">
<i class="fas fa-video me-1"></i>
{% trans "Join" %}
</a>
{% else %}
<span class="text-muted">-</span>
{% endif %}
</td>
<td>
{% if interview.zoom_meeting and interview.zoom_meeting.join_url %}
<button class="btn btn-sm btn-outline-primary" onclick="addToCalendar({{ interview.interview_date|date:'Y' }}, {{ interview.interview_date|date:'m' }}, {{ interview.interview_date|date:'d' }}, '{{ interview.interview_time|time:'H:i' }}', '{{ application.job.title }}')">
<i class="fas fa-calendar-plus me-1"></i>
{% trans "Add to Calendar" %}
</button>
{% 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 %}
<!-- Documents Section -->
{% if application.stage == "Document Review" %}
<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">
<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-sm btn-light" 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">
{% if documents %}
<div class="table-responsive">
<table class="table table-hover">
<thead>
<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">
<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 %}
<!-- Action Cards -->
<div class="row mb-4">
<div class="col-md-3 mb-3">
<div class="kaauh-card h-100">
<div class="card-body text-center">
<i class="fas fa-arrow-left fa-2x text-primary-theme mb-3"></i>
<h6>{% trans "Back to Dashboard" %}</h6>
<p class="text-muted small">{% trans "View all your applications" %}</p>
<a href="{% url 'candidate_portal_dashboard' %}" class="btn btn-main-action w-100">
{% trans "Go to Dashboard" %}
</a>
</div>
</div>
</div>
{% if application.resume %}
<div class="col-md-3 mb-3">
<div class="kaauh-card h-100">
<div class="card-body text-center">
<i class="fas fa-download fa-2x text-success mb-3"></i>
<h6>{% trans "Download Resume" %}</h6>
<p class="text-muted small">{% trans "Get your submitted resume" %}</p>
<a href="{{ application.resume.url }}"
target="_blank"
class="btn btn-main-action w-100">
<i class="fas fa-download me-2"></i>
{% trans "Download" %}
</a>
</div>
</div>
</div>
{% endif %}
<div class="col-md-3 mb-3">
<div class="kaauh-card h-100">
<div class="card-body text-center">
<i class="fas fa-print fa-2x text-info mb-3"></i>
<h6>{% trans "Print Application" %}</h6>
<p class="text-muted small">{% trans "Get a printable version" %}</p>
<button class="btn btn-main-action w-100" onclick="window.print()">
<i class="fas fa-print me-2"></i>
{% trans "Print" %}
</button>
</div>
</div>
</div>
{% comment %} <div class="col-md-3 mb-3">
<div class="kaauh-card h-100">
<div class="card-body text-center">
<i class="fas fa-edit fa-2x text-warning mb-3"></i>
<h6>{% trans "Update Profile" %}</h6>
<p class="text-muted small">{% trans "Edit your personal information" %}</p>
<a href="" class="btn btn-main-action w-100">
<i class="fas fa-edit me-2"></i>
{% trans "Update" %}
</a>
</div>
</div>
</div> {% endcomment %}
</div>
<!-- Next Steps Section -->
{% comment %} <div class="row">
<div class="col-12">
<div class="kaauh-card">
<div class="card-header bg-primary text-white">
<h5 class="mb-0">
<i class="fas fa-info-circle me-2"></i>
{% trans "Next Steps" %}
</h5>
</div>
<div class="card-body">
{% if application.stage == 'Applied' %}
<div class="alert alert-info">
<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 alert-warning">
<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 alert-purple">
<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 alert-purple">
<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 alert-success">
<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 alert-warning">
<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 alert-success">
<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 alert-danger">
<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> {% endcomment %}
</div>
<!-- Upload Document Modal -->
<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>
<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-secondary" 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>
</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 content %}