Merge branch 'feature/getCurAirInfo' into 'develop'
Feature/get cur air info - implement route air condition api - connect the api with client - display the route air condition result See merge request !5
Showing
2 changed files
with
259 additions
and
24 deletions
... | @@ -58,6 +58,30 @@ const getPosition = (lat, lon) => { | ... | @@ -58,6 +58,30 @@ const getPosition = (lat, lon) => { |
58 | console.log(error.response); | 58 | console.log(error.response); |
59 | }); | 59 | }); |
60 | }; | 60 | }; |
61 | +/* GET route airCondition listing. */ | ||
62 | +router.get("/route", async function (req, res, next) { | ||
63 | + console.log("출발지:", req.query.departure); | ||
64 | + console.log("도착지:", req.query.arrival); | ||
65 | + | ||
66 | + let dep = JSON.parse(req.query.departure); | ||
67 | + let depLat = dep["Ha"]; | ||
68 | + let depLon = dep["Ga"]; | ||
69 | + | ||
70 | + let arr = JSON.parse(req.query.arrival); | ||
71 | + let arrLat = arr["Ha"]; | ||
72 | + let arrLon = arr["Ga"]; | ||
73 | + let airCondition = ""; | ||
74 | + | ||
75 | + let response = await getRoute(depLat, depLon, arrLat, arrLon) | ||
76 | + .then((routeInformation) => | ||
77 | + routeAirCondition(depLat, depLon, routeInformation) | ||
78 | + ) | ||
79 | + .then((routeInformation) => { | ||
80 | + airCondition = routeInformation; | ||
81 | + }); | ||
82 | + | ||
83 | + res.send(airCondition); | ||
84 | +}); | ||
61 | 85 | ||
62 | const getCondition = (encodedStation) => { | 86 | const getCondition = (encodedStation) => { |
63 | return axios | 87 | return axios |
... | @@ -78,4 +102,70 @@ const getCondition = (encodedStation) => { | ... | @@ -78,4 +102,70 @@ const getCondition = (encodedStation) => { |
78 | }); | 102 | }); |
79 | }; | 103 | }; |
80 | 104 | ||
105 | +const getRoute = (depLat, depLon, arrLat, arrLon) => { | ||
106 | + return axios | ||
107 | + .get( | ||
108 | + "https://maps.googleapis.com/maps/api/directions/json?origin=" + | ||
109 | + depLat + | ||
110 | + "," + | ||
111 | + depLon + | ||
112 | + "&destination=" + | ||
113 | + arrLat + | ||
114 | + "," + | ||
115 | + arrLon + | ||
116 | + "&mode=transit&departure_time=now&key=" + | ||
117 | + googleMapKey + | ||
118 | + "&language=ko" | ||
119 | + ) | ||
120 | + .then(function (response) { | ||
121 | + console.log(response["data"]); | ||
122 | + let routeInformation = []; | ||
123 | + for ( | ||
124 | + let i = 0; | ||
125 | + i < response["data"].routes[0]["legs"][0]["steps"].length; | ||
126 | + i++ | ||
127 | + ) { | ||
128 | + let info = {}; | ||
129 | + info["instruction"] = | ||
130 | + response["data"].routes[0]["legs"][0]["steps"][i][ | ||
131 | + "html_instructions" | ||
132 | + ]; | ||
133 | + info["location"] = | ||
134 | + response["data"].routes[0]["legs"][0]["steps"][i]["end_location"]; | ||
135 | + info["duration"] = | ||
136 | + response["data"].routes[0]["legs"][0]["steps"][i]["duration"]["text"]; | ||
137 | + info["travel_mode"] = | ||
138 | + response["data"].routes[0]["legs"][0]["steps"][i]["travel_mode"]; | ||
139 | + routeInformation.push(info); | ||
140 | + } | ||
141 | + // console.log(routeInformation); | ||
142 | + return routeInformation; | ||
143 | + }) | ||
144 | + .catch(function (error) { | ||
145 | + console.log(error.response); | ||
146 | + }); | ||
147 | +}; | ||
148 | + | ||
149 | +const routeAirCondition = async (depLat, depLon, routeInformation) => { | ||
150 | + await getPosition(depLat, depLon) | ||
151 | + .then((encodedStation) => getCondition(encodedStation)) | ||
152 | + .then((result) => { | ||
153 | + let info = {}; | ||
154 | + info["airCondition"] = result; | ||
155 | + routeInformation.push(info); | ||
156 | + }); | ||
157 | + for (let i = 0; i < routeInformation.length - 1; i++) { | ||
158 | + await getPosition( | ||
159 | + routeInformation[i]["location"]["lat"], | ||
160 | + routeInformation[i]["location"]["lng"] | ||
161 | + ) | ||
162 | + .then((encodedStation) => getCondition(encodedStation)) | ||
163 | + .then((result) => { | ||
164 | + routeInformation[i]["airCondition"] = result; | ||
165 | + }); | ||
166 | + } | ||
167 | + console.log(routeInformation); | ||
168 | + return routeInformation; | ||
169 | +}; | ||
170 | + | ||
81 | module.exports = router; | 171 | module.exports = router; | ... | ... |
... | @@ -11,7 +11,9 @@ import good from "./gradeIcon/smile.png"; | ... | @@ -11,7 +11,9 @@ import good from "./gradeIcon/smile.png"; |
11 | import bad from "./gradeIcon/angry.png"; | 11 | import bad from "./gradeIcon/angry.png"; |
12 | import veryBad from "./gradeIcon/devil.png"; | 12 | import veryBad from "./gradeIcon/devil.png"; |
13 | import next from "./gradeIcon/next.png"; | 13 | import next from "./gradeIcon/next.png"; |
14 | - | 14 | +import start from "./gradeIcon/start.png"; |
15 | +import finish from "./gradeIcon/finish.png"; | ||
16 | +import loading from "./gradeIcon/loading.gif"; | ||
15 | /* global kakao */ | 17 | /* global kakao */ |
16 | 18 | ||
17 | export default class Home extends Component { | 19 | export default class Home extends Component { |
... | @@ -28,30 +30,27 @@ export default class Home extends Component { | ... | @@ -28,30 +30,27 @@ export default class Home extends Component { |
28 | infoWindow: new kakao.maps.CustomOverlay({}), | 30 | infoWindow: new kakao.maps.CustomOverlay({}), |
29 | region: "은평구청", | 31 | region: "은평구청", |
30 | curAirCondition: null, | 32 | curAirCondition: null, |
31 | - | 33 | + routeInformation: null, |
32 | - // curAirCondition: null, | ||
33 | - // routeInformation: null, | ||
34 | }; | 34 | }; |
35 | - this.removeAllChildNods = this.removeAllChildNods.bind(this); | ||
36 | - this.displayInfowindow = this.displayInfowindow.bind(this); | ||
37 | } | 35 | } |
38 | 36 | ||
39 | - searchPlaces() { | 37 | + searchPlaces = () => { |
40 | var keyword = document.getElementById("keyword").value; | 38 | var keyword = document.getElementById("keyword").value; |
41 | 39 | ||
42 | if (!keyword.replace(/^\s+|\s+$/g, "")) { | 40 | if (!keyword.replace(/^\s+|\s+$/g, "")) { |
43 | alert("키워드를 입력해주세요!"); | 41 | alert("키워드를 입력해주세요!"); |
44 | return false; | 42 | return false; |
45 | } | 43 | } |
44 | + | ||
46 | // 장소검색 객체를 통해 키워드로 장소검색을 요청합니다 | 45 | // 장소검색 객체를 통해 키워드로 장소검색을 요청합니다 |
47 | this.state.placeSearch.keywordSearch( | 46 | this.state.placeSearch.keywordSearch( |
48 | keyword, | 47 | keyword, |
49 | this.placesSearchCB.bind(this) | 48 | this.placesSearchCB.bind(this) |
50 | ); | 49 | ); |
51 | - } | 50 | + }; |
52 | 51 | ||
53 | // 장소검색이 완료됐을 때 호출되는 콜백함수 입니다 | 52 | // 장소검색이 완료됐을 때 호출되는 콜백함수 입니다 |
54 | - placesSearchCB(data, status, pagination) { | 53 | + placesSearchCB = (data, status, pagination) => { |
55 | if (status === kakao.maps.services.Status.OK) { | 54 | if (status === kakao.maps.services.Status.OK) { |
56 | // 정상적으로 검색이 완료됐으면 | 55 | // 정상적으로 검색이 완료됐으면 |
57 | // 검색 목록과 마커를 표출합니다 | 56 | // 검색 목록과 마커를 표출합니다 |
... | @@ -66,9 +65,9 @@ export default class Home extends Component { | ... | @@ -66,9 +65,9 @@ export default class Home extends Component { |
66 | alert("검색 결과 중 오류가 발생했습니다."); | 65 | alert("검색 결과 중 오류가 발생했습니다."); |
67 | return; | 66 | return; |
68 | } | 67 | } |
69 | - } | 68 | + }; |
70 | 69 | ||
71 | - displayPlaces(places) { | 70 | + displayPlaces = (places) => { |
72 | var listEl = document.getElementById("placesList"), | 71 | var listEl = document.getElementById("placesList"), |
73 | menuEl = document.getElementById("menu_wrap"), | 72 | menuEl = document.getElementById("menu_wrap"), |
74 | fragment = document.createDocumentFragment(), | 73 | fragment = document.createDocumentFragment(), |
... | @@ -118,13 +117,13 @@ export default class Home extends Component { | ... | @@ -118,13 +117,13 @@ export default class Home extends Component { |
118 | 117 | ||
119 | // 검색된 장소 위치를 기준으로 지도 범위를 재설정합니다 | 118 | // 검색된 장소 위치를 기준으로 지도 범위를 재설정합니다 |
120 | this.state.map.setBounds(bounds); | 119 | this.state.map.setBounds(bounds); |
121 | - } | 120 | + }; |
122 | // 커스텀 오버레이를 닫기 위해 호출되는 함수입니다 | 121 | // 커스텀 오버레이를 닫기 위해 호출되는 함수입니다 |
123 | - closeOverlay() { | 122 | + closeOverlay = () => { |
124 | this.state.infoWindow.setMap(null); | 123 | this.state.infoWindow.setMap(null); |
125 | - } | 124 | + }; |
126 | 125 | ||
127 | - getListItem(index, places) { | 126 | + getListItem = (index, places) => { |
128 | var el = document.createElement("li"), | 127 | var el = document.createElement("li"), |
129 | itemStr = | 128 | itemStr = |
130 | '<span class="markerbg marker_' + | 129 | '<span class="markerbg marker_' + |
... | @@ -153,9 +152,33 @@ export default class Home extends Component { | ... | @@ -153,9 +152,33 @@ export default class Home extends Component { |
153 | el.className = "item"; | 152 | el.className = "item"; |
154 | 153 | ||
155 | return el; | 154 | return el; |
156 | - } | 155 | + }; |
157 | 156 | ||
158 | - addMarker(position, idx, title) { | 157 | + getRouteAirCondition = () => { |
158 | + this.setState({ | ||
159 | + buttonClicked: true, | ||
160 | + }); | ||
161 | + API.get("/airCondition/route", { | ||
162 | + params: { | ||
163 | + departure: this.state.departure, | ||
164 | + arrival: this.state.arrival, | ||
165 | + }, | ||
166 | + }) | ||
167 | + .then((response) => { | ||
168 | + this.setState({ | ||
169 | + routeInformation: response.data, | ||
170 | + }); | ||
171 | + console.log(this.state.routeInformation); | ||
172 | + }) | ||
173 | + .catch(function (error) { | ||
174 | + console.log(error); | ||
175 | + }) | ||
176 | + .finally(function () { | ||
177 | + // always executed | ||
178 | + }); | ||
179 | + }; | ||
180 | + | ||
181 | + addMarker = (position, idx, title) => { | ||
159 | var imageSrc = | 182 | var imageSrc = |
160 | "http://t1.daumcdn.net/localimg/localimages/07/mapapidoc/marker_number_blue.png", // 마커 이미지 url, 스프라이트 이미지를 씁니다 | 183 | "http://t1.daumcdn.net/localimg/localimages/07/mapapidoc/marker_number_blue.png", // 마커 이미지 url, 스프라이트 이미지를 씁니다 |
161 | imageSize = new kakao.maps.Size(36, 37), // 마커 이미지의 크기 | 184 | imageSize = new kakao.maps.Size(36, 37), // 마커 이미지의 크기 |
... | @@ -175,20 +198,20 @@ export default class Home extends Component { | ... | @@ -175,20 +198,20 @@ export default class Home extends Component { |
175 | this.state.markers.push(marker); // 배열에 생성된 마커를 추가합니다 | 198 | this.state.markers.push(marker); // 배열에 생성된 마커를 추가합니다 |
176 | 199 | ||
177 | return marker; | 200 | return marker; |
178 | - } | 201 | + }; |
179 | 202 | ||
180 | // 지도 위에 표시되고 있는 마커를 모두 제거합니다 | 203 | // 지도 위에 표시되고 있는 마커를 모두 제거합니다 |
181 | - removeMarker() { | 204 | + removeMarker = () => { |
182 | for (var i = 0; i < this.state.markers.length; i++) { | 205 | for (var i = 0; i < this.state.markers.length; i++) { |
183 | this.state.markers[i].setMap(null); | 206 | this.state.markers[i].setMap(null); |
184 | } | 207 | } |
185 | this.setState({ | 208 | this.setState({ |
186 | markers: [], | 209 | markers: [], |
187 | }); | 210 | }); |
188 | - } | 211 | + }; |
189 | 212 | ||
190 | // 검색결과 목록 하단에 페이지번호를 표시는 함수입니다 | 213 | // 검색결과 목록 하단에 페이지번호를 표시는 함수입니다 |
191 | - displayPagination(pagination) { | 214 | + displayPagination = (pagination) => { |
192 | var paginationEl = document.getElementById("pagination"), | 215 | var paginationEl = document.getElementById("pagination"), |
193 | fragment = document.createDocumentFragment(), | 216 | fragment = document.createDocumentFragment(), |
194 | i; | 217 | i; |
... | @@ -216,7 +239,7 @@ export default class Home extends Component { | ... | @@ -216,7 +239,7 @@ export default class Home extends Component { |
216 | fragment.appendChild(el); | 239 | fragment.appendChild(el); |
217 | } | 240 | } |
218 | paginationEl.appendChild(fragment); | 241 | paginationEl.appendChild(fragment); |
219 | - } | 242 | + }; |
220 | 243 | ||
221 | removeAllChildNods(el) { | 244 | removeAllChildNods(el) { |
222 | while (el.hasChildNodes()) { | 245 | while (el.hasChildNodes()) { |
... | @@ -226,7 +249,7 @@ export default class Home extends Component { | ... | @@ -226,7 +249,7 @@ export default class Home extends Component { |
226 | 249 | ||
227 | // 검색결과 목록 또는 마커를 클릭했을 때 호출되는 함수입니다 | 250 | // 검색결과 목록 또는 마커를 클릭했을 때 호출되는 함수입니다 |
228 | // 인포윈도우에 장소명을 표시합니다 | 251 | // 인포윈도우에 장소명을 표시합니다 |
229 | - displayInfowindow(marker, title) { | 252 | + displayInfowindow = (marker, title) => { |
230 | console.log(marker); | 253 | console.log(marker); |
231 | 254 | ||
232 | let content = document.createElement("div"); | 255 | let content = document.createElement("div"); |
... | @@ -316,7 +339,7 @@ export default class Home extends Component { | ... | @@ -316,7 +339,7 @@ export default class Home extends Component { |
316 | this.state.infoWindow.setContent(content); | 339 | this.state.infoWindow.setContent(content); |
317 | this.state.infoWindow.setPosition(marker.getPosition()); | 340 | this.state.infoWindow.setPosition(marker.getPosition()); |
318 | this.state.infoWindow.setMap(this.state.map); | 341 | this.state.infoWindow.setMap(this.state.map); |
319 | - } | 342 | + }; |
320 | 343 | ||
321 | componentDidMount() { | 344 | componentDidMount() { |
322 | // 컴포넌트가 만들어지고, render 함수가 호출된 이후에 호출되는 메소 | 345 | // 컴포넌트가 만들어지고, render 함수가 호출된 이후에 호출되는 메소 |
... | @@ -382,6 +405,128 @@ export default class Home extends Component { | ... | @@ -382,6 +405,128 @@ export default class Home extends Component { |
382 | ); | 405 | ); |
383 | } | 406 | } |
384 | let routeAirCondition = null; | 407 | let routeAirCondition = null; |
408 | + let tempRouteAirCondition = []; | ||
409 | + if (this.state.buttonClicked != null) { | ||
410 | + routeAirCondition = <img src={loading} width="300px" heigth="300px" />; | ||
411 | + } | ||
412 | + if (this.state.routeInformation != null) { | ||
413 | + for (let i = 0; i < this.state.routeInformation.length - 1; i++) { | ||
414 | + tempRouteAirCondition.push(this.state.routeInformation[i]); | ||
415 | + } | ||
416 | + let pm10ImageArray = new Array(); | ||
417 | + let pm25ImageArray = new Array(); | ||
418 | + for (let i = 0; i < this.state.routeInformation.length; i++) { | ||
419 | + let pm10Image = null; | ||
420 | + let pm25Image = null; | ||
421 | + switch (this.state.routeInformation[i]["airCondition"].pm10Grade) { | ||
422 | + case "1": | ||
423 | + pm10Image = <img src={veryGood} width="50px" heigth="100px" />; | ||
424 | + break; | ||
425 | + case "2": | ||
426 | + pm10Image = <img src={good} width="50px" heigth="100px" />; | ||
427 | + break; | ||
428 | + case "3": | ||
429 | + pm10Image = <img src={bad} width="50px" heigth="100px" />; | ||
430 | + break; | ||
431 | + case "4": | ||
432 | + pm10Image = <img src={veryBad} width="50px" heigth="100px" />; | ||
433 | + break; | ||
434 | + default: | ||
435 | + pm10Image = null; | ||
436 | + } | ||
437 | + switch (this.state.routeInformation[i]["airCondition"].pm25Grade) { | ||
438 | + case "1": | ||
439 | + pm25Image = <img src={veryGood} width="50px" heigth="100px" />; | ||
440 | + break; | ||
441 | + case "2": | ||
442 | + pm25Image = <img src={good} width="50px" heigth="100px" />; | ||
443 | + break; | ||
444 | + case "3": | ||
445 | + pm25Image = <img src={bad} width="50px" heigth="100px" />; | ||
446 | + break; | ||
447 | + case "4": | ||
448 | + pm25Image = <img src={veryBad} width="50px" heigth="100px" />; | ||
449 | + break; | ||
450 | + default: | ||
451 | + pm25Image = null; | ||
452 | + } | ||
453 | + pm10ImageArray[i] = pm10Image; | ||
454 | + pm25ImageArray[i] = pm25Image; | ||
455 | + } | ||
456 | + routeAirCondition = ( | ||
457 | + <table> | ||
458 | + <thead> | ||
459 | + <tr> | ||
460 | + <th> | ||
461 | + <br /> | ||
462 | + 경로별 미세먼지 정보 | ||
463 | + </th> | ||
464 | + </tr> | ||
465 | + </thead> | ||
466 | + <tbody> | ||
467 | + <tr> | ||
468 | + <td> | ||
469 | + <img src={start} width="50px" heigth="30px" /> <br /> | ||
470 | + <h6> | ||
471 | + {this.state.departureTitle} <br /> 미세먼지 등급 | ||
472 | + <br /> | ||
473 | + {pm10ImageArray[this.state.routeInformation.length - 1]} | ||
474 | + <br /> | ||
475 | + 미세먼지 지수 :{" "} | ||
476 | + { | ||
477 | + this.state.routeInformation[ | ||
478 | + this.state.routeInformation.length - 1 | ||
479 | + ]["airCondition"].pm10Value | ||
480 | + } | ||
481 | + <br /> | ||
482 | + </h6> | ||
483 | + </td> | ||
484 | + {tempRouteAirCondition.map((listValue, index) => { | ||
485 | + if (index != tempRouteAirCondition.length - 1) { | ||
486 | + return ( | ||
487 | + <td key={index}> | ||
488 | + <img src={next} width="40px" heigth="25px" /> | ||
489 | + <h6> | ||
490 | + {listValue.instruction} | ||
491 | + <br /> | ||
492 | + 소요시간 : {listValue.duration} | ||
493 | + <br /> | ||
494 | + 미세먼지 등급 | ||
495 | + <br /> | ||
496 | + {pm10ImageArray[index]} | ||
497 | + <br /> | ||
498 | + 미세먼지 지수 : <br /> | ||
499 | + {listValue.airCondition.pm10Value} | ||
500 | + <br /> | ||
501 | + </h6> | ||
502 | + </td> | ||
503 | + ); | ||
504 | + } else { | ||
505 | + return ( | ||
506 | + <td key={index}> | ||
507 | + <img src={finish} width="50px" heigth="30px" /> | ||
508 | + <br /> | ||
509 | + <h6> | ||
510 | + {listValue.instruction} | ||
511 | + <br /> | ||
512 | + 소요시간 : {listValue.duration} | ||
513 | + <br /> | ||
514 | + 미세먼지 등급 | ||
515 | + <br /> | ||
516 | + {pm10ImageArray[index]} | ||
517 | + <br /> | ||
518 | + 미세먼지 지수 : {listValue.airCondition.pm10Value} | ||
519 | + <br /> | ||
520 | + </h6> | ||
521 | + </td> | ||
522 | + ); | ||
523 | + } | ||
524 | + })} | ||
525 | + </tr> | ||
526 | + </tbody> | ||
527 | + </table> | ||
528 | + ); | ||
529 | + } | ||
385 | 530 | ||
386 | return ( | 531 | return ( |
387 | <section id="home"> | 532 | <section id="home"> | ... | ... |
-
Please register or login to post a comment