website refactor
This commit is contained in:
158
apps/website/components/races/RaceResultHero.tsx
Normal file
158
apps/website/components/races/RaceResultHero.tsx
Normal file
@@ -0,0 +1,158 @@
|
||||
|
||||
|
||||
import { Trophy } from 'lucide-react';
|
||||
import { Box } from '@/ui/Box';
|
||||
import { DecorativeBlur } from '@/ui/DecorativeBlur';
|
||||
import { Icon } from '@/ui/Icon';
|
||||
import { Stack } from '@/ui/Stack';
|
||||
import { Surface } from '@/ui/Surface';
|
||||
import { Text } from '@/ui/Text';
|
||||
|
||||
interface RaceResultHeroProps {
|
||||
position: number;
|
||||
startPosition: number;
|
||||
positionChange: number;
|
||||
incidents: number;
|
||||
isClean: boolean;
|
||||
isPodium: boolean;
|
||||
ratingChange?: number;
|
||||
animatedRatingChange: number;
|
||||
}
|
||||
|
||||
export function RaceResultHero({
|
||||
position,
|
||||
startPosition,
|
||||
positionChange,
|
||||
incidents,
|
||||
isClean,
|
||||
isPodium,
|
||||
ratingChange,
|
||||
animatedRatingChange,
|
||||
}: RaceResultHeroProps) {
|
||||
const isVictory = position === 1;
|
||||
const isSecond = position === 2;
|
||||
const isThird = position === 3;
|
||||
|
||||
const getPositionBg = () => {
|
||||
if (isVictory) return 'linear-gradient(to bottom right, #facc15, #d97706)';
|
||||
if (isSecond) return 'linear-gradient(to bottom right, #d1d5db, #6b7280)';
|
||||
if (isThird) return 'linear-gradient(to bottom right, #3b82f6, #2563eb)';
|
||||
return 'linear-gradient(to bottom right, #3b82f6, #2563eb)';
|
||||
};
|
||||
|
||||
const getOuterBg = () => {
|
||||
if (isVictory) return 'linear-gradient(to right, #eab308, #facc15, #d97706)';
|
||||
if (isPodium) return 'linear-gradient(to right, #9ca3af, #d1d5db, #6b7280)';
|
||||
return 'linear-gradient(to right, #3b82f6, #60a5fa, #2563eb)';
|
||||
};
|
||||
|
||||
return (
|
||||
<Surface
|
||||
rounded="2xl"
|
||||
p={1}
|
||||
style={{ background: getOuterBg() }}
|
||||
>
|
||||
<Surface variant="dark" rounded="xl" p={8} position="relative">
|
||||
<DecorativeBlur color="blue" size="lg" position="top-right" opacity={10} />
|
||||
|
||||
<Stack direction="row" align="center" justify="between" wrap gap={6} position="relative" zIndex={10}>
|
||||
<Stack direction="row" align="center" gap={5}>
|
||||
<Box
|
||||
position="relative"
|
||||
display="flex"
|
||||
alignItems="center"
|
||||
justifyContent="center"
|
||||
w="28"
|
||||
h="28"
|
||||
rounded="2xl"
|
||||
color={position <= 2 ? 'text-iron-gray' : 'text-white'}
|
||||
shadow="0 20px 25px -5px rgba(0, 0, 0, 0.1)"
|
||||
style={{
|
||||
background: getPositionBg(),
|
||||
fontWeight: 900,
|
||||
fontSize: '3rem'
|
||||
}}
|
||||
>
|
||||
{isVictory && (
|
||||
<Icon
|
||||
icon={Trophy}
|
||||
size={8}
|
||||
color="#fef08a"
|
||||
position="absolute"
|
||||
top="-3"
|
||||
right="-2"
|
||||
/>
|
||||
)}
|
||||
P{position}
|
||||
</Box>
|
||||
|
||||
<Box>
|
||||
<Text
|
||||
size="3xl"
|
||||
weight="bold"
|
||||
block
|
||||
mb={1}
|
||||
color={isVictory ? 'text-yellow-400' : isPodium ? 'text-gray-300' : 'text-white'}
|
||||
>
|
||||
{isVictory ? '🏆 VICTORY!' : isSecond ? '🥈 Second Place' : isThird ? '🥉 Podium Finish' : `P${position} Finish`}
|
||||
</Text>
|
||||
<Stack direction="row" align="center" gap={3}>
|
||||
<Text size="sm" color="text-gray-400">Started P{startPosition}</Text>
|
||||
<Box w="1" h="1" rounded="full" bg="bg-charcoal-outline" />
|
||||
<Text size="sm" color={isClean ? 'text-performance-green' : 'text-gray-400'}>
|
||||
{incidents}x incidents {isClean && '✨'}
|
||||
</Text>
|
||||
</Stack>
|
||||
</Box>
|
||||
</Stack>
|
||||
|
||||
<Stack direction="row" gap={3} wrap>
|
||||
{positionChange !== 0 && (
|
||||
<Surface
|
||||
variant="muted"
|
||||
rounded="2xl"
|
||||
border
|
||||
p={3}
|
||||
style={{
|
||||
minWidth: '100px',
|
||||
textAlign: 'center',
|
||||
background: positionChange > 0 ? 'rgba(16, 185, 129, 0.1)' : 'rgba(239, 68, 68, 0.1)',
|
||||
borderColor: positionChange > 0 ? 'rgba(16, 185, 129, 0.3)' : 'rgba(239, 68, 68, 0.3)'
|
||||
}}
|
||||
>
|
||||
<Stack align="center">
|
||||
<Text size="2xl" weight="bold" color={positionChange > 0 ? 'text-performance-green' : 'text-red-500'}>
|
||||
{positionChange > 0 ? '↑' : '↓'}{Math.abs(positionChange)}
|
||||
</Text>
|
||||
<Text size="xs" color="text-gray-400">{positionChange > 0 ? 'Gained' : 'Lost'}</Text>
|
||||
</Stack>
|
||||
</Surface>
|
||||
)}
|
||||
|
||||
{ratingChange !== undefined && (
|
||||
<Surface
|
||||
variant="muted"
|
||||
rounded="2xl"
|
||||
border
|
||||
p={3}
|
||||
style={{
|
||||
minWidth: '100px',
|
||||
textAlign: 'center',
|
||||
background: ratingChange > 0 ? 'rgba(245, 158, 11, 0.1)' : 'rgba(239, 68, 68, 0.1)',
|
||||
borderColor: ratingChange > 0 ? 'rgba(245, 158, 11, 0.3)' : 'rgba(239, 68, 68, 0.3)'
|
||||
}}
|
||||
>
|
||||
<Stack align="center">
|
||||
<Text font="mono" size="2xl" weight="bold" color={ratingChange > 0 ? 'text-warning-amber' : 'text-red-500'}>
|
||||
{animatedRatingChange > 0 ? '+' : ''}{animatedRatingChange}
|
||||
</Text>
|
||||
<Text size="xs" color="text-gray-400">Rating</Text>
|
||||
</Stack>
|
||||
</Surface>
|
||||
)}
|
||||
</Stack>
|
||||
</Stack>
|
||||
</Surface>
|
||||
</Surface>
|
||||
);
|
||||
}
|
||||
Reference in New Issue
Block a user