// app/rankings/page.tsx // Rankings with pagination, adjustable page size, and filters import { query } from '@/lib/db'; import { TrophyIcon } from '@/components/ui/icons'; import Link from 'next/link'; export const dynamic = "force-dynamic"; interface RankingDriver { driver_guid: string; driver_name: string; driver_team: string | null; car_model: string | null; user_rank: number; laps_completed: number; cuts_alltime: number; contacts_alltime: number; created_at: Date; } interface FilterOptions { teams: string[]; carModels: string[]; } const PAGE_SIZE_OPTIONS = [25, 50, 100]; async function getFilterOptions(): Promise { const teamsQuery = ` SELECT DISTINCT driver_team FROM users WHERE driver_team IS NOT NULL AND driver_team != '' ORDER BY driver_team `; const carsQuery = ` SELECT DISTINCT car_model FROM users WHERE car_model IS NOT NULL AND car_model != '' ORDER BY car_model `; const teams = await query(teamsQuery); const cars = await query(carsQuery); return { teams: teams.map((t: any) => t.driver_team), carModels: cars.map((c: any) => c.car_model) }; } async function getRankings( page: number = 1, pageSize: number = 50, filters: { search?: string; class?: string; team?: string; carModel?: string; } = {} ): Promise<{ drivers: RankingDriver[]; totalCount: number }> { const offset = (page - 1) * pageSize; // Build WHERE clause const conditions: string[] = []; if (filters.search) { conditions.push(`LOWER(driver_name) LIKE LOWER('%${filters.search}%')`); } if (filters.class) { switch (filters.class) { case 'S': conditions.push('user_rank >= 5000'); break; case 'A': conditions.push('user_rank >= 2500 AND user_rank < 5000'); break; case 'B': conditions.push('user_rank >= 1750 AND user_rank < 2500'); break; case 'C': conditions.push('user_rank >= 1250 AND user_rank < 1750'); break; case 'D': conditions.push('user_rank < 1250'); break; } } if (filters.team) { conditions.push(`driver_team = '${filters.team}'`); } if (filters.carModel) { conditions.push(`car_model = '${filters.carModel}'`); } const whereClause = conditions.length > 0 ? `WHERE ${conditions.join(' AND ')}` : ''; // Get total count const countResult = await query(`SELECT COUNT(*) as count FROM users ${whereClause}`); const totalCount = countResult[0]?.count || 0; // Get paginated results const sql = ` SELECT driver_guid, driver_name, driver_team, car_model, user_rank, laps_completed, cuts_alltime, contacts_alltime, created_at FROM users ${whereClause} ORDER BY user_rank DESC LIMIT ${pageSize} OFFSET ${offset} `; const rows = await query(sql); return { drivers: rows as RankingDriver[], totalCount: totalCount }; } function getDriverClass(rank: number): { name: string; color: string; code: string } { if (rank >= 5000) return { name: 'S CLASS', color: 'text-white', code: 'S' }; if (rank >= 2500) return { name: 'A CLASS', color: 'text-white', code: 'A' }; if (rank >= 1750) return { name: 'B CLASS', color: 'text-white/80', code: 'B' }; if (rank >= 1250) return { name: 'C CLASS', color: 'text-white/60', code: 'C' }; return { name: 'D CLASS', color: 'text-white/40', code: 'D' }; } function buildQueryString(params: Record): string { const filtered = Object.entries(params) .filter(([_, value]) => value !== undefined && value !== '') .map(([key, value]) => `${key}=${encodeURIComponent(value!)}`) .join('&'); return filtered ? `?${filtered}` : ''; } export default async function RankingsPage({ searchParams, }: { searchParams: Promise<{ page?: string; pageSize?: string; search?: string; class?: string; team?: string; carModel?: string; }>; }) { const params = await searchParams; const currentPage = parseInt(params.page || '1'); const pageSize = parseInt(params.pageSize || '50'); const searchQuery = params.search || ''; const classFilter = params.class || ''; const teamFilter = params.team || ''; const carModelFilter = params.carModel || ''; const { drivers, totalCount } = await getRankings(currentPage, pageSize, { search: searchQuery, class: classFilter, team: teamFilter, carModel: carModelFilter }); const filterOptions = await getFilterOptions(); const totalPages = Math.ceil(totalCount / pageSize); const startRank = (currentPage - 1) * pageSize + 1; const hasActiveFilters = searchQuery || classFilter || teamFilter || carModelFilter; return ( <> {/* Hero */}
DRIVER RANKINGS

LEADERBOARD

Global driver rankings based on performance, consistency, and clean racing

{totalCount.toLocaleString()} {hasActiveFilters ? 'filtered' : 'total'} drivers

{/* Class Explanation */}
{/* Filters & Controls */}
{/* Single Filter Form */}
{/* Search Bar */}
{/* Filter Grid */}
{/* Class Filter */}
{/* Team Filter */}
{/* Car Model Filter */}
{/* Submit Button */}
{/* Active Filters & Clear */} {hasActiveFilters && (
ACTIVE FILTERS: {searchQuery && ( Search: {searchQuery} )} {classFilter && ( Class: {classFilter} )} {teamFilter && ( Team: {teamFilter} )} {carModelFilter && ( Car: {carModelFilter} )}
CLEAR ALL
)}
{/* Page Size Selector */}
Items per page:
{PAGE_SIZE_OPTIONS.map((size) => { const newParams = buildQueryString({ page: '1', pageSize: size.toString(), search: searchQuery, class: classFilter, team: teamFilter, carModel: carModelFilter }); return ( {size} ); })}
{/* Rankings Table */}
{drivers.length === 0 ? ( ) : ( drivers.map((driver, index) => { const driverClass = getDriverClass(driver.user_rank); const globalRank = startRank + index; const isPodium = globalRank <= 3 && !hasActiveFilters; return ( ); }) )}
RANK DRIVER TEAM CAR RATING CLASS LAPS CUTS
No drivers found matching your filters
3 || hasActiveFilters) ? 'text-white/60' : ''} `}> {String(globalRank).padStart(2, '0')} {isPodium && ( {globalRank === 1 ? '█' : globalRank === 2 ? '▓' : '▒'} )} {driver.driver_name} {driver.driver_team || '—'} {driver.car_model || '—'} {driver.user_rank.toLocaleString()} {driverClass.name} {driver.laps_completed.toLocaleString()} {driver.cuts_alltime.toLocaleString()}
{/* Pagination */} {totalPages > 1 && (
Page {currentPage} of {totalPages} • Showing {startRank}-{Math.min(startRank + pageSize - 1, totalCount)} of {totalCount.toLocaleString()}
{/* First Page */} {currentPage > 1 && ( «« )} {/* Previous Page */} {currentPage > 1 && ( ‹ PREV )} {/* Page Numbers */} {Array.from({ length: Math.min(5, totalPages) }, (_, i) => { let pageNum; if (totalPages <= 5) { pageNum = i + 1; } else if (currentPage <= 3) { pageNum = i + 1; } else if (currentPage >= totalPages - 2) { pageNum = totalPages - 4 + i; } else { pageNum = currentPage - 2 + i; } return ( {pageNum} ); })} {/* Next Page */} {currentPage < totalPages && ( NEXT › )} {/* Last Page */} {currentPage < totalPages && ( »» )}
)} {/* Info Box */}

RANKING SYSTEM

• Rating increases with clean racing and fast lap times

• Penalties applied for track cuts and collisions

• Class promotion based on consistent performance over multiple sessions

); } function ClassCard({ name, range, description }: { name: string; range: string; description: string; }) { return (
{name}
{range}
{description}
); }