// Admin JavaScript for Ryans Recruit Firm // Check authentication on all admin pages except login if (!window.location.pathname.includes('login.html')) { 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.html'; 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.html'; } } // Login page handlers if (window.location.pathname.includes('login.html')) { 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.html', 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.html')) { 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.html')) { 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.

'; return; } container.innerHTML = ` ${applications.map(app => ` `).join('')}
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
`; } catch (err) { console.error('Error loading applications:', err); if (loading) loading.style.display = 'none'; container.innerHTML = '
Failed to load applications
'; } } // Jobs management page if (window.location.pathname.includes('jobs.html') && window.location.pathname.includes('admin')) { loadAdminJobs(); } async function loadAdminJobs() { const container = document.getElementById('jobs-container'); const loading = document.getElementById('loading'); try { const response = await fetch('/api/admin/jobs'); const jobs = await response.json(); if (loading) loading.style.display = 'none'; container.innerHTML = `
${jobs.map(job => ` `).join('')}
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()}
`; } catch (err) { console.error('Error loading jobs:', err); if (loading) loading.style.display = 'none'; container.innerHTML = '
Failed to load jobs
'; } } async function toggleJobStatus(jobId, isActive) { try { const response = await fetch(`/api/admin/jobs/${jobId}`, { method: 'PATCH', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ isActive }) }); if (response.ok) { showAlert(`Job ${isActive ? 'activated' : 'deactivated'} successfully`, 'success'); loadAdminJobs(); } else { showAlert('Failed to update job status', 'error'); } } catch (err) { console.error('Error updating job:', err); showAlert('Failed to update job status', 'error'); } } // Logout async function logout() { try { await fetch('/api/admin/logout', { method: 'POST' }); window.location.href = '/admin/login.html'; } catch (err) { console.error('Logout error:', err); window.location.href = '/admin/login.html'; } } // Utility functions function escapeHtml(text) { if (!text) return ''; const div = document.createElement('div'); div.textContent = text; return div.innerHTML; } function getStatusColor(status) { const colors = { 'new': 'primary', 'reviewing': 'warning', 'interview': 'info', 'hired': 'success', 'rejected': 'error' }; return colors[status] || 'primary'; } 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); }