'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 { Toast, useToast } from '@/components/Toast' import { Plus, Trash2, Edit2, DollarSign, Calendar, Building, RefreshCw, Loader2, TrendingUp, TrendingDown, Tag, ExternalLink, Sparkles, ArrowUpRight, X, } 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 return ( setShowAddModal(true)} disabled={!canAddMore} className="flex items-center gap-2 h-9 px-4 bg-accent text-background rounded-lg font-medium text-sm hover:bg-accent-hover transition-colors disabled:opacity-50 disabled:cursor-not-allowed" > Add Domain } > {toast && }
{/* Summary Stats */} {summary && (

Total Domains

{summary.total_domains}

Total Invested

${summary.total_invested?.toLocaleString() || 0}

Est. Value

${summary.total_value?.toLocaleString() || 0}

= 0 ? "bg-accent/5 border-accent/20" : "bg-red-500/5 border-red-500/20" )}>

Profit/Loss

= 0 ? "text-accent" : "text-red-400" )}> {(summary.total_profit || 0) >= 0 ? '+' : ''}${summary.total_profit?.toLocaleString() || 0}

Sold

{summary.sold_domains || 0}

)} {!canAddMore && (

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

Upgrade
)} {/* Domain List */} {loading ? (
{[...Array(3)].map((_, i) => (
))}
) : portfolio.length === 0 ? (

Your portfolio is empty

Add your first domain to start tracking investments

) : (
{portfolio.map((domain) => (
{/* Domain Info */}

{domain.domain}

{domain.purchase_price && ( Bought: ${domain.purchase_price} )} {domain.registrar && ( {domain.registrar} )} {domain.renewal_date && ( Renews: {new Date(domain.renewal_date).toLocaleDateString()} )}
{/* Valuation */} {domain.current_valuation && (

${domain.current_valuation.toLocaleString()}

Est. Value

)} {/* Actions */}
))}
)}
{/* Add Modal */} {showAddModal && ( setShowAddModal(false)}>
setAddForm({ ...addForm, domain: e.target.value })} placeholder="example.com" className="w-full h-10 px-3 bg-background border border-border rounded-lg text-foreground" required />
setAddForm({ ...addForm, purchase_price: e.target.value })} placeholder="100" className="w-full h-10 px-3 bg-background border border-border rounded-lg text-foreground" />
setAddForm({ ...addForm, purchase_date: e.target.value })} className="w-full h-10 px-3 bg-background border border-border rounded-lg text-foreground" />
setAddForm({ ...addForm, registrar: e.target.value })} placeholder="Namecheap" className="w-full h-10 px-3 bg-background border border-border rounded-lg text-foreground" />
)} {/* Valuation Modal */} {showValuationModal && ( { setShowValuationModal(false); setValuation(null); }}> {valuatingDomain ? (
) : valuation ? (

${valuation.estimated_value.toLocaleString()}

Estimated Value

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

{title}

{children}
) }