Modify front-end of Search Result:
Change Search Result Image Display (1 row to grid)
Showing
4 changed files
with
504 additions
and
42 deletions
main/index.js
0 → 100644
1 | + | ||
2 | +const express = require('express'); | ||
3 | +const session = require('express-session'); | ||
4 | +const passport = require('passport'), LocalStrategy = require('passport-local').Strategy; | ||
5 | +const fs=require('fs'); | ||
6 | +const router = express.Router() | ||
7 | +const fileStore = require('session-file-store')(session); | ||
8 | +const app = express(); | ||
9 | +var flash = require('connect-flash'); | ||
10 | +var NaverStrategy = require('passport-naver').Strategy; | ||
11 | +var KakaoStrategy = require('passport-kakao').Strategy; | ||
12 | + | ||
13 | + | ||
14 | + | ||
15 | + | ||
16 | +//Middle Ware list | ||
17 | +app.use(express.urlencoded({extended:false})); | ||
18 | +app.use(session({ | ||
19 | + secret: 'secret key', | ||
20 | + resave: false, | ||
21 | + saveUninitialized: false, | ||
22 | + store : new fileStore() | ||
23 | + })); | ||
24 | +app.use(passport.initialize()); | ||
25 | +app.use(passport.session()); | ||
26 | +app.use(flash()); | ||
27 | + | ||
28 | + | ||
29 | + | ||
30 | +//사용자 정보 세션 읽기, 쓰기 | ||
31 | +passport.serializeUser(function(user, done) { //쓰기 | ||
32 | + done(null, user.email); | ||
33 | +}); | ||
34 | + | ||
35 | +passport.deserializeUser(function(id, done) { //읽기 | ||
36 | + done(null, id); | ||
37 | +}); | ||
38 | + | ||
39 | +//첫 페이지 | ||
40 | +app.get('/',(req,res)=>{ | ||
41 | + let page = getFirstPage('Passport','This is Passport Example Page',authInfo(req)); | ||
42 | + res.send(page); | ||
43 | +}); | ||
44 | + | ||
45 | +//메인 페이지 | ||
46 | +//Express에서 정적파일(ex: main.html, main.js)들을 사용할경우 | ||
47 | +//경로를 미리 제시해 주는 부분 | ||
48 | +app.use(express.static(__dirname + '/main')); | ||
49 | + | ||
50 | +app.get('/main',(req,res)=>{ | ||
51 | + res.sendFile(__dirname+'/main/main.html') | ||
52 | +}) | ||
53 | + | ||
54 | + | ||
55 | +/*--------------------로그인 처리---------------------- */ | ||
56 | + | ||
57 | +//로그인 페이지 | ||
58 | +app.get('/login',(req,res)=>{ | ||
59 | + let page = getLoginButton(`<a href="/">뒤로가기</a>`); | ||
60 | + res.send(page); | ||
61 | +}); | ||
62 | + | ||
63 | + | ||
64 | + | ||
65 | +//로그인 인증 (Passport) | ||
66 | +passport.use(new LocalStrategy({ | ||
67 | + //로그인 페이지 input 태그 내 name | ||
68 | + usernameField: 'email', | ||
69 | + passwordField: 'password' | ||
70 | + }, | ||
71 | + (id, password, done)=>{ | ||
72 | + console.log(id,password); | ||
73 | + //회원 정보가 한개이상 있을때 | ||
74 | + if(user){ | ||
75 | + console.log(user); | ||
76 | + | ||
77 | + //아이디가 다를때 | ||
78 | + if (id !== user.email){ | ||
79 | + //alert("존재하는 아이디가 없습니다.") | ||
80 | + return done(null, false, { message: '아이디가 다르다' });} | ||
81 | + //비밀번호가 다를때 | ||
82 | + else if (password !== user.password) { | ||
83 | + //alert("비밀번호가 다릅니다."); | ||
84 | + return done(null, false, { message: '비번이 다르다' });} | ||
85 | + //아이디, 비밀번호 모두 맞을 경우 | ||
86 | + return done(null, user); | ||
87 | + } | ||
88 | +})); | ||
89 | + | ||
90 | +//로그인 처리 (Passport) | ||
91 | +app.post('/login', | ||
92 | +passport.authenticate('local', { | ||
93 | + //성공시, 메인페이지 이동 | ||
94 | + //실패시 로그인 페이지 이동 | ||
95 | + successRedirect: '/', | ||
96 | + failureRedirect: '/login', | ||
97 | + badRequestMessage : 'Missing username or password.', | ||
98 | + failureFlash: true | ||
99 | +})); | ||
100 | + | ||
101 | +//로그 아웃 처리 | ||
102 | +app.get('/logout',(req,res)=>{ | ||
103 | + | ||
104 | + //passport 정보 삭제 | ||
105 | + req.logout(); | ||
106 | + //서버측 세션 삭제 | ||
107 | + req.session.destroy(()=>{ | ||
108 | + //클라이언트 측 세션 암호화 쿠키 삭제 | ||
109 | + res.cookie('connect.sid','',{maxAge:0}); | ||
110 | + res.redirect('/'); | ||
111 | + }); | ||
112 | +}); | ||
113 | + | ||
114 | + | ||
115 | +//로그인 로그아웃 여부 | ||
116 | +const authInfo = (req)=>{ | ||
117 | + if(req.user) | ||
118 | + { | ||
119 | + return `${user.name} | <a href="/logout">로그아웃</a>`;} | ||
120 | + else | ||
121 | + return `<a href="/login">로그인</a>`; | ||
122 | +} | ||
123 | + | ||
124 | +// naver 로그인 | ||
125 | +app.get('/naverlogin', passport.authenticate('naver')); | ||
126 | +passport.use('naver',new NaverStrategy({ | ||
127 | + clientID: 'CGVVomc0bhMhzfzbytK2', | ||
128 | + clientSecret: 'XHylcjnZxG', | ||
129 | + callbackURL: "http://localhost:3000/", | ||
130 | + svcType: 0, | ||
131 | + authType: 'reauthenticate' // enable re-authentication | ||
132 | + }, | ||
133 | + | ||
134 | + function(accessToken, refreshToken, profile, done) { | ||
135 | + var _profile = profile._json; | ||
136 | + console.log(_profile.id); | ||
137 | + console.log(_profile.properties.nickname); | ||
138 | + } | ||
139 | + )); | ||
140 | + | ||
141 | + | ||
142 | +// kakao 로그인 | ||
143 | +app.get('/kakaologin', passport.authenticate('kakao-login')); | ||
144 | +passport.use('kakao-login', new KakaoStrategy({ | ||
145 | + clientID: '8a854307a99092b4eeeff5e4a79c0ac0', | ||
146 | + callbackURL: 'http://localhost:3000/' | ||
147 | +}, | ||
148 | +function (accessToken, refreshToken, profile, done) { | ||
149 | + var _profile = profile._json; | ||
150 | + console.log(_profile.id); | ||
151 | + console.log(_profile.properties.nickname); | ||
152 | + | ||
153 | +} | ||
154 | +)); | ||
155 | + | ||
156 | + | ||
157 | +/*--------------------회원가입 처리---------------------- */ | ||
158 | + | ||
159 | + | ||
160 | +//회원가입 처리 Post | ||
161 | +var user = {}; | ||
162 | +app.post('/join',(req,res)=>{ | ||
163 | + user.email = req.body.email; | ||
164 | + user.password = req.body.password; | ||
165 | + user.name=req.body.name; | ||
166 | + //로그인 페이지로 이동 | ||
167 | + console.log(user); | ||
168 | + res.redirect('/login'); | ||
169 | +}); | ||
170 | + | ||
171 | + | ||
172 | + | ||
173 | + | ||
174 | + | ||
175 | +//회원가입 페이지 Get | ||
176 | +app.get('/join',(req,res)=>{ | ||
177 | + let page = getPage('회원가입',` | ||
178 | + <html> | ||
179 | + <head> | ||
180 | + <script> function congratulation() | ||
181 | + { | ||
182 | + alert("새로운 회원이 되신걸 축하합니다!:D \n 레시피 찾을 준비 되셨나요?"); | ||
183 | + } </script> | ||
184 | + <style> | ||
185 | + body { | ||
186 | + padding-top: 15px; | ||
187 | + font-size: 12px | ||
188 | + } | ||
189 | + .main { | ||
190 | + max-width: 320px; | ||
191 | + margin-top:300px auto; | ||
192 | + margin: 0 auto; | ||
193 | + } | ||
194 | + .login-or { | ||
195 | + position: relative; | ||
196 | + font-size: 18px; | ||
197 | + color: rgb(7, 7, 7); | ||
198 | + margin-top: 10px; | ||
199 | + margin-bottom: 10px; | ||
200 | + padding-top: 10px; | ||
201 | + padding-bottom: 10px; | ||
202 | + } | ||
203 | + .span-or { | ||
204 | + display: block; | ||
205 | + position: absolute; | ||
206 | + left: 50%; | ||
207 | + top: -2px; | ||
208 | + margin-left: -25px; | ||
209 | + background-color: #fff; | ||
210 | + width: 50px; | ||
211 | + text-align: center; | ||
212 | + } | ||
213 | + .hr-or { | ||
214 | + background-color: #cdcdcd; | ||
215 | + height: 1px; | ||
216 | + margin-top: 0px !important; | ||
217 | + margin-bottom: 0px !important; | ||
218 | + } | ||
219 | + h3 { | ||
220 | + text-align: center; | ||
221 | + line-height: 300%; | ||
222 | + margin-top:10px auto; | ||
223 | + } | ||
224 | + img{ | ||
225 | + width:320px; | ||
226 | + height:150px; | ||
227 | + object-fit:cover; | ||
228 | + margin-bottom:30px; | ||
229 | + } | ||
230 | + </style><link href="//netdna.bootstrapcdn.com/bootstrap/3.0.0/css/bootstrap.min.css" rel="stylesheet" id="bootstrap-css"> | ||
231 | +<script src="//netdna.bootstrapcdn.com/bootstrap/3.0.0/js/bootstrap.min.js"></script> | ||
232 | +<script src="//code.jquery.com/jquery-1.11.1.min.js"></script> | ||
233 | + | ||
234 | +</head> | ||
235 | + | ||
236 | + <body> | ||
237 | + <div class="container"> | ||
238 | + <div class="row"> | ||
239 | + <div class="main"> | ||
240 | + <img src="https://images.unsplash.com/photo-1600577916048-804c9191e36c?ixlib=rb-1.2.1&ixid=MnwxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8&auto=format&fit=crop&w=1632&q=80" alt=""/> | ||
241 | + <h3>Sign-Up</h3> | ||
242 | + <form action="/join" method="post"> | ||
243 | + <div class="form-group"> | ||
244 | + <input type="email" class="form-control" name="email" placeholder="email"><br> | ||
245 | + </div> | ||
246 | + <div class="form-group"> | ||
247 | + <input type="password" name="password" class="form-control" placeholder="****"><br> | ||
248 | + </div> | ||
249 | + <div class="form-group"> | ||
250 | + <input type="name" name="name" class="form-control" placeholder="이름"><br> | ||
251 | + </div> | ||
252 | + <button type="submit" value="회원가입" class="btn btn btn-primary" onClick="javascript:congratulation()"> | ||
253 | + 회원가입 | ||
254 | + </button> | ||
255 | + </form> | ||
256 | + </html> | ||
257 | + | ||
258 | + `,'<a href="/login">뒤로가기</a>'); | ||
259 | + res.send(page); | ||
260 | +}); | ||
261 | + | ||
262 | + | ||
263 | + | ||
264 | +//포트 연결 | ||
265 | +app.listen(3000,()=>console.log(`http://localhost:3000`)); | ||
266 | + | ||
267 | + | ||
268 | + | ||
269 | +//페이지 템플릿 | ||
270 | +const getPage = (title, content, auth) =>{ | ||
271 | + return ` | ||
272 | + <!DOCTYPE html> | ||
273 | + <html lang="en"> | ||
274 | + <head> | ||
275 | + <meta charset="UTF-8"> | ||
276 | + <meta http-equiv="X-UA-Compatible" content="IE=edge"> | ||
277 | + <meta name="viewport" content="width=device-width, initial-scale=1.0"> | ||
278 | + <title>Passport Example</title> | ||
279 | + </head> | ||
280 | + <body> | ||
281 | + ${auth} | ||
282 | + <h1>${title}</h1> | ||
283 | + <p>${content}</p> | ||
284 | + </body> | ||
285 | + </html> | ||
286 | + `; | ||
287 | +} | ||
288 | + | ||
289 | +//로그인 버튼 | ||
290 | +const getLoginButton = (auth) =>{ | ||
291 | + return ` | ||
292 | + <!DOCTYPE html> | ||
293 | + <html> | ||
294 | + <head> | ||
295 | + <style> | ||
296 | + body { | ||
297 | + padding-top: 15px; | ||
298 | + font-size: 12px | ||
299 | + } | ||
300 | + .main { | ||
301 | + max-width: 320px; | ||
302 | + margin-top:300px auto; | ||
303 | + margin: 0 auto; | ||
304 | + } | ||
305 | + .login-or { | ||
306 | + position: relative; | ||
307 | + font-size: 18px; | ||
308 | + color: rgb(7, 7, 7); | ||
309 | + margin-top: 10px; | ||
310 | + margin-bottom: 10px; | ||
311 | + padding-top: 10px; | ||
312 | + padding-bottom: 10px; | ||
313 | + } | ||
314 | + .span-or { | ||
315 | + display: block; | ||
316 | + position: absolute; | ||
317 | + left: 50%; | ||
318 | + top: -2px; | ||
319 | + margin-left: -25px; | ||
320 | + background-color: #fff; | ||
321 | + width: 50px; | ||
322 | + text-align: center; | ||
323 | + } | ||
324 | + .hr-or { | ||
325 | + background-color: #cdcdcd; | ||
326 | + height: 1px; | ||
327 | + margin-top: 0px !important; | ||
328 | + margin-bottom: 0px !important; | ||
329 | + } | ||
330 | + h3 { | ||
331 | + text-align: center; | ||
332 | + line-height: 300%; | ||
333 | + margin-top:10px auto; | ||
334 | + } | ||
335 | + img{ | ||
336 | + width:300px; | ||
337 | + height:150px; | ||
338 | + object-fit:cover; | ||
339 | + margin-bottom:30px; | ||
340 | + } | ||
341 | + </style> | ||
342 | + <link href="//netdna.bootstrapcdn.com/bootstrap/3.0.0/css/bootstrap.min.css" rel="stylesheet" id="bootstrap-css"> | ||
343 | + <script src="//netdna.bootstrapcdn.com/bootstrap/3.0.0/js/bootstrap.min.js"></script> | ||
344 | + <script src="//code.jquery.com/jquery-1.11.1.min.js"></script> | ||
345 | + <script type="text/javascript" src="https://static.nid.naver.com/js/naverLogin_implicit-1.0.3.js" charset="utf-8"></script> | ||
346 | + <script type="text/javascript" src="http://code.jquery.com/jquery-1.11.3.min.js"></script> | ||
347 | + <title><%= title %></title> | ||
348 | + </head> | ||
349 | + <body> | ||
350 | + ${auth} | ||
351 | + <div class="container"> | ||
352 | + <div class="row"> | ||
353 | + <div class="main"> | ||
354 | + <img src="https://i.ibb.co/k2zSVcn/142437038-e7b564cb-978a-4018-8834-9984cc3b119e.png" alt=""/> | ||
355 | + <!--이미지 아래부분이 살짝 잘림 --> | ||
356 | + <!--로그인,회원가입버튼 오른쪽 맞추는게 더 깔끔할거같음 --> | ||
357 | + | ||
358 | + <h3>Login</h3> | ||
359 | + <form role="form" method="POST" action="/login"> | ||
360 | + <div class="form-group"> | ||
361 | + <label for="userId">아이디</label> | ||
362 | + <input type="text" class="form-control" id="email" name="email"> | ||
363 | + </div> | ||
364 | + <div class="form-group"> | ||
365 | + <label for="password">비밀번호</label> | ||
366 | + <input type="password" class="form-control" id="password" name="password"> | ||
367 | + </div> | ||
368 | + <button type="submit" class="btn btn btn-primary"> | ||
369 | + 로그인 | ||
370 | + </button> | ||
371 | + <button type="submit" class="btn btn btn-primary"> | ||
372 | + <a href="/join" style="color:white;text-decoration-line:none;"> 회원가입</a> | ||
373 | + </form> | ||
374 | + | ||
375 | + </div> | ||
376 | + </div> | ||
377 | + </div> | ||
378 | + | ||
379 | + <div> | ||
380 | + <a href="/naverlogin" class="btn btn-block btn-lg btn-success btn_login">Naver</a> | ||
381 | + <a href="/kakaologin" class="btn btn-block btn-lg btn-warning btn_login">KaKao</a> | ||
382 | + </div> | ||
383 | + | ||
384 | + | ||
385 | +</body> | ||
386 | +</html> | ||
387 | + `; | ||
388 | +} | ||
389 | + | ||
390 | + | ||
391 | +//첫 페이지 화면 | ||
392 | +const getFirstPage =(title, content, auth) =>{ | ||
393 | + return ` | ||
394 | + <!DOCTYPE html> | ||
395 | + <html lang="en"> | ||
396 | + <head> | ||
397 | + <meta charset="UTF-8"> | ||
398 | + <meta http-equiv="X-UA-Compatible" content="IE=edge"> | ||
399 | + <meta name="viewport" content="width=device-width, initial-scale=1.0"> | ||
400 | + <title>Passport Example</title> | ||
401 | + </head> | ||
402 | + <body> | ||
403 | + ${auth} | ||
404 | + <h1>${title}</h1> | ||
405 | + <p>${content}</p> | ||
406 | + <div> | ||
407 | + <input type="button" value="page move" onClick="movepage()"/> | ||
408 | + </div> | ||
409 | + <script type="text/javascript"> | ||
410 | + function movepage(){ | ||
411 | + location.href="main"; | ||
412 | + }</script> | ||
413 | + </body> | ||
414 | + </html> | ||
415 | + `; | ||
416 | + | ||
417 | +} | ||
418 | + |
... | @@ -4,23 +4,69 @@ | ... | @@ -4,23 +4,69 @@ |
4 | box-sizing:border-box; | 4 | box-sizing:border-box; |
5 | } | 5 | } |
6 | .containter{ | 6 | .containter{ |
7 | + position:relative; | ||
7 | width:90%; | 8 | width:90%; |
8 | height:auto; | 9 | height:auto; |
9 | max-width:1200px; | 10 | max-width:1200px; |
10 | - margin:0 auto; | 11 | + margin:0;/*auto*/ |
12 | + color:black; | ||
11 | } | 13 | } |
12 | form{ | 14 | form{ |
13 | - width:50%; | 15 | + width:90%; |
14 | - max-width:400px; | ||
15 | border-radius:4px; | 16 | border-radius:4px; |
17 | + margin-top:-10px; | ||
18 | + margin-left:10px; | ||
19 | + background-color:white; | ||
20 | +} | ||
21 | +form{ | ||
22 | + display:inline-block; | ||
16 | } | 23 | } |
17 | -form input{ | 24 | +.search-result{ |
25 | + /*여러줄로 보여주기 위해선 grid 사용해야하는데, 우선은 영상목록 뽑아보고 결정*/ | ||
26 | + /*grid로 바꿔놓음. 여러 열로 사진들이 정렬됨*/ | ||
27 | + display:grid; | ||
28 | + grid-gap:25px; | ||
29 | + grid-template:auto/repeat(auto-fit,minmax(300px,1fr)); | ||
30 | + margin-top:50px; | ||
18 | width:100%; | 31 | width:100%; |
32 | + margin-left:265px; | ||
33 | +} | ||
34 | +/*form input{ | ||
35 | + width:80%; | ||
36 | + padding:10px; | ||
37 | + border:none; | ||
38 | + outline:none; | ||
39 | + font-size:1.8rem; | ||
40 | + display:inline-block; | ||
19 | } | 41 | } |
20 | form ion-icon{ | 42 | form ion-icon{ |
21 | width:9%; | 43 | width:9%; |
22 | font-size:3rem; | 44 | font-size:3rem; |
23 | - margin:-15px; | 45 | + margin-left:10px; |
46 | + margin-top:15px; | ||
24 | color:rgb(75,75,75); | 47 | color:rgb(75,75,75); |
25 | - | ||
26 | -} | ||
... | \ No newline at end of file | ... | \ No newline at end of file |
48 | +}*/ | ||
49 | +.search-box{ | ||
50 | + margin-left:-10px; | ||
51 | + margin-top:10px; | ||
52 | +} | ||
53 | +img{ | ||
54 | + width:80%; | ||
55 | + height:80%; | ||
56 | + object-fit:cover; | ||
57 | +} | ||
58 | +html{ | ||
59 | + font-size:12px; | ||
60 | +} | ||
61 | +section{ | ||
62 | + min-height:10vh; | ||
63 | + width:100%; | ||
64 | + display:flex; | ||
65 | + padding:100px 0; | ||
66 | +} | ||
67 | +.brand{ | ||
68 | + margin-top:-70px; | ||
69 | + font-size:4rem; | ||
70 | + color:black; | ||
71 | + margin-bottom:30px; | ||
72 | +} | ... | ... |
1 | - | 1 | +<!DOCTYPE html> |
2 | - <!DOCTYPE html> | 2 | +<html lang="en"> |
3 | - <html lang="en"> | 3 | +<head> |
4 | - <head> | 4 | + <meta charset="UTF-8"> |
5 | - <meta charset="UTF-8"> | 5 | + <meta name="viewport" content="width=device-width, initial-scale=1.0"> |
6 | - <meta name="viewport" content="width=device-width, initial-scale=1.0"> | 6 | + <title>Document</title> |
7 | - <title>Document</title> | 7 | + <link rel="stylesheet" href="main.css"> |
8 | - <link rel="style sheet" href="main.css"> | 8 | +</head> |
9 | - </head> | 9 | +<body> |
10 | - <body> | 10 | + <section> |
11 | - <section> | 11 | + <div class="container"> |
12 | - <div class="container"> | 12 | + <h1 class="brand">Recipe APP</h1> |
13 | - <h1 class="brand">Recipe APP</h1> | 13 | + <form> |
14 | - <div class="serach-box"> | 14 | + <input id="name" type="text" placeholder="Search Your Recipe..."> |
15 | - <form> | 15 | + <ion-icon name="search"></ion-icon> |
16 | - <input id="name" type="text" placeholder="Search Your Recipe..."> | 16 | + </form> |
17 | - <ion-icon name="search"></ion-icon> | 17 | + <div class="search-result"> |
18 | - </form> | 18 | + <!--<div class="item"> |
19 | + <img src="./0.jpg" alt=""> | ||
20 | + <div class="flex-container"> | ||
21 | + <h1 class="title">This is a recipe</h1> | ||
22 | + <a href="#">View Recipe</a> | ||
19 | </div> | 23 | </div> |
20 | - <div class="search-result"> | 24 | + <p class="item-data">Calories: 120</p> |
21 | - <!--<div class="item"> | 25 | + </div>--> |
22 | - <img src="./0.jpg" alt=""> | 26 | + </div> |
23 | - <div class="flex-container"> | 27 | + </div> |
24 | - <h1 class="title">This is a recipe</h1> | 28 | + </section> |
25 | - <a href="#">View Recipe</a> | 29 | + <script src="./main.js"></script> |
26 | - </div> | 30 | + <script type="module" src="https://unpkg.com/ionicons@5.5.2/dist/ionicons/ionicons.esm.js"></script> |
27 | - <p class="item-data">Calories: 120</p> | 31 | + <script nomodule src="https://unpkg.com/ionicons@5.5.2/dist/ionicons/ionicons.js"></script> |
28 | - </div>--> | 32 | +</body> |
29 | - </div> | 33 | +</html> |
30 | - </div> | ||
31 | - </section> | ||
32 | - <script src="./main.js"></script> | ||
33 | - <script type="module" src="https://unpkg.com/ionicons@5.5.2/dist/ionicons/ionicons.esm.js"></script> | ||
34 | - <script nomodule src="https://unpkg.com/ionicons@5.5.2/dist/ionicons/ionicons.js"></script> | ||
35 | - </body> | ||
36 | - </html> | ... | ... |
1 | +{"cookie":{"originalMaxAge":null,"expires":null,"httpOnly":true,"path":"/"},"flash":{"error":["Missing username or password."]},"__lastAccess":1638671002743} | ||
... | \ No newline at end of file | ... | \ No newline at end of file |
-
Please register or login to post a comment