- Updated all navigation links in HTML files - Updated all hrefs and window.location redirects in JavaScript - All links now use clean URLs without .html extensions - Improves SEO and provides cleaner user experience
202 lines
7.0 KiB
JavaScript
202 lines
7.0 KiB
JavaScript
// Main JavaScript for Ryans Recruit Firm
|
|
|
|
// Load jobs on jobs.html page
|
|
if (window.location.pathname.includes('jobs')) {
|
|
loadJobs();
|
|
}
|
|
|
|
async function loadJobs() {
|
|
const jobsContainer = document.getElementById('jobs-container');
|
|
const loadingEl = document.getElementById('loading');
|
|
|
|
try {
|
|
const response = await fetch('/api/jobs');
|
|
const jobs = await response.json();
|
|
|
|
if (loadingEl) loadingEl.style.display = 'none';
|
|
|
|
if (jobs.length === 0) {
|
|
jobsContainer.innerHTML = '<div class="text-center"><p>No job openings at the moment. Check back soon!</p></div>';
|
|
return;
|
|
}
|
|
|
|
jobsContainer.innerHTML = jobs.map(job => `
|
|
<div class="job-card">
|
|
<div class="job-header">
|
|
<div>
|
|
<h3 class="job-title">${escapeHtml(job.title)}</h3>
|
|
<div class="job-meta">
|
|
<span class="job-meta-item">📍 ${escapeHtml(job.location || 'Not specified')}</span>
|
|
<span class="job-meta-item">💼 ${escapeHtml(job.employment_type || 'Full-time')}</span>
|
|
${job.salary_range ? `<span class="job-meta-item">💰 ${escapeHtml(job.salary_range)}</span>` : ''}
|
|
${job.department ? `<span class="tag tag-primary">${escapeHtml(job.department)}</span>` : ''}
|
|
</div>
|
|
</div>
|
|
</div>
|
|
<p class="job-description">${escapeHtml(job.description.substring(0, 200))}...</p>
|
|
<a href="/apply?job=${job.id}" class="btn btn-primary">Apply Now</a>
|
|
</div>
|
|
`).join('');
|
|
} catch (err) {
|
|
console.error('Error loading jobs:', err);
|
|
if (loadingEl) loadingEl.style.display = 'none';
|
|
jobsContainer.innerHTML = '<div class="alert alert-error">Failed to load job listings. Please try again later.</div>';
|
|
}
|
|
}
|
|
|
|
// Handle application form on apply.html
|
|
if (window.location.pathname.includes('apply')) {
|
|
loadJobDetails();
|
|
document.getElementById('application-form')?.addEventListener('submit', handleApplicationSubmit);
|
|
}
|
|
|
|
async function loadJobDetails() {
|
|
const urlParams = new URLSearchParams(window.location.search);
|
|
const jobId = urlParams.get('job');
|
|
|
|
if (!jobId) return;
|
|
|
|
try {
|
|
const response = await fetch(`/api/jobs/${jobId}`);
|
|
const job = await response.json();
|
|
|
|
document.getElementById('job-title').textContent = job.title;
|
|
document.getElementById('job-details').innerHTML = `
|
|
<p><strong>Location:</strong> ${escapeHtml(job.location)}</p>
|
|
<p><strong>Type:</strong> ${escapeHtml(job.employment_type)}</p>
|
|
${job.salary_range ? `<p><strong>Salary:</strong> ${escapeHtml(job.salary_range)}</p>` : ''}
|
|
<p><strong>Description:</strong></p>
|
|
<p>${escapeHtml(job.description)}</p>
|
|
`;
|
|
} catch (err) {
|
|
console.error('Error loading job details:', err);
|
|
}
|
|
}
|
|
|
|
async function handleApplicationSubmit(e) {
|
|
e.preventDefault();
|
|
|
|
const form = e.target;
|
|
const submitBtn = form.querySelector('button[type="submit"]');
|
|
const originalBtnText = submitBtn.textContent;
|
|
|
|
submitBtn.disabled = true;
|
|
submitBtn.innerHTML = '<span class="loading"></span> Submitting...';
|
|
|
|
const formData = new FormData(form);
|
|
|
|
try {
|
|
const response = await fetch('/api/apply', {
|
|
method: 'POST',
|
|
body: formData
|
|
});
|
|
|
|
const result = await response.json();
|
|
|
|
if (response.ok) {
|
|
showAlert('Application submitted successfully! We\'ll be in touch soon.', 'success');
|
|
form.reset();
|
|
setTimeout(() => window.location.href = '/jobs', 2000);
|
|
} else {
|
|
showAlert(result.error || 'Failed to submit application', 'error');
|
|
}
|
|
} catch (err) {
|
|
console.error('Error submitting application:', err);
|
|
showAlert('Failed to submit application. Please try again.', 'error');
|
|
} finally {
|
|
submitBtn.disabled = false;
|
|
submitBtn.textContent = originalBtnText;
|
|
}
|
|
}
|
|
|
|
// Handle contact form on contact.html
|
|
if (window.location.pathname.includes('contact')) {
|
|
document.getElementById('contact-form')?.addEventListener('submit', handleContactSubmit);
|
|
}
|
|
|
|
async function handleContactSubmit(e) {
|
|
e.preventDefault();
|
|
|
|
const form = e.target;
|
|
const submitBtn = form.querySelector('button[type="submit"]');
|
|
const originalBtnText = submitBtn.textContent;
|
|
|
|
submitBtn.disabled = true;
|
|
submitBtn.innerHTML = '<span class="loading"></span> Sending...';
|
|
|
|
const formData = new FormData(form);
|
|
const data = Object.fromEntries(formData);
|
|
|
|
try {
|
|
const response = await fetch('/api/contact', {
|
|
method: 'POST',
|
|
headers: { 'Content-Type': 'application/json' },
|
|
body: JSON.stringify(data)
|
|
});
|
|
|
|
const result = await response.json();
|
|
|
|
if (response.ok) {
|
|
showAlert('Message sent successfully! We\'ll get back to you soon.', 'success');
|
|
form.reset();
|
|
} else {
|
|
showAlert(result.error || 'Failed to send message', 'error');
|
|
}
|
|
} catch (err) {
|
|
console.error('Error sending message:', err);
|
|
showAlert('Failed to send message. Please try again.', 'error');
|
|
} finally {
|
|
submitBtn.disabled = false;
|
|
submitBtn.textContent = originalBtnText;
|
|
}
|
|
}
|
|
|
|
// Utility functions
|
|
function escapeHtml(text) {
|
|
const div = document.createElement('div');
|
|
div.textContent = text;
|
|
return div.innerHTML;
|
|
}
|
|
|
|
function showAlert(message, type = 'info') {
|
|
const alertDiv = document.createElement('div');
|
|
alertDiv.className = `alert alert-${type}`;
|
|
alertDiv.textContent = message;
|
|
alertDiv.style.position = 'fixed';
|
|
alertDiv.style.top = '20px';
|
|
alertDiv.style.right = '20px';
|
|
alertDiv.style.zIndex = '10000';
|
|
alertDiv.style.minWidth = '300px';
|
|
|
|
document.body.appendChild(alertDiv);
|
|
|
|
setTimeout(() => {
|
|
alertDiv.remove();
|
|
}, 5000);
|
|
}
|
|
|
|
// File input validation
|
|
document.addEventListener('DOMContentLoaded', () => {
|
|
const fileInputs = document.querySelectorAll('input[type="file"]');
|
|
fileInputs.forEach(input => {
|
|
input.addEventListener('change', (e) => {
|
|
const file = e.target.files[0];
|
|
if (file) {
|
|
const maxSize = 5 * 1024 * 1024; // 5MB
|
|
if (file.size > maxSize) {
|
|
showAlert('File size must be less than 5MB', 'error');
|
|
e.target.value = '';
|
|
return;
|
|
}
|
|
|
|
const allowedTypes = ['application/pdf', 'application/msword', 'application/vnd.openxmlformats-officedocument.wordprocessingml.document'];
|
|
if (!allowedTypes.includes(file.type)) {
|
|
showAlert('Only PDF, DOC, and DOCX files are allowed', 'error');
|
|
e.target.value = '';
|
|
return;
|
|
}
|
|
}
|
|
});
|
|
});
|
|
});
|