// Calculator Logic class ProjectCalculator { constructor() { this.selectedServices = []; this.selectedComplexity = null; this.selectedTimeline = null; this.currentStep = 1; this.totalSteps = 3; this.init(); } init() { this.setupEventListeners(); this.updateProgressBar(); } setupEventListeners() { // Service selection document.querySelectorAll('.service-option').forEach(option => { option.addEventListener('click', (e) => this.handleServiceSelection(e)); }); // Complexity selection document.querySelectorAll('.complexity-option').forEach(option => { option.addEventListener('click', (e) => this.handleComplexitySelection(e)); }); // Timeline selection document.querySelectorAll('.timeline-option').forEach(option => { option.addEventListener('click', (e) => this.handleTimelineSelection(e)); }); // Navigation buttons document.querySelectorAll('.next-step').forEach(btn => { btn.addEventListener('click', () => this.nextStep()); }); document.querySelectorAll('.prev-step').forEach(btn => { btn.addEventListener('click', () => this.prevStep()); }); // Restart button const restartBtn = document.querySelector('.restart-calculator'); if (restartBtn) { restartBtn.addEventListener('click', () => this.restart()); } } handleServiceSelection(e) { const option = e.currentTarget; const service = option.dataset.service; const price = parseInt(option.dataset.basePrice); option.classList.toggle('selected'); if (option.classList.contains('selected')) { this.selectedServices.push({ service, price }); this.animateSelection(option, true); } else { this.selectedServices = this.selectedServices.filter(s => s.service !== service); this.animateSelection(option, false); } this.updateStepButton(); } handleComplexitySelection(e) { const option = e.currentTarget; // Clear previous selections document.querySelectorAll('.complexity-option').forEach(opt => { opt.classList.remove('selected'); this.animateSelection(opt, false); }); // Select current option option.classList.add('selected'); this.animateSelection(option, true); this.selectedComplexity = { value: option.dataset.value, multiplier: parseFloat(option.dataset.multiplier) }; this.updateStepButton(); } handleTimelineSelection(e) { const option = e.currentTarget; // Clear previous selections document.querySelectorAll('.timeline-option').forEach(opt => { opt.classList.remove('selected'); this.animateSelection(opt, false); }); // Select current option option.classList.add('selected'); this.animateSelection(option, true); this.selectedTimeline = { value: option.dataset.value, multiplier: parseFloat(option.dataset.multiplier) }; this.updateStepButton(); } animateSelection(element, selected) { if (selected) { element.style.borderColor = '#3B82F6'; element.style.backgroundColor = '#EBF8FF'; element.style.transform = 'translateY(-2px)'; element.style.boxShadow = '0 8px 25px rgba(59, 130, 246, 0.15)'; } else { element.style.borderColor = ''; element.style.backgroundColor = ''; element.style.transform = ''; element.style.boxShadow = ''; } } updateStepButton() { const step1Button = document.querySelector('#step-1 .next-step'); const step2Button = document.querySelector('#step-2 .next-step'); if (step1Button) { step1Button.disabled = this.selectedServices.length === 0; step1Button.style.opacity = this.selectedServices.length > 0 ? '1' : '0.6'; } if (step2Button) { const isValid = this.selectedComplexity && this.selectedTimeline; step2Button.disabled = !isValid; step2Button.style.opacity = isValid ? '1' : '0.6'; } } updateProgressBar() { const progressBar = document.querySelector('.calculator-progress-bar'); if (progressBar) { const progress = (this.currentStep / this.totalSteps) * 100; progressBar.style.width = `${progress}%`; progressBar.className = `calculator-progress-bar step-${this.currentStep}`; } } nextStep() { if (this.currentStep >= this.totalSteps) return; const currentStepElement = document.querySelector('.calculator-step.active'); const nextStepElement = currentStepElement.nextElementSibling; if (nextStepElement && nextStepElement.classList.contains('calculator-step')) { // Animate out current step currentStepElement.style.opacity = '0'; currentStepElement.style.transform = 'translateX(-20px)'; setTimeout(() => { currentStepElement.classList.remove('active'); currentStepElement.style.display = 'none'; // Animate in next step nextStepElement.classList.add('active'); nextStepElement.style.display = 'block'; nextStepElement.style.opacity = '0'; nextStepElement.style.transform = 'translateX(20px)'; setTimeout(() => { nextStepElement.style.opacity = '1'; nextStepElement.style.transform = 'translateX(0)'; }, 50); this.currentStep++; this.updateProgressBar(); if (this.currentStep === 3) { setTimeout(() => this.calculateFinalPrice(), 300); } }, 200); } } prevStep() { if (this.currentStep <= 1) return; const currentStepElement = document.querySelector('.calculator-step.active'); const prevStepElement = currentStepElement.previousElementSibling; if (prevStepElement && prevStepElement.classList.contains('calculator-step')) { // Animate out current step currentStepElement.style.opacity = '0'; currentStepElement.style.transform = 'translateX(20px)'; setTimeout(() => { currentStepElement.classList.remove('active'); currentStepElement.style.display = 'none'; // Animate in previous step prevStepElement.classList.add('active'); prevStepElement.style.display = 'block'; prevStepElement.style.opacity = '0'; prevStepElement.style.transform = 'translateX(-20px)'; setTimeout(() => { prevStepElement.style.opacity = '1'; prevStepElement.style.transform = 'translateX(0)'; }, 50); this.currentStep--; this.updateProgressBar(); }, 200); } } calculateFinalPrice() { let total = 0; // Calculate base price from services this.selectedServices.forEach(service => { total += service.price; }); // Apply complexity multiplier if (this.selectedComplexity) { total *= this.selectedComplexity.multiplier; } // Apply timeline multiplier if (this.selectedTimeline) { total *= this.selectedTimeline.multiplier; } // Animate price reveal const priceElement = document.getElementById('final-price'); if (priceElement) { priceElement.style.opacity = '0'; priceElement.style.transform = 'scale(0.8)'; setTimeout(() => { priceElement.textContent = '₩' + total.toLocaleString(); priceElement.style.opacity = '1'; priceElement.style.transform = 'scale(1)'; }, 300); } // Generate summary setTimeout(() => this.generateSummary(total), 600); } generateSummary(total) { const summary = document.getElementById('project-summary'); if (!summary) return; let summaryHTML = ''; // Services const servicesLabel = window.calculatorTranslations?.labels?.selected_services || 'Selected Services'; const complexityLabel = window.calculatorTranslations?.labels?.complexity || 'Complexity'; const timelineLabel = window.calculatorTranslations?.labels?.timeline || 'Timeline'; summaryHTML += `