124 lines
4.1 KiB
JavaScript
124 lines
4.1 KiB
JavaScript
import React, { useState, useEffect } from 'react';
|
||
import { Modal, Button, Card, Form } from 'react-bootstrap';
|
||
import { BiTrash } from 'react-icons/bi';
|
||
import api from '../services/api';
|
||
|
||
const CartModal = ({ show, onHide, onCheckout }) => {
|
||
const [cartItems, setCartItems] = useState([]);
|
||
const [total, setTotal] = useState(0);
|
||
|
||
useEffect(() => {
|
||
if (show) {
|
||
loadCart();
|
||
}
|
||
}, [show]);
|
||
|
||
const loadCart = async () => {
|
||
try {
|
||
const response = await api.fetchCartItems();
|
||
const items = response.data;
|
||
setCartItems(items);
|
||
|
||
const newTotal = items.reduce((sum, item) => {
|
||
return sum + (item.book?.price || 0) * (item.quantity || 1);
|
||
}, 0);
|
||
setTotal(newTotal);
|
||
} catch (error) {
|
||
console.error('Ошибка загрузки корзины:', error);
|
||
}
|
||
};
|
||
|
||
const handleQuantityChange = async (id, quantity) => {
|
||
if (quantity < 1) return;
|
||
|
||
try {
|
||
await api.updateCartItem(id, { quantity });
|
||
loadCart();
|
||
} catch (error) {
|
||
console.error('Ошибка обновления количества:', error);
|
||
}
|
||
};
|
||
|
||
const handleRemoveItem = async (id) => {
|
||
try {
|
||
await api.removeFromCart(id);
|
||
loadCart();
|
||
} catch (error) {
|
||
console.error('Ошибка удаления из корзины:', error);
|
||
}
|
||
};
|
||
|
||
return (
|
||
<Modal show={show} onHide={onHide} size="lg">
|
||
<Modal.Header closeButton>
|
||
<Modal.Title>Ваша корзина</Modal.Title>
|
||
</Modal.Header>
|
||
<Modal.Body>
|
||
{cartItems.length === 0 ? (
|
||
<p className="text-muted">Корзина пуста</p>
|
||
) : (
|
||
<>
|
||
{cartItems.map(item => (
|
||
<Card key={item.id} className="mb-3">
|
||
<Card.Body>
|
||
<div className="row align-items-center">
|
||
<div className="col-md-2">
|
||
<img
|
||
src={item.book?.image || "images/default-book.jpg"}
|
||
alt={item.book?.title || "Без названия"}
|
||
className="img-fluid rounded"
|
||
onError={(e) => { e.target.src = 'images/default-book.jpg' }}
|
||
/>
|
||
</div>
|
||
<div className="col-md-6">
|
||
<h5>{item.book?.title || "Без названия"}</h5>
|
||
<p className="text-muted">{item.book?.author || "Автор не указан"}</p>
|
||
<p>
|
||
Цена: {item.book?.price || 0} руб. × {item.quantity || 1} =
|
||
{(item.book?.price || 0) * (item.quantity || 1)} руб.
|
||
</p>
|
||
</div>
|
||
<div className="col-md-2">
|
||
<Form.Control
|
||
type="number"
|
||
min="1"
|
||
value={item.quantity || 1}
|
||
onChange={(e) => handleQuantityChange(item.id, parseInt(e.target.value))}
|
||
className="cart-item-quantity"
|
||
/>
|
||
</div>
|
||
<div className="col-md-2 text-center">
|
||
<Button
|
||
variant="outline-danger"
|
||
onClick={() => handleRemoveItem(item.id)}
|
||
>
|
||
<BiTrash />
|
||
</Button>
|
||
</div>
|
||
</div>
|
||
</Card.Body>
|
||
</Card>
|
||
))}
|
||
|
||
<div className="d-flex justify-content-between align-items-center mt-3">
|
||
<h4>Итого:</h4>
|
||
<h4>{total} руб.</h4>
|
||
</div>
|
||
</>
|
||
)}
|
||
</Modal.Body>
|
||
<Modal.Footer>
|
||
<Button variant="secondary" onClick={onHide}>Продолжить покупки</Button>
|
||
<Button
|
||
variant="success"
|
||
onClick={onCheckout}
|
||
disabled={cartItems.length === 0}
|
||
>
|
||
Оформить заказ
|
||
</Button>
|
||
</Modal.Footer>
|
||
</Modal>
|
||
);
|
||
};
|
||
|
||
export default CartModal; |