Commit a4570666 authored by kusang96's avatar kusang96
Browse files

Merge remote-tracking branch 'origin/sangho' into ourMaster

parents 8118cdae 1169c8dd
......@@ -3,6 +3,7 @@ import { Navbar, Nav } from 'react-bootstrap';
import { handleLogout, isAuthenticated } from '../utils/auth';
function MainNav() {
const user = isAuthenticated()
return (
......@@ -11,8 +12,10 @@ function MainNav() {
<img alt="로고" src="/icon/footprint.svg" width="24" height="24" />
{' '}KU#
</Navbar.Brand>
<Nav className="ml-auto">
{user ? <Nav.Link className="text-light" onClick={() => handleLogout()}>Logout</Nav.Link>
<Nav>
{user ? <> <Nav.Link className="text-light" onClick={() => handleLogout()}>Logout</Nav.Link>
<Nav.Link className="text-light" href="/account"> Mypage </Nav.Link>
</>
: (
<>
<Nav.Link className="text-light" href='/login'>Login</Nav.Link>
......
import React, { useState, useEffect, useRef } from 'react';
import React from 'react';
import { Pagination } from 'react-bootstrap';
function pagination() {
......
import React from 'react'
import React, { useEffect, useState } from 'react'
import { Card, Image, Container, Row, Col, Table, Accordion, Button, Form, Modal, Alert } from 'react-bootstrap'
import { Link } from 'react-router-dom';
import person from '../person.svg';
import mypagetiger from '../mypagetiger.svg';
import axios from 'axios'
import catchErrors from '../utils/catchErrors';
import { isAuthenticated } from '../utils/auth';
const INIT_ACCOUNT = {
name: "",
avatarUrl: ''
}
function Account() {
const [account, setAccount] = useState(INIT_ACCOUNT)
const [error, setError] = useState("")
const userId = isAuthenticated()
async function getUsername(user) {
// console.log("tlg")
try {
const response = await axios.get(`/api/users/account/${user}`)
setAccount(response.data)
// console.log('555555555', response.data);
} catch (error) {
catchErrors(error, setError)
// console.log('error2222', error)
}
}
useEffect(() => {
getUsername(userId)
}, [userId])
const [show, setShow] = useState(false);
const handleClose = () => setShow(false)
const handleShow = () => setShow(true)
const handleChange = (event) => {
const { name, value, files } = event.target
if (files) {
for (const file of files) {
// console.log("name=", name, "value=", value, 'file=', file);
}
setAccount({ ...account, [name]: files })
} else {
console.log("name=", name, "value=", value);
setAccount({ ...account, [name]: value })
}
}
const handleBasic = async (event) => {
const formData = new FormData()
formData.append('avatar', '')
try {
if (userId) {
const response = await axios.put(`/api/users/account/${userId}`, formData)
console.log(response.data)
window.location.reload()
}
} catch (error) {
catchErrors(error, setError)
}
setShow(false)
}
const handleSubmit = async (event) => {
event.preventDefault()
if (account.avatar) {
const formData = new FormData()
formData.append('avatar', account.avatar[0])
try {
if (userId) {
const response = await axios.put(`/api/users/account/${userId}`, formData)
console.log(response.data)
window.location.reload()
}
} catch (error) {
catchErrors(error, setError)
}
} else {
alert("파일을 선택해주세요.")
}
}
return (
<div>
<h5>마이페이지</h5>
</div>
<Container className="px-3">
<h3 className="my-4 mx-3 font-weight-bold">My Page</h3>
<Card md={3} className="p-1 mb-4" style={{ background: '#F7F3F3' }}>
<Row className="p-2">
<Col md={5} className="d-flex align-content-center justify-content-center">
<Button variant="outline-light" onClick={handleShow}>
{account.avatarUrl ? (
<Image src={account.avatarUrl && `/image/${account.avatarUrl}`} className="img-thumbnail"
roundedCircle style={{ objectFit: "cover", width: "10rem", height: "10rem" }} />
) : (
<Image src={person} className="img-thumbnail"
roundedCircle style={{ objectFit: "cover", width: "10rem", height: "10rem" }} />
)}
</Button>
<Modal show={show} onHide={handleClose}>
<Modal.Header closeButton>
<Modal.Title>이미지를 변경하시겠습니까?</Modal.Title>
</Modal.Header>
<Form onSubmit={handleSubmit}>
<Modal.Body>
<Form.Control type="file" name="avatar" onChange={handleChange} />
</Modal.Body>
<Modal.Footer>
<Col className="px-0">
<Button variant="outline-secondary" onClick={handleBasic}
className="d-flex justify-content-start"><small>기본이미지로</small></Button>
{/* 기본이미지로 보내기 */}
</Col>
<Button variant="secondary" onClick={handleClose}>취소</Button>
<Button variant="primary" type="submit" onClick={handleClose}>저장</Button>
</Modal.Footer>
</Form>
</Modal>
</Col>
<Col >
<Row className="mt-4 text-center">
<Col>
<h2>
<strong>{account.name}</strong> <small>({account.id}){" "}님</small>
</h2>
</Col>
</Row>
<Row className="px-3">
<Card.Body className="p-2 text-center">
<h4><Link to="/" class="link-warning">
<strong title="홈으로">
<Image src={mypagetiger} width={"30rem"} roundedCircle className="img-thumbnail" >
</Image>KU#
</strong>
</Link>
{/* 홈페이지로 돌아가기 */}
방문해주신 <em>{account.name}</em> 님,<br></br>
진심으로 환영합니다! 즐거운 쇼핑 되세요.</h4>
</Card.Body>
</Row>
<Row className="mr-1 text-muted d-flex justify-content-end">
<a href="mailto:shoppingmall_KU@korea.ac.kr">
<small title="메일보내기"> * 문의 : shoppingmall_KU@korea.ac.kr </small>
</a>
{/* 쇼핑몰 문의 메일보내기 */}
</Row>
</Col>
</Row>
</Card>
<Accordion>
<Row className="my-3 px-3">
<Table>
<thead className="text-center" style={{ background: '#F7F3F3' }}>
<tr>
<th scope="col">주문현황</th>
<th scope="col">배송중</th>
<th scope="col">배송완료</th>
</tr>
</thead>
<tbody>
<tr>
<th scope="row">케이시앵글부츠(SH)</th>
<td>Mark</td>
<td>Otto</td>
</tr>
<tr>
<th scope="row">2</th>
<td>Jacob</td>
<td>Thornton</td>
</tr>
<tr>
<th scope="row">3</th>
<td colspan="2">Larry the Bird</td>
</tr>
</tbody>
</Table>
</Row>
</Accordion>
</Container >
)
}
export default Account
}
export default Account
import React, { useState, useEffect, useRef } from 'react';
import React from 'react';
import Pagination from '../Components/Pagination';
import { Row, Form, FormControl, Button, Card, Container } from 'react-bootstrap';
......
<?xml version="1.0" standalone="no"?>
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 20010904//EN"
"http://www.w3.org/TR/2001/REC-SVG-20010904/DTD/svg10.dtd">
<svg version="1.0" xmlns="http://www.w3.org/2000/svg"
width="32.000000pt" height="32.000000pt" viewBox="0 0 32.000000 32.000000"
preserveAspectRatio="xMidYMid meet">
<g transform="translate(0.000000,32.000000) scale(0.100000,-0.100000)"
fill="#91877F" stroke="none">
<path d="M86 288 c-19 -27 -20 -39 -4 -73 13 -28 52 -35 62 -9 10 26 7 79 -6
92 -18 18 -35 15 -52 -10z m52 -21 c6 -30 -7 -67 -23 -67 -22 0 -38 46 -24 71
12 24 42 21 47 -4z"/>
<path d="M187 292 c-19 -21 -22 -64 -7 -93 30 -55 95 21 68 79 -16 33 -39 39
-61 14z m51 -43 c4 -47 -23 -74 -44 -44 -26 36 -14 88 20 83 16 -2 22 -11 24
-39z"/>
<path d="M8 175 c-17 -38 0 -80 32 -80 29 0 46 38 36 79 -9 36 -52 37 -68 1z
m58 -9 c6 -26 -10 -66 -27 -66 -19 0 -32 46 -20 69 16 28 39 27 47 -3z"/>
<path d="M251 174 c-25 -31 -27 -57 -6 -74 21 -17 51 -4 65 30 26 62 -18 96
-59 44z m54 5 c9 -13 -13 -66 -30 -73 -26 -10 -38 20 -20 53 16 31 38 40 50
20z"/>
<path d="M95 100 c-41 -42 -48 -53 -39 -68 9 -14 27 -17 104 -17 79 0 94 3
104 18 9 15 7 22 -12 35 -13 9 -37 32 -54 50 -17 17 -36 32 -42 32 -7 0 -34
-23 -61 -50z m119 -14 c34 -32 43 -46 34 -52 -22 -14 -177 -12 -182 1 -6 16
64 94 85 94 8 1 36 -19 63 -43z"/>
</g>
</svg>
<?xml version="1.0" standalone="no"?>
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 20010904//EN"
"http://www.w3.org/TR/2001/REC-SVG-20010904/DTD/svg10.dtd">
<svg version="1.0" xmlns="http://www.w3.org/2000/svg"
width="200.000000pt" height="200.000000pt" viewBox="0 0 200.000000 200.000000"
preserveAspectRatio="xMidYMid meet">
<g transform="translate(0.000000,200.000000) scale(0.100000,-0.100000)"
fill="#91877F" stroke="none" >
<path d="M904 1456 c-147 -69 -174 -273 -49 -373 53 -43 47 -64 -29 -102 -124
-61 -207 -186 -210 -316 l-1 -60 385 0 385 0 -2 63 c-3 125 -90 255 -209 313
-78 39 -80 54 -20 112 84 80 94 201 26 295 -36 50 -118 92 -179 92 -27 0 -67
-10 -97 -24z"/>
</g>
</svg>
......@@ -11,14 +11,15 @@ export async function handleLogout(){
localStorage.removeItem('role')
localStorage.removeItem('name')
await axios.get('/api/auth/logout')
window.location.href='/'
window.location.href = '/'
}
export function isAuthenticated(){
const userId= localStorage.getItem('id')
if(userId){
return userId
} else{
return false
} else {
return false
}
}
\ No newline at end of file
......@@ -3,40 +3,40 @@ import bcrypt from 'bcryptjs'
import jwt from 'jsonwebtoken'
import config from '../config.js'
const login = async(req,res)=>{
const {id, password} =req.body
console.log(id,password)
try{
const user=await User.findOne({id}).select('password role name')
console.log('u=',user)
if(!user){
const login = async (req, res) => {
const { id, password } = req.body
console.log(id, password)
try {
const user = await User.findOne({ id }).select('password role name')
console.log('u=', user)
if (!user) {
return res.status(404).send(`${id}가 존재하지 않습니다.`)
}
const passwordMatch= await bcrypt.compare(password, user.password)
}
const passwordMatch = await bcrypt.compare(password, user.password)
if(passwordMatch){
const token=jwt.sign({userId:user._id},config.jwtSecret,{
expiresIn:'3d'
if (passwordMatch) {
const token = jwt.sign({ userId: user._id }, config.jwtSecret, {
expiresIn: '3d'
})
res.cookie('token',token,{
maxAge:config.cookieMaxAge,
httpOnly:true,
secure:config.env ==='production'
res.cookie('token', token, {
maxAge: config.cookieMaxAge,
httpOnly: true,
secure: config.env === 'production'
})
res.json({userId:user._id, role: user.role, name: user.name})
res.json({ userId: user._id, role: user.role, name: user.name })
}else{
} else {
res.status(401).send('비밀번호가 일치하지 않습니다.')
}
}catch(error){
} catch (error) {
console.log(error)
res.status(500).send('로그인 실패. 다시 시도하세요.')
}
}
const logout =(req,res)=>{
res.clearCookie('token')
res.send('로그아웃 되었습니다.')
}
const logout = (req, res) => {
res.clearCookie('token')
res.send('로그아웃 되었습니다.')
}
export default {login, logout}
\ No newline at end of file
export default { login, logout }
\ No newline at end of file
......@@ -2,10 +2,37 @@ import Cart from "../schemas/Cart.js";
import User from "../schemas/User.js";
import isLength from 'validator/lib/isLength.js';
import bcrypt from 'bcryptjs';
import multer from "multer";
const uploadimg = multer({ dest: 'uploads/' });
const imgUpload = uploadimg.fields([
{ name: 'avatar', maxCount: 1 }
])
const username = (req, res) => {
res.json(req.account)
console.log(req.account)
}
const userById = async (req, res, next, id) => {
try {
const user = await User.findById(id)
if (!user) {
res.status(404).send('사용자를 찾을 수 없습니다')
}
req.account = user
next()
} catch (error) {
console.log(error);
res.status(500).send('사용자 아이디 검색 실패')
}
}
const signup = async (req, res) => {
const { name, number1, number2, id, password, tel ,role} = req.body
const { name, number1, number2, id, password, tel } = req.body
console.log(req.body)
try {
......@@ -37,4 +64,26 @@ const signup = async (req, res) => {
}
}
export default { signup }
\ No newline at end of file
const update = async (req, res) => {
console.log("req", req.body)
try {
if (req.body.avatar == '') {
const user = req.account
user.avatarUrl = req.body.avatar
const updateUser = await user.save()
res.json(updateUser)
} else {
const avatar = req.files['avatar'][0]
const user = req.account
user.avatarUrl = avatar.filename
const updateUser = await user.save()
res.json(updateUser)
}
} catch (error) {
console.log(error);
res.status(500).send('이미지 업데이트 실패')
}
}
export default { signup, username, imgUpload, userById, update }
\ No newline at end of file
......@@ -6,4 +6,12 @@ const router = express.Router()
router.route('/signup')
.post(userCtrl.signup)
router.route('/account/:userId')
.get(userCtrl.username)
.put(userCtrl.imgUpload, userCtrl.update)
router.param('userId', userCtrl.userById)
export default router
\ No newline at end of file
......@@ -33,6 +33,9 @@ const UserSchema = new mongoose.Schema({
required: true,
default: 'user',
enum: ['user', 'admin', 'root']
},
avatarUrl: {
type: String
}
}, {
timestamps: true
......
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