diff --git a/frontend/src/app/terminal/portfolio/page.tsx b/frontend/src/app/terminal/portfolio/page.tsx
index cb912dd..2c15be6 100755
--- a/frontend/src/app/terminal/portfolio/page.tsx
+++ b/frontend/src/app/terminal/portfolio/page.tsx
@@ -169,18 +169,18 @@ export default function PortfolioPage() {
api.checkDomain(domain.domain)
.then(() => {
// Simulate health report - in production this would come from backend
- setHealthReports(prev => ({
- ...prev,
- [domain.id]: {
- domain_id: domain.id,
- checked_at: new Date().toISOString(),
- score: Math.floor(Math.random() * 40) + 60, // Simulated score 60-100
- status: 'healthy' as HealthStatus,
- dns: { has_a: true, has_ns: true, is_parked: false },
- http: { is_reachable: true, status_code: 200, is_parked: false },
- ssl: { has_certificate: true },
- } as DomainHealthReport
- }))
+ const simulatedReport: DomainHealthReport = {
+ domain: domain.domain,
+ checked_at: new Date().toISOString(),
+ score: Math.floor(Math.random() * 40) + 60, // Simulated score 60-100
+ status: 'healthy' as HealthStatus,
+ signals: [],
+ recommendations: [],
+ dns: { has_a: true, has_ns: true, has_mx: false, nameservers: [], is_parked: false },
+ http: { is_reachable: true, status_code: 200, is_parked: false },
+ ssl: { has_certificate: true },
+ }
+ setHealthReports(prev => ({ ...prev, [domain.id]: simulatedReport }))
})
.catch(() => {})
.finally(() => {
@@ -195,18 +195,18 @@ export default function PortfolioPage() {
try {
await api.checkDomain(domainName)
// Simulated - in production, this would return real health data
- setHealthReports(prev => ({
- ...prev,
- [domainId]: {
- domain_id: domainId,
- checked_at: new Date().toISOString(),
- score: Math.floor(Math.random() * 40) + 60,
- status: 'healthy' as HealthStatus,
- dns: { has_a: true, has_ns: true, is_parked: false },
- http: { is_reachable: true, status_code: 200, is_parked: false },
- ssl: { has_certificate: true },
- } as DomainHealthReport
- }))
+ const simulatedReport: DomainHealthReport = {
+ domain: domainName,
+ checked_at: new Date().toISOString(),
+ score: Math.floor(Math.random() * 40) + 60,
+ status: 'healthy' as HealthStatus,
+ signals: [],
+ recommendations: [],
+ dns: { has_a: true, has_ns: true, has_mx: false, nameservers: [], is_parked: false },
+ http: { is_reachable: true, status_code: 200, is_parked: false },
+ ssl: { has_certificate: true },
+ }
+ setHealthReports(prev => ({ ...prev, [domainId]: simulatedReport }))
showToast('Health check complete', 'success')
} catch {
showToast('Health check failed', 'error')
@@ -388,14 +388,14 @@ export default function PortfolioPage() {
{stats.total} domains
-
-
+
+
{/* Stats Grid - Extended with Health */}
{formatCurrency(summary?.total_value || 0).replace('$', '').slice(0, 6)}
Value
@@ -485,7 +485,7 @@ export default function PortfolioPage() {
{item.label} ({item.count})
))}
-
+
{/* Add Domain Button - RIGHT */}
{isRenewingSoon ? `${daysUntilRenewal}d` : formatDate(domain.renewal_date)}
-
+
- )}
-
+ )}
+
{/* Alert Toggles - Mobile */}
-
+ )
)}
setSelectedDomain(domain)}
@@ -718,19 +718,19 @@ export default function PortfolioPage() {
return
}
if (!health) {
- return (
- handleRefreshHealth(domain.id, domain.domain)}
className="text-white/30 hover:text-white"
title="Run health check"
- >
+ >
-
- )
+
+ )
}
const config = healthConfig[health.status]
return (
-
setShowHealthDetail(domain.id)}
className={clsx("flex items-center gap-1 px-1.5 py-0.5 text-[10px] font-mono border", config.bg, config.color)}
title={`Score: ${health.score}/100`}
@@ -739,7 +739,7 @@ export default function PortfolioPage() {
health.status === 'critical' ? :
}
{health.score}
-
+
)
})()
) : (
@@ -782,15 +782,15 @@ export default function PortfolioPage() {
—
) : (
<>
-
handleToggleEmailAlert(domain.id, false)}
disabled={togglingAlerts[domain.id]}
className="w-6 h-6 flex items-center justify-center text-white/30 hover:text-accent border border-transparent hover:border-accent/20 transition-all"
title="Email alerts"
>
-
-
+ handleToggleSmsAlert(domain.id, false)}
disabled={togglingAlerts[domain.id] || !canUseSmsAlerts}
className={clsx(
@@ -802,7 +802,7 @@ export default function PortfolioPage() {
title={canUseSmsAlerts ? "SMS alerts" : "SMS alerts require Tycoon"}
>
{canUseSmsAlerts ? : }
-
+
>
)}
@@ -834,12 +834,12 @@ export default function PortfolioPage() {
{!domain.is_sold && (
domain.is_dns_verified ? (
canListForSale && (
-
+ >
Sell
-
+
)
) : (
- setSelectedDomain(domain)}
title="Edit Details"
className="w-7 h-7 flex items-center justify-center text-white/30 hover:text-white border border-transparent hover:border-white/10 hover:bg-white/5 transition-all rounded-sm"
- >
+ >
-
-
+ handleRefreshValue(domain.id)}
disabled={refreshingId === domain.id}
title="Refresh Valuation"
@@ -875,8 +875,8 @@ export default function PortfolioPage() {
className="w-7 h-7 flex items-center justify-center text-white/30 hover:text-rose-400 border border-transparent hover:border-rose-400/20 hover:bg-rose-500/10 transition-all rounded-sm disabled:opacity-30"
>
{deletingId === domain.id ? : }
-
-
+
+
@@ -900,7 +900,7 @@ export default function PortfolioPage() {
setMenuOpen(true)} className="flex-1 flex flex-col items-center justify-center gap-0.5 text-white/40">
Menu
-
+
{/* MOBILE DRAWER */}
@@ -930,7 +930,7 @@ export default function PortfolioPage() {
+
setShowHealthDetail(null)} className="w-8 h-8 flex items-center justify-center border border-white/10 text-white/40 hover:text-white">
@@ -943,8 +943,8 @@ export default function PortfolioPage() {
{health.score}
{config.label}
-
-
+
+
{/* Health Checks */}
@@ -954,7 +954,7 @@ export default function PortfolioPage() {
DNS Resolution
-
+
{health.dns?.has_a || health.dns?.has_ns ? (
OK
) : (
@@ -1002,12 +1002,12 @@ export default function PortfolioPage() {
{/* Last Check */}
Last checked: {formatTimeAgo(health.checked_at)}
- { handleRefreshHealth(domain.id, domain.domain); setShowHealthDetail(null) }}
className="text-accent hover:underline"
- >
+ >
Refresh
-
+
@@ -1046,7 +1046,7 @@ export default function PortfolioPage() {
1
Point your nameservers to ns.pounce.ch
-
+
2
We analyze visitor intent and route traffic
@@ -1058,20 +1058,20 @@ export default function PortfolioPage() {
- setShowYieldModal(null)}
className="w-full py-3 bg-white/5 border border-white/10 text-white/40 text-sm font-mono"
>
Notify me when available
-
-
+
+
)}
{toast && }
-
+
)
}
@@ -1121,18 +1121,18 @@ function AddDomainModal({ onClose, onSuccess }: { onClose: () => void; onSuccess
)
@@ -1205,30 +1205,30 @@ function DomainDetailModal({ domain, onClose, onUpdate, canListForSale }: { doma
+
{/* Domain Header */}
{domain.domain}
{domain.registrar || 'Unknown registrar'}
-
+
{/* Stats Grid */}
{formatCurrency(domain.purchase_price)}
Purchased
-
+
{formatCurrency(domain.estimated_value)}
Est. Value
-
+
= 0 ? "bg-accent/[0.05] border-accent/20" : "bg-rose-500/[0.05] border-rose-500/20")}>
= 0 ? "text-accent" : "text-rose-400")}>{formatROI(domain.roi)}
ROI
+
-
{/* Dates */}
@@ -1310,13 +1310,13 @@ function SellModal({ onClose, onConfirm }: { onClose: () => void; onConfirm: (da
setSaleDate(e.target.value)}
className="w-full px-3 py-2.5 bg-white/5 border border-white/10 text-white text-sm font-mono outline-none focus:border-accent/50" />
-
-
+
+
setSalePrice(e.target.value)} min="0" required
className="w-full px-3 py-2.5 bg-white/5 border border-white/10 text-white text-sm font-mono outline-none focus:border-accent/50" placeholder="0" />
+
-
Cancel
onConfirm(saleDate, parseFloat(salePrice) || 0)} disabled={!salePrice} className="flex-1 py-2.5 bg-accent text-black text-xs font-bold uppercase disabled:opacity-50">Confirm
@@ -1336,12 +1336,12 @@ function MobileDrawer({ user, tierName, TierIcon, sections, onClose, onLogout }:
{sections.map((section: any) => (
@@ -1352,23 +1352,23 @@ function MobileDrawer({ user, tierName, TierIcon, sections, onClose, onLogout }:
{item.isNew && NEW}
))}
-
+
))}
Settings
{user?.is_admin && Admin}
-
+
{user?.name || user?.email?.split('@')[0] || 'User'}
{tierName}
-
+
{tierName === 'Scout' && Upgrade}
Sign out
-
-
-
+
+
+
)
}
@@ -1438,18 +1438,18 @@ function DnsVerificationModal({ domain, onClose, onSuccess }: { domain: Portfoli
Verify Domain Ownership
-
+
-
+
{/* Domain Header */}
{domain.domain}
DNS Verification Required
-
+
{step === 'loading' && (
@@ -1462,20 +1462,20 @@ function DnsVerificationModal({ domain, onClose, onSuccess }: { domain: Portfoli
{/* Instructions */}
Add this TXT record to your DNS:
-
-
+
+
Host / Name
_pounce
handleCopy('_pounce')} className="w-8 h-8 flex items-center justify-center border border-white/10 text-white/40 hover:text-white">
{copied ? : }
-
+
-
Value
@@ -1483,26 +1483,26 @@ function DnsVerificationModal({ domain, onClose, onSuccess }: { domain: Portfoli
handleCopy(verificationData.verification_code)} className="w-8 h-8 flex items-center justify-center border border-white/10 text-white/40 hover:text-white">
{copied ? : }
-
+
-
+
{/* Info */}
DNS changes can take up to 48 hours to propagate, but usually complete within minutes.
-
+
{/* Error/Check Result */}
{error && (
{error}
-
+
)}
{checkResult && (
{checkResult}
-
+
)}
{/* Actions */}
@@ -1512,8 +1512,8 @@ function DnsVerificationModal({ domain, onClose, onSuccess }: { domain: Portfoli
Check Verification
-
-
+
+
>
)}
@@ -1521,7 +1521,7 @@ function DnsVerificationModal({ domain, onClose, onSuccess }: { domain: Portfoli
Checking DNS records...
-
+
)}
{step === 'instructions' && !verificationData && error && (