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 100      38x     134x                                                   134x 66x                                                                                                                                 68x  
import type { ReactNode } from 'react'
import { Skeleton } from '@/components/ui/skeleton'
import { Button } from '@/components/ui/button'
import { Card, CardContent } from '@/components/ui/card'
 
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-sm 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-muted/50 p-6">
        <div className="grid grid-cols-2 gap-4">
          <div className="col-span-full flex flex-col gap-2">
            <Skeleton className="h-3 w-16" />
            <Skeleton className="h-5 w-48" />
          </div>
          <div className="flex flex-col gap-2">
            <Skeleton className="h-3 w-12" />
            <Skeleton className="h-5 w-32" />
          </div>
          <div className="flex flex-col gap-2">
            <Skeleton className="h-3 w-14" />
            <Skeleton className="h-5 w-28" />
          </div>
        </div>
      </div>
    )
  }
 
  if (children) {
    return (
      <Card>
        <CardContent>{children}</CardContent>
      </Card>
    )
  }
 
  return (
    <Card>
      <CardContent>
        <dl className="grid grid-cols-2 gap-4">
          {fields.map((field, i) => (
            <div
              key={i}
              className={field.spanFull ? 'col-span-full' : ''}
            >
              <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>
          ))}
        </dl>
      </CardContent>
    </Card>
  )
}I