From cfcea534d369c5b9bfb826b7bf4c2bedcba4aa47 Mon Sep 17 00:00:00 2001 From: pjookim <pjookim@naver.com> Date: Sat, 7 Dec 2024 22:04:03 +0900 Subject: [PATCH] refactor: streamline API request handling --- src/components/AddPlace.js | 160 +++++++++++++++++-------------------- 1 file changed, 72 insertions(+), 88 deletions(-) diff --git a/src/components/AddPlace.js b/src/components/AddPlace.js index af2195f..08a8ced 100644 --- a/src/components/AddPlace.js +++ b/src/components/AddPlace.js @@ -167,7 +167,7 @@ const AddPlace = ({ tripId, day, onBack, onPlaceSelect, tripStartDate, tripEndDa ); // 즐겨찾기에 없는 일반 항목들만 필터링 - const nonFavoriteItems = currentState.places.filter(place => + const nonFavoriteItems = currentState.places.filter(place => !favorites.has(place.id) ); @@ -246,7 +246,7 @@ const AddPlace = ({ tripId, day, onBack, onPlaceSelect, tripStartDate, tripEndDa const observerCallback = useCallback(entries => { const target = entries[0]; const currentState = tabStates[activeTab]; - + if (target.isIntersecting && currentState.hasMore && !currentState.loading) { const now = Date.now(); const timeToWait = API_CALL_INTERVAL - (now - lastApiCall); @@ -318,7 +318,15 @@ const AddPlace = ({ tripId, day, onBack, onPlaceSelect, tripStartDate, tripEndDa const searchPlaces = async (page, isNewSearch, keyword = '') => { const currentState = tabStates[activeTab]; if (currentState.loading || (!currentState.hasMore && !isNewSearch)) return; - + + const formatDate = (dateString) => { + if (!dateString) return null; + const year = dateString.substring(0, 4); + const month = dateString.substring(4, 6); + const day = dateString.substring(6, 8); + return `${year}-${month}-${day}`; + }; + const areaCode = getAreaCode(location); if (!areaCode) { toast.error('올바른 지역 정보가 아닙니다.'); @@ -327,29 +335,52 @@ const AddPlace = ({ tripId, day, onBack, onPlaceSelect, tripStartDate, tripEndDa updateTabState(activeTab, { loading: true }); try { - // 키워드가 있으면 키워드 검색 API를, 없으면 기존 지역 기반 API를 사용 - const apiEndpoint = keyword - ? 'searchKeyword1' - : 'areaBasedList1'; + let apiEndpoint; + let apiParams; + + if (activeTab === 'festivals') { + apiEndpoint = 'searchFestival1'; + const formattedTripStartDate = formatISODate(tripStartDate).replace(/-/g, ''); + const formattedTripEndDate = formatISODate(tripEndDate).replace(/-/g, ''); + + console.log('축제 검색 파라미터:', { + 시작일: formattedTripStartDate, + 종료일: formattedTripEndDate, + 지역코드: areaCode, + 페이지: page, + 키워드: keyword + }); - const response = await fetch( - `${TOUR_API_BASE_URL}/${apiEndpoint}` + + apiParams = keyword + ? `&keyword=${encodeURIComponent(keyword)}` + : `&eventStartDate=${formattedTripStartDate}&eventEndDate=${formattedTripEndDate}`; + } else { + apiEndpoint = keyword ? 'searchKeyword1' : 'areaBasedList1'; + apiParams = keyword ? `&keyword=${encodeURIComponent(keyword)}` : ''; + } + + const apiUrl = `${TOUR_API_BASE_URL}/${apiEndpoint}` + `?ServiceKey=${TOUR_API_KEY}` + - `&contentTypeId=${CONTENT_TYPE[activeTab]}` + + `${activeTab !== 'festivals' ? `&contentTypeId=${CONTENT_TYPE[activeTab]}` : ''}` + `&areaCode=${areaCode}` + `&listYN=Y` + `&MobileOS=ETC` + `&MobileApp=AppTest` + `&arrange=E` + - `&numOfRows=` + (CONTENT_TYPE[activeTab] === '15' ? 30 : 20) + + `&numOfRows=${CONTENT_TYPE[activeTab] === '15' ? 30 : 20}` + `&pageNo=${page}` + - (keyword ? `&keyword=${encodeURIComponent(keyword)}` : '') + - `&_type=json` - ); + apiParams + + `&_type=json`; + + console.log('API 요청 URL:', apiUrl); + const response = await fetch(apiUrl); const text = await response.text(); + + console.log('API 응답 원본:', text); if (text.includes('<OpenAPI_ServiceResponse>')) { + console.error('API 에러 응답 발생'); const parser = new DOMParser(); const xmlDoc = parser.parseFromString(text, 'text/xml'); const errorMsg = xmlDoc.querySelector('returnAuthMsg')?.textContent; @@ -369,90 +400,43 @@ const AddPlace = ({ tripId, day, onBack, onPlaceSelect, tripStartDate, tripEndDa }); return; } + const data = JSON.parse(text); + console.log('파싱된 API 응답:', data); const items = data.response.body.items.item || []; - console.log(items); - - if (activeTab === 'festivals') { // 지역 축제인 경우, 여행 기간에 맞게 필터링 - const formattedTripStartDate = formatISODate(tripStartDate); - const formattedTripEndDate = formatISODate(tripEndDate); - - console.log(`Formatted Trip Start Date: ${formattedTripStartDate}`); - console.log(`Formatted Trip End Date: ${formattedTripEndDate}`); - - const filteredItems = await Promise.all( - items.map(async (item) => { - try { - const detailResponse = await fetch( - `${TOUR_API_BASE_URL}/detailIntro1` + - `?ServiceKey=${TOUR_API_KEY}` + - `&contentId=${item.contentid}` + - `&contentTypeId=15` + - `&MobileOS=ETC` + - `&MobileApp=AppTest` + - `&_type=json` - ); - - const detailData = await detailResponse.json(); - const festivalInfo = detailData.response.body.items.item[0]; - const formatDate = (dateString) => { - const year = dateString.substring(0, 4); - const month = dateString.substring(4, 6); - const day = dateString.substring(6, 8); - return `${year}-${month}-${day}`; - }; - - const festivalStart = formatDate(festivalInfo.eventstartdate); - const festivalEnd = formatDate(festivalInfo.eventenddate); - - if (festivalEnd >= formattedTripStartDate && festivalStart <= formattedTripEndDate) { - console.log(festivalInfo.sponsor1); - console.log(festivalInfo.usetimefestival); - console.log(festivalInfo); - return { - ...item, - eventStartDate: festivalStart, - eventEndDate: festivalEnd, - sponsor: festivalInfo.sponsor1, - usetimefestival: festivalInfo.usetimefestival, - }; - } - return null; - } catch (error) { - console.error('Failed to fetch festival details:', error); - return null; - } - }) - ); - - const validItems = filteredItems.filter(item => item !== null); - const newPlaces = validItems.map(item => ({ - id: item.contentid, - type: item.contenttypeid, - name: item.title, - location: `${item.addr1} ${item.addr2 || ''}`.trim(), - coordinates: { - lat: parseFloat(item.mapy), - lng: parseFloat(item.mapx) - }, - image: item.firstimage, - tel: item.tel, - dist: item.dist, - eventStartDate: item.eventStartDate, - eventEndDate: item.eventEndDate, - sponsor: item.sponsor, - usetimefestival: item.usetimefestival - })); + if (activeTab === 'festivals') { + const newPlaces = items.map(item => { + console.log('축제 아이템 데이터:', item); + return { + id: item.contentid, + type: item.contenttypeid, + name: item.title, + location: `${item.addr1} ${item.addr2 || ''}`.trim(), + coordinates: { + lat: parseFloat(item.mapy), + lng: parseFloat(item.mapx) + }, + image: item.firstimage, + tel: item.tel, + dist: item.dist, + eventStartDate: formatDate(item.eventstartdate), + eventEndDate: formatDate(item.eventenddate), + sponsor: item.sponsor1, + usetimefestival: item.usetimefestival + }; + }); + + console.log('변환된 축제 데이터:', newPlaces); updateTabState('festivals', { places: isNewSearch ? newPlaces : [...currentState.places, ...newPlaces], loading: false, hasMore: newPlaces.length > 0, - totalCount: validItems.length + totalCount: parseInt(data.response.body.totalCount) }); - } else { // 그냥 관광지인 경우 + } else { const total = parseInt(data.response.body.totalCount); const newPlaces = items.map(item => ({ id: item.contentid, -- GitLab