216 lines
6.9 KiB
TypeScript

// app/page.tsx
// Homepage - navbar/footer now in layout.tsx
import Link from 'next/link';
import { query } from '@/lib/db';
import { TrophyIcon, ChartIcon, CircleIcon, UsersIcon, ServerIcon, ActivityIcon } from '@/components/ui/icons';
export const dynamic = "force-dynamic";
async function getStats() {
const driversOnline = await query(`
SELECT COUNT(*) as count
FROM users
WHERE is_connect = true
`);
const totalDrivers = await query(`
SELECT COUNT(*) as count
FROM users
`);
const activeServers = await query(`
SELECT COUNT(DISTINCT server_id) as count
FROM servers
WHERE connected_players > 0
`);
return {
driversOnline: driversOnline[0]?.count || 0,
totalDrivers: totalDrivers[0]?.count || 0,
activeServers: activeServers[0]?.count || 0,
};
}
export default async function HomePage() {
const stats = await getStats();
return (
<>
{/* Hero */}
<div className="relative border-b border-white/10">
<div className="absolute inset-0 grid-overlay opacity-50"></div>
<div className="max-w-7xl mx-auto px-6 py-32 relative">
<div className="text-center space-y-8">
{/* Logo */}
<div className="flex justify-center mb-8">
<img
src="https://files.openwheels.racing/img/Openwheels_landscape.svg"
alt="OpenWheels"
className="h-24 brightness-0 invert"
/>
</div>
{/* Tagline */}
<div className="space-y-4">
<h1 className="text-7xl font-bold tracking-tight leading-none">
FREE RACING.<br/>
NO BARRIERS.
</h1>
<p className="text-xl text-white/60 max-w-2xl mx-auto leading-relaxed">
Join our community of passionate racers. Compete in multiple leagues,
track your progress, and race for free on dedicated infrastructure.
</p>
</div>
{/* CTA */}
<div className="flex items-center justify-center space-x-4 pt-8">
<Link
href="/dashboard"
className="px-8 py-4 border-2 border-white hover:bg-white hover:text-[#0a0a0a] transition-all text-base font-medium"
>
VIEW DASHBOARD
</Link>
<a
href="https://discord.gg/nvuB8EvT9P"
target="_blank"
rel="noopener noreferrer"
className="px-8 py-4 border border-white/30 hover:border-white transition-all text-base"
>
JOIN COMMUNITY
</a>
</div>
</div>
{/* Live Stats */}
<div className="grid grid-cols-1 md:grid-cols-3 gap-4 mt-24">
<LiveStatCard
value={stats.driversOnline}
label="ONLINE NOW"
icon={<UsersIcon />}
/>
<LiveStatCard
value={stats.activeServers}
label="ACTIVE SERVERS"
icon={<ServerIcon />}
/>
<LiveStatCard
value={stats.totalDrivers}
label="TOTAL DRIVERS"
icon={<ActivityIcon />}
/>
</div>
</div>
</div>
{/* Features Grid */}
<div className="max-w-7xl mx-auto px-6 py-24">
<div className="text-center mb-20">
<h2 className="text-5xl font-bold tracking-tight mb-4">
INFRASTRUCTURE
</h2>
<p className="text-white/60 text-lg">
Everything required for competitive sim racing
</p>
</div>
<div className="grid grid-cols-1 md:grid-cols-3 gap-6">
<FeatureCard
icon={<TrophyIcon className="w-10 h-10" />}
title="MULTIPLE LEAGUES"
description="Progress through skill-based divisions. C-Class to Pro level competition across all disciplines."
/>
<FeatureCard
icon={<ChartIcon className="w-10 h-10" />}
title="LIVE RANKINGS"
description="Real-time performance tracking. Transparent ELO system with historical data and statistics."
/>
<FeatureCard
icon={<CircleIcon className="w-10 h-10" />}
title="FREE ACCESS"
description="No subscriptions. No hidden costs. Open infrastructure for the racing community."
/>
<FeatureCard
icon={<TrophyIcon className="w-10 h-10" />}
title="WEATHER SYSTEMS"
description="Dynamic conditions. Rain, dry, variable grip. Test your adaptability in all scenarios."
/>
<FeatureCard
icon={<ActivityIcon className="w-10 h-10" />}
title="MULTIPLE CLASSES"
description="MX5, GT4, GT3 categories. Different cars for different racing philosophies and styles."
/>
<FeatureCard
icon={<UsersIcon className="w-10 h-10" />}
title="ACTIVE COMMUNITY"
description="Discord integration. Event organization, race coordination, and community engagement tools."
/>
</div>
</div>
{/* System Status */}
<div className="border-t border-white/10">
<div className="max-w-7xl mx-auto px-6 py-12">
<div className="flex items-center justify-between">
<div className="flex items-center space-x-3">
<div className="w-2 h-2 bg-white rounded-full animate-pulse"></div>
<span className="text-xs tracking-wider text-white/60">SYSTEM OPERATIONAL</span>
</div>
<div className="text-xs text-white/40 font-mono">
v2.0.0 | UPTIME: 99.9%
</div>
</div>
</div>
</div>
</>
);
}
function LiveStatCard({
value,
label,
icon
}: {
value: number;
label: string;
icon: React.ReactNode;
}) {
return (
<div className="border border-white/10 p-8 sharp-border">
<div className="flex items-center justify-between mb-4">
<div className="text-white/40">
{icon}
</div>
<div className="w-2 h-2 bg-white rounded-full animate-pulse"></div>
</div>
<div className="text-5xl font-bold tracking-tight mb-2">
{value.toLocaleString()}
</div>
<div className="text-sm text-white/60 tracking-wider font-medium">
{label}
</div>
</div>
);
}
function FeatureCard({
icon,
title,
description
}: {
icon: React.ReactNode;
title: string;
description: string;
}) {
return (
<div className="border border-white/10 p-8 sharp-border topo-lines-dense bg-black">
<div className="mb-6 text-white/80">
{icon}
</div>
<h3 className="text-xl font-bold tracking-tight mb-3">{title}</h3>
<p className="text-white/60 leading-relaxed">{description}</p>
</div>
);
}