Files
gridpilot.gg/apps/website/components/leagues/LeagueHeader.tsx
2025-12-20 11:02:15 +01:00

108 lines
3.1 KiB
TypeScript
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
'use client';
import MembershipStatus from '@/components/leagues/MembershipStatus';
import Image from 'next/image';
import { useEffect, useState } from 'react';
import type { DriverDTO } from '@core/racing/application/dto/DriverDTO';
import { EntityMappers } from '@core/racing/application/mappers/EntityMappers';
// TODO EntityMapper is legacy. Must use ´useServices` hook.
// Main sponsor info for "by XYZ" display
interface MainSponsorInfo {
name: string;
logoUrl?: string;
websiteUrl?: string;
}
export interface LeagueHeaderProps {
leagueId: string;
leagueName: string;
description?: string | null;
ownerId: string;
ownerName: string;
mainSponsor?: MainSponsorInfo | null;
}
export default function LeagueHeader({
leagueId,
leagueName,
description,
ownerId,
mainSponsor,
}: LeagueHeaderProps) {
const imageService = getImageService();
const logoUrl = imageService.getLeagueLogo(leagueId);
const [ownerDriver, setOwnerDriver] = useState<DriverDTO | null>(null);
useEffect(() => {
let isMounted = true;
async function loadOwner() {
try {
const driverRepo = getDriverRepository();
const entity = await driverRepo.findById(ownerId);
if (!entity || !isMounted) return;
setOwnerDriver(EntityMappers.toDriverDTO(entity));
} catch (err) {
console.error('Failed to load league owner for header:', err);
}
}
loadOwner();
return () => {
isMounted = false;
};
}, [ownerId]);
return (
<div className="mb-8">
{/* League header with logo - no cover image */}
<div className="flex items-center justify-between mb-6">
<div className="flex items-center gap-4">
<div className="h-16 w-16 rounded-xl overflow-hidden border-2 border-charcoal-outline bg-iron-gray shadow-lg">
<Image
src={logoUrl}
alt={`${leagueName} logo`}
width={64}
height={64}
className="w-full h-full object-cover"
/>
</div>
<div>
<div className="flex items-center gap-3 mb-1">
<h1 className="text-2xl font-bold text-white">
{leagueName}
{mainSponsor && (
<span className="text-gray-400 font-normal text-lg ml-2">
by{' '}
{mainSponsor.websiteUrl ? (
<a
href={mainSponsor.websiteUrl}
target="_blank"
rel="noreferrer"
className="text-primary-blue hover:text-primary-blue/80 transition-colors"
>
{mainSponsor.name}
</a>
) : (
<span className="text-primary-blue">{mainSponsor.name}</span>
)}
</span>
)}
</h1>
<MembershipStatus leagueId={leagueId} />
</div>
{description && (
<p className="text-gray-400 text-sm max-w-xl">{description}</p>
)}
</div>
</div>
</div>
</div>
);
}