From 936777cec68663890d3eb31bf8daf94ee04b5510 Mon Sep 17 00:00:00 2001 From: afds4567 <33995840+afds4567@users.noreply.github.com> Date: Sun, 8 Oct 2023 23:48:21 +0900 Subject: [PATCH 01/10] =?UTF-8?q?feat:=20=EC=9E=90=EB=8F=99=EC=99=84?= =?UTF-8?q?=EC=84=B1=20=EC=BB=B4=ED=8F=AC=EB=84=8C=ED=8A=B8=20=EA=B5=AC?= =?UTF-8?q?=ED=98=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../components/common/Input/Autocomplete.tsx | 126 ++++++++++++++++++ 1 file changed, 126 insertions(+) create mode 100644 frontend/src/components/common/Input/Autocomplete.tsx diff --git a/frontend/src/components/common/Input/Autocomplete.tsx b/frontend/src/components/common/Input/Autocomplete.tsx new file mode 100644 index 00000000..d0f79aad --- /dev/null +++ b/frontend/src/components/common/Input/Autocomplete.tsx @@ -0,0 +1,126 @@ +/* eslint-disable react/function-component-definition */ +import { memo, useEffect, useState } from 'react'; +import styled from 'styled-components'; + +import { getPoiApi } from '../../../apis/getPoiApi'; +import Input from '.'; + +interface AutocompleteProps { + defaultValue?: string; + onSuggestionSelected: (suggestion: any) => void; +} + +const Autocomplete = ({ + defaultValue, + onSuggestionSelected, +}: AutocompleteProps) => { + const [inputValue, setInputValue] = useState( + defaultValue, + ); + const [suggestions, setSuggestions] = useState([]); + const [selectedSuggestion, setSelectedSuggestion] = useState( + null, + ); + + const onInputChange = (e: React.ChangeEvent) => { + if (e.target.value.trim() === '') { + setSuggestions([]); + setInputValue(''); + return; + } + setInputValue(e.target.value); + }; + + const onClickSuggestion = (suggestion: any) => { + const { name } = suggestion; + setInputValue(name); + setSelectedSuggestion(name); + onSuggestionSelected(suggestion); + }; + + async function fetchData() { + let fetchedSuggestions; + + try { + fetchedSuggestions = await getPoiApi(inputValue || ''); + } catch (error) { + fetchedSuggestions = []; + } + if (!fetchedSuggestions) return; + setSuggestions(fetchedSuggestions.pois?.poi); + } + + useEffect(() => { + if (!inputValue) return; + + fetchData(); + }, [inputValue]); + + useEffect(() => { + setInputValue(defaultValue); + }, [defaultValue]); + + return ( + <> + setSelectedSuggestion(null)} + /> + + {!selectedSuggestion && ( + + {suggestions?.map((suggestion: any, index: number) => ( + { + onClickSuggestion(suggestion); + }} + > + {suggestion.name} +
+ {suggestion.upperAddrName} {suggestion.middleAddrName}{' '} + {suggestion.roadName} +
+ {suggestion.desc} +
+ ))} +
+ )} + + ); +}; + +export default memo(Autocomplete); + +const AutocompleteInput = styled(Input)` + width: 100%; +`; + +const SuggestionsList = styled.ul` + border: 1px solid #ccc; + border-radius: 4px; + box-shadow: 0px 4px 5px -2px rgba(0, 0, 0, 0.3); +`; + +const SuggestionItem = styled.li` + padding: ${({ theme }) => theme.spacing['2']}; + cursor: pointer; + + &:hover { + background-color: #f7f7f7; + } +`; + +const Address = styled.div` + font-size: ${({ theme }) => theme.fontSize.small}; + color: ${({ theme }) => theme.color.gray}; +`; + +const Description = styled.div` + white-space: nowrap; + overflow: hidden; + text-overflow: ellipsis; +`; From 631860c20278d41044db3c5832380fd0d75188aa Mon Sep 17 00:00:00 2001 From: afds4567 <33995840+afds4567@users.noreply.github.com> Date: Mon, 9 Oct 2023 23:36:04 +0900 Subject: [PATCH 02/10] =?UTF-8?q?feat:=20getPoi=20=EA=B5=AC=ED=98=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- frontend/src/apis/getPoiApi.ts | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) create mode 100644 frontend/src/apis/getPoiApi.ts diff --git a/frontend/src/apis/getPoiApi.ts b/frontend/src/apis/getPoiApi.ts new file mode 100644 index 00000000..6d05c753 --- /dev/null +++ b/frontend/src/apis/getPoiApi.ts @@ -0,0 +1,18 @@ +export const getPoiApi = async (query: string) => { + const response = await fetch( + `https://apis.openapi.sk.com/tmap/pois?version=1&format=json&callback=result&searchKeyword=${query}&resCoordType=WGS84GEO&reqCoordType=WGS84GEO&count=10`, + { + method: 'GET', + headers: { appKey: process.env.TMAP_API_KEY || '' }, + }, + ); + + if (response.status >= 400) { + throw new Error('[POI] GET 요청에 실패했습니다.'); + } + + const responseData: T = await response.json(); + + const { searchPoiInfo } = responseData; + return searchPoiInfo; +}; From facd655e6dcf69ed8b09bc1ca1c730b7e301edd5 Mon Sep 17 00:00:00 2001 From: afds4567 <33995840+afds4567@users.noreply.github.com> Date: Mon, 9 Oct 2023 23:36:28 +0900 Subject: [PATCH 03/10] =?UTF-8?q?feat:=20=EC=9E=90=EB=8F=99=EC=99=84?= =?UTF-8?q?=EC=84=B1=20=EC=BB=B4=ED=8F=AC=EB=84=8C=ED=8A=B8=20=EA=B5=AC?= =?UTF-8?q?=ED=98=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../components/common/Input/Autocomplete.tsx | 20 +++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/frontend/src/components/common/Input/Autocomplete.tsx b/frontend/src/components/common/Input/Autocomplete.tsx index d0f79aad..343a502f 100644 --- a/frontend/src/components/common/Input/Autocomplete.tsx +++ b/frontend/src/components/common/Input/Autocomplete.tsx @@ -5,15 +5,15 @@ import styled from 'styled-components'; import { getPoiApi } from '../../../apis/getPoiApi'; import Input from '.'; -interface AutocompleteProps { +interface AutocompleteProps { defaultValue?: string; - onSuggestionSelected: (suggestion: any) => void; + onSuggestionSelected: (suggestion: T) => void; } -const Autocomplete = ({ +const Autocomplete = ({ defaultValue, onSuggestionSelected, -}: AutocompleteProps) => { +}: AutocompleteProps) => { const [inputValue, setInputValue] = useState( defaultValue, ); @@ -39,15 +39,15 @@ const Autocomplete = ({ }; async function fetchData() { - let fetchedSuggestions; - try { - fetchedSuggestions = await getPoiApi(inputValue || ''); + const fetchedSuggestions = await getPoiApi(inputValue || ''); + if (!fetchedSuggestions) + throw new Error('추천 검색어를 불러오지 못했습니다.'); + setSuggestions(fetchedSuggestions.pois?.poi); } catch (error) { - fetchedSuggestions = []; + setSuggestions([]); + console.error(error); } - if (!fetchedSuggestions) return; - setSuggestions(fetchedSuggestions.pois?.poi); } useEffect(() => { From cdae8c5a77b4cc30cbb4dc2080926e7b5e40e132 Mon Sep 17 00:00:00 2001 From: afds4567 <33995840+afds4567@users.noreply.github.com> Date: Mon, 9 Oct 2023 23:36:47 +0900 Subject: [PATCH 04/10] =?UTF-8?q?feat:=20=ED=95=80=20=EC=B6=94=EA=B0=80=20?= =?UTF-8?q?=ED=8E=98=EC=9D=B4=EC=A7=80=EC=97=90=20=EC=9E=90=EB=8F=99?= =?UTF-8?q?=EC=99=84=EC=84=B1=20=EC=9E=85=EB=A0=A5=EC=B0=BD=20=EC=B6=94?= =?UTF-8?q?=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- frontend/src/pages/NewPin.tsx | 104 +++++++++++++++++++++------------- 1 file changed, 66 insertions(+), 38 deletions(-) diff --git a/frontend/src/pages/NewPin.tsx b/frontend/src/pages/NewPin.tsx index 7df2ecb1..7cae94c7 100644 --- a/frontend/src/pages/NewPin.tsx +++ b/frontend/src/pages/NewPin.tsx @@ -1,13 +1,13 @@ +/* eslint-disable no-nested-ternary */ import { FormEvent, useContext, useEffect, useState } from 'react'; import { useLocation } from 'react-router-dom'; import { styled } from 'styled-components'; import { getApi } from '../apis/getApi'; -import { getMapApi } from '../apis/getMapApi'; import { postApi } from '../apis/postApi'; import Button from '../components/common/Button'; import Flex from '../components/common/Flex'; -import Input from '../components/common/Input'; +import Autocomplete from '../components/common/Input/Autocomplete'; import Space from '../components/common/Space'; import Text from '../components/common/Text'; import InputContainer from '../components/InputContainer'; @@ -51,7 +51,7 @@ function NewPin() { const { routePage } = useNavigator(); const { showToast } = useToast(); const { width } = useSetLayoutWidth(SIDEBAR); - const { openModal, closeModal } = useContext(ModalContext); + const { openModal } = useContext(ModalContext); const { compressImageList } = useCompressImage(); const [formImages, setFormImages] = useState([]); @@ -131,12 +131,10 @@ function NewPin() { return; } let postTopicId = topic?.id; - let postName = formValues.name; if (!topic) { // 토픽이 없으면 selectedTopic을 통해 토픽을 생성한다. postTopicId = selectedTopic?.topicId; - postName = selectedTopic?.topicName; } if (postTopicId) routePage(`/topics/${postTopicId}`, [postTopicId]); @@ -148,38 +146,38 @@ function NewPin() { } }; - const onClickAddressInput = ( - e: - | React.MouseEvent - | React.KeyboardEvent, - ) => { - if (!(e.type === 'click') && e.currentTarget.value) return; - - const width = 500; // 팝업의 너비 - const height = 600; // 팝업의 높이 - new window.daum.Postcode({ - width, // 생성자에 크기 값을 명시적으로 지정해야 합니다. - height, - async onComplete(data: any) { - const addr = data.roadAddress; // 주소 변수 - - // data를 통해 받아온 값을 Tmap api를 통해 위도와 경도를 구한다. - const { ConvertAdd } = await getMapApi( - `https://apis.openapi.sk.com/tmap/geo/convertAddress?version=1&format=json&callback=result&searchTypCd=NtoO&appKey=P2MX6F1aaf428AbAyahIl9L8GsIlES04aXS9hgxo&coordType=WGS84GEO&reqAdd=${addr}`, - ); - const lat = ConvertAdd.oldLat; - const lng = ConvertAdd.oldLon; - - setClickedCoordinate({ - latitude: lat, - longitude: lng, - address: addr, - }); - }, - }).open({ - popupKey: 'postPopUp', - }); - }; + // const onClickAddressInput = ( + // e: + // | React.MouseEvent + // | React.KeyboardEvent, + // ) => { + // if (!(e.type === 'click') && e.currentTarget.value) return; + + // const width = 500; // 팝업의 너비 + // const height = 600; // 팝업의 높이 + // new window.daum.Postcode({ + // width, // 생성자에 크기 값을 명시적으로 지정해야 합니다. + // height, + // async onComplete(data: any) { + // const addr = data.roadAddress; // 주소 변수 + + // // data를 통해 받아온 값을 Tmap api를 통해 위도와 경도를 구한다. + // const { ConvertAdd } = await getMapApi( + // `https://apis.openapi.sk.com/tmap/geo/convertAddress?version=1&format=json&callback=result&searchTypCd=NtoO&appKey=P2MX6F1aaf428AbAyahIl9L8GsIlES04aXS9hgxo&coordType=WGS84GEO&reqAdd=${addr}`, + // ); + // const lat = ConvertAdd.oldLat; + // const lng = ConvertAdd.oldLon; + + // setClickedCoordinate({ + // latitude: lat, + // longitude: lng, + // address: addr, + // }); + // }, + // }).open({ + // popupKey: 'postPopUp', + // }); + // }; const onPinImageChange = async ( event: React.ChangeEvent, @@ -215,6 +213,17 @@ function NewPin() { setShowedImages(imageUrlLists); }; + const onSuggestionSelected = (suggestion: any) => { + const { noorLat, noorLon } = suggestion; + const address = `${suggestion.upperAddrName} ${suggestion.middleAddrName} ${suggestion.roadName}[${suggestion.name}]`; + + setClickedCoordinate({ + latitude: noorLat, + longitude: noorLon, + address, + }); + }; + useEffect(() => { const getTopicId = async () => { if (topicId && topicId.split(',').length === 1) { @@ -319,6 +328,25 @@ function NewPin() { + + + 장소 위치 + + + + * + + + + + + + + {/* + 장소 위치 @@ -339,7 +367,7 @@ function NewPin() { placeholder="지도를 클릭하거나 장소의 위치를 입력해주세요." /> - + */} Date: Mon, 9 Oct 2023 23:37:28 +0900 Subject: [PATCH 05/10] =?UTF-8?q?refactor:=20=EC=A4=8C=20=EB=A0=88?= =?UTF-8?q?=EB=B2=A8=20=EC=84=A4=EC=A0=95=20=EC=A1=B0=EC=A0=95=20=EB=B0=8F?= =?UTF-8?q?=20=ED=83=80=EC=9E=85=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- frontend/src/hooks/useClickedCoordinate.ts | 2 ++ frontend/src/types/tmap.d.ts | 1 + 2 files changed, 3 insertions(+) diff --git a/frontend/src/hooks/useClickedCoordinate.ts b/frontend/src/hooks/useClickedCoordinate.ts index 31bdba85..9a8c59a6 100644 --- a/frontend/src/hooks/useClickedCoordinate.ts +++ b/frontend/src/hooks/useClickedCoordinate.ts @@ -10,10 +10,12 @@ export default function useClickedCoordinate(map: TMap | null) { useEffect(() => { if (!map) return; + const currentZoom = map.getZoom(); if (clickedCoordinate.address) displayClickedMarker(map); // 선택된 좌표가 있으면 해당 좌표로 지도의 중심을 이동 if (clickedCoordinate.latitude && clickedCoordinate.longitude) { + map.setZoom(currentZoom); map.panTo( new Tmapv3.LatLng( clickedCoordinate.latitude, diff --git a/frontend/src/types/tmap.d.ts b/frontend/src/types/tmap.d.ts index 921fb207..d3a9e7d4 100644 --- a/frontend/src/types/tmap.d.ts +++ b/frontend/src/types/tmap.d.ts @@ -20,6 +20,7 @@ interface TMap { fitBounds(bounds: LatLngBounds): void; setCenter(latLng: LatLng): void; setZoom(zoomLevel: number): void; + getZoom(): number; on(eventType: string, callback: (event: evt) => void): void; removeListener(eventType: string, callback: (event: evt) => void): void; } From c829eb6d15a5f6f25cabd51da53f2f7d5e39c8aa Mon Sep 17 00:00:00 2001 From: afds4567 <33995840+afds4567@users.noreply.github.com> Date: Mon, 9 Oct 2023 23:37:47 +0900 Subject: [PATCH 06/10] =?UTF-8?q?refactor:=20tmap=20api=20key=20=EC=B6=94?= =?UTF-8?q?=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .github/workflows/fe-merge-dev.yml | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/.github/workflows/fe-merge-dev.yml b/.github/workflows/fe-merge-dev.yml index 2797eb30..908a8e35 100644 --- a/.github/workflows/fe-merge-dev.yml +++ b/.github/workflows/fe-merge-dev.yml @@ -23,8 +23,8 @@ jobs: uses: actions/setup-node@v3 with: node-version: 18 - cache: 'npm' - cache-dependency-path: 'frontend' + cache: "npm" + cache-dependency-path: "frontend" - name: Install npm run: npm install @@ -35,7 +35,8 @@ jobs: working-directory: frontend env: REACT_APP_GOOGLE_ANALYTICS: ${{ secrets.REACT_APP_GOOGLE_ANALYTICS }} - APP_URL: 'https://mapbefine.kro.kr/api' + APP_URL: "https://mapbefine.kro.kr/api" + TMAP_API_KEY: ${{ secrets.TMAP_API_KEY }} - name: upload to artifact uses: actions/upload-artifact@v3 @@ -66,7 +67,7 @@ jobs: uses: 8398a7/action-slack@v3 with: - mention: 'here' + mention: "here" if_mention: always status: ${{ job.status }} fields: workflow,job,commit,message,ref,author,took From 35234b0e2d853ba0015b9112513591cd3c7b1643 Mon Sep 17 00:00:00 2001 From: afds4567 <33995840+afds4567@users.noreply.github.com> Date: Tue, 10 Oct 2023 00:21:57 +0900 Subject: [PATCH 07/10] =?UTF-8?q?feat:=20Poi=20=ED=83=80=EC=9E=85=20?= =?UTF-8?q?=EC=84=A4=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- frontend/src/apis/getPoiApi.ts | 9 ++- .../components/common/Input/Autocomplete.tsx | 24 +++--- frontend/src/pages/NewPin.tsx | 7 +- frontend/src/types/Poi.ts | 77 +++++++++++++++++++ 4 files changed, 99 insertions(+), 18 deletions(-) create mode 100644 frontend/src/types/Poi.ts diff --git a/frontend/src/apis/getPoiApi.ts b/frontend/src/apis/getPoiApi.ts index 6d05c753..fb63296f 100644 --- a/frontend/src/apis/getPoiApi.ts +++ b/frontend/src/apis/getPoiApi.ts @@ -1,4 +1,6 @@ -export const getPoiApi = async (query: string) => { +import { PoiApiResponse } from '../types/Poi'; + +export const getPoiApi = async (query: string): Promise => { const response = await fetch( `https://apis.openapi.sk.com/tmap/pois?version=1&format=json&callback=result&searchKeyword=${query}&resCoordType=WGS84GEO&reqCoordType=WGS84GEO&count=10`, { @@ -11,8 +13,7 @@ export const getPoiApi = async (query: string) => { throw new Error('[POI] GET 요청에 실패했습니다.'); } - const responseData: T = await response.json(); + const responseData = await response.json(); - const { searchPoiInfo } = responseData; - return searchPoiInfo; + return responseData; }; diff --git a/frontend/src/components/common/Input/Autocomplete.tsx b/frontend/src/components/common/Input/Autocomplete.tsx index 343a502f..9ca9d7c2 100644 --- a/frontend/src/components/common/Input/Autocomplete.tsx +++ b/frontend/src/components/common/Input/Autocomplete.tsx @@ -3,24 +3,25 @@ import { memo, useEffect, useState } from 'react'; import styled from 'styled-components'; import { getPoiApi } from '../../../apis/getPoiApi'; +import { Poi } from '../../../types/Poi'; import Input from '.'; -interface AutocompleteProps { +interface AutocompleteProps { defaultValue?: string; - onSuggestionSelected: (suggestion: T) => void; + onSuggestionSelected: (suggestion: Poi) => void; } -const Autocomplete = ({ +const Autocomplete = ({ defaultValue, onSuggestionSelected, -}: AutocompleteProps) => { +}: AutocompleteProps) => { const [inputValue, setInputValue] = useState( defaultValue, ); - const [suggestions, setSuggestions] = useState([]); - const [selectedSuggestion, setSelectedSuggestion] = useState( - null, - ); + const [suggestions, setSuggestions] = useState([]); + const [selectedSuggestion, setSelectedSuggestion] = useState< + Poi['name'] | null + >(null); const onInputChange = (e: React.ChangeEvent) => { if (e.target.value.trim() === '') { @@ -31,7 +32,7 @@ const Autocomplete = ({ setInputValue(e.target.value); }; - const onClickSuggestion = (suggestion: any) => { + const onClickSuggestion = (suggestion: Poi) => { const { name } = suggestion; setInputValue(name); setSelectedSuggestion(name); @@ -41,9 +42,10 @@ const Autocomplete = ({ async function fetchData() { try { const fetchedSuggestions = await getPoiApi(inputValue || ''); + console.log(fetchedSuggestions); if (!fetchedSuggestions) throw new Error('추천 검색어를 불러오지 못했습니다.'); - setSuggestions(fetchedSuggestions.pois?.poi); + setSuggestions(fetchedSuggestions.searchPoiInfo.pois.poi); } catch (error) { setSuggestions([]); console.error(error); @@ -72,7 +74,7 @@ const Autocomplete = ({ {!selectedSuggestion && ( - {suggestions?.map((suggestion: any, index: number) => ( + {suggestions?.map((suggestion: Poi, index: number) => ( { diff --git a/frontend/src/pages/NewPin.tsx b/frontend/src/pages/NewPin.tsx index 7cae94c7..08acc335 100644 --- a/frontend/src/pages/NewPin.tsx +++ b/frontend/src/pages/NewPin.tsx @@ -24,6 +24,7 @@ import useSetLayoutWidth from '../hooks/useSetLayoutWidth'; import useSetNavbarHighlight from '../hooks/useSetNavbarHighlight'; import useToast from '../hooks/useToast'; import { NewPinFormProps } from '../types/FormValues'; +import { Poi } from '../types/Poi'; import { TopicCardProps } from '../types/Topic'; import { hasErrorMessage, hasNullValue } from '../validations'; @@ -213,13 +214,13 @@ function NewPin() { setShowedImages(imageUrlLists); }; - const onSuggestionSelected = (suggestion: any) => { + const onSuggestionSelected = (suggestion: Poi) => { const { noorLat, noorLon } = suggestion; const address = `${suggestion.upperAddrName} ${suggestion.middleAddrName} ${suggestion.roadName}[${suggestion.name}]`; setClickedCoordinate({ - latitude: noorLat, - longitude: noorLon, + latitude: Number(noorLat), + longitude: Number(noorLon), address, }); }; diff --git a/frontend/src/types/Poi.ts b/frontend/src/types/Poi.ts new file mode 100644 index 00000000..470b9135 --- /dev/null +++ b/frontend/src/types/Poi.ts @@ -0,0 +1,77 @@ +export interface EvCharger { + evCharger: any[]; +} + +export interface NewAddress { + centerLat: string; + centerLon: string; + frontLat: string; +} + +export interface NewAddressList { + newAddress: NewAddress[]; +} + +export interface Poi { + id: string; + pkey: string; + navSeq: string; + collectionType: string; + name: string; + + adminDongCode: string; + bizName: string; + dataKind: string; + desc: string; + + evChargers: EvCharger; + firstBuildNo: string; + firstNo: string; + frontLat: string; + frontLon: string; + + legalDongCode: string; + + lowerAddrName: string; + + middleAddrName: string; + mlClass: string; + + newAddressList: NewAddressList; + + noorLat: string; + noorLon: string; + + parkFlag: string; + + radius: string; + + roadName: string; + + rpFlag: string; + + secondBuildNo: string; + + secondNo: string; + + telNo: string; + + upperAddrName: string; + + zipCode: String; +} + +export interface Pois { + poi: Poi[]; +} + +export interface SearchPoiInfo { + totalCount: string; + count: string; + page: string; + pois: Pois; +} + +export interface PoiApiResponse { + searchPoiInfo: SearchPoiInfo; +} From 00f4fe5468f961f4ffeba18616ff7d958d8c49c3 Mon Sep 17 00:00:00 2001 From: afds4567 <33995840+afds4567@users.noreply.github.com> Date: Tue, 10 Oct 2023 01:07:01 +0900 Subject: [PATCH 08/10] =?UTF-8?q?feat:=20=EC=9E=90=EB=8F=99=EC=99=84?= =?UTF-8?q?=EC=84=B1=20debounce=20=EC=A0=81=EC=9A=A9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../components/common/Input/Autocomplete.tsx | 47 +++++++++++-------- 1 file changed, 27 insertions(+), 20 deletions(-) diff --git a/frontend/src/components/common/Input/Autocomplete.tsx b/frontend/src/components/common/Input/Autocomplete.tsx index 9ca9d7c2..91d00bd0 100644 --- a/frontend/src/components/common/Input/Autocomplete.tsx +++ b/frontend/src/components/common/Input/Autocomplete.tsx @@ -1,5 +1,5 @@ /* eslint-disable react/function-component-definition */ -import { memo, useEffect, useState } from 'react'; +import { memo, useEffect, useRef, useState } from 'react'; import styled from 'styled-components'; import { getPoiApi } from '../../../apis/getPoiApi'; @@ -23,13 +23,39 @@ const Autocomplete = ({ Poi['name'] | null >(null); + const debounceTimeoutRef = useRef(null); + + const fetchData = async (value: string) => { + try { + const fetchedSuggestions = await getPoiApi(value); + + if (!fetchedSuggestions) + throw new Error('추천 검색어를 불러오지 못했습니다.'); + + setSuggestions(fetchedSuggestions.searchPoiInfo.pois.poi); + } catch (error) { + setSuggestions([]); + console.error(error); + } + }; + const onInputChange = (e: React.ChangeEvent) => { if (e.target.value.trim() === '') { setSuggestions([]); setInputValue(''); return; } + setInputValue(e.target.value); + + if (debounceTimeoutRef.current !== null) { + clearTimeout(debounceTimeoutRef.current); + } + + debounceTimeoutRef.current = setTimeout( + () => fetchData(e.target.value), + 500, + ); }; const onClickSuggestion = (suggestion: Poi) => { @@ -39,25 +65,6 @@ const Autocomplete = ({ onSuggestionSelected(suggestion); }; - async function fetchData() { - try { - const fetchedSuggestions = await getPoiApi(inputValue || ''); - console.log(fetchedSuggestions); - if (!fetchedSuggestions) - throw new Error('추천 검색어를 불러오지 못했습니다.'); - setSuggestions(fetchedSuggestions.searchPoiInfo.pois.poi); - } catch (error) { - setSuggestions([]); - console.error(error); - } - } - - useEffect(() => { - if (!inputValue) return; - - fetchData(); - }, [inputValue]); - useEffect(() => { setInputValue(defaultValue); }, [defaultValue]); From b799c5c65808575daa6d69c1a631c8b8b75f7030 Mon Sep 17 00:00:00 2001 From: afds4567 <33995840+afds4567@users.noreply.github.com> Date: Wed, 11 Oct 2023 21:38:42 +0900 Subject: [PATCH 09/10] =?UTF-8?q?refactor:=20=EB=A6=AC=EB=B7=B0=20?= =?UTF-8?q?=EB=B0=98=EC=98=81?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../components/common/Input/Autocomplete.tsx | 21 ++++--- frontend/src/hooks/useClickedCoordinate.ts | 5 +- frontend/src/pages/NewPin.tsx | 57 ------------------- 3 files changed, 14 insertions(+), 69 deletions(-) diff --git a/frontend/src/components/common/Input/Autocomplete.tsx b/frontend/src/components/common/Input/Autocomplete.tsx index 91d00bd0..7db98284 100644 --- a/frontend/src/components/common/Input/Autocomplete.tsx +++ b/frontend/src/components/common/Input/Autocomplete.tsx @@ -5,6 +5,7 @@ import styled from 'styled-components'; import { getPoiApi } from '../../../apis/getPoiApi'; import { Poi } from '../../../types/Poi'; import Input from '.'; +import Text from '../Text'; interface AutocompleteProps { defaultValue?: string; @@ -12,12 +13,10 @@ interface AutocompleteProps { } const Autocomplete = ({ - defaultValue, + defaultValue = '', onSuggestionSelected, }: AutocompleteProps) => { - const [inputValue, setInputValue] = useState( - defaultValue, - ); + const [inputValue, setInputValue] = useState(defaultValue); const [suggestions, setSuggestions] = useState([]); const [selectedSuggestion, setSelectedSuggestion] = useState< Poi['name'] | null @@ -25,9 +24,9 @@ const Autocomplete = ({ const debounceTimeoutRef = useRef(null); - const fetchData = async (value: string) => { + const fetchData = async (query: string) => { try { - const fetchedSuggestions = await getPoiApi(value); + const fetchedSuggestions = await getPoiApi(query); if (!fetchedSuggestions) throw new Error('추천 검색어를 불러오지 못했습니다.'); @@ -89,7 +88,7 @@ const Autocomplete = ({ }} > {suggestion.name} -
+
{suggestion.upperAddrName} {suggestion.middleAddrName}{' '} {suggestion.roadName}
@@ -110,6 +109,7 @@ const AutocompleteInput = styled(Input)` const SuggestionsList = styled.ul` border: 1px solid #ccc; + border-top: none; border-radius: 4px; box-shadow: 0px 4px 5px -2px rgba(0, 0, 0, 0.3); `; @@ -123,12 +123,11 @@ const SuggestionItem = styled.li` } `; -const Address = styled.div` - font-size: ${({ theme }) => theme.fontSize.small}; - color: ${({ theme }) => theme.color.gray}; -`; +const Address = styled(Text)``; const Description = styled.div` + font-size: ${({ theme }) => theme.fontSize.small}; + white-space: nowrap; overflow: hidden; text-overflow: ellipsis; diff --git a/frontend/src/hooks/useClickedCoordinate.ts b/frontend/src/hooks/useClickedCoordinate.ts index 9a8c59a6..f206b889 100644 --- a/frontend/src/hooks/useClickedCoordinate.ts +++ b/frontend/src/hooks/useClickedCoordinate.ts @@ -15,7 +15,10 @@ export default function useClickedCoordinate(map: TMap | null) { // 선택된 좌표가 있으면 해당 좌표로 지도의 중심을 이동 if (clickedCoordinate.latitude && clickedCoordinate.longitude) { - map.setZoom(currentZoom); + if (currentZoom <= 17) { + map.setZoom(17); + } + map.panTo( new Tmapv3.LatLng( clickedCoordinate.latitude, diff --git a/frontend/src/pages/NewPin.tsx b/frontend/src/pages/NewPin.tsx index 08acc335..d1e30358 100644 --- a/frontend/src/pages/NewPin.tsx +++ b/frontend/src/pages/NewPin.tsx @@ -147,39 +147,6 @@ function NewPin() { } }; - // const onClickAddressInput = ( - // e: - // | React.MouseEvent - // | React.KeyboardEvent, - // ) => { - // if (!(e.type === 'click') && e.currentTarget.value) return; - - // const width = 500; // 팝업의 너비 - // const height = 600; // 팝업의 높이 - // new window.daum.Postcode({ - // width, // 생성자에 크기 값을 명시적으로 지정해야 합니다. - // height, - // async onComplete(data: any) { - // const addr = data.roadAddress; // 주소 변수 - - // // data를 통해 받아온 값을 Tmap api를 통해 위도와 경도를 구한다. - // const { ConvertAdd } = await getMapApi( - // `https://apis.openapi.sk.com/tmap/geo/convertAddress?version=1&format=json&callback=result&searchTypCd=NtoO&appKey=P2MX6F1aaf428AbAyahIl9L8GsIlES04aXS9hgxo&coordType=WGS84GEO&reqAdd=${addr}`, - // ); - // const lat = ConvertAdd.oldLat; - // const lng = ConvertAdd.oldLon; - - // setClickedCoordinate({ - // latitude: lat, - // longitude: lng, - // address: addr, - // }); - // }, - // }).open({ - // popupKey: 'postPopUp', - // }); - // }; - const onPinImageChange = async ( event: React.ChangeEvent, ) => { @@ -346,30 +313,6 @@ function NewPin() { - {/* - - - - 장소 위치 - - - - * - - - - - - */} - Date: Thu, 12 Oct 2023 15:56:40 +0900 Subject: [PATCH 10/10] =?UTF-8?q?refactor:=202=EC=B0=A8=20=EB=A6=AC?= =?UTF-8?q?=EB=B7=B0=20=EB=B0=98=EC=98=81?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- frontend/src/components/common/Input/Autocomplete.tsx | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/frontend/src/components/common/Input/Autocomplete.tsx b/frontend/src/components/common/Input/Autocomplete.tsx index 7db98284..10b38113 100644 --- a/frontend/src/components/common/Input/Autocomplete.tsx +++ b/frontend/src/components/common/Input/Autocomplete.tsx @@ -23,7 +23,6 @@ const Autocomplete = ({ >(null); const debounceTimeoutRef = useRef(null); - const fetchData = async (query: string) => { try { const fetchedSuggestions = await getPoiApi(query); @@ -92,7 +91,6 @@ const Autocomplete = ({ {suggestion.upperAddrName} {suggestion.middleAddrName}{' '} {suggestion.roadName}
- {suggestion.desc}
))}
@@ -110,6 +108,7 @@ const AutocompleteInput = styled(Input)` const SuggestionsList = styled.ul` border: 1px solid #ccc; border-top: none; + border-bottom: none; border-radius: 4px; box-shadow: 0px 4px 5px -2px rgba(0, 0, 0, 0.3); `;