Styling refactor
This commit is contained in:
@@ -4,17 +4,20 @@ import { useState } from "react";
|
||||
import { useAuth } from "@/context/AuthContext";
|
||||
import { useCart } from "@/context/CartContext";
|
||||
|
||||
const fieldRowCls = "flex items-center px-5 py-[0.85rem] border-b border-[#eee] last:border-b-0";
|
||||
const fieldLabelCls = "w-[140px] text-[0.9rem] font-semibold text-[#888] uppercase tracking-[0.04em] shrink-0";
|
||||
const fieldValueCls = "text-base text-[#333]";
|
||||
const qtyBtnCls = "w-7 h-7 border border-[#ddd] rounded-md bg-white text-base cursor-pointer flex items-center justify-center transition-colors hover:border-[#e68672] disabled:opacity-50";
|
||||
|
||||
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 }
|
||||
const [feedback, setFeedback] = useState(null);
|
||||
|
||||
function changeQty(delta) {
|
||||
setQuantity((q) => Math.max(1, q + delta));
|
||||
}
|
||||
function changeQty(delta) { setQuantity((q) => Math.max(1, q + delta)); }
|
||||
|
||||
async function handleAddToCart() {
|
||||
setAdding(true);
|
||||
@@ -31,12 +34,12 @@ export default function ProductProfile({ prodId, prodName, categoryName, prodDes
|
||||
}
|
||||
|
||||
return (
|
||||
<div className="pet-detail-card">
|
||||
<div className="pet-detail-image-wrapper">
|
||||
<div className="flex gap-12 bg-white rounded-2xl shadow-[0_6px_24px_rgba(0,0,0,0.1)] overflow-hidden max-[768px]:flex-col max-[768px]:gap-0">
|
||||
<div className="shrink-0 w-[280px] bg-[#fff8ee] flex items-center justify-center max-[768px]:w-full max-[768px]:h-[200px]">
|
||||
<img
|
||||
src={imageUrl || "/images/pet-placeholder.png"}
|
||||
alt={prodName}
|
||||
className="pet-detail-image"
|
||||
className="w-full h-full object-cover"
|
||||
onError={(e) => {
|
||||
e.currentTarget.onerror = null;
|
||||
e.currentTarget.src = "/images/pet-placeholder.png";
|
||||
@@ -44,64 +47,50 @@ export default function ProductProfile({ prodId, prodName, categoryName, prodDes
|
||||
/>
|
||||
</div>
|
||||
|
||||
<div className="pet-detail-info">
|
||||
<div className="pet-detail-header">
|
||||
<h1 className="pet-detail-name">{prodName}</h1>
|
||||
<div className="flex-1 py-10 pr-10 flex flex-col gap-6 max-[768px]:p-7">
|
||||
<div className="flex items-center gap-4 flex-wrap">
|
||||
<h1 className="text-[2.2rem] font-bold text-[#222] m-0">{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 className="flex flex-col border border-[#eee] rounded-[10px] overflow-hidden">
|
||||
<div className={fieldRowCls}>
|
||||
<span className={fieldLabelCls}>Category</span>
|
||||
<span className={fieldValueCls}>{categoryName ?? "—"}</span>
|
||||
</div>
|
||||
<div className="pet-detail-row">
|
||||
<span className="pet-detail-label">Price</span>
|
||||
<span className="pet-detail-value pet-detail-price">
|
||||
<div className={fieldRowCls}>
|
||||
<span className={fieldLabelCls}>Price</span>
|
||||
<span className={`${fieldValueCls} font-bold text-[#1a7a3c] text-[1.1rem]`}>
|
||||
{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 className={fieldRowCls}>
|
||||
<span className={fieldLabelCls}>Description</span>
|
||||
<span className={fieldValueCls}>{prodDesc ?? "—"}</span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div className="pet-detail-cta">
|
||||
<div className="bg-[#fff8ee] rounded-xl p-5">
|
||||
{!user ? (
|
||||
<p className="pet-detail-cta-text">
|
||||
<a href="/login" className="appt-link">Log in</a> to purchase this item.
|
||||
<p className="text-[0.95rem] text-[#555] m-0">
|
||||
<a href="/login" className="text-[#e68672] font-semibold no-underline hover:underline">Log in</a> to purchase this item.
|
||||
</p>
|
||||
) : !selectedStoreId ? (
|
||||
<p className="pet-detail-cta-text">
|
||||
<p className="text-[0.95rem] text-[#555] m-0">
|
||||
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 className="flex items-center gap-4 mb-4">
|
||||
<span className="text-[0.95rem] font-semibold text-[#555]">Quantity</span>
|
||||
<div className="flex items-center gap-2">
|
||||
<button className={qtyBtnCls} onClick={() => changeQty(-1)} disabled={quantity <= 1 || adding} aria-label="Decrease quantity">−</button>
|
||||
<span className="min-w-7 text-center font-semibold">{quantity}</span>
|
||||
<button className={qtyBtnCls} onClick={() => changeQty(1)} disabled={adding} aria-label="Increase quantity">+</button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<button
|
||||
className="product-add-to-cart-btn"
|
||||
className="w-full py-[0.85rem] bg-[#e68672] text-[#2f2f2f] border-none rounded-[10px] text-base font-bold cursor-pointer transition-all hover:bg-[#d4705e] hover:text-white active:scale-[0.98] disabled:opacity-60 disabled:cursor-not-allowed"
|
||||
onClick={handleAddToCart}
|
||||
disabled={adding}
|
||||
>
|
||||
@@ -109,7 +98,7 @@ export default function ProductProfile({ prodId, prodName, categoryName, prodDes
|
||||
</button>
|
||||
|
||||
{feedback && (
|
||||
<p className={`product-cart-feedback product-cart-feedback--${feedback.type}`}>
|
||||
<p className={`mt-3 text-[0.9rem] rounded-lg px-4 py-[0.6rem] ${feedback.type === "success" ? "bg-[#f0fff4] border border-[#b2dfdb] text-[#1a7a3c]" : "bg-[#fff0f0] border border-[#f5c6c6] text-[#c0392b]"}`}>
|
||||
{feedback.message}
|
||||
</p>
|
||||
)}
|
||||
|
||||
Reference in New Issue
Block a user