website refactor
This commit is contained in:
50
apps/website/components/home/CtaSection.tsx
Normal file
50
apps/website/components/home/CtaSection.tsx
Normal file
@@ -0,0 +1,50 @@
|
||||
'use client';
|
||||
|
||||
import React from 'react';
|
||||
import { Section } from '@/ui/Section';
|
||||
import { Heading } from '@/ui/Heading';
|
||||
import { Text } from '@/ui/Text';
|
||||
import { Button } from '@/ui/Button';
|
||||
import { Group } from '@/ui/Group';
|
||||
import { Box } from '@/ui/Box';
|
||||
import { Panel } from '@/ui/Panel';
|
||||
import { Stack } from '@/ui/Stack';
|
||||
import { Trophy } from 'lucide-react';
|
||||
|
||||
/**
|
||||
* CtaSection - Final call to action for league admins.
|
||||
* Redesigned to match the "Modern Precision" theme and "Dieter Rams" style.
|
||||
*/
|
||||
export function CtaSection() {
|
||||
return (
|
||||
<Section variant="default" py={32}>
|
||||
<Panel variant="muted" padding="xl">
|
||||
<Stack gap={12} align="center" textAlign="center">
|
||||
<Box>
|
||||
<Box marginBottom={6} display="flex" justifyContent="center">
|
||||
<Box width="3rem" height="3rem" bg="var(--ui-color-bg-surface)" rounded="full" border={true} display="flex" alignItems="center" justifyContent="center">
|
||||
<Trophy size={24} className="text-[var(--ui-color-intent-primary)]" />
|
||||
</Box>
|
||||
</Box>
|
||||
<Heading level={2} weight="bold" marginBottom={4}>
|
||||
Ready to elevate your league?
|
||||
</Heading>
|
||||
<Text variant="med" size="lg" maxWidth="36rem" mx="auto">
|
||||
Join the growing ecosystem of professional sim racing leagues.
|
||||
Start for free and scale as your community grows.
|
||||
</Text>
|
||||
</Box>
|
||||
|
||||
<Group gap={6} justify="center">
|
||||
<Button variant="primary" size="lg">
|
||||
Create Your League
|
||||
</Button>
|
||||
<Button variant="secondary" size="lg">
|
||||
View Documentation
|
||||
</Button>
|
||||
</Group>
|
||||
</Stack>
|
||||
</Panel>
|
||||
</Section>
|
||||
);
|
||||
}
|
||||
96
apps/website/components/home/EcosystemGrid.tsx
Normal file
96
apps/website/components/home/EcosystemGrid.tsx
Normal file
@@ -0,0 +1,96 @@
|
||||
'use client';
|
||||
|
||||
import React from 'react';
|
||||
import { Section } from '@/ui/Section';
|
||||
import { Heading } from '@/ui/Heading';
|
||||
import { Text } from '@/ui/Text';
|
||||
import { Card } from '@/ui/Card';
|
||||
import { Button } from '@/ui/Button';
|
||||
import { FeatureGrid } from '@/ui/FeatureGrid';
|
||||
import { Stack } from '@/ui/Stack';
|
||||
import { Trophy, Users, Flag } from 'lucide-react';
|
||||
|
||||
interface EcosystemGridProps {
|
||||
leagues: Array<{ id: string; name: string; description: string }>;
|
||||
teams: Array<{ id: string; name: string; description: string }>;
|
||||
races: Array<{ id: string; track: string; car: string; formattedDate: string }>;
|
||||
}
|
||||
|
||||
/**
|
||||
* EcosystemGrid - Discovery section for the live ecosystem.
|
||||
* Designed with a "grid" layout and precision details.
|
||||
* Uses ONLY UI components.
|
||||
*/
|
||||
export function EcosystemGrid({ leagues, teams, races }: EcosystemGridProps) {
|
||||
return (
|
||||
<Section variant="muted" padding="lg">
|
||||
<Stack direction="col" gap={16}>
|
||||
<Stack direction={{ base: 'col', md: 'row' }} align="end" justify="between" gap={8}>
|
||||
<Stack direction="col" gap={4} maxWidth="42rem">
|
||||
<Text variant="primary" weight="bold" uppercase size="xs">
|
||||
Live Ecosystem
|
||||
</Text>
|
||||
<Heading level={2} weight="bold">
|
||||
THE GRID
|
||||
</Heading>
|
||||
<Text size="lg" variant="med" block>
|
||||
Explore the leagues, teams, and races that define the GridPilot ecosystem.
|
||||
</Text>
|
||||
</Stack>
|
||||
<Button variant="secondary" size="md">
|
||||
VIEW ALL DATA
|
||||
</Button>
|
||||
</Stack>
|
||||
|
||||
<FeatureGrid columns={{ base: 1, lg: 3 }} gap={8}>
|
||||
{/* Leagues Column */}
|
||||
<Stack direction="col" gap={6}>
|
||||
<Stack direction="row" align="center" gap={2} px={2}>
|
||||
<Trophy className="w-4 h-4 text-[var(--ui-color-text-low)]" />
|
||||
<Text size="sm" weight="bold" uppercase variant="low">Top Leagues</Text>
|
||||
</Stack>
|
||||
{leagues.slice(0, 3).map((league) => (
|
||||
<Card key={league.id} variant="default" padding="md">
|
||||
<Heading level={5} weight="bold">{league.name}</Heading>
|
||||
<Text size="sm" variant="low" leading="snug" block mt={2}>{league.description}</Text>
|
||||
</Card>
|
||||
))}
|
||||
</Stack>
|
||||
|
||||
{/* Teams Column */}
|
||||
<Stack direction="col" gap={6}>
|
||||
<Stack direction="row" align="center" gap={2} px={2}>
|
||||
<Users className="w-4 h-4 text-[var(--ui-color-text-low)]" />
|
||||
<Text size="sm" weight="bold" uppercase variant="low">Active Teams</Text>
|
||||
</Stack>
|
||||
{teams.slice(0, 3).map((team) => (
|
||||
<Card key={team.id} variant="default" padding="md">
|
||||
<Heading level={5} weight="bold">{team.name}</Heading>
|
||||
<Text size="sm" variant="low" leading="snug" block mt={2}>{team.description}</Text>
|
||||
</Card>
|
||||
))}
|
||||
</Stack>
|
||||
|
||||
{/* Races Column */}
|
||||
<Stack direction="col" gap={6}>
|
||||
<Stack direction="row" align="center" gap={2} px={2}>
|
||||
<Flag className="w-4 h-4 text-[var(--ui-color-text-low)]" />
|
||||
<Text size="sm" weight="bold" uppercase variant="low">Upcoming Races</Text>
|
||||
</Stack>
|
||||
{races.slice(0, 3).map((race) => (
|
||||
<Card key={race.id} variant="default" padding="md">
|
||||
<Stack direction="row" justify="between" align="start">
|
||||
<Stack direction="col" gap={1}>
|
||||
<Heading level={5} weight="bold">{race.track}</Heading>
|
||||
<Text size="xs" variant="primary" weight="bold" uppercase>{race.car}</Text>
|
||||
</Stack>
|
||||
<Text size="xs" variant="low" mono>{race.formattedDate}</Text>
|
||||
</Stack>
|
||||
</Card>
|
||||
))}
|
||||
</Stack>
|
||||
</FeatureGrid>
|
||||
</Stack>
|
||||
</Section>
|
||||
);
|
||||
}
|
||||
65
apps/website/components/home/Hero.tsx
Normal file
65
apps/website/components/home/Hero.tsx
Normal file
@@ -0,0 +1,65 @@
|
||||
'use client';
|
||||
|
||||
import { Heading } from '@/ui/Heading';
|
||||
import { Text } from '@/ui/Text';
|
||||
import { Button } from '@/ui/Button';
|
||||
import { Section } from '@/ui/Section';
|
||||
import { ButtonGroup } from '@/ui/ButtonGroup';
|
||||
import { Stack } from '@/ui/Stack';
|
||||
import { Box } from '@/ui/Box';
|
||||
|
||||
/**
|
||||
* Hero - Refined with Dieter Rams principles.
|
||||
* "Less, but better."
|
||||
* Focuses on clarity, honesty, and unobtrusive design.
|
||||
*/
|
||||
export function Hero() {
|
||||
return (
|
||||
<Section variant="default" py={32}>
|
||||
<Box maxWidth="54rem">
|
||||
<Box marginBottom={24}>
|
||||
<Text
|
||||
variant="primary"
|
||||
weight="bold"
|
||||
uppercase
|
||||
size="xs"
|
||||
leading="none"
|
||||
block
|
||||
letterSpacing="0.2em"
|
||||
marginBottom={10}
|
||||
>
|
||||
Sim Racing Infrastructure
|
||||
</Text>
|
||||
|
||||
<Heading level={1} weight="bold" size="4xl">
|
||||
Professional League Management.<br />
|
||||
Engineered for Control.
|
||||
</Heading>
|
||||
</Box>
|
||||
|
||||
<Box marginBottom={24}>
|
||||
<Text size="xl" variant="med" leading="relaxed" block maxWidth="42rem">
|
||||
GridPilot eliminates the administrative overhead of running iRacing leagues.
|
||||
No spreadsheets. No manual points. No protest chaos.
|
||||
Just pure competition, structured for growth.
|
||||
</Text>
|
||||
</Box>
|
||||
|
||||
<ButtonGroup gap={10}>
|
||||
<Button
|
||||
variant="primary"
|
||||
size="lg"
|
||||
>
|
||||
Create Your League
|
||||
</Button>
|
||||
<Button
|
||||
variant="secondary"
|
||||
size="lg"
|
||||
>
|
||||
View Demo
|
||||
</Button>
|
||||
</ButtonGroup>
|
||||
</Box>
|
||||
</Section>
|
||||
);
|
||||
}
|
||||
151
apps/website/components/home/LeagueIdentityPreview.tsx
Normal file
151
apps/website/components/home/LeagueIdentityPreview.tsx
Normal file
@@ -0,0 +1,151 @@
|
||||
'use client';
|
||||
|
||||
import React from 'react';
|
||||
import { Section } from '@/ui/Section';
|
||||
import { Panel } from '@/ui/Panel';
|
||||
import { Text } from '@/ui/Text';
|
||||
import { Heading } from '@/ui/Heading';
|
||||
import { Group } from '@/ui/Group';
|
||||
import { Stack } from '@/ui/Stack';
|
||||
import { Grid } from '@/ui/Grid';
|
||||
import { Box } from '@/ui/Box';
|
||||
import { StatusBadge } from '@/ui/StatusBadge';
|
||||
import { Trophy, Globe, Settings2, Palette, ShieldCheck, BarChart3 } from 'lucide-react';
|
||||
|
||||
/**
|
||||
* LeagueIdentityPreview - Radically redesigned for "Modern Precision" and "Dieter Rams" style.
|
||||
* Focuses on the professional identity and deep customization options for admins.
|
||||
*/
|
||||
export function LeagueIdentityPreview() {
|
||||
return (
|
||||
<Section variant="default" py={32}>
|
||||
<Box>
|
||||
<Box marginBottom={24} maxWidth="42rem">
|
||||
<Heading level={2} weight="bold" marginBottom={8}>Your Brand. Your Rules.</Heading>
|
||||
<Text variant="med" size="lg" leading="relaxed">
|
||||
GridPilot is designed to be invisible where it matters, letting your league's identity take center stage.
|
||||
Professional tools that respect your community's unique culture.
|
||||
</Text>
|
||||
</Box>
|
||||
|
||||
<Grid cols={{ base: 1, md: 2 }} gap={20}>
|
||||
{/* Your Brand - Visual Identity */}
|
||||
<Box>
|
||||
<Panel variant="muted" padding="lg">
|
||||
<Stack gap={8}>
|
||||
<Stack gap={2}>
|
||||
<Group gap={2}>
|
||||
<Palette size={16} className="text-[var(--ui-color-intent-primary)]" />
|
||||
<Text variant="primary" weight="bold" uppercase size="xs" letterSpacing="0.1em">Your Brand</Text>
|
||||
</Group>
|
||||
<Heading level={3} weight="bold">Professional Presence</Heading>
|
||||
<Text variant="low" size="sm">Build prestige with a dedicated home for your competition.</Text>
|
||||
</Stack>
|
||||
|
||||
<Stack gap={4}>
|
||||
<Panel variant="bordered" padding="md">
|
||||
<Group gap={4}>
|
||||
<Globe size={20} className="text-[var(--ui-color-text-low)]" />
|
||||
<Stack gap={1}>
|
||||
<Text weight="bold">Custom Subdomains</Text>
|
||||
<Text size="xs" variant="low">yourleague.gridpilot.racing</Text>
|
||||
</Stack>
|
||||
</Group>
|
||||
</Panel>
|
||||
<Panel variant="bordered" padding="md">
|
||||
<Group gap={4}>
|
||||
<Trophy size={20} className="text-[var(--ui-color-text-low)]" />
|
||||
<Stack gap={1}>
|
||||
<Text weight="bold">Live Standings</Text>
|
||||
<Text size="xs" variant="low">Real-time updates across all car classes.</Text>
|
||||
</Stack>
|
||||
</Group>
|
||||
</Panel>
|
||||
<Panel variant="bordered" padding="md">
|
||||
<Group gap={4}>
|
||||
<BarChart3 size={20} className="text-[var(--ui-color-text-low)]" />
|
||||
<Stack gap={1}>
|
||||
<Text weight="bold">Driver Roster</Text>
|
||||
<Text size="xs" variant="low">Detailed profiles with lifetime league stats.</Text>
|
||||
</Stack>
|
||||
</Group>
|
||||
</Panel>
|
||||
|
||||
<Panel variant="elevated" padding="sm">
|
||||
<Group gap={3}>
|
||||
<Box width="2.5rem" height="2.5rem" bg="var(--ui-color-bg-surface)" rounded="sm" border={true} display="flex" alignItems="center" justifyContent="center">
|
||||
<Trophy size={20} className="text-[var(--ui-color-text-low)]" />
|
||||
</Box>
|
||||
<Stack gap={0}>
|
||||
<Text weight="bold" size="sm">Apex Racing League</Text>
|
||||
<Text size="xs" variant="low">apex.gridpilot.racing</Text>
|
||||
</Stack>
|
||||
</Group>
|
||||
</Panel>
|
||||
</Stack>
|
||||
</Stack>
|
||||
</Panel>
|
||||
</Box>
|
||||
|
||||
{/* Your Rules - Deep Customization */}
|
||||
<Box>
|
||||
<Panel variant="muted" padding="lg">
|
||||
<Stack gap={8}>
|
||||
<Stack gap={2}>
|
||||
<Group gap={2}>
|
||||
<Settings2 size={16} className="text-[var(--ui-color-intent-primary)]" />
|
||||
<Text variant="primary" weight="bold" uppercase size="xs" letterSpacing="0.1em">Your Rules</Text>
|
||||
</Group>
|
||||
<Heading level={3} weight="bold">Absolute Control</Heading>
|
||||
<Text variant="low" size="sm">The platform adapts to your league, not the other way around.</Text>
|
||||
</Stack>
|
||||
|
||||
<Stack gap={4}>
|
||||
<Panel variant="bordered" padding="md">
|
||||
<Group gap={4}>
|
||||
<ShieldCheck size={20} className="text-[var(--ui-color-text-low)]" />
|
||||
<Stack gap={1}>
|
||||
<Text weight="bold">Flexible Points Systems</Text>
|
||||
<Text size="xs" variant="low">Custom points for positions, fastest laps, and incidents.</Text>
|
||||
</Stack>
|
||||
</Group>
|
||||
</Panel>
|
||||
<Panel variant="bordered" padding="md">
|
||||
<Group gap={4}>
|
||||
<Settings2 size={20} className="text-[var(--ui-color-text-low)]" />
|
||||
<Stack gap={1}>
|
||||
<Text weight="bold">Drop Weeks & Playoffs</Text>
|
||||
<Text size="xs" variant="low">Configure complex season structures with ease.</Text>
|
||||
</Stack>
|
||||
</Group>
|
||||
</Panel>
|
||||
<Panel variant="bordered" padding="md">
|
||||
<Group gap={4}>
|
||||
<Trophy size={20} className="text-[var(--ui-color-text-low)]" />
|
||||
<Stack gap={1}>
|
||||
<Text weight="bold">Multi-Class Support</Text>
|
||||
<Text size="xs" variant="low">Manage GT3, GTP, and more in a single season.</Text>
|
||||
</Stack>
|
||||
</Group>
|
||||
</Panel>
|
||||
|
||||
<Panel variant="elevated" padding="sm">
|
||||
<Stack gap={2}>
|
||||
<Text size="xs" uppercase weight="bold" variant="low">Points Configuration</Text>
|
||||
<Group gap={2} wrap>
|
||||
<StatusBadge variant="info">P1: 25pts</StatusBadge>
|
||||
<StatusBadge variant="info">P2: 18pts</StatusBadge>
|
||||
<StatusBadge variant="info">P3: 15pts</StatusBadge>
|
||||
<StatusBadge variant="warning">INC: -1pt</StatusBadge>
|
||||
</Group>
|
||||
</Stack>
|
||||
</Panel>
|
||||
</Stack>
|
||||
</Stack>
|
||||
</Panel>
|
||||
</Box>
|
||||
</Grid>
|
||||
</Box>
|
||||
</Section>
|
||||
);
|
||||
}
|
||||
47
apps/website/components/home/MigrationSection.tsx
Normal file
47
apps/website/components/home/MigrationSection.tsx
Normal file
@@ -0,0 +1,47 @@
|
||||
'use client';
|
||||
|
||||
import React from 'react';
|
||||
import { Section } from '@/ui/Section';
|
||||
import { Heading } from '@/ui/Heading';
|
||||
import { Text } from '@/ui/Text';
|
||||
import { Button } from '@/ui/Button';
|
||||
import { Stack } from '@/ui/Stack';
|
||||
import { Group } from '@/ui/Group';
|
||||
import { Panel } from '@/ui/Panel';
|
||||
import { ArrowRight, Database } from 'lucide-react';
|
||||
import { routes } from '@/lib/routing/RouteConfig';
|
||||
|
||||
/**
|
||||
* MigrationSection - Offers help with migrating existing league data.
|
||||
*/
|
||||
export function MigrationSection() {
|
||||
return (
|
||||
<Section variant="default" py={32}>
|
||||
<Panel variant="bordered" padding="xl">
|
||||
<Group justify="between" align="center" gap={12} wrap>
|
||||
<Stack gap={6} flex={1} minWidth="20rem">
|
||||
<Group gap={3}>
|
||||
<Database size={20} className="text-[var(--ui-color-intent-primary)]" />
|
||||
<Text variant="primary" weight="bold" uppercase size="xs" letterSpacing="0.1em">League Migration</Text>
|
||||
</Group>
|
||||
<Heading level={2} weight="bold">Moving from Sheets or Discord?</Heading>
|
||||
<Text variant="med" size="lg">
|
||||
We know that moving years of history is daunting. Send us your data, and we will handle the migration for you — for free.
|
||||
We support CSV, Google Sheets, and manual data entry.
|
||||
</Text>
|
||||
</Stack>
|
||||
|
||||
<Button
|
||||
as="a"
|
||||
href={routes.league.migration}
|
||||
variant="primary"
|
||||
size="lg"
|
||||
icon={<ArrowRight size={18} />}
|
||||
>
|
||||
Start Migration
|
||||
</Button>
|
||||
</Group>
|
||||
</Panel>
|
||||
</Section>
|
||||
);
|
||||
}
|
||||
101
apps/website/components/home/StewardingPreview.tsx
Normal file
101
apps/website/components/home/StewardingPreview.tsx
Normal file
@@ -0,0 +1,101 @@
|
||||
'use client';
|
||||
|
||||
import React from 'react';
|
||||
import { Section } from '@/ui/Section';
|
||||
import { Panel } from '@/ui/Panel';
|
||||
import { Text } from '@/ui/Text';
|
||||
import { Heading } from '@/ui/Heading';
|
||||
import { StatusBadge } from '@/ui/StatusBadge';
|
||||
import { Button } from '@/ui/Button';
|
||||
import { Group } from '@/ui/Group';
|
||||
import { Stack } from '@/ui/Stack';
|
||||
import { Grid } from '@/ui/Grid';
|
||||
import { Box } from '@/ui/Box';
|
||||
import { Gavel, Clock, User, MessageSquare } from 'lucide-react';
|
||||
|
||||
/**
|
||||
* StewardingPreview - Refined for "Modern Precision" and "Dieter Rams" style.
|
||||
* Thorough down to the last detail.
|
||||
*/
|
||||
export function StewardingPreview() {
|
||||
return (
|
||||
<Section variant="muted" py={32}>
|
||||
<Box>
|
||||
<Box marginBottom={16} maxWidth="42rem">
|
||||
<Heading level={2} weight="bold" marginBottom={6}>Structured Stewarding</Heading>
|
||||
<Text variant="med" size="lg" leading="relaxed">
|
||||
Protests are part of racing. Managing them shouldn't be a second job.
|
||||
GridPilot provides a dedicated workflow for drivers to report incidents and for you to resolve them with precision.
|
||||
</Text>
|
||||
</Box>
|
||||
|
||||
<Panel variant="elevated" padding="lg">
|
||||
<Stack gap={8}>
|
||||
<Group justify="between" align="center">
|
||||
<Stack gap={1}>
|
||||
<Group gap={2}>
|
||||
<Text variant="low" size="xs" uppercase weight="bold" letterSpacing="0.1em">Incident Report</Text>
|
||||
<Text variant="low" size="xs">•</Text>
|
||||
<Text variant="low" size="xs" uppercase weight="bold" letterSpacing="0.1em">ID: 402-WG</Text>
|
||||
</Group>
|
||||
<Heading level={3} weight="bold">Turn 1 Contact: Miller vs Chen</Heading>
|
||||
</Stack>
|
||||
<StatusBadge variant="warning">UNDER REVIEW</StatusBadge>
|
||||
</Group>
|
||||
|
||||
<Grid cols={{ base: 1, md: 3 }} gap={6}>
|
||||
<Panel variant="bordered" padding="md">
|
||||
<Stack gap={3}>
|
||||
<Group gap={2}>
|
||||
<User size={14} className="text-[var(--ui-color-intent-primary)]" />
|
||||
<Text size="xs" uppercase weight="bold" variant="low">Protestor</Text>
|
||||
</Group>
|
||||
<Text weight="bold">Alex Miller</Text>
|
||||
<Text size="sm" variant="low">#42 - Porsche 911 GT3 R</Text>
|
||||
</Stack>
|
||||
</Panel>
|
||||
<Panel variant="bordered" padding="md">
|
||||
<Stack gap={3}>
|
||||
<Group gap={2}>
|
||||
<User size={14} className="text-[var(--ui-color-intent-critical)]" />
|
||||
<Text size="xs" uppercase weight="bold" variant="low">Defendant</Text>
|
||||
</Group>
|
||||
<Text weight="bold">David Chen</Text>
|
||||
<Text size="sm" variant="low">#18 - BMW M4 GT3</Text>
|
||||
</Stack>
|
||||
</Panel>
|
||||
<Panel variant="bordered" padding="md">
|
||||
<Stack gap={3}>
|
||||
<Group gap={2}>
|
||||
<Clock size={14} className="text-[var(--ui-color-text-low)]" />
|
||||
<Text size="xs" uppercase weight="bold" variant="low">Session Info</Text>
|
||||
</Group>
|
||||
<Text weight="bold">Lap 1, 00:42.150</Text>
|
||||
<Text size="sm" variant="low">Watkins Glen - Cup</Text>
|
||||
</Stack>
|
||||
</Panel>
|
||||
</Grid>
|
||||
|
||||
<Stack gap={4}>
|
||||
<Group gap={2}>
|
||||
<MessageSquare size={14} className="text-[var(--ui-color-text-low)]" />
|
||||
<Text size="xs" uppercase weight="bold" variant="low">Description</Text>
|
||||
</Group>
|
||||
<Panel variant="muted" padding="md">
|
||||
<Text size="sm" variant="high" leading="relaxed">
|
||||
"David missed his braking point into T1 and hit my rear right corner.
|
||||
I was forced into the grass and lost 4 positions. Replay attached shows he was never alongside."
|
||||
</Text>
|
||||
</Panel>
|
||||
</Stack>
|
||||
|
||||
<Group gap={3} justify="end">
|
||||
<Button variant="secondary" size="md">Dismiss</Button>
|
||||
<Button variant="primary" size="md" icon={<Gavel size={16} />}>Apply Penalty</Button>
|
||||
</Group>
|
||||
</Stack>
|
||||
</Panel>
|
||||
</Box>
|
||||
</Section>
|
||||
);
|
||||
}
|
||||
45
apps/website/components/home/TelemetryStrip.tsx
Normal file
45
apps/website/components/home/TelemetryStrip.tsx
Normal file
@@ -0,0 +1,45 @@
|
||||
'use client';
|
||||
|
||||
import React from 'react';
|
||||
import { StatsStrip } from '@/ui/StatsStrip';
|
||||
import { Section } from '@/ui/Section';
|
||||
import { XCircle, CheckCircle2, AlertCircle, ShieldCheck } from 'lucide-react';
|
||||
|
||||
/**
|
||||
* TelemetryStrip - Redesigned as a "Status of Chaos" vs "Status of Order" strip.
|
||||
* Focuses on the transition from manual work to GridPilot.
|
||||
*/
|
||||
export function TelemetryStrip() {
|
||||
const stats = [
|
||||
{
|
||||
label: "NO SPREADSHEETS",
|
||||
value: "STRUCTURED",
|
||||
icon: CheckCircle2,
|
||||
intent: "success" as const
|
||||
},
|
||||
{
|
||||
label: "NO DM PROTESTS",
|
||||
value: "CENTRALIZED",
|
||||
icon: ShieldCheck,
|
||||
intent: "primary" as const
|
||||
},
|
||||
{
|
||||
label: "NO MANUAL POINTS",
|
||||
value: "AUTOMATED",
|
||||
icon: CheckCircle2,
|
||||
intent: "success" as const
|
||||
},
|
||||
{
|
||||
label: "NO ROSTER CHAOS",
|
||||
value: "MANAGED",
|
||||
icon: ShieldCheck,
|
||||
intent: "primary" as const
|
||||
},
|
||||
];
|
||||
|
||||
return (
|
||||
<Section variant="default" py={16}>
|
||||
<StatsStrip stats={stats} />
|
||||
</Section>
|
||||
);
|
||||
}
|
||||
50
apps/website/components/home/ValuePillars.tsx
Normal file
50
apps/website/components/home/ValuePillars.tsx
Normal file
@@ -0,0 +1,50 @@
|
||||
'use client';
|
||||
|
||||
import React from 'react';
|
||||
import { Section } from '@/ui/Section';
|
||||
import { FeatureGrid } from '@/ui/FeatureGrid';
|
||||
import { FeatureItem } from '@/ui/FeatureItem';
|
||||
import { Box } from '@/ui/Box';
|
||||
import { RefreshCw, Gavel, Layout } from 'lucide-react';
|
||||
|
||||
/**
|
||||
* ValuePillars - Redesigned for League Admin features.
|
||||
* Focuses on solving the core problems of league management.
|
||||
*/
|
||||
export function ValuePillars() {
|
||||
const pillars = [
|
||||
{
|
||||
title: "Automatic Results Sync",
|
||||
description: "Direct iRacing integration. Positions, incidents, and best laps imported instantly. Standings update the moment the race ends.",
|
||||
icon: RefreshCw,
|
||||
},
|
||||
{
|
||||
title: "Structured Stewarding",
|
||||
description: "A dedicated review panel for protests. Drivers submit timestamps and clips; you make the call. Points adjust automatically.",
|
||||
icon: Gavel,
|
||||
},
|
||||
{
|
||||
title: "Professional Presence",
|
||||
description: "A clean, modern home for your league. Schedules, standings, and rosters that build prestige and attract drivers.",
|
||||
icon: Layout,
|
||||
},
|
||||
];
|
||||
|
||||
return (
|
||||
<Section variant="default" py={32}>
|
||||
<Box>
|
||||
<FeatureGrid columns={{ base: 1, md: 3 }} gap={16}>
|
||||
{pillars.map((pillar) => (
|
||||
<FeatureItem
|
||||
key={pillar.title}
|
||||
title={pillar.title}
|
||||
description={pillar.description}
|
||||
icon={pillar.icon}
|
||||
/>
|
||||
))}
|
||||
</FeatureGrid>
|
||||
</Box>
|
||||
</Section>
|
||||
);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user