'use client'; import { useState, useEffect } from 'react'; import { useRouter } from 'next/navigation'; import { Users, Trophy, Search, Plus, Sparkles, Crown, Star, TrendingUp, Shield, Zap, UserPlus, ChevronRight, Timer, Target, Award, Handshake, MessageCircle, Calendar, } from 'lucide-react'; import TeamCard from '@/components/teams/TeamCard'; import Button from '@/components/ui/Button'; import Card from '@/components/ui/Card'; import Input from '@/components/ui/Input'; import Heading from '@/components/ui/Heading'; import CreateTeamForm from '@/components/teams/CreateTeamForm'; import { getGetTeamsLeaderboardUseCase } from '@/lib/di-container'; import { TeamsLeaderboardPresenter } from '@/lib/presenters/TeamsLeaderboardPresenter'; import type { TeamLeaderboardItemViewModel, SkillLevel } from '@gridpilot/racing/application/presenters/ITeamsLeaderboardPresenter'; // ============================================================================ // TYPES // ============================================================================ type TeamDisplayData = TeamLeaderboardItemViewModel; // ============================================================================ // SKILL LEVEL CONFIG // ============================================================================ const SKILL_LEVELS: { id: SkillLevel; label: string; icon: React.ElementType; color: string; bgColor: string; borderColor: string; description: string; }[] = [ { id: 'pro', label: 'Pro', icon: Crown, color: 'text-yellow-400', bgColor: 'bg-yellow-400/10', borderColor: 'border-yellow-400/30', description: 'Elite competition, sponsored teams', }, { id: 'advanced', label: 'Advanced', icon: Star, color: 'text-purple-400', bgColor: 'bg-purple-400/10', borderColor: 'border-purple-400/30', description: 'Competitive racing, high consistency', }, { id: 'intermediate', label: 'Intermediate', icon: TrendingUp, color: 'text-primary-blue', bgColor: 'bg-primary-blue/10', borderColor: 'border-primary-blue/30', description: 'Growing skills, regular practice', }, { id: 'beginner', label: 'Beginner', icon: Shield, color: 'text-green-400', bgColor: 'bg-green-400/10', borderColor: 'border-green-400/30', description: 'Learning the basics, friendly environment', }, ]; // ============================================================================ // WHY JOIN A TEAM SECTION // ============================================================================ function WhyJoinTeamSection() { const benefits = [ { icon: Handshake, title: 'Shared Strategy', description: 'Develop setups together, share telemetry, and coordinate pit strategies for endurance races.', }, { icon: MessageCircle, title: 'Team Communication', description: 'Discord integration, voice chat during races, and dedicated team channels.', }, { icon: Calendar, title: 'Coordinated Schedule', description: 'Team calendars, practice sessions, and organized race attendance.', }, { icon: Trophy, title: 'Team Championships', description: 'Compete in team-based leagues and build your collective reputation.', }, ]; return (

Why Join a Team?

Racing is better when you have teammates to share the journey

{benefits.map((benefit) => (

{benefit.title}

{benefit.description}

))}
); } // ============================================================================ // SKILL LEVEL SECTION COMPONENT // ============================================================================ interface SkillLevelSectionProps { level: typeof SKILL_LEVELS[0]; teams: TeamDisplayData[]; onTeamClick: (id: string) => void; defaultExpanded?: boolean; } function SkillLevelSection({ level, teams, onTeamClick, defaultExpanded = false }: SkillLevelSectionProps) { const [isExpanded, setIsExpanded] = useState(defaultExpanded); const recruitingTeams = teams.filter((t) => t.isRecruiting); const displayedTeams = isExpanded ? teams : teams.slice(0, 3); const Icon = level.icon; if (teams.length === 0) return null; return (
{/* Section Header */}

{level.label}

{teams.length} {teams.length === 1 ? 'team' : 'teams'} {recruitingTeams.length > 0 && ( {recruitingTeams.length} recruiting )}

{level.description}

{teams.length > 3 && ( )}
{/* Teams Grid */}
{displayedTeams.map((team) => ( onTeamClick(team.id)} /> ))}
); } // ============================================================================ // FEATURED RECRUITING TEAMS // ============================================================================ interface FeaturedRecruitingProps { teams: TeamDisplayData[]; onTeamClick: (id: string) => void; } function FeaturedRecruiting({ teams, onTeamClick }: FeaturedRecruitingProps) { const recruitingTeams = teams.filter((t) => t.isRecruiting).slice(0, 4); if (recruitingTeams.length === 0) return null; return (

Looking for Drivers

Teams actively recruiting new members

{recruitingTeams.map((team) => { const levelConfig = SKILL_LEVELS.find((l) => l.id === team.performanceLevel); const LevelIcon = levelConfig?.icon || Shield; return ( ); })}
); } // ============================================================================ // TEAM LEADERBOARD PREVIEW COMPONENT (Top 5 + Link) // ============================================================================ interface TeamLeaderboardPreviewProps { topTeams: TeamDisplayData[]; onTeamClick: (id: string) => void; } function TeamLeaderboardPreview({ topTeams, onTeamClick }: TeamLeaderboardPreviewProps) { const router = useRouter(); const getMedalColor = (position: number) => { switch (position) { case 0: return 'text-yellow-400'; case 1: return 'text-gray-300'; case 2: return 'text-amber-600'; default: return 'text-gray-500'; } }; const getMedalBg = (position: number) => { switch (position) { case 0: return 'bg-yellow-400/10 border-yellow-400/30'; case 1: return 'bg-gray-300/10 border-gray-300/30'; case 2: return 'bg-amber-600/10 border-amber-600/30'; default: return 'bg-iron-gray/50 border-charcoal-outline'; } }; if (topTeams.length === 0) return null; return (
{/* Header */}

Top Teams

Highest rated racing teams

{/* Compact Leaderboard */}
{topTeams.map((team, index) => { const levelConfig = SKILL_LEVELS.find((l) => l.id === team.performanceLevel); const LevelIcon = levelConfig?.icon || Shield; return ( ); })}
); } // ============================================================================ // MAIN PAGE COMPONENT // ============================================================================ export default function TeamsPage() { const router = useRouter(); const [realTeams, setRealTeams] = useState([]); const [groupsBySkillLevel, setGroupsBySkillLevel] = useState>({ beginner: [], intermediate: [], advanced: [], pro: [], }); const [topTeams, setTopTeams] = useState([]); const [loading, setLoading] = useState(true); const [searchQuery, setSearchQuery] = useState(''); const [showCreateForm, setShowCreateForm] = useState(false); useEffect(() => { loadTeams(); }, []); const loadTeams = async () => { try { const useCase = getGetTeamsLeaderboardUseCase(); const presenter = new TeamsLeaderboardPresenter(); await useCase.execute(undefined as void, presenter); const viewModel = presenter.getViewModel(); if (viewModel) { setRealTeams(viewModel.teams); setGroupsBySkillLevel(viewModel.groupsBySkillLevel); setTopTeams(viewModel.topTeams); } } catch (error) { console.error('Failed to load teams:', error); } finally { setLoading(false); } }; const teams = realTeams; const handleTeamClick = (teamId: string) => { if (teamId.startsWith('demo-team-')) { return; } router.push(`/teams/${teamId}`); }; const handleCreateSuccess = (teamId: string) => { setShowCreateForm(false); void loadTeams(); router.push(`/teams/${teamId}`); }; // Filter by search query const filteredTeams = teams.filter((team) => { if (!searchQuery) return true; const query = searchQuery.toLowerCase(); return ( team.name.toLowerCase().includes(query) || (team.description ?? '').toLowerCase().includes(query) || (team.region ?? '').toLowerCase().includes(query) || (team.languages ?? []).some((lang) => lang.toLowerCase().includes(query)) ); }); // Group teams by skill level const teamsByLevel: Record = SKILL_LEVELS.reduce( (acc, level) => { const fromGroup = groupsBySkillLevel[level.id] ?? []; acc[level.id] = filteredTeams.filter((team) => fromGroup.some((groupTeam) => groupTeam.id === team.id), ); return acc; }, { beginner: [], intermediate: [], advanced: [], pro: [], } as Record, ); const recruitingCount = teams.filter((t) => t.isRecruiting).length; if (showCreateForm) { return (

Create New Team

setShowCreateForm(false)} onSuccess={handleCreateSuccess} />
); } if (loading) { return (

Loading teams...

); } return (
{/* Hero Section - Different from Leagues */}
{/* Main Hero Card */}
{/* Background decorations */}
{/* Badge */}
Team Racing
Find Your Crew

Solo racing is great. Team racing is unforgettable. Join a team that matches your skill level and ambitions.

{/* Quick Stats */}
{teams.length} Teams
{recruitingCount} Recruiting
{/* CTA Buttons */}
{/* Skill Level Quick Nav */}

Find Your Level

{SKILL_LEVELS.map((level) => { const LevelIcon = level.icon; const count = teamsByLevel[level.id]?.length || 0; return ( ); })}
{/* Search and Filter Bar - Same style as Leagues */}
{/* Search */}
setSearchQuery(e.target.value)} className="pl-11" />
{/* Why Join Section */} {!searchQuery && } {/* Team Leaderboard Preview */} {!searchQuery && } {/* Featured Recruiting */} {!searchQuery && } {/* Teams by Skill Level */} {teams.length === 0 ? (
No teams yet

Be the first to create a racing team. Gather drivers and compete together in endurance events.

) : filteredTeams.length === 0 ? (

No teams found matching "{searchQuery}"

) : (
{SKILL_LEVELS.map((level, index) => (
))}
)}
); }