ATS/templates/recruitment/agency_portal_login.html
2026-02-01 13:38:06 +03:00

245 lines
11 KiB
HTML

{% extends 'portal_base.html' %}
{% load static i18n %}
{% block title %}{% trans "Agency Portal Login" %} - {{ block.super }}{% endblock %}
{% block content %}
<body class="bg-gradient-to-br from-temple-red to-[#7a1a29] min-h-screen">
<div class="min-h-screen flex items-center justify-center p-6">
<div class="bg-white rounded-2xl shadow-2xl border-none max-w-2xl w-full">
<!-- Login Header -->
<div class="bg-gradient-to-br from-temple-red to-[#7a1a29] text-white p-8 rounded-t-2xl text-center">
<div class="mb-4 inline-flex items-center justify-center w-20 h-20 rounded-full bg-white/20 backdrop-blur-sm">
<i data-lucide="building" class="w-10 h-10"></i>
</div>
<h2 class="text-2xl md:text-3xl font-bold mb-2">{% trans "Agency Portal" %}</h2>
<p class="text-white/80 text-sm md:text-base">
{% trans "Submit candidates for job assignments" %}
</p>
</div>
<!-- Login Body -->
<div class="p-8 md:p-10">
<!-- Login Form -->
<form method="post" novalidate id="login-form" class="space-y-6">
{% csrf_token %}
<!-- Access Token Field -->
<div class="space-y-2">
<label for="{{ form.token.id_for_label }}" class="block text-sm font-bold text-gray-700">
<i data-lucide="key" class="w-4 h-4 inline mr-2"></i>
{% trans "Access Token" %}
</label>
<div class="relative">
<span class="absolute left-4 top-1/2 -translate-y-1/2 text-temple-red">
<i data-lucide="lock" class="w-5 h-5"></i>
</span>
<input type="text"
name="token"
id="{{ form.token.id_for_label }}"
class="w-full pl-12 pr-4 py-3.5 border border-gray-300 rounded-xl text-sm focus:ring-2 focus:ring-temple-red/20 focus:border-temple-red outline-none transition"
placeholder="{% trans 'Enter your access token' %}"
required>
</div>
{% if form.token.errors %}
<div class="text-red-600 text-sm mt-1 flex items-center gap-1">
<i data-lucide="alert-circle" class="w-4 h-4"></i>
{% for error in form.token.errors %}{{ error }}{% endfor %}
</div>
{% endif %}
<p class="text-xs text-gray-500">
{% trans "Enter the access token provided by the hiring organization" %}
</p>
</div>
<!-- Password Field -->
<div class="space-y-2">
<label for="{{ form.password.id_for_label }}" class="block text-sm font-bold text-gray-700">
<i data-lucide="shield-check" class="w-4 h-4 inline mr-2"></i>
{% trans "Password" %}
</label>
<div class="relative">
<span class="absolute left-4 top-1/2 -translate-y-1/2 text-temple-red">
<i data-lucide="key" class="w-5 h-5"></i>
</span>
<input type="password"
name="password"
id="{{ form.password.id_for_label }}"
class="w-full pl-12 pr-12 py-3.5 border border-gray-300 rounded-xl text-sm focus:ring-2 focus:ring-temple-red/20 focus:border-temple-red outline-none transition"
placeholder="{% trans 'Enter your password' %}"
required>
<button type="button"
onclick="togglePassword()"
id="password-toggle"
class="absolute right-4 top-1/2 -translate-y-1/2 text-gray-400 hover:text-gray-600 transition">
<i data-lucide="eye" class="w-5 h-5"></i>
</button>
</div>
{% if form.password.errors %}
<div class="text-red-600 text-sm mt-1 flex items-center gap-1">
<i data-lucide="alert-circle" class="w-4 h-4"></i>
{% for error in form.password.errors %}{{ error }}{% endfor %}
</div>
{% endif %}
<p class="text-xs text-gray-500">
{% trans "Enter the password for this access token" %}
</p>
</div>
<!-- Submit Button -->
<button type="submit"
class="w-full bg-gradient-to-r from-temple-red to-[#7a1a29] hover:from-[#8a1d2d] hover:to-[#6a1520] text-white font-bold py-4 rounded-xl text-sm transition shadow-lg hover:shadow-xl transform hover:-translate-y-0.5 flex items-center justify-center gap-2">
<i data-lucide="log-in" class="w-5 h-5"></i>
{% trans "Access Portal" %}
</button>
</form>
<!-- Information Section -->
<div class="mt-8 bg-temple-cream rounded-xl p-6 border border-gray-200">
<h5 class="text-temple-dark font-bold mb-4 flex items-center gap-2">
<i data-lucide="help-circle" class="w-5 h-5 text-temple-red"></i>
{% trans "Need Help?" %}
</h5>
<div class="grid grid-cols-1 md:grid-cols-2 gap-6 text-center">
<div>
<div class="w-16 h-16 mx-auto mb-3 rounded-full bg-gradient-to-br from-temple-red to-[#7a1a29] flex items-center justify-center text-white">
<i data-lucide="mail" class="w-8 h-8"></i>
</div>
<h6 class="font-bold text-gray-900 mb-1">{% trans "Contact Support" %}</h6>
<p class="text-sm text-gray-500">
{% trans "Reach out to your hiring contact" %}
</p>
</div>
<div>
<div class="w-16 h-16 mx-auto mb-3 rounded-full bg-gradient-to-br from-temple-red to-[#7a1a29] flex items-center justify-center text-white">
<i data-lucide="book-open" class="w-8 h-8"></i>
</div>
<h6 class="font-bold text-gray-900 mb-1">{% trans "Documentation" %}</h6>
<p class="text-sm text-gray-500">
{% trans "View user guides and tutorials" %}
</p>
</div>
</div>
</div>
<!-- Security Notice -->
<div class="mt-6 bg-blue-50 border border-blue-200 rounded-xl p-5">
<h6 class="text-blue-800 font-bold mb-3 flex items-center gap-2">
<i data-lucide="shield-check" class="w-4 h-4"></i>
{% trans "Security Notice" %}
</h6>
<p class="text-blue-700 text-sm mb-3">
{% trans "This portal is for authorized agency partners only. Access is monitored and logged." %}
</p>
<hr class="border-blue-200 mb-3">
<p class="text-blue-700 text-sm mb-0">
{% trans "If you believe you've received this link in error, please contact the hiring organization immediately." %}
</p>
</div>
</div>
</div>
</div>
<!-- Toast Notification Container -->
<div id="toast-container"></div>
</body>
{% endblock %}
{% block customJS %}
<script>
lucide.createIcons();
// Auto-format access token (remove spaces and convert to uppercase)
const accessTokenInput = document.getElementById('{{ form.token.id_for_label }}');
if (accessTokenInput) {
accessTokenInput.addEventListener('input', function() {
// Remove spaces and convert to uppercase
this.value = this.value.replace(/\s+/g, '').toUpperCase();
});
// Focus on load
accessTokenInput.focus();
}
// Toggle password visibility
function togglePassword() {
const passwordField = document.getElementById('{{ form.password.id_for_label }}');
const toggleBtn = document.getElementById('password-toggle');
if (passwordField && toggleBtn) {
const type = passwordField.getAttribute('type') === 'password' ? 'text' : 'password';
passwordField.setAttribute('type', type);
const icon = type === 'password' ? 'eye' : 'eye-off';
toggleBtn.innerHTML = `<i data-lucide="${icon}" class="w-5 h-5"></i>`;
lucide.createIcons();
}
}
// Form validation
const form = document.getElementById('login-form');
if (form) {
form.addEventListener('submit', function(e) {
const accessToken = accessTokenInput.value.trim();
const passwordField = document.getElementById('{{ form.password.id_for_label }}');
const password = passwordField ? passwordField.value.trim() : '';
if (!accessToken) {
e.preventDefault();
showError('{% trans "Please enter your access token." %}');
accessTokenInput.focus();
return;
}
if (!password) {
e.preventDefault();
showError('{% trans "Please enter your password." %}');
passwordField.focus();
return;
}
});
}
function showError(message) {
// Remove existing toasts
const container = document.getElementById('toast-container');
container.innerHTML = '';
// Create new toast
const toast = document.createElement('div');
toast.className = 'fixed top-4 right-4 bg-red-600 text-white px-6 py-4 rounded-xl shadow-lg z-50 flex items-center gap-3 animate-pulse';
toast.innerHTML = `
<i data-lucide="alert-circle" class="w-5 h-5"></i>
<span class="flex-1">${message}</span>
<button onclick="this.parentElement.remove()" class="hover:bg-red-700 p-1 rounded-lg transition">
<i data-lucide="x" class="w-4 h-4"></i>
</button>
`;
container.appendChild(toast);
lucide.createIcons();
// Auto-dismiss after 5 seconds
setTimeout(() => {
if (toast.parentNode) {
toast.classList.add('animate-fade-out');
setTimeout(() => toast.remove(), 300);
}
}, 5000);
}
</script>
<style>
@keyframes fade-out {
from { opacity: 1; transform: translateY(0); }
to { opacity: 0; transform: translateY(-20px); }
}
.animate-fade-out {
animation: fade-out 0.3s ease-out forwards;
}
</style>
{% endblock %}