new chnages
This commit is contained in:
parent
6fefee7f43
commit
9cd63d3897
Binary file not shown.
@ -155,19 +155,27 @@ DATABASES = {
|
||||
|
||||
|
||||
|
||||
# AUTH_PASSWORD_VALIDATORS = [
|
||||
# {
|
||||
# 'NAME': 'django.contrib.auth.password_validation.UserAttributeSimilarityValidator',
|
||||
# },
|
||||
# {
|
||||
# 'NAME': 'django.contrib.auth.password_validation.MinimumLengthValidator',
|
||||
# },
|
||||
# {
|
||||
# 'NAME': 'django.contrib.auth.password_validation.CommonPasswordValidator',
|
||||
# },
|
||||
# {
|
||||
# 'NAME': 'django.contrib.auth.password_validation.NumericPasswordValidator',
|
||||
# },
|
||||
# ]
|
||||
|
||||
# settings.py
|
||||
|
||||
AUTH_PASSWORD_VALIDATORS = [
|
||||
{
|
||||
'NAME': 'django.contrib.auth.password_validation.UserAttributeSimilarityValidator',
|
||||
},
|
||||
{
|
||||
'NAME': 'django.contrib.auth.password_validation.MinimumLengthValidator',
|
||||
},
|
||||
{
|
||||
'NAME': 'django.contrib.auth.password_validation.CommonPasswordValidator',
|
||||
},
|
||||
{
|
||||
'NAME': 'django.contrib.auth.password_validation.NumericPasswordValidator',
|
||||
},
|
||||
]
|
||||
|
||||
|
||||
|
||||
Binary file not shown.
Binary file not shown.
Binary file not shown.
@ -1,3 +1,7 @@
|
||||
from pathlib import Path
|
||||
from rich import print
|
||||
from django.conf import settings
|
||||
import os
|
||||
import uuid
|
||||
import random
|
||||
from datetime import date, timedelta
|
||||
@ -39,9 +43,9 @@ class Command(BaseCommand):
|
||||
self.stdout.write(f"Preparing to create {jobs_count} jobs and {candidates_count} candidates.")
|
||||
|
||||
# 1. Clear existing data (Optional, but useful for clean seeding)
|
||||
Candidate.objects.all().delete()
|
||||
JobPosting.objects.all().delete()
|
||||
Source.objects.all().delete()
|
||||
FormTemplate.objects.all().delete()
|
||||
Candidate.objects.all().delete()
|
||||
self.stdout.write(self.style.WARNING("Existing JobPostings and Candidates cleared."))
|
||||
|
||||
# 2. Create Foreign Key dependency: Source
|
||||
@ -75,7 +79,6 @@ class Command(BaseCommand):
|
||||
# Random dates
|
||||
start_date = fake.date_object()
|
||||
deadline_date = start_date + timedelta(days=random.randint(14, 60))
|
||||
joining_date = deadline_date + timedelta(days=random.randint(30, 90))
|
||||
|
||||
# Use Faker's HTML generation for CKEditor5 fields
|
||||
description_html = f"<h1>{title} Role</h1>" + "".join(f"<p>{fake.paragraph(nb_sentences=3, variable_nb_sentences=True)}</p>" for _ in range(3))
|
||||
@ -88,26 +91,11 @@ class Command(BaseCommand):
|
||||
"department": department,
|
||||
"job_type": job_type,
|
||||
"workplace_type": random.choice(WORKPLACE_TYPES),
|
||||
"location_city": fake.city(),
|
||||
"location_state": fake.state_abbr(),
|
||||
"location_country": "Saudia Arabia",
|
||||
"description": description_html,
|
||||
"qualifications": qualifications_html,
|
||||
"salary_range": salary_range,
|
||||
"benefits": benefits_html,
|
||||
"application_url": fake.url(),
|
||||
"application_start_date": start_date,
|
||||
"application_deadline": deadline_date,
|
||||
"application_instructions": instructions_html,
|
||||
"created_by": "Faker Script",
|
||||
"status": random.choice(STATUS_CHOICES),
|
||||
"hash_tags": f"#{department.lower().replace(' ', '')},#jobopening,#{fake.word()}",
|
||||
"position_number": f"{department[:3].upper()}{random.randint(100, 999)}",
|
||||
"reporting_to": random.choice(REPORTING_TO),
|
||||
"joining_date": joining_date,
|
||||
"open_positions": random.randint(1, 5),
|
||||
"source": default_source,
|
||||
"published_at": timezone.now() if random.random() < 0.7 else None,
|
||||
}
|
||||
|
||||
job = JobPosting.objects.create(
|
||||
@ -123,28 +111,33 @@ class Command(BaseCommand):
|
||||
for i in range(candidates_count):
|
||||
# Link candidate to a random job
|
||||
target_job = random.choice(created_jobs)
|
||||
|
||||
print(target_job)
|
||||
first_name = fake.first_name()
|
||||
last_name = fake.last_name()
|
||||
path = os.path.join(settings.BASE_DIR,'media/resumes/')
|
||||
|
||||
# path = Path('media/resumes/') # <-- CORRECT
|
||||
file = random.choice(os.listdir(path))
|
||||
print(file)
|
||||
# file = os.path.abspath(file)
|
||||
candidate_data = {
|
||||
"first_name": first_name,
|
||||
"last_name": last_name,
|
||||
# Create a plausible email based on name
|
||||
"email": f"{first_name.lower()}.{last_name.lower()}@{fake.domain_name()}",
|
||||
"phone": fake.phone_number(),
|
||||
"phone": "0566987458",
|
||||
"address": fake.address(),
|
||||
# Placeholder resume path
|
||||
'match_score': random.randint(0, 100),
|
||||
"resume": f"resumes/{last_name.lower()}_{target_job.internal_job_id}_{fake.file_name(extension='pdf')}",
|
||||
"resume": 'resumes/'+ file,
|
||||
"job": target_job,
|
||||
}
|
||||
print(candidate_data)
|
||||
|
||||
Candidate.objects.create(**candidate_data)
|
||||
self.stdout.write(self.style.NOTICE(
|
||||
f'Created Candidate {i+1}/{candidates_count}: {first_name} for {target_job.title[:30]}...'
|
||||
))
|
||||
|
||||
print("done")
|
||||
else:
|
||||
self.stdout.write(self.style.WARNING("No jobs created, skipping candidate generation."))
|
||||
|
||||
|
||||
@ -1,4 +1,4 @@
|
||||
# Generated by Django 5.2.7 on 2025-10-22 16:33
|
||||
# Generated by Django 5.2.7 on 2025-10-23 14:08
|
||||
|
||||
import django.core.validators
|
||||
import django.db.models.deletion
|
||||
@ -221,6 +221,7 @@ class Migration(migrations.Migration):
|
||||
migrations.CreateModel(
|
||||
name='JobPosting',
|
||||
fields=[
|
||||
('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
|
||||
('created_at', models.DateTimeField(auto_now_add=True, verbose_name='Created at')),
|
||||
('updated_at', models.DateTimeField(auto_now=True, verbose_name='Updated at')),
|
||||
('slug', django_extensions.db.fields.RandomCharField(blank=True, editable=False, length=8, unique=True, verbose_name='Slug')),
|
||||
@ -238,7 +239,7 @@ class Migration(migrations.Migration):
|
||||
('application_url', models.URLField(blank=True, help_text='URL where candidates apply', null=True, validators=[django.core.validators.URLValidator()])),
|
||||
('application_deadline', models.DateField(db_index=True)),
|
||||
('application_instructions', django_ckeditor_5.fields.CKEditor5Field(blank=True, null=True)),
|
||||
('internal_job_id', models.CharField(editable=False, max_length=50, primary_key=True, serialize=False)),
|
||||
('internal_job_id', models.CharField(editable=False, max_length=50)),
|
||||
('created_by', models.CharField(blank=True, help_text='Name of person who created this job', max_length=100)),
|
||||
('status', models.CharField(choices=[('DRAFT', 'Draft'), ('ACTIVE', 'Active'), ('CLOSED', 'Closed'), ('CANCELLED', 'Cancelled'), ('ARCHIVED', 'Archived')], db_index=True, default='DRAFT', max_length=20)),
|
||||
('hash_tags', models.CharField(blank=True, help_text='Comma-separated hashtags for linkedin post like #hiring,#jobopening', max_length=200, validators=[recruitment.validators.validate_hash_tags])),
|
||||
|
||||
@ -92,7 +92,7 @@ class JobPosting(Base):
|
||||
)
|
||||
|
||||
# Internal Tracking
|
||||
internal_job_id = models.CharField(max_length=50, primary_key=True, editable=False)
|
||||
internal_job_id = models.CharField(max_length=50, editable=False)
|
||||
created_by = models.CharField(
|
||||
max_length=100, blank=True, help_text="Name of person who created this job"
|
||||
)
|
||||
@ -193,26 +193,29 @@ class JobPosting(Base):
|
||||
return self.source.name if self.source else "System"
|
||||
|
||||
def save(self, *args, **kwargs):
|
||||
# from django.db import transaction
|
||||
|
||||
# Generate unique internal job ID if not exists
|
||||
if not self.internal_job_id:
|
||||
prefix = "KAAUH"
|
||||
year = timezone.now().year
|
||||
# Get next sequential number
|
||||
last_job = (
|
||||
JobPosting.objects.filter(
|
||||
internal_job_id__startswith=f"{prefix}-{year}-"
|
||||
)
|
||||
.order_by("internal_job_id")
|
||||
.last()
|
||||
)
|
||||
# with transaction.atomic():
|
||||
# if not self.internal_job_id:
|
||||
# prefix = "KAAUH"
|
||||
# year = timezone.now().year
|
||||
# # Get next sequential number
|
||||
# last_job = (
|
||||
# JobPosting.objects.select_for_update().filter(
|
||||
# internal_job_id__startswith=f"{prefix}-{year}-"
|
||||
# )
|
||||
# .order_by("internal_job_id")
|
||||
# .last()
|
||||
# )
|
||||
|
||||
if last_job:
|
||||
last_num = int(last_job.internal_job_id.split("-")[-1])
|
||||
next_num = last_num + 1
|
||||
else:
|
||||
next_num = 1
|
||||
# if last_job:
|
||||
# last_num = int(last_job.internal_job_id.split("-")[-1])
|
||||
# next_num = last_num + 1
|
||||
# else:
|
||||
# next_num = 1
|
||||
|
||||
self.internal_job_id = f"{prefix}-{year}-{next_num:06d}"
|
||||
# self.internal_job_id = f"{prefix}-{year}-{next_num:06d}"
|
||||
|
||||
super().save(*args, **kwargs)
|
||||
|
||||
|
||||
@ -13,7 +13,7 @@ logger = logging.getLogger(__name__)
|
||||
@receiver(post_save, sender=JobPosting)
|
||||
def format_job(sender, instance, created, **kwargs):
|
||||
if created:
|
||||
FormTemplate.objects.create(job=instance, is_active=True, name=instance.title)
|
||||
# FormTemplate.objects.create(job=instance, is_active=False, name=instance.title)
|
||||
async_task(
|
||||
'recruitment.tasks.format_job_description',
|
||||
instance.pk,
|
||||
|
||||
@ -290,7 +290,7 @@ def handle_reume_parsing_and_scoring(pk):
|
||||
"strengths": "Brief summary of strengths",
|
||||
"weaknesses": "Brief summary of weaknesses",
|
||||
"years_of_experience": "Total years of experience (float, e.g., 6.5)",
|
||||
"criteria_checklist": {{ "Python": "Met", "AWS": "Not Mentioned"}},
|
||||
"criteria_checklist": List of job requirements if any {{ "Python": "Met", "AWS": "Not Met"}} only output the criteria_checklist in one of ('Met','Not Met') don't output any extra text,
|
||||
"category": "Most fitting professional field (e.g., Data Science), only output the category name and no other text example ('Software Development', 'correct') , ('Software Development and devops','wrong') ('Software Development / Backend Development','wrong')",
|
||||
"most_recent_job_title": "Candidate's most recent job title",
|
||||
"recommendation": "Detailed hiring recommendation narrative",
|
||||
|
||||
BIN
resumes/AltaCV_Template.pdf
Normal file
BIN
resumes/AltaCV_Template.pdf
Normal file
Binary file not shown.
Binary file not shown.
BIN
resumes/Balance Sheet.pdf
Normal file
BIN
resumes/Balance Sheet.pdf
Normal file
Binary file not shown.
BIN
resumes/Cash Flow Statement1.pdf
Normal file
BIN
resumes/Cash Flow Statement1.pdf
Normal file
Binary file not shown.
BIN
resumes/DA_2026_Syllabus.pdf
Normal file
BIN
resumes/DA_2026_Syllabus.pdf
Normal file
Binary file not shown.
237468
resumes/Django Documentation.pdf
Normal file
237468
resumes/Django Documentation.pdf
Normal file
File diff suppressed because one or more lines are too long
BIN
resumes/E-2025-0000000001_Lead 1 ssfsdf_2025-09-08.pdf
Normal file
BIN
resumes/E-2025-0000000001_Lead 1 ssfsdf_2025-09-08.pdf
Normal file
Binary file not shown.
BIN
resumes/Entry-Level-Developer-Resume-Template (2).docx
Normal file
BIN
resumes/Entry-Level-Developer-Resume-Template (2).docx
Normal file
Binary file not shown.
Binary file not shown.
Binary file not shown.
BIN
resumes/Faheed khan_CV-2.pdf
Normal file
BIN
resumes/Faheed khan_CV-2.pdf
Normal file
Binary file not shown.
BIN
resumes/FaheeedResume.docx
Normal file
BIN
resumes/FaheeedResume.docx
Normal file
Binary file not shown.
BIN
resumes/FaheeedResume.pdf
Normal file
BIN
resumes/FaheeedResume.pdf
Normal file
Binary file not shown.
BIN
resumes/Income Statement.pdf
Normal file
BIN
resumes/Income Statement.pdf
Normal file
Binary file not shown.
Binary file not shown.
BIN
resumes/Journal Entries1.pdf
Normal file
BIN
resumes/Journal Entries1.pdf
Normal file
Binary file not shown.
BIN
resumes/Journal Entries2.pdf
Normal file
BIN
resumes/Journal Entries2.pdf
Normal file
Binary file not shown.
BIN
resumes/LinkedIn Job Posting API Requirements.pdf
Normal file
BIN
resumes/LinkedIn Job Posting API Requirements.pdf
Normal file
Binary file not shown.
BIN
resumes/LinkedIn Job Posting API Requirements_new.pdf
Normal file
BIN
resumes/LinkedIn Job Posting API Requirements_new.pdf
Normal file
Binary file not shown.
BIN
resumes/Partner Application _ Hiring on LinkedIn.pdf
Normal file
BIN
resumes/Partner Application _ Hiring on LinkedIn.pdf
Normal file
Binary file not shown.
Binary file not shown.
BIN
resumes/Software Development Resume.docx
Normal file
BIN
resumes/Software Development Resume.docx
Normal file
Binary file not shown.
BIN
resumes/akash-agarwals-cv.pdf
Normal file
BIN
resumes/akash-agarwals-cv.pdf
Normal file
Binary file not shown.
BIN
resumes/cv-arles-bustamante.pdf
Normal file
BIN
resumes/cv-arles-bustamante.pdf
Normal file
Binary file not shown.
BIN
resumes/cv-for-freshers.pdf
Normal file
BIN
resumes/cv-for-freshers.pdf
Normal file
Binary file not shown.
BIN
resumes/cv-template.docx
Normal file
BIN
resumes/cv-template.docx
Normal file
Binary file not shown.
BIN
resumes/cv.pdf
Normal file
BIN
resumes/cv.pdf
Normal file
Binary file not shown.
BIN
resumes/deedy-resume-reversed.pdf
Normal file
BIN
resumes/deedy-resume-reversed.pdf
Normal file
Binary file not shown.
BIN
resumes/devanshu-sapras-cv.pdf
Normal file
BIN
resumes/devanshu-sapras-cv.pdf
Normal file
Binary file not shown.
BIN
resumes/django-readthedocs-io-en-5.2.x.pdf
Normal file
BIN
resumes/django-readthedocs-io-en-5.2.x.pdf
Normal file
Binary file not shown.
BIN
resumes/hassan-razas-cv.pdf
Normal file
BIN
resumes/hassan-razas-cv.pdf
Normal file
Binary file not shown.
BIN
resumes/ian-appelbaums-cv.pdf
Normal file
BIN
resumes/ian-appelbaums-cv.pdf
Normal file
Binary file not shown.
BIN
resumes/jitendra.pdf
Normal file
BIN
resumes/jitendra.pdf
Normal file
Binary file not shown.
BIN
resumes/jitendra_GSHo58l (1).pdf
Normal file
BIN
resumes/jitendra_GSHo58l (1).pdf
Normal file
Binary file not shown.
BIN
resumes/jitendra_GSHo58l.pdf
Normal file
BIN
resumes/jitendra_GSHo58l.pdf
Normal file
Binary file not shown.
BIN
resumes/jitendra_l1mgJJt.pdf
Normal file
BIN
resumes/jitendra_l1mgJJt.pdf
Normal file
Binary file not shown.
BIN
resumes/jitendra_phcOTgU.pdf
Normal file
BIN
resumes/jitendra_phcOTgU.pdf
Normal file
Binary file not shown.
BIN
resumes/jitendra_xhglvVN.pdf
Normal file
BIN
resumes/jitendra_xhglvVN.pdf
Normal file
Binary file not shown.
BIN
resumes/leonardo-lopez-cuevass-cv.pdf
Normal file
BIN
resumes/leonardo-lopez-cuevass-cv.pdf
Normal file
Binary file not shown.
BIN
resumes/npu-cv.pdf
Normal file
BIN
resumes/npu-cv.pdf
Normal file
Binary file not shown.
BIN
resumes/perrin-viviens-cv.pdf
Normal file
BIN
resumes/perrin-viviens-cv.pdf
Normal file
Binary file not shown.
BIN
resumes/recreating-business-insiders-cv-of-marissa-mayer.pdf
Normal file
BIN
resumes/recreating-business-insiders-cv-of-marissa-mayer.pdf
Normal file
Binary file not shown.
BIN
resumes/resume-of-yogesh-patil.pdf
Normal file
BIN
resumes/resume-of-yogesh-patil.pdf
Normal file
Binary file not shown.
BIN
resumes/resume_juanjosecarin.pdf
Normal file
BIN
resumes/resume_juanjosecarin.pdf
Normal file
Binary file not shown.
BIN
resumes/said-benaissas-cv.pdf
Normal file
BIN
resumes/said-benaissas-cv.pdf
Normal file
Binary file not shown.
BIN
resumes/two-column-cv-template-with-moderncv.pdf
Normal file
BIN
resumes/two-column-cv-template-with-moderncv.pdf
Normal file
Binary file not shown.
BIN
resumes/yuans-resume-template.pdf
Normal file
BIN
resumes/yuans-resume-template.pdf
Normal file
Binary file not shown.
@ -111,12 +111,31 @@
|
||||
|
||||
{# ------------------- ADD EMAIL FORM ------------------- #}
|
||||
<h5 class="fw-bold mb-3">{% translate "Add Email Address" %}</h5>
|
||||
<form method="post" action="{% url 'account_email' %}">
|
||||
<form method="post" action="{% url 'account_email' %}">
|
||||
{% csrf_token %}
|
||||
|
||||
{# 1. Explicitly render non-field errors first #}
|
||||
{% if form.non_field_errors %}
|
||||
<div class="alert alert-danger" role="alert">
|
||||
{% for error in form.non_field_errors %}
|
||||
{{ error }}
|
||||
{% endfor %}
|
||||
</div>
|
||||
{% endif %}
|
||||
|
||||
{# 2. Render the fields using crispy #}
|
||||
{{ form|crispy }}
|
||||
|
||||
{# 3. If there are any global errors (not common here, but safe to include) #}
|
||||
{% if messages %}
|
||||
{% for message in messages %}
|
||||
<div class="alert alert-{{ message.tags }} mt-3">{{ message }}</div>
|
||||
{% endfor %}
|
||||
{% endif %}
|
||||
|
||||
{# Teal/Dark Green button consistent with "Save Changes" #}
|
||||
<button class="btn btn-success mt-3" type="submit" style="background-color: #008080; border-color: #008080;">{% translate "Add Email" %}</button>
|
||||
</form>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@ -2,6 +2,8 @@
|
||||
{% load static %}
|
||||
{% autoescape off %}
|
||||
|
||||
{# Use the built-in context variable 'password_reset_url' that allauth provides. #}
|
||||
|
||||
<div style="font-family: Arial, sans-serif; line-height: 1.6; color: #333; max-width: 600px; margin: auto; border: 1px solid #ddd; border-radius: 8px; overflow: hidden;">
|
||||
|
||||
<div style="background-color: #00636e; padding: 20px; color: white; text-align: center;">
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
{% load static i18n %}
|
||||
<!DOCTYPE html>
|
||||
{% load crispy_forms_tags %} <!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
@ -82,52 +82,8 @@
|
||||
<form method="post" action=".">
|
||||
{% csrf_token %}
|
||||
|
||||
{# Non-Field Errors (General errors like tokens or passwords not matching) #}
|
||||
{% if form.non_field_errors %}
|
||||
<div class="alert alert-danger" role="alert">
|
||||
{% for error in form.non_field_errors %}
|
||||
{{ error }}
|
||||
{% endfor %}
|
||||
</div>
|
||||
{% endif %}
|
||||
|
||||
{# Password 1 Field #}
|
||||
<div class="mb-3">
|
||||
<label for="{{ form.password.id_for_label }}" class="form-label fw-semibold">{% trans "New Password" %} *</label>
|
||||
|
||||
{# **CRITICAL FIX:** Iterate over the errors to display them correctly #}
|
||||
{% if form.password.errors %}
|
||||
<div class="alert alert-danger p-2 small">
|
||||
{% for error in form.password.errors %}
|
||||
{{ error }}
|
||||
{% endfor %}
|
||||
</div>
|
||||
{% endif %}
|
||||
|
||||
<input type="password" name="{{ form.password.name }}" id="{{ form.password.id_for_label }}"
|
||||
class="form-control" placeholder="{% trans 'Enter new password' %}" required autofocus>
|
||||
</div>
|
||||
|
||||
{# Password 2 Field #}
|
||||
<div class="mb-3">
|
||||
<label for="{{ form.password2.id_for_label }}" class="form-label fw-semibold">{% trans "Confirm New Password" %} *</label>
|
||||
|
||||
{# **CRITICAL FIX:** Iterate over the errors to display them correctly #}
|
||||
{% if form.password2.errors %}
|
||||
<div class="alert alert-danger p-2 small">
|
||||
{% for error in form.password2.errors %}
|
||||
{{ error }}
|
||||
{% endfor %}
|
||||
</div>
|
||||
{% endif %}
|
||||
|
||||
<input type="password" name="{{ form.password2.name }}" id="{{ form.password2.id_for_label }}"
|
||||
class="form-control" placeholder="{% trans 'Confirm new password' %}" required>
|
||||
</div>
|
||||
|
||||
{# Hidden fields MUST be present for the POST request to be valid #}
|
||||
{{ form.uid }}
|
||||
{{ form.token }}
|
||||
{# RENDER THE FORM USING CRISPY FORMS #}
|
||||
{{ form|crispy }}
|
||||
|
||||
{# Submit Button #}
|
||||
<button type="submit" class="btn btn-primary w-100 mt-4">
|
||||
|
||||
@ -146,9 +146,12 @@
|
||||
<div class="container-fluid py-4">
|
||||
<nav aria-label="breadcrumb">
|
||||
<ol class="breadcrumb">
|
||||
<li class="breadcrumb-item"><a href="{% url 'job_detail' submission.template.job.slug %}">Job Detail</a></li>
|
||||
<li class="breadcrumb-item"><a href="{% url 'form_builder' submission.template.pk%}">Form Template</a></li>
|
||||
<li class="breadcrumb-item active" aria-current="page">Submission Details</li>
|
||||
<li class="breadcrumb-item text-decorat"><a href="{% url 'job_detail' submission.template.job.slug %}" class="text-secondary">Job Detail</a></li>
|
||||
<li class="breadcrumb-item"><a href="{% url 'form_builder' submission.template.pk%}" class="text-secondary">Form Template</a></li>
|
||||
<li class="breadcrumb-item active" aria-current="page" style="
|
||||
color: #F43B5E; /* Rosy Accent Color */
|
||||
font-weight: 600;
|
||||
">Submission Details</li>
|
||||
</ol>
|
||||
</nav>
|
||||
<div class="row">
|
||||
|
||||
@ -185,9 +185,12 @@
|
||||
<div class="container py-4">
|
||||
<nav aria-label="breadcrumb">
|
||||
<ol class="breadcrumb">
|
||||
<li class="breadcrumb-item"><a href="{% url 'dashboard' %}">{% trans "Dashboard" %}</a></li>
|
||||
<li class="breadcrumb-item"><a href="{% url 'form_templates_list' %}">{% trans "Form Templates" %}</a></li>
|
||||
<li class="breadcrumb-item active">{% trans "Submissions" %}</li>
|
||||
<li class="breadcrumb-item"><a href="{% url 'dashboard' %}" class="text-secondary">{% trans "Dashboard" %}</a></li>
|
||||
<li class="breadcrumb-item"><a href="{% url 'form_templates_list' %}" class="text-secondary">{% trans "Form Templates" %}</a></li>
|
||||
<li class="breadcrumb-item active" style="
|
||||
color: #F43B5E; /* Rosy Accent Color */
|
||||
font-weight: 600;
|
||||
">{% trans "Submissions" %}</li>
|
||||
</ol>
|
||||
</nav>
|
||||
|
||||
|
||||
@ -364,6 +364,7 @@
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
|
||||
<div class="resume-container">
|
||||
<div class="header">
|
||||
<div class="header-content">
|
||||
|
||||
@ -152,7 +152,10 @@
|
||||
<ol class="breadcrumb">
|
||||
<li class="breadcrumb-item"><a href="{% url 'dashboard' %}" class="text-secondary">Home</a></li>
|
||||
<li class="breadcrumb-item"><a href="{% url 'job_list' %}" class="text-secondary">Jobs</a></li>
|
||||
<li class="breadcrumb-item active" aria-current="page">Job Detail</li>
|
||||
<li class="breadcrumb-item active" aria-current="page" style="
|
||||
color: #F43B5E; /* Rosy Accent Color */
|
||||
font-weight: 600;
|
||||
">Job Detail</li>
|
||||
</ol>
|
||||
</nav>
|
||||
<div class="row g-4">
|
||||
|
||||
@ -186,7 +186,10 @@
|
||||
<ol class="breadcrumb">
|
||||
<li class="breadcrumb-item"><a href="{% url 'dashboard' %}" class="text-secondary">Home</a></li>
|
||||
<li class="breadcrumb-item"><a href="{% url 'job_detail' candidate.job.slug %}" class="text-secondary">Job:({{candidate.job.title}})</a></li>
|
||||
<li class="breadcrumb-item active" aria-current="page" class="text-secondary">Applicant Detail</li>
|
||||
<li class="breadcrumb-item active" aria-current="page" class="text-secondary" style="
|
||||
color: #F43B5E; /* Rosy Accent Color */
|
||||
font-weight: 600;
|
||||
">Applicant Detail</li>
|
||||
</ol>
|
||||
</nav>
|
||||
|
||||
|
||||
@ -1,4 +1,5 @@
|
||||
<!DOCTYPE html>
|
||||
{% load i18n %}
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
@ -517,7 +518,10 @@
|
||||
</style>
|
||||
</head>
|
||||
<body class="bg-kaauh-light-bg font-sans">
|
||||
|
||||
<div class="container container-fluid flex-grow-1" style="max-width: 1600px; margin: 0 auto;">
|
||||
|
||||
{% include 'recruitment/partials/ai_overview_breadcromb.html' %}
|
||||
<!-- Header Section -->
|
||||
<header class="header-box">
|
||||
<div class="header-info">
|
||||
@ -716,21 +720,9 @@
|
||||
</div>
|
||||
{% endif %}
|
||||
|
||||
<div style="margin-bottom: 1rem;">
|
||||
<div class="analysis-metric" style="margin-bottom: 0.5rem; border-bottom: none;">
|
||||
<span class="metric-title">Match Score</span>
|
||||
<span class="metric-value">{{ candidate.analysis_data.match_score|default:0 }}/100</span>
|
||||
</div>
|
||||
<div class="progress-container">
|
||||
<div class="progress-bar progress-bar-animated"
|
||||
style="width: {{ candidate.analysis_data.match_score|default:0 }}%; background-color:
|
||||
{% if candidate.analysis_data.match_score|default:0 < 50 %}var(--score-red){% elif candidate.analysis_data.match_score|default:0 < 75 %}var(--score-yellow){% else %}var(--score-green){% endif %}">
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{% if candidate.analysis_data.red_flags %}
|
||||
<div class="narrative-box red-flag-box">
|
||||
<div class="narrative-box">
|
||||
<h3 class="flag-title red"><i class="fas fa-flag"></i>Red Flags</h3>
|
||||
<!-- scoring_data.red_flags -->
|
||||
<p class="narrative-text">{{ candidate.analysis_data.red_flags|join:". "|default:"None." }}</p>
|
||||
|
||||
118
templates/recruitment/partials/ai_overview_breadcromb.html
Normal file
118
templates/recruitment/partials/ai_overview_breadcromb.html
Normal file
@ -0,0 +1,118 @@
|
||||
{% load i18n %}
|
||||
{% with request.resolver_match as resolved %}
|
||||
{% if 'resume-template' in resolved.route and resolved.kwargs.slug == candidate.slug %}
|
||||
<nav aria-label="breadcrumb" style="font-family: 'Inter', sans-serif; margin-bottom:1.5rem;">
|
||||
<ol style="
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
padding: 0;
|
||||
margin: 0;
|
||||
list-style: none;
|
||||
font-size: 0.875rem; /* text-sm */
|
||||
">
|
||||
|
||||
<li style="display: flex; align-items: center;">
|
||||
<a
|
||||
href="{% url 'dashboard' %}"
|
||||
style="
|
||||
color: #6c757d; /* text-secondary/gray */
|
||||
text-decoration: none;
|
||||
transition: color 0.15s ease-in-out;
|
||||
"
|
||||
onmouseover="this.style.color='#000000';"
|
||||
onmouseout="this.style.color='#6c757d';"
|
||||
>
|
||||
{% translate 'Home' %}
|
||||
</a>
|
||||
</li>
|
||||
|
||||
<li style="
|
||||
display: flex;
|
||||
align-items: center;
|
||||
padding-left: 0.5rem;
|
||||
padding-right: 0.5rem;
|
||||
">
|
||||
<span style="color: #6c757d; opacity: 0.75;" aria-hidden="true">/</span>
|
||||
</li>
|
||||
|
||||
<li style="display: flex; align-items: center;">
|
||||
<a
|
||||
href="{% url 'job_list' %}"
|
||||
style="
|
||||
color: #6c757d; /* text-secondary/gray */
|
||||
text-decoration: none;
|
||||
transition: color 0.15s ease-in-out;
|
||||
"
|
||||
onmouseover="this.style.color='#000000';"
|
||||
onmouseout="this.style.color='#6c757d';"
|
||||
>
|
||||
{% trans 'Jobs' %}
|
||||
</a>
|
||||
</li>
|
||||
<li style="
|
||||
display: flex;
|
||||
align-items: center;
|
||||
padding-left: 0.5rem;
|
||||
padding-right: 0.5rem;
|
||||
">
|
||||
<span style="color: #6c757d; opacity: 0.75;" aria-hidden="true">/</span>
|
||||
</li>
|
||||
<li style="display: flex; align-items: center;">
|
||||
<a
|
||||
href="{% url 'candidate_list' %}"
|
||||
style="
|
||||
color: #6c757d; /* text-secondary/gray */
|
||||
text-decoration: none;
|
||||
transition: color 0.15s ease-in-out;
|
||||
"
|
||||
onmouseover="this.style.color='#000000';"
|
||||
onmouseout="this.style.color='#6c757d';"
|
||||
>
|
||||
{% trans 'Applicants' %}
|
||||
</a>
|
||||
</li>
|
||||
<li style="
|
||||
display: flex;
|
||||
align-items: center;
|
||||
padding-left: 0.5rem;
|
||||
padding-right: 0.5rem;
|
||||
">
|
||||
<span style="color: #6c757d; opacity: 0.75;" aria-hidden="true">/</span>
|
||||
</li>
|
||||
<li style="display: flex; align-items: center;">
|
||||
<a
|
||||
href="{% url 'candidate_detail' candidate.slug %}"
|
||||
style="
|
||||
color: #6c757d; /* text-secondary/gray */
|
||||
text-decoration: none;
|
||||
transition: color 0.15s ease-in-out;
|
||||
"
|
||||
onmouseover="this.style.color='#000000';"
|
||||
onmouseout="this.style.color='#6c757d';"
|
||||
>
|
||||
{{candidate.resume_data.full_name}}
|
||||
</a>
|
||||
</li>
|
||||
|
||||
<li style="
|
||||
display: flex;
|
||||
align-items: center;
|
||||
padding-left: 0.5rem;
|
||||
padding-right: 0.5rem;
|
||||
">
|
||||
<span style="color: #6c757d; opacity: 0.75;" aria-hidden="true">/</span>
|
||||
</li>
|
||||
|
||||
<li
|
||||
aria-current="page"
|
||||
style="
|
||||
color: #F43B5E; /* Rosy Accent Color */
|
||||
font-weight: 600;
|
||||
"
|
||||
>
|
||||
{% trans 'AI Overview' %}
|
||||
</li>
|
||||
</ol>
|
||||
</nav>
|
||||
{% endif %}
|
||||
{% endwith %}
|
||||
Loading…
x
Reference in New Issue
Block a user