// DocumentHeader — cabecera estándar (benchmark §5.2): serie/folio, badges de // cada máquina de estado, cliente enlazable, métricas (total, saldo, fechas) y // un identificador copiable (UUID). import { useState, type ReactNode } from 'react' import { useTranslation } from 'react-i18next' import { Check, Copy } from 'lucide-react' import { Button } from '@asteby/metacore-ui/primitives' import { cn } from '@asteby/metacore-ui/lib' import { StatusBadge } from './status-badge' import { formatFieldValue, type FieldFormatOptions } from './format' import type { StatusDef } from './types' export interface HeaderBadge { id: string label?: string status: StatusDef } export interface HeaderMetric { label: string value: string tone?: 'default' | 'critical' mono?: boolean } export interface DocumentHeaderProps { title: string /** Texto bajo el título; si `subtitleHref` viene, es un enlace (ficha del cliente). */ subtitle?: string subtitleHref?: string badges: HeaderBadge[] metrics?: HeaderMetric[] copyable?: { label: string; value: string } /** Zona de acciones (normalmente ``). */ actions?: ReactNode /** Slot antes del título (botón «Volver»). */ leading?: ReactNode /** Renderiza el subtítulo como enlace del router del host. */ renderLink?: (props: { href: string; children: ReactNode; className?: string }) => ReactNode className?: string } export function DocumentHeader({ title, subtitle, subtitleHref, badges, metrics, copyable, actions, leading, renderLink, className, }: DocumentHeaderProps) { const { t } = useTranslation() const [copied, setCopied] = useState(false) const copy = async () => { if (!copyable?.value) return try { await navigator.clipboard.writeText(copyable.value) setCopied(true) setTimeout(() => setCopied(false), 1500) } catch { /* sin portapapeles (contexto inseguro): el valor sigue seleccionable */ } } const subtitleNode = subtitle ? ( subtitleHref ? ( renderLink ? ( renderLink({ href: subtitleHref, children: subtitle, className: 'text-sm text-primary hover:underline' }) ) : ( {subtitle} ) ) : ( {subtitle} ) ) : null return ( {leading} {title} {badges.map((b) => ( ))} {subtitleNode} {actions} {metrics && metrics.length > 0 ? ( {metrics.map((m) => ( {m.label} {m.value} ))} ) : null} {copyable?.value ? ( {copyable.label} {copyable.value} {copied ? : } {copied ? t('document.copied', { defaultValue: 'Copiado' }) : t('document.copy', { defaultValue: 'Copiar' })} ) : null} ) } export { formatFieldValue } export type { FieldFormatOptions }
{copyable.value}