154 lines
4.4 KiB
TypeScript
154 lines
4.4 KiB
TypeScript
'use client';
|
|
|
|
import React, { useEffect, useMemo, useState } from 'react';
|
|
import Link from 'next/link';
|
|
import Image from 'next/image';
|
|
import MembershipStatus from '@/components/leagues/MembershipStatus';
|
|
import FeatureLimitationTooltip from '@/components/alpha/FeatureLimitationTooltip';
|
|
import {
|
|
getDriverRepository,
|
|
getDriverStats,
|
|
getAllDriverRankings,
|
|
getImageService,
|
|
} from '@/lib/di-container';
|
|
import type { DriverDTO } from '@gridpilot/racing/application/dto/DriverDTO';
|
|
import { EntityMappers } from '@gridpilot/racing/application/mappers/EntityMappers';
|
|
import DriverSummaryPill from '@/components/profile/DriverSummaryPill';
|
|
|
|
// 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,
|
|
ownerName,
|
|
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]);
|
|
|
|
const ownerSummary = useMemo(() => {
|
|
if (!ownerDriver) {
|
|
return null;
|
|
}
|
|
|
|
const stats = getDriverStats(ownerDriver.id);
|
|
const allRankings = getAllDriverRankings();
|
|
|
|
let rating: number | null = stats?.rating ?? null;
|
|
let rank: number | null = null;
|
|
|
|
if (stats) {
|
|
if (typeof stats.overallRank === 'number' && stats.overallRank > 0) {
|
|
rank = stats.overallRank;
|
|
} else {
|
|
const indexInGlobal = allRankings.findIndex(
|
|
(stat) => stat.driverId === stats.driverId,
|
|
);
|
|
if (indexInGlobal !== -1) {
|
|
rank = indexInGlobal + 1;
|
|
}
|
|
}
|
|
|
|
if (rating === null) {
|
|
const globalEntry = allRankings.find(
|
|
(stat) => stat.driverId === stats.driverId,
|
|
);
|
|
if (globalEntry) {
|
|
rating = globalEntry.rating;
|
|
}
|
|
}
|
|
}
|
|
|
|
return {
|
|
driver: ownerDriver,
|
|
rating,
|
|
rank,
|
|
};
|
|
}, [ownerDriver]);
|
|
|
|
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>
|
|
);
|
|
} |