Press n or j to go to the next uncovered block, b, p or k for the previous block.
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 | "use client"; import { useEffect, useRef } from "react"; import { useDispatch } from "react-redux"; import ShopDetails from "../ShopDetails"; import { updateProductDetails } from "@/redux/features/productDetails"; import { serializePrismaObject } from "@/lib/core"; import { useFunnelSteps } from "@/hooks/useFunnelTracking"; interface ProductDetails { id: number; title: string; description?: string | null; price: number; discountedPrice: number; stock: number; sku?: string | null; categoryId: number; category?: { id: number; title: string; }; images?: Array<{ id: number; url: string; type: string; }>; // Reviews can be a number (total count) or array of review objects // ShopDetails handles both formats via: Array.isArray(product.reviews) ? product.reviews.length : product.reviews reviews?: number | Array<{ id: number; rating: number; comment?: string | null; user: { id: string; name?: string | null; }; }>; createdAt: Date | string; updatedAt: Date | string; } interface ShopDetailsClientProps { product: ProductDetails; } export default function ShopDetailsClient({ product }: ShopDetailsClientProps) { const dispatch = useDispatch(); const { trackStep } = useFunnelSteps(); const hasTrackedRef = useRef(false); // When product is provided as prop (from server), update Redux store useEffect(() => { if (product) { // Serialize Date objects to ISO strings for Redux compatibility const serializedProduct = serializePrismaObject(product); // Spread to create plain object compatible with Redux payload type dispatch(updateProductDetails({ ...serializedProduct })); localStorage.setItem("productDetails", JSON.stringify(serializedProduct)); } }, [product, dispatch]); // Track product view for funnel analytics useEffect(() => { if (product && !hasTrackedRef.current) { trackStep("checkout", "view_item", { product_id: product.id, product_name: product.title, price: product.discountedPrice}); hasTrackedRef.current = true; } }, [product, trackStep]); return <ShopDetails />; } |