68 lines
2.2 KiB
TypeScript
68 lines
2.2 KiB
TypeScript
"use client";
|
|
|
|
import { ProductCard } from "@/components/molecules/cards";
|
|
import { useCart } from "@/lib/cart-context";
|
|
import { useManager } from "@/lib/manager-context";
|
|
|
|
import type { ProductGridProps } from "./ProductGrid.types";
|
|
|
|
function toDisplayUrl(filename: string) {
|
|
if (!filename) return "/imgs/products/placeholder.jpg";
|
|
if (filename.startsWith("/") || filename.startsWith("http")) return filename;
|
|
return `/api/file/${filename}`;
|
|
}
|
|
|
|
export default function ProductGrid({
|
|
searchQuery = "",
|
|
isSidebarOpen = false,
|
|
}: ProductGridProps) {
|
|
const { addToCart } = useCart();
|
|
const { products } = useManager();
|
|
|
|
const filteredProducts = products.filter((p) => {
|
|
const isAvailable = p.available !== false;
|
|
const matchesSearch =
|
|
searchQuery.trim() === "" ||
|
|
p.name.toLowerCase().includes(searchQuery.toLowerCase()) ||
|
|
p.description.toLowerCase().includes(searchQuery.toLowerCase());
|
|
return isAvailable && matchesSearch;
|
|
});
|
|
|
|
const gridCols = isSidebarOpen
|
|
? "grid-cols-1 min-[480px]:grid-cols-2 lg:grid-cols-2 xl:grid-cols-3 2xl:grid-cols-4"
|
|
: "grid-cols-1 min-[480px]:grid-cols-2 lg:grid-cols-3 xl:grid-cols-4 2xl:grid-cols-5";
|
|
|
|
return (
|
|
<>
|
|
{/* ── Product grid ── */}
|
|
{filteredProducts.length > 0 ? (
|
|
<div className={`grid gap-4 ${gridCols}`}>
|
|
{filteredProducts.map(
|
|
({ id, imageUrl, name, price, description }) => (
|
|
<ProductCard
|
|
key={id}
|
|
image={toDisplayUrl(imageUrl)}
|
|
imageAlt={name}
|
|
productName={name}
|
|
price={price}
|
|
description={description}
|
|
onBuy={() => addToCart({ productId: id!, quantity: 1 })}
|
|
/>
|
|
),
|
|
)}
|
|
</div>
|
|
) : (
|
|
/* Empty state */
|
|
<div className="flex flex-col items-center justify-center gap-4 py-24 text-(--color-text-muted)">
|
|
<i className="fa-solid fa-mug-hot text-5xl opacity-30"></i>
|
|
<p className="text-base font-medium">
|
|
{searchQuery
|
|
? `Không tìm thấy món nào cho "${searchQuery}"`
|
|
: "Chưa có món trong danh mục này"}
|
|
</p>
|
|
</div>
|
|
)}
|
|
</>
|
|
);
|
|
}
|