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

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

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

export default Product