Files
gridpilot.gg/apps/website/components/drivers/RatingBreakdown.tsx
2025-12-04 11:54:23 +01:00

203 lines
6.1 KiB
TypeScript

'use client';
import Card from '../ui/Card';
interface RatingBreakdownProps {
skillRating?: number;
safetyRating?: number;
sportsmanshipRating?: number;
}
export default function RatingBreakdown({
skillRating = 1450,
safetyRating = 92,
sportsmanshipRating = 4.8
}: RatingBreakdownProps) {
return (
<div className="space-y-6">
<Card>
<h3 className="text-lg font-semibold text-white mb-6">Rating Components</h3>
<div className="space-y-6">
<RatingComponent
label="Skill Rating"
value={skillRating}
maxValue={2000}
color="primary-blue"
description="Based on race results, competition strength, and consistency"
breakdown={[
{ label: 'Race Results', percentage: 60 },
{ label: 'Competition Quality', percentage: 25 },
{ label: 'Consistency', percentage: 15 }
]}
/>
<RatingComponent
label="Safety Rating"
value={safetyRating}
maxValue={100}
color="green-400"
suffix="%"
description="Reflects incident-free racing and clean overtakes"
breakdown={[
{ label: 'Incident Rate', percentage: 70 },
{ label: 'Clean Overtakes', percentage: 20 },
{ label: 'Position Awareness', percentage: 10 }
]}
/>
<RatingComponent
label="Sportsmanship"
value={sportsmanshipRating}
maxValue={5}
color="warning-amber"
suffix="/5"
description="Community feedback on racing behavior and fair play"
breakdown={[
{ label: 'Peer Reviews', percentage: 50 },
{ label: 'Fair Racing', percentage: 30 },
{ label: 'Team Play', percentage: 20 }
]}
/>
</div>
</Card>
<Card>
<h3 className="text-lg font-semibold text-white mb-4">Rating History</h3>
<div className="space-y-3">
<HistoryItem
date="November 2024"
skillChange={+15}
safetyChange={+2}
sportsmanshipChange={0}
/>
<HistoryItem
date="October 2024"
skillChange={+28}
safetyChange={-1}
sportsmanshipChange={+0.1}
/>
<HistoryItem
date="September 2024"
skillChange={-12}
safetyChange={+3}
sportsmanshipChange={0}
/>
</div>
</Card>
<Card className="bg-charcoal-200/50 border-primary-blue/30">
<div className="flex items-center gap-3 mb-3">
<div className="text-2xl">📈</div>
<h3 className="text-lg font-semibold text-white">Rating Insights</h3>
</div>
<ul className="space-y-2 text-sm text-gray-400">
<li className="flex items-start gap-2">
<span className="text-green-400 mt-0.5"></span>
<span>Strong safety rating - keep up the clean racing!</span>
</li>
<li className="flex items-start gap-2">
<span className="text-warning-amber mt-0.5"></span>
<span>Skill rating improving - competitive against higher-rated drivers</span>
</li>
<li className="flex items-start gap-2">
<span className="text-primary-blue mt-0.5">i</span>
<span>Complete more races to stabilize your ratings</span>
</li>
</ul>
</Card>
</div>
);
}
function RatingComponent({
label,
value,
maxValue,
color,
suffix = '',
description,
breakdown
}: {
label: string;
value: number;
maxValue: number;
color: string;
suffix?: string;
description: string;
breakdown: { label: string; percentage: number }[];
}) {
const percentage = (value / maxValue) * 100;
return (
<div>
<div className="flex items-center justify-between mb-2">
<span className="text-white font-medium">{label}</span>
<span className={`text-2xl font-bold text-${color}`}>
{value}{suffix}
</span>
</div>
<div className="w-full bg-deep-graphite rounded-full h-2 mb-3">
<div
className={`bg-${color} rounded-full h-2 transition-all duration-500`}
style={{ width: `${percentage}%` }}
/>
</div>
<p className="text-xs text-gray-400 mb-3">{description}</p>
<div className="space-y-1">
{breakdown.map((item, index) => (
<div key={index} className="flex items-center justify-between text-xs">
<span className="text-gray-500">{item.label}</span>
<span className="text-gray-400">{item.percentage}%</span>
</div>
))}
</div>
</div>
);
}
function HistoryItem({
date,
skillChange,
safetyChange,
sportsmanshipChange
}: {
date: string;
skillChange: number;
safetyChange: number;
sportsmanshipChange: number;
}) {
const formatChange = (value: number) => {
if (value === 0) return '—';
return value > 0 ? `+${value}` : `${value}`;
};
const getChangeColor = (value: number) => {
if (value === 0) return 'text-gray-500';
return value > 0 ? 'text-green-400' : 'text-red-400';
};
return (
<div className="flex items-center justify-between p-3 rounded bg-deep-graphite border border-charcoal-outline">
<span className="text-white text-sm">{date}</span>
<div className="flex items-center gap-4 text-xs">
<div className="text-center">
<div className="text-gray-500 mb-1">Skill</div>
<div className={getChangeColor(skillChange)}>{formatChange(skillChange)}</div>
</div>
<div className="text-center">
<div className="text-gray-500 mb-1">Safety</div>
<div className={getChangeColor(safetyChange)}>{formatChange(safetyChange)}</div>
</div>
<div className="text-center">
<div className="text-gray-500 mb-1">Sports</div>
<div className={getChangeColor(sportsmanshipChange)}>{formatChange(sportsmanshipChange)}</div>
</div>
</div>
</div>
);
}