// PropertyInvest Pro Dashboard JavaScript for Tilda
document.addEventListener('DOMContentLoaded', function() {
// Инициализация слайдеров
document.querySelectorAll('.tilda-slider').forEach(slider => {
const valueElement = document.getElementById(slider.id + '-value');
// Установка начального значения
updateSliderValue(slider, valueElement);
// Обновление значения при изменении
slider.addEventListener('input', () => {
updateSliderValue(slider, valueElement);
});
});
function updateSliderValue(slider, valueElement) {
if (slider.id.includes('price-to-market')) {
valueElement.textContent = slider.value + '%';
} else if (slider.id.includes('strategy-count')) {
valueElement.textContent = slider.value + '/5';
} else {
valueElement.textContent = slider.value + '/10';
}
}
// Управление вкладками
document.querySelectorAll('.tilda-tab').forEach(tab => {
tab.addEventListener('click', () => {
// Убираем активный класс со всех вкладок
document.querySelectorAll('.tilda-tab').forEach(t => t.classList.remove('active'));
// Добавляем активный класс к текущей вкладке
tab.classList.add('active');
// Скрываем все содержимое вкладок
document.querySelectorAll('.tilda-tab-content').forEach(content => {
content.classList.remove('active');
});
// Показываем содержимое текущей вкладки
const tabId = tab.getAttribute('data-tab');
document.getElementById(tabId + '-tab').classList.add('active');
});
});
// Автоматический расчет финансовых показателей при изменении данных
document.querySelectorAll('#financial-tab input').forEach(input => {
input.addEventListener('input', calculateFinancialMetrics);
});
// Инициализация пустой радар-диаграммы
const ctx = document.getElementById('tilda-radar-chart').getContext('2d');
const radarChart = new Chart(ctx, {
type: 'radar',
data: {
labels: ['Финансы', 'Ликвидность', 'Рост', 'Локация', 'Риски'],
datasets: [{
label: 'Текущий объект',
data: [0, 0, 0, 0, 0],
backgroundColor: 'rgba(52, 152, 219, 0.2)',
borderColor: 'rgba(52, 152, 219, 1)',
borderWidth: 2,
pointBackgroundColor: 'rgba(52, 152, 219, 1)'
}, {
label: 'Средний по рынку',
data: [6.5, 6.8, 6.2, 6.5, 7.2],
backgroundColor: 'rgba(149, 165, 166, 0.2)',
borderColor: 'rgba(149, 165, 166, 1)',
borderWidth: 2,
pointBackgroundColor: 'rgba(149, 165, 166, 1)'
}]
},
options: {
scales: {
r: {
angleLines: {
display: true
},
suggestedMin: 0,
suggestedMax: 10
}
}
}
});
// Функция расчета финансовых показателей
function calculateFinancialMetrics() {
const purchasePrice = parseFloat(document.getElementById('purchase-price').value) || 0;
const initialInvestment = parseFloat(document.getElementById('initial-investment').value) || 0;
const rentalIncome = parseFloat(document.getElementById('rental-income').value) || 0;
const operatingCosts = parseFloat(document.getElementById('operating-costs').value) || 0;
const loanAmount = parseFloat(document.getElementById('loan-amount').value) || 0;
const loanRate = parseFloat(document.getElementById('loan-rate').value) || 0;
const loanTerm = parseFloat(document.getElementById('loan-term').value) || 0;
// Расчет годовых показателей
const annualRentalIncome = rentalIncome * 12;
const annualOperatingCosts = operatingCosts * 12;
const noi = annualRentalIncome - annualOperatingCosts; // Net Operating Income
// Расчет ежемесячного платежа по кредиту
const monthlyRate = loanRate / 100 / 12;
const numberOfPayments = loanTerm * 12;
let monthlyPayment = 0;
if (monthlyRate > 0 && numberOfPayments > 0) {
monthlyPayment = loanAmount * monthlyRate * Math.pow(1 + monthlyRate, numberOfPayments) /
(Math.pow(1 + monthlyRate, numberOfPayments) - 1);
}
const annualDebtService = monthlyPayment * 12;
const annualCashFlow = noi - annualDebtService;
// Расчет финансовых показателей
const cashOnCashReturn = initialInvestment > 0 ? (annualCashFlow / initialInvestment) * 100 : 0;
const capRate = purchasePrice > 0 ? (noi / purchasePrice) * 100 : 0;
const dscr = annualDebtService > 0 ? noi / annualDebtService : 0;
const ltv = purchasePrice > 0 ? (loanAmount / purchasePrice) * 100 : 0;
const paybackPeriod = annualCashFlow > 0 ? initialInvestment / annualCashFlow : 0;
// Обновление отображения
document.getElementById('cash-on-cash-result').textContent = cashOnCashReturn.toFixed(2) + '%';
document.getElementById('cap-rate-result').textContent = capRate.toFixed(2) + '%';
document.getElementById('dscr-result').textContent = dscr.toFixed(2);
document.getElementById('ltv-result').textContent = ltv.toFixed(2) + '%';
document.getElementById('payback-result').textContent = paybackPeriod.toFixed(1) + ' лет';
}
// Инициализация финансовых расчетов
calculateFinancialMetrics();
// Обработчик кнопки расчета
document.getElementById('calculate-btn').addEventListener('click', function() {
// Расчет финансовых показателей
calculateFinancialMetrics();
// Получаем значения из всех вкладок
const financialScore = calculateFinancialScore();
const liquidityScore = calculateLiquidityScore();
const growthScore = calculateGrowthScore();
const locationScore = calculateLocationScore();
const riskScore = calculateRiskScore();
// Обновляем значения на дашборде
document.getElementById('financial-score').textContent = financialScore.toFixed(1);
document.getElementById('liquidity-score').textContent = liquidityScore.toFixed(1);
document.getElementById('risk-score').textContent = riskScore.toFixed(1);
// Обновляем общий потенциал
const overallScore = (financialScore + liquidityScore + growthScore + locationScore + riskScore) / 5;
document.getElementById('overall-score').textContent = overallScore.toFixed(1);
// Обновляем описания
updateScoreDescriptions(overallScore, financialScore, liquidityScore, riskScore);
// Обновляем радар-диаграмму
radarChart.data.datasets[0].data = [
financialScore,
liquidityScore,
growthScore,
locationScore,
riskScore
];
radarChart.update();
// Генерируем рекомендации
generateRecommendations(financialScore, liquidityScore, growthScore, locationScore, riskScore);
// Показываем уведомление
alert('Анализ завершен! Результаты обновлены.');
});
// Функции расчета оценок для каждого блока
function calculateFinancialScore() {
const cashOnCash = parseFloat(document.getElementById('cash-on-cash-result').textContent) || 0;
const capRate = parseFloat(document.getElementById('cap-rate-result').textContent) || 0;
const dscr = parseFloat(document.getElementById('dscr-result').textContent) || 0;
const ltv = parseFloat(document.getElementById('ltv-result').textContent) || 0;
// Нормализуем показатели к 10-балльной шкале
const cashOnCashScore = Math.min(cashOnCash / 2, 10); // 20% CoC = 10 баллов
const capRateScore = Math.min(capRate * 1.5, 10); // ~6.7% Cap Rate = 10 баллов
const dscrScore = Math.min(dscr * 5, 10); // DSCR 2.0 = 10 баллов
const ltvScore = Math.max(10 - (ltv / 10), 0); // LTV 0% = 10 баллов, 100% = 0 баллов
return (cashOnCashScore + capRateScore + dscrScore + ltvScore) / 4;
}
function calculateLiquidityScore() {
const timeToSell = parseInt(document.getElementById('time-to-sell').value) || 0;
const priceToMarket = parseInt(document.getElementById('price-to-market').value) || 0;
const uniqueness = parseInt(document.getElementById('uniqueness').value) || 0;
const strategyCount = parseInt(document.getElementById('strategy-count').value) || 0;
// Нормализуем показатели к 10-балльной шкале
const timeScore = Math.max(10 - (timeToSell / 10), 0); // 10 дней = 9 баллов, 100 дней = 0 баллов
const priceScore = Math.min(priceToMarket / 10, 10); // 100% от рынка = 10 баллов
const uniquenessScore = uniqueness; // уже в 10-балльной шкале
const strategyScore = strategyCount * 2; // 5 стратегий = 10 баллов
return (timeScore + priceScore + uniquenessScore + strategyScore) / 4;
}
function calculateGrowthScore() {
const historicalGrowth = parseFloat(document.getElementById('historical-growth').value) || 0;
const forcedAppreciation = parseInt(document.getElementById('forced-appreciation').value) || 0;
const locationDevelopment = parseInt(document.getElementById('location-development').value) || 0;
const macroFactors = parseInt(document.getElementById('macro-factors').value) || 0;
// Нормализуем показатели к 10-балльной шкале
const growthScore = Math.min(historicalGrowth * 1.2, 10); // 8.3% рост = 10 баллов
const appreciationScore = forcedAppreciation; // уже в 10-балльной шкале
const developmentScore = locationDevelopment; // уже в 10-балльной шкале
const macroScore = macroFactors; // уже в 10-балльной шкале
return (growthScore + appreciationScore + developmentScore + macroScore) / 4;
}
function calculateLocationScore() {
const transport = parseInt(document.getElementById('transport-access').value) || 0;
const infrastructure = parseInt(document.getElementById('infrastructure').value) || 0;
const ecology = parseInt(document.getElementById('ecology').value) || 0;
return (transport + infrastructure + ecology) / 3;
}
function calculateRiskScore() {
const buildingQuality = parseInt(document.getElementById('building-quality').value) || 0;
const management = parseInt(document.getElementById('management').value) || 0;
const expenseVolatility = parseInt(document.getElementById('expense-volatility').value) || 0;
return (buildingQuality + management + expenseVolatility) / 3;
}
// Функция обновления описаний оценок
function updateScoreDescriptions(overall, financial, liquidity, risk) {
// Общее описание
let overallDesc = "";
if (overall >= 8) overallDesc = "Отличный инвестиционный потенциал";
else if (overall >= 6) overallDesc = "Хороший инвестиционный потенциал";
else if (overall >= 4) overallDesc = "Средний инвестиционный потенциал";
else overallDesc = "Низкий инвестиционный потенциал";
document.getElementById('overall-description').textContent = overallDesc;
// Финансовое описание
let financialDesc = "";
if (financial >= 8) financialDesc = "Высокая доходность";
else if (financial >= 6) financialDesc = "Стабильная доходность";
else if (financial >= 4) financialDesc = "Умеренная доходность";
else financialDesc = "Низкая доходность";
document.getElementById('financial-description').textContent = financialDesc;
// Описание ликвидности
let liquidityDesc = "";
if (liquidity >= 8) liquidityDesc = "Высокая ликвидность";
else if (liquidity >= 6) liquidityDesc = "Хорошая ликвидность";
else if (liquidity >= 4) liquidityDesc = "Средняя ликвидность";
else liquidityDesc = "Низкая ликвидность";
document.getElementById('liquidity-description').textContent = liquidityDesc;
// Описание рисков
let riskDesc = "";
if (risk >= 8) riskDesc = "Минимальные риски";
else if (risk >= 6) riskDesc = "Умеренные риски";
else if (risk >= 4) riskDesc = "Повышенные риски";
else riskDesc = "Высокие риски";
document.getElementById('risk-description').textContent = riskDesc;
}
// Функция генерации рекомендаций
function generateRecommendations(financial, liquidity, growth, location, risk) {
const recommendationsList = document.getElementById('tilda-recommendations-list');
recommendationsList.innerHTML = '';
// Рекомендации по финансам
if (financial < 6) {
recommendationsList.innerHTML += `
Улучшите финансовые показатели
Рассмотрите возможность снижения цены покупки или увеличения арендного дохода для повышения доходности инвестиций.
`;
}
// Рекомендации по ликвидности
if (liquidity < 6) {
recommendationsList.innerHTML += `
Повысьте ликвидность объекта
Рассмотрите стратегии улучшения объекта для ускорения будущей продажи. Цена должна быть конкурентоспособной на рынке.
`;
}
// Рекомендации по росту
if (growth < 6) {
recommendationsList.innerHTML += `
Обратите внимание на потенциал роста
Исследуйте возможности принудительного роста стоимости через ремонт или улучшение объекта.
`;
}
// Рекомендации по локации
if (location < 6) {
recommendationsList.innerHTML += `
Учтите особенности локации
Данная локация может ограничивать потенциал аренды и будущего роста стоимости. Рассмотрите объекты в более развитых районах.
`;
}
// Рекомендации по рискам
if (risk < 6) {
recommendationsList.innerHTML += `
Снизьте операционные риски
Рассмотрите смену управляющей компании и проведите оценку необходимости капитального ремонта для снижения непредвиденных расходов.
`;
}
// Общая рекомендация при хороших показателях
if (financial >= 7 && liquidity >= 7 && risk >= 7) {
recommendationsList.innerHTML += `
Объект имеет хороший инвестиционный потенциал
Данный объект демонстрирует сбалансированные показатели по всем ключевым параметрам. Рекомендуем к рассмотрению для инвестирования.
`;
}
// Если нет рекомендаций
if (recommendationsList.innerHTML === '') {
recommendationsList.innerHTML = `
Заполните все параметры
Введите данные во всех вкладках и нажмите "Рассчитать потенциал" для получения персонализированных рекомендаций.
`;
}
}
// Обработчики кнопок входа и премиума
document.getElementById('login-btn').addEventListener('click', function() {
alert('Функция входа будет доступна в ближайшее время');
});
document.getElementById('premium-btn').addEventListener('click', function() {
alert('Премиум-функции будут доступны после запуска платной подписки');
});
});