diff --git a/frontend/src/component/canvasWithMap/canvasWithMapforDraw/MapCanvasForDraw.tsx b/frontend/src/component/canvasWithMap/canvasWithMapforDraw/MapCanvasForDraw.tsx index f1955730..82320089 100644 --- a/frontend/src/component/canvasWithMap/canvasWithMapforDraw/MapCanvasForDraw.tsx +++ b/frontend/src/component/canvasWithMap/canvasWithMapforDraw/MapCanvasForDraw.tsx @@ -11,6 +11,7 @@ import startmarker from '@/assets/startmarker.png'; import endmarker from '@/assets/endmarker.png'; import { CurrentUserContext } from '@/context/CurrentUserContext'; import { ToolDescription } from '@/component/tooldescription/ToolDescription'; +import { SearchBox } from '@/component/searchbox/SearchBox'; export const MapCanvasForDraw = ({ width, @@ -216,9 +217,27 @@ export const MapCanvasForDraw = ({ if (!clickedPoint) return; switch (toolType) { case ButtonState.START_MARKER: + setCurrentUser(prevUser => ({ + ...prevUser, + start_location: { + ...prevUser.start_location, + title: '', // title을 빈 문자열로 초기화 -> 검색창에 보이게 하려고 + lat: clickedPoint.lat, + lng: clickedPoint.lng, + }, + })); setStartMarker(clickedPoint); break; case ButtonState.DESTINATION_MARKER: + setCurrentUser(prevUser => ({ + ...prevUser, + end_location: { + ...prevUser.end_location, + title: '', // title을 빈 문자열로 초기화 -> 검색창에 보이게 하려고 + lat: clickedPoint.lat, + lng: clickedPoint.lng, + }, + })); setEndMarker(clickedPoint); break; case ButtonState.LINE_DRAWING: @@ -384,6 +403,33 @@ export const MapCanvasForDraw = ({ } }; + const handleCreateMarker = (point: IPoint) => { + if (toolType === ButtonState.START_MARKER) { + setStartMarker(point); + setCurrentUser(prevUser => ({ + ...prevUser, + start_location: { + ...prevUser.start_location, + title: '', + }, + })); + } else { + setEndMarker(point); + setCurrentUser(prevUser => ({ + ...prevUser, + end_location: { + ...prevUser.end_location, + title: '', + }, + })); + } + }; + + const handleDeleteMarker = () => { + if (toolType === ButtonState.START_MARKER) setStartMarker(null); + else setEndMarker(null); + }; + useEffect(() => { if (isDragging) { if (canvasRef.current) { @@ -415,6 +461,16 @@ export const MapCanvasForDraw = ({ onTouchMove={handleTouchMove} onTouchEnd={handleTouchEnd} > + {(toolType === ButtonState.START_MARKER || toolType === ButtonState.DESTINATION_MARKER) && ( +
+ +
+ )}
{toolType === ButtonState.LINE_DRAWING ? (
diff --git a/frontend/src/component/header/Header.tsx b/frontend/src/component/header/Header.tsx index a58bf15c..61d68d5c 100644 --- a/frontend/src/component/header/Header.tsx +++ b/frontend/src/component/header/Header.tsx @@ -23,7 +23,7 @@ export const Header = (props: IHeaderProps) => { return (
diff --git a/frontend/src/component/routebutton/RouteResultButton.tsx b/frontend/src/component/routebutton/RouteResultButton.tsx index 7eb075a1..59cf11e7 100644 --- a/frontend/src/component/routebutton/RouteResultButton.tsx +++ b/frontend/src/component/routebutton/RouteResultButton.tsx @@ -28,11 +28,11 @@ export const RouteResultButton = (props: IRouteResultButtonProps) => { props.user.id > 1 ? '' : 'mr-8', )} > -
- {props.user.start_location.title} +
+ {props.user.end_location.title}
-
+
{props.user.end_location.title}
diff --git a/frontend/src/component/searchbox/SearchBox.tsx b/frontend/src/component/searchbox/SearchBox.tsx index e119c66d..95fd8a4b 100644 --- a/frontend/src/component/searchbox/SearchBox.tsx +++ b/frontend/src/component/searchbox/SearchBox.tsx @@ -1,19 +1,27 @@ import { ToolTypeContext } from '@/context/ToolTypeContext'; import React, { useContext, useEffect, useState } from 'react'; -import { IoMdClose, IoMdSearch } from 'react-icons/io'; +import { IoMdClose } from 'react-icons/io'; import { CurrentUserContext } from '@/context/CurrentUserContext'; +import { IPoint } from '@/lib/types/canvasInterface'; +import { getAddressFromCoordinates } from '@/utils/map/getAddress'; import { ButtonState } from '../common/enums'; interface ISearchResultItem { title: string; address: string; - link: string; + roadAddress: string; lat: number; lng: number; } -export const SearchBox = () => { - const [inputValue, setInputValue] = useState(''); // 검색 입력값 상태 +interface ISearchBoxProps { + startMarker?: IPoint | null; + endMarker?: IPoint | null; + setMarker: (point: IPoint) => void; + deleteMarker: () => void; +} +export const SearchBox = (props: ISearchBoxProps) => { + const [inputValue, setInputValue] = useState(''); // 검색 입력값 상태 const [searchResults, setSearchResults] = useState([]); // 검색 결과 상태 const [loading, setLoading] = useState(false); // 로딩 상태 const [error, setError] = useState(null); // 에러 상태 @@ -68,8 +76,8 @@ export const SearchBox = () => { title: item.title.replace(/<\/?[^>]+(>|$)/g, ''), // HTML 태그 제거 address: item.address || item.roadAddress || '주소 정보 없음', link: item.link || '#', - lat: parseFloat(item.mapy) / 1e7, // 위도 값 변환 - lng: parseFloat(item.mapx) / 1e7, // 경도 값 변환 + lat: parseFloat(item.mapy) / 1e7, + lng: parseFloat(item.mapx) / 1e7, })); console.log(data); setSearchResults(formattedResults); // 검색 결과 상태 업데이트 @@ -83,45 +91,79 @@ export const SearchBox = () => { /* TODO: 자동검색 로직 수정 필요 */ useEffect(() => { - const delayDebounceFn = setTimeout(() => { - if (inputValue.trim()) { - handleSearch(); + const getAddress = async () => { + if (toolType === ButtonState.START_MARKER && props.startMarker) { + if (currentUser.start_location?.title) { + // title이 비어있을 때 === 부산역 같은 title이 없을때 + return; + } + const value = await getAddressFromCoordinates(props.startMarker.lat, props.startMarker.lng); + setInputValue(value); + } else if (toolType === ButtonState.DESTINATION_MARKER && props.endMarker) { + if (currentUser.end_location?.title) { + return; + } + const value = await getAddressFromCoordinates(props.endMarker.lat, props.endMarker.lng); + setInputValue(value); } - }, 300); + }; - return () => clearTimeout(delayDebounceFn); - }, [inputValue]); + getAddress(); + }, [toolType, props.startMarker, props.endMarker]); const handleInputChange = (event: React.ChangeEvent) => { setInputValue(event.target.value); // 상태 업데이트 }; + useEffect(() => { + // 마커가 이미 존재하는 경우 더 이상 검색하지 않도록 방지 + if (toolType === ButtonState.START_MARKER && props.startMarker) { + return; + } + + if (toolType === ButtonState.DESTINATION_MARKER && props.endMarker) { + return; + } + + if (inputValue.trim()) { + const delayDebounceFn = setTimeout(() => { + handleSearch(); + }, 300); + + // Todo : 요부분 반환값 lint 오류 때문에 해결이 안돼요... + // eslint-disable-next-line consistent-return + return () => { + clearTimeout(delayDebounceFn); + }; + } + }, [inputValue, props.startMarker, props.endMarker, toolType]); + const handleSelectResult = (result: ISearchResultItem) => { - setInputValue(result.title); // 선택한 결과로 inputValue를 업데이트 - setSearchResults([]); // 결과 리스트를 닫음 + setInputValue(result.title); + setSearchResults([]); + props.setMarker({ lat: result.lat, lng: result.lng }); updateUser(result.title, result.lat, result.lng); - console.log(`위도: ${result.lat}, 경도: ${result.lng}`); }; const handleClear = () => { - setInputValue(''); // 입력값 초기화 - setSearchResults([]); // 검색 결과 초기화 + setInputValue(''); + setSearchResults([]); + props.deleteMarker(); }; return ( -
+
{/* 검색 입력 */} -
+
- @@ -135,7 +177,7 @@ export const SearchBox = () => { {searchResults.map(result => (