test: centralize evidence passport states
This commit is contained in:
@@ -1,10 +1,10 @@
|
||||
---
|
||||
import SourceBadge from "./SourceBadge.astro";
|
||||
import { ago, freshnessStatus } from "../lib/api";
|
||||
import { ago, freshnessStatus, passportDisplayStatus } from "../lib/api";
|
||||
type Props = { sources: string[]; sourceUrl?: string | null; observedAt?: string | null; periodLabel?: string | null; completeness?: number | null; confidence?: number | null; sampleSize?: number | null; independentPlayers?: number | null; coordinatePrecision?: "exact" | "approximate" | "area" | "missing" | null; sourceConflicts?: string[]; status?: "verified" | "unverified" | "incomplete" | "insufficient" | "blocked" };
|
||||
const { sources, sourceUrl, observedAt, periodLabel = null, completeness = null, confidence = null, sampleSize = null, independentPlayers = null, coordinatePrecision = null, sourceConflicts = [], status = "verified" } = Astro.props as Props;
|
||||
const freshness = freshnessStatus(observedAt);
|
||||
const displayStatus = sourceConflicts.length ? "conflict" : status === "verified" && freshness === "stale" ? "stale" : status;
|
||||
const displayStatus = passportDisplayStatus(status, freshness, sourceConflicts.length > 0);
|
||||
const statusLabels = { verified: "Учтено", unverified: "Ждёт проверки", incomplete: "Неполные данные", insufficient: "Недостаточно данных", blocked: "Источник ограничен", conflict: "Источники расходятся", stale: "Данные устарели" };
|
||||
const completenessLabel = completeness == null ? "Не рассчитана" : `${Math.min(100, Math.max(0, completeness))}% полей`;
|
||||
const precisionLabels = { exact: "точные", approximate: "приблизительные", area: "район", missing: "не указаны" };
|
||||
|
||||
@@ -37,7 +37,7 @@ export type MediaAsset = { id: string; entity_type: "fish" | "waterbody" | "tack
|
||||
|
||||
export const spotPath = (item: Pick<Activity, "waterbody_slug" | "x" | "y">) => `/spots/${item.waterbody_slug}-${item.x}x${item.y}`;
|
||||
|
||||
export { activityLevel, ago, freshnessStatus, kg, plural, sourceStatusLabel } from "./presentation";
|
||||
export { activityLevel, ago, freshnessStatus, kg, passportDisplayStatus, plural, sourceStatusLabel } from "./presentation";
|
||||
|
||||
const base = process.env.API_INTERNAL_URL || import.meta.env.API_INTERNAL_URL || "http://localhost:8000";
|
||||
|
||||
|
||||
@@ -28,6 +28,15 @@ export function freshnessStatus(value: string | null | undefined, now = Date.now
|
||||
return now - timestamp > 48 * 60 * 60 * 1000 ? "stale" : "fresh";
|
||||
}
|
||||
|
||||
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<string, string> = {
|
||||
healthy: "Актуален", stale: "Данные устарели", temporarily_limited: "Источник временно ограничен",
|
||||
|
||||
Reference in New Issue
Block a user