// 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;