Skip to content

Commit

Permalink
Merge pull request #14 from TaePoong719/feature/#5
Browse files Browse the repository at this point in the history
Feature/#5
  • Loading branch information
TaePoong719 authored Sep 13, 2023
2 parents d5742af + 0ab4a54 commit df11a78
Show file tree
Hide file tree
Showing 12 changed files with 1,023 additions and 21 deletions.
720 changes: 720 additions & 0 deletions package-lock.json

Large diffs are not rendered by default.

1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
"@testing-library/jest-dom": "^5.17.0",
"@testing-library/react": "^13.4.0",
"@testing-library/user-event": "^13.5.0",
"firebase": "^10.3.1",
"react": "^18.2.0",
"react-dom": "^18.2.0",
"react-router-dom": "^6.15.0",
Expand Down
13 changes: 7 additions & 6 deletions src/App.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,15 +2,16 @@ import Header from 'components/Header'
import React from 'react'
import { BrowserRouter } from 'react-router-dom'
import Router from 'Router'
import AuthProvider from './authentication/authProvider'

const App = () => {
return (
<>
<BrowserRouter>
<Header/>
<Router />
</BrowserRouter>
</>
<AuthProvider>
<BrowserRouter>
<Header/>
<Router />
</BrowserRouter>
</AuthProvider>
)
}

Expand Down
4 changes: 4 additions & 0 deletions src/Router.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,8 @@ import { Routes, Route } from 'react-router-dom'
import Home from './pages/Home'
import Wiki from './pages/Wiki'
import Gallery from './pages/Gallery'
import Login from './pages/Login'
import SignUp from './pages/SignUp'
import styled from 'styled-components'

const Router = () => {
Expand All @@ -13,6 +15,8 @@ const Router = () => {
<Route path="/" element={<Home />}> </Route>
<Route path="/wiki/*" element={<Wiki />}> </Route>
<Route path="/gallery" element={<Gallery />}> </Route>
<Route path="/login" element={<Login />}> </Route>
<Route path="/signup" element={<SignUp />}> </Route>
</Routes>
</Container>
</>
Expand Down
4 changes: 4 additions & 0 deletions src/authentication/authContext.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
import React from "react";
import { User } from "@firebase/auth";

export const AuthContext = React.createContext<User | null>(null);
24 changes: 24 additions & 0 deletions src/authentication/authProvider.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
import { User } from "@firebase/auth";
import { useEffect, useState } from "react";
import { AuthContext } from "./authContext";
import { auth } from "../firebase";

interface IChildren {
children : React.JSX.Element
}

const AuthProvider = ({ children }: IChildren) => {
const [user, setUser] = useState<User | null>(null);

useEffect(() => {
const subscribe = auth.onAuthStateChanged(fbUser => {
console.log(`현재 유저 정보`, fbUser);
setUser(fbUser);
});
return subscribe;
}, []);

return <AuthContext.Provider value={user}>{children}</AuthContext.Provider>;
};

export default AuthProvider;
6 changes: 0 additions & 6 deletions src/components/Header.css

This file was deleted.

74 changes: 65 additions & 9 deletions src/components/Header.tsx
Original file line number Diff line number Diff line change
@@ -1,32 +1,72 @@
import React from 'react'
import React, { useEffect, useState, useContext } from 'react'
import styled from 'styled-components'
import { Link } from 'react-router-dom'
import './Header.css'
import { Link, useLocation } from 'react-router-dom'
import { AuthContext } from 'authentication/authContext';
import { signOut } from 'firebase/auth'
import { auth } from '../firebase'

const Header = () => {
const pageLink = ["", "Wiki/", "Gallery"]
const pageLink = ["", "Wiki", "Gallery"]
const pageName = ["Home", "Wiki", "Gallery"]
const user = useContext(AuthContext)
const [pathLink, setPathLink ] = useState("")
const location = useLocation()

useEffect(()=>{
setPathLink(location.pathname.split("/")[1])
},[location])

return (
<Container>
<InnerContainer>
<ul className="header__link-wrapper">
{
pageLink.map((link,idx)=>
<li key={pageName[idx]} >
<Link to={`/${link}`}> {pageName[idx]} </Link>
</li>
pageLink.map((link,idx)=>{
let name = ""
if(pathLink === pageLink[idx]) name += "active"
return(
<li key={pageName[idx]} >
<Link to={`/${link}`}><h1 className={name}> {pageName[idx]} </h1> </Link>
</li>
)
}

)
}
<li> <StyledButton> <p> 학습 시간</p> </StyledButton></li>
<li>{(user?.displayName)
? <>{sliceStr(user.displayName, 10)}<button onClick={handlerLogout}><h2>로그아웃</h2></button></>
: <Link to={`/login`}><h2>로그인</h2> </Link>} </li>
</ul>
</InnerContainer>
</Container>
)
}

const sliceStr = (str:string, n:number) => {
return str.length>=n ? str.slice(0,n+1)+ "..." : str
}

const handlerLogout = () => {
signOut(auth);
}

const StyledButton = styled.button`
color: var(--main-color);
border: 0.8px solid var(--main-color);
border-radius: 5px;
width: 100px;
height: 35px;
background-color: #ffff;
cursor: pointer;
p{
margin: 0 auto;
}
`

const InnerContainer = styled.div`
margin: 0 auto;
max-width: 1200px;
`

const Container = styled.nav`
Expand All @@ -40,6 +80,22 @@ const Container = styled.nav`
font-size: 1rem;
z-index: 10;
background-color: #fff;
h1{
font-size: 1.2rem;
}
h2{
font-size: 0.9rem;
}
.active{
color: var(--main-color);
}
.header__link-wrapper{
display:flex;
justify-content: flex-end;
margin-right: 3rem;
gap: 20px;
align-items: center;
}
`

export default Header
19 changes: 19 additions & 0 deletions src/firebase.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
// Import the functions you need from the SDKs you need
import { initializeApp } from "firebase/app";
import { getAuth } from 'firebase/auth'
// TODO: Add SDKs for Firebase products that you want to use
// https://firebase.google.com/docs/web/setup#available-libraries

// Your web app's Firebase configuration
const firebaseConfig = {
apiKey: "AIzaSyBjMrRAvL85KYQ6okbz7FPTy_iJ6EnSPn0",
authDomain: "fastcampus-wiki.firebaseapp.com",
projectId: "fastcampus-wiki",
storageBucket: "fastcampus-wiki.appspot.com",
messagingSenderId: "38983729603",
appId: "1:38983729603:web:395c72acc46e26b15f3d76"
};

// Initialize Firebase
export const app = initializeApp(firebaseConfig);
export const auth = getAuth(app);
33 changes: 33 additions & 0 deletions src/pages/Authentication.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
.authentication__form{
display: flex;
flex-flow: column;
gap: 30px;
margin-bottom: 40px;
width: 300px;
}

.authentication__form-el{
display: flex;
}

.authentication__form-el label{
flex: 0 0 80px;
height: 30px;
}

.authentication__form-el input{
flex: 0 0 200px;
}

.authentication__form .btn{
width: 175px;
height: 48px;
margin: 20px auto;
background-color: var(--main-color);
color: #fff;
border: none;
border-radius: 5px;
box-sizing: border-box;
cursor: pointer;
}

71 changes: 71 additions & 0 deletions src/pages/Login.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
import React, { useState } from 'react'
import styled from 'styled-components'
import { auth } from '../firebase'
import { Link } from 'react-router-dom';
import { signInWithEmailAndPassword } from 'firebase/auth';
import { useNavigate } from 'react-router-dom';
import './Authentication.css'

const Login = () => {
const [email, setEmail] = useState("");
const [pwd, setPwd] = useState("");
const navigate = useNavigate()

const handleEmail = (e: React.ChangeEvent<HTMLInputElement>) => {
e.preventDefault();
setEmail(e.target.value);
};

const handlePwd = (e: React.ChangeEvent<HTMLInputElement>) => {
e.preventDefault();
setPwd(e.target.value);
};

const handleSubmit = (e: React.FormEvent) => {
e.preventDefault();

signInWithEmailAndPassword(auth, email, pwd)
.then(() => {
alert("로그인 성공");
navigate("/")
})
.catch(e => {
alert(e);
});
};

return (
<Container>
<h1> 로그인</h1>
<form className="authentication__form" onSubmit={handleSubmit}>
<div className="authentication__form-el"><label htmlFor="id"> 이메일 </label> <input type="email" id="email" onChange={handleEmail} value={email} /></div>
<div className="authentication__form-el"><label htmlFor="pwd"> 비밀번호 </label> <input type="password" id="pwd" onChange={handlePwd} value={pwd} /></div>
<button className="btn" type="submit"> 로그인 </button>
</form>
<Link to={`/signup`}> <b>회원가입</b> </Link>
</Container>
)
}

const Container = styled.main`
margin: 0 auto;
margin-top: 60px;
width: 90%;
max-width: 800px;
height: 500px;
border: 1.5px solid var(--main-color);
border-radius: 0.8rem;
padding : 20px 5px;
box-sizing: border-box;
display: flex;
flex-flow: column;
align-items: center;
h1{
margin-bottom:5rem;
}
b{
text-decoration: underline solid black 1.5px ;
}
`

export default Login
75 changes: 75 additions & 0 deletions src/pages/SignUp.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@
import { auth } from '../firebase';
import { createUserWithEmailAndPassword, signOut, updateProfile } from 'firebase/auth';
import React, { useState } from 'react'
import styled from 'styled-components'
import { useNavigate } from 'react-router-dom';
import './Authentication.css'

const SignUp = () => {
const [email, setEmail] = useState("");
const [pwd, setPwd] = useState("");
const [nickname, setNickname] = useState("");
const navigate = useNavigate()

const handleEmail = (e: React.ChangeEvent<HTMLInputElement>) => {
e.preventDefault()
setEmail(e.target.value)
}

const handlePwd = (e: React.ChangeEvent<HTMLInputElement>) => {
e.preventDefault()
setPwd(e.target.value)
}

const handleNickname = (e: React.ChangeEvent<HTMLInputElement>) => {
e.preventDefault()
setNickname(e.target.value)
}

const handleClickCreate = async (e: React.FormEvent) => {
e.preventDefault();
try{
const userCredential = await createUserWithEmailAndPassword(auth, email, pwd)
if(userCredential){
await updateProfile(userCredential.user, {
displayName: nickname
})
}
signOut(auth)
alert('회원가입이 완료됐습니다.')
navigate("/login")
}catch(e){
alert(e)
}
}

return (
<Container>
<h1> 회원 가입</h1>
<form className="authentication__form" onSubmit={handleClickCreate}>
<div className="authentication__form-el"><label htmlFor="id"> 이메일 </label> <input type="email" id="email" onChange={handleEmail} value={email} /></div>
<div className="authentication__form-el"><label htmlFor="pwd"> 비밀번호 </label> <input type="password" id="pwd" onChange={handlePwd} value={pwd} /></div>
<div className="authentication__form-el"><label htmlFor="nickname"> 닉네임 </label> <input type="text" id="nickname" onChange={handleNickname} value={nickname} /></div>
<button className="btn" type="submit"> 회원 가입 </button>
</form>
</Container>
)
}
const Container = styled.main`
margin: 0 auto;
margin-top: 60px;
width: 90%;
max-width: 800px;
height: 500px;
border: 1.5px solid var(--main-color);
border-radius: 0.8rem;
padding : 20px 5px;
box-sizing: border-box;
display: flex;
flex-flow: column;
align-items: center;
h1{
margin-bottom:5rem;
}
`
export default SignUp

0 comments on commit df11a78

Please sign in to comment.