Коттеджные поселки

// ============================================ // КАТАЛОГ КОТТЕДЖНЫХ ПОСЕЛКОВ - РАБОЧАЯ ВЕРСИЯ // ============================================ (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 += ''; } 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 += '
'; html += ''; html += '
Показано ' + displayedCount + ' из ' + totalCount + '
'; html += '
'; } else if (totalCount > 0) { html += '
'; html += ''; html += '
Показано ' + displayedCount + ' из ' + totalCount + '
'; 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(); } })();

Html code will be here


Html code will be here