1
+ import React , { useEffect , useState } from 'react' ;
2
+ import { useNavigate , useLocation } from 'react-router-dom' ;
3
+ import mapData from '../../config/mapData.json'
4
+
5
+ const MapComponent = ( ) => {
6
+ const navigate = useNavigate ( ) ;
7
+ const location = useLocation ( ) ;
8
+ const [ map , setMap ] = useState ( null ) ;
9
+ const [ modalVisible , setModalVisible ] = useState ( false ) ;
10
+ const [ modalMessage , setModalMessage ] = useState ( '' ) ;
11
+ const [ data , setData ] = useState ( ) ;
12
+
13
+ useEffect ( ( ) => {
14
+
15
+ } , [ ] )
16
+ const Modal = ( { message, onClose } ) => {
17
+ // 모달 바깥 부분을 클릭했을 때 닫기
18
+ const handleOutsideClick = ( e ) => {
19
+ if ( e . target . className === 'modal' ) {
20
+ onClose ( ) ;
21
+ }
22
+ } ;
23
+ console . log ( message ) ;
24
+ return (
25
+ < div className = "modal" onClick = { handleOutsideClick } >
26
+ < div className = "w-72 h-32 p-4 bg-white rounded-2xl" >
27
+ < div > 작물 : { data . crop } </ div >
28
+ < div > 질병 : { data . disease } </ div >
29
+ < div > 주소 : { data . address } </ div >
30
+ < div > 신고날짜 : { data . date } </ div >
31
+ </ div >
32
+ </ div >
33
+ ) ;
34
+ } ;
35
+
36
+ // 작물별 마커 이미지 경로
37
+ const cropMarkerImages = {
38
+ 'tomato' : 'https://cdn1.iconfinder.com/data/icons/color-bold-style/21/14_2-1024.png' ,
39
+ 'cucumber' : 'https://cdn3.iconfinder.com/data/icons/flat-pro-basic-set-1-1/32/location-green-1024.png' ,
40
+ 'pepper' : 'https://cdn1.iconfinder.com/data/icons/color-bold-style/21/14-1024.png' ,
41
+ 'strawberry' : 'https://cdn1.iconfinder.com/data/icons/black-bold-style-1/3/14-1024.png' ,
42
+ } ;
43
+
44
+ const loadMapScript = ( ) => {
45
+ return new Promise ( ( resolve ) => {
46
+ const script = document . createElement ( 'script' ) ;
47
+ script . type = 'text/javascript' ;
48
+ script . src = `//dapi.kakao.com/v2/maps/sdk.js?appkey=${ process . env . REACT_APP_KAKAO_API_KEY } &autoload=false` ;
49
+ document . head . appendChild ( script ) ;
50
+
51
+ script . onload = ( ) => resolve ( window . kakao . maps . load ( resolve ) ) ;
52
+ } ) ;
53
+ } ;
54
+
55
+ const initializeMap = ( latitude , longitude ) => {
56
+ const container = document . getElementById ( 'map' ) ;
57
+ const options = {
58
+ center : new window . kakao . maps . LatLng ( latitude , longitude ) ,
59
+ level : 3 , // 적절한 확대 레벨 설정
60
+ } ;
61
+ const createdMap = new window . kakao . maps . Map ( container , options ) ;
62
+ setMap ( createdMap ) ;
63
+
64
+ const locPosition = new window . kakao . maps . LatLng ( latitude , longitude ) ;
65
+ const currentMarker = new window . kakao . maps . Marker ( {
66
+ position : locPosition ,
67
+ map : createdMap ,
68
+ title : '현재 위치' ,
69
+ } ) ;
70
+
71
+ const infowindow = new window . kakao . maps . InfoWindow ( {
72
+ content : '<div style="padding:5px;">현재 위치</div>' ,
73
+ } ) ;
74
+ infowindow . open ( createdMap , currentMarker ) ;
75
+
76
+ // 저장된 마커 로드 (예시)
77
+
78
+ const storedMarkers = JSON . parse ( localStorage . getItem ( 'reports' ) ) || [ ] ;
79
+
80
+ mapData . forEach ( ( m ) => {
81
+ const position = new window . kakao . maps . LatLng ( m . lat , m . lng ) ;
82
+ const imageSrc = cropMarkerImages [ m . crop ] || 'default_marker_image.png' ;
83
+ const markerImage = new window . kakao . maps . MarkerImage ( imageSrc , new window . kakao . maps . Size ( 40 , 40 ) ) ;
84
+ const marker = new window . kakao . maps . Marker ( {
85
+ position : position ,
86
+ map : createdMap ,
87
+ title : '신고된 위치' ,
88
+ image : markerImage ,
89
+ } ) ;
90
+
91
+ window . kakao . maps . event . addListener ( marker , 'click' , ( ) => {
92
+ const message = `Marker Details:\nLatitude: ${ m . lat } \nLongitude: ${ m . lng } \nDate: ${ m . date } ` ;
93
+ setData ( m ) ;
94
+ setModalMessage ( message ) ;
95
+ setModalVisible ( true ) ;
96
+ } ) ;
97
+ } ) ;
98
+ } ;
99
+
100
+ useEffect ( ( ) => {
101
+ let isCancelled = false ;
102
+
103
+ loadMapScript ( ) . then ( ( ) => {
104
+ if ( isCancelled ) return ;
105
+
106
+ navigator . geolocation . getCurrentPosition ( ( position ) => {
107
+ const { latitude, longitude } = position . coords ;
108
+ if ( ! isCancelled ) initializeMap ( latitude , longitude ) ;
109
+ } ) ;
110
+ } ) ;
111
+
112
+ return ( ) => {
113
+ isCancelled = true ;
114
+ } ;
115
+ } , [ location . state ] ) ;
116
+
117
+ const goBack = ( ) => {
118
+ navigate ( - 1 ) ;
119
+ } ;
120
+
121
+ return (
122
+ < div style = { { position : 'relative' , width : '100%' , height : '100vh' } } >
123
+ { modalVisible && < Modal message = { modalMessage } onClose = { ( ) => setModalVisible ( false ) } /> }
124
+ < div style = { {
125
+ position : 'absolute' ,
126
+ top : '20px' ,
127
+ right : '20px' ,
128
+ zIndex : 5 ,
129
+ backgroundColor : 'white' ,
130
+ padding : '10px' ,
131
+ borderRadius : '8px' ,
132
+ boxShadow : '0 2px 4px rgba(0,0,0,0.2)'
133
+ } } >
134
+ < div style = { { display : 'flex' , alignItems : 'center' , marginBottom : '5px' } } >
135
+ < div style = { { width : '20px' , height : '20px' , backgroundColor : 'red' , marginRight : '10px' } } > </ div >
136
+ < div > 토마토</ div >
137
+ </ div >
138
+ < div style = { { display : 'flex' , alignItems : 'center' , marginBottom : '5px' } } >
139
+ < div style = { { width : '20px' , height : '20px' , backgroundColor : 'green' , marginRight : '10px' } } > </ div >
140
+ < div > 오이</ div >
141
+ </ div >
142
+ < div style = { { display : 'flex' , alignItems : 'center' , marginBottom : '5px' } } >
143
+ < div style = { { width : '20px' , height : '20px' , backgroundColor : 'skyblue' , marginRight : '10px' } } > </ div >
144
+ < div > 고추</ div >
145
+ </ div >
146
+ < div style = { { display : 'flex' , alignItems : 'center' } } >
147
+ < div style = { { width : '20px' , height : '20px' , backgroundColor : 'black' , marginRight : '10px' } } > </ div >
148
+ < div > 딸기</ div >
149
+ </ div >
150
+ </ div >
151
+ < button onClick = { goBack } style = { {
152
+ position : 'absolute' ,
153
+ top : '20px' ,
154
+ left : '20px' ,
155
+ zIndex : 5
156
+ } } >
157
+ </ button >
158
+ < div id = "map" style = { { width : '100%' , height : '100%' } } > </ div >
159
+ </ div >
160
+ ) ;
161
+ } ;
162
+
163
+ export default MapComponent ;
0 commit comments