Product.js 13.4 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
25
26
27
    useEffect(() => {
        recommend()
    }, [])

28
    useEffect(() => {
Jiwon Yoon's avatar
Jiwon Yoon committed
29
        if (size && color) {
30
            pushOptions()
Jiwon Yoon's avatar
Jiwon Yoon committed
31
        }
Jiwon Yoon's avatar
Jiwon Yoon committed
32
    }, [size, color])
kusang96's avatar
kusang96 committed
33

이재연's avatar
aaaa    
이재연 committed
34
35
    async function recommend(){
        try {
kusang96's avatar
card    
kusang96 committed
36
37
38
39
            console.log("pro=",product.id)
            const response = await axios.post('/api/order/recommend', { productId: product.id})
            console.log("recommend res=",response.data)
            setProductList(response.data)
이재연's avatar
aaaa    
이재연 committed
40
41
42
43
44
        } catch (error) {
            catchErrors(error, setError)
        }
    }

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

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

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

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

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

Jiwon Yoon's avatar
Jiwon Yoon committed
113
    async function addCart(event) {
Jiwon Yoon's avatar
Jiwon Yoon committed
114
        console.log(cart)
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
134
        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('')
135
                    cart.map((el) => {
136
137
                        el.checked = true
                    })
Jiwon Yoon's avatar
Jiwon Yoon committed
138
139
140
141
142
143
144
145
146
                    const response = await axios.put('/api/cart/addcart', {
                        userId: localStorage.getItem('id'),
                        products: cart
                    })
                    console.log(response.data)
                    history.push("/payment")
                } catch (error) {
                    catchErrors(error, setError)
                }
Jiwon Yoon's avatar
Jiwon Yoon committed
147
            }
Jiwon Yoon's avatar
Jiwon Yoon committed
148

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

kusang96's avatar
kusang96 committed
155
156
157
158
159
160
161
162
163

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

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

export default Product