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

167 lines
5.5 KiB
TypeScript

import { Badge } from '@/ui/Badge';
import { Box } from '@/ui/Box';
import { Button } from '@/ui/Button';
import { Heading } from '@/ui/Heading';
import { Icon } from '@/ui/Icon';
import { Image } from '@/ui/Image';
import { Text } from '@/ui/Text';
import { Building, Check, Clock, DollarSign, MessageCircle, X } from 'lucide-react';
import React from 'react';
interface SponsorshipRequestItemProps {
sponsorName: string;
sponsorLogo?: string;
tier: string;
formattedAmount: string;
netAmount: number;
createdAt: Date;
message?: string;
isProcessing: boolean;
isRejecting: boolean;
rejectReason: string;
onAccept: () => void;
onRejectClick: () => void;
onRejectConfirm: () => void;
onRejectCancel: () => void;
onRejectReasonChange: (reason: string) => void;
}
export function SponsorshipRequestItem({
sponsorName,
sponsorLogo,
tier,
formattedAmount,
netAmount,
createdAt,
message,
isProcessing,
isRejecting,
rejectReason,
onAccept,
onRejectClick,
onRejectConfirm,
onRejectCancel,
onRejectReasonChange,
}: SponsorshipRequestItemProps) {
return (
<Box rounded="lg" border borderColor="border-charcoal-outline" bg="bg-deep-graphite/70" p={4}>
{/* Reject Modal */}
{isRejecting && (
<Box mb={4} p={4} rounded="lg" bg="bg-iron-gray/50" border borderColor="border-red-500/30">
<Heading level={4} mb={2}>
Reject sponsorship from {sponsorName}?
</Heading>
<Box
as="textarea"
value={rejectReason}
onChange={(e: React.ChangeEvent<HTMLTextAreaElement>) => onRejectReasonChange(e.target.value)}
placeholder="Optional: Provide a reason for rejection..."
rows={2}
p={3}
py={2}
bg="bg-iron-gray/80"
color="text-white"
border
borderColor="border-charcoal-outline"
rounded="lg"
fullWidth
style={{ resize: 'none' }}
className="text-sm placeholder:text-gray-500 focus:ring-2 focus:ring-red-500 mb-3"
/>
<Box display="flex" gap={2}>
<Button variant="secondary" onClick={onRejectCancel} size="sm">
Cancel
</Button>
<Button
variant="danger"
onClick={onRejectConfirm}
disabled={isProcessing}
size="sm"
>
{isProcessing ? 'Rejecting...' : 'Confirm Reject'}
</Button>
</Box>
</Box>
)}
<Box display="flex" alignItems="start" justifyContent="between" gap={4}>
<Box display="flex" alignItems="start" gap={3} flexGrow={1}>
{/* Sponsor Logo */}
<Box display="flex" h="12" w="12" alignItems="center" justifyContent="center" rounded="lg" bg="bg-iron-gray/50" flexShrink={0}>
{sponsorLogo ? (
<Image src={sponsorLogo} alt={sponsorName} width={32} height={32} objectFit="contain" />
) : (
<Icon icon={Building} size={6} color="rgb(156, 163, 175)" />
)}
</Box>
<Box flexGrow={1} minWidth="0">
<Box display="flex" alignItems="center" gap={2} mb={1}>
<Heading level={4} truncate>
{sponsorName}
</Heading>
<Badge variant={tier === 'main' ? 'primary' : 'default'}>
{tier === 'main' ? 'Main Sponsor' : 'Secondary'}
</Badge>
</Box>
{/* Offer Details */}
<Box display="flex" flexWrap="wrap" gap={3} mb={2}>
<Box display="flex" alignItems="center" gap={1}>
<Icon icon={DollarSign} size={3} color="rgb(16, 185, 129)" />
<Text weight="semibold" color="text-performance-green" size="xs">{formattedAmount}</Text>
</Box>
<Box display="flex" alignItems="center" gap={1}>
<Text color="text-gray-500" size="xs">Net: ${(netAmount / 100).toFixed(2)}</Text>
</Box>
<Box display="flex" alignItems="center" gap={1}>
<Icon icon={Clock} size={3} color="rgb(156, 163, 175)" />
<Text color="text-gray-500" size="xs">
{createdAt.toLocaleDateString('en-US', {
month: 'short',
day: 'numeric',
})}
</Text>
</Box>
</Box>
{/* Message */}
{message && (
<Box display="flex" alignItems="start" gap={1.5} p={2} bg="bg-iron-gray/30" rounded>
<Icon icon={MessageCircle} size={3} color="rgb(156, 163, 175)" flexShrink={0} mt={0.5} />
<Text size="xs" color="text-gray-400" lineClamp={2}>{message}</Text>
</Box>
)}
</Box>
</Box>
{/* Actions */}
{!isRejecting && (
<Box display="flex" gap={2} flexShrink={0}>
<Button
variant="primary"
onClick={onAccept}
disabled={isProcessing}
size="sm"
icon={<Icon icon={Check} size={3} />}
>
{isProcessing ? 'Accepting...' : 'Accept'}
</Button>
<Button
variant="secondary"
onClick={onRejectClick}
disabled={isProcessing}
size="sm"
icon={<Icon icon={X} size={3} />}
>
Reject
</Button>
</Box>
)}
</Box>
</Box>
);
}