ProductDetail.jsx 7.03 KB
import React, { useState, useEffect } from 'react';
import { useParams, useNavigate } from 'react-router-dom';
import { productService } from '../services/api/productService';
import { useCart } from '../context/CartContext';
import LoadingSpinner from '../components/common/LoadingSpinner';
import './product-detail.css';

const ProductDetail = () => {
  const { id } = useParams();
  const navigate = useNavigate();
  const { addToCart } = useCart();
  
  const [product, setProduct] = useState(null);
  const [loading, setLoading] = useState(true);
  const [error, setError] = useState('');
  const [quantity, setQuantity] = useState(1);
  const [selectedImage, setSelectedImage] = useState(0);

  useEffect(() => {
    loadProduct();
  }, [id]);

  const loadProduct = async () => {
    try {
      setLoading(true);
      const productData = await productService.getProduct(id);
      setProduct(productData);
    } catch (error) {
      setError('Product not found');
      console.error('Error loading product:', error);
    } finally {
      setLoading(false);
    }
  };

  const handleAddToCart = async () => {
    if (!product || product.availableQuantity === 0) return;

    const result = await addToCart(product.id, quantity);
    if (result.success) {
      // Show success message
      alert('Product added to cart!');
    } else {
      alert(result.error || 'Failed to add product to cart');
    }
  };

  const handleBuyNow = async () => {
    const result = await addToCart(product.id, quantity);
    if (result.success) {
      navigate('/cart');
    }
  };

  const formatPrice = (price) => {
    return new Intl.NumberFormat('en-US', {
      style: 'currency',
      currency: 'USD'
    }).format(price);
  };

  if (loading) {
    return <LoadingSpinner />;
  }

  if (error || !product) {
    return (
      <div className="container">
        <div className="error-page">
          <h2>{error || 'Product not found'}</h2>
          <button onClick={() => navigate('/products')} className="btn btn-primary">
            Back to Products
          </button>
        </div>
      </div>
    );
  }

  const images = product.images ? Object.values(product.images) : [];
  const mainImage = images[selectedImage] || product.imageUrl || '/images/placeholder-product.jpg';

  return (
    <div className="product-detail-page">
      <div className="container">
        <div className="product-detail">
          {/* Breadcrumb */}
          <nav className="breadcrumb">
            <button onClick={() => navigate('/products')}>Products</button>
            <span>/</span>
            <span>{product.name}</span>
          </nav>

          <div className="product-detail-content">
            {/* Product Images */}
            <div className="product-images">
              <div className="main-image">
                <img 
                  src={mainImage} 
                  alt={product.name}
                  onError={(e) => {
                    e.target.src = '/images/placeholder-product.jpg';
                  }}
                />
              </div>
              
              {images.length > 1 && (
                <div className="image-thumbnails">
                  {images.map((image, index) => (
                    <button
                      key={index}
                      className={`thumbnail ${selectedImage === index ? 'active' : ''}`}
                      onClick={() => setSelectedImage(index)}
                    >
                      <img src={image} alt={`${product.name} ${index + 1}`} />
                    </button>
                  ))}
                </div>
              )}
            </div>

            {/* Product Info */}
            <div className="product-info">
              <h1 className="product-title">{product.name}</h1>
              <p className="product-sku">SKU: {product.sku}</p>
              
              <div className="product-pricing">
                <span className="price">{formatPrice(product.price)}</span>
                {product.comparePrice && product.comparePrice > product.price && (
                  <span className="compare-price">
                    {formatPrice(product.comparePrice)}
                  </span>
                )}
              </div>

              <div className="product-description">
                <p>{product.description}</p>
              </div>

              <div className="product-stock">
                {product.availableQuantity > 0 ? (
                  <span className="in-stock">
                    {product.availableQuantity} in stock
                  </span>
                ) : (
                  <span className="out-of-stock">Out of stock</span>
                )}
              </div>

              {/* Add to Cart */}
              {product.availableQuantity > 0 && (
                <div className="add-to-cart-section">
                  <div className="quantity-selector">
                    <label htmlFor="quantity">Quantity:</label>
                    <select
                      id="quantity"
                      value={quantity}
                      onChange={(e) => setQuantity(parseInt(e.target.value))}
                    >
                      {[...Array(Math.min(product.availableQuantity, 10))].map((_, i) => (
                        <option key={i + 1} value={i + 1}>
                          {i + 1}
                        </option>
                      ))}
                    </select>
                  </div>

                  <div className="action-buttons">
                    <button 
                      className="btn btn-primary add-to-cart-btn"
                      onClick={handleAddToCart}
                    >
                      Add to Cart
                    </button>
                    <button 
                      className="btn btn-secondary buy-now-btn"
                      onClick={handleBuyNow}
                    >
                      Buy Now
                    </button>
                  </div>
                </div>
              )}

              {/* Product Features */}
              <div className="product-features">
                <div className="feature">
                  <span>๐Ÿšš Free shipping on orders over $50</span>
                </div>
                <div className="feature">
                  <span>โ†ฉ๏ธ 30-day return policy</span>
                </div>
                <div className="feature">
                  <span>๐Ÿ”’ Secure checkout</span>
                </div>
              </div>
            </div>
          </div>

          {/* Product Details Tabs */}
          <div className="product-tabs">
            <div className="tab-content">
              <h3>Product Details</h3>
              <div className="product-attributes">
                {product.attributes && Object.entries(product.attributes).map(([key, value]) => (
                  <div key={key} className="attribute">
                    <strong>{key}:</strong> <span>{value}</span>
                  </div>
                ))}
              </div>
            </div>
          </div>
        </div>
      </div>
    </div>
  );
};

export default ProductDetail;