'use client'; import React, { useState, useEffect, useRef } from 'react'; import { apiClient } from '@/app/utils/apiClient'; import Image from 'next/image'; import { useCart } from '@/app/context/CartContext'; import { toast } from 'react-hot-toast'; import './ProductID.scss'; import ProductReviews from '@/app/components/reviews/ProductReviews'; interface ProductMedia { id: number; media_type: string; is_primary: boolean; media_data: string; } interface ProductAdditionalDetails { product_color?: string; product_size?: string; product_weight?: number; product_dimensions?: string; product_material?: string; product_manufacturer?: string; product_origin?: string; } interface Category { id: number; product_category: string; } interface PaymentMethod { id: number; name: string; description?: string; icon?: string; is_active: boolean; processing_time?: string; fee_percentage?: number; fee_fixed?: number; min_amount?: number; max_amount?: number; display_order: number; } interface ProductData { id: number; product_name: string; product_description: string; product_price: number; product_brand: string; product_stock: number; product_discount_active: boolean; product_discount_price?: number; product_discount_percentage?: number; warranty?: string; media: ProductMedia[]; additional_details?: ProductAdditionalDetails; category?: Category; createdAt: string; } interface ProductDetailProps { productId: number; } const ProductDetail: React.FC = ({ productId }) => { const [product, setProduct] = useState(null); const [loading, setLoading] = useState(true); const [error, setError] = useState(null); const [quantity, setQuantity] = useState(1); const [selectedImage, setSelectedImage] = useState(null); const { addToCart } = useCart(); const [activeTab, setActiveTab] = useState('description'); const [isHovered, setIsHovered] = useState(false); const [mousePosition, setMousePosition] = useState({ x: 0, y: 0 }); const imageRef = useRef(null); const productInfoRef = useRef(null); const isMobile = typeof window !== 'undefined' ? window.innerWidth <= 768 : false; const magnificationLevel = 2.5; const [paymentMethods, setPaymentMethods] = useState([]); const [paymentMethodsLoading, setPaymentMethodsLoading] = useState(false); const [paymentMethodsError, setPaymentMethodsError] = useState(null); const placeholderImage = '/placeholder-image.jpg'; useEffect(() => { const fetchProduct = async () => { try { setLoading(true); setError(null); const response = await apiClient(`/product/products/${productId}`, { skipAuth: true }); if (response.success && response.data) { setProduct(response.data); const productData = response.data; if (productData.media && Array.isArray(productData.media)) { const validMedia = productData.media.filter((item: ProductMedia) => item && item.media_data && typeof item.media_data === 'string' && item.media_data.startsWith('data:') ); if (validMedia.length > 0) { const primaryImage = validMedia.find((img: ProductMedia) => img.is_primary); if (primaryImage) { console.log("Setting primary image:", primaryImage.id); setSelectedImage(primaryImage.media_data); } else { console.log("Setting first image:", validMedia[0].id); setSelectedImage(validMedia[0].media_data); } } else { console.warn("No valid images found for this product"); setSelectedImage(placeholderImage); } } else { console.warn("No media array found for this product"); setSelectedImage(placeholderImage); } } else { console.error("API returned unsuccessful response or no data:", response); setError('Failed to load product data'); } } catch (err) { console.error('Error fetching product:', err); setError(`Error loading product: ${err instanceof Error ? err.message : 'Unknown error'}`); } finally { setLoading(false); } }; if (productId) { fetchProduct(); } }, [productId, placeholderImage]); useEffect(() => { const fetchPaymentMethods = async () => { if (!productId) return; try { setPaymentMethodsLoading(true); setPaymentMethodsError(null); const response = await apiClient(`/payment-methods/product/${productId}`, { skipAuth: true }); if (response.success && response.data) { setPaymentMethods(response.data); } else { console.warn("Failed to load payment methods or no payment methods available"); setPaymentMethods([]); } } catch (err) { console.error('Error fetching payment methods:', err); setPaymentMethodsError(`Error loading payment methods: ${err instanceof Error ? err.message : 'Unknown error'}`); setPaymentMethods([]); } finally { setPaymentMethodsLoading(false); } }; if (productId) { fetchPaymentMethods(); } }, [productId]); const handleAddToCart = () => { if (product) { for (let i = 0; i < quantity; i++) { addToCart(product); } toast.success(`${quantity} x ${product.product_name} added to cart`); } }; const handleQuantityChange = (value: number) => { if (value >= 1 && value <= (product?.product_stock || 10)) { setQuantity(value); } }; const formatPrice = (price?: number | string | null): string => { if (price === undefined || price === null) return '$0.00'; const numericPrice = typeof price === 'string' ? parseFloat(price) : price; if (isNaN(numericPrice)) return '$0.00'; return `$${numericPrice.toFixed(2)}`; }; const isValidImage = (src: any): boolean => { return ( src && typeof src === 'string' && (src.startsWith('data:') || src.startsWith('http') || src.startsWith('/')) ); }; const handleMouseMove = (event: React.MouseEvent) => { if (isMobile || !imageRef.current) return; const { left, top, width, height } = imageRef.current.getBoundingClientRect(); // Calculate relative mouse position within the image const relativeX = (event.clientX - left) / width; const relativeY = (event.clientY - top) / height; // Set background position percentage for magnifier const backgroundX = relativeX * 100; const backgroundY = relativeY * 100; setMousePosition({ x: backgroundX, y: backgroundY }); }; if (loading) { return
Loading product details...
; } if (error || !product) { return
{error || 'Product not found'}
; } const discountPercentage = product.product_discount_percentage || (product.product_discount_active && product.product_discount_price ? Math.round(((product.product_price - product.product_discount_price) / product.product_price) * 100) : 0); const validMediaItems = product.media ? product.media.filter(img => isValidImage(img.media_data)) : []; return (
!isMobile && setIsHovered(true)} onMouseLeave={() => setIsHovered(false)} onMouseMove={handleMouseMove} > {isValidImage(selectedImage) ? ( {product.product_name} ) : (
No image available
)} {product.product_discount_active && discountPercentage > 0 && (
-{discountPercentage}%
)}
{validMediaItems.length > 1 && (
{validMediaItems.map((img: ProductMedia) => (
setSelectedImage(img.media_data)} > {`${product.product_name}
))}
)}
{isHovered && !isMobile && isValidImage(selectedImage) && (
)}
{product.category && ( {product.category.product_category} )}

{product.product_name}

{product.product_brand} {product.warranty && ( {product.warranty} )}
{product.product_discount_active && product.product_discount_price ? ( <> {formatPrice(product.product_discount_price)} {formatPrice(product.product_price)} -{discountPercentage}% ) : ( {formatPrice(product.product_price)} )}
0 ? "in-stock" : "out-of-stock"}> {product.product_stock > 0 ? ( <> In Stock ({product.product_stock} available) ) : ( <> Out of Stock )}
handleQuantityChange(parseInt(e.target.value) || 1)} min="1" max={product.product_stock || 10} />

Free Shipping

On orders over $50

Secure Checkout

100% protected payments

24/7 Support

Expert assistance

{activeTab === 'description' && (
{product.product_description}
{product.warranty && (

Warranty Information

{product.warranty}

)}
)} {activeTab === 'specifications' && (
{product.additional_details && Object.values(product.additional_details).some(x => x) ? (
    {product.additional_details.product_color && (
  • Color: {product.additional_details.product_color}
  • )} {product.additional_details.product_size && (
  • Size: {product.additional_details.product_size}
  • )} {product.additional_details.product_weight && (
  • Weight: {product.additional_details.product_weight}g
  • )} {product.additional_details.product_dimensions && (
  • Dimensions: {product.additional_details.product_dimensions}
  • )} {product.additional_details.product_material && (
  • Material: {product.additional_details.product_material}
  • )} {product.additional_details.product_manufacturer && (
  • Manufacturer: {product.additional_details.product_manufacturer}
  • )} {product.additional_details.product_origin && (
  • Country of Origin: {product.additional_details.product_origin}
  • )}
) : (

No detailed specifications available for this product.

)}
)} {activeTab === 'reviews' && (
)} {activeTab === 'shipping' && (

Shipping Information

Standard Shipping

Delivery within 3-5 business days

Free on orders over $50

$4.99 for orders under $50

Express Shipping

Delivery within 1-2 business days

$9.99 for all orders

Same Day Delivery

Available for select areas

Order before 11am

$14.99 for all orders

Return Policy

We accept returns within 30 days of delivery. Items must be in original condition with tags attached and in original packaging.

To initiate a return, please contact our customer service team with your order number.

)} {activeTab === 'payment' && (

Accepted Payment Methods

{paymentMethodsLoading ? (
Loading payment methods...
) : paymentMethodsError ? (
{paymentMethodsError}
) : paymentMethods.length === 0 ? (

No specific payment methods are defined for this product. Standard payment options are available at checkout.

) : (
{paymentMethods.map(method => (
{!method.icon && method.name.charAt(0)}

{method.name}

{method.description && {method.description}} {Processing: {method.processing_time}} {(method.fee_percentage || method.fee_fixed) && ( Fee: {method.fee_percentage ? `${method.fee_percentage}%` : ''} {(method.fee_percentage && method.fee_fixed) ? ' + ' : ''} {method.fee_fixed ? `$${method.fee_fixed.toFixed(2)}` : ''} )}
))}
)}

Secure Checkout

All transactions are secure and encrypted. We never store your credit card information.

Orders are processed in USD. Your bank may charge additional conversion fees for other currencies.

)}
); }; export default ProductDetail;