Commit 645bf09c authored by Choi Ga Young's avatar Choi Ga Young
Browse files

Merge remote-tracking branch 'origin/soo-12-28' into young

parents 01cadfbe fd82fdde
...@@ -6,6 +6,7 @@ ...@@ -6,6 +6,7 @@
"@testing-library/jest-dom": "^5.11.6", "@testing-library/jest-dom": "^5.11.6",
"@testing-library/react": "^11.2.2", "@testing-library/react": "^11.2.2",
"@testing-library/user-event": "^12.6.0", "@testing-library/user-event": "^12.6.0",
"axios": "^0.21.1",
"bootstrap": "^4.5.3", "bootstrap": "^4.5.3",
"react": "^17.0.1", "react": "^17.0.1",
"react-bootstrap": "^1.4.0", "react-bootstrap": "^1.4.0",
......
import React from 'react'; import React, { useState, useEffect } from 'react';
import { Form, Button, Row } from 'react-bootstrap'; import { Form, Button, Row } from 'react-bootstrap';
function Chat(props) { function Chat(props) {
let defaultname = sessionStorage.getItem('name'); let defaultname = sessionStorage.getItem('name');
const [inner, setInner] = useState([''])
const [chat, setChat] = useState([inner]) //object로 key는 보낸사람 value는 메세지
function handleChange(e) { function handleChange(e) {
e.preventDefault() e.preventDefault()
props.setInner(e.target.value) setInner(e.target.value)
console.log(e.target.value) console.log(e.target.value)
} }
function sendMsgCH(e) { function sendMsgCH(e) {
e.preventDefault()
props.setSingleChat(inner)
props.sendMsg(e) props.sendMsg(e)
setInner('')
} }
useEffect(() => {
setChat([...chat, props.singleChat])
}, [props.singleChat])
return ( return (
<div className="chat" id="chat" style={{ border: "2px solid", height: "300%", margin: "1%", borderColor: "#BDBDBD" }}> <div className="chat" id="chat" style={{ border: "2px solid", height: "300%", margin: "1%", borderColor: "#BDBDBD" }}>
<Button variant="light" onClick={props.handleChatc} >{`<`}</Button>
<h2>현재 {props.roomName} 입니다.</h2> <h2>현재 {props.roomName} 입니다.</h2>
{ props.chatmsg.map((value, index) => ( { chat.map((value, index) => (
<Row key={index} className='ml-3'> <Row key={index} className='ml-3'>
{props.roomName}에서 {defaultname}님이 보낸 메세지 : {value} {props.roomName}에서 {defaultname}님이 보낸 메세지 : {value}
</Row> </Row>
))} ))}
<Button variant="light" onClick={props.handleChatc} >{`<`}</Button>
<Form onSubmit={sendMsgCH}> <Form onSubmit={sendMsgCH}>
<Form.Control name='msg' type='text' onChange={handleChange} /> <Form.Group>
<Button variant="primary" type="submit">전송</Button> <Form.Control name='chat' type="text" value={inner} onChange={handleChange} />
</Form.Group>
<Button variant="primary" type="submit">
전송
</Button>
</Form> </Form>
</div> </div>
......
import React, { useState } from 'react';
import { Form, Row, Col, Button } from 'react-bootstrap'
function ChatForm(props) {
const INIT_SAYING = ''
const [saying, setSaying] = useState(INIT_SAYING);
function handleChange(event) {
const { name, value } = event.target
setSaying(value)
console.log(saying)
}
function handleSubmit(event) {
event.preventDefault()
// const response = await axios.post('chat/makeChat', chatR)
props.setSingleChat()
setSaying(INIT_SAYING)
}
return (
<Form onSubmit={handleSubmit}>
<Row>
<Col>
<Form.Group>
<Form.Control name='chat' type='text' onChange={handleChange}>chat</Form.Control>
</Form.Group>
</Col>
<Col>
<Form.Group>
<Button type="submit">send</Button>
</Form.Group>
</Col>
</Row>
</Form>
)
}
export default ChatForm
\ No newline at end of file
...@@ -6,27 +6,25 @@ function ClosedList(props) { ...@@ -6,27 +6,25 @@ function ClosedList(props) {
{ room: '테스트 방1', memnum: 5, admin: '가영' }, { room: '테스트 방1', memnum: 5, admin: '가영' },
{ room: '테스트 방2', memnum: 4, admin: '수현' }] { room: '테스트 방2', memnum: 4, admin: '수현' }]
); );
function enterChatroomCH(e) { function enterChatroomCH(e) {
console.log(e.target.name)
console.log(e.target)
const roomName = e.target.name const roomName = e.target.name
props.enterChatroom(roomName) // 각각의 room으로 들어가도록 설정해야 함 props.enterChatroom(roomName) // 각각의 room으로 들어가도록 설정해야 함
props.setRoomName(roomName) props.setRoomName(roomName)
props.clearChat() // props.clearChat()
} }
return ( return (
<div> <div>
<Row> {list.map((item, index) =>
{list.map((list, index) => <ListGroup key={index}>
<ListGroup key={index}> <ListGroup.Item action onClick={enterChatroomCH} name={item.room}>
<ListGroup.Item action onClick={enterChatroomCH} name={list.room}> {item.room}
{list.room} </ListGroup.Item>
</ListGroup.Item> </ListGroup>
</ListGroup> )}
)}
</Row>
<Col>
</Col>
</div> </div>
) )
} }
......
import React, { useState } from 'react' import React, { useState } from 'react'
import { ListGroup } from 'react-bootstrap'; import { ListGroup } from 'react-bootstrap';
function OpenList() { function OpenList(props) {
const [list, setList] = useState([ const [list, setList] = useState([
{ room: '테스트 방3', memnum: 7, admin: '가영2' }, { room: '테스트 방3', memnum: 7, admin: '가영2' },
{ room: '테스트 방4', memnum: 2, admin: '수현2' }] { room: '테스트 방4', memnum: 2, admin: '수현2' }]
); );
function enterChatroomCH(e) {
const roomName = e.target.name
props.enterChatroom(roomName) // 각각의 room으로 들어가도록 설정해야 함
props.setRoomName(roomName)
// props.clearChat()
}
return ( return (
<div> <div>
{list.map((list, index) => {list.map((list, index) =>
<ListGroup key={index}> <ListGroup key={index}>
<ListGroup.Item action> <ListGroup.Item action onClick={enterChatroomCH} name={list.room}>
<h2>{list.room}</h2> <h2>{list.room}</h2>
</ListGroup.Item> </ListGroup.Item>
</ListGroup> </ListGroup>
......
import React, { useState, useEffect } from 'react'; import React, { useState, useEffect } from 'react';
import { Row, Col, Modal, Button, Navbar, Nav } from 'react-bootstrap'; import axios from 'axios';
import { Row, Col, Modal, Button, Form, Alert } from 'react-bootstrap';
import Tabs from 'react-bootstrap/Tabs'; import Tabs from 'react-bootstrap/Tabs';
import Tab from 'react-bootstrap/Tab'; import Tab from 'react-bootstrap/Tab';
import ClosedList from '../Components/ClosedList'; import ClosedList from '../Components/ClosedList';
import OpenList from '../Components/OpenList'; import OpenList from '../Components/OpenList';
import Chat from '../Components/Chat';
import Menu from '../Components/Menu'; import Menu from '../Components/Menu';
import catchErrors from '../utils/catchErrors';
import { io } from "socket.io-client"; //모듈 가져오기 import { io } from "socket.io-client"; //모듈 가져오기
import Chat from "../Components/Chat";
// const userName = "정연우";
const socket = io(); const socket = io();
const INIT_ROOM = {
roomName: '',
interest: '',
isOpen: false
}
function Home() { function Home() {
const [username, setUsername] = useState('defaultUser') const [show, setShow] = useState(false);
const [show2, setShow2] = useState(false);
const [show, setShow] = useState(false); const [chat, setChat] = useState(false);
const [chat, setChat] = useState(false); const [room, setRoom] = useState(INIT_ROOM);
const [disabled, setDisabled] = useState(true);
const handleClose = () => setShow(false); const [error, setError] = useState('');
const handleShow = () => setShow(true);
const handleChato = () => setChat(true); const [singleChat, setSingleChat] = useState('')
const handleChatc = () => setChat(false); const [roomName, setRoomName] = useState('')
const [inner, setInner] = useState(['']) //인풋값 const handleClose = () => setShow(false);
const [chatmsg, setChatmsg] = useState([inner]) // 전송된 채팅들 저장하는 배열 const handleShow = () => setShow(true);
const [roomName, setRoomName] = useState('dd') //방 선택이 방1을 눌럿다 방2를 누르면 전체로 전송됨 const handleChato = () => setChat(true);
const handleChatc = () => setChat(false);
function enterChatroom(roomName) { //방 입장하기 const handleClose2 = () => setShow2(false);
socket.emit('joinRoom', roomName) const handleShow2 = () => setShow2(true);
console.log(`joinRoom : ${roomName} 입장`)
} useEffect(() => {
const isRoom = Object.values(room).every(el => Boolean(el))
const sendMsg = (e) => { isRoom ? setDisabled(false) : setDisabled(true)
e.preventDefault() }, [room])
console.log('sendMsg', inner)
console.log(roomName) function handleChange(event) {
socket.emit("chat", { const { name, value } = event.target
roomName: roomName, setRoom({ ...room, [name]: value })
msg: inner console.log(room)
}); }
}
async function handleSubmit(event) {
function clearChat() { event.preventDefault()
setChatmsg([]) try {
} setError('')
await axios.post('/room/makeRoom', room)
useEffect(() => { setRoom(INIT_ROOM)
socket.on('broadcast', (msg) => { } catch (error){
catchErrors(error, setError)
console.log('msg', msg) }
console.log('inner :', inner) }
setChatmsg([...chatmsg, msg]) //SOCKET 관련 시작
console.log('useeffect2', chatmsg)
}) function enterChatroom(rName) { //방 입장하기
console.log('useeffect2', chatmsg) socket.emit('joinRoom', rName)
}, [chatmsg]) console.log(`joinRoom : ${rName} 입장`)
}
return ( const sendMsg = (e) => {
<> e.preventDefault()
<Menu /> }
<Row className="mr-0">
<Col className="list" md={5}> useEffect(() => {
<Tabs defaultActiveKey="closed" id="uncontrolled-tab-example"> socket.emit("chat", {
<Tab eventKey="closed" title="내 채팅" onClick={handleChato} > roomName: roomName,
<ClosedList enterChatroom={enterChatroom} setRoomName={setRoomName} clearChat={clearChat} /> msg: singleChat
</Tab> })
<Tab eventKey="open" title="공개방" > socket.on('broadcast', (msg) => {
<OpenList /> console.log(msg)
</Tab> setSingleChat(msg)
</Tabs> })
</Col> }, [singleChat])
<Col style={{ padding: "0" }}>
{chat ? <Chat handleChatc={handleChatc} sendMsg={sendMsg} setInner={setInner} chatmsg={chatmsg} roomName={roomName} /> : null} return (
<>
<Button variant="primary" onClick={handleShow} style={{ position: "fixed", bottom: "10px", right: "10px" }} > <Menu />
생성 <Row className="mr-0">
</Button> <Col className="list" md={5}>
<Tabs defaultActiveKey="closed" id="uncontrolled-tab-example">
<Modal show={show} onHide={handleClose}> <Tab eventKey="closed" title="내 채팅" onClick={handleChato} >
<Modal.Header closeButton> <ClosedList enterChatroom={enterChatroom} setRoomName={setRoomName}/>
<Modal.Title> 생성</Modal.Title> </Tab>
</Modal.Header> <Tab eventKey="open" title="공개방" >
<Modal.Body>여기에 form 입력</Modal.Body> <OpenList enterChatroom={enterChatroom} setRoomName={setRoomName}/>
<Modal.Footer> </Tab>
<Button variant="primary" onClick={handleClose}> </Tabs>
생성 </Col>
</Button> <Col style={{ padding: "0" }}>
</Modal.Footer> {chat ? <Chat handleChatc={handleChatc} sendMsg={sendMsg} singleChat={singleChat} setSingleChat={setSingleChat} roomName={roomName}/> : null}
</Modal>
</Col> <div style={{ position: "fixed", bottom: "20px", right: "30px" }}>
</Row> <Button variant="primary" onClick={handleShow} size="lg" block>
</> 생성
); </Button>
<Button variant="secondary" onClick={handleShow2} size="lg" block>
참가
</Button>
</div>
<Modal show={show} onHide={handleClose}>
<Modal.Header closeButton>
<Modal.Title> 생성</Modal.Title>
</Modal.Header>
{error && <Alert variant='danger'>
{error}
</Alert>}
<Modal.Body>
<Form onSubmit={handleSubmit}>
<Form.Group as={Row} controlId="chatName">
<Form.Label column sm={4}> 이름</Form.Label>
<Col>
<Form.Control name='roomName' type='text' value={room.roomName} onChange={handleChange} />
</Col>
</Form.Group>
<Form.Group as={Row} controlId="chatInterest">
<Form.Label column sm={4}>관심 분야</Form.Label>
<Col>
<Form.Control as="select" defaultValue="Choose..." name='interest' type='text' value={room.interest} onChange={handleChange}>
<option>Choose...</option>
<option>과학</option>
<option>수학</option>
<option>예술</option>
<option>언어</option>
<option>취미</option>
</Form.Control>
{/* <Form.Control type="text" /> */}
</Col>
</Form.Group>
<Form.Group as={Row} controlId="chatIsOpen">
<Form.Label column sm={4}>공개방</Form.Label>
<Col>
<Form.Check
type="checkbox"
checked={room.isOpen}
name='isOpen'
onChange={() => setRoom({ ...room, isOpen: !room.isOpen })} />
</Col>
</Form.Group>
{
(room.isOpen)
? (<p><b>공개방</b>으로 개설되어 공개방 목록에 공개되며, 코드를 공유하여 참가할 수도 있습니다.</p>)
: (<p><b>비밀방</b>으로 개설되며, 참여자들에게 코드를 공유해야합니다.</p>)
}
<Form.Group as={Row}>
<Col sm={{ span: 5, offset: 4 }}>
<Button type="submit" > 생성</Button>
</Col>
</Form.Group>
</Form>
</Modal.Body>
</Modal>
<Modal show={show2} onHide={handleClose2}>
<Modal.Header closeButton>
<Modal.Title>참여 코드로 채팅 참가</Modal.Title>
</Modal.Header>
<Modal.Body>
<Form onSubmit={() => { console.log('제출') }}>
<Form.Group as={Row} controlId="formCodeE">
<Form.Label column sm={4}>참여 코드</Form.Label>
<Col>
<Form.Control type="text" />
</Col>
</Form.Group>
<Form.Group as={Row}>
<Col sm={{ span: 5, offset: 4 }}>
<Button type="submit">참가</Button>
</Col>
</Form.Group>
</Form>
</Modal.Body>
</Modal>
</Col>
</Row>
</>
);
} }
export default Home; export default Home;
function catchErrors(error, displayError) { function catchErrors(error, displayError){
let errorMsg let errorMsg
if (error.response) { if (error.response){
errorMsg = error.response.data errorMsg = error.response.data
console.log(errorMsg) console.log(errorMsg)
} else if (error.request) { } else if (error.request) {
......
import Room from "../models/Room.js"
import { customAlphabet } from 'nanoid'
import isLength from 'validator/lib/isLength.js'
const nanoid = customAlphabet('1234567890abcdef', 10)
const makeRoom = async (req, res) => {
console.log(req.body)
const { roomName, interest, isOpen } = req.body;
console.log(roomName, interest, isOpen)
const roomId = nanoid()
const room = await Room.findOne({ roomId })
while (room) {
roomId = nanoid()
room = await Room.findOne({ roomId })
}
try {
if (!isLength(roomName, { min: 3, max: 20 })) {
return res.status(422).send('채팅방의 이름은 3-20자여야 합니다.')
} else if (interest=='Choose...' || interest==''){
return res.status(422).send('분야를 반드시 선택하여야 합니다.')
}
const newRoom = await new Room({
roomId,
roomName,
interest,
isOpen
}).save()
console.log(newRoom)
res.json(newRoom)
} catch (error) {
console.log(error)
res.status(500).send('방생성 에러')
}
}
export default { makeRoom }
\ No newline at end of file
...@@ -3,7 +3,12 @@ import mongoose from 'mongoose' ...@@ -3,7 +3,12 @@ import mongoose from 'mongoose'
const {String} = mongoose.Schema.Types const {String} = mongoose.Schema.Types
const RoomSchema = new mongoose.Schema({ const RoomSchema = new mongoose.Schema({
name: { roomId: {
type: String,
// default:() => nanoid(),
unique: true
},
roomName: {
type: String, type: String,
required: true, required: true,
}, },
...@@ -13,13 +18,11 @@ const RoomSchema = new mongoose.Schema({ ...@@ -13,13 +18,11 @@ const RoomSchema = new mongoose.Schema({
select: false select: false
}, },
isOpen: { isOpen: {
type: String, type: Boolean,
required: true, required: true,
default: 'user',
enum: ['user', 'admin', 'root']
} }
}, { }, {
timestamps: true timestamps: true
}) })
export default mongoose.models.RoomSchema || mongoose.model('Room', RoomSchema) export default mongoose.models.Room || mongoose.model('Room', RoomSchema)
import express from 'express'
import roomCtrl from '../controllers/room.controller.js'
const router = express.Router()
router.route('/room/makeRoom')
.post(roomCtrl.makeRoom)
export default router
\ No newline at end of file
...@@ -2,11 +2,11 @@ import express from 'express' ...@@ -2,11 +2,11 @@ import express from 'express'
import connectDb from './utils/connectDb.js' import connectDb from './utils/connectDb.js'
import userRouter from './routes/user.routes.js' import userRouter from './routes/user.routes.js'
import authRouter from './routes/auth.routes.js' import authRouter from './routes/auth.routes.js'
import roomRouter from './routes/room.routers.js'
import bodyParser from "body-parser"; import bodyParser from "body-parser";
import http from "http"; import http from "http";
import { Server } from 'socket.io'; import { Server } from 'socket.io';
import cors from "cors"
connectDb() connectDb()
...@@ -16,45 +16,36 @@ const server = http.createServer(app); ...@@ -16,45 +16,36 @@ const server = http.createServer(app);
const io = new Server(server) const io = new Server(server)
io.on("connection", (socket) => { // 기본 연결 io.on("connection", (socket) => { // 기본 연결
console.log("socket connect ok", socket.id) console.log("socket connect ok", socket.id)
socket.on('joinRoom', (data)=>{ // joinRoom을 클라이언트가 emit했을 때
socket.on('joinRoom', (data) => { // joinRoom을 클라이언트가 emit했을 때 let roomName=data;
let roomName = data;
console.log(roomName, "방 입장")
socket.join(roomName); //클라이언트에서 data에 적힌 room으로 참여시킴 socket.join(roomName); //클라이언트에서 data에 적힌 room으로 참여시킴
}); });
socket.on('chat', (data) => { socket.on('chat', (data)=>{
console.log(`chat실행 :`, data.roomName, data.msg) io.to(data.roomName).emit('broadcast',data.msg); //roomName에 존재하는 모든 소켓들에게
io.to(data.roomName).emit('broadcast', data.msg); //roomName에 존재하는 모든 소켓들에게
}) })
socket.on('disconnect', () => { socket.on('disconnect', () => {
console.log('disconnected from server id=', socket.id) console.log('disconnected from server id=', socket.id)
}) })
}); });
// app.use(express.json()) // app.use(express.json())
//이부분을 body 파싱함 //이부분을 body 파싱함
app.use(bodyParser.json()); app.use(bodyParser.json());
app.use(cors());
app.use(userRouter) app.use(userRouter)
app.use(authRouter) app.use(authRouter)
//userRouter로 이동 app.use(roomRouter)
app.get('/', (req, res) => {
res.send('Hello World. 안녕하세요')
})
server.listen(3030, () => { server.listen(3030, () => {
console.log('Listening on port 3030') console.log('Listening on port 3030')
}) })
export default server
// export default server // module.exports = server;
function catchErrors(error, displayError){
let errorMsg
if (error.response){
errorMsg = error.response.data
console.log(errorMsg)
} else if (error.request) {
errorMsg = error.request
console.log(errorMsg)
} else {
errorMsg = error.message
console.log(errorMsg)
}
displayError(errorMsg)
}
export default catchErrors
\ No newline at end of file
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