All files / shared / components MetadataCard.tsx

65.38% Statements 17/26
53.33% Branches 16/30
66.66% Functions 4/6
70.83% Lines 17/24

Press n or j to go to the next uncovered block, b, p or k for the previous block.

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99      69x     68x                                                   68x 20x                                                                                                                                 48x
import type { ReactNode } from 'react'
import { Skeleton } from '@/components/ui/skeleton'
import { Button } from '@/components/ui/button'
import { cn } from '@/lib/utils'
 
export interface MetadataField {
 I label: string
  value?: ReactNode
  render?: () => ReactNode
  spanFull?: boolean
}
 
export interface MetadataCardProps {
  fields: MetadataField[]
  isLoading?: boolean
  error?: Error | null
  onRetry?: () => void
  children?: ReactNode
}
 
export function MetadataCard({
  fields,
  isLoading,
  error,
  onRetry,
  children,
}: MetadataCardProps) {
  if (error) {
    return (
      <div className="flex flex-col items-center gap-4 rounded-lg border bg-card p-6 text-center">
        <p className="text-destructive">
          {error.message || 'Failed to load'}
        </p>
        {onRetry && (
          <Button variant="outline" onClick={onRetry} type="button">
            Retry
          </Button>
        )}
      </div>
    )
  }
 
  if (isLoading) {
    return (
      <div className="rounded-lg border bg-card p-6">
        <div className="grid grid-cols-2 gap-4">
          <div className="col-span-2 space-y-2">
            <Skeleton className="h-3 w-16" />
            <Skeleton className="h-5 w-48" />
          </div>
          <div className="space-y-2">
            <Skeleton className="h-3 w-12" />
            <Skeleton className="h-5 w-32" />
          </div>
          <div className="space-y-2">
            <Skeleton className="h-3 w-14" />
            <Skeleton className="h-5 w-28" />
          </div>
        </div>
      </div>
    )
  }
 
  if (children) {
    return (
      <div className="rounded-lg border bg-card p-6">{children}</div>
    )
  }
 
  return (
    <div className="rounded-lg border bg-card p-6">
      <div className="grid grid-cols-2 gap-4">
        {fields.map((field, i) => (
          <div
            key={i}
            className={cn(
              'space-y-1',
              field.spanFull && 'col-span-2',
            )}
          >
            <dt className="text-sm font-medium text-muted-foreground">
              {field.label}
            </dt>
            <dd className="text-sm">
              {field.render ? (
                field.render()
              ) : field.value !== undefined && field.value !== '' ? (
                field.value
              ) : (
                <span className="text-muted-foreground">{'\u2014'}</span>
              )}
            </dd>
          </div>
        ))}
      </div>
    </div>
  )
}
I