413 lines
15 KiB
HTML
413 lines
15 KiB
HTML
{% extends 'portal_base.html' %}
|
|
{% load static i18n crispy_forms_tags %}
|
|
|
|
{% block title %}{% trans "Submit Application" %} - {{ assignment.job.title }} - Agency Portal{% endblock %}
|
|
|
|
{% block customCSS %}
|
|
<style>
|
|
/* KAAT-S UI Variables */
|
|
:root {
|
|
--kaauh-teal: #00636e;
|
|
--kaauh-teal-dark: #004a53;
|
|
--kaauh-border: #eaeff3;
|
|
--kaauh-primary-text: #343a40;
|
|
--kaauh-success: #28a745;
|
|
--kaauh-info: #17a2b8;
|
|
--kaauh-danger: #dc3545;
|
|
--kaauh-warning: #ffc107;
|
|
}
|
|
|
|
.kaauh-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;
|
|
}
|
|
|
|
.btn-main-action {
|
|
background-color: var(--kaauh-teal);
|
|
border-color: var(--kaauh-teal);
|
|
color: white;
|
|
font-weight: 600;
|
|
transition: all 0.2s ease;
|
|
}
|
|
.btn-main-action:hover {
|
|
background-color: var(--kaauh-teal-dark);
|
|
border-color: var(--kaauh-teal-dark);
|
|
box-shadow: 0 4px 8px rgba(0,0,0,0.15);
|
|
}
|
|
|
|
.form-control:focus {
|
|
border-color: var(--kaauh-teal);
|
|
box-shadow: 0 0 0 0.2rem rgba(0, 99, 110, 0.25);
|
|
}
|
|
|
|
.form-select:focus {
|
|
border-color: var(--kaauh-teal);
|
|
box-shadow: 0 0 0 0.2rem rgba(0, 99, 110, 0.25);
|
|
}
|
|
|
|
.file-upload-area {
|
|
border: 2px dashed var(--kaauh-border);
|
|
border-radius: 0.5rem;
|
|
padding: 2rem;
|
|
text-align: center;
|
|
transition: all 0.3s ease;
|
|
background-color: #f8f9fa;
|
|
}
|
|
.file-upload-area:hover {
|
|
border-color: var(--kaauh-teal);
|
|
background-color: #e9ecef;
|
|
}
|
|
.file-upload-area.has-file {
|
|
border-color: var(--kaauh-success);
|
|
background-color: #d4edda;
|
|
}
|
|
|
|
.progress-indicator {
|
|
height: 4px;
|
|
background-color: var(--kaauh-teal);
|
|
border-radius: 2px;
|
|
transition: width 0.3s ease;
|
|
}
|
|
|
|
.assignment-info {
|
|
background: linear-gradient(135deg, var(--kaauh-teal) 0%, var(--kaauh-teal-dark) 100%);
|
|
color: white;
|
|
border-radius: 0.75rem;
|
|
padding: 1.5rem;
|
|
}
|
|
|
|
.required-field::after {
|
|
content: " *";
|
|
color: var(--kaauh-danger);
|
|
}
|
|
</style>
|
|
{% endblock %}
|
|
|
|
{% block content %}
|
|
<div class="container-fluid py-4">
|
|
<!-- Breadcrumb Navigation -->
|
|
<nav aria-label="breadcrumb" class="mb-4">
|
|
<ol class="breadcrumb">
|
|
<li class="breadcrumb-item">
|
|
<a href="{% url 'agency_portal_dashboard' %}" class="text-decoration-none text-secondary">
|
|
<i class="fas fa-home me-1"></i>{% trans "Dashboard" %}
|
|
</a>
|
|
</li>
|
|
|
|
{% comment %} <li class="breadcrumb-item active" aria-current="page">
|
|
{% trans "Submit Application" %}
|
|
</li> {% endcomment %}
|
|
|
|
<li class="breadcrumb-item active" aria-current="page" style="
|
|
color: #F43B5E; /* Rosy Accent Color */
|
|
font-weight: 600; ">
|
|
{% trans "Submit Application" %}</li>
|
|
</ol>
|
|
</nav>
|
|
|
|
<!-- Header -->
|
|
<div class="d-flex justify-content-between align-items-center mb-4">
|
|
<div>
|
|
<h1 class="h3 mb-1" style="color: var(--kaauh-teal-dark); font-weight: 700;">
|
|
<i class="fas fa-user-plus me-2"></i>
|
|
{% trans "Submit New Application" %}
|
|
</h1>
|
|
<p class="text-muted mb-0">
|
|
<!-- Button trigger modal -->
|
|
{% trans "Submit a Application for" %}
|
|
{{ assignment.job.title }}
|
|
|
|
</p>
|
|
</div>
|
|
<div>
|
|
<a href="{% url 'agency_portal_assignment_detail' assignment.slug %}" class="btn btn-outline-secondary">
|
|
<i class="fas fa-arrow-left me-1"></i> {% trans "Back to Assignment" %}
|
|
</a>
|
|
</div>
|
|
</div>
|
|
|
|
<div class="row">
|
|
<!-- Assignment Info Card -->
|
|
<div class="col-lg-4 mb-4">
|
|
<div class="assignment-info">
|
|
<h5 class="mb-3">
|
|
<i class="fas fa-info-circle me-2"></i>
|
|
{% trans "Assignment Details" %}
|
|
</h5>
|
|
<div class="mb-2">
|
|
<strong>{% trans "Position:" %}</strong> {{ assignment.job.title }}
|
|
</div>
|
|
<div class="mb-2">
|
|
<strong>{% trans "Department:" %}</strong> {{ assignment.job.department|default:"N/A" }}
|
|
</div>
|
|
<div class="mb-2">
|
|
<strong>{% trans "Deadline:" %}</strong> {{ assignment.deadline_date|date:"Y-m-d H:i" }}
|
|
</div>
|
|
<div class="mb-2">
|
|
<strong>{% trans "Days Remaining:" %}</strong>
|
|
<span class="{% if assignment.days_remaining <= 3 %}text-warning{% endif %}">
|
|
{{ assignment.days_remaining }} {% trans "days" %}
|
|
</span>
|
|
</div>
|
|
<div class="mb-2">
|
|
<strong>{% trans "Submitted:" %}</strong> {{ total_submitted }}/{{ assignment.max_candidates }}
|
|
</div>
|
|
<div>
|
|
<strong>{% trans "Status:" %}</strong>
|
|
{% if assignment.can_submit %}
|
|
<span class="badge bg-success">{% trans "Can Submit" %}</span>
|
|
{% else %}
|
|
<span class="badge bg-danger">{% trans "Cannot Submit" %}</span>
|
|
{% endif %}
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- Submission Form -->
|
|
<div class="col-lg-8">
|
|
{% if assignment.can_submit %}
|
|
<div class="kaauh-card p-4">
|
|
<h5 class="mb-4" style="color: var(--kaauh-teal-dark);">
|
|
<i class="fas fa-user-edit me-2"></i>
|
|
{% trans "Application Information" %}
|
|
</h5>
|
|
|
|
<form method="post" enctype="multipart/form-data" id="ApplicationForm"
|
|
action="{% url 'agency_portal_submit_application_page' assignment.slug %}">
|
|
{% csrf_token %}
|
|
{{form|crispy}}
|
|
<button type="submit" class="btn btn-main-action">
|
|
<i class="fas fa-user-plus me-2"></i>
|
|
{% trans "Submit Application" %}
|
|
</button>
|
|
</form>
|
|
</div>
|
|
{% else %}
|
|
<div class="kaauh-card p-4">
|
|
<div class="text-center py-5">
|
|
<i class="fas fa-exclamation-triangle fa-4x text-warning mb-4"></i>
|
|
<h4 class="text-warning mb-3">{% trans "Cannot Submit Applications" %}</h4>
|
|
<div class="alert alert-warning d-inline-block">
|
|
{% if assignment.is_expired %}
|
|
<i class="fas fa-clock me-2"></i>
|
|
{% trans "This assignment has expired. Submissions are no longer accepted." %}
|
|
{% elif assignment.is_full %}
|
|
<i class="fas fa-users me-2"></i>
|
|
{% trans "Maximum Application limit reached for this assignment." %}
|
|
{% else %}
|
|
<i class="fas fa-pause me-2"></i>
|
|
{% trans "This assignment is not currently active." %}
|
|
{% endif %}
|
|
</div>
|
|
<div class="mt-4">
|
|
<a href="{% url 'agency_assignment_detail' assignment.slug %}" class="btn btn-outline-primary">
|
|
<i class="fas fa-arrow-left me-1"></i>
|
|
{% trans "Back to Assignment" %}
|
|
</a>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
{% endif %}
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- Loading Overlay -->
|
|
<div class="modal fade" id="loadingModal" tabindex="-1" data-bs-backdrop="static" data-bs-keyboard="false">
|
|
<div class="modal-dialog modal-sm">
|
|
<div class="modal-content">
|
|
<div class="modal-body text-center py-4">
|
|
<div class="spinner-border text-primary mb-3" role="status">
|
|
<span class="visually-hidden">{% trans "Loading..." %}</span>
|
|
</div>
|
|
<h6>{% trans "Submitting Application..." %}</h6>
|
|
<p class="text-muted small">{% trans "Please wait while we process your submission." %}</p>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
{% endblock %}
|
|
|
|
{% block customJS %}
|
|
<script>
|
|
document.addEventListener('DOMContentLoaded', function() {
|
|
const fileInput = document.getElementById('resume');
|
|
const fileUploadArea = document.getElementById('fileUploadArea');
|
|
const uploadPlaceholder = document.getElementById('uploadPlaceholder');
|
|
const filePreview = document.getElementById('filePreview');
|
|
const fileName = document.getElementById('fileName');
|
|
const removeFileBtn = document.getElementById('removeFile');
|
|
const form = document.getElementById('ApplicationForm');
|
|
const submitBtn = document.getElementById('submitBtn');
|
|
|
|
// File upload area click handler
|
|
fileUploadArea.addEventListener('click', function() {
|
|
fileInput.click();
|
|
});
|
|
|
|
// Drag and drop handlers
|
|
fileUploadArea.addEventListener('dragover', function(e) {
|
|
e.preventDefault();
|
|
this.classList.add('border-primary');
|
|
});
|
|
|
|
fileUploadArea.addEventListener('dragleave', function(e) {
|
|
e.preventDefault();
|
|
this.classList.remove('border-primary');
|
|
});
|
|
|
|
fileUploadArea.addEventListener('drop', function(e) {
|
|
e.preventDefault();
|
|
this.classList.remove('border-primary');
|
|
|
|
const files = e.dataTransfer.files;
|
|
if (files.length > 0) {
|
|
fileInput.files = files;
|
|
handleFileSelect(files[0]);
|
|
}
|
|
});
|
|
|
|
// File input change handler
|
|
fileInput.addEventListener('change', function() {
|
|
if (this.files.length > 0) {
|
|
handleFileSelect(this.files[0]);
|
|
}
|
|
});
|
|
|
|
// Remove file handler
|
|
removeFileBtn.addEventListener('click', function() {
|
|
fileInput.value = '';
|
|
uploadPlaceholder.classList.remove('d-none');
|
|
filePreview.classList.add('d-none');
|
|
fileUploadArea.classList.remove('has-file');
|
|
});
|
|
|
|
// Handle file selection
|
|
function handleFileSelect(file) {
|
|
// Validate file type
|
|
const allowedTypes = ['application/pdf', 'application/msword', 'application/vnd.openxmlformats-officedocument.wordprocessingml.document'];
|
|
if (!allowedTypes.includes(file.type)) {
|
|
alert('{% trans "Please upload a PDF, DOC, or DOCX file." %}');
|
|
return;
|
|
}
|
|
|
|
// Validate file size (5MB)
|
|
const maxSize = 5 * 1024 * 1024; // 5MB in bytes
|
|
if (file.size > maxSize) {
|
|
alert('{% trans "File size must be less than 5MB." %}');
|
|
return;
|
|
}
|
|
|
|
// Show file preview
|
|
fileName.textContent = file.name;
|
|
uploadPlaceholder.classList.add('d-none');
|
|
filePreview.classList.remove('d-none');
|
|
fileUploadArea.classList.add('has-file');
|
|
}
|
|
|
|
// Form submission handler
|
|
form.addEventListener('submit', function(e) {
|
|
e.preventDefault();
|
|
|
|
// Show loading modal
|
|
const loadingModal = new bootstrap.Modal(document.getElementById('loadingModal'));
|
|
loadingModal.show();
|
|
|
|
// Disable submit button
|
|
submitBtn.disabled = true;
|
|
submitBtn.innerHTML = '<i class="fas fa-spinner fa-spin me-1"></i> {% trans "Submitting..." %}';
|
|
|
|
const formData = new FormData(this);
|
|
|
|
fetch(this.action, {
|
|
method: 'POST',
|
|
body: formData,
|
|
headers: {
|
|
'X-Requested-With': 'XMLHttpRequest'
|
|
}
|
|
})
|
|
.then(response => response.json())
|
|
.then(data => {
|
|
loadingModal.hide();
|
|
|
|
if (data.success) {
|
|
// Show success message
|
|
const successAlert = document.createElement('div');
|
|
successAlert.className = 'alert alert-success alert-dismissible fade show position-fixed';
|
|
successAlert.style.cssText = 'position: fixed; top: 20px; right: 20px; z-index: 9999; min-width: 300px;';
|
|
successAlert.innerHTML = `
|
|
<i class="fas fa-check-circle me-2"></i>
|
|
{% trans "Application submitted successfully!" %}
|
|
<button type="button" class="btn-close" data-bs-dismiss="alert"></button>
|
|
`;
|
|
document.body.appendChild(successAlert);
|
|
|
|
// Reset form
|
|
form.reset();
|
|
fileInput.value = '';
|
|
uploadPlaceholder.classList.remove('d-none');
|
|
filePreview.classList.add('d-none');
|
|
fileUploadArea.classList.remove('has-file');
|
|
|
|
// Remove alert after 5 seconds
|
|
setTimeout(() => {
|
|
if (successAlert.parentNode) {
|
|
successAlert.parentNode.removeChild(successAlert);
|
|
}
|
|
}, 5000);
|
|
|
|
// Redirect to assignment detail after 2 seconds
|
|
setTimeout(() => {
|
|
window.location.href = '{% url "agency_portal_assignment_detail" assignment.slug %}';
|
|
}, 2000);
|
|
|
|
} else {
|
|
// Show error message
|
|
const errorAlert = document.createElement('div');
|
|
errorAlert.className = 'alert alert-danger alert-dismissible fade show position-fixed';
|
|
errorAlert.style.cssText = 'position: fixed; top: 20px; right: 20px; z-index: 9999; min-width: 300px;';
|
|
errorAlert.innerHTML = `
|
|
<i class="fas fa-exclamation-triangle me-2"></i>
|
|
${data.message || '{% trans "Error submitting Application. Please try again." %}'}
|
|
<button type="button" class="btn-close" data-bs-dismiss="alert"></button>
|
|
`;
|
|
document.body.appendChild(errorAlert);
|
|
|
|
// Remove alert after 5 seconds
|
|
setTimeout(() => {
|
|
if (errorAlert.parentNode) {
|
|
errorAlert.parentNode.removeChild(errorAlert);
|
|
}
|
|
}, 5000);
|
|
}
|
|
})
|
|
.catch(error => {
|
|
loadingModal.hide();
|
|
console.error('Error:', error);
|
|
|
|
const errorAlert = document.createElement('div');
|
|
errorAlert.className = 'alert alert-danger alert-dismissible fade show position-fixed';
|
|
errorAlert.style.cssText = 'position: fixed; top: 20px; right: 20px; z-index: 9999; min-width: 300px;';
|
|
errorAlert.innerHTML = `
|
|
<i class="fas fa-exclamation-triangle me-2"></i>
|
|
{% trans "Network error. Please check your connection and try again." %}
|
|
<button type="button" class="btn-close" data-bs-dismiss="alert"></button>
|
|
`;
|
|
document.body.appendChild(errorAlert);
|
|
})
|
|
.finally(() => {
|
|
// Re-enable submit button
|
|
submitBtn.disabled = false;
|
|
submitBtn.innerHTML = '<i class="fas fa-paper-plane me-1"></i> {% trans "Submit Application" %}';
|
|
});
|
|
});
|
|
|
|
// Auto-focus on first field
|
|
document.getElementById('first_name').focus();
|
|
});
|
|
</script>
|
|
{% endblock %}
|