Commit b9c8ba1f authored by Choi Ga Young's avatar Choi Ga Young
Browse files

Merge remote-tracking branch 'origin/yeonwoo' into young

parents 8634b7fc f6c113bd
...@@ -2,6 +2,7 @@ ...@@ -2,6 +2,7 @@
"name": "client", "name": "client",
"version": "0.1.0", "version": "0.1.0",
"private": true, "private": true,
"type": "module",
"dependencies": { "dependencies": {
"@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",
......
...@@ -24,7 +24,7 @@ function Chat(props) { ...@@ -24,7 +24,7 @@ function Chat(props) {
useEffect(() => { useEffect(() => {
setChat([...chat, props.singleChat]) setChat([...chat, props.singleChat])
}, [props.singleChat]) }, [props.singleChat])
useEffect(() => { useEffect(() => {
setChat([...chat, props.recievedMsg]) setChat([...chat, props.recievedMsg])
}, [props.recievedMsg]) }, [props.recievedMsg])
......
...@@ -3,35 +3,36 @@ import Menu from '../Components/Menu'; ...@@ -3,35 +3,36 @@ import Menu from '../Components/Menu';
import { Image, Button, Container, Form, Row, Col, Dropdown } from 'react-bootstrap'; import { Image, Button, Container, Form, Row, Col, Dropdown } from 'react-bootstrap';
import { BrowserRouter as Link } from 'react-router-dom'; import { BrowserRouter as Link } from 'react-router-dom';
import axios from 'axios' import axios from 'axios'
import catchErrors from '../utils/catchErrors'
import { isAuthenticated } from '../utils/auth';
import userdefault from '../Images/KakaoTalk_20201230_153151693.png'
import img1 from '../Images/img_1.png'
import img2 from '../Images/img_2.png'
import img3 from '../Images/img_3.jpg'
import DropdownItem from 'react-bootstrap/esm/DropdownItem';
const INIT_USER = {
// const INIT_USER = { username: '',
// username: '', email: '',
// email: '', nickname: '',
// nickname: '' imageUrl: []
// } }
function ProfilePage() { function ProfilePage() {
const [user, setUser] = useState('') const [user, setUser] = useState(INIT_USER)
const [error, setError] = useState('')
const [userimg, setUserimg] = useState(img2)
const [defaultImg, setDefaultImg] = useState(true)
const [hidden, setHidden] = useState(true) const [hidden, setHidden] = useState(true)
const [changed, setChanged] = useState(false)
const userId = isAuthenticated()
async function getLoginedUser() { async function getProfile(userId) {
const userid = sessionStorage.getItem('userId') try {
const response = await axios.post(`/users/${userid}`, { '_id': userid }) const response = await axios.get(`/users/${userId}`)
setUser(response.data) setUser(response.data)
} catch (error) {
catchErrors(error, setError)
}
} }
function handleSubmit(e) { function handleSubmitHidVis(e) {
e.preventDefault() e.preventDefault()
if (hidden) { if (hidden) {
setHidden(false) setHidden(false)
...@@ -40,80 +41,85 @@ function ProfilePage() { ...@@ -40,80 +41,85 @@ function ProfilePage() {
} }
} }
function handleChange(e) { function handleChange(e) {
setUser({ ...user, 'nickname': e.target.value }) const { name, value, files } = e.target
} if (files) {
async function handleNicksave() { setUser({ ...user, [name]: files })
const userid = sessionStorage.getItem('userId') } else {
await axios.put(`/users/${userid}`, user) setUser({ ...user, [name]: value })
}
setChanged(true)
} }
async function handleSubmit(e) {
function setThumbnail(event) { //불러온 사진 <div id='image_container'>에 띄우기 e.preventDefault()
let reader = new FileReader(); if (changed) {
const formData = new FormData()
reader.onload = function (event) { if (user.imageUrl) {
let img = document.createElement("img"); formData.append('imageUrl', user.imageUrl[0])
img.setAttribute("src", event.target.result); }
img.setAttribute("id", "profileImg") formData.append('newNickname', user.nickname) //얘네는 req.body로 들어감
img.setAttribute("style", 'height:300px; width:300px') try {
img.setAttribute("class", "mb-3") if (userId) {
// img.setAttribute("class","d-flex justify-content-center mb-3") await axios.put(`/users/${userId}`, formData)
document.querySelector("div#image_container").appendChild(img); alert('저장되었습니다.')
}; window.location.reload()
reader.readAsDataURL(event.target.files[0]); }
} catch (error) {
if (defaultImg) { //첫 이미지 업로드(default이미지 지우고 유저가 올린걸로 업로드) catchErrors(error, setError)
let del = document.getElementById("defaultImg") }
del.remove()
setDefaultImg(false)
} }
else { //기존에 올렸던 사진 지우고 재선택한 사진 업로드 else {
let del2 = document.getElementById('profileImg') alert('변경사항이 없습니다.')
del2.remove()
reader.onload = function (event) {
let img = document.createElement("img");
img.setAttribute("src", event.target.result);
img.setAttribute("id", "profileImg")
img.setAttribute("style", 'height:300px; width:300px')
document.querySelector("div#image_container").appendChild(img);
};
} }
} }
useEffect(() => { useEffect(() => {
getLoginedUser() getProfile(userId)
}, []) }, [userId])
// const [img, setImg] = useState('')
// function bbb(e) {
// const { name } = e.target
// let reader = new FileReader();
// reader.onload = function (e){
// console.log(e.target.result)
// // setImg(e.target.result)
// // setProfileimg
// // console.log(user,name)
// setUser({...user, [name]: e.target.result})
// };
// reader.readAsDataURL(e.target.files[0])
// )
return ( return (
<div> <>
<Menu /> <Menu />
<Container className='border' fluid> <Container>
<Row> <Row >
<Col sm={4}> <Col sm={4}>
<Row className='justify-content-center'> <Row className='justify-content-center'>
<div className="d-flex ml-3 mt-3" id="defaultImg"> {user.profileimg ? <Image src={user.profileimg && `/images/${user.profileimg}`} style={{ width: "300px", height: "300px" }} roundedCircle /> : <Image src='https://www.flaticon.com/svg/vstatic/svg/149/149071.svg?token=exp=1610922596~hmac=f4b972b9db509d4e3cc2eb40543b0b0f' style={{ width: "300px", height: "300px" }} roundedCircle />}
<Image src={userimg} width="300px" roundedCircle /> {/* {user.profileimg ? <><Image id='profileimg' src={user.profileimg && `/images/${user.profileimg}`} style={{ width: "300px", height: "300px" }} roundedCircle hidden={!hidden}/> */}
</div> {/* <Image id='profileimg' src={user.profileimg} style={{ width: "300px", height: "300px" }} roundedCircle hidden={hidden}/></> : <Image src='https://www.flaticon.com/svg/vstatic/svg/149/149071.svg?token=exp=1610922596~hmac=f4b972b9db509d4e3cc2eb40543b0b0f' style={{ width: "300px", height: "300px" }} roundedCircle />} */}
</Row> </Row>
<Row className='ml-3 mt-3 justify-content-center'> <Row className='ml-3 mt-3 justify-content-center'>
<Form className="d-flex"> <Form className="d-flex">
<Form.Group> <Form.Group>
<div id="image_container"></div> <Form.Label>프로필 사진 변경</Form.Label>
<Form.File label="프로필 사진 변경" accept="image/*" onChange={setThumbnail} /> <Form.Control type='file' name='imageUrl' onChange={handleChange} accept='image/*' />
</Form.Group> </Form.Group>
</Form> </Form>
</Row> </Row>
<Row className="d-flex justify-content-center mb-3"> {/*
<Dropdown> {img?<Image src={img}/> : <h2>아직입니다.</h2>}
<Dropdown.Toggle variant='success' id='dropdown-basic'> <Row className='ml-3 mt-3 justify-content-center'>
프로필 사진 선택 <Form className="d-flex">
</Dropdown.Toggle> <Form.Group>
<Dropdown.Menu> <Form.Label>프로필 사진 변경</Form.Label>
<Dropdown.Item as='button'>홈으로</Dropdown.Item> <Form.Control type='file' name='profileimg' onChange={bbb} accept='image/*' />
<Dropdown.Item href='/'>라이언</Dropdown.Item> </Form.Group>
<Dropdown.Item href='/'>어피치</Dropdown.Item> </Form>
</Dropdown.Menu> </Row> */}
</Dropdown>
</Row>
</Col> </Col>
<Col sm={8}> <Col sm={8}>
<Row className='m-5 justify-content-center'> <Row className='m-5 justify-content-center'>
...@@ -122,7 +128,6 @@ function ProfilePage() { ...@@ -122,7 +128,6 @@ function ProfilePage() {
<Row className="m-3 justify-content-flex-start" style={{ fontWeight: "bold", fontSize: "large" }}> <Row className="m-3 justify-content-flex-start" style={{ fontWeight: "bold", fontSize: "large" }}>
<Col xs={3}>이름 :</Col> <Col xs={3}>이름 :</Col>
<Col xs={6}>{user.username}</Col> <Col xs={6}>{user.username}</Col>
{/* <Col sm={4}></Col> */}
</Row> </Row>
<Row className="m-3 justify-content-flex-start" id="nickname" style={{ fontWeight: "bold", fontSize: "large" }}> <Row className="m-3 justify-content-flex-start" id="nickname" style={{ fontWeight: "bold", fontSize: "large" }}>
<Col xs={3}>별명 :</Col> <Col xs={3}>별명 :</Col>
...@@ -131,11 +136,11 @@ function ProfilePage() { ...@@ -131,11 +136,11 @@ function ProfilePage() {
</Col> </Col>
<Col xs={6} hidden={hidden}> <Col xs={6} hidden={hidden}>
<Form> <Form>
<Form.Control defaultValue={user.nickname} style={{ width: "110%" }} onChange={handleChange} /> <Form.Control defaultValue={user.nickname} name='nickname' style={{ width: "110%" }} onChange={handleChange} />
</Form> </Form>
</Col> </Col>
<Col xs={3}> <Col xs={3}>
<Form className="d-flex" onSubmit={handleSubmit}> <Form className="d-flex" onSubmit={handleSubmitHidVis}>
<Button className="ml-3 d-flex justify-content-end" variant="outline-primary" size="sm" type='submit'>수정</Button> <Button className="ml-3 d-flex justify-content-end" variant="outline-primary" size="sm" type='submit'>수정</Button>
</Form> </Form>
</Col> </Col>
...@@ -145,8 +150,8 @@ function ProfilePage() { ...@@ -145,8 +150,8 @@ function ProfilePage() {
<Col xs={6}>{user.email}</Col> <Col xs={6}>{user.email}</Col>
</Row> </Row>
<Row className='m-3 justify-content-center'> <Row className='m-3 justify-content-center'>
<Form> <Form onSubmit={handleSubmit}>
<Button variant="outline-success" size="sm" className="mr-4" onClick={handleNicksave}>저장</Button> <Button variant="outline-success" size="sm" className="mr-4" type='submit'>저장</Button>
<Link to='/'> <Link to='/'>
<Button variant="outline-success" size="sm" className="ml-4" > 화면으로</Button> <Button variant="outline-success" size="sm" className="ml-4" > 화면으로</Button>
</Link> </Link>
...@@ -155,7 +160,7 @@ function ProfilePage() { ...@@ -155,7 +160,7 @@ function ProfilePage() {
</Col> </Col>
</Row> </Row>
</Container> </Container>
</div> </>
) )
} }
......
...@@ -24,6 +24,7 @@ ...@@ -24,6 +24,7 @@
"express": "^4.17.1", "express": "^4.17.1",
"jsonwebtoken": "^8.5.1", "jsonwebtoken": "^8.5.1",
"mongoose": "^5.11.9", "mongoose": "^5.11.9",
"multer": "^1.4.2",
"nanoid": "^3.1.20", "nanoid": "^3.1.20",
"nodemon": "^2.0.6", "nodemon": "^2.0.6",
"socket.io": "^3.0.5", "socket.io": "^3.0.5",
......
...@@ -2,6 +2,12 @@ import User from "../models/User.js" ...@@ -2,6 +2,12 @@ import User from "../models/User.js"
import isLength from 'validator/lib/isLength.js' import isLength from 'validator/lib/isLength.js'
import isEmail from 'validator/lib/isEmail.js' import isEmail from 'validator/lib/isEmail.js'
import bcrypt from "bcryptjs"; import bcrypt from "bcryptjs";
import multer from "multer";
const upload = multer({ dest: 'uploads/' })
const profileUpload = upload.fields([
{ name: 'imageUrl', maxCount: 1 },
])
const signup = async (req, res) => { const signup = async (req, res) => {
...@@ -32,10 +38,7 @@ const signup = async (req, res) => { ...@@ -32,10 +38,7 @@ const signup = async (req, res) => {
email, email,
password: hash, password: hash,
}).save() }).save()
console.log(newUser)
res.json(newUser) res.json(newUser)
} catch (error) { } catch (error) {
//알수없는 모든 에러발생시 처리 //알수없는 모든 에러발생시 처리
console.log(error) console.log(error)
...@@ -43,23 +46,44 @@ const signup = async (req, res) => { ...@@ -43,23 +46,44 @@ const signup = async (req, res) => {
} }
} }
const logineduser = async (req, res) => { const update = async (req, res) => {
const username = req.user.username
const newNickname = req.body.newNickname
try { try {
let user = await User.findOne(req.body).select('username email nickname').exec() await User.updateOne({ 'username': username }, { 'nickname': newNickname })
return res.json(user) let imageUrl = ''
if (req.files['imageUrl']) {
imageUrl = req.files['imageUrl'][0]
}
const user = req.user
if (req.files['imageUrl']) {
user.profileimg = imageUrl.filename //우리가 사용할 uesr.profileimg에다가 imageUrl의 filename을 저장
}
const updatedUser = await user.save()
res.json(updatedUser)
} catch (error) { } catch (error) {
alert('올바르지 못한 접근입니다.') console.log(error)
res.status(500).send('프로필 업데이트 실패')
} }
} }
const changenick = async (req, res) => { const userById = async (req, res, next, id) => { //id로 찾아와서 req.user를 우리가 찾는 user로 저장
try { try {
const newnick = req.body.nickname const user = await User.findById(id)
await User.updateOne({ 'username': req.body.username }, { 'nickname': newnick }) if (!user) {
res.status(404).send('사용자를 찾을 수 없습니다.')
}
req.user = user
next()
} catch (error) { } catch (error) {
alert('올바르지 못한 접근입니다.') console.log(error)
res.status(500).send('사용자 아이디 검색 실패')
} }
} }
const getProfile = (req, res) => {
res.json(req.user)
}
const loginNavbar = async (req, res) => { const loginNavbar = async (req, res) => {
try { try {
...@@ -70,5 +94,5 @@ const loginNavbar = async (req, res) => { ...@@ -70,5 +94,5 @@ const loginNavbar = async (req, res) => {
} }
} }
export default { signup, logineduser, changenick, loginNavbar } export default { signup, profileUpload, update, userById, getProfile, loginNavbar }
// {} : 객체로 return // {} : 객체로 return함
...@@ -29,7 +29,10 @@ const UserSchema = new mongoose.Schema({ ...@@ -29,7 +29,10 @@ const UserSchema = new mongoose.Schema({
//정보를 찾을때 찾지 않게함 //정보를 찾을때 찾지 않게함
//플러스 옵션을 주면 찾을 수 있음(mongoose에서 용법찾아봐야됨) //플러스 옵션을 주면 찾을 수 있음(mongoose에서 용법찾아봐야됨)
}, },
},{ profileimg: {
type: String
},
}, {
//옵셥을 정의함. //옵셥을 정의함.
timestamps: true timestamps: true
//기본이 false로 되어있음 //기본이 false로 되어있음
......
...@@ -8,23 +8,10 @@ router.route('/users/signup') ...@@ -8,23 +8,10 @@ router.route('/users/signup')
.post(userCtrl.signup) .post(userCtrl.signup)
router.route(`/users/:userId`) router.route(`/users/:userId`)
.post(userCtrl.logineduser) .get(userCtrl.getProfile)
.put(userCtrl.changenick) .put(userCtrl.profileUpload, userCtrl.update)
.get(userCtrl.loginNavbar)
// router.param('userId', userCtrl.userById) router.param('userId', userCtrl.userById)
// router.route('/api/users/signup/:userId') //로그인한 사람의 정보만 가져오도록
// .get
// /api/users/signup로 들어오는 것을 post (method) 를 통해 useCtrl.signup 이것이 처리함
//browser에서 주소창에 치고 들어가면 get (method) 을 타고 들어간것임
//post를 띄우고 싶으면 앱에서 ARC실행해서 post를 실행하게 만들면됨.
//객체에 접근할때는 .을 찍고 접근함/ ex) .hello
//express middleware : (req, res) => {}
//node(req(client의 정보), res)를 넘겨줌.
export default router export default router
\ No newline at end of file
...@@ -43,6 +43,7 @@ io.on("connection", (socket) => { // 기본 연결 ...@@ -43,6 +43,7 @@ io.on("connection", (socket) => { // 기본 연결
app.use(bodyParser.json()); app.use(bodyParser.json());
app.use(cors()); app.use(cors());
app.use('/images', express.static('uploads/'))
app.use(userRouter) app.use(userRouter)
app.use(authRouter) app.use(authRouter)
app.use(roomRouter) app.use(roomRouter)
......
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