-
Notifications
You must be signed in to change notification settings - Fork 3
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
feat: Welcome.js & Welcome.css 추가 수정
[#77]
- Loading branch information
Showing
2 changed files
with
251 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,119 @@ | ||
import React, { useContext } from 'react'; | ||
import { GoogleLogin } from "@react-oauth/google"; | ||
import { GoogleOAuthProvider } from "@react-oauth/google"; | ||
import { jwtDecode } from 'jwt-decode'; // 중괄호 없이 임포트 | ||
import { BrowserRouter as Router, Route, Routes, useNavigate, Link } from 'react-router-dom'; // Router를 추가 | ||
|
||
import { createContext, useState } from 'react'; // UserContext를 포함 | ||
import logo from '../logo/white_logo.png' | ||
import '../css/Welcome.css'; // CSS 파일을 import | ||
|
||
// UserContext를 App.js에 직접 정의합니다. | ||
export const UserContext = createContext(); | ||
|
||
const UserProvider = ({ children }) => { | ||
const [user, setUser] = useState(null); | ||
|
||
return ( | ||
<UserContext.Provider value={{ user, setUser }}> | ||
{children} | ||
</UserContext.Provider> | ||
); | ||
}; | ||
|
||
const GoogleLoginPage = () => { | ||
const clientId = "YOUR_CLIENT_ID"; // 본인의 Google Client ID로 대체하세요. | ||
const navigate = useNavigate(); | ||
const { setUser } = useContext(UserContext); | ||
|
||
const handleLogin = async (credentialResponse) => { | ||
const token = credentialResponse.credential; | ||
const decoded = jwtDecode(token); | ||
setUser(decoded); | ||
console.log(decoded); | ||
|
||
try { | ||
const response = await fetch('http://localhost:8000/api/verify', { | ||
method: 'POST', | ||
headers: { | ||
'Content-Type': 'application/json', | ||
}, | ||
body: JSON.stringify({ token: token }), | ||
}); | ||
if (response.ok) { | ||
const data = await response.json(); | ||
console.log(data); | ||
navigate('/lobby'); | ||
} else { | ||
console.error('Login verification failed'); | ||
} | ||
} catch (error) { | ||
console.error('Error:', error); | ||
} | ||
}; | ||
|
||
return ( | ||
<GoogleOAuthProvider clientId={clientId}> | ||
<div className="login-page"> | ||
<header> | ||
<h1> | ||
<img src={logo} alt="MOPIc 로고" style={{ height: '40px' }} /> | ||
</h1> | ||
<nav> | ||
<Link to="/home">Home</Link> | ||
<Link to="/about">About</Link> | ||
<Link to="/history">History</Link> | ||
</nav> | ||
</header> | ||
|
||
<main> | ||
<div className="content"> | ||
<p>👨🎓 시험 응시료도 만만찮고, 내가 잘하고 있는지도 모르겠어<br /> | ||
취업 시장에서 날이 갈수록 중요해지는 영어 시험<br /> | ||
5분 정도의 테스트로 내가 어느 정도인지 알아보고, 앞으로 어떻게 해야 할지 파악해 보자!<br /> | ||
하루에 딱 5분! 어떤 주제가 나와도 탄탄한 기본기를 쌓으려면? 모픽으로!</p> | ||
<p>지금 바로 로그인하기!</p> | ||
<GoogleLogin | ||
onSuccess={handleLogin} | ||
onError={() => { | ||
console.log("Login Failed"); | ||
}} | ||
/> | ||
</div> | ||
<div className="side-content"> | ||
<div className="logo"> | ||
<img src={logo} alt="MOPIc 로고" /> | ||
</div> | ||
</div> | ||
</main> | ||
|
||
<footer> | ||
<p>© 2024 Mopic. All rights reserved.</p> | ||
</footer> | ||
</div> | ||
</GoogleOAuthProvider> | ||
); | ||
}; | ||
|
||
// Home, About, History 컴포넌트를 간단히 정의 | ||
const Home = () => <div><h2>Home Page</h2></div>; | ||
const About = () => <div><h2>About Page</h2></div>; | ||
const History = () => <div><h2>History Page</h2></div>; | ||
|
||
const App = () => { | ||
return ( | ||
<UserProvider> | ||
<Router> | ||
<Routes> | ||
<Route path="/" element={<GoogleLoginPage />} /> | ||
<Route path="/home" element={<Home />} /> | ||
<Route path="/about" element={<About />} /> | ||
<Route path="/history" element={<History />} /> | ||
{/* 추가적인 경로와 컴포넌트를 여기에서 정의할 수 있습니다 */} | ||
</Routes> | ||
</Router> | ||
</UserProvider> | ||
); | ||
}; | ||
|
||
export default App; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,132 @@ | ||
/* 전체 화면 설정 */ | ||
.login-page { | ||
display: flex; | ||
flex-direction: column; | ||
min-height: 100vh; /* 페이지가 전체 화면을 채우도록 설정 */ | ||
} | ||
/* Flexbox로 레이아웃 설정 */ | ||
body { | ||
display: flex; | ||
flex-direction: column; | ||
font-family: 'Arial', sans-serif; | ||
background-color: #d0d0d0; | ||
/* min-height: 100vh; 주석 처리: main의 min-height를 사용하므로 필요하지 않음 */ | ||
} | ||
|
||
/* 헤더 스타일 */ | ||
header { | ||
display: flex; | ||
justify-content: space-between; | ||
align-items: center; | ||
padding: 10px 20px; | ||
background-color: #6d8d8d; | ||
/* height: 40px; 주석 처리: min-height로 대체 */ | ||
min-height: 5vh; | ||
} | ||
|
||
header h1 { | ||
margin: 0; /* 기본 여백 제거 */ | ||
} | ||
|
||
header img { | ||
width: 100px; /* 로고 크기 조정 */ | ||
height: auto; /* 비율 유지 */ | ||
} | ||
|
||
header nav { | ||
display: flex; | ||
} | ||
|
||
header nav a { | ||
margin: 0 15px; | ||
text-decoration: none; | ||
color: #fff; /* 텍스트 색상 */ | ||
font-size: 16px; | ||
} | ||
|
||
header nav a:hover { | ||
color: #ccc; /* 호버 색상 */ | ||
} | ||
|
||
/* 메인 콘텐츠 스타일 */ | ||
main { | ||
display: flex; | ||
justify-content: space-between; | ||
align-items: stretch; /* 높이 동일하게 맞추기 */ | ||
padding: 10px; /* padding을 줄여서 더 많은 공간 확보 */ | ||
flex: 1; /* 메인 영역이 가변적으로 확장되도록 설정 */ | ||
box-sizing: border-box; /* padding을 포함한 전체 크기 계산 */ | ||
min-height: 85vh; /* 최소 높이를 85% 뷰포트 높이로 설정하여 화면 전체를 채움 */ | ||
} | ||
|
||
/* 콘텐츠와 사이드 콘텐츠를 6:4 비율로 설정 */ | ||
.content { | ||
flex: 6; /* 비율을 위해 너비를 60%로 설정 */ | ||
background-color: #f0f0f0; | ||
padding: 20px; | ||
border-radius: 5px; | ||
box-shadow: 0px 4px 6px rgba(0, 0, 0, 0.1); | ||
display: flex; | ||
flex-direction: column; | ||
justify-content: center; /* 내부 아이템의 위치를 중앙으로 조정 */ | ||
text-align: center; /* 텍스트 가운데 정렬 */ | ||
font-size: 20px; | ||
} | ||
|
||
.side-content { | ||
flex: 4; /* 비율을 위해 너비를 40%로 설정 */ | ||
background-color: #C7D9D9; | ||
color: #fff; | ||
padding: 20px; | ||
border-radius: 5px; | ||
box-shadow: 0px 4px 6px rgba(0, 0, 0, 0.1); | ||
display: flex; | ||
justify-content: center; /* 가로 중앙 정렬 */ | ||
align-items: center; /* 세로 중앙 정렬 */ | ||
text-align: center; /* 텍스트 가운데 정렬 */ | ||
} | ||
|
||
/* 사이드 콘텐츠의 배경 색상과 텍스트 색상 */ | ||
.side-content { | ||
background-color: #C7D9D9; | ||
color: #fff; | ||
} | ||
|
||
/* 로고 스타일 */ | ||
.logo img { | ||
width: 50%; /* 컨테이너에 맞게 조정 */ | ||
height: auto; /* 비율을 유지하면서 높이를 자동으로 조정 */ | ||
object-fit: contain; /* 이미지의 비율을 유지하면서 컨테이너에 맞게 조정 */ | ||
vertical-align: middle; /* 이미지의 정렬을 조정 */ | ||
|
||
} | ||
|
||
|
||
/* 버튼 스타일 */ | ||
button { | ||
width: 200px; /* 버튼의 너비 */ | ||
padding: 12px 24px; /* 버튼 내부의 여백 (상하좌우) */ | ||
margin-top: 20px; /* 버튼 위의 여백 */ | ||
font-size: 18px; /* 버튼 텍스트의 크기 */ | ||
color: #fff; /* 텍스트 색상 */ | ||
background-color: #333; /* 버튼 배경 색상 */ | ||
border: none; /* 버튼의 테두리 제거 */ | ||
border-radius: 8px; /* 버튼의 모서리 둥글기 */ | ||
cursor: pointer; /* 커서를 포인터로 변경 */ | ||
transition: background-color 0.3s, transform 0.2s; /* 배경색과 크기 변경 시 부드러운 전환 효과 */ | ||
margin: 10px auto; | ||
} | ||
button:hover { | ||
background-color: #555; | ||
} | ||
|
||
/* 푸터 스타일 */ | ||
footer { | ||
padding: 10px 20px; | ||
background-color: #333; | ||
color: #fff; | ||
text-align: center; | ||
height: 40px; /* 푸터 높이 조정 */ | ||
flex-shrink: 0; /* 푸터가 축소되지 않도록 설정 */ | ||
min-height: 5vh; | ||
} |