Files
dark-lord/components/shop/VendorShelfRow.tsx
drjones 78a071ba02 Harden onion boot flow and deepen site surfaces
Add persistent onion key backup and restore, improve startup resilience, and flesh out the major site verticals with richer navigation, search coverage, and operator documentation.

Made-with: Cursor
2026-04-07 21:35:52 -07:00

70 lines
3.1 KiB
TypeScript

"use client";
import Image from "next/image";
import Link from "next/link";
import { useState } from "react";
import { useCart } from "@/contexts/CartContext";
import { ProductSocialBlock } from "@/components/shop/ProductSocialBlock";
import { resolveProductImage, type ShopCurrency, type ShopProduct } from "@/lib/shopCatalog";
import { getProductSocialMetrics } from "@/lib/shopProductSocial";
const SYM: Record<ShopCurrency, string> = { BTC: "₿", ETH: "Ξ", USD: "$", XMR: "⏣" };
function formatPrice(price: number, currency: ShopCurrency): string {
if (currency === "BTC") return price.toFixed(6);
if (currency === "ETH") return price.toFixed(4);
if (currency === "XMR") return price.toFixed(3);
return price.toFixed(2);
}
export function VendorShelfRow({ product }: { product: ShopProduct }) {
const { addToCart, hydrated } = useCart();
const [flash, setFlash] = useState(false);
const src = resolveProductImage(product);
const metrics = getProductSocialMetrics(product.id);
return (
<li className="flex flex-col gap-4 rounded-lg border border-orange-950/70 bg-[#080605] p-4 sm:flex-row">
<div className="relative h-28 w-full shrink-0 overflow-hidden rounded border border-orange-900/30 bg-black sm:h-28 sm:w-28">
<Image src={src} alt="" fill className="object-cover" sizes="112px" unoptimized={src.startsWith("/")} />
</div>
<div className="min-w-0 flex-1">
<p className="font-mono text-[10px] uppercase tracking-wider text-orange-500/60">{product.category}</p>
<p className="font-semibold text-orange-50">{product.name}</p>
<div className="mt-2 text-[#c4b5a0]">
<ProductSocialBlock metrics={metrics} compact />
</div>
<p className="mt-2 line-clamp-2 text-xs text-orange-200/65">{product.description}</p>
<p className="mt-2 font-mono text-sm text-orange-300">
{SYM[product.currency]}
{formatPrice(product.price, product.currency)} {product.currency}
</p>
<div className="mt-3 space-y-2 border-t border-orange-950/50 pt-3">
<p className="font-mono text-[9px] font-bold uppercase tracking-widest text-orange-500/50">Verified note</p>
<p className="text-xs italic text-orange-200/60">{metrics.testimonials[0]?.text}</p>
</div>
<div className="mt-4 flex flex-wrap gap-2">
<button
type="button"
disabled={!hydrated}
onClick={() => {
addToCart(product, 1);
setFlash(true);
window.setTimeout(() => setFlash(false), 1500);
}}
className="rounded border border-orange-500 bg-orange-500/90 px-4 py-2 font-mono text-xs font-bold uppercase text-black hover:bg-orange-400 disabled:opacity-50"
>
{flash ? "Added ✓" : "Add to cart"}
</button>
<Link
href="/checkout"
className="rounded border border-orange-800 px-4 py-2 font-mono text-xs text-orange-200 hover:border-orange-600"
>
Cart
</Link>
</div>
</div>
</li>
);
}