diff --git a/frontend/src/app/terminal/intel/[tld]/page.tsx b/frontend/src/app/terminal/intel/[tld]/page.tsx
index 49fc144..a720dc0 100644
--- a/frontend/src/app/terminal/intel/[tld]/page.tsx
+++ b/frontend/src/app/terminal/intel/[tld]/page.tsx
@@ -2,7 +2,7 @@
import { useEffect, useState, useMemo, useRef, useCallback, memo } from 'react'
import { useParams, useRouter } from 'next/navigation'
-import { TerminalLayout } from '@/components/TerminalLayout'
+import { CommandCenterLayout } from '@/components/CommandCenterLayout'
import { useStore } from '@/lib/store'
import { api } from '@/lib/api'
import {
@@ -29,13 +29,14 @@ import {
Lock,
Sparkles,
Diamond,
- Activity
+ Activity,
+ Zap
} from 'lucide-react'
import Link from 'next/link'
import clsx from 'clsx'
// ============================================================================
-// TIER ACCESS LEVELS
+// TYPES & HELPERS
// ============================================================================
type UserTier = 'scout' | 'trader' | 'tycoon'
@@ -50,87 +51,6 @@ function getTierLevel(tier: UserTier): number {
}
}
-// ============================================================================
-// SHARED COMPONENTS (Synced with Overview)
-// ============================================================================
-
-const Tooltip = memo(({ children, content }: { children: React.ReactNode; content: string }) => (
-
-))
-Tooltip.displayName = 'Tooltip'
-
-// EXACT COPY OF STATCARD FROM INTEL PAGE (Modified for flexibility)
-const StatCard = memo(({
- label,
- value,
- subValue,
- icon: Icon,
- highlight,
- locked = false,
- lockTooltip,
- valueClassName
-}: {
- label: string
- value: string | number
- subValue?: string
- icon: any
- highlight?: boolean
- locked?: boolean
- lockTooltip?: string
- valueClassName?: string
-}) => (
-
- {/* Icon Top Right (Absolute) */}
-
-
-
-
-
- {/* Label & Small Icon */}
-
-
- {label}
-
-
- {locked ? (
-
-
-
- —
-
-
- ) : (
-
-
- {value}
-
- {subValue &&
{subValue}}
-
- )}
-
- {highlight && (
-
- ● LIVE
-
- )}
-
-
-))
-StatCard.displayName = 'StatCard'
-
-// ============================================================================
-// TYPES & DATA
-// ============================================================================
-
interface TldDetails {
tld: string
type: string
@@ -139,11 +59,7 @@ interface TldDetails {
introduced: number
trend: string
trend_reason: string
- pricing: {
- avg: number
- min: number
- max: number
- }
+ pricing: { avg: number; min: number; max: number }
registrars: Array<{
name: string
registration_price: number
@@ -166,10 +82,7 @@ interface TldHistory {
price_change_90d: number
trend: string
trend_reason: string
- history: Array<{
- date: string
- price: number
- }>
+ history: Array<{ date: string; price: number }>
}
interface DomainCheckResult {
@@ -192,7 +105,7 @@ const REGISTRAR_URLS: Record = {
}
// ============================================================================
-// SUB-COMPONENTS
+// CHART COMPONENT
// ============================================================================
function PriceChart({
@@ -207,8 +120,8 @@ function PriceChart({
if (data.length === 0) {
return (
-
-
+
+
No price history available
)
@@ -258,25 +171,22 @@ function PriceChart({
{hoveredIndex !== null && points[hoveredIndex] && (
-
-
-
+
)}
- {/* Hover Dot (HTML overlay to avoid SVG scaling distortion) */}
{hoveredIndex !== null && points[hoveredIndex] && (
)}
- {/* Chart Tooltip */}
{hoveredIndex !== null && points[hoveredIndex] && (
- ${points[hoveredIndex].price.toFixed(2)}
- {new Date(points[hoveredIndex].date).toLocaleDateString()}
+ ${points[hoveredIndex].price.toFixed(2)}
+ {new Date(points[hoveredIndex].date).toLocaleDateString()}
-
)}
)
}
-function LockedChartOverlay({ onUpgrade }: { onUpgrade: () => void }) {
- return (
-
-
-
-
-
Detailed History Locked
-
- Upgrade to Trader to access detailed price charts and historical data.
-
-
-
- )
-}
-
// ============================================================================
// MAIN PAGE
// ============================================================================
-export default function CommandTldDetailPage() {
+export default function TldDetailPage() {
const params = useParams()
const router = useRouter()
const { fetchSubscription, subscription } = useStore()
const tld = params.tld as string
- // Determine user tier
const userTier: UserTier = (subscription?.tier as UserTier) || 'scout'
const tierLevel = getTierLevel(userTier)
- // Feature access checks
- const canAccessDetailPage = tierLevel >= 2 // Trader+
- const canSeeRenewal = tierLevel >= 2 // Trader+
- const canSeeFullHistory = tierLevel >= 3 // Tycoon only
+ const canAccessDetailPage = tierLevel >= 2
+ const canSeeRenewal = tierLevel >= 2
+ const canSeeFullHistory = tierLevel >= 3
- // Available chart periods based on tier
const availablePeriods: ChartPeriod[] = useMemo(() => {
if (tierLevel >= 3) return ['1M', '3M', '1Y', 'ALL']
- if (tierLevel >= 2) return ['1Y'] // Trader gets only 1Y
- return [] // Scout gets no chart
+ if (tierLevel >= 2) return ['1Y']
+ return []
}, [tierLevel])
const [details, setDetails] = useState(null)
@@ -360,9 +244,7 @@ export default function CommandTldDetailPage() {
useEffect(() => {
fetchSubscription()
- if (tld) {
- loadData()
- }
+ if (tld) loadData()
}, [tld, fetchSubscription])
const loadData = async () => {
@@ -377,7 +259,6 @@ export default function CommandTldDetailPage() {
const sortedRegistrars = [...(compareData.registrars || [])].sort((a, b) =>
a.registration_price - b.registration_price
)
-
const tldFromOverview = overviewData?.tlds?.[0]
setDetails({
@@ -415,17 +296,14 @@ export default function CommandTldDetailPage() {
const filteredHistory = useMemo(() => {
if (!history?.history) return []
-
const now = new Date()
let cutoffDays = 365
-
switch (chartPeriod) {
case '1M': cutoffDays = 30; break
case '3M': cutoffDays = 90; break
case '1Y': cutoffDays = 365; break
case 'ALL': cutoffDays = 9999; break
}
-
const cutoff = new Date(now.getTime() - cutoffDays * 24 * 60 * 60 * 1000)
return history.history.filter(h => new Date(h.date) >= cutoff)
}, [history, chartPeriod])
@@ -442,10 +320,8 @@ export default function CommandTldDetailPage() {
const handleDomainCheck = async () => {
if (!domainSearch.trim()) return
-
setCheckingDomain(true)
setDomainResult(null)
-
try {
const domain = domainSearch.includes('.') ? domainSearch : `${domainSearch}.${tld}`
const result = await api.checkDomain(domain, false)
@@ -475,404 +351,406 @@ export default function CommandTldDetailPage() {
if (!details?.registrars?.length) return null
const cheapest = details.registrars[0]
const ratio = cheapest.renewal_price / cheapest.registration_price
- return {
- registration: cheapest.registration_price,
- renewal: cheapest.renewal_price,
- ratio,
- isTrap: ratio > 2,
- }
+ return { registration: cheapest.registration_price, renewal: cheapest.renewal_price, ratio, isTrap: ratio > 2 }
}
const renewalInfo = getRenewalInfo()
- const getRiskBadge = () => {
- if (!details) return null
- const level = details.risk_level
- const reason = details.risk_reason
- return (
-
-
-
- {level} Risk
-
-
- )
- }
-
- const handleUpgrade = useCallback(() => {
- router.push('/pricing')
- }, [router])
-
if (loading) {
return (
-
+
-
-
-
+
+
+
)
}
if (error || !details) {
return (
-
-
-
-
TLD Not Found
-
The extension .{tld} is not currently tracked.
-
-
Back to Intelligence
-
-
-
+
+
+
+
TLD Not Found
+
The extension .{tld} is not currently tracked.
+
+
Back to Intel
+
+
+
)
}
return (
-
-
-
- {/* Ambient Background Glow (Consistent with Overview) */}
-
-
-
-
- {/* Header Section */}
-
-
- {/* Breadcrumb */}
-
-
-
-
-
-
-
- .{details.tld}
-
- {getRiskBadge()}
-
-
- {details.description}
-
-
-
-
+
+ {/* ═══════════════════════════════════════════════════════════════════════ */}
+ {/* HEADER */}
+ {/* ═══════════════════════════════════════════════════════════════════════ */}
+
+
+
+ {/* Breadcrumb */}
+
-
- {/* Tier Badge */}
-
-
- {userTier === 'tycoon' ? 'Tycoon Access' : userTier === 'trader' ? 'Trader Access' : 'Scout Access'}
+
+
+
+
+
+ .{details.tld}
+
+ {/* Risk Badge */}
+
+ {details.risk_level} risk
+
+
+
{details.description}
-
- {/* Metric Grid */}
-
-
-
- 0 ? '+' : ''}${details.price_change_1y.toFixed(0)}%`}
- subValue="Volatility"
- icon={details.price_change_1y > 0 ? TrendingUp : TrendingDown}
- valueClassName={
- details.price_change_1y > 5 ? "text-orange-400" :
- details.price_change_1y < -5 ? "text-emerald-400" :
- "text-zinc-400"
- }
- />
- 0 ? '+' : ''}${details.price_change_3y.toFixed(0)}%` : '—'}
- subValue={canSeeFullHistory ? "Long-term" : undefined}
- icon={BarChart3}
- locked={!canSeeFullHistory}
- lockTooltip="Upgrade to Tycoon for 3-year trends"
- valueClassName={
- canSeeFullHistory && details.price_change_3y > 10 ? "text-orange-400" :
- canSeeFullHistory && details.price_change_3y < -10 ? "text-emerald-400" :
- "text-zinc-400"
- }
- />
-
-
-
-
- {/* Left Column: Chart & Info */}
-
-
- {/* Price History Chart */}
-
-
-
- {/* Lock overlay for Scout users */}
- {!canAccessDetailPage &&
}
-
-
-
-
-
- Price History
-
-
Historical registration price trends
-
-
- {(['1M', '3M', '1Y', 'ALL'] as ChartPeriod[]).map((period) => {
- const isAvailable = availablePeriods.includes(period)
- const isActive = chartPeriod === period && isAvailable
- return (
-
-
-
- )
- })}
-
-
-
-
-
-
-
High
-
${chartStats.high.toFixed(2)}
-
-
-
Average
-
${chartStats.avg.toFixed(2)}
-
-
-
Low
-
${chartStats.low.toFixed(2)}
-
-
-
-
- {/* Quick Check Bar */}
-
-
-
-
-
-
- Check Availability
-
-
Instantly check if your desired .{details.tld} domain is available.
-
-
-
-
- setDomainSearch(e.target.value)}
- onKeyDown={(e) => e.key === 'Enter' && handleDomainCheck()}
- placeholder={`example.${details.tld}`}
- className="w-full h-12 bg-black/50 border border-white/10 rounded-lg pl-4 pr-4 text-white placeholder:text-zinc-600 focus:outline-none focus:border-emerald-500/50 focus:ring-1 focus:ring-emerald-500/50 transition-all font-mono"
- />
-
-
-
-
-
- {/* Check Result */}
- {domainResult && (
-
+
-
- {domainResult.is_available ? (
-
- ) : (
-
+
+ {userTier}
+
+
+
+
+
+ {/* ═══════════════════════════════════════════════════════════════════════ */}
+ {/* STATS GRID */}
+ {/* ═══════════════════════════════════════════════════════════════════════ */}
+
+
+ {/* Registration */}
+
+
+
+ Registration
+
+
${details.pricing.min.toFixed(2)}
+
at {details.cheapest_registrar}
+
+
+ {/* Renewal */}
+
+
+
+ Renewal
+
+ {canSeeRenewal ? (
+ <>
+
+ ${details.min_renewal_price.toFixed(2)}
+
+ {renewalInfo?.isTrap && (
+
{renewalInfo.ratio.toFixed(1)}x markup
)}
+ >
+ ) : (
+
+
+ —
+
+ )}
+
+
+ {/* 1Y Trend */}
+
+
+ {details.price_change_1y > 0 ? : }
+ 1Y Trend
+
+
5 ? "text-orange-400" :
+ details.price_change_1y < -5 ? "text-accent" :
+ "text-white/40"
+ )}>
+ {details.price_change_1y > 0 ? '+' : ''}{details.price_change_1y.toFixed(0)}%
+
+
+
+ {/* 3Y Trend */}
+
+
+
+ 3Y Trend
+
+ {canSeeFullHistory ? (
+
10 ? "text-orange-400" :
+ details.price_change_3y < -10 ? "text-accent" :
+ "text-white/40"
+ )}>
+ {details.price_change_3y > 0 ? '+' : ''}{details.price_change_3y.toFixed(0)}%
+
+ ) : (
+
+
+ —
+
+ )}
+
+
+
+
+ {/* ═══════════════════════════════════════════════════════════════════════ */}
+ {/* MAIN CONTENT */}
+ {/* ═══════════════════════════════════════════════════════════════════════ */}
+
+
+
+ {/* Left Column: Chart + Search */}
+
+
+ {/* Price Chart */}
+
+ {/* Lock overlay for Scout */}
+ {!canAccessDetailPage && (
+
+
+
+
+
Charts Locked
+
+ Upgrade to Trader for detailed price history.
+
+
+
+ Unlock
+
+
+ )}
+
+
-
{domainResult.domain}
-
- {domainResult.is_available ? 'Available for registration' : 'Already Registered'}
-
+
Price History
+
+
+ {(['1M', '3M', '1Y', 'ALL'] as ChartPeriod[]).map((period) => {
+ const isAvailable = availablePeriods.includes(period)
+ const isActive = chartPeriod === period && isAvailable
+ return (
+
+ )
+ })}
- {domainResult.is_available && (
-
- Buy at {details.cheapest_registrar}
-
- )}
-
-
- )}
-
-
- {/* TLD Info Cards */}
-
-
-
-
-
Type
+
+
+
+
+
High
+
${chartStats.high.toFixed(2)}
+
+
+
Average
+
${chartStats.avg.toFixed(2)}
+
+
+
Low
+
${chartStats.low.toFixed(2)}
+
-
{details.type}
-
-
-
- Registry
-
-
{details.registry}
-
+
+ {/* Domain Check */}
+
+
+
+
+
+ Check Availability
+
+
Check if your .{details.tld} domain is available
-
-
- {/* Right Column: Registrars Table */}
-
-
-
Registrar Prices
-
Live comparison sorted by price
+
+ setDomainSearch(e.target.value)}
+ onKeyDown={(e) => e.key === 'Enter' && handleDomainCheck()}
+ placeholder={`example.${details.tld}`}
+ className="flex-1 h-10 bg-white/5 border border-white/10 px-4 text-white placeholder:text-white/25 outline-none focus:border-accent/50 font-mono text-sm"
+ />
+
+
-
-
-
-
-
- | Registrar |
- Reg |
-
- {canSeeRenewal ? 'Renew' : (
-
-
- Renew
-
-
- )}
- |
- |
-
-
-
- {details.registrars.map((registrar, idx) => {
- const hasRenewalTrap = registrar.renewal_price / registrar.registration_price > 1.5
- const isBest = idx === 0 && !hasRenewalTrap
-
- return (
-
- |
- {registrar.name}
- {isBest && Best Value}
- {idx === 0 && hasRenewalTrap && canSeeRenewal && Renewal Trap}
- |
-
-
- ${registrar.registration_price.toFixed(2)}
-
- |
-
- {canSeeRenewal ? (
-
- ${registrar.renewal_price.toFixed(2)}
-
- ) : (
- —
- )}
- |
-
-
-
-
- |
-
- )
- })}
-
-
-
-
- {/* Upgrade CTA for Scout users */}
- {userTier === 'scout' && (
-
-
-
- Upgrade to see renewal prices
-
-
- )}
+
+ {domainResult && (
+
+
+
+ {domainResult.is_available ? (
+
+
+
+ ) : (
+
+
+
+ )}
+
+
{domainResult.domain}
+
+ {domainResult.is_available ? 'Available' : 'Registered'}
+
+
+
+
+ {domainResult.is_available && (
+
+ Buy at {details.cheapest_registrar}
+
+
+ )}
+
+
+ )}
+ {/* Info Cards */}
+
+
+
+
+ Type
+
+
{details.type}
+
+
+
+
+ Registry
+
+
{details.registry}
+
+
+ {/* Right Column: Registrars */}
+
+
+
Registrar Prices
+
+
+
+ {details.registrars.map((registrar, idx) => {
+ const hasRenewalTrap = registrar.renewal_price / registrar.registration_price > 1.5
+ const isBest = idx === 0 && !hasRenewalTrap
+
+ return (
+
+
+
+
{registrar.name}
+ {isBest &&
Best Value}
+ {idx === 0 && hasRenewalTrap && canSeeRenewal && (
+
Renewal Trap
+ )}
+
+
+
+ ${registrar.registration_price.toFixed(2)}
+
+ {canSeeRenewal && (
+
+ ${registrar.renewal_price.toFixed(2)}/yr
+
+ )}
+
+
+
+ Visit
+
+
+
+ )
+ })}
+
+
+ {userTier === 'scout' && (
+
+
+
+ Upgrade for renewal prices
+
+
+ )}
+
-
-
+
+
)
}