174 lines
5.4 KiB
TypeScript
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>
|
|
);
|
|
}
|