Files
runners-calendar/frontend/src/lib/raceVisuals.ts
2026-07-12 15:08:00 +03:00

93 lines
2.1 KiB
TypeScript

import type { Race } from "../api";
export type RaceVisualVariant = "short" | "half" | "marathon" | "trail" | "night";
export type RaceVisualFit = "cover" | "contain";
interface RaceVisual {
variant: RaceVisualVariant;
imageSrc: string;
fallbackSrc: string;
imageFit: RaceVisualFit;
label: string;
}
const FALLBACK_VISUALS: Record<RaceVisualVariant, RaceVisual> = {
short: {
variant: "short",
imageSrc: "/images/race-short.jpg",
fallbackSrc: "/images/race-short.jpg",
imageFit: "cover",
label: "Городской темп",
},
half: {
variant: "half",
imageSrc: "/images/race-half.jpg",
fallbackSrc: "/images/race-half.jpg",
imageFit: "cover",
label: "Полумарафон",
},
marathon: {
variant: "marathon",
imageSrc: "/images/race-marathon.jpg",
fallbackSrc: "/images/race-marathon.jpg",
imageFit: "cover",
label: "Марафон",
},
trail: {
variant: "trail",
imageSrc: "/images/race-trail.jpg",
fallbackSrc: "/images/race-trail.jpg",
imageFit: "cover",
label: "Трейл",
},
night: {
variant: "night",
imageSrc: "/images/race-night.jpg",
fallbackSrc: "/images/race-night.jpg",
imageFit: "cover",
label: "Ночной старт",
},
};
function getFallbackRaceVisual(race: Race): RaceVisual {
const title = race.title.toLowerCase();
if (title.includes("ночной")) {
return FALLBACK_VISUALS.night;
}
if (
title.includes("trail") ||
title.includes("extreme") ||
title.includes("suvorov") ||
title.includes("трейл") ||
title.includes("экстрим")
) {
return FALLBACK_VISUALS.trail;
}
if (Math.abs(race.distanceKm - 42.2) < 0.8) {
return FALLBACK_VISUALS.marathon;
}
if (Math.abs(race.distanceKm - 21.1) < 0.4) {
return FALLBACK_VISUALS.half;
}
return FALLBACK_VISUALS.short;
}
export function getRaceVisual(race: Race): RaceVisual {
const fallback = getFallbackRaceVisual(race);
if (race.coverImageUrl) {
return {
...fallback,
imageSrc: race.coverImageUrl,
fallbackSrc: fallback.imageSrc,
};
}
return fallback;
}