website refactor
This commit is contained in:
@@ -5,10 +5,9 @@ import { useState, useRef, useEffect } from 'react';
|
||||
import type * as React from 'react';
|
||||
import { createPortal } from 'react-dom';
|
||||
import type { LeagueConfigFormModel } from '@/lib/types/LeagueConfigFormModel';
|
||||
import { Box } from '@/ui/Box';
|
||||
import { Stack } from '@/ui/Stack';
|
||||
import { Text } from '@/ui/Text';
|
||||
import { Heading } from '@/ui/Heading';
|
||||
import { Stack } from '@/ui/Stack';
|
||||
import { Icon } from '@/ui/Icon';
|
||||
|
||||
// Minimum drivers for ranked leagues
|
||||
@@ -87,7 +86,7 @@ function InfoFlyout({ isOpen, onClose, title, children, anchorRef }: InfoFlyoutP
|
||||
if (!isOpen || !mounted) return null;
|
||||
|
||||
return createPortal(
|
||||
<Box
|
||||
<Stack
|
||||
ref={flyoutRef}
|
||||
position="fixed"
|
||||
zIndex={50}
|
||||
@@ -100,7 +99,7 @@ function InfoFlyout({ isOpen, onClose, title, children, anchorRef }: InfoFlyoutP
|
||||
// eslint-disable-next-line gridpilot-rules/component-classification
|
||||
style={{ top: position.top, left: position.left, maxHeight: '80vh', overflowY: 'auto' }}
|
||||
>
|
||||
<Box
|
||||
<Stack
|
||||
display="flex"
|
||||
alignItems="center"
|
||||
justifyContent="between"
|
||||
@@ -116,7 +115,7 @@ function InfoFlyout({ isOpen, onClose, title, children, anchorRef }: InfoFlyoutP
|
||||
<Icon icon={HelpCircle} size={4} color="text-primary-blue" />
|
||||
<Text size="sm" weight="semibold" color="text-white">{title}</Text>
|
||||
</Stack>
|
||||
<Box
|
||||
<Stack
|
||||
as="button"
|
||||
type="button"
|
||||
onClick={onClose}
|
||||
@@ -130,12 +129,12 @@ function InfoFlyout({ isOpen, onClose, title, children, anchorRef }: InfoFlyoutP
|
||||
hoverBg="bg-charcoal-outline"
|
||||
>
|
||||
<Icon icon={X} size={4} color="text-gray-400" />
|
||||
</Box>
|
||||
</Box>
|
||||
<Box p={4}>
|
||||
</Stack>
|
||||
</Stack>
|
||||
<Stack p={4}>
|
||||
{children}
|
||||
</Box>
|
||||
</Box>,
|
||||
</Stack>
|
||||
</Stack>,
|
||||
document.body
|
||||
);
|
||||
}
|
||||
@@ -189,20 +188,20 @@ export function LeagueVisibilitySection({
|
||||
return (
|
||||
<Stack gap={8}>
|
||||
{/* Emotional header for the step */}
|
||||
<Box textAlign="center" pb={2}>
|
||||
<Stack textAlign="center" pb={2}>
|
||||
<Heading level={3} mb={2}>
|
||||
Choose your league's destiny
|
||||
</Heading>
|
||||
<Text size="sm" color="text-gray-400" maxWidth="lg" mx="auto" block>
|
||||
Will you compete for glory on the global leaderboards, or race with friends in a private series?
|
||||
</Text>
|
||||
</Box>
|
||||
</Stack>
|
||||
|
||||
{/* League Type Selection */}
|
||||
<Box display="grid" responsiveGridCols={{ base: 1, md: 2 }} gap={6}>
|
||||
<Stack display="grid" responsiveGridCols={{ base: 1, md: 2 }} gap={6}>
|
||||
{/* Ranked (Public) Option */}
|
||||
<Box position="relative">
|
||||
<Box
|
||||
<Stack position="relative">
|
||||
<Stack
|
||||
as="button"
|
||||
type="button"
|
||||
disabled={disabled}
|
||||
@@ -227,9 +226,9 @@ export function LeagueVisibilitySection({
|
||||
group
|
||||
>
|
||||
{/* Header */}
|
||||
<Box display="flex" alignItems="start" justifyContent="between">
|
||||
<Stack display="flex" alignItems="start" justifyContent="between">
|
||||
<Stack direction="row" align="center" gap={3}>
|
||||
<Box
|
||||
<Stack
|
||||
display="flex"
|
||||
h="14"
|
||||
w="14"
|
||||
@@ -239,18 +238,18 @@ export function LeagueVisibilitySection({
|
||||
bg={isRanked ? 'bg-primary-blue/30' : 'bg-charcoal-outline/50'}
|
||||
>
|
||||
<Icon icon={Trophy} size={7} color={isRanked ? 'text-primary-blue' : 'text-gray-400'} />
|
||||
</Box>
|
||||
<Box>
|
||||
</Stack>
|
||||
<Stack>
|
||||
<Text weight="bold" size="xl" color={isRanked ? 'text-white' : 'text-gray-300'} block>
|
||||
Ranked
|
||||
</Text>
|
||||
<Text size="sm" color={isRanked ? 'text-primary-blue' : 'text-gray-500'} block>
|
||||
Compete for glory
|
||||
</Text>
|
||||
</Box>
|
||||
</Stack>
|
||||
</Stack>
|
||||
{/* Radio indicator */}
|
||||
<Box
|
||||
<Stack
|
||||
display="flex"
|
||||
h="7"
|
||||
w="7"
|
||||
@@ -264,8 +263,8 @@ export function LeagueVisibilitySection({
|
||||
transition
|
||||
>
|
||||
{isRanked && <Icon icon={Check} size={4} color="text-white" />}
|
||||
</Box>
|
||||
</Box>
|
||||
</Stack>
|
||||
</Stack>
|
||||
|
||||
{/* Emotional tagline */}
|
||||
<Text size="sm" color={isRanked ? 'text-gray-300' : 'text-gray-500'} block>
|
||||
@@ -289,16 +288,16 @@ export function LeagueVisibilitySection({
|
||||
</Stack>
|
||||
|
||||
{/* Requirement badge */}
|
||||
<Box display="flex" alignItems="center" gap={2} mt="auto" px={3} py={2} rounded="lg" bg="bg-warning-amber/10" border borderColor="border-warning-amber/20" w="fit">
|
||||
<Stack display="flex" alignItems="center" gap={2} mt="auto" px={3} py={2} rounded="lg" bg="bg-warning-amber/10" border borderColor="border-warning-amber/20" w="fit">
|
||||
<Icon icon={Users} size={4} color="text-warning-amber" />
|
||||
<Text size="xs" color="text-warning-amber" weight="medium">
|
||||
Requires {MIN_RANKED_DRIVERS}+ drivers for competitive integrity
|
||||
</Text>
|
||||
</Box>
|
||||
</Box>
|
||||
</Stack>
|
||||
</Stack>
|
||||
|
||||
{/* Info button */}
|
||||
<Box
|
||||
<Stack
|
||||
as="button"
|
||||
ref={rankedInfoRef}
|
||||
type="button"
|
||||
@@ -318,8 +317,8 @@ export function LeagueVisibilitySection({
|
||||
hoverBg="bg-primary-blue/10"
|
||||
>
|
||||
<Icon icon={HelpCircle} size={4} />
|
||||
</Box>
|
||||
</Box>
|
||||
</Stack>
|
||||
</Stack>
|
||||
|
||||
{/* Ranked Info Flyout */}
|
||||
<InfoFlyout
|
||||
@@ -343,16 +342,16 @@ export function LeagueVisibilitySection({
|
||||
Requirements
|
||||
</Text>
|
||||
<Stack gap={1.5}>
|
||||
<Box display="flex" alignItems="start" gap={2}>
|
||||
<Stack display="flex" alignItems="start" gap={2}>
|
||||
<Icon icon={Users} size={3.5} color="text-warning-amber" flexShrink={0} mt={0.5} />
|
||||
<Text size="xs" color="text-gray-400">
|
||||
<Text weight="bold" color="text-white">Minimum {MIN_RANKED_DRIVERS} drivers</Text> for competitive integrity
|
||||
</Text>
|
||||
</Box>
|
||||
<Box display="flex" alignItems="start" gap={2}>
|
||||
</Stack>
|
||||
<Stack display="flex" alignItems="start" gap={2}>
|
||||
<Icon icon={Check} size={3.5} color="text-performance-green" flexShrink={0} mt={0.5} />
|
||||
<Text size="xs" color="text-gray-400">Anyone can discover and join your league</Text>
|
||||
</Box>
|
||||
</Stack>
|
||||
</Stack>
|
||||
</Stack>
|
||||
|
||||
@@ -365,22 +364,22 @@ export function LeagueVisibilitySection({
|
||||
Benefits
|
||||
</Text>
|
||||
<Stack gap={1.5}>
|
||||
<Box display="flex" alignItems="start" gap={2}>
|
||||
<Stack display="flex" alignItems="start" gap={2}>
|
||||
<Icon icon={Trophy} size={3.5} color="text-primary-blue" flexShrink={0} mt={0.5} />
|
||||
<Text size="xs" color="text-gray-400">Results affect driver ratings and rankings</Text>
|
||||
</Box>
|
||||
<Box display="flex" alignItems="start" gap={2}>
|
||||
</Stack>
|
||||
<Stack display="flex" alignItems="start" gap={2}>
|
||||
<Icon icon={Check} size={3.5} color="text-performance-green" flexShrink={0} mt={0.5} />
|
||||
<Text size="xs" color="text-gray-400">Featured in league discovery</Text>
|
||||
</Box>
|
||||
</Stack>
|
||||
</Stack>
|
||||
</Stack>
|
||||
</Stack>
|
||||
</InfoFlyout>
|
||||
|
||||
{/* Unranked (Private) Option */}
|
||||
<Box position="relative">
|
||||
<Box
|
||||
<Stack position="relative">
|
||||
<Stack
|
||||
as="button"
|
||||
type="button"
|
||||
disabled={disabled}
|
||||
@@ -405,9 +404,9 @@ export function LeagueVisibilitySection({
|
||||
group
|
||||
>
|
||||
{/* Header */}
|
||||
<Box display="flex" alignItems="start" justifyContent="between">
|
||||
<Stack display="flex" alignItems="start" justifyContent="between">
|
||||
<Stack direction="row" align="center" gap={3}>
|
||||
<Box
|
||||
<Stack
|
||||
display="flex"
|
||||
h="14"
|
||||
w="14"
|
||||
@@ -417,18 +416,18 @@ export function LeagueVisibilitySection({
|
||||
bg={!isRanked ? 'bg-neon-aqua/30' : 'bg-charcoal-outline/50'}
|
||||
>
|
||||
<Icon icon={Users} size={7} color={!isRanked ? 'text-neon-aqua' : 'text-gray-400'} />
|
||||
</Box>
|
||||
<Box>
|
||||
</Stack>
|
||||
<Stack>
|
||||
<Text weight="bold" size="xl" color={!isRanked ? 'text-white' : 'text-gray-300'} block>
|
||||
Unranked
|
||||
</Text>
|
||||
<Text size="sm" color={!isRanked ? 'text-neon-aqua' : 'text-gray-500'} block>
|
||||
Race with friends
|
||||
</Text>
|
||||
</Box>
|
||||
</Stack>
|
||||
</Stack>
|
||||
{/* Radio indicator */}
|
||||
<Box
|
||||
<Stack
|
||||
display="flex"
|
||||
h="7"
|
||||
w="7"
|
||||
@@ -442,8 +441,8 @@ export function LeagueVisibilitySection({
|
||||
transition
|
||||
>
|
||||
{!isRanked && <Icon icon={Check} size={4} color="text-deep-graphite" />}
|
||||
</Box>
|
||||
</Box>
|
||||
</Stack>
|
||||
</Stack>
|
||||
|
||||
{/* Emotional tagline */}
|
||||
<Text size="sm" color={!isRanked ? 'text-gray-300' : 'text-gray-500'} block>
|
||||
@@ -467,16 +466,16 @@ export function LeagueVisibilitySection({
|
||||
</Stack>
|
||||
|
||||
{/* Flexibility badge */}
|
||||
<Box display="flex" alignItems="center" gap={2} mt="auto" px={3} py={2} rounded="lg" bg="bg-neon-aqua/10" border borderColor="border-neon-aqua/20" w="fit">
|
||||
<Stack display="flex" alignItems="center" gap={2} mt="auto" px={3} py={2} rounded="lg" bg="bg-neon-aqua/10" border borderColor="border-neon-aqua/20" w="fit">
|
||||
<Icon icon={Users} size={4} color={!isRanked ? 'text-neon-aqua' : 'text-gray-400'} />
|
||||
<Text size="xs" color={!isRanked ? 'text-neon-aqua' : 'text-gray-400'} weight="medium">
|
||||
Any size — even 2 friends
|
||||
</Text>
|
||||
</Box>
|
||||
</Box>
|
||||
</Stack>
|
||||
</Stack>
|
||||
|
||||
{/* Info button */}
|
||||
<Box
|
||||
<Stack
|
||||
as="button"
|
||||
ref={unrankedInfoRef}
|
||||
type="button"
|
||||
@@ -496,8 +495,8 @@ export function LeagueVisibilitySection({
|
||||
hoverBg="bg-neon-aqua/10"
|
||||
>
|
||||
<Icon icon={HelpCircle} size={4} />
|
||||
</Box>
|
||||
</Box>
|
||||
</Stack>
|
||||
</Stack>
|
||||
|
||||
{/* Unranked Info Flyout */}
|
||||
<InfoFlyout
|
||||
@@ -522,18 +521,18 @@ export function LeagueVisibilitySection({
|
||||
Perfect For
|
||||
</Text>
|
||||
<Stack gap={1.5}>
|
||||
<Box display="flex" alignItems="start" gap={2}>
|
||||
<Stack display="flex" alignItems="start" gap={2}>
|
||||
<Icon icon={Check} size={3.5} color="text-neon-aqua" flexShrink={0} mt={0.5} />
|
||||
<Text size="xs" color="text-gray-400">Private racing with friends</Text>
|
||||
</Box>
|
||||
<Box display="flex" alignItems="start" gap={2}>
|
||||
</Stack>
|
||||
<Stack display="flex" alignItems="start" gap={2}>
|
||||
<Icon icon={Check} size={3.5} color="text-neon-aqua" flexShrink={0} mt={0.5} />
|
||||
<Text size="xs" color="text-gray-400">Practice and training sessions</Text>
|
||||
</Box>
|
||||
<Box display="flex" alignItems="start" gap={2}>
|
||||
</Stack>
|
||||
<Stack display="flex" alignItems="start" gap={2}>
|
||||
<Icon icon={Check} size={3.5} color="text-neon-aqua" flexShrink={0} mt={0.5} />
|
||||
<Text size="xs" color="text-gray-400">Small groups (2+ drivers)</Text>
|
||||
</Box>
|
||||
</Stack>
|
||||
</Stack>
|
||||
</Stack>
|
||||
|
||||
@@ -546,29 +545,29 @@ export function LeagueVisibilitySection({
|
||||
Features
|
||||
</Text>
|
||||
<Stack gap={1.5}>
|
||||
<Box display="flex" alignItems="start" gap={2}>
|
||||
<Stack display="flex" alignItems="start" gap={2}>
|
||||
<Icon icon={Users} size={3.5} color="text-neon-aqua" flexShrink={0} mt={0.5} />
|
||||
<Text size="xs" color="text-gray-400">Invite-only membership</Text>
|
||||
</Box>
|
||||
<Box display="flex" alignItems="start" gap={2}>
|
||||
</Stack>
|
||||
<Stack display="flex" alignItems="start" gap={2}>
|
||||
<Icon icon={Check} size={3.5} color="text-neon-aqua" flexShrink={0} mt={0.5} />
|
||||
<Text size="xs" color="text-gray-400">Full stats and standings (internal only)</Text>
|
||||
</Box>
|
||||
</Stack>
|
||||
</Stack>
|
||||
</Stack>
|
||||
</Stack>
|
||||
</InfoFlyout>
|
||||
</Box>
|
||||
</Stack>
|
||||
|
||||
{errors?.visibility && (
|
||||
<Box display="flex" alignItems="center" gap={2} p={3} rounded="lg" bg="bg-warning-amber/10" border borderColor="border-warning-amber/20">
|
||||
<Stack display="flex" alignItems="center" gap={2} p={3} rounded="lg" bg="bg-warning-amber/10" border borderColor="border-warning-amber/20">
|
||||
<Icon icon={HelpCircle} size={4} color="text-warning-amber" flexShrink={0} />
|
||||
<Text size="xs" color="text-warning-amber">{errors.visibility}</Text>
|
||||
</Box>
|
||||
</Stack>
|
||||
)}
|
||||
|
||||
{/* Contextual info based on selection */}
|
||||
<Box
|
||||
<Stack
|
||||
rounded="xl"
|
||||
p={5}
|
||||
border
|
||||
@@ -576,33 +575,33 @@ export function LeagueVisibilitySection({
|
||||
bg={isRanked ? 'bg-primary-blue/5' : 'bg-neon-aqua/5'}
|
||||
borderColor={isRanked ? 'border-primary-blue/20' : 'border-neon-aqua/20'}
|
||||
>
|
||||
<Box display="flex" alignItems="start" gap={3}>
|
||||
<Stack display="flex" alignItems="start" gap={3}>
|
||||
{isRanked ? (
|
||||
<>
|
||||
<Icon icon={Trophy} size={5} color="text-primary-blue" flexShrink={0} mt={0.5} />
|
||||
<Box>
|
||||
<Stack>
|
||||
<Text size="sm" weight="medium" color="text-white" block mb={1}>Ready to compete</Text>
|
||||
<Text size="xs" color="text-gray-400" block>
|
||||
Your league will be visible to all GridPilot drivers. Results will affect driver ratings
|
||||
and contribute to the global leaderboards. Make sure you have at least {MIN_RANKED_DRIVERS} drivers
|
||||
to ensure competitive integrity.
|
||||
</Text>
|
||||
</Box>
|
||||
</Stack>
|
||||
</>
|
||||
) : (
|
||||
<>
|
||||
<Icon icon={Users} size={5} color="text-neon-aqua" flexShrink={0} mt={0.5} />
|
||||
<Box>
|
||||
<Stack>
|
||||
<Text size="sm" weight="medium" color="text-white" block mb={1}>Private racing awaits</Text>
|
||||
<Text size="xs" color="text-gray-400" block>
|
||||
Your league will be invite-only. Perfect for racing with friends, practice sessions,
|
||||
or any time you want to have fun without affecting your official ratings.
|
||||
</Text>
|
||||
</Box>
|
||||
</Stack>
|
||||
</>
|
||||
)}
|
||||
</Box>
|
||||
</Box>
|
||||
</Stack>
|
||||
</Stack>
|
||||
</Stack>
|
||||
);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user