98 lines
2.9 KiB
JavaScript
98 lines
2.9 KiB
JavaScript
"use client";
|
||
|
||
import Link from "next/link";
|
||
import { useState } from "react";
|
||
import { useRouter } from "next/navigation";
|
||
import { useAuth } from "@/context/AuthContext";
|
||
import { useCart } from "@/context/CartContext";
|
||
|
||
export default function ProductCard({ prodId, prodName, categoryName, prodPrice, imageUrl }) {
|
||
const { user } = useAuth();
|
||
const { addItem, selectedStoreId } = useCart();
|
||
const router = useRouter();
|
||
const [quantity, setQuantity] = useState(1);
|
||
const [adding, setAdding] = useState(false);
|
||
const [feedback, setFeedback] = useState(null);
|
||
|
||
async function handleAddToCart(e) {
|
||
e.preventDefault();
|
||
if (!user) {
|
||
router.push("/login");
|
||
return;
|
||
}
|
||
if (!selectedStoreId) {
|
||
setFeedback("Please select a store first");
|
||
setTimeout(() => setFeedback(null), 2500);
|
||
return;
|
||
}
|
||
setAdding(true);
|
||
setFeedback(null);
|
||
try {
|
||
await addItem(prodId, quantity);
|
||
setFeedback("Added!");
|
||
setTimeout(() => setFeedback(null), 1500);
|
||
} catch (err) {
|
||
setFeedback(err.message || "Failed to add");
|
||
setTimeout(() => setFeedback(null), 2500);
|
||
} finally {
|
||
setAdding(false);
|
||
}
|
||
}
|
||
|
||
return (
|
||
<div className="pet-card product-card-wrapper">
|
||
<Link href={`/products/${prodId}`} className="product-card-link">
|
||
<div className="pet-card-image-wrapper">
|
||
<img
|
||
src={imageUrl || "/images/pet-placeholder.png"}
|
||
alt={prodName}
|
||
className="pet-card-image"
|
||
onError={(e) => {
|
||
e.currentTarget.onerror = null;
|
||
e.currentTarget.src = "/images/pet-placeholder.png";
|
||
}}
|
||
/>
|
||
</div>
|
||
<div className="pet-card-body">
|
||
<h3 className="pet-card-name">{prodName}</h3>
|
||
<p className="pet-card-species">{categoryName}</p>
|
||
{prodPrice != null && (
|
||
<span className="product-card-price">${parseFloat(prodPrice).toFixed(2)}</span>
|
||
)}
|
||
</div>
|
||
</Link>
|
||
|
||
<div className="product-card-actions">
|
||
<div className="product-card-qty-row">
|
||
<button
|
||
className="product-card-qty-btn"
|
||
type="button"
|
||
onClick={() => setQuantity((q) => Math.max(1, q - 1))}
|
||
disabled={adding}
|
||
>
|
||
−
|
||
</button>
|
||
<span className="product-card-qty-val">{quantity}</span>
|
||
<button
|
||
className="product-card-qty-btn"
|
||
type="button"
|
||
onClick={() => setQuantity((q) => q + 1)}
|
||
disabled={adding}
|
||
>
|
||
+
|
||
</button>
|
||
</div>
|
||
<button
|
||
className="product-card-add-btn"
|
||
type="button"
|
||
onClick={handleAddToCart}
|
||
disabled={adding}
|
||
>
|
||
{adding ? "Adding…" : "Add to Cart"}
|
||
</button>
|
||
{feedback && <p className="product-card-feedback">{feedback}</p>}
|
||
</div>
|
||
</div>
|
||
);
|
||
}
|