Product.js 13.4 KB
Newer Older
Kim, Subin's avatar
Kim, Subin committed
1
import React, { useState, useEffect, useRef } from 'react';
kusang96's avatar
card    
kusang96 committed
2
3
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


Kim, Subin's avatar
Kim, Subin committed
9
function Product({ 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
    const [show, setShow] = useState(false);
    let history = useHistory();
Kim, Subin's avatar
Kim, Subin committed
21
    const boxRef = useRef(null);
Jiwon Yoon's avatar
Jiwon Yoon committed
22
    const handleClose = () => setShow(false);
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
        getRecommend()
    }, [product])

    useEffect(() => {
29
        window.scrollTo(0,0)
kusang96's avatar
kusang96 committed
30
31
        setProduct(location.state)
    }, [location.state])
kusang96's avatar
card    
kusang96 committed
32

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

39
    async function getRecommend() {
이재연's avatar
aaaa    
이재연 committed
40
        try {
Jiwon Yoon's avatar
Jiwon Yoon committed
41
            const response = await axios.get(`/api/order/recommend?products=${product.id}`)
kusang96's avatar
card    
kusang96 committed
42
            setProductList(response.data)
Kim, Subin's avatar
Kim, Subin committed
43
44
45
            if (response.data.length == 0) {
                boxRef.current.style.display = "none"
            }
이재연's avatar
aaaa    
이재연 committed
46
        } catch (error) {
47
            catchErrors(error, setError)
이재연's avatar
aaaa    
이재연 committed
48
49
50
        }
    }

Kim, Subin's avatar
Kim, Subin committed
51
52
    function handleClick() {
        boxRef.current.style.display = "none"
kusang96's avatar
kusang96 committed
53
54
    }

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

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

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

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

Jiwon Yoon's avatar
Jiwon Yoon committed
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
    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('')
137
                    cart.map((el) => {
138
139
                        el.checked = true
                    })
Jiwon Yoon's avatar
Jiwon Yoon committed
140
141
142
143
144
145
146
147
                    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
148
149
150
151
            }
        } else {
            alert("로그인을 해주세요.")
            return <Redirect to='/login' />
152
153
154
        }
    }

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

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

export default Product