프로젝트/쩝쩝박사
20220415(금)
수기
2022. 4. 15. 01:56
MainContainer.tsx
import React, { useState, useEffect } from 'react';
import SideBar from '../components/SideBar/SideBar';
import KakaoMap from '../KakaoMap/KakaoMap';
import styles from './MainContainer.module.scss'
import { getYoutubeItems, getVideoStatistic, getVideoComments } from '../api/youtube'
import { async } from '@firebase/util';
type thumbnailType = {
height: number;
url: string;
width: number;
}
type statisticType = {
etag: string;
id: string;
kind: string;
statistics: {
commentCount: string;
favoriteCount: string;
likeCount: string;
viewCount: string
}
}
type itemType = {
etag: string;
id: {
kind: string;
videoId: string;
}
kind: string;
snippet: {
channelId: string;
channelTitle: string;
description: string;
publishTime: string;
publishedAt: string;
title: string;
thumbnails: {
default: thumbnailType;
high: thumbnailType;
medium: thumbnailType
}
}
}
type pageInfoType = {
nextPageToken?: string;
}
function MainContainer() {
const maxResults: number = 20; // !한페이지에 불러올 영상 개수 지정
const [items, setItems] = useState<itemType[]>([])
const [statistics, setStatistics] = useState<any[]>([])
const [pageInfo, setPageInfo] = useState({ nextPageToken: '' })
const [isLastElement, setIsLastElement] = useState<boolean>(false);
const [commentInfo, setCommentInfo] = useState<any[]>([]);
const [loading, setLoading] = useState(false)
const [loading_items, setLoading_items] = useState(false)
const setYoutubeItems = async () => {
//TODO 유투브영상, 페이지 토큰 분리
try {
setLoading_items(true)
const prev = items;
const response = await getYoutubeItems(maxResults, pageInfo.nextPageToken);
setItems([...prev, ...response.items])
setPageInfo({ nextPageToken: response.nextPageToken })
}
catch (e) {
console.error(e);
}
setLoading_items(false)
}
const setVideoStatistic = async () => {
try {
const response: statisticType[] = await Promise.all(
items.map((item, index) => {
return getVideoStatistic(item.id.videoId)
})
)
setStatistics([...response]);
}
catch (e) {
console.error(e)
}
}
// const videoId = ['2i5JWqL3p60', '7GIRtKIHVXA', 'jSp2j643ZjE' ]
const setVideoComments = async () => {
try {
setLoading(true);
// const response = await getVideoComments(videoId[0])
console.log(items)
const response = await Promise.all(
items.map((item:any, index:any) => {
return getVideoComments(item.id.videoId)
})
)
setCommentInfo([...commentInfo, response]);
console.log('setVieoComments', commentInfo)
}
catch (e) {
console.error(e)
}
setLoading(false);
}
useEffect(() => {
setYoutubeItems();
if(commentInfo.length !== 0) return;
console.log(commentInfo)
setVideoComments();
return (() => {
console.log('컴포넌트 제거됨');
})
}, [])
useEffect(() => {
// 스크롤이 맨 밑에 도착했고, 다음 페이지가 존재할 때 유투브 컨텐츠를 받아옴
if (isLastElement && pageInfo.nextPageToken) {
// setYoutubeItems()
}
}, [isLastElement])
// if(loading_items) return <div>로딩중..</div>;
if(items == null || items === undefined || items === []) return null;
// if(loading) return <div>로딩중..</div>;
if(commentInfo == null || commentInfo === undefined || commentInfo === []) return null;
return (
<div className={styles['container']}>
<div className={styles['contents']}>
<SideBar items={items} statistics={statistics} isLastElement={isLastElement} setIsLastElement={setIsLastElement} />
<KakaoMap items={items} />
{/* {
items.map(a => {
console.log(a.id.videoId);
})
} */}
{
commentInfo.map(a => console.log(a))
// 여기다 하면 무한반복처리됨. why?..
}
</div>
</div >
)
}
export default MainContainer;
KakaoMap.tsx
import React, { useState, useEffect, useCallback } from 'react';
import styles from './KakaoMap.module.scss'
import { restaurantsInfo } from '../api/restuarants'
import { async } from '@firebase/util';
import { defaultMaxListeners } from 'events';
import Icon from '/Users/sk/kakao_map/src/assets/circle-dot-solid.svg'
import { useSelector } from 'react-redux';
import { RootState } from '../modules';
import { getVideoComments } from '../api/youtube';
declare global {
interface Window {
kakao: any
}
}
type positionType = {
lat: number;
lon: number
}
type markerType = {
id?: string,
title: string,
latlng: object,
// url: string
}
type addressType = {
id?: string,
text?: string,
title?: string,
latlng?: object
}
function KakaoMap(props:any) {
const [position, setPosition] = useState({ lat: 0, lon: 0 })
const [markerData, setMarkerData] = useState<markerType[]>([])
const [addressInfo, setAddressInfo] = useState<addressType[]>([])
const [address, setAddress] = useState<addressType[]>([])
// console.log(props.items);
// let items = props.items;
// 같은 state만 사용해보기
function createMap(position: positionType) {
console.log(props.comment)
let container = document.getElementById('map')
let options: object = {
center: new window.kakao.maps.LatLng(position.lat, position.lon),
level: 12
}
let map = new window.kakao.maps.Map(container, options)
getCommentInfo(map)
// console.log(markerData);
}
function setMarker(map:object){
// 텍스트 주소 -> 위치 주소로 변경
// getCommentInfo();
// restaurant 마커 정보 추가
let positions = addressInfo
console.log(positions)
positions.map(data => {
// 마커 이미지의 이미지 주소
let imageSrc = Icon;
// 마커 이미지의 이미지 크기
let imageSize = new window.kakao.maps.Size(22, 22);
// 마커 이미지를 생성합니다
let markerImage = new window.kakao.maps.MarkerImage(imageSrc, imageSize, )
// { offset: new window.kakao.maps.Point(24, 24) }// 마커이미지의 옵션입니다. 마커의 좌표와 일치시킬 이미지 안에서의 좌표를 설정합니다.);)
// 마커를 생성합니다
let marker = new window.kakao.maps.Marker({
map: map,
position: data.latlng,
title: data.title, // 마커의 타이틀, 마커에 마우스를 올리면 타이틀이 표시됩니다
image: markerImage // 마커 이미지
});
// 커스텀 오버레이에 표출될 내용으로 HTML 문자열이나 document element가 가능
let content = `<div id="customoverlay" class=${styles['customoverlay']} >` +
` <a href="#" target="_blank">` +
` <span class=${styles['title']}>${data.title}</span>` +
' </a>' +
'</div>';
// 커스텀 오버레이가 표시될 위치
let position = new window.kakao.maps.LatLng(data.latlng);
// 커스텀 오버레이를 생성
let customOverlay = new window.kakao.maps.CustomOverlay({
map: map,
position: data.latlng,
content: content,
yAnchor: 1,
});
})
}
function getCurrentPosition() {
if (navigator.geolocation) {
navigator.geolocation.getCurrentPosition(function (position) {
let lat = position.coords.latitude;
let lon = position.coords.longitude;
setPosition({ lat: lat, lon: lon })
})
}
}
// Comment에서 댓글 텍스트만 걸러내기
const getCommentInfo = (map:any) => {
let comment = props.comment
console.log('KakaoMap Comment' , comment)
for(let i in comment){
if(comment[i] !== null && comment[i] !== undefined){
let text = comment[i].snippet.topLevelComment.snippet.textOriginal
let id = comment[i].snippet.videoId
// setAddressInfo(addressInfo => [...addressInfo, {text:comment[i].snippet.topLevelComment.snippet.textOriginal, id:comment[i].snippet.videoId}]);
let addressIndex = text.indexOf('주소');
let numIndex = text.indexOf('전화번호');
if( (text.indexOf('매장번호') !== -1 && text.indexOf('매장번호') < numIndex) || numIndex === -1) numIndex = text.indexOf('매장번호');
if( (text.indexOf('영업시간') !== -1 && text.indexOf('영업시간') < numIndex) || numIndex === -1) numIndex = text.indexOf('영업시간');
if(addressIndex !== -1 && numIndex !== -1){
text = text.substring(addressIndex+3, numIndex)
// console.log(text)
}
// "주소" 를 "위치" 데이터로 변환
let geocoder = new window.kakao.maps.services.Geocoder();
geocoder.addressSearch(text, function(result:any, status:any) {
if(status === window.kakao.maps.services.Status.OK) {
let coords = new window.kakao.maps.LatLng(result[0].y, result[0].x)
let titleIndexEnd = text.lastIndexOf("\n");
if(text.substring(titleIndexEnd-1, titleIndexEnd) === ')') titleIndexEnd = titleIndexEnd - 1
let titleIndexStart = text.lastIndexOf(" ", titleIndexEnd)+1
// console.log(titleIndexStart, titleIndexEnd)
let title = text.substring(titleIndexStart, titleIndexEnd);
displayMarker(id, title, coords, map);
// setAddressInfo(addressInfo => [...addressInfo, {id:id, title:title, latlng:coords}])
console.log(title)
}
})
}
}
console.log(addressInfo)
// 댓글 중에서 "주소" 텍스트 만 걸러내기
// getAddressInfo();
// "주소" 를 "위치" 데이터로 변환
// transAddressInfo()
}
function displayMarker(id:any, title:any, coords:any, map:any){
// restaurant 마커 정보 추가
// let positions = addressInfo
// console.log(positions)
// positions.map(data => {
// 마커 이미지의 이미지 주소
let imageSrc = Icon;
// 마커 이미지의 이미지 크기
let imageSize = new window.kakao.maps.Size(22, 22);
// 마커 이미지를 생성합니다
let markerImage = new window.kakao.maps.MarkerImage(imageSrc, imageSize, )
let marker = new window.kakao.maps.Marker({
map: map,
position: coords,
title: title, // 마커의 타이틀, 마커에 마우스를 올리면 타이틀이 표시됩니다
image: markerImage // 마커 이미지
});
// 커스텀 오버레이에 표출될 내용으로 HTML 문자열이나 document element가 가능
let content = `<div id="customoverlay" class=${styles['customoverlay']} >` +
` <a href="#" target="_blank">` +
` <span class=${styles['title']}>${title}</span>` +
' </a>' +
'</div>';
// 커스텀 오버레이가 표시될 위치
let position = new window.kakao.maps.LatLng(coords);
// 커스텀 오버레이를 생성
let customOverlay = new window.kakao.maps.CustomOverlay({
map: map,
position: coords,
content: content,
yAnchor: 1,
});
// })
}
useEffect(() => {
// 초기 위치 설정
getCurrentPosition();
// 위치 데이터 업데이트
}, [])
useEffect(() => {
createMap(position)
}, [position])
return (
<>
<div id="map" className={styles['map']}>
<button className={styles['location']} onClick={getCurrentPosition}></button>
</div>
<h1> </h1>
</>
)
}
export default KakaoMap;