import { useState, useEffect } from 'react'
import { useNavigate } from 'react-router-dom'
import './Marketplace.css'
function Marketplace({ user }) {
const navigate = useNavigate()
const [products, setProducts] = useState([])
const [quantities, setQuantities] = useState({})
const [basket, setBasket] = useState([])
const [message, setMessage] = useState('')
useEffect(() => {
const load = async () => {
const res = await fetch('/api/products')
const data = await res.json()
setProducts(data)
}
load()
}, [])
const changeQty = (id, delta) => {
setQuantities(prev => ({
...prev,
[id]: Math.max(1, (prev[id] || 1) + delta)
}))
}
const addToBasket = (product) => {
if (!user) { navigate('/login'); return }
const qty = quantities[product.productID] || 1
const existing = basket.find(i => i.productID === product.productID)
if (existing) {
setBasket(basket.map(i =>
i.productID === product.productID
? { ...i, quantity: i.quantity + qty }
: i
))
} else {
setBasket([...basket, {
productID: product.productID,
product_name: product.product_name,
product_price: product.product_price,
quantity: qty
}])
}
setMessage('Added to basket!')
setTimeout(() => setMessage(''), 2000)
}
const goToCheckout = () => {
if (basket.length === 0) { alert('Your basket is empty'); return }
navigate('/checkout', { state: { basket } })
}
return (
Marketplace
{message && <p className="success">{message}</p>}
{basket.length > 0 && (
<button className="basket-btn" onClick={goToCheckout}>
Go to Checkout ({basket.length} items)
</button>
)}
<div className="product-grid">
{products.map(product => (
<div key={product.productID} className="product-card">
<div className="product-img" />
<p className="product-name">{product.product_name}</p>
<p className="product-price">£{Number(product.product_price).toFixed(2)}</p>
<p className="product-stock">Stock: {product.product_stock}</p>
<p className="product-desc">{product.product_description}</p>
<div className="product-controls">
<button onClick={() => changeQty(product.productID, -1)}>-</button>
<span>{quantities[product.productID] || 1}</span>
<button onClick={() => changeQty(product.productID, +1)}>+</button>
<button onClick={() => addToBasket(product)}>
{user ? 'Add to Basket' : 'Login to Order'}
</button>
</div>
</div>
))}
</div>
</div>
)
}
export default Marketplace
.page { padding: 30px; }
.success {
background: #A2C24A;
color: white;
padding: 10px;
border-radius: 6px;
margin-bottom: 15px;
text-align: center;
}
.basket-btn {
background: #144A5C;
color: white;
border: none;
padding: 10px 20px;
border-radius: 6px;
cursor: pointer;
font-family: 'Gluten', cursive;
margin-bottom: 20px;
}
.product-grid {
display: grid;
grid-template-columns: repeat(3, 1fr);
gap: 20px;
}
.product-card {
border: 1px solid #ccc;
border-radius: 8px;
padding: 16px;
}
.product-img {
background: #c8c8c8;
height: 120px;
border-radius: 6px;
margin-bottom: 10px;
}
.product-name { font-weight: 700; margin-bottom: 5px; }
.product-price { color: #A2C24A; font-weight: 700; margin-bottom: 5px; }
.product-stock { font-size: 13px; margin-bottom: 5px; }
.product-desc { font-size: 13px; color: #666; margin-bottom: 10px; }
.product-controls {
display: flex;
align-items: center;
gap: 8px;
flex-wrap: wrap;
}
.product-controls button {
background: #144A5C;
color: white;
border: none;
border-radius: 6px;
padding: 6px 12px;
cursor: pointer;
font-family: 'Gluten', cursive;
}
Top comments (0)