husseinelsaadi's picture
style updated
4991915
raw
history blame
14.6 kB
{% extends "base.html" %}
{% block title %}Apply for {{ job.role }} - Codingo{% endblock %}
{% block hero %}
<section class="hero" style="padding: 3rem 1rem;">
<div class="container">
<div class="hero-content">
<h1>Apply for {{ job.role }}</h1>
<p>{{ job.company }}{% if job.seniority %} β€’ {{ job.seniority }}{% endif %}</p>
</div>
</div>
</section>
{% endblock %}
{% block content %}
<section class="content-section">
<ul class="breadcrumbs">
<li><a href="{{ url_for('index') }}">Home</a></li>
<li><a href="{{ url_for('jobs') }}">Jobs</a></li>
<li><a href="{{ url_for('job_detail', job_id=job.id) }}">{{ job.role }}</a></li>
<li>Apply</li>
</ul>
<div class="application-container">
<div class="card application-card">
<div class="card-header">
<h2>Submit Your Application</h2>
<p>Please upload your resume and fill in the required information below.</p>
</div>
<div class="card-body">
<form method="POST" enctype="multipart/form-data" id="application-form">
<!-- Resume Upload Section -->
<div class="upload-section">
<div class="form-group">
<label for="resume">
<i class="upload-icon">πŸ“„</i>
Upload Resume
</label>
<div class="file-input-wrapper">
<input type="file" name="resume" id="resume" class="file-input" required accept=".pdf,.doc,.docx">
<div class="file-input-display">
<span class="file-placeholder">Choose file... (PDF, DOCX)</span>
<span class="file-name"></span>
</div>
</div>
<button type="button" id="parse-resume" class="btn btn-secondary mt-2">
<span class="btn-icon">πŸ”</span> Parse Resume
</button>
</div>
</div>
<!-- Personal Information -->
<div class="form-section">
<h3 class="section-title">Personal Information</h3>
<div class="form-group">
<label for="full-name">Full Name</label>
<input type="text" name="full_name" id="full-name" class="form-control" placeholder="e.g. Jane Doe" required>
</div>
</div>
<!-- Professional Details -->
<div class="form-section">
<h3 class="section-title">Professional Details</h3>
<div class="form-group">
<label for="skills">Skills</label>
<textarea name="skills" id="skills" class="form-control" rows="3"
placeholder="e.g. Python, Data Analysis, Project Management" required></textarea>
<small class="form-text">Separate skills with commas</small>
</div>
<div class="form-group">
<label for="experience">Experience</label>
<textarea name="experience" id="experience" class="form-control" rows="4"
placeholder="e.g. 3 years at TechCorp as a Backend Developer" required></textarea>
<small class="form-text">List your relevant work experience</small>
</div>
<div class="form-group">
<label for="education">Education</label>
<textarea name="education" id="education" class="form-control" rows="3"
placeholder="e.g. B.Sc. in Computer Science, M.Sc. in Data Science" required></textarea>
<small class="form-text">Include degrees, certifications, and relevant coursework</small>
</div>
</div>
<!-- Submit Section -->
<div class="application-actions">
<button type="submit" class="btn btn-primary btn-lg">
<span class="btn-icon">βœ“</span> Submit Application
</button>
<a href="{{ url_for('job_detail', job_id=job.id) }}" class="btn btn-outline">
<span class="btn-icon">←</span> Back to Job Details
</a>
</div>
</form>
</div>
</div>
<!-- Job Summary Sidebar -->
<div class="job-summary-sidebar">
<div class="card">
<div class="card-header">
<h3>Job Summary</h3>
</div>
<div class="card-body">
<div class="summary-item">
<strong>Role:</strong> {{ job.role }}
</div>
<div class="summary-item">
<strong>Company:</strong> {{ job.company }}
</div>
{% if job.seniority %}
<div class="summary-item">
<strong>Seniority:</strong> {{ job.seniority }}
</div>
{% endif %}
{% if job.location %}
<div class="summary-item">
<strong>Location:</strong> {{ job.location }}
</div>
{% endif %}
{% if job.salary %}
<div class="summary-item">
<strong>Salary:</strong> {{ job.salary }}
</div>
{% endif %}
</div>
</div>
</div>
</div>
</section>
<style>
/* Application Container */
.application-container {
display: grid;
grid-template-columns: 1fr;
gap: 2rem;
}
@media (min-width: 992px) {
.application-container {
grid-template-columns: 2fr 1fr;
}
}
/* Card Enhancements */
.application-card {
background: white;
border-radius: 12px;
box-shadow: 0 8px 24px rgba(0, 0, 0, 0.08);
overflow: hidden;
}
.application-card .card-header {
background: linear-gradient(135deg, var(--primary), var(--secondary));
color: white;
padding: 2rem;
}
.application-card .card-header h2 {
margin: 0 0 0.5rem 0;
font-size: 1.75rem;
}
.application-card .card-header p {
margin: 0;
opacity: 0.9;
}
.application-card .card-body {
padding: 2rem;
}
/* Form Sections */
.form-section {
margin-bottom: 2.5rem;
}
.section-title {
font-size: 1.25rem;
color: var(--primary);
margin-bottom: 1.5rem;
padding-bottom: 0.5rem;
border-bottom: 2px solid #e9ecef;
}
/* Form Elements */
.form-group {
margin-bottom: 1.5rem;
}
.form-group label {
font-weight: 600;
color: var(--dark);
margin-bottom: 0.5rem;
display: flex;
align-items: center;
gap: 0.5rem;
}
.form-control {
width: 100%;
padding: 0.875rem;
font-size: 1rem;
border-radius: 8px;
border: 2px solid #e9ecef;
transition: all 0.3s ease;
background-color: #f8f9fa;
}
.form-control:focus {
outline: none;
border-color: var(--primary);
background-color: white;
box-shadow: 0 0 0 4px rgba(67, 97, 238, 0.1);
}
.form-text {
display: block;
margin-top: 0.5rem;
color: #6c757d;
font-size: 0.875rem;
}
/* File Upload Styling */
.upload-section {
background-color: #f8f9fa;
padding: 1.5rem;
border-radius: 8px;
margin-bottom: 2rem;
}
.upload-icon {
font-size: 1.5rem;
}
.file-input-wrapper {
position: relative;
overflow: hidden;
display: inline-block;
width: 100%;
}
.file-input {
position: absolute;
left: -9999px;
}
.file-input-display {
display: block;
padding: 0.875rem;
border: 2px dashed var(--primary);
border-radius: 8px;
background-color: white;
cursor: pointer;
transition: all 0.3s ease;
text-align: center;
}
.file-input-wrapper:hover .file-input-display {
border-color: var(--secondary);
background-color: #f8f9fa;
}
.file-placeholder {
color: #6c757d;
}
.file-name {
color: var(--primary);
font-weight: 500;
}
/* Button Enhancements */
.btn {
display: inline-flex;
align-items: center;
gap: 0.5rem;
padding: 0.75rem 1.5rem;
font-weight: 500;
border-radius: 8px;
transition: all 0.3s ease;
}
.btn-lg {
padding: 1rem 2rem;
font-size: 1.1rem;
}
.btn-secondary {
background: #6c757d;
color: white;
border: none;
}
.btn-secondary:hover {
background: #5a6268;
transform: translateY(-2px);
}
.btn-icon {
font-size: 1.2rem;
}
/* Application Actions */
.application-actions {
display: flex;
gap: 1rem;
margin-top: 2rem;
padding-top: 2rem;
border-top: 2px solid #e9ecef;
flex-wrap: wrap;
}
/* Job Summary Sidebar */
.job-summary-sidebar .card {
position: sticky;
top: 2rem;
}
.job-summary-sidebar .card-header {
background-color: #f8f9fa;
padding: 1rem 1.5rem;
}
.job-summary-sidebar .card-header h3 {
margin: 0;
font-size: 1.2rem;
color: var(--primary);
}
.summary-item {
padding: 0.75rem 0;
border-bottom: 1px solid #e9ecef;
}
.summary-item:last-child {
border-bottom: none;
}
/* Responsive Adjustments */
@media (max-width: 768px) {
.application-card .card-header {
padding: 1.5rem;
}
.application-card .card-body {
padding: 1.5rem;
}
.form-section {
margin-bottom: 2rem;
}
.application-actions {
flex-direction: column;
}
.application-actions .btn {
width: 100%;
justify-content: center;
}
.job-summary-sidebar {
order: -1;
}
}
/* Loading State */
.btn:disabled {
opacity: 0.6;
cursor: not-allowed;
}
/* Success Animation */
@keyframes successPulse {
0% {
box-shadow: 0 0 0 0 rgba(46, 204, 113, 0.4);
}
70% {
box-shadow: 0 0 0 10px rgba(46, 204, 113, 0);
}
100% {
box-shadow: 0 0 0 0 rgba(46, 204, 113, 0);
}
}
.application-success {
animation: successPulse 2s infinite;
}
</style>
<script>
document.addEventListener('DOMContentLoaded', function() {
// File input handling
const fileInput = document.getElementById('resume');
const fileDisplay = document.querySelector('.file-input-display');
const filePlaceholder = document.querySelector('.file-placeholder');
const fileName = document.querySelector('.file-name');
fileInput.addEventListener('change', function() {
if (this.files && this.files[0]) {
filePlaceholder.style.display = 'none';
fileName.textContent = this.files[0].name;
fileName.style.display = 'block';
fileDisplay.style.borderStyle = 'solid';
fileDisplay.style.borderColor = 'var(--success)';
}
});
// Parse resume functionality
const parseBtn = document.getElementById('parse-resume');
if (parseBtn) {
parseBtn.addEventListener('click', function() {
const resumeInput = document.getElementById('resume');
if (!resumeInput || !resumeInput.files || resumeInput.files.length === 0) {
alert('Please upload your resume before parsing.');
return;
}
// Show loading state
parseBtn.disabled = true;
parseBtn.innerHTML = '<span class="btn-icon">⏳</span> Parsing...';
const formData = new FormData();
formData.append('resume', resumeInput.files[0]);
fetch('/parse_resume', {
method: 'POST',
body: formData
})
.then(resp => resp.json())
.then(data => {
if (data) {
// Populate fields with animation
const fields = [
{ id: 'full-name', value: data.name },
{ id: 'skills', value: data.skills },
{ id: 'education', value: data.education },
{ id: 'experience', value: data.experience }
];
fields.forEach((field, index) => {
if (field.value && document.getElementById(field.id)) {
setTimeout(() => {
const element = document.getElementById(field.id);
element.value = field.value;
element.style.borderColor = 'var(--success)';
setTimeout(() => {
element.style.borderColor = '';
}, 1000);
}, index * 200);
}
});
// Show success message
parseBtn.innerHTML = '<span class="btn-icon">βœ“</span> Parsed Successfully';
parseBtn.classList.add('btn-success');
}
})
.catch(err => {
console.error(err);
alert('Unable to parse resume. Please fill in the fields manually.');
})
.finally(() => {
setTimeout(() => {
parseBtn.disabled = false;
parseBtn.innerHTML = '<span class="btn-icon">πŸ”</span> Parse Resume';
parseBtn.classList.remove('btn-success');
}, 2000);
});
});
}
// Form validation
const form = document.getElementById('application-form');
form.addEventListener('submit', function(e) {
const submitBtn = form.querySelector('button[type="submit"]');
submitBtn.disabled = true;
submitBtn.innerHTML = '<span class="btn-icon">⏳</span> Submitting...';
});
});
</script>
{% endblock %}