diff --git a/.env b/.env index b9e2bf0..8d7fbd5 100644 --- a/.env +++ b/.env @@ -1,3 +1,3 @@ -DB_NAME=norahuniversity -DB_USER=norahuniversity -DB_PASSWORD=norahuniversity \ No newline at end of file +DB_NAME=haikal_db +DB_USER=faheed +DB_PASSWORD=Faheed@215 \ No newline at end of file diff --git a/NorahUniversity/settings.py b/NorahUniversity/settings.py index 7bb0640..ae1397a 100644 --- a/NorahUniversity/settings.py +++ b/NorahUniversity/settings.py @@ -209,23 +209,32 @@ ACCOUNT_LOGIN_ON_EMAIL_CONFIRMATION = True ACCOUNT_FORMS = {"signup": "recruitment.forms.StaffSignupForm"} -# MAIL_BACKEND = "django.core.mail.backends.console.EmailBackend" -# EMAIL_HOST = "10.10.1.110" -# EMAIL_PORT = 2225 +MAIL_BACKEND = "django.core.mail.backends.console.EmailBackend" +EMAIL_HOST = "10.10.1.110" +EMAIL_PORT = 2225 # EMAIL_BACKEND = "django.core.mail.backends.console.EmailBackend" -EMAIL_HOST_PASSWORD = os.getenv("EMAIL_PASSWORD", "mssp.0Q0rSwb.zr6ke4n2k3e4on12.aHwJqnI") -EMAIL_HOST = "smtp.mailersend.net" -EMAIL_PORT = 2525 -EMAIL_HOST_USER = "MS_lhygCJ@test-65qngkd8nx3lwr12.mlsender.net" -EMAIL_HOST_PASSWORD = "mssp.0Q0rSwb.zr6ke4n2k3e4on12.aHwJqnI" -EMAIL_USE_TLS = True -EMAIL_HOST = 'sandbox.smtp.mailtrap.io' -EMAIL_HOST_USER = '38e5179debe69a' -EMAIL_HOST_PASSWORD = 'ffa75647d01ecb' -EMAIL_PORT = '2525' +# EMAIL_HOST_PASSWORD = os.getenv("EMAIL_PASSWORD", "mssp.0Q0rSwb.zr6ke4n2k3e4on12.aHwJqnI") +# EMAIL_HOST = "smtp.mailersend.net" +# EMAIL_PORT = 2525 +# EMAIL_HOST_USER = "MS_lhygCJ@test-65qngkd8nx3lwr12.mlsender.net" +# EMAIL_HOST_PASSWORD = "mssp.0Q0rSwb.zr6ke4n2k3e4on12.aHwJqnI" +# EMAIL_USE_TLS = True +# EMAIL_HOST = 'sandbox.smtp.mailtrap.io' +# EMAIL_HOST_USER = '38e5179debe69a' +# EMAIL_HOST_PASSWORD = 'ffa75647d01ecb' +# EMAIL_PORT = '2525' + +# EMAIL_BACKEND = 'django.core.mail.backends.smtp.EmailBackend' +# EMAIL_HOST = 'smtp.gmail.com' +# EMAIL_PORT = 587 +# EMAIL_USE_TLS = True +# EMAIL_HOST_USER = 'faheedk215@gmail.com' # Use your actual Gmail email address +# EMAIL_HOST_PASSWORD = 'nfxf xpzo bpsb lqje' # +# DEFAULT_FROM_EMAIL='faheedlearn@gmail.com' + # Crispy Forms Configuration CRISPY_ALLOWED_TEMPLATE_PACKS = "bootstrap5" CRISPY_TEMPLATE_PACK = "bootstrap5" diff --git a/NorahUniversity/urls.py b/NorahUniversity/urls.py index 59170ce..8c21eee 100644 --- a/NorahUniversity/urls.py +++ b/NorahUniversity/urls.py @@ -23,7 +23,7 @@ urlpatterns = [ path("ckeditor5/", include('django_ckeditor_5.urls')), path('application//', views.application_submit_form, name='application_submit_form'), - path('application//submit/', views.application_submit, name='application_submit'), + path('application//submit/', views.application_submit, name='application_submit'), path('application//apply/', views.job_application_detail, name='job_application_detail'), path('application//signup/', views.application_signup, name='application_signup'), path('application//success/', views.application_success, name='application_success'), @@ -31,7 +31,7 @@ urlpatterns = [ path('api/v1/templates/', views.list_form_templates, name='list_form_templates'), path('api/v1/templates/save/', views.save_form_template, name='save_form_template'), - path('api/v1/templates//', views.load_form_template, name='load_form_template'), + path('api/v1/templates//', views.load_form_template, name='load_form_template'), path('api/v1/templates//delete/', views.delete_form_template, name='delete_form_template'), path('api/v1/sync/task//status/', views.sync_task_status, name='sync_task_status'), diff --git a/ats-ERD.png b/ats-ERD.png new file mode 100644 index 0000000..425667f Binary files /dev/null and b/ats-ERD.png differ diff --git a/ats.png b/ats.png new file mode 100644 index 0000000..e6b0071 Binary files /dev/null and b/ats.png differ diff --git a/recruitment/urls.py b/recruitment/urls.py index e49764c..890dec5 100644 --- a/recruitment/urls.py +++ b/recruitment/urls.py @@ -119,12 +119,12 @@ urlpatterns = [ path("forms/template//submissions/", views.form_template_submissions_list, name="form_template_submissions_list"), path("forms/template//all-submissions/", views.form_template_all_submissions, name="form_template_all_submissions"), - # Application Forms (Public) - path("application/signup//", views.application_signup, name="application_signup"), - path("application//", views.application_submit_form, name="application_submit_form"), - path("application//submit/", views.application_submit, name="application_submit"), - path("application//apply/", views.job_application_detail, name="job_application_detail"), - path("application//success/", views.application_success, name="application_success"), + # # Application Forms (Public) + # path("application/signup//", views.application_signup, name="application_signup"), + # path("application//", views.application_submit_form, name="application_submit_form"), + # path("application//submit/", views.application_submit, name="application_submit"), + # path("application//apply/", views.job_application_detail, name="job_application_detail"), + # path("application//success/", views.application_success, name="application_success"), # ======================================================================== # INTEGRATION & EXTERNAL SERVICES diff --git a/recruitment/views.py b/recruitment/views.py index 353423f..5951654 100644 --- a/recruitment/views.py +++ b/recruitment/views.py @@ -215,7 +215,7 @@ class PersonListView(StaffRequiredMixin, ListView, LoginRequiredMixin): .distinct() .order_by("nationality") ) - + nationality = self.request.GET.get("nationality") context["nationality"] = nationality context["nationalities"] = nationalities @@ -879,6 +879,8 @@ def form_builder(request, template_slug=None): context = {} if template_slug: template = get_object_or_404(FormTemplate, slug=template_slug) + job_slug=template.job.slug + context['job_slug']=job_slug context["template"] = template context["template_slug"] = template.slug context["template_name"] = template.name @@ -1142,10 +1144,11 @@ def save_form_template(request): # ) -def load_form_template(request, template_slug): +def load_form_template(request, slug): """Load an existing form template""" try: - template = get_object_or_404(FormTemplate, slug=template_slug) + job = get_object_or_404(JobPosting, slug=slug) + template = job.form_template # Get stages with fields stages = [] @@ -1308,6 +1311,7 @@ def delete_form_template(request, template_id): def application_submit_form(request, slug): """Display the form as a step-by-step wizard""" job = get_object_or_404(JobPosting, slug=slug) + if not request.user.is_authenticated: return redirect("application_signup", slug=slug) @@ -1342,7 +1346,7 @@ def application_submit_form(request, slug): return render( request, "applicant/application_submit_form.html", - {"template_slug": job.form_template.slug, "job_id": job.internal_job_id}, + {"template_slug": job.form_template.slug,"job_slug": job.slug, "job_id": job.internal_job_id}, ) @@ -1350,24 +1354,19 @@ def application_submit_form(request, slug): @require_POST @login_required @candidate_user_required -def application_submit(request, template_slug): - import re - +def application_submit(request, slug): """Handle form submission""" - if not request.user.is_authenticated or request.user.user_type != "candidate": - return JsonResponse({"success": False, "message": "Unauthorized access."}) + # if not request.user.is_authenticated or request.user.user_type != "candidate": + # return JsonResponse({"success": False, "message": "Unauthorized access."}) - template = get_object_or_404(FormTemplate, slug=template_slug) - job = template.job + job = get_object_or_404(JobPosting, slug=slug) + template = job.form_template + if request.method == "POST": try: - with transaction.atomic(): - job_posting = JobPosting.objects.select_for_update().get( - form_template=template - ) - - current_count = job_posting.applications.count() - if current_count >= job_posting.max_applications: + with transaction.atomic(): + current_count = job.applications.count() + if current_count >= job.max_applications: template.is_active = False template.save() return JsonResponse( @@ -2432,8 +2431,11 @@ def create_staff_user(request): @superuser_required def admin_settings(request): staffs = User.objects.filter(user_type="staff", is_superuser=False) + paginator=Paginator(staffs,20) + page_number=request.GET.get('page') + page_obj=paginator.get_page(page_number) form = ToggleAccountForm() - context = {"staffs": staffs, "form": form} + context = {"staffs": page_obj, "form": form,"page_obj":page_obj} return render(request, "user/admin_settings.html", context) @@ -2769,7 +2771,7 @@ def agency_assignment_list(request): assignments = assignments.filter(status=status_filter) # Pagination - paginator = Paginator(assignments, 15) # Show 15 assignments per page + paginator = Paginator(assignments, 20) # Show 15 assignments per page page_number = request.GET.get("page") page_obj = paginator.get_page(page_number) @@ -4514,133 +4516,133 @@ def api_application_detail(request, candidate_id): # Source CRUD Views -@login_required -@staff_user_required -def source_list(request): - """List all sources with search and pagination""" - search_query = request.GET.get("q", "") - sources = Source.objects.all() +# @login_required +# @staff_user_required +# def source_list(request): +# """List all sources with search and pagination""" +# search_query = request.GET.get("q", "") +# sources = Source.objects.all() + +# if search_query: +# sources = sources.filter( +# Q(name__icontains=search_query) +# | Q(source_type__icontains=search_query) +# | Q(description__icontains=search_query) +# ) - if search_query: - sources = sources.filter( - Q(name__icontains=search_query) - | Q(source_type__icontains=search_query) - | Q(description__icontains=search_query) - ) +# # Order by most recently created +# sources = sources.order_by("-created_at") - # Order by most recently created - sources = sources.order_by("-created_at") +# # Pagination +# paginator = Paginator(sources, 1) # Show 15 sources per page +# page_number = request.GET.get("page") +# page_obj = paginator.get_page(page_number) - # Pagination - paginator = Paginator(sources, 1) # Show 15 sources per page - page_number = request.GET.get("page") - page_obj = paginator.get_page(page_number) - - context = { - "page_obj": page_obj, - "search_query": search_query, - "total_sources": sources.count(), - } - return render(request, "recruitment/source_list.html", context) +# context = { +# "page_obj": page_obj, +# "search_query": search_query, +# "total_sources": sources.count(), +# } +# return render(request, "recruitment/source_list.html", context) -@login_required -@staff_user_required -def source_create(request): - """Create a new source""" - if request.method == "POST": - form = SourceForm(request.POST) - if form.is_valid(): - source = form.save() - messages.success(request, f'Source "{source.name}" created successfully!') - return redirect("source_detail", slug=source.slug) - else: - messages.error(request, "Please correct the errors below.") - else: - form = SourceForm() +# @login_required +# @staff_user_required +# def source_create(request): +# """Create a new source""" +# if request.method == "POST": +# form = SourceForm(request.POST) +# if form.is_valid(): +# source = form.save() +# messages.success(request, f'Source "{source.name}" created successfully!') +# return redirect("source_detail", slug=source.slug) +# else: +# messages.error(request, "Please correct the errors below.") +# else: +# form = SourceForm() - context = { - "form": form, - "title": "Create New Source", - "button_text": "Create Source", - } - return render(request, "recruitment/source_form.html", context) +# context = { +# "form": form, +# "title": "Create New Source", +# "button_text": "Create Source", +# } +# return render(request, "recruitment/source_form.html", context) -@login_required -@staff_user_required -def source_detail(request, slug): - """View details of a specific source""" - source = get_object_or_404(Source, slug=slug) +# @login_required +# @staff_user_required +# def source_detail(request, slug): +# """View details of a specific source""" +# source = get_object_or_404(Source, slug=slug) - # Get integration logs for this source - integration_logs = source.integration_logs.order_by("-created_at")[ - :10 - ] # Show recent 10 logs +# # Get integration logs for this source +# integration_logs = source.integration_logs.order_by("-created_at")[ +# :10 +# ] # Show recent 10 logs - # Statistics - total_logs = source.integration_logs.count() - successful_logs = source.integration_logs.filter(method="POST").count() - failed_logs = source.integration_logs.filter( - method="POST", status_code__gte=400 - ).count() +# # Statistics +# total_logs = source.integration_logs.count() +# successful_logs = source.integration_logs.filter(method="POST").count() +# failed_logs = source.integration_logs.filter( +# method="POST", status_code__gte=400 +# ).count() - context = { - "source": source, - "integration_logs": integration_logs, - "total_logs": total_logs, - "successful_logs": successful_logs, - "failed_logs": failed_logs, - } - return render(request, "recruitment/source_detail.html", context) +# context = { +# "source": source, +# "integration_logs": integration_logs, +# "total_logs": total_logs, +# "successful_logs": successful_logs, +# "failed_logs": failed_logs, +# } +# return render(request, "recruitment/source_detail.html", context) -@login_required -@staff_user_required -def source_update(request, slug): - """Update an existing source""" - source = get_object_or_404(Source, slug=slug) +# @login_required +# @staff_user_required +# def source_update(request, slug): +# """Update an existing source""" +# source = get_object_or_404(Source, slug=slug) - if request.method == "POST": - form = SourceForm(request.POST, instance=source) - if form.is_valid(): - source = form.save() - messages.success(request, f'Source "{source.name}" updated successfully!') - return redirect("source_detail", slug=source.slug) - else: - messages.error(request, "Please correct the errors below.") - else: - form = SourceForm(instance=source) +# if request.method == "POST": +# form = SourceForm(request.POST, instance=source) +# if form.is_valid(): +# source = form.save() +# messages.success(request, f'Source "{source.name}" updated successfully!') +# return redirect("source_detail", slug=source.slug) +# else: +# messages.error(request, "Please correct the errors below.") +# else: +# form = SourceForm(instance=source) - context = { - "form": form, - "source": source, - "title": _("Edit Source: %(name)s") % {"name": source.name}, - "button_text": _("Update Source"), - } - return render(request, "recruitment/source_form.html", context) +# context = { +# "form": form, +# "source": source, +# "title": _("Edit Source: %(name)s") % {"name": source.name}, +# "button_text": _("Update Source"), +# } +# return render(request, "recruitment/source_form.html", context) -@login_required -@staff_user_required -def source_delete(request, slug): - """Delete a source""" - source = get_object_or_404(Source, slug=slug) +# @login_required +# @staff_user_required +# def source_delete(request, slug): +# """Delete a source""" +# source = get_object_or_404(Source, slug=slug) - if request.method == "POST": - source_name = source.name - source.delete() - messages.success(request, f'Source "{source_name}" deleted successfully!') - return redirect("source_list") +# if request.method == "POST": +# source_name = source.name +# source.delete() +# messages.success(request, f'Source "{source_name}" deleted successfully!') +# return redirect("source_list") - context = { - "source": source, - "title": _("Delete Source: %(name)s") % {"name": source.name}, - "message": _('Are you sure you want to delete the source "%(name)s"?') - % {"name": source.name}, - "cancel_url": reverse("source_detail", kwargs={"slug": source.slug}), - } - return render(request, "recruitment/source_confirm_delete.html", context) +# context = { +# "source": source, +# "title": _("Delete Source: %(name)s") % {"name": source.name}, +# "message": _('Are you sure you want to delete the source "%(name)s"?') +# % {"name": source.name}, +# "cancel_url": reverse("source_detail", kwargs={"slug": source.slug}), +# } +# return render(request, "recruitment/source_confirm_delete.html", context) @login_required @@ -4696,8 +4698,7 @@ def source_toggle_status(request, slug): def application_signup(request, slug): from .forms import ApplicantSignupForm - form_template = get_object_or_404(FormTemplate, slug=slug) - job = form_template.job + job = get_object_or_404(JobPosting, slug=slug) if request.method == "POST": form = ApplicantSignupForm(request.POST) @@ -4815,8 +4816,7 @@ def interview_list(request): return render(request, "interviews/interview_list.html", context) -from django_ratelimit.decorators import ratelimit -@ratelimit(key='user_or_ip', rate='1/m', block=True) + @login_required @staff_user_required def generate_ai_questions(request, slug): @@ -5379,7 +5379,7 @@ class JobListView(LoginRequiredMixin, StaffRequiredMixin, ListView): model = JobPosting template_name = "jobs/job_list.html" context_object_name = "jobs" - paginate_by = 10 + paginate_by = 20 def get_queryset(self): queryset = super().get_queryset().order_by("-created_at") @@ -5507,8 +5507,8 @@ class ApplicationListView(LoginRequiredMixin, StaffRequiredMixin, ListView): queryset = queryset.filter(job__slug=job) if stage: queryset = queryset.filter(stage=stage) - - return queryset.order_by("-created_at") + queryset=queryset.order_by("-created_at") + return queryset def get_context_data(self, **kwargs): context = super().get_context_data(**kwargs) diff --git a/static/css/main.css b/static/css/main.css index a7120d8..43c1fa6 100644 --- a/static/css/main.css +++ b/static/css/main.css @@ -1,32 +1,45 @@ -/* - * KAAT-S Theme Styles (V2.0 - Consolidated Global, Nav, and Components) - * This file contains all variables, global layout styles, navigation, and component-specific styles. +/* * KAAT-S Theme Styles (V3.0 - Integrated Enterprise Suite) + * Consolidated Global, Sidebar CRM, Nav, and Components */ /* ---------------------------------- */ -/* 1. UI Variables and Global Reset */ +/* 1. VARIABLES & RESET */ /* ---------------------------------- */ :root { + /* Brand Colors */ --kaauh-teal: #00636e; --kaauh-teal-dark: #004a53; --kaauh-light-bg: #f9fbfd; --kaauh-border: #eaeff3; --kaauh-primary-text: #343a40; + + /* Functional Colors */ --kaauh-success: #28a745; --kaauh-info: #17a2b8; --kaauh-danger: #dc3545; --kaauh-warning: #ffc107; + --kaauh-gray-light: #f8f9fa; + + /* Sidebar Dimensions */ + --sidebar-width: 260px; + --sidebar-collapsed-width: 70px; + --topbar-height: 64px; + --sidebar-bg: #00363a; + --sidebar-hover: rgba(255, 255, 255, 0.1); + --sidebar-active: #007c8a; } -/* Primary Color Overrides */ +/* ---------------------------------- */ +/* 2. GLOBAL UTILITIES */ +/* ---------------------------------- */ .text-success { color: var(--kaauh-success) !important; } .text-info { color: var(--kaauh-info) !important; } .text-danger { color: var(--kaauh-danger) !important; } .text-warning { color: var(--kaauh-warning) !important; } -.text-primary-theme { color: var(--kaauh-teal) !important; } +.text-primary-theme, .text-primary { color: var(--kaauh-teal) !important; } .bg-primary-theme { background-color: var(--kaauh-teal) !important; } +.text-kaauh-primary { color: var(--kaauh-primary-text); } -/* Global Layout Control */ .max-width-1600 { max-width: 1600px; margin-right: auto; @@ -35,118 +48,151 @@ padding-left: var(--bs-gutter-x, 0.75rem); } -/* Global Container Padding for main content */ -.container-fluid.py-4 { padding-top: 1.5rem !important; padding-bottom: 1.5rem !important; } - -/* Main content minimum height */ main.container-fluid { min-height: calc(100vh - 200px); padding: 1.5rem 0; } /* ---------------------------------- */ -/* 2. Navigation and Header */ +/* 3. CRM SIDEBAR & LAYOUT */ /* ---------------------------------- */ +.sidebar { + width: var(--sidebar-width); + height: 100vh; + position: fixed; + top: 0; + left: 0; + background-color: var(--sidebar-bg); + z-index: 1050; + transition: all 0.3s cubic-bezier(0.4, 0, 0.2, 1); + display: flex; + flex-direction: column; + box-shadow: 4px 0 10px rgba(0,0,0,0.1); + overflow-x: hidden; +} -/* Top Bar (Contact/Social) */ +.sidebar-brand { + padding: 1.25rem; + text-align: center; + border-bottom: 1px solid rgba(255, 255, 255, 0.08); +} + +.sidebar-nav { + padding: 1.25rem 0; + flex-grow: 1; + overflow-y: auto; +} + +/* Sidebar Links */ +.nav-link-custom { + display: flex; + align-items: center; + padding: 0.85rem 1.5rem; + color: rgba(255, 255, 255, 0.7); + text-decoration: none !important; + transition: all 0.2s ease; + margin-bottom: 0.25rem; + font-weight: 500; + font-size: 0.95rem; + border-left: 4px solid transparent; + white-space: nowrap; +} + +.nav-link-custom:hover { + color: #fff; + background-color: var(--sidebar-hover); +} + +.nav-link-custom.active { + color: #fff; + background-color: var(--sidebar-active); + border-left: 4px solid var(--kaauh-warning); +} + +.nav-link-custom i { + width: 28px; + font-size: 1.1rem; + opacity: 0.9; +} + +/* Main Content Wrapper */ +.main-wrapper { + margin-left: var(--sidebar-width); + min-height: 100vh; + display: flex; + flex-direction: column; + transition: all 0.3s ease; +} + +.content-header { + height: var(--topbar-height); + background: #ffffff; + border-bottom: 1px solid var(--kaauh-border); + display: flex; + align-items: center; + padding: 0 1.5rem; + position: sticky; + top: 0; + z-index: 1000; +} + +/* Sidebar Collapse Logic */ +.sidebar.collapsed { + width: var(--sidebar-collapsed-width); +} + +.sidebar.collapsed + .main-wrapper { + margin-left: var(--sidebar-collapsed-width); +} + +.sidebar.collapsed .nav-link-custom span, +.sidebar.collapsed .sidebar-brand .fw-bold, +.sidebar.collapsed .badge, +.sidebar.collapsed .brand-subtitle { + display: none !important; +} + +.sidebar.collapsed .nav-link-custom i { + margin: 0 !important; + font-size: 1.2rem; + width: 100%; + text-align: center; +} + +/* ---------------------------------- */ +/* 4. NAVIGATION COMPONENTS */ +/* ---------------------------------- */ .top-bar { background-color: white; border-bottom: 1px solid var(--kaauh-border); font-size: 0.825rem; padding: 0.4rem 0; } -.top-bar a { text-decoration: none; } -.top-bar .social-icons i { - color: var(--kaauh-teal); - transition: color 0.2s; -} -.top-bar .social-icons i:hover { - color: var(--kaauh-teal-dark); -} -.top-bar .contact-item { - display: flex; - align-items: center; - gap: 0.35rem; - padding: 0.25rem 0.5rem; -} -.top-bar .logo-container img { - height: 60px; - object-fit: contain; -} -@media (max-width: 767.98px) { - .top-bar { - display: none; - } -} -/* Navbar */ -.navbar-brand { - font-weight: 700; - letter-spacing: -0.5px; - font-size: 1.25rem; - display: flex; - align-items: center; - gap: 0.5rem; -} .navbar-dark { background-color: var(--kaauh-teal) !important; box-shadow: 0 2px 6px rgba(0,0,0,0.12); } -/* Ensure the inner container of the navbar stretches to allow max-width-1600 */ -.navbar-dark > .container { - max-width: 100%; -} + .nav-link { font-weight: 500; transition: all 0.2s ease; - padding: 0.5rem 0.75rem; } -.nav-link:hover, -.nav-link.active { + +.nav-link:hover, .nav-link.active { color: white !important; background: rgba(255,255,255,0.12) !important; border-radius: 4px; } -/* Dropdown */ .dropdown-menu { backdrop-filter: blur(4px); background-color: rgba(255, 255, 255, 0.98); border: 1px solid var(--kaauh-border); box-shadow: 0 6px 20px rgba(0,0,0,0.12); border-radius: 8px; - padding: 0.5rem 0; - min-width: 200px; - will-change: transform, opacity; - transition: transform 0.2s ease, opacity 0.2s ease; -} -.dropdown-item { - padding: 0.5rem 1.25rem; - transition: background-color 0.15s; -} -.dropdown-item:hover { - background-color: var(--kaauh-light-bg); - color: var(--kaauh-teal-dark); } -/* Language Toggle Button Style */ -.language-toggle-btn { - color: white !important; - background: none !important; - border: none !important; - display: flex; - align-items: center; - gap: 0.3rem; - padding: 0.5rem 0.75rem !important; - font-weight: 500; - transition: all 0.2s ease; -} -.language-toggle-btn:hover { - background: rgba(255,255,255,0.12) !important; - border-radius: 4px; -} - -/* Profile Avatar */ .profile-avatar { width: 36px; height: 36px; @@ -157,42 +203,28 @@ main.container-fluid { justify-content: center; color: white; font-weight: bold; - font-size: 0.85rem; - transition: transform 0.1s ease; -} -.navbar-nav .dropdown-toggle:hover .profile-avatar { - transform: scale(1.05); -} -.navbar-nav .dropdown-toggle.p-0:hover { - background: none !important; } - /* ---------------------------------- */ -/* 3. Component Styles (Cards & Forms)*/ +/* 5. CARDS, FORMS & TYPOGRAPHY */ /* ---------------------------------- */ -.kaauh-card { +.kaauh-card, .card { border: 1px solid var(--kaauh-border); border-radius: 0.75rem; box-shadow: 0 4px 12px rgba(0,0,0,0.06); background-color: white; + overflow: hidden; } -/* NEW: Filter Controls Container Style */ -.filter-controls { +.filter-controls, .tier-controls { border: 1px solid var(--kaauh-border); border-radius: 0.75rem; - box-shadow: 0 4px 12px rgba(0,0,0,0.06); background-color: white; - padding: 1.5rem; /* Consistent internal padding */ - margin-bottom: 1.5rem; /* Space below filter */ + padding: 1.5rem; + margin-bottom: 1.5rem; } -/* Typography & Headers */ -.page-header { - color: var(--kaauh-teal-dark); - font-weight: 700; -} +.page-header { color: var(--kaauh-teal-dark); font-weight: 700; } .section-header { color: var(--kaauh-primary-text); font-weight: 600; @@ -200,14 +232,7 @@ main.container-fluid { padding-bottom: 0.5rem; margin-bottom: 1rem; } -label { - font-weight: 500; - color: var(--kaauh-primary-text); - font-size: 0.9rem; - margin-bottom: 0.25rem; -} -/* Forms - Default Size */ .form-control, .form-select { border-radius: 0.5rem; border: 1px solid #ced4da; @@ -215,71 +240,13 @@ label { font-size: 0.9rem; } -/* Forms - Compact Size (for modals/tables) */ -.form-control-sm, -.form-select-sm, -.btn-sm { - padding: 0.25rem 0.5rem !important; /* Adjusted padding */ +.form-control-sm, .form-select-sm, .btn-sm { + padding: 0.25rem 0.5rem !important; font-size: 0.8rem !important; - line-height: 1.25 !important; /* Standard small line height */ - height: auto !important; } -.form-select-sm { - padding: 0.25rem 2rem 0.25rem 0.5rem !important; /* Increased right padding for arrow */ - font-size: 0.8rem !important; - line-height: 1.25 !important; - height: auto !important; /* Remove fixed height */ - border-radius: 0.5rem; - border: 1px solid #ced4da; -} - -/* Scrollable Multiple Select Fix */ -.form-group select[multiple] { - max-height: 450px; - overflow-y: auto; - min-height: 250px; - padding: 0; -} - -/* Break Times Section Styling (Schedule Interviews) */ -.break-time-form { - background-color: #f8f9fa; - padding: 0.75rem; - border-radius: 0.5rem; - border: 1px solid var(--kaauh-border); - align-items: flex-end; -} -.note-box { - background-color: #fff3cd; - border-left: 5px solid var(--kaauh-warning); - padding: 1rem; - border-radius: 0.25rem; - font-size: 0.9rem; - margin-bottom: 1rem; -} - -/* Tier Controls (Kept for consistency/future use) */ -.tier-controls { - background-color: var(--kaauh-border); - border-radius: 0.75rem; - padding: 1.25rem; - margin-bottom: 2rem; - border: 1px solid var(--kaauh-border); -} -.tier-controls .form-row { - display: flex; - align-items: end; - gap: 1rem; -} -.tier-controls .form-group { - flex: 1; - margin-bottom: 0; -} - - /* ---------------------------------- */ -/* 4. Button Styles (Component Themed)*/ +/* 6. BUTTONS */ /* ---------------------------------- */ .btn-main-action { background-color: var(--kaauh-teal); @@ -295,6 +262,15 @@ label { } .btn-main-action.btn-sm { font-weight: 600 !important; } + +.btn-outline-primary { + color: var(--kaauh-teal); + border-color: var(--kaauh-teal); +} +.btn-outline-primary:hover { + background-color: var(--kaauh-teal); + color: white; +} .btn-outline-secondary { color: var(--kaauh-teal-dark); border-color: var(--kaauh-teal); @@ -305,6 +281,7 @@ label { border-color: var(--kaauh-teal-dark); } + .btn-bulk-pass { background-color: var(--kaauh-success); border-color: var(--kaauh-success); @@ -344,394 +321,143 @@ label { } /* ---------------------------------- */ -/* 5. Table & Footer Styles */ +/* 7. TABLES & PAGINATION */ /* ---------------------------------- */ -.candidate-table { - table-layout: fixed; +.candidate-table, .job-table { width: 100%; border-collapse: separate; - border-spacing: 0; background-color: white; border-radius: 0.5rem; overflow: hidden; - box-shadow: 0 4px 12px rgba(0,0,0,0.06); -} -.candidate-table thead { - background-color: var(--kaauh-border); -} -.candidate-table th { - padding: 0.75rem; - font-weight: 600; - color: var(--kaauh-teal-dark); - border-bottom: 2px solid var(--kaauh-teal); - font-size: 0.9rem; - vertical-align: middle; -} -.candidate-table td { - padding: 0.75rem; - border-bottom: 1px solid var(--kaauh-border); - vertical-align: middle; - font-size: 0.9rem; -} -.candidate-table tbody tr:hover { - background-color: #f1f3f4; -} -.candidate-name { - font-weight: 600; - color: var(--kaauh-primary-text); -} -.candidate-details { - font-size: 0.8rem; - color: #6c757d; } -/* Job Table Specific Styles */ -.job-table-wrapper { - background: white; - border-radius: 10px; - overflow: hidden; - box-shadow: 0 4px 16px rgba(0,0,0,0.06); - margin-bottom: 2rem; +.candidate-table th { + background-color: var(--kaauh-border); + color: var(--kaauh-teal-dark); + font-weight: 600; + padding: 0.75rem; + border-bottom: 2px solid var(--kaauh-teal); } + .job-table thead th { background: var(--kaauh-teal); color: white; - font-weight: 600; padding: 1rem; - text-align: center; -} -.job-table td { - padding: 1rem; - vertical-align: middle; - text-align: center; -} -.job-table tr:hover td { - background-color: rgba(0, 99, 110, 0.03); } -/* Table Responsiveness */ -@media (max-width: 575.98px) { - .table-responsive { - overflow-x: auto; - -webkit-overflow-scrolling: touch; - } - .job-table th, - .job-table td { - white-space: nowrap; - font-size: 0.875rem; - } +.pagination .page-link { + color: var(--kaauh-teal); + border-color: var(--kaauh-border); } -/* Bulk Action Bar (Interview Management) */ -.bulk-action-bar { - display: flex; - align-items: center; - gap: 0.5rem; - padding-bottom: 0.75rem; - margin-bottom: 1rem; - border-bottom: 1px solid var(--kaauh-border); -} -.action-group { - display: flex; - align-items: center; - gap: 0.5rem; -} - -/* Badges (Adapted for Interview Tiers/Status) */ -.ai-score-badge { /* Used as an all-purpose secondary badge */ - background-color: var(--kaauh-teal-dark) !important; +.pagination .page-item.active .page-link { + background-color: var(--kaauh-teal); + border-color: var(--kaauh-teal); color: white; - font-weight: 700; - padding: 0.4em 0.8em; - border-radius: 0.4rem; - font-size: 0.8rem; } -.tier-badge { /* Used for Tier labels */ + +/* ---------------------------------- */ +/* 8. BADGES & TIMELINE */ +/* ---------------------------------- */ +.tier-badge, .stage-badge, .status-badge { font-size: 0.75rem; - padding: 0.125rem 0.5rem; - border-radius: 0.5rem; + padding: 0.25rem 0.6rem; + border-radius: 0.4rem; font-weight: 600; - margin-left: 0.5rem; display: inline-block; } + .tier-1-badge { background-color: var(--kaauh-success); color: white; } -.tier-2-badge { background-color: var(--kaauh-warning); color: #856404; } -.tier-3-badge { background-color: #d1ecf1; color: #0c5460; } -.cd_interview{ color: #00636e; } - -/* NEW: Application Stage Badges */ -.stage-badge { - font-size: 0.8rem; - padding: 0.2em 0.6em; - border-radius: 0.4rem; - font-weight: 600; - display: inline-block; - margin-top: 0.25rem; -} -.stage-Application { background-color: #e9ecef; color: #495057; } -.stage-Screening { background-color: #d1ecf1; color: #0c5460; } -.stage-Exam { background-color: #cce5ff; color: #004085; } .stage-Interview { background-color: #fff3cd; color: #856404; } -.stage-Offer { background-color: #d4edda; color: #155724; } -/* NEW: Applicant Status Badges */ -.status-badge { - font-size: 0.8rem; - padding: 0.2em 0.6em; - border-radius: 0.4rem; - font-weight: 500; - display: inline-block; -} -.bg-candidate { background-color: var(--kaauh-teal-dark); color: white; } -.bg-applicant { background-color: #f8f9fa; color: #495057; border: 1px solid #ced4da; } - -/* Table Column Width Fixes */ -.candidate-table th:nth-child(1) { width: 40px; } -.candidate-table th:nth-child(4) { width: 15%; } -.candidate-table th:nth-child(5) { width: 80px; } -.candidate-table th:nth-child(6) { width: 180px; } - -/* Footer & Alerts */ -.footer { - background: var(--kaauh-light-bg); - padding: 1.5rem 0; - border-top: 1px solid var(--kaauh-border); - font-size: 0.9rem; - color: #555; -} -.alert { - border: none; - border-radius: 8px; - box-shadow: 0 2px 6px rgba(0,0,0,0.05); -} - -/* ---------------------------------- */ -/* 6. RTL Support */ -/* ---------------------------------- */ -html[dir="rtl"] { - text-align: right; - direction: rtl; -} -html[dir="rtl"] .navbar-brand { - flex-direction: row-reverse; -} -html[dir="rtl"] .dropdown-menu { - right: auto; - left: 0; -} -/* RTL Spacing adjustments */ -html[dir="rtl"] .me-3 { margin-right: 0 !important; margin-left: 1rem !important; } -html[dir="rtl"] .ms-3 { margin-left: 0 !important; margin-right: 1rem !important; } -html[dir="rtl"] .me-2 { margin-right: 0 !important; margin-left: 0.5rem !important; } -html[dir="rtl"] .ms-2 { margin-left: 0 !important; margin-right: 0.5rem !important; } -html[dir="rtl"] .ms-auto { margin-left: 0 !important; margin-right: auto !important; } -html[dir="rtl"] .me-auto { margin-right: 0 !important; margin-left: auto !important; } - - -/* ================================================= */ -/* 1. THEME VARIABLES AND GLOBAL STYLES */ -/* ================================================= */ -:root { - --kaauh-teal: #00636e; - --kaauh-teal-dark: #004a53; - --kaauh-border: #eaeff3; - --kaauh-primary-text: #343a40; -} - -/* Primary Color Overrides */ -.text-primary { color: var(--kaauh-teal) !important; } -.text-info { color: #17a2b8 !important; } -.text-success { color: #28a745 !important; } -.text-secondary { color: #6c757d !important; } -.text-kaauh-primary { color: var(--kaauh-primary-text); } /* Custom class for primary text color if needed */ - - -/* ---------------------------------- */ -/* 2. Button Styles */ -/* ---------------------------------- */ - -/* Main Action Button Style (Used for Download Resume) */ -.btn-main-action { - background-color: var(--kaauh-teal); - border-color: var(--kaauh-teal); - color: white; - font-weight: 600; - padding: 0.6rem 1.2rem; - transition: all 0.2s ease; - display: inline-flex; - align-items: center; - gap: 0.5rem; -} -.btn-main-action:hover { - background-color: var(--kaauh-teal-dark); - border-color: var(--kaauh-teal-dark); - transform: translateY(-1px); - box-shadow: 0 4px 8px rgba(0,0,0,0.15); -} - -/* Outlined Button Styles */ -.btn-outline-primary { - color: var(--kaauh-teal); - border-color: var(--kaauh-teal); -} -.btn-outline-primary:hover { - background-color: var(--kaauh-teal); - color: white; -} -.btn-outline-secondary { - color: var(--kaauh-teal-dark); - border-color: var(--kaauh-teal); -} -.btn-outline-secondary:hover { - background-color: var(--kaauh-teal-dark); - color: white; - border-color: var(--kaauh-teal-dark); -} - -/* ---------------------------------- */ -/* 3. Card/Modal Styles */ -/* ---------------------------------- */ - -/* Card enhancements */ -.kaauh-card, .card { - border: 1px solid var(--kaauh-border); - border-radius: 0.75rem; - overflow: hidden; - box-shadow: 0 4px 12px rgba(0,0,0,0.06); - background-color: white; -} - -/* Candidate Header Card (The teal header) */ -.candidate-header-card { - background: linear-gradient(135deg, var(--kaauh-teal), #004d57); - color: white; - border-radius: 0.75rem 0.75rem 0 0; - padding: 1.5rem; - box-shadow: 0 4px 10px rgba(0,0,0,0.15); -} -.candidate-header-card h1 { - font-weight: 700; - margin: 0; - font-size: 1.8rem; -} -.candidate-header-card .badge { - font-size: 0.9rem; - padding: 0.4em 0.8em; - border-radius: 0.4rem; - font-weight: 700; -} - -/* ---------------------------------- */ -/* 4. Tab Navigation Styles (Candidate Detail View) */ -/* ---------------------------------- */ - -/* Left Column Tabs (Main Content Tabs) */ -.main-tabs { - border-bottom: 1px solid var(--kaauh-border); - background-color: #f8f9fa; - padding: 0 1.25rem; -} -.main-tabs .nav-link { - border: none; - border-bottom: 3px solid transparent; - color: var(--kaauh-primary-text); - font-weight: 500; - padding: 0.75rem 1rem; - margin-right: 0.5rem; - transition: all 0.2s; -} -.main-tabs .nav-link:hover { - color: var(--kaauh-teal); -} -.main-tabs .nav-link.active { - color: var(--kaauh-teal-dark) !important; - background-color: white !important; - border-bottom: 3px solid var(--kaauh-teal); - font-weight: 600; -} - -/* Right Column Card (General styling for tab content if needed) */ -.right-column-card .tab-content { - padding: 1.5rem 1.25rem; - background-color: white; -} - -/* ---------------------------------- */ -/* 5. Vertical Timeline Styling */ -/* ---------------------------------- */ - -/* Highlight box for the current stage */ -.current-stage { - border: 1px solid var(--kaauh-border); - background-color: #f0f8ff; /* Light, subtle blue background */ -} -.current-stage .text-primary { - color: var(--kaauh-teal) !important; -} - -.timeline { - position: relative; - padding-left: 2rem; -} +.timeline { position: relative; padding-left: 2rem; } .timeline::before { - content: ''; - position: absolute; - top: 0; - bottom: 0; - left: 1.25rem; - width: 2px; - background-color: var(--kaauh-border); -} -.timeline-item { - position: relative; - margin-bottom: 2rem; - padding-left: 1.5rem; + content: ''; position: absolute; top: 0; bottom: 0; left: 1.25rem; + width: 2px; background-color: var(--kaauh-border); } + .timeline-icon { - position: absolute; - left: 0; - top: 0; - width: 32px; - height: 32px; - border-radius: 50%; - display: flex; - align-items: center; - justify-content: center; - color: white; - font-size: 0.8rem; - z-index: 10; - border: 4px solid white; -} -.timeline-item:last-child { - margin-bottom: 0; + position: absolute; left: 0; top: 0; width: 32px; height: 32px; + border-radius: 50%; display: flex; align-items: center; justify-content: center; + color: white; border: 4px solid white; z-index: 10; } -/* Custom Timeline Background Classes for Stages (Using Bootstrap color palette) */ -.timeline-bg-applied { background-color: var(--kaauh-teal) !important; } -.timeline-bg-exam { background-color: #17a2b8 !important; } -.timeline-bg-interview { background-color: #ffc107 !important; } -.timeline-bg-offer { background-color: #28a745 !important; } -.timeline-bg-rejected { background-color: #dc3545 !important; } -.loading { - background: linear-gradient(135deg, var(--kaauh-teal), #004d57); - color: white; - border-radius: 0.75rem 0.75rem 0 0; - padding: 1.5rem; - box-shadow: 0 4px 10px rgba(0,0,0,0.15); +/* ---------------------------------- */ +/* 9. RTL SUPPORT */ +/* ---------------------------------- */ +html[dir="rtl"] { text-align: right; direction: rtl; } + +html[dir="rtl"] .sidebar { + left: auto; right: 0; + box-shadow: -4px 0 10px rgba(0,0,0,0.1); } +html[dir="rtl"] .main-wrapper { + margin-left: 0; + margin-right: var(--sidebar-width); +} - /* Breadcrumb Styling */ - .breadcrumb { - background-color: transparent; - padding: 0; - margin-bottom: 1rem; - } +html[dir="rtl"] .sidebar.collapsed + .main-wrapper { + margin-right: var(--sidebar-collapsed-width); +} - .breadcrumb-item + .breadcrumb-item::before { - content: ">"; - color: var(--kaauh-teal); - } +html[dir="rtl"] .nav-link-custom { + border-left: none; + border-right: 4px solid transparent; +} +html[dir="rtl"] .nav-link-custom.active { + border-right: 4px solid var(--kaauh-warning); +} - \ No newline at end of file +/* ---------------------------------- */ +/* 10. RESPONSIVE */ +/* ---------------------------------- */ +@media (max-width: 991.98px) { + .sidebar { left: calc(-1 * var(--sidebar-width)); } + html[dir="rtl"] .sidebar { right: calc(-1 * var(--sidebar-width)); left: auto; } + + .sidebar.show { left: 0; } + html[dir="rtl"] .sidebar.show { right: 0; } + + .main-wrapper { margin-left: 0 !important; margin-right: 0 !important; } +} + +/* --- Logout Section Improvements --- */ +.sidebar .logout-section { + padding: 0.85rem 1.5rem; /* Match nav-link-custom padding */ + transition: all 0.3s ease; + border-top: 1px solid rgba(255, 255, 255, 0.08); +} + +.sidebar.collapsed .logout-section { + padding: 0.85rem 0; + text-align: center; +} + +.sidebar .logout-section button { + color: rgba(255, 255, 255, 0.7) !important; + width: 100%; + justify-content: flex-start; + transition: color 0.2s; +} + +.sidebar .logout-section button:hover { + color: var(--kaauh-danger) !important; +} + +/* Hide text and handle icon centering in collapsed mode */ +.sidebar.collapsed .logout-section span { + display: none !important; +} + +.sidebar.collapsed .logout-section i { + margin: 0 !important; + width: 100%; + font-size: 1.1rem; +} + +/* Ensure form doesn't add extra margins */ +.sidebar .logout-section form { + margin: 0; +} \ No newline at end of file diff --git a/templates/account/email.html b/templates/account/email.html index 5979a19..57f7372 100644 --- a/templates/account/email.html +++ b/templates/account/email.html @@ -3,7 +3,7 @@ {% load account %} {% load crispy_forms_tags %} -{% block title %}{% translate "Email Addresses" %}{% endblock %} +{% block title %}{% trans "Email Addresses" %}{% endblock %} {% block content %}
diff --git a/templates/account/login.html b/templates/account/login.html index ba7a332..8d408ac 100644 --- a/templates/account/login.html +++ b/templates/account/login.html @@ -6,7 +6,7 @@ - KAAUH ATS - Sign In (Bootstrap) + {% trans "KAAUH ATS - Sign In" %} diff --git a/templates/account/logout.html b/templates/account/logout.html index 4af2a35..539f669 100644 --- a/templates/account/logout.html +++ b/templates/account/logout.html @@ -2,15 +2,15 @@ {% load i18n %} {% load account %} -{% block title %}{% translate "Sign Out" %}{% endblock %} +{% block title %}{% trans "Sign Out" %}{% endblock %} {% block content %}
-

{% translate "Account Settings" %}

-

{% translate "Manage your personal details and security." %}

+

{% trans "Account Settings" %}

+

{% trans "Manage your personal details and security." %}

@@ -23,18 +23,18 @@
@@ -47,9 +47,9 @@
-

{% translate "Confirm Sign Out" %}

+

{% trans "Confirm Sign Out" %}

-

{% translate "Are you sure you want to sign out of your account?" %}

+

{% trans "Are you sure you want to sign out of your account?" %}

{% csrf_token %} @@ -63,12 +63,12 @@
{# Sign Out button in danger color #} {# Cancel/Go Back button with outline #} - {% translate "Cancel" %} + {% trans "Cancel" %}
diff --git a/templates/account/password_reset.html b/templates/account/password_reset.html index 98ae130..3a75efc 100644 --- a/templates/account/password_reset.html +++ b/templates/account/password_reset.html @@ -4,7 +4,7 @@ - KAAUH ATS - Sign In (Bootstrap) + {% trans Reset Password %}-KAAUH ATS diff --git a/templates/account/verification_sent.html b/templates/account/verification_sent.html index 0718199..e0039cb 100644 --- a/templates/account/verification_sent.html +++ b/templates/account/verification_sent.html @@ -7,7 +7,7 @@ - KAAUH ATS - Verify Email + {% trans "Verify Email" %}-KAAUH ATS diff --git a/templates/applicant/application_submit_form.html b/templates/applicant/application_submit_form.html index cbb8b5c..e794788 100644 --- a/templates/applicant/application_submit_form.html +++ b/templates/applicant/application_submit_form.html @@ -1,4 +1,5 @@ {% extends 'applicant/partials/candidate_facing_base.html'%} + {% load static i18n %} {% block content %} -{% endblock %} - -{% block content %} -
- - {# --- TOP BAR --- #} -
- - {% trans "Back to Meetings" %} - -
- - {% trans "Edit Meeting" %} - -
- {% csrf_token %} - -
-
-
- - {# --- MAIN TITLE --- #} -
-

- - {{ meeting.topic|default:"[Meeting Topic]" }} - - {{ interview.get_status_display|default:"Scheduled" }} - -

-
- - {# --- INTERVIEW & CONNECTION CARDS --- #} -
- {# Interview Detail #} -
-
-

{% trans "Interview Detail" %}

-
-
-
{% trans "Job Title" %}:
-
{{ job.title|default:"N/A" }}
-
-
-
{% trans "Candidate Name" %}:
-
{{ candidate.full_name|default:"N/A" }}
-
-
-
{% trans "Candidate Email" %}:
-
{{ candidate.email|default:"N/A" }}
-
-
-
{% trans "Job Type" %}:
-
{{ job.job_type|default:"N/A" }}
-
- {% if candidate.belong_to_agency %} -
-
{% trans "Agency" %}:
-
{{ candidate.hiring_agency.name|default:"N/A" }}
-
- {% endif %} -
-
-
- - {# Connection Details #} -
-
-

{% trans "Connection Details" %}

-
-
-
{% trans "Date & Time" %}:
-
- {{ interview.interview_date }} {{ interview.interview_time }} ({{ meeting.timezone }}) -
-
-
-
{% trans "Duration" %}:
-
- {% if meeting.location_type == "Remote" %} - {{ meeting.zoommeetingdetails.duration|default:"N/A" }} - {% elif meeting.location_type == "Onsite" %} - {{ meeting.onsitelocationdetails.duration|default:"N/A" }} - {% else %} - N/A - {% endif %} - {% trans "minutes" %} -
-
- - {% if meeting.location_type == "Remote" %} - {% with zoom=meeting.zoommeetingdetails %} -
-
{% trans "Meeting ID" %}:
-
{{ zoom.meeting_id|default:"N/A" }}
-
-
-
{% trans "Host Email" %}:
-
{{ zoom.host_email|default:"N/A" }}
-
- {% if meeting.details_url %} -
-
- {% trans "Copied!" %} -
-
-
- {% trans "Join URL" %}: - {{ meeting.details_url }} -
- -
-
- {% endif %} - {% endwith %} - {% elif meeting.location_type == "Onsite" %} - {% with onsite=meeting.onsitelocationdetails %} -
-
{% trans "Address" %}:
-
{{ onsite.physical_address|default:"N/A" }}
-
-
-
{% trans "Room" %}:
-
{{ onsite.room_number|default:"TBD" }}
-
- {% endwith %} - {% endif %} -
-
-
-
- - {# --- PARTICIPANTS --- #} - {% comment %}
-
-
-
-

{% trans "Assigned Participants" %}

-
- - -
-
- - - - - - - - - - - - - {% for participant in external_participants %} - - - - - - - - {% endfor %} - {% for user in system_participants %} - - - - - - - - {% endfor %} - -
{% trans "Name" %}{% trans "Role" %}{% trans "Email" %}{% trans "Phone" %}{% trans "Type" %}
{{ participant.name }}{{ participant.designation|default:"Participant" }}{{ participant.email|default:"N/A" }}{{ participant.phone|default:"N/A" }}{% trans "External" %}
{{ user.get_full_name|default:user.username }}Admin{{ user.email|default:"N/A" }}{{ user.phone|default:"N/A" }}{% trans "System User" %}
-
-
-
{% endcomment %} - - {# --- COMMENTS --- #} -
-
-
-
-
- - {% trans "Comments" %} ({{ interview.notes.count }}) -
-
-
-
- {% for note in interview.notes.all|dictsortreversed:"created_at" %} -
-
-
- - {% if note.author == user or user.is_staff %} -
- -
- {% csrf_token %} - -
-
- {% endif %} -
-

{{ note.content|linebreaksbr }}

-
- - -
- {% empty %} -

{% trans "No comments yet. Be the first to comment!" %}

- {% endfor %} -
- -
-
{% trans "Add a New Comment" %}
-
- {% csrf_token %} -
- - -
- -
-
-
-
-
-
- -{# MODALS #} - - - - - - -{% endblock %} - -{% block customJS %} - -{% endblock %} \ No newline at end of file diff --git a/templates/interviews/interview_create_onsite.html b/templates/interviews/interview_create_onsite.html index 17a8410..384f9b1 100644 --- a/templates/interviews/interview_create_onsite.html +++ b/templates/interviews/interview_create_onsite.html @@ -11,7 +11,7 @@

- Create Onsite Interview for {{ application.name }} + {% trans "Create Onsite Interview for" %} {{ application.name }}

@@ -21,8 +21,8 @@

- Schedule an onsite interview for {{ application.name }} - for the position of {{ job.title }}. + {% trans "Schedule an onsite interview for" %} {{ application.name }} + {% trans "for the position of" %} {{ job.title }}.

{% if messages %} diff --git a/templates/interviews/interview_create_remote.html b/templates/interviews/interview_create_remote.html index 9bf7c9d..d65e19a 100644 --- a/templates/interviews/interview_create_remote.html +++ b/templates/interviews/interview_create_remote.html @@ -11,7 +11,7 @@

- Schedule a remote interview for {{ application.name }} - for the position of {{ job.title }}. + {% trans "Schedule a remote interview for" %} {{ application.name }} + {% trans "for the position of" %} {{ job.title }}.

{% if messages %} diff --git a/templates/interviews/interview_create_type_selection.html b/templates/interviews/interview_create_type_selection.html index 72ea9d6..9ae0409 100644 --- a/templates/interviews/interview_create_type_selection.html +++ b/templates/interviews/interview_create_type_selection.html @@ -11,13 +11,13 @@

- Create Interview for {{ application.name }} + {% trans "Create Interview for" %} {{ application.name }}

- Select the type of interview you want to schedule for {{ application.name }} - for the position of {{ job.title }}. + {% trans "Select the type of interview you want to schedule for" %} {{ application.name }} + {% trans "for the position of" %} {{ job.title }}.

diff --git a/templates/interviews/interview_detail.html b/templates/interviews/interview_detail.html index 0fc3317..b098c8c 100644 --- a/templates/interviews/interview_detail.html +++ b/templates/interviews/interview_detail.html @@ -518,20 +518,35 @@
-
-
- {% trans "AI Generated Questions" %} -
-
-
- {% csrf_token %} - -
+ +
+
diff --git a/templates/interviews/interview_list.html b/templates/interviews/interview_list.html index 1b54cec..9b4c6a3 100644 --- a/templates/interviews/interview_list.html +++ b/templates/interviews/interview_list.html @@ -1,7 +1,7 @@ {% extends 'base.html' %} {% load static i18n %} -{% block title %}{% trans "Interview Management" %} - ATS{% endblock %} +{% block title %}{% trans "Interviews" %} - ATS{% endblock %} {% block customCSS %} {% endblock %} diff --git a/templates/interviews/onsite_location_form.html b/templates/interviews/onsite_location_form.html index dde8002..80727cb 100644 --- a/templates/interviews/onsite_location_form.html +++ b/templates/interviews/onsite_location_form.html @@ -6,7 +6,7 @@
-

Set Interview Location

+

{% trans "Set Interview Location" %}

@@ -18,12 +18,12 @@
- Close + {% trans "Close" %}
diff --git a/templates/interviews/partials/interview_list.html b/templates/interviews/partials/interview_list.html index 8683408..d15a4f5 100644 --- a/templates/interviews/partials/interview_list.html +++ b/templates/interviews/partials/interview_list.html @@ -28,7 +28,7 @@ -
View + {% trans "View" %} {% empty %} diff --git a/templates/interviews/preview_schedule.html b/templates/interviews/preview_schedule.html index 44bc1a0..39bb8e2 100644 --- a/templates/interviews/preview_schedule.html +++ b/templates/interviews/preview_schedule.html @@ -1,7 +1,7 @@ {% extends "base.html" %} {% load static crispy_forms_tags %} {%load i18n %} - +{% block title%} {% trans "Preview Interview Schedule" %}{%endblock%} {% block customCSS %} {% endblock %} {% block content %} -
-
-
-

Interview Calendar

-
- {{ job.title }} -
+
+
+
+

{% trans "Interview Calendar" %}

+

{{ job.title|default:"Global Schedule" }}

+
+
+

Tenhal | تنحل

@@ -128,42 +93,44 @@
- Scheduled + {% trans "Scheduled" %}
- Confirmed + {% trans "Confirmed" %}
- Cancelled + {% trans "Cancelled" %}
- Completed + {% trans "Completed" %}
-