retry filed for ai scoring and hooks

This commit is contained in:
Faheed 2025-10-26 15:36:22 +03:00
parent 9cd63d3897
commit de83838392
17 changed files with 331 additions and 70 deletions

View File

@ -185,8 +185,7 @@ ACCOUNT_SIGNUP_FIELDS = ['email*', 'password1*', 'password2*']
ACCOUNT_UNIQUE_EMAIL = True ACCOUNT_UNIQUE_EMAIL = True
ACCOUNT_EMAIL_VERIFICATION = 'none' ACCOUNT_EMAIL_VERIFICATION = 'none'
ACCOUNT_USER_MODEL_USERNAME_FIELD = None ACCOUNT_USER_MODEL_USERNAME_FIELD = None
ACCOUNT_EMAIL_VERIFICATION = "mandatory"
ACCOUNT_LOGIN_ON_EMAIL_CONFIRMATION = True ACCOUNT_LOGIN_ON_EMAIL_CONFIRMATION = True
@ -238,7 +237,7 @@ STATICFILES_DIRS = [
BASE_DIR / 'static' BASE_DIR / 'static'
] ]
STATIC_ROOT = os.path.join(BASE_DIR, 'staticfiles') STATIC_ROOT = os.path.join(BASE_DIR, 'staticfiles')
MEDIA_ROOT = os.path.join(BASE_DIR, 'static/media') MEDIA_ROOT = os.path.join(BASE_DIR, 'media')
# Default primary key field type # Default primary key field type
# https://docs.djangoproject.com/en/5.2/ref/settings/#default-auto-field # https://docs.djangoproject.com/en/5.2/ref/settings/#default-auto-field

View File

@ -642,3 +642,6 @@ class CandidateExamDateForm(forms.ModelForm):
widgets = { widgets = {
'exam_date': forms.DateTimeInput(attrs={'type': 'datetime-local', 'class': 'form-control'}), 'exam_date': forms.DateTimeInput(attrs={'type': 'datetime-local', 'class': 'form-control'}),
} }

View File

@ -1 +1,14 @@
from .models import Candidate
from time import sleep
def callback_ai_parsing(task):
if task.success:
try:
pk = task.args[0]
c = Candidate.objects.get(pk=pk)
if c.retry and not c.is_resume_parsed:
sleep(30)
c.retry -= 1
c.save()
except Exception as e:
print(e)

View File

@ -7,7 +7,7 @@ import random
from datetime import date, timedelta from datetime import date, timedelta
from django.core.management.base import BaseCommand from django.core.management.base import BaseCommand
from django.utils import timezone from django.utils import timezone
from time import sleep
from faker import Faker from faker import Faker
from recruitment.models import JobPosting, Candidate, Source, FormTemplate from recruitment.models import JobPosting, Candidate, Source, FormTemplate
@ -67,6 +67,7 @@ class Command(BaseCommand):
created_jobs = [] created_jobs = []
for i in range(jobs_count): for i in range(jobs_count):
# Dynamic job details # Dynamic job details
sleep(random.randint(4,10))
title = fake.job() title = fake.job()
department = random.choice(DEPARTMENTS) department = random.choice(DEPARTMENTS)
is_faculty = random.random() < 0.1 # 10% chance of being a faculty job is_faculty = random.random() < 0.1 # 10% chance of being a faculty job
@ -101,7 +102,7 @@ class Command(BaseCommand):
job = JobPosting.objects.create( job = JobPosting.objects.create(
**job_data **job_data
) )
FormTemplate.objects.create(job=job, name=f"{job.title} Form", description=f"Form for {job.title}",is_active=True) # FormTemplate.objects.create(job=job, name=f"{job.title} Form", description=f"Form for {job.title}",is_active=True)
created_jobs.append(job) created_jobs.append(job)
self.stdout.write(self.style.SUCCESS(f'Created JobPosting {i+1}/{jobs_count}: {job.title}')) self.stdout.write(self.style.SUCCESS(f'Created JobPosting {i+1}/{jobs_count}: {job.title}'))
@ -109,6 +110,7 @@ class Command(BaseCommand):
# 4. Generate Candidates # 4. Generate Candidates
if created_jobs: if created_jobs:
for i in range(candidates_count): for i in range(candidates_count):
sleep(random.randint(4,10))
# Link candidate to a random job # Link candidate to a random job
target_job = random.choice(created_jobs) target_job = random.choice(created_jobs)
print(target_job) print(target_job)

View File

@ -0,0 +1,18 @@
# Generated by Django 5.2.7 on 2025-10-26 11:53
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('recruitment', '0001_initial'),
]
operations = [
migrations.AddField(
model_name='candidate',
name='retry',
field=models.SmallIntegerField(default=3, verbose_name='Resume Parsing Retry'),
),
]

View File

@ -453,6 +453,7 @@ class Candidate(Base):
related_name="submitted_candidates", related_name="submitted_candidates",
verbose_name=_("Submitted by Agency"), verbose_name=_("Submitted by Agency"),
) )
retry = models.SmallIntegerField(verbose_name="Resume Parsing Retry",default=3)
class Meta: class Meta:
verbose_name = _("Candidate") verbose_name = _("Candidate")

View File

@ -13,7 +13,7 @@ logger = logging.getLogger(__name__)
@receiver(post_save, sender=JobPosting) @receiver(post_save, sender=JobPosting)
def format_job(sender, instance, created, **kwargs): def format_job(sender, instance, created, **kwargs):
if created: if created:
# FormTemplate.objects.create(job=instance, is_active=False, name=instance.title) FormTemplate.objects.create(job=instance, is_active=False, name=instance.title)
async_task( async_task(
'recruitment.tasks.format_job_description', 'recruitment.tasks.format_job_description',
instance.pk, instance.pk,
@ -52,7 +52,7 @@ def score_candidate_resume(sender, instance, created, **kwargs):
async_task( async_task(
'recruitment.tasks.handle_reume_parsing_and_scoring', 'recruitment.tasks.handle_reume_parsing_and_scoring',
instance.pk, instance.pk,
# hook='myapp.tasks.email_sent_callback' # Optional callback hook='recruitment.hooks.callback_ai_parsing'
) )
@receiver(post_save, sender=FormTemplate) @receiver(post_save, sender=FormTemplate)

View File

@ -167,6 +167,7 @@ def ai_handler(prompt):
print(response.status_code) print(response.status_code)
if response.status_code == 200: if response.status_code == 200:
res = response.json() res = response.json()
print(res)
content = res["choices"][0]['message']['content'] content = res["choices"][0]['message']['content']
try: try:
# print(content) # print(content)
@ -231,7 +232,7 @@ def handle_reume_parsing_and_scoring(pk):
logger.error(f"Error during initial data retrieval/parsing for candidate {instance.pk}: {e}") logger.error(f"Error during initial data retrieval/parsing for candidate {instance.pk}: {e}")
print(f"Error during initial data retrieval/parsing for candidate {instance.pk}: {e}") print(f"Error during initial data retrieval/parsing for candidate {instance.pk}: {e}")
return return
print(resume_text)
# --- 3. Single, Combined LLM Prompt (Major Cost & Latency Optimization) --- # --- 3. Single, Combined LLM Prompt (Major Cost & Latency Optimization) ---
prompt = f""" prompt = f"""
You are an expert AI system functioning as both a Resume Parser and a Technical Recruiter. You are an expert AI system functioning as both a Resume Parser and a Technical Recruiter.

View File

@ -17,12 +17,13 @@
<div class="row"> <div class="row">
{# ------------------- LEFT COLUMN: ACCOUNT MENU (New Card Style) ------------------- #} {# ------------------- LEFT COLUMN: ACCOUNT MENU ------------------- #}
<div class="col-md-4 col-lg-3 mb-4"> <div class="col-md-4 col-lg-3 mb-4">
<div class="card shadow-sm border-0 rounded-4"> <div class="card shadow-sm border-0 rounded-4">
<div class="card-body p-0"> <div class="card-body p-0">
<div class="list-group list-group-flush rounded-4"> <div class="list-group list-group-flush rounded-4">
{# Assuming a main 'Profile' or 'Personal Information' page exists #} {# Assuming a main 'Profile' or 'Personal Information' page exists #}
{# NOTE: You will need to replace 'user_detail' with your actual profile URL name #}
<a href="{% url 'user_detail' user.pk %}" class="list-group-item list-group-item-action border-0 rounded-top-4 py-3"> <a href="{% url 'user_detail' user.pk %}" class="list-group-item list-group-item-action border-0 rounded-top-4 py-3">
<i class="fas fa-user-circle me-2"></i> {% translate "Personal Information" %} <i class="fas fa-user-circle me-2"></i> {% translate "Personal Information" %}
</a> </a>
@ -51,6 +52,15 @@
<h5 class="fw-bold mb-3">{% translate "Email Addresses" %}</h5> <h5 class="fw-bold mb-3">{% translate "Email Addresses" %}</h5>
<p class="text-muted border-bottom pb-3">{% translate "These email addresses are linked to your account. You can set the primary address, resend verification, or remove an address." %}</p> <p class="text-muted border-bottom pb-3">{% translate "These email addresses are linked to your account. You can set the primary address, resend verification, or remove an address." %}</p>
{# Django Messages for Success/Error feedback #}
{% if messages %}
{% for message in messages %}
<div class="alert alert-{{ message.tags }} mt-3" role="alert">
{{ message }}
</div>
{% endfor %}
{% endif %}
{% if emailaddresses %} {% if emailaddresses %}
{% for emailaddress in emailaddresses %} {% for emailaddress in emailaddresses %}
<div class="d-flex flex-column flex-sm-row justify-content-between align-items-sm-center py-3 {% if not forloop.last %}border-bottom{% endif %}"> <div class="d-flex flex-column flex-sm-row justify-content-between align-items-sm-center py-3 {% if not forloop.last %}border-bottom{% endif %}">
@ -58,7 +68,7 @@
<p class="mb-2 mb-sm-0 me-3"> <p class="mb-2 mb-sm-0 me-3">
<span class="fw-bold text-dark">{{ emailaddress.email }}</span> <span class="fw-bold text-dark">{{ emailaddress.email }}</span>
{# Status Badges: Using rounded-pill and appropriate colors #} {# Status Badges #}
{% if emailaddress.primary %} {% if emailaddress.primary %}
<span class="badge rounded-pill bg-info text-dark ms-2">{% translate "Primary" %}</span> <span class="badge rounded-pill bg-info text-dark ms-2">{% translate "Primary" %}</span>
{% endif %} {% endif %}
@ -71,33 +81,30 @@
<div class="d-flex flex-wrap gap-2"> <div class="d-flex flex-wrap gap-2">
{# 1. MAKE PRIMARY ACTION #} {# 1. MAKE PRIMARY ACTION (Uses 'action_primary') #}
{% if not emailaddress.primary %} {% if not emailaddress.primary %}
<form method="post" action="{% url 'account_email' %}" class="d-inline"> <form method="post" action="{% url 'account_email' %}" class="d-inline">
{% csrf_token %} {% csrf_token %}
<input type="hidden" name="email" value="{{ emailaddress.email }}" /> <input type="hidden" name="email" value="{{ emailaddress.email }}" />
<input type="hidden" name="action" value="set_primary" /> <button type="submit" name="action_primary" class="btn btn-sm btn-outline-primary">{% translate "Make Primary" %}</button>
<button type="submit" class="btn btn-sm btn-outline-primary">{% translate "Make Primary" %}</button>
</form> </form>
{% endif %} {% endif %}
{# 2. RESEND VERIFICATION ACTION #} {# 2. RESEND VERIFICATION ACTION (Uses 'action_send') #}
{% if not emailaddress.verified %} {% if not emailaddress.verified %}
<form method="post" action="{% url 'account_email' %}" class="d-inline"> <form method="post" action="{% url 'account_email' %}" class="d-inline">
{% csrf_token %} {% csrf_token %}
<input type="hidden" name="email" value="{{ emailaddress.email }}" /> <input type="hidden" name="email" value="{{ emailaddress.email }}" />
<input type="hidden" name="action" value="send" /> <button type="submit" name="action_send" class="btn btn-sm btn-outline-warning">{% translate "Re-send Verification" %}</button>
<button type="submit" class="btn btn-sm btn-outline-warning">{% translate "Re-send Verification" %}</button>
</form> </form>
{% endif %} {% endif %}
{# 3. REMOVE ACTION #} {# 3. REMOVE ACTION (Uses 'action_remove') #}
{% if not emailaddress.primary %} {% if not emailaddress.primary %}
<form method="post" action="{% url 'account_email' %}" class="d-inline"> <form method="post" action="{% url 'account_email' %}" class="d-inline">
{% csrf_token %} {% csrf_token %}
<input type="hidden" name="email" value="{{ emailaddress.email }}" /> <input type="hidden" name="email" value="{{ emailaddress.email }}" />
<input type="hidden" name="action" value="remove" /> <button type="submit" name="action_remove" class="btn btn-sm btn-outline-danger">{% translate "Remove" %}</button>
<button type="submit" class="btn btn-sm btn-outline-danger">{% translate "Remove" %}</button>
</form> </form>
{% endif %} {% endif %}
</div> </div>
@ -109,33 +116,26 @@
<hr class="my-4"> <hr class="my-4">
{# ------------------- ADD EMAIL FORM ------------------- #} {# ------------------- ADD EMAIL FORM (The form that failed previously) ------------------- #}
<h5 class="fw-bold mb-3">{% translate "Add Email Address" %}</h5> {% if can_add_email %}
<form method="post" action="{% url 'account_email' %}"> <h5 class="fw-bold mb-3">{% translate "Add Email Address" %}</h5>
{% csrf_token %} <form method="post" action="{% url 'account_email' %}" class="add_email">
{% csrf_token %}
{# 1. Explicitly render non-field errors first #} {# Ensure non-field errors are displayed (e.g., "Email already registered") #}
{% if form.non_field_errors %} {% if form.non_field_errors %}
<div class="alert alert-danger" role="alert"> <div class="alert alert-danger" role="alert">
{% for error in form.non_field_errors %} {{ form.non_field_errors }}
{{ error }} </div>
{% endfor %} {% endif %}
</div>
{% endif %}
{# 2. Render the fields using crispy #} {# Crispy renders the form fields (including new_email) #}
{{ form|crispy }} {{ form|crispy }}
{# 3. If there are any global errors (not common here, but safe to include) #} {# The button name is crucial for the allauth view to recognize the "Add" action #}
{% if messages %} <button class="btn btn-success mt-3" type="submit" name="action_add" style="background-color: #008080; border-color: #008080;">{% translate "Add Email" %}</button>
{% for message in messages %} </form>
<div class="alert alert-{{ message.tags }} mt-3">{{ message }}</div> {% endif %}
{% 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>
</div> </div>
</div> </div>
</div> </div>

View File

@ -0,0 +1,28 @@
{% load account i18n %}
{% autoescape off %}
<p style="font-family: Arial, sans-serif; font-size: 16px; color: #333;">
{% blocktrans %}Hello,{% endblocktrans %}
</p>
<p style="font-family: Arial, sans-serif; font-size: 16px; color: #333;">
{% blocktrans %}Thank you for choosing **KAAUH ATS**. To verify the ownership of your email address, please click the confirmation link below:{% endblocktrans %}
</p>
<div style="text-align: center; margin: 30px 0;">
<a href="{{ activate_url }}"
style="display: inline-block; padding: 15px 35px; background-color: #008080; color: #ffffff; text-decoration: none; border-radius: 8px; font-weight: bold; font-size: 18px;">
{% trans "Confirm My KAAUH ATS Email" %}
</a>
</div>
<p style="font-family: Arial, sans-serif; font-size: 14px; color: #777; margin-top: 20px;">
{% blocktrans %}If you did not request this verification, you can safely ignore this email.{% endblocktrans %}
</p>
<p style="font-family: Arial, sans-serif; font-size: 14px; color: #777; margin-top: 10px;">
{% blocktrans %}Alternatively, copy and paste this link into your browser:{% endblocktrans %}<br>
<a href="{{ activate_url }}" style="color: #008080; word-break: break-all;">{{ activate_url }}</a>
</p>
{% endautoescape %}

View File

@ -2,62 +2,65 @@
{% load i18n %} {% load i18n %}
{% load account %} {% load account %}
{% block title %}{% translate "Confirm Email Address" %}{% endblock %} {% block title %}{% trans "Confirm Email Address" %}{% endblock %}
{% block content %} {% block content %}
<div class="container my-5"> <div class="container my-5">
<div class="row mb-4"> {# Centering the main header content #}
<div class="col"> <div class="row mb-5 justify-content-center text-center">
<h3 class="fw-bold">{% translate "Account Verification" %}</h3> <div class="col-md-8 col-lg-6">
<p class="text-muted">{% translate "Verify your email to secure your account and unlock full features." %}</p> <h3 class="fw-bolder" style="color: #00636e;">{% trans "Account Verification" %}</h3>
<p class="lead text-muted">{% trans "Verify your email to secure your account and unlock full features." %}</p>
</div> </div>
</div> </div>
<div class="row justify-content-center"> <div class="row justify-content-center">
<div class="col-md-8 col-lg-6"> <div class="col-md-8 col-lg-6">
<div class="card shadow-sm border-0 rounded-4"> <div class="card shadow-lg border-0 rounded-4">
<div class="card-body p-5 text-center"> <div class="card-body p-5 text-center">
{% with emailaddress.email as email %} {% with email as email %}
{% if confirmation %} {% if confirmation %}
{# ------------------- CONFIRMATION REQUEST (GET) ------------------- #} {# ------------------- CONFIRMATION REQUEST (GET) - Success Theme ------------------- #}
{% user_display confirmation.email_address.user as user_display %} {% user_display confirmation.email_address.user as user_display %}
<i class="fas fa-envelope-open-text mb-4" style="font-size: 3rem; color: #008080;"></i> <i class="fas fa-check-circle mb-4" style="font-size: 4rem; color: #008080;"></i> {# Changed icon to a checkmark for clarity #}
<h4 class="fw-bold mb-3">{% translate "Confirm Your Email Address" %}</h4> <h4 class="fw-bold mb-3">{% translate "Confirm Your Email Address" %}</h4>
<p class="lead text-muted"> <p class="lead" style="color: #343a40;">
{% blocktrans with email as email %}Please confirm that **{{ email }}** is an email address for user **{{ user_display }}**.{% endblocktrans %} {% blocktrans with email as email %}Please confirm that **{{ email }}** is the correct email address for your account.{% endblocktrans %}
</p> </p>
{# Confirmation Form #} {# Confirmation Form #}
<form method="post" action="{% url 'account_confirm_email' confirmation.key %}"> <form method="post" action="{% url 'account_confirm_email' confirmation.key %}">
{% csrf_token %} {% csrf_token %}
{# Teal/Dark Green button consistent with the UI theme #} <button class="btn btn-lg mt-4 px-5 fw-semibold text-white" type="submit"
<button class="btn btn-lg mt-4 px-5" type="submit" style="background-color: #008080; border-color: #008080; color: white;"> style="background-color: #008080; border-color: #008080; box-shadow: 0 4px 8px rgba(0, 128, 128, 0.3);">
{% translate "Confirm" %} {% translate "Confirm & Activate" %}
</button> </button>
</form> </form>
{% else %} {% else %}
{# ------------------- CONFIRMATION FAILED (Error) ------------------- #} {# ------------------- CONFIRMATION FAILED (Error) - Danger Theme ------------------- #}
<i class="fas fa-exclamation-triangle text-danger mb-4" style="font-size: 3rem;"></i> <i class="fas fa-unlink text-danger mb-4" style="font-size: 4rem;"></i> {# Changed icon to be more specific #}
<h4 class="fw-bold mb-3 text-danger">{% translate "Invalid Link" %}</h4>
<p class="lead"> <h4 class="fw-bold mb-3 text-danger">{% translate "Verification Failed" %}</h4>
{% translate "The email confirmation link has expired or is invalid." %}
<p class="lead text-danger">
{% translate "The email confirmation link is expired or invalid." %}
</p> </p>
<p class="text-muted"> <p class="text-muted small">
{% translate "Please request a new verification email from your account settings page." %} {% translate "If you recently requested a link, please ensure you use the newest one. You can request a new verification email from your account settings." %}
</p> </p>
<a href="{% url 'account_email' %}" class="btn btn-outline-secondary mt-3 px-5"> <a href="{% url 'account_email' %}" class="btn btn-outline-secondary mt-4 px-5 fw-semibold">
{% translate "Go to Settings" %} <i class="fas fa-cog me-2"></i> {% translate "Go to Settings" %}
</a> </a>
{% endif %} {% endif %}

View File

@ -0,0 +1,193 @@
{% load static %}
{% load i18n %}
{% load allauth %}
{% load account %}
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>KAAUH ATS - Verify Email</title>
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.3/dist/css/bootstrap.min.css" rel="stylesheet" integrity="sha384-QWTKZyjpPEjISv5WaRU9OFeRpok6YctnYmDr5pNlyT2bRjXh0JMhjY6hW+ALEwIH" crossorigin="anonymous">
<style>
/* -------------------------------------------------------------------------- */
/* CUSTOM TEAL THEME OVERRIDES FOR BOOTSTRAP (Copied from your provided code) */
/* -------------------------------------------------------------------------- */
:root {
/* Define TEAL as the primary color for Bootstrap overrides */
--bs-primary: #00636e; /* Dark Teal */
--bs-primary-rgb: 0, 99, 110;
--bs-primary-light: #007a88; /* Lighter Teal for hover */
/* Background and Text Colors */
--bs-body-bg: #f8f9fa; /* Light gray background */
--bs-body-color: #212529; /* Dark text */
/* Utility colors */
--bs-border-color: #dee2e6; /* Bootstrap default border */
}
body {
font-family: 'Inter', sans-serif;
background-color: var(--bs-body-bg);
}
/* Custom Left Panel (Replicating the original look) */
.left-panel {
flex: 1;
/* NOTE: Ensure you have an 'image/kaauh_banner.png' in your static files */
background: url("{% static 'image/kaauh_banner.png' %}") no-repeat center center;
background-size: cover;
position: relative;
display: flex;
align-items: flex-end;
padding: 3rem;
color: white;
z-index: 1;
}
.left-panel::before {
content: '';
position: absolute;
top: 0;
left: 0;
right: 0;
bottom: 0;
background: linear-gradient(to top, rgba(0,0,0,0.8) 0%, rgba(0,0,0,0) 50%);
z-index: 0;
}
.left-panel-content {
position: relative;
z-index: 2;
}
/* Right Panel Styling */
.right-panel {
background-color: white;
padding: 3rem;
}
.form-fields {
max-height: 100%;
overflow-y: auto;
}
/* Component Overrides to use Teal Theme */
.btn-primary {
background-color: var(--bs-primary);
border-color: var(--bs-primary);
font-weight: 600;
border-radius: 0.5rem;
box-shadow: 0 4px 8px rgba(0, 99, 110, 0.2);
transition: all 0.2s ease;
}
.btn-primary:hover {
background-color: var(--bs-primary-light);
border-color: var(--bs-primary-light);
box-shadow: 0 6px 10px rgba(0, 99, 110, 0.3);
}
.form-control:focus {
border-color: var(--bs-primary);
box-shadow: 0 0 0 0.25rem rgba(0, 99, 110, 0.25);
}
.form-check-input:checked {
background-color: var(--bs-primary);
border-color: var(--bs-primary);
}
.text-accent {
color: var(--bs-primary) !important;
}
.text-accent:hover {
color: var(--bs-primary-light) !important;
text-decoration: underline;
}
/* Custom size adjustment for right panel on desktop */
@media (min-width: 992px) {
/* 1. Set a NARROWER fixed width for the right panel container */
.right-panel-col {
flex: 0 0 450px; /* Reduced from 800px to 450px */
}
/* 2. Vertically and horizontally center the content within the narrow panel */
.right-panel-col > .d-flex {
height: 100%;
justify-content: center;
align-items: center;
padding-top: 0;
padding-bottom: 0;
}
/* 3. Ensure the form container doesn't exceed a smaller size and is centered */
.right-panel-content-wrapper {
max-width: 350px; /* Max width of the form elements inside the panel */
width: 100%;
}
}
</style>
</head>
<body>
<div class="d-flex vh-100 w-100">
<div class="left-panel d-none d-lg-flex flex-grow-1">
<div class="left-panel-content">
<h1 class="text-4xl font-weight-bold mb-4" style="font-size: 1.5rem;">
<span class="text-white">
<div class="hospital-text text-center text-md-start me-3">
<div class="ar small">جامعة الأميرة نورة بنت عبدالرحمن الأكاديمية</div>
<div class="ar small">ومستشفى الملك عبدالله بن عبدالعزيز التخصصي</div>
<div class="en small">Princess Nourah bint Abdulrahman University</div>
<div class="en small">King Abdullah bin Abdulaziz University Hospital</div>
</div>
</span>
</h1>
<small>Powered By TENHAL | تنحل</small>
</div>
</div>
<div class="d-flex flex-column right-panel right-panel-col flex-grow-1 align-items-center justify-content-center">
<div class="right-panel-content-wrapper text-center">
<h2 id="form-title" class="h3 fw-bold mb-4 text-center text-accent">
{% trans "Verify Your Email Address" %}
</h2>
<div class="form-fields text-start">
<p class="mb-4">
{% blocktrans %}
We have sent an email to your email id for verification. Follow the link provided to finalize the signup process.
{% endblocktrans %}
</p>
<p class="mb-4 text-muted small">
{% trans "If you do not see the verification email in your main inbox, please check your spam folder." %}
</p>
<p class="mb-4 text-muted small">
{% trans "Please contact us if you do not receive the verification email within a few minutes." %}
</p>
<hr>
<div class="d-grid mt-4">
<a href="{% url 'account_email' %}" class="btn btn-outline-secondary w-100">
{% trans "Change or Resend Email" %}
</a>
</div>
<div class="text-center mt-3">
<a href="{% url 'account_login' %}" class="small text-accent fw-medium">
{% trans "Go to Sign In" %}
</a>
</div>
</div>
</div>
</div>
</div>
<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.3.3/dist/js/bootstrap.bundle.min.js" integrity="sha384-YvpcrYf0tY3lHB60NNkmXc5s9fDVZLESaAA55NDzOxhy9GkcIdslK1eN7N6jIeHz" crossorigin="anonymous"></script>
</body>
</html>