
{"id":37706,"date":"2026-06-10T20:04:30","date_gmt":"2026-06-10T13:04:30","guid":{"rendered":"https:\/\/bds.re\/?page_id=37706"},"modified":"2026-06-11T11:21:12","modified_gmt":"2026-06-11T04:21:12","slug":"ban-do-bds","status":"publish","type":"page","link":"https:\/\/bds.re\/en\/ban-do-bds\/","title":{"rendered":"B\u1ea3n \u0111\u1ed3 b\u0111s"},"content":{"rendered":"\n<p class=\"wp-block-paragraph\"><\/p>\n\n\n    <link rel=\"stylesheet\" href=\"https:\/\/unpkg.com\/leaflet@1.9.4\/dist\/leaflet.css\" \/>\r\n    <script src=\"https:\/\/unpkg.com\/leaflet@1.9.4\/dist\/leaflet.js\"><\/script>\r\n\r\n    <style>\r\n        .bds-map-wrapper { width: 100%; height: 80vh; position: relative; font-family: sans-serif; }\r\n        #bds_price_map { width: 100%; height: 100%; z-index: 1; }\r\n        .map-control-box { position: absolute; z-index: 1000; top: 15px; display: flex; flex-direction: column; gap: 5px; }\r\n        .pos-top-left { left: 15px; }\r\n        .pos-top-right { right: 15px; align-items: flex-end; }\r\n        .map-btn-toggle { background: #2980b9; color: #fff; border: none; padding: 10px 15px; border-radius: 6px; font-weight: bold; font-size: 14px; cursor: pointer; box-shadow: 0 4px 10px rgba(0,0,0,0.2); transition: 0.3s; }\r\n        .map-btn-toggle:hover { background: #1c5980; }\r\n        .map-panel { background: rgba(255,255,255,0.95); padding: 15px; border-radius: 8px; box-shadow: 0 4px 15px rgba(0,0,0,0.2); display: none; flex-direction: column; gap: 10px; width: 220px; }\r\n        .map-panel.active { display: flex; }\r\n        .map-panel select, .map-panel input[type=\"number\"] { width: 100%; padding: 8px; border: 1px solid #ccc; border-radius: 4px; font-size: 13px; box-sizing: border-box; outline: none; }\r\n        .map-panel label { font-size: 14px; font-weight: bold; display: flex; align-items: center; gap: 8px; cursor: pointer; color: #333; }\r\n        .qh-slider-box { border-top: 1px solid #ddd; padding-top: 10px; margin-top: 5px; display: flex; flex-direction: column; gap: 5px; }\r\n        .custom-pulse { z-index: 9999 !important; }\r\n\t\t.gps-pulse { background: #3498db; border-radius: 50%; height: 16px; width: 16px; position: absolute; left: 0; top: 0; box-shadow: 0 0 0 rgba(52, 152, 219, 0.4); animation: pulse 2s infinite; border: 2px solid #fff; }\r\n\t\t@keyframes pulse { 0% { box-shadow: 0 0 0 0 rgba(52, 152, 219, 0.7); } 70% { box-shadow: 0 0 0 15px rgba(52, 152, 219, 0); } 100% { box-shadow: 0 0 0 0 rgba(52, 152, 219, 0); } }\r\n\t\t.btn-locate-me { position: absolute; bottom: 30px; right: 20px; z-index: 1000; background: #2980b9; color: #fff; border: none; padding: 12px 20px; border-radius: 30px; font-weight: bold; font-size: 14px; box-shadow: 0 4px 10px rgba(0,0,0,0.3); cursor: pointer; transition: 0.3s; display: flex; align-items: center; gap: 8px; }\r\n        .btn-locate-me:hover { background: #1c5980; transform: scale(1.05); }\r\n        .price-marker { background: #e74c3c; color: #fff; padding: 4px 8px; border-radius: 6px; font-weight: bold; font-size: 12px; box-shadow: 0 2px 5px rgba(0,0,0,0.4); text-align: center; white-space: nowrap; border: 1px solid #fff; position: relative; transition: 0.3s; cursor: pointer; }\r\n        .price-marker::after { content: \"\"; position: absolute; bottom: -5px; left: 50%; transform: translateX(-50%); border-width: 5px 5px 0; border-style: solid; border-color: #e74c3c transparent transparent transparent; }\r\n        .price-marker:hover { background: #c0392b; z-index: 9999 !important; transform: scale(1.1); }\r\n        .price-marker.cheap { background: #27ae60; }\r\n        .price-marker.cheap::after { border-color: #27ae60 transparent transparent transparent; }\r\n        \/* CSS L\u00c0M \u0110\u1eb8P POPUP B\u0110S & N\u00daT SO S\u00c1NH (CHU\u1ea8N UX M\u1edaI) *\/\r\n        .map-popup-card { width: 240px; max-width: 90vw; font-family: sans-serif; overflow: hidden; border-radius: 8px; background-color: #ffffff; color: #000000; }\r\n        .map-popup-img { width: 100%; height: 160px; object-fit: cover; border-radius: 8px 8px 0 0; margin-bottom: 8px; display: block; }\r\n        .map-popup-title { font-size: 14px; font-weight: bold; line-height: 1.3; color: #000000; margin: 0 0 5px 0; display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical; overflow: hidden; }\r\n        .map-popup-price { color: #e74c3c; font-weight: bold; font-size: 16px; margin-bottom: 8px; }\r\n        .map-popup-specs { font-size: 12px; color: #333333; margin-bottom: 12px; border-bottom: 1px solid #eeeeee; padding-bottom: 8px; line-height: 1.5; font-weight: 500; }\r\n\t\t\r\n        .map-popup-actions { display: flex; gap: 8px; }\r\n        .map-popup-btn { flex: 1; text-align: center; background: #2980b9; color: #fff !important; padding: 8px 0; border-radius: 4px; text-decoration: none; font-size: 12px; font-weight: bold; transition: 0.2s; cursor: pointer; border: none; }\r\n        .map-popup-btn:hover { background: #1c5980; }\r\n        .map-popup-btn-compare { background: #27ae60; }\r\n        .map-popup-btn-compare:hover { background: #1e8449; }\r\n\r\n        \/* S\u1eeda khung vi\u1ec1n c\u1ee7a Popup Leaflet *\/\r\n        .leaflet-popup-content-wrapper { padding: 0; border-radius: 8px; box-shadow: 0 4px 15px rgba(0,0,0,0.2); }\r\n        .leaflet-popup-content { margin: 0; }\r\n        .leaflet-container a.leaflet-popup-close-button { top: 5px; right: 5px; color: #fff; background: rgba(0,0,0,0.5); border-radius: 50%; width: 22px; height: 22px; text-align: center; line-height: 22px; padding: 0; font-size: 14px; transition: 0.2s; }\r\n        .leaflet-container a.leaflet-popup-close-button:hover { background: #e74c3c; color: #fff; }\r\n    <\/style>\r\n\r\n    <div class=\"bds-map-wrapper\">\r\n        <!-- N\u00daT & DROPDOWN L\u1eccC (G\u00d3C TR\u00c1I) -->\r\n        <div class=\"map-control-box pos-top-left\">\r\n            <button class=\"map-btn-toggle\" onclick=\"toggleMapPanel('filter_panel')\">\ud83d\udd0d L\u1ecdc B\u0110S<\/button>\r\n            <div class=\"map-panel\" id=\"filter_panel\">\r\n                <select id=\"filter_hinh_thuc\" onchange=\"fetchMapData()\">\r\n                    <option value=\"\">T\u1ea5t c\u1ea3 h\u00ecnh th\u1ee9c<\/option>\r\n                    <option value=\"B\u00e1n\">B\u00e1n<\/option>\r\n                    <option value=\"Cho thu\u00ea\">Cho thu\u00ea<\/option>\r\n                <\/select>\r\n                <select id=\"filter_loai_hinh\" onchange=\"fetchMapData()\">\r\n                    <option value=\"\">T\u1ea5t c\u1ea3 lo\u1ea1i h\u00ecnh<\/option>\r\n                    <option value=\"\u0110\u1ea5t\">\u0110\u1ea5t (\u0110\u1ea5t n\u1ec1n\/\u0110\u1ea5t x\u00e3)<\/option>\r\n                    <option value=\"Nh\u00e0 ph\u1ed1\">Nh\u00e0 ph\u1ed1 \/ Bi\u1ec7t th\u1ef1<\/option>\r\n                    <option value=\"C\u0103n h\u1ed9\">C\u0103n h\u1ed9 \/ Chung c\u01b0<\/option>\r\n                <\/select>\r\n                <input type=\"number\" id=\"filter_max_price\" placeholder=\"Gi\u00e1 T\u1ed1i \u0110a (\u0111)\" onchange=\"fetchMapData()\">\r\n                \r\n                <!-- Th\u00eam c\u00e1c Tag (B\u1ed9 l\u1ecdc nhanh) -->\r\n                <div style=\"display: flex; flex-wrap: wrap; gap: 5px; margin-top: 5px;\">\r\n                    <button type=\"button\" class=\"quick-filter-btn\" onclick=\"setQuickFilter('gia_re_30_ngay', this)\" style=\"background: #e74c3c; color: #fff; border: none; padding: 5px 8px; border-radius: 4px; font-size: 11px; cursor: pointer; transition: 0.2s;\">\ud83d\udd25 Gi\u00e1 r\u1ebb (30 ng\u00e0y)<\/button>\r\n                    <button type=\"button\" class=\"quick-filter-btn\" onclick=\"setQuickFilter('ban_gap', this)\" style=\"background: #e67e22; color: #fff; border: none; padding: 5px 8px; border-radius: 4px; font-size: 11px; cursor: pointer; opacity: 0.5; transform: scale(0.95); transition: 0.2s;\">\u26a1 B\u00e1n g\u1ea5p<\/button>\r\n                    <button type=\"button\" class=\"quick-filter-btn\" onclick=\"setQuickFilter('all', this)\" style=\"background: #7f8c8d; color: #fff; border: none; padding: 5px 8px; border-radius: 4px; font-size: 11px; cursor: pointer; opacity: 0.5; transform: scale(0.95); transition: 0.2s;\">\ud83c\udf1f T\u1ea5t c\u1ea3<\/button>\r\n                <\/div>\r\n                <input type=\"hidden\" id=\"filter_quick_tag\" value=\"gia_re_30_ngay\">\r\n                \r\n                <!-- B\u1ed8 L\u1eccC N\u00c2NG CAO (TH\u1ef0C CHI\u1ebeN) -->\r\n                <div style=\"display: flex; flex-direction: column; gap: 8px; margin-top: 10px; border-top: 1px solid #ddd; padding-top: 10px;\">\r\n                    <label style=\"font-size: 13px; font-weight: normal; color: #333;\"><input type=\"checkbox\" id=\"filter_oto\" onchange=\"fetchMapData()\"> \ud83d\ude97 \u0110\u01b0\u1eddng \u00f4 t\u00f4 (\u2265 4m)<\/label>\r\n                    <label style=\"font-size: 13px; font-weight: normal; color: #333;\"><input type=\"checkbox\" id=\"filter_phaply\" onchange=\"fetchMapData()\"> \ud83d\udcdc Ph\u00e1p l\u00fd chu\u1ea9n (S\u1ed5\/H\u0110MB)<\/label>\r\n                    <label style=\"font-size: 13px; font-weight: normal; color: #333;\"><input type=\"checkbox\" id=\"filter_thocu\" onchange=\"fetchMapData()\"> \ud83c\udfe1 C\u00f3 th\u1ed5 c\u01b0<\/label>\r\n                <\/div>\r\n           \r\n                <!-- B\u1ed8 L\u1eccC KHU V\u1ef0C 3 C\u1ea4P (Cascading Dropdown) -->\r\n                <div style=\"display: flex; flex-direction: column; gap: 5px;\">\r\n                    <select id=\"filter_tinh\" onchange=\"loadCities(this.value); fetchMapData();\" style=\"font-weight: bold; color: #2980b9;\">\r\n                        <option value=\"\">\ud83d\uddfa\ufe0f T\u1ea5t c\u1ea3 T\u1ec9nh\/Th\u00e0nh<\/option>\r\n                        <option value=\"khanh-hoa\">Kh\u00e1nh H\u00f2a<\/option><option value=\"ninh-thuan\">Ninh Thu\u1eadn<\/option>                    <\/select>\r\n                    \r\n                    <select id=\"filter_huyen\" onchange=\"loadAreas(this.value); fetchMapData();\" disabled style=\"color: #7f8c8d;\">\r\n                        <option value=\"\">-- Ch\u1ecdn Qu\u1eadn\/Huy\u1ec7n --<\/option>\r\n                    <\/select>\r\n\r\n                    <select id=\"filter_xa\" onchange=\"fetchMapData()\" disabled style=\"color: #7f8c8d;\">\r\n                        <option value=\"\">-- Ch\u1ecdn Ph\u01b0\u1eddng\/X\u00e3 --<\/option>\r\n                    <\/select>\r\n                <\/div>\r\n            <\/div>\r\n        <\/div>\r\n\r\n        <!-- N\u00daT & DROPDOWN QUY HO\u1ea0CH (G\u00d3C PH\u1ea2I) -->\r\n        <div class=\"map-control-box pos-top-right\">\r\n            <button class=\"map-btn-toggle\" onclick=\"toggleMapPanel('qh_panel')\" style=\"background: #e67e22;\">\ud83d\uddfa\ufe0f Xem QH<\/button>\r\n            <div class=\"map-panel\" id=\"qh_panel\">\r\n                <div id=\"qh_dynamic_list\" style=\"max-height: 300px; overflow-y: auto;\">\r\n                <div style=\"font-weight:bold; color:#2980b9; margin: 8px 0 4px 0; border-bottom: 1px solid #eee; padding-bottom: 2px;\">Cam L\u00e2m<\/div><label style=\"margin-left: 8px;\"><input type=\"checkbox\" class=\"qh-checkbox\" value=\"qh-2045\"> QH 2045<\/label><label style=\"margin-left: 8px;\"><input type=\"checkbox\" class=\"qh-checkbox\" value=\"qh-2030\"> QH 2030<\/label><label style=\"margin-left: 8px;\"><input type=\"checkbox\" class=\"qh-checkbox\" value=\"dk-1-500-suoi-tan\"> DK 1.500 Su\u1ed1i T\u00e2n<\/label><label style=\"margin-left: 8px;\"><input type=\"checkbox\" class=\"qh-checkbox\" value=\"dk-1-500-cam-tan\"> DK 1.500 Cam T\u00e2n<\/label>\t\t\t\t<\/div>\r\n                \r\n                <div class=\"qh-slider-box\">\r\n                    <span style=\"font-size:12px; font-weight:bold; color:#d63638;\">Ch\u1ec9nh \u0111\u1ed9 m\u1edd \u1ea3nh:<\/span>\r\n                    <input type=\"range\" id=\"quyhoach_opacity\" min=\"0\" max=\"1\" step=\"0.1\" value=\"0.7\">\r\n                <\/div>\r\n            <\/div>\r\n        <\/div>\r\n        <div id=\"bds_price_map\"><\/div>\r\n        <button type=\"button\" class=\"btn-locate-me\" onclick=\"locateUser()\">\ud83d\udccd T\u00ccM QUANH T\u00d4I<\/button>\r\n    <\/div>\r\n\r\n    <script>\r\n        var map = L.map('bds_price_map').setView([12.24507, 109.19482], 14);\r\n        L.tileLayer('https:\/\/{s}.basemaps.cartocdn.com\/rastertiles\/voyager\/{z}\/{x}\/{y}{r}.png', {\r\n            attribution: '\u00a9 OpenStreetMap & BDS.RE', maxZoom: 19\r\n        }).addTo(map);\r\n\r\n        var markersLayer = L.layerGroup().addTo(map);\r\n\t\t\r\n\t\t\/\/ X\u1eed l\u00fd khi b\u1ea5m n\u00fat B\u1ed9 L\u1ecdc Nhanh (Tags)\r\n        function setQuickFilter(tagValue, btnElement) {\r\n            document.getElementById('filter_quick_tag').value = tagValue;\r\n            var btns = document.querySelectorAll('.quick-filter-btn');\r\n            btns.forEach(function(btn) { btn.style.opacity = '0.5'; btn.style.transform = 'scale(0.95)'; }); \/\/ L\u00e0m m\u1edd c\u00e1c n\u00fat kh\u00e1c\r\n            btnElement.style.opacity = '1'; btnElement.style.transform = 'scale(1)'; \/\/ L\u00e0m s\u00e1ng n\u00fat \u0111\u01b0\u1ee3c b\u1ea5m\r\n            fetchMapData(); \/\/ G\u1ecdi h\u00e0m t\u1ea3i l\u1ea1i b\u1ea3n \u0111\u1ed3\r\n        }\r\n\t\t\r\n\t\t\/\/ X\u1eed l\u00fd b\u1eadt\/t\u1eaft (Dropdown) c\u00e1c b\u1ea3ng \u0111i\u1ec1u khi\u1ec3n\r\n\t\t\/\/ X\u1eed l\u00fd b\u1eadt\/t\u1eaft (Dropdown) c\u00e1c b\u1ea3ng \u0111i\u1ec1u khi\u1ec3n\r\n\t\tfunction toggleMapPanel(panelId) {\r\n\t\t\tvar panel = document.getElementById(panelId);\r\n            \r\n            \/\/ \u0110\u00f3ng t\u1ea5t c\u1ea3 c\u00e1c panel kh\u00e1c tr\u01b0\u1edbc khi m\u1edf\/\u0111\u00f3ng panel hi\u1ec7n t\u1ea1i (Tr\u00e1nh b\u1ecb \u0111\u00e8 l\u1ed9n x\u1ed9n)\r\n            document.querySelectorAll('.map-panel').forEach(function(p) {\r\n                if (p.id !== panelId) p.classList.remove('active');\r\n            });\r\n            \r\n\t\t\tpanel.classList.toggle('active');\r\n\t\t}\r\n\r\n        \/\/ T\u1ef0 \u0110\u1ed8NG \u0110\u00d3NG: Khi kh\u00e1ch h\u00e0ng click ra ngo\u00e0i khung l\u1ecdc\r\n        document.addEventListener('click', function(event) {\r\n            var isClickInsidePanel = event.target.closest('.map-panel');\r\n            var isClickOnButton = event.target.closest('.map-btn-toggle');\r\n            \r\n            \/\/ N\u1ebfu click kh\u00f4ng tr\u00fang khung l\u1ecdc v\u00e0 kh\u00f4ng tr\u00fang n\u00fat b\u1ea5m -> \u0110\u00f3ng t\u1ea5t c\u1ea3\r\n            if (!isClickInsidePanel && !isClickOnButton) {\r\n                document.querySelectorAll('.map-panel').forEach(function(p) {\r\n                    p.classList.remove('active');\r\n                });\r\n            }\r\n        });\r\n\r\n        \/\/ T\u1ef0 \u0110\u1ed8NG \u0110\u00d3NG: Khi kh\u00e1ch h\u00e0ng b\u1eaft \u0111\u1ea7u ch\u1ea1m\/k\u00e9o\/vu\u1ed1t b\u1ea3n \u0111\u1ed3\r\n        map.on('dragstart', function() {\r\n            document.querySelectorAll('.map-panel').forEach(function(p) {\r\n                p.classList.remove('active');\r\n            });\r\n        });\r\n\t\t\r\n\t\t\/\/ AJAX: G\u1ecdi Qu\u1eadn\/Huy\u1ec7n khi ch\u1ecdn T\u1ec9nh\r\n        function loadCities(tinh_slug) {\r\n            var huyenSelect = document.getElementById('filter_huyen');\r\n            var xaSelect = document.getElementById('filter_xa');\r\n            \r\n            \/\/ Reset \u00f4 X\u00e3\r\n            xaSelect.innerHTML = '<option value=\"\">-- Ch\u1ecdn Ph\u01b0\u1eddng\/X\u00e3 --<\/option>';\r\n            xaSelect.disabled = true;\r\n            xaSelect.style.color = '#7f8c8d';\r\n\r\n            if (!tinh_slug) {\r\n                huyenSelect.innerHTML = '<option value=\"\">-- Ch\u1ecdn Qu\u1eadn\/Huy\u1ec7n --<\/option>';\r\n                huyenSelect.disabled = true;\r\n                huyenSelect.style.color = '#7f8c8d';\r\n                return;\r\n            }\r\n\r\n            huyenSelect.innerHTML = '<option value=\"\">\u0110ang t\u1ea3i...<\/option>';\r\n            huyenSelect.disabled = false;\r\n            huyenSelect.style.color = '#2980b9';\r\n\r\n            var formData = new FormData();\r\n            formData.append('action', 'bdsre_get_cities_by_state');\r\n            formData.append('tinh_slug', tinh_slug);\r\n            formData.append('security', '3bcd49f7cf');\r\n\r\n            fetch('https:\/\/bds.re\/wp-admin\/admin-ajax.php', { method: 'POST', body: formData })\r\n            .then(res => res.json())\r\n            .then(res => {\r\n                if(res.success && res.data.length > 0) {\r\n                    let html = '<option value=\"\">-- T\u1ea5t c\u1ea3 Qu\u1eadn\/Huy\u1ec7n --<\/option>';\r\n                    res.data.forEach(city => {\r\n                        html += `<option value=\"${city.slug}\">${city.name}<\/option>`;\r\n                    });\r\n                    huyenSelect.innerHTML = html;\r\n                } else {\r\n                    huyenSelect.innerHTML = '<option value=\"\">(Kh\u00f4ng c\u00f3 d\u1eef li\u1ec7u)<\/option>';\r\n                }\r\n            });\r\n        }\r\n\r\n        \/\/ AJAX: G\u1ecdi Ph\u01b0\u1eddng\/X\u00e3 khi ch\u1ecdn Qu\u1eadn\/Huy\u1ec7n\r\n        function loadAreas(huyen_slug) {\r\n            var xaSelect = document.getElementById('filter_xa');\r\n\r\n            if (!huyen_slug) {\r\n                xaSelect.innerHTML = '<option value=\"\">-- Ch\u1ecdn Ph\u01b0\u1eddng\/X\u00e3 --<\/option>';\r\n                xaSelect.disabled = true;\r\n                xaSelect.style.color = '#7f8c8d';\r\n                return;\r\n            }\r\n\r\n            xaSelect.innerHTML = '<option value=\"\">\u0110ang t\u1ea3i...<\/option>';\r\n            xaSelect.disabled = false;\r\n            xaSelect.style.color = '#2980b9';\r\n\r\n            var formData = new FormData();\r\n            formData.append('action', 'bdsre_get_areas_by_city');\r\n            formData.append('huyen_slug', huyen_slug);\r\n            formData.append('security', '3bcd49f7cf');\r\n\r\n            fetch('https:\/\/bds.re\/wp-admin\/admin-ajax.php', { method: 'POST', body: formData })\r\n            .then(res => res.json())\r\n            .then(res => {\r\n                if(res.success && res.data.length > 0) {\r\n                    let html = '<option value=\"\">-- T\u1ea5t c\u1ea3 Ph\u01b0\u1eddng\/X\u00e3 --<\/option>';\r\n                    res.data.forEach(area => {\r\n                        html += `<option value=\"${area.slug}\">${area.name}<\/option>`;\r\n                    });\r\n                    xaSelect.innerHTML = html;\r\n                } else {\r\n                    xaSelect.innerHTML = '<option value=\"\">(Kh\u00f4ng c\u00f3 d\u1eef li\u1ec7u)<\/option>';\r\n                }\r\n            });\r\n        }\r\n\r\n\t\t\/\/ 1. Nh\u1eadn to\u00e0n b\u1ed9 d\u1eef li\u1ec7u c\u1ea5u h\u00ecnh b\u1ea3n \u0111\u1ed3 t\u1eeb PHP Database truy\u1ec1n sang\r\n        var qhServerData = [{\"id\":\"qh-2045\",\"name\":\"QH 2045\",\"group\":\"Cam L\\u00e2m\",\"order\":1,\"url\":\"https:\\\/\\\/bds.re\\\/wp-content\\\/uploads\\\/2026\\\/07\\\/CL2045-1.png\",\"sw_lat\":11.942673,\"sw_lng\":108.953585,\"ne_lat\":12.21549,\"ne_lng\":109.230249},{\"id\":\"qh-2030\",\"name\":\"QH 2030\",\"group\":\"Cam L\\u00e2m\",\"order\":2,\"url\":\"https:\\\/\\\/bds.re\\\/wp-content\\\/uploads\\\/2026\\\/07\\\/CL2025.png\",\"sw_lat\":11.931227,\"sw_lng\":108.926939,\"ne_lat\":12.218908,\"ne_lng\":109.22442},{\"id\":\"dk-1-500-suoi-tan\",\"name\":\"DK 1.500 Su\\u1ed1i T\\u00e2n\",\"group\":\"Cam L\\u00e2m\",\"order\":3,\"url\":\"https:\\\/\\\/bds.re\\\/wp-content\\\/uploads\\\/2026\\\/07\\\/DKST1.500.png\",\"sw_lat\":12.136941,\"sw_lng\":109.054078,\"ne_lat\":12.172975,\"ne_lng\":109.106976},{\"id\":\"dk-1-500-cam-tan\",\"name\":\"DK 1.500 Cam T\\u00e2n\",\"group\":\"Cam L\\u00e2m\",\"order\":4,\"url\":\"https:\\\/\\\/bds.re\\\/wp-content\\\/uploads\\\/2026\\\/07\\\/DKCT1.500.png\",\"sw_lat\":12.107081,\"sw_lng\":109.093046,\"ne_lat\":12.136374,\"ne_lng\":109.113939}];\r\n        var qhLayers = {}; \/\/ Kh\u1edfi t\u1ea1o kho ch\u1ee9a r\u1ed7ng\r\n\r\n        \/\/ 2. V\u00f2ng l\u1eb7p t\u1ef1 \u0111\u1ed9ng ph\u00e2n lo\u1ea1i v\u00e0 t\u1ea1o L\u1edbp B\u1ea3n \u0110\u1ed3 (H\u1ed7 tr\u1ee3 c\u1ea3 PNG t\u0129nh v\u00e0 XYZ Tiles)\r\n        qhServerData.forEach(function(qh) {\r\n            var currentOpacity = document.getElementById('quyhoach_opacity').value;\r\n            \r\n            \/\/ N\u1ebfu link ch\u1ee9a chu\u1ed7i {z} -> K\u00edch ho\u1ea1t c\u01a1 ch\u1ebf B\u1ea3n \u0111\u1ed3 c\u1eaft m\u1ea3nh XYZ Tiles (Hi\u1ec7u n\u0103ng cao)\r\n            if (qh.url.indexOf('{z}') !== -1) {\r\n                qhLayers[qh.id] = L.tileLayer(qh.url, {\r\n                    bounds: [[qh.sw_lat, qh.sw_lng], [qh.ne_lat, qh.ne_lng]], \/\/ Gi\u1edbi h\u1ea1n khung \u0111\u1ec3 kh\u00f4ng t\u1ea3i d\u01b0 \u1ea3nh r\u00e1c\r\n                    opacity: currentOpacity,\r\n                    maxNativeZoom: 18, \/\/ M\u1ee9c Zoom t\u1ed1i \u0111a b\u1ea1n \u0111\u00e3 c\u1eaft trong Global Mapper\r\n                    maxZoom: 22,       \/\/ \u00c9p tr\u00ecnh duy\u1ec7t t\u1ef1 ph\u00f3ng to \u1ea3nh m\u1edd l\u00ean n\u1ebfu kh\u00e1ch c\u1ed1 zoom > 18\r\n                    pane: 'overlayPane'\r\n                });\r\n            } \r\n            \/\/ Ng\u01b0\u1ee3c l\u1ea1i -> V\u1eabn gi\u1eef nguy\u00ean c\u01a1 ch\u1ebf B\u1ea3n \u0111\u1ed3 1 t\u1ea5m \u1ea3nh (Image Overlay) c\u0169\r\n            else {\r\n                qhLayers[qh.id] = L.imageOverlay(\r\n                    qh.url, \r\n                    [[qh.sw_lat, qh.sw_lng], [qh.ne_lat, qh.ne_lng]], \r\n                    { opacity: currentOpacity, interactive: false }\r\n                );\r\n            }\r\n        });\r\n\r\n\t\t\/\/ L\u1eafng nghe s\u1ef1 ki\u1ec7n B\u1eadt\/T\u1eaft Checkbox Quy Ho\u1ea1ch\r\n\t\tdocument.querySelectorAll('.qh-checkbox').forEach(function(checkbox) {\r\n\t\t\tcheckbox.addEventListener('change', function() {\r\n\t\t\t\tvar layer = qhLayers[this.value];\r\n\t\t\t\tif (!layer) return; \/\/ B\u1ea3o m\u1eadt: B\u1ecf qua n\u1ebfu kh\u00f4ng t\u1ed3n t\u1ea1i layer\r\n\t\t\t\t\r\n\t\t\t\tif (this.checked) {\r\n\t\t\t\t\tmap.addLayer(layer);\r\n\t\t\t\t\tlayer.setOpacity(document.getElementById('quyhoach_opacity').value);\r\n\t\t\t\t} else {\r\n\t\t\t\t\tmap.removeLayer(layer);\r\n\t\t\t\t}\r\n\t\t\t});\r\n\t\t});\r\n\r\n\t\t\/\/ K\u00e9o thanh tr\u01b0\u1ee3t s\u1ebd thay \u0111\u1ed5i \u0111\u1ed9 m\u1edd cho T\u1ea4T C\u1ea2 c\u00e1c b\u1ea3n \u0111\u1ed3 \u0111ang \u0111\u01b0\u1ee3c b\u1eadt\r\n\t\tdocument.getElementById('quyhoach_opacity').addEventListener('input', function(e) {\r\n\t\t\tvar newOpacity = e.target.value;\r\n\t\t\tfor (var key in qhLayers) {\r\n\t\t\t\tif (map.hasLayer(qhLayers[key])) {\r\n\t\t\t\t\tqhLayers[key].setOpacity(newOpacity);\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t});\r\n\r\n        function formatPrice(num) {\r\n            if (num >= 1000000000) {\r\n                let ty = num \/ 1000000000;\r\n                return (Number.isInteger(ty) ? ty : ty.toFixed(1)) + \" T\u1ef7\";\r\n            }\r\n            if (num >= 1000000) return Math.round(num \/ 1000000) + \" Tr\";\r\n            return num.toLocaleString() + \" \u0111\";\r\n        }\r\n\r\n        let fetchTimeout;\r\n        function fetchMapData() {\r\n            clearTimeout(fetchTimeout);\r\n            fetchTimeout = setTimeout(() => {\r\n                var bounds = map.getBounds();\r\n                var formData = new FormData();\r\n\t\t\t\tformData.append('security', '3bcd49f7cf');\r\n                formData.append('action', 'bdsre_load_map_data');\r\n                formData.append('sw_lat', bounds.getSouthWest().lat);\r\n                formData.append('sw_lng', bounds.getSouthWest().lng);\r\n                formData.append('ne_lat', bounds.getNorthEast().lat);\r\n                formData.append('ne_lng', bounds.getNorthEast().lng);\r\n                formData.append('hinh_thuc', document.getElementById('filter_hinh_thuc').value);\r\n                formData.append('loai_hinh', document.getElementById('filter_loai_hinh').value);\r\n                formData.append('max_price', document.getElementById('filter_max_price').value);\r\n                \/\/ B\u00e1o cho API bi\u1ebft T\u1ec9nh\/Huy\u1ec7n\/X\u00e3 \u0111ang \u0111\u01b0\u1ee3c ch\u1ecdn l\u00e0 g\u00ec\r\n                formData.append('tinh', document.getElementById('filter_tinh').value);\r\n                formData.append('huyen', document.getElementById('filter_huyen').value);\r\n                formData.append('xa', document.getElementById('filter_xa').value);\r\n                \r\n                formData.append('quick_tag', document.getElementById('filter_quick_tag').value);\r\n                \r\n                \/\/ G\u1eedi th\u00eam tr\u1ea1ng th\u00e1i b\u1eadt\/t\u1eaft c\u1ee7a 3 checkbox l\u1ecdc n\u00e2ng cao (1 = B\u1eadt, 0 = T\u1eaft)\r\n                formData.append('chk_oto', document.getElementById('filter_oto').checked ? 1 : 0);\r\n                formData.append('chk_phaply', document.getElementById('filter_phaply').checked ? 1 : 0);\r\n                formData.append('chk_thocu', document.getElementById('filter_thocu').checked ? 1 : 0);\r\n\r\n                fetch('https:\/\/bds.re\/wp-admin\/admin-ajax.php', { method: 'POST', body: formData })\r\n                .then(res => res.json())\r\n                .then(res => {\r\n                    if(res.success) {\r\n                        markersLayer.clearLayers();\r\n                        res.data.forEach(bds => {\r\n                            let priceText = formatPrice(bds.p);\r\n                            let colorClass = bds.p <= 2000000000 ? 'cheap' : '';\r\n                            let customIcon = L.divIcon({\r\n                                className: 'custom-div-icon',\r\n                                html: `<div class=\"price-marker ${colorClass}\">${priceText}<\/div>`,\r\n                                iconSize: [60, 24], iconAnchor: [30, 24]\r\n                            });\r\n                            let marker = L.marker([bds.lat, bds.lng], {icon: customIcon});\r\n                            \r\n                            \/\/ T\u1ea1o HTML cho Th\u1ebb B\u0110S Mini (C\u00f3 n\u00fat So S\u00e1nh chu\u1ea9n k\u1ebft n\u1ed1i v\u1edbi Plugin So S\u00e1nh)\r\n                            let safeTitle = bds.title.replace(\/'\/g, \"\\\\'\").replace(\/\"\/g, '&quot;');\r\n                            let popupHtml = `\r\n                                <div class=\"map-popup-card\">\r\n                                    <img decoding=\"async\" src=\"${bds.thumb}\" class=\"map-popup-img\" alt=\"\u1ea2nh B\u0110S\">\r\n                                    <div style=\"padding: 0 12px 12px 12px;\">\r\n                                        <div class=\"map-popup-price\">${priceText}<\/div>\r\n                                        <h3 class=\"map-popup-title\" title=\"${safeTitle}\">${bds.title}<\/h3>\r\n                                        <div class=\"map-popup-specs\">${bds.specs}<\/div>\r\n                                        <div class=\"map-popup-actions\">\r\n                                            <button class=\"map-popup-btn map-popup-btn-compare local-compare-btn\" data-id=\"${bds.id}\" data-title=\"${safeTitle}\" data-thumb=\"${bds.thumb}\">\u2696\ufe0f So S\u00e1nh<\/button>\r\n                                            <a href=\"${bds.link}\" target=\"_blank\" class=\"map-popup-btn\">\ud83d\udc41\ufe0f Xem C\u0103n<\/a>\r\n                                        <\/div>\r\n                                    <\/div>\r\n                                <\/div>\r\n                            `;\r\n                            marker.bindPopup(popupHtml);\r\n                            markersLayer.addLayer(marker);\r\n                        });\r\n                    }\r\n                });\r\n            }, 400);\r\n        }\r\n\r\n        map.on('moveend', fetchMapData);\r\n        fetchMapData();\r\n\r\n        var watchId = null;\r\n    var liveMarker = null;\r\n\r\n    function locateUser() {\r\n        if (!navigator.geolocation) {\r\n            alert(\"Tr\u00ecnh duy\u1ec7t c\u1ee7a b\u1ea1n kh\u00f4ng h\u1ed7 tr\u1ee3 \u0111\u1ecbnh v\u1ecb.\"); return;\r\n        }\r\n\r\n        var btn = document.querySelector('.btn-locate-me');\r\n\r\n        \/\/ N\u1ebeU \u0110ANG B\u1eacT -> T\u1eaeT \u0110I\r\n        if (watchId !== null) {\r\n            navigator.geolocation.clearWatch(watchId);\r\n            watchId = null;\r\n            if (liveMarker) { map.removeLayer(liveMarker); liveMarker = null; }\r\n            btn.style.background = '#2980b9'; \r\n            btn.innerHTML = '\ud83d\udccd T\u00ccM QUANH T\u00d4I';\r\n            return;\r\n        }\r\n\r\n        \/\/ N\u1ebeU \u0110ANG T\u1eaeT -> B\u1eacT L\u00caN\r\n        btn.style.background = '#27ae60'; \r\n        btn.innerHTML = '\ud83d\udce1 V\u1eca TR\u00cd...';\r\n\r\n        var isFirstZoom = true;\r\n\r\n        watchId = navigator.geolocation.watchPosition(function(position) {\r\n            var lat = position.coords.latitude;\r\n            var lng = position.coords.longitude;\r\n            var newLatLng = new L.LatLng(lat, lng);\r\n\r\n            \/\/ N\u1ebfu ch\u01b0a c\u00f3 marker, t\u1ea1o m\u1edbi v\u1edbi icon nh\u1ea5p nh\u00e1y\r\n            if (!liveMarker) {\r\n                var pulseIcon = L.divIcon({ className: 'custom-pulse', html: '<div class=\"gps-pulse\"><\/div>', iconSize: [16, 16], iconAnchor: [8, 8] });\r\n                liveMarker = L.marker(newLatLng, { icon: pulseIcon }).addTo(map);\r\n            } else {\r\n                \/\/ N\u1ebfu c\u00f3 r\u1ed3i, ch\u1ec9 c\u1ea7n di chuy\u1ec3n n\u00f3 m\u01b0\u1ee3t m\u00e0 \u0111\u1ebfn v\u1ecb tr\u00ed m\u1edbi\r\n                liveMarker.setLatLng(newLatLng);\r\n            }\r\n\r\n            \/\/ Ch\u1ec9 t\u1ef1 \u0111\u1ed9ng zoom b\u1ea3n \u0111\u1ed3 v\u00e0o v\u1ecb tr\u00ed kh\u00e1ch \u1edf l\u1ea7n \u0111\u1ea7u ti\u00ean. \r\n            \/\/ Nh\u1eefng l\u1ea7n sau kh\u00e1ch t\u1ef1 vu\u1ed1t b\u1ea3n \u0111\u1ed3 s\u1ebd kh\u00f4ng b\u1ecb gi\u1eadt ng\u01b0\u1ee3c l\u1ea1i.\r\n            if (isFirstZoom) {\r\n                map.flyTo([lat, lng], 16, { duration: 1.2 });\r\n                isFirstZoom = false;\r\n            }\r\n        }, function(error) {\r\n            alert(\"L\u1ed7i \u0111\u1ecbnh v\u1ecb. Vui l\u00f2ng b\u1eadt GPS tr\u00ean m\u00e1y.\");\r\n            btn.click(); \/\/ Reset n\u00fat\r\n        }, {\r\n            enableHighAccuracy: true, \/\/ \u00c9p d\u00f9ng chip GPS \u0111\u1ec3 l\u1ea5y \u0111\u1ed9 ch\u00ednh x\u00e1c cao nh\u1ea5t (t\u1edbi t\u1eebng m\u00e9t)\r\n            maximumAge: 0,\r\n            timeout: 10000\r\n        });\r\n    }\r\n    <\/script>\r\n    \n","protected":false},"excerpt":{"rendered":"","protected":false},"author":1,"featured_media":0,"parent":0,"menu_order":0,"comment_status":"closed","ping_status":"closed","template":"","meta":{"inline_featured_image":false,"footnotes":""},"class_list":["post-37706","page","type-page","status-publish","hentry"],"_links":{"self":[{"href":"https:\/\/bds.re\/en\/wp-json\/wp\/v2\/pages\/37706","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/bds.re\/en\/wp-json\/wp\/v2\/pages"}],"about":[{"href":"https:\/\/bds.re\/en\/wp-json\/wp\/v2\/types\/page"}],"author":[{"embeddable":true,"href":"https:\/\/bds.re\/en\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/bds.re\/en\/wp-json\/wp\/v2\/comments?post=37706"}],"version-history":[{"count":2,"href":"https:\/\/bds.re\/en\/wp-json\/wp\/v2\/pages\/37706\/revisions"}],"predecessor-version":[{"id":37715,"href":"https:\/\/bds.re\/en\/wp-json\/wp\/v2\/pages\/37706\/revisions\/37715"}],"wp:attachment":[{"href":"https:\/\/bds.re\/en\/wp-json\/wp\/v2\/media?parent=37706"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}