Commit 1b8d7cda authored by Yoon, Daeki's avatar Yoon, Daeki 😅
Browse files

Merge branch 'young' into master

parents cada8594 5f25610a
<?xml version="1.0" encoding="iso-8859-1"?>
<!-- Generator: Adobe Illustrator 19.0.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
<svg version="1.1" id="Capa_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
viewBox="0 0 53 53" style="enable-background:new 0 0 53 53;" xml:space="preserve">
<path style="fill:#E7ECED;" d="M18.613,41.552l-7.907,4.313c-0.464,0.253-0.881,0.564-1.269,0.903C14.047,50.655,19.998,53,26.5,53
c6.454,0,12.367-2.31,16.964-6.144c-0.424-0.358-0.884-0.68-1.394-0.934l-8.467-4.233c-1.094-0.547-1.785-1.665-1.785-2.888v-3.322
c0.238-0.271,0.51-0.619,0.801-1.03c1.154-1.63,2.027-3.423,2.632-5.304c1.086-0.335,1.886-1.338,1.886-2.53v-3.546
c0-0.78-0.347-1.477-0.886-1.965v-5.126c0,0,1.053-7.977-9.75-7.977s-9.75,7.977-9.75,7.977v5.126
c-0.54,0.488-0.886,1.185-0.886,1.965v3.546c0,0.934,0.491,1.756,1.226,2.231c0.886,3.857,3.206,6.633,3.206,6.633v3.24
C20.296,39.899,19.65,40.986,18.613,41.552z"/>
<g>
<path style="fill:#556080;" d="M26.953,0.004C12.32-0.246,0.254,11.414,0.004,26.047C-0.138,34.344,3.56,41.801,9.448,46.76
c0.385-0.336,0.798-0.644,1.257-0.894l7.907-4.313c1.037-0.566,1.683-1.653,1.683-2.835v-3.24c0,0-2.321-2.776-3.206-6.633
c-0.734-0.475-1.226-1.296-1.226-2.231v-3.546c0-0.78,0.347-1.477,0.886-1.965v-5.126c0,0-1.053-7.977,9.75-7.977
s9.75,7.977,9.75,7.977v5.126c0.54,0.488,0.886,1.185,0.886,1.965v3.546c0,1.192-0.8,2.195-1.886,2.53
c-0.605,1.881-1.478,3.674-2.632,5.304c-0.291,0.411-0.563,0.759-0.801,1.03V38.8c0,1.223,0.691,2.342,1.785,2.888l8.467,4.233
c0.508,0.254,0.967,0.575,1.39,0.932c5.71-4.762,9.399-11.882,9.536-19.9C53.246,12.32,41.587,0.254,26.953,0.004z"/>
</g>
<g>
</g>
<g>
</g>
<g>
</g>
<g>
</g>
<g>
</g>
<g>
</g>
<g>
</g>
<g>
</g>
<g>
</g>
<g>
</g>
<g>
</g>
<g>
</g>
<g>
</g>
<g>
</g>
<g>
</g>
</svg>
.nav-tabs .nav-item.nav-link {
color: silver !important;
}
.nav-tabs .nav-item.nav-link.active {
color:slateblue !important;
}
.list-group-item-action{
border-top: none;
}
import React, { useState, useEffect } from 'react';
import { Row, Col, Button, Tabs, Tab, Form } from 'react-bootstrap';
import styled from 'styled-components';
import ClosedList from '../Components/ClosedList';
import OpenList from '../Components/OpenList';
import Menu from '../Components/Menu';
import { io } from "socket.io-client";
import Chat from "../Components/Chat";
import RoomMake from "../Components/RoomMake"
import EnterRoom from "../Components/EnterRoom"
import axios from 'axios';
import "./Home.css"
import catchErrors from '../utils/catchErrors';
const socket = io();
const INIT_ROOM = {
roomName: '',
interest: '',
roomId: '',
member: '',
}
const INIT_LIST = [{
interest: '',
isOpen: '',
memeber: [],
roomId: '',
roomName: '',
}]
const INIT_UNREAD = {
roomCode: '',
unreadcount: '',
}
function Home() {
const userName = sessionStorage.getItem('name')
const userId = sessionStorage.getItem('userId')
const realTime = new Date().toISOString()
const [error, setError] = useState('')
const [checknew, setChecknew] = useState('')
const [unreadnumber, setUnreadnumber] = useState(INIT_UNREAD)
const [showModal, setShowModal] = useState(false);
const [showEnter, setShowEnter] = useState(false);
const [chat, setChat] = useState(false);
const [open, setOpen] = useState(false);
const [room, setRoom] = useState(INIT_ROOM)
const [show, setShow] = useState(false)
//소켓
const [singleChat, setSingleChat] = useState('')
const [recievedMsg, setRecievedMsg] = useState('')
const [roomCode, setRoomCode] = useState('')
const [sysmsg, setSysmsg] = useState('')
const [roomName, setRoomName] = useState('')
const [singleUser, setSingleUser] = useState('')
const [recievedUser, setRecievedUser] = useState('')
const [singleImg, setSingleImg] = useState('')
const [recievedImg, setRecievedImg] = useState('')
const [singleTime, setSingleTime] = useState('')
const [recievedTime, setRecievedTime] = useState('')
const handleCloseModal = () => {
setShowModal(false);
getClosedList()
getOpenList()
}
const handleShowModal = () => setShowModal(true);
const handleCloseEnter = () => setShowEnter(false);
const handleShowEnter = () => setShowEnter(true);
const handleChato = () => setChat(true);
const handleChatc = () => setChat(false);
const [closedlist, setClosedList] = useState(INIT_LIST);
const [openlist, setOpenlist] = useState([])
//SOCKET 관련 시작
async function enterChatRoom(rCode) { //방 입장하기
socket.emit('joinRoom', rCode)
socket.emit('newUser', { rmIf: rCode, userInfo: userName })
setShow(true)
console.log(`joinRoom : ${rCode} 입장`)
console.log('HomePage/enterChatRoom 끝났습니다')
}
function closeChatRoom(rCode) {
socket.emit('closeRoom', rCode)
console.log(`${rCode}방 보기 중단`)
}
async function exitRoom(roomId) {
const response = await axios.get('/users/check', { params: { '_id': userId } })
const userNick = response.data.nickname;
await axios.put('/room/deleteMem', { userId: userId, roomId: roomId })
setSysmsg(`${userNick}님이 나갔습니다.`)
setRoomCode("")
}
async function getClosedList() {
const userid = sessionStorage.getItem('userId')
let res = await axios.get('/room/closedlist', { params: { '_id': userid } })
setClosedList(res.data)
}
async function getOpenList() {
let res = await axios.get('/room/openlist')
setOpenlist(res.data)
}
async function openListroom(roomId) {
const roomInf = await axios.get('/room/changeMem', { params: { 'roomId': roomId } })
setRoom(roomInf.data[0])
setShow(false)
setOpen(true)
}
//오픈채팅방에서 참가하기
async function attendListRoom() {
const roomId = room.roomId
const tf = await axios.put('/room/changeMem', { userId: userId, roomId: roomId })
const response = await axios.get('/users/check', { params: { '_id': userId } })
const userNick = response.data.nickname;
if (tf.data) {
alert('참가되었습니다.')
setSysmsg(`${userNick}님이 들어왔습니다.`)
getClosedList()
recordEntryLog()
} else {
alert('이미 참가된 방입니다.')
}
}
async function recordEntryLog() {
const leaveInfo = { userId: userId, roomCode: roomCode, leaveTime: realTime }
try {
const check = await axios.get('/room/entrylog', { params: leaveInfo })
if (check.data) { //있으면 put으로
await axios.put('/room/entrylog', leaveInfo)
} else { //없으면 post
await axios.post('/room/entrylog', leaveInfo)
}
} catch (error) {
catchErrors(error, setError)
}
}
function enterButton() {
setOpen(false)
}
const sendMsg = (e) => {
e.preventDefault()
}
useEffect(() => {
getClosedList();
getOpenList();
}, [roomCode]);
useEffect(() => {
if (!(singleChat === "")) {
socket.emit("chat", {
roomInfo: roomCode,
sendInfo: {
msg: singleChat,
sender: singleUser,
img: singleImg,
time: singleTime
}
})
setSingleChat("")
}
}, [singleChat])
useEffect(() => {
if (!(sysmsg === '')) {
socket.emit("chat", {
roomInfo: roomCode,
sendInfo: {
msg: sysmsg,
sender: "system",
}
})
setSysmsg('')
}
}, [sysmsg])
const INIT_LEFT = {
userId: '',
roomCode: '',
now: '',
}
const [leftInfo, setLeftInfo] = useState(INIT_LEFT)
async function unreadMessage() {
const userId = sessionStorage.getItem('userId')
let leaveInfo = []
try {
for (let i = 0; i < closedlist.length; i++) {
leaveInfo.push({ userId: userId, roomCode: closedlist[i].roomId, now: 0 })
}
for (let i = 0; i < closedlist.length; i++) {
if (leaveInfo[i].roomCode === roomCode) {
leaveInfo[i].now = '보는중'
} else {
leaveInfo[i].now = 0
}
}
setUnreadnumber([''])
const respond = await axios.get('/room/unreadMessage', { params: leaveInfo })
setUnreadnumber(respond.data)
setLeftInfo(leaveInfo)
} catch (error) {
console.log(error)
}
}
useEffect(() => {
socket.on("sendedMSG", (sendInfo) => {
setRecievedTime(sendInfo.time)
setRecievedImg(sendInfo.img)
setRecievedUser(sendInfo.sender)
setRecievedMsg(sendInfo.msg)
})
socket.on('checking', (check) => {
console.log('클라이언트', check)
setChecknew(check)
})
}, [])
return (
<div style={{ weight: "100vw", height: "100vh", backgroundColor: "" }}>
<Menu style={{ weight: "100%", height: "10%" }} />
<Row className="mr-0" style={{ weight: "100%", height: "80%" }}>
<Col className="list" md={5}>
<Sdiv chat={chat} open={open}>
<Tabs defaultActiveKey="closed" id="uncontrolled-tab-example" >
<Tab eventKey="closed" title="내 채팅" onClick={handleChato} >
<ClosedList closedlist={closedlist} leftInfo={leftInfo} checknew={checknew} unreadMessage={unreadMessage} unreadnumber={unreadnumber} setUnreadnumber={setUnreadnumber} userId={userId} singleChat={singleChat} recievedMsg={recievedMsg} enterChatRoom={enterChatRoom} setRoomCode={setRoomCode} setRoomName={setRoomName} roomCode={roomCode} closeChatRoom={closeChatRoom} />
</Tab>
<Tab eventKey="open" title="공개방" onClick={handleChatc}>
<OpenList openlist={openlist} enterChatRoom={enterChatRoom} openListroom={openListroom} setRoomCode={setRoomCode} setRoomName={setRoomName} roomCode={roomCode} closeChatRoom={closeChatRoom} />
</Tab>
</Tabs>
</Sdiv>
</Col>
<Col style={{ padding: "5px", marginLeft: "15px" }}>
{show ? <>
{chat ? <Chat leftInfo={leftInfo} setLeftInfo={setLeftInfo} handleChatc={handleChatc} sendMsg={sendMsg} singleChat={singleChat} singleUser={singleUser} singleImg={singleImg} singleTime={singleTime} recievedMsg={recievedMsg} recievedUser={recievedUser} recievedImg={recievedImg} recievedTime={recievedTime} setSingleChat={setSingleChat} setSingleUser={setSingleUser} setSingleImg={setSingleImg} setSingleTime={setSingleTime} setRecievedMsg={setRecievedMsg} roomCode={roomCode} roomName={roomName} closeChatRoom={closeChatRoom} exitRoom={exitRoom} setRoomCode={setRoomCode} />
: <div style={{ position: "fixed", bottom: "20px", right: "30px" }}>
<Button style={{ borderColor: "#9174ad", backgroundColor: "#9174ad", color: 'white' }} onClick={handleShowModal} size="lg" block>생성</Button>
<Button style={{ borderColor: "#9174ad", backgroundColor: "#9174ad", color: 'white' }} onClick={handleShowEnter} size="lg" block>참가</Button>
</div>} </>
: <> {open ?
<div className="vh-90 flex-column align-items-center justify-content-center mt-2" variant="dark">
<div className="d-flex justify-content-center">
<div className="mt-5 p-5 mr-2" style={{ display: "flex", flexDirection: "column", borderStyle: "solid", borderRadius: "5px", borderColor: "#4A5D7E", backgroundColor: "#FFFFFF", padding: '15px', position: "relative" }}>
<h2 className="d-flex justify-content-center mb-3">현재 {room.roomName} 입니다.</h2>
<h5> 관심분야 : {room.interest}</h5>
<h5> 참여인원 : {room.member.length}</h5>
<h5 className="mb-3"> 방코드(방코드를 통해서도 참여할 있습니다.) : {room.roomId}</h5>
<Row className='justify-content-center'>
<Button variant="outline" style={{ border: "3px solid", borderColor: "#b49dc9" }} size="sm" className="mr-4" onClick={enterButton}>뒤로가기</Button>
<Button variant="outline" style={{ border: "3px solid", borderColor: "#b49dc9" }} size="sm" className="ml-4" type='submit' onClick={attendListRoom}>참가</Button>
</Row>
</div>
</div>
</div> : <div style={{ position: "fixed", bottom: "20px", right: "30px" }}>
<Button style={{ borderColor: "#9174ad", backgroundColor: "#9174ad", color: 'white' }} onClick={handleShowModal} size="lg" block>생성</Button>
<Button style={{ borderColor: "#9174ad", backgroundColor: "#9174ad", color: 'white' }} onClick={handleShowEnter} size="lg" block>참가</Button>
</div>} </>}
</Col>
</Row>
<RoomMake showModal={showModal} handleCloseModal={handleCloseModal} />
<EnterRoom showEnter={showEnter} enterChatRoom={enterChatRoom} handleCloseEnter={handleCloseEnter} handleChato={handleChato} setRoomCode={setRoomCode} setRoomName={setRoomName} sysmsg={sysmsg} setSysmsg={setSysmsg} />
</div>
);
}
const Sdiv = styled.div`
@media screen and (max-width: 768px) {
display: ${({ chat, open }) => {
return (chat || open) ? 'none' : 'block'
}}
}
`
export default Home;
\ No newline at end of file
import React, { useState, useEffect } from 'react';
import axios from 'axios'
import { Button, Form, Container, Spinner, Alert } from 'react-bootstrap';
import catchErrors from '../utils/catchErrors'
import { Redirect } from 'react-router-dom'
import { handleLogin } from '../utils/auth'
import Menu from '../Components/Menu';
const INIT_USER = {
email: '',
password: '',
}
function LogIn() {
const [user, setUser] = useState(INIT_USER)
const [disabled, setDisabled] = useState(true)
const [error, setError] = useState('')
const [success, setSucces] = useState(false)
const [loading, setLoading] = useState(false)
useEffect(() => {
const isUser = Object.values(user).every(el => Boolean(el))
isUser ? setDisabled(false) : setDisabled(true)
}, [user])
function handleChange(event) {
const { name, value } = event.target
setUser({ ...user, [name]: value })
}
async function handleSubmit(event) {
event.preventDefault()
try {
setLoading(true)
setError('')
let res = await axios.post('/auth/login', user)
handleLogin(res.data)
setSucces(true)
} catch (error) {
catchErrors(error, setError)
} finally {
setLoading(false)
}
//server쪽에서 json형식으로 보낼것임
}
//success시 링크이동
if (success) {
console.log('success', success)
alert('로그인 되었습니다!')
return <Redirect to='/' />
}
return (
<>
<Menu />
<Form onSubmit={handleSubmit} className="vh-90 flex-column align-items-center justify-content-center mt-2" variant="dark">
<div className="d-flex justify-content-center">
<div className="mt-5 p-5 mr-2" style={{ display: "flex", flexDirection: "column", borderStyle: "solid", borderRadius: "5px", borderColor: "#4A5D7E", backgroundColor: "#FFFFFF", padding: '15px', position: "relative" }}>
<h2 className="text-center">로그인</h2>
<Form.Group controlId="formGroupEmail">
<Form.Label>이메일</Form.Label>
<Form.Control
required
type="email"
name="email"
onChange={handleChange}
value={user.email}
placeholder="이메일을 입력해주세요" />
<Form.Control.Feedback type="invalid">
필수 정보입니다! 이메일을 입력해주세요!
</Form.Control.Feedback>
</Form.Group>
<Form.Group controlId="formGroupPassword">
<Form.Label>비밀번호</Form.Label>
<Form.Control
required
type="password"
name="password"
onChange={handleChange}
value={user.password}
placeholder="비밀번호를 입력해주세요" />
<Form.Control.Feedback type="invalid">
필수 정보입니다! 비밀번호를 입력해주세요!
</Form.Control.Feedback>
</Form.Group>
<Button
disabled={disabled || loading}
type="submit"
variant="outline"
size="lg"
className="mr-4"
style={{ border: "3px solid", borderColor: "#b49dc9", background: 'white', font: 'dark' }}
block>
{loading && <Spinner as='span' animation='border' size='sm' role='status' aria-hidden='true' style={{ color: "#b49dc9" }} />} {' '} 로그
</Button>
{error && <Alert variant='danger'>
{error}
</Alert>}
</div>
</div>
</Form>
</>
);
}
export default LogIn
\ No newline at end of file
import React, { useState, useEffect } from 'react'
import Menu from '../Components/Menu';
import { Image, Button, Container, Form, Row, Col } from 'react-bootstrap';
import axios from 'axios'
import catchErrors from '../utils/catchErrors'
import { isAuthenticated } from '../utils/auth';
const INIT_USER = {
username: '',
email: '',
nickname: '',
imageUrl: []
}
function ProfilePage() {
const [user, setUser] = useState(INIT_USER)
const [error, setError] = useState('')
const [hidden, setHidden] = useState(true)
const [changed, setChanged] = useState(false)
const [selectedImg, setSelectedImg] = useState('')
const userId = isAuthenticated()
async function getProfile(userId) {
try {
const response = await axios.get(`/users/${userId}`)
setUser(response.data)
} catch (error) {
catchErrors(error, setError)
}
}
function handleSubmitHidVis(e) {
e.preventDefault()
if (hidden) {
setHidden(false)
} else {
setHidden(true)
}
}
function handleChange(e) {
const { name, value, files } = e.target
if (files) {
setUser({ ...user, [name]: files })
} else {
setUser({ ...user, [name]: value })
}
setChanged(true)
if (files) {
let reader = new FileReader()
reader.onload = function (e) {
setSelectedImg(e.target.result)
}
reader.readAsDataURL(e.target.files[0])
}
}
async function handleSubmit(e) {
e.preventDefault()
if (changed) {
const formData = new FormData()
if (user.imageUrl) {
formData.append('imageUrl', user.imageUrl[0])
}
formData.append('newNickname', user.nickname) //얘네는 req.body로 들어감
try {
if (userId) {
await axios.put(`/users/${userId}`, formData)
alert('저장되었습니다.')
window.location.reload()
}
} catch (error) {
catchErrors(error, setError)
}
}
else {
alert('변경사항이 없습니다.')
}
}
useEffect(() => {
getProfile(userId)
}, [userId])
return (
<>
<Menu />
<Container>
<Row >
<Col sm={4}>
<Row className='justify-content-center'>
{!selectedImg ? <Image src={user.profileimg && `/images/${user.profileimg}`} style={{ width: "300px", height: "300px" }} roundedCircle /> :
<Image src={selectedImg} style={{ width: "300px", height: "300px" }} roundedCircle />}
</Row>
<Row className='ml-3 mt-3 justify-content-center'>
<Form className="d-flex">
<Form.Group>
<Form.Label>프로필 사진 변경</Form.Label>
<Form.Control type='file' name='imageUrl' onChange={handleChange} accept='image/*' />
</Form.Group>
</Form>
</Row>
</Col>
<Col sm={8}>
<Row className='m-5 justify-content-center'>
<h2>{user.username}님의 프로필 정보</h2>
</Row>
<Row className="m-3 justify-content-flex-start" style={{ fontWeight: "bold", fontSize: "large" }}>
<Col xs={3}>이름 :</Col>
<Col xs={6}>{user.username}</Col>
</Row>
<Row className="m-3 justify-content-flex-start" id="nickname" style={{ fontWeight: "bold", fontSize: "large" }}>
<Col xs={3}>별명 :</Col>
<Col xs={6} hidden={!hidden}>
{user.nickname}
</Col>
<Col xs={6} hidden={hidden}>
<Form>
<Form.Control defaultValue={user.nickname} name='nickname' style={{ width: "110%" }} onChange={handleChange} />
</Form>
</Col>
<Col xs={3}>
<Form className="d-flex" onSubmit={handleSubmitHidVis}>
<Button className="ml-3 d-flex justify-content-end" variant="outline" style={{ border: "3px solid", borderColor: "#b49dc9", background: 'white' }} size="sm" type='submit'>수정</Button>
</Form>
</Col>
</Row>
<Row className="m-3" style={{ fontWeight: "bold", fontSize: "large" }}>
<Col xs={3}>이메일 : </Col>
<Col xs={6}>{user.email}</Col>
</Row>
<Row className='m-3 justify-content-center'>
<Form onSubmit={handleSubmit}>
<Button size="sm" className="mr-4" type='submit' variant="outline" style={{ border: "3px solid", borderColor: "#9174ad", background: 'white' }}>저장</Button>
<Button href="/" size="sm" className="ml-4" variant="outline" style={{ border: "3px solid", borderColor: "#9174ad", background: 'white' }}> 화면으로</Button>
</Form>
</Row>
</Col>
</Row>
</Container>
</>
)
}
export default ProfilePage
import React, { useState, useEffect } from 'react';
import axios from 'axios'
import { Button, Form, Container, Alert, Spinner } from 'react-bootstrap';
import catchErrors from '../utils/catchErrors';
import { Redirect } from 'react-router-dom';
import Menu from '../Components/Menu';
const INIT_USER = {
username: '',
nickname: '',
email: '',
password: '',
}
function SingUp() {
//const [validated, setValidated] = useState(false);
const [user, setUser] = useState(INIT_USER)
const [error, setError] = useState('')
const [disabled, setDisabled] = useState(true)
const [success, setSuccess] = useState(false)
const [loading, setLoading] = useState(false)
useEffect(() => {
const isUser = Object.values(user).every(el => Boolean(el))
isUser ? setDisabled(false) : setDisabled(true)
}, [user])
function handleChange(event) {
const { name, value } = event.target
setUser({ ...user, [name]: value })
}
async function handleSubmit(event) {
event.preventDefault();
try {
setLoading(true)
setError('')
await axios.post('/users/signup', user)
setSuccess(true)
} catch (error) {
catchErrors(error, setError)
} finally {
setLoading(false)
}
}
if (success) {
console.log('success', success)
alert('회원가입이 완료되었습니다!')
return <Redirect to='/login' />
}
return (
<>
<Menu />
<Form onSubmit={handleSubmit} className="vh-90 flex-column align-items-center justify-content-center mt-2" variant="dark">
<div className="d-flex justify-content-center">
<div className="mt-5 p-5 mr-2" style={{ display: "flex", flexDirection: "column", borderStyle: "solid", borderRadius: "5px", borderColor: "#4A5D7E", backgroundColor: "#FFFFFF", padding: '15px', position: "relative" }}>
<h2 className="text-center ">회원가입</h2>
<Form.Group controlId="formGroupUsername">
<Form.Label>이름</Form.Label>
<Form.Control
required
type="text"
name="username"
onChange={handleChange}
value={user.username}
placeholder="이름을 입력해주세요" />
<Form.Control.Feedback type="invalid">
필수 정보입니다! 이름을 입력해주세요!
</Form.Control.Feedback>
</Form.Group>
<Form.Group controlId="formGroupNickname">
<Form.Label>별명</Form.Label>
<Form.Control
required
type="text"
name="nickname"
onChange={handleChange}
value={user.nickname}
placeholder="별명을 입력해주세요" />
<Form.Control.Feedback type="invalid">
필수 정보입니다! 별명을 입력해주세요!
</Form.Control.Feedback>
</Form.Group>
<Form.Group controlId="formGroupEmail">
<Form.Label>이메일</Form.Label>
<Form.Control
required
type="email"
name="email"
onChange={handleChange}
value={user.email}
placeholder="이메일을 입력해주세요" />
<Form.Control.Feedback type="invalid">
필수 정보입니다! 이메일을 입력해주세요!
</Form.Control.Feedback>
</Form.Group>
<Form.Group controlId="formGroupPassword">
<Form.Label>비밀번호</Form.Label>
<Form.Control
required
type="password"
name="password"
onChange={handleChange}
value={user.password}
placeholder="비밀번호를 입력해주세요" />
<Form.Control.Feedback type="invalid">
필수 정보입니다! 비밀번호를 입력해주세요!
</Form.Control.Feedback>
</Form.Group>
<Button
disabled={disabled}
type='submit'
variant="outline"
size="lg"
className="mr-4"
style={{ border: "3px solid", borderColor: "#b49dc9", background: 'white', font: 'dark' }}
block>
{loading && <Spinner as='span' animation='border' size='sm' role='status' aria-hidden='true' style={{ color: "#b49dc9" }} />}가입</Button>
{error && <Alert variant='danger'>
{error}
</Alert>}
</div>
</div>
</Form>
</>
)
}
export default SingUp
\ No newline at end of file
body {
margin: 0;
font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', 'Roboto', 'Oxygen',
'Ubuntu', 'Cantarell', 'Fira Sans', 'Droid Sans', 'Helvetica Neue',
sans-serif;
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
}
code {
font-family: source-code-pro, Menlo, Monaco, Consolas, 'Courier New',
monospace;
}
import React from 'react';
import ReactDOM from 'react-dom';
import 'bootstrap/dist/css/bootstrap.min.css';
import './index.css';
import { BrowserRouter as Router, Route, Switch } from 'react-router-dom';
import reportWebVitals from './reportWebVitals';
import SignUpPage from './Pages/SignUpPage';
import ProfilePage from './Pages/ProfilePage';
import 'bootstrap/dist/css/bootstrap.min.css';
import LogInPage from './Pages/LogInPage';
import HomePage from './Pages/HomePage'
import PrivateRoute from './Components/PrivateRoute';
ReactDOM.render(
<Router>
<Switch>
<PrivateRoute exact path="/">
<HomePage />
</PrivateRoute>
<PrivateRoute path="/home">
<HomePage />
</PrivateRoute>
<Route path="/home" component={HomePage} />
<Route path="/login" component={LogInPage} />
<Route path="/signup" component={SignUpPage} />
<Route path="/profile" component={ProfilePage} />
<PrivateRoute path="/profile">
<ProfilePage />
</PrivateRoute>
</Switch>
</Router>,
document.getElementById('root')
);
// If you want to start measuring performance in your app, pass a function
// to log results (for example: reportWebVitals(console.log))
// or send to an analytics endpoint. Learn more: https://bit.ly/CRA-vitals
reportWebVitals();
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 841.9 595.3"><g fill="#61DAFB"><path d="M666.3 296.5c0-32.5-40.7-63.3-103.1-82.4 14.4-63.6 8-114.2-20.2-130.4-6.5-3.8-14.1-5.6-22.4-5.6v22.3c4.6 0 8.3.9 11.4 2.6 13.6 7.8 19.5 37.5 14.9 75.7-1.1 9.4-2.9 19.3-5.1 29.4-19.6-4.8-41-8.5-63.5-10.9-13.5-18.5-27.5-35.3-41.6-50 32.6-30.3 63.2-46.9 84-46.9V78c-27.5 0-63.5 19.6-99.9 53.6-36.4-33.8-72.4-53.2-99.9-53.2v22.3c20.7 0 51.4 16.5 84 46.6-14 14.7-28 31.4-41.3 49.9-22.6 2.4-44 6.1-63.6 11-2.3-10-4-19.7-5.2-29-4.7-38.2 1.1-67.9 14.6-75.8 3-1.8 6.9-2.6 11.5-2.6V78.5c-8.4 0-16 1.8-22.6 5.6-28.1 16.2-34.4 66.7-19.9 130.1-62.2 19.2-102.7 49.9-102.7 82.3 0 32.5 40.7 63.3 103.1 82.4-14.4 63.6-8 114.2 20.2 130.4 6.5 3.8 14.1 5.6 22.5 5.6 27.5 0 63.5-19.6 99.9-53.6 36.4 33.8 72.4 53.2 99.9 53.2 8.4 0 16-1.8 22.6-5.6 28.1-16.2 34.4-66.7 19.9-130.1 62-19.1 102.5-49.9 102.5-82.3zm-130.2-66.7c-3.7 12.9-8.3 26.2-13.5 39.5-4.1-8-8.4-16-13.1-24-4.6-8-9.5-15.8-14.4-23.4 14.2 2.1 27.9 4.7 41 7.9zm-45.8 106.5c-7.8 13.5-15.8 26.3-24.1 38.2-14.9 1.3-30 2-45.2 2-15.1 0-30.2-.7-45-1.9-8.3-11.9-16.4-24.6-24.2-38-7.6-13.1-14.5-26.4-20.8-39.8 6.2-13.4 13.2-26.8 20.7-39.9 7.8-13.5 15.8-26.3 24.1-38.2 14.9-1.3 30-2 45.2-2 15.1 0 30.2.7 45 1.9 8.3 11.9 16.4 24.6 24.2 38 7.6 13.1 14.5 26.4 20.8 39.8-6.3 13.4-13.2 26.8-20.7 39.9zm32.3-13c5.4 13.4 10 26.8 13.8 39.8-13.1 3.2-26.9 5.9-41.2 8 4.9-7.7 9.8-15.6 14.4-23.7 4.6-8 8.9-16.1 13-24.1zM421.2 430c-9.3-9.6-18.6-20.3-27.8-32 9 .4 18.2.7 27.5.7 9.4 0 18.7-.2 27.8-.7-9 11.7-18.3 22.4-27.5 32zm-74.4-58.9c-14.2-2.1-27.9-4.7-41-7.9 3.7-12.9 8.3-26.2 13.5-39.5 4.1 8 8.4 16 13.1 24 4.7 8 9.5 15.8 14.4 23.4zM420.7 163c9.3 9.6 18.6 20.3 27.8 32-9-.4-18.2-.7-27.5-.7-9.4 0-18.7.2-27.8.7 9-11.7 18.3-22.4 27.5-32zm-74 58.9c-4.9 7.7-9.8 15.6-14.4 23.7-4.6 8-8.9 16-13 24-5.4-13.4-10-26.8-13.8-39.8 13.1-3.1 26.9-5.8 41.2-7.9zm-90.5 125.2c-35.4-15.1-58.3-34.9-58.3-50.6 0-15.7 22.9-35.6 58.3-50.6 8.6-3.7 18-7 27.7-10.1 5.7 19.6 13.2 40 22.5 60.9-9.2 20.8-16.6 41.1-22.2 60.6-9.9-3.1-19.3-6.5-28-10.2zM310 490c-13.6-7.8-19.5-37.5-14.9-75.7 1.1-9.4 2.9-19.3 5.1-29.4 19.6 4.8 41 8.5 63.5 10.9 13.5 18.5 27.5 35.3 41.6 50-32.6 30.3-63.2 46.9-84 46.9-4.5-.1-8.3-1-11.3-2.7zm237.2-76.2c4.7 38.2-1.1 67.9-14.6 75.8-3 1.8-6.9 2.6-11.5 2.6-20.7 0-51.4-16.5-84-46.6 14-14.7 28-31.4 41.3-49.9 22.6-2.4 44-6.1 63.6-11 2.3 10.1 4.1 19.8 5.2 29.1zm38.5-66.7c-8.6 3.7-18 7-27.7 10.1-5.7-19.6-13.2-40-22.5-60.9 9.2-20.8 16.6-41.1 22.2-60.6 9.9 3.1 19.3 6.5 28.1 10.2 35.4 15.1 58.3 34.9 58.3 50.6-.1 15.7-23 35.6-58.4 50.6zM320.8 78.4z"/><circle cx="420.9" cy="296.5" r="45.7"/><path d="M520.5 78.1z"/></g></svg>
\ No newline at end of file
.showText {
display: flex;
flex-direction: row;
margin-right: 5px;
margin-left: 5px;
position: absolute;
right: 0;
}
.showTextBFLogin {
display: flex;
flex-direction: row;
margin-right: 5px;
margin-left: 5px;
position: absolute;
right: 0;
}
.showIcon {
display: none;
}
@media screen and (max-width: 768px) {
.showText {
display: none;
}
.showIcon {
display: flex;
flex-direction: row;
margin-right: 5px;
margin-left: 5px;
position: absolute;
right: 0;
}
}
\ No newline at end of file
const reportWebVitals = onPerfEntry => {
if (onPerfEntry && onPerfEntry instanceof Function) {
import('web-vitals').then(({ getCLS, getFID, getFCP, getLCP, getTTFB }) => {
getCLS(onPerfEntry);
getFID(onPerfEntry);
getFCP(onPerfEntry);
getLCP(onPerfEntry);
getTTFB(onPerfEntry);
});
}
};
export default reportWebVitals;
// jest-dom adds custom jest matchers for asserting on DOM nodes.
// allows you to do things like:
// expect(element).toHaveTextContent(/react/i)
// learn more: https://github.com/testing-library/jest-dom
import '@testing-library/jest-dom';
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment