← back to Wine Finder Next

components/mobile/WineDetailModal.tsx

290 lines

'use client'

import { useState, useEffect } from 'react';
import Image from 'next/image';
import { Wine } from '@/lib/types/wine';
import PriceChart from '../PriceChart';
import AffiliateButton from './AffiliateButton';
import PriceComparisonSheet from './PriceComparisonSheet';

interface WineDetailModalProps {
  wine: Wine | null;
  isOpen: boolean;
  onClose: () => void;
}

export default function WineDetailModal({
  wine,
  isOpen,
  onClose
}: WineDetailModalProps) {
  const [showPriceHistory, setShowPriceHistory] = useState(false);
  const [showComparison, setShowComparison] = useState(false);
  const [chartData, setChartData] = useState<any>(null);
  const [loading, setLoading] = useState(false);
  const [imageIndex, setImageIndex] = useState(0);

  useEffect(() => {
    if (isOpen && wine) {
      // Reset state
      setImageIndex(0);
      setShowPriceHistory(false);
      setChartData(null);

      // Prevent body scroll
      document.body.style.overflow = 'hidden';
    } else {
      document.body.style.overflow = '';
    }

    return () => {
      document.body.style.overflow = '';
    };
  }, [isOpen, wine]);

  const loadPriceHistory = async () => {
    if (!wine || loading || chartData) return;

    setLoading(true);
    try {
      const response = await fetch(
        `/api/price-history?wine=${encodeURIComponent(wine.name)}&vintage=${wine.vintage || ''}`
      );
      const data = await response.json();
      setChartData(data);
    } catch (error) {
      console.error('Failed to load price history:', error);
    } finally {
      setLoading(false);
    }
  };

  if (!isOpen || !wine) return null;

  const isInStock = wine.availability?.toLowerCase().includes('stock');

  return (
    <>
      {/* Backdrop */}
      <div
        className="fixed inset-0 bg-black/70 z-50 animate-fadeIn"
        onClick={onClose}
      />

      {/* Modal */}
      <div className="fixed inset-0 z-50 flex items-end sm:items-center justify-center pointer-events-none">
        <div
          className="bg-white w-full max-w-2xl max-h-[95vh] rounded-t-3xl sm:rounded-3xl overflow-hidden shadow-2xl pointer-events-auto animate-slideUp"
          onClick={(e) => e.stopPropagation()}
        >
          {/* Close Button */}
          <button
            onClick={onClose}
            className="absolute top-4 right-4 z-10 w-10 h-10 bg-white/90 backdrop-blur rounded-full flex items-center justify-center text-gray-700 hover:bg-white shadow-lg transition-all"
          >
            ✕
          </button>

          {/* Scrollable Content */}
          <div className="overflow-y-auto max-h-[95vh]">
            {/* Image Section */}
            <div className="relative h-80 bg-gradient-to-br from-purple-100 to-pink-100">
              {wine.image ? (
                <Image
                  src={wine.image}
                  alt={wine.name}
                  fill
                  className="object-contain p-8"
                  sizes="(max-width: 768px) 100vw, 50vw"
                  priority
                />
              ) : (
                <div className="flex items-center justify-center h-full text-8xl">
                  🍷
                </div>
              )}

              {/* Badge */}
              {wine.badge && (
                <div className="absolute top-4 left-4 bg-gradient-to-r from-purple-600 to-pink-600 text-white px-4 py-2 rounded-full font-bold text-sm shadow-lg">
                  {wine.badge === 'new' && '🆕 New Vintage'}
                  {wine.badge === 'deal' && '🔥 Hot Deal'}
                  {wine.badge === 'featured' && '⭐ Featured'}
                </div>
              )}
            </div>

            {/* Content */}
            <div className="p-6 space-y-4">
              {/* Title */}
              <div>
                <h2 className="text-2xl font-bold text-gray-900 mb-2">
                  {wine.name}
                </h2>
                {wine.winery && (
                  <p className="text-lg text-purple-600 font-medium">
                    🏛️ {wine.winery}
                  </p>
                )}
              </div>

              {/* Price & Rating */}
              <div className="flex items-center justify-between p-4 bg-gradient-to-r from-purple-50 to-pink-50 rounded-xl">
                <div>
                  <div className="text-4xl font-bold text-purple-700">
                    ${wine.price}
                  </div>
                  {wine.priceHistory?.previousPrice && (
                    <div className="text-sm text-gray-500 line-through">
                      ${wine.priceHistory.previousPrice}
                    </div>
                  )}
                </div>
                {wine.rating && (
                  <div className="text-right">
                    <div className="flex items-center gap-2 bg-yellow-50 px-4 py-3 rounded-xl border-2 border-yellow-200">
                      <span className="text-yellow-500 text-2xl">⭐</span>
                      <span className="text-2xl font-bold text-gray-800">
                        {wine.rating}
                      </span>
                    </div>
                    {wine.reviews && (
                      <div className="text-xs text-gray-500 mt-1">
                        {wine.reviews.toLocaleString()} reviews
                      </div>
                    )}
                  </div>
                )}
              </div>

              {/* Details Grid */}
              <div className="grid grid-cols-2 gap-3">
                {wine.vintage && (
                  <div className="bg-purple-50 p-3 rounded-lg">
                    <div className="text-xs text-gray-600">Vintage</div>
                    <div className="font-bold text-purple-800">🗓️ {wine.vintage}</div>
                  </div>
                )}
                {wine.region && (
                  <div className="bg-pink-50 p-3 rounded-lg">
                    <div className="text-xs text-gray-600">Region</div>
                    <div className="font-bold text-pink-800">📍 {wine.region}</div>
                  </div>
                )}
                {wine.type && (
                  <div className="bg-indigo-50 p-3 rounded-lg">
                    <div className="text-xs text-gray-600">Type</div>
                    <div className="font-bold text-indigo-800">{wine.type}</div>
                  </div>
                )}
                {wine.varietal && (
                  <div className="bg-green-50 p-3 rounded-lg">
                    <div className="text-xs text-gray-600">Varietal</div>
                    <div className="font-bold text-green-800">🍇 {wine.varietal}</div>
                  </div>
                )}
              </div>

              {/* Description */}
              {wine.description && (
                <div className="border-l-4 border-purple-500 pl-4 py-2 bg-gray-50 rounded-r-lg">
                  <p className="text-gray-700 italic">"{wine.description}"</p>
                </div>
              )}

              {/* Availability */}
              <div className="flex items-center justify-between p-3 bg-gray-50 rounded-lg">
                <span className="text-sm text-gray-600">Availability</span>
                <span className={`text-sm font-bold px-3 py-1 rounded-full ${
                  isInStock
                    ? 'bg-green-100 text-green-700'
                    : 'bg-gray-200 text-gray-600'
                }`}>
                  {isInStock ? '✓' : '○'} {wine.availability || 'Check retailer'}
                </span>
              </div>

              {/* Price History Toggle */}
              <button
                onClick={() => {
                  if (!showPriceHistory && !chartData) {
                    loadPriceHistory();
                  }
                  setShowPriceHistory(!showPriceHistory);
                }}
                className="w-full py-3 px-4 bg-gradient-to-r from-blue-500 to-indigo-500 text-white rounded-xl font-bold flex items-center justify-center gap-2 hover:from-blue-600 hover:to-indigo-600 transition-all"
              >
                {showPriceHistory ? '📊 Hide' : '📈 Show'} Price History
                {loading && <div className="animate-spin rounded-full h-4 w-4 border-2 border-white border-t-transparent"></div>}
              </button>

              {/* Price Chart */}
              {showPriceHistory && chartData && (
                <div className="animate-fadeIn">
                  {chartData.success && chartData.pricePoints?.length > 0 ? (
                    <PriceChart
                      data={chartData.pricePoints}
                      currentPrice={parseFloat(wine.price.toString())}
                      trend={chartData.stats?.trend || 'stable'}
                      dealScore={chartData.stats?.dealScore || 50}
                    />
                  ) : (
                    <div className="bg-gray-100 border border-gray-200 rounded-xl p-6 text-center">
                      <div className="text-gray-600 mb-2">📊 No Price History</div>
                      <div className="text-sm text-gray-500">
                        Historical data not yet available for this wine.
                      </div>
                    </div>
                  )}
                </div>
              )}

              {/* CTA Buttons */}
              <div className="space-y-3 pt-4 border-t border-gray-200">
                <AffiliateButton
                  wine={wine}
                  partnerId={wine.source.toLowerCase().replace(/[^a-z]/g, '-')}
                  partnerName={wine.source}
                  variant="primary"
                  fullWidth
                  showPrice
                />

                <button
                  onClick={() => setShowComparison(true)}
                  className="w-full py-3 px-4 border-2 border-purple-600 text-purple-600 rounded-xl font-bold hover:bg-purple-50 transition-all"
                >
                  💰 Compare Prices from 5+ Retailers
                </button>
              </div>

              {/* Affiliate Disclosure */}
              <p className="text-xs text-gray-500 text-center pt-2">
                We may earn a commission from purchases made through our links.
              </p>
            </div>
          </div>
        </div>
      </div>

      {/* Price Comparison Sheet */}
      <PriceComparisonSheet
        wine={wine}
        isOpen={showComparison}
        onClose={() => setShowComparison(false)}
      />

      <style jsx>{`
        @keyframes slideUp {
          from { transform: translateY(100%); }
          to { transform: translateY(0); }
        }
        @keyframes fadeIn {
          from { opacity: 0; }
          to { opacity: 1; }
        }
      `}</style>
    </>
  );
}