website refactor

This commit is contained in:
2026-01-20 01:30:17 +01:00
parent 30a31dc44f
commit 3556db494f
6 changed files with 210 additions and 162 deletions

View File

@@ -8,8 +8,9 @@ import { Text } from '@/ui/Text';
import { Box } from '@/ui/Box';
import { Group } from '@/ui/Group';
import { Surface } from '@/ui/Surface';
import { Stack } from '@/ui/Stack';
import { LeagueCard as UILeagueCard, LeagueCardStats, LeagueCardFooter } from '@/ui/LeagueCard';
import { Calendar as LucideCalendar } from 'lucide-react';
import { Calendar, Users, Activity } from 'lucide-react';
import React, { ReactNode } from 'react';
interface LeagueCardProps {
@@ -54,80 +55,81 @@ export function LeagueCard({
coverUrl={coverUrl}
logo={
<Surface
width="3rem"
height="3rem"
rounded="md"
width="3.5rem"
height="3.5rem"
rounded="lg"
overflow="hidden"
border
variant="dark"
variant="precision"
>
{logoUrl ? (
<Image
src={logoUrl}
alt={`${name} logo`}
width={48}
height={48}
width={56}
height={56}
objectFit="cover"
/>
) : (
<PlaceholderImage size={48} />
<PlaceholderImage size={56} />
)}
</Surface>
}
badges={
<React.Fragment>
<Group gap={2}>
{badges}
{championshipBadge}
</React.Fragment>
</Group>
}
>
<Box marginBottom={1}>
<Group gap={2}>
<Box width="0.25rem" height="1rem" bg="var(--ui-color-intent-primary)" />
<Heading level={3} weight="bold" truncate>{name}</Heading>
</Group>
</Box>
<Text size="xs" variant="low" lineClamp={2} style={{ height: '2.5rem' }} block leading="relaxed" marginBottom={4}>
{description || 'No description available'}
</Text>
<LeagueCardStats
label={slotLabel}
value={`${usedSlots}/${maxSlots || '∞'}`}
percentage={fillPercentage}
intent={fillPercentage >= 90 ? 'warning' : fillPercentage >= 70 ? 'primary' : 'success'}
/>
{hasOpenSlots && (
<Box marginBottom={4}>
<Surface
display="flex"
alignItems="center"
gap={1.5}
paddingX={2}
paddingY={1}
bg="rgba(25, 140, 255, 0.05)"
border="1px solid rgba(25, 140, 255, 0.2)"
rounded="sm"
width="fit-content"
>
<Box width="0.375rem" height="0.375rem" rounded="full" bg="var(--ui-color-intent-primary)" />
<Text size="xs" variant="primary" weight="bold" uppercase>{openSlotsCount} OPEN</Text>
</Surface>
</Box>
)}
<LeagueCardFooter>
{timingSummary && (
<Group gap={2}>
<Icon icon={LucideCalendar} size={3} intent="low" />
<Text size="xs" variant="low" font="mono">
{timingSummary.split('•')[1]?.trim() || timingSummary}
</Text>
<Stack gap={4} fullHeight>
<Stack gap={1}>
<Group gap={2} align="center">
<Box width="2px" height="1rem" bg="var(--ui-color-intent-telemetry)" />
<Heading level={3} weight="bold" truncate>{name}</Heading>
</Group>
)}
</LeagueCardFooter>
<Text size="xs" variant="low" lineClamp={2} block leading="relaxed">
{description || 'No infrastructure description provided.'}
</Text>
</Stack>
<Box>
<LeagueCardStats
label={slotLabel}
value={`${usedSlots} / ${maxSlots || '∞'}`}
percentage={fillPercentage}
intent={fillPercentage >= 90 ? 'warning' : fillPercentage >= 70 ? 'primary' : 'success'}
/>
{hasOpenSlots && (
<Group gap={2} align="center">
<Icon icon={Activity} size={3} intent="success" />
<Text size="xs" variant="success" weight="bold" uppercase font="mono">
{openSlotsCount} slots available
</Text>
</Group>
)}
</Box>
<LeagueCardFooter>
<Stack gap={2}>
{timingSummary && (
<Group gap={2}>
<Icon icon={Calendar} size={3} intent="low" />
<Text size="xs" variant="low" font="mono">
{timingSummary.split('•')[1]?.trim() || timingSummary}
</Text>
</Group>
)}
<Group gap={2}>
<Icon icon={Users} size={3} intent="low" />
<Text size="xs" variant="low" font="mono">
{usedSlots} active participants
</Text>
</Group>
</Stack>
</LeagueCardFooter>
</Stack>
</UILeagueCard>
);
}

View File

@@ -5,6 +5,8 @@ import {
Flag,
Award,
Sparkles,
Gamepad2,
Layers,
} from 'lucide-react';
import type { LeagueSummaryViewModel } from '@/lib/view-models/LeagueSummaryViewModel';
import { getMediaUrl } from '@/lib/utilities/media';
@@ -152,24 +154,24 @@ export function LeagueCard({ league, onClick }: LeagueCardProps) {
badges={
<>
{isNew && (
<Badge variant="success" icon={Sparkles}>
<Badge variant="success" icon={Sparkles} size="sm">
NEW
</Badge>
)}
{league.scoring?.gameName && (
<Badge variant={gameVariant}>
<Badge variant={gameVariant} icon={Gamepad2} size="sm">
{league.scoring.gameName}
</Badge>
)}
{league.category && (
<Badge variant={categoryVariant}>
<Badge variant={categoryVariant} icon={Layers} size="sm">
{categoryLabel}
</Badge>
)}
</>
}
championshipBadge={
<Badge variant="default" icon={ChampionshipIcon}>
<Badge variant="outline" icon={ChampionshipIcon} size="sm">
{championshipLabel}
</Badge>
}