style: Yield and Listing tables match Auctions styling
Some checks failed
CI / Frontend Lint & Type Check (push) Has been cancelled
CI / Frontend Build (push) Has been cancelled
CI / Backend Lint (push) Has been cancelled
CI / Backend Tests (push) Has been cancelled
CI / Docker Build (push) Has been cancelled
CI / Security Scan (push) Has been cancelled
Deploy / Build & Push Images (push) Has been cancelled
Deploy / Deploy to Server (push) Has been cancelled
Deploy / Notify (push) Has been cancelled

Both tables now have:
- Same border wrapper (border-white/[0.08] bg-[#020202])
- Same header (px-5 py-3, tracking-[0.12em], bg-white/[0.02])
- Same rows (group-hover:bg-white/[0.02])
- Same divide-y divider
- Same action button styling (w-8 h-8 with borders)
- Same hover opacity transitions
- Same empty state styling (larger icons, centered text)
This commit is contained in:
2025-12-18 14:23:24 +01:00
parent 202e615e2b
commit 8d91caefae
2 changed files with 64 additions and 60 deletions

View File

@ -247,26 +247,30 @@ export default function MyListingsPage() {
<Loader2 className="w-6 h-6 text-accent animate-spin" /> <Loader2 className="w-6 h-6 text-accent animate-spin" />
</div> </div>
) : listings.length === 0 ? ( ) : listings.length === 0 ? (
<div className="text-center py-16 border border-dashed border-white/[0.08]"> <div className="text-center py-24 border border-dashed border-white/[0.08] bg-white/[0.01]">
<Tag className="w-8 h-8 text-white/10 mx-auto mb-3" /> <Tag className="w-16 h-16 text-white/5 mx-auto mb-6" />
<p className="text-white/40 text-sm font-mono mb-2">No listings yet</p> <p className="text-white/50 text-sm font-mono uppercase tracking-widest font-bold">No listings yet</p>
<p className="text-white/25 text-xs font-mono mb-4">Create your first listing to start selling</p> <p className="text-white/20 text-xs font-mono mt-3 uppercase tracking-wider max-w-sm mx-auto leading-relaxed">
<button onClick={() => setShowCreateWizard(true)} className="inline-flex items-center gap-2 px-4 py-2 bg-accent text-black text-xs font-bold uppercase"> Create your first listing to start selling domains
</p>
<button onClick={() => setShowCreateWizard(true)} className="mt-6 inline-flex items-center gap-2 px-5 py-3 bg-accent text-black text-xs font-black uppercase tracking-widest hover:bg-white transition-colors">
<Plus className="w-4 h-4" />Create Listing <Plus className="w-4 h-4" />Create Listing
</button> </button>
</div> </div>
) : ( ) : (
<div className="space-y-px bg-white/[0.04] border border-white/[0.08]"> <div className="border border-white/[0.08] bg-[#020202] overflow-hidden">
{/* Header */} {/* Header */}
<div className="hidden lg:grid grid-cols-[1fr_100px_100px_60px_60px_120px] gap-4 px-3 py-2 text-[10px] font-mono text-white/40 uppercase tracking-wider border-b border-white/[0.08]"> <div className="hidden lg:grid grid-cols-[1fr_100px_90px_60px_60px_auto] gap-4 px-5 py-3 text-[10px] font-mono text-white/40 uppercase tracking-[0.12em] border-b border-white/[0.08] bg-white/[0.02]">
<div>Domain</div> <div>Domain</div>
<div className="text-right">Price</div> <div className="text-right">Price</div>
<div className="text-center">Status</div> <div className="text-center">Status</div>
<div className="text-right">Views</div> <div className="text-right">Views</div>
<div className="text-right">Leads</div> <div className="text-right">Leads</div>
<div className="text-right">Actions</div> <div className="text-right pr-1">Actions</div>
</div> </div>
{/* Table Body */}
<div className="divide-y divide-white/[0.04]">
{listings.map((listing) => ( {listings.map((listing) => (
<ListingRow <ListingRow
key={listing.id} key={listing.id}
@ -281,6 +285,7 @@ export default function MyListingsPage() {
/> />
))} ))}
</div> </div>
</div>
)} )}
{!canAddMore && listings.length >= maxListings && ( {!canAddMore && listings.length >= maxListings && (
@ -393,7 +398,7 @@ function ListingRow({
const needsVerification = !listing.is_verified const needsVerification = !listing.is_verified
return ( return (
<div className="bg-[#020202] hover:bg-white/[0.02] transition-all group"> <div className="group transition-all">
{/* Mobile */} {/* Mobile */}
<div className="lg:hidden p-3"> <div className="lg:hidden p-3">
<div className="flex items-center justify-between mb-2"> <div className="flex items-center justify-between mb-2">
@ -457,37 +462,37 @@ function ListingRow({
</div> </div>
{/* Desktop */} {/* Desktop */}
<div className="hidden lg:grid grid-cols-[1fr_100px_100px_60px_60px_120px] gap-4 items-center px-3 py-3"> <div className="hidden lg:grid grid-cols-[1fr_100px_90px_60px_60px_auto] gap-4 items-center px-5 py-3 group-hover:bg-white/[0.02]">
<div className="flex items-center gap-3"> <div className="flex items-center gap-3 min-w-0">
<div> <span className="text-sm font-bold text-white font-mono truncate group-hover:text-accent transition-colors">{listing.domain}</span>
<span className="text-sm font-bold text-white font-mono group-hover:text-accent transition-colors">{listing.domain}</span> <div className="flex items-center gap-2 text-[9px] font-mono text-white/20 uppercase tracking-wider opacity-0 group-hover:opacity-100 transition-opacity">
{isTycoon && <span className="ml-2 px-1 py-0.5 text-[8px] font-mono bg-amber-400/10 text-amber-400 border border-amber-400/20">Featured</span>} {isTycoon && <span className="px-1 py-0.5 bg-amber-400/10 text-amber-400 border border-amber-400/20">Featured</span>}
{!listing.is_verified && <span className="ml-2 text-[9px] text-amber-400/60 font-mono">Unverified</span>} {!listing.is_verified && <span className="text-amber-400/60">Unverified</span>}
</div> </div>
</div> </div>
<div className="text-right text-sm font-bold font-mono text-accent">${listing.asking_price?.toLocaleString() || '—'}</div> <div className="text-right text-sm font-bold font-mono text-accent">${listing.asking_price?.toLocaleString() || '—'}</div>
<div className="flex justify-center"> <div className="flex justify-center">
<span className={clsx("px-2 py-1 text-[9px] font-mono border", <span className={clsx("px-2.5 py-1.5 text-[10px] font-mono font-bold uppercase border",
isActive ? "bg-accent/10 text-accent border-accent/20" : isActive ? "bg-accent/10 text-accent border-accent/20" :
isDraft ? "bg-amber-400/10 text-amber-400 border-amber-400/20" : isDraft ? "bg-amber-400/10 text-amber-400 border-amber-400/20" :
"bg-white/5 text-white/40 border-white/10" "bg-white/5 text-white/40 border-white/10"
)}>{listing.status}</span> )}>{listing.status}</span>
</div> </div>
<div className="text-right text-xs font-mono text-white/60">{listing.view_count}</div> <div className="text-right text-sm font-mono text-white/50">{listing.view_count}</div>
<div className="text-right text-xs font-mono text-white/60">{listing.inquiry_count}</div> <div className="text-right text-sm font-mono text-white/50">{listing.inquiry_count}</div>
<div className="flex items-center justify-end gap-1"> <div className="flex items-center justify-end gap-1 opacity-40 group-hover:opacity-100 transition-all">
{isDraft && needsVerification && ( {isDraft && needsVerification && (
<button onClick={onVerify} className="px-2 py-1 bg-amber-400/10 border border-amber-400/20 text-amber-400 text-[9px] font-mono uppercase hover:bg-amber-400/20 transition-colors"> <button onClick={onVerify} className="h-8 px-3 bg-amber-400/10 border border-amber-400/20 text-amber-400 text-[9px] font-mono uppercase hover:bg-amber-400/20 transition-colors">
Verify Verify
</button> </button>
)} )}
{isDraft && !needsVerification && ( {isDraft && !needsVerification && (
<button onClick={onPublish} className="px-2 py-1 bg-accent text-black text-[9px] font-bold uppercase hover:bg-white transition-colors"> <button onClick={onPublish} className="h-8 px-3 bg-accent text-black text-[9px] font-bold uppercase hover:bg-white transition-colors">
Publish Publish
</button> </button>
)} )}
{isActive && ( {isActive && (
<a href={listing.public_url} target="_blank" className="w-7 h-7 flex items-center justify-center border border-white/10 text-white/30 hover:text-accent"> <a href={listing.public_url} target="_blank" className="w-8 h-8 flex items-center justify-center border border-white/10 text-white/40 hover:text-accent hover:border-accent/20 hover:bg-accent/10 transition-all">
<ExternalLink className="w-3.5 h-3.5" /> <ExternalLink className="w-3.5 h-3.5" />
</a> </a>
)} )}
@ -495,7 +500,7 @@ function ListingRow({
<button <button
type="button" type="button"
onClick={onMarkSold} onClick={onMarkSold}
className="w-7 h-7 flex items-center justify-center border border-white/10 text-white/30 hover:text-accent" className="w-8 h-8 flex items-center justify-center border border-white/10 text-white/40 hover:text-accent hover:border-accent/20 hover:bg-accent/10 transition-all"
title="Mark as sold" title="Mark as sold"
> >
<CheckCircle className="w-3.5 h-3.5" /> <CheckCircle className="w-3.5 h-3.5" />
@ -505,14 +510,14 @@ function ListingRow({
<button <button
type="button" type="button"
onClick={onLeads} onClick={onLeads}
className="w-7 h-7 flex items-center justify-center border border-white/10 text-white/30 hover:text-accent" className="w-8 h-8 flex items-center justify-center border border-white/10 text-white/40 hover:text-accent hover:border-accent/20 hover:bg-accent/10 transition-all"
title="View buyer inquiries" title="View buyer inquiries"
> >
<MessageSquare className="w-3.5 h-3.5" /> <MessageSquare className="w-3.5 h-3.5" />
</button> </button>
)} )}
<button onClick={onDelete} disabled={isDeleting} <button onClick={onDelete} disabled={isDeleting}
className="w-7 h-7 flex items-center justify-center border border-white/10 text-white/30 hover:text-rose-400"> className="w-8 h-8 flex items-center justify-center border border-white/10 text-white/40 hover:text-rose-400 hover:border-rose-400/20 hover:bg-rose-500/10 transition-all">
{isDeleting ? <Loader2 className="w-3.5 h-3.5 animate-spin" /> : <Trash2 className="w-3.5 h-3.5" />} {isDeleting ? <Loader2 className="w-3.5 h-3.5 animate-spin" /> : <Trash2 className="w-3.5 h-3.5" />}
</button> </button>
</div> </div>

View File

@ -614,15 +614,17 @@ export default function YieldPage() {
<Loader2 className="w-6 h-6 text-accent animate-spin" /> <Loader2 className="w-6 h-6 text-accent animate-spin" />
</div> </div>
) : !dashboard?.domains?.length ? ( ) : !dashboard?.domains?.length ? (
<div className="text-center py-16 border border-dashed border-white/[0.08]"> <div className="text-center py-24 border border-dashed border-white/[0.08] bg-white/[0.01]">
<TrendingUp className="w-8 h-8 text-white/10 mx-auto mb-3" /> <TrendingUp className="w-16 h-16 text-white/5 mx-auto mb-6" />
<p className="text-white/40 text-sm font-mono mb-2">No yield domains yet</p> <p className="text-white/50 text-sm font-mono uppercase tracking-widest font-bold">No yield domains yet</p>
<p className="text-white/25 text-xs font-mono">Activate domains to earn passive income</p> <p className="text-white/20 text-xs font-mono mt-3 uppercase tracking-wider max-w-sm mx-auto leading-relaxed">
Activate domains to earn passive income from parked traffic
</p>
</div> </div>
) : ( ) : (
<div className="space-y-px bg-white/[0.04] border border-white/[0.08]"> <div className="border border-white/[0.08] bg-[#020202] overflow-hidden">
{/* Header */} {/* Header */}
<div className="hidden lg:grid grid-cols-[1fr_80px_160px_120px_80px_80px_80px_60px] gap-4 px-3 py-2 text-[10px] font-mono text-white/40 uppercase tracking-wider border-b border-white/[0.08]"> <div className="hidden lg:grid grid-cols-[1fr_80px_140px_120px_70px_60px_80px_50px] gap-4 px-5 py-3 text-[10px] font-mono text-white/40 uppercase tracking-[0.12em] border-b border-white/[0.08] bg-white/[0.02]">
<div>Domain</div> <div>Domain</div>
<div className="text-center">Status</div> <div className="text-center">Status</div>
<div>Intent</div> <div>Intent</div>
@ -630,11 +632,14 @@ export default function YieldPage() {
<div className="text-right">Clicks</div> <div className="text-right">Clicks</div>
<div className="text-right">Conv.</div> <div className="text-right">Conv.</div>
<div className="text-right">Revenue</div> <div className="text-right">Revenue</div>
<div className="text-right">Action</div> <div></div>
</div> </div>
{/* Table Body */}
<div className="divide-y divide-white/[0.04]">
{dashboard.domains.map((domain: YieldDomain) => ( {dashboard.domains.map((domain: YieldDomain) => (
<div key={domain.id} className="bg-[#020202] hover:bg-white/[0.02] transition-all"> <div key={domain.id} className="group transition-all">
{/* Mobile */} {/* Mobile */}
<div className="lg:hidden p-3"> <div className="lg:hidden p-3">
<div className="flex items-center justify-between mb-2"> <div className="flex items-center justify-between mb-2">
@ -697,62 +702,55 @@ export default function YieldPage() {
</div> </div>
{/* Desktop */} {/* Desktop */}
<div className="hidden lg:grid grid-cols-[1fr_80px_160px_120px_80px_80px_80px_60px] gap-4 items-center px-3 py-3"> <div className="hidden lg:grid grid-cols-[1fr_80px_140px_120px_70px_60px_80px_50px] gap-4 items-center px-5 py-3 group-hover:bg-white/[0.02]">
<div className="flex items-center gap-3"> <div className="flex items-center gap-3 min-w-0">
<span className="text-sm font-bold text-white font-mono">{domain.domain}</span> <span className="text-sm font-bold text-white font-mono truncate group-hover:text-accent transition-colors">{domain.domain}</span>
</div> </div>
<div className="flex justify-center"><StatusBadge status={domain.status} /></div> <div className="flex justify-center"><StatusBadge status={domain.status} /></div>
<span className="text-xs text-white/60 capitalize font-mono">{domain.detected_intent?.replace('_', ' ') || '—'}</span> <span className="text-sm text-white/50 capitalize font-mono truncate">{domain.detected_intent?.replace('_', ' ') || '—'}</span>
<div> <div>
<details className="group"> <details className="group/details">
<summary <summary
className="cursor-pointer text-xs font-mono text-white/50 hover:text-white/70 flex items-center justify-between" className="cursor-pointer text-xs font-mono text-white/50 hover:text-white/70 flex items-center gap-2"
title="View landing page details" title="View landing page details"
> >
<span>
{domain.landing_headline ? ( {domain.landing_headline ? (
<span className="text-accent font-bold">Ready</span> <span className="text-accent">Ready</span>
) : ( ) : (
<span className="text-amber-400 font-bold">Missing</span> <span className="text-amber-400">Missing</span>
)} )}
</span>
<span className="text-white/30 group-open:text-white/50">details</span>
</summary> </summary>
<div className="mt-2 p-3 bg-[#050505] border border-white/[0.08] space-y-2"> <div className="absolute mt-2 p-3 bg-[#050505] border border-white/[0.08] space-y-2 z-10 w-80">
{domain.landing_headline ? ( {domain.landing_headline ? (
<> <>
<div className="text-xs font-bold text-white">{domain.landing_headline}</div> <div className="text-xs font-bold text-white">{domain.landing_headline}</div>
{domain.landing_intro && <div className="text-[10px] text-white/50 max-w-[520px]">{domain.landing_intro}</div>} {domain.landing_intro && <div className="text-[10px] text-white/50">{domain.landing_intro}</div>}
<div className="text-[10px] font-mono text-white/40"> <div className="text-[10px] font-mono text-white/40">
CTA: <span className="text-white/70">{domain.landing_cta_label || '—'}</span> CTA: <span className="text-white/70">{domain.landing_cta_label || '—'}</span>
</div> </div>
<div className="text-[10px] font-mono text-white/30">
{domain.landing_generated_at ? new Date(domain.landing_generated_at).toLocaleString() : '—'}
{domain.landing_model ? <span className="text-white/20"> {domain.landing_model}</span> : null}
</div>
</> </>
) : ( ) : (
<div className="text-[10px] text-white/40"> <div className="text-[10px] text-white/40">
No landing config stored yet. Remove + re-activate on Tycoon to regenerate. No landing config. Re-activate on Tycoon to generate.
</div> </div>
)} )}
</div> </div>
</details> </details>
</div> </div>
<div className="text-right text-xs font-mono text-white/60">{domain.total_clicks}</div> <div className="text-right text-sm font-mono text-white/50">{domain.total_clicks}</div>
<div className="text-right text-xs font-mono text-white/60">{domain.total_conversions}</div> <div className="text-right text-sm font-mono text-white/50">{domain.total_conversions}</div>
<div className="text-right text-sm font-bold font-mono text-accent">${domain.total_revenue}</div> <div className="text-right text-sm font-bold font-mono text-accent">${domain.total_revenue}</div>
<div className="flex justify-end"> <div className="flex justify-end opacity-40 group-hover:opacity-100 transition-all">
<button <button
onClick={() => handleDeleteYield(domain.id, domain.domain)} onClick={() => handleDeleteYield(domain.id, domain.domain)}
disabled={deletingId === domain.id} disabled={deletingId === domain.id}
className="p-1.5 text-white/30 hover:text-rose-400 disabled:opacity-50 transition-colors" className="w-8 h-8 flex items-center justify-center text-white/40 hover:text-rose-400 border border-white/10 hover:border-rose-400/20 hover:bg-rose-500/10 transition-all"
title="Remove from Yield" title="Remove from Yield"
> >
{deletingId === domain.id ? ( {deletingId === domain.id ? (
<Loader2 className="w-4 h-4 animate-spin" /> <Loader2 className="w-3.5 h-3.5 animate-spin" />
) : ( ) : (
<Trash2 className="w-4 h-4" /> <Trash2 className="w-3.5 h-3.5" />
)} )}
</button> </button>
</div> </div>
@ -760,6 +758,7 @@ export default function YieldPage() {
</div> </div>
))} ))}
</div> </div>
</div>
)} )}
</section> </section>