website refactor
This commit is contained in:
168
apps/website/templates/SponsorCampaignsTemplate.tsx
Normal file
168
apps/website/templates/SponsorCampaignsTemplate.tsx
Normal file
@@ -0,0 +1,168 @@
|
||||
import React from 'react';
|
||||
import { Container } from '@/ui/Container';
|
||||
import { Stack } from '@/ui/Stack';
|
||||
import { Box } from '@/ui/Box';
|
||||
import { Button } from '@/ui/Button';
|
||||
import { Icon } from '@/ui/Icon';
|
||||
import { SponsorDashboardHeader } from '@/components/sponsors/SponsorDashboardHeader';
|
||||
import { BillingSummaryPanel } from '@/components/sponsors/BillingSummaryPanel';
|
||||
import { SponsorContractCard } from '@/components/sponsors/SponsorContractCard';
|
||||
import {
|
||||
Search,
|
||||
Check,
|
||||
Clock,
|
||||
Eye,
|
||||
BarChart3,
|
||||
LucideIcon
|
||||
} from 'lucide-react';
|
||||
|
||||
export type SponsorshipType = 'all' | 'leagues' | 'teams' | 'drivers' | 'races' | 'platform';
|
||||
export type SponsorshipStatus = 'all' | 'active' | 'pending_approval' | 'approved' | 'rejected' | 'expired';
|
||||
|
||||
export interface SponsorCampaignsViewData {
|
||||
sponsorships: Array<{
|
||||
id: string;
|
||||
type: string;
|
||||
status: string;
|
||||
leagueName: string;
|
||||
seasonName: string;
|
||||
tier: string;
|
||||
pricing: { amount: number; currency: string };
|
||||
metrics: { impressions: number };
|
||||
seasonStartDate?: Date;
|
||||
seasonEndDate?: Date;
|
||||
}>;
|
||||
stats: {
|
||||
total: number;
|
||||
active: number;
|
||||
pending: number;
|
||||
approved: number;
|
||||
rejected: number;
|
||||
totalInvestment: number;
|
||||
totalImpressions: number;
|
||||
};
|
||||
}
|
||||
|
||||
interface SponsorCampaignsTemplateProps {
|
||||
viewData: SponsorCampaignsViewData;
|
||||
filteredSponsorships: SponsorCampaignsViewData['sponsorships'];
|
||||
typeFilter: SponsorshipType;
|
||||
setTypeFilter: (type: SponsorshipType) => void;
|
||||
searchQuery: string;
|
||||
setSearchQuery: (query: string) => void;
|
||||
}
|
||||
|
||||
export function SponsorCampaignsTemplate({
|
||||
viewData,
|
||||
filteredSponsorships,
|
||||
typeFilter,
|
||||
setTypeFilter,
|
||||
searchQuery,
|
||||
setSearchQuery
|
||||
}: SponsorCampaignsTemplateProps) {
|
||||
const billingStats: Array<{
|
||||
label: string;
|
||||
value: string | number;
|
||||
icon: LucideIcon;
|
||||
variant: 'success' | 'warning' | 'info' | 'default';
|
||||
}> = [
|
||||
{
|
||||
label: 'Active Campaigns',
|
||||
value: viewData.stats.active,
|
||||
icon: Check,
|
||||
variant: 'success',
|
||||
},
|
||||
{
|
||||
label: 'Pending Approval',
|
||||
value: viewData.stats.pending,
|
||||
icon: Clock,
|
||||
variant: viewData.stats.pending > 0 ? 'warning' : 'default',
|
||||
},
|
||||
{
|
||||
label: 'Total Investment',
|
||||
value: `$${viewData.stats.totalInvestment.toLocaleString()}`,
|
||||
icon: BarChart3,
|
||||
variant: 'info',
|
||||
},
|
||||
{
|
||||
label: 'Total Impressions',
|
||||
value: `${(viewData.stats.totalImpressions / 1000).toFixed(0)}k`,
|
||||
icon: Eye,
|
||||
variant: 'default',
|
||||
},
|
||||
];
|
||||
|
||||
return (
|
||||
<Container size="lg" py={8}>
|
||||
<Stack gap={8}>
|
||||
<SponsorDashboardHeader
|
||||
sponsorName="Sponsor"
|
||||
onRefresh={() => console.log('Refresh')}
|
||||
/>
|
||||
|
||||
<BillingSummaryPanel stats={billingStats} />
|
||||
|
||||
<Box>
|
||||
<Stack direction={{ base: 'col', lg: 'row' }} gap={4} mb={6}>
|
||||
<Box position="relative" flexGrow={1}>
|
||||
<Box position="absolute" left={3} top="1/2" transform="-translate-y-1/2">
|
||||
<Icon icon={Search} size={4} color="text-gray-500" />
|
||||
</Box>
|
||||
<Box
|
||||
as="input"
|
||||
type="text"
|
||||
placeholder="Search sponsorships..."
|
||||
value={searchQuery}
|
||||
onChange={(e: React.ChangeEvent<HTMLInputElement>) => setSearchQuery(e.target.value)}
|
||||
w="full"
|
||||
pl={10}
|
||||
pr={4}
|
||||
py={2}
|
||||
rounded="lg"
|
||||
border
|
||||
borderColor="border-charcoal-outline"
|
||||
bg="bg-iron-gray/50"
|
||||
color="text-white"
|
||||
outline="none"
|
||||
focusBorderColor="border-primary-blue"
|
||||
/>
|
||||
</Box>
|
||||
|
||||
<Stack direction="row" gap={2} overflow="auto" pb={{ base: 2, lg: 0 }}>
|
||||
{(['all', 'leagues', 'teams', 'drivers'] as const).map((type) => (
|
||||
<Button
|
||||
key={type}
|
||||
variant={typeFilter === type ? 'primary' : 'secondary'}
|
||||
size="sm"
|
||||
onClick={() => setTypeFilter(type)}
|
||||
>
|
||||
{type.charAt(0).toUpperCase() + type.slice(1)}
|
||||
</Button>
|
||||
))}
|
||||
</Stack>
|
||||
</Stack>
|
||||
|
||||
<Box display="grid" gridCols={{ base: 1, lg: 2 }} gap={4}>
|
||||
{filteredSponsorships.map((s) => {
|
||||
return (
|
||||
<SponsorContractCard
|
||||
key={s.id}
|
||||
id={s.id}
|
||||
type="league"
|
||||
status={s.status}
|
||||
title={s.leagueName}
|
||||
subtitle={s.seasonName}
|
||||
tier={s.tier}
|
||||
investment={`$${s.pricing.amount.toLocaleString()}`}
|
||||
impressions={s.metrics.impressions.toLocaleString()}
|
||||
startDate={s.seasonStartDate ? new Date(s.seasonStartDate).toLocaleDateString() : undefined}
|
||||
endDate={s.seasonEndDate ? new Date(s.seasonEndDate).toLocaleDateString() : undefined}
|
||||
/>
|
||||
);
|
||||
})}
|
||||
</Box>
|
||||
</Box>
|
||||
</Stack>
|
||||
</Container>
|
||||
);
|
||||
}
|
||||
Reference in New Issue
Block a user