287 lines
9.9 KiB
TypeScript
287 lines
9.9 KiB
TypeScript
'use client';
|
|
|
|
import { BillingSummaryPanel } from '@/components/sponsors/BillingSummaryPanel';
|
|
import { MetricCard } from '@/components/sponsors/MetricCard';
|
|
import { RenewalAlert } from '@/components/sponsors/RenewalAlert';
|
|
import { Activity, SponsorActivityPanel } from '@/components/sponsors/SponsorActivityPanel';
|
|
import { SponsorContractCard } from '@/components/sponsors/SponsorContractCard';
|
|
import { SponsorDashboardHeader } from '@/components/sponsors/SponsorDashboardHeader';
|
|
import { SponsorshipCategoryCard } from '@/components/sponsors/SponsorshipCategoryCard';
|
|
import { routes } from '@/lib/routing/RouteConfig';
|
|
import type { SponsorDashboardViewData } from '@/lib/view-data/SponsorDashboardViewData';
|
|
import { Box } from '@/ui/Box';
|
|
import { Button } from '@/ui/Button';
|
|
import { Card } from '@/ui/Card';
|
|
import { Container } from '@/ui/Container';
|
|
import { Heading } from '@/ui/Heading';
|
|
import { Icon } from '@/ui/Icon';
|
|
import { Link } from '@/ui/Link';
|
|
import { Grid } from '@/ui/Grid';
|
|
import { GridItem } from '@/ui/GridItem';
|
|
import { Stack } from '@/ui/Stack';
|
|
import {
|
|
Bell,
|
|
Car,
|
|
ChevronRight,
|
|
Clock,
|
|
DollarSign,
|
|
Eye,
|
|
Flag,
|
|
LucideIcon,
|
|
Megaphone,
|
|
Plus,
|
|
TrendingUp,
|
|
Trophy,
|
|
Users
|
|
} from 'lucide-react';
|
|
|
|
interface SponsorDashboardTemplateProps {
|
|
viewData: SponsorDashboardViewData;
|
|
}
|
|
|
|
export function SponsorDashboardTemplate({ viewData }: SponsorDashboardTemplateProps) {
|
|
const categoryData = viewData.categoryData;
|
|
|
|
const billingStats: Array<{
|
|
label: string;
|
|
value: string | number;
|
|
icon: LucideIcon;
|
|
variant: 'info' | 'success' | 'default' | 'warning';
|
|
}> = [
|
|
{
|
|
label: 'Total Investment',
|
|
value: viewData.formattedTotalInvestment,
|
|
icon: DollarSign,
|
|
variant: 'info',
|
|
},
|
|
{
|
|
label: 'Active Sponsorships',
|
|
value: viewData.activeSponsorships,
|
|
icon: Trophy,
|
|
variant: 'success',
|
|
},
|
|
{
|
|
label: 'Cost per 1K Views',
|
|
value: viewData.costPerThousandViews,
|
|
icon: Eye,
|
|
variant: 'default',
|
|
},
|
|
{
|
|
label: 'Upcoming Renewals',
|
|
value: viewData.upcomingRenewals.length,
|
|
icon: Bell,
|
|
variant: viewData.upcomingRenewals.length > 0 ? 'warning' : 'default',
|
|
},
|
|
];
|
|
|
|
const activities: Activity[] = viewData.recentActivity.map(a => ({
|
|
id: a.id,
|
|
type: 'sponsorship_approved', // Mapping logic would go here
|
|
title: a.message,
|
|
description: a.formattedImpressions ? `${a.formattedImpressions} impressions` : '',
|
|
timestamp: a.time,
|
|
icon: Clock,
|
|
color: a.typeColor || 'text-primary-blue',
|
|
}));
|
|
|
|
return (
|
|
<Container size="lg" py={8}>
|
|
<Stack gap={8}>
|
|
{/* Header */}
|
|
<SponsorDashboardHeader
|
|
sponsorName={viewData.sponsorName}
|
|
onRefresh={() => console.log('Refresh')}
|
|
/>
|
|
|
|
{/* Billing Summary */}
|
|
<BillingSummaryPanel stats={billingStats} />
|
|
|
|
{/* Key Metrics */}
|
|
<Grid cols={4} gap={4}>
|
|
<MetricCard
|
|
title="Total Impressions"
|
|
value={viewData.totalImpressions}
|
|
change={viewData.metrics.impressionsChange}
|
|
icon={Eye}
|
|
delay={0}
|
|
/>
|
|
<MetricCard
|
|
title="Unique Viewers"
|
|
value="12.5k"
|
|
change={viewData.metrics.viewersChange}
|
|
icon={Users}
|
|
delay={0.1}
|
|
/>
|
|
<MetricCard
|
|
title="Engagement Rate"
|
|
value="4.2%"
|
|
change={viewData.metrics.exposureChange}
|
|
icon={TrendingUp}
|
|
suffix="%"
|
|
delay={0.2}
|
|
/>
|
|
<MetricCard
|
|
title="Total Investment"
|
|
value={viewData.totalInvestment}
|
|
icon={DollarSign}
|
|
prefix="$"
|
|
delay={0.3}
|
|
/>
|
|
</Grid>
|
|
|
|
{/* Main Content Grid */}
|
|
<Grid cols={12} gap={6}>
|
|
<GridItem colSpan={12} lgSpan={8}>
|
|
<Stack gap={6}>
|
|
{/* Sponsorship Categories */}
|
|
<Box>
|
|
<Stack direction="row" align="center" justify="between" mb={4}>
|
|
<Heading level={3}>Your Sponsorships</Heading>
|
|
<Link href={routes.sponsor.campaigns}>
|
|
<Button variant="secondary" size="sm" icon={<Icon icon={ChevronRight} size={4} />}>
|
|
View All
|
|
</Button>
|
|
</Link>
|
|
</Stack>
|
|
|
|
<Grid cols={5} gap={4}>
|
|
<SponsorshipCategoryCard
|
|
icon={Trophy}
|
|
title="Leagues"
|
|
countLabel={categoryData.leagues.countLabel}
|
|
impressionsLabel={categoryData.leagues.impressionsLabel}
|
|
color="#3b82f6"
|
|
href="/sponsor/campaigns?type=leagues"
|
|
/>
|
|
<SponsorshipCategoryCard
|
|
icon={Users}
|
|
title="Teams"
|
|
countLabel={categoryData.teams.countLabel}
|
|
impressionsLabel={categoryData.teams.impressionsLabel}
|
|
color="#a855f7"
|
|
href="/sponsor/campaigns?type=teams"
|
|
/>
|
|
<SponsorshipCategoryCard
|
|
icon={Car}
|
|
title="Drivers"
|
|
countLabel={categoryData.drivers.countLabel}
|
|
impressionsLabel={categoryData.drivers.impressionsLabel}
|
|
color="#10b981"
|
|
href="/sponsor/campaigns?type=drivers"
|
|
/>
|
|
<SponsorshipCategoryCard
|
|
icon={Flag}
|
|
title="Races"
|
|
countLabel={categoryData.races.countLabel}
|
|
impressionsLabel={categoryData.races.impressionsLabel}
|
|
color="#f59e0b"
|
|
href="/sponsor/campaigns?type=races"
|
|
/>
|
|
<SponsorshipCategoryCard
|
|
icon={Megaphone}
|
|
title="Platform Ads"
|
|
countLabel={categoryData.platform.countLabel}
|
|
impressionsLabel={categoryData.platform.impressionsLabel}
|
|
color="#ef4444"
|
|
href="/sponsor/campaigns?type=platform"
|
|
/>
|
|
</Grid>
|
|
</Box>
|
|
|
|
{/* Top Performing Sponsorships */}
|
|
<Box>
|
|
<Stack direction="row" align="center" justify="between" mb={4}>
|
|
<Heading level={3}>Top Performing</Heading>
|
|
<Link href={routes.public.leagues}>
|
|
<Button variant="secondary" size="sm" icon={<Icon icon={Plus} size={4} />}>
|
|
Find More
|
|
</Button>
|
|
</Link>
|
|
</Stack>
|
|
<Grid cols={2} gap={4}>
|
|
<SponsorContractCard
|
|
id="sample-1"
|
|
type="league"
|
|
status="active"
|
|
title="Sample League"
|
|
subtitle="Season 5 • GT3 Series"
|
|
tier="Main Sponsor"
|
|
investment="$2,500"
|
|
impressions="1.2M"
|
|
startDate="2025-10-01"
|
|
endDate="2026-02-15"
|
|
/>
|
|
<SponsorContractCard
|
|
id="sample-2"
|
|
type="team"
|
|
status="active"
|
|
title="Apex Racing Team"
|
|
subtitle="Endurance Championship"
|
|
tier="Secondary Sponsor"
|
|
investment="$1,200"
|
|
impressions="450k"
|
|
startDate="2025-11-15"
|
|
endDate="2026-03-20"
|
|
/>
|
|
</Grid>
|
|
</Box>
|
|
</Stack>
|
|
</GridItem>
|
|
|
|
<GridItem colSpan={12} lgSpan={4}>
|
|
<Stack gap={6}>
|
|
{/* Recent Activity */}
|
|
<SponsorActivityPanel activities={activities} />
|
|
|
|
{/* Quick Actions */}
|
|
<Card>
|
|
<Stack gap={4}>
|
|
<Heading level={3}>Quick Actions</Heading>
|
|
<Stack gap={2}>
|
|
<Link href={routes.public.leagues}>
|
|
<Button variant="secondary" fullWidth icon={<Icon icon={Trophy} size={4} />}>
|
|
Find Leagues to Sponsor
|
|
</Button>
|
|
</Link>
|
|
<Link href={routes.public.teams}>
|
|
<Button variant="secondary" fullWidth icon={<Icon icon={Users} size={4} />}>
|
|
Browse Teams
|
|
</Button>
|
|
</Link>
|
|
<Link href={routes.public.drivers}>
|
|
<Button variant="secondary" fullWidth icon={<Icon icon={Car} size={4} />}>
|
|
Discover Drivers
|
|
</Button>
|
|
</Link>
|
|
<Link href={routes.sponsor.billing}>
|
|
<Button variant="secondary" fullWidth icon={<Icon icon={DollarSign} size={4} />}>
|
|
Manage Billing
|
|
</Button>
|
|
</Link>
|
|
</Stack>
|
|
</Stack>
|
|
</Card>
|
|
|
|
{/* Renewal Alerts */}
|
|
{viewData.upcomingRenewals.length > 0 && (
|
|
<Card>
|
|
<Stack gap={4}>
|
|
<Heading level={3} icon={<Icon icon={Bell} size={5} color="#f59e0b" />}>
|
|
Upcoming Renewals
|
|
</Heading>
|
|
<Stack gap={3}>
|
|
{viewData.upcomingRenewals.map((renewal) => (
|
|
<RenewalAlert key={renewal.id} renewal={renewal} />
|
|
))}
|
|
</Stack>
|
|
</Stack>
|
|
</Card>
|
|
)}
|
|
</Stack>
|
|
</GridItem>
|
|
</Grid>
|
|
</Stack>
|
|
</Container>
|
|
);
|
|
}
|