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
    useEffect(() => {
kusang96's avatar
kusang96 committed
25
26
27
28
29
30
        getRecommend()
    }, [product])

    useEffect(() => {
        setProduct(location.state)
    }, [location.state])
kusang96's avatar
card    
kusang96 committed
31

32
    useEffect(() => {
Jiwon Yoon's avatar
Jiwon Yoon committed
33
        if (size && color) {
34
            pushOptions()
Jiwon Yoon's avatar
Jiwon Yoon committed
35
        }
Jiwon Yoon's avatar
Jiwon Yoon committed
36
    }, [size, color])
kusang96's avatar
kusang96 committed
37

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

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

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

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

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

Jiwon Yoon's avatar
Jiwon Yoon committed
98
    function handleCount(e) {
99
100
101
        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
102
            } else {
103
                return { ...el, count: e.target.value }
Jiwon Yoon's avatar
Jiwon Yoon committed
104
105
            }
        })
106
        let preprice = 0
박상호's avatar
박상호 committed
107
108
        addCount.map((el) => {
            preprice = preprice + el.count * product.price
109
110
        })
        setPrice(Number(preprice))
Jiwon Yoon's avatar
Jiwon Yoon committed
111
        setCart(addCount)
Jiwon Yoon's avatar
Jiwon Yoon committed
112
        setCount(e.value)
kusang96's avatar
kusang96 committed
113
114
    }

Jiwon Yoon's avatar
Jiwon Yoon committed
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
    async function addCart(event) {
        if (cart.length < 1) {
            alert("옵션을 선택해주세요")
        }
        else if (localStorage.getItem('id')) {
            if (event.target.name === "shoppingcart") {
                try {
                    setError('')
                    const response = await axios.put('/api/cart/addcart', {
                        userId: localStorage.getItem('id'),
                        products: cart
                    })
                    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
                    const response = await axios.put('/api/cart/addcart', {
                        userId: localStorage.getItem('id'),
                        products: cart
                    })
                    history.push("/payment")
                } catch (error) {
                    catchErrors(error, setError)
                }
Jiwon Yoon's avatar
Jiwon Yoon committed
145
146
147
148
            }
        } else {
            alert("로그인을 해주세요.")
            return <Redirect to='/login' />
149
150
151
        }
    }

kusang96's avatar
kusang96 committed
152
153
154
155
    return (
        <div>
            <style type="text/css">
                {`
kusang96's avatar
kusang96 committed
156
157
158
159
                a, a:hover, a:active {
                    color: #000;
                    text-decoration: none;
                }
박상호's avatar
css    
박상호 committed
160
161
162
163
164
165
166
                @font-face {
                    font-family: 'Jal_Onuel';
                    src: url('https://cdn.jsdelivr.net/gh/projectnoonnu/noonfonts_20-10-21@1.0/Jal_Onuel.woff') format('woff');
                    font-weight: normal;
                    font-style: normal;
                }
                body{font-family:'Jal_Onuel'}
kusang96's avatar
kusang96 committed
167
168
169
170
                .btn {
                    background-color: #CDC5C2;
                    border-color: #CDC5C2;
                }
kusang96's avatar
css    
kusang96 committed
171
172
173
174
175
176
177
178
179
180
                .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
181
182
183
184
185
                    background-color: #91877F;
                    border-color: #91877F;
                }
                `}
            </style>
186
187
188
189
190
191
192
193
194
195
            <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
196
197
            <Row className="justify-content-center mt-5 mx-0">
                <Col sm={11} md={4}>
박상호's avatar
css    
박상호 committed
198
                    <img src={`/images/${product.main_img}`} style={{ objectFit: "contain", maxWidth: "100%", height: 'auto' }} />
kusang96's avatar
kusang96 committed
199
200
                </Col>
                <Col sm={11} md={4} className="align-middle mt-4">
kusang96's avatar
0115    
kusang96 committed
201
202
                    <h3 className="mb-4">{product.name}</h3>
                    <h5 className="mb-4">가격 : {product.price}</h5>
kusang96's avatar
kusang96 committed
203
204
205
                    <Form style={{ borderBottom: "1px solid" }}>
                        <Form.Group style={{ borderBottom: "1px solid", paddingBottom: "2rem" }}>
                            <Form.Label>색상</Form.Label>
Jiwon Yoon's avatar
Jiwon Yoon committed
206
                            <Form.Control as="select" className="mb-2" name="colors" value={color} defaultValue="옵션 선택" onChange={handleChange}>
kusang96's avatar
kusang96 committed
207
                                <option>옵션선택</option>
Jiwon Yoon's avatar
qwr    
Jiwon Yoon committed
208
209
210
                                {product.colors.map((e) => (
                                    <option>{e}</option>
                                ))}
kusang96's avatar
kusang96 committed
211
212
                            </Form.Control>
                            <Form.Label>사이즈</Form.Label>
Jiwon Yoon's avatar
Jiwon Yoon committed
213
                            <Form.Control as="select" className="mb-2" name="sizes" value={size} defaultValue="옵션 선택" onChange={handleChange}>
kusang96's avatar
kusang96 committed
214
                                <option>옵션선택</option>
Jiwon Yoon's avatar
qwr    
Jiwon Yoon committed
215
216
217
                                {product.sizes.map((e) => (
                                    <option>{e}</option>
                                ))}
kusang96's avatar
kusang96 committed
218
219
                            </Form.Control>
                        </Form.Group>
Jiwon Yoon's avatar
Jiwon Yoon committed
220
                        {cart.map((e) => (
221
222
223
                            <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
224
                                    <input type='number' id={e.color} name={e.size} onChange={handleCount} value={count} style={{ width: '3rem' }} className="text-center" />
225
226
227
228
229
                                </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
230

231
                        ))}
kusang96's avatar
kusang96 committed
232
233
                        <Row className="justify-content-between mx-0 my-3" style={{ width: "100%" }}>
                            <Col> 금액</Col>
Jiwon Yoon's avatar
0113    
Jiwon Yoon committed
234
                            <Col className="text-right">{price}</Col>
kusang96's avatar
kusang96 committed
235
236
                        </Row>
                        <Row className="justify-content-between mx-0 my-3" style={{ width: "100%" }}>
kusang96's avatar
css    
kusang96 committed
237
                            <Button type='button' name="shoppingcart" onClick={addCart} style={{ width: "49%" }} variant="primary" >장바구니</Button>
Jiwon Yoon's avatar
Jiwon Yoon committed
238
                            <Button type='button' name="payment" onClick={addCart} style={{ width: "49%" }}>구매하기</Button>
kusang96's avatar
kusang96 committed
239
240
241
242
243
244
                        </Row>
                    </Form>
                </Col>
            </Row>
            <Row className="justify-content-center mt-5 mx-0">
                <Col sm={11} md={8}>
박상호's avatar
박상호 committed
245
246
247
                    <h3 style={{ borderBottom: "1px solid #91877F", paddingBottom: "5px", marginBottom: "1em" }} className="p-3">
                        설명
                        </h3>
박상호's avatar
css    
박상호 committed
248
249
                    <Col className='text-center'>
                        <div className='p-2 text-center border' style={{ background: '#CDC5C2', width: '60%', margin: 'auto', fontSize: '3.5vmin' }} >
박상호's avatar
0126    
박상호 committed
250
251
                            {product.name}
                        </div>
박상호's avatar
css    
박상호 committed
252
                        <Image src={`/images/${product.main_img}`} className='d-flex justify-content-center p-4' style={{ objectFit: "contain", maxWidth: "100%", height: 'auto', margin: 'auto' }} />
박상호's avatar
박상호 committed
253
                        <Card style={{ width: '80%', margin: 'auto' }} className='my-4' >
박상호's avatar
0126    
박상호 committed
254
255
256
                            <Card.Header className='text-center' style={{ background: '#CDC5C2' }}>
                                <h5 className='m-0' style={{ whiteSpace: 'nowrap' }}> [ Description ]</h5>
                            </Card.Header>
박상호's avatar
css    
박상호 committed
257
258
                            <Card.Body className='text-center m-2' style={{ whiteSpace: "pre-line", background: '#F7F3F3', fontSize: '1.2vw' }}>
                                {product.description}
259
260
                            </Card.Body>
                        </Card>
박상호's avatar
0126    
박상호 committed
261
                        <Col className='p-5'>
박상호's avatar
css    
박상호 committed
262
                            <div className='border p-2' style={{ maxWidth: "100%", height: 'auto', margin: 'auto', fontSize: '3.5vmin' }}>[ Detail Images ]</div>
263
264
265
                            {product.detail_imgs.map((el) => (
                                <Image src={`/images/${el}`} style={{ objectFit: "contain", maxWidth: "100%", height: 'auto', margin: 'auto' }} className='p-4 d-flex justify-content-center' />
                            ))}
박상호's avatar
0126    
박상호 committed
266
                        </Col>
박상호's avatar
박상호 committed
267
                    </Col>
kusang96's avatar
kusang96 committed
268
269
270
                </Col>
            </Row>
            <Row className="justify-content-center mx-0 pt-3 px-2" style={{ position: "fixed", bottom: "0", width: "100%", backgroundColor: "#fff" }}>
Jiwon Yoon's avatar
asd    
Jiwon Yoon committed
271
                <Col sm={12} md={8}>
kusang96's avatar
kusang96 committed
272
                    <h6 style={{ borderBottom: "1px solid", paddingBottom: "5px", marginBottom: "1em" }}>회원님이 선호할만한 상품 추천
박상호's avatar
0120    
박상호 committed
273
                        <a className="close float-right" onClick={(e) => handleClick(e)} style={{ fontSize: "1rem", cursor: "pointer" }}>X</a>
kusang96's avatar
kusang96 committed
274
                    </h6>
kusang96's avatar
kusang96 committed
275
                    <Row className="justify-content-lg-center mx-auto" style={{ flexWrap: "nowrap", width: "100%", overflowX: "auto" }}>
kusang96's avatar
card    
kusang96 committed
276
277
278
279
280
                        {productList.map(pro => (
                            <Link to={{
                                pathname: `/product/${pro._id}`,
                                state: {
                                    id: pro._id,
281
282
283
284
285
286
287
                                    name: pro.product[0].pro_name,
                                    price: pro.product[0].price,
                                    colors: pro.product[0].colors,
                                    sizes: pro.product[0].sizes,
                                    description: pro.product[0].description,
                                    main_img: pro.product[0].main_imgUrl,
                                    detail_imgs: pro.product[0].detail_imgUrls
kusang96's avatar
card    
kusang96 committed
288
289
                                }
                            }}>
290
                                <ListCard id={pro._id} name={pro.product[0].pro_name} price={pro.product[0].price} main_img={pro.product[0].main_imgUrl} status={'recommend'} />
kusang96's avatar
card    
kusang96 committed
291
292
                            </Link>
                        ))}
kusang96's avatar
kusang96 committed
293
294
295
296
297
298
299
300
                    </Row>
                </Col>
            </Row>
        </div>
    )
}

export default Product