kaauh_ats/templates/recruitment/agency_detail.html

775 lines
32 KiB
HTML

{% extends 'base.html' %}
{% load static i18n %}
{% block title %}{{ agency.name }} - {% trans "Agency Details" %} - ATS{% 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;
}
/* Primary Color Overrides */
.text-primary-theme { color: var(--kaauh-teal) !important; }
.bg-primary-theme { background-color: var(--kaauh-teal) !important; }
/* Main Container & Card Styling */
.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;
}
/* Agency Header */
.agency-header {
background: linear-gradient(135deg, var(--kaauh-teal) 0%, var(--kaauh-teal-dark) 100%);
color: white;
padding: 2rem;
border-radius: 0.75rem 0.75rem 0 0;
position: relative;
overflow: hidden;
}
.agency-header::before {
content: '';
position: absolute;
top: 0;
right: 0;
width: 200px;
height: 200px;
background: rgba(255, 255, 255, 0.1);
border-radius: 50%;
transform: translate(50%, -50%);
}
/* Info Section */
.info-section {
background-color: #f8f9fa;
border-radius: 0.75rem;
padding: 1.5rem;
margin-bottom: 1.5rem;
border: 1px solid var(--kaauh-border);
}
.info-item {
display: flex;
align-items: center;
margin-bottom: 1rem;
padding-bottom: 1rem;
border-bottom: 1px solid #e9ecef;
}
.info-item:last-child {
margin-bottom: 0;
padding-bottom: 0;
border-bottom: none;
}
.info-icon {
width: 40px;
height: 40px;
background-color: var(--kaauh-teal);
color: white;
border-radius: 0.5rem;
display: flex;
align-items: center;
justify-content: center;
margin-right: 1rem;
flex-shrink: 0;
}
.info-content {
flex: 1;
}
.info-label {
font-weight: 600;
color: var(--kaauh-primary-text);
margin-bottom: 0.25rem;
font-size: 0.875rem;
text-transform: uppercase;
letter-spacing: 0.5px;
}
.info-value {
color: #6c757d;
font-size: 1rem;
}
/* Stats Cards */
.stat-card {
background: linear-gradient(135deg, #f8f9fa 0%, #e9ecef 100%);
border-radius: 0.75rem;
padding: 1.5rem;
text-align: center;
border: 1px solid var(--kaauh-border);
transition: all 0.3s ease;
}
.stat-card:hover {
transform: translateY(-2px);
box-shadow: 0 8px 25px rgba(0,0,0,0.1);
}
.stat-number {
font-size: 2rem;
font-weight: 700;
color: var(--kaauh-teal);
margin-bottom: 0.5rem;
}
.stat-label {
color: #6c757d;
font-size: 0.875rem;
font-weight: 600;
text-transform: uppercase;
letter-spacing: 0.5px;
}
/* Button Styling */
.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);
}
/* Candidate List */
.candidate-item {
background-color: white;
border: 1px solid var(--kaauh-border);
border-radius: 0.5rem;
padding: 1rem;
margin-bottom: 0.75rem;
transition: all 0.2s ease;
}
.candidate-item:hover {
background-color: #f8f9fa;
border-color: var(--kaauh-teal);
}
.candidate-name {
font-weight: 600;
color: var(--kaauh-primary-text);
margin-bottom: 0.25rem;
}
.candidate-details {
font-size: 0.875rem;
color: #6c757d;
}
/* Job List - Consistent with Candidate List */
.job-item {
background-color: white;
border: 1px solid var(--kaauh-border);
border-radius: 0.5rem;
padding: 1rem;
margin-bottom: 0.75rem;
transition: all 0.2s ease;
}
.job-item:hover {
background-color: #f8f9fa;
border-color: var(--kaauh-teal);
}
.job-title {
font-weight: 600;
color: var(--kaauh-primary-text);
margin-bottom: 0.25rem;
}
.job-details {
font-size: 0.875rem;
color: #6c757d;
}
.job-status-badge {
font-size: 0.75rem;
padding: 0.25rem 0.6rem;
border-radius: 0.3rem;
font-weight: 600;
display: inline-block;
background-color: #e9ecef;
color: #495057;
}
/* Stage Badge */
.stage-badge {
font-size: 0.75rem;
padding: 0.25rem 0.6rem;
border-radius: 0.3rem;
font-weight: 600;
display: inline-block;
}
.stage-Applied { background-color: #e9ecef; color: #495057; }
.stage-Screening { background-color: var(--kaauh-info); color: white; }
.stage-Exam { background-color: var(--kaauh-warning); color: #856404; }
.stage-Interview { background-color: #17a2b8; color: white; }
.stage-Offer { background-color: var(--kaauh-success); color: white; }
.stage-Hired { background-color: #28a745; color: white; }
.stage-Rejected { background-color: var(--kaauh-danger); color: white; }
/* Empty State */
.empty-state {
text-align: center;
padding: 2rem;
color: #6c757d;
}
.empty-state i {
font-size: 1rem;
margin-bottom: 0.5rem;
opacity: 0.5;
}
/* Password Display Styling */
.password-display-section {
background-color: #f8f9fa;
border-radius: 0.5rem;
padding: 1rem;
margin-top: 1rem;
border: 1px solid #e9ecef;
}
.password-container {
display: flex;
align-items: center;
gap: 0.5rem;
}
.password-value {
font-family: 'Courier New', monospace;
font-size: 1.1rem;
font-weight: 600;
color: #2d3436;
background-color: #ffffff;
padding: 0.5rem 0.75rem;
border: 1px solid #dee2e6;
border-radius: 0.375rem;
letter-spacing: 0.05em;
}
.password-value:hover {
background-color: #f8f9fa;
}
/* --- TAB OVERRIDES FOR TEAL THEME CONSISTENCY AND VISIBILITY --- */
/* Ensure card-header-tabs sit correctly, use kaauh-border */
.card-header-tabs {
border-bottom: 1px solid var(--kaauh-border); /* Consistent thin bottom border for the entire row */
}
/* Tabs Theming - Applies to the right column */
.nav-tabs {
border-bottom: 1px solid var(--kaauh-border);
background-color: #f8f9fa;
padding: 0;
}
.nav-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;
}
/* Active Link */
.nav-tabs .nav-link.active {
color: var(--kaauh-teal-dark) !important;
background-color: white !important;
border-bottom: 3px solid var(--kaauh-teal) !important;
font-weight: 600;
z-index: 2;
border-right-color: transparent !important;
margin-bottom: -1px;
}
</style>
{% endblock %}
{% block content %}
<div class="container-fluid py-4">
<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-building me-2"></i>
{{ agency.name }}
</h1>
<p class="text-muted mb-0">
{% trans "Hiring Agency Details and Application Management" %}
</p>
</div>
<div>
<a href="{% url 'agency_assignment_list' %}" class="btn btn-main-action me-2">
<i class="fas fa-tasks me-1"></i> {% trans "All Assignments" %}
</a>
<a href="{% url 'agency_assignment_create_with_agency' agency.slug %}" class="btn btn-main-action me-2">
<i class="fas fa-edit me-1"></i> {% trans "Assign job" %}
</a>
<a href="{% url 'agency_update' agency.slug %}" class="btn btn-main-action me-2">
<i class="fas fa-edit me-1"></i> {% trans "Edit Agency" %}
</a>
<a href="{% url 'agency_list' %}" class="btn btn-secondary">
<i class="fas fa-arrow-left me-1"></i> {% trans "Back to Agencies" %}
</a>
</div>
</div>
<div class="row">
<div class="col-lg-8">
<div class="card kaauh-card mb-4">
<div class="agency-header">
<div class="row align-items-center">
<div class="col-md-8">
<h2 class="h4 mb-2">{{ agency.name }}</h2>
{% if agency.contact_person %}
<p class="mb-1">
<i class="fas fa-user me-2"></i>
{% trans "Contact:" %} {{ agency.contact_person }}
</p>
{% endif %}
{% if agency.email %}
<p class="mb-0">
<i class="fas fa-envelope me-2"></i>
{{ agency.email }}
</p>
{% endif %}
</div>
<div class="col-md-4 text-end">
{% if agency.website %}
<a href="{{ agency.website }}" target="_blank" class="btn btn-light btn-sm me-2">
<i class="fas fa-external-link-alt me-1"></i> {% trans "Website" %}
</a>
{% endif %}
{% if agency.email %}
<a href="mailto:{{ agency.email }}" class="btn btn-light btn-sm">
<i class="fas fa-envelope me-1"></i> {% trans "Email" %}
</a>
{% endif %}
</div>
</div>
</div>
<div class="card-body p-4">
<div class="row">
<div class="col-md-6">
<div class="info-section">
<h5 class="mb-3">
<i class="fas fa-address-book me-2" style="color: var(--kaauh-teal);"></i>
{% trans "Contact Information" %}
</h5>
{% if agency.phone %}
<div class="info-item">
<div class="info-icon">
<i class="fas fa-phone"></i>
</div>
<div class="info-content">
<div class="info-label">{% trans "Phone" %}</div>
<div class="info-value">{{ agency.phone }}</div>
</div>
</div>
{% endif %}
{% if agency.email %}
<div class="info-item">
<div class="info-icon">
<i class="fas fa-envelope"></i>
</div>
<div class="info-content">
<div class="info-label">{% trans "Email" %}</div>
<div class="info-value">{{ agency.email }}</div>
</div>
</div>
{% endif %}
{% if agency.website %}
<div class="info-item">
<div class="info-icon">
<i class="fas fa-globe"></i>
</div>
<div class="info-content">
<div class="info-label">{% trans "Website" %}</div>
<div class="info-value">
<a href="{{ agency.website }}" target="_blank" class="text-decoration-none text-secondary">
{{ agency.website }}
<i class="fas fa-external-link-alt ms-1 small"></i>
</a>
</div>
</div>
</div>
{% endif %}
</div>
</div>
<div class="col-md-6">
<div class="info-section">
<h5 class="mb-3">
<i class="fas fa-map-marker-alt me-2" style="color: var(--kaauh-teal);"></i>
{% trans "Location Information" %}
</h5>
{% if agency.address %}
<div class="info-item">
<div class="info-icon">
<i class="fas fa-home"></i>
</div>
<div class="info-content">
<div class="info-label">{% trans "Address" %}</div>
<div class="info-value">{{ agency.address }}</div>
</div>
</div>
{% endif %}
{% if agency.city %}
<div class="info-item">
<div class="info-icon">
<i class="fas fa-city"></i>
</div>
<div class="info-content">
<div class="info-label">{% trans "City" %}</div>
<div class="info-value">{{ agency.city }}</div>
</div>
</div>
{% endif %}
{% if agency.country %}
<div class="info-item">
<div class="info-icon">
<i class="fas fa-flag"></i>
</div>
<div class="info-content">
<div class="info-label">{% trans "Country" %}</div>
<div class="info-value">{{ agency.get_country_display }}</div>
</div>
</div>
{% endif %}
</div>
</div>
</div>
{% if agency.description %}
<div class="info-section mt-3">
<h5 class="mb-3">
<i class="fas fa-comment-dots me-2" style="color: var(--kaauh-teal);"></i>
{% trans "Description" %}
</h5>
<p class="mb-0">{{ agency.description|linebreaks }}</p>
</div>
{% endif %}
{% if generated_password and request.user.is_staff %}
<div class="info-section mt-4">
<h5 class="mb-3">
<i class="fas fa-key me-2" style="color: var(--kaauh-teal);"></i>
{% trans "Agency Login Information" %}
</h5>
<div class="alert " role="alert">
<h6 class="alert-heading">
<i class="fas fa-info-circle me-2"></i>
{% trans "Important Security Notice" %}
</h6>
<p class="mb-2">
{% trans "This password provides access to the agency portal. Share it securely with the agency contact person." %}
</p>
</div>
<div class="password-display-section">
<div class="info-item">
<div class="info-icon">
<i class="fas fa-user"></i>
</div>
<div class="info-content">
<div class="info-label">{% trans "Username" %}</div>
<div class="info-value">{{ agency.user.username }}</div>
</div>
</div>
<div class="info-item">
<div class="info-icon">
<i class="fas fa-lock"></i>
</div>
<div class="info-content">
<div class="info-label">{% trans "Generated Password" %}</div>
<div class="password-container">
<div class="password-value" id="password-value">{{ generated_password }}</div>
<button type="button" class="btn btn-sm btn-outline-secondary ms-2" onclick="copyPassword(this)">
<i class="fas fa-copy me-1"></i>
{% trans "Copy" %}
</button>
</div>
</div>
</div>
<div class="d-grid gap-2 mt-4">
<a href="{% url 'regenerate_agency_password' agency.slug %}"
class="btn btn-danger"
title="{% trans 'This action resets the agency\'s current login password.' %}"
onclick="return confirm('{% trans "Are you sure you want to regenerate the password for this agency? This cannot be undone." %}');"
>
<i class="fas fa-key me-2"></i>
{% trans "Regenerate Agency Password" %}
</a>
</div>
</div>
</div>
{% endif %}
</div>
</div>
<div class="card kaauh-card mb-4">
<div class="card-header p-0 bg-white">
<ul class="nav nav-tabs card-header-tabs" id="agencyTabs" role="tablist">
<li class="nav-item ms-2" role="presentation">
<button
class="nav-link active"
id="candidates-tab"
data-bs-toggle="tab"
data-bs-target="#candidates"
type="button"
role="tab"
aria-controls="candidates"
aria-selected="true"
>
<i class="fas fa-users me-1"></i>
<span>({{total_applications}})</span>
{% trans "Recent Applications" %}
</button>
</li>
<li class="nav-item" role="presentation">
<button
class="nav-link"
id="jobs-tab"
data-bs-toggle="tab"
data-bs-target="#jobs"
type="button"
role="tab"
aria-controls="jobs"
aria-selected="false"
>
<i class="fas fa-briefcase me-1"></i>
<span>({{total_job_assignments}})</span>
{% trans "Assigned Jobs" %}
</button>
</li>
</ul>
</div>
<div class="tab-content" id="agencyTabsContent">
<div
class="tab-pane fade show active p-4"
id="candidates"
role="tabpanel"
aria-labelledby="candidates-tab"
>
{% if applications %}
{% for application in applications %}
<div class="candidate-item">
<div class="d-flex justify-content-between align-items-center">
<div>
<div class="candidate-name">{{ application.name }}</div>
<div class="candidate-details">
<i class="fas fa-envelope me-1"></i> {{ application.email }}
{% if application.phone %}
<span class="ms-3"><i class="fas fa-phone me-1"></i> {{ application.phone }}</span>
{% endif %}
<span class="ms-3"><i class="fas fa-briefcase me-1"></i> {{ application.job.title}}</span>
</div>
</div>
<div class="text-end">
<span class="stage-badge stage-{{ application.stage }}">
{{ application.get_stage_display }}
</span>
<div class="small text-muted mt-1">
{{ application.created_at|date:"M d, Y" }}
</div>
</div>
</div>
</div>
{% endfor %}
{% else %}
<div class="empty-state">
<i class="fas fa-user-slash"></i>
<h6>{% trans "No applications yet" %}</h6>
<p class="mb-0">{% trans "This agency hasn't submitted any applications yet." %}</p>
</div>
{% endif %}
</div>
<div
class="tab-pane fade p-4"
id="jobs"
role="tabpanel"
aria-labelledby="jobs-tab"
>
{% comment %}
NOTE: You will need to pass an 'assigned_jobs' list
from your Django view context to populate this section.
{% endcomment %}
{% if job_assignments %}
{% for assignment in job_assignments%}
<div class="job-item">
<div class="d-flex justify-content-between align-items-center">
<div>
<div class="job-title">
<a href="{% url 'job_detail' assignment.job.slug %}" class="text-decoration-none text-primary-theme">
{{ assignment.job.title }}
</a>
</div>
<div class="job-details">
<i class="fas fa-map-pin me-1"></i> {{ assignment.job.get_location_display }}
{% if assessment.job.department %}
<span class="ms-3"><i class="fas fa-user-tie me-1"></i> {{ assignment.job.department|default:"" }}</span>
{% endif %}
</div>
</div>
<div class="text-end">
<span class="job-status-badge">
{% trans "Assigned" %}
</span>
<div class="small text-muted mt-1">
{% trans "Assigned On:" %} {{ assignment.created_at|date:"M d, Y" }}
</div>
</div>
</div>
</div>
{% endfor %}
{% else %}
<div class="empty-state">
<i class="fas fa-briefcase-slash"></i>
<h6>{% trans "No jobs assigned" %}</h6>
<p class="mb-0">{% trans "There are no open job assignments for this agency." %}</p>
<a href="{% url 'agency_assignment_create_with_agency' agency.slug %}" class="btn btn-main-action mt-3 btn-sm">
<i class="fas fa-plus me-1"></i> {% trans "Assign New Job" %}
</a>
</div>
{% endif %}
</div>
</div>
</div>
</div>
<div class="col-lg-4">
<div class="card kaauh-card mb-4">
<div class="card-header bg-white border-bottom">
<h5 class="mb-0" style="color: var(--kaauh-teal-dark);">
<i class="fas fa-chart-bar me-2"></i>
{% trans "Application Statistics" %}
</h5>
</div>
<div class="card-body">
<div class="row g-3">
<div class="col-6">
<div class="stat-card">
<div class="stat-number">{{ total_applications }}</div>
<div class="stat-label">{% trans "Total" %}</div>
</div>
</div>
<div class="col-6">
<div class="stat-card">
<div class="stat-number">{{ active_applications }}</div>
<div class="stat-label">{% trans "Active" %}</div>
</div>
</div>
<div class="col-6">
<div class="stat-card">
<div class="stat-number">{{ hired_applications }}</div>
<div class="stat-label">{% trans "Hired" %}</div>
</div>
</div>
<div class="col-6">
<div class="stat-card">
<div class="stat-number">{{ rejected_applications }}</div>
<div class="stat-label">{% trans "Rejected" %}</div>
</div>
</div>
</div>
</div>
</div>
<div class="card kaauh-card">
<div class="card-header bg-white border-bottom">
<h5 class="mb-0" style="color: var(--kaauh-teal-dark);">
<i class="fas fa-info-circle me-2"></i>
{% trans "Agency Information" %}
</h5>
</div>
<div class="card-body">
<p class="mb-2">
<strong>{% trans "Created:" %}</strong><br>
{{ agency.created_at|date:"F d, Y" }}
</p>
<p class="mb-2">
<strong>{% trans "Last Updated:" %}</strong><br>
{{ agency.updated_at|date:"F d, Y" }}
</p>
<p class="mb-0">
<strong>{% trans "Agency ID:" %}</strong><br>
<code>{{ agency.slug }}</code>
</p>
</div>
</div>
</div>
</div>
</div>
<script>
function copyPassword(button) {
const passwordTextEl = document.getElementById('password-value');
if (!passwordTextEl) return;
const passwordText = passwordTextEl.textContent;
// Try Clipboard API first
const doFeedback = (btn) => {
const originalHTML = btn.innerHTML;
btn.innerHTML = '<i class="fas fa-check me-1"></i> {% trans "Copied!" %}';
btn.classList.remove('btn-outline-secondary');
btn.classList.add('btn-success');
setTimeout(function() {
btn.innerHTML = originalHTML;
btn.classList.remove('btn-success');
btn.classList.add('btn-outline-secondary');
}, 2000);
};
if (navigator.clipboard && navigator.clipboard.writeText) {
navigator.clipboard.writeText(passwordText).then(function() {
doFeedback(button);
}).catch(function(err) {
console.error('Failed to copy password via Clipboard API: ', err);
// fallback
const ta = document.createElement('textarea');
ta.value = passwordText;
document.body.appendChild(ta);
ta.select();
try { document.execCommand('copy'); doFeedback(button); } catch (e) { console.error('execCommand fallback failed', e); }
document.body.removeChild(ta);
});
} else {
// fallback for older browsers
const ta = document.createElement('textarea');
ta.value = passwordText;
document.body.appendChild(ta);
ta.select();
try { document.execCommand('copy'); doFeedback(button); } catch (e) { console.error('execCommand fallback failed', e); }
document.body.removeChild(ta);
}
}
</script>
{% endblock %}