← back to Wine Finder Next

app/wine/[id]/page.tsx

332 lines

'use client'

import { useState, useEffect } from 'react'
import { useRouter, useParams } from 'next/navigation'
import Image from 'next/image'
import PriceChart from '@/components/PriceChart'
import RelatedWines from '@/components/RelatedWines'
import WhereToBuy from '@/components/WhereToBuy'

interface WineDetails {
  name: string
  vintage?: string
  price: string
  rating?: number
  image?: string
  source: string
  url?: string
  winery?: string
  region?: string
  country?: string
  type?: string
  varietal?: string
  alcohol?: string
  description?: string
  reviews?: number
  tastingNotes?: string[]
  foodPairings?: string[]
  priceHistory?: any
  availableAt?: Array<{
    retailer: string
    price: number
    url: string
    availability: string
    logo?: string
  }>
}

export default function WineDetailPage() {
  const router = useRouter()
  const params = useParams()
  const [wine, setWine] = useState<WineDetails | null>(null)
  const [loading, setLoading] = useState(true)
  const [error, setError] = useState<string | null>(null)
  const [showFullDescription, setShowFullDescription] = useState(false)

  useEffect(() => {
    loadWineDetails()
  }, [params.id])

  const loadWineDetails = async () => {
    try {
      setLoading(true)
      // In a real implementation, fetch wine details from API
      // For now, using mock data
      await new Promise(resolve => setTimeout(resolve, 500)) // Simulate API call

      // Mock wine data
      setWine({
        name: 'Caymus Cabernet Sauvignon',
        vintage: '2021',
        price: '89.99',
        rating: 92,
        image: 'https://images.vivino.com/thumbs/default-wine-bottle.png',
        source: 'Vivino',
        url: 'https://www.vivino.com/wines/12345',
        winery: 'Caymus Vineyards',
        region: 'Napa Valley',
        country: 'USA',
        type: 'Red Wine',
        varietal: 'Cabernet Sauvignon',
        alcohol: '14.5%',
        description: 'Rich and concentrated, this Napa Valley Cabernet Sauvignon showcases the signature style of Caymus. Dark fruit flavors, velvety tannins, and a long, luxurious finish make this a wine to remember.',
        reviews: 45231,
        tastingNotes: ['Blackberry', 'Dark Cherry', 'Vanilla', 'Oak', 'Black Pepper'],
        foodPairings: ['Grilled Steak', 'Lamb Chops', 'Aged Cheese', 'BBQ Ribs'],
        availableAt: [
          {
            retailer: 'Vivino',
            price: 89.99,
            url: 'https://www.vivino.com/wines/12345',
            availability: 'In Stock',
            logo: '🍇'
          },
          {
            retailer: 'Total Wine & More',
            price: 94.99,
            url: 'https://www.totalwine.com/product/12345',
            availability: 'In Stock',
            logo: '🏪'
          },
          {
            retailer: 'K&L Wine Merchants',
            price: 92.99,
            url: 'https://www.klwines.com/p/12345',
            availability: 'Limited Stock',
            logo: '🍷'
          }
        ]
      })
    } catch (err) {
      console.error('Error loading wine details:', err)
      setError('Failed to load wine details')
    } finally {
      setLoading(false)
    }
  }

  if (loading) {
    return (
      <div className="min-h-screen bg-gradient-to-br from-wine-50 via-purple-50 to-pink-50 flex items-center justify-center">
        <div className="text-center">
          <div className="inline-block animate-spin rounded-full h-16 w-16 border-t-4 border-b-4 border-wine-600 mb-4"></div>
          <p className="text-gray-600 text-lg">Loading wine details...</p>
        </div>
      </div>
    )
  }

  if (error || !wine) {
    return (
      <div className="min-h-screen bg-gradient-to-br from-wine-50 via-purple-50 to-pink-50 flex items-center justify-center">
        <div className="text-center max-w-md mx-auto p-6">
          <div className="text-6xl mb-4">😔</div>
          <h2 className="text-2xl font-bold text-gray-900 mb-3">Wine Not Found</h2>
          <p className="text-gray-600 mb-6">{error || 'The wine you are looking for does not exist.'}</p>
          <button
            onClick={() => router.push('/')}
            className="px-6 py-3 bg-wine-600 text-white rounded-full font-semibold hover:bg-wine-700 transition-colors"
          >
            Back to Home
          </button>
        </div>
      </div>
    )
  }

  return (
    <div className="min-h-screen bg-gradient-to-br from-wine-50 via-purple-50 to-pink-50">
      {/* Header */}
      <header className="bg-gradient-to-r from-wine-900 via-burgundy-800 to-purple-900 text-white shadow-wine-lg">
        <div className="container mx-auto px-4 py-4">
          <button
            onClick={() => router.back()}
            className="flex items-center gap-2 text-white hover:text-gold-300 transition-colors"
            aria-label="Go back"
          >
            <svg className="w-6 h-6" fill="none" stroke="currentColor" viewBox="0 0 24 24">
              <path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M10 19l-7-7m0 0l7-7m-7 7h18" />
            </svg>
            <span className="font-semibold">Back</span>
          </button>
        </div>
      </header>

      <main className="container mx-auto px-4 py-8 sm:py-12">
        <div className="grid grid-cols-1 lg:grid-cols-2 gap-8 lg:gap-12 mb-12">
          {/* Left Column - Image */}
          <div className="animate-fade-in">
            <div className="sticky top-8">
              <div className="bg-white rounded-3xl shadow-wine-lg p-8 sm:p-12">
                <div className="relative h-96 sm:h-128">
                  {wine.image ? (
                    <Image
                      src={wine.image}
                      alt={wine.name}
                      fill
                      className="object-contain"
                      sizes="(max-width: 768px) 100vw, 50vw"
                      priority
                    />
                  ) : (
                    <div className="flex items-center justify-center h-full text-9xl">🍷</div>
                  )}
                </div>

                {/* Rating Badge */}
                {wine.rating && (
                  <div className="mt-6 text-center">
                    <div className="inline-flex items-center gap-2 bg-gold-100 border-2 border-gold-300 px-6 py-3 rounded-full">
                      <span className="text-3xl">⭐</span>
                      <div className="text-left">
                        <div className="text-3xl font-bold text-gray-900">{wine.rating}</div>
                        {wine.reviews && (
                          <div className="text-xs text-gray-600">
                            {wine.reviews.toLocaleString()} reviews
                          </div>
                        )}
                      </div>
                    </div>
                  </div>
                )}
              </div>
            </div>
          </div>

          {/* Right Column - Details */}
          <div className="animate-slide-up space-y-6">
            {/* Title & Price */}
            <div className="bg-white rounded-3xl shadow-wine-lg p-6 sm:p-8">
              <div className="flex items-start justify-between gap-4 mb-4">
                <div>
                  <h1 className="text-3xl sm:text-4xl font-bold text-gray-900 mb-2">
                    {wine.name}
                  </h1>
                  {wine.vintage && (
                    <span className="inline-block bg-wine-100 text-wine-800 px-4 py-2 rounded-full font-semibold text-lg">
                      {wine.vintage}
                    </span>
                  )}
                </div>
                <div className="text-right">
                  <div className="text-sm text-gray-500 mb-1">Best Price</div>
                  <div className="text-4xl font-bold text-wine-700">${wine.price}</div>
                </div>
              </div>

              {/* Winery & Region */}
              {wine.winery && (
                <p className="text-lg font-medium text-purple-700 mb-2 flex items-center gap-2">
                  <span>🏛️</span> {wine.winery}
                </p>
              )}
              {(wine.region || wine.country) && (
                <p className="text-gray-600 flex items-center gap-2 mb-4">
                  <span>📍</span> {wine.region}{wine.region && wine.country && ', '}{wine.country}
                </p>
              )}

              {/* Quick Info */}
              <div className="grid grid-cols-2 gap-3 mt-4">
                {wine.type && (
                  <div className="bg-pink-50 px-4 py-3 rounded-xl">
                    <div className="text-xs text-gray-500 mb-1">Type</div>
                    <div className="font-semibold text-gray-900">{wine.type}</div>
                  </div>
                )}
                {wine.varietal && (
                  <div className="bg-purple-50 px-4 py-3 rounded-xl">
                    <div className="text-xs text-gray-500 mb-1">Varietal</div>
                    <div className="font-semibold text-gray-900">{wine.varietal}</div>
                  </div>
                )}
                {wine.alcohol && (
                  <div className="bg-wine-50 px-4 py-3 rounded-xl">
                    <div className="text-xs text-gray-500 mb-1">Alcohol</div>
                    <div className="font-semibold text-gray-900">{wine.alcohol}</div>
                  </div>
                )}
              </div>
            </div>

            {/* Description */}
            {wine.description && (
              <div className="bg-white rounded-3xl shadow-wine-lg p-6 sm:p-8">
                <h2 className="text-2xl font-bold text-gray-900 mb-4">About This Wine</h2>
                <p className={`text-gray-700 leading-relaxed ${!showFullDescription && 'line-clamp-3'}`}>
                  {wine.description}
                </p>
                {wine.description.length > 150 && (
                  <button
                    onClick={() => setShowFullDescription(!showFullDescription)}
                    className="mt-3 text-wine-600 font-semibold hover:text-wine-700 transition-colors"
                  >
                    {showFullDescription ? 'Show less' : 'Read more'}
                  </button>
                )}
              </div>
            )}

            {/* Tasting Notes */}
            {wine.tastingNotes && wine.tastingNotes.length > 0 && (
              <div className="bg-white rounded-3xl shadow-wine-lg p-6 sm:p-8">
                <h2 className="text-2xl font-bold text-gray-900 mb-4">Tasting Notes</h2>
                <div className="flex flex-wrap gap-2">
                  {wine.tastingNotes.map((note, i) => (
                    <span
                      key={i}
                      className="px-4 py-2 bg-gradient-to-r from-wine-100 to-purple-100 text-gray-800 rounded-full text-sm font-medium"
                    >
                      {note}
                    </span>
                  ))}
                </div>
              </div>
            )}

            {/* Food Pairings */}
            {wine.foodPairings && wine.foodPairings.length > 0 && (
              <div className="bg-white rounded-3xl shadow-wine-lg p-6 sm:p-8">
                <h2 className="text-2xl font-bold text-gray-900 mb-4 flex items-center gap-2">
                  <span>🍽️</span> Perfect Pairings
                </h2>
                <div className="grid grid-cols-2 gap-3">
                  {wine.foodPairings.map((pairing, i) => (
                    <div key={i} className="bg-gold-50 px-4 py-3 rounded-xl text-center font-medium text-gray-800">
                      {pairing}
                    </div>
                  ))}
                </div>
              </div>
            )}
          </div>
        </div>

        {/* Where to Buy Section */}
        {wine.availableAt && wine.availableAt.length > 0 && (
          <WhereToBuy retailers={wine.availableAt} wineName={wine.name} />
        )}

        {/* Price History Chart */}
        <div className="mt-12 bg-white rounded-3xl shadow-wine-lg p-6 sm:p-8">
          <h2 className="text-2xl sm:text-3xl font-bold text-gray-900 mb-6">Price History</h2>
          <PriceChart
            data={[
              { date: '2024-01', price: 95 },
              { date: '2024-02', price: 92 },
              { date: '2024-03', price: 94 },
              { date: '2024-04', price: 89.99 }
            ]}
            currentPrice={parseFloat(wine.price)}
            trend="falling"
            dealScore={75}
          />
        </div>

        {/* Related Wines */}
        <RelatedWines currentWine={wine} />
      </main>
    </div>
  )
}