Files
gridpilot.gg/apps/website/components/sponsors/SponsorContractCard.tsx
2026-01-18 23:24:30 +01:00

143 lines
4.7 KiB
TypeScript

'use client';
import { Button } from '@/ui/Button';
import { Card } from '@/ui/Card';
import { Heading } from '@/ui/Heading';
import { Icon } from '@/ui/Icon';
import { Stack } from '@/ui/Stack';
import { Text } from '@/ui/Text';
import {
BarChart3,
Calendar,
Car,
ChevronRight,
ExternalLink,
Flag,
Megaphone,
Trophy,
Users
} from 'lucide-react';
import { SponsorStatus, SponsorStatusChip } from './SponsorStatusChip';
export type SponsorshipType = 'league' | 'team' | 'driver' | 'race' | 'platform';
interface SponsorContractCardProps {
id: string;
type: SponsorshipType;
status: string; // Accept raw status string
title: string;
subtitle?: string;
tier: string;
investment: string;
impressions: string;
startDate?: string;
endDate?: string;
onViewDetails?: (id: string) => void;
}
const TYPE_CONFIG = {
league: { icon: Trophy, color: 'text-primary-blue', bgColor: 'bg-primary-blue/10', label: 'League' },
team: { icon: Users, color: 'text-purple-400', bgColor: 'bg-purple-400/10', label: 'Team' },
driver: { icon: Car, color: 'text-performance-green', bgColor: 'bg-performance-green/10', label: 'Driver' },
race: { icon: Flag, color: 'text-warning-amber', bgColor: 'bg-warning-amber/10', label: 'Race' },
platform: { icon: Megaphone, color: 'text-racing-red', bgColor: 'bg-racing-red/10', label: 'Platform' },
};
function mapStatus(status: string): SponsorStatus {
if (status === 'pending_approval' || status === 'pending') return 'pending';
if (status === 'rejected' || status === 'declined') return 'declined';
if (status === 'expired') return 'expired';
if (status === 'approved') return 'approved';
if (status === 'active') return 'active';
return 'pending';
}
/**
* SponsorContractCard
*
* Semantic component for displaying a sponsorship contract/campaign.
* Provides a high-density overview of the sponsorship status and performance.
*/
export function SponsorContractCard({
id,
type,
status,
title,
subtitle,
tier,
investment,
impressions,
startDate,
endDate,
onViewDetails
}: SponsorContractCardProps) {
const typeConfig = TYPE_CONFIG[type];
const mappedStatus = mapStatus(status);
return (
<Card p={5} hoverBorderColor="border-primary-blue/30">
<Stack direction="row" align="start" justify="between" mb={4}>
<Stack direction="row" align="center" gap={3}>
<Stack w="10" h="10" rounded="lg" bg={typeConfig.bgColor as string} display="flex" alignItems="center" justifyContent="center">
<Icon icon={typeConfig.icon} size={5} color={typeConfig.color as string} />
</Stack>
<Stack>
<Text size="xs" weight="bold" uppercase letterSpacing="wider" color={typeConfig.color as string}>
{typeConfig.label} {tier}
</Text>
<Heading level={4} fontSize="lg" weight="bold" color="text-white">
{title}
</Heading>
{subtitle && <Text size="xs" color="text-gray-500">{subtitle}</Text>}
</Stack>
</Stack>
<SponsorStatusChip status={mappedStatus} />
</Stack>
<Stack display="grid" gridCols={3} gap={4} mb={4} p={3} rounded="lg" bg="bg-iron-gray/20">
<Stack>
<Text size="xs" color="text-gray-500" block mb={1}>Impressions</Text>
<Stack direction="row" align="center" gap={1}>
<Icon icon={BarChart3} size={3} color="text-gray-400" />
<Text weight="bold" color="text-white">{impressions}</Text>
</Stack>
</Stack>
<Stack>
<Text size="xs" color="text-gray-500" block mb={1}>Investment</Text>
<Text weight="bold" color="text-white">{investment}</Text>
</Stack>
<Stack>
<Text size="xs" color="text-gray-500" block mb={1}>Term</Text>
<Stack direction="row" align="center" gap={1}>
<Icon icon={Calendar} size={3} color="text-gray-400" />
<Text weight="bold" color="text-white">{endDate || 'N/A'}</Text>
</Stack>
</Stack>
</Stack>
<Stack direction="row" align="center" justify="between" pt={4} borderTop borderColor="border-charcoal-outline/30">
<Text size="xs" color="text-gray-500">
{startDate ? `Started ${startDate}` : 'Contract pending'}
</Text>
<Stack direction="row" gap={2}>
<Button
variant="secondary"
size="sm"
icon={<Icon icon={ExternalLink} size={3} />}
onClick={() => onViewDetails?.(id)}
>
View
</Button>
<Button
variant="secondary"
size="sm"
icon={<Icon icon={ChevronRight} size={3} />}
>
Details
</Button>
</Stack>
</Stack>
</Card>
);
}