export function kg(grams: number) { return `${(grams / 1000).toFixed(2)} кг`; } export function plural(number: number, forms: readonly [string, string, string]) { const absolute = Math.abs(number) % 100; const last = absolute % 10; if (absolute > 10 && absolute < 20) return forms[2]; if (last === 1) return forms[0]; if (last >= 2 && last <= 4) return forms[1]; return forms[2]; } export function activityLevel(score: number) { if (score >= 80) return { short: "Очень высокий", description: "Очень высокая активность" }; if (score >= 60) return { short: "Высокий", description: "Высокая активность" }; if (score >= 40) return { short: "Средний", description: "Средняя активность" }; return { short: "Низкий", description: "Низкая активность" }; } export function ago(value: string) { const minutes = Math.max(0, Math.round((Date.now() - new Date(value).getTime()) / 60000)); return minutes < 60 ? `${minutes} мин назад` : `${Math.floor(minutes / 60)} ч назад`; } export function freshnessStatus(value: string | null | undefined, now = Date.now()): "fresh" | "stale" | "unknown" { if (!value) return "unknown"; const timestamp = new Date(value).getTime(); if (!Number.isFinite(timestamp)) return "unknown"; return now - timestamp > 48 * 60 * 60 * 1000 ? "stale" : "fresh"; } export type CoordinatePrecision = "exact" | "approximate" | "area" | "missing"; export function coordinatePrecisionLabel(value: CoordinatePrecision | string | null | undefined): string { return ({ exact: "точные", approximate: "приблизительные", area: "район", missing: "не указаны" } as Record)[value ?? ""] ?? "не указаны"; } export type PassportStatus = "verified" | "unverified" | "incomplete" | "insufficient" | "blocked"; export type PassportDisplayStatus = PassportStatus | "conflict" | "stale"; export function passportDisplayStatus(status: PassportStatus, freshness: "fresh" | "stale" | "unknown", hasConflicts: boolean): PassportDisplayStatus { if (hasConflicts) return "conflict"; if (status === "verified" && freshness === "stale") return "stale"; return status; } export function sourceStatusLabel(status: string) { const labels: Record = { healthy: "Актуален", stale: "Данные устарели", temporarily_limited: "Источник временно ограничен", source_changed: "Источник изменился", waiting: "Ожидает запуска", disabled: "Выключен", }; return labels[status] ?? "Состояние не определено"; }