Commit 9e604666 authored by 이재연's avatar 이재연
Browse files

Merge remote-tracking branch 'origin/jiwon' into jaeyeon

parents d8de2d3f 506fb316
...@@ -9,6 +9,7 @@ import Admin from './Pages/Admin'; ...@@ -9,6 +9,7 @@ import Admin from './Pages/Admin';
import ProductRegist from './Pages/ProductRegist'; import ProductRegist from './Pages/ProductRegist';
import ShoppingCart from './Pages/ShoppingCart'; import ShoppingCart from './Pages/ShoppingCart';
import Payment from './Pages/Payment'; import Payment from './Pages/Payment';
import PaymentCompleted from './Pages/PaymentCompleted';
import Account from './Pages/Account'; import Account from './Pages/Account';
import MainNav from './Components/MainNav'; import MainNav from './Components/MainNav';
import SubNav from './Components/SubNav'; import SubNav from './Components/SubNav';
...@@ -24,11 +25,13 @@ function App() { ...@@ -24,11 +25,13 @@ function App() {
<Route path="/login" component={Login} /> <Route path="/login" component={Login} />
<Route path="/signup" component={Signup} /> <Route path="/signup" component={Signup} />
<Route path="/product/:productId" component={Product} /> <Route path="/product/:productId" component={Product} />
<Route path="/categories/:main/:sub" component={ProductsList} />
<Route path="/categories/:main" component={ProductsList} /> <Route path="/categories/:main" component={ProductsList} />
<Route path="/admin" component={Admin} /> <Route path="/admin" component={Admin} />
<Route path="/regist" component={ProductRegist} /> <Route path="/regist" component={ProductRegist} />
<Route path="/shoppingcart" component={ShoppingCart} /> <Route path="/shoppingcart" component={ShoppingCart} />
<Route path="/payment" component={Payment} /> <Route path="/payment" component={Payment} />
<Route path="/paymentcompleted" component={PaymentCompleted} />
<Route path="/account" component={Account} /> <Route path="/account" component={Account} />
<Route path='/kakao' component={() => { window.location.href = 'https://compmath.korea.ac.kr'; return null; }} /> <Route path='/kakao' component={() => { window.location.href = 'https://compmath.korea.ac.kr'; return null; }} />
<Redirect path="/" to="/" /> <Redirect path="/" to="/" />
......
import React from 'react' import React from 'react'
import { Card, Button, Container, Row, Col } from 'react-bootstrap'; import { Card, Row, Col } from 'react-bootstrap';
function CartCard(props) { function CartCard(props) {
console.log(props)
return ( return (
<> <>
{props.cart.map((e) => ( {props.cart.map((e) => (
<Card> <Card>
<Row className="mx-1"> <Row className="mx-1">
<Col xs={2} sm={2} className="text-center my-auto"> <Col xs={2} sm={2} className="text-center my-auto">
<input className="" type="checkbox" id="exampleCheck1" /> <input className="" type="checkbox" name={String(e._id)} onChange={props.checkedCart} />
</Col> </Col>
<Col className="text-center"> <Col className="text-center">
<Card.Img className="img-fluid" variant="top" src={e.productId.main_imgUrl && `/images/${e.productId.main_imgUrl}`} style={{ width: '20rem' }} /> <Card.Img className="img-fluid" variant="top" src={e.productId.main_imgUrl && `/images/${e.productId.main_imgUrl}`} style={{ width: '20rem' }} />
</Col> </Col>
<Col md={6} className="p-2"> <Col md={6} className="p-2">
<Card.Body> <Card.Body>
<input type="image" name={String(e.productId._id)} alt="삭제버튼" src="https://img.icons8.com/fluent-systems-regular/24/000000/close-window.png" className="float-right" onClick={props.deleteCart} /> <input type="image" name={String(e._id)} alt="삭제버튼" src="https://img.icons8.com/fluent-systems-regular/24/000000/close-window.png" className="float-right" onClick={props.deleteCart} />
<Card.Title className="font-weight-bold mt-3">{e.productId.pro_name}</Card.Title> <Card.Title className="font-weight-bold mt-3">{e.productId.pro_name}</Card.Title>
<Card.Text>가격: {e.productId.price}</Card.Text> <Card.Text className="mb-0">가격: {e.productId.price}</Card.Text>
<Card.Text>옵션: {e.sizes}/{e.colors}</Card.Text> <Card.Text className="mb-0">옵션: {e.size}/{e.color}</Card.Text>
<Card.Text>수량</Card.Text> <Card.Text >수량</Card.Text>
<div> <div>
<input type="image" alt="마이너스" src="https://img.icons8.com/ios-glyphs/20/000000/minus-math.png" className="align-middle" onClick={props.minusNum} /> <input type="image" name={String(e._id)} alt="마이너스" src="https://img.icons8.com/ios-glyphs/20/000000/minus-math.png" className="align-middle" onClick={props.minusNum} />
<input type="text" style={{ width: '30px' }} className="text-center align-middle mx-1" placeholder={e.count} value={e.count} readOnly></input> <input type="number" style={{ width: '30px' }} className="text-center align-middle mx-1" placeholder={e.count} value={e.count} readOnly></input>
<input type="image" alt="플러스" src="https://img.icons8.com/ios-glyphs/20/000000/plus-math.png" className="align-middle" onClick={props.plusNum} /> <input type="image" name={String(e._id)} alt="플러스" src="https://img.icons8.com/ios-glyphs/20/000000/plus-math.png" className="align-middle" onClick={props.plusNum} />
</div> </div>
</Card.Body> </Card.Body>
</Col> </Col>
......
import React, { useState, useEffect, useRef } from 'react'; import React, { useState, useEffect, useRef } from 'react';
import { Card } from 'react-bootstrap'; import { Card, Button } from 'react-bootstrap';
function ListCard({ id, name, price, main_img }) { function ListCard({ id, name, price, main_img }) {
function handleDelete(e) {
const card = e.target.parentNode.parentNode
alert('해당 상품을 성공적으로 삭제하였습니다.')
card.remove()
}
return ( return (
<Card id={id} className="mt-5" style={{ width: "18rem", margin: "auto" }}> <Card id={id} className="m-3" style={{ width: "18rem" }}>
<Card.Img variant="top" src={main_img && `/images/${main_img}`} style={{ objectFit: "contain", height: "22rem" }} /> <Card.Img variant="top" src={main_img && `/images/${main_img}`} style={{ objectFit: "contain", height: "22rem" }} />
<Card.Body> <Card.Body>
<Card.Title style={{ whiteSpace: "nowrap", overflow: "hidden", textOverflow: "ellipsis" }}>{name}</Card.Title> <Card.Title style={{ whiteSpace: "nowrap", overflow: "hidden", textOverflow: "ellipsis" }}>{name}</Card.Title>
<Card.Text>{price} </Card.Text> <Card.Text>{price} </Card.Text>
{/* <Button className="float-right" onClick={handleDelete}>삭제</Button> */}
</Card.Body> </Card.Body>
</Card> </Card>
) )
} }
export default ListCard export default ListCard
\ No newline at end of file
...@@ -13,8 +13,8 @@ function MainNav() { ...@@ -13,8 +13,8 @@ function MainNav() {
<img alt="로고" src="/icon/footprint.svg" width="24" height="24" /> <img alt="로고" src="/icon/footprint.svg" width="24" height="24" />
{' '}KU# {' '}KU#
</Navbar.Brand> </Navbar.Brand>
<Nav> <Nav className="ml-auto">
{user,admin ? <> <Nav.Link className="text-light" onClick={() => handleLogout()}>Logout</Nav.Link> {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="/account"> Mypage </Nav.Link>
</> </>
: ( : (
......
import React from 'react' import React from 'react'
import { Card, Row, Col } from 'react-bootstrap';
function PaymentCard() {
function PaymentCard(props) {
return ( return (
<Card > <>
{props.cart.map((e) => (
<Card>
<Row className="mx-1"> <Row className="mx-1">
<Col className="text-center"> <Col className="text-center">
<Card.Img className="img-fluid" variant="top" src="img/asd.jpg" style={{ width: '20rem' }} /> <Card.Img className="img-fluid" variant="top" src={e.productId.main_imgUrl && `/images/${e.productId.main_imgUrl}`} style={{ width: '20rem' }} />
</Col> </Col>
<Col md={6} className="p-2"> <Col md={6} className="p-2">
<Card.Body> <Card.Body>
<input type="image" alt="삭제버튼" src="https://img.icons8.com/fluent-systems-regular/24/000000/close-window.png" className="float-right" onClick={deleteCart} /> <input type="image" name={String(e._id)} alt="삭제버튼" src="https://img.icons8.com/fluent-systems-regular/24/000000/close-window.png" className="float-right" onClick={props.deleteOrder} />
<Card.Title className="font-weight-bold mt-3">제품명</Card.Title> <Card.Title className="font-weight-bold mt-3">{e.productId.pro_name}</Card.Title>
<Card.Text>가격</Card.Text> <Card.Text>가격: {e.productId.price}</Card.Text>
<Card.Text>옵션</Card.Text> <Card.Text>옵션: {e.size}/{e.color}</Card.Text>
<Card.Text>수량</Card.Text> <Card.Text>수량: {e.count}</Card.Text>
<div>
<input type="image" alt="마이너스" src="https://img.icons8.com/ios-glyphs/20/000000/minus-math.png" className="align-middle" onClick={minusNum} />
<input type="text" style={{ width: '30px' }} className="text-center align-middle mx-1" placeholder="1" value={num} readOnly></input>
<input type="image" alt="플러스" src="https://img.icons8.com/ios-glyphs/20/000000/plus-math.png" className="align-middle" onClick={plusNum} />
</div>
</Card.Body> </Card.Body>
</Col> </Col>
</Row> </Row>
</Card> </Card>
))
}
</>
) )
} }
......
...@@ -8,7 +8,6 @@ function SubNav() { ...@@ -8,7 +8,6 @@ function SubNav() {
const [categoriesDiv, setCategoriesDiv] = useState([]) const [categoriesDiv, setCategoriesDiv] = useState([])
const [error, setError] = useState('') const [error, setError] = useState('')
useEffect(async () => { useEffect(async () => {
try { try {
const response = await axios.get('/api/categories/main') const response = await axios.get('/api/categories/main')
...@@ -17,6 +16,7 @@ function SubNav() { ...@@ -17,6 +16,7 @@ function SubNav() {
const url = ele.toLowerCase() const url = ele.toLowerCase()
list.push( list.push(
<Nav.Link as={Link} to={`/categories/${url}`}>{ele}</Nav.Link> <Nav.Link as={Link} to={`/categories/${url}`}>{ele}</Nav.Link>
//categories/${SubNav.url}/&{url}
) )
}) })
setCategoriesDiv(list) setCategoriesDiv(list)
...@@ -34,7 +34,7 @@ function SubNav() { ...@@ -34,7 +34,7 @@ function SubNav() {
} }
`} `}
</style> </style>
<Nav style={{overflowX: "auto"}}> <Nav style={{ overflowX: "auto" }}>
{categoriesDiv.map(item => item)} {categoriesDiv.map(item => item)}
</Nav> </Nav>
</Navbar> </Navbar>
......
import React, { useEffect, useState } from 'react' import React, { useEffect, useState } from 'react'
import { Card, Image, Container, Row, Col, Table, Accordion, Button, Form, Modal, Alert } from 'react-bootstrap' import { Card, Image, Container, Row, Col, Table, Accordion, Button, Form, Modal, Alert } from 'react-bootstrap'
import { Link } from 'react-router-dom'; import { Link } from 'react-router-dom';
import axios from 'axios' import axios from 'axios';
import catchErrors from '../utils/catchErrors'; import catchError from '../utils/catchErrors';
import { isAuthenticated } from '../utils/auth'; import { isAuthenticated } from '../utils/auth';
const INIT_ACCOUNT = { const INIT_ACCOUNT = {
...@@ -10,21 +10,21 @@ const INIT_ACCOUNT = { ...@@ -10,21 +10,21 @@ const INIT_ACCOUNT = {
avatarUrl: '' avatarUrl: ''
} }
function Account() { function Account() {
const [account, setAccount] = useState(INIT_ACCOUNT) const [account, setAccount] = useState(INIT_ACCOUNT)
const [show, setShow] = useState(false);
const [proshow, setProshow] = useState(false)
const [error, setError] = useState("") const [error, setError] = useState("")
const userId = isAuthenticated() const userId = isAuthenticated()
async function getUsername(user) { async function getUsername(user) {
// console.log("tlg") // console.log("tlg")
try { try {
const response = await axios.get(`/api/users/account/${user}`) const response = await axios.get(`/api/users/account/${user}`)
setAccount(response.data) setAccount(response.data)
// console.log('555555555', response.data); console.log('555555555', response.data);
} catch (error) { } catch (error) {
catchErrors(error, setError) catchError(error, setError)
// console.log('error2222', error) // console.log('error2222', error)
} }
} }
...@@ -33,13 +33,6 @@ function Account() { ...@@ -33,13 +33,6 @@ function Account() {
getUsername(userId) getUsername(userId)
}, [userId]) }, [userId])
const [show, setShow] = useState(false);
const handleClose = () => setShow(false)
const handleShow = () => setShow(true)
const handleChange = (event) => { const handleChange = (event) => {
const { name, value, files } = event.target const { name, value, files } = event.target
if (files) { if (files) {
...@@ -63,7 +56,7 @@ function Account() { ...@@ -63,7 +56,7 @@ function Account() {
window.location.reload() window.location.reload()
} }
} catch (error) { } catch (error) {
catchErrors(error, setError) catchError(error, setError)
} }
setShow(false) setShow(false)
} }
...@@ -81,7 +74,7 @@ function Account() { ...@@ -81,7 +74,7 @@ function Account() {
window.location.reload() window.location.reload()
} }
} catch (error) { } catch (error) {
catchErrors(error, setError) catchError(error, setError)
} }
} else { } else {
alert("파일을 선택해주세요.") alert("파일을 선택해주세요.")
...@@ -89,13 +82,20 @@ function Account() { ...@@ -89,13 +82,20 @@ function Account() {
} }
return ( return (
<Container className="px-3"> <Container className="px-3">
<style type="text/css">
{`
a, a:hover, a:active {
color: #91877F;
text-decoration-color: #91877F;
}
`}
</style>
<h3 className="my-4 mx-3 font-weight-bold">My Page</h3> <h3 className="my-4 mx-3 font-weight-bold">My Page</h3>
<Card md={3} className="p-1 mb-4" style={{ background: '#F7F3F3' }}> <Card md={3} className="p-1 mb-4" style={{ background: '#F7F3F3' }}>
<Row className="p-2"> <Row className="p-2">
<Col md={5} className="d-flex align-content-center justify-content-center"> <Col md={5} className="d-flex align-content-center justify-content-center">
<Button variant="outline-light" onClick={handleShow}> <Button variant="outline-light" onClick={() => setShow(true)}>
{account.avatarUrl ? ( {account.avatarUrl ? (
<Image src={account.avatarUrl && `/images/${account.avatarUrl}`} className="img-thumbnail" <Image src={account.avatarUrl && `/images/${account.avatarUrl}`} className="img-thumbnail"
roundedCircle style={{ objectFit: "cover", width: "10rem", height: "10rem" }} /> roundedCircle style={{ objectFit: "cover", width: "10rem", height: "10rem" }} />
...@@ -104,9 +104,9 @@ function Account() { ...@@ -104,9 +104,9 @@ function Account() {
roundedCircle style={{ objectFit: "cover", width: "10rem", height: "10rem" }} /> roundedCircle style={{ objectFit: "cover", width: "10rem", height: "10rem" }} />
)} )}
</Button> </Button>
<Modal show={show} onHide={handleClose}> <Modal show={show} onHide={() => setShow(false)}>
<Modal.Header closeButton> <Modal.Header closeButton style={{background:"#F7F3F3"}}>
<Modal.Title>이미지를 변경하시겠습니까?</Modal.Title> <Modal.Title >이미지를 변경하시겠습니까?</Modal.Title>
</Modal.Header> </Modal.Header>
<Form onSubmit={handleSubmit}> <Form onSubmit={handleSubmit}>
<Modal.Body> <Modal.Body>
...@@ -118,8 +118,8 @@ function Account() { ...@@ -118,8 +118,8 @@ function Account() {
className="d-flex justify-content-start"><small>기본이미지로</small></Button> className="d-flex justify-content-start"><small>기본이미지로</small></Button>
{/* 기본이미지로 보내기 */} {/* 기본이미지로 보내기 */}
</Col> </Col>
<Button variant="secondary" onClick={handleClose}>취소</Button> <Button variant="secondary" onClick={() => setShow(false)}>취소</Button>
<Button variant="primary" type="submit" onClick={handleClose}>저장</Button> <Button variant="primary" type="submit" onClick={() => setShow(false)}>저장</Button>
</Modal.Footer> </Modal.Footer>
</Form> </Form>
</Modal> </Modal>
...@@ -128,21 +128,42 @@ function Account() { ...@@ -128,21 +128,42 @@ function Account() {
<Row className="mt-4 text-center"> <Row className="mt-4 text-center">
<Col> <Col>
<h2> <h2>
<strong>{account.name}</strong> <small>({account.id}){" "}님</small> <strong title='회원정보' style={{ cursor: "pointer", textDecoration: 'underline' }} onClick={() => setProshow(true)}>
{account.name}
</strong>
<Modal
size="sm"
show={proshow}
onHide={() => setProshow(false)}>
<Modal.Header closeButton style={{background:"#F7F3F3"}}>
<Modal.Title>회원정보</Modal.Title>
</Modal.Header>
<Modal.Body>
<Col className="p-1">
<li><strong>Role :</strong> {account.role}</li>
<li><strong>ID :</strong> {account.id}</li>
<li><strong>Username :</strong> {account.name}</li>
<li><strong>Email :</strong> {account.email}</li>
<li><strong>Tel :</strong> {account.tel}</li>
</Col>
</Modal.Body>
</Modal>
<small>{' '}({account.id}){" "}</small>
</h2> </h2>
</Col> </Col>
</Row> </Row>
<Row className="px-3"> <Row className="px-3">
<Card.Body className="p-2 text-center"> <Card.Body className="p-2 text-center">
<h4><Link to="/" class="link-warning"> <h4><Link to="/">
<strong title="홈으로"> <strong title="홈으로">
<Image src="/icon/mypagetiger.svg" width={"30rem"} roundedCircle className="img-thumbnail" > <Image src="/icon/mypagetiger.svg" width={"30rem"} roundedCircle className="img-thumbnail" >
</Image>KU# </Image>KU#
</strong> </strong>
</Link> </Link>
{/* 홈페이지로 돌아가기 */} 방문해주신 <em>{account.name}</em> 님,<br />
방문해주신 <em>{account.name}</em> 님,<br></br> 진심으로 환영합니다! 즐거운 쇼핑 되세요.
진심으로 환영합니다! 즐거운 쇼핑 되세요.</h4> </h4>
</Card.Body> </Card.Body>
</Row> </Row>
<Row className="mr-1 text-muted d-flex justify-content-end"> <Row className="mr-1 text-muted d-flex justify-content-end">
......
import React from 'react'; import React, { useState, useEffect, useRef } from 'react';
import { Redirect } from 'react-router-dom';
import ListCard from '../Components/ListCard';
import Pagination from '../Components/Pagination'; import Pagination from '../Components/Pagination';
import axios from 'axios';
import { isAdmin } from "../utils/auth";
import catchError from '../utils/catchErrors';
import { Row, Form, FormControl, Button, Card, Container } from 'react-bootstrap'; import { Row, Form, FormControl, Button, Card, Container } from 'react-bootstrap';
function Admin() { function Admin() {
function handleClick(e) { const [productlist, setProductlist] = useState([])
const card = e.target.parentNode.parentNode const [error, setError] = useState('')
alert('해당 상품을 성공적으로 삭제하였습니다.') const role = isAdmin()
card.remove()
useEffect(() => {
getProductlist()
}, [])
async function getProductlist() {
try {
const response = await axios.get(`/api/product/getproduct/all`)
console.log("response.data=", response.data)
setProductlist(response.data)
} catch (error) {
catchError(error, setError)
}
}
function handleSearch() {
} }
function handleSubmit(e) { function handleSubmit(e) {
e.preventDefault() e.preventDefault()
} }
if(!role) {
alert('죄송합니다.접근 권한이 없습니다.')
return <Redirect to="/" />
}
return ( return (
<div> <Container>
<style type="text/css"> <style type="text/css">
{` {`
.btn { .btn {
...@@ -28,7 +54,6 @@ function Admin() { ...@@ -28,7 +54,6 @@ function Admin() {
} }
`} `}
</style> </style>
<Container>
<Row as={Form} onSubmit={handleSubmit} className="justify-content-end mx-0 my-5"> <Row as={Form} onSubmit={handleSubmit} className="justify-content-end mx-0 my-5">
<FormControl type="text" placeholder="Search" style={{ width: "13rem" }} /> <FormControl type="text" placeholder="Search" style={{ width: "13rem" }} />
<Button type="submit" className="px-2"> <Button type="submit" className="px-2">
...@@ -36,89 +61,13 @@ function Admin() { ...@@ -36,89 +61,13 @@ function Admin() {
</Button> </Button>
<Button sm={2} xs={6} type="button" href="/regist" className="ml-1">상품 등록</Button> <Button sm={2} xs={6} type="button" href="/regist" className="ml-1">상품 등록</Button>
</Row> </Row>
<Row className="justify-content-start m-5"> <Row className="justify-content-center m-5">
<Card className="mt-5" style={{ width: "18rem", margin: "auto" }}> {productlist.map(pro => (
<Card.Img variant="top" src="https://img.sonyunara.com/files/goods/67460/1607053816_0.jpg" style={{ objectFit: "contain", height: "22rem" }} /> <ListCard id={pro._id} name={pro.pro_name} price={pro.price} main_img={pro.main_imgUrl} />
<Card.Body> ))}
<Card.Title>케이시앵글부츠(SH)</Card.Title>
<Card.Text>
재고: 8<br />
구매자 : 10
</Card.Text>
<Button className="float-right" onClick={(e) => handleClick(e)}>삭제</Button>
</Card.Body>
</Card>
<Card className="mt-5" style={{ width: "18rem", margin: "auto" }}>
<Card.Img variant="top" src="https://img.sonyunara.com/files/goods/48705/1552562469_0.jpg" style={{ objectFit: "contain", height: "22rem" }} />
<Card.Body>
<Card.Title>메리제인플랫(SH)</Card.Title>
<Card.Text>
재고: 20<br />
구매자 : 60
</Card.Text>
<Button className="float-right" onClick={(e) => handleClick(e)}>삭제</Button>
</Card.Body>
</Card>
<Card className="mt-5" style={{ width: "18rem", margin: "auto" }}>
<Card.Img variant="top" src="https://img.sonyunara.com/files/goods/53386/1567390097_2.jpg" style={{ objectFit: "contain", height: "22rem" }} />
<Card.Body>
<Card.Title>솔티드스니커즈(SH)</Card.Title>
<Card.Text>
재고: 34<br />
구매자 : 5
</Card.Text>
<Button className="float-right" onClick={(e) => handleClick(e)}>삭제</Button>
</Card.Body>
</Card>
<Card className="mt-5" style={{ width: "18rem", margin: "auto" }}>
<Card.Img variant="top" src="https://img.sonyunara.com/files/goods/61286/1587540563_0.jpg" style={{ objectFit: "contain", height: "22rem" }} />
<Card.Body>
<Card.Title>버켄슬리퍼(SH)</Card.Title>
<Card.Text>
재고: 50<br />
구매자 : 18
</Card.Text>
<Button className="float-right" onClick={(e) => handleClick(e)}>삭제</Button>
</Card.Body>
</Card>
<Card className="mt-5" style={{ width: "18rem", margin: "auto" }}>
<Card.Img variant="top" src="https://hotping.co.kr/web/product/big/202011/b8f4c6471955b80fc3991b7d6df8926a.jpg" style={{ objectFit: "contain", height: "22rem" }} />
<Card.Body>
<Card.Title>크레센도 하이힐펌프스</Card.Title>
<Card.Text>
재고: 35<br />
구매자 : 70
</Card.Text>
<Button className="float-right" onClick={(e) => handleClick(e)}>삭제</Button>
</Card.Body>
</Card>
<Card className="mt-5" style={{ width: "18rem", margin: "auto" }}>
<Card.Img variant="top" src="https://hotping.co.kr/web/product/big/202011/888e4e8d6a2c2e7da385b079151fcba2.jpg" style={{ objectFit: "contain", height: "22rem" }} />
<Card.Body>
<Card.Title>어텀솔져1cm 스웨이드로퍼</Card.Title>
<Card.Text>
재고: 40<br />
구매자 : 30
</Card.Text>
<Button className="float-right" onClick={(e) => handleClick(e)}>삭제</Button>
</Card.Body>
</Card>
<Card className="mt-5" style={{ width: "18rem", margin: "auto" }}>
<Card.Img variant="top" src="https://hotping.co.kr/web/product/big/202007/3308564012eb14e6c11ed621fa7555fb.jpg" style={{ objectFit: "contain", height: "22rem" }} />
<Card.Body>
<Card.Title>포웰3.5cm 스니커즈</Card.Title>
<Card.Text>
재고: 15<br />
구매자 : 50
</Card.Text>
<Button className="float-right" onClick={(e) => handleClick(e)}>삭제</Button>
</Card.Body>
</Card>
</Row> </Row>
<Pagination /> <Pagination />
</Container> </Container>
</div>
) )
} }
......
import React, { useState, useEffect, useRef } from 'react'; import React, { useState, useEffect, useRef } from 'react';
import { Link } from 'react-router-dom';
import ListCard from '../Components/ListCard'; import ListCard from '../Components/ListCard';
import axios from 'axios'; import axios from 'axios';
import catchError from '../utils/catchErrors'; import catchError from '../utils/catchErrors';
import { Card, Container, Row } from 'react-bootstrap'; import { Container, Row } from 'react-bootstrap';
function Home() { function Home() {
const [productlist, setProductlist] = useState([]) const INIT_PRODUCT = {
bestProduct: [],
newProduct: [],
}
const [productlist, setProductlist] = useState(INIT_PRODUCT)
const [error, setError] = useState('') const [error, setError] = useState('')
useEffect(() => { useEffect(() => {
...@@ -16,78 +21,67 @@ function Home() { ...@@ -16,78 +21,67 @@ function Home() {
async function getProductlist() { async function getProductlist() {
try { try {
const response = await axios.get(`/api/product/getproduct`) const response = await axios.get(`/api/product/getproduct`)
console.log(response.data) console.log("res=", response.data)
setProductlist(response.data) setProductlist({ bestProduct: response.data.bestProduct, newProduct: response.data.newProduct })
} catch (error) { } catch (error) {
catchError(error, setError) catchError(error, setError)
} }
} }
return ( return (
<div> <Container>
<Container className="my-5"> <style type="text/css">
{`
a, a:hover, a:active {
color: #000;
text-decoration: none;
`}
</style>
<div className="my-4"> <div className="my-4">
<h2 style={{ marginRight: "5rem", marginLeft: "3rem", marginBottom: "2rem" }}><u>Best</u></h2> <h2 style={{ marginRight: "5rem", marginLeft: "3rem", marginBottom: "2rem" }}><u>Best</u></h2>
<Row className="justify-content-center mx-0"> <Row className="justify-content-center mx-0">
<ListCard productlist={productlist} /> {productlist.bestProduct.map(pro => (
<Card className="mx-1 my-2" style={{ width: '18rem' }}> <Link to={{
<Card.Img className="img-fluid" variant="top" src="/icon/asd.jpg" /> pathname: `/product/${pro._id}`,
<Card.Body> state: {
<Card.Title className="font-weight-bold">제품명</Card.Title> id: pro._id,
<Card.Text>가격</Card.Text> name: pro.pro_name,
</Card.Body> price: pro.price,
</Card> colors: pro.colors,
sizes: pro.sizes,
description: pro.description,
main_img: pro.main_imgUrl,
detail_imgs: pro.detail_imgUrls
}
}}>
<ListCard id={pro._id} name={pro.pro_name} price={pro.price} main_img={pro.main_imgUrl} />
</Link>
))}
</Row> </Row>
</div> </div>
<div className="my-4"> <div className="my-4">
<h2 style={{ marginRight: "5rem", marginLeft: "3rem", marginBottom: "2rem", marginTop: "2rem" }}><u>New Arrival</u></h2> <h2 style={{ marginRight: "5rem", marginLeft: "3rem", marginBottom: "2rem", marginTop: "2rem" }}><u>New Arrival</u></h2>
<Row className="justify-content-center mx-0"> <Row className="justify-content-center mx-0">
<Card className="mx-1 my-2" style={{ width: '18rem' }}> {productlist.newProduct.map(pro => (
<Card.Img className="img-fluid" variant="top" src="/icon/asd.jpg" /> <Link to={{
<Card.Body> pathname: `/product/${pro._id}`,
<Card.Title className="font-weight-bold">제품명</Card.Title> state: {
<Card.Text>가격</Card.Text> id: pro._id,
</Card.Body> name: pro.pro_name,
</Card> price: pro.price,
<Card className="mx-1 my-2" style={{ width: '18rem' }}> colors: pro.colors,
<Card.Img className="img-fluid" variant="top" src="/icon/asd.jpg" /> sizes: pro.sizes,
<Card.Body> description: pro.description,
<Card.Title className="font-weight-bold">제품명</Card.Title> main_img: pro.main_imgUrl,
<Card.Text>가격</Card.Text> detail_imgs: pro.detail_imgUrls
</Card.Body> }
</Card> }}>
<Card className="mx-1 my-2" style={{ width: '18rem' }}> <ListCard id={pro._id} name={pro.pro_name} price={pro.price} main_img={pro.main_imgUrl} />
<Card.Img className="img-fluid" variant="top" src="/icon/asd.jpg" /> </Link>
<Card.Body> ))}
<Card.Title className="font-weight-bold">제품명</Card.Title>
<Card.Text>가격</Card.Text>
</Card.Body>
</Card>
<Card className="mx-1 my-2" style={{ width: '18rem' }}>
<Card.Img className="img-fluid" variant="top" src="/icon/asd.jpg" />
<Card.Body>
<Card.Title className="font-weight-bold">제품명</Card.Title>
<Card.Text>가격</Card.Text>
</Card.Body>
</Card>
<Card className="mx-1 my-2" style={{ width: '18rem' }}>
<Card.Img className="img-fluid" variant="top" src="/icon/asd.jpg" />
<Card.Body>
<Card.Title className="font-weight-bold">제품명</Card.Title>
<Card.Text>가격</Card.Text>
</Card.Body>
</Card>
<Card className="mx-1 my-2" style={{ width: '18rem' }}>
<Card.Img className="img-fluid" variant="top" src="/icon/asd.jpg" />
<Card.Body>
<Card.Title className="font-weight-bold">제품명</Card.Title>
<Card.Text>가격</Card.Text>
</Card.Body>
</Card>
</Row> </Row>
</div> </div>
</Container> </Container>
</div>
) )
} }
......
...@@ -27,8 +27,6 @@ function Login() { ...@@ -27,8 +27,6 @@ function Login() {
function handleChange(event) { function handleChange(event) {
const { name, value } = event.target const { name, value } = event.target
setUser({ ...user, [name]: value }) setUser({ ...user, [name]: value })
setAdmin({ ...admin, [name]: value })
} }
async function handleSubmit(event) { async function handleSubmit(event) {
...@@ -58,8 +56,6 @@ function Login() { ...@@ -58,8 +56,6 @@ function Login() {
window.location.href = '/' window.location.href = '/'
} }
return ( return (
<Container className="my-5"> <Container className="my-5">
<Row className="justify-content-center"> <Row className="justify-content-center">
...@@ -103,8 +99,8 @@ function Login() { ...@@ -103,8 +99,8 @@ function Login() {
</Form.Control.Feedback> </Form.Control.Feedback>
</Form.Row> </Form.Row>
</Form.Group> </Form.Group>
<Button style={{ background: '#91877F', borderColor: '#91877F' }} type="submit" block>Login</Button> <Button style={{ background: '#91877F', borderColor: '#91877F' }} type="submit" block >Login</Button>
<div className="loginLine"> <div className="loginLine m-1">
<Link to="/signup" style={{ color: '#91877F' }}>회원이 아니십니까?</Link> <Link to="/signup" style={{ color: '#91877F' }}>회원이 아니십니까?</Link>
</div> </div>
</Form> </Form>
......
import axios from 'axios';
import React, { useState, useEffect, useRef } from 'react'; import React, { useState, useEffect, useRef } from 'react';
import DaumPostcode from "react-daum-postcode"; import DaumPostcode from "react-daum-postcode";
import { Container, Card, Row, Col, Button, Form, FormGroup } from 'react-bootstrap'; import { Container, Card, Row, Col, Button, Form, FormGroup } from 'react-bootstrap';
import { Redirect } from 'react-router-dom'; import { Redirect, Link, useHistory } from 'react-router-dom';
import PaymentCard from '../Components/PaymentCard';
import { isAuthenticated } from '../utils/auth';
import catchErrors from '../utils/catchErrors';
function Payment() { function Payment({ match, location }) {
const [paymentWay, setPaymentWay] = useState([]) const [cart, setCart] = useState([])
const [isAddress, setIsAddress] = useState(""); const [order, setOrder] = useState({ products: [] })
const [isZoneCode, setIsZoneCode] = useState(); const [userData, setUserData] = useState({})
const [isPostOpen, setIsPostOpen] = useState(); const [error, setError] = useState()
const [post, setPost] = useState([]) const [post, setPost] = useState([])
const [redirect, setRedirect] = useState(null) const [redirect, setRedirect] = useState(null)
const [address, setAddress] = useState("") const [address, setAddress] = useState("")
const [num, setNum] = useState(0) const [finalPrice, setFinalPrice] = useState(0)
const [paymentWay, setPaymentWay] = useState([])
const [completeState, setCompleteState] = useState(false)
const user = isAuthenticated()
let history = useHistory();
const preCart = []
useEffect(() => {
getUser()
getCart()
}, [user])
useEffect(() => {
let price = 0
cart.map((el) => {
price = Number(el.count) * Number(el.productId.price) + price
})
setFinalPrice(price)
}, [cart])
async function getUser() {
const name = localStorage.getItem('name')
const tel = localStorage.getItem('tel')
const email = localStorage.getItem('email')
setUserData({ name: name, tel: tel, email: email })
}
async function getCart() {
try {
setError('')
const response = await axios.get(`/api/cart/showcart/${user}`)
console.log(response.data)
const preCart = response.data.filter((el) => el.checked === true)
if (preCart.length) {
setCart(preCart)
setOrder({ products: preCart })
} else {
alert("주문하실 상품이 없습니다.")
history.push("/home")
}
} catch (error) {
catchErrors(error, setError)
}
}
async function deleteOrder(e) {
try {
setError('')
const response = await axios.post('/api/cart/deletecart', {
userId: user,
cartId: e.target.name
})
console.log(response.data)
const preCart = response.data.products.filter((el) => el.checked === true)
setCart(preCart)
setOrder({ products: preCart })
} catch (error) {
catchErrors(error, setError)
}
}
function handleReceiverInfo(e) {
const { name, value } = e.target
console.log(name, value)
setOrder({ ...order, receiverInfo: { ...order.receiverInfo, [name]: value } })
}
function postClick() { function postClick() {
if (post.length !== 0) { if (post.length !== 0) {
...@@ -42,8 +111,8 @@ function Payment() { ...@@ -42,8 +111,8 @@ function Payment() {
} }
fullAddress += extraAddress !== "" ? ` (${extraAddress})` : ""; fullAddress += extraAddress !== "" ? ` (${extraAddress})` : "";
} }
setAddress({ full: fullAddress, zone: data.zonecode }); setAddress({ full: fullAddress, code: data.zonecode });
setOrder({ ...order, receiverInfo: { ...order.receiverInfo, address: fullAddress, postalCode: data.zonecode } })
console.log(fullAddress); console.log(fullAddress);
} }
...@@ -58,9 +127,9 @@ function Payment() { ...@@ -58,9 +127,9 @@ function Payment() {
function handleClick() { function handleClick() {
if (paymentWay.length !== 0) { if (paymentWay.length !== 0) {
setCompleteState(false)
setPaymentWay([]) setPaymentWay([])
} } else {
else {
const a = ( const a = (
<Row className="justify-content-md-center"> <Row className="justify-content-md-center">
<Col md={6} className="border m-5 p-5"> <Col md={6} className="border m-5 p-5">
...@@ -89,13 +158,46 @@ function Payment() { ...@@ -89,13 +158,46 @@ function Payment() {
} }
} }
function handleClick2() { async function kakaopay() {
if (paymentWay.length !== 0) {
setPaymentWay([]) setCompleteState("kakaopay")
} setPaymentWay(
<div className="text-center">
<p className=" font-weight-bold" style={{ display: 'inline' }}>'카카오페이'</p><p style={{ display: 'inline' }}>를 선택하셨습니다. </p>
<p>주문하기를 눌러 결제를 이어가주세요.</p>
</div>
)
// window.location.href = data.redirect_url
// setRedirect(data.redirect_url)
} }
async function kakaopay() { async function paymentCompleted() {
console.log(order)
const cartIds = []
order.products.map((el) => {
cartIds.push(el._id)
})
try {
setError('')
const response = await axios.post(`/api/order/addorder`, {
userId: user,
...order,
total: finalPrice + 2500
})
const response2 = await axios.post(`/api/cart/deletecart2`, {
userId: user,
cartId: cartIds
})
const response3 = await axios.post(`/api/product/pluspurchase`, {
products: order.products
})
if (completeState === "kakaopay") {
let itemNames = ""
if (cart.length > 1) {
itemNames = cart[0].productId.pro_name + '' + String(cart.length - 1) + ''
} else {
itemNames = cart[0].productId.pro_name
}
const response = await fetch('/api/kakaopay/test/single', { const response = await fetch('/api/kakaopay/test/single', {
method: "POST", method: "POST",
headers: { headers: {
...@@ -104,47 +206,35 @@ function Payment() { ...@@ -104,47 +206,35 @@ function Payment() {
body: JSON.stringify({ body: JSON.stringify({
cid: 'TC0ONETIME', cid: 'TC0ONETIME',
partner_order_id: 'partner_order_id', partner_order_id: 'partner_order_id',
partner_user_id: 'partner_user_id', partner_user_id: user,
item_name: '앙고라 반목 폴라 베이직 모헤어 니트 (T)', item_name: itemNames,
quantity: 1, quantity: cart.length,
total_amount: 22000, total_amount: finalPrice + 2500,
vat_amount: 200, vat_amount: 200,
tax_free_amount: 0, tax_free_amount: 0,
approval_url: 'http://localhost:3000/account', approval_url: 'http://localhost:3000/paymentcompleted',
fail_url: 'http://localhost:3000/shoppingcart', fail_url: 'http://localhost:3000/shoppingcart',
cancel_url: 'http://localhost:3000/kakaopay/payment', cancel_url: 'http://localhost:3000/shoppingcart',
}) })
}) })
const data = await response.json() const data = await response.json()
console.log(data)
window.location.href = data.redirect_url window.location.href = data.redirect_url
// setRedirect(data.redirect_url) } else {
} console.log(response.data)
console.log(response2.data)
function plusNum() { console.log(response3.data)
setNum(num + 1) alert("주문이 완료되었습니다.")
} history.push('/paymentcompleted')
function minusNum() {
if (num === 0) {
setNum(0)
} }
else { } catch (error) {
setNum(num - 1) catchErrors(error, setError)
alert("주문에 실패하셨습니다. 다시 확인해주세요.")
}
}
function deleteCart() {
//장바구니 DB에서 해당 항목 삭제
console.log('카트에 담긴 항목을 삭제했습니다.')
} }
if (redirect) {
console.log(redirect)
return <Redirect to={'/kakao'} />
} }
return ( return (
<div> <div>
{/* {console.log(completeState)} */}
<Container> <Container>
<h3 className="my-5 font-weight-bold text-center">주문/결제</h3> <h3 className="my-5 font-weight-bold text-center">주문/결제</h3>
<div> <div>
...@@ -154,15 +244,15 @@ function Payment() { ...@@ -154,15 +244,15 @@ function Payment() {
<Form> <Form>
<Form.Group controlId="formBasicName"> <Form.Group controlId="formBasicName">
<Form.Label>이름</Form.Label> <Form.Label>이름</Form.Label>
<Form.Control type="text" placeholder="윤지원" /> <Form.Control type="text" value={userData.name} readOnly />
</Form.Group>
<Form.Group controlId="formBasicEmail">
<Form.Label>이메일</Form.Label>
<Form.Control type="email" placeholder="jiwon5393@naver.com" />
</Form.Group> </Form.Group>
<Form.Group controlId="formBasicTel"> <Form.Group controlId="formBasicTel">
<Form.Label>휴대전화</Form.Label> <Form.Label>휴대전화</Form.Label>
<Form.Control type="tel" placeholder="010-0000-0000" /> <Form.Control type="tel" value={userData.tel} readOnly />
</Form.Group>
<Form.Group controlId="formBasicEmail">
<Form.Label>이메일</Form.Label>
<Form.Control type="email" value={userData.email} readOnly />
</Form.Group> </Form.Group>
</Form> </Form>
</Col> </Col>
...@@ -176,13 +266,17 @@ function Payment() { ...@@ -176,13 +266,17 @@ function Payment() {
<Form> <Form>
<Form.Group> <Form.Group>
<Form.Label>이름</Form.Label> <Form.Label>이름</Form.Label>
<Form.Control></Form.Control> <Form.Control type="text" name="name" onChange={handleReceiverInfo}></Form.Control>
</Form.Group>
<Form.Group>
<Form.Label>휴대전화</Form.Label>
<Form.Control type="text" name="tel" onChange={handleReceiverInfo}></Form.Control>
</Form.Group> </Form.Group>
<Form.Group controlId="formBasicAdd"> <Form.Group controlId="formBasicAdd">
<Form.Label>주소</Form.Label> <Form.Label>주소</Form.Label>
<Form.Row> <Form.Row>
<Col xs={4} sm={4}> <Col xs={4} sm={4}>
<Form.Control type="text" id="add" value={address.zone} disabled={(address.zone == null) ? false : true} placeholder="우편번호" required ></Form.Control> <Form.Control type="text" name="postalCode" id="add" onChange={handleReceiverInfo} value={address.code} disabled={(address.code == null) ? false : true} placeholder="우편번호" required ></Form.Control>
</Col> </Col>
<Col > <Col >
<Button style={{ background: '#91877F', borderColor: '#91877F' }} className="mx-1" onClick={postClick}>우편번호</Button> <Button style={{ background: '#91877F', borderColor: '#91877F' }} className="mx-1" onClick={postClick}>우편번호</Button>
...@@ -191,72 +285,46 @@ function Payment() { ...@@ -191,72 +285,46 @@ function Payment() {
</Form.Row> </Form.Row>
<Form.Row> <Form.Row>
<Col> <Col>
<Form.Control type="text" id="add1" value={address.full} disabled={(address.zone == null) ? false : true} placeholder="주소" required></Form.Control> <Form.Control type="text" name="address" id="add1" onChange={handleReceiverInfo} value={address.full} disabled={(address.code == null) ? false : true} placeholder="주소" required></Form.Control>
<Form.Control type="text" id="add2" placeholder="상세주소" required></Form.Control> <Form.Control type="text" name="address2" id="add2" onChange={handleReceiverInfo} placeholder="상세주소" required></Form.Control>
<Form.Control.Feedback type="invalid" > 상세 주소를 입력하세요. </Form.Control.Feedback> <Form.Control.Feedback type="invalid" > 상세 주소를 입력하세요. </Form.Control.Feedback>
</Col> </Col>
</Form.Row> </Form.Row>
</Form.Group> </Form.Group>
<Form.Group>
<Form.Label>휴대전화</Form.Label>
<Form.Control></Form.Control>
</Form.Group>
</Form> </Form>
</Col> </Col>
</Row> </Row>
</div> </div>
<div> <div>
<h5 className="font-weight-bold py-3 border-top border-bottom text-center" style={{ background: '#F7F3F3' }}>주문상품정보</h5> <h5 className="font-weight-bold py-3 border-top border-bottom text-center" style={{ background: '#F7F3F3' }}>주문상품정보</h5>
<Card > <PaymentCard cart={cart} deleteOrder={deleteOrder} />
<Row className="mx-1">
<Col className="text-center">
<Card.Img className="img-fluid" variant="top" src="img/asd.jpg" style={{ width: '20rem' }} />
</Col>
<Col md={6} className="p-2">
<Card.Body>
<input type="image" alt="삭제버튼" src="https://img.icons8.com/fluent-systems-regular/24/000000/close-window.png" className="float-right" onClick={deleteCart} />
<Card.Title className="font-weight-bold mt-3">제품명</Card.Title>
<Card.Text>가격</Card.Text>
<Card.Text>옵션</Card.Text>
<Card.Text>수량</Card.Text>
<div>
<input type="image" alt="마이너스" src="https://img.icons8.com/ios-glyphs/20/000000/minus-math.png" className="align-middle" onClick={minusNum} />
<input type="text" style={{ width: '30px' }} className="text-center align-middle mx-1" placeholder="1" value={num} readOnly></input>
<input type="image" alt="플러스" src="https://img.icons8.com/ios-glyphs/20/000000/plus-math.png" className="align-middle" onClick={plusNum} />
</div>
</Card.Body>
</Col>
</Row>
</Card>
</div> </div>
<div className="p-5 m-5" style={{ background: '#F7F3F3' }}> <div className="p-5 m-3" style={{ background: '#F7F3F3' }}>
<ul className="pl-0" style={{ listStyle: 'none' }}> <ul className="pl-0" style={{ listStyle: 'none' }}>
<li> <li>
<span className="text-secondary"> 상품금액</span> <span className="text-secondary"> 상품금액</span>
<span className="text-secondary float-right">12,000</span> <span className="text-secondary float-right">{finalPrice}</span>
</li> </li>
<li> <li>
<span className="text-secondary">배송비</span> <span className="text-secondary">배송비</span>
<span className="text-secondary float-right">2,500</span> <span className="text-secondary float-right">2500</span>
</li> </li>
</ul> </ul>
<div className="my-1 pt-2 border-top font-weight-bold"> <div className="my-1 pt-2 border-top font-weight-bold">
결제금액<span className="float-right">14,500</span> 결제금액<span className="float-right">{finalPrice + 2500}</span>
</div> </div>
</div> </div>
<div> <div>
<h5 className="font-weight-bold py-3 border-top border-bottom text-center" style={{ background: '#F7F3F3' }}>결제수단</h5> <h5 className="font-weight-bold py-3 border-top border-bottom text-center" style={{ background: '#F7F3F3' }}>결제수단</h5>
<div className="text-center mt-5"> <div className="text-center m-3">
<Button variant="success" className="align-top" onClick={handleClick} >무통장입금</Button> <Button className="align-top m-1" variant="success" onClick={handleClick} style={{ height: '42px' }}>무통장입금</Button>
<input type="image" alt="카카오페이결제" src="icon/payment_icon_yellow_small.png" onClick={kakaopay} /> <Button className="align-top m-1 p-0" style={{ borderColor: "#ffeb00" }} type="button" onClick={kakaopay} alt="카카오페이"><img src="icon/payment_icon_yellow_small2.png" /></Button>
</div> </div>
{paymentWay} {paymentWay}
</div> </div>
<div className="text-center"> <div className="text-center">
<Button className="px-5" style={{ background: "#91877F", borderColor: '#91877F' }} href="/account" block>결제완료</Button> <Button type="button" onClick={paymentCompleted} className="px-5" style={{ background: "#91877F", borderColor: '#91877F' }} block>결제완료</Button>
</div> </div>
</Container> </Container>
</div> </div>
......
import React, { useState, useEffect } from 'react'
import axios from 'axios';
import { isAuthenticated } from '../utils/auth'
import catchErrors from '../utils/catchErrors';
import { Card, Row, Col, Button, Alert } from 'react-bootstrap';
import { Link } from 'react-router-dom';
function PaymentCompleted() {
const user = isAuthenticated()
const [error, setError] = useState()
const [order, setOrder] = useState([])
const [total, setTotal] = useState(0)
const [receiverInfo, setReceiverInfo] = useState({})
useEffect(() => {
getOrder()
}, [user])
async function getOrder() {
try {
setError('')
const response = await axios.get(`/api/order/showorder/${user}`)
console.log(response.data)
setOrder(response.data.products)
setTotal(response.data.total)
setReceiverInfo(response.data.receiverInfo)
} catch (error) {
catchErrors(error, setError)
}
}
return (
<div>
<div className="mx-3 my-5 text-center px-3 py-4 border">
<div className="mb-1">
<h5 className=" font-weight-bold" style={{ display: 'inline' }}>고객님의 </h5>
<h5 className=" font-weight-bold text-danger" style={{ display: 'inline' }}>주문이 완료</h5>
<h5 className=" font-weight-bold " style={{ display: 'inline' }}>되었습니다!</h5>
</div>
<div className="mb-0">주문내역 확인은 마이페이지의 </div>
<div> "주문/배송조회"에서 하실 있습니다.</div>
</div>
<h3 className="text-center font-weight-bold my-3">주문내역</h3>
<h5 className="font-weight-bold py-3 border-top border-bottom text-center" style={{ background: '#F7F3F3' }}>받는사람 정보</h5>
<div className="m-3">
<Row>
<Col xs={4} className="text-right">이름</Col>
<Col>{receiverInfo.name}</Col>
</Row>
<Row>
<Col xs={4} className="text-right">전화번호</Col>
<Col>{receiverInfo.tel}</Col>
</Row>
<Row>
<Col xs={4} className="text-right">주소</Col>
<Col>{receiverInfo.address}{receiverInfo.address2}</Col>
</Row>
</div>
<h5 className="font-weight-bold py-3 border-top border-bottom text-center" style={{ background: '#F7F3F3' }}>주문 상품 정보</h5>
{order.map((e) => (
<Card className="mx-2">
<Row className="mx-1">
<Col className="text-center">
<Card.Img className="img-fluid" variant="top" src={e.productId.main_imgUrl && `/images/${e.productId.main_imgUrl}`} style={{ width: '20rem' }} />
</Col>
<Col md={6} className="p-2">
<Card.Body>
<Card.Title className="font-weight-bold mt-3">{e.productId.pro_name}</Card.Title>
<Card.Text className="mb-0">가격: {e.productId.price}</Card.Text>
<Card.Text className="mb-0">옵션: {e.size}/{e.color}</Card.Text>
<Card.Text>수량: {e.count}</Card.Text>
</Card.Body>
</Col>
</Row>
</Card>
))
}
<Row className="m-3 font-weight-bold py-3" style={{ background: '#F7F3F3' }}>
<Col xs={6} className="text-right"> 결제금액:</Col>
<Col>{total}</Col>
</Row>
<div className="text-center my-3">
<Button href="/" className="mx-1" style={{ background: "#91877F", borderColor: '#91877F', width: "7rem" }}>홈으로</Button>
<Button href="/account" className="mx-1" style={{ background: "#91877F", borderColor: '#91877F', width: "7rem" }}>마이페이지</Button>
</div>
</div>
)
}
export default PaymentCompleted
import axios from 'axios'; import axios from 'axios';
import React, { useState, useEffect, useRef } from 'react'; import React, { useState, useEffect, useRef } from 'react';
import { Row, Col, Form, Card, Button } from 'react-bootstrap'; import { Row, Col, Form, Card, Button, Modal } from 'react-bootstrap';
import { Redirect, useHistory } from 'react-router-dom';
import catchErrors from '../utils/catchErrors'; import catchErrors from '../utils/catchErrors';
const preCart = []
function Product({ match, location }) { function Product({ match, location }) {
const [product, setProduct] = useState(location.state) const [product, setProduct] = useState(location.state)
const [cart, setCart] = useState(location.state) const [color, setColor] = useState("")
const [size, setSize] = useState("")
const [cart, setCart] = useState([])
const [error, setError] = useState('') const [error, setError] = useState('')
const [selected, setSelected] = useState({ sizes: false, colors: false }) const [selected, setSelected] = useState({ sizes: false, colors: false })
const [count, setCount] = useState(1)
const [price, setPrice] = useState(0) const [price, setPrice] = useState(0)
const [show, setShow] = useState(false);
let history = useHistory();
const handleClose = () => setShow(false);
const handleShow = () => setShow(true);
useEffect(() => { useEffect(() => {
if (selected.sizes === true && selected.colors === true) { if (size && color) {
pushOptions() pushOptions()
console.log(preCart) // console.log(cart)
} }
}, [cart]) }, [size, color])
function handleClick(e) { function handleClick(e) {
const box = e.target.parentNode.parentNode const box = e.target.parentNode.parentNode
...@@ -26,79 +33,126 @@ function Product({ match, location }) { ...@@ -26,79 +33,126 @@ function Product({ match, location }) {
} }
function pushOptions() { function pushOptions() {
preCart.push(cart) // console.log(cart)
const a = cart.map(el => {
const rObj = {}
rObj["color"] = el.color;
rObj["size"] = el.size;
return rObj
})
const isDuplicated = a.some(el => el.color === color && el.size === size)
if (isDuplicated) {
selected.sizes = false
selected.colors = false
setColor("")
setSize("")
alert("이미 선택한 옵션입니다.")
} else {
selected.sizes = false selected.sizes = false
selected.colors = false selected.colors = false
setPrice(product.price+price) setCart([...cart, { color, size, productId: product.id, count: 1 , checked:false}])
setColor("")
setSize("")
setPrice(product.price + price)
} }
}
function handleChange(e) { function handleChange(e) {
const { name, value } = e.target const { name, value } = e.target
if (e.target.name === "sizes") { if (name === "sizes") {
setCart({ ...cart, [name]: value }) setSize(value)
selected.sizes = true selected.sizes = true
} else if (e.target.name === "colors") { } else if (name === "colors") {
setCart({ ...cart, [name]: value }) setColor(value)
selected.colors = true selected.colors = true
} }
// setCart({ ...cart, [name]: value })
// handleCreate()
} }
function listDelete(e) { function deleteOption(e) {
e.preventDefault() e.preventDefault()
const parent = e.target.parentNode let preprice = 0
parent.remove() const asd = cart.filter((el) => el.color !== e.target.id || el.size !== e.target.name)
} asd.map((el) => {
preprice = preprice + el.count * product.price
function handleCreate() { })
// if (product !== undefined) { setCart(asd)
// if (product.colors !== "" && product.sizes !== "") { setPrice(Number(preprice))
// cart.push( }
// <div className="d-flex justify-content-between my-2" >
// <p>{product.color} {product.size} </p> function handleCount(e) {
// <input name="count" type="number" min="0" max="10" style="width: 40px" onChange={handleChange} /> const addCount = cart.map((el) => {
// <p style="margin-bottom: 0px">{product.price}</p> if (el.color !== e.target.id || el.size !== e.target.name) {
// </div> return { ...el }
// ) } else {
// const list = document.getElementById('list') return { ...el, count: e.target.value }
// list.style.borderBottom = "1px solid" }
// const shopping = document.createElement('div') })
// shopping.className = "d-flex justify-content-between my-2" let preprice = 0
// shopping.innerHTML = `${product.color} / ${product.size} addCount.map((el) => {
// <input type="number" min="0" max="10" value="1" style="width: 40px" /> preprice = preprice + el.count * product.price
// <p style="margin-bottom: 0px">14,000원</p>` })
// const deleteA = document.createElement('a') setPrice(Number(preprice))
// deleteA.innerText = 'X' setCart(addCount)
// deleteA.addEventListener('click', listDelete) setCount(e.value)
// shopping.appendChild(deleteA) }
// list.appendChild(shopping)
// } async function addCart(event) {
// } console.log(cart)
} if (cart.length < 1) {
alert("옵션을 선택해주세요")
async function addCart() { }
else if (localStorage.getItem('id')) {
if (event.target.name === "shoppingcart") {
// preCart(color, size, count), productId(productlist에서 props), userId(로컬) 를 보내줌 // preCart(color, size, count), productId(productlist에서 props), userId(로컬) 를 보내줌
try { try {
setError('') setError('')
const response = await axios.put('/api/cart/addcart', { const response = await axios.put('/api/cart/addcart', {
userId: localStorage.getItem('loginStatus'), userId: localStorage.getItem('id'),
productId: "a8f4d63ead77717f940a2b27deb707a6", products: cart
products: preCart })
console.log(response.data)
setShow(true)
} catch (error) {
catchErrors(error, setError)
}
} else {
try {
setError('')
cart.map((el)=>{
el.checked = true
})
const response = await axios.put('/api/cart/addcart', {
userId: localStorage.getItem('id'),
products: cart
}) })
console.log(response) console.log(response.data)
history.push("/payment")
} catch (error) { } catch (error) {
catchErrors(error, setError) catchErrors(error, setError)
} }
} }
// useEffect(() => { } else {
// handleCreate() alert("로그인을 해주세요.")
// }, [product]) return <Redirect to='/login' />
}
}
return ( return (
<div> <div>
{console.log("match=",match.params, "location=",location.state, "product=",product)} <Modal show={show} onHide={handleClose}>
<Modal.Header closeButton>
<Modal.Title>장바구니에 상품담기</Modal.Title>
</Modal.Header>
<Modal.Body>정상적으로 장바구니에 상품을 담았습니다.</Modal.Body>
<Modal.Footer>
<Button variant="secondary" onClick={handleClose}>쇼핑계속하기</Button>
<Button variant="primary" href='/shoppingcart'>장바구니로 이동</Button>
</Modal.Footer>
</Modal>
{/* {console.log(cart)} */}
<style type="text/css"> <style type="text/css">
{` {`
.btn { .btn {
...@@ -122,30 +176,39 @@ function Product({ match, location }) { ...@@ -122,30 +176,39 @@ function Product({ match, location }) {
<Form style={{ borderBottom: "1px solid" }}> <Form style={{ borderBottom: "1px solid" }}>
<Form.Group style={{ borderBottom: "1px solid", paddingBottom: "2rem" }}> <Form.Group style={{ borderBottom: "1px solid", paddingBottom: "2rem" }}>
<Form.Label>색상</Form.Label> <Form.Label>색상</Form.Label>
<Form.Control as="select" className="mb-2" name="colors" defaultValue="옵션 선택" onChange={handleChange}> <Form.Control as="select" className="mb-2" name="colors" value={color} defaultValue="옵션 선택" onChange={handleChange}>
<option>옵션선택</option> <option>옵션선택</option>
{product.colors.map((e) => ( {product.colors.map((e) => (
<option>{e}</option> <option>{e}</option>
))} ))}
</Form.Control> </Form.Control>
<Form.Label>사이즈</Form.Label> <Form.Label>사이즈</Form.Label>
<Form.Control as="select" className="mb-2" name="sizes" defaultValue="옵션 선택" onChange={handleChange}> <Form.Control as="select" className="mb-2" name="sizes" value={size} defaultValue="옵션 선택" onChange={handleChange}>
<option>옵션선택</option> <option>옵션선택</option>
{product.sizes.map((e) => ( {product.sizes.map((e) => (
<option>{e}</option> <option>{e}</option>
))} ))}
</Form.Control> </Form.Control>
</Form.Group> </Form.Group>
{preCart.map((e) => ( {cart.map((e) => (
<div>{e.colors}/{e.sizes}</div> <Row className="mx-1">
<Col xs={6}>{e.color}/{e.size}</Col>
<Col xs={4} className="text-right" >
<input type='number' id={e.color} name={e.size} onChange={handleCount} value={count} style={{ width: '3rem' }} className="text-center" />
</Col>
<Col xs={2} className="text-right">
<input onClick={deleteOption} id={e.color} name={e.size} type="image" alt="삭제버튼" src="https://img.icons8.com/fluent-systems-regular/24/000000/close-window.png" className="align-middle" />
</Col>
</Row>
))} ))}
<Row className="justify-content-between mx-0 my-3" style={{ width: "100%" }}> <Row className="justify-content-between mx-0 my-3" style={{ width: "100%" }}>
<Col> 금액</Col> <Col> 금액</Col>
<Col className="text-right">{price}</Col> <Col className="text-right">{price}</Col>
</Row> </Row>
<Row className="justify-content-between mx-0 my-3" style={{ width: "100%" }}> <Row className="justify-content-between mx-0 my-3" style={{ width: "100%" }}>
<Button onClick={addCart} style={{ width: "49%" }}>장바구니</Button> <Button type='button' name="shoppingcart" onClick={addCart} style={{ width: "49%" }}>장바구니</Button>
<Button style={{ width: "49%" }}>구매하기</Button> <Button type='button' name="payment" onClick={addCart} style={{ width: "49%" }}>구매하기</Button>
</Row> </Row>
</Form> </Form>
</Col> </Col>
...@@ -159,7 +222,7 @@ function Product({ match, location }) { ...@@ -159,7 +222,7 @@ function Product({ match, location }) {
<Row className="justify-content-center mx-0 pt-3 px-2" style={{ position: "fixed", bottom: "0", width: "100%", backgroundColor: "#fff" }}> <Row className="justify-content-center mx-0 pt-3 px-2" style={{ position: "fixed", bottom: "0", width: "100%", backgroundColor: "#fff" }}>
<Col sm={12} md={9}> <Col sm={12} md={9}>
<h6 style={{ borderBottom: "1px solid", paddingBottom: "5px", marginBottom: "1em" }}>회원님이 선호할만한 상품 추천 <h6 style={{ borderBottom: "1px solid", paddingBottom: "5px", marginBottom: "1em" }}>회원님이 선호할만한 상품 추천
<a className="close float-right" onClick={(e) => handleClick(e)} style={{ fontSize: "1rem" }}>X</a> <a className="close float-right" onClick={(e) => handleClick(e)} style={{ fontSize: "1rem", cursor: "pointer" }}>X</a>
</h6> </h6>
<Row className="justify-content-space mx-0" style={{ flexWrap: "nowrap", width: "100%", overflowX: "auto" }}> <Row className="justify-content-space mx-0" style={{ flexWrap: "nowrap", width: "100%", overflowX: "auto" }}>
<Col as={Card} style={{ minWidth: "10rem", marginRight: "1rem" }}> <Col as={Card} style={{ minWidth: "10rem", marginRight: "1rem" }}>
......
import React, { useState, useEffect, useRef } from 'react'; import React, { useState, useEffect, useRef } from 'react';
import { Redirect } from 'react-router-dom'; import { Redirect } from 'react-router-dom';
import { Row, Col, Button, Form, Container, Alert } from 'react-bootstrap'; import { Row, Col, Button, Form, Container, Alert, Spinner } from 'react-bootstrap';
import axios from 'axios'; import axios from 'axios';
import catchErrors from '../utils/catchErrors'; import catchErrors from '../utils/catchErrors';
...@@ -23,13 +23,17 @@ function ProductsRegist() { ...@@ -23,13 +23,17 @@ function ProductsRegist() {
} }
const [categories, setCategories] = useState({ 0: [], 1: [[]] }) const [categories, setCategories] = useState({ 0: [], 1: [[]] })
const [product, setProduct] = useState(INIT_PRODUCT) const [product, setProduct] = useState(INIT_PRODUCT)
const [categoryNum, setCategoryNum] = useState(0) const [categoryNum, setCategoryNum] = useState('')
const [tag, setTag] = useState(0) const [tag, setTag] = useState(0)
const [subCate, setSubCate] = useState('') const [subCate, setSubCate] = useState('')
const [color, setColor] = useState({}) const [color, setColor] = useState({})
const [error, setError] = useState('') const [error, setError] = useState('')
const [success, setSuccess] = useState(false) const [success, setSuccess] = useState(false)
const [checked, setChecked] = useState({ "Free": false, "XL": false, "L": false, "M": false, "S": false, "XS": false }) const [checked, setChecked] = useState({ "Free": false, "XL": false, "L": false, "M": false, "S": false, "XS": false })
const [disabled, setDisabled] = useState(true)
const [loading, setLoading] = useState(false)
const selectRef = useRef(null)
const colorRef = useRef(null)
useEffect(async () => { useEffect(async () => {
try { try {
...@@ -41,28 +45,37 @@ function ProductsRegist() { ...@@ -41,28 +45,37 @@ function ProductsRegist() {
} }
}, []) }, [])
function addCategory() { useEffect(() => {
const isProduct = Object.values(product).every(el => { console.log("el=", el); Boolean(el) })
isProduct ? setDisabled(false) : setDisabled(true)
}, [product])
function addCategory(e) {
if (selectRef.current.value === '') {
alert('하위 분류를 반드시 선택해 주세요.')
} else {
list.push( list.push(
<div> <div>
<span name={subCate} >{product["main_category"]} / {subCate} </span> <span name={subCate} >{product["main_category"]} / {subCate} </span>
<input name={subCate} type="image" src="https://img.icons8.com/fluent-systems-regular/24/000000/close-window.png" className="float-right align-middle" onClick={deleteCategory} /> <input name={subCate} type="image" src="https://img.icons8.com/fluent-systems-regular/24/000000/close-window.png" className="float-right align-middle" onClick={deleteCategory} />
</div>) </div>)
setTag(tag + 1) setTag(tag + 1)
console.log(list) selectRef.current.selectedIndex = 0
}
} }
function deleteCategory(e) { function deleteCategory(e) {
e.target.parentNode.remove() e.target.parentNode.remove()
const index = product["sub_category"].findIndex((item)=>{return item === e.target.name}) const index = product["sub_category"].findIndex((item) => { return item === e.target.name })
product["sub_category"].splice(index, 1) product["sub_category"].splice(index, 1)
setSubCate('') setSubCate('')
console.log(product["sub_category"].length) console.log(product["sub_category"].length)
} }
function handleCategory(e) { function handleCategory(e) {
const { name, value } = e.target const { name, value, selectedIndex } = e.target
if (e.target.name === "main_category") { if (name === "main_category") {
setCategoryNum(e.target.selectedIndex - 1) setCategoryNum(selectedIndex - 1)
} }
if (name === "sub_category") { if (name === "sub_category") {
product[name].push(value) product[name].push(value)
...@@ -70,7 +83,6 @@ function ProductsRegist() { ...@@ -70,7 +83,6 @@ function ProductsRegist() {
} else { } else {
setProduct({ ...product, [name]: value }) setProduct({ ...product, [name]: value })
} }
console.log(value)
} }
function handleCheckBox(e) { function handleCheckBox(e) {
...@@ -85,15 +97,16 @@ function ProductsRegist() { ...@@ -85,15 +97,16 @@ function ProductsRegist() {
<input name={subCate} type="image" src="https://img.icons8.com/fluent-systems-regular/24/000000/close-window.png" className="float-right align-middle" onClick={deleteColor} /> <input name={subCate} type="image" src="https://img.icons8.com/fluent-systems-regular/24/000000/close-window.png" className="float-right align-middle" onClick={deleteColor} />
</div> </div>
) )
setColor({}) colorRef.current.value = ''
setProduct({ ...product, "colors": preColors }) setProduct({ ...product, "colors": preColors })
} }
function deleteColor(e) { function deleteColor(e) {
// console.log("e.name=",e.target.name)
e.target.parentNode.remove() e.target.parentNode.remove()
product["colors"].splice(e.name, 1) product["colors"].splice(e.name, 1)
setColor({}) // setColor({})
console.log(product) // console.log(product)
} }
function handleColor(e) { function handleColor(e) {
...@@ -102,13 +115,11 @@ function ProductsRegist() { ...@@ -102,13 +115,11 @@ function ProductsRegist() {
function handleChange(event) { function handleChange(event) {
const { name, value, files } = event.target const { name, value, files } = event.target
console.log("event.target.name=", name, "event.target.value=", value)
if (files) { if (files) {
setProduct({ ...product, [name]: files }) setProduct({ ...product, [name]: files })
} else { } else {
setProduct({ ...product, [name]: value }) setProduct({ ...product, [name]: value })
} }
} }
async function handleSubmit(e) { async function handleSubmit(e) {
...@@ -120,25 +131,35 @@ function ProductsRegist() { ...@@ -120,25 +131,35 @@ function ProductsRegist() {
} }
} }
product["sizes"] = sizes product["sizes"] = sizes
console.log(product)
const formData = new FormData(); const formData = new FormData();
for (let key in product) { for (let key in product) {
if (key === "main_image" ||key === "detail_image") { if (key === "main_image" || key === "detail_image") {
console.log(product[key][0])
formData.append(key, product[key][0]) formData.append(key, product[key][0])
} else { } else if (key === "sizes" || key === "colors" || key === "sub_category") {
for (let i = 0; i < product[key].length; i++) {
formData.append([key], product[key][i])
}
}
else {
formData.append(key, product[key]) formData.append(key, product[key])
} }
} }
try { try {
setLoading(true)
setError('')
const response = await axios.post('/api/product/regist', formData) const response = await axios.post('/api/product/regist', formData)
console.log(response) console.log(response)
setSuccess(true) setSuccess(true)
} catch (error) { } catch (error) {
catchErrors(error, setError) catchErrors(error, setError)
} finally {
setLoading(false)
} }
} }
if (success) { if (success) {
alert('상품 등록을 완료하였습니다.')
return <Redirect to='/admin' /> return <Redirect to='/admin' />
} }
...@@ -173,11 +194,11 @@ function ProductsRegist() { ...@@ -173,11 +194,11 @@ function ProductsRegist() {
</Form.Control> </Form.Control>
</Col> </Col>
<Col md={6}> <Col md={6}>
<Form.Control as="select" name="sub_category" onChange={handleCategory} disabled={product["main_category"] === "TRAINING"}> <Form.Control as="select" ref={selectRef} name="sub_category" onChange={handleCategory}>
<option value="" >하위분류</option> <option value="" >하위분류</option>
{categories[1][categoryNum].map((sub) => ( {(categoryNum === '') ? '' : (categories[1][categoryNum].map((sub) => (
<option value={sub}>{sub}</option> <option value={sub}>{sub}</option>
))} )))}
</Form.Control> </Form.Control>
</Col> </Col>
<Col > <Col >
...@@ -188,18 +209,37 @@ function ProductsRegist() { ...@@ -188,18 +209,37 @@ function ProductsRegist() {
</Form.Group> </Form.Group>
<Form.Group> <Form.Group>
<Form.Label>사이즈</Form.Label> <Form.Label>사이즈</Form.Label>
<Form.Check type="checkbox" name="sizes" label="Free" value="Free" onChange={handleCheckBox} /> <Row>
<Col>
<Form.Check type="checkbox" name="sizes" label="210" value="210" onChange={handleCheckBox} />
<Form.Check type="checkbox" name="sizes" label="215" value="215" onChange={handleCheckBox} />
<Form.Check type="checkbox" name="sizes" label="220" value="220" onChange={handleCheckBox} />
<Form.Check type="checkbox" name="sizes" label="225" value="225" onChange={handleCheckBox} />
<Form.Check type="checkbox" name="sizes" label="230" value="230" onChange={handleCheckBox} />
<Form.Check type="checkbox" name="sizes" label="235" value="235" onChange={handleCheckBox} />
<Form.Check type="checkbox" name="sizes" label="240" value="240" onChange={handleCheckBox} />
<Form.Check type="checkbox" name="sizes" label="245" value="245" onChange={handleCheckBox} />
<Form.Check type="checkbox" name="sizes" label="250" value="250" onChange={handleCheckBox} />
<Form.Check type="checkbox" name="sizes" label="255" value="255" onChange={handleCheckBox} />
<Form.Check type="checkbox" name="sizes" label="260" value="260" onChange={handleCheckBox} />
<Form.Check type="checkbox" name="sizes" label="265" value="265" onChange={handleCheckBox} />
<Form.Check type="checkbox" name="sizes" label="270" value="270" onChange={handleCheckBox} />
</Col>
<Col>
<Form.Check type="checkbox" name="sizes" label="FREE" value="FREE" onChange={handleCheckBox} />
<Form.Check type="checkbox" name="sizes" label="XL" value="XL" onChange={handleCheckBox} /> <Form.Check type="checkbox" name="sizes" label="XL" value="XL" onChange={handleCheckBox} />
<Form.Check type="checkbox" name="sizes" label="L" value="L" onChange={handleCheckBox} /> <Form.Check type="checkbox" name="sizes" label="L" value="L" onChange={handleCheckBox} />
<Form.Check type="checkbox" name="sizes" label="M" value="M" onChange={handleCheckBox} /> <Form.Check type="checkbox" name="sizes" label="M" value="M" onChange={handleCheckBox} />
<Form.Check type="checkbox" name="sizes" label="S" value="S" onChange={handleCheckBox} /> <Form.Check type="checkbox" name="sizes" label="S" value="S" onChange={handleCheckBox} />
<Form.Check type="checkbox" name="sizes" label="XS" value="XS" onChange={handleCheckBox} /> <Form.Check type="checkbox" name="sizes" label="XS" value="XS" onChange={handleCheckBox} />
</Col>
</Row>
</Form.Group> </Form.Group>
<Form.Group> <Form.Group>
<Form.Label>색상</Form.Label> <Form.Label>색상</Form.Label>
<Row> <Row>
<Col md={10}> <Col md={10}>
<Form.Control as="textarea" rows={1} name="colors" value={color["colors"]} placeholder="색상" onChange={handleColor} /> <Form.Control as="input" ref={colorRef} name="colors" placeholder="색상" onChange={handleColor} />
</Col> </Col>
<Col> <Col>
<Button className="float-right" style={{ background: '#91877F', borderColor: '#91877F' }} onClick={addColor}>추가</Button> <Button className="float-right" style={{ background: '#91877F', borderColor: '#91877F' }} onClick={addColor}>추가</Button>
...@@ -207,7 +247,6 @@ function ProductsRegist() { ...@@ -207,7 +247,6 @@ function ProductsRegist() {
</Row> </Row>
{colorHtml.map((element) => element)} {colorHtml.map((element) => element)}
</Form.Group> </Form.Group>
<Form.Group controlId="productDescriptionform"> <Form.Group controlId="productDescriptionform">
<Form.Label>상품설명</Form.Label> <Form.Label>상품설명</Form.Label>
<Form.Control as="textarea" name="description" rows={3} placeholder="상품을 설명해주세요" onChange={handleChange} /> <Form.Control as="textarea" name="description" rows={3} placeholder="상품을 설명해주세요" onChange={handleChange} />
...@@ -220,7 +259,9 @@ function ProductsRegist() { ...@@ -220,7 +259,9 @@ function ProductsRegist() {
<Form.Label>상세이미지</Form.Label> <Form.Label>상세이미지</Form.Label>
<Form.File id="productImageform" name="detail_image" onChange={handleChange} /> <Form.File id="productImageform" name="detail_image" onChange={handleChange} />
</Form.Group> </Form.Group>
<Button className="float-right" type="submit" style={{ background: '#91877F', borderColor: '#91877F' }}>등록</Button> <Button type="submit" style={{ background: '#91877F', borderColor: '#91877F' }} block>
{loading && <Spinner as='span' animation='border' size='sm' role='status' aria-hidden='true' />}{' '}등록
</Button>
</Form> </Form>
</Col> </Col>
</Row> </Row>
......
import React, { useState, useEffect, useRef } from 'react'; import React, { useState, useEffect, useRef } from 'react';
import { Link } from 'react-router-dom'; import { Link } from 'react-router-dom';
import ListCard from '../Components/ListCard'; import ListCard from '../Components/ListCard';
import Pagination from '../Components/Pagination';
import axios from 'axios'; import axios from 'axios';
import catchError from '../utils/catchErrors'; import catchError from '../utils/catchErrors';
import { isAuthenticated } from '../utils/auth'; import { Container, Row, Col, Form, FormControl, Button, Dropdown, ButtonGroup } from 'react-bootstrap';
import { Container, Row, Col, Form, FormControl, Button, Dropdown } from 'react-bootstrap';
import catchErrors from '../utils/catchErrors';
function ProductsList({ match }) { function ProductsList({ match }) {
const [mainCategory, setMainCategory] = useState(match.params.main.toUpperCase()) const [mainCategory, setMainCategory] = useState(match.params.main.toUpperCase())
const [subcategory, setSubcategory] = useState([]) const [subcategory, setSubcategory] = useState([])
const [productlist, setProductlist] = useState([]) const [productlist, setProductlist] = useState([])
const [bestlist, setBestlist] = useState([])
const [newlist, setNewlist] = useState([])
const [sub, setSub] = useState([])
const [error, setError] = useState('') const [error, setError] = useState('')
// const user=isAuthenticated() useEffect(() => {
setMainCategory(match.params.main.toUpperCase())
}, [match.params.main])
useEffect(() => { useEffect(() => {
// getSubsCategories() getSubsCategories([])
getProductlist() getProductlist()
}, [mainCategory]) }, [mainCategory])
useEffect(() => {
setMainCategory(match.params.main.toUpperCase())
}, [match.params.main])
function handleSearch() { function handleSearch() {
} }
// async function handleClick(subCategory) { async function getSubsCategories([]) {
// try { try {
// const response = await axios.get(`/api/product/getproduct/${subCategory}`) const response = await axios.get(`/api/categories/sub/${mainCategory}`)
// console.log("response.data=", response.data) setSubcategory(Object.values(response.data)[0])
// setProductlist(response.data)
// } catch (error) {
// catchErrors(error, setError)
// }
// }
// function handleSubmit(e) {
// e.preventDefault()
// }
// async function getSubsCategories() { console.log("response data=", response.data)
// try { console.log("object value=", Object.values(response.data));
// const response = await axios.get(`/api/categories/sub/${mainCategory}`)
// console.log("sub", response.data)
// setSubcategory(response.data)
// } catch (error) {
// catchError(error, setError)
// }
// }
async function getProductlist() {
try {
const response = await axios.get(`/api/product/getproduct/${mainCategory}`)
console.log("response.data=", response.data)
setProductlist(response.data)
} catch (error) { } catch (error) {
catchError(error, setError) catchError(error, setError)
} }
} }
function handleClick(e){ async function getProductlist() {
e.preventDefault()
return getsubproductlist()
}
async function getsubproductlist(){
try { try {
const response = await axios.get(`/api/product/getproduct/${subcategory}`) const response = await axios.get(`/api/product/getproduct/${mainCategory}`)
console.log("response.data sub=",response.data) console.log("response.data=", response.data)
setProductlist(response.data) setProductlist(response.data)
} catch (error) { } catch (error) {
catchErrors(error,setError) catchError(error, setError)
} }
} }
return ( return (
<div> <div>
{console.log("main=",mainCategory)}
<style type="text/css"> <style type="text/css">
{` {`
a, a:hover, a:active { a, a:hover, a:active {
...@@ -104,21 +71,22 @@ function ProductsList({ match }) { ...@@ -104,21 +71,22 @@ function ProductsList({ match }) {
`} `}
</style> </style>
<Container> <Container>
<Row className="justify-content-center" > <Row className="justify-content-center">
<Col sm={10} xs={12} > <Col sm={10} xs={12} >
<h1 style={{ fontSize: "3rem" }} className="text-center">{mainCategory}</h1> <h1 style={{ fontSize: "3rem" }} className="text-center">{mainCategory}</h1>
<div className="text-center">{subcategory.map((ele) => ( <div className="text-center">
<Button className="m-1" onClick={(ele) => handleClick(ele)}>{ele}</Button> <ButtonGroup className="m-3" variant="outline-light secondary" style={{ display: "inline-block" }}>
))}</div> {subcategory.map(el => (<Button className="m-1" variant="secondary">{el}</Button>))}
</ButtonGroup>
</div>
</Col> </Col>
</Row> </Row>
<Row className="justify-content-end mx-0 my-5"> <Row className="justify-content-end mx-0 my-5">
{/* <Form as={Row} onSubmit={handleSubmit} className="justify-content-end mx-0"> */}
<Dropdown> <Dropdown>
<Dropdown.Toggle className="mx-2">정렬</Dropdown.Toggle> <Dropdown.Toggle className="mx-2">정렬</Dropdown.Toggle>
<Dropdown.Menu> <Dropdown.Menu>
<Dropdown.Item >인기상품</Dropdown.Item> <Dropdown.Item>인기상품</Dropdown.Item>
<Dropdown.Item >신상품</Dropdown.Item> <Dropdown.Item>신상품</Dropdown.Item>
<Dropdown.Item>낮은가격</Dropdown.Item> <Dropdown.Item>낮은가격</Dropdown.Item>
<Dropdown.Item>높은가격</Dropdown.Item> <Dropdown.Item>높은가격</Dropdown.Item>
</Dropdown.Menu> </Dropdown.Menu>
...@@ -129,10 +97,22 @@ function ProductsList({ match }) { ...@@ -129,10 +97,22 @@ function ProductsList({ match }) {
<img src="/icon/search.svg" width="20" height="20" /> <img src="/icon/search.svg" width="20" height="20" />
</Button> </Button>
</Form> </Form>
{/* </Form> */}
</Row> </Row>
<Row md={8} sm={12} className="justify-content-start m-2"> <Row md={8} sm={12} className="justify-content-center m-2">
{productlist.map(pro => ( {productlist.map(pro => (
// <ListCard as={Link} id={pro._id} name={pro.pro_name} price={pro.price} main_img={pro.main_imgUrl} to={{
// pathname: `/product/${pro._id}`,
// state: {
// id: pro._id,
// name: pro.pro_name,
// price: pro.price,
// colors: pro.colors,
// sizes: pro.sizes,
// description: pro.description,
// main_img: pro.main_imgUrl,
// detail_imgs: pro.detail_imgUrls
// }
// }} />
<Link to={{ <Link to={{
pathname: `/product/${pro._id}`, pathname: `/product/${pro._id}`,
state: { state: {
...@@ -151,7 +131,6 @@ function ProductsList({ match }) { ...@@ -151,7 +131,6 @@ function ProductsList({ match }) {
))} ))}
</Row> </Row>
</Container> </Container>
{/* <Pagination postsPerPage={postsPerPage} totalPosts={posts.length} paginate={paginate} /> */}
</div> </div>
) )
} }
......
...@@ -7,50 +7,94 @@ import { isAuthenticated } from '../utils/auth' ...@@ -7,50 +7,94 @@ import { isAuthenticated } from '../utils/auth'
import CartCard from '../Components/CartCard'; import CartCard from '../Components/CartCard';
function ShoppingCart() { function ShoppingCart() {
const [num, setNum] = useState()
const [error, setError] = useState('') const [error, setError] = useState('')
const [cart, setCart] = useState([]) const [cart, setCart] = useState([])
const [finalCart, setFinalCart] = useState([])
const [finalPrice, setFinalPrice] = useState(0) const [finalPrice, setFinalPrice] = useState(0)
const user = isAuthenticated() const user = isAuthenticated()
useEffect(() => { useEffect(() => {
getCart() getCart()
// console.log(cart)
}, [user]) }, [user])
function plusNum() { function plusNum(e) {
num = num + 1 const addCount = cart.map((el) => {
setNum(num + 1) if (el._id === e.target.name) {
return { ...el, count: el.count+1}
} else {
return { ...el }
} }
function minusNum() { })
if (num === 0) { setCart(addCount)
setNum(0) }
function minusNum(e) {
const addCount = cart.map((el) => {
if (el._id === e.target.name) {
return { ...el, count: el.count-1 }
} else {
return { ...el }
} }
else { })
setNum(num - 1) setCart(addCount)
}
function checkedCart(e) {
let price = 0
const cartCheck = cart.map((el) => {
if (el._id === e.target.name) {
return { ...el, checked: !el.checked }
} else {
return { ...el }
} }
})
const asd = cartCheck.filter((el) => el.checked === true)
asd.map((el)=>{
price = el.count*el.productId.price + price
})
setFinalPrice(price)
setCart(cartCheck)
setFinalCart(asd)
} }
async function deleteCart(e) { async function deleteCart(e) {
//장바구니 DB에서 해당 항목 삭제 //장바구니 DB에서 해당 항목 삭제
console.log(e.target.name) // console.log(e.target.name)
try { try {
const response = await axios.post('/api/cart/deletecart', { cartId: e.target.name }) const response = await axios.post('/api/cart/deletecart', {
userId: user,
cartId: e.target.name
})
console.log(response.data) console.log(response.data)
setCart(response.data.products)
} catch (error) { } catch (error) {
catchErrors(error, setError) catchErrors(error, setError)
} }
// console.log('카트에 담긴 항목을 삭제했습니다.')
console.log('카트에 담긴 항목을 삭제했습니다.')
} }
async function getCart() { async function getCart() {
try { try {
setError('')
const response = await axios.get(`/api/cart/showcart/${user}`) const response = await axios.get(`/api/cart/showcart/${user}`)
console.log(response.data) const addChecked = response.data.map((el) => {
setCart(response.data) return { ...el, checked: false }
const finalPrices = response.data.map((e) => {
return e.count * e.productId.price
}) })
setFinalPrice(finalPrices.reduce((a, b) => (a + b))) console.log("addchecked=",addChecked)
setCart(addChecked)
} catch (error) {
catchErrors(error, setError)
}
}
function putCheckedCart(){
try {
setError('')
const response = axios.post(`/api/cart/changecart`, {
userId:user,
products: cart
})
console.log(response.data)
} catch (error) { } catch (error) {
catchErrors(error, setError) catchErrors(error, setError)
} }
...@@ -58,12 +102,13 @@ function ShoppingCart() { ...@@ -58,12 +102,13 @@ function ShoppingCart() {
return ( return (
<div> <div>
{/* {console.log(cart)} */}
<Container className="justify-content-center"> <Container className="justify-content-center">
<h1 className="my-5 font-weight-bold text-center">장바구니</h1> <h1 className="my-5 font-weight-bold text-center">장바구니</h1>
<div> <div>
<h4 className="font-weight-bold py-3 border-top border-bottom text-center" style={{ background: '#F7F3F3' }}>주문상품정보</h4> <h4 className="font-weight-bold py-3 border-top border-bottom text-center" style={{ background: '#F7F3F3' }}>주문상품정보</h4>
{cart.length >0 {cart.length > 0
? <CartCard cart={cart} deleteCart={deleteCart} minusNum={minusNum} plusNum={plusNum} num={num} /> ? <CartCard cart={cart} deleteCart={deleteCart} minusNum={minusNum} plusNum={plusNum} checkedCart={checkedCart} />
: <div className="text-center my-5">장바구니에 담긴 상품이 없습니다.</div>} : <div className="text-center my-5">장바구니에 담긴 상품이 없습니다.</div>}
</div> </div>
...@@ -85,8 +130,8 @@ function ShoppingCart() { ...@@ -85,8 +130,8 @@ function ShoppingCart() {
<div className="text-center"> <div className="text-center">
<Button as={Link} to={{ <Button as={Link} to={{
pathname: `/payment`, pathname: `/payment`,
state: { cart } state: finalCart
}} className="px-5" style={{ background: "#91877F", borderColor: '#91877F' }} block>결제하기</Button> }} className="px-5" style={{ background: "#91877F", borderColor: '#91877F' }} onClick={putCheckedCart} block>결제하기</Button>
</div> </div>
</Container> </Container>
......
...@@ -10,7 +10,8 @@ const INIT_USER = { ...@@ -10,7 +10,8 @@ const INIT_USER = {
id: '', id: '',
password: '', password: '',
password2: '', password2: '',
tel: '' tel: '',
email: ''
} }
function Signup() { function Signup() {
...@@ -61,10 +62,10 @@ function Signup() { ...@@ -61,10 +62,10 @@ function Signup() {
if (success) { if (success) {
alert('회원가입 되었습니다.') alert('회원가입 되었습니다.')
return <Redirect to='/login'/> return <Redirect to='/login' />
} }
return ( return (
<div> <div>
<Container className="my-5"> <Container className="my-5">
...@@ -94,27 +95,31 @@ return ( ...@@ -94,27 +95,31 @@ return (
<Form.Group controlId="formBasicNumber"> <Form.Group controlId="formBasicNumber">
<Form.Row> <Form.Row>
<Col sm={4} xs={6} as={Form.Label} for="number">주민등록번호</Col> <Col sm={4} xs={6} as={Form.Label} for="number">주민등록번호</Col>
<Col as={Row} sm={8} xs={10} > <Row>
<Form.Control <Form.Control
required type="text" required type="text"
name="number1" name="number1"
maxlength="6" maxlength="6"
className="mx-2" style={{ width: '17 0px' }} className="mx-3 p-1" style={{ width: '80px' }}
value={user.number1} value={user.number1}
onChange={handleChange}> onChange={handleChange}>
</Form.Control> </Form.Control>
<div className='font-weight-bold d-flex align-items-center' style={{ text: 'center' }}>
- -
</div>
<Form.Control <Form.Control
required type="text" required type="text"
name="number2" name="number2"
maxlength="1" className="mx-3" maxlength="1" className="mx-3 p-1"
style={{ width: '50px' }} style={{ width: '30px' }}
value={user.number2} value={user.number2}
onChange={handleChange}> onChange={handleChange}>
</Form.Control> </Form.Control>
****** <div className='font-weight-bold d-flex align-items-center'>
* * * * * *
</div>
<Form.Control.Feedback type="invalid">주민등록번호를 입력하세요.</Form.Control.Feedback> <Form.Control.Feedback type="invalid">주민등록번호를 입력하세요.</Form.Control.Feedback>
</Col> </Row>
</Form.Row> </Form.Row>
</Form.Group> </Form.Group>
<Form.Group controlId="formBasicId"> <Form.Group controlId="formBasicId">
...@@ -164,16 +169,35 @@ return ( ...@@ -164,16 +169,35 @@ return (
</Form.Control.Feedback> </Form.Control.Feedback>
</Form.Row> </Form.Row>
</Form.Group> </Form.Group>
<Form.Group controlId="formBasicEmail">
<Form.Row>
<Col sm={4} xs={6} as={Form.Label} for="email">이메일</Col>
<Col sm={8} xs={12} as={Form.Control}
required type="email"
name="email"
placeholder="E-mail"
style={{ width: '160px' }}
value={user.email}
onChange={handleChange} />
<Form.Control.Feedback type="invalid"> 이메일 입력하세요. </Form.Control.Feedback>
</Form.Row>
</Form.Group>
<Form.Group controlId="formBasicTel"> <Form.Group controlId="formBasicTel">
<Form.Row> <Form.Row>
<Col sm={4} xs={6} as={Form.Label} for="tel">휴대전화</Col> <Col sm={4} xs={6} as={Form.Label} for="tel">휴대전화</Col>
<Col sm={8} xs={12} as={Form.Control} <Col sm={8} xs={12} style={{ width: '160px' }} className='p-0'>
required <Col
type="text" as={Form.Control}
required type="text"
name="tel" name="tel"
size="sm" style={{ width: '160px' }} placeholder="Telephone"
className='p-1'
value={user.tel} value={user.tel}
onChange={handleChange} /> onChange={handleChange}>
</Col>
<div className='d-flex justify-content-end mt-1'><small >' - ' 함께 입력해주세요^^</small></div>
</Col>
<Form.Control.Feedback type="invalid"> 휴대전화를 입력하세요. </Form.Control.Feedback> <Form.Control.Feedback type="invalid"> 휴대전화를 입력하세요. </Form.Control.Feedback>
</Form.Row> </Form.Row>
</Form.Group> </Form.Group>
...@@ -188,7 +212,7 @@ return ( ...@@ -188,7 +212,7 @@ return (
</Row> </Row>
</Container> </Container>
</div> </div>
) )
} }
export default Signup export default Signup
\ No newline at end of file
import axios from "axios" import axios from "axios";
export function handleLogin({userId,adminId,role,name}){ export function handleLogin({ userId, role, name, tel, email }) {
localStorage.setItem('id',userId) localStorage.setItem('id', userId)
localStorage.setItem('role',role) localStorage.setItem('role', role)
localStorage.setItem('name',name) localStorage.setItem('name', name)
localStorage.setItem('adminId',adminId) localStorage.setItem('tel', tel)
localStorage.setItem('email', email)
} }
export async function handleLogout(){ export async function handleLogout() {
localStorage.removeItem('id') localStorage.clear()
localStorage.removeItem('role')
localStorage.removeItem('name')
localStorage.removeItem('adminId')
localStorage.removeItem('adminrole')
localStorage.removeItem('adminname')
await axios.get('/api/auth/logout') await axios.get('/api/auth/logout')
window.location.href = '/' window.location.href = '/'
} }
export function isAuthenticatedAdmin(){ export function isAuthenticated() {
const adminId= localStorage.getItem('adminId') const userId = localStorage.getItem('id')
if(adminId){ if (userId) {
return adminId return userId
} else { } else {
return false return false
} }
} }
export function isAuthenticated(){ export function isAdmin() {
const userId= localStorage.getItem('id') const role = localStorage.getItem('role')
if(userId){ if (role === 'admin') {
return userId return true
} else { } else {
return false return false
} }
} }
\ No newline at end of file
...@@ -9,6 +9,7 @@ import path from 'path' ...@@ -9,6 +9,7 @@ import path from 'path'
import kakaopayRoutes from './routes/kakaopay.routes.js' import kakaopayRoutes from './routes/kakaopay.routes.js'
import config from './config.js' import config from './config.js'
import authRouter from './routes/auth.routes.js' import authRouter from './routes/auth.routes.js'
import orderRouter from './routes/order.routes.js'
import cors from 'cors' import cors from 'cors'
fs.readdir('uploads', (error) => { fs.readdir('uploads', (error) => {
...@@ -33,6 +34,7 @@ app.use('/api/users',userRouter) ...@@ -33,6 +34,7 @@ app.use('/api/users',userRouter)
app.use('/api/auth',authRouter) app.use('/api/auth',authRouter)
app.use('/api/product', productRouter) app.use('/api/product', productRouter)
app.use('/api/cart', cartRouter) app.use('/api/cart', cartRouter)
app.use('/api/order', orderRouter)
app.listen(config.port, () => { app.listen(config.port, () => {
console.info('Server started on port %s.', config.port) console.info('Server started on port %s.', config.port)
......
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