Files
gridpilot.gg/apps/website/components/teams/TeamCard.tsx
2026-01-18 13:26:35 +01:00

174 lines
5.4 KiB
TypeScript

import {
ChevronRight,
Globe,
Users
} from 'lucide-react';
import { ReactNode } from 'react';
import { Badge } from '@/ui/Badge';
import { Box } from '@/ui/Box';
import { Card } from '@/ui/Card';
import { Heading } from '@/ui/Heading';
import { Icon } from '@/ui/Icon';
import { Image } from '@/ui/Image';
import { PlaceholderImage } from '@/ui/PlaceholderImage';
import { Stack } from '@/ui/Stack';
import { Text } from '@/ui/Text';
interface TeamCardProps {
name: string;
description?: string;
logo?: string;
memberCount: number;
isRecruiting?: boolean;
performanceBadge?: ReactNode;
specializationContent?: ReactNode;
categoryBadge?: ReactNode;
region?: string;
languagesContent?: ReactNode;
statsContent?: ReactNode;
onClick?: () => void;
}
export function TeamCard({
name,
description,
logo,
memberCount,
isRecruiting,
performanceBadge,
specializationContent,
categoryBadge,
region,
languagesContent,
statsContent: _statsContent,
onClick,
}: TeamCardProps) {
return (
<Box onClick={onClick} h="full" cursor={onClick ? 'pointer' : 'default'} className="group">
<Card h="full" p={0} display="flex" flexDirection="col" overflow="hidden" className="bg-panel-gray/40 border-border-gray/50 hover:border-primary-accent/30 hover:bg-panel-gray/60 transition-all duration-300">
{/* Header with Logo */}
<Box p={5} pb={0}>
<Stack direction="row" align="start" gap={4}>
{/* Logo */}
<Box
w="16"
h="16"
rounded="none"
bg="graphite-black"
display="flex"
center
overflow="hidden"
border
borderColor="border-gray/50"
className="relative"
>
{logo ? (
<Image
src={logo}
alt={name}
width={64}
height={64}
fullWidth
fullHeight
objectFit="cover"
/>
) : (
<PlaceholderImage size={64} />
)}
<Box position="absolute" top="-1px" left="-1px" w="2" h="2" borderTop borderLeft borderColor="primary-accent/30" />
</Box>
{/* Title & Badges */}
<Box flexGrow={1} minWidth="0">
<Stack direction="row" align="start" justify="between" gap={2}>
<Heading level={4} weight="bold" fontSize="lg" className="tracking-tight group-hover:text-primary-accent transition-colors">
{name}
</Heading>
{isRecruiting && (
<Badge variant="success" size="xs">
RECRUITING
</Badge>
)}
</Stack>
{/* Performance Level & Category */}
<Stack direction="row" align="center" gap={2} wrap mt={2}>
{performanceBadge}
{specializationContent}
{categoryBadge}
</Stack>
</Box>
</Stack>
</Box>
{/* Content */}
<Box p={5} display="flex" flexDirection="col" flexGrow={1}>
{/* Description */}
<Text
size="xs"
color="text-gray-500"
mb={4}
lineClamp={2}
block
leading="relaxed"
style={{ height: '2.5rem' }}
>
{description || 'No description available'}
</Text>
{/* Region & Languages */}
{(region || languagesContent) && (
<Stack direction="row" align="center" gap={2} wrap mb={4}>
{region && (
<Box
display="flex"
alignItems="center"
gap={2}
px={2}
py={1}
rounded="none"
bg="panel-gray/20"
border
borderColor="border-gray/30"
>
<Icon icon={Globe} size={3} color="text-primary-accent" />
<Text size="xs" color="text-gray-400" weight="bold" className="uppercase tracking-widest">{region}</Text>
</Box>
)}
{languagesContent}
</Stack>
)}
{/* Spacer */}
<Box flexGrow={1} />
{/* Footer */}
<Box
display="flex"
alignItems="center"
justifyContent="between"
pt={4}
borderTop
borderColor="border-gray/30"
mt="auto"
>
<Stack direction="row" align="center" gap={2}>
<Icon icon={Users} size={3} color="text-gray-500" />
<Text size="xs" color="text-gray-500" font="mono">
{memberCount} {memberCount === 1 ? 'MEMBER' : 'MEMBERS'}
</Text>
</Stack>
<Stack direction="row" align="center" gap={1} className="group-hover:text-primary-accent transition-colors">
<Text size="xs" color="text-gray-500" weight="bold" className="uppercase tracking-widest">VIEW</Text>
<Icon icon={ChevronRight} size={3} color="text-gray-500" className="transition-transform group-hover:translate-x-0.5" />
</Stack>
</Box>
</Box>
</Card>
</Box>
);
}