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


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

22
    useEffect(() => {
Jiwon Yoon's avatar
Jiwon Yoon committed
23
        if (size && color) {
24
            pushOptions()
Jiwon Yoon's avatar
Jiwon Yoon committed
25
        }
이재연's avatar
aaaa    
이재연 committed
26
        recommend()
Jiwon Yoon's avatar
Jiwon Yoon committed
27
    }, [size, color])
kusang96's avatar
kusang96 committed
28

이재연's avatar
aaaa    
이재연 committed
29
30
31
32
33
34
35
36
    async function recommend(){
        try {
            const response = await axios.post('/api/order/recommend')
        } catch (error) {
            catchErrors(error, setError)
        }
    }

kusang96's avatar
kusang96 committed
37
38
39
40
41
    function handleClick(e) {
        const box = e.target.parentNode.parentNode
        box.style.display = "none"
    }

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

kusang96's avatar
kusang96 committed
66
67
    function handleChange(e) {
        const { name, value } = e.target
Jiwon Yoon's avatar
Jiwon Yoon committed
68
69
        if (name === "sizes") {
            setSize(value)
70
            selected.sizes = true
Jiwon Yoon's avatar
Jiwon Yoon committed
71
72
        } else if (name === "colors") {
            setColor(value)
73
74
            selected.colors = true
        }
kusang96's avatar
kusang96 committed
75
76
    }

Jiwon Yoon's avatar
Jiwon Yoon committed
77
    function deleteOption(e) {
kusang96's avatar
kusang96 committed
78
        e.preventDefault()
79
        let preprice = 0
kusang96's avatar
kusang96 committed
80
81
        const list = cart.filter((el) => el.color !== e.target.id || el.size !== e.target.name)
        list.map((el) => {
박상호's avatar
박상호 committed
82
            preprice = preprice + el.count * product.price
83
        })
kusang96's avatar
kusang96 committed
84
        setCart(list)
85
        setPrice(Number(preprice))
kusang96's avatar
kusang96 committed
86
87
    }

Jiwon Yoon's avatar
Jiwon Yoon committed
88
    function handleCount(e) {
89
90
91
        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
92
            } else {
93
                return { ...el, count: e.target.value }
Jiwon Yoon's avatar
Jiwon Yoon committed
94
95
            }
        })
96
        let preprice = 0
박상호's avatar
박상호 committed
97
98
        addCount.map((el) => {
            preprice = preprice + el.count * product.price
99
100
        })
        setPrice(Number(preprice))
Jiwon Yoon's avatar
Jiwon Yoon committed
101
        setCart(addCount)
Jiwon Yoon's avatar
Jiwon Yoon committed
102
        setCount(e.value)
kusang96's avatar
kusang96 committed
103
104
    }

Jiwon Yoon's avatar
Jiwon Yoon committed
105
    async function addCart(event) {
Jiwon Yoon's avatar
Jiwon Yoon committed
106
        console.log(cart)
Jiwon Yoon's avatar
Jiwon Yoon committed
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
        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('')
127
                    cart.map((el) => {
128
129
                        el.checked = true
                    })
Jiwon Yoon's avatar
Jiwon Yoon committed
130
131
132
133
134
135
136
137
138
                    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
139
            }
Jiwon Yoon's avatar
Jiwon Yoon committed
140

Jiwon Yoon's avatar
Jiwon Yoon committed
141
142
143
        } else {
            alert("로그인을 해주세요.")
            return <Redirect to='/login' />
144
145
146
        }
    }

kusang96's avatar
kusang96 committed
147
148
149
150
151
152
153
154
155

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

216
                        ))}
kusang96's avatar
kusang96 committed
217
218
                        <Row className="justify-content-between mx-0 my-3" style={{ width: "100%" }}>
                            <Col> 금액</Col>
Jiwon Yoon's avatar
0113    
Jiwon Yoon committed
219
                            <Col className="text-right">{price}</Col>
kusang96's avatar
kusang96 committed
220
221
                        </Row>
                        <Row className="justify-content-between mx-0 my-3" style={{ width: "100%" }}>
kusang96's avatar
css    
kusang96 committed
222
                            <Button type='button' name="shoppingcart" onClick={addCart} style={{ width: "49%" }} variant="primary" >장바구니</Button>
Jiwon Yoon's avatar
Jiwon Yoon committed
223
                            <Button type='button' name="payment" onClick={addCart} style={{ width: "49%" }}>구매하기</Button>
kusang96's avatar
kusang96 committed
224
225
226
227
228
229
                        </Row>
                    </Form>
                </Col>
            </Row>
            <Row className="justify-content-center mt-5 mx-0">
                <Col sm={11} md={8}>
박상호's avatar
박상호 committed
230
231
232
                    <h3 style={{ borderBottom: "1px solid #91877F", paddingBottom: "5px", marginBottom: "1em" }} className="p-3">
                        설명
                        </h3>
박상호's avatar
0126    
박상호 committed
233
234
235
236
237
                    <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
238
                        <Card style={{ width: '80%', margin: 'auto' }} className='my-4' >
박상호's avatar
0126    
박상호 committed
239
240
241
                            <Card.Header className='text-center' style={{ background: '#CDC5C2' }}>
                                <h5 className='m-0' style={{ whiteSpace: 'nowrap' }}> [ Description ]</h5>
                            </Card.Header>
박상호's avatar
박상호 committed
242
                            <Card.Body className='text-center m-2' style={{ whiteSpace: "pre-line", background: '#F7F3F3', fontSize: '1vw' }}>
박상호's avatar
good    
박상호 committed
243
                                <small>{product.description}</small>
244
245
                            </Card.Body>
                        </Card>
박상호's avatar
0126    
박상호 committed
246
247
248
249
250
                        <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
251
                    </Col>
kusang96's avatar
kusang96 committed
252
253
254
255
256
                </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
257
                        <a className="close float-right" onClick={(e) => handleClick(e)} style={{ fontSize: "1rem", cursor: "pointer" }}>X</a>
kusang96's avatar
kusang96 committed
258
                    </h6>
kusang96's avatar
css    
kusang96 committed
259
260
                    <Row className="justify-content-evenly mx-0" style={{ flexWrap: "nowrap", width: "100%", overflowX: "auto" }}>
                        <Col as={Card} style={{ minWidth: "8rem" }}>
kusang96's avatar
kusang96 committed
261
262
263
264
265
266
                            <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>
                        </Col>
kusang96's avatar
css    
kusang96 committed
267
                        <Col as={Card} style={{ minWidth: "8rem" }}>
kusang96's avatar
kusang96 committed
268
269
270
271
272
273
                            <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>
                        </Col>
kusang96's avatar
css    
kusang96 committed
274
                        <Col as={Card} style={{ minWidth: "8rem" }}>
kusang96's avatar
kusang96 committed
275
276
277
278
279
280
                            <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>
                        </Col>
kusang96's avatar
css    
kusang96 committed
281
                        <Col as={Card} style={{ minWidth: "8rem" }}>
kusang96's avatar
kusang96 committed
282
283
284
285
286
287
288
289
290
291
292
293
294
295
                            <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>
                        </Col>
                    </Row>
                </Col>
            </Row>
        </div>
    )
}

export default Product