'use client' import { useEffect, useState } from 'react' import { useStore } from '@/lib/store' import { api, PortfolioDomain, PortfolioSummary, DomainValuation } from '@/lib/api' import { CommandCenterLayout } from '@/components/CommandCenterLayout' import { PremiumTable, StatCard, PageContainer, TableActionButton } from '@/components/PremiumTable' import { Toast, useToast } from '@/components/Toast' import { Plus, Trash2, Edit2, DollarSign, Calendar, Building, RefreshCw, Loader2, TrendingUp, Sparkles, ArrowUpRight, X, Briefcase, PiggyBank, ShoppingCart, } from 'lucide-react' import clsx from 'clsx' import Link from 'next/link' export default function PortfolioPage() { const { subscription } = useStore() const { toast, showToast, hideToast } = useToast() const [portfolio, setPortfolio] = useState([]) const [summary, setSummary] = useState(null) const [loading, setLoading] = useState(true) const [showAddModal, setShowAddModal] = useState(false) const [showEditModal, setShowEditModal] = useState(false) const [showSellModal, setShowSellModal] = useState(false) const [showValuationModal, setShowValuationModal] = useState(false) const [selectedDomain, setSelectedDomain] = useState(null) const [valuation, setValuation] = useState(null) const [valuatingDomain, setValuatingDomain] = useState('') const [addingDomain, setAddingDomain] = useState(false) const [savingEdit, setSavingEdit] = useState(false) const [processingSale, setProcessingSale] = useState(false) const [refreshingId, setRefreshingId] = useState(null) const [addForm, setAddForm] = useState({ domain: '', purchase_price: '', purchase_date: '', registrar: '', renewal_date: '', renewal_cost: '', notes: '', }) const [editForm, setEditForm] = useState({ purchase_price: '', purchase_date: '', registrar: '', renewal_date: '', renewal_cost: '', notes: '', }) const [sellForm, setSellForm] = useState({ sale_date: new Date().toISOString().split('T')[0], sale_price: '', }) useEffect(() => { loadPortfolio() }, []) const loadPortfolio = async () => { setLoading(true) try { const [portfolioData, summaryData] = await Promise.all([ api.getPortfolio(), api.getPortfolioSummary(), ]) setPortfolio(portfolioData) setSummary(summaryData) } catch (error) { console.error('Failed to load portfolio:', error) } finally { setLoading(false) } } const handleAddDomain = async (e: React.FormEvent) => { e.preventDefault() if (!addForm.domain.trim()) return setAddingDomain(true) try { await api.addToPortfolio({ domain: addForm.domain.trim(), purchase_price: addForm.purchase_price ? parseFloat(addForm.purchase_price) : undefined, purchase_date: addForm.purchase_date || undefined, registrar: addForm.registrar || undefined, renewal_date: addForm.renewal_date || undefined, renewal_cost: addForm.renewal_cost ? parseFloat(addForm.renewal_cost) : undefined, notes: addForm.notes || undefined, }) showToast(`Added ${addForm.domain} to portfolio`, 'success') setAddForm({ domain: '', purchase_price: '', purchase_date: '', registrar: '', renewal_date: '', renewal_cost: '', notes: '' }) setShowAddModal(false) loadPortfolio() } catch (err: any) { showToast(err.message || 'Failed to add domain', 'error') } finally { setAddingDomain(false) } } const handleEditDomain = async (e: React.FormEvent) => { e.preventDefault() if (!selectedDomain) return setSavingEdit(true) try { await api.updatePortfolioDomain(selectedDomain.id, { purchase_price: editForm.purchase_price ? parseFloat(editForm.purchase_price) : undefined, purchase_date: editForm.purchase_date || undefined, registrar: editForm.registrar || undefined, renewal_date: editForm.renewal_date || undefined, renewal_cost: editForm.renewal_cost ? parseFloat(editForm.renewal_cost) : undefined, notes: editForm.notes || undefined, }) showToast('Domain updated', 'success') setShowEditModal(false) loadPortfolio() } catch (err: any) { showToast(err.message || 'Failed to update', 'error') } finally { setSavingEdit(false) } } const handleSellDomain = async (e: React.FormEvent) => { e.preventDefault() if (!selectedDomain || !sellForm.sale_price) return setProcessingSale(true) try { await api.markAsSold(selectedDomain.id, { sale_date: sellForm.sale_date, sale_price: parseFloat(sellForm.sale_price), }) showToast(`Marked ${selectedDomain.domain} as sold`, 'success') setShowSellModal(false) loadPortfolio() } catch (err: any) { showToast(err.message || 'Failed to process sale', 'error') } finally { setProcessingSale(false) } } const handleValuate = async (domain: PortfolioDomain) => { setValuatingDomain(domain.domain) setShowValuationModal(true) try { const result = await api.getValuation(domain.domain) setValuation(result) } catch (err: any) { showToast(err.message || 'Failed to get valuation', 'error') setShowValuationModal(false) } finally { setValuatingDomain('') } } const handleRefresh = async (domain: PortfolioDomain) => { setRefreshingId(domain.id) try { await api.refreshPortfolioValuation(domain.id) showToast('Valuation refreshed', 'success') loadPortfolio() } catch (err: any) { showToast(err.message || 'Failed to refresh', 'error') } finally { setRefreshingId(null) } } const handleDelete = async (domain: PortfolioDomain) => { if (!confirm(`Remove ${domain.domain} from your portfolio?`)) return try { await api.removeFromPortfolio(domain.id) showToast(`Removed ${domain.domain}`, 'success') loadPortfolio() } catch (err: any) { showToast(err.message || 'Failed to remove', 'error') } } const openEditModal = (domain: PortfolioDomain) => { setSelectedDomain(domain) setEditForm({ purchase_price: domain.purchase_price?.toString() || '', purchase_date: domain.purchase_date || '', registrar: domain.registrar || '', renewal_date: domain.renewal_date || '', renewal_cost: domain.renewal_cost?.toString() || '', notes: domain.notes || '', }) setShowEditModal(true) } const openSellModal = (domain: PortfolioDomain) => { setSelectedDomain(domain) setSellForm({ sale_date: new Date().toISOString().split('T')[0], sale_price: '', }) setShowSellModal(true) } const portfolioLimit = subscription?.portfolio_limit || 0 const canAddMore = portfolioLimit === -1 || portfolio.length < portfolioLimit // Dynamic subtitle const getSubtitle = () => { if (loading) return 'Loading your portfolio...' if (portfolio.length === 0) return 'Start tracking your domain investments' const profit = summary?.total_profit || 0 if (profit > 0) return `${portfolio.length} domains • +$${profit.toLocaleString()} profit` if (profit < 0) return `${portfolio.length} domains • -$${Math.abs(profit).toLocaleString()} loss` return `Managing ${portfolio.length} domain${portfolio.length !== 1 ? 's' : ''}` } return ( setShowAddModal(true)} disabled={!canAddMore} className="flex items-center gap-2 h-9 px-4 bg-gradient-to-r from-accent to-accent/80 text-background rounded-lg font-medium text-sm hover:shadow-[0_0_20px_-5px_rgba(16,185,129,0.4)] transition-all disabled:opacity-50 disabled:cursor-not-allowed" > Add Domain } > {toast && } {/* Summary Stats */}
= 0 ? '+' : ''}$${(summary?.total_profit || 0).toLocaleString()}`} icon={PiggyBank} accent={(summary?.total_profit || 0) >= 0} />
{!canAddMore && (

You've reached your portfolio limit. Upgrade to add more.

Upgrade
)} {/* Portfolio Table */} d.id} loading={loading} emptyIcon={} emptyTitle="Your portfolio is empty" emptyDescription="Add your first domain to start tracking investments" columns={[ { key: 'domain', header: 'Domain', render: (domain) => (
{domain.domain} {domain.registrar && (

{domain.registrar}

)}
), }, { key: 'purchase', header: 'Purchase', hideOnMobile: true, render: (domain) => (
{domain.purchase_price && ( ${domain.purchase_price.toLocaleString()} )} {domain.purchase_date && (

{new Date(domain.purchase_date).toLocaleDateString()}

)}
), }, { key: 'valuation', header: 'Est. Value', align: 'right', render: (domain) => ( domain.current_valuation ? ( ${domain.current_valuation.toLocaleString()} ) : ( ) ), }, { key: 'renewal', header: 'Renewal', hideOnMobile: true, hideOnTablet: true, render: (domain) => ( domain.renewal_date ? ( {new Date(domain.renewal_date).toLocaleDateString()} ) : ( ) ), }, { key: 'actions', header: '', align: 'right', render: (domain) => (
handleValuate(domain)} title="Get valuation" /> handleRefresh(domain)} loading={refreshingId === domain.id} title="Refresh valuation" /> openEditModal(domain)} title="Edit" /> handleDelete(domain)} variant="danger" title="Remove" />
), }, ]} />
{/* Add Modal */} {showAddModal && ( setShowAddModal(false)}>
setAddForm({ ...addForm, domain: e.target.value })} placeholder="example.com" className="w-full h-11 px-4 bg-background border border-border/50 rounded-xl text-foreground focus:outline-none focus:border-accent/50 transition-all" required />
setAddForm({ ...addForm, purchase_price: e.target.value })} placeholder="100" className="w-full h-11 px-4 bg-background border border-border/50 rounded-xl text-foreground focus:outline-none focus:border-accent/50" />
setAddForm({ ...addForm, purchase_date: e.target.value })} className="w-full h-11 px-4 bg-background border border-border/50 rounded-xl text-foreground focus:outline-none focus:border-accent/50" />
setAddForm({ ...addForm, registrar: e.target.value })} placeholder="Namecheap" className="w-full h-11 px-4 bg-background border border-border/50 rounded-xl text-foreground focus:outline-none focus:border-accent/50" />
)} {/* Edit Modal */} {showEditModal && selectedDomain && ( setShowEditModal(false)}>
setEditForm({ ...editForm, purchase_price: e.target.value })} className="w-full h-11 px-4 bg-background border border-border/50 rounded-xl text-foreground focus:outline-none focus:border-accent/50" />
setEditForm({ ...editForm, registrar: e.target.value })} className="w-full h-11 px-4 bg-background border border-border/50 rounded-xl text-foreground focus:outline-none focus:border-accent/50" />
)} {/* Sell Modal */} {showSellModal && selectedDomain && ( setShowSellModal(false)}>
setSellForm({ ...sellForm, sale_price: e.target.value })} placeholder="1000" className="w-full h-11 px-4 bg-background border border-border/50 rounded-xl text-foreground focus:outline-none focus:border-accent/50" required />
setSellForm({ ...sellForm, sale_date: e.target.value })} className="w-full h-11 px-4 bg-background border border-border/50 rounded-xl text-foreground focus:outline-none focus:border-accent/50" />
)} {/* Valuation Modal */} {showValuationModal && ( { setShowValuationModal(false); setValuation(null); }}> {valuatingDomain ? (
) : valuation ? (

${valuation.estimated_value.toLocaleString()}

Estimated Value

Confidence {valuation.confidence}
Formula {valuation.valuation_formula}
) : null}
)}
) } // Modal Component function Modal({ title, children, onClose }: { title: string; children: React.ReactNode; onClose: () => void }) { return (
e.stopPropagation()} >

{title}

{children}
) }