// 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 summaryHTML += '
Selected Services:
'; this.selectedServices.forEach(service => { summaryHTML += `
${this.getServiceName(service.service)} ₩${service.price.toLocaleString()}
`; }); // Complexity if (this.selectedComplexity) { summaryHTML += `
Complexity: ${this.getComplexityName(this.selectedComplexity.value)} ×${this.selectedComplexity.multiplier}
`; } // Timeline if (this.selectedTimeline) { summaryHTML += `
Timeline: ${this.getTimelineName(this.selectedTimeline.value)} ×${this.selectedTimeline.multiplier}
`; } // Animate summary appearance summary.style.opacity = '0'; summary.innerHTML = summaryHTML; setTimeout(() => { summary.style.opacity = '1'; }, 200); } getServiceName(service) { if (window.calculatorTranslations && window.calculatorTranslations.services) { return window.calculatorTranslations.services[service] || service; } const names = { web: 'Web Development', mobile: 'Mobile App', design: 'UI/UX Design', marketing: 'Digital Marketing' }; return names[service] || service; } getComplexityName(complexity) { if (window.calculatorTranslations && window.calculatorTranslations.complexity) { return window.calculatorTranslations.complexity[complexity] || complexity; } const names = { simple: 'Simple', medium: 'Medium', complex: 'Complex' }; return names[complexity] || complexity; } getTimelineName(timeline) { if (window.calculatorTranslations && window.calculatorTranslations.timeline) { return window.calculatorTranslations.timeline[timeline] || timeline; } const names = { standard: 'Standard', rush: 'Rush', extended: 'Extended' }; return names[timeline] || timeline; } restart() { // Reset all selections this.selectedServices = []; this.selectedComplexity = null; this.selectedTimeline = null; this.currentStep = 1; // Reset UI document.querySelectorAll('.service-option, .complexity-option, .timeline-option').forEach(opt => { opt.classList.remove('selected'); this.animateSelection(opt, false); }); // Reset steps document.querySelectorAll('.calculator-step').forEach(step => { step.classList.remove('active'); step.style.display = 'none'; step.style.opacity = '1'; step.style.transform = 'translateX(0)'; }); // Show first step const firstStep = document.getElementById('step-1'); if (firstStep) { firstStep.classList.add('active'); firstStep.style.display = 'block'; } this.updateProgressBar(); this.updateStepButton(); } } // Initialize calculator when DOM is loaded document.addEventListener('DOMContentLoaded', function() { // Theme initialization const theme = localStorage.getItem('theme') || 'light'; document.documentElement.className = theme === 'dark' ? 'dark' : ''; // Initialize calculator if (document.querySelector('.calculator-step')) { new ProjectCalculator(); } });