// Dynamic Price Island Controller class PriceIsland { constructor() { this.island = document.getElementById('priceIsland'); this.container = document.getElementById('islandContainer'); this.content = document.getElementById('islandContent'); this.totalPrice = document.getElementById('totalPrice'); this.selectedServices = []; this.projectDetails = {}; this.appliedPromo = null; this.isExpanded = false; this.init(); } init() { // Listen for calculator changes document.addEventListener('calculatorStateChange', (e) => { this.updateIsland(e.detail); }); // Initialize promo code functionality this.initPromoCode(); // Show island initially as compact this.showCompact(); } updateIsland(calculatorData) { const { selectedServices, complexity, timeline, totalPrice } = calculatorData; this.selectedServices = selectedServices || []; this.projectDetails = { complexity, timeline }; // Update total price this.updateTotalPrice(totalPrice || 0); // Update content this.updateContent(); // Expand if there's data to show if (this.selectedServices.length > 0 || complexity || timeline) { this.expand(); } else { this.collapse(); } } updateTotalPrice(price) { if (this.totalPrice) { this.totalPrice.textContent = this.formatPrice(price); this.totalPrice.classList.add('price-update'); setTimeout(() => { this.totalPrice.classList.remove('price-update'); }, 300); } } updateContent() { this.updateSelectedServices(); this.updateProjectDetails(); this.updatePriceBreakdown(); } updateSelectedServices() { const container = document.getElementById('selectedServices'); const list = document.getElementById('servicesList'); if (this.selectedServices.length > 0) { container.classList.remove('hidden'); list.innerHTML = this.selectedServices.map(service => `
${service.name} ${this.formatPrice(service.price)}
`).join(''); } else { container.classList.add('hidden'); } } updateProjectDetails() { const container = document.getElementById('projectDetails'); const list = document.getElementById('detailsList'); const details = []; if (this.projectDetails.complexity) { details.push(`Сложность: ${this.projectDetails.complexity.name} (×${this.projectDetails.complexity.multiplier})`); } if (this.projectDetails.timeline) { details.push(`Сроки: ${this.projectDetails.timeline.name} (×${this.projectDetails.timeline.multiplier})`); } if (details.length > 0) { container.classList.remove('hidden'); list.innerHTML = details.map(detail => `
${detail}
`).join(''); } else { container.classList.add('hidden'); } } updatePriceBreakdown() { const container = document.getElementById('priceBreakdown'); const list = document.getElementById('breakdownList'); if (this.selectedServices.length > 0) { container.classList.remove('hidden'); const basePrice = this.selectedServices.reduce((sum, service) => sum + service.price, 0); const complexityMultiplier = this.projectDetails.complexity?.multiplier || 1; const timelineMultiplier = this.projectDetails.timeline?.multiplier || 1; const afterComplexity = basePrice * complexityMultiplier; const final = afterComplexity * timelineMultiplier; let breakdown = [ { label: 'Базовая стоимость', value: basePrice } ]; if (complexityMultiplier !== 1) { breakdown.push({ label: `Сложность (×${complexityMultiplier})`, value: afterComplexity }); } if (timelineMultiplier !== 1) { breakdown.push({ label: `Сроки (×${timelineMultiplier})`, value: final }); } if (this.appliedPromo) { const discount = final * (this.appliedPromo.discount / 100); breakdown.push({ label: `Скидка ${this.appliedPromo.code} (-${this.appliedPromo.discount}%)`, value: final - discount, isDiscount: true }); } list.innerHTML = breakdown.map(item => `
${item.label} ${this.formatPrice(item.value)}
`).join(''); } else { container.classList.add('hidden'); } } initPromoCode() { const promoBtn = document.getElementById('applyPromoBtn'); const promoInput = document.getElementById('promoInput'); const promoStatus = document.getElementById('promoStatus'); if (promoBtn && promoInput) { promoBtn.addEventListener('click', () => { const code = promoInput.value.trim().toUpperCase(); this.applyPromoCode(code); }); promoInput.addEventListener('keypress', (e) => { if (e.key === 'Enter') { const code = promoInput.value.trim().toUpperCase(); this.applyPromoCode(code); } }); } } applyPromoCode(code) { const promoStatus = document.getElementById('promoStatus'); // Simulate promo code validation const validCodes = { 'WELCOME10': { discount: 10, name: 'Скидка новичка' }, 'SAVE20': { discount: 20, name: 'Экономия 20%' }, 'VIP15': { discount: 15, name: 'VIP скидка' } }; if (validCodes[code]) { this.appliedPromo = { code, ...validCodes[code] }; promoStatus.textContent = `✓ Применен: ${this.appliedPromo.name}`; promoStatus.className = 'text-xs mt-1 text-green-600 dark:text-green-400'; // Trigger recalculation this.updateContent(); this.recalculateTotal(); } else if (code) { promoStatus.textContent = '✗ Неверный промокод'; promoStatus.className = 'text-xs mt-1 text-red-600 dark:text-red-400'; } else { promoStatus.textContent = ''; } } recalculateTotal() { if (this.selectedServices.length > 0) { const basePrice = this.selectedServices.reduce((sum, service) => sum + service.price, 0); const complexityMultiplier = this.projectDetails.complexity?.multiplier || 1; const timelineMultiplier = this.projectDetails.timeline?.multiplier || 1; let total = basePrice * complexityMultiplier * timelineMultiplier; if (this.appliedPromo) { total = total * (1 - this.appliedPromo.discount / 100); } this.updateTotalPrice(total); // Also update mobile price if exists const mobilePrice = document.getElementById('mobilePriceValue'); if (mobilePrice) { mobilePrice.textContent = this.formatPrice(total); } } } expand() { if (!this.isExpanded) { this.isExpanded = true; this.content.style.maxHeight = this.content.scrollHeight + 'px'; // Show promo section when expanded const promoSection = document.getElementById('promoSection'); if (promoSection) { promoSection.classList.remove('hidden'); } } } collapse() { if (this.isExpanded) { this.isExpanded = false; this.content.style.maxHeight = '0'; // Hide promo section when collapsed const promoSection = document.getElementById('promoSection'); if (promoSection) { promoSection.classList.add('hidden'); } } } showCompact() { this.island.classList.remove('hidden'); } hide() { this.island.classList.add('hidden'); } formatPrice(price) { return new Intl.NumberFormat('ko-KR', { style: 'currency', currency: 'KRW', maximumFractionDigits: 0 }).format(price); } } // CSS for price update animation const style = document.createElement('style'); style.textContent = ` .price-update { animation: priceUpdate 0.3s ease-out; } @keyframes priceUpdate { 0% { transform: scale(1); } 50% { transform: scale(1.1); } 100% { transform: scale(1); } } `; document.head.appendChild(style); // Initialize when DOM is loaded document.addEventListener('DOMContentLoaded', () => { window.priceIsland = new PriceIsland(); }); // Export for use in calculator window.PriceIsland = PriceIsland;