fix: Health check API + Portfolio UX improvements
API FIX: - quickHealthCheck now uses POST method (was GET) - Fixes 'int_parsing' error for domain_id PORTFOLIO UX: 1. Health Check now works correctly with POST /domains/health-check 2. Clear separation of List vs Sell: - 'List' button → Opens listing form (marketplace) - 'Sold?' button → Records completed sale (P&L tracking) 3. Improved Valuation Modal: - Shows 'Pounce Score Estimate' instead of just 'Estimated Value' - Color-coded confidence badge (high/medium/low) - Clear disclaimer about algorithmic estimate 4. Record Sale Modal: - Clear explanation of purpose (P&L tracking) - Hint to use 'List' button for marketplace LISTINGS PAGE: - Accepts ?domain= query parameter - Auto-opens create modal with prefilled domain - Seamless flow from Portfolio → List on Marketplace
This commit is contained in:
@ -1,6 +1,7 @@
|
||||
'use client'
|
||||
|
||||
import { useEffect, useState } from 'react'
|
||||
import { useSearchParams } from 'next/navigation'
|
||||
import { useStore } from '@/lib/store'
|
||||
import { api } from '@/lib/api'
|
||||
import { CommandCenterLayout } from '@/components/CommandCenterLayout'
|
||||
@ -61,11 +62,13 @@ interface VerificationInfo {
|
||||
|
||||
export default function MyListingsPage() {
|
||||
const { subscription } = useStore()
|
||||
const searchParams = useSearchParams()
|
||||
const prefillDomain = searchParams.get('domain')
|
||||
|
||||
const [listings, setListings] = useState<Listing[]>([])
|
||||
const [loading, setLoading] = useState(true)
|
||||
|
||||
// Modals
|
||||
// Modals - auto-open if domain is prefilled
|
||||
const [showCreateModal, setShowCreateModal] = useState(false)
|
||||
const [showVerifyModal, setShowVerifyModal] = useState(false)
|
||||
const [selectedListing, setSelectedListing] = useState<Listing | null>(null)
|
||||
@ -89,6 +92,14 @@ export default function MyListingsPage() {
|
||||
loadListings()
|
||||
}, [])
|
||||
|
||||
// Auto-open create modal if domain is prefilled from portfolio
|
||||
useEffect(() => {
|
||||
if (prefillDomain) {
|
||||
setNewListing(prev => ({ ...prev, domain: prefillDomain }))
|
||||
setShowCreateModal(true)
|
||||
}
|
||||
}, [prefillDomain])
|
||||
|
||||
const loadListings = async () => {
|
||||
setLoading(true)
|
||||
try {
|
||||
|
||||
@ -25,6 +25,7 @@ import {
|
||||
Activity,
|
||||
Shield,
|
||||
AlertTriangle,
|
||||
Tag,
|
||||
} from 'lucide-react'
|
||||
|
||||
// Health status configuration
|
||||
@ -447,11 +448,20 @@ export default function PortfolioPage() {
|
||||
onClick={() => openEditModal(domain)}
|
||||
title="Edit"
|
||||
/>
|
||||
<Link
|
||||
href={`/command/listings?domain=${encodeURIComponent(domain.domain)}`}
|
||||
onClick={(e) => e.stopPropagation()}
|
||||
className="px-3 py-2 text-xs font-medium text-accent hover:bg-accent/10 rounded-lg transition-colors flex items-center gap-1"
|
||||
>
|
||||
<Tag className="w-3 h-3" />
|
||||
List
|
||||
</Link>
|
||||
<button
|
||||
onClick={(e) => { e.stopPropagation(); openSellModal(domain) }}
|
||||
className="px-3 py-2 text-xs font-medium text-accent hover:bg-accent/10 rounded-lg transition-colors"
|
||||
className="px-3 py-2 text-xs font-medium text-foreground-muted hover:bg-foreground/5 rounded-lg transition-colors"
|
||||
title="Record a completed sale (for P&L tracking)"
|
||||
>
|
||||
Sell
|
||||
Sold?
|
||||
</button>
|
||||
<TableActionButton
|
||||
icon={Trash2}
|
||||
@ -586,10 +596,14 @@ export default function PortfolioPage() {
|
||||
</Modal>
|
||||
)}
|
||||
|
||||
{/* Sell Modal */}
|
||||
{/* Record Sale Modal - for tracking completed sales */}
|
||||
{showSellModal && selectedDomain && (
|
||||
<Modal title={`Sell ${selectedDomain.domain}`} onClose={() => setShowSellModal(false)}>
|
||||
<Modal title={`Record Sale: ${selectedDomain.domain}`} onClose={() => setShowSellModal(false)}>
|
||||
<form onSubmit={handleSellDomain} className="space-y-4">
|
||||
<div className="p-3 bg-accent/10 border border-accent/20 rounded-lg text-sm text-foreground-muted">
|
||||
<p>Record a completed sale to track your profit/loss. This will mark the domain as sold in your portfolio.</p>
|
||||
<p className="mt-2 text-accent">Want to list it for sale instead? Use the <strong>"List"</strong> button.</p>
|
||||
</div>
|
||||
<div className="grid grid-cols-2 gap-4">
|
||||
<div>
|
||||
<label className="block text-sm text-foreground-muted mb-1.5">Sale Price *</label>
|
||||
@ -647,16 +661,26 @@ export default function PortfolioPage() {
|
||||
<div className="space-y-4">
|
||||
<div className="text-center p-6 bg-accent/5 border border-accent/20 rounded-xl">
|
||||
<p className="text-4xl font-display text-accent">${valuation.estimated_value.toLocaleString()}</p>
|
||||
<p className="text-sm text-foreground-muted mt-1">Estimated Value</p>
|
||||
<p className="text-sm text-foreground-muted mt-1">Pounce Score Estimate</p>
|
||||
</div>
|
||||
<div className="space-y-2 text-sm">
|
||||
<div className="flex justify-between p-3 bg-foreground/5 rounded-lg">
|
||||
<span className="text-foreground-muted">Confidence</span>
|
||||
<span className="text-foreground capitalize font-medium">{valuation.confidence}</span>
|
||||
<div className="flex justify-between items-center p-3 bg-foreground/5 rounded-lg">
|
||||
<span className="text-foreground-muted">Confidence Level</span>
|
||||
<span className={clsx(
|
||||
"px-2 py-0.5 rounded text-xs font-medium capitalize",
|
||||
valuation.confidence === 'high' && "bg-accent/20 text-accent",
|
||||
valuation.confidence === 'medium' && "bg-amber-400/20 text-amber-400",
|
||||
valuation.confidence === 'low' && "bg-foreground/10 text-foreground-muted"
|
||||
)}>
|
||||
{valuation.confidence}
|
||||
</span>
|
||||
</div>
|
||||
<div className="flex justify-between p-3 bg-foreground/5 rounded-lg">
|
||||
<span className="text-foreground-muted">Formula</span>
|
||||
<span className="text-foreground font-mono text-xs">{valuation.valuation_formula}</span>
|
||||
<div className="p-3 bg-foreground/5 rounded-lg">
|
||||
<p className="text-foreground-muted mb-1">Valuation Formula</p>
|
||||
<p className="text-foreground font-mono text-xs break-all">{valuation.valuation_formula}</p>
|
||||
</div>
|
||||
<div className="p-3 bg-amber-400/10 border border-amber-400/20 rounded-lg text-xs text-amber-400">
|
||||
<p>This is an algorithmic estimate based on domain length, TLD, and market patterns. Actual market value may vary.</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@ -385,7 +385,9 @@ class ApiClient {
|
||||
|
||||
// Quick health check for any domain (premium)
|
||||
async quickHealthCheck(domain: string) {
|
||||
return this.request<DomainHealthReport>(`/domains/health-check?domain=${encodeURIComponent(domain)}`)
|
||||
return this.request<DomainHealthReport>(`/domains/health-check?domain=${encodeURIComponent(domain)}`, {
|
||||
method: 'POST',
|
||||
})
|
||||
}
|
||||
|
||||
// TLD Pricing
|
||||
|
||||
Reference in New Issue
Block a user