'use strict'; function initBriefWizard() { const form = document.querySelector('[data-brief-wizard]'); if (!form) return; const panels = Array.from(form.querySelectorAll('[data-wizard-panel]')); const indicators = Array.from(form.querySelectorAll('[data-wizard-step-indicator]')); const prevBtn = form.querySelector('[data-wizard-prev]'); const nextBtn = form.querySelector('[data-wizard-next]'); const submitBtn = form.querySelector('[data-wizard-submit]'); const progressFill = form.querySelector('[data-wizard-progress-fill]'); const reviewBlock = form.querySelector('[data-wizard-review]'); const totalSteps = panels.length; let currentStep = Number(form.dataset.initialStep || '1'); if (currentStep < 1 || currentStep > totalSteps) { currentStep = 1; } function getPanel(step) { return form.querySelector(`[data-wizard-panel="${step}"]`); } function getFields(step) { const panel = getPanel(step); if (!panel) return []; const fieldNames = (panel.dataset.stepFields || '').split(',').filter(Boolean); return fieldNames .map((name) => { if (name === 'attachments') { return form.querySelector('#id_attachments'); } return form.querySelector(`[name="${name}"]`); }) .filter(Boolean); } function stepForField(field) { if (!field || !field.name) return 1; for (const panel of panels) { const fieldNames = (panel.dataset.stepFields || '').split(',').filter(Boolean); if (fieldNames.includes(field.name)) { return Number(panel.dataset.wizardPanel); } } return 1; } function isFieldValid(field) { if (!field) return true; if (field.disabled) return true; if (field.type === 'file') return true; if (field.required && !String(field.value || '').trim()) { field.reportValidity(); return false; } if (!field.checkValidity()) { field.reportValidity(); return false; } return true; } function validateStep(step) { const fields = getFields(step); return fields.every((field) => isFieldValid(field)); } function validateAllRequired() { const requiredFields = Array.from( form.querySelectorAll('input, select, textarea') ).filter((field) => field.required && !field.disabled); for (const field of requiredFields) { if (!isFieldValid(field)) { setStep(stepForField(field)); field.focus(); return false; } } return true; } function optionLabel(select) { if (!select || select.tagName !== 'SELECT') return '—'; const option = select.options[select.selectedIndex]; if (!option || !option.value) return 'Not specified'; return option.textContent.trim(); } function updateReview() { if (!reviewBlock) return; const title = form.querySelector('#id_title'); const category = form.querySelector('#id_category'); const description = form.querySelector('#id_description'); const budget = form.querySelector('#id_budget_range'); const deadline = form.querySelector('#id_desired_deadline'); const links = form.querySelector('#id_reference_links'); const attachments = form.querySelector('#id_attachments'); const setReview = (name, value) => { const target = reviewBlock.querySelector(`[data-review-field="${name}"]`); if (target) target.textContent = value || '—'; }; setReview('title', title ? title.value.trim() : '—'); setReview('category', optionLabel(category)); setReview('description', description && description.value.trim() ? description.value.trim() : 'Not specified'); setReview('budget_range', optionLabel(budget)); setReview('desired_deadline', deadline && deadline.value ? deadline.value : 'Not specified'); setReview('reference_links', links && links.value.trim() ? links.value.trim() : 'None'); if (attachments && attachments.files && attachments.files.length) { const names = Array.from(attachments.files).map((file) => file.name).join(', '); setReview('attachments', names); } else { setReview('attachments', 'None'); } } function setStep(step) { currentStep = step; panels.forEach((panel) => { const panelStep = Number(panel.dataset.wizardPanel); const isActive = panelStep === step; panel.classList.toggle('is-active', isActive); panel.hidden = !isActive; }); indicators.forEach((indicator) => { const indicatorStep = Number(indicator.dataset.wizardStepIndicator); indicator.classList.toggle('is-active', indicatorStep === step); indicator.classList.toggle('is-complete', indicatorStep < step); }); if (progressFill && totalSteps > 1) { const progress = ((step - 1) / (totalSteps - 1)) * 100; progressFill.style.width = `${progress}%`; } if (prevBtn) prevBtn.hidden = step === 1; if (nextBtn) nextBtn.hidden = step === totalSteps; if (submitBtn) submitBtn.hidden = step !== totalSteps; if (reviewBlock) reviewBlock.hidden = step !== totalSteps; if (step === totalSteps) { updateReview(); } } if (prevBtn) { prevBtn.addEventListener('click', () => { if (currentStep > 1) { setStep(currentStep - 1); } }); } if (nextBtn) { nextBtn.addEventListener('click', () => { if (!validateStep(currentStep)) return; if (currentStep < totalSteps) { setStep(currentStep + 1); } }); } form.addEventListener('submit', (event) => { if (currentStep !== totalSteps) { event.preventDefault(); if (validateStep(currentStep) && currentStep < totalSteps) { setStep(currentStep + 1); } return; } if (!validateAllRequired()) { event.preventDefault(); } }); form.querySelectorAll('input, select, textarea').forEach((field) => { field.addEventListener('keydown', (event) => { if (event.key === 'Enter' && field.tagName !== 'TEXTAREA' && currentStep !== totalSteps) { event.preventDefault(); if (validateStep(currentStep) && currentStep < totalSteps) { setStep(currentStep + 1); } } }); field.addEventListener('input', () => { if (currentStep === totalSteps) { updateReview(); } }); field.addEventListener('change', () => { if (currentStep === totalSteps) { updateReview(); } }); }); setStep(currentStep); } document.addEventListener('DOMContentLoaded', initBriefWizard);