spb/countryatlas
Public
TypeScript 57%
Python 38.6%
JavaScript 3.6%
CSS 0.6%
1import { Clock } from 'lucide-react';2import { t } from '@/i18n';3import { cn } from '@/lib/cn';4import { formatDate, freshnessLevel, relativeFreshness } from '@/lib/format';5import type { ObservationStatus } from '@/lib/types';67/** Small retrieval-freshness chip: "Updated 3 d ago" with a colour + icon (never colour alone). */8export function FreshnessBadge({ retrievedAt, now, className }: { retrievedAt: string | null | undefined; now?: number; className?: string }) {9 const level = freshnessLevel(retrievedAt, now);10 if (!level) return null;11 return (12 <span13 className={cn(14 'inline-flex items-center gap-1 rounded-sm px-1.5 py-0.5 text-2xs font-medium',15 level === 'fresh' && 'bg-accent-soft text-accent',16 level === 'recent' && 'bg-surface-2 text-ink-2',17 level === 'stale' && 'bg-surface-2 text-warn',18 className,19 )}20 title={formatDate(retrievedAt)}21 >22 <Clock size={11} aria-hidden />23 {t('common.freshness.updated', { when: relativeFreshness(retrievedAt, now) })}24 </span>25 );26}2728export function StatusBadge({ status }: { status: ObservationStatus }) {29 const label = t(`common.status.${status}` as const);30 return (31 <span32 className={cn(33 'inline-flex items-center rounded-sm border px-1.5 py-0.5 text-2xs font-medium',34 status === 'verified' && 'border-rule text-ink-2',35 status === 'imported' && 'border-rule text-ink-3',36 (status === 'warning' || status === 'stale') && 'border-warn/40 text-warn',37 status === 'quarantined' && 'border-down/40 text-down',38 )}39 >40 {label}41 </span>42 );43}44