조국현

Modify front-end of Search Result:

Change Search Result Image Display (1 row to grid)
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