429 lines
19 KiB
HTML
429 lines
19 KiB
HTML
{% extends "base.html" %}
|
|
{% load static humanize i18n %}
|
|
|
|
{% block title %}{{ candidate.name }} - {{ block.super }}{% endblock %}
|
|
|
|
{% block customCSS %}
|
|
<style>
|
|
/* ================================================= */
|
|
/* THEME VARIABLES AND GLOBAL STYLES */
|
|
/* ================================================= */
|
|
:root {
|
|
--kaauh-teal: #00636e;
|
|
--kaauh-teal-dark: #004a53;
|
|
--kaauh-border: #eaeff3;
|
|
--kaauh-primary-text: #343a40;
|
|
}
|
|
|
|
/* Primary Color Overrides */
|
|
.text-primary { color: var(--kaauh-teal) !important; }
|
|
.text-info { color: #17a2b8 !important; }
|
|
.text-success { color: #28a745 !important; }
|
|
.text-secondary { color: #6c757d !important; }
|
|
|
|
/* Main Action Button Style (Used for Download Resume) */
|
|
.btn-main-action {
|
|
background-color: var(--kaauh-teal);
|
|
border-color: var(--kaauh-teal);
|
|
color: white;
|
|
font-weight: 600;
|
|
padding: 0.6rem 1.2rem;
|
|
transition: all 0.2s ease;
|
|
display: inline-flex;
|
|
align-items: center;
|
|
gap: 0.5rem;
|
|
}
|
|
.btn-main-action:hover {
|
|
background-color: var(--kaauh-teal-dark);
|
|
border-color: var(--kaauh-teal-dark);
|
|
transform: translateY(-1px);
|
|
box-shadow: 0 4px 8px rgba(0,0,0,0.15);
|
|
}
|
|
|
|
/* Outlined Button Styles (Only used variants kept) */
|
|
.btn-outline-primary {
|
|
color: var(--kaauh-teal);
|
|
border-color: var(--kaauh-teal);
|
|
}
|
|
.btn-outline-primary:hover {
|
|
background-color: var(--kaauh-teal);
|
|
color: white;
|
|
}
|
|
.btn-outline-secondary {
|
|
color: var(--kaauh-teal-dark);
|
|
border-color: var(--kaauh-teal);
|
|
}
|
|
.btn-outline-secondary:hover {
|
|
background-color: var(--kaauh-teal-dark);
|
|
color: white;
|
|
border-color: var(--kaauh-teal-dark);
|
|
}
|
|
|
|
/* Card enhancements */
|
|
.card {
|
|
border: 1px solid var(--kaauh-border);
|
|
border-radius: 0.75rem;
|
|
overflow: hidden;
|
|
box-shadow: 0 4px 12px rgba(0,0,0,0.06);
|
|
background-color: white;
|
|
}
|
|
|
|
/* Candidate Header Card (The teal header) */
|
|
.candidate-header-card {
|
|
background: linear-gradient(135deg, var(--kaauh-teal), #004d57);
|
|
color: white;
|
|
border-radius: 0.75rem 0.75rem 0 0;
|
|
padding: 1.5rem;
|
|
box-shadow: 0 4px 10px rgba(0,0,0,0.15);
|
|
}
|
|
.candidate-header-card h1 {
|
|
font-weight: 700;
|
|
margin: 0;
|
|
font-size: 1.8rem;
|
|
}
|
|
.candidate-header-card .badge {
|
|
font-size: 0.9rem;
|
|
padding: 0.4em 0.8em;
|
|
border-radius: 0.4rem;
|
|
font-weight: 700;
|
|
}
|
|
|
|
/* Left Column Tabs (Main Content Tabs) */
|
|
.main-tabs {
|
|
border-bottom: 1px solid var(--kaauh-border);
|
|
background-color: #f8f9fa;
|
|
padding: 0 1.25rem;
|
|
}
|
|
.main-tabs .nav-link {
|
|
border: none;
|
|
border-bottom: 3px solid transparent;
|
|
color: var(--kaauh-primary-text);
|
|
font-weight: 500;
|
|
padding: 0.75rem 1rem;
|
|
margin-right: 0.5rem;
|
|
transition: all 0.2s;
|
|
}
|
|
.main-tabs .nav-link:hover {
|
|
color: var(--kaauh-teal);
|
|
}
|
|
.main-tabs .nav-link.active {
|
|
color: var(--kaauh-teal-dark) !important;
|
|
background-color: white !important;
|
|
border-bottom: 3px solid var(--kaauh-teal);
|
|
font-weight: 600;
|
|
}
|
|
|
|
/* Right Column Card (General styling) */
|
|
.right-column-card .tab-content {
|
|
padding: 1.5rem 1.25rem;
|
|
background-color: white;
|
|
}
|
|
|
|
/* ==================================== */
|
|
/* NEW: Vertical Timeline Styling */
|
|
/* ==================================== */
|
|
|
|
/* Highlight box for the current stage */
|
|
.current-stage {
|
|
border: 1px solid var(--kaauh-border);
|
|
background-color: #f0f8ff; /* Light, subtle blue background */
|
|
}
|
|
.current-stage .text-primary {
|
|
color: var(--kaauh-teal) !important;
|
|
}
|
|
|
|
.timeline {
|
|
position: relative;
|
|
padding-left: 2rem;
|
|
}
|
|
.timeline::before {
|
|
content: '';
|
|
position: absolute;
|
|
top: 0;
|
|
bottom: 0;
|
|
left: 1.25rem;
|
|
width: 2px;
|
|
background-color: var(--kaauh-border);
|
|
}
|
|
.timeline-item {
|
|
position: relative;
|
|
margin-bottom: 2rem;
|
|
padding-left: 1.5rem;
|
|
}
|
|
.timeline-icon {
|
|
position: absolute;
|
|
left: 0;
|
|
top: 0;
|
|
width: 32px;
|
|
height: 32px;
|
|
border-radius: 50%;
|
|
display: flex;
|
|
align-items: center;
|
|
justify-content: center;
|
|
color: white;
|
|
font-size: 0.8rem;
|
|
z-index: 10;
|
|
border: 4px solid white;
|
|
}
|
|
.timeline-item:last-child {
|
|
margin-bottom: 0;
|
|
}
|
|
|
|
/* Custom Timeline Background Classes for Stages (Using Bootstrap color palette) */
|
|
.timeline-bg-applied { background-color: var(--kaauh-teal) !important; }
|
|
.timeline-bg-exam { background-color: #17a2b8 !important; }
|
|
.timeline-bg-interview { background-color: #ffc107 !important; }
|
|
.timeline-bg-offer { background-color: #28a745 !important; }
|
|
.timeline-bg-rejected { background-color: #dc3545 !important; }
|
|
</style>
|
|
{% endblock %}
|
|
|
|
{% block content %}
|
|
<div class="container-fluid py-4">
|
|
<div class="row g-4">
|
|
<nav aria-label="breadcrumb">
|
|
<ol class="breadcrumb">
|
|
<li class="breadcrumb-item"><a href="{% url 'dashboard' %}" class="text-secondary">Home</a></li>
|
|
<li class="breadcrumb-item"><a href="{% url 'job_detail' candidate.job.slug %}" class="text-secondary">Job:({{candidate.job.title}})</a></li>
|
|
<li class="breadcrumb-item active" aria-current="page" class="text-secondary">Applicant Detail</li>
|
|
</ol>
|
|
</nav>
|
|
|
|
{# LEFT COLUMN: MAIN CANDIDATE DETAILS AND TABS #}
|
|
<div class="col-lg-8">
|
|
<div class="card shadow-sm no-hover">
|
|
|
|
{# HEADER SECTION #}
|
|
<div class="candidate-header-card">
|
|
<div class="d-flex justify-content-between align-items-start flex-wrap">
|
|
<div>
|
|
<h1 class="h3 mb-2">{{ candidate.name }}</h1>
|
|
<div class="d-flex align-items-center gap-2 mb-2">
|
|
|
|
<span id="stageDisplay" class="badge"
|
|
data-class="{'bg-primary': $stage == 'Applied', 'bg-info': $stage == 'Exam', 'bg-warning': $stage == 'Interview', 'bg-success': $stage == 'Offer'}"
|
|
data-signals-stage="'{{ candidate.stage }}'">
|
|
{% trans "Stage:" %}
|
|
<span data-text="$stage"></span>
|
|
</span>
|
|
</div>
|
|
<small class="text-white opacity-75">
|
|
{% trans "Applied for:" %} <strong>{{ candidate.job.title }}</strong>
|
|
</small>
|
|
</div>
|
|
{# Change Stage button #}
|
|
{% if user.is_staff %}
|
|
<button type="button" class="btn btn-outline-light btn-sm mt-1" data-bs-toggle="modal" data-bs-target="#stageUpdateModal">
|
|
<i class="fas fa-exchange-alt"></i> {% trans "Change Stage" %}
|
|
</button>
|
|
{% endif %}
|
|
</div>
|
|
</div>
|
|
|
|
{# LEFT TABS NAVIGATION #}
|
|
<ul class="nav nav-tabs main-tabs" id="candidateTabs" role="tablist">
|
|
<li class="nav-item" role="presentation">
|
|
<button class="nav-link active" id="contact-tab" data-bs-toggle="tab" data-bs-target="#contact-pane" type="button" role="tab" aria-controls="contact-pane" aria-selected="true">
|
|
<i class="fas fa-id-card me-1"></i> {% trans "Contact & Job" %}
|
|
</button>
|
|
</li>
|
|
{% if candidate.resume %}
|
|
<li class="nav-item" role="presentation">
|
|
<button class="nav-link" id="resume-tab" data-bs-toggle="tab" data-bs-target="#resume-pane" type="button" role="tab" aria-controls="resume-pane" aria-selected="false">
|
|
<i class="fas fa-file-pdf me-1"></i> {% trans "Resume" %}
|
|
</button>
|
|
</li>
|
|
{% endif %}
|
|
{% if candidate.parsed_summary %}
|
|
<li class="nav-item" role="presentation">
|
|
<button class="nav-link" id="summary-tab" data-bs-toggle="tab" data-bs-target="#summary-pane" type="button" role="tab" aria-controls="summary-pane" aria-selected="false">
|
|
<i class="fas fa-chart-bar me-1"></i> {% trans "Resume Summary" %}
|
|
</button>
|
|
</li>
|
|
{% endif %}
|
|
</ul>
|
|
|
|
<div class="card-body">
|
|
<div class="tab-content" id="candidateTabsContent">
|
|
|
|
{# TAB 1 CONTENT: CONTACT & DATES #}
|
|
<div class="tab-pane fade show active" id="contact-pane" role="tabpanel" aria-labelledby="contact-tab">
|
|
<h5 class="text-primary mb-4">{% trans "Core Details" %}</h5>
|
|
<div class="row g-4">
|
|
<div class="col-md-6">
|
|
<div class="d-flex align-items-center">
|
|
<i class="fas fa-envelope fa-2x text-muted me-3"></i>
|
|
<div>
|
|
<small class="text-muted d-block">{% trans "Email" %}</small>
|
|
<strong>{{ candidate.email }}</strong>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
<div class="col-md-6">
|
|
<div class="d-flex align-items-center">
|
|
<i class="fas fa-briefcase fa-2x text-muted me-3"></i>
|
|
<div>
|
|
<small class="text-muted d-block">{% trans "Position Applied" %}</small>
|
|
<strong>{{ candidate.job.title }}</strong>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
<div class="col-12">
|
|
<div class="d-flex align-items-center">
|
|
<i class="fas fa-calendar-check fa-2x text-muted me-3"></i>
|
|
<div>
|
|
<small class="text-muted d-block">{% trans "Applied Date" %}</small>
|
|
<div class="d-flex align-items-center gap-2">
|
|
<strong>{{ candidate.created_at|date:"M d, Y H:i" }}</strong>
|
|
<span class="badge bg-light text-dark">
|
|
<i class="far fa-clock me-1"></i>
|
|
{{ candidate.created_at|naturaltime }}
|
|
</span>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
{# TAB 2 CONTENT: RESUME #}
|
|
{% if candidate.resume %}
|
|
<div class="tab-pane fade" id="resume-pane" role="tabpanel" aria-labelledby="resume-tab">
|
|
<h5 class="text-primary mb-4">{% trans "Resume Document" %}</h5>
|
|
<div class="d-flex align-items-center justify-content-between p-3 border rounded">
|
|
<div>
|
|
<p class="mb-1"><strong>{{ candidate.resume.name }}</strong></p>
|
|
<small class="text-muted">{{ candidate.resume.name|truncatechars:30 }}</small>
|
|
</div>
|
|
<a href="{{ candidate.resume.url }}" download class="btn btn-main-action">
|
|
<i class="fas fa-download me-1"></i>
|
|
{% trans "Download Resume" %}
|
|
</a>
|
|
</div>
|
|
</div>
|
|
{% endif %}
|
|
|
|
{# TAB 3 CONTENT: PARSED SUMMARY #}
|
|
{% if candidate.parsed_summary %}
|
|
<div class="tab-pane fade" id="summary-pane" role="tabpanel" aria-labelledby="summary-tab">
|
|
<h5 class="text-primary mb-4">{% trans "AI Generated Summary" %}</h5>
|
|
<div class="border-start border-primary ps-3 pt-1 pb-1">
|
|
{% include 'includes/candidate_modal_body.html' %}
|
|
</div>
|
|
</div>
|
|
{% endif %}
|
|
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
{# RIGHT COLUMN: ACTIONS AND CANDIDATE TIMELINE #}
|
|
<div class="col-lg-4">
|
|
|
|
{# ACTIONS CARD #}
|
|
{% if user.is_staff %}
|
|
<div class="card shadow-sm mb-4 p-3">
|
|
<h5 class="text-muted mb-3"><i class="fas fa-cog me-2"></i>{% trans "Management Actions" %}</h5>
|
|
<div class="d-grid gap-2">
|
|
<a href="{% url 'candidate_update' candidate.slug %}" class="btn btn-outline-primary">
|
|
<i class="fas fa-edit"></i> {% trans "Edit Details" %}
|
|
</a>
|
|
<a href="{% url 'candidate_delete' candidate.slug %}" class="btn btn-outline-danger" onclick="return confirm('{% trans "Are you sure you want to delete this candidate?" %}')">
|
|
<i class="fas fa-trash-alt"></i> {% trans "Delete Candidate" %}
|
|
</a>
|
|
<a href="{% url 'candidate_list' %}" class="btn btn-outline-secondary">
|
|
<i class="fas fa-arrow-left"></i> {% trans "Back to List" %}
|
|
</a>
|
|
</div>
|
|
</div>
|
|
{% endif %}
|
|
|
|
{# ENHANCED: CANDIDATE JOURNEY TIMELINE CARD #}
|
|
<div class="card shadow-sm timeline-card">
|
|
<div class="card-header bg-white border-bottom py-3">
|
|
<h5 class="mb-0 text-muted"><i class="fas fa-route me-2"></i>{% trans "Candidate Journey" %}</h5>
|
|
</div>
|
|
<div class="card-body p-4">
|
|
|
|
<h6 class="text-uppercase text-secondary mb-3">{% trans "Current Stage" %}</h6>
|
|
<div class="p-3 mb-4 rounded current-stage">
|
|
<p class="mb-0 fw-bold fs-5 text-primary">{{ candidate.stage }}</p>
|
|
<small class="text-muted d-block mt-1">
|
|
{% trans "Latest status update:" %} {{ candidate.updated_at|date:"M d, Y" }}
|
|
</small>
|
|
</div>
|
|
|
|
<h6 class="text-uppercase text-secondary mb-3 pt-2 border-top">{% trans "Historical Timeline" %}</h6>
|
|
<div class="timeline">
|
|
|
|
|
|
{# Base Status: Application Submitted (Always required) #}
|
|
<div class="timeline-item">
|
|
<div class="timeline-icon timeline-bg-applied"><i class="fas fa-file-signature"></i></div>
|
|
<div class="timeline-content">
|
|
<p class="timeline-stage fw-bold mb-0 ms-2">{% trans "Application Submitted" %}</p>
|
|
<small class="text-muted">
|
|
<i class="far fa-calendar-alt me-1"></i> {{ candidate.created_at|date:"M d, Y" }}
|
|
<span class="ms-2">|</span>
|
|
<i class="far fa-clock ms-2 me-1"></i> {{ candidate.created_at|date:"h:i A" }}
|
|
</small>
|
|
</div>
|
|
|
|
</div>
|
|
{% if candidate.exam_date %}
|
|
<div class="timeline-item">
|
|
<div class="timeline-icon timeline-bg-applied"><i class="fas fa-clipboard-check"></i></div>
|
|
<div class="timeline-content">
|
|
<p class="timeline-stage fw-bold mb-0 ms-2">{% trans "Exam" %}</p>
|
|
<small class="text-muted">
|
|
<i class="far fa-calendar-alt me-1"></i> {{ candidate.exam_date|date:"M d, Y" }}
|
|
<span class="ms-2">|</span>
|
|
<i class="far fa-clock ms-2 me-1"></i> {{ candidate.exam_date|date:"h:i A" }}
|
|
</small>
|
|
</div>
|
|
|
|
</div>
|
|
{% endif %}
|
|
{% if candidate.interview_date %}
|
|
<div class="timeline-item">
|
|
<div class="timeline-icon timeline-bg-applied"><i class="fas fas fa-comments"></i></div>
|
|
<div class="timeline-content">
|
|
<p class="timeline-stage fw-bold mb-0 ms-2">{% trans "Interview" %}</p>
|
|
<small class="text-muted">
|
|
<i class="far fa-calendar-alt me-1"></i> {{ candidate.interview_date|date:"M d, Y" }}
|
|
<span class="ms-2">|</span>
|
|
<i class="far fa-clock ms-2 me-1"></i> {{ candidate.interview_date|date:"h:i A" }}
|
|
</small>
|
|
</div>
|
|
|
|
</div>
|
|
{% endif %}
|
|
|
|
{% if candidate.offer_date %}
|
|
<div class="timeline-item">
|
|
<div class="timeline-icon timeline-bg-applied"><i class="fas fas fa-handshake"></i></div>
|
|
<div class="timeline-content">
|
|
<p class="timeline-stage fw-bold mb-0 ms-2">{% trans "Offer" %}</p>
|
|
<small class="text-muted">
|
|
<i class="far fa-calendar-alt me-1"></i> {{ candidate.offer_date|date:"M d, Y" }}
|
|
<span class="ms-2">|</span>
|
|
<i class="far fa-clock ms-2 me-1"></i> {{ candidate.offer_date|date:"h:i A" }}
|
|
</small>
|
|
</div>
|
|
|
|
</div>
|
|
{% endif %}
|
|
</div>
|
|
|
|
</div>
|
|
</div>
|
|
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
{% if user.is_staff %}
|
|
{% include "recruitment/partials/stage_update_modal.html" with candidate=candidate form=stage_form %}
|
|
{% endif %}
|
|
{% endblock %} |