/ packages / frontend / src / components / CustomerViewListings.tsx
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  }