docs
This commit is contained in:
@@ -27,12 +27,73 @@ import Button from '@/components/ui/Button';
|
||||
import Card from '@/components/ui/Card';
|
||||
|
||||
import { getCountryFlag } from '@/lib/utilities/country';
|
||||
import { getGreeting, timeUntil } from '@/lib/utilities/time';
|
||||
import { getGreeting } from '@/lib/utilities/time';
|
||||
|
||||
import { DashboardOverviewViewModel } from '@/lib/view-models/DashboardOverviewViewModel';
|
||||
interface DashboardViewData {
|
||||
currentDriver: {
|
||||
name: string;
|
||||
avatarUrl: string;
|
||||
country: string;
|
||||
rating: string;
|
||||
rank: string;
|
||||
totalRaces: string;
|
||||
wins: string;
|
||||
podiums: string;
|
||||
consistency: string;
|
||||
};
|
||||
nextRace: {
|
||||
id: string;
|
||||
track: string;
|
||||
car: string;
|
||||
scheduledAt: string;
|
||||
formattedDate: string;
|
||||
formattedTime: string;
|
||||
timeUntil: string;
|
||||
isMyLeague: boolean;
|
||||
} | null;
|
||||
upcomingRaces: Array<{
|
||||
id: string;
|
||||
track: string;
|
||||
car: string;
|
||||
scheduledAt: string;
|
||||
formattedDate: string;
|
||||
formattedTime: string;
|
||||
timeUntil: string;
|
||||
isMyLeague: boolean;
|
||||
}>;
|
||||
leagueStandings: Array<{
|
||||
leagueId: string;
|
||||
leagueName: string;
|
||||
position: string;
|
||||
points: string;
|
||||
totalDrivers: string;
|
||||
}>;
|
||||
feedItems: Array<{
|
||||
id: string;
|
||||
type: string;
|
||||
headline: string;
|
||||
body?: string;
|
||||
timestamp: string;
|
||||
formattedTime: string;
|
||||
ctaHref?: string;
|
||||
ctaLabel?: string;
|
||||
}>;
|
||||
friends: Array<{
|
||||
id: string;
|
||||
name: string;
|
||||
avatarUrl: string;
|
||||
country: string;
|
||||
}>;
|
||||
activeLeaguesCount: string;
|
||||
friendCount: string;
|
||||
hasUpcomingRaces: boolean;
|
||||
hasLeagueStandings: boolean;
|
||||
hasFeedItems: boolean;
|
||||
hasFriends: boolean;
|
||||
}
|
||||
|
||||
interface DashboardTemplateProps {
|
||||
data: DashboardOverviewViewModel;
|
||||
data: DashboardViewData;
|
||||
}
|
||||
|
||||
export function DashboardTemplate({ data }: DashboardTemplateProps) {
|
||||
@@ -44,7 +105,7 @@ export function DashboardTemplate({ data }: DashboardTemplateProps) {
|
||||
const friends = data.friends;
|
||||
const activeLeaguesCount = data.activeLeaguesCount;
|
||||
|
||||
const { totalRaces, wins, podiums, rating, globalRank, consistency } = currentDriver;
|
||||
const { totalRaces, wins, podiums, rating, rank, consistency } = currentDriver;
|
||||
|
||||
return (
|
||||
<main className="min-h-screen bg-deep-graphite">
|
||||
@@ -89,7 +150,7 @@ export function DashboardTemplate({ data }: DashboardTemplateProps) {
|
||||
</div>
|
||||
<div className="flex items-center gap-1.5 px-3 py-1 rounded-full bg-yellow-400/10 border border-yellow-400/30">
|
||||
<Trophy className="w-3.5 h-3.5 text-yellow-400" />
|
||||
<span className="text-sm font-semibold text-yellow-400">#{globalRank}</span>
|
||||
<span className="text-sm font-semibold text-yellow-400">#{rank}</span>
|
||||
</div>
|
||||
<span className="text-xs text-gray-500">{totalRaces} races completed</span>
|
||||
</div>
|
||||
@@ -129,61 +190,54 @@ export function DashboardTemplate({ data }: DashboardTemplateProps) {
|
||||
{/* Left Column - Main Content */}
|
||||
<div className="lg:col-span-2 space-y-6">
|
||||
{/* Next Race Card */}
|
||||
{nextRace && (
|
||||
<Card className="relative overflow-hidden bg-gradient-to-br from-iron-gray to-iron-gray/80 border-primary-blue/30">
|
||||
<div className="absolute top-0 right-0 w-40 h-40 bg-gradient-to-bl from-primary-blue/20 to-transparent rounded-bl-full" />
|
||||
<div className="relative">
|
||||
<div className="flex items-center gap-2 mb-4">
|
||||
<div className="flex items-center gap-2 px-3 py-1 rounded-full bg-primary-blue/20 border border-primary-blue/30">
|
||||
<Play className="w-3.5 h-3.5 text-primary-blue" />
|
||||
<span className="text-xs font-semibold text-primary-blue uppercase tracking-wider">Next Race</span>
|
||||
</div>
|
||||
{nextRace.isMyLeague && (
|
||||
<span className="px-2 py-0.5 rounded-full bg-performance-green/20 text-performance-green text-xs font-medium">
|
||||
Your League
|
||||
</span>
|
||||
)}
|
||||
</div>
|
||||
|
||||
<div className="flex flex-col md:flex-row md:items-end md:justify-between gap-4">
|
||||
<div>
|
||||
<h2 className="text-2xl font-bold text-white mb-2">{nextRace.track}</h2>
|
||||
<p className="text-gray-400 mb-3">{nextRace.car}</p>
|
||||
<div className="flex flex-wrap items-center gap-4 text-sm">
|
||||
<span className="flex items-center gap-1.5 text-gray-400">
|
||||
<Calendar className="w-4 h-4" />
|
||||
{nextRace.scheduledAt.toLocaleDateString('en-US', {
|
||||
weekday: 'long',
|
||||
month: 'short',
|
||||
day: 'numeric',
|
||||
})}
|
||||
</span>
|
||||
<span className="flex items-center gap-1.5 text-gray-400">
|
||||
<Clock className="w-4 h-4" />
|
||||
{nextRace.scheduledAt.toLocaleTimeString('en-US', {
|
||||
hour: '2-digit',
|
||||
minute: '2-digit',
|
||||
})}
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div className="flex flex-col items-end gap-3">
|
||||
<div className="text-right">
|
||||
<p className="text-xs text-gray-500 uppercase tracking-wider mb-1">Starts in</p>
|
||||
<p className="text-3xl font-bold text-primary-blue font-mono">{timeUntil(nextRace.scheduledAt)}</p>
|
||||
</div>
|
||||
<Link href={`/races/${nextRace.id}`}>
|
||||
<Button variant="primary" className="flex items-center gap-2">
|
||||
View Details
|
||||
<ChevronRight className="w-4 h-4" />
|
||||
</Button>
|
||||
</Link>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</Card>
|
||||
)}
|
||||
{nextRace && (
|
||||
<Card className="relative overflow-hidden bg-gradient-to-br from-iron-gray to-iron-gray/80 border-primary-blue/30">
|
||||
<div className="absolute top-0 right-0 w-40 h-40 bg-gradient-to-bl from-primary-blue/20 to-transparent rounded-bl-full" />
|
||||
<div className="relative">
|
||||
<div className="flex items-center gap-2 mb-4">
|
||||
<div className="flex items-center gap-2 px-3 py-1 rounded-full bg-primary-blue/20 border border-primary-blue/30">
|
||||
<Play className="w-3.5 h-3.5 text-primary-blue" />
|
||||
<span className="text-xs font-semibold text-primary-blue uppercase tracking-wider">Next Race</span>
|
||||
</div>
|
||||
{nextRace.isMyLeague && (
|
||||
<span className="px-2 py-0.5 rounded-full bg-performance-green/20 text-performance-green text-xs font-medium">
|
||||
Your League
|
||||
</span>
|
||||
)}
|
||||
</div>
|
||||
|
||||
<div className="flex flex-col md:flex-row md:items-end md:justify-between gap-4">
|
||||
<div>
|
||||
<h2 className="text-2xl font-bold text-white mb-2">{nextRace.track}</h2>
|
||||
<p className="text-gray-400 mb-3">{nextRace.car}</p>
|
||||
<div className="flex flex-wrap items-center gap-4 text-sm">
|
||||
<span className="flex items-center gap-1.5 text-gray-400">
|
||||
<Calendar className="w-4 h-4" />
|
||||
{nextRace.formattedDate}
|
||||
</span>
|
||||
<span className="flex items-center gap-1.5 text-gray-400">
|
||||
<Clock className="w-4 h-4" />
|
||||
{nextRace.formattedTime}
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div className="flex flex-col items-end gap-3">
|
||||
<div className="text-right">
|
||||
<p className="text-xs text-gray-500 uppercase tracking-wider mb-1">Starts in</p>
|
||||
<p className="text-3xl font-bold text-primary-blue font-mono">{nextRace.timeUntil}</p>
|
||||
</div>
|
||||
<Link href={`/races/${nextRace.id}`}>
|
||||
<Button variant="primary" className="flex items-center gap-2">
|
||||
View Details
|
||||
<ChevronRight className="w-4 h-4" />
|
||||
</Button>
|
||||
</Link>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</Card>
|
||||
)}
|
||||
|
||||
{/* League Standings Preview */}
|
||||
{leagueStandingsSummaries.length > 0 && (
|
||||
|
||||
Reference in New Issue
Block a user