'use client'; import { useAppI18n } from '@/lib/i18n/provider'; import { Badge } from '@/components/ui/badge'; import { cn } from '@/lib/utils'; import type { OfficeTaskStatus, OfficeZoneView } from '@/lib/office'; import { officeTaskStatusLabel } from '@/lib/office'; export function OfficeStatusBadge({ status, className, }: { status: OfficeTaskStatus; className?: string; }) { const { locale } = useAppI18n(); return ( {officeTaskStatusLabel(status, locale)} ); } export function formatOfficeTime(value?: string | null, locale: 'zh-CN' | 'en-US' = 'zh-CN'): string { if (!value) return '-'; const date = new Date(value); if (Number.isNaN(date.getTime())) return value; return new Intl.DateTimeFormat(locale, { month: '2-digit', day: '2-digit', hour: '2-digit', minute: '2-digit', }).format(date); } export function formatOfficeDuration(durationMs: number | null, locale: 'zh-CN' | 'en-US' = 'zh-CN'): string { if (durationMs === null || durationMs < 0) return '-'; if (durationMs < 1000) return locale === 'en-US' ? '<1s' : '<1秒'; const seconds = Math.floor(durationMs / 1000); const hours = Math.floor(seconds / 3600); const minutes = Math.floor((seconds % 3600) / 60); const remainingSeconds = seconds % 60; if (hours > 0) return locale === 'en-US' ? `${hours}h ${minutes}m` : `${hours}小时 ${minutes}分`; if (minutes > 0) return locale === 'en-US' ? `${minutes}m ${remainingSeconds}s` : `${minutes}分 ${remainingSeconds}秒`; return locale === 'en-US' ? `${remainingSeconds}s` : `${remainingSeconds}秒`; } export function progressPercent(value: number | null, max: number | null): number { if (value === null || max === null || max <= 0) return 0; return Math.max(0, Math.min(100, Math.round((value / max) * 100))); } export function zonePanelClassName(zone: OfficeZoneView): string { return cn( 'relative min-h-[220px] overflow-hidden rounded-2xl border p-4 shadow-sm', 'before:pointer-events-none before:absolute before:inset-0 before:bg-[radial-gradient(circle_at_top_left,rgba(255,255,255,0.9),transparent_40%)]', zone.tone === 'info' && 'border-sky-200 bg-[linear-gradient(180deg,rgba(240,249,255,0.95),rgba(224,242,254,0.7))]', zone.tone === 'warn' && 'border-amber-200 bg-[linear-gradient(180deg,rgba(255,251,235,0.95),rgba(254,243,199,0.72))]', zone.tone === 'danger' && 'border-rose-200 bg-[linear-gradient(180deg,rgba(255,241,242,0.96),rgba(255,228,230,0.76))]', zone.tone === 'success' && 'border-emerald-200 bg-[linear-gradient(180deg,rgba(236,253,245,0.96),rgba(209,250,229,0.74))]', zone.tone === 'neutral' && 'border-border bg-card' ); }