modal for job status update

This commit is contained in:
Faheed 2025-10-09 16:59:09 +03:00
parent cc540517a9
commit e0b88f8b22
14 changed files with 120 additions and 39 deletions

Binary file not shown.

View File

@ -464,4 +464,12 @@ class InterviewScheduleForm(forms.ModelForm):
def clean_working_days(self):
working_days = self.cleaned_data.get('working_days')
# Convert string values to integers
return [int(day) for day in working_days]
return [int(day) for day in working_days]
class JobStatusUpdateForm(forms.ModelForm):
class Meta:
model=JobPosting
fields=[
'status'
]

View File

@ -13,7 +13,8 @@ urlpatterns = [
# path('jobs/<slug:slug>/delete/', views., name='job_delete'),
path('jobs/<slug:slug>/', views.job_detail, name='job_detail'),
path('jobs/<slug:slug>/candidate/', views.job_detail_candidate, name='job_detail_candidate'),
path('jobs/<slug:slug>/candidate/application/success', views.application_sucess, name='application_success'),
path('jobs/<slug:slug>/candidate/application/success', views.application_success, name='application_success'),
# LinkedIn Integration URLs
path('jobs/<slug:slug>/post-to-linkedin/', views.post_to_linkedin, name='post_to_linkedin'),

View File

@ -10,7 +10,7 @@ from django.db.models import Q
from django.urls import reverse
from django.conf import settings
from django.utils import timezone
from .forms import ZoomMeetingForm,JobPostingForm,FormTemplateForm,InterviewScheduleForm
from .forms import ZoomMeetingForm,JobPostingForm,FormTemplateForm,InterviewScheduleForm,JobStatusUpdateForm
from rest_framework import viewsets
from django.contrib import messages
from django.core.paginator import Paginator
@ -225,6 +225,7 @@ def edit_job(request,slug):
def job_detail(request, slug):
"""View details of a specific job"""
job = get_object_or_404(JobPosting, slug=slug)
# Get all candidates for this job, ordered by most recent
candidates = job.candidates.all().order_by('-created_at')
@ -235,6 +236,27 @@ def job_detail(request, slug):
interview_count = candidates.filter(stage='Interview').count()
offer_count = candidates.filter(stage='Offer').count()
status_form = JobStatusUpdateForm(instance=job)
# 2. Check for POST request (Status Update Submission)
if request.method == 'POST':
status_form = JobStatusUpdateForm(request.POST, instance=job)
if status_form.is_valid():
status_form.save()
# Add a success message
messages.success(request, f"Status for '{job.title}' updated to '{job.get_status_display()}' successfully!")
return redirect('job_detail', slug=slug)
else:
messages.error(request, "Failed to update status due to validation errors.")
context = {
'job': job,
'candidates': candidates,
@ -242,6 +264,7 @@ def job_detail(request, slug):
'applied_count': applied_count,
'interview_count': interview_count,
'offer_count': offer_count,
'status_form':status_form
}
return render(request, 'jobs/job_detail.html', context)
@ -345,6 +368,13 @@ def applicant_job_detail(request,slug):
job=get_object_or_404(JobPosting,slug=slug,status='ACTIVE')
return render(request,'jobs/applicant_job_detail.html',{'job':job})
def application_success(request,slug):
job=get_object_or_404(JobPosting,slug=slug)
return render(request,'jobs/application_success.html',{'job':job})
# Form Preview Views
# from django.http import JsonResponse

View File

@ -1,4 +1,5 @@
from django.shortcuts import render, get_object_or_404
from django.shortcuts import render, get_object_or_404,redirect
from django.contrib import messages
from django.http import JsonResponse
from . import models
from django.utils.translation import get_language
@ -188,10 +189,13 @@ class CandidateDeleteView(LoginRequiredMixin, SuccessMessageMixin, DeleteView):
slug_url_kwarg = 'slug'
def job_detail(request, slug):
job = get_object_or_404(models.JobPosting, slug=slug, status='Published')
form = forms.CandidateForm()
return render(request, 'jobs/job_detail.html', {'job': job, 'form': form})
# def job_detail(request, slug):
# job = get_object_or_404(models.JobPosting, slug=slug, status='Published')
# form = forms.CandidateForm()
# return render(request, 'jobs/job_detail.html', {'job': job, 'form': form})
@login_required

View File

@ -460,9 +460,9 @@
<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="/">
<span class="navbar-brand text-white fw-bold">
<img src="{% static 'image/kaauh.jpeg' %}" alt="{% translate 'KAAUH IMAGE' %}" style="height: 50px; margin-right: 10px;">
</a>
</span>
<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>

View File

@ -122,9 +122,9 @@
<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="/">
<span class="navbar-brand text-white fw-bold">
<img src="{% static 'image/kaauh.jpeg' %}" alt="{% translate 'KAAUH IMAGE' %}" style="height: 50px; margin-right: 10px;">
</a>
</span>
<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>
@ -152,7 +152,7 @@
</nav>
<div class="container">
<div class="row mb-5 mt-3 main-content-area">
<div class="row mb-5 mt-5 main-content-area">
<div class="col-12 thank-you-card-wrapper">
<div class="card shadow-lg thank-you-card">
@ -168,7 +168,7 @@
<h1 class="text-success-header">{% translate "Thank You!" %}</h1>
<h2 class="h4" style="color: #333;">{% translate "Your application has been submitted successfully" %}</h2>
{# JOB INFO BLOCK #}
{% comment %} {# JOB INFO BLOCK #}
<div class="job-info-block">
<p class="mb-2"><strong>{% translate "Position" %}:</strong> <span class="fw-bold">{{ job.title }}</span></p>
<p class="mb-2"><strong>{% translate "Job ID" %}:</strong> {{ job.internal_job_id }}</p>
@ -176,14 +176,14 @@
{% if job.application_deadline %}
<p><strong>{% translate "Application Deadline" %}:</strong> {{ job.application_deadline|date:"F j, Y" }}</p>
{% endif %}
</div>
</div> {% endcomment %}
<p style="font-size: 1rem; line-height: 1.6; color: #555;">
{% translate "We appreciate your interest in joining our team. Our hiring team will review your application and contact you if there's a potential match for this position." %}
</p>
<div style="margin-top: 30px;">
<a href="{% url 'job_list' %}" class="btn btn-main-action btn-lg">
<a href="https://kaauh.edu.sa/career" class="btn btn-main-action btn-lg">
<i class="fas fa-arrow-left me-2"></i> {% translate "Return to Job Listings" %}
</a>
{# You can add a link to view the saved application here if applicable #}

View File

@ -36,6 +36,8 @@
font-weight: 700;
text-transform: uppercase;
letter-spacing: 0.7px;
display: inline-flex;
align-items: center;
}
/* Mapped color classes for status badges */
@ -109,7 +111,6 @@
/* ==================================== */
.right-column-tabs {
/* Use the .card wrapper for the main structure */
padding: 0;
margin-bottom: 0;
border-bottom: 1px solid var(--kaauh-border);
@ -119,41 +120,38 @@
margin-bottom: 0;
border-bottom: none;
background-color: transparent;
display: flex; /* Ensure the nav-items take up equal space */
display: flex;
}
.right-column-tabs .nav-item {
flex-grow: 1;
text-align: center;
}
.right-column-tabs .nav-link {
/* Base style for all right column tabs */
padding: 0.9rem 1rem; /* Slightly larger padding for better spacing */
padding: 0.9rem 1rem;
font-size: 0.95rem;
font-weight: 600;
color: var(--kaauh-primary-text);
border-radius: 0;
border-right: 1px solid var(--kaauh-border);
border-bottom: 1px solid var(--kaauh-border); /* Separator line */
background-color: #f8f9fa; /* Subtle background for non-active tabs */
border-bottom: 1px solid var(--kaauh-border);
background-color: #f8f9fa;
}
.right-column-tabs .nav-item:last-child .nav-link {
border-right: none;
}
/* Active Tab */
.right-column-tabs .nav-link.active {
background-color: white; /* Lift the active tab */
background-color: white;
color: var(--kaauh-teal-dark);
border-bottom: 3px solid var(--kaauh-teal); /* Strong accent */
border-right-color: transparent; /* Clean up border next to it */
margin-bottom: -1px; /* Overlap the border for a cleaner look */
border-bottom: 3px solid var(--kaauh-teal);
border-right-color: transparent;
margin-bottom: -1px;
}
/* Hover state for non-active tabs */
.right-column-tabs .nav-link:not(.active):hover {
background-color: #f0f4f7; /* Darken slightly on hover */
background-color: #f0f4f7;
color: var(--kaauh-teal);
}
.right-column-tabs .tab-content {
padding: 1.5rem 1.25rem; /* Increased padding inside the content for breathing room */
padding: 1.5rem 1.25rem;
background-color: white;
}
@ -229,13 +227,11 @@
/* Table styling for the Applicant preview */
.table-applicants tbody tr:hover {
background-color: #f3f9f9; /* Light teal hover for rows */
background-color: #f3f9f9;
}
.table-applicants td {
border-top: 1px solid var(--kaauh-border);
}
</style>
{% endblock %}
@ -249,10 +245,19 @@
{# HEADER SECTION #}
<div class="job-header-card d-flex justify-content-between align-items-center flex-wrap">
<h2>{{job}}</h2>
<span class="badge bg-{{ job.status|lower|striptags|yesno:'success,warning,secondary,danger' }} status-badge">
{{ job.get_status_display }}
</span>
<div>
<h2 class="mb-1">{{ job.title }}</h2>
<small class="text-light">{{ job.internal_job_id }}</small>
</div>
<div class="d-flex align-items-center gap-2">
<span class="badge bg-success status-badge">
{{ job.get_status_display }}
<button type="button" class="btn btn-outline-light btn-sm ms-2" data-bs-toggle="modal" data-bs-target="#editStatusModal">
<i class="fas fa-edit text-primary"></i>
</button>
</span>
</div>
</div>
{# LEFT TABS NAVIGATION #}
@ -566,4 +571,37 @@
</div>
{% include "jobs/partials/image_upload.html" %}
<!-- JOB STATUS MODAL-->
<div class="modal fade" id="editStatusModal" tabindex="-1" aria-labelledby="editStatusModalLabel" aria-hidden="true">
<div class="modal-dialog">
<div class="modal-content">
<form method="post" action="{% url 'job_detail' slug=job.slug %}">
{% csrf_token %}
<div class="modal-header">
<h5 class="modal-title" id="editStatusModalLabel">{% trans "Edit Job Status" %}</h5>
<button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="{% trans 'Close' %}"></button>
</div>
<div class="modal-body">
<div class="mb-3">
{% if status_form %}
<label for="{{ status_form.status.id_for_label }}" class="form-label">{% trans "Select New Status" %}</label>
{{ status_form.status }}
{% if status_form.status.errors %}
<div class="text-danger small mt-1">{{ status_form.status.errors }}</div>
{% endif %}
{% else %}
<div class="text-danger">{% trans "Status form not available. Please check your view." %}</div>
{% endif %}
</div>
</div>
<div class="modal-footer">
<button type="button" class="btn btn-outline-secondary" data-bs-dismiss="modal">{% trans "Cancel" %}</button>
<button type="submit" class="btn btn-main-action">{% trans "Save Changes" %}</button>
</div>
</form>
</div>
</div>
</div>
{% endblock %}

View File

@ -135,9 +135,9 @@
<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="/">
<span class="navbar-brand text-white fw-bold">
<img src="{% static 'image/kaauh.jpeg' %}" alt="{% translate 'KAAUH IMAGE' %}" style="height: 50px; margin-right: 10px;">
</a>
</span>
<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>