CustomerViewListings.tsx
1 // SPDX-FileCopyrightText: 2024 Mass Labs 2 // 3 // SPDX-License-Identifier: GPL-3.0-or-later 4 5 import { Link } from "@tanstack/react-router"; 6 import { formatUnits } from "viem"; 7 8 import { Listing } from "@massmarket/schema"; 9 10 import { ListingViewState } from "../types.ts"; 11 import { useBaseToken } from "../hooks/useBaseToken.ts"; 12 13 export default function CustomerViewProducts({ 14 products, 15 }: { 16 products: Listing[] | null; 17 }) { 18 const { baseToken } = useBaseToken(); 19 20 function renderProducts() { 21 if (!products?.length) { 22 return ( 23 <div className="flex justify-center w-full mb-4"> 24 <p>No Products</p> 25 </div> 26 ); 27 } 28 return products.map((item: Listing) => { 29 const visible = item.ViewState === ListingViewState.Published; 30 31 let productImage = "/assets/no-image.png"; 32 if (item.Metadata.Images && item.Metadata.Images.length > 0) { 33 productImage = item.Metadata.Images[0]; 34 } 35 return ( 36 <Link 37 key={item.ID} 38 data-testid="product-container" 39 to="/listing-detail" 40 search={(prev: Record<string, string>) => ({ 41 shopId: prev.shopId, 42 itemId: item.ID, 43 })} 44 className={`${!visible ? "hidden" : ""}`} 45 style={{ color: "black" }} 46 > 47 <div className="w-40 xxs:w-36 md:w-[190px]"> 48 <div data-testid="product-img"> 49 <img 50 src={productImage} 51 width={160} 52 height={144} 53 alt="product-thumb" 54 className="h-36 rounded-t-lg object-cover object-center w-full" 55 /> 56 </div> 57 <div className="bg-white flex flex-col gap-2 rounded-b-lg p-3 h-24 w-full"> 58 <div className="min-h-8"> 59 <h3 60 data-testid="product-name" 61 className="leading-[1.1] line-clamp-2 md:p-1" 62 > 63 {item.Metadata.Title} 64 </h3> 65 </div> 66 <div className="flex gap-2 items-center"> 67 <img 68 src={baseToken?.symbol === "ETH" 69 ? "/icons/eth-coin.svg" 70 : "/icons/usdc-coin.png"} 71 alt="coin" 72 width={20} 73 height={20} 74 className="w-5 h-5" 75 data-testid="coin-icon" 76 /> 77 <p data-testid="product-price" className="truncate"> 78 {formatUnits(item.Price, baseToken.decimals)} 79 </p> 80 </div> 81 </div> 82 </div> 83 </Link> 84 ); 85 }); 86 } 87 return ( 88 <section 89 className="mt-4 flex justify-center" 90 data-testid="customer-view-listings" 91 > 92 <section> 93 <h1>Shop</h1> 94 <section className="grid grid-cols-2 md:grid-cols-4 gap-5 pt-5"> 95 {renderProducts()} 96 </section> 97 </section> 98 </section> 99 ); 100 }