This commit is contained in:
2025-12-03 16:33:12 +01:00
parent a572e6edce
commit c0fdae3d3c
157 changed files with 7824 additions and 1042 deletions

View File

@@ -2,9 +2,14 @@
import { getAppMode } from '@/lib/mode';
import { useRouter } from 'next/navigation';
import { useEffect, useState } from 'react';
import Card from '@/components/ui/Card';
import Button from '@/components/ui/Button';
import CompanionStatus from '@/components/alpha/CompanionStatus';
import DataWarning from '@/components/alpha/DataWarning';
import RaceCard from '@/components/alpha/RaceCard';
import LeagueCard from '@/components/alpha/LeagueCard';
import TeamCard from '@/components/alpha/TeamCard';
import Hero from '@/components/landing/Hero';
import AlternatingSection from '@/components/landing/AlternatingSection';
import FeatureGrid from '@/components/landing/FeatureGrid';
@@ -16,12 +21,164 @@ import RaceHistoryMockup from '@/components/mockups/RaceHistoryMockup';
import CompanionAutomationMockup from '@/components/mockups/CompanionAutomationMockup';
import SimPlatformMockup from '@/components/mockups/SimPlatformMockup';
import MockupStack from '@/components/ui/MockupStack';
import { getRaceRepository, getLeagueRepository } from '@/lib/di-container';
import { getAllTeams, getTeamMembers } from '@/lib/team-data';
import { getLeagueMembers } from '@/lib/membership-data';
import type { Race } from '@gridpilot/racing-domain/entities/Race';
import type { League } from '@gridpilot/racing-domain/entities/League';
function AlphaDashboard() {
const router = useRouter();
const [upcomingRaces, setUpcomingRaces] = useState<Race[]>([]);
const [topLeagues, setTopLeagues] = useState<League[]>([]);
const [featuredTeams, setFeaturedTeams] = useState<any[]>([]);
const [recentActivity, setRecentActivity] = useState<any[]>([]);
useEffect(() => {
const raceRepo = getRaceRepository();
const leagueRepo = getLeagueRepository();
// Get upcoming races
raceRepo.findAll().then(races => {
const upcoming = races
.filter(r => r.status === 'scheduled')
.sort((a, b) => new Date(a.scheduledAt).getTime() - new Date(b.scheduledAt).getTime())
.slice(0, 5);
setUpcomingRaces(upcoming);
});
// Get top leagues
leagueRepo.findAll().then(leagues => {
const sorted = leagues
.map(league => ({
league,
memberCount: getLeagueMembers(league.id).length,
}))
.sort((a, b) => b.memberCount - a.memberCount)
.slice(0, 4)
.map(item => item.league);
setTopLeagues(sorted);
});
// Get featured teams
const teams = getAllTeams();
const featured = teams
.map(team => ({
...team,
memberCount: getTeamMembers(team.id).length,
}))
.sort((a, b) => b.memberCount - a.memberCount)
.slice(0, 4);
setFeaturedTeams(featured);
// Generate recent activity
const activities = [
{ type: 'race', text: 'Max Verstappen won at Monza GP', time: '2 hours ago' },
{ type: 'join', text: 'Lando Norris joined European GT Championship', time: '5 hours ago' },
{ type: 'team', text: 'Charles Leclerc joined Weekend Warriors', time: '1 day ago' },
{ type: 'race', text: 'Upcoming: Spa-Francorchamps in 2 days', time: '2 days ago' },
{ type: 'league', text: 'European GT Championship: 4 active members', time: '3 days ago' },
];
setRecentActivity(activities);
}, []);
return (
<div className="max-w-4xl mx-auto">
<div className="max-w-7xl mx-auto">
<DataWarning />
{/* Upcoming Races Section */}
{upcomingRaces.length > 0 && (
<div className="mb-12">
<div className="flex items-center justify-between mb-6">
<h2 className="text-3xl font-bold text-white">Upcoming Races</h2>
<Button variant="secondary" onClick={() => router.push('/races')}>
View All Races
</Button>
</div>
<div className="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-4">
{upcomingRaces.slice(0, 3).map(race => (
<RaceCard
key={race.id}
race={race}
onClick={() => router.push(`/races/${race.id}`)}
/>
))}
</div>
</div>
)}
{/* Top Leagues Section */}
{topLeagues.length > 0 && (
<div className="mb-12">
<div className="flex items-center justify-between mb-6">
<h2 className="text-3xl font-bold text-white">Top Leagues</h2>
<Button variant="secondary" onClick={() => router.push('/leagues')}>
Browse Leagues
</Button>
</div>
<div className="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-4 gap-4">
{topLeagues.map(league => (
<LeagueCard
key={league.id}
league={league}
onClick={() => router.push(`/leagues/${league.id}`)}
/>
))}
</div>
</div>
)}
{/* Featured Teams Section */}
{featuredTeams.length > 0 && (
<div className="mb-12">
<div className="flex items-center justify-between mb-6">
<h2 className="text-3xl font-bold text-white">Featured Teams</h2>
<Button variant="secondary" onClick={() => router.push('/teams')}>
Browse Teams
</Button>
</div>
<div className="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-4 gap-4">
{featuredTeams.map(team => (
<TeamCard
key={team.id}
id={team.id}
name={team.name}
logo={undefined}
memberCount={team.memberCount}
leagues={team.leagues}
onClick={() => router.push(`/teams/${team.id}`)}
/>
))}
</div>
</div>
)}
{/* Recent Activity Section */}
{recentActivity.length > 0 && (
<div className="mb-12">
<h2 className="text-3xl font-bold text-white mb-6">Recent Activity</h2>
<Card>
<div className="space-y-4">
{recentActivity.map((activity, idx) => (
<div
key={idx}
className={`flex items-start gap-3 pb-4 ${
idx < recentActivity.length - 1 ? 'border-b border-charcoal-outline' : ''
}`}
>
<div className="w-2 h-2 rounded-full bg-primary-blue mt-2 flex-shrink-0" />
<div className="flex-1">
<p className="text-sm text-gray-300">{activity.text}</p>
<p className="text-xs text-gray-500 mt-1">{activity.time}</p>
</div>
</div>
))}
</div>
</Card>
</div>
)}
<div className="max-w-4xl mx-auto">
{/* Welcome Header */}
<div className="mb-8">
<h1 className="text-4xl font-bold text-white mb-4">GridPilot Alpha</h1>
@@ -274,6 +431,7 @@ function AlphaDashboard() {
</Card>
</div>
</div>
</div>
</div>
);
}