Files
sanihome/src/components/product/SimilarProducts.tsx
T
amirhosein.ashourlooandClaude Sonnet 5 66f92b634e Add customer auth, real cart/checkout, store-items pages, comments, contact form
- Real in-site login/register (password + SMS OTP) against Meshkee's
  /auth API, with self-healing access-token refresh (15 min lifetime) and
  an in-flight-refresh guard so AuthContext and CartContext don't race
  each other into a failed concurrent refresh.
- Real cart: header cart button/badge, a cart popup, and a working
  "add to cart" on both product cards (where a specific variant id is
  known) and the product/store-item detail buy-box (always resolves a
  purchasable variant, even for single-SKU products with no selectable
  variation).
- /checkout: address + cash/bank-transfer payment, posts to the real
  checkout API and creates an order; refreshes the cart afterward so the
  header badge doesn't go stale.
- New /store-items and /store-items/[id] pages (variant-level browsing,
  separate from the product-level /products catalog), cross-referencing
  the parent product for images/description/technical-info.
- Product gallery: click-to-open fullscreen lightbox alongside the
  existing hover-zoom.
- Comments tab wired to the real comments API, gated to logged-in users
  (a product decision — the API itself doesn't require auth) with a
  login prompt otherwise.
- Similar-products row on product/store-item detail pages.
- Contact page wired to the real contact-submissions API, with a toast
  and inline confirmation on success, and the form resetting.
- CONTEXT.md: a maintained architecture/conventions doc for this repo,
  now auto-loaded via CLAUDE.md, covering the Meshkee integration quirks
  and UI conventions established across this project.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-09-06 08:06:30 +03:30

46 lines
1.4 KiB
TypeScript

import { Carousel } from "@/components/ui/Carousel";
import { ProductCard } from "@/components/ui/ProductCard";
import { getProducts, productHref, type Product } from "@/lib/meshkee";
export async function SimilarProducts({
categoryId,
excludeProductId,
contactPhone,
}: {
categoryId?: string;
excludeProductId: string;
contactPhone?: string;
}) {
if (!categoryId) return null;
const { items } = await getProducts({ categoryId, pageSize: 9 });
const products: Product[] = items.filter((p) => p.id !== excludeProductId).slice(0, 8);
if (products.length === 0) return null;
return (
<div className="mt-12 border-t border-border pt-10">
<h2 className="mb-5 flex items-center gap-2 text-lg font-bold">
<span className="h-2 w-2 shrink-0 rounded-full bg-red" aria-hidden />
محصولات مشابه
</h2>
<Carousel ariaLabel="محصولات مشابه">
{products.map((product) => (
<ProductCard
key={product.id}
name={product.name}
brand={product.brand ?? ""}
price={product.price}
oldPrice={product.oldPrice}
discount={product.discount}
image={product.image ?? "/images/placeholder.svg"}
href={productHref(product)}
contactPhone={contactPhone}
variantId={product.variantId}
/>
))}
</Carousel>
</div>
);
}