깃허브를 추가한다.
그러면 이러한 팝업창이 뜨는데
아래의 url을 깃허브에 등록해주면 된다.
깃허브 개발자세팅에서 New Oauth App 버튼 클릭!
이름과 홈페이지 URL은 아무거나 입력하면 되고, 콜백 url 은 위에서 파이어베이스에서
발급받은 url 붙여넣기하면됨.
발급받은 ClientID와 Client secrets를 파이어베이스에 입력하면된다.
사용설정이 완료되었다.
그리고 깃허브 연동 버튼을 만들어줄건데 컴포넌트로 만들거임
깃허브 로고를 다운로드 받는다.
public 폴더에 넣음
GithubButton.jsx 파일을 생성해서 깃허브 버튼을 만들어줄거임
import { GithubAuthProvider, signInWithPopup } from "firebase/auth";
import { styled } from "styled-components";
import { auth } from "../firebase";
import { useNavigate } from "react-router-dom";
const Button = styled.span`
margin-top: 50px;
background-color: white;
font-weight: 500;
width: 100%;
color: black;
padding: 10px 20px;
border-radius: 50px;
border: 0;
display: flex;
gap: 5px;
align-items: center;
justify-content: center;
cursor: pointer;
`;
const Logo = styled.img`
height: 25px;
`;
const GithubButton = () => {
const navigate = useNavigate();
const onClick = async () => {
try {
//깃허브인증 제공 객체
//팝업으로 깃허브인증받기
navigate("/");
} catch (error) {
console.error(error);
}
};
return (
<Button onClick={onClick}>
<Logo src="/github-logo.svg" />
Continue with Github
</Button>
);
};
export default GithubButton;
CreateUser.jsx 와 Login.jsx에 추가한다.
GithubButton.jsx
깃허브 인증 제공객체와 팝업으로 인증받기를 추가한다.
const GithubButton = () => {
const navigate = useNavigate();
const onClick = async () => {
try {
const provider = new GithubAuthProvider(); //깃허브인증 제공 객체
await signInWithPopup(auth, provider); //팝업으로 깃허브인증받기
navigate("/");
} catch (error) {
console.error(error);
}
};
return (
<Button onClick={onClick}>
<Logo src="/github-logo.svg" />
Continue with Github
</Button>
);
};
깃허브 인증하면 기본페이지로 이동
이제 Layout을 꾸며줄거다.
Layout.jsx
import React from "react";
import { Link, Outlet, useNavigate } from "react-router-dom";
import styled from "styled-components";
import { auth } from "../firebase";
const Wrapper = styled.div`
display: grid;
gap: 20px;
grid-template-columns: 1fr 4fr;
height: 100%;
padding: 50px 0px;
width: 100%;
max-width: 860px;
`;
const Menu = styled.div`
display: flex;
flex-direction: column;
align-items: center;
gap: 20px;
`;
const MenuItem = styled.div`
cursor: pointer;
display: flex;
align-items: center;
justify-content: center;
border: 2px solid white;
height: 50px;
width: 50px;
border-radius: 50%;
svg {
width: 30px;
color: white;
fill: white;
}
&.log-out {
border-color: tomato;
svg {
fill: tomato;
}
}
`;
const Layout = () => {
const navigate = useNavigate();
const onLogOut = async () => {
const ok = confirm("정말로 로그아웃 하시겠습니까?");
if (ok) {
await auth.signOut();
navigate("/login");
}
};
return (
<>
<Wrapper>
<Menu>
<Link to="/">
<MenuItem>
<svg
fill="none"
stroke="currentColor"
strokeWidth="1.5"
viewBox="0 0 24 24"
aria-hidden="true"
>
<path
strokeLinecap="round"
strokeLinejoin="round"
d="M2.25 12l8.954-8.955c.44-.439 1.152-.439 1.591 0L21.75 12M4.5 9.75v10.125c0 .621.504 1.125 1.125 1.125H9.75v-4.875c0-.621.504-1.125 1.125-1.125h2.25c.621 0 1.125.504 1.125 1.125V21h4.125c.621 0 1.125-.504 1.125-1.125V9.75M8.25 21h8.25"
></path>
</svg>
</MenuItem>
</Link>
<Link to="/profile">
<MenuItem>
<svg
fill="none"
stroke="currentColor"
strokeWidth="1.5"
viewBox="0 0 24 24"
aria-hidden="true"
>
<path
strokeLinecap="round"
strokeLinejoin="round"
d="M15.75 6a3.75 3.75 0 11-7.5 0 3.75 3.75 0 017.5 0zM4.501 20.118a7.5 7.5 0 0114.998 0A17.933 17.933 0 0112 21.75c-2.676 0-5.216-.584-7.499-1.632z"
></path>
</svg>
</MenuItem>
</Link>
<MenuItem onClick={onLogOut} className="log-out">
<svg
fill="none"
stroke="currentColor"
strokeWidth="1.5"
viewBox="0 0 24 24"
aria-hidden="true"
>
<path
strokeLinecap="round"
strokeLinejoin="round"
d="M15.75 9V5.25A2.25 2.25 0 0013.5 3h-6a2.25 2.25 0 00-2.25 2.25v13.5A2.25 2.25 0 007.5 21h6a2.25 2.25 0 002.25-2.25V15M12 9l-3 3m0 0l3 3m-3-3h12.75"
></path>
</svg>
</MenuItem>
</Menu>
<Outlet />
</Wrapper>
</>
);
};
export default Layout;
https://heroicons.dev/?search=home
MenuItem안의 이미지는 위의 사이트에서 복사해서 붙여넣기함
각 버튼을 클릭할 때마다 페이지가 바뀐다.
그리고 레이아웃에서 바로 로그아웃을 구현했으니
Home.jsx 에서는 삭제한다.
import { auth } from "../firebase";
const Home = () => {
//로그아웃 함수
const logOut = () => {
auth.signOut();
};
return <h1>Home</h1>;
};
export default Home;
PostTweetForm.jsx을 생성한다.
import { useState } from "react";
import { styled } from "styled-components";
const Form = styled.form`
display: flex;
flex-direction: column;
gap: 10px;
margin-right: 10px;
`;
const TextArea = styled.textarea`
border: 2px solid white;
padding: 20px;
border-radius: 20px;
font-size: 16px;
color: white;
background-color: black;
width: 100%;
resize: none;
font-family: system-ui, -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto,
Oxygen, Ubuntu, Cantarell, "Open Sans", "Helvetica Neue", sans-serif;
&::placeholder {
font-size: 16px;
}
&:focus {
outline: none;
border-color: #1d9bf0;
}
`;
const AttachFileButton = styled.label`
padding: 10px 0px;
color: #1d9bf0;
text-align: center;
border-radius: 20px;
border: 1px solid #1d9bf0;
font-size: 14px;
font-weight: 600;
cursor: pointer;
`;
const AttachFileInput = styled.input`
display: none;
`;
const SubmitBtn = styled.input`
background-color: #1d9bf0;
color: white;
border: none;
padding: 10px 0px;
border-radius: 20px;
font-size: 16px;
cursor: pointer;
&:hover,
&:active {
opacity: 0.9;
}
`;
const PostTweetForm = () => {
const [isLoading, setLoading] = useState(false);
const [tweet, setTweet] = useState("");
const [file, setFile] = useState(null);
const onChange = (e) => {
setTweet(e.target.value);
};
const onFileChange = (e) => {
const { files } = e.target;
if (files && files.length === 1) {
setFile(files[0]);
}
};
return (
<Form>
<TextArea
rows={5}
maxLength={180}
onChange={onChange}
value={tweet}
placeholder="What is happening?!"
/>
<AttachFileButton htmlFor="file">
{file ? "Photo added ✅" : "Add photo"}
</AttachFileButton>
<AttachFileInput
onChange={onFileChange}
type="file"
id="file"
accept="image/*"
/>
<SubmitBtn
type="submit"
value={isLoading ? "Posting..." : "Post Tweet"}
/>
</Form>
);
};
export default PostTweetForm;
Home.jsx에 추가한다.
import PostTweetForm from "../components/PostTweetForm";
const Home = () => {
return (
<h1>
<PostTweetForm />
</h1>
);
};
export default Home;
이미지 파일만 등록이 가능하고 파일이 입력되면 다시 랜더링되며니서 Photo added 가 나오게됨
'FRONTEND > React' 카테고리의 다른 글
[Nwitter-Fire] 프로필 페이지 유저 아바타 / 프로필 업데이트/ 프로필 이름 수정 (1) | 2023.12.11 |
---|---|
[Nwitter-Fire] 파이어 스토어 스토리지 사용설정 / 트윗 저장/이미지 저장 / 타임라인 생성 및 실시간 업데이트/ 트윗 삭제 (0) | 2023.12.08 |
[Nwitter-Fire] ProtectedRoute 비인증시 블록 및 로그인 기능 (1) | 2023.12.08 |
[Nwitter-Fire] SNS 프로젝트 시작하기 /styled 컴포넌트/ firebase9 유저인증 (1) | 2023.12.08 |
[슈퍼챗] firebase9 활용한 슈퍼챗 만들기 (2) | 2023.12.07 |