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" />
</div>
) : listings.length === 0 ? (
<div className="text-center py-16 border border-dashed border-white/[0.08]">
<Tag className="w-8 h-8 text-white/10 mx-auto mb-3" />
<p className="text-white/40 text-sm font-mono mb-2">No listings yet</p>
<p className="text-white/25 text-xs font-mono mb-4">Create your first listing to start selling</p>
<button onClick={() => setShowCreateWizard(true)} className="inline-flex items-center gap-2 px-4 py-2 bg-accent text-black text-xs font-bold uppercase">
<div className="text-center py-24 border border-dashed border-white/[0.08] bg-white/[0.01]">
<Tag className="w-16 h-16 text-white/5 mx-auto mb-6" />
<p className="text-white/50 text-sm font-mono uppercase tracking-widest font-bold">No listings yet</p>
<p className="text-white/20 text-xs font-mono mt-3 uppercase tracking-wider max-w-sm mx-auto leading-relaxed">
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
</button>
</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 */}
<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 className="text-right">Price</div>
<div className="text-center">Status</div>
<div className="text-right">Views</div>
<div className="text-right">Leads</div>
<div className="text-right">Actions</div>
<div className="text-right pr-1">Actions</div>
</div>
{/* Table Body */}
<div className="divide-y divide-white/[0.04]">
{listings.map((listing) => (
<ListingRow
key={listing.id}
@ -281,6 +285,7 @@ export default function MyListingsPage() {
/>
))}
</div>
</div>
)}
{!canAddMore && listings.length >= maxListings && (
@ -393,7 +398,7 @@ function ListingRow({
const needsVerification = !listing.is_verified
return (
<div className="bg-[#020202] hover:bg-white/[0.02] transition-all group">
<div className="group transition-all">
{/* Mobile */}
<div className="lg:hidden p-3">
<div className="flex items-center justify-between mb-2">
@ -457,37 +462,37 @@ function ListingRow({
</div>
{/* Desktop */}
<div className="hidden lg:grid grid-cols-[1fr_100px_100px_60px_60px_120px] gap-4 items-center px-3 py-3">
<div className="flex items-center gap-3">
<div>
<span className="text-sm font-bold text-white font-mono group-hover:text-accent transition-colors">{listing.domain}</span>
{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>}
{!listing.is_verified && <span className="ml-2 text-[9px] text-amber-400/60 font-mono">Unverified</span>}
<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 min-w-0">
<span className="text-sm font-bold text-white font-mono truncate 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="px-1 py-0.5 bg-amber-400/10 text-amber-400 border border-amber-400/20">Featured</span>}
{!listing.is_verified && <span className="text-amber-400/60">Unverified</span>}
</div>
</div>
<div className="text-right text-sm font-bold font-mono text-accent">${listing.asking_price?.toLocaleString() || '—'}</div>
<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" :
isDraft ? "bg-amber-400/10 text-amber-400 border-amber-400/20" :
"bg-white/5 text-white/40 border-white/10"
)}>{listing.status}</span>
</div>
<div className="text-right text-xs font-mono text-white/60">{listing.view_count}</div>
<div className="text-right text-xs font-mono text-white/60">{listing.inquiry_count}</div>
<div className="flex items-center justify-end gap-1">
<div className="text-right text-sm font-mono text-white/50">{listing.view_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 opacity-40 group-hover:opacity-100 transition-all">
{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
</button>
)}
{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
</button>
)}
{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" />
</a>
)}
@ -495,7 +500,7 @@ function ListingRow({
<button
type="button"
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"
>
<CheckCircle className="w-3.5 h-3.5" />
@ -505,14 +510,14 @@ function ListingRow({
<button
type="button"
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"
>
<MessageSquare className="w-3.5 h-3.5" />
</button>
)}
<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" />}
</button>
</div>

View File

@ -614,15 +614,17 @@ export default function YieldPage() {
<Loader2 className="w-6 h-6 text-accent animate-spin" />
</div>
) : !dashboard?.domains?.length ? (
<div className="text-center py-16 border border-dashed border-white/[0.08]">
<TrendingUp className="w-8 h-8 text-white/10 mx-auto mb-3" />
<p className="text-white/40 text-sm font-mono mb-2">No yield domains yet</p>
<p className="text-white/25 text-xs font-mono">Activate domains to earn passive income</p>
<div className="text-center py-24 border border-dashed border-white/[0.08] bg-white/[0.01]">
<TrendingUp className="w-16 h-16 text-white/5 mx-auto mb-6" />
<p className="text-white/50 text-sm font-mono uppercase tracking-widest font-bold">No yield domains yet</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 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 */}
<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 className="text-center">Status</div>
<div>Intent</div>
@ -630,11 +632,14 @@ export default function YieldPage() {
<div className="text-right">Clicks</div>
<div className="text-right">Conv.</div>
<div className="text-right">Revenue</div>
<div className="text-right">Action</div>
<div></div>
</div>
{/* Table Body */}
<div className="divide-y divide-white/[0.04]">
{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 */}
<div className="lg:hidden p-3">
<div className="flex items-center justify-between mb-2">
@ -697,62 +702,55 @@ export default function YieldPage() {
</div>
{/* 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="flex items-center gap-3">
<span className="text-sm font-bold text-white font-mono">{domain.domain}</span>
<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 min-w-0">
<span className="text-sm font-bold text-white font-mono truncate group-hover:text-accent transition-colors">{domain.domain}</span>
</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>
<details className="group">
<details className="group/details">
<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"
>
<span>
{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>
<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 ? (
<>
<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">
CTA: <span className="text-white/70">{domain.landing_cta_label || '—'}</span>
</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">
No landing config stored yet. Remove + re-activate on Tycoon to regenerate.
No landing config. Re-activate on Tycoon to generate.
</div>
)}
</div>
</details>
</div>
<div className="text-right text-xs font-mono text-white/60">{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_clicks}</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="flex justify-end">
<div className="flex justify-end opacity-40 group-hover:opacity-100 transition-all">
<button
onClick={() => handleDeleteYield(domain.id, domain.domain)}
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"
>
{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>
</div>
@ -760,6 +758,7 @@ export default function YieldPage() {
</div>
))}
</div>
</div>
)}
</section>