ATS/templates/recruitment/agency_assignment_form.html
2026-02-01 19:47:32 +03:00

289 lines
15 KiB
HTML

{% extends "base.html" %}
{% load static i18n %}
{% block title %}{{ title }} - {{ block.super }}{% endblock %}
{% block content %}
<div class="max-w-4xl mx-auto py-6 px-4">
<!-- Breadcrumb -->
<nav class="mb-6" aria-label="breadcrumb">
<ol class="flex items-center gap-2 text-sm flex-wrap">
<li><a href="{% url 'agency_assignment_list' %}" class="text-gray-500 hover:underline transition flex items-center gap-1">
<i data-lucide="briefcase" class="w-4 h-4"></i> {% trans "Assignments" %}
</a></li>
<li class="text-gray-400">/</li>
<li class="font-semibold" style="color: #9d2235;">{{ title }}</li>
</ol>
</nav>
<!-- Header -->
<div class="flex flex-col sm:flex-row justify-between items-start sm:items-center gap-4 mb-6">
<h1 class="text-2xl sm:text-3xl font-bold flex items-center gap-3">
<div class="w-12 h-12 rounded-xl flex items-center justify-center" style="background-color: rgba(157, 34, 53, 0.1);">
<i data-lucide="briefcase" class="w-6 h-6" style="color: #9d2235;"></i>
</div>
{{ title }}
</h1>
<a href="{% url 'agency_assignment_list' %}"
class="inline-flex items-center gap-2 px-6 py-3 rounded-lg font-medium border-2 border-gray-200 text-gray-700 hover:bg-gray-50 transition-all duration-200">
<i data-lucide="arrow-left" class="w-4 h-4"></i>
<span class="hidden sm:inline">{% trans "Back to List" %}</span>
</a>
</div>
<!-- Info Card -->
<div class="bg-white rounded-xl shadow-sm border border-gray-200 mb-6 p-6">
<div class="rounded-lg p-4 border-l-4" style="background-color: #eff6ff; border-color: #9d2235;">
<h6 class="font-bold mb-2 flex items-center gap-2" style="color: #9d2235;">
<i data-lucide="info" class="w-4 h-4"></i>
{% trans "About Assignments" %}
</h6>
<p class="text-gray-600 text-sm">
{% trans "Assign a job to an external hiring agency. The agency will be able to submit candidates for this position until the deadline." %}
</p>
</div>
</div>
<!-- Form Card -->
<div class="bg-white rounded-xl shadow-sm border border-gray-200">
<div class="px-6 py-4 border-b border-gray-100" style="background-color: #f8f9fa;">
<h2 class="text-lg font-bold flex items-center gap-2">
<i data-lucide="briefcase" class="w-5 h-5" style="color: #9d2235;"></i>
{% trans "Assignment Details" %}
</h2>
</div>
<div class="p-6">
{% if form.non_field_errors %}
<div class="mb-6 p-4 rounded-lg bg-red-50 border border-red-200" role="alert">
<div class="flex items-start gap-3">
<i data-lucide="alert-triangle" class="w-5 h-5 text-red-600 flex-shrink-0 mt-0.5"></i>
<div>
<h5 class="font-semibold text-red-800 mb-1">{% trans "Error" %}</h5>
{% for error in form.non_field_errors %}
<p class="text-red-700 mb-0">{{ error }}</p>
{% endfor %}
</div>
</div>
</div>
{% endif %}
<form method="post" novalidate id="assignment-form" class="space-y-6">
{% csrf_token %}
<div class="grid grid-cols-1 md:grid-cols-2 gap-4">
<!-- Agency -->
<div>
<label for="{{ form.agency.id_for_label }}" class="block text-sm font-semibold text-gray-700 mb-2">
{{ form.agency.label }} <span class="text-red-500">*</span>
</label>
<select name="agency" id="{{ form.agency.id_for_label }}"
class="w-full px-4 py-3 border border-gray-200 rounded-xl text-sm focus:ring-2 focus:ring-temple-red/20 focus:border-temple-red outline-none transition bg-white">
<option value="">{% trans "Select Agency" %}</option>
{% for choice in form.agency.field.queryset %}
<option value="{{ choice.pk }}" {% if form.agency.value == choice.pk|stringformat:"s" %}selected{% endif %}>
{{ choice.name }}
</option>
{% endfor %}
</select>
{% if form.agency.errors %}
<div class="text-red-600 text-sm mt-1">{{ form.agency.errors.0 }}</div>
{% endif %}
{% if form.agency.help_text %}
<p class="text-xs text-gray-500 mt-1">{{ form.agency.help_text }}</p>
{% endif %}
</div>
<!-- Job -->
<div>
<label for="{{ form.job.id_for_label }}" class="block text-sm font-semibold text-gray-700 mb-2">
{{ form.job.label }} <span class="text-red-500">*</span>
</label>
<select name="job" id="{{ form.job.id_for_label }}"
class="w-full px-4 py-3 border border-gray-200 rounded-xl text-sm focus:ring-2 focus:ring-temple-red/20 focus:border-temple-red outline-none transition bg-white">
<option value="">{% trans "Select Job" %}</option>
{% for choice in form.job.field.queryset %}
<option value="{{ choice.pk }}" {% if form.job.value == choice.pk|stringformat:"s" %}selected{% endif %}>
{{ choice.title }}
</option>
{% endfor %}
</select>
{% if form.job.errors %}
<div class="text-red-600 text-sm mt-1">{{ form.job.errors.0 }}</div>
{% endif %}
{% if form.job.help_text %}
<p class="text-xs text-gray-500 mt-1">{{ form.job.help_text }}</p>
{% endif %}
</div>
<!-- Max Candidates -->
<div>
<label for="{{ form.max_candidates.id_for_label }}" class="block text-sm font-semibold text-gray-700 mb-2">
{{ form.max_candidates.label }} <span class="text-red-500">*</span>
</label>
<input type="number"
name="max_candidates"
id="{{ form.max_candidates.id_for_label }}"
value="{{ form.max_candidates.value|default:'' }}"
min="1"
class="w-full px-4 py-3 border border-gray-200 rounded-xl text-sm focus:ring-2 focus:ring-temple-red/20 focus:border-temple-red outline-none transition"
placeholder="{% trans 'Maximum candidates' %}">
{% if form.max_candidates.errors %}
<div class="text-red-600 text-sm mt-1">{{ form.max_candidates.errors.0 }}</div>
{% endif %}
{% if form.max_candidates.help_text %}
<p class="text-xs text-gray-500 mt-1">{{ form.max_candidates.help_text }}</p>
{% else %}
<p class="text-xs text-gray-500 mt-1">{% trans "Maximum number of candidates agency can submit" %}</p>
{% endif %}
</div>
<!-- Deadline Date -->
<div>
<label for="{{ form.deadline_date.id_for_label }}" class="block text-sm font-semibold text-gray-700 mb-2">
{{ form.deadline_date.label }} <span class="text-red-500">*</span>
</label>
<input type="datetime-local"
name="deadline_date"
id="{{ form.deadline_date.id_for_label }}"
value="{{ form.deadline_date.value|default:'' }}"
class="w-full px-4 py-3 border border-gray-200 rounded-xl text-sm focus:ring-2 focus:ring-temple-red/20 focus:border-temple-red outline-none transition">
{% if form.deadline_date.errors %}
<div class="text-red-600 text-sm mt-1">{{ form.deadline_date.errors.0 }}</div>
{% endif %}
{% if form.deadline_date.help_text %}
<p class="text-xs text-gray-500 mt-1">{{ form.deadline_date.help_text }}</p>
{% else %}
<p class="text-xs text-gray-500 mt-1">{% trans "Date and time when submission period ends" %}</p>
{% endif %}
</div>
</div>
<!-- Admin Notes (Full Width) -->
<div>
<label for="{{ form.admin_notes.id_for_label }}" class="block text-sm font-semibold text-gray-700 mb-2">
{{ form.admin_notes.label }}
</label>
<textarea
name="admin_notes"
id="{{ form.admin_notes.id_for_label }}"
rows="4"
class="w-full px-4 py-3 border border-gray-200 rounded-xl text-sm focus:ring-2 focus:ring-temple-red/20 focus:border-temple-red outline-none transition resize-vertical"
placeholder="{% trans 'Internal notes about this assignment (not visible to agency)' %}">{{ form.admin_notes.value|default:'' }}</textarea>
{% if form.admin_notes.errors %}
<div class="text-red-600 text-sm mt-1">{{ form.admin_notes.errors.0 }}</div>
{% endif %}
{% if form.admin_notes.help_text %}
<p class="text-xs text-gray-500 mt-1">{{ form.admin_notes.help_text }}</p>
{% endif %}
</div>
<!-- Form Actions -->
<div class="flex flex-col sm:flex-row justify-between items-center gap-4 pt-4 border-t border-gray-200">
<a href="{% url 'agency_assignment_list' %}"
class="inline-flex items-center gap-2 px-6 py-3 rounded-lg font-medium border-2 border-gray-200 text-gray-700 hover:bg-gray-50 transition-all duration-200">
<i data-lucide="x" class="w-4 h-4"></i>
{% trans "Cancel" %}
</a>
<button type="submit"
class="inline-flex items-center gap-2 px-8 py-3 rounded-lg font-medium text-white transition-all duration-200"
style="background-color: #9d2235;"
onmouseover="this.style.backgroundColor='#7a1a29'"
onmouseout="this.style.backgroundColor='#9d2235'">
<i data-lucide="save" class="w-4 h-4"></i>
{{ button_text|default:"{% trans 'Create Assignment' %}" }}
</button>
</div>
</form>
</div>
</div>
</div>
<script>
document.addEventListener('DOMContentLoaded', function() {
// Initialize Lucide icons
if (typeof lucide !== 'undefined') {
lucide.createIcons();
}
// Form Validation
const form = document.getElementById('assignment-form');
if (form) {
form.addEventListener('submit', function(e) {
const agencySelect = document.getElementById('{{ form.agency.id_for_label }}');
const jobSelect = document.getElementById('{{ form.job.id_for_label }}');
const maxCandidatesInput = document.getElementById('{{ form.max_candidates.id_for_label }}');
const deadlineInput = document.getElementById('{{ form.deadline_date.id_for_label }}');
// Agency validation
if (agencySelect && !agencySelect.value) {
e.preventDefault();
alert("{% trans 'Please select an agency.' %}");
agencySelect.focus();
return false;
}
// Job validation
if (jobSelect && !jobSelect.value) {
e.preventDefault();
alert("{% trans 'Please select a job.' %}");
jobSelect.focus();
return false;
}
// Max candidates validation
if (maxCandidatesInput && (!maxCandidatesInput.value || parseInt(maxCandidatesInput.value) < 1)) {
e.preventDefault();
alert("{% trans 'Please enter a valid number of candidates (minimum 1).' %}");
maxCandidatesInput.focus();
return false;
}
// Deadline validation
if (deadlineInput && !deadlineInput.value) {
e.preventDefault();
alert("{% trans 'Please select a deadline date and time.' %}");
deadlineInput.focus();
return false;
}
// Check deadline is in future
if (deadlineInput && deadlineInput.value) {
const deadline = new Date(deadlineInput.value);
const now = new Date();
if (deadline <= now) {
e.preventDefault();
alert("{% trans 'Deadline must be in the future.' %}");
deadlineInput.focus();
return false;
}
}
});
}
// Set minimum datetime for deadline to current time
const deadlineInput = document.getElementById('{{ form.deadline_date.id_for_label }}');
if (deadlineInput) {
const now = new Date();
const localDateTime = new Date(now.getTime() - now.getTimezoneOffset() * 60000)
.toISOString()
.slice(0, 16);
deadlineInput.min = localDateTime;
}
// Auto-populate or log job selection
const jobSelect = document.getElementById('{{ form.job.id_for_label }}');
const agencySelect = document.getElementById('{{ form.agency.id_for_label }}');
if (jobSelect && agencySelect) {
jobSelect.addEventListener('change', function() {
// You could add logic here to filter agencies based on job requirements
// For now, just log the selection
console.log('Job selected:', this.value);
});
}
});
</script>
{% endblock %}