update
This commit is contained in:
parent
ef952ab596
commit
f02d859c7a
Binary file not shown.
Binary file not shown.
@ -66,6 +66,7 @@ MIDDLEWARE = [
|
||||
'corsheaders.middleware.CorsMiddleware',
|
||||
'django.middleware.security.SecurityMiddleware',
|
||||
'django.contrib.sessions.middleware.SessionMiddleware',
|
||||
'django.middleware.locale.LocaleMiddleware',
|
||||
'django.middleware.common.CommonMiddleware',
|
||||
'django.middleware.csrf.CsrfViewMiddleware',
|
||||
'django.contrib.auth.middleware.AuthenticationMiddleware',
|
||||
|
||||
@ -1,24 +1,9 @@
|
||||
"""
|
||||
URL configuration for NorahUniversity project.
|
||||
|
||||
The `urlpatterns` list routes URLs to views. For more information please see:
|
||||
https://docs.djangoproject.com/en/5.2/topics/http/urls/
|
||||
Examples:
|
||||
Function views
|
||||
1. Add an import: from my_app import views
|
||||
2. Add a URL to urlpatterns: path('', views.home, name='home')
|
||||
Class-based views
|
||||
1. Add an import: from other_app.views import Home
|
||||
2. Add a URL to urlpatterns: path('', Home.as_view(), name='home')
|
||||
Including another URLconf
|
||||
1. Import the include() function: from django.urls import include, path
|
||||
2. Add a URL to urlpatterns: path('blog/', include('blog.urls'))
|
||||
"""
|
||||
from django.contrib import admin
|
||||
from django.urls import path, include
|
||||
from django.conf.urls.static import static
|
||||
from django.conf import settings
|
||||
from django.conf.urls.i18n import i18n_patterns
|
||||
from django.conf.urls.i18n import i18n_patterns # Import i18n_patterns
|
||||
from rest_framework.routers import DefaultRouter
|
||||
from recruitment import views
|
||||
|
||||
@ -26,11 +11,19 @@ router = DefaultRouter()
|
||||
router.register(r'jobs', views.JobPostingViewSet)
|
||||
router.register(r'candidates', views.CandidateViewSet)
|
||||
|
||||
# 1. URLs that DO NOT have a language prefix (admin, API, static files)
|
||||
urlpatterns = [
|
||||
path('admin/', admin.site.urls),
|
||||
path('api/', include(router.urls)),
|
||||
path('accounts/', include('allauth.urls')),
|
||||
path('', include('recruitment.urls')),
|
||||
path('i18n/', include('django.conf.urls.i18n')),
|
||||
]
|
||||
|
||||
# 2. URLs that DO have a language prefix (user-facing views)
|
||||
# This includes the root path (''), which is handled by 'recruitment.urls'
|
||||
urlpatterns += i18n_patterns(
|
||||
path('', include('recruitment.urls')),
|
||||
)
|
||||
|
||||
urlpatterns += static(settings.MEDIA_URL, document_root=settings.MEDIA_ROOT)
|
||||
urlpatterns += static(settings.STATIC_URL, document_root=settings.STATIC_ROOT)
|
||||
urlpatterns += static(settings.STATIC_URL, document_root=settings.STATIC_ROOT)
|
||||
BIN
db.sqlite3
BIN
db.sqlite3
Binary file not shown.
1428
locale/ar/LC_MESSAGES/django.po
Normal file
1428
locale/ar/LC_MESSAGES/django.po
Normal file
File diff suppressed because it is too large
Load Diff
1427
locale/en/LC_MESSAGES/django.po
Normal file
1427
locale/en/LC_MESSAGES/django.po
Normal file
File diff suppressed because it is too large
Load Diff
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
@ -20,6 +20,7 @@
|
||||
--kaauh-light-bg: #f9fbfd;
|
||||
--kaauh-border: #eaeff3;
|
||||
}
|
||||
|
||||
|
||||
/* === Top Bar === */
|
||||
.top-bar {
|
||||
@ -260,8 +261,7 @@
|
||||
<nav class="navbar navbar-expand-lg navbar-dark sticky-top">
|
||||
<div class="container">
|
||||
<a class="navbar-brand text-white" href="{% url 'dashboard' %}">
|
||||
<i class="fas fa-hospital"></i>
|
||||
<span class="d-lg-none ms-1">KAAUH ATS</span>
|
||||
<img src="{% static 'image/kaauh.jpeg' %}" alt="{% trans 'Saudi Vision 2030' %}" style="width: 60px; height: 60px;">
|
||||
</a>
|
||||
|
||||
<button class="navbar-toggler" type="button" data-bs-toggle="collapse" data-bs-target="#navbarNav"
|
||||
@ -271,14 +271,14 @@
|
||||
|
||||
<div class="collapse navbar-collapse" id="navbarNav">
|
||||
<ul class="navbar-nav me-auto mb-2 mb-lg-0">
|
||||
<li class="nav-item">
|
||||
{% comment %} <li class="nav-item">
|
||||
<a class="nav-link {% if request.resolver_match.url_name == 'dashboard' %}active{% endif %}" href="{% url 'dashboard' %}">
|
||||
<span class="d-flex align-items-center gap-2">
|
||||
{% include "icons/dashboard.html" %}
|
||||
{% trans "Dashboard" %}
|
||||
</span>
|
||||
</a>
|
||||
</li>
|
||||
</li> {% endcomment %}
|
||||
<li class="nav-item">
|
||||
<a class="nav-link {% if request.resolver_match.url_name == 'job_list' %}active{% endif %}" href="{% url 'job_list' %}">
|
||||
<span class="d-flex align-items-center gap-2">
|
||||
@ -345,48 +345,38 @@
|
||||
</li>
|
||||
</ul>
|
||||
|
||||
{% if not request.session.linkedin_authenticated %}
|
||||
<ul class="navbar-nav ms-auto">
|
||||
<li class="nav-item">
|
||||
<a class="nav-link" href="{% url 'linkedin_login' %}">
|
||||
<i class="fab fa-linkedin me-1"></i> {% trans "Connect LinkedIn" %}
|
||||
</a>
|
||||
</li>
|
||||
</ul>
|
||||
{% else %}
|
||||
<span class="text-success d-none d-lg-inline ms-auto me-3">
|
||||
<i class="fab fa-linkedin me-1"></i> {% trans "LinkedIn Connected" %}
|
||||
</span>
|
||||
{% endif %}
|
||||
|
||||
<ul class="navbar-nav me-2">
|
||||
<li class="nav-item dropdown">
|
||||
<a class="language-toggle-btn dropdown-toggle" href="#" role="button" data-bs-toggle="dropdown"
|
||||
data-bs-offset="0, 8" aria-expanded="false" aria-label="{% trans 'Toggle language menu' %}">
|
||||
data-bs-offset="0, 8" aria-expanded="false" aria-label="{% trans 'Toggle language menu' %}">
|
||||
<i class="fas fa-globe"></i>
|
||||
<span class="d-none d-lg-inline">{{ LANGUAGE_CODE|upper }}</span>
|
||||
</a>
|
||||
<ul class="dropdown-menu dropdown-menu-end" data-bs-popper="static">
|
||||
|
||||
{% get_current_language as LANGUAGE_CODE %}
|
||||
|
||||
<li>
|
||||
<form action="" method="post" class="d-inline">{% csrf_token %}
|
||||
<form action="{% url 'set_language' %}" method="post" class="d-inline">{% csrf_token %}
|
||||
<input name="next" type="hidden" value="{{ request.get_full_path }}">
|
||||
<button name="language" value="en" class="dropdown-item {% if LANGUAGE_CODE == 'en' %}active bg-light-subtle{% endif %}" type="submit">
|
||||
<span class="me-2">🇺🇸</span> English
|
||||
</button>
|
||||
</form>
|
||||
</li>
|
||||
|
||||
<li>
|
||||
<form action="" method="post" class="d-inline">{% csrf_token %}
|
||||
<form action="{% url 'set_language' %}" method="post" class="d-inline">{% csrf_token %}
|
||||
<input name="next" type="hidden" value="{{ request.get_full_path }}">
|
||||
<button name="language" value="ar" class="dropdown-item {% if LANGUAGE_CODE == 'ar' %}active bg-light-subtle{% endif %}" type="submit">
|
||||
<span class="me-2">🇸🇦</span> العربية (Arabic)
|
||||
</button>
|
||||
</form>
|
||||
</li>
|
||||
</ul>
|
||||
</ul>
|
||||
</li>
|
||||
</ul>
|
||||
|
||||
</ul>
|
||||
|
||||
<ul class="navbar-nav">
|
||||
<li class="nav-item dropdown">
|
||||
@ -426,6 +416,23 @@
|
||||
<li><a class="dropdown-item py-2 px-4 d-flex align-items-center text-decoration-none" href="#"><i class="fas fa-cog me-3 text-primary fs-5"></i> <span>{% trans "Settings" %}</span></a></li>
|
||||
<li><a class="dropdown-item py-2 px-4 d-flex align-items-center text-decoration-none" href="#"><i class="fas fa-history me-3 text-primary fs-5"></i> <span>{% trans "Activity Log" %}</span></a></li>
|
||||
<li><a class="dropdown-item py-2 px-4 d-flex align-items-center text-decoration-none" href="#"><i class="fas fa-question-circle me-3 text-primary fs-5"></i> <span>{% trans "Help & Support" %}</span></a></li>
|
||||
<li><a class="dropdown-item py-2 px-4 d-flex align-items-center text-decoration-none" href="#">
|
||||
{% if not request.session.linkedin_authenticated %}
|
||||
<ul class="navbar-nav ms-auto">
|
||||
<li class="nav-item">
|
||||
<a class="nav-link" href="{% url 'linkedin_login' %}">
|
||||
<i class="fab fa-linkedin me-1"></i> {% trans "Connect LinkedIn" %}
|
||||
</a>
|
||||
</li>
|
||||
</ul>
|
||||
{% else %}
|
||||
<i class="fab fa-linkedin text-primary me-1"></i>
|
||||
<span class="text-primary d-none d-lg-inline ms-auto me-3">
|
||||
{% trans "LinkedIn Connected" %}
|
||||
</span>
|
||||
{% endif %}
|
||||
</a></li>
|
||||
|
||||
<li><hr class="dropdown-divider my-1"></li>
|
||||
<li>
|
||||
<form method="post" action="" class="d-inline">
|
||||
|
||||
@ -1,454 +1,544 @@
|
||||
<!-- templates/form_wizard.html -->
|
||||
{% load static i18n %}
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<title>Application Form</title>
|
||||
<title>{% translate "Application Form" %}</title>
|
||||
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.0/dist/css/bootstrap.min.css" rel="stylesheet">
|
||||
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.4.0/css/all.min.css">
|
||||
<style>
|
||||
/* KAAT-S Theme Variables */
|
||||
:root {
|
||||
--kaauh-teal: #00636e; /* Main Primary Color */
|
||||
--kaauh-teal-dark: #004a53; /* Dark Primary Color */
|
||||
|
||||
/* Mapping wizard defaults to theme colors */
|
||||
--primary: var(--kaauh-teal);
|
||||
--primary-light: #007c89; /* Slightly lighter shade for subtle hover/border */
|
||||
--secondary: var(--kaauh-teal-dark);
|
||||
--success: #198754; /* Keeping a standard success green for Submit */
|
||||
--error: #dc3545; /* Standard danger red */
|
||||
|
||||
--light: #f8f9fa;
|
||||
--dark: #212529;
|
||||
--gray: #6c757d;
|
||||
--light-gray: #e9ecef;
|
||||
--border: #dee2e6;
|
||||
--shadow: 0 4px 6px rgba(0, 0, 0, 0.1);
|
||||
--radius: 16px; /* Increased radius for a softer look */
|
||||
--transition: all 0.3s ease;
|
||||
}
|
||||
<style>
|
||||
/* KAAT-S Theme Variables */
|
||||
:root {
|
||||
--kaauh-teal: #00636e; /* Main Primary Color */
|
||||
--kaauh-teal-dark: #004a53; /* Dark Primary Color */
|
||||
|
||||
/* Mapping wizard defaults to theme colors */
|
||||
--primary: var(--kaauh-teal);
|
||||
--primary-light: #007c89; /* Slightly lighter shade for subtle hover/border */
|
||||
--secondary: var(--kaauh-teal-dark);
|
||||
--success: #198754; /* Keeping a standard success green for Submit */
|
||||
--error: #dc3545; /* Standard danger red */
|
||||
|
||||
--light: #f8f9fa;
|
||||
--dark: #212529;
|
||||
--gray: #6c757d;
|
||||
--light-gray: #e9ecef;
|
||||
--border: #dee2e6;
|
||||
--shadow: 0 4px 6px rgba(0, 0, 0, 0.1);
|
||||
--radius: 16px; /* Increased radius for a softer look */
|
||||
--transition: all 0.3s ease;
|
||||
}
|
||||
|
||||
body {
|
||||
/* Dark gradient background to match the theme */
|
||||
background: linear-gradient(135deg, var(--kaauh-teal-dark) 0%, #1e3a47 100%);
|
||||
min-height: 100vh;
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
padding: 20px;
|
||||
font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif;
|
||||
}
|
||||
body {
|
||||
/* Remove centering/flex properties to allow for normal document flow and scrolling */
|
||||
padding-top: 56px; /* Space for the sticky navbar */
|
||||
|
||||
/* Dark gradient background to match the theme */
|
||||
background: linear-gradient(135deg, var(--kaauh-teal-dark) 0%, #1e3a47 100%);
|
||||
background-image: url("{% static 'image/vision.svg' %}");
|
||||
background-repeat: no-repeat;
|
||||
background-position: 60px;
|
||||
background-size: 320px auto;
|
||||
min-height: 100vh;
|
||||
padding: 0; /* Remove padding from body */
|
||||
font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif;
|
||||
}
|
||||
|
||||
/* Wrapper to center the wizard content below the navbar */
|
||||
.page-content-wrapper {
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
padding: 20px; /* Re-apply padding here for the content area */
|
||||
min-height: calc(100vh - 56px); /* Adjust height to account for navbar */
|
||||
}
|
||||
|
||||
.wizard-container {
|
||||
width: 100%;
|
||||
max-width: 800px; /* Increased max-width slightly for content */
|
||||
background: white;
|
||||
border-radius: 20px;
|
||||
overflow: hidden;
|
||||
box-shadow: 0 20px 40px rgba(0, 0, 0, 0.2);
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
/* Allow height to be determined by content, constrained by max-height */
|
||||
height: auto;
|
||||
max-height: 90vh;
|
||||
}
|
||||
|
||||
/* Progress Bar */
|
||||
.progress-container {
|
||||
height: 8px; /* Slightly thicker bar */
|
||||
background: var(--light-gray);
|
||||
position: relative;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.progress-bar {
|
||||
height: 100%;
|
||||
background: var(--primary); /* Teal color */
|
||||
transition: width 0.4s ease;
|
||||
width: 0%;
|
||||
}
|
||||
|
||||
/* Header */
|
||||
.wizard-header {
|
||||
padding: 25px 30px 15px;
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.logo {
|
||||
font-size: 1.4rem;
|
||||
font-weight: 700;
|
||||
color: var(--secondary); /* Dark teal for logo */
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 10px;
|
||||
}
|
||||
|
||||
.progress-text {
|
||||
font-size: 0.9rem;
|
||||
color: var(--gray);
|
||||
font-weight: 500;
|
||||
}
|
||||
|
||||
/* Main Content */
|
||||
.wizard-content {
|
||||
flex: 1;
|
||||
padding: 0 30px 30px;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.stage-container {
|
||||
flex: 1;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
overflow-y: auto;
|
||||
padding-right: 15px; /* Space for scrollbar */
|
||||
}
|
||||
|
||||
.stage-title {
|
||||
font-size: 1.8rem;
|
||||
font-weight: 700;
|
||||
margin-bottom: 25px;
|
||||
color: var(--dark);
|
||||
line-height: 1.3;
|
||||
}
|
||||
|
||||
.field-container {
|
||||
margin-bottom: 25px;
|
||||
}
|
||||
|
||||
.field-label {
|
||||
font-size: 1.1rem;
|
||||
font-weight: 600;
|
||||
margin-bottom: 12px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 8px;
|
||||
color: var(--dark);
|
||||
}
|
||||
|
||||
.required-indicator {
|
||||
color: var(--error);
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
/* Input Styles */
|
||||
.form-input {
|
||||
width: 100%;
|
||||
padding: 14px 16px;
|
||||
border: 2px solid var(--border);
|
||||
border-radius: 12px;
|
||||
font-size: 1rem;
|
||||
transition: var(--transition);
|
||||
}
|
||||
|
||||
.form-input:focus {
|
||||
outline: none;
|
||||
border-color: var(--primary); /* Teal focus border */
|
||||
box-shadow: 0 0 0 4px rgba(0, 99, 110, 0.2); /* Teal shadow */
|
||||
}
|
||||
|
||||
.form-input.error {
|
||||
border-color: var(--error);
|
||||
box-shadow: 0 0 0 4px rgba(220, 53, 69, 0.2);
|
||||
}
|
||||
|
||||
.error-message {
|
||||
color: var(--error);
|
||||
font-size: 0.85rem;
|
||||
margin-top: 5px;
|
||||
display: none;
|
||||
}
|
||||
|
||||
.error-message.show {
|
||||
display: block;
|
||||
}
|
||||
|
||||
.form-textarea {
|
||||
min-height: 120px;
|
||||
resize: vertical;
|
||||
}
|
||||
|
||||
/* File Upload Styles */
|
||||
.file-upload-area {
|
||||
border: 2px dashed var(--border);
|
||||
border-radius: 12px;
|
||||
padding: 25px;
|
||||
text-align: center;
|
||||
background: var(--light);
|
||||
transition: var(--transition);
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.file-upload-area:hover {
|
||||
border-color: var(--primary); /* Teal hover border */
|
||||
background: rgba(0, 99, 110, 0.05); /* Light teal background */
|
||||
}
|
||||
|
||||
.file-upload-area.error {
|
||||
border-color: var(--error);
|
||||
background: rgba(220, 53, 69, 0.05);
|
||||
}
|
||||
|
||||
.file-upload-icon {
|
||||
font-size: 2.5rem;
|
||||
color: var(--primary); /* Teal icon */
|
||||
margin-bottom: 15px;
|
||||
}
|
||||
|
||||
.file-upload-text {
|
||||
font-size: 1.1rem;
|
||||
margin-bottom: 10px;
|
||||
}
|
||||
|
||||
.file-upload-text strong {
|
||||
color: var(--primary); /* Teal text */
|
||||
}
|
||||
|
||||
.file-upload-info {
|
||||
font-size: 0.9rem;
|
||||
color: var(--gray);
|
||||
}
|
||||
|
||||
.uploaded-file {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
background: white;
|
||||
border: 1px solid var(--border);
|
||||
border-radius: 12px;
|
||||
padding: 12px 16px;
|
||||
margin-top: 15px;
|
||||
}
|
||||
|
||||
.file-info {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 12px;
|
||||
}
|
||||
|
||||
.file-icon {
|
||||
color: var(--primary); /* Teal icon */
|
||||
font-size: 1.2rem;
|
||||
}
|
||||
|
||||
.file-name {
|
||||
font-weight: 600;
|
||||
}
|
||||
|
||||
.file-size {
|
||||
font-size: 0.85rem;
|
||||
color: var(--gray);
|
||||
}
|
||||
|
||||
.remove-file-btn {
|
||||
background: none;
|
||||
border: none;
|
||||
color: var(--error);
|
||||
cursor: pointer;
|
||||
font-size: 1.2rem;
|
||||
width: 32px;
|
||||
height: 32px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
border-radius: 50%;
|
||||
transition: var(--transition);
|
||||
}
|
||||
|
||||
.remove-file-btn:hover {
|
||||
background: rgba(220, 53, 69, 0.1);
|
||||
}
|
||||
|
||||
/* Radio/Checkbox Styles */
|
||||
.option-item {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
margin-bottom: 12px;
|
||||
padding: 12px;
|
||||
border: 2px solid var(--border);
|
||||
border-radius: 12px;
|
||||
transition: var(--transition);
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.option-item:hover {
|
||||
border-color: var(--primary-light);
|
||||
}
|
||||
|
||||
.option-item.selected {
|
||||
border-color: var(--primary); /* Teal border */
|
||||
background: rgba(0, 99, 110, 0.05); /* Light teal background */
|
||||
}
|
||||
|
||||
.option-item.error {
|
||||
border-color: var(--error);
|
||||
background: rgba(220, 53, 69, 0.05);
|
||||
}
|
||||
|
||||
/* Ensures radio/checkbox controls themselves use the primary color */
|
||||
.option-item input[type="radio"]:checked,
|
||||
.option-item input[type="checkbox"]:checked {
|
||||
accent-color: var(--primary);
|
||||
}
|
||||
|
||||
.option-item input {
|
||||
margin-right: 12px;
|
||||
width: 20px;
|
||||
height: 20px;
|
||||
}
|
||||
|
||||
/* Preview Styles */
|
||||
.preview-container {
|
||||
background: var(--light);
|
||||
border-radius: 12px;
|
||||
padding: 20px;
|
||||
margin-bottom: 25px;
|
||||
}
|
||||
|
||||
.preview-item {
|
||||
margin-bottom: 15px;
|
||||
padding-bottom: 15px;
|
||||
border-bottom: 1px solid var(--border);
|
||||
}
|
||||
|
||||
.preview-item:last-child {
|
||||
border-bottom: none;
|
||||
margin-bottom: 0;
|
||||
padding-bottom: 0;
|
||||
}
|
||||
|
||||
.preview-label {
|
||||
font-weight: 600;
|
||||
margin-bottom: 5px;
|
||||
color: var(--dark);
|
||||
}
|
||||
|
||||
.preview-value {
|
||||
color: var(--gray);
|
||||
}
|
||||
|
||||
/* Navigation */
|
||||
.wizard-footer {
|
||||
padding: 0 30px 30px;
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.nav-btn {
|
||||
padding: 14px 28px;
|
||||
border-radius: 12px;
|
||||
border: none;
|
||||
font-weight: 600;
|
||||
font-size: 1rem;
|
||||
cursor: pointer;
|
||||
transition: var(--transition);
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 10px;
|
||||
}
|
||||
|
||||
.btn-back {
|
||||
background: var(--light-gray); /* Match theme's light gray */
|
||||
color: var(--gray);
|
||||
}
|
||||
|
||||
.btn-back:hover {
|
||||
background: #d8dadc;
|
||||
}
|
||||
|
||||
.btn-next {
|
||||
background: var(--primary); /* Teal color */
|
||||
color: white;
|
||||
box-shadow: 0 4px 12px rgba(0, 99, 110, 0.3); /* Teal shadow */
|
||||
}
|
||||
|
||||
.btn-next:hover {
|
||||
background: var(--secondary); /* Darker teal on hover */
|
||||
transform: translateY(-2px);
|
||||
}
|
||||
|
||||
.btn-submit {
|
||||
background: var(--success); /* Green for submit */
|
||||
color: white;
|
||||
box-shadow: 0 4px 12px rgba(25, 135, 84, 0.3);
|
||||
}
|
||||
|
||||
.btn-submit:hover {
|
||||
background: #157347;
|
||||
transform: translateY(-2px);
|
||||
}
|
||||
|
||||
/* Responsive */
|
||||
@media (max-width: 600px) {
|
||||
.wizard-container {
|
||||
width: 100%;
|
||||
max-width: 800px; /* Increased max-width slightly for content */
|
||||
background: white;
|
||||
border-radius: 20px;
|
||||
overflow: hidden;
|
||||
box-shadow: 0 20px 40px rgba(0, 0, 0, 0.2);
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
height: 90vh;
|
||||
}
|
||||
|
||||
/* Progress Bar */
|
||||
.progress-container {
|
||||
height: 8px; /* Slightly thicker bar */
|
||||
background: var(--light-gray);
|
||||
position: relative;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.progress-bar {
|
||||
height: 100%;
|
||||
background: var(--primary); /* Teal color */
|
||||
transition: width 0.4s ease;
|
||||
width: 0%;
|
||||
}
|
||||
|
||||
/* Header */
|
||||
.wizard-header {
|
||||
padding: 25px 30px 15px;
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.logo {
|
||||
font-size: 1.4rem;
|
||||
font-weight: 700;
|
||||
color: var(--secondary); /* Dark teal for logo */
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 10px;
|
||||
}
|
||||
|
||||
.progress-text {
|
||||
font-size: 0.9rem;
|
||||
color: var(--gray);
|
||||
font-weight: 500;
|
||||
}
|
||||
|
||||
/* Main Content */
|
||||
.wizard-content {
|
||||
flex: 1;
|
||||
padding: 0 30px 30px;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.stage-container {
|
||||
flex: 1;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
overflow-y: auto;
|
||||
padding-right: 15px; /* Space for scrollbar */
|
||||
height: 100vh;
|
||||
border-radius: 0;
|
||||
max-width: 100%;
|
||||
max-height: 100vh;
|
||||
}
|
||||
|
||||
.stage-title {
|
||||
font-size: 1.8rem;
|
||||
font-weight: 700;
|
||||
margin-bottom: 25px;
|
||||
color: var(--dark);
|
||||
line-height: 1.3;
|
||||
font-size: 1.5rem;
|
||||
}
|
||||
|
||||
.field-container {
|
||||
margin-bottom: 25px;
|
||||
.wizard-header {
|
||||
padding: 20px;
|
||||
}
|
||||
|
||||
.field-label {
|
||||
font-size: 1.1rem;
|
||||
font-weight: 600;
|
||||
margin-bottom: 12px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 8px;
|
||||
color: var(--dark);
|
||||
.wizard-content {
|
||||
padding: 0 20px 20px;
|
||||
}
|
||||
|
||||
.required-indicator {
|
||||
color: var(--error);
|
||||
font-weight: bold;
|
||||
.wizard-footer {
|
||||
padding: 0 20px 20px;
|
||||
}
|
||||
|
||||
/* Input Styles */
|
||||
.form-input {
|
||||
width: 100%;
|
||||
padding: 14px 16px;
|
||||
border: 2px solid var(--border);
|
||||
border-radius: 12px;
|
||||
font-size: 1rem;
|
||||
transition: var(--transition);
|
||||
}
|
||||
|
||||
.form-input:focus {
|
||||
outline: none;
|
||||
border-color: var(--primary); /* Teal focus border */
|
||||
box-shadow: 0 0 0 4px rgba(0, 99, 110, 0.2); /* Teal shadow */
|
||||
}
|
||||
|
||||
.form-input.error {
|
||||
border-color: var(--error);
|
||||
box-shadow: 0 0 0 4px rgba(220, 53, 69, 0.2);
|
||||
}
|
||||
|
||||
.error-message {
|
||||
color: var(--error);
|
||||
font-size: 0.85rem;
|
||||
}
|
||||
|
||||
/* === FIX FOR SMALL-SCREEN HAMBURGER MENU === */
|
||||
@media (max-width: 991.98px) {
|
||||
/* Add vertical spacing to the navigation items when the navbar is collapsed */
|
||||
#navbarNav .nav-item {
|
||||
margin-top: 5px;
|
||||
display: none;
|
||||
margin-bottom: 5px;
|
||||
padding: 5px 0;
|
||||
border-bottom: 1px solid #f0f0f0;
|
||||
}
|
||||
|
||||
.error-message.show {
|
||||
|
||||
#navbarNav .nav-item:last-child {
|
||||
border-bottom: none;
|
||||
}
|
||||
|
||||
#navbarNav .nav-link {
|
||||
padding: 8px 15px;
|
||||
display: block;
|
||||
}
|
||||
|
||||
.form-textarea {
|
||||
min-height: 120px;
|
||||
resize: vertical;
|
||||
/* Adjust the total margin of the top navbar container when collapsed */
|
||||
#topNavbar.mb-3 {
|
||||
margin-bottom: 0 !important;
|
||||
}
|
||||
}
|
||||
|
||||
/* File Upload Styles */
|
||||
.file-upload-area {
|
||||
border: 2px dashed var(--border);
|
||||
border-radius: 12px;
|
||||
padding: 25px;
|
||||
text-align: center;
|
||||
background: var(--light);
|
||||
transition: var(--transition);
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.file-upload-area:hover {
|
||||
border-color: var(--primary); /* Teal hover border */
|
||||
background: rgba(0, 99, 110, 0.05); /* Light teal background */
|
||||
}
|
||||
|
||||
.file-upload-area.error {
|
||||
border-color: var(--error);
|
||||
background: rgba(220, 53, 69, 0.05);
|
||||
}
|
||||
|
||||
.file-upload-icon {
|
||||
font-size: 2.5rem;
|
||||
color: var(--primary); /* Teal icon */
|
||||
margin-bottom: 15px;
|
||||
}
|
||||
|
||||
.file-upload-text {
|
||||
font-size: 1.1rem;
|
||||
margin-bottom: 10px;
|
||||
}
|
||||
|
||||
.file-upload-text strong {
|
||||
color: var(--primary); /* Teal text */
|
||||
}
|
||||
|
||||
.file-upload-info {
|
||||
font-size: 0.9rem;
|
||||
color: var(--gray);
|
||||
}
|
||||
|
||||
.uploaded-file {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
background: white;
|
||||
border: 1px solid var(--border);
|
||||
border-radius: 12px;
|
||||
padding: 12px 16px;
|
||||
margin-top: 15px;
|
||||
}
|
||||
|
||||
.file-info {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 12px;
|
||||
}
|
||||
|
||||
.file-icon {
|
||||
color: var(--primary); /* Teal icon */
|
||||
font-size: 1.2rem;
|
||||
}
|
||||
|
||||
.file-name {
|
||||
font-weight: 600;
|
||||
}
|
||||
|
||||
.file-size {
|
||||
font-size: 0.85rem;
|
||||
color: var(--gray);
|
||||
}
|
||||
|
||||
.remove-file-btn {
|
||||
background: none;
|
||||
border: none;
|
||||
color: var(--error);
|
||||
cursor: pointer;
|
||||
font-size: 1.2rem;
|
||||
width: 32px;
|
||||
height: 32px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
border-radius: 50%;
|
||||
transition: var(--transition);
|
||||
}
|
||||
|
||||
.remove-file-btn:hover {
|
||||
background: rgba(220, 53, 69, 0.1);
|
||||
}
|
||||
|
||||
/* Radio/Checkbox Styles */
|
||||
.option-item {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
margin-bottom: 12px;
|
||||
padding: 12px;
|
||||
border: 2px solid var(--border);
|
||||
border-radius: 12px;
|
||||
transition: var(--transition);
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.option-item:hover {
|
||||
border-color: var(--primary-light);
|
||||
}
|
||||
|
||||
.option-item.selected {
|
||||
border-color: var(--primary); /* Teal border */
|
||||
background: rgba(0, 99, 110, 0.05); /* Light teal background */
|
||||
}
|
||||
|
||||
.option-item.error {
|
||||
border-color: var(--error);
|
||||
background: rgba(220, 53, 69, 0.05);
|
||||
}
|
||||
|
||||
/* Ensures radio/checkbox controls themselves use the primary color */
|
||||
.option-item input[type="radio"]:checked,
|
||||
.option-item input[type="checkbox"]:checked {
|
||||
accent-color: var(--primary);
|
||||
}
|
||||
|
||||
.option-item input {
|
||||
margin-right: 12px;
|
||||
width: 20px;
|
||||
height: 20px;
|
||||
}
|
||||
|
||||
/* Preview Styles */
|
||||
.preview-container {
|
||||
background: var(--light);
|
||||
border-radius: 12px;
|
||||
padding: 20px;
|
||||
margin-bottom: 25px;
|
||||
}
|
||||
|
||||
.preview-item {
|
||||
margin-bottom: 15px;
|
||||
padding-bottom: 15px;
|
||||
border-bottom: 1px solid var(--border);
|
||||
}
|
||||
|
||||
.preview-item:last-child {
|
||||
border-bottom: none;
|
||||
margin-bottom: 0;
|
||||
padding-bottom: 0;
|
||||
}
|
||||
|
||||
.preview-label {
|
||||
font-weight: 600;
|
||||
margin-bottom: 5px;
|
||||
color: var(--dark);
|
||||
}
|
||||
|
||||
.preview-value {
|
||||
color: var(--gray);
|
||||
}
|
||||
|
||||
/* Navigation */
|
||||
.wizard-footer {
|
||||
padding: 0 30px 30px;
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.nav-btn {
|
||||
padding: 14px 28px;
|
||||
border-radius: 12px;
|
||||
border: none;
|
||||
font-weight: 600;
|
||||
font-size: 1rem;
|
||||
cursor: pointer;
|
||||
transition: var(--transition);
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 10px;
|
||||
}
|
||||
|
||||
.btn-back {
|
||||
background: var(--light-gray); /* Match theme's light gray */
|
||||
color: var(--gray);
|
||||
}
|
||||
|
||||
.btn-back:hover {
|
||||
background: #d8dadc;
|
||||
}
|
||||
|
||||
.btn-next {
|
||||
background: var(--primary); /* Teal color */
|
||||
color: white;
|
||||
box-shadow: 0 4px 12px rgba(0, 99, 110, 0.3); /* Teal shadow */
|
||||
}
|
||||
|
||||
.btn-next:hover {
|
||||
background: var(--secondary); /* Darker teal on hover */
|
||||
transform: translateY(-2px);
|
||||
}
|
||||
|
||||
.btn-submit {
|
||||
background: var(--success); /* Green for submit */
|
||||
color: white;
|
||||
box-shadow: 0 4px 12px rgba(25, 135, 84, 0.3);
|
||||
}
|
||||
|
||||
.btn-submit:hover {
|
||||
background: #157347;
|
||||
transform: translateY(-2px);
|
||||
}
|
||||
|
||||
/* Responsive */
|
||||
@media (max-width: 600px) {
|
||||
.wizard-container {
|
||||
height: 100vh;
|
||||
border-radius: 0;
|
||||
max-width: 100%;
|
||||
}
|
||||
|
||||
.stage-title {
|
||||
font-size: 1.5rem;
|
||||
}
|
||||
|
||||
.wizard-header {
|
||||
padding: 20px;
|
||||
}
|
||||
|
||||
.wizard-content {
|
||||
padding: 0 20px 20px;
|
||||
}
|
||||
|
||||
.wizard-footer {
|
||||
padding: 0 20px 20px;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
#bottomNavbar {
|
||||
/* Position the dark navbar 72px from the top of the viewport */
|
||||
top: 72px;
|
||||
/* The z-index is already 1030 in the inline style, which is correct */
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<div class="wizard-container">
|
||||
<div class="progress-container">
|
||||
<div class="progress-bar" id="progressBar"></div>
|
||||
</div>
|
||||
|
||||
<div class="wizard-header">
|
||||
<div class="logo">
|
||||
<i class="fas fa-file-alt"></i>
|
||||
<span id="formTitle">Application Form</span>
|
||||
</div>
|
||||
<div class="progress-text" id="progressText">1 of 1</div>
|
||||
</div>
|
||||
|
||||
<div class="wizard-content">
|
||||
<div class="stage-container" id="stageContainer">
|
||||
</div>
|
||||
|
||||
<div class="preview-container" id="previewContainer" style="display: none;">
|
||||
<h3 class="mb-4">Review Your Application</h3>
|
||||
<div id="previewContent"></div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="wizard-footer">
|
||||
<button id="backBtn" class="nav-btn btn-back" style="display: none;">
|
||||
<i class="fas fa-arrow-left"></i> Back
|
||||
</button>
|
||||
|
||||
<button id="nextBtn" class="nav-btn btn-next">
|
||||
Next <i class="fas fa-arrow-right"></i>
|
||||
</button>
|
||||
|
||||
<button id="submitBtn" class="nav-btn btn-submit" style="display: none;">
|
||||
Submit Application <i class="fas fa-paper-plane"></i>
|
||||
</button>
|
||||
|
||||
<nav id="topNavbar" class="navbar navbar-expand-lg sticky-top" style="background-color: white; z-index: 1030;">
|
||||
<div class="container-fluid">
|
||||
<a class="navbar-brand text-white fw-bold" href="/">
|
||||
<img src="{% static 'image/kaauh.jpeg' %}" alt="{% translate 'KAAUH IMAGE' %}" style="height: 50px; margin-right: 10px;">
|
||||
</a>
|
||||
<button class="navbar-toggler" type="button" data-bs-toggle="collapse" data-bs-target="#navbarNav"
|
||||
aria-controls="navbarNav" aria-expanded="false" aria-label="Toggle navigation">
|
||||
<span class="navbar-toggler-icon"></span>
|
||||
</button>
|
||||
<div class="collapse navbar-collapse" id="navbarNav">
|
||||
<ul class="navbar-nav ms-auto">
|
||||
|
||||
<li class="nav-item">
|
||||
<a class="nav-link text-secondary" href="/applications/">{% translate "Applications" %}</a>
|
||||
</li>
|
||||
<li class="nav-item">
|
||||
<a class="nav-link text-secondary" href="/profile/">{% translate "Profile" %}</a>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
</nav>
|
||||
<nav id="bottomNavbar" class="navbar navbar-expand-lg sticky-top" style="background-color: var(--kaauh-teal); z-index: 1030;">
|
||||
</nav>
|
||||
|
||||
<div class="page-content-wrapper">
|
||||
<div class="wizard-container">
|
||||
<div class="progress-container">
|
||||
<div class="progress-bar" id="progressBar"></div>
|
||||
</div>
|
||||
|
||||
<script>
|
||||
<div class="wizard-header">
|
||||
<div class="logo">
|
||||
<i class="fas fa-file-alt"></i>
|
||||
<span id="formTitle">{% translate "Application Form" %}</span>
|
||||
</div>
|
||||
<div class="progress-text" id="progressText">1 of 1</div>
|
||||
</div>
|
||||
|
||||
<div class="wizard-content">
|
||||
<div class="stage-container" id="stageContainer">
|
||||
</div>
|
||||
|
||||
<div class="preview-container" id="previewContainer" style="display: none;">
|
||||
<h3 class="mb-4">{% translate "Review Your Application" %}</h3>
|
||||
<div id="previewContent"></div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="wizard-footer">
|
||||
<button id="backBtn" class="nav-btn btn-back" style="display: none;">
|
||||
<i class="fas fa-arrow-left"></i> {% translate "Back" %}
|
||||
</button>
|
||||
|
||||
<button id="nextBtn" class="nav-btn btn-next">
|
||||
{% translate "Next" %} <i class="fas fa-arrow-right"></i>
|
||||
</button>
|
||||
|
||||
<button id="submitBtn" class="nav-btn btn-submit" style="display: none;">
|
||||
{% translate "Submit Application" %} <i class="fas fa-paper-plane"></i>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div> <script>
|
||||
// Placeholder for the complete JavaScript logic (omitted for brevity, but required for functionality)
|
||||
// This script block should contain the Application State, DOM Elements, Validation, API, Rendering, and Event Handlers
|
||||
console.log("JavaScript logic for form wizard needs to be included here.");
|
||||
|
||||
// --- COMPLETE JAVASCRIPT LOGIC GOES HERE ---
|
||||
// (The logic provided in the previous turn, including the completed createFieldElement and renderPreview functions)
|
||||
|
||||
// Example structure for reference:
|
||||
// function validateEmail(email) { ... }
|
||||
// function loadFormTemplate() { ... }
|
||||
// function renderCurrentStage() { ... }
|
||||
// function createFieldElement(field) { ... }
|
||||
// function renderPreview() { ... }
|
||||
// document.addEventListener('DOMContentLoaded', loadFormTemplate);
|
||||
</script>
|
||||
<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.3.0/dist/js/bootstrap.bundle.min.js"></script>
|
||||
<script>
|
||||
// Application State
|
||||
const csrfToken = '{{ csrf_token }}';
|
||||
const state = {
|
||||
@ -1154,4 +1244,4 @@
|
||||
document.addEventListener('DOMContentLoaded', init);
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
</html>
|
||||
|
||||
@ -1,18 +1,30 @@
|
||||
{% extends "base.html" %}
|
||||
|
||||
{% block title %}{{ job.title }} - University ATS{% endblock %}
|
||||
{% block customCSS %}
|
||||
|
||||
<style>
|
||||
{% load static i18n %}
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<title>{% translate "Application Form" %}</title>
|
||||
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.0/dist/css/bootstrap.min.css" rel="stylesheet">
|
||||
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.4.0/css/all.min.css">
|
||||
<style>
|
||||
/* ---------------------------------------------------------------------- */
|
||||
/* THEME STYLES (Keep from previous response) */
|
||||
/* THEME & UTILITY VARIABLES */
|
||||
/* ---------------------------------------------------------------------- */
|
||||
:root {
|
||||
--kaauh-teal: #00636e;
|
||||
--kaauh-teal-dark: #004a53;
|
||||
--success: #198754;
|
||||
/* Define a subtle background for mobile sticky bar */
|
||||
--light-bg: #f8f9fa;
|
||||
|
||||
/* CALCULATED STICKY HEIGHTS */
|
||||
/* Standard Bootstrap Navbar Height (approx 56px) */
|
||||
--navbar-height: 56px;
|
||||
/* Bootstrap mb-3 spacing (1rem or 16px) */
|
||||
--navbar-gap: 16px;
|
||||
|
||||
/* Combined height of the two navbars when collapsed on desktop (56 + 16 + 56 = 128px) */
|
||||
--sticky-navbar-total-height: 128px;
|
||||
}
|
||||
|
||||
.btn-main-action {
|
||||
@ -32,14 +44,67 @@
|
||||
.bg-kaauh-teal-dark {
|
||||
background-color: var(--kaauh-teal-dark) !important;
|
||||
}
|
||||
|
||||
|
||||
/* ---------------------------------------------------------------------- */
|
||||
/* MOBILE RESPONSIVE STYLES */
|
||||
/* LAYOUT & STICKY POSITIONING FIXES (Desktop/Tablet) */
|
||||
/* ---------------------------------------------------------------------- */
|
||||
|
||||
/* 1. Mobile Fixed Footer Bar for Application */
|
||||
/* 1. Position the dark navbar below the white navbar + gap */
|
||||
#bottomNavbar {
|
||||
/* 56px (white nav) + 16px (mb-3) = 72px */
|
||||
top: calc(var(--navbar-height) + var(--navbar-gap));
|
||||
z-index: 1030;
|
||||
}
|
||||
|
||||
/* 2. Pushes the main content down so it's not hidden under the navbars */
|
||||
.main-content-area {
|
||||
/* Total Sticky Height (128px) + Extra Margin (12px) = 140px */
|
||||
margin-top: calc(var(--sticky-navbar-total-height) + 12px);
|
||||
}
|
||||
|
||||
/* 3. Positions the sticky sidebar correctly */
|
||||
.card.sticky-top {
|
||||
/* Start scrolling the sidebar just below the two navbars + a small gap */
|
||||
top: calc(var(--sticky-navbar-total-height) + 15px);
|
||||
}
|
||||
|
||||
/* ---------------------------------------------------------------------- */
|
||||
/* MOBILE RESPONSIVE STYLES (Below 992px) */
|
||||
/* ---------------------------------------------------------------------- */
|
||||
@media (max-width: 991.98px) {
|
||||
/* Fix the "Apply" button bar to the bottom on mobile/tablet */
|
||||
|
||||
/* --- FIX: Spacing for Collapsed Hamburger Menu --- */
|
||||
#navbarNav .nav-item {
|
||||
margin-top: 5px;
|
||||
margin-bottom: 5px;
|
||||
padding: 5px 0;
|
||||
border-bottom: 1px solid #f0f0f0;
|
||||
}
|
||||
|
||||
#navbarNav .nav-item:last-child {
|
||||
border-bottom: none;
|
||||
}
|
||||
|
||||
#navbarNav .nav-link {
|
||||
padding: 8px 15px;
|
||||
display: block;
|
||||
}
|
||||
/* --- END FIX --- */
|
||||
|
||||
/* On mobile, the top navbar is generally only 56px tall when collapsed.
|
||||
The bottom navbar position remains correct (72px down). */
|
||||
#bottomNavbar {
|
||||
top: calc(var(--navbar-height) + var(--navbar-gap));
|
||||
}
|
||||
|
||||
/* Main content area needs less margin on mobile since the sidebar isn't active
|
||||
and the navs are collapsed by default. */
|
||||
.main-content-area {
|
||||
/* Reduced margin-top for smaller screens */
|
||||
margin-top: calc(var(--sticky-navbar-total-height) / 2);
|
||||
}
|
||||
|
||||
/* Mobile Fixed Footer Bar for Application */
|
||||
.mobile-fixed-apply-bar {
|
||||
position: fixed;
|
||||
bottom: 0;
|
||||
@ -47,9 +112,9 @@
|
||||
right: 0;
|
||||
width: 100%;
|
||||
padding: 15px;
|
||||
background-color: var(--light-bg); /* Use a light background */
|
||||
background-color: var(--light-bg);
|
||||
border-top: 1px solid #ddd;
|
||||
z-index: 1000; /* Ensure it stays above everything */
|
||||
z-index: 1000;
|
||||
box-shadow: 0 -4px 10px rgba(0, 0, 0, 0.08);
|
||||
}
|
||||
|
||||
@ -58,173 +123,133 @@
|
||||
padding-bottom: 90px;
|
||||
}
|
||||
|
||||
/* Adjust header font size for small screens */
|
||||
.card-header h2 {
|
||||
font-size: 1.25rem !important;
|
||||
}
|
||||
|
||||
/* Change job overview grid to single column on small phones */
|
||||
.row-cols-md-2 {
|
||||
--bs-gutter-x: 1.5rem;
|
||||
--bs-gutter-y: 1rem;
|
||||
}
|
||||
/* Fix job overview grid responsiveness (ensures 1 column) */
|
||||
.row-cols-md-2 > .col {
|
||||
flex: 0 0 100%; /* force to 1 column */
|
||||
flex: 0 0 100%;
|
||||
max-width: 100%;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
{% endblock %}
|
||||
|
||||
{% block content %}
|
||||
<div class="row mb-5">
|
||||
|
||||
<div class="col-lg-4 order-lg-2 order-1 d-none d-lg-block">
|
||||
<div class="card shadow-sm sticky-top" style="top: 90px;">
|
||||
<div class="card-header bg-kaauh-teal-dark text-white">
|
||||
<h5 class="mb-0"><i class="fas fa-file-signature me-2"></i>Ready to Apply?</h5>
|
||||
</div>
|
||||
<div class="card-body text-center">
|
||||
<p class="text-muted">Review the job details, then apply below.</p>
|
||||
|
||||
{% if job.form_template %}
|
||||
<a href="{% url 'form_wizard' job.form_template.pk %}" class="btn btn-main-action btn-lg w-100">
|
||||
<i class="fas fa-paper-plane me-2"></i> Apply for this Position
|
||||
</a>
|
||||
{% endif %}
|
||||
|
||||
{% comment %} <p class="text-muted mt-3 mb-0">
|
||||
<small>Application ID: **{{ job.pk }}**</small>
|
||||
</p> {% endcomment %}
|
||||
</div>
|
||||
</head>
|
||||
<body>
|
||||
|
||||
<nav id="topNavbar" class="navbar navbar-expand-lg sticky-top" style="background-color: white; z-index: 1030;">
|
||||
<div class="container-fluid">
|
||||
<a class="navbar-brand text-white fw-bold" href="/">
|
||||
<img src="{% static 'image/kaauh.jpeg' %}" alt="{% translate 'KAAUH IMAGE' %}" style="height: 50px; margin-right: 10px;">
|
||||
</a>
|
||||
<button class="navbar-toggler" type="button" data-bs-toggle="collapse" data-bs-target="#navbarNav"
|
||||
aria-controls="navbarNav" aria-expanded="false" aria-label="Toggle navigation">
|
||||
<span class="navbar-toggler-icon"></span>
|
||||
</button>
|
||||
<div class="collapse navbar-collapse" id="navbarNav">
|
||||
<ul class="navbar-nav ms-auto">
|
||||
|
||||
<li class="nav-item">
|
||||
<a class="nav-link text-secondary" href="/applications/">{% translate "Applications" %}</a>
|
||||
</li>
|
||||
<li class="nav-item">
|
||||
<a class="nav-link text-secondary" href="/profile/">{% translate "Profile" %}</a>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="col-lg-8 order-lg-1 order-2">
|
||||
<div class="card shadow-sm">
|
||||
<div class="card-header bg-kaauh-teal-dark text-white d-flex justify-content-between align-items-center">
|
||||
<h2 class="h3 mb-0 fw-bold">{{ job.title }}</h2>
|
||||
|
||||
{% with status_class=job.status|lower %}
|
||||
<span class="badge
|
||||
{% if status_class == 'open' %}bg-success
|
||||
{% elif status_class == 'closed' %}bg-danger
|
||||
{% elif status_class == 'draft' %}bg-secondary
|
||||
{% else %}bg-primary
|
||||
{% endif %}
|
||||
status-badge fw-bold p-2">
|
||||
{{ job.get_status_display }}
|
||||
</span>
|
||||
{% endwith %}
|
||||
</div>
|
||||
|
||||
<div class="card-body">
|
||||
|
||||
<h4 class="mb-3" style="color: var(--kaauh-teal-dark);">Job Overview</h4>
|
||||
<div class="row row-cols-1 row-cols-md-2 g-3 mb-4">
|
||||
|
||||
{% if job.salary_range %}
|
||||
<div class="col">
|
||||
<i class="fas fa-money-bill-wave text-success me-2"></i>
|
||||
<strong>Salary:</strong>
|
||||
<span class="fw-bold text-success">{{ job.salary_range }}</span>
|
||||
</nav>
|
||||
|
||||
<nav id="bottomNavbar" class="navbar navbar-expand-lg sticky-top" style="background-color: var(--kaauh-teal); z-index: 1030;">
|
||||
<div class="container-fluid">
|
||||
<span class="navbar-text text-white fw-bold">{% translate "Job Overview" %}</span>
|
||||
</div>
|
||||
</nav>
|
||||
|
||||
<div class="container">
|
||||
<div class="row mb-5 mt-3 main-content-area">
|
||||
|
||||
<div class="col-lg-4 order-lg-2 order-1 d-none d-lg-block">
|
||||
<div class="card shadow-sm sticky-top" style="top: var(--sticky-navbar-total-height);">
|
||||
<div class="card-header bg-kaauh-teal-dark text-white">
|
||||
<h5 class="mb-0"><i class="fas fa-file-signature me-2"></i>Ready to Apply?</h5>
|
||||
</div>
|
||||
{% endif %}
|
||||
|
||||
<div class="col">
|
||||
<i class="fas fa-calendar-alt text-muted me-2"></i>
|
||||
<strong>Deadline:</strong>
|
||||
{% if job.application_deadline %}
|
||||
{{ job.application_deadline|date:"M d, Y" }}
|
||||
{% if job.is_expired %}
|
||||
<span class="badge bg-danger ms-2">EXPIRED</span>
|
||||
{% endif %}
|
||||
{% else %}
|
||||
<span class="text-muted">Not specified</span>
|
||||
<div class="card-body text-center">
|
||||
<p class="text-muted">Review the job details, then apply below.</p>
|
||||
|
||||
{% if job.form_template %}
|
||||
<a href="{% url 'form_wizard' job.form_template.pk %}" class="btn btn-main-action btn-lg w-100">
|
||||
<i class="fas fa-paper-plane me-2"></i> Apply for this Position
|
||||
</a>
|
||||
{% endif %}
|
||||
</div>
|
||||
|
||||
<div class="col">
|
||||
<i class="fas fa-briefcase text-muted me-2"></i>
|
||||
<strong>Job Type:</strong> {{ job.get_job_type_display }}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="col-lg-8 order-lg-1 order-2">
|
||||
<div class="card shadow-sm">
|
||||
<div class="card-header bg-kaauh-teal-dark text-white d-flex justify-content-between align-items-center">
|
||||
<h2 class="h3 mb-0 fw-bold">{{ job.title }}</h2>
|
||||
|
||||
{% comment %} {% with status_class=job.status|lower %}
|
||||
<span class="badge
|
||||
{% if status_class == 'open' %}bg-success
|
||||
{% elif status_class == 'closed' %}bg-danger
|
||||
{% elif status_class == 'draft' %}bg-secondary
|
||||
{% else %}bg-primary
|
||||
{% endif %}
|
||||
status-badge fw-bold p-2">
|
||||
{{ job.get_status_display }}
|
||||
</span>
|
||||
{% endwith %} {% endcomment %}
|
||||
</div>
|
||||
|
||||
<div class="col">
|
||||
<i class="fas fa-map-marker-alt text-muted me-2"></i>
|
||||
<strong>Location:</strong> {{ job.get_location_display }}
|
||||
</div>
|
||||
|
||||
<div class="col">
|
||||
<i class="fas fa-building text-muted me-2"></i>
|
||||
<strong>Department:</strong> {{ job.department|default:"Not specified" }}
|
||||
</div>
|
||||
|
||||
<div class="col">
|
||||
<i class="fas fa-hashtag text-muted me-2"></i>
|
||||
<strong>JOB ID:</strong> {{ job.internal_job_id|default:"N/A" }}
|
||||
</div>
|
||||
|
||||
<div class="col">
|
||||
<i class="fas fa-desktop text-muted me-2"></i>
|
||||
<strong>Workplace:</strong> {{ job.get_workplace_type_display }}
|
||||
</div>
|
||||
|
||||
<div class="col">
|
||||
<i class="fas fa-user-tie text-muted me-2"></i>
|
||||
<strong>Created By:</strong> {{ job.created_by|default:"N/A" }}
|
||||
|
||||
<div class="card-body">
|
||||
|
||||
<h4 class="mb-3" style="color: var(--kaauh-teal-dark);">Job Overview</h4>
|
||||
<div class="row row-cols-1 row-cols-md-2 g-3 mb-4">
|
||||
{% if job.salary_range %}
|
||||
<div class="col">
|
||||
<i class="fas fa-money-bill-wave text-success me-2"></i>
|
||||
<strong>Salary:</strong>
|
||||
<span class="fw-bold text-success">{{ job.salary_range }}</span>
|
||||
</div>
|
||||
{% endif %}
|
||||
|
||||
<div class="col">
|
||||
<i class="fas fa-calendar-alt text-muted me-2"></i>
|
||||
<strong>Deadline:</strong>
|
||||
{% if job.application_deadline %}
|
||||
{{ job.application_deadline|date:"M d, Y" }}
|
||||
{% if job.is_expired %}
|
||||
<span class="badge bg-danger ms-2">EXPIRED</span>
|
||||
{% endif %}
|
||||
{% else %}
|
||||
<span class="text-muted">Not specified</span>
|
||||
{% endif %}
|
||||
</div>
|
||||
|
||||
<div class="col"> <i class="fas fa-briefcase text-muted me-2"></i> <strong>Job Type:</strong> {{ job.get_job_type_display }} </div>
|
||||
<div class="col"> <i class="fas fa-map-marker-alt text-muted me-2"></i> <strong>Location:</strong> {{ job.get_location_display }} </div>
|
||||
<div class="col"> <i class="fas fa-building text-muted me-2"></i> <strong>Department:</strong> {{ job.department|default:"Not specified" }} </div>
|
||||
<div class="col"> <i class="fas fa-hashtag text-muted me-2"></i> <strong>JOB ID:</strong> {{ job.internal_job_id|default:"N/A" }} </div>
|
||||
<div class="col"> <i class="fas fa-desktop text-muted me-2"></i> <strong>Workplace:</strong> {{ job.get_workplace_type_display }} </div>
|
||||
{% comment %} <div class="col"> <i class="fas fa-user-tie text-muted me-2"></i> <strong>Created By:</strong> {{ job.created_by|default:"N/A" }} </div> {% endcomment %}
|
||||
</div>
|
||||
|
||||
{% if job.description %}<hr class="my-4"><div class="mb-4"><h5 class="fw-bold" style="color: var(--kaauh-teal-dark);"><i class="fas fa-info-circle me-2"></i>Job Description</h5><div class="text-secondary">{{ job.description|linebreaks }}</div></div>{% endif %}
|
||||
{% if job.qualifications %}<hr class="my-4"><div class="mb-4"><h5 class="fw-bold" style="color: var(--kaauh-teal-dark);"><i class="fas fa-graduation-cap me-2"></i>Qualifications</h5><div class="text-secondary">{{ job.qualifications|linebreaks }}</div></div>{% endif %}
|
||||
{% if job.benefits %}<hr class="my-4"><div class="mb-4"><h5 class="fw-bold" style="color: var(--kaauh-teal-dark);"><i class="fas fa-hand-holding-usd me-2"></i>Benefits</h5><div class="text-secondary">{{ job.benefits|linebreaks }}</div></div>{% endif %}
|
||||
{% if job.application_instructions %}<hr class="my-4"><div class="mb-4"><h5 class="fw-bold" style="color: var(--kaauh-teal-dark);"><i class="fas fa-file-alt me-2"></i>Application Instructions</h5><div class="text-secondary">{{ job.application_instructions|linebreaks }}</div></div>{% endif %}
|
||||
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{% if job.description %}
|
||||
<hr class="my-4">
|
||||
<div class="mb-4">
|
||||
<h5 class="fw-bold" style="color: var(--kaauh-teal-dark);">
|
||||
<i class="fas fa-info-circle me-2"></i>Job Description
|
||||
</h5>
|
||||
<div class="text-secondary">{{ job.description|linebreaks }}</div>
|
||||
</div>
|
||||
{% endif %}
|
||||
|
||||
{% if job.qualifications %}
|
||||
<hr class="my-4">
|
||||
<div class="mb-4">
|
||||
<h5 class="fw-bold" style="color: var(--kaauh-teal-dark);">
|
||||
<i class="fas fa-graduation-cap me-2"></i>Qualifications
|
||||
</h5>
|
||||
<div class="text-secondary">{{ job.qualifications|linebreaks }}</div>
|
||||
</div>
|
||||
{% endif %}
|
||||
|
||||
{% if job.benefits %}
|
||||
<hr class="my-4">
|
||||
<div class="mb-4">
|
||||
<h5 class="fw-bold" style="color: var(--kaauh-teal-dark);">
|
||||
<i class="fas fa-hand-holding-usd me-2"></i>Benefits
|
||||
</h5>
|
||||
<div class="text-secondary">{{ job.benefits|linebreaks }}</div>
|
||||
</div>
|
||||
{% endif %}
|
||||
|
||||
{% if job.application_instructions %}
|
||||
<hr class="my-4">
|
||||
<div class="mb-4">
|
||||
<h5 class="fw-bold" style="color: var(--kaauh-teal-dark);">
|
||||
<i class="fas fa-file-alt me-2"></i>Application Instructions
|
||||
</h5>
|
||||
<div class="text-secondary">{{ job.application_instructions|linebreaks }}</div>
|
||||
</div>
|
||||
{% endif %}
|
||||
|
||||
</div>
|
||||
</div>
|
||||
</div> <div class="mobile-fixed-apply-bar d-lg-none">
|
||||
{% if job.form_template %}
|
||||
<a href="{% url 'form_wizard' job.form_template.pk %}" class="btn btn-main-action btn-lg w-100">
|
||||
<i class="fas fa-paper-plane me-2"></i> Apply for this Position
|
||||
</a>
|
||||
{% endif %}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="mobile-fixed-apply-bar d-lg-none">
|
||||
{% if job.form_template %}
|
||||
<a href="{% url 'form_wizard' job.form_template.pk %}" class="btn btn-main-action btn-lg w-100">
|
||||
<i class="fas fa-paper-plane me-2"></i> Apply for this Position
|
||||
</a>
|
||||
{% endif %}
|
||||
</div>
|
||||
{% endblock %}
|
||||
<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.3.0/dist/js/bootstrap.bundle.min.js"></script>
|
||||
</body>
|
||||
</html>
|
||||
@ -1,8 +1,7 @@
|
||||
|
||||
{% extends "base.html" %}
|
||||
{% load static %}
|
||||
{% load static i18n %}
|
||||
|
||||
{% block title %}Recruitment Dashboard - {{ block.super }}{% endblock %}
|
||||
{% block title %}{% trans "Recruitment Dashboard" %} - {{ block.super }}{% endblock %}
|
||||
|
||||
{% block customCSS %}
|
||||
<style>
|
||||
@ -88,56 +87,56 @@
|
||||
{% block content %}
|
||||
<div class="container-fluid py-4">
|
||||
|
||||
<h1 class="mb-4" style="color: var(--kaauh-teal-dark); font-weight: 700;">Recruitment Overview 🚀</h1>
|
||||
<h1 class="mb-4" style="color: var(--kaauh-teal-dark); font-weight: 700;">{% trans "Recruitment Overview" %} 🚀</h1>
|
||||
|
||||
<div class="stats">
|
||||
|
||||
<div class="card">
|
||||
<div class="card-header">
|
||||
<h3><i class="fas fa-briefcase stat-icon"></i> Total Jobs</h3>
|
||||
<h3><i class="fas fa-briefcase stat-icon"></i> {% trans "Total Jobs" %}</h3>
|
||||
</div>
|
||||
<div class="stat-value">{{ total_jobs }}</div>
|
||||
<div class="stat-caption">Active & Drafted Positions</div>
|
||||
<div class="stat-caption">{% trans "Active & Drafted Positions" %}</div>
|
||||
</div>
|
||||
|
||||
<div class="card">
|
||||
<div class="card-header">
|
||||
<h3><i class="fas fa-users stat-icon"></i> Total Candidates</h3>
|
||||
<h3><i class="fas fa-users stat-icon"></i> {% trans "Total Candidates" %}</h3>
|
||||
</div>
|
||||
<div class="stat-value">{{ total_candidates }}</div>
|
||||
<div class="stat-caption">All Profiles in ATS</div>
|
||||
<div class="stat-caption">{% trans "All Profiles in ATS" %}</div>
|
||||
</div>
|
||||
|
||||
<div class="card">
|
||||
<div class="card-header">
|
||||
<h3><i class="fas fa-chart-line stat-icon"></i> Avg. Apps per Job</h3>
|
||||
<h3><i class="fas fa-chart-line stat-icon"></i> {% trans "Avg. Apps per Job" %}</h3>
|
||||
</div>
|
||||
<div class="stat-value">{{ average_applications|floatformat:1 }}</div>
|
||||
<div class="stat-caption">Key Efficiency Metric</div>
|
||||
<div class="stat-caption">{% trans "Key Efficiency Metric" %}</div>
|
||||
</div>
|
||||
|
||||
<div class="card">
|
||||
<div class="card-header">
|
||||
<h3><i class="fas fa-arrow-alt-circle-up stat-icon" style="color: var(--color-success);"></i> Active Listings</h3>
|
||||
<h3><i class="fas fa-arrow-alt-circle-up stat-icon" style="color: var(--color-success);"></i> {% trans "Active Listings" %}</h3>
|
||||
</div>
|
||||
<div class="stat-value">22</div>
|
||||
<div class="stat-caption">Jobs currently open for application</div>
|
||||
<div class="stat-caption">{% trans "Jobs currently open for application" %}</div>
|
||||
</div>
|
||||
|
||||
<div class="card">
|
||||
<div class="card-header">
|
||||
<h3><i class="fas fa-clock stat-icon" style="color: var(--color-info);"></i> Time to Hire</h3>
|
||||
<h3><i class="fas fa-clock stat-icon" style="color: var(--color-info);"></i> {% trans "Time to Hire" %}</h3>
|
||||
</div>
|
||||
<div class="stat-value">35d</div>
|
||||
<div class="stat-caption">Average days from apply to offer</div>
|
||||
<div class="stat-caption">{% trans "Average days from apply to offer" %}</div>
|
||||
</div>
|
||||
|
||||
<div class="card">
|
||||
<div class="card-header">
|
||||
<h3><i class="fas fa-handshake stat-icon" style="color: var(--kaauh-teal-light);"></i> Offer Acceptance</h3>
|
||||
<h3><i class="fas fa-handshake stat-icon" style="color: var(--kaauh-teal-light);"></i> {% trans "Offer Acceptance" %}</h3>
|
||||
</div>
|
||||
<div class="stat-value">85%</div>
|
||||
<div class="stat-caption">Successful offers vs. Total offers</div>
|
||||
<div class="stat-caption">{% trans "Successful offers vs. Total offers" %}</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@ -145,7 +144,7 @@
|
||||
<div class="card-header">
|
||||
<h2 class="d-flex align-items-center mb-0">
|
||||
<i class="fas fa-chart-bar stat-icon"></i>
|
||||
Applications Volume by Job
|
||||
{% trans "Applications Volume by Job" %}
|
||||
</h2>
|
||||
</div>
|
||||
<div class="chart-container">
|
||||
@ -156,13 +155,17 @@
|
||||
|
||||
<script src="https://cdn.jsdelivr.net/npm/chart.js"></script>
|
||||
<script>
|
||||
|
||||
// if the strings are visible to the user. 'Applications' is used for Chart.js here.
|
||||
const ctx = document.getElementById('applicationsChart').getContext('2d');
|
||||
const chart = new Chart(ctx, {
|
||||
type: 'bar',
|
||||
data: {
|
||||
labels: {{ job_titles|safe }},
|
||||
datasets: [{
|
||||
label: 'Applications',
|
||||
|
||||
// For simplicity, we are leaving it as-is for now, assuming the context provides the translated labels.
|
||||
label: '{% trans "Applications" %}',
|
||||
data: {{ job_app_counts|safe }},
|
||||
backgroundColor: ' #00636e', // Green theme
|
||||
borderColor: ' #004a53',
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user