Changes: - Added pounce-logo.png to /public - Updated Header.tsx: Replaced text logo with Image component - Updated Footer.tsx: Replaced text logo with Image component - Updated login/page.tsx: Replaced text logo with Image component - Updated register/page.tsx: Replaced text logo with Image component Logo sizing: - Header: 32px (mobile) / 36px (desktop) - Footer: 40px - Login/Register: 48px All logos use Next.js Image component for optimization
181 lines
6.7 KiB
TypeScript
181 lines
6.7 KiB
TypeScript
'use client'
|
|
|
|
import { useState } from 'react'
|
|
import { useRouter } from 'next/navigation'
|
|
import Link from 'next/link'
|
|
import Image from 'next/image'
|
|
import { useStore } from '@/lib/store'
|
|
import { Loader2, ArrowRight, Check, Eye, EyeOff } from 'lucide-react'
|
|
|
|
// Logo Component - Puma Image
|
|
function Logo() {
|
|
return (
|
|
<Image
|
|
src="/pounce-logo.png"
|
|
alt="pounce"
|
|
width={48}
|
|
height={48}
|
|
className="w-12 h-12"
|
|
/>
|
|
)
|
|
}
|
|
|
|
const benefits = [
|
|
'Monitor up to 3 domains free',
|
|
'Daily availability checks',
|
|
'Instant email notifications',
|
|
'Track expiration dates',
|
|
]
|
|
|
|
export default function RegisterPage() {
|
|
const router = useRouter()
|
|
const { register } = useStore()
|
|
|
|
const [email, setEmail] = useState('')
|
|
const [password, setPassword] = useState('')
|
|
const [showPassword, setShowPassword] = useState(false)
|
|
const [error, setError] = useState<string | null>(null)
|
|
const [loading, setLoading] = useState(false)
|
|
|
|
const handleSubmit = async (e: React.FormEvent) => {
|
|
e.preventDefault()
|
|
setError(null)
|
|
setLoading(true)
|
|
|
|
try {
|
|
await register(email, password)
|
|
router.push('/dashboard')
|
|
} catch (err) {
|
|
setError(err instanceof Error ? err.message : 'Registration failed')
|
|
} finally {
|
|
setLoading(false)
|
|
}
|
|
}
|
|
|
|
return (
|
|
<div className="min-h-screen flex relative">
|
|
{/* Ambient glow */}
|
|
<div className="fixed inset-0 pointer-events-none">
|
|
<div className="absolute top-1/4 left-1/3 w-[400px] h-[300px] bg-accent/[0.02] rounded-full blur-3xl" />
|
|
</div>
|
|
|
|
{/* Left Panel - Form */}
|
|
<div className="flex-1 flex items-center justify-center px-4 sm:px-6 py-8 sm:py-12">
|
|
<div className="relative w-full max-w-sm animate-fade-in">
|
|
{/* Logo */}
|
|
<Link href="/" className="block mb-12 sm:mb-16 hover:opacity-80 transition-opacity duration-300">
|
|
<Logo />
|
|
</Link>
|
|
|
|
{/* Header */}
|
|
<div className="mb-8 sm:mb-10">
|
|
<h1 className="font-display text-[2rem] sm:text-[2.5rem] md:text-[3rem] leading-[1.1] tracking-[-0.03em] text-foreground mb-2 sm:mb-3">Create your account</h1>
|
|
<p className="text-body-sm sm:text-body text-foreground-muted">
|
|
Start monitoring domains in under a minute
|
|
</p>
|
|
</div>
|
|
|
|
{/* Form */}
|
|
<form onSubmit={handleSubmit} className="space-y-3 sm:space-y-4">
|
|
{error && (
|
|
<div className="p-3 sm:p-4 bg-danger-muted border border-danger/20 rounded-2xl">
|
|
<p className="text-danger text-body-xs sm:text-body-sm">{error}</p>
|
|
</div>
|
|
)}
|
|
|
|
<div className="space-y-2.5 sm:space-y-3">
|
|
<input
|
|
type="email"
|
|
value={email}
|
|
onChange={(e) => setEmail(e.target.value)}
|
|
placeholder="Email address"
|
|
required
|
|
className="input-elegant text-body-sm sm:text-body"
|
|
/>
|
|
<div className="relative">
|
|
<input
|
|
type={showPassword ? 'text' : 'password'}
|
|
value={password}
|
|
onChange={(e) => setPassword(e.target.value)}
|
|
placeholder="Create password (min. 8 characters)"
|
|
required
|
|
minLength={8}
|
|
className="input-elegant text-body-sm sm:text-body pr-12"
|
|
/>
|
|
<button
|
|
type="button"
|
|
onClick={() => setShowPassword(!showPassword)}
|
|
className="absolute right-3 sm:right-4 top-1/2 -translate-y-1/2 text-foreground-muted hover:text-foreground transition-colors duration-200"
|
|
aria-label={showPassword ? 'Hide password' : 'Show password'}
|
|
>
|
|
{showPassword ? (
|
|
<EyeOff className="w-4 h-4 sm:w-5 sm:h-5" />
|
|
) : (
|
|
<Eye className="w-4 h-4 sm:w-5 sm:h-5" />
|
|
)}
|
|
</button>
|
|
</div>
|
|
</div>
|
|
|
|
<button
|
|
type="submit"
|
|
disabled={loading}
|
|
className="w-full py-3 sm:py-4 bg-foreground text-background text-ui-sm sm:text-ui font-medium rounded-xl
|
|
hover:bg-foreground/90 disabled:opacity-50 disabled:cursor-not-allowed
|
|
transition-all duration-300 flex items-center justify-center gap-2 sm:gap-2.5"
|
|
>
|
|
{loading ? (
|
|
<Loader2 className="w-4 h-4 animate-spin" />
|
|
) : (
|
|
<>
|
|
Get Started
|
|
<ArrowRight className="w-3.5 sm:w-4 h-3.5 sm:h-4" />
|
|
</>
|
|
)}
|
|
</button>
|
|
</form>
|
|
|
|
{/* Login Link */}
|
|
<p className="mt-8 sm:mt-10 text-body-xs sm:text-body-sm text-foreground-muted">
|
|
Already have an account?{' '}
|
|
<Link href="/login" className="text-foreground hover:text-accent transition-colors duration-300">
|
|
Sign in
|
|
</Link>
|
|
</p>
|
|
</div>
|
|
</div>
|
|
|
|
{/* Right Panel - Benefits */}
|
|
<div className="hidden lg:flex flex-1 bg-background-secondary/50 items-center justify-center p-8 xl:p-12 border-l border-border-subtle">
|
|
<div className="max-w-sm animate-slide-up delay-200">
|
|
<div className="inline-flex items-center gap-2 sm:gap-2.5 px-3 sm:px-4 py-1.5 sm:py-2 bg-background-tertiary border border-border rounded-full mb-8 sm:mb-10">
|
|
<div className="w-1.5 h-1.5 rounded-full bg-accent" />
|
|
<span className="text-ui-sm sm:text-ui text-foreground-muted">Free Plan Included</span>
|
|
</div>
|
|
|
|
<h2 className="font-display text-[1.75rem] sm:text-[2.25rem] md:text-[2.75rem] leading-[1.15] tracking-[-0.025em] text-foreground mb-8 sm:mb-10">
|
|
Everything you need to get started
|
|
</h2>
|
|
|
|
<ul className="space-y-4 sm:space-y-5">
|
|
{benefits.map((item) => (
|
|
<li key={item} className="flex items-center gap-3 sm:gap-4">
|
|
<div className="w-8 sm:w-9 h-8 sm:h-9 rounded-lg bg-accent/10 flex items-center justify-center shrink-0">
|
|
<Check className="w-3.5 sm:w-4 h-3.5 sm:h-4 text-accent" strokeWidth={2.5} />
|
|
</div>
|
|
<span className="text-body-sm sm:text-body text-foreground-muted">{item}</span>
|
|
</li>
|
|
))}
|
|
</ul>
|
|
|
|
<div className="divider my-8 sm:my-10" />
|
|
|
|
<p className="text-body-xs sm:text-body-sm text-foreground-subtle">
|
|
No credit card required. Upgrade anytime.
|
|
</p>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
)
|
|
}
|