123 lines
4.0 KiB
JavaScript
123 lines
4.0 KiB
JavaScript
"use client";
|
||
|
||
import { useState } from "react";
|
||
import { useAuth } from "@/context/AuthContext";
|
||
import { useCart } from "@/context/CartContext";
|
||
|
||
export default function ProductProfile({ prodId, prodName, categoryName, prodDesc, prodPrice, imageUrl }) {
|
||
const { user } = useAuth();
|
||
const { addItem, selectedStoreId } = useCart();
|
||
|
||
const [quantity, setQuantity] = useState(1);
|
||
const [adding, setAdding] = useState(false);
|
||
const [feedback, setFeedback] = useState(null); // { type: "success"|"error", message }
|
||
|
||
function changeQty(delta) {
|
||
setQuantity((q) => Math.max(1, q + delta));
|
||
}
|
||
|
||
async function handleAddToCart() {
|
||
setAdding(true);
|
||
setFeedback(null);
|
||
try {
|
||
await addItem(prodId, quantity);
|
||
setFeedback({ type: "success", message: `${quantity} × ${prodName} added to cart!` });
|
||
setQuantity(1);
|
||
} catch (err) {
|
||
setFeedback({ type: "error", message: err.message ?? "Failed to add to cart." });
|
||
} finally {
|
||
setAdding(false);
|
||
}
|
||
}
|
||
|
||
return (
|
||
<div className="pet-detail-card">
|
||
<div className="pet-detail-image-wrapper">
|
||
<img
|
||
src={imageUrl || "/images/pet-placeholder.png"}
|
||
alt={prodName}
|
||
className="pet-detail-image"
|
||
onError={(e) => {
|
||
e.currentTarget.onerror = null;
|
||
e.currentTarget.src = "/images/pet-placeholder.png";
|
||
}}
|
||
/>
|
||
</div>
|
||
|
||
<div className="pet-detail-info">
|
||
<div className="pet-detail-header">
|
||
<h1 className="pet-detail-name">{prodName}</h1>
|
||
</div>
|
||
|
||
<div className="pet-detail-fields">
|
||
<div className="pet-detail-row">
|
||
<span className="pet-detail-label">Category</span>
|
||
<span className="pet-detail-value">{categoryName ?? "—"}</span>
|
||
</div>
|
||
<div className="pet-detail-row">
|
||
<span className="pet-detail-label">Price</span>
|
||
<span className="pet-detail-value pet-detail-price">
|
||
{prodPrice != null ? `$${parseFloat(prodPrice).toFixed(2)}` : "—"}
|
||
</span>
|
||
</div>
|
||
<div className="pet-detail-row">
|
||
<span className="pet-detail-label">Description</span>
|
||
<span className="pet-detail-value">{prodDesc ?? "—"}</span>
|
||
</div>
|
||
</div>
|
||
|
||
<div className="pet-detail-cta">
|
||
{!user ? (
|
||
<p className="pet-detail-cta-text">
|
||
<a href="/login" className="appt-link">Log in</a> to purchase this item.
|
||
</p>
|
||
) : !selectedStoreId ? (
|
||
<p className="pet-detail-cta-text">
|
||
Select a store from the navigation bar to add items to your cart.
|
||
</p>
|
||
) : (
|
||
<>
|
||
<div className="product-qty-row">
|
||
<span className="product-qty-label">Quantity</span>
|
||
<div className="product-qty-controls">
|
||
<button
|
||
className="cart-qty-btn"
|
||
onClick={() => changeQty(-1)}
|
||
disabled={quantity <= 1 || adding}
|
||
aria-label="Decrease quantity"
|
||
>
|
||
−
|
||
</button>
|
||
<span className="cart-qty-val">{quantity}</span>
|
||
<button
|
||
className="cart-qty-btn"
|
||
onClick={() => changeQty(1)}
|
||
disabled={adding}
|
||
aria-label="Increase quantity"
|
||
>
|
||
+
|
||
</button>
|
||
</div>
|
||
</div>
|
||
|
||
<button
|
||
className="product-add-to-cart-btn"
|
||
onClick={handleAddToCart}
|
||
disabled={adding}
|
||
>
|
||
{adding ? "Adding…" : "Add to Cart"}
|
||
</button>
|
||
|
||
{feedback && (
|
||
<p className={`product-cart-feedback product-cart-feedback--${feedback.type}`}>
|
||
{feedback.message}
|
||
</p>
|
||
)}
|
||
</>
|
||
)}
|
||
</div>
|
||
</div>
|
||
</div>
|
||
);
|
||
}
|