이선호

Theme show the map and list

...@@ -14,6 +14,7 @@ passport.use( ...@@ -14,6 +14,7 @@ passport.use(
14 if (err) return res.status(400).send("카카오 로그인 에러"); 14 if (err) return res.status(400).send("카카오 로그인 에러");
15 else if (user) { 15 else if (user) {
16 id = profile.id; 16 id = profile.id;
17 +
17 return done(null, user); 18 return done(null, user);
18 } else { 19 } else {
19 const new_user = new User({ 20 const new_user = new User({
......
1 +.map_wrap,
2 +.map_wrap * {
3 + margin: 0;
4 + padding: 0;
5 + font-family: "Malgun Gothic", dotum, "돋움", sans-serif;
6 + font-size: 12px;
7 +}
8 +.map_wrap a,
9 +.map_wrap a:hover,
10 +.map_wrap a:active {
11 + color: #000;
12 + text-decoration: none;
13 +}
14 +.map_wrap {
15 + position: absolute;
16 + bottom: 00px;
17 + width: 100%;
18 + height: 500px;
19 +}
20 +#menu_wrap {
21 + position: absolute;
22 + top: 0;
23 + left: 0;
24 + bottom: 0;
25 + width: 250px;
26 + margin: 10px 0 30px 10px;
27 + padding: 5px;
28 + overflow-y: auto;
29 + background: rgba(255, 255, 255, 0.7);
30 + z-index: 1;
31 + font-size: 12px;
32 + border-radius: 10px;
33 +}
34 +.bg_white {
35 + background: #fff;
36 +}
37 +#menu_wrap hr {
38 + display: block;
39 + height: 1px;
40 + border: 0;
41 + border-top: 2px solid #5f5f5f;
42 + margin: 3px 0;
43 +}
44 +#menu_wrap .option {
45 + text-align: center;
46 +}
47 +#menu_wrap .option p {
48 + margin: 10px 0;
49 +}
50 +#menu_wrap .option button {
51 + margin-left: 5px;
52 +}
53 +#placesList li {
54 + list-style: none;
55 +}
56 +#placesList .item {
57 + position: relative;
58 + border-bottom: 1px solid #888;
59 + overflow: hidden;
60 + cursor: pointer;
61 + min-height: 65px;
62 +}
63 +#placesList .item span {
64 + display: block;
65 + margin-top: 4px;
66 +}
67 +#placesList .item h5,
68 +#placesList .item .info {
69 + text-overflow: ellipsis;
70 + overflow: hidden;
71 + white-space: nowrap;
72 +}
73 +#placesList .item .info {
74 + padding: 10px 0 10px 55px;
75 +}
76 +#placesList .info .gray {
77 + color: #8a8a8a;
78 +}
79 +#placesList .info .jibun {
80 + padding-left: 26px;
81 + background: url(https://t1.daumcdn.net/localimg/localimages/07/mapapidoc/places_jibun.png)
82 + no-repeat;
83 +}
84 +#placesList .info .tel {
85 + color: #009900;
86 +}
87 +#placesList .item .markerbg {
88 + float: left;
89 + position: absolute;
90 + width: 36px;
91 + height: 37px;
92 + margin: 10px 0 0 10px;
93 + background: url(https://t1.daumcdn.net/localimg/localimages/07/mapapidoc/marker_number_blue.png)
94 + no-repeat;
95 +}
96 +#placesList .item .marker_1 {
97 + background-position: 0 -10px;
98 +}
99 +#placesList .item .marker_2 {
100 + background-position: 0 -56px;
101 +}
102 +#placesList .item .marker_3 {
103 + background-position: 0 -102px;
104 +}
105 +#placesList .item .marker_4 {
106 + background-position: 0 -148px;
107 +}
108 +#placesList .item .marker_5 {
109 + background-position: 0 -194px;
110 +}
111 +#placesList .item .marker_6 {
112 + background-position: 0 -240px;
113 +}
114 +#placesList .item .marker_7 {
115 + background-position: 0 -286px;
116 +}
117 +#placesList .item .marker_8 {
118 + background-position: 0 -332px;
119 +}
120 +#placesList .item .marker_9 {
121 + background-position: 0 -378px;
122 +}
123 +#placesList .item .marker_10 {
124 + background-position: 0 -423px;
125 +}
126 +#placesList .item .marker_11 {
127 + background-position: 0 -470px;
128 +}
129 +#placesList .item .marker_12 {
130 + background-position: 0 -516px;
131 +}
132 +#placesList .item .marker_13 {
133 + background-position: 0 -562px;
134 +}
135 +#placesList .item .marker_14 {
136 + background-position: 0 -608px;
137 +}
138 +#placesList .item .marker_15 {
139 + background-position: 0 -654px;
140 +}
141 +#pagination {
142 + margin: 10px auto;
143 + text-align: center;
144 +}
145 +#pagination a {
146 + display: inline-block;
147 + margin-right: 10px;
148 +}
149 +#pagination .on {
150 + font-weight: bold;
151 + cursor: default;
152 + color: #777;
153 +}
...@@ -20,7 +20,7 @@ passport.deserializeUser((req, user, done) => { ...@@ -20,7 +20,7 @@ passport.deserializeUser((req, user, done) => {
20 router.get("/login/kakao", passport.authenticate("kakao")); 20 router.get("/login/kakao", passport.authenticate("kakao"));
21 router.get( 21 router.get(
22 "/login/kakao/callback", 22 "/login/kakao/callback",
23 - passport.authenticate("kakao", { failureRedirect: "/auth/login" }), 23 + passport.authenticate("kakao", { failureRedirect: "/" }),
24 function (req, res) { 24 function (req, res) {
25 console.log("successlogin"); 25 console.log("successlogin");
26 res.render("users"); 26 res.render("users");
......
...@@ -10,9 +10,11 @@ ...@@ -10,9 +10,11 @@
10 10
11 <script src="/bootstraps/js/bootstrap.min.js"></script> 11 <script src="/bootstraps/js/bootstrap.min.js"></script>
12 <link rel="stylesheet" type="text/css" href="/css/find.css"> 12 <link rel="stylesheet" type="text/css" href="/css/find.css">
13 + <link rel="stylesheet" type="text/css" href="/css/map.css"/>
13 14
14 <link rel="stylesheet" type="text/css" href="/bootstraps/css/bootstrap.min.css"/> 15 <link rel="stylesheet" type="text/css" href="/bootstraps/css/bootstrap.min.css"/>
15 <script src="/javascript/search.js"></script> 16 <script src="/javascript/search.js"></script>
17 +
16 <title>FoodFight</title> 18 <title>FoodFight</title>
17 </head> 19 </head>
18 <body> 20 <body>
...@@ -23,13 +25,30 @@ ...@@ -23,13 +25,30 @@
23 </div> 25 </div>
24 </nav> 26 </nav>
25 <form class="input-group" method="post" action="/foodtravel"> 27 <form class="input-group" method="post" action="/foodtravel">
26 - <input type="text" id="myInput" name='user_place' class="form-control" placeholder="오늘의 목적지를 입력하세요!" > 28 + <input type="text" id="myInput" class="form-control" placeholder="오늘의 목적지를 입력하세요!" name='user_place'>
27 <span class="input-group-btn"> 29 <span class="input-group-btn">
28 <button class="btn btn-secondary" type="submit">찾기</button> 30 <button class="btn btn-secondary" type="submit">찾기</button>
29 </span> 31 </span>
30 </form> 32 </form>
31 - 33 + <div class="map_wrap">
32 - <script> 34 + <div id="map" style="width:100%;height:100%;"></div>
35 +
36 + <div id="menu_wrap" class="bg_white">
37 + <div class="option">
38 + <div>
39 + <form onsubmit="searchPlaces(); return false;">
40 + 키워드 : <input type="text" value="맛집" id="keyword" size="15">
41 + <button type="submit">검색하기</button>
42 + </form>
43 + </div>
44 + </div>
45 + <hr>
46 + <ul id="placesList"></ul>
47 + <div id="pagination"></div>
48 + </div>
49 + </div>
50 + <script type="text/javascript" src="//dapi.kakao.com/v2/maps/sdk.js?appkey=23f90b23f8f678caad181fbb316393fc&libraries=services,clusterer"></script>
51 + <script>
33 52
34 $(function () { //화면 로딩후 시작 53 $(function () { //화면 로딩후 시작
35 $("#myInput").autocomplete({ //오토 컴플릿트 시작 54 $("#myInput").autocomplete({ //오토 컴플릿트 시작
...@@ -42,8 +61,226 @@ ...@@ -42,8 +61,226 @@
42 position:{my :'right top', at:'right bottom'} 61 position:{my :'right top', at:'right bottom'}
43 }); 62 });
44 }); 63 });
45 - 64 +
46 - </script> 65 + </script>
66 + <script>
67 + var markers = [];
68 +
69 + var mapContainer = document.getElementById('map'), // 지도를 표시할 div
70 + mapOption = {
71 + center: new kakao.maps.LatLng(37.566826, 126.9786567), // 지도의 중심좌표
72 + level: 3 // 지도의 확대 레벨
73 + };
74 +
75 + // 지도를 생성합니다
76 + var map = new kakao.maps.Map(mapContainer, mapOption);
77 +
78 + // 장소 검색 객체를 생성합니다
79 + var ps = new kakao.maps.services.Places();
80 +
81 + // 검색 결과 목록이나 마커를 클릭했을 때 장소명을 표출할 인포윈도우를 생성합니다
82 + var infowindow = new kakao.maps.InfoWindow({zIndex:1});
83 +
84 + // 키워드로 장소를 검색합니다
85 + searchPlaces();
86 +
87 + // 키워드 검색을 요청하는 함수입니다
88 + function searchPlaces() {
89 +
90 + var keyword = document.getElementById('keyword').value;
91 +
92 + if (!keyword.replace(/^\s+|\s+$/g, '')) {
93 + alert('키워드를 입력해주세요!');
94 + return false;
95 + }
96 +
97 + // 장소검색 객체를 통해 키워드로 장소검색을 요청합니다
98 + ps.keywordSearch( keyword, placesSearchCB);
99 + }
100 +
101 + // 장소검색이 완료됐을 때 호출되는 콜백함수 입니다
102 + function placesSearchCB(data, status, pagination) {
103 + if (status === kakao.maps.services.Status.OK) {
104 +
105 + // 정상적으로 검색이 완료됐으면
106 + // 검색 목록과 마커를 표출합니다
107 + displayPlaces(data);
108 +
109 + // 페이지 번호를 표출합니다
110 + displayPagination(pagination);
111 +
112 + } else if (status === kakao.maps.services.Status.ZERO_RESULT) {
113 +
114 + alert('검색 결과가 존재하지 않습니다.');
115 + return;
116 +
117 + } else if (status === kakao.maps.services.Status.ERROR) {
118 +
119 + alert('검색 결과 중 오류가 발생했습니다.');
120 + return;
121 +
122 + }
123 + }
124 +
125 + // 검색 결과 목록과 마커를 표출하는 함수입니다
126 + function displayPlaces(places) {
127 +
128 + var listEl = document.getElementById('placesList'),
129 + menuEl = document.getElementById('menu_wrap'),
130 + fragment = document.createDocumentFragment(),
131 + bounds = new kakao.maps.LatLngBounds(),
132 + listStr = '';
133 +
134 + // 검색 결과 목록에 추가된 항목들을 제거합니다
135 + removeAllChildNods(listEl);
136 +
137 + // 지도에 표시되고 있는 마커를 제거합니다
138 + removeMarker();
139 +
140 + for ( var i=0; i<places.length; i++ ) {
141 +
142 + // 마커를 생성하고 지도에 표시합니다
143 + var placePosition = new kakao.maps.LatLng(places[i].y, places[i].x),
144 + marker = addMarker(placePosition, i),
145 + itemEl = getListItem(i, places[i]); // 검색 결과 항목 Element를 생성합니다
146 +
147 + // 검색된 장소 위치를 기준으로 지도 범위를 재설정하기위해
148 + // LatLngBounds 객체에 좌표를 추가합니다
149 + bounds.extend(placePosition);
150 +
151 + // 마커와 검색결과 항목에 mouseover 했을때
152 + // 해당 장소에 인포윈도우에 장소명을 표시합니다
153 + // mouseout 했을 때는 인포윈도우를 닫습니다
154 + (function(marker, title) {
155 + kakao.maps.event.addListener(marker, 'mouseover', function() {
156 + displayInfowindow(marker, title);
157 + });
158 +
159 + kakao.maps.event.addListener(marker, 'mouseout', function() {
160 + infowindow.close();
161 + });
162 +
163 + itemEl.onmouseover = function () {
164 + displayInfowindow(marker, title);
165 + };
166 +
167 + itemEl.onmouseout = function () {
168 + infowindow.close();
169 + };
170 + })(marker, places[i].place_name);
171 +
172 + fragment.appendChild(itemEl);
173 + }
174 +
175 + // 검색결과 항목들을 검색결과 목록 Elemnet에 추가합니다
176 + listEl.appendChild(fragment);
177 + menuEl.scrollTop = 0;
178 +
179 + // 검색된 장소 위치를 기준으로 지도 범위를 재설정합니다
180 + map.setBounds(bounds);
181 + }
182 +
183 + // 검색결과 항목을 Element로 반환하는 함수입니다
184 + function getListItem(index, places) {
185 +
186 + var el = document.createElement('li'),
187 + itemStr = '<span class="markerbg marker_' + (index+1) + '"></span>' +
188 + '<div class="info">' +
189 + ' <h5>' + places.place_name + '</h5>';
190 +
191 + if (places.road_address_name) {
192 + itemStr += ' <span>' + places.road_address_name + '</span>' +
193 + ' <span class="jibun gray">' + places.address_name + '</span>';
194 + } else {
195 + itemStr += ' <span>' + places.address_name + '</span>';
196 + }
197 +
198 + itemStr += ' <span class="tel">' + places.phone + '</span>' +
199 + '</div>';
200 +
201 + el.innerHTML = itemStr;
202 + el.className = 'item';
203 +
204 + return el;
205 + }
206 +
207 + // 마커를 생성하고 지도 위에 마커를 표시하는 함수입니다
208 + function addMarker(position, idx, title) {
209 + var imageSrc = 'https://t1.daumcdn.net/localimg/localimages/07/mapapidoc/marker_number_blue.png', // 마커 이미지 url, 스프라이트 이미지를 씁니다
210 + imageSize = new kakao.maps.Size(36, 37), // 마커 이미지의 크기
211 + imgOptions = {
212 + spriteSize : new kakao.maps.Size(36, 691), // 스프라이트 이미지의 크기
213 + spriteOrigin : new kakao.maps.Point(0, (idx*46)+10), // 스프라이트 이미지 중 사용할 영역의 좌상단 좌표
214 + offset: new kakao.maps.Point(13, 37) // 마커 좌표에 일치시킬 이미지 내에서의 좌표
215 + },
216 + markerImage = new kakao.maps.MarkerImage(imageSrc, imageSize, imgOptions),
217 + marker = new kakao.maps.Marker({
218 + position: position, // 마커의 위치
219 + image: markerImage
220 + });
221 +
222 + marker.setMap(map); // 지도 위에 마커를 표출합니다
223 + markers.push(marker); // 배열에 생성된 마커를 추가합니다
224 +
225 + return marker;
226 + }
227 +
228 + // 지도 위에 표시되고 있는 마커를 모두 제거합니다
229 + function removeMarker() {
230 + for ( var i = 0; i < markers.length; i++ ) {
231 + markers[i].setMap(null);
232 + }
233 + markers = [];
234 + }
235 +
236 + // 검색결과 목록 하단에 페이지번호를 표시는 함수입니다
237 + function displayPagination(pagination) {
238 + var paginationEl = document.getElementById('pagination'),
239 + fragment = document.createDocumentFragment(),
240 + i;
241 +
242 + // 기존에 추가된 페이지번호를 삭제합니다
243 + while (paginationEl.hasChildNodes()) {
244 + paginationEl.removeChild (paginationEl.lastChild);
245 + }
246 +
247 + for (i=1; i<=pagination.last; i++) {
248 + var el = document.createElement('a');
249 + el.href = "#";
250 + el.innerHTML = i;
251 +
252 + if (i===pagination.current) {
253 + el.className = 'on';
254 + } else {
255 + el.onclick = (function(i) {
256 + return function() {
257 + pagination.gotoPage(i);
258 + }
259 + })(i);
260 + }
261 +
262 + fragment.appendChild(el);
263 + }
264 + paginationEl.appendChild(fragment);
265 + }
266 +
267 + // 검색결과 목록 또는 마커를 클릭했을 때 호출되는 함수입니다
268 + // 인포윈도우에 장소명을 표시합니다
269 + function displayInfowindow(marker, title) {
270 + var content = '<div style="padding:5px;z-index:1;">' + title + '</div>';
271 +
272 + infowindow.setContent(content);
273 + infowindow.open(map, marker);
274 + }
275 +
276 + // 검색결과 목록의 자식 Element를 제거하는 함수입니다
277 + function removeAllChildNods(el) {
278 + while (el.hasChildNodes()) {
279 + el.removeChild (el.lastChild);
280 + }
281 + }
282 + </script>
283 +
47 284
48 285
49 </body> 286 </body>
......
...@@ -11,7 +11,7 @@ ...@@ -11,7 +11,7 @@
11 <script src="/bootstraps/js/bootstrap.min.js"></script> 11 <script src="/bootstraps/js/bootstrap.min.js"></script>
12 12
13 <link rel="stylesheet" type="text/css" href="/bootstraps/css/bootstrap.min.css"/> 13 <link rel="stylesheet" type="text/css" href="/bootstraps/css/bootstrap.min.css"/>
14 - <script src="../routes/auth.js"></script> 14 + <!-- <script src="../routes/auth.js"></script> -->
15 <style> 15 <style>
16 .hide{ 16 .hide{
17 display: none; 17 display: none;
...@@ -35,11 +35,11 @@ ...@@ -35,11 +35,11 @@
35 35
36 <button type="button" id="start">What 2 Do</button> 36 <button type="button" id="start">What 2 Do</button>
37 37
38 - 38 +
39 <div class="container hide"> 39 <div class="container hide">
40 <div class="page-header"><h1 style="color: cadetblue;">추천테마</h1></div> 40 <div class="page-header"><h1 style="color: cadetblue;">추천테마</h1></div>
41 <div class="container-fluid"> 41 <div class="container-fluid">
42 - 42 +
43 <div class="row gy-4 mt-5 justify-content-center" > 43 <div class="row gy-4 mt-5 justify-content-center" >
44 <div class="col-xl-2 col-md-4"> 44 <div class="col-xl-2 col-md-4">
45 <div class="icon-box"> 45 <div class="icon-box">
...@@ -78,20 +78,20 @@ ...@@ -78,20 +78,20 @@
78 </div> 78 </div>
79 </div> 79 </div>
80 </div> 80 </div>
81 - 81 +
82 - 82 +
83 </div> 83 </div>
84 - 84 +
85 </div> 85 </div>
86 - 86 +
87 87
88 88
89 <p> 89 <p>
90 - 90 +
91 </p> 91 </p>
92 92
93 93
94 - 94 +
95 </body> 95 </body>
96 <script> 96 <script>
97 let BTn=document.getElementById("start"); 97 let BTn=document.getElementById("start");
......