swa07016

MypickPage 구현 및 LoginLink, UserCards 컴포넌트 생성

1 +import React from 'react'
2 +import {Container, Jumbotron, Button} from 'reactstrap';
3 +const LoginLink = () => {
4 + return (
5 + <>
6 + <div style={{paddingTop:'8rem', 'display':'flex', 'width':'100%', "height":'100%', 'textAlign':'center', 'alignItems':'center'}}>
7 + <Container style={{}}>
8 + <Jumbotron
9 + style={{'backgroundColor':'#fff'}}
10 + >
11 + <h1 className="display-3">My pick</h1><br/>
12 + <p className="lead">로그인이 필요합니다.
13 + </p>
14 + <br/>
15 + <hr className="my-2" />
16 + <br/>
17 + <Button color="link" href='/signin'>로그인</Button>
18 + <Button color="link" href='/signup'>회원가입</Button>
19 + </Jumbotron>
20 + </Container>
21 + </div>
22 + </>
23 + )
24 +}
25 +
26 +export default LoginLink;
...\ No newline at end of file ...\ No newline at end of file
1 +import React, { useState, useEffect } from 'react';
2 +import { Container, Row, Col } from 'reactstrap';
3 +import axios from 'axios';
4 +import MealCard from '../components/MealCard';
5 +
6 +const UserCards = () => {
7 + const [datas, setDatas] = useState([]);
8 + const [picks, setPicks] = useState([{
9 + "id": "1",
10 + "name": "#신슨즈(#Shinsons)",
11 + "address": "경기도 용인시 기흥구 서그내로15번길 34 (서천동)",
12 + "latitude": "37.2464876",
13 + "longitude": "127.0768072",
14 + "type": "호프",
15 + "menu": "칵테일, 술",
16 + "img": "/images/1_img.jpg",
17 + "img_source": "https://www.picuki.com/profile/shinsons"
18 + },
19 + {
20 + "id": "2",
21 + "name": "감쟈",
22 + "address": "경기도 용인시 기흥구 서그내로15번길 29, 102호 (서천동)",
23 + "latitude": "37.2464608",
24 + "longitude": "127.0764465",
25 + "type": "술집",
26 + "menu": "안주, 술",
27 + "img": "/images/2_img.jpg",
28 + "img_source": "https://www.facebook.com/gamjua/posts/1408798555882739/"
29 + },
30 + {
31 + "id": "3",
32 + "name": "깜냥",
33 + "address": "경기도 용인시 기흥구 서그내로15번길 29 (서천동,1층)",
34 + "latitude": "37.2464608",
35 + "longitude": "127.0764465",
36 + "type": "술집",
37 + "menu": "안주, 술",
38 + "img": "/images/3_img.jpg",
39 + "img_source": "https://www.facebook.com/ggamnyang316/"
40 + },
41 + {
42 + "id": "4",
43 + "name": "꼬꼬리아통닭",
44 + "address": "경기도 용인시 기흥구 서그내로15번길 39 (서천동)",
45 + "latitude": "37.2465772",
46 + "longitude": "127.0775286",
47 + "type": "호프",
48 + "menu": "치킨, 술",
49 + "img": "/images/4_img.jpg",
50 + "img_source": "https://bigsta.net/tag/%EA%BC%AC%EA%BC%AC%EB%A6%AC%EC%95%84/"
51 + },
52 + {
53 + "id": "5",
54 + "name": "도스마스수원경희대점",
55 + "address": "경기도 용인시 기흥구 서그내로15번길 33 (서천동, 서윤빌딩1층)",
56 + "latitude": "37.2467668",
57 + "longitude": "127.0768863",
58 + "type": "기타",
59 + "menu": "부리또, 타코",
60 + "img": "/images/5_img.jpg",
61 + "img_source": "https://blog.naver.com/alttium/221443978130"
62 + }]);
63 +
64 + useEffect(() => {
65 + const fetchData = async () => {
66 + const result = await axios(
67 + 'http://localhost:5000/api/datas',
68 + // localhost로 바꾸기
69 + );
70 + setDatas(result.data);
71 + };
72 + fetchData();
73 +
74 + }, []);
75 +
76 +
77 +
78 + return (
79 + <>
80 + <h1 style={{'paddingTop':'3rem'}} className="text-center">
81 + <span className="font-weight-bold">User's Pick</span>
82 + </h1>
83 + <br/>
84 + <hr className="my-2" />
85 + <br/>
86 + <Container style={{'paddingTop':'1.2rem'}}>
87 + <Row xs="2" sm="2" md="4">
88 + {picks.map((data, index) =>
89 + <Col>
90 + <MealCard
91 + key = {index}
92 + id = {data.id}
93 + name = {data.name}
94 + address = {data.address}
95 + latitude = {data.latitude}
96 + longitude = {data.longitude}
97 + type = {data.type}
98 + menu = {data.menu}
99 + img = {data.img}
100 + img_source = {data.img_source}
101 + />
102 + </Col>
103 + )
104 + }
105 + </Row>
106 + </Container>
107 + </>
108 + )
109 +}
110 +
111 +export default UserCards;
...\ No newline at end of file ...\ No newline at end of file
...@@ -12,7 +12,6 @@ const MenuPage = (props) => { ...@@ -12,7 +12,6 @@ const MenuPage = (props) => {
12 const [datas, setDatas] = useState([]); 12 const [datas, setDatas] = useState([]);
13 const [filteredDatas, setFilteredDatas] = useState([]); 13 const [filteredDatas, setFilteredDatas] = useState([]);
14 const [isLoading, setIsLoading] = useState(false); 14 const [isLoading, setIsLoading] = useState(false);
15 -
16 const [all, setAll] = useState(false); 15 const [all, setAll] = useState(false);
17 const [Kfood, setKfood] = useState(false); 16 const [Kfood, setKfood] = useState(false);
18 const [Cfood, setCfood] = useState(false); 17 const [Cfood, setCfood] = useState(false);
......
1 -import React, { useState } from 'react' 1 +import React, { useState, useEffect } from 'react'
2 import NavBar from '../components/NavBar'; 2 import NavBar from '../components/NavBar';
3 - 3 +import LoginLink from '../components/LoginLink';
4 +import UserCards from '../components/UserCards';
5 +import { Container } from 'reactstrap';
4 // auth로 로그인한 사용자일 때와 아닐때 판단해서 화면을 다르게 6 // auth로 로그인한 사용자일 때와 아닐때 판단해서 화면을 다르게
5 // 렌더링 7 // 렌더링
8 +// useEffect로 초기 인증
6 9
7 const MypickPage = () => { 10 const MypickPage = () => {
8 const [isLogin, setIsLogin] = useState(false); 11 const [isLogin, setIsLogin] = useState(false);
12 + const [username, setUsername] = useState('');
13 + const authApi = () => {
14 + const user = JSON.parse(localStorage.getItem('user'));
15 + return fetch('/api/auth', {
16 + method: 'GET',
17 + headers: {
18 + 'Content-Type': 'application/json',
19 + 'authorization': user
20 + }
21 + }).then(response => response.json())
22 + .then(result => {
23 + if(result.message === 'valid token') {
24 + setIsLogin(true);
25 +
26 + } else if(result.message === 'expired token') {
27 + alert('토큰이 만료되었습니다. 로그인 해주세요.');
28 + setIsLogin(false);
29 + } else if(result.message === 'invalid token') {
30 + setIsLogin(false);
31 + }
32 + });
33 + }
34 +
35 + useEffect(() => {
36 + authApi();
37 + }, [isLogin]);
38 +
9 return ( 39 return (
10 <> 40 <>
41 + <Container>
11 <NavBar/> 42 <NavBar/>
12 { 43 {
13 - isLogin ? <h1>mypick</h1> : <a>aaa</a> 44 + isLogin ?
45 + (<>
46 +
47 + <UserCards/>
48 + </>)
49 + :
50 + (<>
51 + <LoginLink/>
52 + </>)
14 } 53 }
54 + </Container>
15 </> 55 </>
16 ) 56 )
17 } 57 }
......
...@@ -31,7 +31,7 @@ const SigninPage = (props) => { ...@@ -31,7 +31,7 @@ const SigninPage = (props) => {
31 if (response.message === "Token issue") { 31 if (response.message === "Token issue") {
32 localStorage.setItem("user", JSON.stringify(response.token)); 32 localStorage.setItem("user", JSON.stringify(response.token));
33 alert('Login success'); 33 alert('Login success');
34 - props.history.push('/'); 34 + props.history.push('/mypick');
35 } else if(response.message === "user does not exist"){ 35 } else if(response.message === "user does not exist"){
36 alert('User does not exist'); 36 alert('User does not exist');
37 props.history.push('/signin'); 37 props.history.push('/signin');
......
...@@ -110,7 +110,6 @@ app.post("/api/signin", (req, res) => { ...@@ -110,7 +110,6 @@ app.post("/api/signin", (req, res) => {
110 code: 500, 110 code: 500,
111 message: 'server error', 111 message: 'server error',
112 }); 112 });
113 -
114 } 113 }
115 114
116 } else { 115 } else {
...@@ -158,4 +157,4 @@ app.get('/api/auth', (req, res) => { ...@@ -158,4 +157,4 @@ app.get('/api/auth', (req, res) => {
158 }); 157 });
159 158
160 159
161 -app.listen(port, () => console.log(`Listening on port ${port}`)); 160 +app.listen(port, () => console.log(`Listening on port ${port}`));
...\ No newline at end of file ...\ No newline at end of file
......