document.addEventListener('DOMContentLoaded', () => { loadJobs(); loadSavedJobs(); setupEventListeners(); }); // Feature 1 & 3: Global State & Event Listeners function setupEventListeners() { const searchInput = document.getElementById('jobSearch'); const categorySelect = document.getElementById('categoryFilter'); searchInput.addEventListener('input', debounce(() => { loadJobs(searchInput.value, categorySelect.value); }, 500)); categorySelect.addEventListener('change', () => { loadJobs(searchInput.value, categorySelect.value); }); // Listen for save events from job cards document.addEventListener('job-saved', (e) => { saveJob(e.detail); }); // Listen for remove events document.addEventListener('job-removed', (e) => { removeJob(e.detail.id); }); } // Feature 3: Save Job Logic function saveJob(jobData) { let saved = JSON.parse(localStorage.getItem('warriorSavedJobs')) || []; // Avoid duplicates if (saved.some(j => j.url === jobData.url)) { alert('Target already in Hitlist.'); return; } jobData.savedAt = new Date().toISOString(); saved.push(jobData); localStorage.setItem('warriorSavedJobs', JSON.stringify(saved)); loadSavedJobs(); // Refresh UI } function removeJob(url) { let saved = JSON.parse(localStorage.getItem('warriorSavedJobs')) || []; saved = saved.filter(j => j.url !== url); localStorage.setItem('warriorSavedJobs', JSON.stringify(saved)); loadSavedJobs(); // Refresh UI } function loadSavedJobs() { const container = document.getElementById('saved-jobs-list'); const saved = JSON.parse(localStorage.getItem('warriorSavedJobs')) || []; if (saved.length === 0) { container.innerHTML = `

No targets locked yet. Click the heart on job cards to save them.

`; return; } container.innerHTML = ''; saved.forEach(job => { const el = document.createElement('div'); el.className = 'bg-slate-800 p-4 rounded-lg border border-slate-700 flex flex-col sm:flex-row justify-between items-start sm:items-center gap-4'; el.innerHTML = `

${job.title}

${job.company}

Apply
`; container.appendChild(el); }); feather.replace(); } // Feature 1: Enhanced Load Jobs with Filtering async function loadJobs(searchTerm = '', category = '') { const grid = document.getElementById('job-grid'); // Show loading state if it's empty if (grid.innerHTML.trim() === '') { grid.innerHTML = `

Scanning market...

`; feather.replace(); } try { const response = await fetch('https://remotive.com/api/remote-jobs?limit=12'); const data = await response.json(); grid.innerHTML = ''; if(data.jobs && data.jobs.length > 0) { const filtered = data.jobs.filter(job => { // Category Filter Logic if (category && job.category !== category) return false; // Search Logic if (searchTerm) { const term = searchTerm.toLowerCase(); const title = job.title.toLowerCase(); const company = job.company_name.toLowerCase(); return title.includes(term) || company.includes(term); } return true; }); if (filtered.length === 0) { grid.innerHTML = '

No targets match your filters.

'; return; } filtered.forEach(job => { // Check if already saved const saved = JSON.parse(localStorage.getItem('warriorSavedJobs')) || []; const isSaved = saved.some(j => j.url === job.url); const card = document.createElement('job-card'); card.setAttribute('title', job.title); card.setAttribute('company', job.company_name); card.setAttribute('salary', job.salary || 'Competitive'); card.setAttribute('type', job.job_type); card.setAttribute('url', job.url); card.setAttribute('category', job.category); card.setAttribute('saved', isSaved); // Pass state grid.appendChild(card); }); } } catch (error) { console.error('Error:', error); grid.innerHTML = `

Connection lost.

`; } } // Utility: Debounce search input function debounce(func, wait) { let timeout; return function executedFunction(...args) { const later = () => { clearTimeout(timeout); func(...args); }; clearTimeout(timeout); timeout = setTimeout(later, wait); }; } async function loadJobs() { const grid = document.getElementById('job-grid'); try { // Using Remotive API for remote jobs (Public, No Key needed usually) const response = await fetch('https://remotive.com/api/remote-jobs?limit=9'); const data = await response.json(); grid.innerHTML = ''; // Clear loading state if(data.jobs && data.jobs.length > 0) { data.jobs.forEach(job => { // Create a job-card element const card = document.createElement('job-card'); // Set attributes (Passing data to component) card.setAttribute('title', job.title); card.setAttribute('company', job.company_name); card.setAttribute('salary', job.salary || 'Competitive'); card.setAttribute('type', job.job_type); card.setAttribute('url', job.url); card.setAttribute('category', job.category); grid.appendChild(card); }); } else { grid.innerHTML = '

No targets found at this moment.

'; } } catch (error) { console.error('Error fetching jobs:', error); grid.innerHTML = `

Connection lost to the network.

`; } }