Files
gridpilot.gg/apps/website/app/sponsor/signup/page.tsx
2025-12-10 12:38:55 +01:00

429 lines
15 KiB
TypeScript

'use client';
import { useState } from 'react';
import { useRouter } from 'next/navigation';
import Card from '@/components/ui/Card';
import Button from '@/components/ui/Button';
import Input from '@/components/ui/Input';
import { Building2, Mail, Globe, Upload, Zap, Eye, TrendingUp, Users, ArrowRight } from 'lucide-react';
export default function SponsorSignupPage() {
const router = useRouter();
const [mode, setMode] = useState<'landing' | 'signup' | 'login'>('landing');
const [formData, setFormData] = useState({
name: '',
contactEmail: '',
websiteUrl: '',
logoFile: null as File | null,
password: '',
});
const [errors, setErrors] = useState<Record<string, string>>({});
const [submitting, setSubmitting] = useState(false);
const handleDemoLogin = async () => {
setSubmitting(true);
try {
// Demo: Set cookie to indicate sponsor mode
document.cookie = 'gridpilot_demo_mode=sponsor; path=/; max-age=86400';
document.cookie = 'gridpilot_sponsor_id=demo-sponsor-1; path=/; max-age=86400';
await new Promise(resolve => setTimeout(resolve, 500));
router.push('/leagues');
} finally {
setSubmitting(false);
}
};
const handleSubmit = async (e: React.FormEvent) => {
e.preventDefault();
const newErrors: Record<string, string> = {};
if (!formData.name.trim()) {
newErrors.name = 'Company name required';
}
if (!formData.contactEmail.trim()) {
newErrors.contactEmail = 'Contact email required';
} else if (!/^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(formData.contactEmail)) {
newErrors.contactEmail = 'Invalid email format';
}
if (mode === 'signup' && !formData.password.trim()) {
newErrors.password = 'Password required';
}
if (Object.keys(newErrors).length > 0) {
setErrors(newErrors);
return;
}
setSubmitting(true);
try {
// Alpha: In-memory only, set demo sponsor cookie
console.log('Sponsor signup:', formData);
document.cookie = 'gridpilot_demo_mode=sponsor; path=/; max-age=86400';
document.cookie = `gridpilot_sponsor_name=${encodeURIComponent(formData.name)}; path=/; max-age=86400`;
await new Promise(resolve => setTimeout(resolve, 800));
router.push('/leagues');
} catch (err) {
console.error('Sponsor signup failed:', err);
alert('Registration failed. Try again.');
} finally {
setSubmitting(false);
}
};
// Landing page for sponsors
if (mode === 'landing') {
return (
<div className="max-w-4xl mx-auto py-12">
{/* Hero */}
<div className="text-center mb-12">
<div className="flex justify-center mb-6">
<div className="flex h-16 w-16 items-center justify-center rounded-2xl bg-primary-blue/10">
<Building2 className="w-8 h-8 text-primary-blue" />
</div>
</div>
<h1 className="text-4xl font-bold text-white mb-4">Sponsor Sim Racing Leagues</h1>
<p className="text-lg text-gray-400 max-w-2xl mx-auto">
Connect your brand with passionate sim racing communities. Get exposure through liveries, league branding, and engaged audiences.
</p>
</div>
{/* Benefits */}
<div className="grid grid-cols-1 md:grid-cols-3 gap-6 mb-12">
<Card>
<div className="flex flex-col items-center text-center">
<div className="flex h-12 w-12 items-center justify-center rounded-xl bg-primary-blue/10 mb-4">
<Eye className="w-6 h-6 text-primary-blue" />
</div>
<h3 className="text-lg font-semibold text-white mb-2">Brand Exposure</h3>
<p className="text-sm text-gray-400">
Your logo on liveries, league pages, and race broadcasts. Reach thousands of dedicated sim racers.
</p>
</div>
</Card>
<Card>
<div className="flex flex-col items-center text-center">
<div className="flex h-12 w-12 items-center justify-center rounded-xl bg-performance-green/10 mb-4">
<TrendingUp className="w-6 h-6 text-performance-green" />
</div>
<h3 className="text-lg font-semibold text-white mb-2">Analytics Dashboard</h3>
<p className="text-sm text-gray-400">
Track impressions, clicks, and engagement. See exactly how your sponsorship performs.
</p>
</div>
</Card>
<Card>
<div className="flex flex-col items-center text-center">
<div className="flex h-12 w-12 items-center justify-center rounded-xl bg-warning-amber/10 mb-4">
<Users className="w-6 h-6 text-warning-amber" />
</div>
<h3 className="text-lg font-semibold text-white mb-2">Engaged Audience</h3>
<p className="text-sm text-gray-400">
Connect with a passionate, tech-savvy community that values authentic partnerships.
</p>
</div>
</Card>
</div>
{/* CTA Buttons */}
<div className="flex flex-col sm:flex-row gap-4 justify-center mb-8">
<Button
variant="primary"
onClick={() => setMode('signup')}
className="px-8 py-3"
>
<Building2 className="w-5 h-5 mr-2" />
Create Sponsor Account
</Button>
<Button
variant="secondary"
onClick={() => setMode('login')}
className="px-8 py-3"
>
Sign In
<ArrowRight className="w-5 h-5 ml-2" />
</Button>
</div>
{/* Demo Login */}
<div className="text-center">
<div className="inline-flex items-center gap-2 px-4 py-2 rounded-full bg-iron-gray/50 border border-charcoal-outline">
<Zap className="w-4 h-4 text-warning-amber" />
<span className="text-sm text-gray-400">Try it now:</span>
<button
onClick={handleDemoLogin}
disabled={submitting}
className="text-sm font-medium text-primary-blue hover:text-primary-blue/80 transition-colors disabled:opacity-50"
>
{submitting ? 'Loading...' : 'Demo Sponsor Login'}
</button>
</div>
</div>
{/* Alpha Notice */}
<div className="mt-12 rounded-lg bg-warning-amber/10 border border-warning-amber/30 p-4">
<p className="text-xs text-gray-400 text-center">
<strong className="text-warning-amber">Alpha Preview:</strong> Sponsorship features are demonstration-only.
In production, you'll have access to payment processing, detailed analytics, and automated livery placement.
</p>
</div>
</div>
);
}
// Login form
if (mode === 'login') {
return (
<div className="max-w-md mx-auto py-12">
<div className="mb-8">
<button
onClick={() => setMode('landing')}
className="text-sm text-gray-400 hover:text-white mb-4"
>
← Back
</button>
<div className="flex items-center gap-3 mb-4">
<div className="flex h-12 w-12 items-center justify-center rounded-xl bg-primary-blue/10">
<Building2 className="w-6 h-6 text-primary-blue" />
</div>
<div>
<h1 className="text-2xl font-bold text-white">Sponsor Sign In</h1>
<p className="text-sm text-gray-400">Access your sponsor dashboard</p>
</div>
</div>
</div>
<Card>
<form onSubmit={handleSubmit} className="space-y-6">
<div>
<label className="block text-sm font-medium text-gray-300 mb-2">
<div className="flex items-center gap-2">
<Mail className="w-4 h-4 text-gray-500" />
Email
</div>
</label>
<Input
type="email"
value={formData.contactEmail}
onChange={(e) => setFormData({ ...formData, contactEmail: e.target.value })}
placeholder="sponsor@company.com"
error={!!errors.contactEmail}
errorMessage={errors.contactEmail}
/>
</div>
<div>
<label className="block text-sm font-medium text-gray-300 mb-2">
Password
</label>
<Input
type="password"
value={formData.password}
onChange={(e) => setFormData({ ...formData, password: e.target.value })}
placeholder="••••••••"
error={!!errors.password}
errorMessage={errors.password}
/>
</div>
<Button
type="submit"
variant="primary"
disabled={submitting}
className="w-full"
>
{submitting ? 'Signing in...' : 'Sign In'}
</Button>
</form>
<div className="mt-6 pt-6 border-t border-charcoal-outline text-center">
<p className="text-sm text-gray-400">
Don't have an account?{' '}
<button
onClick={() => setMode('signup')}
className="text-primary-blue hover:text-primary-blue/80"
>
Create one
</button>
</p>
</div>
<div className="mt-4 text-center">
<button
onClick={handleDemoLogin}
disabled={submitting}
className="text-sm text-gray-500 hover:text-gray-400"
>
Or use demo login
</button>
</div>
</Card>
</div>
);
}
// Signup form
return (
<div className="max-w-2xl mx-auto py-12">
{/* Header */}
<div className="mb-8">
<button
onClick={() => setMode('landing')}
className="text-sm text-gray-400 hover:text-white mb-4"
>
Back
</button>
<div className="flex items-center gap-3 mb-4">
<div className="flex h-12 w-12 items-center justify-center rounded-xl bg-primary-blue/10">
<Building2 className="w-6 h-6 text-primary-blue" />
</div>
<div>
<h1 className="text-2xl font-bold text-white">Create Sponsor Account</h1>
<p className="text-sm text-gray-400">Register your company to sponsor leagues</p>
</div>
</div>
</div>
<Card>
<form onSubmit={handleSubmit} className="space-y-6">
{/* Company Name */}
<div>
<label className="block text-sm font-medium text-gray-300 mb-2">
Company Name
</label>
<Input
type="text"
value={formData.name}
onChange={(e) => setFormData({ ...formData, name: e.target.value })}
placeholder="Your company name"
error={!!errors.name}
errorMessage={errors.name}
/>
</div>
{/* Contact Email */}
<div>
<label className="block text-sm font-medium text-gray-300 mb-2">
<div className="flex items-center gap-2">
<Mail className="w-4 h-4 text-gray-500" />
Contact Email
</div>
</label>
<Input
type="email"
value={formData.contactEmail}
onChange={(e) => setFormData({ ...formData, contactEmail: e.target.value })}
placeholder="sponsor@company.com"
error={!!errors.contactEmail}
errorMessage={errors.contactEmail}
/>
</div>
{/* Website URL */}
<div>
<label className="block text-sm font-medium text-gray-300 mb-2">
<div className="flex items-center gap-2">
<Globe className="w-4 h-4 text-gray-500" />
Website URL (optional)
</div>
</label>
<Input
type="url"
value={formData.websiteUrl}
onChange={(e) => setFormData({ ...formData, websiteUrl: e.target.value })}
placeholder="https://company.com"
/>
</div>
{/* Logo Upload */}
<div>
<label className="block text-sm font-medium text-gray-300 mb-2">
<div className="flex items-center gap-2">
<Upload className="w-4 h-4 text-gray-500" />
Company Logo (optional)
</div>
</label>
<div className="flex items-center gap-3">
<input
type="file"
accept="image/png,image/jpeg,image/svg+xml"
onChange={(e) => {
const file = e.target.files?.[0] || null;
setFormData({ ...formData, logoFile: file });
}}
className="block w-full text-sm text-gray-400 file:mr-4 file:py-2 file:px-4 file:rounded-full file:border-0 file:text-sm file:font-semibold file:bg-primary-blue/10 file:text-primary-blue hover:file:bg-primary-blue/20"
/>
</div>
<p className="text-xs text-gray-500 mt-1">
PNG, JPEG, or SVG. Recommended: 500x500px transparent background.
</p>
</div>
{/* Password */}
<div>
<label className="block text-sm font-medium text-gray-300 mb-2">
Password
</label>
<Input
type="password"
value={formData.password}
onChange={(e) => setFormData({ ...formData, password: e.target.value })}
placeholder="Create a password"
error={!!errors.password}
errorMessage={errors.password}
/>
</div>
{/* Alpha Notice */}
<div className="rounded-lg bg-warning-amber/10 border border-warning-amber/30 p-4">
<p className="text-xs text-gray-400">
<strong className="text-warning-amber">Alpha Note:</strong> Sponsor registration is demonstration-only.
In production, you'll have access to full payment processing and analytics.
</p>
</div>
{/* Actions */}
<div className="flex gap-3 pt-4">
<Button
type="submit"
variant="primary"
disabled={submitting}
className="flex-1"
>
{submitting ? 'Creating Account...' : 'Create Account'}
</Button>
<Button
type="button"
variant="secondary"
onClick={() => setMode('landing')}
disabled={submitting}
>
Cancel
</Button>
</div>
</form>
<div className="mt-6 pt-6 border-t border-charcoal-outline text-center">
<p className="text-sm text-gray-400">
Already have an account?{' '}
<button
onClick={() => setMode('login')}
className="text-primary-blue hover:text-primary-blue/80"
>
Sign in
</button>
</p>
</div>
</Card>
</div>
);
}