← back to Wine Finder Next

app/membership/page.tsx

642 lines

'use client';

import { useState, useEffect, useCallback, useMemo } from 'react';
import type { Bottle, GovernanceVote, MarketplaceListing } from '@/src/types/membership';
import JsonLd from './JsonLd';
import LoadingSkeleton from '@/components/membership/LoadingSkeleton';

export default function MembershipPage() {
  const [bottles, setBottles] = useState<Bottle[]>([]);
  const [activeVotes, setActiveVotes] = useState<GovernanceVote[]>([]);
  const [marketplaceListings, setMarketplaceListings] = useState<MarketplaceListing[]>([]);
  const [selectedTab, setSelectedTab] = useState<'bottles' | 'voting' | 'marketplace' | 'my-holdings'>('bottles');
  const [loading, setLoading] = useState(true);

  const loadData = useCallback(async () => {
    try {
      const [bottlesRes, votesRes, marketRes] = await Promise.all([
        fetch('/api/membership/bottles'),
        fetch('/api/membership/votes?active=true'),
        fetch('/api/membership/marketplace?active=true')
      ]);

      const [bottlesData, votesData, marketData] = await Promise.all([
        bottlesRes.json(),
        votesRes.json(),
        marketRes.json()
      ]);

      if (bottlesData.success) setBottles(bottlesData.data);
      if (votesData.success) setActiveVotes(votesData.data);
      if (marketData.success) setMarketplaceListings(marketData.data);
    } catch (error) {
      console.error('Error loading data:', error);
    } finally {
      setLoading(false);
    }
  }, []);

  useEffect(() => {
    loadData();
  }, [loadData]);

  // Memoize tabs configuration
  const tabs = useMemo(() => [
    { id: 'bottles' as const, label: 'Investment Bottles', icon: '🍷', ariaLabel: 'View available wine bottles for investment' },
    { id: 'voting' as const, label: 'Governance Voting', icon: '🗳️', ariaLabel: 'Participate in governance votes' },
    { id: 'marketplace' as const, label: 'Trading Marketplace', icon: '🏪', ariaLabel: 'Browse marketplace listings' },
    { id: 'my-holdings' as const, label: 'My Portfolio', icon: '💼', ariaLabel: 'View your wine portfolio' }
  ], []);

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

  return (
    <>
      <JsonLd />
      <div className="min-h-screen bg-gradient-to-br from-purple-900 via-indigo-900 to-blue-900 transition-all duration-300">
        {/* Optimized Header with better mobile responsiveness */}
        <header className="bg-black/30 backdrop-blur-md border-b border-white/10 sticky top-0 z-50 transition-all duration-300">
          <div className="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8 py-6">
            <h1 className="text-3xl sm:text-4xl font-bold text-white mb-2 animate-slide-down">
              Tokenized Wine Investment Platform | Wine Membership DAO
            </h1>
            <p className="text-gray-300 text-base sm:text-lg animate-fade-in">
              Own fractional shares in rare wine bottles like Château Margaux 1996 and DRC La Tâche 2005.
              Participate in governance voting, receive sample distributions, and trade shares on our marketplace.
            </p>

            {/* Info Grid with improved mobile layout */}
            <div className="mt-4 grid grid-cols-1 sm:grid-cols-2 lg:grid-cols-3 gap-3 sm:gap-4">
              <div className="text-white bg-white/5 rounded-lg p-3 backdrop-blur-sm transition-all duration-200 hover:bg-white/10">
                <span className="font-semibold block sm:inline">10,000 Shares</span>
                <span className="text-sm sm:text-base text-gray-300 block sm:inline sm:ml-1">per bottle</span>
              </div>
              <div className="text-white bg-white/5 rounded-lg p-3 backdrop-blur-sm transition-all duration-200 hover:bg-white/10">
                <span className="font-semibold block sm:inline">Democratic Governance</span>
                <span className="text-sm sm:text-base text-gray-300 block sm:inline sm:ml-1">with voting rights</span>
              </div>
              <div className="text-white bg-white/5 rounded-lg p-3 backdrop-blur-sm transition-all duration-200 hover:bg-white/10">
                <span className="font-semibold block sm:inline">Licensed Distribution</span>
                <span className="text-sm sm:text-base text-gray-300 block sm:inline sm:ml-1">via compliance partners</span>
              </div>
            </div>
          </div>
        </header>

        {/* Improved Navigation with keyboard support and animations */}
        <div className="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8 py-6">
          <nav
            className="flex flex-col sm:flex-row gap-2 mb-8 bg-black/20 p-2 rounded-xl backdrop-blur-sm animate-slide-up"
            role="navigation"
            aria-label="Membership platform sections"
          >
            {tabs.map((tab) => (
              <button
                key={tab.id}
                onClick={() => setSelectedTab(tab.id)}
                onKeyDown={(e) => {
                  if (e.key === 'Enter' || e.key === ' ') {
                    e.preventDefault();
                    setSelectedTab(tab.id);
                  }
                }}
                aria-label={tab.ariaLabel}
                aria-current={selectedTab === tab.id ? 'page' : undefined}
                className={`flex-1 py-3 px-4 sm:px-6 rounded-lg font-semibold transition-all duration-300 transform focus:outline-none focus:ring-2 focus:ring-purple-400 focus:ring-offset-2 focus:ring-offset-purple-900 ${
                  selectedTab === tab.id
                    ? 'bg-white text-purple-900 shadow-lg scale-105'
                    : 'text-white hover:bg-white/10 hover:scale-102'
                }`}
              >
                <span className="hidden sm:inline">{tab.icon} {tab.label}</span>
                <span className="sm:hidden text-center">{tab.icon}<br /><span className="text-xs">{tab.label.split(' ')[0]}</span></span>
              </button>
            ))}
          </nav>

          {/* Content with fade transitions */}
          <main className="animate-fade-in">
            {selectedTab === 'bottles' && <BottlesTab bottles={bottles} />}
            {selectedTab === 'voting' && <VotingTab votes={activeVotes} bottles={bottles} onVoteComplete={loadData} />}
            {selectedTab === 'marketplace' && <MarketplaceTab listings={marketplaceListings} bottles={bottles} onPurchase={loadData} />}
            {selectedTab === 'my-holdings' && <MyHoldingsTab />}
          </main>
        </div>

        {/* Enhanced Footer */}
        <footer className="bg-black/40 border-t border-white/10 mt-12 py-8">
          <div className="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8">
            <h2 className="text-2xl font-bold text-white mb-4">About Tokenized Wine Investment</h2>
            <div className="grid md:grid-cols-2 gap-6 text-gray-300">
              <div>
                <h3 className="font-semibold text-white mb-2">What is Wine Tokenization?</h3>
                <p className="text-sm leading-relaxed">
                  Wine tokenization allows investors to purchase fractional shares in ultra-premium wine bottles.
                  Each bottle is divided into 10,000 membership units, making rare wines like Château Margaux
                  and Domaine de la Romanée-Conti accessible to wine enthusiasts and investors at any budget level.
                </p>
              </div>
              <div>
                <h3 className="font-semibold text-white mb-2">Investment Benefits</h3>
                <ul className="text-sm space-y-1">
                  <li>• Fractional ownership of investment-grade wines</li>
                  <li>• Democratic governance through voting rights</li>
                  <li>• Professional sample distribution when unlocked</li>
                  <li>• Secondary market trading via our marketplace</li>
                  <li>• Authenticated provenance and secure storage</li>
                </ul>
              </div>
            </div>
            <div className="mt-6 text-center text-gray-400 text-sm">
              <p>Red Thunder Wine Membership Platform | Tokenized Rare Wine Investment</p>
              <p className="mt-2">Featuring Bordeaux First Growths, Burgundy Grand Crus, and other collectible wines</p>
            </div>
          </div>
        </footer>
      </div>
    </>
  );
}

function BottlesTab({ bottles }: { bottles: Bottle[] }) {
  return (
    <section aria-label="Available tokenized wine bottles for investment">
      <h2 className="text-2xl sm:text-3xl font-bold text-white mb-6">Investment-Grade Wine Bottles</h2>
      <div className="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-4 sm:gap-6">
        {bottles.map((bottle, index) => {
          const sharesSold = bottle.totalMembershipUnits - bottle.availableMembershipUnits;
          const sharesNeeded = bottle.totalMembershipUnits;
          const pricePerShare = bottle.estimatedValue / bottle.totalMembershipUnits;
          const fundingProgress = (sharesSold / sharesNeeded) * 100;

          return (
            <article
              key={bottle.id}
              className="bg-white/10 backdrop-blur-sm rounded-xl p-4 sm:p-6 border border-white/20 hover:border-white/40 transition-all duration-300 transform hover:scale-105 hover:shadow-2xl animate-scale-in focus-within:ring-2 focus-within:ring-purple-400"
              style={{ animationDelay: `${index * 100}ms` }}
              itemScope
              itemType="https://schema.org/Product"
            >
              <div className="flex justify-between items-start mb-4">
                <div className="flex-1">
                  <h3 className="text-lg sm:text-xl font-bold text-white mb-1" itemProp="name">
                    {bottle.name}
                  </h3>
                  <p className="text-gray-300 text-sm sm:text-base">{bottle.vintage}</p>
                </div>
                <span
                  className={`px-3 py-1 rounded-full text-xs font-semibold transition-all duration-200 ${
                    bottle.status === 'active' ? 'bg-green-500/20 text-green-300 border border-green-500/50' :
                    bottle.status === 'unlocked' ? 'bg-yellow-500/20 text-yellow-300 border border-yellow-500/50' :
                    'bg-gray-500/20 text-gray-300 border border-gray-500/50'
                  }`}
                  role="status"
                  aria-label={`Status: ${bottle.status}`}
                >
                  {bottle.status}
                </span>
              </div>

              <div className="space-y-2 mb-4" itemProp="description">
                <p className="text-gray-300 text-sm">
                  <span className="font-semibold">Producer:</span> <span itemProp="brand">{bottle.producer}</span>
                </p>
                <p className="text-gray-300 text-sm">
                  <span className="font-semibold">Region:</span> {bottle.region}
                </p>
                <p className="text-gray-300 text-sm">
                  <span className="font-semibold">Size:</span> {bottle.size}
                </p>
              </div>

              <div className="bg-black/20 rounded-lg p-3 sm:p-4 mb-4">
                <div className="grid grid-cols-2 gap-3 sm:gap-4">
                  <div>
                    <p className="text-lg sm:text-xl font-bold text-white mb-1">
                      ${(bottle.estimatedValue / 4.5).toLocaleString()}
                    </p>
                    <p className="text-gray-400 text-xs">Market Price</p>
                  </div>
                  <div itemProp="offers" itemScope itemType="https://schema.org/Offer">
                    <meta itemProp="priceCurrency" content="USD" />
                    <meta itemProp="price" content={bottle.estimatedValue.toString()} />
                    <p className="text-lg sm:text-xl font-bold text-green-400 mb-1">
                      ${bottle.estimatedValue.toLocaleString()}
                    </p>
                    <p className="text-gray-400 text-xs">Total Value</p>
                  </div>
                </div>
                <p className="text-xs text-gray-500 mt-2">Includes acquisition, authentication, insurance & storage</p>
              </div>

              {/* Enhanced Progress Bar with animation */}
              <div className="mb-4">
                <div className="flex justify-between text-sm mb-2">
                  <span className="text-white font-semibold text-xs sm:text-sm">
                    {sharesSold.toLocaleString()} / {sharesNeeded.toLocaleString()} Sold
                  </span>
                  <span className="text-purple-300 font-bold">{fundingProgress.toFixed(1)}%</span>
                </div>
                <div className="h-3 bg-black/30 rounded-full overflow-hidden border border-purple-500/30">
                  <div
                    className="h-full bg-gradient-to-r from-purple-500 to-pink-500 transition-all duration-1000 ease-out"
                    style={{ width: `${fundingProgress}%` }}
                    role="progressbar"
                    aria-valuenow={fundingProgress}
                    aria-valuemin={0}
                    aria-valuemax={100}
                    aria-label={`${fundingProgress.toFixed(1)}% funded`}
                  />
                </div>
                <p className="text-xs text-gray-400 mt-1">
                  {bottle.availableMembershipUnits.toLocaleString()} shares available
                </p>
              </div>

              <div className="grid grid-cols-2 gap-3 mb-4">
                <div className="bg-black/30 rounded-lg p-3 border border-purple-500/20 transition-colors hover:border-purple-500/40">
                  <p className="text-base sm:text-lg font-bold text-white">${pricePerShare.toFixed(2)}</p>
                  <p className="text-xs text-gray-400">Per Share</p>
                </div>
                <div className="bg-black/30 rounded-lg p-3 border border-green-500/20 transition-colors hover:border-green-500/40">
                  <p className="text-base sm:text-lg font-bold text-green-300">{bottle.availableMembershipUnits.toLocaleString()}</p>
                  <p className="text-xs text-gray-400">Available</p>
                </div>
              </div>

              <button
                className="w-full bg-gradient-to-r from-purple-600 to-pink-600 text-white py-3 rounded-lg font-semibold hover:from-purple-700 hover:to-pink-700 transition-all duration-300 shadow-lg hover:shadow-xl transform hover:scale-105 focus:outline-none focus:ring-2 focus:ring-purple-400 focus:ring-offset-2 focus:ring-offset-purple-900"
                aria-label={`Buy shares of ${bottle.name} ${bottle.vintage}`}
              >
                Buy Wine Shares
              </button>
            </article>
          );
        })}
      </div>
    </section>
  );
}

function VotingTab({ votes, bottles, onVoteComplete }: {
  votes: GovernanceVote[];
  bottles: Bottle[];
  onVoteComplete: () => void;
}) {
  const [selectedVote, setSelectedVote] = useState<string | null>(null);
  const [voteChoice, setVoteChoice] = useState<'for' | 'against' | 'abstain'>('for');
  const [userId] = useState('user_1');
  const [membershipUnitId, setMembershipUnitId] = useState('');
  const [isSubmitting, setIsSubmitting] = useState(false);

  const handleCastVote = async (voteId: string) => {
    if (!membershipUnitId) {
      alert('Please enter your Membership Unit ID');
      return;
    }

    setIsSubmitting(true);
    try {
      const res = await fetch(`/api/membership/votes/${voteId}/cast`, {
        method: 'POST',
        headers: { 'Content-Type': 'application/json' },
        body: JSON.stringify({ userId, membershipUnitId, choice: voteChoice })
      });

      const data = await res.json();

      if (data.success) {
        alert('Vote cast successfully!');
        setSelectedVote(null);
        setMembershipUnitId('');
        onVoteComplete();
      } else {
        alert(data.error || 'Failed to cast vote');
      }
    } catch (error) {
      alert('Error casting vote');
    } finally {
      setIsSubmitting(false);
    }
  };

  return (
    <section aria-label="Active governance votes">
      <h2 className="text-2xl sm:text-3xl font-bold text-white mb-6">Governance & Voting</h2>
      <div className="space-y-6">
        {votes.map((vote, index) => {
          const bottle = bottles.find(b => b.id === vote.bottleId);
          const totalVotes = vote.votesFor + vote.votesAgainst + vote.votesAbstain;
          const forPercentage = totalVotes > 0 ? (vote.votesFor / totalVotes) * 100 : 0;
          const againstPercentage = totalVotes > 0 ? (vote.votesAgainst / totalVotes) * 100 : 0;
          const quorumProgress = bottle ? (totalVotes / bottle.totalMembershipUnits) * 100 : 0;

          const totalShares = bottle?.totalMembershipUnits || 0;
          const votesNeededForQuorum = Math.ceil(totalShares * (vote.quorumRequired / 100));
          const votesNeededToPass = Math.ceil(votesNeededForQuorum * (vote.approvalThreshold / 100));
          const votesRemainingForQuorum = Math.max(0, votesNeededForQuorum - totalVotes);
          const votesRemainingToPass = Math.max(0, votesNeededToPass - vote.votesFor);

          return (
            <article
              key={vote.id}
              className="bg-white/10 backdrop-blur-sm rounded-xl p-4 sm:p-6 border border-white/20 transition-all duration-300 hover:border-white/30 animate-slide-up"
              style={{ animationDelay: `${index * 100}ms` }}
            >
              <div className="flex flex-col sm:flex-row sm:justify-between sm:items-start gap-4 mb-4">
                <div className="flex-1">
                  <h3 className="text-xl sm:text-2xl font-bold text-white mb-2">{vote.proposal}</h3>
                  <p className="text-gray-300 mb-2 text-sm sm:text-base">{vote.description}</p>
                  {bottle && (
                    <p className="text-purple-300 font-semibold text-sm sm:text-base">
                      📦 {bottle.name} ({bottle.vintage})
                    </p>
                  )}
                </div>
                <span
                  className="px-4 py-2 rounded-full text-sm font-semibold bg-green-500/20 text-green-300 border border-green-500/50 self-start"
                  role="status"
                  aria-label={`Vote status: ${vote.status}`}
                >
                  {vote.status}
                </span>
              </div>

              {/* Responsive Stats Grid */}
              <div className="grid grid-cols-2 lg:grid-cols-4 gap-3 sm:gap-4 mb-6">
                <div className="bg-black/30 rounded-lg p-3 sm:p-4 border border-purple-500/30">
                  <div className="text-lg sm:text-2xl font-bold text-white">{totalShares.toLocaleString()}</div>
                  <div className="text-xs text-gray-400">Total Shares</div>
                </div>
                <div className="bg-black/30 rounded-lg p-3 sm:p-4 border border-blue-500/30">
                  <div className="text-lg sm:text-2xl font-bold text-blue-300">{(totalShares - (bottle?.availableMembershipUnits || 0)).toLocaleString()}</div>
                  <div className="text-xs text-gray-400">Shares Sold</div>
                </div>
                <div className="bg-black/30 rounded-lg p-3 sm:p-4 border border-green-500/30">
                  <div className="text-lg sm:text-2xl font-bold text-green-300">{votesNeededForQuorum.toLocaleString()}</div>
                  <div className="text-xs text-gray-400">Quorum Needed</div>
                </div>
                <div className="bg-black/30 rounded-lg p-3 sm:p-4 border border-yellow-500/30">
                  <div className="text-lg sm:text-2xl font-bold text-yellow-300">{votesRemainingToPass.toLocaleString()}</div>
                  <div className="text-xs text-gray-400">To Unlock</div>
                </div>
              </div>

              {/* Enhanced Vote Progress with better contrast */}
              <div className="space-y-4 mb-6">
                <div>
                  <div className="flex justify-between text-sm mb-2">
                    <span className="text-white font-semibold text-xs sm:text-sm">
                      ✅ For: {vote.votesFor} ({votesRemainingToPass} more needed)
                    </span>
                    <span className="text-green-300 font-semibold">{forPercentage.toFixed(1)}%</span>
                  </div>
                  <div className="h-4 bg-black/40 rounded-full overflow-hidden border-2 border-green-500/30">
                    <div
                      className="h-full bg-gradient-to-r from-green-500 to-green-400 transition-all duration-1000"
                      style={{ width: `${forPercentage}%` }}
                      role="progressbar"
                      aria-valuenow={forPercentage}
                      aria-valuemin={0}
                      aria-valuemax={100}
                      aria-label={`${forPercentage.toFixed(1)}% votes for`}
                    />
                  </div>
                </div>

                <div>
                  <div className="flex justify-between text-sm mb-2">
                    <span className="text-white font-semibold text-xs sm:text-sm">
                      ❌ Against: {vote.votesAgainst}
                    </span>
                    <span className="text-red-300 font-semibold">{againstPercentage.toFixed(1)}%</span>
                  </div>
                  <div className="h-4 bg-black/40 rounded-full overflow-hidden border-2 border-red-500/30">
                    <div
                      className="h-full bg-gradient-to-r from-red-500 to-red-400 transition-all duration-1000"
                      style={{ width: `${againstPercentage}%` }}
                      role="progressbar"
                      aria-valuenow={againstPercentage}
                      aria-valuemin={0}
                      aria-valuemax={100}
                      aria-label={`${againstPercentage.toFixed(1)}% votes against`}
                    />
                  </div>
                </div>

                <div>
                  <div className="flex justify-between text-sm mb-2">
                    <span className="text-white font-semibold text-xs sm:text-sm">
                      📊 Quorum: {totalVotes}/{votesNeededForQuorum} ({votesRemainingForQuorum} needed)
                    </span>
                    <span className="text-blue-300 font-semibold">{quorumProgress.toFixed(1)}%</span>
                  </div>
                  <div className="h-4 bg-black/40 rounded-full overflow-hidden border-2 border-blue-500/30">
                    <div
                      className="h-full bg-gradient-to-r from-blue-500 to-blue-400 transition-all duration-1000"
                      style={{ width: `${Math.min(quorumProgress, 100)}%` }}
                      role="progressbar"
                      aria-valuenow={Math.min(quorumProgress, 100)}
                      aria-valuemin={0}
                      aria-valuemax={100}
                      aria-label={`${quorumProgress.toFixed(1)}% quorum reached`}
                    />
                  </div>
                </div>
              </div>

              <p className="text-gray-400 text-sm mb-4">
                Voting ends: {new Date(vote.endDate).toLocaleDateString()} at {new Date(vote.endDate).toLocaleTimeString()}
              </p>

              {/* Cast Vote Interface */}
              {selectedVote === vote.id ? (
                <div className="bg-black/20 p-4 rounded-lg space-y-3 border border-white/10">
                  <label htmlFor={`membership-id-${vote.id}`} className="sr-only">
                    Membership Unit ID
                  </label>
                  <input
                    id={`membership-id-${vote.id}`}
                    type="text"
                    placeholder="Enter your Membership Unit ID"
                    value={membershipUnitId}
                    onChange={(e) => setMembershipUnitId(e.target.value)}
                    className="w-full px-4 py-3 bg-white/10 border border-white/20 rounded-lg text-white placeholder-gray-400 focus:outline-none focus:ring-2 focus:ring-purple-400 focus:border-transparent text-base"
                    style={{ fontSize: '16px' }}
                    disabled={isSubmitting}
                    aria-required="true"
                  />
                  <fieldset className="flex flex-col sm:flex-row gap-2">
                    <legend className="sr-only">Choose your vote</legend>
                    {(['for', 'against', 'abstain'] as const).map((choice) => (
                      <button
                        key={choice}
                        type="button"
                        onClick={() => setVoteChoice(choice)}
                        disabled={isSubmitting}
                        className={`flex-1 py-3 rounded-lg font-semibold transition-all duration-200 focus:outline-none focus:ring-2 focus:ring-purple-400 ${
                          voteChoice === choice
                            ? 'bg-purple-600 text-white shadow-lg scale-105'
                            : 'bg-white/10 text-gray-300 hover:bg-white/20'
                        } disabled:opacity-50 disabled:cursor-not-allowed`}
                        aria-pressed={voteChoice === choice}
                      >
                        {choice === 'for' && '✅ For'}
                        {choice === 'against' && '❌ Against'}
                        {choice === 'abstain' && '⚪ Abstain'}
                      </button>
                    ))}
                  </fieldset>
                  <div className="flex flex-col sm:flex-row gap-2">
                    <button
                      onClick={() => handleCastVote(vote.id)}
                      disabled={isSubmitting}
                      className="flex-1 bg-gradient-to-r from-green-600 to-green-500 text-white py-3 rounded-lg font-semibold hover:from-green-700 hover:to-green-600 transition-all duration-300 shadow-lg disabled:opacity-50 disabled:cursor-not-allowed focus:outline-none focus:ring-2 focus:ring-green-400"
                    >
                      {isSubmitting ? 'Submitting...' : 'Confirm Vote'}
                    </button>
                    <button
                      onClick={() => setSelectedVote(null)}
                      disabled={isSubmitting}
                      className="px-6 bg-white/10 text-white py-3 rounded-lg font-semibold hover:bg-white/20 transition-all duration-200 disabled:opacity-50 disabled:cursor-not-allowed focus:outline-none focus:ring-2 focus:ring-gray-400"
                    >
                      Cancel
                    </button>
                  </div>
                </div>
              ) : (
                <button
                  onClick={() => setSelectedVote(vote.id)}
                  className="w-full bg-gradient-to-r from-purple-600 to-pink-600 text-white py-3 rounded-lg font-semibold hover:from-purple-700 hover:to-pink-700 transition-all duration-300 shadow-lg transform hover:scale-105 focus:outline-none focus:ring-2 focus:ring-purple-400"
                >
                  Cast Your Vote
                </button>
              )}
            </article>
          );
        })}

        {votes.length === 0 && (
          <div className="text-center py-12 bg-white/5 rounded-xl border border-white/10">
            <p className="text-gray-300 text-lg">No active governance votes at this time</p>
          </div>
        )}
      </div>
    </section>
  );
}

function MarketplaceTab({ listings, bottles, onPurchase }: {
  listings: MarketplaceListing[];
  bottles: Bottle[];
  onPurchase: () => void;
}) {
  const [isPurchasing, setIsPurchasing] = useState<string | null>(null);

  const handlePurchase = async (listingId: string) => {
    const buyerId = 'user_1';
    const buyerEmail = 'buyer@example.com';
    const buyerName = 'Demo Buyer';

    if (!confirm('Are you sure you want to purchase this item?')) return;

    setIsPurchasing(listingId);
    try {
      const res = await fetch(`/api/membership/marketplace/${listingId}/purchase`, {
        method: 'POST',
        headers: { 'Content-Type': 'application/json' },
        body: JSON.stringify({ buyerId, buyerEmail, buyerName })
      });

      const data = await res.json();

      if (data.success) {
        alert('Purchase successful!');
        onPurchase();
      } else {
        alert(data.error || 'Purchase failed');
      }
    } catch (error) {
      alert('Error completing purchase');
    } finally {
      setIsPurchasing(null);
    }
  };

  return (
    <section aria-label="Marketplace for trading wine shares">
      <h2 className="text-2xl sm:text-3xl font-bold text-white mb-6">Secondary Market Trading</h2>
      <div className="grid grid-cols-1 md:grid-cols-2 gap-4 sm:gap-6">
        {listings.map((listing, index) => {
          const bottle = bottles.find(b => b.id === listing.bottleId);
          const isPurchasingThis = isPurchasing === listing.id;

          return (
            <article
              key={listing.id}
              className="bg-white/10 backdrop-blur-sm rounded-xl p-4 sm:p-6 border border-white/20 transition-all duration-300 hover:border-white/30 hover:shadow-xl animate-scale-in"
              style={{ animationDelay: `${index * 100}ms` }}
            >
              <div className="flex justify-between items-start mb-4">
                <div className="flex-1">
                  <span className="inline-block px-3 py-1 rounded-full text-xs font-semibold bg-purple-500/20 text-purple-300 border border-purple-500/50 mb-2">
                    {listing.listingType === 'membership' ? '🎫 Membership Share' : '🧪 Sample Right'}
                  </span>
                  <h3 className="text-lg sm:text-xl font-bold text-white mt-2">
                    {bottle?.name || 'Unknown Bottle'}
                  </h3>
                  <p className="text-gray-300 text-sm sm:text-base">{bottle?.vintage}</p>
                </div>
              </div>

              <div className="bg-black/20 rounded-lg p-4 mb-4">
                <p className="text-2xl sm:text-3xl font-bold text-white mb-1">
                  ${listing.price.toLocaleString()}
                </p>
                <p className="text-gray-400 text-sm">Listed by: {listing.sellerName}</p>
              </div>

              <p className="text-gray-400 text-sm mb-4">
                Listed: {new Date(listing.listedAt).toLocaleDateString()}
              </p>

              <button
                onClick={() => handlePurchase(listing.id)}
                disabled={isPurchasingThis}
                className="w-full bg-gradient-to-r from-green-600 to-emerald-600 text-white py-3 rounded-lg font-semibold hover:from-green-700 hover:to-emerald-700 transition-all duration-300 shadow-lg transform hover:scale-105 disabled:opacity-50 disabled:cursor-not-allowed focus:outline-none focus:ring-2 focus:ring-green-400"
              >
                {isPurchasingThis ? 'Processing...' : 'Purchase Wine Share'}
              </button>
            </article>
          );
        })}

        {listings.length === 0 && (
          <div className="col-span-2 text-center py-12 bg-white/5 rounded-xl border border-white/10">
            <p className="text-gray-300 text-lg">No items currently listed in marketplace</p>
          </div>
        )}
      </div>
    </section>
  );
}

function MyHoldingsTab() {
  return (
    <section
      aria-label="Your wine investment portfolio"
      className="bg-white/10 backdrop-blur-sm rounded-xl p-6 sm:p-8 border border-white/20 text-center animate-fade-in"
    >
      <h2 className="text-2xl font-bold text-white mb-4">My Wine Investment Portfolio</h2>
      <p className="text-gray-300 mb-6 text-sm sm:text-base">
        Connect your wallet to view your wine membership shares, sample rights, and voting history
      </p>
      <button className="bg-gradient-to-r from-blue-600 to-cyan-600 text-white px-6 sm:px-8 py-3 rounded-lg font-semibold hover:from-blue-700 hover:to-cyan-700 transition-all duration-300 shadow-lg transform hover:scale-105 focus:outline-none focus:ring-2 focus:ring-blue-400">
        Connect Wallet
      </button>
    </section>
  );
}