Skip to content
Snippets Groups Projects

Compare revisions

Changes are shown as if the source revision was being merged into the target revision. Learn more about comparing revisions.

Source

Select target project
No results found
Select Git revision
  • bottleneck
  • jwt
  • jwtreal
  • logout
  • main
  • master
  • secure
7 results

Target

Select target project
  • festivelo/festivelo_frontend
1 result
Select Git revision
  • bottleneck
  • jwt
  • jwtreal
  • logout
  • main
  • master
  • secure
7 results
Show changes
Commits on Source (2)
......@@ -27,10 +27,6 @@
Learn how to configure a non-root public URL by running `npm run build`.
-->
<title>React App</title>
<script
type="text/javascript"
src="https://dapi.kakao.com/v2/maps/sdk.js?appkey=%REACT_APP_KAKAO_MAP_APP_KEY%&libraries=services,clusterer,drawing"
></script>
</head>
<body>
......
import React, { useEffect } from 'react';
const Map = ({ latitude, longitude, markers, map, setMap }) => {
useEffect(() => {
const container = document.getElementById('map');
if (!map && container) {
const options = {
center: new window.kakao.maps.LatLng(latitude, longitude),
level: 5
};
const newMap = new window.kakao.maps.Map(container, options);
setMap(newMap);
}
}, []);
useEffect(() => {
if (map) {
const moveLatLon = new window.kakao.maps.LatLng(latitude, longitude);
map.setCenter(moveLatLon);
}
}, [latitude, longitude, map]);
import React from 'react';
const Map = () => {
return (
<div id="map" style={{ width: '100%', height: '100%' }}
/>
......
......@@ -32,18 +32,6 @@ const PlaceDirections = ({ startPlace, endPlace, map, onClose }) => {
});
setActiveInfowindow(null);
};
const handleZoomChange = useCallback(() => {
const level = map.getLevel();
markers.forEach(({ overlay }) => {
if (overlay) {
if (level <= 4) {
overlay.setMap(map);
} else {
overlay.setMap(null);
}
}
});
}, [map, markers]);
useEffect(() => {
return () => {
......@@ -58,7 +46,7 @@ const PlaceDirections = ({ startPlace, endPlace, map, onClose }) => {
const newClusterer = new window.kakao.maps.MarkerClusterer({
map: map,
averageCenter: true,
minLevel: 4,
minLevel: 6,
calculator: [10, 30, 50],
styles: [
{
......@@ -98,20 +86,13 @@ const PlaceDirections = ({ startPlace, endPlace, map, onClose }) => {
});
setClusterer(newClusterer);
const zoomChangedListener = window.kakao.maps.event.addListener(
map,
'zoom_changed',
handleZoomChange
);
return () => {
if (clusterer) {
clusterer.clear();
}
window.kakao.maps.event.removeListener(map, zoomChangedListener);
};
}
}, [map, handleZoomChange]);
}, [map]);
useEffect(() => {
return () => {
......@@ -324,22 +305,22 @@ const PlaceDirections = ({ startPlace, endPlace, map, onClose }) => {
}
};
useEffect(() => {
const handleClickOutside = (event) => {
if (directionsRef.current && !directionsRef.current.contains(event.target)) {
onClose();
}
};
// useEffect(() => {
// const handleClickOutside = (event) => {
// if (directionsRef.current && !directionsRef.current.contains(event.target)) {
// onClose();
// }
// };
document.addEventListener('mousedown', handleClickOutside);
return () => {
document.removeEventListener('mousedown', handleClickOutside);
};
}, [onClose]);
// document.addEventListener('mousedown', handleClickOutside);
// return () => {
// document.removeEventListener('mousedown', handleClickOutside);
// };
// }, [onClose]);
return (
<div className="place-directions" ref={directionsRef}>
<div className="direction-header">
<div className="directions-header">
<h2>길찾기</h2>
<button className="close-button" onClick={onClose}>×</button>
</div>
......@@ -357,11 +338,11 @@ const PlaceDirections = ({ startPlace, endPlace, map, onClose }) => {
</div>
{searchResults.length > 0 && (
<div className="search-results-list">
<div className="directions-search-results-list">
{searchResults.map((place) => (
<div
key={place.id}
className="search-result-item"
className="directions-search-result-item"
onClick={() => {
showPlaceInfo(place);
map.panTo(new window.kakao.maps.LatLng(place.coordinates.lat, place.coordinates.lng));
......@@ -370,7 +351,7 @@ const PlaceDirections = ({ startPlace, endPlace, map, onClose }) => {
<h3>{place.name}</h3>
<p>{place.address}</p>
{place.phone && <p className="phone">{place.phone}</p>}
<div className="place-actions">
<div className="directions-place-actions">
<button onClick={() => setSelectedStart(place)}>출발지로 설정</button>
<button onClick={() => setSelectedEnd(place)}>도착지로 설정</button>
</div>
......@@ -379,20 +360,20 @@ const PlaceDirections = ({ startPlace, endPlace, map, onClose }) => {
</div>
)}
<div className="route-info">
<div className="place-select">
<div className="start-place">
<div className="directions-route-info">
<div className="directions-place-select">
<div className="directions-start-place">
<label>출발지</label>
<div className="selected-place">
<div className="directions-selected-place">
{selectedStart ? selectedStart.name : '출발지를 선택하세요'}
{selectedStart && (
<button onClick={() => setSelectedStart(null)}>×</button>
)}
</div>
</div>
<div className="end-place">
<div className="directions-end-place">
<label>도착지</label>
<div className="selected-place">
<div className="directions-selected-place">
{selectedEnd ? selectedEnd.name : '도착지를 선택하세요'}
{selectedEnd && (
<button onClick={() => setSelectedEnd(null)}>×</button>
......@@ -402,7 +383,7 @@ const PlaceDirections = ({ startPlace, endPlace, map, onClose }) => {
</div>
<button
className="find-route-button"
className="directions-find-route-button"
onClick={findRoute}
disabled={loading || !selectedStart || !selectedEnd}
>
......@@ -410,7 +391,7 @@ const PlaceDirections = ({ startPlace, endPlace, map, onClose }) => {
</button>
{routeInfo && (
<div className="route-summary">
<div className="directions-route-summary">
<p> 거리: {routeInfo.distance}</p>
<p>예상 소요 시간: {routeInfo.duration}</p>
{routeInfo.fare && (
......@@ -420,7 +401,7 @@ const PlaceDirections = ({ startPlace, endPlace, map, onClose }) => {
</>
)}
<div
className="route-guides-header"
className="directions-route-guides-header"
onClick={() => setShowGuides(!showGuides)}
>
<h4>상세 경로 안내</h4>
......@@ -429,9 +410,9 @@ const PlaceDirections = ({ startPlace, endPlace, map, onClose }) => {
</span>
</div>
{showGuides && (
<div className="route-guides">
<div className="directions-route-guides">
{routeInfo.guides.map((guide, index) => (
<div key={index} className="guide-item">
<div key={index} className="directions-guide-item">
{guide.name && <strong>{guide.name}: </strong>}
<span>{guide.guidance}</span>
<small>({(guide.distance/1000).toFixed(1)}km)</small>
......
......@@ -5,23 +5,48 @@ const UseKakaoMap = (initialLocation) => {
const [markers, setMarkers] = useState([]);
const mapContainerRef = useRef(null);
const scriptLoadedRef = useRef(false);
const markersRef = useRef(markers);
const mapInstanceRef = useRef(null);
useEffect(() => {
markersRef.current = markers;
}, [markers]);
const handleZoomChange = useCallback(() => {
const level = mapInstanceRef.current.getLevel();
console.log('Current zoom level:', level);
console.log('markers', markersRef.current);
markersRef.current.forEach(({ marker, overlay }) => {
if (overlay) {
overlay.setMap(level <= 7 ? mapInstanceRef.current : null);
}
});
}, []);
const initializeMap = useCallback(() => {
if (map || !window.kakao || !window.kakao.maps) return;
if (!window.kakao || !window.kakao.maps) return;
const container = document.getElementById('map');
if (!container) return;
const options = {
center: new window.kakao.maps.LatLng(
initialLocation.latitude,
initialLocation.longitude
),
level: 5
};
const mapInstance = new window.kakao.maps.Map(container, options);
setMap(mapInstance);
}, [initialLocation, map]);
try {
const options = {
center: new window.kakao.maps.LatLng(
initialLocation.latitude,
initialLocation.longitude
),
level: 5
};
const mapInstance = new window.kakao.maps.Map(container, options);
mapInstanceRef.current = mapInstance;
window.kakao.maps.event.addListener(mapInstance, 'zoom_changed', handleZoomChange);
setMap(mapInstance);
} catch (error) {
console.error('Error creating map:', error);
}
}, [initialLocation, handleZoomChange]);
const clearMap = useCallback(() => {
console.log('clearMap1');
......@@ -30,8 +55,16 @@ const UseKakaoMap = (initialLocation) => {
console.log(markers);
markers.forEach(marker => {
if (marker.marker) marker.marker.setMap(null);
if (marker.overlay) marker.overlay.setMap(null);
if (marker.marker) {
marker.marker.setMap(null);
}
if (marker.overlay) {
marker.overlay.setMap(null);
const element = marker.overlay.getContent();
if (element && element.parentNode) {
element.parentNode.removeChild(element);
}
}
});
setMarkers([]);
......@@ -57,43 +90,43 @@ const UseKakaoMap = (initialLocation) => {
const loadKakaoMapScript = useCallback(() => {
if (scriptLoadedRef.current) {
console.log('Script already loaded');
initializeMap();
return;
}
console.log('Loading Kakao Maps script...');
const script = document.createElement('script');
script.src = `https://dapi.kakao.com/v2/maps/sdk.js?appkey=${process.env.REACT_APP_KAKAO_MAP_API_KEY}&libraries=services,clusterer`;
script.src = `https://dapi.kakao.com/v2/maps/sdk.js?appkey=${process.env.REACT_APP_KAKAO_MAP_APP_KEY}&libraries=services,clusterer&autoload=false`;
script.async = true;
script.onload = () => {
console.log('Script loaded, initializing Kakao Maps...');
window.kakao.maps.load(() => {
console.log('Kakao Maps loaded successfully');
scriptLoadedRef.current = true;
initializeMap();
});
};
script.onerror = (error) => {
console.error('Error loading Kakao Maps script:', error);
};
document.head.appendChild(script);
}, [initializeMap]);
useEffect(() => {
loadKakaoMapScript();
return () => {
if (map) {
window.kakao.maps.event.removeListener(map, 'zoom_changed');
clearMap();
setMap(null);
}
};
}, []);
useEffect(() => {
if (map) {
const moveLatLon = new window.kakao.maps.LatLng(
initialLocation.latitude,
initialLocation.longitude
);
map.setCenter(moveLatLon);
}
}, [initialLocation, map]);
return {
map,
setMap,
......
......@@ -217,7 +217,7 @@ const Home = () => {
const markerClusterer = new window.kakao.maps.MarkerClusterer({
map: map,
averageCenter: true,
minLevel: 5,
minLevel: 8,
disableClickZoom: true,
styles: [{
width: '50px',
......@@ -235,7 +235,7 @@ const Home = () => {
const overlayClusterer = new window.kakao.maps.MarkerClusterer({
map: map,
averageCenter: true,
minLevel: 5,
minLevel: 8,
disableClickZoom: true,
styles: [{
width: '50px',
......@@ -250,7 +250,7 @@ const Home = () => {
}]
});
const markers = [];
const realMarkers = [];
const overlayMarkers = [];
allPlaces.forEach((place, index) => {
......@@ -259,26 +259,29 @@ const Home = () => {
place.coordinates.lng
);
const marker = new window.kakao.maps.Marker({ position });
const placeMarker = new window.kakao.maps.Marker({ position, map: null });
const overlayMarker = new window.kakao.maps.Marker({
position,
opacity: 0
opacity: 0,
map: null
});
const overlay = createCustomOverlay(position, `${index + 1}. ${place.name}`);
window.kakao.maps.event.addListener(marker, 'click', () => {
window.kakao.maps.event.addListener(placeMarker, 'click', () => {
handlePlaceSelect(place);
});
bounds.extend(position);
linePath.push(position);
markers.push(marker);
realMarkers.push(placeMarker);
overlayMarkers.push(overlayMarker);
newMarkers.push({ marker, overlay });
newMarkers.push({ marker: placeMarker, overlay });
});
markerClusterer.addMarkers(markers);
markerClusterer.addMarkers(realMarkers);
overlayClusterer.addMarkers(overlayMarkers);
window.kakao.maps.event.addListener(markerClusterer, 'clusterclick', (cluster) => {
......@@ -297,6 +300,9 @@ const Home = () => {
polyline.setMap(map);
map.polyline = polyline;
console.log('newMarkers[0].overlay', newMarkers[0].overlay);
console.log('newMarkers', newMarkers);
setMarkers(newMarkers);
map.setBounds(bounds);
map.relayout();
......@@ -537,13 +543,7 @@ const Home = () => {
trips={trips}
/>
)}
<Map
latitude={selectedLocation.latitude}
longitude={selectedLocation.longitude}
markers={markers}
map={map}
setMap={setMap}
/>
<Map/>
</div>
</div>
</div>
......
......@@ -90,7 +90,7 @@
.add-places-list {
height: calc(100vh - 17rem);
overflow-y: auto;
padding: 10px 0;
padding: 10px 8px;
}
.loading {
......@@ -99,16 +99,6 @@
color: #666;
}
.place-item {
display: flex;
justify-content: space-between;
align-items: center;
padding: 15px;
cursor: pointer;
border-bottom: 1px solid #eee;
transition: background-color 0.2s;
}
.place-item:hover {
background-color: #f5f5f5;
}
......@@ -189,10 +179,6 @@
color: var(--primary-color-dark);
}
.place-info .location {
margin-bottom: 10px;
}
.place-info p {
display: flex;
align-items: center;
......@@ -201,6 +187,10 @@
line-height: 1.25;
}
.place-item .button-group {
margin-top: 0;
}
.place-info .tel-icon,
.place-info .calendar-icon,
.place-info .sponsor-icon,
......
......@@ -25,7 +25,7 @@
border-width: 1px;
border-style: solid;
background-color: white;
padding: 20px;
padding: 1rem;
box-shadow: 0 0 8px rgba(0, 0, 0, 0.15);
overflow-y: auto;
}
......
......@@ -152,14 +152,14 @@
color: white;
}
.add-button {
/* .add-button {
background: none;
border: none;
color: #4CAF50;
cursor: pointer;
padding: 0.5rem;
font-size: 1.2rem;
}
} */
.search-result-item {
display: flex;
......
......@@ -106,12 +106,13 @@
position: relative;
display: flex;
align-items: center;
padding: 15px;
padding: 1rem;
background: #fff;
border-radius: 8px;
margin-bottom: 10px;
margin-bottom: 12px;
cursor: pointer;
transition: all 0.2s ease;
box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1);
}
.place-item.dragging {
......
......@@ -40,14 +40,14 @@
background-color: #444;
}
.direction-header {
.directions-header {
display: flex;
justify-content: space-between;
align-items: center;
margin-bottom: 20px;
}
.direction-header h2 {
.directions-header h2 {
margin: 0;
}
......@@ -80,7 +80,7 @@
cursor: pointer;
}
.search-results-list {
.directions-search-results-list {
max-height: 300px;
overflow-y: auto;
margin: 15px 0;
......@@ -88,40 +88,40 @@
border-radius: 4px;
}
.search-result-item {
.directions-search-result-item {
padding: 15px;
border-bottom: 1px solid #eee;
cursor: pointer;
transition: background-color 0.2s;
}
.search-result-item:hover {
.directions-search-result-item:hover {
background-color: #f5f5f5;
}
.search-result-item h3 {
.directions-search-result-item h3 {
margin: 0;
font-size: 16px;
color: #333;
}
.search-result-item p {
.directions-search-result-item p {
margin: 5px 0 0;
font-size: 14px;
color: #666;
}
.search-result-item .phone {
.directions-search-result-item .phone {
color: #2196F3;
}
.place-actions {
.directions-place-actions {
display: flex;
gap: 8px;
margin-top: 10px;
}
.place-actions button {
.directions-place-actions button {
padding: 6px 12px;
font-size: 12px;
border: none;
......@@ -130,12 +130,12 @@
transition: background-color 0.2s;
}
.place-actions button:first-child {
.directions-place-actions button:first-child {
background-color: #4285f4;
color: white;
}
.place-actions button:last-child {
.directions-place-actions button:last-child {
background-color: #34a853;
color: white;
}
......@@ -144,14 +144,14 @@
margin-top: 20px;
}
.place-select {
.directions-place-select {
display: flex;
flex-direction: column;
gap: 15px;
margin-bottom: 20px;
}
.selected-place {
.directions-selected-place {
display: flex;
justify-content: space-between;
align-items: center;
......@@ -161,14 +161,14 @@
margin-top: 5px;
}
.selected-place button {
.directions-selected-place button {
background: none;
border: none;
cursor: pointer;
color: #666;
}
.find-route-button {
.directions-find-route-button {
width: 100%;
padding: 12px;
background: #333;
......@@ -179,18 +179,18 @@
margin-bottom: 15px;
}
.find-route-button:disabled {
.directions-find-route-button:disabled {
background: #ccc;
cursor: not-allowed;
}
.route-summary {
.directions-route-summary {
padding: 15px;
background: #f5f5f5;
border-radius: 4px;
}
.route-summary p {
.directions-route-summary p {
margin: 5px 0;
font-size: 14px;
}
......@@ -265,33 +265,33 @@
background-color: #3367d6;
}
.route-guides {
.directions-route-guides {
margin-top: 20px;
padding: 10px;
background-color: #f5f5f5;
border-radius: 8px;
}
.guide-item {
.directions-guide-item {
padding: 8px 0;
border-bottom: 1px solid #ddd;
font-size: 14px;
}
.guide-item:last-child {
.directions-guide-item:last-child {
border-bottom: none;
}
.guide-item strong {
.directions-guide-item strong {
color: #4A90E2;
}
.guide-item small {
.directions-guide-item small {
color: #666;
margin-left: 8px;
}
.route-guides-header {
.directions-route-guides-header {
display: flex;
justify-content: space-between;
align-items: center;
......@@ -303,25 +303,25 @@
transition: background-color 0.2s;
}
.route-guides-header:hover {
.directions-route-guides-header:hover {
background-color: #e9e9e9;
}
.route-guides-header h4 {
.directions-route-guides-header h4 {
margin: 0;
font-size: 15px;
}
.toggle-icon {
.directions-toggle-icon {
font-size: 12px;
transition: transform 0.2s;
}
.toggle-icon.open {
.directions-toggle-icon.open {
transform: rotate(180deg);
}
.route-guides {
.directions-route-guides {
margin-top: 0;
border-top: none;
border-top-left-radius: 0;
......