Files
jongryangje/app/Views/components/kakao_map_modal.php

154 lines
5.5 KiB
PHP
Raw Normal View History

<?php
declare(strict_types=1);
$key = trim((string) ($kakaoJavascriptKey ?? ''));
?>
<div id="kakao-map-modal" class="hidden fixed inset-0 z-[300] flex items-center justify-center p-4" aria-hidden="true" role="dialog" aria-modal="true" aria-labelledby="kakao-map-modal-title">
<div class="absolute inset-0 bg-black/50" id="kakao-map-modal-backdrop"></div>
<div class="relative z-[301] w-full max-w-2xl max-h-[90vh] flex flex-col rounded border border-gray-300 bg-white shadow-lg overflow-hidden">
<div class="flex items-center justify-between px-3 py-2 border-b border-gray-200 bg-gray-50 shrink-0">
<span id="kakao-map-modal-title" class="text-sm font-bold text-gray-800">위치</span>
<button type="button" id="kakao-map-modal-close" class="text-gray-600 hover:text-gray-900 text-xl leading-none px-1" aria-label="닫기">&times;</button>
</div>
<div id="kakao-map-modal-container" class="w-full bg-gray-100" style="min-height: 380px; height: 50vh;"></div>
</div>
</div>
<script>
(function () {
var APP_KEY = <?= json_encode($key, JSON_HEX_TAG | JSON_HEX_APOS | JSON_HEX_QUOT) ?>;
var modal = document.getElementById('kakao-map-modal');
var backdrop = document.getElementById('kakao-map-modal-backdrop');
var btnClose = document.getElementById('kakao-map-modal-close');
var mapContainer = document.getElementById('kakao-map-modal-container');
var mapInstance = null;
var markerInstance = null;
var scriptLoading = false;
var pendingAfterLoad = [];
function hideModal() {
if (!modal) return;
modal.classList.add('hidden');
modal.setAttribute('aria-hidden', 'true');
}
function showModal() {
if (!modal) return;
modal.classList.remove('hidden');
modal.setAttribute('aria-hidden', 'false');
}
function runPending() {
var q = pendingAfterLoad;
pendingAfterLoad = [];
q.forEach(function (fn) {
try {
fn();
} catch (e) {}
});
}
function ensureScript(cb) {
if (!APP_KEY) {
window.alert('카카오맵 JavaScript 키가 설정되지 않았습니다. .env에 kakao.javascriptKey를 설정해 주세요. (Kakao Developers → 앱 키 → JavaScript 키)');
return;
}
if (typeof kakao !== 'undefined' && kakao.maps) {
cb();
return;
}
pendingAfterLoad.push(cb);
if (scriptLoading) {
return;
}
scriptLoading = true;
var s = document.createElement('script');
s.charset = 'UTF-8';
s.async = true;
// 동적 삽입 시 autoload=false 후 kakao.maps.load() 필수 (카카오 웹 가이드)
s.src = 'https://dapi.kakao.com/v2/maps/sdk.js?appkey=' + encodeURIComponent(APP_KEY) + '&libraries=services&autoload=false';
s.onload = function () {
scriptLoading = false;
if (typeof kakao === 'undefined' || !kakao.maps || typeof kakao.maps.load !== 'function') {
pendingAfterLoad = [];
window.alert(
'카카오맵 API를 불러올 수 없습니다.\n\n' +
'Kakao Developers → 내 애플리케이션 → 해당 앱 → 「제품 설정」에서 「Kakao Map」(지도) / 로컬 API를 사용 설정으로 켜 주세요.\n' +
'(비활성 시 서버에서 OPEN_MAP_AND_LOCAL 오류가 납니다.)\n\n' +
'또한 플랫폼(Web)에 이 사이트 주소(예: http://localhost:8080)가 등록되어 있어야 합니다.'
);
return;
}
kakao.maps.load(function () {
runPending();
});
};
s.onerror = function () {
scriptLoading = false;
pendingAfterLoad = [];
window.alert(
'카카오맵 스크립트를 불러오지 못했습니다.\n\n' +
'• 네트워크·차단(광고 차단) 확인\n' +
'• Kakao Developers → 제품 설정에서 「Kakao Map」활성화\n' +
'• 플랫폼(Web)에 접속 중인 URL 등록'
);
};
document.head.appendChild(s);
}
if (btnClose) {
btnClose.addEventListener('click', hideModal);
}
if (backdrop) {
backdrop.addEventListener('click', hideModal);
}
document.addEventListener('keydown', function (e) {
if (e.key !== 'Escape' || !modal || modal.classList.contains('hidden')) {
return;
}
hideModal();
});
window.openDesignatedShopKakaoMap = function (addressQuery) {
var q = String(addressQuery || '').trim();
if (!q) {
window.alert('주소가 없습니다.');
return;
}
ensureScript(function () {
if (typeof kakao === 'undefined' || !kakao.maps || !kakao.maps.services) {
window.alert('카카오맵을 초기화할 수 없습니다.');
return;
}
var geocoder = new kakao.maps.services.Geocoder();
geocoder.addressSearch(q, function (result, status) {
if (status !== kakao.maps.services.Status.OK || !result || !result[0]) {
window.alert('주소를 지도에서 찾을 수 없습니다.');
return;
}
var coords = new kakao.maps.LatLng(result[0].y, result[0].x);
showModal();
if (!mapInstance) {
mapInstance = new kakao.maps.Map(mapContainer, {
center: coords,
level: 3
});
} else {
mapInstance.setCenter(coords);
mapInstance.setLevel(3);
}
if (markerInstance) {
markerInstance.setMap(null);
}
markerInstance = new kakao.maps.Marker({ position: coords, map: mapInstance });
setTimeout(function () {
if (mapInstance) {
mapInstance.relayout();
mapInstance.setCenter(coords);
}
}, 100);
});
});
};
})();
</script>