Files
gridpilot.gg/apps/website/templates/SponsorDashboardTemplate.tsx
Marc Mintel 09632d004d
Some checks failed
CI / lint-typecheck (pull_request) Failing after 12s
CI / tests (pull_request) Has been skipped
CI / contract-tests (pull_request) Has been skipped
CI / e2e-tests (pull_request) Has been skipped
CI / comment-pr (pull_request) Has been skipped
CI / commit-types (pull_request) Has been skipped
code quality
2026-01-26 22:16:33 +01:00

308 lines
11 KiB
TypeScript

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 { Grid } from '@/ui/Grid';
import { Heading } from '@/ui/Heading';
import { Icon } from '@/ui/Icon';
import { Link } from '@/ui/Link';
import { Stack } from '@/ui/Stack';
import { Text } from '@/ui/Text';
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: any) => ({
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 || 'primary-accent',
}));
return (
<Container size="lg" spacing="md">
<Stack gap={8}>
{/* Header */}
<SponsorDashboardHeader
sponsorName={viewData.sponsorName}
onRefresh={() => console.log('Refresh')}
/>
{/* Billing Summary */}
<BillingSummaryPanel stats={billingStats} />
{/* Key Metrics */}
<Grid responsiveGridCols={{ base: 1, sm: 2, lg: 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.impressionsChange}
icon={Users}
delay={0.1}
/>
<MetricCard
title="Engagement Rate"
value="4.2%"
change={viewData.metrics.impressionsChange}
icon={TrendingUp}
suffix="%"
delay={0.2}
/>
<MetricCard
title="Total Investment"
value={viewData.totalInvestment}
icon={DollarSign}
prefix="$"
delay={0.3}
/>
</Grid>
{/* Main Content Grid */}
<Grid responsiveGridCols={{ base: 1, lg: 12 }} gap={6}>
<Box responsiveColSpan={{ base: 1, lg: 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">
<Stack direction="row" align="center" gap={2}>
<Text>View All</Text>
<Icon icon={ChevronRight} size={4} />
</Stack>
</Button>
</Link>
</Stack>
<Grid responsiveGridCols={{ base: 2, md: 3, lg: 5 }} gap={4}>
<SponsorshipCategoryCard
icon={Trophy}
title="Leagues"
countLabel={categoryData.leagues.countLabel}
impressionsLabel={categoryData.leagues.impressionsLabel}
color="primary-accent"
href="/sponsor/campaigns?type=leagues"
/>
<SponsorshipCategoryCard
icon={Users}
title="Teams"
countLabel={categoryData.teams.countLabel}
impressionsLabel={categoryData.teams.impressionsLabel}
color="var(--color-warning)"
href="/sponsor/campaigns?type=teams"
/>
<SponsorshipCategoryCard
icon={Car}
title="Drivers"
countLabel={categoryData.drivers.countLabel}
impressionsLabel={categoryData.drivers.impressionsLabel}
color="var(--color-success)"
href="/sponsor/campaigns?type=drivers"
/>
<SponsorshipCategoryCard
icon={Flag}
title="Races"
countLabel={categoryData.races.countLabel}
impressionsLabel={categoryData.races.impressionsLabel}
color="var(--color-warning)"
href="/sponsor/campaigns?type=races"
/>
<SponsorshipCategoryCard
icon={Megaphone}
title="Platform Ads"
countLabel={categoryData.platform.countLabel}
impressionsLabel={categoryData.platform.impressionsLabel}
color="critical-red"
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">
<Stack direction="row" align="center" gap={2}>
<Icon icon={Plus} size={4} />
<Text>Find More</Text>
</Stack>
</Button>
</Link>
</Stack>
<Grid responsiveGridCols={{ base: 1, md: 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>
</Box>
<Box responsiveColSpan={{ base: 1, lg: 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>
<Stack direction="row" align="center" gap={2}>
<Icon icon={Trophy} size={4} />
<Text>Find Leagues to Sponsor</Text>
</Stack>
</Button>
</Link>
<Link href={routes.public.teams}>
<Button variant="secondary" fullWidth>
<Stack direction="row" align="center" gap={2}>
<Icon icon={Users} size={4} />
<Text>Browse Teams</Text>
</Stack>
</Button>
</Link>
<Link href={routes.public.drivers}>
<Button variant="secondary" fullWidth>
<Stack direction="row" align="center" gap={2}>
<Icon icon={Car} size={4} />
<Text>Discover Drivers</Text>
</Stack>
</Button>
</Link>
<Link href={routes.sponsor.billing}>
<Button variant="secondary" fullWidth>
<Stack direction="row" align="center" gap={2}>
<Icon icon={DollarSign} size={4} />
<Text>Manage Billing</Text>
</Stack>
</Button>
</Link>
</Stack>
</Stack>
</Card>
{/* Renewal Alerts */}
{viewData.upcomingRenewals.length > 0 && (
<Card>
<Stack gap={4}>
<Heading level={3}>
<Stack direction="row" align="center" gap={2}>
<Icon icon={Bell} size={5} color="warning-amber" />
<Text>Upcoming Renewals</Text>
</Stack>
</Heading>
<Stack gap={3}>
{viewData.upcomingRenewals.map((renewal: any) => (
<RenewalAlert key={renewal.id} renewal={renewal} />
))}
</Stack>
</Stack>
</Card>
)}
</Stack>
</Box>
</Grid>
</Stack>
</Container>
);
}