← back to Wine Finder Next

app/portfolio/page.tsx

131 lines

// app/portfolio/page.tsx
import { getUserPortfolio } from '@/lib/portfolio';
import Link from 'next/link';

export const dynamic = 'force-dynamic';

export default async function PortfolioPage() {
  // Demo user ID - replace with real auth
  const userId = 1;
  const rows = getUserPortfolio(userId);

  const totalValue = rows.reduce((sum: number, r: any) => sum + (r.market_value || 0), 0);
  const totalCost = rows.reduce((sum: number, r: any) => sum + (r.cost_total || 0), 0);
  const totalGainLoss = totalValue - totalCost;
  const totalGainLossPercent = totalCost > 0 ? ((totalGainLoss / totalCost) * 100) : 0;

  return (
    <main className="max-w-6xl mx-auto p-6 space-y-6">
      <div className="flex justify-between items-center">
        <h1 className="text-3xl font-bold text-gray-900">🍷 My Wine Portfolio</h1>
        <Link href="/wines" className="px-4 py-2 bg-purple-600 text-white rounded-lg hover:bg-purple-700 transition">
          Browse Wines
        </Link>
      </div>

      {/* Portfolio Summary */}
      <div className="grid grid-cols-1 md:grid-cols-4 gap-6">
        <div className="bg-white p-6 rounded-lg shadow-md border">
          <div className="text-2xl font-bold text-gray-900">${totalValue.toLocaleString()}</div>
          <div className="text-gray-600">Total Portfolio Value</div>
        </div>
        <div className="bg-white p-6 rounded-lg shadow-md border">
          <div className="text-2xl font-bold text-gray-900">${totalCost.toLocaleString()}</div>
          <div className="text-gray-600">Total Cost Basis</div>
        </div>
        <div className="bg-white p-6 rounded-lg shadow-md border">
          <div className={`text-2xl font-bold ${totalGainLoss >= 0 ? 'text-green-600' : 'text-red-600'}`}>
            ${Math.abs(totalGainLoss).toLocaleString()}
          </div>
          <div className="text-gray-600">
            {totalGainLoss >= 0 ? 'Total Gain' : 'Total Loss'}
          </div>
        </div>
        <div className="bg-white p-6 rounded-lg shadow-md border">
          <div className={`text-2xl font-bold ${totalGainLossPercent >= 0 ? 'text-green-600' : 'text-red-600'}`}>
            {totalGainLossPercent >= 0 ? '+' : ''}{totalGainLossPercent.toFixed(1)}%
          </div>
          <div className="text-gray-600">Total Return</div>
        </div>
      </div>

      {/* Holdings Table */}
      <div className="bg-white rounded-lg shadow-md border overflow-hidden">
        <div className="px-6 py-4 bg-gray-50 border-b">
          <h2 className="text-xl font-semibold text-gray-900">Holdings</h2>
        </div>
        
        {rows.length === 0 ? (
          <div className="p-8 text-center">
            <h3 className="text-lg font-medium text-gray-500 mb-2">No wines in portfolio</h3>
            <p className="text-gray-400 mb-4">Start building your collection!</p>
            <Link href="/wines" className="inline-block px-6 py-3 bg-purple-600 text-white rounded-lg hover:bg-purple-700 transition">
              Browse Wines
            </Link>
          </div>
        ) : (
          <div className="overflow-x-auto">
            <table className="w-full">
              <thead className="bg-gray-50">
                <tr>
                  <th className="px-6 py-3 text-left text-xs font-medium text-gray-500 uppercase tracking-wider">Wine</th>
                  <th className="px-6 py-3 text-right text-xs font-medium text-gray-500 uppercase tracking-wider">Units</th>
                  <th className="px-6 py-3 text-right text-xs font-medium text-gray-500 uppercase tracking-wider">Cost/Unit</th>
                  <th className="px-6 py-3 text-right text-xs font-medium text-gray-500 uppercase tracking-wider">Current Price</th>
                  <th className="px-6 py-3 text-right text-xs font-medium text-gray-500 uppercase tracking-wider">Market Value</th>
                  <th className="px-6 py-3 text-right text-xs font-medium text-gray-500 uppercase tracking-wider">Gain/Loss</th>
                  <th className="px-6 py-3 text-right text-xs font-medium text-gray-500 uppercase tracking-wider">% Change</th>
                </tr>
              </thead>
              <tbody className="divide-y divide-gray-200">
                {rows.map((r: any) => (
                  <tr key={r.id} className="hover:bg-gray-50">
                    <td className="px-6 py-4">
                      <Link href={`/wines/${r.wine_id}`} className="font-medium text-purple-600 hover:underline">
                        {r.name}
                      </Link>
                      <div className="text-sm text-gray-500">
                        {r.varietal} • {r.region} • {r.country}
                      </div>
                    </td>
                    <td className="px-6 py-4 text-right text-sm font-medium">{r.units}</td>
                    <td className="px-6 py-4 text-right text-sm">
                      ${r.cost_basis?.toFixed(2) ?? '-'}
                    </td>
                    <td className="px-6 py-4 text-right text-sm font-medium">
                      ${r.current_price?.toFixed(2) ?? '-'}
                    </td>
                    <td className="px-6 py-4 text-right text-sm font-bold">
                      ${r.market_value?.toFixed(2) ?? '-'}
                    </td>
                    <td className="px-6 py-4 text-right text-sm">
                      {r.current_price && r.cost_basis ? (
                        <span className={`font-medium ${
                          (r.current_price - r.cost_basis) >= 0 ? 'text-green-600' : 'text-red-600'
                        }`}>
                          {(r.current_price - r.cost_basis) >= 0 ? '+' : ''}
                          ${((r.current_price - r.cost_basis) * r.units).toFixed(2)}
                        </span>
                      ) : (
                        '-'
                      )}
                    </td>
                    <td className="px-6 py-4 text-right text-sm">
                      {r.pct_change != null ? (
                        <span className={`font-medium ${r.pct_change >= 0 ? 'text-green-600' : 'text-red-600'}`}>
                          {r.pct_change >= 0 ? '+' : ''}{r.pct_change.toFixed(1)}%
                        </span>
                      ) : (
                        '-'
                      )}
                    </td>
                  </tr>
                ))}
              </tbody>
            </table>
          </div>
        )}
      </div>
    </main>
  );
}