// ============================================
// КАТАЛОГ КОТТЕДЖНЫХ ПОСЕЛКОВ - РАБОЧАЯ ВЕРСИЯ
// ============================================
(function() {
'use strict';
// КОНФИГУРАЦИЯ
var CONFIG = {
PROXY_URL: 'https://reputation-promo.online/crm-proxy.php',
IMAGE_PROXY: 'https://reputation-promo.online/image-proxy.php?path=',
CACHE_KEY: 'newhouse_villages_cache',
CACHE_TIME: 30 * 60 * 1000,
ITEMS_PER_PAGE: 30,
FIELDS: {
REGION: 553,
DISTRICT: 784,
HIGHWAY: 3249,
MKAD: 542,
DESCRIPTION: 626,
VILLAGE_DESCRIPTION: 4028,
VILLAGE_PHOTOS: 4027,
TYPE: 778
}
};
var allVillages = [];
var filteredVillages = [];
var displayedCount = 0;
// ВСПОМОГАТЕЛЬНЫЕ ФУНКЦИИ
function formatNumber(value) {
if (!value) return '';
return value.toString().replace(/\D/g, '');
}
function parseNumber(value) {
if (!value) return null;
var num = parseInt(value.toString().replace(/\D/g, ''));
return isNaN(num) ? null : num;
}
function sortPhotos(photos) {
if (!photos) return [];
var photosArray = Array.isArray(photos) ? photos : [photos];
return photosArray.sort(function(a, b) {
var numA = parseInt(String(a).replace(/\D/g, '')) || 0;
var numB = parseInt(String(b).replace(/\D/g, '')) || 0;
return numA - numB;
});
}
function getPhotoUrl(photoPath) {
if (!photoPath) return null;
if (photoPath.startsWith('http')) return photoPath;
var cleanPath = String(photoPath).trim().replace(/^\/+/, '');
return CONFIG.IMAGE_PROXY + encodeURIComponent(cleanPath);
}
function debounce(func, wait) {
var timeout;
return function() {
var context = this, args = arguments;
clearTimeout(timeout);
timeout = setTimeout(function() {
func.apply(context, args);
}, wait);
};
}
function escapeHtml(str) {
if (!str) return '';
return str.replace(/&/g, '&').replace(//g, '>').replace(/"/g, '"').replace(/'/g, ''');
}
// ЗАГРУЗКА ДАННЫХ
async function loadVillages() {
var container = document.getElementById('villagesContainer');
if (!container) return;
try {
var cached = localStorage.getItem(CONFIG.CACHE_KEY);
if (cached) {
var parsed = JSON.parse(cached);
if (Date.now() - parsed.timestamp < CONFIG.CACHE_TIME) {
console.log('Из кэша:', parsed.data.length);
allVillages = parsed.data;
processVillages();
return;
}
}
console.log('Загрузка из CRM...');
var response = await fetch(CONFIG.PROXY_URL, {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ type: 3, limit: 500 })
});
if (!response.ok) throw new Error('HTTP ' + response.status);
var data = await response.json();
if (data.status === 'success' && data.data && data.data.list) {
var villages = data.data.list
.filter(function(obj) {
var fields = {};
if (obj.fields) {
obj.fields.forEach(function(f) { fields[f.id] = f.value; });
}
return !fields[CONFIG.FIELDS.TYPE];
})
.map(function(obj) {
var fields = {};
if (obj.fields) {
obj.fields.forEach(function(f) { fields[f.id] = f.value; });
}
var name = obj.name || fields[CONFIG.FIELDS.VILLAGE] || 'Коттеджный поселок';
var imageUrl = null;
if (fields[CONFIG.FIELDS.VILLAGE_PHOTOS]) {
var photos = Array.isArray(fields[CONFIG.FIELDS.VILLAGE_PHOTOS])
? fields[CONFIG.FIELDS.VILLAGE_PHOTOS]
: [fields[CONFIG.FIELDS.VILLAGE_PHOTOS]];
if (photos.length > 0) {
var sortedPhotos = sortPhotos(photos);
imageUrl = getPhotoUrl(sortedPhotos[0]);
}
}
return {
id: obj.id,
name: name,
region: fields[CONFIG.FIELDS.REGION] || '',
district: fields[CONFIG.FIELDS.DISTRICT] || '',
highway: fields[CONFIG.FIELDS.HIGHWAY] || '',
mkad: fields[CONFIG.FIELDS.MKAD] || '',
description: fields[CONFIG.FIELDS.VILLAGE_DESCRIPTION] || fields[CONFIG.FIELDS.DESCRIPTION] || '',
image: imageUrl
};
});
console.log('Загружено поселков:', villages.length);
localStorage.setItem(CONFIG.CACHE_KEY, JSON.stringify({
data: villages,
timestamp: Date.now()
}));
allVillages = villages;
if (villages.length === 0) {
container.innerHTML = '
🏘️ Поселки временно недоступны
';
return;
}
processVillages();
} else {
container.innerHTML = '
❌ Ошибка загрузки данных
';
}
} catch (error) {
console.error('Ошибка:', error);
container.innerHTML = '
❌ Ошибка загрузки. Попробуйте обновить страницу.
';
}
}
// ОБРАБОТКА
function processVillages() {
filteredVillages = allVillages.slice();
displayedCount = 0;
displayVillages();
populateFilters();
}
function populateFilters() {
var highwaySelect = document.getElementById('highwaySelect');
if (highwaySelect && allVillages.length > 0) {
var highways = [];
for (var i = 0; i < allVillages.length; i++) {
if (allVillages[i].highway && highways.indexOf(allVillages[i].highway) === -1) {
highways.push(allVillages[i].highway);
}
}
highways.sort();
var options = '
Все шоссе ';
for (var j = 0; j < highways.length; j++) {
var shortName = highways[j].replace(' шоссе', '').replace('шоссе', '').trim();
options += '
' + shortName + ' ';
}
highwaySelect.innerHTML = options;
}
}
function displayVillages(loadMore) {
var container = document.getElementById('villagesContainer');
if (!container) return;
if (!loadMore) {
displayedCount = Math.min(CONFIG.ITEMS_PER_PAGE, filteredVillages.length);
} else {
displayedCount = Math.min(displayedCount + CONFIG.ITEMS_PER_PAGE, filteredVillages.length);
}
var villagesToShow = filteredVillages.slice(0, displayedCount);
if (villagesToShow.length === 0) {
container.innerHTML = '
🔍 Поселки не найдены
';
return;
}
var totalCount = filteredVillages.length;
var hasMore = displayedCount < totalCount;
var html = '
📊 Найдено поселков: ' + totalCount + '
';
html += '
';
if (hasMore) {
html += '';
} else if (totalCount > 0) {
html += '';
}
container.innerHTML = html;
var loadMoreBtn = document.getElementById('loadMoreBtn');
if (loadMoreBtn && hasMore) {
loadMoreBtn.addEventListener('click', function() {
this.classList.add('loading');
this.innerHTML = '⏳ ЗАГРУЗКА...';
this.disabled = true;
setTimeout(function() { displayVillages(true); }, 300);
});
}
document.title = (totalCount === allVillages.length) ? 'Все коттеджные поселки (' + totalCount + ')' : 'Найдено ' + totalCount + ' коттеджных поселков';
}
// ФИЛЬТРАЦИЯ
function filterVillages() {
var searchInput = document.getElementById('searchInput');
var highwaySelect = document.getElementById('highwaySelect');
var mkadFromInput = document.getElementById('mkadFrom');
var mkadToInput = document.getElementById('mkadTo');
var sortSelect = document.getElementById('sortSelect');
var searchText = searchInput ? searchInput.value.toLowerCase().trim() : '';
var highway = highwaySelect ? highwaySelect.value : 'all';
var mkadFrom = parseNumber(mkadFromInput ? mkadFromInput.value : null);
var mkadTo = parseNumber(mkadToInput ? mkadToInput.value : null);
var sortType = sortSelect ? sortSelect.value : 'default';
var filtered = allVillages.filter(function(village) {
if (searchText && village.name.toLowerCase().indexOf(searchText) === -1) return false;
if (highway !== 'all' && village.highway !== highway) return false;
var mkad = parseFloat(village.mkad);
if (mkadFrom && (!mkad || mkad < mkadFrom)) return false;
if (mkadTo && (!mkad || mkad > mkadTo)) return false;
return true;
});
if (sortType !== 'default') {
filtered.sort(function(a, b) {
if (sortType === 'name_asc') return a.name.localeCompare(b.name);
if (sortType === 'name_desc') return b.name.localeCompare(a.name);
if (sortType === 'mkad_asc') return (parseFloat(a.mkad) || 999) - (parseFloat(b.mkad) || 999);
if (sortType === 'mkad_desc') return (parseFloat(b.mkad) || 0) - (parseFloat(a.mkad) || 0);
return 0;
});
}
filteredVillages = filtered;
displayedCount = 0;
displayVillages();
updateActiveFilters();
}
function updateActiveFilters() {
var container = document.getElementById('activeFilters');
var searchInput = document.getElementById('searchInput');
var highwaySelect = document.getElementById('highwaySelect');
var mkadFromInput = document.getElementById('mkadFrom');
var mkadToInput = document.getElementById('mkadTo');
var searchText = searchInput ? searchInput.value : '';
var highway = highwaySelect ? highwaySelect.value : '';
var mkadFrom = mkadFromInput ? mkadFromInput.value : '';
var mkadTo = mkadToInput ? mkadToInput.value : '';
var tags = [];
if (searchText) tags.push({type: 'search', text: '🔍 Поиск: "' + searchText + '"'});
if (highway && highway !== 'all') tags.push({type: 'highway', text: '🛣️ Шоссе: ' + highway.replace(' шоссе', '')});
if (mkadFrom || mkadTo) {
var text = '📍 МКАД: ';
if (mkadFrom) text += 'от ' + mkadFrom + ' км';
if (mkadFrom && mkadTo) text += ' ';
if (mkadTo) text += 'до ' + mkadTo + ' км';
tags.push({type: 'mkad', text: text});
}
if (tags.length > 0) {
container.style.display = 'flex';
var tagsHtml = '';
for (var i = 0; i < tags.length; i++) {
tagsHtml += '
' + tags[i].text + '× ';
}
container.innerHTML = tagsHtml;
var btns = document.querySelectorAll('.remove-tag-btn');
for (var j = 0; j < btns.length; j++) {
btns[j].addEventListener('click', (function(index) {
return function() { removeFilterTag(tags[index].type); };
})(j));
}
} else {
container.style.display = 'none';
}
}
function removeFilterTag(filterType) {
if (filterType === 'search') {
var searchInput = document.getElementById('searchInput');
if (searchInput) searchInput.value = '';
} else if (filterType === 'highway') {
var highwaySelect = document.getElementById('highwaySelect');
if (highwaySelect) highwaySelect.value = 'all';
} else if (filterType === 'mkad') {
var mkadFrom = document.getElementById('mkadFrom');
var mkadTo = document.getElementById('mkadTo');
if (mkadFrom) mkadFrom.value = '';
if (mkadTo) mkadTo.value = '';
}
filterVillages();
}
function resetFilters() {
var searchInput = document.getElementById('searchInput');
var highwaySelect = document.getElementById('highwaySelect');
var mkadFrom = document.getElementById('mkadFrom');
var mkadTo = document.getElementById('mkadTo');
var sortSelect = document.getElementById('sortSelect');
if (searchInput) searchInput.value = '';
if (highwaySelect) highwaySelect.value = 'all';
if (mkadFrom) mkadFrom.value = '';
if (mkadTo) mkadTo.value = '';
if (sortSelect) sortSelect.value = 'default';
filteredVillages = allVillages.slice();
displayedCount = 0;
displayVillages();
updateActiveFilters();
}
// ЗАПУСК
function init() {
loadVillages();
var searchInput = document.getElementById('searchInput');
var highwaySelect = document.getElementById('highwaySelect');
var sortSelect = document.getElementById('sortSelect');
var resetBtn = document.getElementById('resetFiltersBtn');
var debouncedFilter = debounce(filterVillages, 300);
if (searchInput) searchInput.addEventListener('input', debouncedFilter);
if (highwaySelect) highwaySelect.addEventListener('change', filterVillages);
if (sortSelect) sortSelect.addEventListener('change', filterVillages);
if (resetBtn) resetBtn.addEventListener('click', resetFilters);
var mkadFrom = document.getElementById('mkadFrom');
var mkadTo = document.getElementById('mkadTo');
if (mkadFrom) {
mkadFrom.addEventListener('input', function(e) {
e.target.value = formatNumber(e.target.value);
debouncedFilter();
});
}
if (mkadTo) {
mkadTo.addEventListener('input', function(e) {
e.target.value = formatNumber(e.target.value);
debouncedFilter();
});
}
}
// Ждем загрузки DOM
if (document.readyState === 'loading') {
document.addEventListener('DOMContentLoaded', init);
} else {
init();
}
})();