components
include
page
login
service
firebase / authLogic
redux
toast
userAuth
App.jsx
/ → Login.jsx
/maker → Market.jsx
<네임카드 작성 - App.jsx>
import { Route, Routes } from "react-router-dom";
import "./App.css";
import styled from "styled-components";
import Login from "./components/login/Login";
import CardManager from "./components/page/CardManager";
const AppDiv = styled.div`
width: 100%;
height: 100vh;
display: flex;
justify-content: center;
align-item: center;
background-color: #FFF3E2;
`
const App = () => {
return (
<>
<AppDiv>
<Routes>
<Route path="/" element={<Login />} />
<Route path="/manager" element={<CardManager />} />
</Routes>
</AppDiv>
</>
);
}
export default App;
<네임카드 작성 - Login.jsx>
import React, { useState } from 'react'
import styled from 'styled-components'
import Header from '../include/Header'
import Footer from '../include/Footer'
import { useNavigate } from 'react-router-dom'
import { useDispatch, useSelector } from 'react-redux'
import { setToastMsg } from '../../redux/toastStatus/action'
import { loginGoogle } from '../../service/authLogic'
const LoginDiv = styled.div`
width: 30em;
background-color: white;
text-align: center;
display: flex;
flex-direction: column;
justify-content: center;
`
const ListUl = styled.ul`
width: 100%;
display: flex;
flex-direction: column;
padding: 0.5rem;
list-style: none;
`
const ItemLi = styled.li`
margin-bottom: 0.5em;
`
const BtnLogin = styled.button`
width: 100%;
height: 2.5em;
font-size: 1.2rem;
border-radius: 1.2rem;
background-color: transparent;
color: #E74646;
cursor: pointer;
border: 0.2rem solid #FA9884;
outline: 0;
&:hover{
background-color: #FA9884;
color: #FFF3E2;
}
`
const Login = () => {
// 구글 로그인 성공시 CardManager화면으로 이동처리에 사용
const navigate = useNavigate()
// 구글 로그인 진행 중 에러 발생하면 에러 메시지 출력 처리 위해 사용
const dispatch = useDispatch()
// 구글 로그인시 auth와 googleProvider 파라미터로 전송위해
const userAuth = useSelector(store => store.userAuth)
const [userId, setUserId] = useState()
const onLogin = async() => {
try {
const result = await loginGoogle(userAuth.auth, userAuth.googleProvider)
console.log(result)
console.log(result.uid)
setUserId(result.uid)
window.localStorage.setItem("userId", result.uid)
navigate('/manager')
// window.location.reload()
} catch (error) {
dispatch(setToastMsg(error+': 로그인 오류'))
}
}
return (
<LoginDiv>
<Header />
<section>
<h1>Login</h1>
<ListUl>
<ItemLi><BtnLogin onClick={onLogin}>Google</BtnLogin></ItemLi>
<ItemLi><BtnLogin>Github</BtnLogin></ItemLi>
</ListUl>
</section>
<Footer />
</LoginDiv>
)
}
export default Login
<네임카드 작성 - Header.jsx>
import React, { useEffect, useState } from 'react'
import { useSelector } from 'react-redux'
import { useNavigate } from 'react-router-dom'
import styled from 'styled-components'
import { logout } from '../../service/authLogic'
const HeaderDiv = styled.div`
width: 100%;
text-align: center;
background-color: #FFE5CA;
padding: 0.5em;
position: relative;
`
const Img = styled.img`
width: 3em;
`
const BtnLogout = styled.button`
position: absolute;
right: 3em;
top: 1em;
padding: 0.8em;
border-radius: 20%;
background-color: #FA9884;
color: #FFF3E2;
outline: 0;
border: 0;
cursor: pointer;
`
const TitleH1 = styled.h1`
color: #E74646;
`
const Header = () => {
const navigate = useNavigate()
const {userAuth} = useSelector(state => state)
const [userId, setUserId] = useState()
useEffect(() => {
setUserId(localStorage.getItem("userId"))
}, [])
const onLogout = () => {
console.log('onLogout')
logout(userAuth.auth)
navigate('/')
// window.location.reload()
}
return (
<HeaderDiv>
{userId && <BtnLogout onClick={onLogout}>Logout</BtnLogout>}
<Img src='/images/icon-palette.png' alt='logo' />
<TitleH1>Name Card</TitleH1>
</HeaderDiv>
)
}
export default Header
<네임카드 작성 - Footer.jsx>
import React from 'react'
import styled from 'styled-components'
const FooterDiv = styled.div`
width: 100%;
background-color: #FA9884;
text-align: center;
`
const TitleP = styled.p`
color: #FFF3E2;
`
const Footer = () => {
return (
<FooterDiv>
<TitleP>No pain, No gain</TitleP>
</FooterDiv>
)
}
export default Footer
<네임카드 작성 - CardManager.jsx>
import React, { useState } from 'react'
import Header from '../include/Header'
import Footer from '../include/Footer'
import styled from 'styled-components'
import Preview from './Preview'
import CardEditor from './CardEditor'
const MakerDiv = styled.div`
width: 100%;
height: 100%;
max-width: 80rem;
display: flex;
flex-direction: column;
background-color: white;
`
const ContainerDiv = styled.div`
display: flex;
flex: 1;
min-height: 0;
`
const CardManager = () => {
const [cards, setCards] = useState({
'1':{
id: '1',
name: '이성계',
company: 'Samsung',
theme: 'dark',
title: 'Software Engineer',
email: 'lee@gmail.com',
message: 'go for it',
fileName: 'lee',
fileURL: null,
},
'2':{
id: '2',
name: '김유신',
company: 'Cupang',
theme: 'light',
title: 'Software Engineer',
email: 'kim@gmail.com',
message: 'I can do it',
fileName: 'kim',
fileURL: 'kim.png',
},
'3':{
id: '3',
name: '유재석',
company: 'MBC',
theme: 'colorful',
title: 'Software Engineer',
email: 'you@gmail.com',
message: 'we are the world',
fileName: 'you',
fileURL: null,
}
});
return (
<MakerDiv>
<Header />
<ContainerDiv>
<CardEditor cards={cards} />
<Preview cards={cards} />
</ContainerDiv>
<Footer />
</MakerDiv>
)
}
export default CardManager
<네임카드 작성 - Preview.jsx>
import React from 'react'
import styled from 'styled-components'
import Card from './Card'
const PreviewDiv = styled.div`
flex-basis: 50%;
overflow: auto;
`
const TitleH1 = styled.h1`
width: 100%;
text-align: center;
margin-bottom: 1em;
color: #E74646;
`
const CardsUl = styled.ul`
width: 100%;
height: 100%;
padding: 0.5em 2em;
display: flex;
flex-direction: column;
align-item: center;
`
const Preview = ({cards}) => {
return (
<PreviewDiv>
<TitleH1>
CardPreview
</TitleH1>
<CardsUl>
{
Object.keys(cards).map((key) => (
<Card key={key} card={cards[key]} />
))
}
</CardsUl>
</PreviewDiv>
)
}
export default Preview
<네임카드 작성 - Card.jsx>
import React from 'react'
import styled from 'styled-components'
import styles from './card.module.css'
const CardLi = styled.li`
display: flex; /* 이름같은것들 이미지 옆으로 보내기 */
align-items: center; /* flex속성일때 사용 가능 */
width: 100%;
background-color: #FFE5CA;
margin-bottom: 0.5em;
border-radius: 1em;
padding: 0.2em 0;
box-shadow: 6px 6px 8px 0px rgba(217,217,217,1);
max-width: 30em; /* 넓이 제약 */
`
const AvatarImg = styled.img`
width: 10em;
height: 10em;
padding: 1em;
border-radius:20%
margin-right: 1em; /* 이미지와 글자사이에 마진 */
margin-left: 0.5em; /* 이미지 앞쪽에 마진 */
`
const NameH1 = styled.h1`
margin: 0;
font-size: 1.2rem;
margin-bottom: 0.2em;
`
const CompanyP = styled.p`
margin: 0;
font-size: 0.8rem;
margin-bottom: 1em;
`
const TitleP = styled.p`
margin: 0;
font-size: 0.8rem;
margin-bottom: 1em;
`
const EmailP = styled.p`
margin: 0;
font-size: 0.8rem;
margin-bottom: 1em;
`
const MessageP = styled.p`
margin: 0;
font-size: 0.8rem;
margin-bottom: 1em;
`
const Card = ({card}) => {
const DEFAULT_IMG = '/images/icon-coin.png'
const {name, company, title, email, message, theme } = card
const getStyles = (theme) => {
switch(theme) {
case 'dark':
return styles.dark;
case 'light':
return styles.light;
case 'colorful':
return styles.colorful;
default:
throw new Error(`unknown theme:${theme}`)
}
}
return (
<CardLi className={`${styles.card} ${getStyles(theme)}`}>
<AvatarImg src={DEFAULT_IMG} alt='profile image' />
<div className={{width: '100%'}}>
<NameH1>{name}</NameH1>
<CompanyP>{company}</CompanyP>
<TitleP>{title}</TitleP>
<EmailP>{email}</EmailP>
<MessageP>{message}</MessageP>
</div>
</CardLi>
)
}
export default Card
.<네임카드 작성 - CardEditor.jsx>
import React from 'react'
import CardEditorForm from './CardEditorForm'
import CardAddForm from './CardAddForm'
import styled from 'styled-components'
const EditorDiv = styled.div`
flex-basis: 50%;
border-right: 2px solid #FFE5CA;
padding: 0.5em 2em;
overflow-y: auto;
`
const TitleH1 = styled.h1`
width: 100%;
text-align: center;
margin-bottom: 1em;
color: #E74646;
`
const CardEditor = ({cards}) => {
return (
<EditorDiv>
<TitleH1>Card Editor</TitleH1>
{Object.keys(cards).map(key => (
<CardEditorForm key={key} />
))
}
<CardAddForm />
</EditorDiv>
)
}
export default CardEditor
'국비학원 > 수업기록' 카테고리의 다른 글
국비 지원 개발자 과정_Day93 (0) | 2023.04.12 |
---|---|
국비 지원 개발자 과정_Day92 (0) | 2023.04.11 |
국비 지원 개발자 과정_Day90 (0) | 2023.04.06 |
국비 지원 개발자 과정_Day89 (0) | 2023.04.05 |
국비 지원 개발자 과정_Day88 (0) | 2023.04.04 |
댓글