1153 lines
54 KiB
TypeScript
1153 lines
54 KiB
TypeScript
'use client'
|
|
|
|
import { useState, useEffect } from 'react'
|
|
import { useParams, useRouter } from 'next/navigation'
|
|
import { Button } from '@/components/ui/button'
|
|
import { Badge } from '@/components/ui/badge'
|
|
import { Separator } from '@/components/ui/separator'
|
|
import { ShoppingCart, Star, Truck, Shield, RefreshCw, ArrowLeft, Leaf, Clock, Award, MapPin, Thermometer, Package, Utensils, Heart, ChevronRight, Plus, Minus, Share2, Bookmark, Eye, TrendingUp, CheckCircle, Info, Zap } from 'lucide-react'
|
|
import { motion, AnimatePresence } from 'framer-motion'
|
|
import { toast } from 'sonner'
|
|
import { cartManager } from '@/lib/cart'
|
|
import { isFeatureEnabled } from '@/lib/business-config'
|
|
import Link from 'next/link'
|
|
import OptimizedImage from '@/components/ui/OptimizedImage'
|
|
import ReviewsList from '@/components/reviews/ReviewsList'
|
|
import B2BInquiryForm from '@/components/shop/B2BInquiryForm'
|
|
import StructuredData, { MultipleStructuredData } from '@/components/StructuredData'
|
|
import { generateProductJsonLd, generateBreadcrumbJsonLd } from '@/lib/structured-data'
|
|
|
|
interface Product {
|
|
id: string
|
|
name: string
|
|
description: string
|
|
price: number
|
|
discount: number
|
|
images: string[]
|
|
stock: number
|
|
sku: string
|
|
slug: string
|
|
brand?: string
|
|
origin?: string
|
|
weight?: string
|
|
category: {
|
|
id: string
|
|
name: string
|
|
}
|
|
}
|
|
|
|
const getDiscountedPrice = (price: number, discount: number) => {
|
|
return price - (price * discount / 100)
|
|
}
|
|
|
|
// Helper function to calculate per kg price
|
|
const getPerKgPrice = (price: number, weight: string | undefined, discount: number = 0) => {
|
|
if (!weight) return null
|
|
|
|
// Extract numeric value from weight string (e.g., "1kg", "500g", "2.5 kg")
|
|
const weightMatch = weight.toLowerCase().match(/(\d+(?:\.\d+)?)\s*(kg|g|gram|kilos?)/i)
|
|
if (!weightMatch) return null
|
|
|
|
const value = parseFloat(weightMatch[1])
|
|
const unit = weightMatch[2].toLowerCase()
|
|
|
|
// Convert to kg
|
|
let weightInKg = value
|
|
if (unit.startsWith('g')) {
|
|
weightInKg = value / 1000
|
|
}
|
|
|
|
const finalPrice = discount > 0 ? getDiscountedPrice(price, discount) : price
|
|
return Math.round(finalPrice / weightInKg)
|
|
}
|
|
|
|
export default function ProductDetailPage() {
|
|
const params = useParams()
|
|
const router = useRouter()
|
|
const [product, setProduct] = useState<Product | null>(null)
|
|
const [loading, setLoading] = useState(true)
|
|
const [selectedImage, setSelectedImage] = useState(0)
|
|
const [quantity, setQuantity] = useState(1)
|
|
const [addingToCart, setAddingToCart] = useState(false)
|
|
const [activeTab, setActiveTab] = useState('overview')
|
|
const [isInquiryFormOpen, setIsInquiryFormOpen] = useState(false)
|
|
|
|
useEffect(() => {
|
|
if (params.slug && typeof params.slug === 'string') {
|
|
// Decode the slug in case it's URL encoded
|
|
const decodedSlug = decodeURIComponent(params.slug)
|
|
fetchProduct(decodedSlug)
|
|
}
|
|
}, [params.slug])
|
|
|
|
const fetchProduct = async (slug: string) => {
|
|
try {
|
|
setLoading(true)
|
|
|
|
const response = await fetch(`/api/products/${slug}`)
|
|
|
|
if (!response.ok) {
|
|
const errorData = await response.json().catch(() => ({ error: 'Unknown error' }))
|
|
throw new Error(errorData.error || 'Product not found')
|
|
}
|
|
|
|
const data = await response.json()
|
|
setProduct(data)
|
|
} catch (error) {
|
|
console.error('Error fetching product:', error)
|
|
toast.error(error instanceof Error ? error.message : 'Failed to load product')
|
|
} finally {
|
|
setLoading(false)
|
|
}
|
|
}
|
|
|
|
// Food information helper function
|
|
const getFoodInfo = (category: string, productName: string) => {
|
|
const categoryLower = category.toLowerCase()
|
|
const productLower = productName.toLowerCase()
|
|
|
|
if (categoryLower.includes('rice') || productLower.includes('rice')) {
|
|
return {
|
|
nutritionalInfo: [
|
|
{ label: 'Calories', value: '130 per 100g', icon: '🔥' },
|
|
{ label: 'Carbohydrates', value: '28g per 100g', icon: '🌾' },
|
|
{ label: 'Protein', value: '2.7g per 100g', icon: '💪' },
|
|
{ label: 'Fat', value: '0.3g per 100g', icon: '🫒' },
|
|
{ label: 'Fiber', value: '0.4g per 100g', icon: '🌿' },
|
|
{ label: 'Glycemic Index', value: 'Medium (56-69)', icon: '📊' }
|
|
],
|
|
benefits: [
|
|
'Rich in essential carbohydrates for energy',
|
|
'Naturally gluten-free grain',
|
|
'Contains important minerals like manganese',
|
|
'Low in fat and sodium',
|
|
'Easy to digest and suitable for all ages'
|
|
],
|
|
cookingInstructions: [
|
|
'Rinse rice thoroughly until water runs clear',
|
|
'Use 1:1.5 rice to water ratio for perfect texture',
|
|
'Bring to boil, then reduce heat and simmer for 18-20 minutes',
|
|
'Let it rest for 5 minutes before opening the lid',
|
|
'Fluff gently with a fork for best results'
|
|
],
|
|
storage: 'Store in airtight container in cool, dry place away from direct sunlight. Best consumed within 12-18 months of packaging.',
|
|
origin: 'Sourced from premium rice fields in Punjab and Haryana, known for their fertile soil and ideal climate conditions.',
|
|
certification: ['FSSAI Approved', 'Organic Certified', 'Pesticide Free', 'Premium Grade A']
|
|
}
|
|
} else if (categoryLower.includes('flour') || productLower.includes('flour') || productLower.includes('atta')) {
|
|
return {
|
|
nutritionalInfo: [
|
|
{ label: 'Calories', value: '340 per 100g', icon: '🔥' },
|
|
{ label: 'Carbohydrates', value: '72g per 100g', icon: '🌾' },
|
|
{ label: 'Protein', value: '12g per 100g', icon: '💪' },
|
|
{ label: 'Fat', value: '1.7g per 100g', icon: '🫒' },
|
|
{ label: 'Fiber', value: '11g per 100g', icon: '🌿' },
|
|
{ label: 'Iron', value: '4.6mg per 100g', icon: '⚡' }
|
|
],
|
|
benefits: [
|
|
'High fiber content supports digestive health',
|
|
'Rich in protein for muscle development',
|
|
'Contains essential B vitamins',
|
|
'Good source of minerals like iron and magnesium',
|
|
'Helps maintain stable blood sugar levels'
|
|
],
|
|
cookingInstructions: [
|
|
'Knead with warm water for soft, pliable dough',
|
|
'Add a pinch of salt and oil for better texture',
|
|
'Rest the dough for 15-20 minutes before rolling',
|
|
'Roll evenly for uniform cooking',
|
|
'Cook on medium heat for golden, soft rotis'
|
|
],
|
|
storage: 'Store in cool, dry place in airtight containers. Use within 6-8 months for best quality and freshness.',
|
|
origin: 'Milled from premium wheat grains sourced from the fertile plains of Punjab, Haryana, and Uttar Pradesh.',
|
|
certification: ['FSSAI Approved', 'Whole Grain', 'Stone Ground', 'Chemical Free']
|
|
}
|
|
} else if (categoryLower.includes('spice') || categoryLower.includes('masala') || productLower.includes('spice')) {
|
|
return {
|
|
nutritionalInfo: [
|
|
{ label: 'Antioxidants', value: 'High', icon: '🛡️' },
|
|
{ label: 'Vitamins', value: 'A, C, K', icon: '💊' },
|
|
{ label: 'Minerals', value: 'Iron, Calcium', icon: '⚡' },
|
|
{ label: 'Calories', value: '10-15 per tsp', icon: '🔥' },
|
|
{ label: 'Sodium', value: 'Low', icon: '🧂' }
|
|
],
|
|
benefits: [
|
|
'Rich in antioxidants and anti-inflammatory compounds',
|
|
'Supports digestive health and metabolism',
|
|
'Natural antimicrobial and antibacterial properties',
|
|
'Enhances flavor without adding calories',
|
|
'May help regulate blood sugar and cholesterol levels'
|
|
],
|
|
cookingInstructions: [
|
|
'Dry roast whole spices for enhanced aroma and flavor',
|
|
'Add spices at the right time during cooking',
|
|
'Store ground spices in airtight containers',
|
|
'Use within 6-12 months for best potency',
|
|
'Combine with oil or ghee for better absorption'
|
|
],
|
|
storage: 'Store in cool, dry place away from light and heat. Keep in airtight containers to preserve aroma and potency.',
|
|
origin: 'Sourced from spice gardens of Kerala, Karnataka, Tamil Nadu, and Kashmir - regions known for their aromatic spices.',
|
|
certification: ['FSSAI Approved', 'Pure & Natural', 'Chemical Free', 'Hand Picked']
|
|
}
|
|
} else {
|
|
return {
|
|
nutritionalInfo: [
|
|
{ label: 'Quality', value: 'Premium Grade', icon: '⭐' },
|
|
{ label: 'Freshness', value: 'Farm Fresh', icon: '🌱' },
|
|
{ label: 'Processing', value: 'Minimal', icon: '🏭' },
|
|
{ label: 'Shelf Life', value: '12 months', icon: '📅' }
|
|
],
|
|
benefits: [
|
|
'High nutritional value with natural goodness',
|
|
'Carefully processed to retain nutrients',
|
|
'Free from artificial preservatives',
|
|
'Supports healthy lifestyle and balanced diet',
|
|
'Trusted quality from Padmaaja Rasooi'
|
|
],
|
|
cookingInstructions: [
|
|
'Follow traditional cooking methods for best results',
|
|
'Use fresh ingredients for enhanced taste',
|
|
'Store properly after opening to maintain quality',
|
|
'Cook as per package instructions',
|
|
'Enjoy fresh preparations for optimal nutrition'
|
|
],
|
|
storage: 'Store in cool, dry place away from direct sunlight and moisture. Keep in original packaging or airtight containers.',
|
|
origin: 'Sourced from trusted farmers and suppliers across India, ensuring authenticity and quality.',
|
|
certification: ['FSSAI Approved', 'Quality Assured', 'Safe for Consumption', 'Hygienically Processed']
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
const handleAddToCart = () => {
|
|
if (!product) return
|
|
|
|
setAddingToCart(true)
|
|
|
|
if (product.stock === 0) {
|
|
toast.error('Product is out of stock')
|
|
setAddingToCart(false)
|
|
return
|
|
}
|
|
|
|
if (quantity > product.stock) {
|
|
toast.error('Not enough stock available')
|
|
setAddingToCart(false)
|
|
return
|
|
}
|
|
|
|
try {
|
|
const success = cartManager.addToCart(product, quantity)
|
|
if (success) {
|
|
toast.success(`${product.name} added to cart!`)
|
|
} else {
|
|
toast.error('Failed to add to cart')
|
|
}
|
|
} catch (error) {
|
|
console.error('Error adding to cart:', error)
|
|
toast.error('Failed to add to cart')
|
|
} finally {
|
|
setAddingToCart(false)
|
|
}
|
|
}
|
|
|
|
const handleShare = async () => {
|
|
const url = window.location.href
|
|
const title = `${product?.name} - Padmaaja Rasooi`
|
|
const text = `Check out this premium ${product?.name} from Padmaaja Rasooi!`
|
|
|
|
if (navigator.share) {
|
|
try {
|
|
await navigator.share({
|
|
title,
|
|
text,
|
|
url,
|
|
})
|
|
toast.success('Shared successfully!')
|
|
} catch (error) {
|
|
console.error('Error sharing:', error)
|
|
// Fallback to copy URL
|
|
handleCopyUrl()
|
|
}
|
|
} else {
|
|
// Fallback to copy URL
|
|
handleCopyUrl()
|
|
}
|
|
}
|
|
|
|
const handleCopyUrl = async () => {
|
|
try {
|
|
await navigator.clipboard.writeText(window.location.href)
|
|
toast.success('URL copied to clipboard!')
|
|
} catch (error) {
|
|
console.error('Error copying URL:', error)
|
|
toast.error('Failed to copy URL')
|
|
}
|
|
}
|
|
|
|
if (loading) {
|
|
return (
|
|
<div className="min-h-screen bg-gradient-to-br from-slate-50 via-white to-gray-50">
|
|
<div className="bg-white/80 backdrop-blur-sm border-b border-gray-100 sticky top-0 z-40">
|
|
<div className="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8 py-4">
|
|
<div className="h-6 bg-gray-200 rounded animate-pulse w-1/3"></div>
|
|
</div>
|
|
</div>
|
|
<div className="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8 py-8 lg:py-12">
|
|
<div className="grid grid-cols-1 lg:grid-cols-2 gap-8 lg:gap-16">
|
|
<div className="space-y-6">
|
|
<div className="aspect-square bg-gray-200 rounded-2xl animate-pulse"></div>
|
|
<div className="flex space-x-3">
|
|
{[1, 2, 3, 4].map((i) => (
|
|
<div key={i} className="w-20 h-20 bg-gray-200 rounded-xl animate-pulse"></div>
|
|
))}
|
|
</div>
|
|
</div>
|
|
<div className="space-y-6">
|
|
<div className="h-8 bg-gray-200 rounded animate-pulse"></div>
|
|
<div className="h-12 bg-gray-200 rounded animate-pulse"></div>
|
|
<div className="h-20 bg-gray-200 rounded animate-pulse"></div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
)
|
|
}
|
|
|
|
if (!product) {
|
|
return (
|
|
<div className="min-h-screen bg-gradient-to-br from-slate-50 via-white to-gray-50 flex items-center justify-center">
|
|
<div className="text-center max-w-md mx-auto px-4">
|
|
<div className="mb-8">
|
|
<Package className="h-24 w-24 text-gray-300 mx-auto mb-4" />
|
|
<h1 className="text-3xl font-bold text-gray-900 mb-4">Product Not Found</h1>
|
|
<p className="text-gray-600 text-lg mb-8">The product you're looking for doesn't exist or has been moved.</p>
|
|
</div>
|
|
<div className="space-x-4">
|
|
<Button onClick={() => router.back()} variant="outline" size="lg">
|
|
<ArrowLeft className="h-4 w-4 mr-2" />
|
|
Go Back
|
|
</Button>
|
|
<Link href="/products">
|
|
<Button size="lg">
|
|
Browse Products
|
|
</Button>
|
|
</Link>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
)
|
|
}
|
|
|
|
// Generate JSON-LD structured data for SEO
|
|
const baseUrl = process.env.NEXT_PUBLIC_BASE_URL || (typeof window !== 'undefined' ? window.location.origin : 'https://padmaajarasooi.com')
|
|
const productJsonLd = generateProductJsonLd(product as any, baseUrl)
|
|
|
|
const breadcrumbJsonLd = generateBreadcrumbJsonLd([
|
|
{ name: 'Home', url: '/' },
|
|
{ name: 'Products', url: '/products' },
|
|
{ name: product.category.name, url: `/products?category=${product.category.id}` },
|
|
{ name: product.name, url: `/products/${product.slug}` }
|
|
], baseUrl)
|
|
|
|
return (
|
|
<div className="min-h-screen bg-white">
|
|
{/* SEO: Product & Breadcrumb Schema - Critical for Google indexing */}
|
|
<MultipleStructuredData
|
|
dataArray={[productJsonLd, breadcrumbJsonLd]}
|
|
idPrefix="product"
|
|
/>
|
|
|
|
{/* Premium Navigation Bar */}
|
|
<nav className="">
|
|
<div className="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8">
|
|
<div className="flex items-center h-16">
|
|
{/* Breadcrumb */}
|
|
<div className="flex items-center space-x-2 text-sm">
|
|
<Link href="/" className="text-gray-500 hover:text-emerald-600 transition-colors font-medium">
|
|
Home
|
|
</Link>
|
|
<ChevronRight className="h-3.5 w-3.5 text-gray-400" />
|
|
<Link href="/products" className="text-gray-500 hover:text-emerald-600 transition-colors font-medium">
|
|
Products
|
|
</Link>
|
|
<ChevronRight className="h-3.5 w-3.5 text-gray-400" />
|
|
<span className="text-gray-900 font-semibold">{product.category.name}</span>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</nav>
|
|
|
|
{/* Main Product Section */}
|
|
<div className="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8">
|
|
<div className="grid grid-cols-1 lg:grid-cols-2 gap-12 xl:gap-16">
|
|
|
|
{/* Product Gallery */}
|
|
<motion.div
|
|
initial={{ opacity: 0, x: -20 }}
|
|
animate={{ opacity: 1, x: 0 }}
|
|
transition={{ duration: 0.6 }}
|
|
className="space-y-4"
|
|
>
|
|
{/* Main Image */}
|
|
<div className="relative aspect-square bg-gray-50 rounded-3xl overflow-hidden border border-gray-100 group">
|
|
<OptimizedImage
|
|
src={product.images[selectedImage] || product.images[0] || '/logo.png'}
|
|
alt={product.name}
|
|
width={600}
|
|
height={600}
|
|
className="w-full h-full object-cover transition-transform duration-500 group-hover:scale-105"
|
|
priority
|
|
quality={95}
|
|
/>
|
|
|
|
{/* Floating Badges */}
|
|
<div className="absolute top-6 left-6 flex flex-col space-y-2">
|
|
{product.discount > 0 && (
|
|
<Badge className="bg-red-500 text-white px-3 py-1.5 text-sm font-semibold shadow-lg">
|
|
-{product.discount}% OFF
|
|
</Badge>
|
|
)}
|
|
{product.stock < 10 && product.stock > 0 && (
|
|
<Badge variant="secondary" className="bg-orange-100 text-orange-800 px-3 py-1.5 text-sm font-medium shadow-lg">
|
|
Only {product.stock} left
|
|
</Badge>
|
|
)}
|
|
</div>
|
|
|
|
{/* Image Counter */}
|
|
{product.images.length > 1 && (
|
|
<div className="absolute bottom-6 right-6 bg-black/60 text-white px-3 py-1.5 rounded-full text-sm font-medium">
|
|
{selectedImage + 1} / {product.images.length}
|
|
</div>
|
|
)}
|
|
</div>
|
|
|
|
{/* Thumbnail Gallery */}
|
|
{product.images.length > 1 && (
|
|
<div className="flex space-x-3 overflow-x-auto pb-2">
|
|
{product.images.map((image, index) => (
|
|
<button
|
|
key={index}
|
|
onClick={() => setSelectedImage(index)}
|
|
className={`relative flex-shrink-0 w-20 h-20 rounded-2xl overflow-hidden border-2 transition-all duration-200 ${
|
|
selectedImage === index
|
|
? 'border-emerald-500 ring-2 ring-emerald-200'
|
|
: 'border-gray-200 hover:border-gray-300'
|
|
}`}
|
|
>
|
|
<OptimizedImage
|
|
src={image}
|
|
alt={`${product.name} ${index + 1}`}
|
|
width={80}
|
|
height={80}
|
|
className="w-full h-full object-cover"
|
|
quality={80}
|
|
/>
|
|
</button>
|
|
))}
|
|
</div>
|
|
)}
|
|
</motion.div>
|
|
|
|
{/* Product Information */}
|
|
<motion.div
|
|
initial={{ opacity: 0, x: 20 }}
|
|
animate={{ opacity: 1, x: 0 }}
|
|
transition={{ duration: 0.6, delay: 0.1 }}
|
|
className="space-y-8"
|
|
>
|
|
{/* Header Section */}
|
|
<div className="space-y-4">
|
|
{/* Category & Stock Status */}
|
|
<div className="flex items-center justify-between">
|
|
<Badge variant="outline" className="border-emerald-200 text-emerald-700 bg-emerald-50 px-3 py-1">
|
|
{product.category.name}
|
|
</Badge>
|
|
<div className="flex items-center space-x-2">
|
|
{product.stock > 0 ? (
|
|
<div className="flex items-center space-x-1 text-green-600">
|
|
<CheckCircle className="h-4 w-4" />
|
|
<span className="text-sm font-medium">In Stock</span>
|
|
</div>
|
|
) : (
|
|
<div className="flex items-center space-x-1 text-red-600">
|
|
<Info className="h-4 w-4" />
|
|
<span className="text-sm font-medium">Out of Stock</span>
|
|
</div>
|
|
)}
|
|
</div>
|
|
</div>
|
|
|
|
{/* Product Name */}
|
|
<h1 className="text-3xl lg:text-4xl font-bold text-gray-900 leading-tight">
|
|
{product.name}
|
|
</h1>
|
|
|
|
{/* Rating & Reviews */}
|
|
<div className="flex items-center space-x-4">
|
|
<div className="flex items-center space-x-1">
|
|
{[1, 2, 3, 4, 5].map((star) => (
|
|
<Star key={star} className="h-5 w-5 fill-yellow-400 text-yellow-400" />
|
|
))}
|
|
</div>
|
|
<span className="text-gray-600 text-sm">4.8 (2,547 reviews)</span>
|
|
<button className="text-emerald-600 text-sm font-medium hover:underline">
|
|
Write a review
|
|
</button>
|
|
</div>
|
|
|
|
{/* Description */}
|
|
<p className="text-gray-600 text-lg leading-relaxed">
|
|
{product.description || `Premium quality ${product.name} sourced directly from trusted suppliers. Experience the authentic taste and exceptional quality that Padmaaja is known for.`}
|
|
</p>
|
|
</div>
|
|
|
|
{/* Pricing Section */}
|
|
<div className="bg-gradient-to-r from-emerald-50 to-green-50 rounded-2xl p-6 border border-emerald-100">
|
|
<div className="flex items-center justify-between">
|
|
<div className="space-y-1">
|
|
{/* <div className="flex items-baseline space-x-3">
|
|
{product.discount > 0 ? (
|
|
<>
|
|
<span className="text-3xl font-bold text-emerald-600">
|
|
₹{getDiscountedPrice(product.price, product.discount).toFixed(2)}
|
|
</span>
|
|
<span className="text-lg text-gray-500 line-through">
|
|
₹{product.price.toFixed(2)}
|
|
</span>
|
|
</>
|
|
) : (
|
|
<span className="text-3xl font-bold text-emerald-600">
|
|
₹{product.price.toFixed(2)}
|
|
</span>
|
|
)}
|
|
</div> */}
|
|
|
|
{/* Per kg price display */}
|
|
{getPerKgPrice(product.price, product.weight, product.discount) && (
|
|
<div className="text-3xl font-bold text-emerald-600 leading-none !mb-0">
|
|
₹{getPerKgPrice(product.price, product.weight, product.discount)}/kg
|
|
</div>
|
|
)}
|
|
|
|
{product.discount > 0 && (
|
|
<div className="flex items-center space-x-2">
|
|
<Badge className="bg-green-100 text-green-800 hover:bg-green-100">
|
|
Save ₹{(product.price * product.discount / 100).toFixed(2)}
|
|
</Badge>
|
|
<span className="text-sm text-gray-600">
|
|
({product.discount}% off)
|
|
</span>
|
|
</div>
|
|
)}
|
|
</div>
|
|
|
|
{/* Stock Indicator */}
|
|
{/* <div className="text-right">
|
|
<div className="flex items-center space-x-2 text-sm text-gray-600">
|
|
<Package className="h-4 w-4" />
|
|
<span>{product.stock} available</span>
|
|
</div>
|
|
</div> */}
|
|
</div>
|
|
</div>
|
|
|
|
{/* Purchase Section - B2B/B2C Mode */}
|
|
{product.stock > 0 ? (
|
|
<div className="space-y-6">
|
|
{/* B2C Feature - Quantity & Cart (Disabled for B2B mode) */}
|
|
{isFeatureEnabled('cart') ? (
|
|
<>
|
|
{/* Quantity Selector */}
|
|
<div className="space-y-3">
|
|
<label className="text-sm font-semibold text-gray-900 uppercase tracking-wide">
|
|
Quantity
|
|
</label>
|
|
<div className="flex items-center space-x-4">
|
|
<div className="flex items-center border border-gray-300 rounded-xl overflow-hidden">
|
|
<button
|
|
onClick={() => setQuantity(Math.max(1, quantity - 1))}
|
|
className="p-3 hover:bg-gray-50 transition-colors border-r border-gray-300"
|
|
disabled={quantity <= 1}
|
|
>
|
|
<Minus className="h-4 w-4 text-gray-600" />
|
|
</button>
|
|
<div className="px-6 py-3 bg-white min-w-[80px] text-center font-semibold text-gray-900">
|
|
{quantity}
|
|
</div>
|
|
<button
|
|
onClick={() => setQuantity(Math.min(product.stock, quantity + 1))}
|
|
className="p-3 hover:bg-gray-50 transition-colors border-l border-gray-300"
|
|
disabled={quantity >= product.stock}
|
|
>
|
|
<Plus className="h-4 w-4 text-gray-600" />
|
|
</button>
|
|
</div>
|
|
<span className="text-sm text-gray-500">
|
|
{product.stock} available
|
|
</span>
|
|
</div>
|
|
</div>
|
|
|
|
{/* Action Buttons */}
|
|
<div className="space-y-3">
|
|
<Button
|
|
onClick={handleAddToCart}
|
|
disabled={addingToCart}
|
|
className="w-full h-14 bg-emerald-600 hover:bg-emerald-700 text-white font-semibold text-lg rounded-xl shadow-lg hover:shadow-xl transition-all duration-200"
|
|
>
|
|
{addingToCart ? (
|
|
<div className="flex items-center space-x-2">
|
|
<div className="animate-spin rounded-full h-5 w-5 border-b-2 border-white"></div>
|
|
<span>Adding to Cart...</span>
|
|
</div>
|
|
) : (
|
|
<div className="flex items-center space-x-2">
|
|
<ShoppingCart className="h-5 w-5" />
|
|
<span>Add to Cart - ₹{(getDiscountedPrice(product.price, product.discount) * quantity).toFixed(2)}</span>
|
|
</div>
|
|
)}
|
|
</Button>
|
|
</div>
|
|
</>
|
|
) : (
|
|
/* B2B Mode - Quote Request */
|
|
<div className="space-y-6">
|
|
<div className="bg-emerald-50 border border-emerald-200 rounded-xl p-6">
|
|
<h3 className="text-lg font-semibold text-emerald-900 mb-2">Bulk Orders & Wholesale</h3>
|
|
<p className="text-emerald-700 mb-4">Get competitive pricing for bulk orders. Contact us for custom quotes and wholesale rates.</p>
|
|
<div className="grid grid-cols-2 gap-4 text-sm">
|
|
<div>
|
|
<span className="font-medium text-emerald-900">Minimum Order:</span>
|
|
<span className="text-emerald-700 ml-2">1+ ton</span>
|
|
</div>
|
|
<div>
|
|
<span className="font-medium text-emerald-900">Delivery:</span>
|
|
<span className="text-emerald-700 ml-2">PAN India</span>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
{/* B2B Quantity Selector - In Tons */}
|
|
<div className="space-y-3">
|
|
<label className="text-sm font-semibold text-gray-900 uppercase tracking-wide">
|
|
Quantity (Tons)
|
|
</label>
|
|
<div className="flex items-center space-x-4">
|
|
<div className="flex items-center border border-gray-300 rounded-xl overflow-hidden">
|
|
<button
|
|
onClick={() => setQuantity(Math.max(1, quantity - 1))}
|
|
className="p-3 hover:bg-gray-50 transition-colors border-r border-gray-300"
|
|
disabled={quantity <= 1}
|
|
>
|
|
<Minus className="h-4 w-4 text-gray-600" />
|
|
</button>
|
|
<div className="px-6 py-3 bg-white min-w-[100px] text-center font-semibold text-gray-900">
|
|
{quantity} {quantity === 1 ? 'Ton' : 'Tons'}
|
|
</div>
|
|
<button
|
|
onClick={() => setQuantity(quantity + 1)}
|
|
className="p-3 hover:bg-gray-50 transition-colors border-l border-gray-300"
|
|
>
|
|
<Plus className="h-4 w-4 text-gray-600" />
|
|
</button>
|
|
</div>
|
|
<span className="text-sm text-emerald-600 font-medium">
|
|
= {(quantity * 1000).toLocaleString()} kg
|
|
</span>
|
|
</div>
|
|
<p className="text-xs text-gray-500">
|
|
Bulk pricing available for orders above 5 tons. Contact us for volume discounts.
|
|
</p>
|
|
</div>
|
|
|
|
{/* B2B Action Buttons */}
|
|
<div className="space-y-3">
|
|
<Button
|
|
onClick={() => setIsInquiryFormOpen(true)}
|
|
className="w-full h-14 bg-emerald-600 hover:bg-emerald-700 text-white font-semibold text-lg rounded-xl shadow-lg hover:shadow-xl transition-all duration-200"
|
|
>
|
|
<div className="flex items-center space-x-2">
|
|
<Eye className="h-5 w-5" />
|
|
<span>Request Quote for {quantity} {quantity === 1 ? 'Ton' : 'Tons'}</span>
|
|
</div>
|
|
</Button>
|
|
<Button
|
|
onClick={() => {
|
|
window.location.href = '/contact';
|
|
}}
|
|
variant="outline"
|
|
className="w-full h-12 border-emerald-300 text-emerald-700 hover:bg-emerald-50"
|
|
>
|
|
Contact for Bulk Orders
|
|
</Button>
|
|
</div>
|
|
</div>
|
|
)}
|
|
|
|
<div className="grid grid-cols-2 gap-3">
|
|
<Button variant="outline" className="h-12 border-gray-300 hover:bg-gray-50" onClick={handleShare}>
|
|
<Share2 className="h-4 w-4 mr-2" />
|
|
Share
|
|
</Button>
|
|
<Button variant="outline" className="h-12 border-gray-300 hover:bg-gray-50">
|
|
<Bookmark className="h-4 w-4 mr-2" />
|
|
Save
|
|
</Button>
|
|
</div>
|
|
</div>
|
|
) : (
|
|
<div className="text-center py-8 bg-gray-50 rounded-xl">
|
|
<Package className="h-12 w-12 text-gray-400 mx-auto mb-3" />
|
|
<h3 className="font-semibold text-gray-900 mb-2">Out of Stock</h3>
|
|
<p className="text-gray-600 mb-4">This product is currently unavailable</p>
|
|
<Button variant="outline" className="h-12">
|
|
<Eye className="h-4 w-4 mr-2" />
|
|
Notify When Available
|
|
</Button>
|
|
</div>
|
|
)}
|
|
|
|
{/* Trust Indicators */}
|
|
<div className="grid grid-cols-3 gap-4 pt-6 border-t border-gray-100">
|
|
<div className="text-center p-4 bg-green-50 rounded-xl">
|
|
<Truck className="h-6 w-6 text-green-600 mx-auto mb-2" />
|
|
<p className="text-sm font-medium text-gray-900">Free Delivery</p>
|
|
<p className="text-xs text-gray-600">Orders above ₹500</p>
|
|
</div>
|
|
<div className="text-center p-4 bg-blue-50 rounded-xl">
|
|
<Shield className="h-6 w-6 text-blue-600 mx-auto mb-2" />
|
|
<p className="text-sm font-medium text-gray-900">Quality Assured</p>
|
|
<p className="text-xs text-gray-600">Premium products</p>
|
|
</div>
|
|
<div className="text-center p-4 bg-purple-50 rounded-xl">
|
|
<Zap className="h-6 w-6 text-purple-600 mx-auto mb-2" />
|
|
<p className="text-sm font-medium text-gray-900">Fresh & Pure</p>
|
|
<p className="text-xs text-gray-600">No additives</p>
|
|
</div>
|
|
</div>
|
|
</motion.div>
|
|
</div>
|
|
|
|
{/* Modern Product Information Tabs */}
|
|
<motion.section
|
|
initial={{ opacity: 0, y: 30 }}
|
|
whileInView={{ opacity: 1, y: 0 }}
|
|
transition={{ duration: 0.6 }}
|
|
viewport={{ once: true }}
|
|
className="mt-20"
|
|
>
|
|
{/* Tab Navigation */}
|
|
<div className="border-b border-gray-200 mb-8">
|
|
<nav className="flex space-x-8 overflow-x-auto">
|
|
{[
|
|
{ id: 'overview', label: 'Overview', icon: Info },
|
|
{ id: 'nutrition', label: 'Nutrition', icon: Utensils },
|
|
{ id: 'benefits', label: 'Benefits', icon: Heart },
|
|
{ id: 'instructions', label: 'Instructions', icon: Clock },
|
|
{ id: 'specifications', label: 'Specifications', icon: Package }
|
|
].map((tab) => {
|
|
const Icon = tab.icon
|
|
return (
|
|
<button
|
|
key={tab.id}
|
|
onClick={() => setActiveTab(tab.id)}
|
|
className={`flex items-center space-x-2 py-4 px-2 border-b-2 font-medium text-sm whitespace-nowrap transition-colors ${
|
|
activeTab === tab.id
|
|
? 'border-emerald-500 text-emerald-600'
|
|
: 'border-transparent text-gray-500 hover:text-gray-700 hover:border-gray-300'
|
|
}`}
|
|
>
|
|
<Icon className="h-4 w-4" />
|
|
<span>{tab.label}</span>
|
|
</button>
|
|
)
|
|
})}
|
|
</nav>
|
|
</div>
|
|
|
|
{/* Tab Content */}
|
|
<div className="min-h-[400px]">
|
|
<AnimatePresence mode="wait">
|
|
{(() => {
|
|
const foodInfo = getFoodInfo(product.category.name, product.name)
|
|
|
|
switch (activeTab) {
|
|
case 'overview':
|
|
return (
|
|
<motion.div
|
|
key="overview"
|
|
initial={{ opacity: 0, x: 20 }}
|
|
animate={{ opacity: 1, x: 0 }}
|
|
exit={{ opacity: 0, x: -20 }}
|
|
transition={{ duration: 0.3 }}
|
|
className="space-y-8"
|
|
>
|
|
<div className="grid grid-cols-1 lg:grid-cols-2 gap-8">
|
|
<div className="space-y-6">
|
|
<h3 className="text-2xl font-bold text-gray-900">Product Description</h3>
|
|
<p className="text-gray-700 leading-relaxed text-lg">
|
|
{product.description || `Experience the finest quality ${product.name} from Padmaaja. Our products are carefully sourced and processed to maintain their natural goodness and authentic flavor. Perfect for your daily cooking needs with guaranteed freshness and purity.`}
|
|
</p>
|
|
|
|
<div className="bg-gradient-to-r from-emerald-50 to-green-50 rounded-2xl p-6">
|
|
<h4 className="font-semibold text-gray-900 mb-3 flex items-center">
|
|
<Award className="h-5 w-5 text-emerald-600 mr-2" />
|
|
Quality Promise
|
|
</h4>
|
|
<ul className="space-y-2 text-gray-700">
|
|
<li className="flex items-center space-x-2">
|
|
<CheckCircle className="h-4 w-4 text-green-500" />
|
|
<span>100% authentic and pure</span>
|
|
</li>
|
|
<li className="flex items-center space-x-2">
|
|
<CheckCircle className="h-4 w-4 text-green-500" />
|
|
<span>No artificial preservatives</span>
|
|
</li>
|
|
<li className="flex items-center space-x-2">
|
|
<CheckCircle className="h-4 w-4 text-green-500" />
|
|
<span>Hygienically processed</span>
|
|
</li>
|
|
<li className="flex items-center space-x-2">
|
|
<CheckCircle className="h-4 w-4 text-green-500" />
|
|
<span>Quality tested</span>
|
|
</li>
|
|
</ul>
|
|
</div>
|
|
</div>
|
|
|
|
<div className="space-y-6">
|
|
<h3 className="text-2xl font-bold text-gray-900">Product Details</h3>
|
|
<div className="bg-white rounded-2xl border border-gray-200 p-6 space-y-4">
|
|
<div className="grid grid-cols-2 gap-4">
|
|
<div>
|
|
<p className="text-sm text-gray-500 mb-1">SKU</p>
|
|
<p className="font-semibold text-gray-900">{product.sku}</p>
|
|
</div>
|
|
<div>
|
|
<p className="text-sm text-gray-500 mb-1">Category</p>
|
|
<p className="font-semibold text-gray-900">{product.category.name}</p>
|
|
</div>
|
|
{product.brand && (
|
|
<div>
|
|
<p className="text-sm text-gray-500 mb-1">Brand</p>
|
|
<p className="font-semibold text-gray-900">{product.brand}</p>
|
|
</div>
|
|
)}
|
|
{product.weight && (
|
|
<div>
|
|
<p className="text-sm text-gray-500 mb-1">Weight</p>
|
|
<p className="font-semibold text-gray-900">{product.weight}</p>
|
|
</div>
|
|
)}
|
|
{product.origin && (
|
|
<div className="col-span-2">
|
|
<p className="text-sm text-gray-500 mb-1">Origin</p>
|
|
<p className="font-semibold text-gray-900">{product.origin}</p>
|
|
</div>
|
|
)}
|
|
</div>
|
|
</div>
|
|
|
|
<div className="bg-blue-50 rounded-2xl p-6">
|
|
<h4 className="font-semibold text-blue-900 mb-3 flex items-center">
|
|
<Truck className="h-5 w-5 text-blue-600 mr-2" />
|
|
Shipping Information
|
|
</h4>
|
|
<ul className="space-y-2 text-blue-800 text-sm">
|
|
<li>• Free delivery on orders above ₹500</li>
|
|
<li>• Standard delivery: 2-4 business days</li>
|
|
<li>• Express delivery available</li>
|
|
<li>• Secure packaging guaranteed</li>
|
|
</ul>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</motion.div>
|
|
)
|
|
|
|
case 'nutrition':
|
|
return (
|
|
<motion.div
|
|
key="nutrition"
|
|
initial={{ opacity: 0, x: 20 }}
|
|
animate={{ opacity: 1, x: 0 }}
|
|
exit={{ opacity: 0, x: -20 }}
|
|
transition={{ duration: 0.3 }}
|
|
className="space-y-8"
|
|
>
|
|
<div className="text-center mb-8">
|
|
<h3 className="text-3xl font-bold text-gray-900 mb-4">Nutritional Information</h3>
|
|
<p className="text-gray-600 text-lg max-w-2xl mx-auto">
|
|
Discover the nutritional value and health benefits of our premium {product.name.toLowerCase()}.
|
|
</p>
|
|
</div>
|
|
|
|
<div className="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-6">
|
|
{foodInfo.nutritionalInfo.map((info, index) => (
|
|
<motion.div
|
|
key={index}
|
|
initial={{ opacity: 0, y: 20 }}
|
|
animate={{ opacity: 1, y: 0 }}
|
|
transition={{ delay: index * 0.1 }}
|
|
className="bg-gradient-to-br from-white to-gray-50 rounded-2xl p-6 border border-gray-200 hover:shadow-lg transition-shadow"
|
|
>
|
|
<div className="flex items-center space-x-4 mb-3">
|
|
<div className="w-12 h-12 bg-emerald-100 rounded-xl flex items-center justify-center text-2xl">
|
|
{info.icon}
|
|
</div>
|
|
<div>
|
|
<h4 className="font-semibold text-gray-900">{info.label}</h4>
|
|
<p className="text-emerald-600 font-bold text-lg">{info.value}</p>
|
|
</div>
|
|
</div>
|
|
</motion.div>
|
|
))}
|
|
</div>
|
|
</motion.div>
|
|
)
|
|
|
|
case 'benefits':
|
|
return (
|
|
<motion.div
|
|
key="benefits"
|
|
initial={{ opacity: 0, x: 20 }}
|
|
animate={{ opacity: 1, x: 0 }}
|
|
exit={{ opacity: 0, x: -20 }}
|
|
transition={{ duration: 0.3 }}
|
|
className="space-y-8"
|
|
>
|
|
<div className="text-center mb-8">
|
|
<h3 className="text-3xl font-bold text-gray-900 mb-4">Health Benefits</h3>
|
|
<p className="text-gray-600 text-lg max-w-2xl mx-auto">
|
|
Discover why {product.name.toLowerCase()} is an excellent choice for your health and wellness.
|
|
</p>
|
|
</div>
|
|
|
|
<div className="grid grid-cols-1 md:grid-cols-2 gap-6">
|
|
{foodInfo.benefits.map((benefit, index) => (
|
|
<motion.div
|
|
key={index}
|
|
initial={{ opacity: 0, y: 20 }}
|
|
animate={{ opacity: 1, y: 0 }}
|
|
transition={{ delay: index * 0.1 }}
|
|
className="flex items-start space-x-4 p-6 bg-gradient-to-r from-green-50 to-emerald-50 rounded-2xl border border-green-200"
|
|
>
|
|
<div className="flex-shrink-0 w-8 h-8 bg-green-500 rounded-full flex items-center justify-center">
|
|
<CheckCircle className="h-5 w-5 text-white" />
|
|
</div>
|
|
<p className="text-gray-800 leading-relaxed">{benefit}</p>
|
|
</motion.div>
|
|
))}
|
|
</div>
|
|
</motion.div>
|
|
)
|
|
|
|
case 'instructions':
|
|
return (
|
|
<motion.div
|
|
key="instructions"
|
|
initial={{ opacity: 0, x: 20 }}
|
|
animate={{ opacity: 1, x: 0 }}
|
|
exit={{ opacity: 0, x: -20 }}
|
|
transition={{ duration: 0.3 }}
|
|
className="space-y-8"
|
|
>
|
|
<div className="grid grid-cols-1 lg:grid-cols-2 gap-8">
|
|
{/* Cooking Instructions */}
|
|
<div className="space-y-6">
|
|
<h3 className="text-2xl font-bold text-gray-900 flex items-center">
|
|
<Clock className="h-6 w-6 text-blue-600 mr-3" />
|
|
Cooking Instructions
|
|
</h3>
|
|
<div className="space-y-4">
|
|
{foodInfo.cookingInstructions.map((instruction, index) => (
|
|
<motion.div
|
|
key={index}
|
|
initial={{ opacity: 0, x: -20 }}
|
|
animate={{ opacity: 1, x: 0 }}
|
|
transition={{ delay: index * 0.1 }}
|
|
className="flex items-start space-x-4 p-4 bg-blue-50 rounded-xl border border-blue-200"
|
|
>
|
|
<div className="flex-shrink-0 w-8 h-8 bg-blue-600 text-white rounded-full flex items-center justify-center font-bold text-sm">
|
|
{index + 1}
|
|
</div>
|
|
<p className="text-gray-800 leading-relaxed">{instruction}</p>
|
|
</motion.div>
|
|
))}
|
|
</div>
|
|
</div>
|
|
|
|
{/* Storage Instructions */}
|
|
<div className="space-y-6">
|
|
<h3 className="text-2xl font-bold text-gray-900 flex items-center">
|
|
<Package className="h-6 w-6 text-purple-600 mr-3" />
|
|
Storage Guidelines
|
|
</h3>
|
|
<div className="p-6 bg-purple-50 rounded-2xl border border-purple-200">
|
|
<p className="text-gray-800 leading-relaxed mb-6">{foodInfo.storage}</p>
|
|
|
|
<div className="space-y-3">
|
|
<h4 className="font-semibold text-purple-900 flex items-center">
|
|
<Thermometer className="h-5 w-5 mr-2" />
|
|
Storage Tips
|
|
</h4>
|
|
<ul className="space-y-2 text-purple-800">
|
|
<li className="flex items-center space-x-2">
|
|
<div className="w-1.5 h-1.5 bg-purple-600 rounded-full"></div>
|
|
<span>Keep away from direct sunlight</span>
|
|
</li>
|
|
<li className="flex items-center space-x-2">
|
|
<div className="w-1.5 h-1.5 bg-purple-600 rounded-full"></div>
|
|
<span>Store in cool, dry place</span>
|
|
</li>
|
|
<li className="flex items-center space-x-2">
|
|
<div className="w-1.5 h-1.5 bg-purple-600 rounded-full"></div>
|
|
<span>Use airtight containers</span>
|
|
</li>
|
|
<li className="flex items-center space-x-2">
|
|
<div className="w-1.5 h-1.5 bg-purple-600 rounded-full"></div>
|
|
<span>Check expiry dates regularly</span>
|
|
</li>
|
|
</ul>
|
|
</div>
|
|
</div>
|
|
|
|
{/* Origin & Certification */}
|
|
<div className="p-6 bg-orange-50 rounded-2xl border border-orange-200">
|
|
<h4 className="font-semibold text-orange-900 mb-3 flex items-center">
|
|
<MapPin className="h-5 w-5 text-orange-600 mr-2" />
|
|
Origin & Quality
|
|
</h4>
|
|
<p className="text-orange-800 mb-4">{foodInfo.origin}</p>
|
|
|
|
<div className="flex flex-wrap gap-2">
|
|
{foodInfo.certification.map((cert, index) => (
|
|
<Badge key={index} variant="outline" className="border-orange-300 text-orange-700 bg-orange-100">
|
|
{cert}
|
|
</Badge>
|
|
))}
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</motion.div>
|
|
)
|
|
|
|
case 'specifications':
|
|
return (
|
|
<motion.div
|
|
key="specifications"
|
|
initial={{ opacity: 0, x: 20 }}
|
|
animate={{ opacity: 1, x: 0 }}
|
|
exit={{ opacity: 0, x: -20 }}
|
|
transition={{ duration: 0.3 }}
|
|
className="space-y-8"
|
|
>
|
|
<div className="text-center mb-8">
|
|
<h3 className="text-3xl font-bold text-gray-900 mb-4">Product Specifications</h3>
|
|
<p className="text-gray-600 text-lg max-w-2xl mx-auto">
|
|
Detailed specifications and technical information about {product.name.toLowerCase()}.
|
|
</p>
|
|
</div>
|
|
|
|
<div className="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-6">
|
|
<div className="bg-white rounded-2xl border border-gray-200 p-6 text-center hover:shadow-lg transition-shadow">
|
|
<Package className="h-8 w-8 text-gray-600 mx-auto mb-3" />
|
|
<p className="text-sm text-gray-500 mb-1">SKU</p>
|
|
<p className="font-bold text-gray-900 font-mono">{product.sku}</p>
|
|
</div>
|
|
|
|
<div className="bg-white rounded-2xl border border-gray-200 p-6 text-center hover:shadow-lg transition-shadow">
|
|
<Award className="h-8 w-8 text-gray-600 mx-auto mb-3" />
|
|
<p className="text-sm text-gray-500 mb-1">Category</p>
|
|
<p className="font-bold text-gray-900">{product.category.name}</p>
|
|
</div>
|
|
|
|
{product.weight && (
|
|
<div className="bg-white rounded-2xl border border-gray-200 p-6 text-center hover:shadow-lg transition-shadow">
|
|
<TrendingUp className="h-8 w-8 text-gray-600 mx-auto mb-3" />
|
|
<p className="text-sm text-gray-500 mb-1">Weight</p>
|
|
<p className="font-bold text-gray-900">{product.weight}</p>
|
|
</div>
|
|
)}
|
|
|
|
{product.brand && (
|
|
<div className="bg-white rounded-2xl border border-gray-200 p-6 text-center hover:shadow-lg transition-shadow">
|
|
<Star className="h-8 w-8 text-gray-600 mx-auto mb-3" />
|
|
<p className="text-sm text-gray-500 mb-1">Brand</p>
|
|
<p className="font-bold text-gray-900">{product.brand}</p>
|
|
</div>
|
|
)}
|
|
|
|
{product.origin && (
|
|
<div className="bg-white rounded-2xl border border-gray-200 p-6 text-center hover:shadow-lg transition-shadow">
|
|
<MapPin className="h-8 w-8 text-gray-600 mx-auto mb-3" />
|
|
<p className="text-sm text-gray-500 mb-1">Origin</p>
|
|
<p className="font-bold text-gray-900">{product.origin}</p>
|
|
</div>
|
|
)}
|
|
|
|
<div className="bg-white rounded-2xl border border-gray-200 p-6 text-center hover:shadow-lg transition-shadow">
|
|
<Shield className="h-8 w-8 text-gray-600 mx-auto mb-3" />
|
|
<p className="text-sm text-gray-500 mb-1">Quality</p>
|
|
<p className="font-bold text-gray-900">Premium Grade</p>
|
|
</div>
|
|
</div>
|
|
</motion.div>
|
|
)
|
|
|
|
default:
|
|
return null
|
|
}
|
|
})()}
|
|
</AnimatePresence>
|
|
</div>
|
|
</motion.section>
|
|
|
|
{/* Reviews Section */}
|
|
<motion.section
|
|
initial={{ opacity: 0, y: 20 }}
|
|
animate={{ opacity: 1, y: 0 }}
|
|
transition={{ duration: 0.6, delay: 0.4 }}
|
|
className="py-16"
|
|
>
|
|
<div className="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8">
|
|
<div className="text-center mb-12">
|
|
<h2 className="text-3xl md:text-4xl font-bold text-gray-900 mb-4">
|
|
Customer Reviews
|
|
</h2>
|
|
<p className="text-lg text-gray-600 max-w-2xl mx-auto">
|
|
See what our customers are saying about {product.name}
|
|
</p>
|
|
</div>
|
|
|
|
<div className="max-w-4xl mx-auto">
|
|
<ReviewsList
|
|
productId={product.id}
|
|
productName={product.name}
|
|
disableImageUpload={true}
|
|
/>
|
|
</div>
|
|
</div>
|
|
</motion.section>
|
|
</div>
|
|
|
|
{/* B2B Inquiry Form */}
|
|
{product && (
|
|
<B2BInquiryForm
|
|
isOpen={isInquiryFormOpen}
|
|
onOpenChange={setIsInquiryFormOpen}
|
|
product={{
|
|
id: product.id,
|
|
name: product.name,
|
|
category: product.category,
|
|
price: product.price,
|
|
weight: product.weight
|
|
}}
|
|
/>
|
|
)}
|
|
</div>
|
|
)
|
|
} |