ATS/templates/applicant/career.html
2026-02-01 13:38:06 +03:00

719 lines
26 KiB
HTML

{% extends 'applicant/partials/candidate_facing_base.html' %}
{% load static i18n %}
{% block title %}{% trans "Career Opportunities" %}{% endblock %}
{% block content %}
<div class="main-content-area">
<!-- Hero Section with Modern Design -->
<header class="hero-section relative overflow-hidden">
<div class="hero-bg absolute inset-0"></div>
<div class="hero-pattern absolute inset-0 opacity-10"></div>
<div class="container mx-auto px-6 relative z-10">
<div class="hero-content text-center py-20 md:py-32">
<div class="hero-badge inline-block px-6 py-2 bg-white/10 backdrop-blur-sm rounded-full text-white/90 text-sm font-medium mb-6 animate-fade-in">
{% trans "We're Hiring" %}
</div>
<h1 class="hero-title text-4xl md:text-7xl font-bold mb-6 text-white animate-slide-up">
{% trans "Build Your Future" %}
</h1>
<p class="hero-subtitle text-lg md:text-2xl max-w-3xl mx-auto text-white/80 font-light leading-relaxed animate-slide-up-delay">
{% trans "Join a community of excellence and growth. Discover opportunities that match your passion and expertise." %}
</p>
<div class="hero-stats mt-12 flex flex-wrap justify-center gap-8 md:gap-16 animate-fade-in-delay">
<div class="stat-item">
<div class="text-3xl md:text-5xl font-bold text-white">{{ total_open_roles|default:"0" }}</div>
<div class="text-sm md:text-base text-white/70 mt-1">{% trans "Open Positions" %}</div>
</div>
<div class="stat-item">
<div class="text-3xl md:text-5xl font-bold text-white">50+</div>
<div class="text-sm md:text-base text-white/70 mt-1">{% trans "Departments" %}</div>
</div>
<div class="stat-item">
<div class="text-3xl md:text-5xl font-bold text-white">95%</div>
<div class="text-sm md:text-base text-white/70 mt-1">{% trans "Satisfaction Rate" %}</div>
</div>
</div>
</div>
</div>
<div class="hero-wave absolute bottom-0 left-0 w-full">
<svg viewBox="0 0 1440 120" fill="none" xmlns="http://www.w3.org/2000/svg" class="w-full h-auto">
<path d="M0,64L48,69.3C96,75,192,85,288,80C384,75,480,53,576,48C672,43,768,53,864,58.7C960,64,1056,64,1152,58.7C1248,53,1344,43,1392,37.3L1440,32L1440,120L1392,120C1344,120,1248,120,1152,120C1056,120,960,120,864,120C768,120,672,120,576,120C480,120,384,120,288,120C192,120,96,120,48,120L0,120Z" fill="#ffffff"/>
</svg>
</div>
</header>
<div class="container mx-auto px-6 py-12 md:py-20">
<!-- Mobile Filter Trigger -->
<button onclick="toggleFilters()"
type="button"
class="filter-trigger w-full md:hidden bg-gradient-to-r from-temple-red to-[#7a1a29] hover:shadow-xl text-white font-semibold py-4 px-6 rounded-2xl flex items-center justify-center gap-3 transition-all duration-300 mb-8 group">
<i data-lucide="sliders-horizontal" class="w-5 h-5 group-hover:rotate-90 transition-transform duration-300"></i>
<span>{% trans "Filter Jobs" %}</span>
</button>
<div class="grid grid-cols-1 lg:grid-cols-12 gap-8 items-start">
<!-- Filter Sidebar -->
<aside class="lg:col-span-4 xl:col-span-3">
<div id="sidebar" class="filter-sidebar lg:static hidden lg:block">
<div class="filter-card bg-white rounded-3xl p-8 shadow-xl shadow-gray-200/50 border border-gray-100 relative">
<button onclick="toggleFilters()"
type="button"
class="close-filters absolute top-6 right-6 w-10 h-10 flex items-center justify-center rounded-full bg-gray-100 hover:bg-gray-200 text-gray-600 transition-colors lg:hidden">
<i data-lucide="x" class="w-5 h-5"></i>
</button>
<div class="filter-header mb-8">
<div class="flex items-center gap-3 mb-2">
<div class="w-10 h-10 bg-gradient-to-br from-temple-red to-[#7a1a29] rounded-xl flex items-center justify-center">
<i data-lucide="filter" class="w-5 h-5 text-white"></i>
</div>
<h4 class="text-2xl font-bold text-gray-900">
{% trans "Filters" %}
</h4>
</div>
<p class="text-sm text-gray-500">{% trans "Find your perfect role" %}</p>
</div>
<form method="GET" class="space-y-6">
<!-- Search -->
<div class="form-group">
<label class="form-label">
<i data-lucide="search" class="w-4 h-4"></i>
{% trans "Keywords" %}
</label>
<div class="relative">
<input type="text"
name="q"
placeholder="{% trans 'Search positions...' %}"
value="{{ request.GET.q|default:'' }}"
class="form-input">
</div>
</div>
<!-- Employment Type -->
<div class="form-group">
<label class="form-label">
<i data-lucide="briefcase" class="w-4 h-4"></i>
{% trans "Employment Type" %}
</label>
<select class="form-select" name="employment_type">
<option value="">{% trans "All Types" %}</option>
{% for key in job_type_keys %}
<option value="{{ key }}" {% if key == selected_job_type %}selected{% endif %}>{{ key }}</option>
{% endfor %}
</select>
</div>
<!-- Workplace Type -->
<div class="form-group">
<label class="form-label">
<i data-lucide="home" class="w-4 h-4"></i>
{% trans "Workplace" %}
</label>
<select class="form-select" name="workplace_type">
<option value="">{% trans "All Locations" %}</option>
{% for key in workplace_type_keys %}
<option value="{{ key }}" {% if key == selected_workplace_type %}selected{% endif %}>{{ key }}</option>
{% endfor %}
</select>
</div>
<!-- Department -->
<div class="form-group">
<label class="form-label">
<i data-lucide="building-2" class="w-4 h-4"></i>
{% trans "Department" %}
</label>
<select class="form-select" name="department">
<option value="">{% trans "All Departments" %}</option>
{% for key in department_type_keys %}
<option value="{{ key }}" {% if key == selected_department %}selected{% endif %}>{{ key }}</option>
{% endfor %}
</select>
</div>
<button type="submit"
class="submit-btn w-full bg-gradient-to-r from-temple-red to-[#7a1a29] hover:shadow-xl text-white font-semibold py-4 rounded-xl transition-all duration-300 transform hover:-translate-y-0.5">
{% trans "Apply Filters" %}
</button>
</form>
</div>
</div>
</aside>
<!-- Main Content -->
<main class="lg:col-span-8 xl:col-span-9">
<!-- Active Filters Bar -->
<div class="filters-bar bg-gradient-to-r from-gray-50 to-gray-100/50 backdrop-blur-sm p-6 rounded-2xl mb-8 border border-gray-200/50">
<div class="flex flex-col lg:flex-row justify-between items-start lg:items-center gap-4">
<div class="results-count">
<span class="text-3xl font-bold text-temple-red">{{ total_open_roles|default:"0" }}</span>
<span class="text-gray-600 ml-2 text-lg">{% trans "opportunities available" %}</span>
</div>
{% if selected_job_type or selected_workplace_type or selected_department %}
<div class="flex flex-wrap gap-2 items-center">
<span class="text-xs text-gray-500 font-medium">{% trans "Active filters:" %}</span>
{% if selected_job_type %}
<span class="filter-tag">
<span class="filter-tag-label">{{ selected_job_type }}</span>
<a href="?{% for key, value in request.GET.items %}{% if key != 'employment_type' %}{{ key }}={{ value }}{% if not forloop.last %}&{% endif %}{% endif %}{% endfor %}"
title="{% trans 'Remove' %}"
class="filter-tag-remove">
<i data-lucide="x" class="w-3 h-3"></i>
</a>
</span>
{% endif %}
{% if selected_workplace_type %}
<span class="filter-tag">
<span class="filter-tag-label">{{ selected_workplace_type }}</span>
<a href="?{% for key, value in request.GET.items %}{% if key != 'workplace_type' %}{{ key }}={{ value }}{% if not forloop.last %}&{% endif %}{% endif %}{% endfor %}"
title="{% trans 'Remove' %}"
class="filter-tag-remove">
<i data-lucide="x" class="w-3 h-3"></i>
</a>
</span>
{% endif %}
{% if selected_department %}
<span class="filter-tag">
<span class="filter-tag-label">{{ selected_department }}</span>
<a href="?{% for key, value in request.GET.items %}{% if key != 'department' %}{{ key }}={{ value }}{% if not forloop.last %}&{% endif %}{% endif %}{% endfor %}"
title="{% trans 'Remove' %}"
class="filter-tag-remove">
<i data-lucide="x" class="w-3 h-3"></i>
</a>
</span>
{% endif %}
<a href="?" class="clear-all-btn">
{% trans "Clear all" %}
</a>
</div>
{% endif %}
</div>
</div>
<!-- Job List -->
<div class="job-list space-y-5">
{% for job in active_jobs %}
<a href="{% url 'job_application_detail' job.slug %}"
class="job-card group">
<div class="job-card-accent"></div>
<div class="job-card-content">
<div class="flex flex-col md:flex-row md:justify-between md:items-start gap-3 mb-4">
<div class="flex-1">
<h3 class="job-title">
{{ job.title }}
<i data-lucide="arrow-up-right" class="job-arrow"></i>
</h3>
<p class="job-department">{{ job.department }}</p>
</div>
<div class="job-deadline">
<i data-lucide="clock" class="w-4 h-4"></i>
<span>{{ job.application_deadline }}</span>
</div>
</div>
<div class="job-meta">
<div class="job-meta-item">
<i data-lucide="map-pin" class="w-4 h-4"></i>
<span>{{ job.location_city|default:"Riyadh" }}</span>
</div>
<div class="job-meta-item">
<i data-lucide="briefcase" class="w-4 h-4"></i>
<span>{{ job.workplace_type }}</span>
</div>
</div>
</div>
</a>
{% empty %}
<div class="empty-state">
<div class="empty-state-icon">
<i data-lucide="inbox" class="w-16 h-16"></i>
</div>
<h3 class="empty-state-title">{% trans "No positions found" %}</h3>
<p class="empty-state-text">{% trans "Try adjusting your filters to see more opportunities" %}</p>
<a href="?" class="empty-state-btn">
{% trans "Clear Filters" %}
</a>
</div>
{% endfor %}
</div>
</main>
</div>
</div>
</div>
<style>
@import url('https://fonts.googleapis.com/css2?family=Archivo:wght@400;500;600;700;800&family=Outfit:wght@300;400;500;600;700&display=swap');
:root {
--temple-red: #9d2235;
--temple-red-dark: #7a1a29;
--temple-red-light: #b92d42;
}
* {
font-family: 'Outfit', -apple-system, BlinkMacSystemFont, sans-serif;
}
/* Hero Section */
.hero-section {
background: linear-gradient(135deg, var(--temple-red) 0%, var(--temple-red-dark) 100%);
position: relative;
}
.hero-bg {
background:
radial-gradient(circle at 20% 50%, rgba(255, 255, 255, 0.1) 0%, transparent 50%),
radial-gradient(circle at 80% 80%, rgba(255, 255, 255, 0.05) 0%, transparent 50%);
}
.hero-pattern {
background-image:
linear-gradient(30deg, rgba(255, 255, 255, 0.03) 12%, transparent 12.5%, transparent 87%, rgba(255, 255, 255, 0.03) 87.5%, rgba(255, 255, 255, 0.03)),
linear-gradient(150deg, rgba(255, 255, 255, 0.03) 12%, transparent 12.5%, transparent 87%, rgba(255, 255, 255, 0.03) 87.5%, rgba(255, 255, 255, 0.03)),
linear-gradient(30deg, rgba(255, 255, 255, 0.03) 12%, transparent 12.5%, transparent 87%, rgba(255, 255, 255, 0.03) 87.5%, rgba(255, 255, 255, 0.03)),
linear-gradient(150deg, rgba(255, 255, 255, 0.03) 12%, transparent 12.5%, transparent 87%, rgba(255, 255, 255, 0.03) 87.5%, rgba(255, 255, 255, 0.03));
background-size: 80px 140px;
background-position: 0 0, 0 0, 40px 70px, 40px 70px;
}
.hero-title {
font-family: 'Archivo', sans-serif;
font-weight: 800;
letter-spacing: -0.02em;
line-height: 1.1;
}
.hero-subtitle {
font-weight: 300;
}
.stat-item {
text-align: center;
}
/* Animations */
@keyframes fadeIn {
from { opacity: 0; }
to { opacity: 1; }
}
@keyframes slideUp {
from {
opacity: 0;
transform: translateY(30px);
}
to {
opacity: 1;
transform: translateY(0);
}
}
.animate-fade-in {
animation: fadeIn 0.8s ease-out forwards;
}
.animate-fade-in-delay {
animation: fadeIn 0.8s ease-out 0.4s forwards;
opacity: 0;
}
.animate-slide-up {
animation: slideUp 0.8s ease-out forwards;
}
.animate-slide-up-delay {
animation: slideUp 0.8s ease-out 0.2s forwards;
opacity: 0;
}
/* Filter Sidebar */
.filter-sidebar {
position: fixed;
inset: 0;
background: rgba(0, 0, 0, 0.6);
backdrop-filter: blur(4px);
z-index: 2000;
padding: 1rem;
animation: fadeIn 0.2s ease-out;
display: flex;
align-items: center;
justify-content: center;
}
.filter-sidebar.lg\:static {
position: static;
background: none;
backdrop-filter: none;
padding: 0;
animation: none;
display: block;
}
.filter-card {
width: 100%;
max-width: 500px;
animation: slideUp 0.3s ease-out;
max-height: 90vh;
overflow-y: auto;
}
.filter-sidebar.lg\:static .filter-card {
max-width: none;
animation: none;
max-height: none;
}
/* Form Elements */
.form-group {
position: relative;
}
.form-label {
display: flex;
align-items: center;
gap: 0.5rem;
font-size: 0.875rem;
font-weight: 600;
color: #374151;
margin-bottom: 0.75rem;
}
.form-input,
.form-select {
width: 100%;
padding: 0.875rem 1rem;
border: 2px solid #e5e7eb;
border-radius: 0.75rem;
background: #f9fafb;
font-size: 0.9375rem;
color: #1f2937;
transition: all 0.2s ease;
}
.form-input:focus,
.form-select:focus {
outline: none;
border-color: var(--temple-red);
background: white;
box-shadow: 0 0 0 3px rgba(157, 34, 53, 0.1);
}
.form-select {
cursor: pointer;
appearance: none;
background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='24' height='24' viewBox='0 0 24 24' fill='none' stroke='%236b7280' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpolyline points='6 9 12 15 18 9'%3E%3C/polyline%3E%3C/svg%3E");
background-repeat: no-repeat;
background-position: right 0.75rem center;
background-size: 1.25rem;
padding-right: 2.5rem;
}
/* Filter Tags */
.filter-tag {
display: inline-flex;
align-items: center;
gap: 0.5rem;
background: white;
border: 2px solid var(--temple-red);
border-radius: 9999px;
padding: 0.5rem 0.75rem;
font-size: 0.8125rem;
font-weight: 600;
color: var(--temple-red);
transition: all 0.2s ease;
}
.filter-tag:hover {
background: rgba(157, 34, 53, 0.05);
transform: translateY(-1px);
}
.filter-tag-label {
line-height: 1;
}
.filter-tag-remove {
display: flex;
align-items: center;
justify-content: center;
width: 1.25rem;
height: 1.25rem;
border-radius: 50%;
background: var(--temple-red);
color: white;
transition: all 0.2s ease;
}
.filter-tag-remove:hover {
background: var(--temple-red-dark);
transform: rotate(90deg);
}
.clear-all-btn {
font-size: 0.8125rem;
font-weight: 600;
color: var(--temple-red);
text-decoration: underline;
text-underline-offset: 2px;
transition: color 0.2s ease;
}
.clear-all-btn:hover {
color: var(--temple-red-dark);
}
/* Job Cards */
.job-card {
position: relative;
display: block;
background: white;
border-radius: 1.5rem;
overflow: hidden;
border: 2px solid #f3f4f6;
transition: all 0.3s cubic-bezier(0.4, 0, 0.2, 1);
}
.job-card:hover {
border-color: var(--temple-red);
transform: translateY(-4px);
box-shadow: 0 20px 40px rgba(157, 34, 53, 0.15);
}
.job-card-accent {
position: absolute;
left: 0;
top: 0;
bottom: 0;
width: 6px;
background: linear-gradient(180deg, var(--temple-red) 0%, var(--temple-red-dark) 100%);
transform: scaleY(0.3);
transform-origin: top;
transition: transform 0.3s ease;
}
.job-card:hover .job-card-accent {
transform: scaleY(1);
}
.job-card-content {
padding: 2rem;
padding-left: 2.5rem;
}
.job-title {
font-family: 'Archivo', sans-serif;
font-size: 1.375rem;
font-weight: 700;
color: #111827;
margin: 0;
display: flex;
align-items: center;
gap: 0.5rem;
transition: color 0.2s ease;
}
.job-card:hover .job-title {
color: var(--temple-red);
}
.job-arrow {
width: 1.25rem;
height: 1.25rem;
opacity: 0;
transform: translate(-8px, 8px);
transition: all 0.3s ease;
}
.job-card:hover .job-arrow {
opacity: 1;
transform: translate(0, 0);
}
.job-department {
font-size: 0.9375rem;
color: #6b7280;
margin: 0.5rem 0 0 0;
font-weight: 500;
}
.job-deadline {
display: flex;
align-items: center;
gap: 0.5rem;
font-size: 0.8125rem;
color: #6b7280;
background: #f9fafb;
padding: 0.5rem 1rem;
border-radius: 9999px;
white-space: nowrap;
}
.job-meta {
display: flex;
flex-wrap: wrap;
gap: 1.5rem;
margin-top: 1rem;
}
.job-meta-item {
display: flex;
align-items: center;
gap: 0.5rem;
font-size: 0.875rem;
color: #6b7280;
font-weight: 500;
}
.job-meta-item i {
color: var(--temple-red);
}
/* Empty State */
.empty-state {
text-align: center;
padding: 4rem 2rem;
background: white;
border-radius: 1.5rem;
border: 2px dashed #e5e7eb;
}
.empty-state-icon {
display: inline-flex;
align-items: center;
justify-content: center;
width: 5rem;
height: 5rem;
background: linear-gradient(135deg, #f9fafb 0%, #f3f4f6 100%);
border-radius: 50%;
color: #9ca3af;
margin-bottom: 1.5rem;
}
.empty-state-title {
font-family: 'Archivo', sans-serif;
font-size: 1.5rem;
font-weight: 700;
color: #111827;
margin-bottom: 0.75rem;
}
.empty-state-text {
font-size: 1rem;
color: #6b7280;
margin-bottom: 1.5rem;
}
.empty-state-btn {
display: inline-block;
padding: 0.875rem 2rem;
background: linear-gradient(135deg, var(--temple-red) 0%, var(--temple-red-dark) 100%);
color: white;
font-weight: 600;
border-radius: 0.75rem;
transition: all 0.3s ease;
}
.empty-state-btn:hover {
transform: translateY(-2px);
box-shadow: 0 10px 25px rgba(157, 34, 53, 0.3);
}
/* Responsive */
@media (min-width: 1024px) {
.filter-sidebar {
position: static !important;
background: none !important;
backdrop-filter: none !important;
padding: 0 !important;
animation: none !important;
}
.close-filters {
display: none !important;
}
}
@media (max-width: 768px) {
.hero-title {
font-size: 2rem;
}
.hero-subtitle {
font-size: 1rem;
}
.job-title {
font-size: 1.125rem;
}
.job-card-content {
padding: 1.5rem;
}
}
</style>
<script>
document.addEventListener('DOMContentLoaded', function() {
if (typeof lucide !== 'undefined') {
lucide.createIcons();
}
});
function toggleFilters() {
const sidebar = document.getElementById('sidebar');
if (sidebar) {
sidebar.classList.toggle('hidden');
sidebar.classList.toggle('lg:block');
document.body.style.overflow = sidebar.classList.contains('hidden') ? 'auto' : 'hidden';
}
}
// Close sidebar when clicking the backdrop on mobile
document.addEventListener('click', function(e) {
const sidebar = document.getElementById('sidebar');
if (sidebar && !sidebar.classList.contains('hidden') && window.innerWidth < 1024) {
if (e.target === sidebar) {
toggleFilters();
}
}
});
// Stagger animation for job cards
const observerOptions = {
threshold: 0.1,
rootMargin: '0px 0px -50px 0px'
};
const observer = new IntersectionObserver((entries) => {
entries.forEach((entry, index) => {
if (entry.isIntersecting) {
setTimeout(() => {
entry.target.style.opacity = '1';
entry.target.style.transform = 'translateY(0)';
}, index * 100);
observer.unobserve(entry.target);
}
});
}, observerOptions);
document.addEventListener('DOMContentLoaded', function() {
document.querySelectorAll('.job-card').forEach((card) => {
card.style.opacity = '0';
card.style.transform = 'translateY(20px)';
card.style.transition = 'opacity 0.6s ease, transform 0.6s ease';
observer.observe(card);
});
});
</script>
{% endblock %}