fix: Revert to dots instead of icons, use accent green, fix max-width
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
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
DASHBOARD: - Reverted status icons to simple dots with pulse animation - Changed max-width from 5xl to 7xl (matching tld-pricing) - All colors back to accent/green (no cyan/emerald/etc) - Stats cards use accent color for positive values - Monitoring domains show pulsing green dot - Added proper spacing (pt-28/32, pb-20/24) SETTINGS: - Updated to match dashboard style (max-w-7xl) - Same padding and spacing - rounded-2xl for modern look - Accent green for highlights - Pulsing dots for active alerts - Consistent border and bg colors
This commit is contained in:
@ -36,10 +36,6 @@ import {
|
||||
Globe,
|
||||
ArrowUpRight,
|
||||
ArrowDownRight,
|
||||
Radio,
|
||||
CircleCheck,
|
||||
CircleX,
|
||||
CircleAlert,
|
||||
} from 'lucide-react'
|
||||
import clsx from 'clsx'
|
||||
import Link from 'next/link'
|
||||
@ -374,59 +370,12 @@ export default function DashboardPage() {
|
||||
const isProOrHigher = tierName === 'Professional' || tierName === 'Enterprise' || tierName === 'Trader' || tierName === 'Tycoon'
|
||||
const isEnterprise = tierName === 'Enterprise' || tierName === 'Tycoon'
|
||||
|
||||
// Get domain status with icon
|
||||
const getDomainStatus = (domain: any) => {
|
||||
const exp = formatExpirationDate(domain.expiration_date)
|
||||
|
||||
if (domain.is_available) {
|
||||
return {
|
||||
icon: CircleCheck,
|
||||
label: 'Available',
|
||||
color: 'text-emerald-400',
|
||||
bg: 'bg-emerald-400/10',
|
||||
ring: 'ring-emerald-400/30',
|
||||
pulse: false
|
||||
}
|
||||
}
|
||||
|
||||
if (exp?.urgent) {
|
||||
return {
|
||||
icon: CircleAlert,
|
||||
label: 'Expiring',
|
||||
color: 'text-amber-400',
|
||||
bg: 'bg-amber-400/10',
|
||||
ring: 'ring-amber-400/30',
|
||||
pulse: true
|
||||
}
|
||||
}
|
||||
|
||||
if (domain.notify_on_available) {
|
||||
return {
|
||||
icon: Radio,
|
||||
label: 'Monitoring',
|
||||
color: 'text-cyan-400',
|
||||
bg: 'bg-cyan-400/10',
|
||||
ring: 'ring-cyan-400/30',
|
||||
pulse: true
|
||||
}
|
||||
}
|
||||
|
||||
return {
|
||||
icon: CircleX,
|
||||
label: 'Registered',
|
||||
color: 'text-foreground-subtle',
|
||||
bg: 'bg-foreground/5',
|
||||
ring: 'ring-foreground/10',
|
||||
pulse: false
|
||||
}
|
||||
}
|
||||
|
||||
return (
|
||||
<div className="min-h-screen bg-background flex flex-col">
|
||||
<Header />
|
||||
|
||||
<main className="flex-1 pt-28 sm:pt-32 pb-20 sm:pb-24 px-4 sm:px-6">
|
||||
<div className="max-w-5xl mx-auto">
|
||||
<main className="flex-1 pt-28 sm:pt-32 pb-20 sm:pb-24 px-4 sm:px-6 lg:px-8">
|
||||
<div className="max-w-7xl mx-auto">
|
||||
{/* Header */}
|
||||
<div className="flex flex-col sm:flex-row sm:items-end sm:justify-between gap-4 mb-8">
|
||||
<div>
|
||||
@ -512,49 +461,26 @@ export default function DashboardPage() {
|
||||
<div className="space-y-6">
|
||||
{/* Stats Row */}
|
||||
<div className="grid grid-cols-2 sm:grid-cols-4 gap-4">
|
||||
<div className="p-5 bg-background-secondary/50 border border-border rounded-2xl hover:border-foreground/20 transition-colors">
|
||||
<div className="flex items-center gap-2 mb-2">
|
||||
<div className="w-6 h-6 rounded-md bg-foreground/10 flex items-center justify-center">
|
||||
<Eye className="w-3.5 h-3.5 text-foreground-muted" />
|
||||
</div>
|
||||
<p className="text-ui-xs text-foreground-muted uppercase tracking-wider">Tracked</p>
|
||||
</div>
|
||||
<div className="p-5 bg-background-secondary border border-border rounded-2xl hover:border-foreground/20 transition-colors">
|
||||
<p className="text-ui-xs text-foreground-muted uppercase tracking-wider mb-2">Tracked</p>
|
||||
<p className="text-3xl font-display text-foreground">{domains.length}</p>
|
||||
</div>
|
||||
<div className="p-5 bg-emerald-500/5 border border-emerald-500/20 rounded-2xl hover:border-emerald-500/40 transition-colors">
|
||||
<div className="flex items-center gap-2 mb-2">
|
||||
<div className="w-6 h-6 rounded-md bg-emerald-500/20 flex items-center justify-center">
|
||||
<CircleCheck className="w-3.5 h-3.5 text-emerald-400" />
|
||||
</div>
|
||||
<p className="text-ui-xs text-emerald-400/80 uppercase tracking-wider">Available</p>
|
||||
</div>
|
||||
<p className="text-3xl font-display text-emerald-400">{availableCount}</p>
|
||||
<div className="p-5 bg-accent/5 border border-accent/20 rounded-2xl hover:border-accent/40 transition-colors">
|
||||
<p className="text-ui-xs text-accent/80 uppercase tracking-wider mb-2">Available</p>
|
||||
<p className="text-3xl font-display text-accent">{availableCount}</p>
|
||||
</div>
|
||||
<div className="p-5 bg-cyan-500/5 border border-cyan-500/20 rounded-2xl hover:border-cyan-500/40 transition-colors">
|
||||
<div className="flex items-center gap-2 mb-2">
|
||||
<div className="w-6 h-6 rounded-md bg-cyan-500/20 flex items-center justify-center">
|
||||
<Radio className="w-3.5 h-3.5 text-cyan-400" />
|
||||
</div>
|
||||
<p className="text-ui-xs text-cyan-400/80 uppercase tracking-wider">Monitoring</p>
|
||||
</div>
|
||||
<p className="text-3xl font-display text-cyan-400">{domains.filter(d => d.notify_on_available).length}</p>
|
||||
<div className="p-5 bg-accent/5 border border-accent/20 rounded-2xl hover:border-accent/40 transition-colors">
|
||||
<p className="text-ui-xs text-accent/80 uppercase tracking-wider mb-2">Monitoring</p>
|
||||
<p className="text-3xl font-display text-accent">{domains.filter(d => d.notify_on_available).length}</p>
|
||||
</div>
|
||||
<div className={clsx(
|
||||
"p-5 border rounded-2xl transition-colors",
|
||||
expiringCount > 0
|
||||
? "bg-amber-500/5 border-amber-500/20 hover:border-amber-500/40"
|
||||
: "bg-background-secondary/50 border-border hover:border-foreground/20"
|
||||
? "bg-warning/5 border-warning/20 hover:border-warning/40"
|
||||
: "bg-background-secondary border-border hover:border-foreground/20"
|
||||
)}>
|
||||
<div className="flex items-center gap-2 mb-2">
|
||||
<div className={clsx(
|
||||
"w-6 h-6 rounded-md flex items-center justify-center",
|
||||
expiringCount > 0 ? "bg-amber-500/20" : "bg-foreground/10"
|
||||
)}>
|
||||
<CircleAlert className={clsx("w-3.5 h-3.5", expiringCount > 0 ? "text-amber-400" : "text-foreground-muted")} />
|
||||
</div>
|
||||
<p className={clsx("text-ui-xs uppercase tracking-wider", expiringCount > 0 ? "text-amber-400/80" : "text-foreground-muted")}>Expiring</p>
|
||||
</div>
|
||||
<p className={clsx("text-3xl font-display", expiringCount > 0 ? "text-amber-400" : "text-foreground")}>{expiringCount}</p>
|
||||
<p className={clsx("text-ui-xs uppercase tracking-wider mb-2", expiringCount > 0 ? "text-warning/80" : "text-foreground-muted")}>Expiring</p>
|
||||
<p className={clsx("text-3xl font-display", expiringCount > 0 ? "text-warning" : "text-foreground")}>{expiringCount}</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@ -601,43 +527,40 @@ export default function DashboardPage() {
|
||||
<tbody className="divide-y divide-border/50">
|
||||
{domains.map((domain) => {
|
||||
const exp = formatExpirationDate(domain.expiration_date)
|
||||
const status = getDomainStatus(domain)
|
||||
const StatusIcon = status.icon
|
||||
const isMonitoring = domain.notify_on_available
|
||||
return (
|
||||
<tr key={domain.id} className="group hover:bg-background-secondary/60 transition-all duration-200">
|
||||
<td className="px-5 py-4">
|
||||
<div className="flex items-center gap-3.5">
|
||||
<div className={clsx(
|
||||
"relative w-8 h-8 rounded-lg flex items-center justify-center ring-1",
|
||||
status.bg, status.ring
|
||||
)}>
|
||||
<StatusIcon className={clsx("w-4 h-4", status.color)} />
|
||||
{status.pulse && (
|
||||
<span className={clsx(
|
||||
"absolute inset-0 rounded-lg animate-ping opacity-30",
|
||||
status.bg
|
||||
)} />
|
||||
<div className="flex items-center gap-3">
|
||||
<div className="relative">
|
||||
<div className={clsx(
|
||||
"w-2.5 h-2.5 rounded-full",
|
||||
domain.is_available ? "bg-accent" : isMonitoring ? "bg-accent" : "bg-foreground-subtle"
|
||||
)} />
|
||||
{isMonitoring && (
|
||||
<span className="absolute inset-0 rounded-full bg-accent animate-ping opacity-40" />
|
||||
)}
|
||||
</div>
|
||||
<div>
|
||||
<span className="font-mono text-body-sm font-medium text-foreground">{domain.name}</span>
|
||||
<p className={clsx("text-ui-xs mt-0.5 sm:hidden", status.color)}>{status.label}</p>
|
||||
</div>
|
||||
<span className="font-mono text-body-sm text-foreground">{domain.name}</span>
|
||||
</div>
|
||||
</td>
|
||||
<td className="px-5 py-4 hidden sm:table-cell">
|
||||
<span className={clsx(
|
||||
"inline-flex items-center gap-1.5 text-ui-xs px-2.5 py-1 rounded-full font-medium",
|
||||
status.bg, status.color
|
||||
"text-ui-xs px-2.5 py-1 rounded-full",
|
||||
domain.is_available
|
||||
? "text-accent bg-accent/10"
|
||||
: isMonitoring
|
||||
? "text-accent bg-accent/10"
|
||||
: "text-foreground-muted bg-foreground/5"
|
||||
)}>
|
||||
{status.label}
|
||||
{domain.is_available ? 'Available' : isMonitoring ? 'Monitoring' : 'Registered'}
|
||||
</span>
|
||||
</td>
|
||||
<td className="px-5 py-4 hidden lg:table-cell">
|
||||
{exp ? (
|
||||
<span className={clsx(
|
||||
"text-body-sm flex items-center gap-1.5",
|
||||
exp.urgent ? "text-amber-400 font-medium" : "text-foreground-subtle"
|
||||
exp.urgent ? "text-warning font-medium" : "text-foreground-subtle"
|
||||
)}>
|
||||
<Calendar className="w-3.5 h-3.5" />{exp.text}
|
||||
</span>
|
||||
@ -664,7 +587,7 @@ export default function DashboardPage() {
|
||||
className={clsx(
|
||||
"p-2 rounded-lg transition-all",
|
||||
domain.notify_on_available
|
||||
? "text-cyan-400 hover:bg-cyan-400/10"
|
||||
? "text-accent hover:bg-accent/10"
|
||||
: "text-foreground-subtle hover:text-foreground hover:bg-foreground/10"
|
||||
)}
|
||||
title={domain.notify_on_available ? "Monitoring active" : "Enable monitoring"}
|
||||
@ -674,7 +597,7 @@ export default function DashboardPage() {
|
||||
<button onClick={() => handleRefresh(domain.id)} disabled={refreshingId === domain.id} className="p-2 text-foreground-subtle hover:text-foreground hover:bg-foreground/10 rounded-lg transition-all" title="Refresh">
|
||||
<RefreshCw className={clsx("w-4 h-4", refreshingId === domain.id && "animate-spin")} />
|
||||
</button>
|
||||
<button onClick={() => handleDelete(domain.id)} className="p-2 text-foreground-subtle hover:text-rose-400 hover:bg-rose-400/10 rounded-lg transition-all" title="Remove">
|
||||
<button onClick={() => handleDelete(domain.id)} className="p-2 text-foreground-subtle hover:text-danger hover:bg-danger/10 rounded-lg transition-all" title="Remove">
|
||||
<Trash2 className="w-4 h-4" />
|
||||
</button>
|
||||
</div>
|
||||
@ -695,62 +618,34 @@ export default function DashboardPage() {
|
||||
{/* Portfolio Stats */}
|
||||
{portfolioSummary && (
|
||||
<div className="grid grid-cols-2 sm:grid-cols-4 gap-4">
|
||||
<div className="p-5 bg-background-secondary/50 border border-border rounded-2xl hover:border-foreground/20 transition-colors">
|
||||
<div className="flex items-center gap-2 mb-2">
|
||||
<div className="w-6 h-6 rounded-md bg-foreground/10 flex items-center justify-center">
|
||||
<DollarSign className="w-3.5 h-3.5 text-foreground-muted" />
|
||||
</div>
|
||||
<p className="text-ui-xs text-foreground-muted uppercase tracking-wider">Total Value</p>
|
||||
</div>
|
||||
<div className="p-5 bg-background-secondary border border-border rounded-2xl hover:border-foreground/20 transition-colors">
|
||||
<p className="text-ui-xs text-foreground-muted uppercase tracking-wider mb-2">Total Value</p>
|
||||
<p className="text-2xl sm:text-3xl font-display text-foreground">{formatCurrency(portfolioSummary.total_value)}</p>
|
||||
</div>
|
||||
<div className="p-5 bg-violet-500/5 border border-violet-500/20 rounded-2xl hover:border-violet-500/40 transition-colors">
|
||||
<div className="flex items-center gap-2 mb-2">
|
||||
<div className="w-6 h-6 rounded-md bg-violet-500/20 flex items-center justify-center">
|
||||
<Tag className="w-3.5 h-3.5 text-violet-400" />
|
||||
</div>
|
||||
<p className="text-ui-xs text-violet-400/80 uppercase tracking-wider">Invested</p>
|
||||
</div>
|
||||
<p className="text-2xl sm:text-3xl font-display text-violet-400">{formatCurrency(portfolioSummary.total_invested)}</p>
|
||||
<div className="p-5 bg-background-secondary border border-border rounded-2xl hover:border-foreground/20 transition-colors">
|
||||
<p className="text-ui-xs text-foreground-muted uppercase tracking-wider mb-2">Invested</p>
|
||||
<p className="text-2xl sm:text-3xl font-display text-foreground">{formatCurrency(portfolioSummary.total_invested)}</p>
|
||||
</div>
|
||||
<div className={clsx(
|
||||
"p-5 border rounded-2xl transition-colors",
|
||||
portfolioSummary.unrealized_profit >= 0
|
||||
? "bg-emerald-500/5 border-emerald-500/20 hover:border-emerald-500/40"
|
||||
: "bg-rose-500/5 border-rose-500/20 hover:border-rose-500/40"
|
||||
? "bg-accent/5 border-accent/20 hover:border-accent/40"
|
||||
: "bg-danger/5 border-danger/20 hover:border-danger/40"
|
||||
)}>
|
||||
<div className="flex items-center gap-2 mb-2">
|
||||
<div className={clsx(
|
||||
"w-6 h-6 rounded-md flex items-center justify-center",
|
||||
portfolioSummary.unrealized_profit >= 0 ? "bg-emerald-500/20" : "bg-rose-500/20"
|
||||
)}>
|
||||
{portfolioSummary.unrealized_profit >= 0
|
||||
? <ArrowUpRight className="w-3.5 h-3.5 text-emerald-400" />
|
||||
: <ArrowDownRight className="w-3.5 h-3.5 text-rose-400" />
|
||||
}
|
||||
</div>
|
||||
<p className={clsx("text-ui-xs uppercase tracking-wider", portfolioSummary.unrealized_profit >= 0 ? "text-emerald-400/80" : "text-rose-400/80")}>P/L</p>
|
||||
</div>
|
||||
<p className={clsx("text-2xl sm:text-3xl font-display", portfolioSummary.unrealized_profit >= 0 ? "text-emerald-400" : "text-rose-400")}>
|
||||
{portfolioSummary.unrealized_profit >= 0 ? '+' : ''}{formatCurrency(portfolioSummary.unrealized_profit)}
|
||||
<p className={clsx("text-ui-xs uppercase tracking-wider mb-2", portfolioSummary.unrealized_profit >= 0 ? "text-accent/80" : "text-danger/80")}>P/L</p>
|
||||
<p className={clsx("text-2xl sm:text-3xl font-display flex items-center gap-1", portfolioSummary.unrealized_profit >= 0 ? "text-accent" : "text-danger")}>
|
||||
{portfolioSummary.unrealized_profit >= 0 ? <ArrowUpRight className="w-5 h-5" /> : <ArrowDownRight className="w-5 h-5" />}
|
||||
{formatCurrency(Math.abs(portfolioSummary.unrealized_profit))}
|
||||
</p>
|
||||
</div>
|
||||
<div className={clsx(
|
||||
"p-5 border rounded-2xl transition-colors",
|
||||
portfolioSummary.overall_roi >= 0
|
||||
? "bg-emerald-500/5 border-emerald-500/20 hover:border-emerald-500/40"
|
||||
: "bg-rose-500/5 border-rose-500/20 hover:border-rose-500/40"
|
||||
? "bg-accent/5 border-accent/20 hover:border-accent/40"
|
||||
: "bg-danger/5 border-danger/20 hover:border-danger/40"
|
||||
)}>
|
||||
<div className="flex items-center gap-2 mb-2">
|
||||
<div className={clsx(
|
||||
"w-6 h-6 rounded-md flex items-center justify-center",
|
||||
portfolioSummary.overall_roi >= 0 ? "bg-emerald-500/20" : "bg-rose-500/20"
|
||||
)}>
|
||||
<BarChart3 className={clsx("w-3.5 h-3.5", portfolioSummary.overall_roi >= 0 ? "text-emerald-400" : "text-rose-400")} />
|
||||
</div>
|
||||
<p className={clsx("text-ui-xs uppercase tracking-wider", portfolioSummary.overall_roi >= 0 ? "text-emerald-400/80" : "text-rose-400/80")}>ROI</p>
|
||||
</div>
|
||||
<p className={clsx("text-2xl sm:text-3xl font-display", portfolioSummary.overall_roi >= 0 ? "text-emerald-400" : "text-rose-400")}>
|
||||
<p className={clsx("text-ui-xs uppercase tracking-wider mb-2", portfolioSummary.overall_roi >= 0 ? "text-accent/80" : "text-danger/80")}>ROI</p>
|
||||
<p className={clsx("text-2xl sm:text-3xl font-display", portfolioSummary.overall_roi >= 0 ? "text-accent" : "text-danger")}>
|
||||
{portfolioSummary.overall_roi >= 0 ? '+' : ''}{portfolioSummary.overall_roi.toFixed(1)}%
|
||||
</p>
|
||||
</div>
|
||||
@ -817,9 +712,9 @@ export default function DashboardPage() {
|
||||
)}
|
||||
|
||||
{/* Quick Links */}
|
||||
<div className="mt-12 p-6 bg-gradient-to-r from-accent/5 via-cyan-500/5 to-violet-500/5 border border-accent/20 rounded-2xl flex flex-col sm:flex-row items-start sm:items-center justify-between gap-4">
|
||||
<div className="mt-12 p-6 bg-accent/5 border border-accent/20 rounded-2xl flex flex-col sm:flex-row items-start sm:items-center justify-between gap-4">
|
||||
<div className="flex items-center gap-4">
|
||||
<div className="w-12 h-12 bg-accent/10 rounded-xl flex items-center justify-center ring-1 ring-accent/20">
|
||||
<div className="w-12 h-12 bg-accent/10 rounded-xl flex items-center justify-center">
|
||||
<TrendingUp className="w-6 h-6 text-accent" />
|
||||
</div>
|
||||
<div>
|
||||
|
||||
@ -147,24 +147,16 @@ export default function SettingsPage() {
|
||||
]
|
||||
|
||||
return (
|
||||
<div className="min-h-screen bg-background relative flex flex-col">
|
||||
{/* Ambient glow */}
|
||||
<div className="fixed inset-0 pointer-events-none">
|
||||
<div className="absolute top-0 left-1/3 w-[500px] h-[400px] bg-accent/[0.02] rounded-full blur-3xl" />
|
||||
</div>
|
||||
|
||||
<div className="min-h-screen bg-background flex flex-col">
|
||||
<Header />
|
||||
|
||||
<main className="relative pt-32 sm:pt-36 pb-20 px-4 sm:px-6 flex-1">
|
||||
<div className="max-w-4xl mx-auto">
|
||||
<main className="flex-1 pt-28 sm:pt-32 pb-20 sm:pb-24 px-4 sm:px-6 lg:px-8">
|
||||
<div className="max-w-7xl mx-auto">
|
||||
{/* Header */}
|
||||
<div className="mb-8 animate-fade-in">
|
||||
<div className="flex items-center gap-3 mb-2">
|
||||
<Settings className="w-6 h-6 text-accent" />
|
||||
<h1 className="font-display text-[2rem] sm:text-[2.5rem] leading-[1.1] tracking-[-0.03em] text-foreground">
|
||||
Settings
|
||||
</h1>
|
||||
</div>
|
||||
<div className="mb-10">
|
||||
<h1 className="font-display text-[2rem] sm:text-[2.5rem] leading-[1.1] tracking-[-0.03em] text-foreground mb-2">
|
||||
Settings
|
||||
</h1>
|
||||
<p className="text-body text-foreground-muted">
|
||||
Your account. Your rules.
|
||||
</p>
|
||||
@ -172,7 +164,7 @@ export default function SettingsPage() {
|
||||
|
||||
{/* Messages */}
|
||||
{error && (
|
||||
<div className="mb-6 p-4 bg-danger-muted border border-danger/20 rounded-xl flex items-center gap-3 animate-fade-in">
|
||||
<div className="mb-6 p-4 bg-danger/5 border border-danger/20 rounded-2xl flex items-center gap-3">
|
||||
<AlertCircle className="w-5 h-5 text-danger shrink-0" />
|
||||
<p className="text-body-sm text-danger flex-1">{error}</p>
|
||||
<button onClick={() => setError(null)} className="text-danger hover:text-danger/80">
|
||||
@ -182,7 +174,7 @@ export default function SettingsPage() {
|
||||
)}
|
||||
|
||||
{success && (
|
||||
<div className="mb-6 p-4 bg-accent-muted border border-accent/20 rounded-xl flex items-center gap-3 animate-fade-in">
|
||||
<div className="mb-6 p-4 bg-accent/5 border border-accent/20 rounded-2xl flex items-center gap-3">
|
||||
<Check className="w-5 h-5 text-accent shrink-0" />
|
||||
<p className="text-body-sm text-accent flex-1">{success}</p>
|
||||
<button onClick={() => setSuccess(null)} className="text-accent hover:text-accent/80">
|
||||
@ -191,7 +183,7 @@ export default function SettingsPage() {
|
||||
</div>
|
||||
)}
|
||||
|
||||
<div className="flex flex-col lg:flex-row gap-6">
|
||||
<div className="flex flex-col lg:flex-row gap-8">
|
||||
{/* Sidebar - Horizontal scroll on mobile, vertical on desktop */}
|
||||
<div className="lg:w-64 shrink-0">
|
||||
{/* Mobile: Horizontal scroll tabs */}
|
||||
@ -201,10 +193,10 @@ export default function SettingsPage() {
|
||||
key={tab.id}
|
||||
onClick={() => setActiveTab(tab.id)}
|
||||
className={clsx(
|
||||
"flex items-center gap-2 px-4 py-2.5 text-ui-sm font-medium rounded-xl whitespace-nowrap transition-all",
|
||||
"flex items-center gap-2 px-5 py-2.5 text-ui font-medium rounded-xl whitespace-nowrap transition-all",
|
||||
activeTab === tab.id
|
||||
? "bg-foreground text-background"
|
||||
: "bg-background-secondary/50 text-foreground-muted hover:text-foreground border border-border"
|
||||
? "bg-foreground text-background shadow-lg"
|
||||
: "bg-background-secondary text-foreground-muted hover:text-foreground border border-border"
|
||||
)}
|
||||
>
|
||||
<tab.icon className="w-4 h-4" />
|
||||
@ -214,16 +206,16 @@ export default function SettingsPage() {
|
||||
</nav>
|
||||
|
||||
{/* Desktop: Vertical tabs */}
|
||||
<nav className="hidden lg:block p-2 bg-background-secondary/50 border border-border rounded-xl">
|
||||
<nav className="hidden lg:block p-1.5 bg-background-secondary/70 border border-border rounded-2xl">
|
||||
{tabs.map((tab) => (
|
||||
<button
|
||||
key={tab.id}
|
||||
onClick={() => setActiveTab(tab.id)}
|
||||
className={clsx(
|
||||
"w-full flex items-center gap-3 px-4 py-3 text-ui-sm font-medium rounded-lg transition-all",
|
||||
"w-full flex items-center gap-3 px-4 py-3 text-ui font-medium rounded-xl transition-all",
|
||||
activeTab === tab.id
|
||||
? "bg-foreground text-background"
|
||||
: "text-foreground-muted hover:text-foreground hover:bg-background-tertiary"
|
||||
? "bg-foreground text-background shadow-lg"
|
||||
: "text-foreground-muted hover:text-foreground hover:bg-foreground/5"
|
||||
)}
|
||||
>
|
||||
<tab.icon className="w-4 h-4" />
|
||||
@ -233,9 +225,9 @@ export default function SettingsPage() {
|
||||
</nav>
|
||||
|
||||
{/* Plan info - hidden on mobile, shown in content area instead */}
|
||||
<div className="hidden lg:block mt-4 p-4 bg-background-secondary/30 border border-border rounded-xl">
|
||||
<div className="hidden lg:block mt-4 p-5 bg-accent/5 border border-accent/20 rounded-2xl">
|
||||
<div className="flex items-center gap-2 mb-2">
|
||||
{isProOrHigher ? <Crown className="w-4 h-4 text-accent" /> : <Zap className="w-4 h-4 text-foreground-muted" />}
|
||||
{isProOrHigher ? <Crown className="w-4 h-4 text-accent" /> : <Zap className="w-4 h-4 text-accent" />}
|
||||
<span className="text-body-sm font-medium text-foreground">{tierName} Plan</span>
|
||||
</div>
|
||||
<p className="text-body-xs text-foreground-muted mb-3">
|
||||
@ -244,7 +236,7 @@ export default function SettingsPage() {
|
||||
{!isProOrHigher && (
|
||||
<Link
|
||||
href="/pricing"
|
||||
className="flex items-center justify-center gap-2 w-full py-2 bg-accent text-background text-ui-xs font-medium rounded-lg hover:bg-accent-hover transition-all"
|
||||
className="flex items-center justify-center gap-2 w-full py-2.5 bg-accent text-background text-ui-sm font-medium rounded-xl hover:bg-accent-hover transition-all"
|
||||
>
|
||||
Upgrade
|
||||
<ChevronRight className="w-3.5 h-3.5" />
|
||||
@ -257,10 +249,10 @@ export default function SettingsPage() {
|
||||
<div className="flex-1 min-w-0">
|
||||
{/* Profile Tab */}
|
||||
{activeTab === 'profile' && (
|
||||
<div className="p-6 bg-background-secondary/50 border border-border rounded-xl animate-fade-in">
|
||||
<div className="p-6 sm:p-8 bg-background-secondary/30 border border-border rounded-2xl">
|
||||
<h2 className="text-body-lg font-medium text-foreground mb-6">Profile Information</h2>
|
||||
|
||||
<form onSubmit={handleSaveProfile} className="space-y-4">
|
||||
<form onSubmit={handleSaveProfile} className="space-y-5">
|
||||
<div>
|
||||
<label className="block text-ui-sm text-foreground-muted mb-2">Name</label>
|
||||
<input
|
||||
@ -268,8 +260,8 @@ export default function SettingsPage() {
|
||||
value={profileForm.name}
|
||||
onChange={(e) => setProfileForm({ ...profileForm, name: e.target.value })}
|
||||
placeholder="Your name"
|
||||
className="w-full px-4 py-3 bg-background border border-border rounded-xl text-body text-foreground
|
||||
placeholder:text-foreground-subtle focus:outline-none focus:border-border-hover transition-all"
|
||||
className="w-full px-4 py-3.5 bg-background border border-border rounded-xl text-body text-foreground
|
||||
placeholder:text-foreground-subtle focus:outline-none focus:ring-1 focus:ring-accent/50 focus:border-accent/50 transition-all"
|
||||
/>
|
||||
</div>
|
||||
|
||||
@ -279,16 +271,16 @@ export default function SettingsPage() {
|
||||
type="email"
|
||||
value={profileForm.email}
|
||||
disabled
|
||||
className="w-full px-4 py-3 bg-background-tertiary border border-border rounded-xl text-body text-foreground-muted cursor-not-allowed"
|
||||
className="w-full px-4 py-3.5 bg-background-tertiary border border-border rounded-xl text-body text-foreground-muted cursor-not-allowed"
|
||||
/>
|
||||
<p className="text-ui-xs text-foreground-subtle mt-1">Email cannot be changed</p>
|
||||
<p className="text-ui-xs text-foreground-subtle mt-1.5">Email cannot be changed</p>
|
||||
</div>
|
||||
|
||||
<button
|
||||
type="submit"
|
||||
disabled={saving}
|
||||
className="px-6 py-3 bg-foreground text-background text-ui font-medium rounded-xl
|
||||
hover:bg-foreground/90 disabled:opacity-50 transition-all flex items-center gap-2"
|
||||
className="px-6 py-3.5 bg-foreground text-background text-ui font-medium rounded-xl
|
||||
hover:bg-foreground/90 disabled:opacity-50 transition-all flex items-center gap-2 shadow-lg shadow-foreground/10"
|
||||
>
|
||||
{saving ? <Loader2 className="w-4 h-4 animate-spin" /> : <Check className="w-4 h-4" />}
|
||||
Save Changes
|
||||
@ -299,12 +291,12 @@ export default function SettingsPage() {
|
||||
|
||||
{/* Notifications Tab */}
|
||||
{activeTab === 'notifications' && (
|
||||
<div className="space-y-6 animate-fade-in">
|
||||
<div className="p-6 bg-background-secondary/50 border border-border rounded-xl">
|
||||
<h2 className="text-body-lg font-medium text-foreground mb-4">Email Preferences</h2>
|
||||
<div className="space-y-6">
|
||||
<div className="p-6 sm:p-8 bg-background-secondary/30 border border-border rounded-2xl">
|
||||
<h2 className="text-body-lg font-medium text-foreground mb-5">Email Preferences</h2>
|
||||
|
||||
<div className="space-y-3">
|
||||
<label className="flex items-center justify-between p-4 bg-background-tertiary rounded-xl cursor-pointer">
|
||||
<label className="flex items-center justify-between p-4 bg-background border border-border rounded-xl cursor-pointer hover:border-foreground/20 transition-colors">
|
||||
<div>
|
||||
<p className="text-body-sm font-medium text-foreground">Domain Availability</p>
|
||||
<p className="text-body-xs text-foreground-muted">Get notified when watched domains become available</p>
|
||||
@ -312,7 +304,7 @@ export default function SettingsPage() {
|
||||
<input type="checkbox" defaultChecked className="w-5 h-5 accent-accent" />
|
||||
</label>
|
||||
|
||||
<label className="flex items-center justify-between p-4 bg-background-tertiary rounded-xl cursor-pointer">
|
||||
<label className="flex items-center justify-between p-4 bg-background border border-border rounded-xl cursor-pointer hover:border-foreground/20 transition-colors">
|
||||
<div>
|
||||
<p className="text-body-sm font-medium text-foreground">Price Alerts</p>
|
||||
<p className="text-body-xs text-foreground-muted">Get notified when TLD prices change</p>
|
||||
@ -320,7 +312,7 @@ export default function SettingsPage() {
|
||||
<input type="checkbox" defaultChecked className="w-5 h-5 accent-accent" />
|
||||
</label>
|
||||
|
||||
<label className="flex items-center justify-between p-4 bg-background-tertiary rounded-xl cursor-pointer">
|
||||
<label className="flex items-center justify-between p-4 bg-background border border-border rounded-xl cursor-pointer hover:border-foreground/20 transition-colors">
|
||||
<div>
|
||||
<p className="text-body-sm font-medium text-foreground">Weekly Digest</p>
|
||||
<p className="text-body-xs text-foreground-muted">Receive a weekly summary of your portfolio</p>
|
||||
@ -331,20 +323,20 @@ export default function SettingsPage() {
|
||||
</div>
|
||||
|
||||
{/* Active Price Alerts */}
|
||||
<div className="p-6 bg-background-secondary/50 border border-border rounded-xl">
|
||||
<h2 className="text-body-lg font-medium text-foreground mb-4">Active Price Alerts</h2>
|
||||
<div className="p-6 sm:p-8 bg-background-secondary/30 border border-border rounded-2xl">
|
||||
<h2 className="text-body-lg font-medium text-foreground mb-5">Active Price Alerts</h2>
|
||||
|
||||
{loadingAlerts ? (
|
||||
<div className="py-8 flex items-center justify-center">
|
||||
<Loader2 className="w-5 h-5 animate-spin text-accent" />
|
||||
<div className="py-10 flex items-center justify-center">
|
||||
<Loader2 className="w-6 h-6 animate-spin text-accent" />
|
||||
</div>
|
||||
) : priceAlerts.length === 0 ? (
|
||||
<div className="py-8 text-center">
|
||||
<Bell className="w-8 h-8 text-foreground-subtle mx-auto mb-3" />
|
||||
<p className="text-body-sm text-foreground-muted mb-3">No price alerts set</p>
|
||||
<div className="py-12 text-center border border-dashed border-border/50 rounded-xl bg-background/30">
|
||||
<Bell className="w-10 h-10 text-foreground-subtle mx-auto mb-4" />
|
||||
<p className="text-body text-foreground-muted mb-3">No price alerts set</p>
|
||||
<Link
|
||||
href="/tld-pricing"
|
||||
className="text-accent hover:text-accent-hover text-body-sm"
|
||||
className="text-accent hover:text-accent-hover text-body-sm font-medium"
|
||||
>
|
||||
Browse TLD prices →
|
||||
</Link>
|
||||
@ -354,13 +346,18 @@ export default function SettingsPage() {
|
||||
{priceAlerts.map((alert) => (
|
||||
<div
|
||||
key={alert.id}
|
||||
className="flex items-center justify-between p-4 bg-background-tertiary rounded-xl"
|
||||
className="flex items-center justify-between p-4 bg-background border border-border rounded-xl hover:border-foreground/20 transition-colors"
|
||||
>
|
||||
<div className="flex items-center gap-3">
|
||||
<div className={clsx(
|
||||
"w-2 h-2 rounded-full",
|
||||
alert.is_active ? "bg-accent" : "bg-foreground-subtle"
|
||||
)} />
|
||||
<div className="relative">
|
||||
<div className={clsx(
|
||||
"w-2.5 h-2.5 rounded-full",
|
||||
alert.is_active ? "bg-accent" : "bg-foreground-subtle"
|
||||
)} />
|
||||
{alert.is_active && (
|
||||
<span className="absolute inset-0 rounded-full bg-accent animate-ping opacity-40" />
|
||||
)}
|
||||
</div>
|
||||
<div>
|
||||
<Link
|
||||
href={`/tld-pricing/${alert.tld}`}
|
||||
@ -377,7 +374,7 @@ export default function SettingsPage() {
|
||||
<button
|
||||
onClick={() => handleDeletePriceAlert(alert.tld, alert.id)}
|
||||
disabled={deletingAlertId === alert.id}
|
||||
className="p-2 text-foreground-subtle hover:text-danger hover:bg-danger-muted rounded-lg transition-all"
|
||||
className="p-2 text-foreground-subtle hover:text-danger hover:bg-danger/10 rounded-lg transition-all"
|
||||
>
|
||||
{deletingAlertId === alert.id ? (
|
||||
<Loader2 className="w-4 h-4 animate-spin" />
|
||||
@ -395,10 +392,10 @@ export default function SettingsPage() {
|
||||
|
||||
{/* Billing Tab */}
|
||||
{activeTab === 'billing' && (
|
||||
<div className="p-6 bg-background-secondary/50 border border-border rounded-xl animate-fade-in">
|
||||
<div className="p-6 sm:p-8 bg-background-secondary/30 border border-border rounded-2xl">
|
||||
<h2 className="text-body-lg font-medium text-foreground mb-6">Subscription & Billing</h2>
|
||||
|
||||
<div className="p-4 bg-background-tertiary rounded-xl mb-6">
|
||||
<div className="p-5 bg-accent/5 border border-accent/20 rounded-xl mb-6">
|
||||
<div className="flex items-center justify-between mb-4">
|
||||
<div>
|
||||
<p className="text-body font-medium text-foreground">{tierName} Plan</p>
|
||||
@ -407,8 +404,8 @@ export default function SettingsPage() {
|
||||
</p>
|
||||
</div>
|
||||
<span className={clsx(
|
||||
"px-3 py-1 text-ui-xs font-medium rounded-full",
|
||||
isProOrHigher ? "bg-accent-muted text-accent" : "bg-background text-foreground-muted"
|
||||
"px-3 py-1.5 text-ui-xs font-medium rounded-full",
|
||||
isProOrHigher ? "bg-accent/10 text-accent" : "bg-foreground/5 text-foreground-muted"
|
||||
)}>
|
||||
{isProOrHigher ? 'Active' : 'Free'}
|
||||
</span>
|
||||
@ -417,8 +414,8 @@ export default function SettingsPage() {
|
||||
{isProOrHigher ? (
|
||||
<button
|
||||
onClick={handleOpenBillingPortal}
|
||||
className="w-full py-3 bg-background text-foreground text-ui font-medium rounded-xl
|
||||
hover:bg-background-secondary transition-all flex items-center justify-center gap-2"
|
||||
className="w-full py-3 bg-background text-foreground text-ui font-medium rounded-xl border border-border
|
||||
hover:border-foreground/20 transition-all flex items-center justify-center gap-2"
|
||||
>
|
||||
<ExternalLink className="w-4 h-4" />
|
||||
Manage Subscription
|
||||
@ -427,7 +424,7 @@ export default function SettingsPage() {
|
||||
<Link
|
||||
href="/pricing"
|
||||
className="w-full py-3 bg-accent text-background text-ui font-medium rounded-xl
|
||||
hover:bg-accent-hover transition-all flex items-center justify-center gap-2"
|
||||
hover:bg-accent-hover transition-all flex items-center justify-center gap-2 shadow-lg shadow-accent/20"
|
||||
>
|
||||
<Zap className="w-4 h-4" />
|
||||
Upgrade Plan
|
||||
@ -457,51 +454,53 @@ export default function SettingsPage() {
|
||||
|
||||
{/* Security Tab */}
|
||||
{activeTab === 'security' && (
|
||||
<div className="space-y-6 animate-fade-in">
|
||||
<div className="p-6 bg-background-secondary/50 border border-border rounded-xl">
|
||||
<div className="space-y-6">
|
||||
<div className="p-6 sm:p-8 bg-background-secondary/30 border border-border rounded-2xl">
|
||||
<h2 className="text-body-lg font-medium text-foreground mb-4">Password</h2>
|
||||
<p className="text-body-sm text-foreground-muted mb-4">
|
||||
<p className="text-body-sm text-foreground-muted mb-5">
|
||||
Change your password or reset it if you've forgotten it.
|
||||
</p>
|
||||
<Link
|
||||
href="/forgot-password"
|
||||
className="inline-flex items-center gap-2 px-4 py-2 bg-background-tertiary text-foreground text-ui-sm font-medium rounded-lg
|
||||
hover:bg-background transition-all"
|
||||
className="inline-flex items-center gap-2 px-5 py-3 bg-background border border-border text-foreground text-ui font-medium rounded-xl
|
||||
hover:border-foreground/20 transition-all"
|
||||
>
|
||||
<Key className="w-4 h-4" />
|
||||
Change Password
|
||||
</Link>
|
||||
</div>
|
||||
|
||||
<div className="p-6 bg-background-secondary/50 border border-border rounded-xl">
|
||||
<h2 className="text-body-lg font-medium text-foreground mb-4">Account Security</h2>
|
||||
<div className="p-6 sm:p-8 bg-background-secondary/30 border border-border rounded-2xl">
|
||||
<h2 className="text-body-lg font-medium text-foreground mb-5">Account Security</h2>
|
||||
|
||||
<div className="space-y-3">
|
||||
<div className="flex items-center justify-between p-4 bg-background-tertiary rounded-xl">
|
||||
<div className="flex items-center justify-between p-4 bg-background border border-border rounded-xl">
|
||||
<div>
|
||||
<p className="text-body-sm font-medium text-foreground">Email Verified</p>
|
||||
<p className="text-body-xs text-foreground-muted">Your email address has been verified</p>
|
||||
</div>
|
||||
<Check className="w-5 h-5 text-accent" />
|
||||
<div className="w-8 h-8 bg-accent/10 rounded-lg flex items-center justify-center">
|
||||
<Check className="w-4 h-4 text-accent" />
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div className="flex items-center justify-between p-4 bg-background-tertiary rounded-xl">
|
||||
<div className="flex items-center justify-between p-4 bg-background border border-border rounded-xl">
|
||||
<div>
|
||||
<p className="text-body-sm font-medium text-foreground">Two-Factor Authentication</p>
|
||||
<p className="text-body-xs text-foreground-muted">Coming soon</p>
|
||||
</div>
|
||||
<span className="text-ui-xs px-2 py-1 bg-background text-foreground-muted rounded-full">Soon</span>
|
||||
<span className="text-ui-xs px-2.5 py-1 bg-foreground/5 text-foreground-muted rounded-full">Soon</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div className="p-6 bg-danger-muted/30 border border-danger/20 rounded-xl">
|
||||
<div className="p-6 sm:p-8 bg-danger/5 border border-danger/20 rounded-2xl">
|
||||
<h2 className="text-body-lg font-medium text-danger mb-2">Danger Zone</h2>
|
||||
<p className="text-body-sm text-foreground-muted mb-4">
|
||||
<p className="text-body-sm text-foreground-muted mb-5">
|
||||
Permanently delete your account and all associated data.
|
||||
</p>
|
||||
<button
|
||||
className="px-4 py-2 bg-danger text-white text-ui-sm font-medium rounded-lg hover:bg-danger/90 transition-all"
|
||||
className="px-5 py-3 bg-danger text-white text-ui font-medium rounded-xl hover:bg-danger/90 transition-all"
|
||||
>
|
||||
Delete Account
|
||||
</button>
|
||||
|
||||
Reference in New Issue
Block a user