Vollstaendige Next.js/Prisma-E-Commerce-Anwendung fuer eine Imkerei: Shop, Warenkorb, Stripe-Checkout, Kundenkonto mit 2FA, Admin-Bereich (Produkte, Ernten, Chargen, Bestellungen, Gutscheine, admin-editierbare Website-Inhalte), i18n (DE/EN), Rate-Limiting/CSP/Audit-Log-Haertung, PostgreSQL- und MySQL-Unterstuetzung ueber austauschbare Prisma- Treiber-Adapter, Unit-/Komponenten-/E2E-Tests.
48 lines
1.6 KiB
TypeScript
48 lines
1.6 KiB
TypeScript
"use client";
|
|
|
|
import { useEffect, useState } from "react";
|
|
import { useRecentlyViewedStore } from "@/store/recently-viewed-store";
|
|
import { getRecentlyViewedProducts } from "@/app/shop/actions";
|
|
import { ProductCard } from "@/components/product-card";
|
|
import { useI18n } from "@/i18n/i18n-provider";
|
|
import type { ProductWithRelations } from "@/lib/data";
|
|
|
|
/**
|
|
* Zeigt zuletzt angesehene Produkte (aus dem lokalen Verlauf) als Raster,
|
|
* optional ohne das aktuell angezeigte Produkt selbst. Rendert nichts, wenn
|
|
* (noch) keine oder keine anzeigbaren Produkte vorliegen.
|
|
*/
|
|
export function RecentlyViewedSection({ excludeProductId }: { excludeProductId?: string }) {
|
|
const { t } = useI18n();
|
|
const viewedIds = useRecentlyViewedStore((s) => s.viewedIds);
|
|
const [products, setProducts] = useState<ProductWithRelations[]>([]);
|
|
|
|
useEffect(() => {
|
|
const ids = viewedIds.filter((id) => id !== excludeProductId);
|
|
if (ids.length === 0) {
|
|
setProducts([]);
|
|
return;
|
|
}
|
|
let cancelled = false;
|
|
getRecentlyViewedProducts(ids).then((result) => {
|
|
if (!cancelled) setProducts(result);
|
|
});
|
|
return () => {
|
|
cancelled = true;
|
|
};
|
|
}, [viewedIds, excludeProductId]);
|
|
|
|
if (products.length === 0) return null;
|
|
|
|
return (
|
|
<div className="mt-20">
|
|
<h2 className="text-2xl text-forest mb-8">{t.productPage.recentlyViewedHeading}</h2>
|
|
<div className="grid grid-cols-1 sm:grid-cols-2 lg:grid-cols-3 gap-x-8 gap-y-14">
|
|
{products.map((product) => (
|
|
<ProductCard key={product.id} product={product} />
|
|
))}
|
|
</div>
|
|
</div>
|
|
);
|
|
}
|