ATS/templates/jobs/job_detail.html
2026-01-29 14:19:03 +03:00

677 lines
40 KiB
HTML

{% extends "base.html" %}
{% load i18n static crispy_forms_tags %}
{% block title %}{{ job.title }} - KAAUH ATS{% endblock %}
{% block customCSS %}
<style>
@import url('https://fonts.googleapis.com/css2?family=Inter:wght@300;400;600;700&display=swap');
body { font-family: 'Inter', sans-serif; }
</style>
{% endblock %}
{% block content %}
<div class="container-fluid py-4">
<!-- Modal for Staff Assignment -->
<div id="staffAssignmentModal" class="fixed inset-0 bg-black/50 backdrop-blur-sm z-50 hidden flex items-center justify-center p-4">
<div class="bg-white rounded-2xl shadow-xl max-w-lg w-full">
<div class="flex items-center justify-between p-4 border-b border-gray-200">
<h5 class="text-lg font-bold text-gray-900 flex items-center gap-2">
<i data-lucide="user-plus" class="w-5 h-5"></i>
{% trans "Assign Staff Member" %}
</h5>
<button type="button" onclick="document.getElementById('staffAssignmentModal').classList.add('hidden')" class="text-gray-400 hover:text-gray-600 transition">
<i data-lucide="x" class="w-5 h-5"></i>
</button>
</div>
<div class="p-4">
<form method="post" action="{% url 'staff_assignment_view' job.slug %}">
{% csrf_token %}
{{staff_form|crispy}}
<div class="flex justify-end mt-3">
<button type="submit" class="inline-flex items-center gap-2 bg-kaauh-blue hover:bg-[#004f57] text-white font-medium px-4 py-2.5 rounded-xl text-sm transition shadow-sm hover:shadow-md">
<i data-lucide="save" class="w-4 h-4"></i>
{% trans "Save Assignment" %}
</button>
</div>
</form>
</div>
</div>
</div>
<!-- Breadcrumb -->
<nav class="mb-6" aria-label="breadcrumb">
<ol class="flex items-center gap-2 text-sm flex-wrap">
<li><a href="{% url 'dashboard' %}" class="text-gray-500 hover:text-kaauh-blue transition flex items-center gap-1">
<i data-lucide="home" class="w-4 h-4"></i> {% trans "Home" %}
</a></li>
<li class="text-gray-400">/</li>
<li><a href="{% url 'job_list' %}" class="text-gray-500 hover:text-kaauh-blue transition">{% trans "Jobs" %}</a></li>
<li class="text-gray-400">/</li>
<li class="text-temple-red font-semibold">{% trans "Job Detail" %}</li>
</ol>
</nav>
<div class="grid grid-cols-1 lg:grid-cols-12 gap-6">
<!-- LEFT COLUMN: JOB DETAILS -->
<div class="lg:col-span-7">
<div class="bg-white rounded-2xl shadow-sm border border-gray-100 overflow-hidden">
<!-- Header Section -->
<div class="bg-gradient-to-br from-temple-red to-[#7a1a29] text-white p-6">
<div class="flex flex-col md:flex-row md:items-start md:justify-between gap-4">
<div class="flex-1">
<h1 class="text-2xl font-bold mb-1">{{ job.title }}</h1>
<p class="text-sm text-white/80 mb-2">{% trans "JOB ID:" %} {{ job.internal_job_id }}</p>
{% if job.application_deadline %}
<div class="flex items-center gap-2 text-sm">
<i data-lucide="calendar-x" class="w-4 h-4"></i>
<span class="text-white font-semibold">{% trans "Deadline:" %}</span>
<span class="bg-white/20 px-2 py-0.5 rounded">{{ job.application_deadline }}</span>
</div>
{% endif %}
</div>
<div class="flex flex-col items-start md:items-end gap-3">
<!-- Status Badge -->
<div class="flex items-center gap-2">
<span class="inline-flex items-center px-3 py-1.5 rounded-full text-xs font-bold uppercase tracking-wide
{% if job.status == "ACTIVE" %}bg-emerald-500 text-white
{% elif job.status == "DRAFT" %}bg-gray-500 text-white
{% elif job.status == "CLOSED" %}bg-amber-500 text-white
{% elif job.status == "CANCELLED" %}bg-red-500 text-white
{% elif job.status == "ARCHIVED" %}bg-gray-600 text-white
{% else %}bg-gray-500 text-white{% endif %}">
{{ job.get_status_display }}
</span>
{% if user.is_superuser or user.is_staff and user == job.assigned_to %}
<button type="button" onclick="document.getElementById('editStatusModal').classList.remove('hidden')"
class="p-2 bg-white/10 hover:bg-white/20 rounded-lg text-white transition">
<i data-lucide="edit-2" class="w-4 h-4"></i>
</button>
{% endif %}
</div>
<!-- Share Link Button -->
<button type="button" id="copyJobLinkButton" data-url="{{ job.application_url }}"
class="inline-flex items-center gap-2 bg-yellow-400 hover:bg-yellow-500 text-gray-900 font-medium px-3 py-2 rounded-xl text-sm transition shadow-lg">
<i data-lucide="link" class="w-4 h-4"></i>
{% trans "Share Link" %}
</button>
<span id="copyFeedback" class="text-sm text-emerald-400 hidden">{% trans "Copied!" %}</span>
</div>
</div>
</div>
<!-- Content Section -->
<div class="p-6">
<!-- Administrative Header -->
<div class="flex items-center justify-between mb-4 pb-4 border-b border-gray-200">
<h5 class="text-sm font-bold text-gray-600 flex items-center gap-2">
<i data-lucide="settings" class="w-5 h-5"></i>
{% trans "Administrative & Location" %}
</h5>
{% if job.status == 'DRAFT' and user.is_superuser %}
<a href="{% url 'job_update' job.slug %}" class="inline-flex items-center gap-2 bg-gray-100 hover:bg-gray-200 text-gray-700 font-medium px-3 py-2 rounded-xl text-sm transition">
<i data-lucide="edit" class="w-4 h-4"></i>
{% trans "Edit Job" %}
</a>
{% endif %}
</div>
<!-- Staff Assignment -->
<div class="mb-4">
{% if job.assigned_to %}
<div class="flex items-center gap-2 text-sm">
<i data-lucide="user-tie" class="w-5 h-5 text-kaauh-blue"></i>
<span class="text-gray-600">{% trans "Assigned to:" %}</span>
<span class="font-semibold text-gray-900">{{ job.assigned_to }}</span>
</div>
{% else %}
<button type="button" onclick="document.getElementById('staffAssignmentModal').classList.remove('hidden')"
class="inline-flex items-center gap-2 bg-temple-red hover:bg-[#7a1a29] text-white font-medium px-3 py-2 rounded-xl text-sm transition shadow-sm hover:shadow-md">
<i data-lucide="user-plus" class="w-4 h-4"></i>
{% trans "Click To Assign" %}
</button>
{% endif %}
</div>
<!-- Job Details Grid -->
<div class="grid grid-cols-1 md:grid-cols-2 gap-3 mb-6 pb-6 border-b border-gray-200 text-sm">
<div class="flex items-start gap-2">
<i data-lucide="building-2" class="w-5 h-5 text-gray-400 flex-shrink-0 mt-0.5"></i>
<span class="text-gray-700"><strong>{% trans "Department:" %}</strong> {{ job.department|default:"-" }}</span>
</div>
<div class="flex items-start gap-2">
<i data-lucide="hash" class="w-5 h-5 text-gray-400 flex-shrink-0 mt-0.5"></i>
<span class="text-gray-700"><strong>{% trans "Position No:" %}</strong> {{ job.position_number|default:"-" }}</span>
</div>
<div class="flex items-start gap-2">
<i data-lucide="briefcase" class="w-5 h-5 text-gray-400 flex-shrink-0 mt-0.5"></i>
<span class="text-gray-700"><strong>{% trans "Job Type:" %}</strong> {{ job.get_job_type_display }}</span>
</div>
<div class="flex items-start gap-2">
<i data-lucide="map-pin" class="w-5 h-5 text-gray-400 flex-shrink-0 mt-0.5"></i>
<span class="text-gray-700"><strong>{% trans "Workplace:" %}</strong> {{ job.get_workplace_type_display }}</span>
</div>
<div class="flex items-start gap-2">
<i data-lucide="globe" class="w-5 h-5 text-gray-400 flex-shrink-0 mt-0.5"></i>
<span class="text-gray-700"><strong>{% trans "Location:" %}</strong> {{ job.get_location_display }}</span>
</div>
<div class="flex items-start gap-2">
<i data-lucide="banknote" class="w-5 h-5 text-gray-400 flex-shrink-0 mt-0.5"></i>
<span class="text-gray-700"><strong>{% trans "Salary:" %}</strong> {{ job.salary_range|default:"-" }}</span>
</div>
<div class="flex items-start gap-2">
<i data-lucide="user-tie" class="w-5 h-5 text-gray-400 flex-shrink-0 mt-0.5"></i>
<span class="text-gray-700"><strong>{% trans "Created By:" %}</strong> {{ job.created_by|default:"-" }}</span>
</div>
<div class="flex items-start gap-2">
<i data-lucide="calendar" class="w-5 h-5 text-gray-400 flex-shrink-0 mt-0.5"></i>
<span class="text-gray-700"><strong>{% trans "Created At:" %}</strong> {{ job.created_at|date:"M d, Y"|default:"-" }}</span>
</div>
</div>
<!-- Description Blocks -->
{% if job.has_description_content %}
<div class="mb-4">
<h5 class="text-base font-bold text-gray-900 mb-3 flex items-center gap-2">
<i data-lucide="file-text" class="w-5 h-5 text-temple-red"></i>
{% trans "Job Description" %}
</h5>
<div class="text-gray-600 text-sm leading-relaxed">{{ job.description|safe }}</div>
</div>
{% endif %}
{% if job.has_qualifications_content %}
<div class="mb-4">
<h5 class="text-base font-bold text-gray-900 mb-3 flex items-center gap-2">
<i data-lucide="award" class="w-5 h-5 text-temple-red"></i>
{% trans "Required Qualifications" %}
</h5>
<div class="text-gray-600 text-sm leading-relaxed">{{ job.qualifications|safe }}</div>
</div>
{% endif %}
{% if job.has_benefits_content %}
<div class="mb-4">
<h5 class="text-base font-bold text-gray-900 mb-3 flex items-center gap-2">
<i data-lucide="gift" class="w-5 h-5 text-temple-red"></i>
{% trans "Benefits" %}
</h5>
<div class="text-gray-600 text-sm leading-relaxed">{{ job.benefits|safe }}</div>
</div>
{% endif %}
{% if job.has_application_instructions_content %}
<div class="mb-4">
<h5 class="text-base font-bold text-gray-900 mb-3 flex items-center gap-2">
<i data-lucide="info" class="w-5 h-5 text-temple-red"></i>
{% trans "Application Instructions" %}
</h5>
<div class="text-gray-600 text-sm leading-relaxed">{{ job.application_instructions|safe }}</div>
</div>
{% endif %}
</div>
</div>
</div>
<!-- RIGHT COLUMN: TABBED CARDS -->
<div class="lg:col-span-5 space-y-4">
<!-- Main Tabbed Card -->
<div class="bg-white rounded-2xl shadow-sm border border-gray-100 overflow-hidden">
<!-- Tab Navigation -->
<div class="border-b border-gray-200 bg-gray-50 overflow-x-auto">
<div class="flex min-w-max">
<button class="tab-btn px-4 py-3 text-sm font-medium border-b-2 border-transparent hover:bg-gray-100 transition whitespace-nowrap"
onclick="showTab('applicants-pane')" data-tab="applicants-pane">
<i data-lucide="users" class="w-4 h-4 mr-2 inline"></i>
{% trans "Applications" %}
</button>
<button class="tab-btn px-4 py-3 text-sm font-medium border-b-2 border-transparent hover:bg-gray-100 transition whitespace-nowrap"
onclick="showTab('tracking-pane')" data-tab="tracking-pane">
<i data-lucide="route" class="w-4 h-4 mr-2 inline"></i>
{% trans "Tracking" %}
</button>
<button class="tab-btn px-4 py-3 text-sm font-medium border-b-2 border-transparent hover:bg-gray-100 transition whitespace-nowrap"
onclick="showTab('manage-pane')" data-tab="manage-pane">
<i data-lucide="clipboard-list" class="w-4 h-4 mr-2 inline"></i>
{% trans "Form Template" %}
</button>
<button class="tab-btn px-4 py-3 text-sm font-medium border-b-2 border-transparent hover:bg-gray-100 transition whitespace-nowrap"
onclick="showTab('staff-pane')" data-tab="staff-pane">
<i data-lucide="user-tie" class="w-4 h-4 mr-2 inline"></i>
{% trans "Assigned Staff" %}
</button>
<button class="tab-btn px-4 py-3 text-sm font-medium border-b-2 border-transparent hover:bg-gray-100 transition whitespace-nowrap"
onclick="showTab('linkedin-pane')" data-tab="linkedin-pane">
<i data-lucide="linkedin" class="w-4 h-4 mr-2 inline"></i>
{% trans "LinkedIn" %}
</button>
</div>
</div>
<!-- Tab Content -->
<div class="p-4">
<!-- Applications Tab -->
<div id="applicants-pane" class="tab-content">
<div class="flex items-center justify-between mb-4">
<h5 class="text-base font-bold text-gray-900">{% trans "Total Applications" %} (<span id="total_candidates">{{ total_applications }}</span>)</h5>
</div>
<div class="space-y-2">
<a href="{% url 'application_create_for_job' job.slug %}" class="inline-flex items-center gap-2 w-full bg-temple-red hover:bg-[#7a1a29] text-white font-medium px-4 py-2.5 rounded-xl text-sm transition shadow-sm hover:shadow-md">
<i data-lucide="user-plus" class="w-4 h-4"></i>
{% trans "Create Application" %}
</a>
<a href="{% url 'applications_screening_view' job.slug %}" class="inline-flex items-center gap-2 w-full bg-temple-red hover:bg-[#7a1a29] text-white font-medium px-4 py-2.5 rounded-xl text-sm transition shadow-sm hover:shadow-md">
<i data-lucide="layers" class="w-4 h-4"></i>
{% trans "Manage Applications" %}
</a>
<a href="{% url 'interview_calendar' job.slug %}" class="inline-flex items-center gap-2 w-full bg-temple-red hover:bg-[#7a1a29] text-white font-medium px-4 py-2.5 rounded-xl text-sm transition shadow-sm hover:shadow-md">
<i data-lucide="calendar" class="w-4 h-4"></i>
{% trans "View Calendar" %}
</a>
{% if not job.form_template.is_active %}
{% if not jobzip_created %}
<a href="{% url 'request_cvs_download' job.slug %}" class="inline-flex items-center gap-2 w-full bg-temple-red hover:bg-[#7a1a29] text-white font-medium px-4 py-2.5 rounded-xl text-sm transition shadow-sm hover:shadow-md">
<i data-lucide="download" class="w-4 h-4"></i>
{% trans "Generate All CVs" %}
</a>
{% endif %}
{% if job.zip_created %}
<a href="{% url 'download_ready_cvs' job.slug %}" class="inline-flex items-center gap-2 w-full bg-gray-100 hover:bg-gray-200 text-gray-700 font-medium px-4 py-2.5 rounded-xl text-sm transition">
<i data-lucide="eye" class="w-4 h-4"></i>
{% trans "View All CVs" %}
</a>
{% endif %}
{% else %}
<p class="text-sm text-gray-500">{% trans "Bulk CV download is inactive. To activate please change the status of job to CLOSED." %}</p>
{% endif %}
</div>
</div>
<!-- Tracking Tab -->
<div id="tracking-pane" class="tab-content hidden">
<h5 class="text-base font-bold text-gray-900 mb-3 flex items-center gap-2">
<i data-lucide="route" class="w-5 h-5 text-temple-red"></i>
{% trans "Applications Stages" %}
</h5>
{% include 'jobs/partials/applicant_tracking.html' %}
<p class="text-xs text-gray-500 mt-3">
{% trans "The applicant tracking flow is defined by the attached Form Template. View Form Template tab to manage stages and fields." %}
</p>
</div>
<!-- Form Template Tab -->
<div id="manage-pane" class="tab-content hidden">
<h5 class="text-base font-bold text-gray-900 mb-3 flex items-center gap-2">
<i data-lucide="clipboard-list" class="w-5 h-5 text-temple-red"></i>
{% trans "Form Management" %}
</h5>
<p class="text-sm text-gray-500 mb-4">{% trans "Manage custom application forms associated with this job posting." %}</p>
{% if user.is_superuser or user.is_staff and user == job.assigned_to %}
<a href="{% url 'form_builder' job.form_template.slug %}" class="inline-flex items-center gap-2 w-full bg-temple-red hover:bg-[#7a1a29] text-white font-medium px-4 py-2.5 rounded-xl text-sm transition shadow-sm hover:shadow-md">
<i data-lucide="list-alt" class="w-4 h-4"></i>
{% trans "Manage Job Form" %}
</a>
{% endif %}
</div>
<!-- Staff Tab -->
<div id="staff-pane" class="tab-content hidden">
<h5 class="text-base font-bold text-gray-900 mb-3 flex items-center gap-2">
<i data-lucide="user-tie" class="w-5 h-5 text-temple-red"></i>
{% trans "Staff Assignment" %}
</h5>
{% if job.assigned_to %}
<p class="text-sm text-gray-600 mb-4">
<strong>{% trans "Assigned to:" %}</strong> {{ job.assigned_to }}
</p>
{% endif %}
{% if not job.assigned_to or job.assigned_to == request.user %}
<button type="button" onclick="document.getElementById('staffAssignmentModal').classList.remove('hidden')"
class="inline-flex items-center gap-2 w-full bg-temple-red hover:bg-[#7a1a29] text-white font-medium px-4 py-2.5 rounded-xl text-sm transition shadow-sm hover:shadow-md">
<i data-lucide="user-plus" class="w-4 h-4"></i>
{% trans "Assign Staff Member" %}
</button>
{% endif %}
{% if not job.assigned_to %}
<div class="bg-amber-50 border border-amber-200 rounded-xl p-3 mt-4">
<div class="flex items-start gap-2 text-sm text-amber-700">
<i data-lucide="info" class="w-5 h-5 flex-shrink-0 mt-0.5"></i>
<p>{% trans "No staff members assigned to this job yet." %}</p>
</div>
</div>
{% endif %}
</div>
<!-- LinkedIn Tab -->
<div id="linkedin-pane" class="tab-content hidden">
<h5 class="text-base font-bold text-gray-900 mb-3 flex items-center gap-2">
<i data-lucide="linkedin" class="w-5 h-5 text-temple-red"></i>
{% trans "LinkedIn Integration" %}
</h5>
<div class="space-y-3">
{% if job.posted_to_linkedin %}
<div class="bg-emerald-50 border border-emerald-200 rounded-xl p-3">
<div class="flex items-center gap-2 text-sm text-emerald-700">
<i data-lucide="check-circle" class="w-5 h-5"></i>
<span class="font-medium">{% trans "Posted successfully!" %}</span>
</div>
</div>
{% if job.linkedin_post_url %}
<a href="{{ job.linkedin_post_url }}" target="_blank" class="inline-flex items-center gap-2 w-full bg-gray-100 hover:bg-gray-200 text-gray-700 font-medium px-4 py-2.5 rounded-xl text-sm transition">
<i data-lucide="linkedin" class="w-4 h-4"></i>
{% trans "View on LinkedIn" %}
</a>
{% endif %}
<p class="text-xs text-gray-500 text-center">{% trans "Posted on:" %} {{ job.linkedin_posted_at|date:"M d, Y" }}</p>
{% else %}
<p class="text-sm text-gray-500">{% trans "This job has not been posted to LinkedIn yet." %}</p>
{% endif %}
<form method="post" action="{% url 'post_to_linkedin' job.slug %}" class="mt-2">
{% csrf_token %}
<button type="submit" class="inline-flex items-center gap-2 w-full bg-temple-red hover:bg-[#7a1a29] text-white font-medium px-4 py-2.5 rounded-xl text-sm transition shadow-sm hover:shadow-md
{% if not request.session.linkedin_authenticated %}opacity-50 cursor-not-allowed{% endif %}">
<i data-lucide="linkedin" class="w-4 h-4"></i>
{% if job.posted_to_linkedin %}{% trans "Re-post to LinkedIn" %}{% else %}{% trans "Post to LinkedIn" %}{% endif %}
</button>
</form>
<button type="button" onclick="document.getElementById('imageUploadModal').classList.remove('hidden')"
class="inline-flex items-center gap-2 w-full bg-gray-100 hover:bg-gray-200 text-gray-700 font-medium px-4 py-2.5 rounded-xl text-sm transition">
<i data-lucide="image" class="w-4 h-4"></i>
{% trans "Upload Image for Post" %}
</button>
{% if not request.session.linkedin_authenticated %}
<p class="text-xs text-gray-500 text-center">
{% trans "You need to" %} <a href="{% url 'linkedin_login' %}" class="text-temple-red hover:text-temple-red/80 font-medium">{% trans "authenticate with LinkedIn" %}</a> {% trans "first." %}
</p>
{% endif %}
{% if job.linkedin_post_status and 'ERROR' in job.linkedin_post_status %}
<div class="bg-red-50 border border-red-200 rounded-xl p-3 mt-3">
<div class="flex items-start gap-2 text-sm text-red-700">
<i data-lucide="alert-triangle" class="w-5 h-5 flex-shrink-0 mt-0.5"></i>
<p><strong>{% trans "Error:" %}</strong> {{ job.linkedin_post_status }}</p>
</div>
</div>
{% endif %}
{% if job.linkedin_post_formated_data %}
<button type="button" onclick="document.getElementById('linkedinModal').classList.remove('hidden')"
class="inline-flex items-center gap-2 w-full bg-temple-red hover:bg-[#7a1a29] text-white font-medium px-4 py-2.5 rounded-xl text-sm transition shadow-sm hover:shadow-md">
<i data-lucide="edit" class="w-4 h-4"></i>
{% trans "Update LinkedIn Content" %}
</button>
{% endif %}
</div>
</div>
</div>
</div>
<!-- Application Category Chart -->
<div class="bg-white rounded-2xl shadow-sm border border-gray-100 overflow-hidden">
<div class="p-4 border-b border-gray-200 bg-gray-50">
<h6 class="text-sm font-bold text-gray-900 flex items-center gap-2">
<i data-lucide="pie-chart" class="w-5 h-5 text-temple-red"></i>
{% trans "Application Categories & Scores" %}
</h6>
</div>
<div class="p-4">
<div style="height: 300px;">
<canvas id="jobCategoryMatchChart"></canvas>
</div>
</div>
</div>
<!-- Position Stats -->
<div class="bg-white rounded-2xl shadow-sm border border-gray-100 overflow-hidden">
<div class="p-4 border-b border-gray-200 bg-gray-50">
<h6 class="text-sm font-bold text-gray-900 flex items-center gap-2">
<i data-lucide="briefcase" class="w-5 h-5 text-temple-red"></i>
{% trans "Position Statistics" %}
</h6>
</div>
<div class="p-4">
<div class="grid grid-cols-3 gap-3">
<div class="text-center p-3 bg-temple-red/5 rounded-xl border-l-4 border-temple-red">
<i data-lucide="door-open" class="w-6 h-6 text-temple-red mx-auto mb-2"></i>
<div class="text-2xl font-bold text-temple-red">{{ job.open_positions }}</div>
<p class="text-xs text-gray-600">{% trans "Open Positions" %}</p>
</div>
<div class="text-center p-3 bg-emerald-50 rounded-xl">
<i data-lucide="user-check" class="w-6 h-6 text-emerald-500 mx-auto mb-2"></i>
<div class="text-2xl font-bold text-emerald-600">{{ positions_filled }}</div>
<p class="text-xs text-gray-600">{% trans "Positions Filled" %}</p>
</div>
<div class="text-center p-3 bg-gray-100 rounded-xl">
<i data-lucide="hourglass" class="w-6 h-6 text-gray-500 mx-auto mb-2"></i>
<div class="text-2xl font-bold text-gray-600">{{ vacant_positions }}</div>
<p class="text-xs text-gray-600">{% trans "Vacant Positions" %}</p>
</div>
</div>
</div>
</div>
<!-- KPIs -->
<div class="bg-white rounded-2xl shadow-sm border border-gray-100 overflow-hidden">
<div class="p-4 border-b border-gray-200 bg-gray-50">
<h6 class="text-sm font-bold text-gray-900 flex items-center gap-2">
<i data-lucide="info" class="w-5 h-5 text-temple-red"></i>
{% trans "Key Performance Indicators" %}
</h6>
</div>
<div class="p-4">
<div class="grid grid-cols-3 gap-3">
<div class="text-center p-3 bg-temple-red/5 rounded-xl border-l-4 border-temple-red">
<i data-lucide="star" class="w-6 h-6 text-temple-red mx-auto mb-2"></i>
<div class="text-2xl font-bold text-temple-red">{{ avg_match_score|floatformat:1 }}</div>
<p class="text-xs text-gray-600">{% trans "Avg. AI Score" %}</p>
</div>
<div class="text-center p-3 bg-emerald-50 rounded-xl">
<i data-lucide="trophy" class="w-6 h-6 text-emerald-500 mx-auto mb-2"></i>
<div class="text-2xl font-bold text-emerald-600">{{ high_potential_count }}</div>
<p class="text-xs text-gray-600">{% trans "High Potential" %}</p>
</div>
<div class="text-center p-3 bg-gray-100 rounded-xl">
<i data-lucide="percent" class="w-6 h-6 text-gray-500 mx-auto mb-2"></i>
<div class="text-2xl font-bold text-gray-600">{{ job.vacancy_fill_rate|floatformat:2 }}%</div>
<p class="text-xs text-gray-600">{% trans "Fill Rate" %}</p>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
{% include "jobs/partials/image_upload.html" %}
{% include "jobs/partials/linkedin_content_form.html" %}
<!-- Edit Status Modal -->
<div id="editStatusModal" class="fixed inset-0 bg-black/50 backdrop-blur-sm z-50 hidden flex items-center justify-center p-4">
<div class="bg-white rounded-2xl shadow-xl max-w-lg w-full">
<form method="post" action="{% url 'job_detail' slug=job.slug %}">
{% csrf_token %}
<div class="flex items-center justify-between p-4 border-b border-gray-200">
<h5 class="text-lg font-bold text-gray-900">{% trans "Edit Job Status" %}</h5>
<button type="button" onclick="document.getElementById('editStatusModal').classList.add('hidden')" class="text-gray-400 hover:text-gray-600 transition">
<i data-lucide="x" class="w-5 h-5"></i>
</button>
</div>
<div class="p-4">
<div>
{% if status_form %}
<label for="{{ status_form.status.id_for_label }}" class="block text-sm font-semibold text-gray-700 mb-2">{% trans "Select New Status" %}</label>
<select name="{{ status_form.status.name }}" id="{{ status_form.status.id_for_label }}" class="w-full px-4 py-2.5 border border-gray-200 rounded-xl text-sm focus:ring-2 focus:ring-kaauh-blue/20 focus:border-kaauh-blue outline-none transition">
{% for value, label in status_form.status.field.choices %}
<option value="{{ value }}" {% if status_form.status.value == value %}selected{% endif %}>{{ label }}</option>
{% endfor %}
</select>
{% if status_form.status.errors %}
<div class="mt-1 text-xs text-red-600">{{ status_form.status.errors }}</div>
{% endif %}
{% else %}
<div class="text-red-600 text-sm">{% trans "Status form not available. Please check your view." %}</div>
{% endif %}
</div>
</div>
<div class="flex gap-3 p-4 border-t border-gray-200">
<button type="button" onclick="document.getElementById('editStatusModal').classList.add('hidden')" class="inline-flex items-center gap-2 flex-1 bg-gray-100 hover:bg-gray-200 text-gray-700 font-medium px-4 py-2.5 rounded-xl text-sm transition">
{% trans "Cancel" %}
</button>
<button type="submit" class="inline-flex items-center gap-2 flex-1 bg-temple-red hover:bg-[#7a1a29] text-white font-medium px-4 py-2.5 rounded-xl text-sm transition shadow-sm hover:shadow-md">
<i data-lucide="save" class="w-4 h-4"></i>
{% trans "Save Changes" %}
</button>
</div>
</form>
</div>
</div>
{% endblock %}
{% block customJS %}
<script src="https://cdn.jsdelivr.net/npm/chart.js"></script>
<script>
// Tab switching functionality
function showTab(tabId) {
// Hide all tab contents
document.querySelectorAll('.tab-content').forEach(content => {
content.classList.add('hidden');
});
// Remove active state from all tabs
document.querySelectorAll('.tab-btn').forEach(btn => {
btn.classList.remove('border-kaauh-blue', 'text-kaauh-blue', 'bg-white');
btn.classList.add('border-transparent', 'text-gray-600');
});
// Show selected tab content
document.getElementById(tabId).classList.remove('hidden');
// Add active state to selected tab
const activeBtn = document.querySelector(`[data-tab="${tabId}"]`);
activeBtn.classList.add('border-kaauh-blue', 'text-kaauh-blue', 'bg-white');
activeBtn.classList.remove('border-transparent', 'text-gray-600');
}
// Initialize first tab as active
showTab('applicants-pane');
// Copy job link functionality
document.getElementById('copyJobLinkButton').addEventListener('click', function() {
const urlToCopy = this.getAttribute('data-url');
navigator.clipboard.writeText(urlToCopy).then(() => {
const feedback = document.getElementById('copyFeedback');
feedback.classList.remove('hidden');
setTimeout(() => {
feedback.classList.add('hidden');
}, 2000);
}).catch(err => {
console.error('Could not copy text: ', err);
alert('{% trans "Copy failed. Please copy URL manually:" %} ' + urlToCopy);
});
});
// Chart.js Configuration
window.jobChartData = {
categories: {{ categories|safe|default:"[]" }},
applications_count: {{ applications_count|safe|default:"[]" }},
avg_scores: {{ avg_scores|safe|default:"[]" }}
};
document.addEventListener('DOMContentLoaded', function() {
const ctx = document.getElementById('jobCategoryMatchChart');
if (!ctx) {
console.warn('Job category chart canvas not found.');
return;
}
const chartCtx = ctx.getContext('2d');
const jobChartData = window.jobChartData || { categories: [], applications_count: [], avg_scores: [] };
const categories = jobChartData.categories || [];
const candidateCounts = jobChartData.applications_count || [];
const avgScores = jobChartData.avg_scores || [];
if (categories.length > 0) {
new Chart(chartCtx, {
type: 'doughnut',
data: {
labels: categories,
datasets: [{
label: '{% trans "Number of Applications" %}',
data: candidateCounts,
backgroundColor: [
'rgba(157, 34, 53, 0.7)',
'rgba(0, 99, 110, 0.7)',
'rgba(245, 158, 11, 0.7)',
'rgba(16, 185, 129, 0.7)',
'rgba(99, 102, 241, 0.7)',
'rgba(236, 72, 153, 0.7)',
],
borderColor: [
'rgba(157, 34, 53, 1)',
'rgba(0, 99, 110, 1)',
'rgba(245, 158, 11, 1)',
'rgba(16, 185, 129, 1)',
'rgba(99, 102, 241, 1)',
'rgba(236, 72, 153, 1)',
],
borderWidth: 1,
}]
},
options: {
responsive: true,
maintainAspectRatio: false,
plugins: {
legend: {
position: 'right',
},
title: {
display: false,
},
tooltip: {
callbacks: {
label: function(context) {
let label = context.label || '';
if (label) {
label += ': ';
}
label += context.parsed + '{% trans " application(s)" %}';
return label;
}
}
}
}
}
});
} else {
chartCtx.canvas.parentNode.innerHTML = '<p class="text-center text-gray-500 text-sm mt-8">{% trans "No application category data available for this job." %}</p>';
}
});
// Initialize Lucide icons
lucide.createIcons();
</script>
{% endblock %}