<script src="https://cdn.jsdelivr.net/npm/chart.js@3.8.0"></script>
<script>
document.addEventListener('DOMContentLoaded', function() {
const donutColor1 = '#D6D6D6';
const donutColor2 = '#FF6B01';
const forms = document.querySelectorAll('.form-section div[data-elem-type="form"]');
let renderedForms = 0;
const totalForms = forms.length;
let chart = null;
function initCalculator() {
if (window._calculatorInitialized) {
return;
}
window._calculatorInitialized = true;
let control = true;
const diagramm = document.querySelector('.diagramm');
if (diagramm) {
diagramm.innerHTML = '<div class="diag-wrapper"><canvas id="doughnutChartID"></canvas></div>';
}
const posPriceRange = document.querySelector('input[name="pos-price-range"]');
const prepaidRange = document.querySelector('input[name="prepaid-range"]');
const termRange = document.querySelector('input[name="term-range"]');
const posPriceInp = document.querySelector('input[name="pos-price-inp"]');
const prepaidInp = document.querySelector('input[name="prepaid-inp"]');
const termInp = document.querySelector('input[name="term-inp"]');
const monthPayEl = document.querySelector('.month-pay .tn-atom');
const creditEl = document.querySelector('.credit .tn-atom');
const finalPercentEl = document.querySelector('.final-percent .tn-atom');
const percentNumEl = document.querySelector('.percent-num .tn-atom');
if (!posPriceRange || !prepaidRange || !termRange) {
console.warn('Не все элементы формы найдены');
return;
}
function formatNumber(num) {
return Math.round(num).toString().replace(/\B(?=(\d{3})+(?!\d))/g, ' ');
}
function cleanNumber(str) {
if (!str) return 0;
return parseInt(str.toString().replace(/[^0-9]/g, '')) || 0;
}
function updateRangeLabels() {
const formSection = document.querySelector('.form-section');
if (!formSection) return;
const rangeGroups = formSection.querySelectorAll('.t-input-group_rg');
rangeGroups.forEach(function(group) {
const rangeInput = group.querySelector('input[type="range"]');
if (!rangeInput) return;
const minVal = parseInt(rangeInput.min) || 0;
const maxVal = parseInt(rangeInput.max) || 0;
const minLabel = group.querySelector('.t-range__interval-txt_min');
const maxLabel = group.querySelector('.t-range__interval-txt_max');
if (minLabel) {
minLabel.setAttribute('data-num', formatNumber(minVal));
}
if (maxLabel) {
maxLabel.setAttribute('data-num', formatNumber(maxVal));
}
});
}
function countCalc() {
let summa = cleanNumber(posPriceRange.value);
let vznos = cleanNumber(prepaidRange.value);
let srok = cleanNumber(termRange.value);
let percent = 105;
let creditSumm = summa - vznos;
if (creditSumm <= 0) creditSumm = 0;
let monthPercent = percent / 12 / 100;
let degree = Math.pow(1 + monthPercent, -srok);
let monthCredit = creditSumm * (monthPercent / (1 - degree));
let finalSumm = monthCredit * srok;
let percentSumm = finalSumm - creditSumm;
let percentSumm2 = percentSumm;
let income = monthCredit * 1.6667;
let itSumm = creditSumm + vznos + percentSumm;
let creditSumm2 = itSumm;
monthCredit = formatNumber(monthCredit);
creditSumm = formatNumber(creditSumm);
itSumm = formatNumber(itSumm);
finalSumm = formatNumber(finalSumm);
percentSumm = formatNumber(percentSumm);
income = formatNumber(income);
if (monthPayEl) monthPayEl.textContent = monthCredit + ' ₽';
if (creditEl) creditEl.textContent = itSumm + ' ₽';
if (finalPercentEl) finalPercentEl.textContent = percentSumm + ' ₽';
let allSumm = creditSumm2 + percentSumm2;
let prcDiag = Math.round((creditSumm2 * 100) / allSumm);
if (chart) {
chart.data.datasets[0].data[0] = 100 - prcDiag;
chart.data.datasets[0].data[1] = prcDiag;
chart.update();
}
setTimeout(function() {
const hiddenCost = document.querySelector('input[type="hidden"][name="Сумма"]');
const hiddenPrepaid = document.querySelector('input[type="hidden"][name="Первоначальный взнос"]');
const hiddenTerm = document.querySelector('input[type="hidden"][name="Срок"]');
const hiddenRate = document.querySelector('input[type="hidden"][name="Ставка"]');
const hiddenTotal = document.querySelector('input[type="hidden"][name="Итоговая стоимость"]');
const hiddenMarkup = document.querySelector('input[type="hidden"][name="Торговая наценка"]');
const hiddenPayment = document.querySelector('input[type="hidden"][name="Ежемесячный платёж"]');
if (hiddenCost) hiddenCost.value = posPriceInp ? posPriceInp.value : '';
if (hiddenPrepaid) hiddenPrepaid.value = prepaidInp ? prepaidInp.value : '';
if (hiddenTerm) hiddenTerm.value = termInp ? termInp.value : '';
if (hiddenRate) hiddenRate.value = percent + '%';
if (hiddenTotal) hiddenTotal.value = itSumm + ' ₽';
if (hiddenMarkup) hiddenMarkup.value = percentSumm + ' ₽';
if (hiddenPayment) hiddenPayment.value = monthCredit + ' ₽';
updateRangeLabels();
}, 500);
}
if (typeof Chart !== 'undefined') {
const canvas = document.getElementById('doughnutChartID');
if (canvas) {
try {
chart = new Chart(canvas, {
type: 'doughnut',
data: {
datasets: [{
data: [100, 0],
backgroundColor: [donutColor1, donutColor2],
spacing: 1,
rotation: 90,
borderRadius: 5,
}],
},
options: {
cutout: 28,
},
});
} catch(e) {
console.error('Ошибка создания графика:', e);
}
}
}
function setInpVal() {
if (posPriceInp && posPriceRange) {
posPriceInp.value = formatNumber(cleanNumber(posPriceRange.value)) + ' ₽';
}
if (prepaidInp && prepaidRange) {
let prc = cleanNumber(prepaidRange.value);
prepaidInp.value = formatNumber(prc) + ' ₽';
}
if (percentNumEl && posPriceRange && prepaidRange) {
let summa = cleanNumber(posPriceRange.value);
let prc = cleanNumber(prepaidRange.value);
let percent = summa > 0 ? ((prc * 100) / summa).toFixed(1) : '0';
percentNumEl.textContent = percent + '%';
}
if (termInp && termRange) {
let term = cleanNumber(termRange.value);
let pdps = ' мес';
if (term == 1 || term == 21 || term == 31) pdps = ' мес';
if (term == 2 || term == 3 || term == 4 || term == 22 || term == 23 || term == 24 || term == 32 || term == 33 || term == 34) pdps = ' мес';
termInp.value = term + pdps;
}
}
function updateRangeFromInput(input, range, format = true, suffix = ' ₽') {
if (!input || !range) return;
let val = cleanNumber(input.value);
let min = parseInt(range.min) || 0;
let max = parseInt(range.max) || 0;
val = Math.max(min, Math.min(max, val));
range.value = val;
if (format) {
input.value = formatNumber(val) + suffix;
}
setInpVal();
countCalc();
range.dispatchEvent(new Event('input', { bubbles: true }));
range.dispatchEvent(new Event('change', { bubbles: true }));
}
function maxCorrect() {
setTimeout(function() {
if (posPriceRange && prepaidRange) {
let costt = cleanNumber(posPriceRange.value);
let newMax = Math.round(+costt * 0.50);
let newMin = Math.round(+costt * 0.25);
prepaidRange.max = newMax;
prepaidRange.min = newMin;
let prepaidVal = cleanNumber(prepaidRange.value);
if (prepaidVal > newMax) {
prepaidRange.value = newMax;
if (prepaidInp) {
prepaidInp.value = formatNumber(newMax) + ' ₽';
}
} else if (prepaidVal < newMin) {
prepaidRange.value = newMin;
if (prepaidInp) {
prepaidInp.value = formatNumber(newMin) + ' ₽';
}
}
prepaidRange.dispatchEvent(new Event('input', { bubbles: true }));
updateRangeLabels();
setInpVal();
countCalc();
}
}, 500);
}
function digits_int(target) {
let val = target.value.replace(/[^0-9.]/g, '');
if (val) {
let num = parseInt(val);
target.value = formatNumber(num);
}
}
setTimeout(function() {
maxCorrect();
setInpVal();
countCalc();
setTimeout(updateRangeLabels, 100);
}, 1500);
if (posPriceInp) {
posPriceInp.addEventListener('blur', function(e) {
updateRangeFromInput(this, posPriceRange, true, ' ₽');
maxCorrect();
});
posPriceInp.addEventListener('input', function(e) {
let val = this.value.replace(/[^0-9]/g, '');
let num = parseInt(val) || 0;
this.value = formatNumber(num) + ' ₽';
});
}
if (prepaidInp) {
prepaidInp.addEventListener('blur', function(e) {
updateRangeFromInput(this, prepaidRange, true, ' ₽');
});
prepaidInp.addEventListener('input', function(e) {
let val = this.value.replace(/[^0-9]/g, '');
let num = parseInt(val) || 0;
this.value = formatNumber(num) + ' ₽';
});
}
if (termInp) {
termInp.addEventListener('blur', function(e) {
let term = cleanNumber(this.value);
let min = parseInt(termRange.min) || 0;
let max = parseInt(termRange.max) || 0;
term = Math.max(min, Math.min(max, term));
termRange.value = term;
let pdps = ' мес';
if (term == 1 || term == 21 || term == 31) pdps = ' мес';
if (term == 2 || term == 3 || term == 4 || term == 22 || term == 23 || term == 24 || term == 32 || term == 33 || term == 34) pdps = ' мес';
this.value = term + pdps;
setInpVal();
countCalc();
termRange.dispatchEvent(new Event('input', { bubbles: true }));
});
termInp.addEventListener('input', function(e) {
let term = cleanNumber(this.value);
let pdps = ' мес';
if (term == 1 || term == 21 || term == 31) pdps = ' мес';
if (term == 2 || term == 3 || term == 4 || term == 22 || term == 23 || term == 24 || term == 32 || term == 33 || term == 34) pdps = ' мес';
this.value = term + pdps;
});
}
if (posPriceRange) {
posPriceRange.addEventListener('input', function() {
setInpVal();
countCalc();
});
posPriceRange.addEventListener('change', function() {
maxCorrect();
});
}
if (prepaidRange) {
prepaidRange.addEventListener('input', function() {
setInpVal();
countCalc();
});
}
if (termRange) {
termRange.addEventListener('input', function() {
setInpVal();
countCalc();
});
}
}
function checkFormsRendered() {
let allRendered = true;
forms.forEach(function(form) {
if (!form.querySelector('input, select, textarea')) {
allRendered = false;
}
});
return allRendered;
}
if (totalForms === 0) {
initCalculator();
return;
}
if (checkFormsRendered()) {
initCalculator();
return;
}
forms.forEach(function(form) {
form.addEventListener('render', function onRender() {
renderedForms++;
if (renderedForms === totalForms) {
initCalculator();
}
form.removeEventListener('render', onRender);
});
});
setTimeout(function() {
if (renderedForms < totalForms) {
console.warn('Не все формы отрендерились за отведенное время, принудительная инициализация');
initCalculator();
}
}, 5000);
});
</script>
<style>
.diag-wrapper {
height: inherit;
width: inherit;
}
#allrecords .form-section [data-elem-type="form"]:has(.t-input-group_rg) {
z-index: 1
}
.form-section .t-range__value-txt {
display: none !important;
}
.form-section input.t-range {
filter: brightness(0.94);
}
.form-section .t-range__interval-txt {
opacity: 0.7;
font-size: 0px;
}
.form-section .t-range__interval-txt:before {
content: attr(data-num);
font-size: 12px;
}
.form-section .t-range__interval-txt:after {
content: " ₽";
font-size: 12px;
}
.form-section [data-field-name="term-range"] .t-range__interval-txt:after {
content: " мес";
font-size: 12px;
}
.form-section .t-range::-webkit-slider-runnable-track {
height: 4px;
border-radius: 2px;
}
.form-section .t-range::-webkit-slider-thumb {
-webkit-appearance: none;
appearance: none;
width: 14px;
height: 14px;
margin-top: -6px;
box-shadow: 0 0 0 2px #ffffff, 0 0 0 3px #e37d1c;
transition: all 0.1s ease-in-out;
}
.form-section .t-range::-webkit-slider-thumb:hover {
transform: scale(1.1);
}
.form-section .t-range::-moz-range-track {
height: 4px;
border-radius: 2px;
}
.form-section .t-range::-moz-range-thumb {
width: 14px;
height: 14px;
border: none;
border-radius: 50%;
box-shadow: 0 0 0 2px #ffffff, 0 0 0 3px #e37d1c;
transition: all 0.1s ease-in-out;
}
.form-section .t-range::-moz-range-thumb:hover {
transform: scale(1.1);
}
</style>