Product.js 13.3 KB
Newer Older
kusang96's avatar
card    
kusang96 committed
1
2
3
import React, { useState, useEffect } from 'react';
import { Redirect, Link, useHistory } from 'react-router-dom';
import ListCard from "../Components/ListCard";
4
import axios from 'axios';
5
import catchErrors from '../utils/catchErrors';
6
import { Row, Col, Form, Card, Button, Modal, Image } from 'react-bootstrap';
kusang96's avatar
kusang96 committed
7
8


9
function Product({ match, location }) {
kusang96's avatar
0115    
kusang96 committed
10
    const [product, setProduct] = useState(location.state)
kusang96's avatar
card    
kusang96 committed
11
    const [productList, setProductList] = useState([])
Jiwon Yoon's avatar
Jiwon Yoon committed
12
13
14
    const [color, setColor] = useState("")
    const [size, setSize] = useState("")
    const [cart, setCart] = useState([])
15
    const [error, setError] = useState('')
16
    const [selected, setSelected] = useState({ sizes: false, colors: false })
Jiwon Yoon's avatar
Jiwon Yoon committed
17
    const [count, setCount] = useState(1)
Jiwon Yoon's avatar
0113    
Jiwon Yoon committed
18
    const [price, setPrice] = useState(0)
Jiwon Yoon's avatar
Jiwon Yoon committed
19
20
21
22
    const [show, setShow] = useState(false);
    let history = useHistory();
    const handleClose = () => setShow(false);
    const handleShow = () => setShow(true);
Jiwon Yoon's avatar
Jiwon Yoon committed
23

kusang96's avatar
card    
kusang96 committed
24
25
26
27
    useEffect(() => {
        recommend()
    }, [])

28
    useEffect(() => {
Jiwon Yoon's avatar
Jiwon Yoon committed
29
        if (size && color) {
30
            pushOptions()
Jiwon Yoon's avatar
Jiwon Yoon committed
31
        }
Jiwon Yoon's avatar
Jiwon Yoon committed
32
        getRecommend()
Jiwon Yoon's avatar
Jiwon Yoon committed
33
    }, [size, color])
kusang96's avatar
kusang96 committed
34

Jiwon Yoon's avatar
Jiwon Yoon committed
35
    async function getRecommend(){
이재연's avatar
aaaa    
이재연 committed
36
        try {
Jiwon Yoon's avatar
Jiwon Yoon committed
37
            const response = await axios.get(`/api/order/recommend?products=${product.id}`)
kusang96's avatar
card    
kusang96 committed
38
            setProductList(response.data)
이재연's avatar
aaaa    
이재연 committed
39
        } catch (error) {
Jiwon Yoon's avatar
Jiwon Yoon committed
40
            catchErrors(error,setError)
이재연's avatar
aaaa    
이재연 committed
41
42
43
        }
    }

kusang96's avatar
kusang96 committed
44
45
46
47
48
    function handleClick(e) {
        const box = e.target.parentNode.parentNode
        box.style.display = "none"
    }

49
    function pushOptions() {
kusang96's avatar
kusang96 committed
50
51
52
53
54
        const cartSet = cart.map(el => {
            const newObj = {}
            newObj["color"] = el.color;
            newObj["size"] = el.size;
            return newObj
Jiwon Yoon's avatar
Jiwon Yoon committed
55
        })
kusang96's avatar
kusang96 committed
56
        const isDuplicated = cartSet.some(el => el.color === color && el.size === size)
Jiwon Yoon's avatar
Jiwon Yoon committed
57
58
59
60
61
62
63
64
65
        if (isDuplicated) {
            selected.sizes = false
            selected.colors = false
            setColor("")
            setSize("")
            alert("이미 선택한 옵션입니다.")
        } else {
            selected.sizes = false
            selected.colors = false
66
            setCart([...cart, { color, size, productId: product.id, count: 1, checked: false }])
Jiwon Yoon's avatar
Jiwon Yoon committed
67
68
69
70
            setColor("")
            setSize("")
            setPrice(product.price + price)
        }
71
    }
Jiwon Yoon's avatar
Jiwon Yoon committed
72

kusang96's avatar
kusang96 committed
73
74
    function handleChange(e) {
        const { name, value } = e.target
Jiwon Yoon's avatar
Jiwon Yoon committed
75
76
        if (name === "sizes") {
            setSize(value)
77
            selected.sizes = true
Jiwon Yoon's avatar
Jiwon Yoon committed
78
79
        } else if (name === "colors") {
            setColor(value)
80
81
            selected.colors = true
        }
kusang96's avatar
kusang96 committed
82
83
    }

Jiwon Yoon's avatar
Jiwon Yoon committed
84
    function deleteOption(e) {
kusang96's avatar
kusang96 committed
85
        e.preventDefault()
86
        let preprice = 0
kusang96's avatar
kusang96 committed
87
88
        const list = cart.filter((el) => el.color !== e.target.id || el.size !== e.target.name)
        list.map((el) => {
박상호's avatar
박상호 committed
89
            preprice = preprice + el.count * product.price
90
        })
kusang96's avatar
kusang96 committed
91
        setCart(list)
92
        setPrice(Number(preprice))
kusang96's avatar
kusang96 committed
93
94
    }

Jiwon Yoon's avatar
Jiwon Yoon committed
95
    function handleCount(e) {
96
97
98
        const addCount = cart.map((el) => {
            if (el.color !== e.target.id || el.size !== e.target.name) {
                return { ...el }
Jiwon Yoon's avatar
Jiwon Yoon committed
99
            } else {
100
                return { ...el, count: e.target.value }
Jiwon Yoon's avatar
Jiwon Yoon committed
101
102
            }
        })
103
        let preprice = 0
박상호's avatar
박상호 committed
104
105
        addCount.map((el) => {
            preprice = preprice + el.count * product.price
106
107
        })
        setPrice(Number(preprice))
Jiwon Yoon's avatar
Jiwon Yoon committed
108
        setCart(addCount)
Jiwon Yoon's avatar
Jiwon Yoon committed
109
        setCount(e.value)
kusang96's avatar
kusang96 committed
110
111
    }

Jiwon Yoon's avatar
Jiwon Yoon committed
112
    async function addCart(event) {
Jiwon Yoon's avatar
Jiwon Yoon committed
113
        console.log(cart)
Jiwon Yoon's avatar
Jiwon Yoon committed
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
        if (cart.length < 1) {
            alert("옵션을 선택해주세요")
        }
        else if (localStorage.getItem('id')) {
            if (event.target.name === "shoppingcart") {
                // preCart(color, size, count), productId(productlist에서 props), userId(로컬) 를 보내줌
                try {
                    setError('')
                    const response = await axios.put('/api/cart/addcart', {
                        userId: localStorage.getItem('id'),
                        products: cart
                    })
                    console.log(response.data)
                    setShow(true)
                } catch (error) {
                    catchErrors(error, setError)
                }
            } else {
                try {
                    setError('')
134
                    cart.map((el) => {
135
136
                        el.checked = true
                    })
Jiwon Yoon's avatar
Jiwon Yoon committed
137
138
139
140
141
142
143
144
145
                    const response = await axios.put('/api/cart/addcart', {
                        userId: localStorage.getItem('id'),
                        products: cart
                    })
                    console.log(response.data)
                    history.push("/payment")
                } catch (error) {
                    catchErrors(error, setError)
                }
Jiwon Yoon's avatar
Jiwon Yoon committed
146
            }
Jiwon Yoon's avatar
Jiwon Yoon committed
147

Jiwon Yoon's avatar
Jiwon Yoon committed
148
149
150
        } else {
            alert("로그인을 해주세요.")
            return <Redirect to='/login' />
151
152
153
        }
    }

kusang96's avatar
kusang96 committed
154
155
156

    return (
        <div>
Jiwon Yoon's avatar
Jiwon Yoon committed
157
            {console.log(product)}
kusang96's avatar
kusang96 committed
158
159
160
161
162
163
            <style type="text/css">
                {`
                .btn {
                    background-color: #CDC5C2;
                    border-color: #CDC5C2;
                }
kusang96's avatar
css    
kusang96 committed
164
165
166
167
168
169
170
171
172
173
                .btn:hover {
                    background-color: #91877F;
                    border-color: #91877F;
                }
                .btn-primary:focus {
                    background-color: #91877F;
                    border-color: #91877F;
                    box-shadow: 0 0 0 0;
                }
                .btn-primary:not(:disabled):not(.disabled):active, .show>.btn-primary.dropdown-toggle {
kusang96's avatar
kusang96 committed
174
175
176
177
178
                    background-color: #91877F;
                    border-color: #91877F;
                }
                `}
            </style>
179
180
181
182
183
184
185
186
187
188
            <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>
kusang96's avatar
kusang96 committed
189
190
            <Row className="justify-content-center mt-5 mx-0">
                <Col sm={11} md={4}>
Jiwon Yoon's avatar
asdf    
Jiwon Yoon committed
191
                    <img src={`/images/${product.main_img}`} style={{ objectFit: "contain", width: "100%" }} />
kusang96's avatar
kusang96 committed
192
193
                </Col>
                <Col sm={11} md={4} className="align-middle mt-4">
kusang96's avatar
0115    
kusang96 committed
194
195
                    <h3 className="mb-4">{product.name}</h3>
                    <h5 className="mb-4">가격 : {product.price}</h5>
kusang96's avatar
kusang96 committed
196
197
198
                    <Form style={{ borderBottom: "1px solid" }}>
                        <Form.Group style={{ borderBottom: "1px solid", paddingBottom: "2rem" }}>
                            <Form.Label>색상</Form.Label>
Jiwon Yoon's avatar
Jiwon Yoon committed
199
                            <Form.Control as="select" className="mb-2" name="colors" value={color} defaultValue="옵션 선택" onChange={handleChange}>
kusang96's avatar
kusang96 committed
200
                                <option>옵션선택</option>
Jiwon Yoon's avatar
qwr    
Jiwon Yoon committed
201
202
203
                                {product.colors.map((e) => (
                                    <option>{e}</option>
                                ))}
kusang96's avatar
kusang96 committed
204
205
                            </Form.Control>
                            <Form.Label>사이즈</Form.Label>
Jiwon Yoon's avatar
Jiwon Yoon committed
206
                            <Form.Control as="select" className="mb-2" name="sizes" value={size} defaultValue="옵션 선택" onChange={handleChange}>
kusang96's avatar
kusang96 committed
207
                                <option>옵션선택</option>
Jiwon Yoon's avatar
qwr    
Jiwon Yoon committed
208
209
210
                                {product.sizes.map((e) => (
                                    <option>{e}</option>
                                ))}
kusang96's avatar
kusang96 committed
211
212
                            </Form.Control>
                        </Form.Group>
Jiwon Yoon's avatar
Jiwon Yoon committed
213
                        {cart.map((e) => (
214
215
216
                            <Row className="mx-1">
                                <Col xs={6}>{e.color}/{e.size}</Col>
                                <Col xs={4} className="text-right" >
Jiwon Yoon's avatar
Jiwon Yoon committed
217
                                    <input type='number' id={e.color} name={e.size} onChange={handleCount} value={count} style={{ width: '3rem' }} className="text-center" />
218
219
220
221
222
                                </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>
Jiwon Yoon's avatar
Jiwon Yoon committed
223

224
                        ))}
kusang96's avatar
kusang96 committed
225
226
                        <Row className="justify-content-between mx-0 my-3" style={{ width: "100%" }}>
                            <Col> 금액</Col>
Jiwon Yoon's avatar
0113    
Jiwon Yoon committed
227
                            <Col className="text-right">{price}</Col>
kusang96's avatar
kusang96 committed
228
229
                        </Row>
                        <Row className="justify-content-between mx-0 my-3" style={{ width: "100%" }}>
kusang96's avatar
css    
kusang96 committed
230
                            <Button type='button' name="shoppingcart" onClick={addCart} style={{ width: "49%" }} variant="primary" >장바구니</Button>
Jiwon Yoon's avatar
Jiwon Yoon committed
231
                            <Button type='button' name="payment" onClick={addCart} style={{ width: "49%" }}>구매하기</Button>
kusang96's avatar
kusang96 committed
232
233
234
235
236
237
                        </Row>
                    </Form>
                </Col>
            </Row>
            <Row className="justify-content-center mt-5 mx-0">
                <Col sm={11} md={8}>
박상호's avatar
박상호 committed
238
239
240
                    <h3 style={{ borderBottom: "1px solid #91877F", paddingBottom: "5px", marginBottom: "1em" }} className="p-3">
                        설명
                        </h3>
박상호's avatar
0126    
박상호 committed
241
242
243
244
245
                    <Col className='text-center' style={{ fontSize: '1px' }}>
                        <div className='p-2 text-center border' style={{ background: '#CDC5C2', width: '50%', margin: 'auto', fontSize: '3.5vmin' }} >
                            {product.name}
                        </div>
                        <Image src={`/images/${product.main_img}`} className='d-flex justify-content-center p-4' style={{ objectFit: "contain", maxWidth: "100%", margin: 'auto' }} />
박상호's avatar
박상호 committed
246
                        <Card style={{ width: '80%', margin: 'auto' }} className='my-4' >
박상호's avatar
0126    
박상호 committed
247
248
249
                            <Card.Header className='text-center' style={{ background: '#CDC5C2' }}>
                                <h5 className='m-0' style={{ whiteSpace: 'nowrap' }}> [ Description ]</h5>
                            </Card.Header>
박상호's avatar
박상호 committed
250
                            <Card.Body className='text-center m-2' style={{ whiteSpace: "pre-line", background: '#F7F3F3', fontSize: '1vw' }}>
박상호's avatar
good    
박상호 committed
251
                                <small>{product.description}</small>
252
253
                            </Card.Body>
                        </Card>
박상호's avatar
0126    
박상호 committed
254
255
256
257
258
                        <Col className='p-5'>
                            <div className='border p-2' style={{ width: '60%', margin: 'auto', fontSize: '3.5vmin' }}>[ Detail Images ]</div>
                            <Image src={`/images/${product.detail_imgs}`} style={{ objectFit: "contain", maxWidth: "100%", margin: 'auto' }} className='p-4 d-flex justify-content-center' />

                        </Col>
박상호's avatar
박상호 committed
259
                    </Col>
kusang96's avatar
kusang96 committed
260
261
262
263
264
                </Col>
            </Row>
            <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}>
                    <h6 style={{ borderBottom: "1px solid", paddingBottom: "5px", marginBottom: "1em" }}>회원님이 선호할만한 상품 추천
박상호's avatar
0120    
박상호 committed
265
                        <a className="close float-right" onClick={(e) => handleClick(e)} style={{ fontSize: "1rem", cursor: "pointer" }}>X</a>
kusang96's avatar
kusang96 committed
266
                    </h6>
kusang96's avatar
css    
kusang96 committed
267
                    <Row className="justify-content-evenly mx-0" style={{ flexWrap: "nowrap", width: "100%", overflowX: "auto" }}>
kusang96's avatar
card    
kusang96 committed
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
                        {productList.map(pro => (
                            <Link 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
                                }
                            }}>
                                <ListCard id={pro._id} name={pro.pro_name} price={pro.price} main_img={pro.main_imgUrl} status={'recommend'} />
                            </Link>
                        ))}
                        {/* <Col as={Card} style={{ minWidth: "8rem" }}>
kusang96's avatar
kusang96 committed
286
287
288
289
290
                            <Card.Img variant="top" src="https://img.sonyunara.com/files/goods/67504/1607328307_0.jpg" style={{ objectFit: "contain" }} />
                            <Card.Body className="px-0">
                                <Card.Title>클로타탄원피스</Card.Title>
                                <Card.Text>구매자 수: 30</Card.Text>
                            </Card.Body>
kusang96's avatar
card    
kusang96 committed
291
                        </Col> */}
kusang96's avatar
kusang96 committed
292
293
294
295
296
297
298
299
                    </Row>
                </Col>
            </Row>
        </div>
    )
}

export default Product