// Admin JavaScript for Ryans Recruit Firm // Check authentication on all admin pages except login if (!window.location.pathname.includes('login')) { checkAuth(); } async function checkAuth() { try { const response = await fetch('/api/admin/check'); const data = await response.json(); if (!data.loggedIn) { window.location.href = '/admin/login'; return; } // Update admin name in header if exists const adminNameEl = document.getElementById('admin-name'); if (adminNameEl && data.admin) { adminNameEl.textContent = data.admin.fullName; } } catch (err) { console.error('Auth check failed:', err); window.location.href = '/admin/login'; } } // Login page handlers if (window.location.pathname.includes('login')) { checkFirstAdmin(); document.getElementById('login-form')?.addEventListener('submit', handleLogin); } async function checkFirstAdmin() { try { const response = await fetch('/api/admin/check-first'); const data = await response.json(); if (data.isFirstAdmin) { document.getElementById('first-admin-notice').style.display = 'block'; document.getElementById('full-name-group').style.display = 'block'; document.querySelector('button[type="submit"]').textContent = 'Create Admin Account'; } } catch (err) { console.error('Error checking first admin:', err); } } async function handleLogin(e) { e.preventDefault(); const form = e.target; const submitBtn = form.querySelector('button[type="submit"]'); const originalText = submitBtn.textContent; submitBtn.disabled = true; submitBtn.innerHTML = ' Processing...'; const formData = new FormData(form); const data = Object.fromEntries(formData); try { const response = await fetch('/api/admin/login', { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify(data) }); const result = await response.json(); if (response.ok) { showAlert('Login successful!', 'success'); setTimeout(() => window.location.href = '/admin/dashboard', 500); } else { showAlert(result.error || 'Login failed', 'error'); } } catch (err) { console.error('Login error:', err); showAlert('Login failed. Please try again.', 'error'); } finally { submitBtn.disabled = false; submitBtn.textContent = originalText; } } // Dashboard page if (window.location.pathname.includes('dashboard')) { loadDashboardStats(); } async function loadDashboardStats() { try { const response = await fetch('/api/admin/stats'); const stats = await response.json(); document.getElementById('stat-new-applications').textContent = stats.new_applications || 0; document.getElementById('stat-total-applications').textContent = stats.total_applications || 0; document.getElementById('stat-total-applicants').textContent = stats.total_applicants || 0; document.getElementById('stat-active-jobs').textContent = stats.active_jobs || 0; if (stats.unread_messages > 0) { document.getElementById('stat-unread-messages').textContent = stats.unread_messages; document.getElementById('stat-unread-messages').parentElement.style.display = 'block'; } } catch (err) { console.error('Error loading stats:', err); } } // Applications page if (window.location.pathname.includes('applicants')) { loadApplications(); } async function loadApplications(filters = {}) { const container = document.getElementById('applications-container'); const loading = document.getElementById('loading'); try { const params = new URLSearchParams(filters); const response = await fetch(`/api/admin/applications?${params}`); const applications = await response.json(); if (loading) loading.style.display = 'none'; if (applications.length === 0) { container.innerHTML = '
No applications found.
| Applicant | Job | Experience | Applied | Status | Actions |
|---|---|---|---|---|---|
|
${escapeHtml(app.full_name)} ${escapeHtml(app.email)} |
${escapeHtml(app.job_title || 'General Application')} | ${app.years_of_experience || 'N/A'} years | ${new Date(app.applied_at).toLocaleDateString()} | ${escapeHtml(app.status)} | View CV |
| Title | Department | Location | Status | Created | Actions |
|---|---|---|---|---|---|
| ${escapeHtml(job.title)} | ${escapeHtml(job.department || 'N/A')} | ${escapeHtml(job.location || 'N/A')} | ${job.is_active ? 'Active' : 'Inactive'} | ${new Date(job.created_at).toLocaleDateString()} |