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
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)
Kim, Subin's avatar
Kim, Subin committed
42
43
44
            if (response.data.length == 0) {
                boxRef.current.style.display = "none"
            }
이재연's avatar
aaaa    
이재연 committed
45
        } catch (error) {
46
            catchErrors(error, setError)
이재연's avatar
aaaa    
이재연 committed
47
48
49
        }
    }

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

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

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

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

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

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

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

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

export default Product