import { useTranslation } from "react-i18next"; import { SURFACE_COLORS, DEFAULT_SURFACE_COLOR, HIGHWAY_COLORS, DEFAULT_HIGHWAY_COLOR, } from "@trails-cool/map-core"; import { formatDistanceKm } from "~/lib/stats"; export interface SurfaceBreakdownData { surface: Record; highway: Record; } function Bar({ title, data, colorFor, }: { title: string; data: Record; colorFor: (category: string) => string; }) { const { t } = useTranslation("journal"); const entries = Object.entries(data) .filter(([, m]) => m > 0) .sort((a, b) => b[1] - a[1]); const total = entries.reduce((s, [, m]) => s + m, 0); if (total <= 0) return null; const label = (cat: string) => cat === "unknown" ? t("surface.other") : t(`surface.cat.${cat}`, { defaultValue: cat.replace(/_/g, " ") }); return (

{title}

{entries.map(([cat, m]) => (
))}
    {entries.map(([cat, m]) => (
  • {label(cat)} {Math.round((m / total) * 100)}% · {formatDistanceKm(m)}
  • ))}
); } /** * Surface + waytype proportion bars (route-surface-breakdown). Renders nothing * when there's no breakdown data. Colours come from the shared map-core * palettes; unknown tags collapse into "other". */ export function SurfaceBreakdown({ breakdown, className, }: { breakdown: SurfaceBreakdownData | null | undefined; className?: string; }) { const { t } = useTranslation("journal"); if (!breakdown) return null; const hasSurface = Object.values(breakdown.surface).some((m) => m > 0); const hasHighway = Object.values(breakdown.highway).some((m) => m > 0); if (!hasSurface && !hasHighway) return null; return (
SURFACE_COLORS[c] ?? DEFAULT_SURFACE_COLOR} /> HIGHWAY_COLORS[c] ?? DEFAULT_HIGHWAY_COLOR} />
); }