КАРТА ТЕРРИТОРИЙ
0 m — войти
Режим территории: нажмите «Включить радар» и кликайте по углам здания на карте, чтобы очертить контур покупки.
📟 ХРОНИКИ: Спутниковые радары запущены. Ожидаем приватизации недвижимости...

Новая метка

Выберите точку на карте

Купить территорию

Стоимость захвата: 2 500 m
// ============================================================ // ПЕРЕКЛЮЧЕНИЕ РЕЖИМОВ // ============================================================ function switchMode(mode) { currentMode = mode; // Сброс предыдущего режима if (isDrawMode) stopDrawMode(); if (drawPoints.length) clearCurrentDraw(); // Кнопки document.getElementById('mode-territory').classList.toggle('active', mode === 'territory'); document.getElementById('mode-mark').classList.toggle('active', mode === 'mark'); // Панель действий document.getElementById('actions-territory').style.display = (mode === 'territory') ? 'flex' : 'none'; // Инструкция var inst = document.getElementById('instruction-text'); if (mode === 'territory') { inst.innerHTML = 'Режим территории: нажмите «Включить радар» и кликайте по углам здания на карте, чтобы очертить контур покупки.'; } else { inst.innerHTML = 'Режим метки: кликните по карте в любом месте — откроется форма для текста и медиа.'; } } // ============================================================ // РЕЖИМ ТЕРРИТОРИИ — РИСОВАНИЕ ПОЛИГОНА // ============================================================ function toggleDrawMode() { var btn = document.getElementById('btn-start'); if (!isDrawMode) { isDrawMode = true; drawPoints = []; btn.innerText = 'РАДАР АКТИВЕН'; btn.classList.add('active'); document.getElementById('instruction-text').innerHTML = 'Радар активен: отмечайте углы здания кликами. Замкните контур, кликнув рядом с первой точкой.'; } else { stopDrawMode(); } } function stopDrawMode() { isDrawMode = false; var btn = document.getElementById('btn-start'); if (btn) { btn.innerText = 'Включить радар'; btn.classList.remove('active'); } } // Клик по карте — общий обработчик map.on('click', function(e) { var latlng = e.latlng; // РЕЖИМ МЕТКИ if (currentMode === 'mark') { openMarkModal(latlng.lat, latlng.lng); return; } // РЕЖИМ ТЕРРИТОРИИ if (!isDrawMode) return; // Проверка замыкания контура if (drawPoints.length > 2) { var firstPoint = L.latLng(drawPoints[0][0], drawPoints[0][1]); if (latlng.distanceTo(firstPoint) < 20) { finishDrawing(); return; } } drawPoints.push([latlng.lat, latlng.lng]); var dot = L.circleMarker(latlng, { radius: 6, color: '#d4af37', fillColor: '#fff', fillOpacity: 1, weight: 2 }).addTo(map); markerLayers.push(dot); if (drawPoints.length === 1) { map.on('mousemove', moveRubber); } if (polygonLayer) map.removeLayer(polygonLayer); polygonLayer = L.polygon(drawPoints, { color: '#d4af37', fillColor: '#d4af37', fillOpacity: 0.25, weight: 3 }).addTo(map); document.getElementById('btn-save').style.display = 'inline-block'; document.getElementById('btn-clear').style.display = 'inline-block'; }); function moveRubber(e) { if (drawPoints.length === 0) return; if (rubberLine) map.removeLayer(rubberLine); rubberLine = L.polyline( [drawPoints[drawPoints.length - 1], [e.latlng.lat, e.latlng.lng]], { color: '#d4af37', weight: 2, dashArray: '5,5' } ).addTo(map); } function finishDrawing() { if (rubberLine) map.removeLayer(rubberLine); map.off('mousemove', moveRubber); stopDrawMode(); document.getElementById('instruction-text').innerHTML = 'Контур замкнут! Жмите «Купить участок» и заполните данные.'; } function clearCurrentDraw() { if (polygonLayer) map.removeLayer(polygonLayer); if (rubberLine) map.removeLayer(rubberLine); map.off('mousemove', moveRubber); markerLayers.forEach(function(l) { map.removeLayer(l); }); markerLayers = []; drawPoints = []; stopDrawMode(); document.getElementById('btn-save').style.display = 'none'; document.getElementById('btn-clear').style.display = 'none'; document.getElementById('instruction-text').innerHTML = 'Сброшено. Включите радар заново.'; } // ============================================================ // ПОКУПКА ТЕРРИТОРИИ // ============================================================ function buyTerritory() { if (drawPoints.length < 3) { alert('Очертите минимум 3 угла здания!'); return; } if (!isLoggedIn) { // Гостя — на регистрацию window.location.href = 'https://karta-mest.ru/register/'; return; } if (userBalance < 2500) { alert('Недостаточно монет! Стоимость: 2500. У вас: ' + userBalance); return; } openTerritoryModal(); } function openTerritoryModal() { document.getElementById('territory-modal').classList.add('is-open'); document.body.style.overflow = 'hidden'; document.getElementById('terr-status').innerText = ''; } function closeTerritoryModal() { document.getElementById('territory-modal').classList.remove('is-open'); document.body.style.overflow = ''; } function confirmBuyTerritory() { var status = document.getElementById('terr-status'); status.className = 'lux-status'; status.innerText = 'Определяем адрес...'; var lat = drawPoints[0][0]; var lon = drawPoints[0][1]; // Обратный геокодинг — Nominatim fetch('https://nominatim.openstreetmap.org/reverse?format=json&lat=' + lat + '&lon=' + lon + '&addressdetails=1&accept-language=ru', { headers: { 'User-Agent': 'MoscowichiGame/1.0' } }) .then(function(r) { return r.json(); }) .then(function(geo) { var addr = ''; if (geo && geo.address) { var city = geo.address.city || geo.address.town || geo.address.village || 'Город'; var road = geo.address.road || 'Улица'; var house = geo.address.house_number || ''; addr = city + ', ' + road + ' ' + house; } else { addr = 'Адрес не определён'; } var uniqueId = Math.abs(Math.floor(lat * lon * 100000)).toFixed(0); var data = new URLSearchParams(); data.append('action', 'buy_building_territory'); data.append('building_id', uniqueId); data.append('address', addr); data.append('coordinates_json', JSON.stringify(drawPoints)); data.append('desc', document.getElementById('terr-desc').value || ''); data.append('media_photo', document.getElementById('terr-photo').value || ''); data.append('media_video', document.getElementById('terr-video').value || ''); data.append('media_audio', document.getElementById('terr-audio').value || ''); status.innerText = 'Сохраняем покупку...'; return fetch(ajaxurl, { method: 'POST', body: data, headers: { 'Content-Type': 'application/x-www-form-urlencoded' } }); }) .then(function(r) { return r.json(); }) .then(function(res) { if (res.success) { document.getElementById('user-balance').innerText = res.data.new_balance; userBalance = res.data.new_balance; document.getElementById('news-feed').innerHTML = '' + res.data.title + ' — ' + res.data.text; // Красим полигон в золотой if (polygonLayer) { polygonLayer.setStyle({ color: '#d4af37', fillColor: '#d4af37', fillOpacity: 0.3, weight: 3 }); var pHTML = "
" + "👑 " + res.data.boss + "" + "
" + res.data.address + "
" + "
" + (document.getElementById('terr-desc').value || '') + "
" + "
"; polygonLayer.bindPopup(pHTML); } status.className = 'lux-status success'; status.innerText = '✓ Территория куплена!'; setTimeout(function() { closeTerritoryModal(); clearCurrentDraw(); }, 1500); } else { status.className = 'lux-status error'; status.innerText = '✕ ' + (res.data.message || 'Ошибка'); } }) .catch(function(err) { console.error(err); status.className = 'lux-status error'; status.innerText = '✕ Ошибка сети'; }); } // ============================================================ // МЕТКИ — МОДАЛКА И СОХРАНЕНИЕ // ============================================================ function openMarkModal(lat, lng) { pendingMarkCoords = { lat: lat, lng: lng }; document.getElementById('mark-coords-label').innerText = 'Координаты: ' + lat.toFixed(5) + ', ' + lng.toFixed(5); document.getElementById('mark-text').value = ''; document.getElementById('mark-photo').value = ''; document.getElementById('mark-video').value = ''; document.getElementById('mark-audio').value = ''; document.getElementById('mark-status').innerText = ''; document.getElementById('mark-status').className = 'lux-status'; document.getElementById('mark-submit').disabled = false; document.getElementById('mark-modal').classList.add('is-open'); document.body.style.overflow = 'hidden'; } function closeMarkModal() { document.getElementById('mark-modal').classList.remove('is-open'); document.body.style.overflow = ''; pendingMarkCoords = null; } function submitMark() { var status = document.getElementById('mark-status'); var btn = document.getElementById('mark-submit'); var text = document.getElementById('mark-text').value.trim(); if (!text) { status.className = 'lux-status error'; status.innerText = 'Введите текст метки'; return; } if (!pendingMarkCoords) { status.className = 'lux-status error'; status.innerText = 'Ошибка координат'; return; } btn.disabled = true; status.className = 'lux-status'; status.innerText = 'Публикуем...'; // Собираем FormData var formData = new FormData(); formData.append('lat', pendingMarkCoords.lat); formData.append('lng', pendingMarkCoords.lng); formData.append('txt', text); var photo = document.getElementById('mark-photo').files[0]; var video = document.getElementById('mark-video').files[0]; var audio = document.getElementById('mark-audio').files[0]; // Отправляем ОДИН файл (бэкенд принимает только map_img) // Приоритет: фото → видео → аудио var file = photo || video || audio; if (file) { formData.append('map_img', file); } fetch(wpRestUrl, { method: 'POST', headers: { 'X-WP-Nonce': wpNonce }, body: formData }) .then(function(r) { return r.json(); }) .then(function(res) { if (res && res.success) { status.className = 'lux-status success'; status.innerText = '✓ Метка опубликована!'; // Добавляем пин на карту var color = photo ? '#2ecc71' : (video ? '#2196f3' : (audio ? '#d4af37' : '#999')); var icon = photo ? '📷' : (video ? '🎥' : (audio ? '🎵' : '💬')); var pin = L.circleMarker([pendingMarkCoords.lat, pendingMarkCoords.lng], { radius: 9, color: color, fillColor: color, fillOpacity: 0.85, weight: 2 }).addTo(map); var popupHTML = "
" + "" + icon + " МЕТКА" + "
" + text + "
"; if (file) { var objURL = URL.createObjectURL(file); if (photo) popupHTML += "
"; if (video) popupHTML += "
"; if (audio) popupHTML += "
"; } popupHTML += "
"; pin.bindPopup(popupHTML); setTimeout(function() { closeMarkModal(); }, 1200); } else { status.className = 'lux-status error'; status.innerText = '✕ Ошибка сохранения'; btn.disabled = false; } }) .catch(function(err) { console.error(err); status.className = 'lux-status error'; status.innerText = '✕ Ошибка сети'; btn.disabled = false; }); } // ============================================================ // ПОИСК АДРЕСА // ============================================================ function searchAddress() { var q = document.getElementById('address-input').value.trim(); if (!q) return; fetch('https://nominatim.openstreetmap.org/search?format=json&q=' + encodeURIComponent(q) + '&limit=1&accept-language=ru', { headers: { 'User-Agent': 'MoscowichiGame/1.0' } }) .then(function(r) { return r.json(); }) .then(function(d) { if (d && d.length > 0) { map.setView([parseFloat(d[0].lat), parseFloat(d[0].lon)], 18); } else { document.getElementById('instruction-text').innerHTML = 'Адрес не найден. Попробуйте иначе.'; } }) .catch(function(err) { console.error(err); }); } // Enter в поле поиска document.getElementById('address-input').addEventListener('keypress', function(e) { if (e.key === 'Enter') { e.preventDefault(); searchAddress(); } }); // ============================================================ // ОБРАБОТКА ?post=ID В URL (центрирование на посте) // ============================================================ (function() { var params = new URLSearchParams(window.location.search); var postId = params.get('post'); if (!postId) return; fetch('https://karta-mest.ru/wp-json/wp/v2/posts/' + postId, { headers: { 'X-WP-Nonce': wpNonce } }) .then(function(r) { return r.json(); }) .then(function(post) { if (post && post.content && post.content.rendered) { // Ищем координаты в контенте (если есть) var match = post.content.rendered.match(/([0-9]{2}\.[0-9]+)[,\s]+([0-9]{2}\.[0-9]+)/); if (match) { var lat = parseFloat(match[1]); var lng = parseFloat(match[2]); map.setView([lat, lng], 18); L.circleMarker([lat, lng], { radius: 10, color: '#d4af37', fillColor: '#d4af37', fillOpacity: 0.8, weight: 3 }).addTo(map).bindPopup('
📍 Место поста
').openPopup(); } } }) .catch(function(err) { console.warn('Не удалось загрузить пост:', err); }); })(); // ============================================================ // ЗАКРЫТИЕ МОДАЛОК ПО ESC И КЛИКУ НА ФОН // ============================================================ document.querySelectorAll('.lux-modal').forEach(function(m) { m.addEventListener('click', function(e) { if (e.target === m) { m.classList.remove('is-open'); document.body.style.overflow = ''; } }); }); document.addEventListener('keydown', function(e) { if (e.key === 'Escape') { document.querySelectorAll('.lux-modal.is-open').forEach(function(m) { m.classList.remove('is-open'); }); document.body.style.overflow = ''; } });