Product.js 13 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

Jiwon Yoon's avatar
Jiwon Yoon committed
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) {
Jiwon Yoon's avatar
Jiwon Yoon committed
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
    async function addCart(event) {
Jiwon Yoon's avatar
Jiwon Yoon committed
116
        console.log(cart)
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
136
        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('')
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
            }
Jiwon Yoon's avatar
Jiwon Yoon committed
149

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

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

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

export default Product